| |
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 |
| |
22 #include "internal.h" |
| |
23 #include "gtkgaim.h" |
| |
24 |
| |
25 #include "conversation.h" |
| |
26 |
| |
27 #include "gtkconv.h" |
| |
28 #include "gtkplugin.h" |
| |
29 #include "gtkutils.h" |
| |
30 |
| |
31 #include "notify.h" |
| |
32 #include "version.h" |
| |
33 #include "debug.h" |
| |
34 |
| |
35 #define DBUS_API_SUBJECT_TO_CHANGE |
| |
36 #include <dbus/dbus.h> |
| |
37 #include "dbus-maybe.h" |
| |
38 #include "dbus-bindings.h" |
| |
39 #include "dbus-server.h" |
| |
40 #include "dbus-gaim.h" |
| |
41 |
| |
42 #define MUSICMESSAGING_PLUGIN_ID "gtk-hazure-musicmessaging" |
| |
43 #define MUSICMESSAGING_PREFIX "##MM##" |
| |
44 #define MUSICMESSAGING_START_MSG _("A music messaging session has been requested. Please click the MM icon to accept.") |
| |
45 #define MUSICMESSAGING_CONFIRM_MSG _("Music messaging session confirmed.") |
| |
46 |
| |
47 typedef struct { |
| |
48 GaimConversation *conv; /* pointer to the conversation */ |
| |
49 GtkWidget *seperator; /* seperator in the conversation */ |
| |
50 GtkWidget *button; /* button in the conversation */ |
| |
51 GPid pid; /* the pid of the score editor */ |
| |
52 |
| |
53 gboolean started; /* session has started and editor run */ |
| |
54 gboolean originator; /* started the mm session */ |
| |
55 gboolean requested; /* received a request to start a session */ |
| |
56 |
| |
57 } MMConversation; |
| |
58 |
| |
59 static gboolean start_session(MMConversation *mmconv); |
| |
60 static void run_editor(MMConversation *mmconv); |
| |
61 static void kill_editor(MMConversation *mmconv); |
| |
62 static void add_button (MMConversation *mmconv); |
| |
63 static void remove_widget (GtkWidget *button); |
| |
64 static void init_conversation (GaimConversation *conv); |
| |
65 static void conv_destroyed(GaimConversation *conv); |
| |
66 static gboolean intercept_sent(GaimAccount *account, const char *who, char **message, void* pData); |
| |
67 static gboolean intercept_received(GaimAccount *account, char **sender, char **message, GaimConversation *conv, int *flags); |
| |
68 static gboolean send_change_request (const int session, const char *id, const char *command, const char *parameters); |
| |
69 static gboolean send_change_confirmed (const int session, const char *command, const char *parameters); |
| |
70 static void session_end (MMConversation *mmconv); |
| |
71 |
| |
72 /* Globals */ |
| |
73 /* List of sessions */ |
| |
74 GList *conversations; |
| |
75 |
| |
76 /* Pointer to this plugin */ |
| |
77 GaimPlugin *plugin_pointer; |
| |
78 |
| |
79 /* Define types needed for DBus */ |
| |
80 DBusGConnection *connection; |
| |
81 DBusGProxy *proxy; |
| |
82 #define DBUS_SERVICE_GSCORE "org.gscore.GScoreService" |
| |
83 #define DBUS_PATH_GSCORE "/org/gscore/GScoreObject" |
| |
84 #define DBUS_INTERFACE_GSCORE "org.gscore.GScoreInterface" |
| |
85 |
| |
86 /* Define the functions to export for use with DBus */ |
| |
87 DBUS_EXPORT void music_messaging_change_request (const int session, const char *command, const char *parameters); |
| |
88 DBUS_EXPORT void music_messaging_change_confirmed (const int session, const char *command, const char *parameters); |
| |
89 DBUS_EXPORT void music_messaging_change_failed (const int session, const char *id, const char *command, const char *parameters); |
| |
90 DBUS_EXPORT void music_messaging_done_session (const int session); |
| |
91 |
| |
92 /* This file has been generated by the #dbus-analize-functions.py |
| |
93 script. It contains dbus wrappers for the four functions declared |
| |
94 above. */ |
| |
95 #include "music-messaging-bindings.c" |
| |
96 |
| |
97 /* Exported functions */ |
| |
98 void music_messaging_change_request(const int session, const char *command, const char *parameters) |
| |
99 { |
| |
100 |
| |
101 MMConversation *mmconv = (MMConversation *)g_list_nth_data(conversations, session); |
| |
102 |
| |
103 if (mmconv->started) |
| |
104 { |
| |
105 if (mmconv->originator) |
| |
106 { |
| |
107 char *name = (mmconv->conv)->name; |
| |
108 send_change_request (session, name, command, parameters); |
| |
109 } else |
| |
110 { |
| |
111 GString *to_send = g_string_new(""); |
| |
112 g_string_append_printf(to_send, "##MM## request %s %s##MM##", command, parameters); |
| |
113 |
| |
114 gaim_conv_im_send(GAIM_CONV_IM(mmconv->conv), to_send->str); |
| |
115 |
| |
116 gaim_debug_misc("Sent request: %s\n", to_send->str); |
| |
117 } |
| |
118 } |
| |
119 |
| |
120 } |
| |
121 |
| |
122 void music_messaging_change_confirmed(const int session, const char *command, const char *parameters) |
| |
123 { |
| |
124 |
| |
125 MMConversation *mmconv = (MMConversation *)g_list_nth_data(conversations, session); |
| |
126 |
| |
127 if (mmconv->started) |
| |
128 { |
| |
129 if (mmconv->originator) |
| |
130 { |
| |
131 GString *to_send = g_string_new(""); |
| |
132 g_string_append_printf(to_send, "##MM## confirm %s %s##MM##", command, parameters); |
| |
133 |
| |
134 gaim_conv_im_send(GAIM_CONV_IM(mmconv->conv), to_send->str); |
| |
135 } else |
| |
136 { |
| |
137 /* Do nothing. If they aren't the originator, then they can't confirm. */ |
| |
138 } |
| |
139 } |
| |
140 |
| |
141 } |
| |
142 |
| |
143 void music_messaging_change_failed(const int session, const char *id, const char *command, const char *parameters) |
| |
144 { |
| |
145 MMConversation *mmconv = (MMConversation *)g_list_nth_data(conversations, session); |
| |
146 |
| |
147 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_INFO, command, |
| |
148 parameters, NULL, NULL, NULL); |
| |
149 |
| |
150 if (mmconv->started) |
| |
151 { |
| |
152 if (mmconv->originator) |
| |
153 { |
| |
154 GString *to_send = g_string_new(""); |
| |
155 g_string_append_printf(to_send, "##MM## failed %s %s %s##MM##", id, command, parameters); |
| |
156 |
| |
157 gaim_conv_im_send(GAIM_CONV_IM(mmconv->conv), to_send->str); |
| |
158 } else |
| |
159 { |
| |
160 /* Do nothing. If they aren't the originator, then they can't confirm. */ |
| |
161 } |
| |
162 } |
| |
163 } |
| |
164 |
| |
165 void music_messaging_done_session(const int session) |
| |
166 { |
| |
167 MMConversation *mmconv = (MMConversation *)g_list_nth_data(conversations, session); |
| |
168 |
| |
169 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_INFO, "Session", |
| |
170 "Session Complete", NULL, NULL, NULL); |
| |
171 |
| |
172 session_end(mmconv); |
| |
173 } |
| |
174 |
| |
175 |
| |
176 /* DBus commands that can be sent to the editor */ |
| |
177 G_BEGIN_DECLS |
| |
178 DBusConnection *gaim_dbus_get_connection(void); |
| |
179 G_END_DECLS |
| |
180 |
| |
181 static gboolean send_change_request (const int session, const char *id, const char *command, const char *parameters) |
| |
182 { |
| |
183 DBusMessage *message; |
| |
184 |
| |
185 /* Create the signal we need */ |
| |
186 message = dbus_message_new_signal (DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, "GscoreChangeRequest"); |
| |
187 |
| |
188 /* Append the string "Ping!" to the signal */ |
| |
189 dbus_message_append_args (message, |
| |
190 DBUS_TYPE_INT32, &session, |
| |
191 DBUS_TYPE_STRING, &id, |
| |
192 DBUS_TYPE_STRING, &command, |
| |
193 DBUS_TYPE_STRING, ¶meters, |
| |
194 DBUS_TYPE_INVALID); |
| |
195 |
| |
196 /* Send the signal */ |
| |
197 dbus_connection_send (gaim_dbus_get_connection(), message, NULL); |
| |
198 |
| |
199 /* Free the signal now we have finished with it */ |
| |
200 dbus_message_unref (message); |
| |
201 |
| |
202 /* Tell the user we sent a signal */ |
| |
203 g_printerr("Sent change request signal: %d %s %s %s\n", session, id, command, parameters); |
| |
204 |
| |
205 return TRUE; |
| |
206 } |
| |
207 |
| |
208 static gboolean send_change_confirmed (const int session, const char *command, const char *parameters) |
| |
209 { |
| |
210 DBusMessage *message; |
| |
211 |
| |
212 /* Create the signal we need */ |
| |
213 message = dbus_message_new_signal (DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, "GscoreChangeConfirmed"); |
| |
214 |
| |
215 /* Append the string "Ping!" to the signal */ |
| |
216 dbus_message_append_args (message, |
| |
217 DBUS_TYPE_INT32, &session, |
| |
218 DBUS_TYPE_STRING, &command, |
| |
219 DBUS_TYPE_STRING, ¶meters, |
| |
220 DBUS_TYPE_INVALID); |
| |
221 |
| |
222 /* Send the signal */ |
| |
223 dbus_connection_send (gaim_dbus_get_connection(), message, NULL); |
| |
224 |
| |
225 /* Free the signal now we have finished with it */ |
| |
226 dbus_message_unref (message); |
| |
227 |
| |
228 /* Tell the user we sent a signal */ |
| |
229 g_printerr("Sent change confirmed signal.\n"); |
| |
230 |
| |
231 return TRUE; |
| |
232 } |
| |
233 |
| |
234 |
| |
235 static int |
| |
236 mmconv_from_conv_loc(GaimConversation *conv) |
| |
237 { |
| |
238 MMConversation *mmconv_current = NULL; |
| |
239 guint i; |
| |
240 |
| |
241 for (i = 0; i < g_list_length(conversations); i++) |
| |
242 { |
| |
243 mmconv_current = (MMConversation *)g_list_nth_data(conversations, i); |
| |
244 if (conv == mmconv_current->conv) |
| |
245 { |
| |
246 return i; |
| |
247 } |
| |
248 } |
| |
249 return -1; |
| |
250 } |
| |
251 |
| |
252 static MMConversation* |
| |
253 mmconv_from_conv(GaimConversation *conv) |
| |
254 { |
| |
255 return (MMConversation *)g_list_nth_data(conversations, mmconv_from_conv_loc(conv)); |
| |
256 } |
| |
257 |
| |
258 static gboolean |
| |
259 plugin_load(GaimPlugin *plugin) { |
| |
260 void *conv_list_handle; |
| |
261 |
| |
262 GAIM_DBUS_RETURN_FALSE_IF_DISABLED(plugin); |
| |
263 |
| |
264 /* First, we have to register our four exported functions with the |
| |
265 main gaim dbus loop. Without this statement, the gaim dbus |
| |
266 code wouldn't know about our functions. */ |
| |
267 GAIM_DBUS_REGISTER_BINDINGS(plugin); |
| |
268 |
| |
269 /* Keep the plugin for reference (needed for notify's) */ |
| |
270 plugin_pointer = plugin; |
| |
271 |
| |
272 /* Add the button to all the current conversations */ |
| |
273 gaim_conversation_foreach (init_conversation); |
| |
274 |
| |
275 /* Listen for any new conversations */ |
| |
276 conv_list_handle = gaim_conversations_get_handle(); |
| |
277 |
| |
278 gaim_signal_connect(conv_list_handle, "conversation-created", |
| |
279 plugin, GAIM_CALLBACK(init_conversation), NULL); |
| |
280 |
| |
281 /* Listen for conversations that are ending */ |
| |
282 gaim_signal_connect(conv_list_handle, "deleting-conversation", |
| |
283 plugin, GAIM_CALLBACK(conv_destroyed), NULL); |
| |
284 |
| |
285 /* Listen for sending/receiving messages to replace tags */ |
| |
286 gaim_signal_connect(conv_list_handle, "sending-im-msg", |
| |
287 plugin, GAIM_CALLBACK(intercept_sent), NULL); |
| |
288 gaim_signal_connect(conv_list_handle, "receiving-im-msg", |
| |
289 plugin, GAIM_CALLBACK(intercept_received), NULL); |
| |
290 |
| |
291 return TRUE; |
| |
292 } |
| |
293 |
| |
294 static gboolean |
| |
295 plugin_unload(GaimPlugin *plugin) { |
| |
296 MMConversation *mmconv = NULL; |
| |
297 |
| |
298 while (g_list_length(conversations) > 0) |
| |
299 { |
| |
300 mmconv = g_list_first(conversations)->data; |
| |
301 conv_destroyed(mmconv->conv); |
| |
302 } |
| |
303 return TRUE; |
| |
304 } |
| |
305 |
| |
306 |
| |
307 |
| |
308 static gboolean |
| |
309 intercept_sent(GaimAccount *account, const char *who, char **message, void* pData) |
| |
310 { |
| |
311 |
| |
312 if (0 == strncmp(*message, MUSICMESSAGING_PREFIX, strlen(MUSICMESSAGING_PREFIX))) |
| |
313 { |
| |
314 gaim_debug_misc("gaim-musicmessaging", "Sent MM Message: %s\n", *message); |
| |
315 message = 0; |
| |
316 } |
| |
317 else if (0 == strncmp(*message, MUSICMESSAGING_START_MSG, strlen(MUSICMESSAGING_START_MSG))) |
| |
318 { |
| |
319 gaim_debug_misc("gaim-musicmessaging", "Sent MM request.\n"); |
| |
320 return FALSE; |
| |
321 } |
| |
322 else if (0 == strncmp(*message, MUSICMESSAGING_CONFIRM_MSG, strlen(MUSICMESSAGING_CONFIRM_MSG))) |
| |
323 { |
| |
324 gaim_debug_misc("gaim-musicmessaging", "Sent MM confirm.\n"); |
| |
325 return FALSE; |
| |
326 } |
| |
327 else if (0 == strncmp(*message, "test1", strlen("test1"))) |
| |
328 { |
| |
329 gaim_debug_misc("gaim-musicmessaging", "\n\nTEST 1\n\n"); |
| |
330 send_change_request(0, "test-id", "test-command", "test-parameters"); |
| |
331 return FALSE; |
| |
332 } |
| |
333 else if (0 == strncmp(*message, "test2", strlen("test2"))) |
| |
334 { |
| |
335 gaim_debug_misc("gaim-musicmessaging", "\n\nTEST 2\n\n"); |
| |
336 send_change_confirmed(1, "test-command", "test-parameters"); |
| |
337 return FALSE; |
| |
338 } |
| |
339 else |
| |
340 { |
| |
341 return FALSE; |
| |
342 /* Do nothing...procceed as normal */ |
| |
343 } |
| |
344 return TRUE; |
| |
345 } |
| |
346 |
| |
347 static gboolean |
| |
348 intercept_received(GaimAccount *account, char **sender, char **message, GaimConversation *conv, int *flags) |
| |
349 { |
| |
350 MMConversation *mmconv = mmconv_from_conv(conv); |
| |
351 |
| |
352 gaim_debug_misc("gaim-musicmessaging", "Intercepted: %s\n", *message); |
| |
353 if (strstr(*message, MUSICMESSAGING_PREFIX)) |
| |
354 { |
| |
355 char *parsed_message = strtok(strstr(*message, MUSICMESSAGING_PREFIX), "<"); |
| |
356 gaim_debug_misc("gaim-musicmessaging", "Received an MM Message: %s\n", parsed_message); |
| |
357 |
| |
358 if (mmconv->started) |
| |
359 { |
| |
360 if (strstr(parsed_message, "request")) |
| |
361 { |
| |
362 if (mmconv->originator) |
| |
363 { |
| |
364 int session = mmconv_from_conv_loc(conv); |
| |
365 char *id = (mmconv->conv)->name; |
| |
366 char *command; |
| |
367 char *parameters; |
| |
368 |
| |
369 gaim_debug_misc("gaim-musicmessaging", "Sending request to gscore.\n"); |
| |
370 |
| |
371 /* Get past the first two terms - '##MM##' and 'request' */ |
| |
372 strtok(parsed_message, " "); /* '##MM##' */ |
| |
373 strtok(NULL, " "); /* 'request' */ |
| |
374 |
| |
375 command = strtok(NULL, " "); |
| |
376 parameters = strtok(NULL, "#"); |
| |
377 |
| |
378 send_change_request (session, id, command, parameters); |
| |
379 |
| |
380 } |
| |
381 } else if (strstr(parsed_message, "confirm")) |
| |
382 { |
| |
383 if (!mmconv->originator) |
| |
384 { |
| |
385 int session = mmconv_from_conv_loc(conv); |
| |
386 char *command; |
| |
387 char *parameters; |
| |
388 |
| |
389 gaim_debug_misc("gaim-musicmessaging", "Sending confirmation to gscore.\n"); |
| |
390 |
| |
391 /* Get past the first two terms - '##MM##' and 'confirm' */ |
| |
392 strtok(parsed_message, " "); /* '##MM##' */ |
| |
393 strtok(NULL, " "); /* 'confirm' */ |
| |
394 |
| |
395 command = strtok(NULL, " "); |
| |
396 parameters = strtok(NULL, "#"); |
| |
397 |
| |
398 send_change_confirmed (session, command, parameters); |
| |
399 } |
| |
400 } else if (strstr(parsed_message, "failed")) |
| |
401 { |
| |
402 char *id; |
| |
403 char *command; |
| |
404 |
| |
405 /* Get past the first two terms - '##MM##' and 'confirm' */ |
| |
406 strtok(parsed_message, " "); /* '##MM##' */ |
| |
407 strtok(NULL, " "); /* 'failed' */ |
| |
408 |
| |
409 id = strtok(NULL, " "); |
| |
410 command = strtok(NULL, " "); |
| |
411 /* char *parameters = strtok(NULL, "#"); DONT NEED PARAMETERS */ |
| |
412 |
| |
413 if ((mmconv->conv)->name == id) |
| |
414 { |
| |
415 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_ERROR, |
| |
416 _("Music Messaging"), |
| |
417 _("There was a conflict in running the command:"), command, NULL, NULL); |
| |
418 } |
| |
419 } |
| |
420 } |
| |
421 |
| |
422 message = 0; |
| |
423 } |
| |
424 else if (strstr(*message, MUSICMESSAGING_START_MSG)) |
| |
425 { |
| |
426 gaim_debug_misc("gaim-musicmessaging", "Received MM request.\n"); |
| |
427 if (!(mmconv->originator)) |
| |
428 { |
| |
429 mmconv->requested = TRUE; |
| |
430 return FALSE; |
| |
431 } |
| |
432 |
| |
433 } |
| |
434 else if (strstr(*message, MUSICMESSAGING_CONFIRM_MSG)) |
| |
435 { |
| |
436 gaim_debug_misc("gaim-musicmessagin", "Received MM confirm.\n"); |
| |
437 |
| |
438 if (mmconv->originator) |
| |
439 { |
| |
440 start_session(mmconv); |
| |
441 return FALSE; |
| |
442 } |
| |
443 } |
| |
444 else |
| |
445 { |
| |
446 return FALSE; |
| |
447 /* Do nothing. */ |
| |
448 } |
| |
449 return TRUE; |
| |
450 } |
| |
451 |
| |
452 static void send_request(MMConversation *mmconv) |
| |
453 { |
| |
454 GaimConnection *connection = gaim_conversation_get_gc(mmconv->conv); |
| |
455 const char *convName = gaim_conversation_get_name(mmconv->conv); |
| |
456 serv_send_im(connection, convName, MUSICMESSAGING_START_MSG, GAIM_MESSAGE_SEND); |
| |
457 } |
| |
458 |
| |
459 static void send_request_confirmed(MMConversation *mmconv) |
| |
460 { |
| |
461 GaimConnection *connection = gaim_conversation_get_gc(mmconv->conv); |
| |
462 const char *convName = gaim_conversation_get_name(mmconv->conv); |
| |
463 serv_send_im(connection, convName, MUSICMESSAGING_CONFIRM_MSG, GAIM_MESSAGE_SEND); |
| |
464 } |
| |
465 |
| |
466 |
| |
467 static gboolean |
| |
468 start_session(MMConversation *mmconv) |
| |
469 { |
| |
470 run_editor(mmconv); |
| |
471 return TRUE; |
| |
472 } |
| |
473 |
| |
474 static void session_end (MMConversation *mmconv) |
| |
475 { |
| |
476 mmconv->started = FALSE; |
| |
477 mmconv->originator = FALSE; |
| |
478 mmconv->requested = FALSE; |
| |
479 kill_editor(mmconv); |
| |
480 } |
| |
481 |
| |
482 static void music_button_toggled (GtkWidget *widget, gpointer data) |
| |
483 { |
| |
484 MMConversation *mmconv = mmconv_from_conv(((MMConversation *) data)->conv); |
| |
485 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) |
| |
486 { |
| |
487 if (((MMConversation *) data)->requested) |
| |
488 { |
| |
489 start_session(mmconv); |
| |
490 send_request_confirmed(mmconv); |
| |
491 } |
| |
492 else |
| |
493 { |
| |
494 ((MMConversation *) data)->originator = TRUE; |
| |
495 send_request((MMConversation *) data); |
| |
496 } |
| |
497 } else { |
| |
498 session_end((MMConversation *)data); |
| |
499 } |
| |
500 } |
| |
501 |
| |
502 static void set_editor_path (GtkWidget *button, GtkWidget *text_field) |
| |
503 { |
| |
504 const char * path = gtk_entry_get_text((GtkEntry*)text_field); |
| |
505 gaim_prefs_set_string("/plugins/gtk/musicmessaging/editor_path", path); |
| |
506 |
| |
507 } |
| |
508 |
| |
509 static void run_editor (MMConversation *mmconv) |
| |
510 { |
| |
511 GError *spawn_error = NULL; |
| |
512 GString *session_id; |
| |
513 gchar * args[4]; |
| |
514 args[0] = (gchar *)gaim_prefs_get_string("/plugins/gtk/musicmessaging/editor_path"); |
| |
515 |
| |
516 args[1] = "-session_id"; |
| |
517 session_id = g_string_new(""); |
| |
518 g_string_sprintfa(session_id, "%d", mmconv_from_conv_loc(mmconv->conv)); |
| |
519 args[2] = session_id->str; |
| |
520 |
| |
521 args[3] = NULL; |
| |
522 |
| |
523 if (!(g_spawn_async (".", args, NULL, 4, NULL, NULL, &(mmconv->pid), &spawn_error))) |
| |
524 { |
| |
525 gaim_notify_error(plugin_pointer, _("Error Running Editor"), |
| |
526 _("The following error has occurred:"), spawn_error->message); |
| |
527 mmconv->started = FALSE; |
| |
528 } |
| |
529 else |
| |
530 { |
| |
531 mmconv->started = TRUE; |
| |
532 } |
| |
533 } |
| |
534 |
| |
535 static void kill_editor (MMConversation *mmconv) |
| |
536 { |
| |
537 if (mmconv->pid) |
| |
538 { |
| |
539 kill(mmconv->pid, SIGINT); |
| |
540 mmconv->pid = 0; |
| |
541 } |
| |
542 } |
| |
543 |
| |
544 static void init_conversation (GaimConversation *conv) |
| |
545 { |
| |
546 MMConversation *mmconv; |
| |
547 mmconv = g_malloc(sizeof(MMConversation)); |
| |
548 |
| |
549 mmconv->conv = conv; |
| |
550 mmconv->started = FALSE; |
| |
551 mmconv->originator = FALSE; |
| |
552 mmconv->requested = FALSE; |
| |
553 |
| |
554 add_button(mmconv); |
| |
555 |
| |
556 conversations = g_list_append(conversations, mmconv); |
| |
557 } |
| |
558 |
| |
559 static void conv_destroyed (GaimConversation *conv) |
| |
560 { |
| |
561 MMConversation *mmconv = mmconv_from_conv(conv); |
| |
562 |
| |
563 remove_widget(mmconv->button); |
| |
564 remove_widget(mmconv->seperator); |
| |
565 if (mmconv->started) |
| |
566 { |
| |
567 kill_editor(mmconv); |
| |
568 } |
| |
569 conversations = g_list_remove(conversations, mmconv); |
| |
570 } |
| |
571 |
| |
572 static void add_button (MMConversation *mmconv) |
| |
573 { |
| |
574 GaimConversation *conv = mmconv->conv; |
| |
575 |
| |
576 GtkWidget *button, *image, *sep; |
| |
577 gchar *file_path; |
| |
578 |
| |
579 button = gtk_toggle_button_new(); |
| |
580 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); |
| |
581 |
| |
582 g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(music_button_toggled), mmconv); |
| |
583 |
| |
584 file_path = g_build_filename(DATADIR, "pixmaps", "gaim", "buttons", |
| |
585 "music.png", NULL); |
| |
586 image = gtk_image_new_from_file(file_path); |
| |
587 g_free(file_path); |
| |
588 |
| |
589 gtk_container_add((GtkContainer *)button, image); |
| |
590 |
| |
591 sep = gtk_vseparator_new(); |
| |
592 |
| |
593 mmconv->seperator = sep; |
| |
594 mmconv->button = button; |
| |
595 |
| |
596 gtk_widget_show(sep); |
| |
597 gtk_widget_show(image); |
| |
598 gtk_widget_show(button); |
| |
599 |
| |
600 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), sep, FALSE, FALSE, 0); |
| |
601 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), button, FALSE, FALSE, 0); |
| |
602 } |
| |
603 |
| |
604 static void remove_widget (GtkWidget *button) |
| |
605 { |
| |
606 gtk_widget_hide(button); |
| |
607 gtk_widget_destroy(button); |
| |
608 } |
| |
609 |
| |
610 static GtkWidget * |
| |
611 get_config_frame(GaimPlugin *plugin) |
| |
612 { |
| |
613 GtkWidget *ret; |
| |
614 GtkWidget *vbox; |
| |
615 |
| |
616 GtkWidget *editor_path; |
| |
617 GtkWidget *editor_path_label; |
| |
618 GtkWidget *editor_path_button; |
| |
619 |
| |
620 /* Outside container */ |
| |
621 ret = gtk_vbox_new(FALSE, 18); |
| |
622 gtk_container_set_border_width(GTK_CONTAINER(ret), 10); |
| |
623 |
| |
624 /* Configuration frame */ |
| |
625 vbox = gaim_gtk_make_frame(ret, _("Music Messaging Configuration")); |
| |
626 |
| |
627 /* Path to the score editor */ |
| |
628 editor_path = gtk_entry_new(); |
| |
629 editor_path_label = gtk_label_new(_("Score Editor Path")); |
| |
630 editor_path_button = gtk_button_new_with_mnemonic(_("_Apply")); |
| |
631 |
| |
632 gtk_entry_set_text((GtkEntry*)editor_path, "/usr/local/bin/gscore"); |
| |
633 |
| |
634 g_signal_connect(G_OBJECT(editor_path_button), "clicked", |
| |
635 G_CALLBACK(set_editor_path), editor_path); |
| |
636 |
| |
637 gtk_box_pack_start(GTK_BOX(vbox), editor_path_label, FALSE, FALSE, 0); |
| |
638 gtk_box_pack_start(GTK_BOX(vbox), editor_path, FALSE, FALSE, 0); |
| |
639 gtk_box_pack_start(GTK_BOX(vbox), editor_path_button, FALSE, FALSE, 0); |
| |
640 |
| |
641 gtk_widget_show_all(ret); |
| |
642 |
| |
643 return ret; |
| |
644 } |
| |
645 |
| |
646 static GaimGtkPluginUiInfo ui_info = |
| |
647 { |
| |
648 get_config_frame, |
| |
649 0 /* page_num (reserved) */ |
| |
650 }; |
| |
651 |
| |
652 static GaimPluginInfo info = { |
| |
653 GAIM_PLUGIN_MAGIC, |
| |
654 GAIM_MAJOR_VERSION, |
| |
655 GAIM_MINOR_VERSION, |
| |
656 GAIM_PLUGIN_STANDARD, /**< type */ |
| |
657 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ |
| |
658 0, /**< flags */ |
| |
659 NULL, /**< dependencies */ |
| |
660 GAIM_PRIORITY_DEFAULT, /**< priority */ |
| |
661 |
| |
662 MUSICMESSAGING_PLUGIN_ID, /**< id */ |
| |
663 "Music Messaging", /**< name */ |
| |
664 VERSION, /**< version */ |
| |
665 N_("Music Messaging Plugin for collaborative composition."), |
| |
666 /** summary */ |
| |
667 N_("The Music Messaging Plugin allows a number of users to simultaneously work on a piece of music by editting a common score in real-time."), |
| |
668 /** description */ |
| |
669 "Christian Muise <christian.muise@gmail.com>", /**< author */ |
| |
670 GAIM_WEBSITE, /**< homepage */ |
| |
671 plugin_load, /**< load */ |
| |
672 plugin_unload, /**< unload */ |
| |
673 NULL, /**< destroy */ |
| |
674 &ui_info, /**< ui_info */ |
| |
675 NULL, /**< extra_info */ |
| |
676 NULL, |
| |
677 NULL |
| |
678 }; |
| |
679 |
| |
680 static void |
| |
681 init_plugin(GaimPlugin *plugin) { |
| |
682 gaim_prefs_add_none("/plugins/gtk/musicmessaging"); |
| |
683 gaim_prefs_add_string("/plugins/gtk/musicmessaging/editor_path", "/usr/local/bin/gscore"); |
| |
684 } |
| |
685 |
| |
686 GAIM_INIT_PLUGIN(musicmessaging, init_plugin, info); |