b77d65981b8cea9c41f9dd1fde59e70b1667c58e
[python-purple] / c_purple.c
1 /*
2  * Copyright (c) 2008 INdT - Instituto Nokia de Tecnologia
3  *
4  * This file is part of python-purple.
5  *
6  * python-purple is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * python-purple is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <purple.h>
22
23 #include <glib.h>
24
25 #include <signal.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include "c_purple.h"
30
31 #define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
32 #define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
33
34 typedef struct _PurpleGLibIOClosure {
35         PurpleInputFunction function;
36         guint result;
37         gpointer data;
38 } PurpleGLibIOClosure;
39
40 static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
41 {
42         PurpleGLibIOClosure *closure = data;
43         PurpleInputCondition purple_cond = 0;
44
45         if (condition & PURPLE_GLIB_READ_COND)
46                 purple_cond |= PURPLE_INPUT_READ;
47         if (condition & PURPLE_GLIB_WRITE_COND)
48                 purple_cond |= PURPLE_INPUT_WRITE;
49
50         closure->function(closure->data, g_io_channel_unix_get_fd(source),
51                         purple_cond);
52
53         return TRUE;
54 }
55
56 static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function,
57                 gpointer data)
58 {
59         PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
60         GIOChannel *channel;
61         GIOCondition cond = 0;
62
63         closure->function = function;
64         closure->data = data;
65
66         if (condition & PURPLE_INPUT_READ)
67                 cond |= PURPLE_GLIB_READ_COND;
68         if (condition & PURPLE_INPUT_WRITE)
69                 cond |= PURPLE_GLIB_WRITE_COND;
70
71         channel = g_io_channel_unix_new(fd);
72         closure->result = g_io_add_watch_full(channel, 0, cond,
73                         purple_glib_io_invoke, closure, g_free);
74
75         g_io_channel_unref(channel);
76         return closure->result;
77 }
78
79 static PurpleEventLoopUiOps glib_eventloops =
80 {
81         g_timeout_add,
82         g_source_remove,
83         glib_input_add,
84         g_source_remove,
85         NULL,
86 #if GLIB_CHECK_VERSION(2,14,0)
87         g_timeout_add_seconds,
88 #else
89         NULL,
90 #endif
91
92         /* padding */
93         NULL,
94         NULL,
95         NULL
96 };
97 /*** End of the eventloop functions. ***/
98
99 /*** Conversation uiops ***/
100 /* FIXME: Revisit this function. Is it needed? How it should be more general?*/
101 static void
102 write_conv(PurpleConversation *conv, const char *who, const char *alias,
103                         const char *message, PurpleMessageFlags flags, time_t mtime)
104 {
105         const char *name;
106         if (alias && *alias)
107                 name = alias;
108         else if (who && *who)
109                 name = who;
110         else
111                 name = NULL;
112
113         printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
114                         purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
115                         name, message);
116 }
117
118 static PurpleConversationUiOps conv_uiops = 
119 {
120         NULL,                      /* create_conversation  */
121         NULL,                      /* destroy_conversation */
122         NULL,                      /* write_chat           */
123         NULL,                      /* write_im             */
124         write_conv,                /* write_conv           */
125         NULL,                      /* chat_add_users       */
126         NULL,                      /* chat_rename_user     */
127         NULL,                      /* chat_remove_users    */
128         NULL,                      /* chat_update_user     */
129         NULL,                      /* present              */
130         NULL,                      /* has_focus            */
131         NULL,                      /* custom_smiley_add    */
132         NULL,                      /* custom_smiley_write  */
133         NULL,                      /* custom_smiley_close  */
134         NULL,                      /* send_confirm         */
135         NULL,
136         NULL,
137         NULL,
138         NULL
139 };
140
141 /* FIXME: Is this a valid struct? */
142 static void
143 ui_init(void)
144 {
145         /**
146          * This should initialize the UI components for all the modules. Here we
147          * just initialize the UI for conversations.
148          */
149         purple_conversations_set_ui_ops(&conv_uiops);
150 }
151
152 static PurpleCoreUiOps core_uiops =
153 {
154         NULL,
155         NULL,
156         ui_init,
157         NULL,
158
159         /* padding */
160         NULL,
161         NULL,
162         NULL,
163         NULL
164 };
165
166 void init_libpurple(const char *ui_id)
167 {
168         purple_core_set_ui_ops(&core_uiops);
169
170         purple_eventloop_set_ui_ops(&glib_eventloops);
171
172         if (!purple_core_init(ui_id)) {
173                 /* Initializing the core failed. Terminate. */
174                 fprintf(stderr,
175                                 "libpurple initialization failed. Dumping core.\n"
176                                 "Please report this!\n");
177                 abort();
178         }
179
180         printf("libpurple initialized");
181 }