| 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(ml_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 = ml_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 = ml_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 ml_delegate_invoke(sig_data->func, meth_args); |
|
| 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 static void cb_void__pointer_pointer_pointer(void *arg1, void *arg2, void *arg3, void *data) |
|
| 57 { |
|
| 58 dispatch_callback((SignalData*)data, ((SignalData*)data)->num_vals, arg1, arg2, arg3); |
|
| 59 } |
|
| 60 |
|
| 61 |
|
| 62 int gaim_signal_connect_glue(MonoObject* h, MonoObject *plugin, MonoString *signal, MonoObject *func) |
|
| 63 { |
|
| 64 char *sig; |
|
| 65 void **instance = NULL; |
|
| 66 SignalData *sig_data; |
|
| 67 GaimMonoPlugin *mplug; |
|
| 68 MonoClass *klass; |
|
| 69 |
|
| 70 sig = mono_string_to_utf8(signal); |
|
| 71 gaim_debug(GAIM_DEBUG_INFO, "mono", "connecting signal: %s\n", sig); |
|
| 72 |
|
| 73 instance = (void*)mono_object_unbox(h); |
|
| 74 |
|
| 75 sig_data = g_new0(SignalData, 1); |
|
| 76 |
|
| 77 sig_data->func = func; |
|
| 78 sig_data->signal = sig; |
|
| 79 |
|
| 80 gaim_signal_get_values(*instance, sig, &sig_data->ret_value, &sig_data->num_vals, &sig_data->values); |
|
| 81 |
|
| 82 klass = mono_object_get_class(plugin); |
|
| 83 |
|
| 84 mplug = ml_find_plugin_by_class(klass); |
|
| 85 |
|
| 86 mplug->signal_data = g_list_append(mplug->signal_data, (gpointer)sig_data); |
|
| 87 |
|
| 88 return gaim_signal_connect(*instance, sig, (gpointer)klass, get_callback(sig_data), (gpointer)sig_data); |
|
| 89 } |
|
| 90 |
|
| 91 static int determine_index(GaimType type) |
|
| 92 { |
|
| 93 switch (type) { |
|
| 94 case GAIM_TYPE_SUBTYPE: |
|
| 95 case GAIM_TYPE_STRING: |
|
| 96 case GAIM_TYPE_OBJECT: |
|
| 97 case GAIM_TYPE_POINTER: |
|
| 98 case GAIM_TYPE_BOXED: |
|
| 99 return 1; |
|
| 100 break; |
|
| 101 default: |
|
| 102 return type; |
|
| 103 break; |
|
| 104 } |
|
| 105 } |
|
| 106 |
|
| 107 static gpointer callbacks[]= { |
|
| 108 NULL, |
|
| 109 cb_void__pointer, |
|
| 110 NULL, |
|
| 111 cb_void__pointer_pointer_pointer |
|
| 112 }; |
|
| 113 |
|
| 114 static int callbacks_array_size = sizeof(callbacks) / sizeof(GaimCallback); |
|
| 115 |
|
| 116 |
|
| 117 static GaimCallback get_callback(SignalData *sig_data) |
|
| 118 { |
|
| 119 int i, index = 0; |
|
| 120 |
|
| 121 if (sig_data->ret_value == NULL) |
|
| 122 index = 0; |
|
| 123 else |
|
| 124 index = determine_index(gaim_value_get_type(sig_data->ret_value)); |
|
| 125 |
|
| 126 for (i = 0; i < sig_data->num_vals; i++) { |
|
| 127 index += determine_index(gaim_value_get_type(sig_data->values[i])); |
|
| 128 } |
|
| 129 |
|
| 130 gaim_debug(GAIM_DEBUG_INFO, "mono", "get_callback index = %d\n", index); |
|
| 131 |
|
| 132 if (index >= callbacks_array_size || callbacks[index] == NULL) { |
|
| 133 gaim_debug(GAIM_DEBUG_ERROR, "mono", "couldn't find a callback function for signal: %s\n", sig_data->signal); |
|
| 134 return NULL; |
|
| 135 } |
|
| 136 |
|
| 137 gaim_debug(GAIM_DEBUG_MISC, "mono", "using callback at index: %d\n", index); |
|
| 138 return GAIM_CALLBACK(callbacks[index]); |
|
| 139 } |
|