comparison plugins/musicmessaging/musicmessaging.c @ 11200:4295083cf489

[gaim-migrate @ 13328] Added dbus capabilities to the mm plugin committer: Tailor Script <tailor@pidgin.im>
author Christian Muise <christian.muise@gmail.com>
date Mon, 08 Aug 2005 01:40:41 +0000
parents 778d5464a9b8
children 1b32ad61e114
comparison
equal deleted inserted replaced
11199:30a3d97503be 11200:4295083cf489
1 /*
2 * Music messaging plugin for Gaim
3 *
4 * Copyright (C) 2005 Christian Muise.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
1 #include "internal.h" 22 #include "internal.h"
2 #include "gtkgaim.h" 23 #include "gtkgaim.h"
3 24
4 #include "conversation.h" 25 #include "conversation.h"
5 26
7 #include "gtkplugin.h" 28 #include "gtkplugin.h"
8 #include "gtkutils.h" 29 #include "gtkutils.h"
9 30
10 #include "notify.h" 31 #include "notify.h"
11 #include "version.h" 32 #include "version.h"
12 33 #include "debug.h"
13 #define MUSICMESSAGIN_PLUGIN_ID "gtk-hazure-musicmessaging" 34
14 35 #define DBUS_API_SUBJECT_TO_CHANGE
15 static gboolean start_session(void); 36 #include <dbus/dbus.h>
16 static void run_editor(void); 37 #include "dbus-maybe.h"
17 static void add_button (GaimConversation *conv); 38 #include "dbus-bindings.h"
18 static void remove_button (GtkWidget *button); 39 #include "dbus-server.h"
19 40
20 typedef struct { 41 #define MUSICMESSAGING_PLUGIN_ID "gtk-hazure-musicmessaging"
21 GaimBuddy *buddy; 42 #define MUSICMESSAGING_PREFIX "##MM##"
22 GtkWidget *window; 43 #define MUSICMESSAGING_START_TAG "<a href=mm-plugin>"
23 /* Something for the ly file? */ 44
24 45 /* Globals */
25 /* Anything else needed for a session? */
26
27 } MMSession;
28
29 /* List of sessions */ 46 /* List of sessions */
30 GList *sessions; 47 GList *conversations;
31
32 /* List of created buttons */
33 GList *widgets;
34 48
35 /* Pointer to this plugin */ 49 /* Pointer to this plugin */
36 GaimPlugin *plugin_pointer; 50 GaimPlugin *plugin_pointer;
37 51
52 /* Define types needed for DBus */
53
54 /* Define the functions to export for use with DBus */
55 DBUS_EXPORT void music_messaging_change_request (const char *command, const char *parameters);
56 DBUS_EXPORT void music_messaging_change_confirmed (const char *command, const char *parameters);
57 DBUS_EXPORT void music_messaging_change_failed (const char *id, const char *command, const char *parameters);
58 DBUS_EXPORT void music_messaging_done_session (void);
59
60 /* This file has been generated by the #dbus-analize-functions.py
61 script. It contains dbus wrappers for the four functions declared
62 above. */
63 #include "music-messaging-bindings.c"
64
65 /* Exported functions */
66 void music_messaging_change_request(const char *command, const char *parameters)
67 {
68 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_INFO, command,
69 parameters, NULL, NULL, NULL);
70 }
71
72 void music_messaging_change_confirmed(const char *command, const char *parameters)
73 {
74 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_INFO, command,
75 parameters, NULL, NULL, NULL);
76 }
77
78 void music_messaging_change_failed(const char *id, const char *command, const char *parameters)
79 {
80 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_INFO, command,
81 parameters, NULL, NULL, NULL);
82 }
83
84 void music_messaging_done_session(void)
85 {
86 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_INFO, "Session",
87 "Session Complete", NULL, NULL, NULL);
88 }
89
90 typedef struct {
91 GaimConversation *conv; /* pointer to the conversation */
92 GtkWidget *seperator; /* seperator in the conversation */
93 GtkWidget *button; /* button in the conversation */
94 GPid pid; /* the pid of the score editor */
95
96 gboolean started; /* session has started and editor run */
97 gboolean originator; /* started the mm session */
98 gboolean requested; /* received a request to start a session */
99
100 } MMConversation;
101
102 static gboolean start_session(MMConversation *mmconv);
103 static void run_editor(MMConversation *mmconv);
104 static void kill_editor(MMConversation *mmconv);
105 static void add_button (MMConversation *mmconv);
106 static void remove_widget (GtkWidget *button);
107 static void init_conversation (GaimConversation *conv);
108 static void conv_destroyed(GaimConversation *conv);
109 static void intercept_sent(GaimAccount *account, GaimConversation *conv, char **message, void* pData);
110 static void intercept_received(GaimAccount *account, char **sender, char **message, GaimConversation *conv, int *flags);
111
112
113 G_BEGIN_DECLS
114 DBusConnection *gaim_dbus_get_connection(void);
115 G_END_DECLS
116
117 void send_change_request (const char *id, const char *command, const char *parameters)
118 {
119 DBusMessage *signal;
120 signal = dbus_message_new_signal("/org/gscore/GScoreObject", "org.gscore.GScoreInterface", "gscore_change_request");
121
122 dbus_message_append_args(signal,
123 DBUS_TYPE_STRING, &id,
124 DBUS_TYPE_STRING, &command,
125 DBUS_TYPE_STRING, &parameters,
126 DBUS_TYPE_INVALID);
127
128 dbus_connection_send(gaim_dbus_get_connection(), signal, NULL);
129 dbus_message_unref(signal);
130 }
131
132 void send_change_confirmed (const char *command, const char *parameters)
133 {
134 DBusMessage *signal;
135 signal = dbus_message_new_signal("/org/gscore/GScoreObject", "org.gscore.GScoreInterface", "gscore_change_confirmed");
136
137 dbus_message_append_args(signal,
138 DBUS_TYPE_STRING, &command,
139 DBUS_TYPE_STRING, &parameters,
140 DBUS_TYPE_INVALID);
141
142 dbus_connection_send(gaim_dbus_get_connection(), signal, NULL);
143 dbus_message_unref(signal);
144 }
145
146
38 static gboolean 147 static gboolean
39 plugin_load(GaimPlugin *plugin) { 148 plugin_load(GaimPlugin *plugin) {
40 gaim_notify_message(plugin, GAIM_NOTIFY_MSG_INFO, "Welcome", 149 /* First, we have to register our four exported functions with the
150 main gaim dbus loop. Without this statement, the gaim dbus
151 code wouldn't know about our functions. */
152 GAIM_DBUS_REGISTER_BINDINGS(plugin);
153
154 gaim_notify_message(plugin, GAIM_NOTIFY_MSG_INFO, "Welcome",
41 "Welcome to music messaging.", NULL, NULL, NULL); 155 "Welcome to music messaging.", NULL, NULL, NULL);
42 /* Keep the plugin for reference (needed for notify's) */ 156 /* Keep the plugin for reference (needed for notify's) */
43 plugin_pointer = plugin; 157 plugin_pointer = plugin;
44 158
45 /* Add the button to all the current conversations */ 159 /* Add the button to all the current conversations */
46 gaim_conversation_foreach (add_button); 160 gaim_conversation_foreach (init_conversation);
47 161
48 /* Listen for any new conversations */ 162 /* Listen for any new conversations */
49 void *conv_list_handle = gaim_conversations_get_handle(); 163 void *conv_list_handle = gaim_conversations_get_handle();
50 164
51 gaim_signal_connect(conv_list_handle, "conversation-created", 165 gaim_signal_connect(conv_list_handle, "conversation-created",
52 plugin, GAIM_CALLBACK(add_button), NULL); 166 plugin, GAIM_CALLBACK(init_conversation), NULL);
167
168 /* Listen for conversations that are ending */
169 gaim_signal_connect(conv_list_handle, "deleting-conversation",
170 plugin, GAIM_CALLBACK(conv_destroyed), NULL);
171
172 /* Listen for sending/receiving messages to replace tags */
173 gaim_signal_connect(conv_list_handle, "writing-im-msg",
174 plugin, GAIM_CALLBACK(intercept_sent), NULL);
175 gaim_signal_connect(conv_list_handle, "receiving-im-msg",
176 plugin, GAIM_CALLBACK(intercept_received), NULL);
53 177
54 return TRUE; 178 return TRUE;
55 } 179 }
56 180
57 static gboolean 181 static gboolean
58 plugin_unload(GaimPlugin *plugin) { 182 plugin_unload(GaimPlugin *plugin) {
59 183
60 gaim_notify_message(plugin, GAIM_NOTIFY_MSG_INFO, "Unloaded", 184 gaim_notify_message(plugin, GAIM_NOTIFY_MSG_INFO, "Unloaded",
61 gaim_prefs_get_string ("/plugins/gtk/musicmessaging/editor_path"), NULL, NULL, NULL); 185 DATADIR, NULL, NULL, NULL);
62 186
63 g_list_foreach(widgets, (GFunc) remove_button, NULL); 187 MMConversation *mmconv = NULL;
188 while (g_list_length(conversations) > 0)
189 {
190 mmconv = g_list_first(conversations)->data;
191 conv_destroyed(mmconv->conv);
192 }
64 return TRUE; 193 return TRUE;
65 } 194 }
66 195
196 static void intercept_sent(GaimAccount *account, GaimConversation *conv, char **message, void* pData)
197 {
198 GaimConvIm *imData = gaim_conversation_get_im_data(conv);
199 GaimConnection *connection = gaim_conversation_get_gc(conv);
200 const char *convName = gaim_conversation_get_name(conv);
201 const char *who = gaim_account_get_username(account);
202
203 if (0 == strncmp(*message, MUSICMESSAGING_PREFIX, strlen(MUSICMESSAGING_PREFIX)))
204 {
205 message = 0;
206 gaim_debug(GAIM_DEBUG_MISC, "gaim-musicmessaging", "Received MM Message\n");
207 send_change_confirmed("the command", "the params");
208 }
209 else if (0 == strncmp(*message, MUSICMESSAGING_START_TAG, strlen(MUSICMESSAGING_START_TAG)))
210 {
211
212 }
213 else
214 {
215 serv_send_im(connection, convName, *message, GAIM_MESSAGE_SEND);
216 gaim_conv_im_write (imData, NULL, *message, GAIM_MESSAGE_SYSTEM, time(NULL));
217 }
218 }
219
220 static void intercept_received(GaimAccount *account, char **sender, char **message, GaimConversation *conv, int *flags)
221 {
222
223 }
224
225
67 static gboolean 226 static gboolean
68 start_session(void) 227 start_session(MMConversation *mmconv)
69 { 228 {
70 run_editor(); 229 mmconv->started = TRUE;
230 run_editor(mmconv);
71 return TRUE; 231 return TRUE;
72 } 232 }
73 233
74 static void music_button_toggled (GtkWidget *widget, gpointer data) 234 static void music_button_toggled (GtkWidget *widget, gpointer data)
75 { 235 {
76 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 236 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
77 { 237 {
78 start_session(); 238 start_session((MMConversation *) data);
79 } else { 239 } else {
80 240 kill_editor((MMConversation *) data);
81 /* kill program */
82 } 241 }
83 } 242 }
84 243
85 static void set_editor_path (GtkWidget *button, GtkWidget *text_field) 244 static void set_editor_path (GtkWidget *button, GtkWidget *text_field)
86 { 245 {
87 const char * path = gtk_entry_get_text((GtkEntry*)text_field); 246 const char * path = gtk_entry_get_text((GtkEntry*)text_field);
88 gaim_prefs_set_string("/plugins/gtk/musicmessaging/editor_path", path); 247 gaim_prefs_set_string("/plugins/gtk/musicmessaging/editor_path", path);
89 248
90 } 249 }
91 250
92 static void run_editor (void) 251 static void run_editor (MMConversation *mmconv)
93 { 252 {
94 GError *spawn_error = NULL; 253 GError *spawn_error = NULL;
95 gchar * args[2]; 254 gchar * args[2];
96 args[0] = (gchar *)gaim_prefs_get_string("/plugins/gtk/musicmessaging/editor_path"); 255 args[0] = (gchar *)gaim_prefs_get_string("/plugins/gtk/musicmessaging/editor_path");
97 args[1] = NULL; 256 args[1] = NULL;
98 if (!(g_spawn_async (".", args, NULL, 0, NULL, NULL, NULL, &spawn_error))) 257 if (!(g_spawn_async (".", args, NULL, 12, NULL, NULL, &(mmconv->pid), &spawn_error)))
99 { 258 {
100 gaim_notify_error(plugin_pointer, "Error Running Editor", 259 gaim_notify_error(plugin_pointer, "Error Running Editor",
101 "The following error has occured:", spawn_error->message); 260 "The following error has occured:", spawn_error->message);
102 } 261 }
103 } 262 }
104 263
105 static void add_button (GaimConversation *conv) 264 static void kill_editor (MMConversation *mmconv)
106 { 265 {
266 if (mmconv->pid)
267 {
268 kill(mmconv->pid, SIGINT);
269 mmconv->pid = 0;
270 }
271 }
272
273 static void init_conversation (GaimConversation *conv)
274 {
275 MMConversation *mmconv;
276 mmconv = g_malloc(sizeof(MMConversation));
277
278 mmconv->conv = conv;
279 mmconv->started = FALSE;
280 mmconv->originator = FALSE;
281 mmconv->requested = FALSE;
282
283 add_button(mmconv);
284
285 conversations = g_list_append(conversations, mmconv);
286 }
287
288 static void conv_destroyed (GaimConversation *conv)
289 {
290 MMConversation *mmconv_current = NULL;
291 MMConversation *mmconv = NULL;
292 guint i;
293
294 for (i = 0; i < g_list_length(conversations); i++)
295 {
296 mmconv_current = (MMConversation *)g_list_nth_data(conversations, i);
297 if (conv == mmconv_current->conv)
298 {
299 mmconv = mmconv_current;
300 }
301 }
302
303 remove_widget(mmconv->button);
304 remove_widget(mmconv->seperator);
305 if (mmconv->started)
306 {
307 kill_editor(mmconv);
308 }
309 conversations = g_list_remove(conversations, mmconv);
310 }
311
312 static void add_button (MMConversation *mmconv)
313 {
314 GaimConversation *conv = mmconv->conv;
315
107 GtkWidget *button, *image, *sep; 316 GtkWidget *button, *image, *sep;
108 317
109 button = gtk_toggle_button_new(); 318 button = gtk_toggle_button_new();
110 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); 319 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
111 320
112 g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(music_button_toggled), NULL); 321 g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(music_button_toggled), mmconv);
113 322
114 gchar *file_path = g_build_filename (DATADIR, "pixmaps", "gaim", "buttons", "music.png", NULL); 323 gchar *file_path = g_build_filename (DATADIR, "pixmaps", "gaim", "buttons", "music.png", NULL);
115 image = gtk_image_new_from_file("/usr/local/share/pixmaps/gaim/buttons/music.png"); 324 image = gtk_image_new_from_file("/usr/local/share/pixmaps/gaim/buttons/music.png");
116 325
117 gtk_container_add((GtkContainer *)button, image); 326 gtk_container_add((GtkContainer *)button, image);
118 327
119 sep = gtk_vseparator_new(); 328 sep = gtk_vseparator_new();
120 329
121 g_list_append(widgets, sep); 330 mmconv->seperator = sep;
122 g_list_append(widgets, button); 331 mmconv->button = button;
123 332
124 gtk_widget_show(sep); 333 gtk_widget_show(sep);
125 gtk_widget_show(image); 334 gtk_widget_show(image);
126 gtk_widget_show(button); 335 gtk_widget_show(button);
127 336
128 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), sep, FALSE, FALSE, 0); 337 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), sep, FALSE, FALSE, 0);
129 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), button, FALSE, FALSE, 0); 338 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), button, FALSE, FALSE, 0);
130 } 339 }
131 340
132 static void remove_button (GtkWidget *button) 341 static void remove_widget (GtkWidget *button)
133 { 342 {
134 gtk_widget_hide(button); 343 gtk_widget_hide(button);
135 gtk_widget_destroy(button); 344 gtk_widget_destroy(button);
136 } 345 }
137 346
184 GAIM_GTK_PLUGIN_TYPE, 393 GAIM_GTK_PLUGIN_TYPE,
185 0, 394 0,
186 NULL, 395 NULL,
187 GAIM_PRIORITY_DEFAULT, 396 GAIM_PRIORITY_DEFAULT,
188 397
189 MUSICMESSAGIN_PLUGIN_ID, 398 MUSICMESSAGING_PLUGIN_ID,
190 "Music Messaging", 399 "Music Messaging",
191 VERSION, 400 VERSION,
192 "Music Messaging Plugin for collabrative composition.", 401 "Music Messaging Plugin for collabrative composition.",
193 "The Music Messaging Plugin allows a number of users to simultaniously work on a piece of music by editting a common score in real-time.", 402 "The Music Messaging Plugin allows a number of users to simultaniously work on a piece of music by editting a common score in real-time.",
194 "Christian Muise <christian.muise@gmail.com>", 403 "Christian Muise <christian.muise@gmail.com>",