remove mmx asm
[rofl0r-ixchat.git] / src / common / dbus / dbus-plugin.c
blob012812cc72424c671db3cea146df1129224a396c
1 /* dbus-plugin.c - xchat plugin for remote access using D-Bus
2 * Copyright (C) 2006 Claessens Xavier
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 * Claessens Xavier
19 * xclaesse@gmail.com
22 #define DBUS_API_SUBJECT_TO_CHANGE
24 #include <config.h>
25 #include <dbus/dbus-glib.h>
26 #include <dbus/dbus-glib-lowlevel.h>
27 #include <glib/gi18n.h>
28 #include "../xchat-plugin.h"
30 #define PNAME _("remote access")
31 #define PDESC _("plugin for remote access using DBUS")
32 #define PVERSION ""
34 #define DBUS_SERVICE "org.xchat.service"
35 #define DBUS_OBJECT_PATH "/org/xchat"
37 static xchat_plugin *ph;
38 static guint last_context_id = 0;
39 static GList *contexts = NULL;
40 static GHashTable *clients = NULL;
41 static DBusGConnection *connection;
43 typedef struct RemoteObject RemoteObject;
44 typedef struct RemoteObjectClass RemoteObjectClass;
46 GType Remote_object_get_type (void);
48 struct RemoteObject
50 GObject parent;
52 guint last_hook_id;
53 guint last_list_id;
54 xchat_context *context;
55 char *dbus_path;
56 char *filename;
57 GHashTable *hooks;
58 GHashTable *lists;
59 void *handle;
62 struct RemoteObjectClass
64 GObjectClass parent;
67 typedef struct
69 guint id;
70 int return_value;
71 xchat_hook *hook;
72 RemoteObject *obj;
73 } HookInfo;
75 typedef struct
77 guint id;
78 xchat_context *context;
79 } ContextInfo;
81 enum
83 SERVER_SIGNAL,
84 COMMAND_SIGNAL,
85 PRINT_SIGNAL,
86 UNLOAD_SIGNAL,
87 LAST_SIGNAL
90 static guint signals[LAST_SIGNAL] = { 0 };
92 #define REMOTE_TYPE_OBJECT (remote_object_get_type ())
93 #define REMOTE_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), REMOTE_TYPE_OBJECT, RemoteObject))
94 #define REMOTE_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), REMOTE_TYPE_OBJECT, RemoteObjectClass))
95 #define REMOTE_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), REMOTE_TYPE_OBJECT))
96 #define REMOTE_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), REMOTE_TYPE_OBJECT))
97 #define REMOTE_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), REMOTE_TYPE_OBJECT, RemoteObjectClass))
98 #define REMOTE_OBJECT_ERROR (remote_object_error_quark ())
99 #define REMOTE_TYPE_ERROR (remote_object_error_get_type ())
101 G_DEFINE_TYPE (RemoteObject, remote_object, G_TYPE_OBJECT)
103 /* Available services */
105 static gboolean remote_object_connect (RemoteObject *obj,
106 const char *filename,
107 const char *name,
108 const char *desc,
109 const char *version,
110 DBusGMethodInvocation *context);
112 static gboolean remote_object_disconnect (RemoteObject *obj,
113 DBusGMethodInvocation *context);
115 static gboolean remote_object_command (RemoteObject *obj,
116 const char *command,
117 GError **error);
119 static gboolean remote_object_print (RemoteObject *obj,
120 const char *text,
121 GError **error);
123 static gboolean remote_object_find_context (RemoteObject *obj,
124 const char *server,
125 const char *channel,
126 guint *ret_id,
127 GError **error);
129 static gboolean remote_object_get_context (RemoteObject *obj,
130 guint *ret_id,
131 GError **error);
133 static gboolean remote_object_set_context (RemoteObject *obj,
134 guint id,
135 gboolean *ret,
136 GError **error);
138 static gboolean remote_object_print (RemoteObject *obj,
139 const char *text,
140 GError **error);
142 static gboolean remote_object_get_info (RemoteObject *obj,
143 const char *id,
144 char **ret_info,
145 GError **error);
147 static gboolean remote_object_get_prefs (RemoteObject *obj,
148 const char *name,
149 int *ret_type,
150 char **ret_str,
151 int *ret_int,
152 GError **error);
154 static gboolean remote_object_hook_command (RemoteObject *obj,
155 const char *name,
156 int pri,
157 const char *help_text,
158 int return_value,
159 guint *ret_id,
160 GError **error);
162 static gboolean remote_object_hook_server (RemoteObject *obj,
163 const char *name,
164 int pri,
165 int return_value,
166 guint *ret_id,
167 GError **error);
169 static gboolean remote_object_hook_print (RemoteObject *obj,
170 const char *name,
171 int pri,
172 int return_value,
173 guint *ret_id,
174 GError **error);
176 static gboolean remote_object_unhook (RemoteObject *obj,
177 guint id,
178 GError **error);
180 static gboolean remote_object_list_get (RemoteObject *obj,
181 const char *name,
182 guint *ret_id,
183 GError **error);
185 static gboolean remote_object_list_next (RemoteObject *obj,
186 guint id,
187 gboolean *ret,
188 GError **error);
190 static gboolean remote_object_list_str (RemoteObject *obj,
191 guint id,
192 const char *name,
193 char **ret_str,
194 GError **error);
196 static gboolean remote_object_list_int (RemoteObject *obj,
197 guint id,
198 const char *name,
199 int *ret_int,
200 GError **error);
202 static gboolean remote_object_list_time (RemoteObject *obj,
203 guint id,
204 const char *name,
205 guint64 *ret_time,
206 GError **error);
208 static gboolean remote_object_list_fields (RemoteObject *obj,
209 const char *name,
210 char ***ret,
211 GError **error);
213 static gboolean remote_object_list_free (RemoteObject *obj,
214 guint id,
215 GError **error);
217 static gboolean remote_object_emit_print (RemoteObject *obj,
218 const char *event_name,
219 const char *args[],
220 gboolean *ret,
221 GError **error);
223 static gboolean remote_object_nickcmp (RemoteObject *obj,
224 const char *nick1,
225 const char *nick2,
226 int *ret,
227 GError **error);
229 static gboolean remote_object_strip (RemoteObject *obj,
230 const char *str,
231 int len,
232 int flag,
233 char **ret_str,
234 GError **error);
236 static gboolean remote_object_send_modes (RemoteObject *obj,
237 const char *targets[],
238 int modes_per_line,
239 char sign,
240 char mode,
241 GError **error);
243 #include "remote-object-glue.h"
244 #include "marshallers.h"
246 /* Useful functions */
248 static char** build_list (char *word[]);
249 static guint context_list_find_id (xchat_context *context);
250 static xchat_context* context_list_find_context (guint id);
252 /* Remote Object */
254 static void
255 hook_info_destroy (gpointer data)
257 HookInfo *info = (HookInfo*)data;
259 if (info == NULL) {
260 return;
262 xchat_unhook (ph, info->hook);
263 g_free (info);
266 static void
267 list_info_destroy (gpointer data)
269 xchat_list_free (ph, (xchat_list*)data);
272 static void
273 remote_object_finalize (GObject *obj)
275 RemoteObject *self = (RemoteObject*)obj;
277 g_hash_table_destroy (self->lists);
278 g_hash_table_destroy (self->hooks);
279 g_free (self->dbus_path);
280 g_free (self->filename);
281 xchat_plugingui_remove (ph, self->handle);
283 G_OBJECT_CLASS (remote_object_parent_class)->finalize (obj);
286 static void
287 remote_object_init (RemoteObject *obj)
289 obj->hooks =
290 g_hash_table_new_full (g_int_hash,
291 g_int_equal,
292 NULL,
293 hook_info_destroy);
295 obj->lists =
296 g_hash_table_new_full (g_int_hash,
297 g_int_equal,
298 g_free,
299 list_info_destroy);
300 obj->dbus_path = NULL;
301 obj->filename = NULL;
302 obj->last_hook_id = 0;
303 obj->last_list_id = 0;
304 obj->context = xchat_get_context (ph);
307 static void
308 remote_object_class_init (RemoteObjectClass *klass)
310 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
312 gobject_class->finalize = remote_object_finalize;
314 signals[SERVER_SIGNAL] =
315 g_signal_new ("server_signal",
316 G_OBJECT_CLASS_TYPE (klass),
317 G_SIGNAL_RUN_LAST,
319 NULL, NULL,
320 g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
321 G_TYPE_NONE,
322 4, G_TYPE_STRV, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT);
324 signals[COMMAND_SIGNAL] =
325 g_signal_new ("command_signal",
326 G_OBJECT_CLASS_TYPE (klass),
327 G_SIGNAL_RUN_LAST,
329 NULL, NULL,
330 g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
331 G_TYPE_NONE,
332 4, G_TYPE_STRV, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT);
334 signals[PRINT_SIGNAL] =
335 g_signal_new ("print_signal",
336 G_OBJECT_CLASS_TYPE (klass),
337 G_SIGNAL_RUN_LAST,
339 NULL, NULL,
340 g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
341 G_TYPE_NONE,
342 3, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT);
344 signals[UNLOAD_SIGNAL] =
345 g_signal_new ("unload_signal",
346 G_OBJECT_CLASS_TYPE (klass),
347 G_SIGNAL_RUN_LAST,
349 NULL, NULL,
350 g_cclosure_marshal_VOID__VOID,
351 G_TYPE_NONE,
355 /* Implementation of services */
357 static gboolean
358 remote_object_connect (RemoteObject *obj,
359 const char *filename,
360 const char *name,
361 const char *desc,
362 const char *version,
363 DBusGMethodInvocation *context)
365 static guint count = 0;
366 char *sender, *path;
367 RemoteObject *remote_object;
369 sender = dbus_g_method_get_sender (context);
370 remote_object = g_hash_table_lookup (clients, sender);
371 if (remote_object != NULL) {
372 dbus_g_method_return (context, remote_object->dbus_path);
373 g_free (sender);
374 return TRUE;
376 path = g_strdup_printf (DBUS_OBJECT_PATH"/%d", count++);
377 remote_object = g_object_new (REMOTE_TYPE_OBJECT, NULL);
378 remote_object->dbus_path = path;
379 remote_object->filename = g_path_get_basename (filename);
380 remote_object->handle = xchat_plugingui_add (ph,
381 remote_object->filename,
382 name,
383 desc,
384 version, NULL);
385 dbus_g_connection_register_g_object (connection,
386 path,
387 G_OBJECT (remote_object));
389 g_hash_table_insert (clients,
390 sender,
391 remote_object);
393 dbus_g_method_return (context, path);
394 return TRUE;
397 static gboolean
398 remote_object_disconnect (RemoteObject *obj,
399 DBusGMethodInvocation *context)
401 char *sender;
403 sender = dbus_g_method_get_sender (context);
404 g_hash_table_remove (clients, sender);
405 g_free (sender);
407 dbus_g_method_return (context);
408 return TRUE;
411 static gboolean
412 remote_object_command (RemoteObject *obj,
413 const char *command,
414 GError **error)
416 if (xchat_set_context (ph, obj->context)) {
417 xchat_command (ph, command);
419 return TRUE;
422 static gboolean
423 remote_object_print (RemoteObject *obj,
424 const char *text,
425 GError **error)
427 if (xchat_set_context (ph, obj->context)) {
428 xchat_print (ph, text);
430 return TRUE;
433 static gboolean
434 remote_object_find_context (RemoteObject *obj,
435 const char *server,
436 const char *channel,
437 guint *ret_id,
438 GError **error)
440 xchat_context *context;
442 if (*server == '\0') {
443 server = NULL;
445 if (*channel == '\0') {
446 channel = NULL;
448 context = xchat_find_context (ph, server, channel);
449 *ret_id = context_list_find_id (context);
451 return TRUE;
454 static gboolean
455 remote_object_get_context (RemoteObject *obj,
456 guint *ret_id,
457 GError **error)
459 *ret_id = context_list_find_id (obj->context);
460 return TRUE;
463 static gboolean
464 remote_object_set_context (RemoteObject *obj,
465 guint id,
466 gboolean *ret,
467 GError **error)
469 xchat_context *context;
471 context = context_list_find_context (id);
472 if (context == NULL) {
473 *ret = FALSE;
474 return TRUE;
476 obj->context = context;
477 *ret = TRUE;
479 return TRUE;
482 static gboolean
483 remote_object_get_info (RemoteObject *obj,
484 const char *id,
485 char **ret_info,
486 GError **error)
488 /* win_ptr is a GtkWindow* casted to char* and will crash
489 * D-Bus if we send it as a string */
490 if (!xchat_set_context (ph, obj->context) ||
491 g_str_equal (id, "win_ptr")) {
492 *ret_info = NULL;
493 return TRUE;
495 *ret_info = g_strdup (xchat_get_info (ph, id));
496 return TRUE;
499 static gboolean
500 remote_object_get_prefs (RemoteObject *obj,
501 const char *name,
502 int *ret_type,
503 char **ret_str,
504 int *ret_int,
505 GError **error)
507 const char *str;
509 if (!xchat_set_context (ph, obj->context)) {
510 *ret_type = 0;
511 return TRUE;
513 *ret_type = xchat_get_prefs (ph, name, &str, ret_int);
514 *ret_str = g_strdup (str);
516 return TRUE;
519 static int
520 server_hook_cb (char *word[],
521 char *word_eol[],
522 void *userdata)
524 HookInfo *info = (HookInfo*)userdata;
525 char **arg1;
526 char **arg2;
528 arg1 = build_list (word + 1);
529 arg2 = build_list (word_eol + 1);
530 info->obj->context = xchat_get_context (ph);
531 g_signal_emit (info->obj,
532 signals[SERVER_SIGNAL],
534 arg1, arg2, info->id,
535 context_list_find_id (info->obj->context));
536 g_strfreev (arg1);
537 g_strfreev (arg2);
539 return info->return_value;
542 static int
543 command_hook_cb (char *word[],
544 char *word_eol[],
545 void *userdata)
547 HookInfo *info = (HookInfo*)userdata;
548 char **arg1;
549 char **arg2;
551 arg1 = build_list (word + 1);
552 arg2 = build_list (word_eol + 1);
553 info->obj->context = xchat_get_context (ph);
554 g_signal_emit (info->obj,
555 signals[COMMAND_SIGNAL],
557 arg1, arg2, info->id,
558 context_list_find_id (info->obj->context));
559 g_strfreev (arg1);
560 g_strfreev (arg2);
562 return info->return_value;
565 static int
566 print_hook_cb (char *word[],
567 void *userdata)
569 HookInfo *info = (HookInfo*)userdata;
570 char **arg1;
572 arg1 = build_list (word + 1);
573 info->obj->context = xchat_get_context (ph);
574 g_signal_emit (info->obj,
575 signals[PRINT_SIGNAL],
577 arg1, info->id,
578 context_list_find_id (info->obj->context));
579 g_strfreev (arg1);
581 return info->return_value;
584 static gboolean
585 remote_object_hook_command (RemoteObject *obj,
586 const char *name,
587 int priority,
588 const char *help_text,
589 int return_value,
590 guint *ret_id,
591 GError **error)
593 HookInfo *info;
595 info = g_new0 (HookInfo, 1);
596 info->obj = obj;
597 info->return_value = return_value;
598 info->id = ++obj->last_hook_id;
599 info->hook = xchat_hook_command (ph,
600 name,
601 priority,
602 command_hook_cb,
603 help_text,
604 info);
605 g_hash_table_insert (obj->hooks, &info->id, info);
606 *ret_id = info->id;
608 return TRUE;
611 static gboolean
612 remote_object_hook_server (RemoteObject *obj,
613 const char *name,
614 int priority,
615 int return_value,
616 guint *ret_id,
617 GError **error)
619 HookInfo *info;
621 info = g_new0 (HookInfo, 1);
622 info->obj = obj;
623 info->return_value = return_value;
624 info->id = ++obj->last_hook_id;
625 info->hook = xchat_hook_server (ph,
626 name,
627 priority,
628 server_hook_cb,
629 info);
630 g_hash_table_insert (obj->hooks, &info->id, info);
631 *ret_id = info->id;
633 return TRUE;
636 static gboolean
637 remote_object_hook_print (RemoteObject *obj,
638 const char *name,
639 int priority,
640 int return_value,
641 guint *ret_id,
642 GError **error)
644 HookInfo *info;
646 info = g_new0 (HookInfo, 1);
647 info->obj = obj;
648 info->return_value = return_value;
649 info->id = ++obj->last_hook_id;
650 info->hook = xchat_hook_print (ph,
651 name,
652 priority,
653 print_hook_cb,
654 info);
655 g_hash_table_insert (obj->hooks, &info->id, info);
656 *ret_id = info->id;
658 return TRUE;
661 static gboolean
662 remote_object_unhook (RemoteObject *obj,
663 guint id,
664 GError **error)
666 g_hash_table_remove (obj->hooks, &id);
667 return TRUE;
670 static gboolean
671 remote_object_list_get (RemoteObject *obj,
672 const char *name,
673 guint *ret_id,
674 GError **error)
676 xchat_list *xlist;
677 guint *id;
679 if (!xchat_set_context (ph, obj->context)) {
680 *ret_id = 0;
681 return TRUE;
683 xlist = xchat_list_get (ph, name);
684 if (xlist == NULL) {
685 *ret_id = 0;
686 return TRUE;
688 id = g_new (guint, 1);
689 *id = ++obj->last_list_id;
690 *ret_id = *id;
691 g_hash_table_insert (obj->lists,
693 xlist);
695 return TRUE;
698 static gboolean
699 remote_object_list_next (RemoteObject *obj,
700 guint id,
701 gboolean *ret,
702 GError **error)
704 xchat_list *xlist;
706 xlist = g_hash_table_lookup (obj->lists, &id);
707 if (xlist == NULL) {
708 *ret = FALSE;
709 return TRUE;
711 *ret = xchat_list_next (ph, xlist);
713 return TRUE;
716 static gboolean
717 remote_object_list_str (RemoteObject *obj,
718 guint id,
719 const char *name,
720 char **ret_str,
721 GError **error)
723 xchat_list *xlist;
725 xlist = g_hash_table_lookup (obj->lists, &id);
726 if (xlist == NULL && !xchat_set_context (ph, obj->context)) {
727 *ret_str = NULL;
728 return TRUE;
730 if (g_str_equal (name, "context")) {
731 *ret_str = NULL;
732 return TRUE;
734 *ret_str = g_strdup (xchat_list_str (ph, xlist, name));
736 return TRUE;
739 static gboolean
740 remote_object_list_int (RemoteObject *obj,
741 guint id,
742 const char *name,
743 int *ret_int,
744 GError **error)
746 xchat_list *xlist;
748 xlist = g_hash_table_lookup (obj->lists, &id);
749 if (xlist == NULL && !xchat_set_context (ph, obj->context)) {
750 *ret_int = -1;
751 return TRUE;
753 if (g_str_equal (name, "context")) {
754 xchat_context *context;
755 context = (xchat_context*)xchat_list_str (ph, xlist, name);
756 *ret_int = context_list_find_id (context);
757 } else {
758 *ret_int = xchat_list_int (ph, xlist, name);
761 return TRUE;
764 static gboolean
765 remote_object_list_time (RemoteObject *obj,
766 guint id,
767 const char *name,
768 guint64 *ret_time,
769 GError **error)
771 xchat_list *xlist;
773 xlist = g_hash_table_lookup (obj->lists, &id);
774 if (xlist == NULL) {
775 *ret_time = (guint64) -1;
776 return TRUE;
778 *ret_time = xchat_list_time (ph, xlist, name);
780 return TRUE;
783 static gboolean
784 remote_object_list_fields (RemoteObject *obj,
785 const char *name,
786 char ***ret,
787 GError **error)
789 *ret = g_strdupv ((char**)xchat_list_fields (ph, name));
790 if (*ret == NULL) {
791 *ret = g_new0 (char*, 1);
793 return TRUE;
796 static gboolean
797 remote_object_list_free (RemoteObject *obj,
798 guint id,
799 GError **error)
801 g_hash_table_remove (obj->lists, &id);
802 return TRUE;
805 static gboolean
806 remote_object_emit_print (RemoteObject *obj,
807 const char *event_name,
808 const char *args[],
809 gboolean *ret,
810 GError **error)
812 const char *argv[4] = {NULL, NULL, NULL, NULL};
813 int i;
815 for (i = 0; i < 4 && args[i] != NULL; i++) {
816 argv[i] = args[i];
819 *ret = xchat_set_context (ph, obj->context);
820 if (*ret) {
821 *ret = xchat_emit_print (ph, event_name, argv[0], argv[1],
822 argv[2], argv[3]);
825 return TRUE;
828 static gboolean
829 remote_object_nickcmp (RemoteObject *obj,
830 const char *nick1,
831 const char *nick2,
832 int *ret,
833 GError **error)
835 xchat_set_context (ph, obj->context);
836 *ret = xchat_nickcmp (ph, nick1, nick2);
837 return TRUE;
840 static gboolean
841 remote_object_strip (RemoteObject *obj,
842 const char *str,
843 int len,
844 int flag,
845 char **ret_str,
846 GError **error)
848 *ret_str = xchat_strip (ph, str, len, flag);
849 return TRUE;
852 static gboolean
853 remote_object_send_modes (RemoteObject *obj,
854 const char *targets[],
855 int modes_per_line,
856 char sign,
857 char mode,
858 GError **error)
860 if (xchat_set_context (ph, obj->context)) {
861 xchat_send_modes (ph, targets,
862 g_strv_length ((char**)targets),
863 modes_per_line,
864 sign, mode);
866 return TRUE;
869 /* DBUS stuffs */
871 static void
872 name_owner_changed (DBusGProxy *driver_proxy,
873 const char *name,
874 const char *old_owner,
875 const char *new_owner,
876 void *user_data)
878 if (*new_owner == '\0') {
879 /* this name has vanished */
880 g_hash_table_remove (clients, name);
884 static gboolean
885 init_dbus (void)
887 DBusGProxy *proxy;
888 RemoteObject *remote;
889 guint request_name_result;
890 GError *error = NULL;
892 dbus_g_object_type_install_info (REMOTE_TYPE_OBJECT,
893 &dbus_glib_remote_object_object_info);
895 connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
896 if (connection == NULL) {
897 xchat_printf (ph, _("Couldn't connect to session bus: %s\n"),
898 error->message);
899 g_error_free (error);
900 return FALSE;
903 proxy = dbus_g_proxy_new_for_name (connection,
904 DBUS_SERVICE_DBUS,
905 DBUS_PATH_DBUS,
906 DBUS_INTERFACE_DBUS);
908 if (!dbus_g_proxy_call (proxy, "RequestName", &error,
909 G_TYPE_STRING, DBUS_SERVICE,
910 G_TYPE_UINT, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
911 G_TYPE_INVALID,
912 G_TYPE_UINT, &request_name_result,
913 G_TYPE_INVALID)) {
914 xchat_printf (ph, _("Failed to acquire %s: %s\n"),
915 DBUS_SERVICE,
916 error->message);
917 g_error_free (error);
919 return FALSE;
922 dbus_g_proxy_add_signal (proxy, "NameOwnerChanged",
923 G_TYPE_STRING,
924 G_TYPE_STRING,
925 G_TYPE_STRING,
926 G_TYPE_INVALID);
927 dbus_g_proxy_connect_signal (proxy, "NameOwnerChanged",
928 G_CALLBACK (name_owner_changed),
929 NULL, NULL);
931 remote = g_object_new (REMOTE_TYPE_OBJECT, NULL);
932 dbus_g_connection_register_g_object (connection,
933 DBUS_OBJECT_PATH"/Remote",
934 G_OBJECT (remote));
936 return TRUE;
939 /* xchat_plugin stuffs */
941 static char**
942 build_list (char *word[])
944 guint i;
945 guint num = 0;
946 char **result;
948 if (word == NULL) {
949 return NULL;
952 while (word[num] && word[num][0]) {
953 num++;
956 result = g_new0 (char*, num + 1);
957 for (i = 0; i < num; i++) {
958 result[i] = g_strdup (word[i]);
961 return result;
964 static guint
965 context_list_find_id (xchat_context *context)
967 GList *l = NULL;
969 for (l = contexts; l != NULL; l = l->next) {
970 if (((ContextInfo*)l->data)->context == context) {
971 return ((ContextInfo*)l->data)->id;
975 return 0;
978 static xchat_context*
979 context_list_find_context (guint id)
981 GList *l = NULL;
983 for (l = contexts; l != NULL; l = l->next) {
984 if (((ContextInfo*)l->data)->id == id) {
985 return ((ContextInfo*)l->data)->context;
989 return NULL;
992 static int
993 open_context_cb (char *word[],
994 void *userdata)
996 ContextInfo *info;
998 info = g_new0 (ContextInfo, 1);
999 info->id = ++last_context_id;
1000 info->context = xchat_get_context (ph);
1001 contexts = g_list_prepend (contexts, info);
1003 return XCHAT_EAT_NONE;
1006 static int
1007 close_context_cb (char *word[],
1008 void *userdata)
1010 GList *l;
1011 xchat_context *context = xchat_get_context (ph);
1013 for (l = contexts; l != NULL; l = l->next) {
1014 if (((ContextInfo*)l->data)->context == context) {
1015 g_free (l->data);
1016 contexts = g_list_delete_link (contexts, l);
1017 break;
1021 return XCHAT_EAT_NONE;
1024 static gboolean
1025 clients_find_filename_foreach (gpointer key,
1026 gpointer value,
1027 gpointer user_data)
1029 RemoteObject *obj = REMOTE_OBJECT (value);
1030 return g_str_equal (obj->filename, (char*)user_data);
1033 static int
1034 unload_plugin_cb (char *word[], char *word_eol[], void *userdata)
1036 RemoteObject *obj;
1038 obj = g_hash_table_find (clients,
1039 clients_find_filename_foreach,
1040 word[2]);
1041 if (obj != NULL) {
1042 g_signal_emit (obj,
1043 signals[UNLOAD_SIGNAL],
1045 return XCHAT_EAT_ALL;
1048 return XCHAT_EAT_NONE;
1052 dbus_plugin_init (xchat_plugin *plugin_handle,
1053 char **plugin_name,
1054 char **plugin_desc,
1055 char **plugin_version,
1056 char *arg)
1058 ph = plugin_handle;
1059 *plugin_name = PNAME;
1060 *plugin_desc = PDESC;
1061 *plugin_version = PVERSION;
1063 if (init_dbus()) {
1064 /*xchat_printf (ph, _("%s loaded successfully!\n"), PNAME);*/
1066 clients = g_hash_table_new_full (g_str_hash,
1067 g_str_equal,
1068 g_free,
1069 g_object_unref);
1071 xchat_hook_print (ph, "Open Context",
1072 XCHAT_PRI_NORM,
1073 open_context_cb,
1074 NULL);
1076 xchat_hook_print (ph, "Close Context",
1077 XCHAT_PRI_NORM,
1078 close_context_cb,
1079 NULL);
1081 xchat_hook_command (ph, "unload",
1082 XCHAT_PRI_HIGHEST,
1083 unload_plugin_cb, NULL, NULL);
1086 return TRUE;