ruburple 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/GPL-2 +339 -0
- data/README +34 -0
- data/ext/extconf.rb +45 -0
- data/ext/ruburple_ext.c +1239 -0
- data/lib/ruburple/ruburple.rb +105 -0
- data/lib/ruburple.rb +21 -0
- metadata +52 -0
data/ext/ruburple_ext.c
ADDED
@@ -0,0 +1,1239 @@
|
|
1
|
+
// Ruburple - a ruby wrapper for libpurple
|
2
|
+
// Copyright (C) 2007 Martin Kihlgren <zond at troja dot ath dot cx>
|
3
|
+
//
|
4
|
+
// This program is free software; you can redistribute it and/or
|
5
|
+
// modify it under the terms of the GNU General Public License
|
6
|
+
// as published by the Free Software Foundation; either version 2
|
7
|
+
// of the License, or (at your option) any later version.
|
8
|
+
//
|
9
|
+
// This program is distributed in the hope that it will be useful,
|
10
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
// GNU General Public License for more details.
|
13
|
+
//
|
14
|
+
// You should have received a copy of the GNU General Public License
|
15
|
+
// along with this program; if not, write to the Free Software
|
16
|
+
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
+
|
18
|
+
#include <libpurple/account.h>
|
19
|
+
#include <libpurple/conversation.h>
|
20
|
+
#include <libpurple/core.h>
|
21
|
+
#include <libpurple/debug.h>
|
22
|
+
#include <libpurple/cipher.h>
|
23
|
+
#include <libpurple/eventloop.h>
|
24
|
+
#include <libpurple/ft.h>
|
25
|
+
#include <libpurple/log.h>
|
26
|
+
#include <libpurple/notify.h>
|
27
|
+
#include <libpurple/prefs.h>
|
28
|
+
#include <libpurple/prpl.h>
|
29
|
+
#include <libpurple/pounce.h>
|
30
|
+
#include <libpurple/savedstatuses.h>
|
31
|
+
#include <libpurple/sound.h>
|
32
|
+
#include <libpurple/status.h>
|
33
|
+
#include <libpurple/util.h>
|
34
|
+
#include <libpurple/whiteboard.h>
|
35
|
+
|
36
|
+
#include <glib.h>
|
37
|
+
#include <stdio.h>
|
38
|
+
#include <string.h>
|
39
|
+
#include <unistd.h>
|
40
|
+
#include <errno.h>
|
41
|
+
#include <ruby.h>
|
42
|
+
#include <stdarg.h>
|
43
|
+
|
44
|
+
/*
|
45
|
+
* The ruby classes.
|
46
|
+
*/
|
47
|
+
static VALUE rb_ruburple;
|
48
|
+
static VALUE rb_ruburple_plugin;
|
49
|
+
static VALUE rb_ruburple_protocol;
|
50
|
+
static VALUE rb_ruburple_protocol_info;
|
51
|
+
static VALUE rb_ruburple_protocol_account;
|
52
|
+
static VALUE rb_ruburple_protocol_account_transfer;
|
53
|
+
static VALUE rb_ruburple_protocol_account_conversation;
|
54
|
+
static VALUE rb_ruburple_protocol_account_chat;
|
55
|
+
static VALUE rb_ruburple_protocol_account_savedstatus;
|
56
|
+
static VALUE rb_ruburple_protocol_connection;
|
57
|
+
static VALUE rb_ruburple_blist_status;
|
58
|
+
static VALUE rb_ruburple_blist;
|
59
|
+
static VALUE rb_ruburple_blist_buddy_icon;
|
60
|
+
static VALUE rb_ruburple_blist_buddy;
|
61
|
+
static VALUE rb_ruburple_blist_node;
|
62
|
+
static VALUE rb_ruburple_blist_group;
|
63
|
+
static VALUE rb_ruburple_handle;
|
64
|
+
static VALUE rb_ruburple_cipher;
|
65
|
+
static VALUE rb_ruburple_log;
|
66
|
+
static VALUE rb_ruburple_xmlnode;
|
67
|
+
static VALUE rb_ruburple_userinfo;
|
68
|
+
static VALUE rb_ruburple_storedimage;
|
69
|
+
static VALUE rb_ruburple_subscription;
|
70
|
+
static VALUE rb_ruburple_pointer;
|
71
|
+
|
72
|
+
/*
|
73
|
+
* A few globals.
|
74
|
+
*/
|
75
|
+
static GMainLoop *main_loop;
|
76
|
+
static VALUE call_method_id;
|
77
|
+
static VALUE idle_handler_method_id;
|
78
|
+
static int purple_event_queue[2];
|
79
|
+
|
80
|
+
/*
|
81
|
+
* The UI name for libpurple.
|
82
|
+
*/
|
83
|
+
#define UI_ID "ruburple"
|
84
|
+
|
85
|
+
/**
|
86
|
+
* The following eventloop functions are used in both pidgin and purple-text. If your
|
87
|
+
* application uses glib mainloop, you can safely use this verbatim.
|
88
|
+
*/
|
89
|
+
#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
|
90
|
+
#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
|
91
|
+
|
92
|
+
/* util macros */
|
93
|
+
#define FATAL(s, ...) fprintf(stderr, "FATAL: "); fprintf(stderr, s, ## __VA_ARGS__); fprintf(stderr, "\n"); exit(1)
|
94
|
+
#define RETURN_QNIL_IF_NULL(pointer) if (pointer == NULL) return Qnil
|
95
|
+
|
96
|
+
/*
|
97
|
+
* Conversions from c to ruby.
|
98
|
+
*/
|
99
|
+
#define BOOL(gbool) (gbool == FALSE ? Qfalse : Qtrue)
|
100
|
+
#define RB_RUBURPLE_PROTOCOL_ACCOUNT(purple_account_pointer) Data_Wrap_Struct(rb_ruburple_protocol_account, NULL, NULL, purple_account_pointer)
|
101
|
+
#define RB_RUBURPLE_PROTOCOL_ACCOUNT_gc(purple_account_pointer) Data_Wrap_Struct(rb_ruburple_protocol_account, NULL, rb_ruburple_protocol_account_free, purple_account_pointer)
|
102
|
+
#define RB_RUBURPLE_PROTOCOL_ACCOUNT_CONVERSATION(purple_conversation_pointer) Data_Wrap_Struct(rb_ruburple_protocol_account_conversation, NULL, NULL, purple_conversation_pointer)
|
103
|
+
#define RB_RUBURPLE_PROTOCOL_ACCOUNT_TRANSFER(purple_xfer_pointer) Data_Wrap_Struct(rb_ruburple_protocol_account_transfer, NULL, NULL, purple_xfer_pointer)
|
104
|
+
#define RB_RUBURPLE_PROTOCOL_ACCOUNT_CHAT(purple_chat_pointer) Data_Wrap_Struct(rb_ruburple_protocol_account_chat, NULL, NULL, purple_chat_pointer)
|
105
|
+
#define RB_RUBURPLE_PROTOCOL_CONNECTION(purple_connection_pointer) Data_Wrap_Struct(rb_ruburple_protocol_connection, NULL, NULL, purple_connection_pointer)
|
106
|
+
#define RB_RUBURPLE_PROTOCOL_ACCOUNT_SAVEDSTATUS(purple_savedstatus_pointer) Data_Wrap_Struct(rb_ruburple_protocol_account_savedstatus, NULL, NULL, purple_savedstatus_pointer)
|
107
|
+
#define RB_RUBURPLE_PROTOCOL(purple_plugin_pointer) Data_Wrap_Struct(rb_ruburple_protocol, NULL, NULL, purple_plugin_pointer)
|
108
|
+
#define RB_RUBURPLE_PLUGIN(purple_plugin_pointer) Data_Wrap_Struct(rb_ruburple_plugin, NULL, NULL, purple_plugin_pointer)
|
109
|
+
#define RB_RUBURPLE_PROTOCOL_INFO(purple_plugin_info_pointer) Data_Wrap_Struct(rb_ruburple_protocol_info, NULL, NULL, purple_plugin_info_pointer)
|
110
|
+
#define RB_RUBURPLE_BLIST_STATUS(purple_status_pointer) Data_Wrap_Struct(rb_ruburple_blist_status, NULL, NULL, purple_status_pointer)
|
111
|
+
#define RB_RUBURPLE_BLIST(purple_blist_pointer) Data_Wrap_Struct(rb_ruburple_blist, NULL, NULL, purple_blist_pointer)
|
112
|
+
#define RB_RUBURPLE_BLIST_BUDDY(purple_buddy_pointer) Data_Wrap_Struct(rb_ruburple_blist_buddy, NULL, NULL, purple_buddy_pointer)
|
113
|
+
#define RB_RUBURPLE_BLIST_NODE(purple_blist_node_pointer) Data_Wrap_Struct(rb_ruburple_blist_node, NULL, NULL, purple_blist_node_pointer)
|
114
|
+
#define RB_RUBURPLE_BLIST_GROUP(purple_blist_group_pointer) Data_Wrap_Struct(rb_ruburple_blist_group, NULL, NULL, purple_blist_group_pointer)
|
115
|
+
#define RB_RUBURPLE_BLIST_BUDDY_ICON(purple_buddy_icon_pointer) Data_Wrap_Struct(rb_ruburple_blist_buddy_icon, NULL, NULL, purple_buddy_icon_pointer)
|
116
|
+
#define RB_RUBURPLE_HANDLE(void_pointer) Data_Wrap_Struct(rb_ruburple_handle, NULL, NULL, void_pointer)
|
117
|
+
#define RB_RUBURPLE_CIPHER(purple_cipher_pointer) Data_Wrap_Struct(rb_ruburple_cipher, NULL, NULL, purple_cipher_pointer)
|
118
|
+
#define RB_RUBURPLE_LOG(purple_log_pointer) Data_Wrap_Struct(rb_ruburple_log, NULL, NULL, purple_log_pointer)
|
119
|
+
#define RB_RUBURPLE_XMLNODE(xmlnode_pointer) Data_Wrap_Struct(rb_ruburple_xmlnode, NULL, NULL, xmlnode_pointer)
|
120
|
+
#define RB_RUBURPLE_USERINFO(purple_notify_user_info_pointer) Data_Wrap_Struct(rb_ruburple_userinfo, NULL, NULL, purple_notify_user_info_pointer)
|
121
|
+
#define RB_RUBURPLE_STOREDIMAGE(purple_stored_image_pointer) Data_Wrap_Struct(rb_ruburple_storedimage, NULL, NULL, purple_stored_image_pointer)
|
122
|
+
#define RB_RUBURPLE_SUBSCRIPTION_gc(ruburple_signal_handler_pointer) Data_Wrap_Struct(rb_ruburple_subscription, ruburple_signal_handler_mark, ruburple_signal_handler_free, ruburple_signal_handler_pointer)
|
123
|
+
#define RB_RUBURPLE_POINTER(gpointer) Data_Wrap_Struct(rb_ruburple_pointer, NULL, NULL, gpointer)
|
124
|
+
|
125
|
+
/*
|
126
|
+
* Conversions from ruby to c.
|
127
|
+
*/
|
128
|
+
#define GBOOL(bool) ((bool == Qnil || bool == Qfalse) ? FALSE : TRUE)
|
129
|
+
#define PURPLE_ACCOUNT(rb_ruburple_protocol_account,purple_account_pointer) Data_Get_Struct(rb_ruburple_protocol_account, PurpleAccount, purple_account_pointer)
|
130
|
+
#define PURPLE_PLUGIN(rb_ruburple_protocol,purple_plugin_pointer) Data_Get_Struct(rb_ruburple_protocol, PurplePlugin, purple_plugin_pointer)
|
131
|
+
#define PURPLE_PLUGIN_INFO(rb_ruburple_protocol_info,purple_plugin_info_pointer) Data_Get_Struct(rb_ruburple_protocol_info, PurplePluginInfo, purple_plugin_info_pointer)
|
132
|
+
#define PURPLE_SAVEDSTATUS(rb_ruburple_protocol_account_savedstatus,purple_saved_status_pointer) Data_Get_Struct(rb_ruburple_protocol_account_savedstatus, PurpleSavedStatus, purple_saved_status_pointer)
|
133
|
+
#define RUBURPLE_SIGNAL_HANDLER(rb_ruburple_subscription,ruburple_signal_handler_pointer) Data_Get_Struct(rb_ruburple_subscription, RuburpleSignalHandler, ruburple_signal_handler_pointer)
|
134
|
+
#define PURPLE_CONNECTION(rb_ruburple_protocol_connection,purple_connection_pointer) Data_Get_Struct(rb_ruburple_protocol_connection, PurpleConnection, purple_connection_pointer)
|
135
|
+
#define GPOINTER(rb_ruburple_pointer,gpointer) Data_Get_Struct(rb_ruburple_pointer, void, gpointer)
|
136
|
+
|
137
|
+
/*
|
138
|
+
* The libpurple signal handler for Ruburple.
|
139
|
+
*/
|
140
|
+
typedef struct
|
141
|
+
{
|
142
|
+
gpointer handle;
|
143
|
+
VALUE callable;
|
144
|
+
char *signal;
|
145
|
+
} RuburpleSignalHandler;
|
146
|
+
|
147
|
+
static RuburpleSignalHandler*
|
148
|
+
ruburple_signal_handler_new(gpointer handle, char *signal_name, VALUE callable)
|
149
|
+
{
|
150
|
+
RuburpleSignalHandler *handler = g_new(RuburpleSignalHandler, 1);
|
151
|
+
handler->handle = handle;
|
152
|
+
handler->signal = strdup(signal_name);
|
153
|
+
handler->callable = callable;
|
154
|
+
return handler;
|
155
|
+
}
|
156
|
+
|
157
|
+
static void
|
158
|
+
ruburple_signal_handler_free(RuburpleSignalHandler *handler)
|
159
|
+
{
|
160
|
+
g_free(handler->signal);
|
161
|
+
g_free(handler);
|
162
|
+
}
|
163
|
+
|
164
|
+
static void
|
165
|
+
ruburple_signal_handler_mark(RuburpleSignalHandler *handler)
|
166
|
+
{
|
167
|
+
rb_gc_mark(handler->callable);
|
168
|
+
}
|
169
|
+
|
170
|
+
/*
|
171
|
+
* A definition of an incoming event for ruby.
|
172
|
+
*/
|
173
|
+
typedef struct
|
174
|
+
{
|
175
|
+
VALUE receiver;
|
176
|
+
VALUE method;
|
177
|
+
int argc;
|
178
|
+
VALUE *argv;
|
179
|
+
GMutex *lock;
|
180
|
+
GCond *flag;
|
181
|
+
} IncomingRuburpleEvent;
|
182
|
+
|
183
|
+
/*
|
184
|
+
* Asking the glib main loop to do stuff for us.
|
185
|
+
*/
|
186
|
+
|
187
|
+
/* A shorthand for a generic function */
|
188
|
+
typedef gpointer (*RuburpleCallFunc)(gpointer);
|
189
|
+
|
190
|
+
/* A definition of something we want run once */
|
191
|
+
typedef struct
|
192
|
+
{
|
193
|
+
RuburpleCallFunc function;
|
194
|
+
gpointer data;
|
195
|
+
gpointer result;
|
196
|
+
GCond *done;
|
197
|
+
GMutex *lock;
|
198
|
+
gboolean do_free;
|
199
|
+
gboolean run;
|
200
|
+
} RuburpleSingleShotCall;
|
201
|
+
|
202
|
+
/* Creator of single shot calls */
|
203
|
+
static RuburpleSingleShotCall*
|
204
|
+
ruburple_single_shot_call_new(RuburpleCallFunc function, gpointer data, gboolean do_free)
|
205
|
+
{
|
206
|
+
RuburpleSingleShotCall *return_value = g_new(RuburpleSingleShotCall, 1);
|
207
|
+
return_value->function = function;
|
208
|
+
return_value->data = data;
|
209
|
+
return_value->do_free = do_free;
|
210
|
+
return_value->run = FALSE;
|
211
|
+
return_value->done = g_cond_new();
|
212
|
+
return_value->lock = g_mutex_new();
|
213
|
+
return return_value;
|
214
|
+
}
|
215
|
+
|
216
|
+
/* Destructor of single shot calls */
|
217
|
+
static void
|
218
|
+
ruburple_single_shot_call_free(RuburpleSingleShotCall *call)
|
219
|
+
{
|
220
|
+
g_mutex_free(call->lock);
|
221
|
+
g_cond_free(call->done);
|
222
|
+
g_free(call);
|
223
|
+
}
|
224
|
+
|
225
|
+
/* Call one of our single shots */
|
226
|
+
static gboolean
|
227
|
+
call_single_shot(gpointer data)
|
228
|
+
{
|
229
|
+
RuburpleSingleShotCall *call = (RuburpleSingleShotCall *) data;
|
230
|
+
|
231
|
+
g_mutex_lock(call->lock);
|
232
|
+
|
233
|
+
call->result = call->function(call->data);
|
234
|
+
call->run = TRUE;
|
235
|
+
g_cond_broadcast(call->done);
|
236
|
+
|
237
|
+
g_mutex_unlock(call->lock);
|
238
|
+
|
239
|
+
if (call->do_free) {
|
240
|
+
ruburple_single_shot_call_free(call);
|
241
|
+
}
|
242
|
+
|
243
|
+
return FALSE;
|
244
|
+
}
|
245
|
+
|
246
|
+
/* Ask glib to run something once */
|
247
|
+
static RuburpleSingleShotCall*
|
248
|
+
add_single_shot(RuburpleCallFunc function, gpointer data, gboolean do_free)
|
249
|
+
{
|
250
|
+
RuburpleSingleShotCall *call = ruburple_single_shot_call_new(function, data, do_free);
|
251
|
+
g_idle_add(call_single_shot, call);
|
252
|
+
return call;
|
253
|
+
}
|
254
|
+
|
255
|
+
/* Ask glib to run something for us once and wait for the result to be ready */
|
256
|
+
static gpointer
|
257
|
+
call_and_get_result(RuburpleCallFunc function, gpointer data)
|
258
|
+
{
|
259
|
+
RuburpleSingleShotCall *call = add_single_shot(function, data, FALSE);
|
260
|
+
gpointer return_value;
|
261
|
+
|
262
|
+
g_mutex_lock(call->lock);
|
263
|
+
|
264
|
+
while (!call->run) {
|
265
|
+
g_cond_wait(call->done, call->lock);
|
266
|
+
}
|
267
|
+
|
268
|
+
return_value = call->result;
|
269
|
+
|
270
|
+
g_mutex_unlock(call->lock);
|
271
|
+
|
272
|
+
ruburple_single_shot_call_free(call);
|
273
|
+
|
274
|
+
return return_value;
|
275
|
+
}
|
276
|
+
|
277
|
+
/*
|
278
|
+
* The magical stuff taken more or less verbatim from nullclient.c
|
279
|
+
*/
|
280
|
+
|
281
|
+
typedef struct _PurpleGLibIOClosure {
|
282
|
+
PurpleInputFunction function;
|
283
|
+
guint result;
|
284
|
+
gpointer data;
|
285
|
+
} PurpleGLibIOClosure;
|
286
|
+
|
287
|
+
static void purple_glib_io_destroy(gpointer data)
|
288
|
+
{
|
289
|
+
g_free(data);
|
290
|
+
}
|
291
|
+
|
292
|
+
static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
|
293
|
+
{
|
294
|
+
PurpleGLibIOClosure *closure = data;
|
295
|
+
PurpleInputCondition purple_cond = 0;
|
296
|
+
|
297
|
+
if (condition & PURPLE_GLIB_READ_COND)
|
298
|
+
purple_cond |= PURPLE_INPUT_READ;
|
299
|
+
if (condition & PURPLE_GLIB_WRITE_COND)
|
300
|
+
purple_cond |= PURPLE_INPUT_WRITE;
|
301
|
+
|
302
|
+
closure->function(closure->data, g_io_channel_unix_get_fd(source),
|
303
|
+
purple_cond);
|
304
|
+
|
305
|
+
return TRUE;
|
306
|
+
}
|
307
|
+
|
308
|
+
static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function,
|
309
|
+
gpointer data)
|
310
|
+
{
|
311
|
+
PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
|
312
|
+
GIOChannel *channel;
|
313
|
+
GIOCondition cond = 0;
|
314
|
+
|
315
|
+
closure->function = function;
|
316
|
+
closure->data = data;
|
317
|
+
|
318
|
+
if (condition & PURPLE_INPUT_READ)
|
319
|
+
cond |= PURPLE_GLIB_READ_COND;
|
320
|
+
if (condition & PURPLE_INPUT_WRITE)
|
321
|
+
cond |= PURPLE_GLIB_WRITE_COND;
|
322
|
+
|
323
|
+
channel = g_io_channel_unix_new(fd);
|
324
|
+
closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
|
325
|
+
purple_glib_io_invoke, closure, purple_glib_io_destroy);
|
326
|
+
|
327
|
+
g_io_channel_unref(channel);
|
328
|
+
return closure->result;
|
329
|
+
}
|
330
|
+
|
331
|
+
static PurpleEventLoopUiOps glib_eventloops =
|
332
|
+
{
|
333
|
+
g_timeout_add,
|
334
|
+
g_source_remove,
|
335
|
+
glib_input_add,
|
336
|
+
g_source_remove,
|
337
|
+
NULL
|
338
|
+
};
|
339
|
+
/*** End of the eventloop functions. ***/
|
340
|
+
|
341
|
+
static gpointer
|
342
|
+
run_the_loop(gpointer data)
|
343
|
+
{
|
344
|
+
main_loop = g_main_loop_new(NULL, FALSE);
|
345
|
+
g_main_loop_run(main_loop);
|
346
|
+
}
|
347
|
+
|
348
|
+
static VALUE
|
349
|
+
rb_ruburple_init(VALUE self)
|
350
|
+
{
|
351
|
+
if (purple_get_core() == NULL) {
|
352
|
+
/* We do not want any debugging for now to keep the noise to a minimum. */
|
353
|
+
purple_debug_set_enabled(FALSE);
|
354
|
+
|
355
|
+
/* Set the uiops for the eventloop. If your client is glib-based, you can safely
|
356
|
+
* copy this verbatim. */
|
357
|
+
purple_eventloop_set_ui_ops(&glib_eventloops);
|
358
|
+
|
359
|
+
/* Now that all the essential stuff has been set, let's try to init the core. It's
|
360
|
+
* necessary to provide a non-NULL name for the current ui to the core. This name
|
361
|
+
* is used by stuff that depends on this ui, for example the ui-specific plugins. */
|
362
|
+
if (!purple_core_init(UI_ID)) {
|
363
|
+
/* Initializing the core failed. Terminate. */
|
364
|
+
fprintf(stderr,
|
365
|
+
"libpurple initialization failed. Dumping core.\n"
|
366
|
+
"Please report this!\n");
|
367
|
+
abort();
|
368
|
+
}
|
369
|
+
|
370
|
+
/* Create and load the buddylist. */
|
371
|
+
purple_set_blist(purple_blist_new());
|
372
|
+
purple_blist_load();
|
373
|
+
|
374
|
+
/* Load the preferences. */
|
375
|
+
purple_prefs_load();
|
376
|
+
|
377
|
+
/* Load the pounces. */
|
378
|
+
purple_pounces_load();
|
379
|
+
|
380
|
+
g_thread_create(run_the_loop, NULL, FALSE, NULL);
|
381
|
+
}
|
382
|
+
return Qnil;
|
383
|
+
}
|
384
|
+
|
385
|
+
static VALUE
|
386
|
+
rb_ruburple_quit(VALUE self)
|
387
|
+
{
|
388
|
+
if (purple_get_core() != NULL) {
|
389
|
+
g_main_loop_quit(main_loop);
|
390
|
+
purple_core_quit();
|
391
|
+
}
|
392
|
+
return Qnil;
|
393
|
+
}
|
394
|
+
|
395
|
+
static gpointer
|
396
|
+
ruburple_set_debug(gpointer data)
|
397
|
+
{
|
398
|
+
purple_debug_set_enabled(GBOOL(* ((VALUE *) data)));
|
399
|
+
return NULL;
|
400
|
+
}
|
401
|
+
|
402
|
+
static VALUE
|
403
|
+
rb_ruburple_set_debug(VALUE self, VALUE enabled)
|
404
|
+
{
|
405
|
+
gpointer return_value = call_and_get_result(ruburple_set_debug, (gpointer) (&enabled));
|
406
|
+
return Qnil;
|
407
|
+
}
|
408
|
+
|
409
|
+
static VALUE
|
410
|
+
rb_protocol_get_id(VALUE self)
|
411
|
+
{
|
412
|
+
PurplePlugin *plugin;
|
413
|
+
const gchar *id;
|
414
|
+
PURPLE_PLUGIN(self, plugin);
|
415
|
+
id = purple_plugin_get_id(plugin);
|
416
|
+
RETURN_QNIL_IF_NULL(id);
|
417
|
+
return rb_str_new2(id);
|
418
|
+
}
|
419
|
+
|
420
|
+
static VALUE
|
421
|
+
rb_protocol_get_summary(VALUE self)
|
422
|
+
{
|
423
|
+
PurplePlugin *plugin;
|
424
|
+
const gchar *summary;
|
425
|
+
PURPLE_PLUGIN(self, plugin);
|
426
|
+
summary = purple_plugin_get_summary(plugin);
|
427
|
+
RETURN_QNIL_IF_NULL(summary);
|
428
|
+
return rb_str_new2(summary);
|
429
|
+
}
|
430
|
+
|
431
|
+
static VALUE
|
432
|
+
rb_protocol_get_version(VALUE self)
|
433
|
+
{
|
434
|
+
PurplePlugin *plugin;
|
435
|
+
const gchar *version;
|
436
|
+
PURPLE_PLUGIN(self, plugin);
|
437
|
+
version = purple_plugin_get_version(plugin);
|
438
|
+
RETURN_QNIL_IF_NULL(version);
|
439
|
+
return rb_str_new2(version);
|
440
|
+
}
|
441
|
+
|
442
|
+
static VALUE
|
443
|
+
rb_protocol_get_name(VALUE self)
|
444
|
+
{
|
445
|
+
PurplePlugin *plugin;
|
446
|
+
const gchar *name;
|
447
|
+
PURPLE_PLUGIN(self, plugin);
|
448
|
+
name = purple_plugin_get_name(plugin);
|
449
|
+
RETURN_QNIL_IF_NULL(name);
|
450
|
+
return rb_str_new2(name);
|
451
|
+
}
|
452
|
+
|
453
|
+
static VALUE
|
454
|
+
rb_protocol_get_description(VALUE self)
|
455
|
+
{
|
456
|
+
PurplePlugin *plugin;
|
457
|
+
const gchar *description;
|
458
|
+
PURPLE_PLUGIN(self, plugin);
|
459
|
+
description = purple_plugin_get_description(plugin);
|
460
|
+
RETURN_QNIL_IF_NULL(description);
|
461
|
+
return rb_str_new2(description);
|
462
|
+
}
|
463
|
+
|
464
|
+
static VALUE
|
465
|
+
rb_protocol_get_author(VALUE self)
|
466
|
+
{
|
467
|
+
PurplePlugin *plugin;
|
468
|
+
const gchar *author;
|
469
|
+
PURPLE_PLUGIN(self, plugin);
|
470
|
+
author = purple_plugin_get_author(plugin);
|
471
|
+
RETURN_QNIL_IF_NULL(author);
|
472
|
+
return rb_str_new2(author);
|
473
|
+
}
|
474
|
+
|
475
|
+
static VALUE
|
476
|
+
rb_protocol_get_homepage(VALUE self)
|
477
|
+
{
|
478
|
+
PurplePlugin *plugin;
|
479
|
+
const gchar *homepage;
|
480
|
+
PURPLE_PLUGIN(self, plugin);
|
481
|
+
homepage = purple_plugin_get_homepage(plugin);
|
482
|
+
RETURN_QNIL_IF_NULL(homepage);
|
483
|
+
return rb_str_new2(homepage);
|
484
|
+
}
|
485
|
+
|
486
|
+
static gpointer
|
487
|
+
ruburple_get_protocols(gpointer data)
|
488
|
+
{
|
489
|
+
return (gpointer) purple_plugins_get_protocols();
|
490
|
+
}
|
491
|
+
|
492
|
+
static VALUE
|
493
|
+
rb_ruburple_get_protocols(VALUE self)
|
494
|
+
{
|
495
|
+
GList *iter;
|
496
|
+
VALUE return_value = rb_ary_new();
|
497
|
+
|
498
|
+
iter = (GList *) call_and_get_result(ruburple_get_protocols, NULL);
|
499
|
+
|
500
|
+
for (iter = purple_plugins_get_protocols(); iter; iter = iter->next) {
|
501
|
+
rb_ary_push(return_value, RB_RUBURPLE_PROTOCOL(iter->data));
|
502
|
+
}
|
503
|
+
|
504
|
+
return return_value;
|
505
|
+
}
|
506
|
+
|
507
|
+
static gpointer
|
508
|
+
ruburple_protocol_account_free(gpointer data)
|
509
|
+
{
|
510
|
+
PurpleAccount *account = (PurpleAccount *) data;
|
511
|
+
if (!purple_account_is_disconnected(account) && !account->disconnecting)
|
512
|
+
purple_account_disconnect(account);
|
513
|
+
purple_account_destroy(account);
|
514
|
+
return NULL;
|
515
|
+
}
|
516
|
+
|
517
|
+
static void
|
518
|
+
rb_ruburple_protocol_account_free(PurpleAccount *account)
|
519
|
+
{
|
520
|
+
call_and_get_result(ruburple_protocol_account_free, account);
|
521
|
+
}
|
522
|
+
|
523
|
+
static gpointer
|
524
|
+
ruburple_protocol_get_account(gpointer data)
|
525
|
+
{
|
526
|
+
gpointer *args = (gpointer *) data;
|
527
|
+
return (gpointer) purple_account_new((char *) args[0], (char *) args[1]);
|
528
|
+
}
|
529
|
+
|
530
|
+
static VALUE
|
531
|
+
rb_ruburple_protocol_get_account(VALUE self, VALUE name)
|
532
|
+
{
|
533
|
+
PurplePlugin *plugin;
|
534
|
+
gpointer *args = g_new(gpointer, 2);
|
535
|
+
VALUE return_value;
|
536
|
+
|
537
|
+
Check_Type(name, T_STRING);
|
538
|
+
PURPLE_PLUGIN(self, plugin);
|
539
|
+
|
540
|
+
args[0] = (gpointer) RSTRING(name)->ptr;
|
541
|
+
args[1] = (gpointer) plugin->info->id;
|
542
|
+
|
543
|
+
return_value = RB_RUBURPLE_PROTOCOL_ACCOUNT_gc((PurpleAccount *) call_and_get_result(ruburple_protocol_get_account, args));
|
544
|
+
|
545
|
+
g_free(args);
|
546
|
+
|
547
|
+
return return_value;
|
548
|
+
}
|
549
|
+
|
550
|
+
static gpointer
|
551
|
+
ruburple_protocol_account_set_password(gpointer data)
|
552
|
+
{
|
553
|
+
gpointer *args = (gpointer *) data;
|
554
|
+
purple_account_set_password((PurpleAccount *) args[0], (char *) args[1]);
|
555
|
+
return NULL;
|
556
|
+
}
|
557
|
+
|
558
|
+
static VALUE
|
559
|
+
rb_ruburple_protocol_account_set_password(VALUE self, VALUE password)
|
560
|
+
{
|
561
|
+
PurpleAccount *account;
|
562
|
+
gpointer *args = g_new(gpointer, 2);
|
563
|
+
|
564
|
+
Check_Type(password, T_STRING);
|
565
|
+
PURPLE_ACCOUNT(self, account);
|
566
|
+
args[0] = (gpointer) account;
|
567
|
+
args[1] = (gpointer) RSTRING(password)->ptr;
|
568
|
+
|
569
|
+
call_and_get_result(ruburple_protocol_account_set_password, args);
|
570
|
+
|
571
|
+
g_free(args);
|
572
|
+
|
573
|
+
return Qnil;
|
574
|
+
}
|
575
|
+
|
576
|
+
static gpointer
|
577
|
+
ruburple_protocol_account_connect(gpointer data)
|
578
|
+
{
|
579
|
+
PurpleAccount *account = (PurpleAccount *) data;
|
580
|
+
purple_account_set_enabled(account, UI_ID, TRUE);
|
581
|
+
return NULL;
|
582
|
+
}
|
583
|
+
|
584
|
+
static VALUE
|
585
|
+
rb_ruburple_protocol_account_connect(VALUE self)
|
586
|
+
{
|
587
|
+
PurpleAccount *account;
|
588
|
+
PURPLE_ACCOUNT(self, account);
|
589
|
+
|
590
|
+
call_and_get_result(ruburple_protocol_account_connect, account);
|
591
|
+
|
592
|
+
return Qnil;
|
593
|
+
}
|
594
|
+
|
595
|
+
static gpointer
|
596
|
+
ruburple_protocol_account_set_savedstatus(gpointer data)
|
597
|
+
{
|
598
|
+
gpointer *args = (gpointer *) data;
|
599
|
+
purple_savedstatus_activate_for_account((PurpleSavedStatus *) args[0], (PurpleAccount *) args[1]);
|
600
|
+
return NULL;
|
601
|
+
}
|
602
|
+
|
603
|
+
static VALUE
|
604
|
+
rb_ruburple_protocol_account_set_savedstatus(VALUE self, VALUE savedstatus_value)
|
605
|
+
{
|
606
|
+
PurpleAccount *account;
|
607
|
+
PurpleSavedStatus *savedstatus;
|
608
|
+
gpointer *args = g_new(gpointer, 2);
|
609
|
+
|
610
|
+
PURPLE_ACCOUNT(self, account);
|
611
|
+
PURPLE_SAVEDSTATUS(savedstatus_value, savedstatus);
|
612
|
+
|
613
|
+
args[0] = (gpointer) savedstatus;
|
614
|
+
args[1] = (gpointer) account;
|
615
|
+
|
616
|
+
call_and_get_result(ruburple_protocol_account_set_savedstatus, args);
|
617
|
+
|
618
|
+
g_free(args);
|
619
|
+
|
620
|
+
return Qnil;
|
621
|
+
}
|
622
|
+
|
623
|
+
static gpointer
|
624
|
+
ruburple_protocol_account_savedstatus_alloc(gpointer data)
|
625
|
+
{
|
626
|
+
return (gpointer) purple_savedstatus_new(NULL, PURPLE_STATUS_UNSET);
|
627
|
+
}
|
628
|
+
|
629
|
+
static VALUE
|
630
|
+
rb_ruburple_protocol_account_savedstatus_alloc(VALUE klass)
|
631
|
+
{
|
632
|
+
PurpleSavedStatus *savedstatus = (PurpleSavedStatus *) call_and_get_result(ruburple_protocol_account_savedstatus_alloc, NULL);
|
633
|
+
return Data_Wrap_Struct(klass, NULL, free, savedstatus);
|
634
|
+
}
|
635
|
+
|
636
|
+
static gpointer
|
637
|
+
ruburple_protocol_account_savedstatus_initialize(gpointer data)
|
638
|
+
{
|
639
|
+
gpointer *args = (gpointer *) data;
|
640
|
+
purple_savedstatus_set_type((PurpleSavedStatus *) args[0], NUM2INT(*( (VALUE *) args[1])));
|
641
|
+
}
|
642
|
+
|
643
|
+
static VALUE
|
644
|
+
rb_ruburple_protocol_account_savedstatus_initialize(VALUE self, VALUE status_constant)
|
645
|
+
{
|
646
|
+
PurpleSavedStatus *savedstatus;
|
647
|
+
gpointer *args = g_new(gpointer, 2);
|
648
|
+
|
649
|
+
Check_Type(status_constant, T_FIXNUM);
|
650
|
+
PURPLE_SAVEDSTATUS(self, savedstatus);
|
651
|
+
|
652
|
+
args[0] = (gpointer) savedstatus;
|
653
|
+
args[1] = (gpointer) (&status_constant);
|
654
|
+
|
655
|
+
call_and_get_result(ruburple_protocol_account_savedstatus_initialize, args);
|
656
|
+
|
657
|
+
g_free(args);
|
658
|
+
|
659
|
+
return Qnil;
|
660
|
+
}
|
661
|
+
|
662
|
+
static VALUE
|
663
|
+
get_ruby_instance_from_subtype(PurpleValue *value, gpointer data, int i, char *signal_name)
|
664
|
+
{
|
665
|
+
switch (purple_value_get_subtype(value)) {
|
666
|
+
case PURPLE_SUBTYPE_UNKNOWN:
|
667
|
+
FATAL("argument %d of callback from signal %s is of PURPLE_TYPE_SUBTYPE:PURPLE_TYPE_UNKNOWN",
|
668
|
+
i,
|
669
|
+
signal_name);
|
670
|
+
break;
|
671
|
+
case PURPLE_SUBTYPE_ACCOUNT:
|
672
|
+
return(RB_RUBURPLE_PROTOCOL_ACCOUNT((PurpleAccount *) data));
|
673
|
+
break;
|
674
|
+
case PURPLE_SUBTYPE_BLIST:
|
675
|
+
return(RB_RUBURPLE_BLIST((PurpleBuddyList *) data));
|
676
|
+
break;
|
677
|
+
case PURPLE_SUBTYPE_BLIST_BUDDY:
|
678
|
+
return(RB_RUBURPLE_BLIST_BUDDY((PurpleBuddy *) data));
|
679
|
+
break;
|
680
|
+
case PURPLE_SUBTYPE_BLIST_GROUP:
|
681
|
+
return(RB_RUBURPLE_BLIST_GROUP((PurpleGroup *) data));
|
682
|
+
break;
|
683
|
+
case PURPLE_SUBTYPE_BLIST_CHAT:
|
684
|
+
return(RB_RUBURPLE_PROTOCOL_ACCOUNT_CHAT((PurpleChat *) data));
|
685
|
+
break;
|
686
|
+
case PURPLE_SUBTYPE_BUDDY_ICON:
|
687
|
+
return(RB_RUBURPLE_BLIST_BUDDY_ICON((PurpleBuddyIcon *) data));
|
688
|
+
break;
|
689
|
+
case PURPLE_SUBTYPE_CONNECTION:
|
690
|
+
return(RB_RUBURPLE_PROTOCOL_CONNECTION((PurpleConnection *) data));
|
691
|
+
break;
|
692
|
+
case PURPLE_SUBTYPE_CONVERSATION:
|
693
|
+
return(RB_RUBURPLE_PROTOCOL_ACCOUNT_CONVERSATION((PurpleConversation *) data));
|
694
|
+
break;
|
695
|
+
case PURPLE_SUBTYPE_PLUGIN:
|
696
|
+
return(RB_RUBURPLE_PLUGIN((PurplePlugin *) data));
|
697
|
+
break;
|
698
|
+
case PURPLE_SUBTYPE_BLIST_NODE:
|
699
|
+
return(RB_RUBURPLE_BLIST_NODE((PurpleBlistNode *) data));
|
700
|
+
break;
|
701
|
+
case PURPLE_SUBTYPE_CIPHER:
|
702
|
+
return(RB_RUBURPLE_CIPHER((PurpleCipher *) data));
|
703
|
+
break;
|
704
|
+
case PURPLE_SUBTYPE_STATUS:
|
705
|
+
return(RB_RUBURPLE_BLIST_STATUS((PurpleStatus *) data));
|
706
|
+
break;
|
707
|
+
case PURPLE_SUBTYPE_LOG:
|
708
|
+
return(RB_RUBURPLE_LOG((PurpleLog *) data));
|
709
|
+
break;
|
710
|
+
case PURPLE_SUBTYPE_XFER:
|
711
|
+
return(RB_RUBURPLE_PROTOCOL_ACCOUNT_TRANSFER((PurpleXfer *) data));
|
712
|
+
break;
|
713
|
+
case PURPLE_SUBTYPE_SAVEDSTATUS:
|
714
|
+
return(RB_RUBURPLE_PROTOCOL_ACCOUNT_SAVEDSTATUS((PurpleSavedStatus *) data));
|
715
|
+
break;
|
716
|
+
case PURPLE_SUBTYPE_XMLNODE:
|
717
|
+
return(RB_RUBURPLE_XMLNODE((xmlnode *) data));
|
718
|
+
break;
|
719
|
+
case PURPLE_SUBTYPE_USERINFO:
|
720
|
+
return(RB_RUBURPLE_USERINFO((PurpleNotifyUserInfo *) data));
|
721
|
+
break;
|
722
|
+
case PURPLE_SUBTYPE_STORED_IMAGE:
|
723
|
+
return(RB_RUBURPLE_STOREDIMAGE((PurpleStoredImage *) data));
|
724
|
+
break;
|
725
|
+
default:
|
726
|
+
FATAL("argument %d of callback from signal %s is of a completely unknown PURPLE_TYPE_SUBTYPE %d",
|
727
|
+
i,
|
728
|
+
signal_name,
|
729
|
+
purple_value_get_subtype(value));
|
730
|
+
break;
|
731
|
+
}
|
732
|
+
}
|
733
|
+
|
734
|
+
static void
|
735
|
+
ruburple_callback(va_list args, void *data)
|
736
|
+
{
|
737
|
+
RuburpleSignalHandler *handler = (RuburpleSignalHandler *) data;
|
738
|
+
void *ret_val;
|
739
|
+
int value_count;
|
740
|
+
int i;
|
741
|
+
PurpleValue *ret_value, **values;
|
742
|
+
IncomingRuburpleEvent event;
|
743
|
+
IncomingRuburpleEvent *event_pointer = &event;
|
744
|
+
VALUE *ruby_args;
|
745
|
+
gpointer next_arg;
|
746
|
+
|
747
|
+
purple_signal_get_values(handler->handle, handler->signal,
|
748
|
+
&ret_value, &value_count, &values);
|
749
|
+
|
750
|
+
ruby_args = g_new(VALUE, value_count);
|
751
|
+
|
752
|
+
for (i = 0; i < value_count; i++) {
|
753
|
+
if (purple_value_is_outgoing(values[i])) {
|
754
|
+
switch (purple_value_get_type(values[i])) {
|
755
|
+
case PURPLE_TYPE_UNKNOWN: /**< Unknown type. */
|
756
|
+
FATAL("argument %d of callback from signal %s is of PURPLE_TYPE_UNKNOWN",
|
757
|
+
i,
|
758
|
+
handler->signal);
|
759
|
+
break;
|
760
|
+
case PURPLE_TYPE_SUBTYPE: /**< Subtype. */
|
761
|
+
if ((next_arg = (gpointer) va_arg(args, gpointer *)) == NULL) {
|
762
|
+
ruby_args[i] = Qnil;
|
763
|
+
} else {
|
764
|
+
ruby_args[i] = get_ruby_instance_from_subtype(values[i], *( (gpointer *) next_arg), i, handler->signal);
|
765
|
+
}
|
766
|
+
break;
|
767
|
+
case PURPLE_TYPE_CHAR: /**< Character. */
|
768
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
769
|
+
ruby_args[i] = Qnil;
|
770
|
+
else
|
771
|
+
ruby_args[i] = INT2NUM(*(char *) next_arg);
|
772
|
+
break;
|
773
|
+
case PURPLE_TYPE_UCHAR: /**< Unsigned character. */
|
774
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
775
|
+
ruby_args[i] = Qnil;
|
776
|
+
else
|
777
|
+
ruby_args[i] = INT2NUM(*(unsigned char *) next_arg);
|
778
|
+
break;
|
779
|
+
case PURPLE_TYPE_BOOLEAN: /**< Boolean. */
|
780
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
781
|
+
ruby_args[i] = Qnil;
|
782
|
+
else
|
783
|
+
ruby_args[i] = (*(gboolean *) next_arg == TRUE ? Qtrue : Qfalse);
|
784
|
+
break;
|
785
|
+
case PURPLE_TYPE_SHORT: /**< Short integer. */
|
786
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
787
|
+
ruby_args[i] = Qnil;
|
788
|
+
else
|
789
|
+
ruby_args[i] = INT2NUM(*(short *) next_arg);
|
790
|
+
break;
|
791
|
+
case PURPLE_TYPE_USHORT: /**< Unsigned short integer. */
|
792
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
793
|
+
ruby_args[i] = Qnil;
|
794
|
+
else
|
795
|
+
ruby_args[i] = INT2NUM(*(unsigned short *) next_arg);
|
796
|
+
break;
|
797
|
+
case PURPLE_TYPE_INT: /**< Integer. */
|
798
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
799
|
+
ruby_args[i] = Qnil;
|
800
|
+
else
|
801
|
+
ruby_args[i] = INT2NUM(*(int *) next_arg);
|
802
|
+
break;
|
803
|
+
case PURPLE_TYPE_UINT: /**< Unsigned integer. */
|
804
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
805
|
+
ruby_args[i] = Qnil;
|
806
|
+
else
|
807
|
+
ruby_args[i] = INT2NUM(*(unsigned int *) next_arg);
|
808
|
+
break;
|
809
|
+
case PURPLE_TYPE_LONG: /**< Long integer. */
|
810
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
811
|
+
ruby_args[i] = Qnil;
|
812
|
+
else
|
813
|
+
ruby_args[i] = INT2NUM(*(long *) next_arg);
|
814
|
+
break;
|
815
|
+
case PURPLE_TYPE_ULONG: /**< Unsigned long integer. */
|
816
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
817
|
+
ruby_args[i] = Qnil;
|
818
|
+
else
|
819
|
+
ruby_args[i] = INT2NUM(*(unsigned long *) next_arg);
|
820
|
+
break;
|
821
|
+
case PURPLE_TYPE_INT64: /**< 64-bit integer. */
|
822
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
823
|
+
ruby_args[i] = Qnil;
|
824
|
+
else
|
825
|
+
ruby_args[i] = INT2NUM(*(gint64 *) next_arg);
|
826
|
+
break;
|
827
|
+
case PURPLE_TYPE_UINT64: /**< 64-bit unsigned integer. */
|
828
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL)
|
829
|
+
ruby_args[i] = Qnil;
|
830
|
+
else
|
831
|
+
ruby_args[i] = INT2NUM(*(guint64 *) next_arg);
|
832
|
+
break;
|
833
|
+
case PURPLE_TYPE_STRING: /**< String. */
|
834
|
+
if ((next_arg = va_arg(args, gpointer *)) == NULL)
|
835
|
+
ruby_args[i] = Qnil;
|
836
|
+
else
|
837
|
+
ruby_args[i] = rb_str_new2(*(char **) next_arg);
|
838
|
+
break;
|
839
|
+
case PURPLE_TYPE_OBJECT: /**< Object pointer. */
|
840
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_OBJECT which I dont know what the hell to do with",
|
841
|
+
i);
|
842
|
+
break;
|
843
|
+
case PURPLE_TYPE_POINTER: /**< Generic pointer. */
|
844
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_POINTER which I dont know what the hell to do with",
|
845
|
+
i);
|
846
|
+
break;
|
847
|
+
case PURPLE_TYPE_ENUM: /**< Enum. */
|
848
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_ENUM which I dont know what the hell to do with",
|
849
|
+
i);
|
850
|
+
break;
|
851
|
+
case PURPLE_TYPE_BOXED: /**< Boxed pointer with specific type. */
|
852
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_BOXED which I dont know what the hell to do with",
|
853
|
+
i);
|
854
|
+
break;
|
855
|
+
default:
|
856
|
+
FATAL("argument %d of callback from signal %s is of a completely unknown type %d",
|
857
|
+
i,
|
858
|
+
handler->signal,
|
859
|
+
purple_value_get_type(values[i]));
|
860
|
+
break;
|
861
|
+
}
|
862
|
+
} else {
|
863
|
+
switch (purple_value_get_type(values[i])) {
|
864
|
+
case PURPLE_TYPE_UNKNOWN: /**< Unknown type. */
|
865
|
+
FATAL("argument %d of callback from signal %s is of PURPLE_TYPE_UNKNOWN",
|
866
|
+
i,
|
867
|
+
handler->signal);
|
868
|
+
break;
|
869
|
+
case PURPLE_TYPE_SUBTYPE: /**< Subtype. */
|
870
|
+
if ((next_arg = va_arg(args, gpointer)) == NULL) {
|
871
|
+
ruby_args[i] = Qnil;
|
872
|
+
} else {
|
873
|
+
ruby_args[i] = get_ruby_instance_from_subtype(values[i], next_arg, i, handler->signal);
|
874
|
+
}
|
875
|
+
break;
|
876
|
+
default:
|
877
|
+
switch (purple_value_get_type(values[i])) {
|
878
|
+
case PURPLE_TYPE_BOOLEAN: /**< Boolean. */
|
879
|
+
ruby_args[i] = va_arg(args, gboolean) == TRUE ? Qtrue : Qfalse;
|
880
|
+
break;
|
881
|
+
case PURPLE_TYPE_INT: /**< Integer. */
|
882
|
+
ruby_args[i] = INT2NUM(va_arg(args, int));
|
883
|
+
break;
|
884
|
+
case PURPLE_TYPE_UINT: /**< Unsigned integer. */
|
885
|
+
ruby_args[i] = INT2NUM(va_arg(args, unsigned int));
|
886
|
+
break;
|
887
|
+
case PURPLE_TYPE_LONG: /**< Long integer. */
|
888
|
+
ruby_args[i] = INT2NUM(va_arg(args, long));
|
889
|
+
break;
|
890
|
+
case PURPLE_TYPE_ULONG: /**< Unsigned long integer. */
|
891
|
+
ruby_args[i] = INT2NUM(va_arg(args, unsigned long));
|
892
|
+
break;
|
893
|
+
case PURPLE_TYPE_INT64: /**< 64-bit integer. */
|
894
|
+
ruby_args[i] = INT2NUM(va_arg(args, gint64));
|
895
|
+
break;
|
896
|
+
case PURPLE_TYPE_UINT64: /**< 64-bit unsigned integer. */
|
897
|
+
ruby_args[i] = INT2NUM(va_arg(args, guint64));
|
898
|
+
break;
|
899
|
+
case PURPLE_TYPE_STRING: /**< String. */
|
900
|
+
ruby_args[i] = rb_str_new2(va_arg(args, char *));
|
901
|
+
break;
|
902
|
+
case PURPLE_TYPE_OBJECT: /**< Object pointer. */
|
903
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_OBJECT which I dont know what the hell to do with",
|
904
|
+
i);
|
905
|
+
break;
|
906
|
+
case PURPLE_TYPE_POINTER: /**< Generic pointer. */
|
907
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_POINTER which I dont know what the hell to do with",
|
908
|
+
i);
|
909
|
+
break;
|
910
|
+
case PURPLE_TYPE_ENUM: /**< Enum. */
|
911
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_ENUM which I dont know what the hell to do with",
|
912
|
+
i);
|
913
|
+
break;
|
914
|
+
case PURPLE_TYPE_BOXED: /**< Boxed pointer with specific type. */
|
915
|
+
FATAL("argument %d of callback from signal %s is of type PURPLE_TYPE_BOXED which I dont know what the hell to do with",
|
916
|
+
i);
|
917
|
+
break;
|
918
|
+
default:
|
919
|
+
FATAL("argument %d of callback from signal %s is of a completely unknown type %d",
|
920
|
+
i,
|
921
|
+
handler->signal,
|
922
|
+
purple_value_get_type(values[i]));
|
923
|
+
break;
|
924
|
+
}
|
925
|
+
}
|
926
|
+
}
|
927
|
+
}
|
928
|
+
|
929
|
+
event.receiver = handler->callable;
|
930
|
+
event.method = call_method_id;
|
931
|
+
event.argc = value_count;
|
932
|
+
event.argv = ruby_args;
|
933
|
+
event.lock = g_mutex_new();
|
934
|
+
event.flag = g_cond_new();
|
935
|
+
|
936
|
+
g_mutex_lock(event.lock);
|
937
|
+
|
938
|
+
write(purple_event_queue[1], (char *) &event_pointer, sizeof(IncomingRuburpleEvent *));
|
939
|
+
|
940
|
+
g_cond_wait(event.flag, event.lock);
|
941
|
+
|
942
|
+
g_mutex_unlock(event.lock);
|
943
|
+
|
944
|
+
g_mutex_free(event.lock);
|
945
|
+
g_cond_free(event.flag);
|
946
|
+
g_free(event.argv);
|
947
|
+
}
|
948
|
+
|
949
|
+
static VALUE
|
950
|
+
rb_ruburple_read_event(VALUE self)
|
951
|
+
{
|
952
|
+
IncomingRuburpleEvent *event;
|
953
|
+
VALUE return_value;
|
954
|
+
int i;
|
955
|
+
|
956
|
+
read(purple_event_queue[0], (char *) &event, sizeof(IncomingRuburpleEvent *));
|
957
|
+
|
958
|
+
return_value = rb_funcall2(event->receiver, event->method, event->argc, event->argv);
|
959
|
+
|
960
|
+
g_mutex_lock(event->lock);
|
961
|
+
g_cond_signal(event->flag);
|
962
|
+
g_mutex_unlock(event->lock);
|
963
|
+
|
964
|
+
return return_value;
|
965
|
+
}
|
966
|
+
|
967
|
+
static gpointer
|
968
|
+
ruburple_signal_connect_vargs(gpointer data)
|
969
|
+
{
|
970
|
+
RuburpleSignalHandler *handler = (RuburpleSignalHandler *) data;
|
971
|
+
purple_signal_connect_vargs(handler->handle, handler->signal, (gpointer) handler->callable, PURPLE_CALLBACK(ruburple_callback), (gpointer) handler);
|
972
|
+
return NULL;
|
973
|
+
}
|
974
|
+
|
975
|
+
static VALUE
|
976
|
+
rb_ruburple_subscribe(VALUE self, VALUE handle_value, VALUE signal_name, VALUE callable)
|
977
|
+
{
|
978
|
+
VALUE return_value;
|
979
|
+
gpointer handle;
|
980
|
+
GPOINTER(handle_value, handle);
|
981
|
+
RuburpleSignalHandler *handler = ruburple_signal_handler_new(handle,
|
982
|
+
RSTRING(signal_name)->ptr,
|
983
|
+
callable);
|
984
|
+
|
985
|
+
call_and_get_result(ruburple_signal_connect_vargs, (gpointer) handler);
|
986
|
+
|
987
|
+
return_value = RB_RUBURPLE_SUBSCRIPTION_gc(handler);
|
988
|
+
|
989
|
+
rb_gc_register_address(&return_value);
|
990
|
+
|
991
|
+
return return_value;
|
992
|
+
}
|
993
|
+
|
994
|
+
static gpointer
|
995
|
+
ruburple_signal_disconnect(gpointer data)
|
996
|
+
{
|
997
|
+
RuburpleSignalHandler *handler = (RuburpleSignalHandler *) data;
|
998
|
+
purple_signal_disconnect(handler->handle, handler->signal, (gpointer) handler->callable, PURPLE_CALLBACK(ruburple_callback));
|
999
|
+
return NULL;
|
1000
|
+
}
|
1001
|
+
|
1002
|
+
static VALUE
|
1003
|
+
rb_ruburple_subscription_unsubscribe(VALUE self)
|
1004
|
+
{
|
1005
|
+
RuburpleSignalHandler *handler;
|
1006
|
+
RUBURPLE_SIGNAL_HANDLER(self, handler);
|
1007
|
+
|
1008
|
+
call_and_get_result(ruburple_signal_disconnect, (gpointer) handler);
|
1009
|
+
|
1010
|
+
rb_gc_unregister_address(&self);
|
1011
|
+
|
1012
|
+
return Qnil;
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
static VALUE
|
1016
|
+
rb_ruburple_protocol_account_get_connection(VALUE self)
|
1017
|
+
{
|
1018
|
+
PurpleAccount *account;
|
1019
|
+
PurpleConnection *connection;
|
1020
|
+
PURPLE_ACCOUNT(self, account);
|
1021
|
+
connection = purple_account_get_connection(account);
|
1022
|
+
RETURN_QNIL_IF_NULL(connection);
|
1023
|
+
return RB_RUBURPLE_PROTOCOL_CONNECTION(connection);
|
1024
|
+
}
|
1025
|
+
|
1026
|
+
static gpointer
|
1027
|
+
ruburple_serv_send_im(gpointer data)
|
1028
|
+
{
|
1029
|
+
gpointer *args = (gpointer *) data;
|
1030
|
+
int *rval = g_new(int, 1);
|
1031
|
+
*rval = serv_send_im((PurpleConnection *) args[0], (char *) args[1], (char *) args[2], * (int *) args[3]);
|
1032
|
+
return (gpointer) rval;
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
static VALUE
|
1036
|
+
rb_ruburple_protocol_connection_send_im(int argc, VALUE *argv, VALUE self)
|
1037
|
+
{
|
1038
|
+
PurpleConnection *connection;
|
1039
|
+
int flags = 0;
|
1040
|
+
gpointer tmp;
|
1041
|
+
gpointer args[4];
|
1042
|
+
int rval;
|
1043
|
+
|
1044
|
+
if (argc > 3)
|
1045
|
+
rb_raise(rb_eRuntimeError, "Connection#send_im(RECIPIENT, MESSAGE, FLAGS = 0) takes at most 3 arguments");
|
1046
|
+
if (argc == 3) {
|
1047
|
+
Check_Type(argv[2], T_FIXNUM);
|
1048
|
+
flags = NUM2INT(argv[2]);
|
1049
|
+
}
|
1050
|
+
if (argc >= 2) {
|
1051
|
+
Check_Type(argv[1], T_STRING);
|
1052
|
+
Check_Type(argv[0], T_STRING);
|
1053
|
+
} else {
|
1054
|
+
rb_raise(rb_eRuntimeError, "Connection#send_im(RECIPIENT, MESSAGE, FLAGS = 0) takes at least 2 arguments");
|
1055
|
+
}
|
1056
|
+
|
1057
|
+
PURPLE_CONNECTION(self, connection);
|
1058
|
+
|
1059
|
+
args[0] = (gpointer) connection;
|
1060
|
+
args[1] = (gpointer) RSTRING(argv[0])->ptr;
|
1061
|
+
args[2] = (gpointer) RSTRING(argv[1])->ptr;
|
1062
|
+
args[3] = (gpointer) &flags;
|
1063
|
+
|
1064
|
+
tmp = call_and_get_result(ruburple_serv_send_im, args);
|
1065
|
+
rval = * (int *) tmp;
|
1066
|
+
g_free(tmp);
|
1067
|
+
|
1068
|
+
return INT2NUM(rval);
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
static gpointer
|
1072
|
+
ruburple_protocol_connection_close(gpointer data)
|
1073
|
+
{
|
1074
|
+
PurpleConnection *connection = (PurpleConnection *) data;
|
1075
|
+
PurpleAccount *account = purple_connection_get_account(connection);
|
1076
|
+
if (!purple_account_is_disconnected(account) && !account->disconnecting)
|
1077
|
+
purple_account_disconnect(account);
|
1078
|
+
return NULL;
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
static VALUE
|
1082
|
+
rb_ruburple_protocol_connection_close(VALUE self)
|
1083
|
+
{
|
1084
|
+
PurpleConnection *connection;
|
1085
|
+
PURPLE_CONNECTION(self, connection);
|
1086
|
+
call_and_get_result(ruburple_protocol_connection_close, connection);
|
1087
|
+
return Qnil;
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
static gpointer
|
1091
|
+
ruburple_protocol_account_is_connected(gpointer data)
|
1092
|
+
{
|
1093
|
+
PurpleAccount *account = (PurpleAccount *) data;
|
1094
|
+
gboolean *rval = g_new(gboolean, 1);
|
1095
|
+
*rval = purple_account_is_connected(account);
|
1096
|
+
return rval;
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
static VALUE
|
1100
|
+
rb_ruburple_protocol_account_is_connected(VALUE self)
|
1101
|
+
{
|
1102
|
+
PurpleAccount *account;
|
1103
|
+
gboolean *tmp;
|
1104
|
+
VALUE rval;
|
1105
|
+
PURPLE_ACCOUNT(self, account);
|
1106
|
+
tmp = (gboolean *) call_and_get_result(ruburple_protocol_account_is_connected, account);
|
1107
|
+
rval = BOOL(*tmp);
|
1108
|
+
g_free(tmp);
|
1109
|
+
return rval;
|
1110
|
+
}
|
1111
|
+
|
1112
|
+
#ifdef __cplusplus
|
1113
|
+
extern "C" {
|
1114
|
+
#endif
|
1115
|
+
void Init_ruburple_ext() {
|
1116
|
+
VALUE io_class = rb_define_class("IO", rb_cObject);
|
1117
|
+
VALUE new_method = rb_intern("new");
|
1118
|
+
|
1119
|
+
if (pipe(purple_event_queue) == -1)
|
1120
|
+
rb_raise(rb_eRuntimeError, "error creating event pipe from libpurple to ruby: %s", strerror(errno));
|
1121
|
+
|
1122
|
+
call_method_id = rb_intern("call");
|
1123
|
+
idle_handler_method_id = rb_intern("_idle_handler");
|
1124
|
+
|
1125
|
+
rb_ruburple = rb_define_module("Ruburple");
|
1126
|
+
rb_define_singleton_method(rb_ruburple, "quit", rb_ruburple_quit, 0);
|
1127
|
+
rb_define_singleton_method(rb_ruburple, "debug=", rb_ruburple_set_debug, 1);
|
1128
|
+
rb_define_singleton_method(rb_ruburple, "protocols", rb_ruburple_get_protocols, 0);
|
1129
|
+
rb_define_singleton_method(rb_ruburple, "init", rb_ruburple_init, 0);
|
1130
|
+
rb_define_singleton_method(rb_ruburple, "_subscribe", rb_ruburple_subscribe, 3);
|
1131
|
+
rb_define_singleton_method(rb_ruburple, "_read_event", rb_ruburple_read_event, 0);
|
1132
|
+
rb_define_const(rb_ruburple, "MESSAGE_SEND", INT2NUM(PURPLE_MESSAGE_SEND)); /**< Outgoing message. */
|
1133
|
+
rb_define_const(rb_ruburple, "MESSAGE_RECV", INT2NUM(PURPLE_MESSAGE_RECV)); /**< Incoming message. */
|
1134
|
+
rb_define_const(rb_ruburple, "MESSAGE_SYSTEM", INT2NUM(PURPLE_MESSAGE_SYSTEM)); /**< System message. */
|
1135
|
+
rb_define_const(rb_ruburple, "MESSAGE_AUTO_RESP", INT2NUM(PURPLE_MESSAGE_AUTO_RESP)); /**< Auto response. */
|
1136
|
+
rb_define_const(rb_ruburple, "MESSAGE_ACTIVE_ONLY", INT2NUM(PURPLE_MESSAGE_ACTIVE_ONLY)); /**< Hint to the UI that this
|
1137
|
+
message should not be
|
1138
|
+
shown in conversations
|
1139
|
+
which are only open for
|
1140
|
+
internal UI purposes
|
1141
|
+
(e.g. for contact-aware
|
1142
|
+
conversions). */
|
1143
|
+
rb_define_const(rb_ruburple, "MESSAGE_NICK", INT2NUM(PURPLE_MESSAGE_NICK)); /**< Contains your nick. */
|
1144
|
+
rb_define_const(rb_ruburple, "MESSAGE_NO_LOG", INT2NUM(PURPLE_MESSAGE_NO_LOG)); /**< Do not log. */
|
1145
|
+
rb_define_const(rb_ruburple, "MESSAGE_WHISPER", INT2NUM(PURPLE_MESSAGE_WHISPER)); /**< Whispered message. */
|
1146
|
+
rb_define_const(rb_ruburple, "MESSAGE_ERROR", INT2NUM(PURPLE_MESSAGE_ERROR)); /**< Error message. */
|
1147
|
+
rb_define_const(rb_ruburple, "MESSAGE_DELAYED", INT2NUM(PURPLE_MESSAGE_DELAYED)); /**< Delayed message. */
|
1148
|
+
rb_define_const(rb_ruburple, "MESSAGE_RAW", INT2NUM(PURPLE_MESSAGE_RAW)); /**< "Raw" message - don't
|
1149
|
+
apply formatting */
|
1150
|
+
rb_define_const(rb_ruburple, "MESSAGE_IMAGES", INT2NUM(PURPLE_MESSAGE_IMAGES)); /**< Message contains images */
|
1151
|
+
rb_define_const(rb_ruburple, "MESSAGE_NOTIFY", INT2NUM(PURPLE_MESSAGE_NOTIFY)); /**< Message is a notification */
|
1152
|
+
|
1153
|
+
rb_define_const(rb_ruburple, "HANDLE_ACCOUNTS", RB_RUBURPLE_POINTER(purple_accounts_get_handle()));
|
1154
|
+
rb_define_const(rb_ruburple, "HANDLE_CONNECTIONS", RB_RUBURPLE_POINTER(purple_connections_get_handle()));
|
1155
|
+
rb_define_const(rb_ruburple, "HANDLE_CONVERSATIONS", RB_RUBURPLE_POINTER(purple_conversations_get_handle()));
|
1156
|
+
rb_define_const(rb_ruburple, "HANDLE_BLIST", RB_RUBURPLE_POINTER(purple_blist_get_handle()));
|
1157
|
+
rb_define_const(rb_ruburple, "HANDLE_CIPHERS", RB_RUBURPLE_POINTER(purple_ciphers_get_handle()));
|
1158
|
+
rb_define_const(rb_ruburple, "HANDLE_CORE", RB_RUBURPLE_POINTER(purple_get_core()));
|
1159
|
+
rb_define_const(rb_ruburple, "HANDLE_LOG", RB_RUBURPLE_POINTER(purple_log_get_handle()));
|
1160
|
+
rb_define_const(rb_ruburple, "HANDLE_PLUGINS", RB_RUBURPLE_POINTER(purple_plugins_get_handle()));
|
1161
|
+
rb_define_const(rb_ruburple, "HANDLE_SAVEDSTATUSES", RB_RUBURPLE_POINTER(purple_savedstatuses_get_handle()));
|
1162
|
+
rb_define_const(rb_ruburple, "HANDLE_XFERS", RB_RUBURPLE_POINTER(purple_xfers_get_handle()));
|
1163
|
+
rb_define_const(rb_ruburple, "EVENT_INPUT", rb_funcall(io_class, new_method, 1, INT2NUM(purple_event_queue[0])));
|
1164
|
+
|
1165
|
+
rb_ruburple_plugin = rb_define_class_under(rb_ruburple, "Plugin", rb_cObject);
|
1166
|
+
|
1167
|
+
rb_ruburple_protocol = rb_define_class_under(rb_ruburple, "Protocol", rb_ruburple_plugin);
|
1168
|
+
rb_define_method(rb_ruburple_protocol, "get_account", rb_ruburple_protocol_get_account, 1);
|
1169
|
+
rb_define_method(rb_ruburple_protocol, "id", rb_protocol_get_id, 0);
|
1170
|
+
rb_define_method(rb_ruburple_protocol, "name", rb_protocol_get_name, 0);
|
1171
|
+
rb_define_method(rb_ruburple_protocol, "version", rb_protocol_get_version, 0);
|
1172
|
+
rb_define_method(rb_ruburple_protocol, "summary", rb_protocol_get_summary, 0);
|
1173
|
+
rb_define_method(rb_ruburple_protocol, "description", rb_protocol_get_description, 0);
|
1174
|
+
rb_define_method(rb_ruburple_protocol, "author", rb_protocol_get_author, 0);
|
1175
|
+
rb_define_method(rb_ruburple_protocol, "homepage", rb_protocol_get_homepage, 0);
|
1176
|
+
|
1177
|
+
rb_ruburple_protocol_account = rb_define_class_under(rb_ruburple, "Account", rb_cObject);
|
1178
|
+
rb_define_method(rb_ruburple_protocol_account, "password=", rb_ruburple_protocol_account_set_password, 1);
|
1179
|
+
rb_define_method(rb_ruburple_protocol_account, "connect", rb_ruburple_protocol_account_connect, 0);
|
1180
|
+
rb_define_method(rb_ruburple_protocol_account, "savedstatus=", rb_ruburple_protocol_account_set_savedstatus, 1);
|
1181
|
+
rb_define_method(rb_ruburple_protocol_account, "connection", rb_ruburple_protocol_account_get_connection, 0);
|
1182
|
+
rb_define_method(rb_ruburple_protocol_account, "connected?", rb_ruburple_protocol_account_is_connected, 0);
|
1183
|
+
|
1184
|
+
rb_ruburple_protocol_account_conversation = rb_define_class_under(rb_ruburple_protocol_account, "Conversation", rb_cObject);
|
1185
|
+
|
1186
|
+
rb_ruburple_protocol_account_savedstatus = rb_define_class_under(rb_ruburple_protocol_account, "SavedStatus", rb_cObject);
|
1187
|
+
rb_define_alloc_func(rb_ruburple_protocol_account_savedstatus, rb_ruburple_protocol_account_savedstatus_alloc);
|
1188
|
+
rb_define_private_method(rb_ruburple_protocol_account_savedstatus, "initialize", rb_ruburple_protocol_account_savedstatus_initialize, 1);
|
1189
|
+
|
1190
|
+
rb_ruburple_blist = rb_define_class_under(rb_ruburple, "BuddyList", rb_cObject);
|
1191
|
+
|
1192
|
+
rb_ruburple_blist_status = rb_define_class_under(rb_ruburple_blist, "Status", rb_cObject);
|
1193
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_UNSET", INT2NUM(PURPLE_STATUS_UNSET));
|
1194
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_OFFLINE", INT2NUM(PURPLE_STATUS_OFFLINE));
|
1195
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_AVAILABLE", INT2NUM(PURPLE_STATUS_AVAILABLE));
|
1196
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_UNAVAILABLE", INT2NUM(PURPLE_STATUS_UNAVAILABLE));
|
1197
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_INVISIBLE", INT2NUM(PURPLE_STATUS_INVISIBLE));
|
1198
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_AWAY", INT2NUM(PURPLE_STATUS_AWAY));
|
1199
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_EXTENDED_AWAY", INT2NUM(PURPLE_STATUS_EXTENDED_AWAY));
|
1200
|
+
rb_define_const(rb_ruburple_blist_status, "STATUS_MOBILE", INT2NUM(PURPLE_STATUS_MOBILE));
|
1201
|
+
|
1202
|
+
rb_ruburple_protocol_connection = rb_define_class_under(rb_ruburple_protocol, "Connection", rb_cObject);
|
1203
|
+
rb_define_method(rb_ruburple_protocol_connection, "send_im", rb_ruburple_protocol_connection_send_im, -1);
|
1204
|
+
rb_define_method(rb_ruburple_protocol_connection, "close", rb_ruburple_protocol_connection_close, 0);
|
1205
|
+
|
1206
|
+
rb_ruburple_protocol_account_transfer = rb_define_class_under(rb_ruburple_protocol_account, "Transfer", rb_cObject);
|
1207
|
+
|
1208
|
+
rb_ruburple_blist_node = rb_define_class_under(rb_ruburple_blist, "Node", rb_cObject);
|
1209
|
+
|
1210
|
+
rb_ruburple_blist_buddy = rb_define_class_under(rb_ruburple_blist, "Buddy", rb_cObject);
|
1211
|
+
|
1212
|
+
rb_ruburple_blist_group = rb_define_class_under(rb_ruburple_blist, "Group", rb_cObject);
|
1213
|
+
|
1214
|
+
rb_ruburple_blist_buddy_icon = rb_define_class_under(rb_ruburple_blist, "BuddyIcon", rb_cObject);
|
1215
|
+
|
1216
|
+
rb_ruburple_handle = rb_define_class_under(rb_ruburple, "Handle", rb_cObject);
|
1217
|
+
|
1218
|
+
rb_ruburple_cipher = rb_define_class_under(rb_ruburple, "Cipher", rb_cObject);
|
1219
|
+
|
1220
|
+
rb_ruburple_log = rb_define_class_under(rb_ruburple, "Log", rb_cObject);
|
1221
|
+
|
1222
|
+
rb_ruburple_xmlnode = rb_define_class_under(rb_ruburple, "XMLNode", rb_cObject);
|
1223
|
+
|
1224
|
+
rb_ruburple_userinfo = rb_define_class_under(rb_ruburple, "UserInfo", rb_cObject);
|
1225
|
+
|
1226
|
+
rb_ruburple_storedimage = rb_define_class_under(rb_ruburple, "StoredImage", rb_cObject);
|
1227
|
+
|
1228
|
+
rb_ruburple_subscription = rb_define_class_under(rb_ruburple, "Subscription", rb_cObject);
|
1229
|
+
rb_define_method(rb_ruburple_subscription, "unsubscribe", rb_ruburple_subscription_unsubscribe, 0);
|
1230
|
+
|
1231
|
+
rb_ruburple_pointer = rb_define_class_under(rb_ruburple, "Pointer", rb_cObject);
|
1232
|
+
|
1233
|
+
g_thread_init(NULL);
|
1234
|
+
|
1235
|
+
}
|
1236
|
+
#ifdef __cplusplus
|
1237
|
+
}
|
1238
|
+
#endif
|
1239
|
+
|