source: protocols/purple/purple.c @ e046390

Last change on this file since e046390 was e046390, checked in by Wilmer van der Gaast <wilmer@…>, at 2009-10-10T23:25:54Z

Make purple use BitlBee's event handling API. Since the APIs never really
diverged too much this is fairly transparent. I did rename and redefine
GAIM_INPUT_* variables to really make it work without adding another stupid
layer in between.

One problem left, the new libpurple input API doesn't care about return
values. Fixing that in the next CL.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  libpurple module - Main file                                             *
5*                                                                           *
6*  Copyright 2009 Wilmer van der Gaast <wilmer@gaast.net>                   *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
12*                                                                           *
13*  This program is distributed in the hope that it will be useful,          *
14*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
15*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
16*  GNU General Public License for more details.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24#include <glib.h>
25#include <purple.h>
26
27#include "bitlbee.h"
28
29GSList *purple_connections;
30
31#undef g_io_add_watch
32#undef g_io_add_watch_full
33#undef g_timeout_add
34#undef g_source_remove
35
36/**
37 * The following eventloop functions are used in both pidgin and purple-text. If your
38 * application uses glib mainloop, you can safely use this verbatim.
39 */
40#define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
41#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
42
43typedef struct _PurpleGLibIOClosure {
44        PurpleInputFunction function;
45        guint result;
46        gpointer data;
47} PurpleGLibIOClosure;
48
49static struct im_connection *purple_ic_by_pa( PurpleAccount *pa )
50{
51        GSList *i;
52       
53        for( i = purple_connections; i; i = i->next )
54                if( ((struct im_connection *)i->data)->proto_data == pa )
55                        return i->data;
56       
57        return NULL;
58}
59
60static struct im_connection *purple_ic_by_gc( PurpleConnection *gc )
61{
62        return purple_ic_by_pa( purple_connection_get_account( gc ) );
63}
64
65static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata )
66{
67        return b_timeout_add( interval, (b_event_handler) func, udata );
68}
69
70static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata )
71{
72        return (guint) b_input_add( fd, cond, (b_event_handler) func, udata );
73}
74
75static PurpleEventLoopUiOps glib_eventloops = 
76{
77        prplcb_ev_timeout_add,
78        b_event_remove,
79        prplcb_ev_input_add,
80        b_event_remove,
81};
82
83static void purple_init( account_t *acc )
84{
85        /* TODO: Figure out variables to export via set. */
86       
87}
88
89static void purple_login( account_t *acc )
90{
91        struct im_connection *ic = imcb_new( acc );
92        PurpleAccount *pa;
93        //PurpleSavedStatus *ps;
94        //GList *i;
95       
96        /* For now this is needed in the _connected() handlers if using
97           GLib event handling, to make sure we're not handling events
98           on dead connections. */
99        purple_connections = g_slist_prepend( purple_connections, ic );
100       
101        pa = purple_account_new( acc->user, acc->prpl->name );
102        purple_account_set_password( pa, acc->pass );
103       
104        ic->proto_data = pa;
105       
106        purple_account_set_enabled( pa, "BitlBee", TRUE );
107       
108        /*
109        for( i = ((PurplePluginProtocolInfo *)pa->gc->prpl->info->extra_info)->protocol_options; i; i = i->next )
110        {
111                PurpleAccountOption *o = i->data;
112               
113                printf( "%s\n", o->pref_name );
114        }
115        */
116       
117        //ps = purple_savedstatus_new( NULL, PURPLE_STATUS_AVAILABLE );
118        //purple_savedstatus_activate_for_account( ps, pa );
119}
120
121static void purple_logout( struct im_connection *ic )
122{
123        purple_connections = g_slist_remove( purple_connections, ic );
124}
125
126static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
127{
128        PurpleConversation *conv;
129       
130        if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM,
131                                                            who, ic->proto_data ) ) == NULL )
132        {
133                conv = purple_conversation_new( PURPLE_CONV_TYPE_IM,
134                                                ic->proto_data, who );
135        }
136       
137        purple_conv_im_send( purple_conversation_get_im_data( conv ), message );
138       
139        return 1;
140}
141
142static GList *purple_away_states( struct im_connection *ic )
143{
144        return NULL;
145}
146
147static void purple_set_away( struct im_connection *ic, char *state_txt, char *message )
148{
149}
150
151static void purple_add_buddy( struct im_connection *ic, char *who, char *group )
152{
153}
154
155static void purple_remove_buddy( struct im_connection *ic, char *who, char *group )
156{
157}
158
159static void purple_keepalive( struct im_connection *ic )
160{
161}
162
163static int purple_send_typing( struct im_connection *ic, char *who, int typing )
164{
165        return 1;
166}
167
168static void purple_ui_init();
169
170static PurpleCoreUiOps bee_core_uiops = 
171{
172        NULL,
173        NULL,
174        purple_ui_init,
175        NULL,
176
177        /* padding */
178        NULL,
179        NULL,
180        NULL,
181        NULL
182};
183
184static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count )
185{
186        struct im_connection *ic = purple_ic_by_gc( gc );
187       
188        imcb_log( ic, "%s", text );
189}
190
191static void prplcb_conn_connected( PurpleConnection *gc )
192{
193        struct im_connection *ic = purple_ic_by_gc( gc );
194       
195        imcb_connected( ic );
196       
197        if( gc->flags & PURPLE_CONNECTION_HTML )
198                ic->flags |= OPT_DOES_HTML;
199}
200
201static void prplcb_conn_disconnected( PurpleConnection *gc )
202{
203        struct im_connection *ic = purple_ic_by_gc( gc );
204       
205        if( ic != NULL )
206                imc_logout( ic, TRUE );
207}
208
209static void prplcb_conn_notice( PurpleConnection *gc, const char *text )
210{
211        struct im_connection *ic = purple_ic_by_gc( gc );
212       
213        if( ic != NULL )
214                imcb_log( ic, "%s", text );
215}
216
217static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text )
218{
219        struct im_connection *ic = purple_ic_by_gc( gc );
220       
221        /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login,
222           should probably handle that. */
223        if( ic != NULL )
224                imcb_error( ic, "%s", text );
225}
226
227static PurpleConnectionUiOps bee_conn_uiops =
228{
229        prplcb_conn_progress,
230        prplcb_conn_connected,
231        prplcb_conn_disconnected,
232        prplcb_conn_notice,
233        NULL,
234        NULL,
235        NULL,
236        prplcb_conn_report_disconnect_reason,
237};
238
239static void prplcb_blist_new( PurpleBlistNode *node )
240{
241        PurpleBuddy *bud = (PurpleBuddy*) node;
242        struct im_connection *ic = purple_ic_by_pa( bud->account );
243       
244        if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL )
245        {
246                imcb_add_buddy( ic, bud->name, NULL );
247                if( bud->server_alias )
248                        imcb_buddy_nick_hint( ic, bud->name, bud->server_alias );
249        }
250}
251
252static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node )
253{
254        PurpleBuddy *bud = (PurpleBuddy*) node;
255        struct im_connection *ic = purple_ic_by_pa( bud->account );
256       
257        if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL  )
258        {
259                imcb_buddy_status( ic, bud->name,
260                                   purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0,
261                                   NULL, NULL );
262        }
263}
264
265static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node )
266{
267        PurpleBuddy *bud = (PurpleBuddy*) node;
268        struct im_connection *ic = purple_ic_by_pa( bud->account );
269       
270        if( node->type == PURPLE_BLIST_BUDDY_NODE && ic != NULL  )
271        {
272                imcb_remove_buddy( ic, bud->name, NULL );
273        }
274}
275
276static PurpleBlistUiOps bee_blist_uiops =
277{
278        NULL,
279        prplcb_blist_new,
280        NULL,
281        prplcb_blist_update,
282        prplcb_blist_remove,
283};
284
285static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime )
286{
287        struct im_connection *ic = purple_ic_by_pa( conv->account );
288       
289        /* ..._SEND means it's an outgoing message, no need to echo those. */
290        if( !( flags & PURPLE_MESSAGE_SEND ) )
291                imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime );
292}
293
294static PurpleConversationUiOps bee_conv_uiops = 
295{
296        NULL,                      /* create_conversation  */
297        NULL,                      /* destroy_conversation */
298        NULL,                      /* write_chat           */
299        prplcb_conv_im,            /* write_im             */
300        NULL,                      /* write_conv           */
301        NULL,                      /* chat_add_users       */
302        NULL,                      /* chat_rename_user     */
303        NULL,                      /* chat_remove_users    */
304        NULL,                      /* chat_update_user     */
305        NULL,                      /* present              */
306        NULL,                      /* has_focus            */
307        NULL,                      /* custom_smiley_add    */
308        NULL,                      /* custom_smiley_write  */
309        NULL,                      /* custom_smiley_close  */
310        NULL,                      /* send_confirm         */
311        NULL,
312        NULL,
313        NULL,
314        NULL
315};
316
317static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s )
318{
319        printf( "DEBUG %s: %s", category, arg_s );
320}
321
322static PurpleDebugUiOps bee_debug_uiops =
323{
324        prplcb_debug_print,
325};
326
327static void purple_ui_init()
328{
329        purple_blist_set_ui_ops( &bee_blist_uiops );
330        purple_connections_set_ui_ops( &bee_conn_uiops );
331        purple_conversations_set_ui_ops( &bee_conv_uiops );
332        //purple_debug_set_ui_ops( &bee_debug_uiops );
333}
334
335void purple_initmodule()
336{
337        GList *prots;
338       
339        if( B_EV_IO_READ != PURPLE_INPUT_READ ||
340            B_EV_IO_WRITE != PURPLE_INPUT_WRITE )
341        {
342                /* FIXME FIXME FIXME FIXME FIXME :-) */
343                exit( 1 );
344        }
345       
346        purple_util_set_user_dir("/tmp");
347        purple_debug_set_enabled(FALSE);
348        purple_core_set_ui_ops(&bee_core_uiops);
349        purple_eventloop_set_ui_ops(&glib_eventloops);
350        if( !purple_core_init( "BitlBee") )
351        {
352                /* Initializing the core failed. Terminate. */
353                fprintf( stderr, "libpurple initialization failed.\n" );
354                abort();
355        }
356       
357        /* This seems like stateful shit we don't want... */
358        purple_set_blist(purple_blist_new());
359        purple_blist_load();
360       
361        /* Meh? */
362        purple_prefs_load();
363       
364        for( prots = purple_plugins_get_protocols(); prots; prots = prots->next )
365        {
366                struct prpl *ret = g_new0( struct prpl, 1 );
367                PurplePlugin *prot = prots->data;
368               
369                ret->name = prot->info->id;
370                ret->login = purple_login;
371                ret->init = purple_init;
372                ret->logout = purple_logout;
373                ret->buddy_msg = purple_buddy_msg;
374                ret->away_states = purple_away_states;
375                ret->set_away = purple_set_away;
376                ret->add_buddy = purple_add_buddy;
377                ret->remove_buddy = purple_remove_buddy;
378                ret->keepalive = purple_keepalive;
379                ret->send_typing = purple_send_typing;
380                ret->handle_cmp = g_strcasecmp;
381               
382                register_protocol( ret );
383        }
384}
Note: See TracBrowser for help on using the repository browser.