libpurple initialization
[python-purple] / c_purple.c
1 #include <purple.h>
2
3 #include <glib.h>
4
5 #include <signal.h>
6 #include <string.h>
7 #include <unistd.h>
8
9 #include "c_purple.h"
10
11 #define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
12 #define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
13
14 typedef struct _PurpleGLibIOClosure {
15         PurpleInputFunction function;
16         guint result;
17         gpointer data;
18 } PurpleGLibIOClosure;
19
20 static void purple_glib_io_destroy(gpointer data)
21 {
22         g_free(data);
23 }
24
25 static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
26 {
27         PurpleGLibIOClosure *closure = data;
28         PurpleInputCondition purple_cond = 0;
29
30         if (condition & PURPLE_GLIB_READ_COND)
31                 purple_cond |= PURPLE_INPUT_READ;
32         if (condition & PURPLE_GLIB_WRITE_COND)
33                 purple_cond |= PURPLE_INPUT_WRITE;
34
35         closure->function(closure->data, g_io_channel_unix_get_fd(source),
36                         purple_cond);
37
38         return TRUE;
39 }
40
41 static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function,
42                 gpointer data)
43 {
44         PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
45         GIOChannel *channel;
46         GIOCondition cond = 0;
47
48         closure->function = function;
49         closure->data = data;
50
51         if (condition & PURPLE_INPUT_READ)
52                 cond |= PURPLE_GLIB_READ_COND;
53         if (condition & PURPLE_INPUT_WRITE)
54                 cond |= PURPLE_GLIB_WRITE_COND;
55
56         channel = g_io_channel_unix_new(fd);
57         closure->result = g_io_add_watch_full(channel, 0, cond,
58                         purple_glib_io_invoke, closure, purple_glib_io_destroy);
59
60         g_io_channel_unref(channel);
61         return closure->result;
62 }
63
64 static PurpleEventLoopUiOps glib_eventloops =
65 {
66         g_timeout_add,
67         g_source_remove,
68         glib_input_add,
69         g_source_remove,
70         NULL,
71 #if GLIB_CHECK_VERSION(2,14,0)
72         g_timeout_add_seconds,
73 #else
74         NULL,
75 #endif
76
77         /* padding */
78         NULL,
79         NULL,
80         NULL
81 };
82 /*** End of the eventloop functions. ***/
83
84 /*** Conversation uiops ***/
85 /* FIXME: Revisit this function. Is it needed? How it should be more general?*/
86 static void
87 write_conv(PurpleConversation *conv, const char *who, const char *alias,
88                         const char *message, PurpleMessageFlags flags, time_t mtime)
89 {
90         const char *name;
91         if (alias && *alias)
92                 name = alias;
93         else if (who && *who)
94                 name = who;
95         else
96                 name = NULL;
97
98         printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
99                         purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
100                         name, message);
101 }
102
103 static PurpleConversationUiOps conv_uiops = 
104 {
105         NULL,                      /* create_conversation  */
106         NULL,                      /* destroy_conversation */
107         NULL,                      /* write_chat           */
108         NULL,                      /* write_im             */
109         write_conv,           /* write_conv           */
110         NULL,                      /* chat_add_users       */
111         NULL,                      /* chat_rename_user     */
112         NULL,                      /* chat_remove_users    */
113         NULL,                      /* chat_update_user     */
114         NULL,                      /* present              */
115         NULL,                      /* has_focus            */
116         NULL,                      /* custom_smiley_add    */
117         NULL,                      /* custom_smiley_write  */
118         NULL,                      /* custom_smiley_close  */
119         NULL,                      /* send_confirm         */
120         NULL,
121         NULL,
122         NULL,
123         NULL
124 };
125
126 /* FIXME: Is this a valid struct? */
127 static void
128 ui_init(void)
129 {
130         /**
131          * This should initialize the UI components for all the modules. Here we
132          * just initialize the UI for conversations.
133          */
134         purple_conversations_set_ui_ops(&conv_uiops);
135 }
136
137 static PurpleCoreUiOps core_uiops =
138 {
139         NULL,
140         NULL,
141         ui_init,
142         NULL,
143
144         /* padding */
145         NULL,
146         NULL,
147         NULL,
148         NULL
149 };
150
151 void init_libpurple(void)
152 {
153         /* Set a custom user directory (optional) */
154         /* FIXME: Put a valid carman directory here*/
155         purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
156
157         /* We do not want any debugging for now to keep the noise to a minimum. */
158         purple_debug_set_enabled(FALSE);
159
160         purple_core_set_ui_ops(&core_uiops);
161
162         purple_eventloop_set_ui_ops(&glib_eventloops);
163
164         purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH);
165
166         if (!purple_core_init(UI_ID)) {
167                 /* Initializing the core failed. Terminate. */
168                 fprintf(stderr,
169                                 "libpurple initialization failed. Dumping core.\n"
170                                 "Please report this!\n");
171                 abort();
172         }
173         printf("libpurple initialized");
174 }