11660
|
1 #include "mono-glue.h"
|
|
2 #include "mono-helper.h"
|
|
3 #include "debug.h"
|
|
4 #include "blist.h"
|
|
5 #include "signals.h"
|
|
6 #include "value.h"
|
|
7
|
|
8 typedef struct {
|
|
9 MonoObject *func;
|
|
10 char *signal;
|
|
11 GaimValue **values;
|
|
12 GaimValue *ret_value;
|
|
13 int num_vals;
|
|
14 } SignalData;
|
|
15
|
|
16 static GaimCallback get_callback(SignalData *sig_data);
|
|
17
|
|
18 static gpointer dispatch_callback(SignalData *sig_data, int num_vals, ...)
|
|
19 {
|
|
20 MonoArray *array;
|
|
21 MonoObject *obj;
|
|
22 int i;
|
|
23 gpointer meth_args[1];
|
|
24 gpointer gaim_obj;
|
|
25
|
|
26 va_list args;
|
|
27
|
|
28 va_start(args, num_vals);
|
|
29
|
|
30 array = mono_array_new(mono_loader_get_domain(), mono_get_object_class(), num_vals);
|
|
31
|
|
32 for (i = 0; i < num_vals; i++) {
|
|
33 if (gaim_value_get_type(sig_data->values[i]) == GAIM_TYPE_SUBTYPE) {
|
|
34 gaim_obj = va_arg(args, gpointer);
|
|
35 obj = mono_loader_object_from_gaim_subtype(gaim_value_get_subtype(sig_data->values[i]), gaim_obj);
|
|
36 mono_array_set(array, MonoObject*, i, obj);
|
|
37 } else {
|
|
38 gaim_obj = va_arg(args, gpointer);
|
|
39 obj = mono_loader_object_from_gaim_type(gaim_value_get_type(sig_data->values[i]), gaim_obj);
|
|
40 mono_array_set(array, MonoObject*, i, obj);
|
|
41 }
|
|
42 }
|
|
43
|
|
44 va_end(args);
|
|
45
|
|
46 meth_args[0] = array;
|
|
47
|
|
48 return mono_runtime_delegate_invoke(sig_data->func, meth_args, NULL);
|
|
49 }
|
|
50
|
|
51 static void cb_void__pointer(void *arg1, void *data)
|
|
52 {
|
|
53 dispatch_callback((SignalData*)data, ((SignalData*)data)->num_vals, arg1);
|
|
54
|
|
55 }
|
|
56
|
|
57 int gaim_signal_connect_glue(MonoObject* h, MonoObject *plugin, MonoString *signal, MonoObject *func)
|
|
58 {
|
|
59 char *sig;
|
|
60 void **instance = NULL;
|
|
61 SignalData *sig_data;
|
|
62
|
|
63 sig = mono_string_to_utf8(signal);
|
|
64 gaim_debug(GAIM_DEBUG_INFO, "mono", "connecting signal: %s\n", sig);
|
|
65
|
|
66 instance = (void*)mono_object_unbox(h);
|
|
67
|
|
68 sig_data = g_new0(SignalData, 1);
|
|
69
|
|
70 sig_data->func = func;
|
|
71 sig_data->signal = sig;
|
|
72
|
|
73 gaim_signal_get_values(*instance, sig, &sig_data->ret_value, &sig_data->num_vals, &sig_data->values);
|
|
74
|
|
75 return gaim_signal_connect(*instance, sig, (gpointer)mono_object_get_class(plugin), get_callback(sig_data), (gpointer)sig_data);
|
|
76 }
|
|
77
|
|
78 static int determine_index(GaimType type)
|
|
79 {
|
|
80 switch (type) {
|
|
81 case GAIM_TYPE_SUBTYPE:
|
|
82 case GAIM_TYPE_STRING:
|
|
83 case GAIM_TYPE_OBJECT:
|
|
84 case GAIM_TYPE_POINTER:
|
|
85 case GAIM_TYPE_BOXED:
|
|
86 return 1;
|
|
87 break;
|
|
88 default:
|
|
89 return type;
|
|
90 break;
|
|
91 }
|
|
92 }
|
|
93
|
|
94 static gpointer callbacks[]= {
|
|
95 NULL,
|
|
96 cb_void__pointer,
|
|
97 };
|
|
98
|
|
99 static int callbacks_array_size = sizeof(callbacks) / sizeof(GaimCallback);
|
|
100
|
|
101
|
|
102 static GaimCallback get_callback(SignalData *sig_data)
|
|
103 {
|
|
104 int i, index = 0;
|
|
105
|
|
106 if (sig_data->ret_value == NULL)
|
|
107 index = 0;
|
|
108 else
|
|
109 index = gaim_value_get_type(sig_data->ret_value);
|
|
110
|
|
111 for (i = 0; i < sig_data->num_vals; i++) {
|
|
112 index += determine_index(gaim_value_get_type(sig_data->values[i]));
|
|
113 }
|
|
114
|
|
115 if (index >= callbacks_array_size || callbacks[index] == NULL) {
|
|
116 gaim_debug(GAIM_DEBUG_ERROR, "mono", "couldn't find a callback function for signal: %s\n", sig_data->signal);
|
|
117 return NULL;
|
|
118 }
|
|
119
|
|
120 gaim_debug(GAIM_DEBUG_MISC, "mono", "using callback at index: %d\n", index);
|
|
121 return GAIM_CALLBACK(callbacks[index]);
|
|
122 }
|