| 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, GaimConversation *conv, 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 /* First, we have to register our four exported functions with the |
|
| 263 main gaim dbus loop. Without this statement, the gaim dbus |
|
| 264 code wouldn't know about our functions. */ |
|
| 265 GAIM_DBUS_REGISTER_BINDINGS(plugin); |
|
| 266 |
|
| 267 /* Keep the plugin for reference (needed for notify's) */ |
|
| 268 plugin_pointer = plugin; |
|
| 269 |
|
| 270 /* Add the button to all the current conversations */ |
|
| 271 gaim_conversation_foreach (init_conversation); |
|
| 272 |
|
| 273 /* Listen for any new conversations */ |
|
| 274 conv_list_handle = gaim_conversations_get_handle(); |
|
| 275 |
|
| 276 gaim_signal_connect(conv_list_handle, "conversation-created", |
|
| 277 plugin, GAIM_CALLBACK(init_conversation), NULL); |
|
| 278 |
|
| 279 /* Listen for conversations that are ending */ |
|
| 280 gaim_signal_connect(conv_list_handle, "deleting-conversation", |
|
| 281 plugin, GAIM_CALLBACK(conv_destroyed), NULL); |
|
| 282 |
|
| 283 /* Listen for sending/receiving messages to replace tags */ |
|
| 284 gaim_signal_connect(conv_list_handle, "writing-im-msg", |
|
| 285 plugin, GAIM_CALLBACK(intercept_sent), NULL); |
|
| 286 gaim_signal_connect(conv_list_handle, "receiving-im-msg", |
|
| 287 plugin, GAIM_CALLBACK(intercept_received), NULL); |
|
| 288 |
|
| 289 return TRUE; |
|
| 290 } |
|
| 291 |
|
| 292 static gboolean |
|
| 293 plugin_unload(GaimPlugin *plugin) { |
|
| 294 MMConversation *mmconv = NULL; |
|
| 295 |
|
| 296 while (g_list_length(conversations) > 0) |
|
| 297 { |
|
| 298 mmconv = g_list_first(conversations)->data; |
|
| 299 conv_destroyed(mmconv->conv); |
|
| 300 } |
|
| 301 return TRUE; |
|
| 302 } |
|
| 303 |
|
| 304 |
|
| 305 |
|
| 306 static gboolean |
|
| 307 intercept_sent(GaimAccount *account, GaimConversation *conv, char **message, void* pData) |
|
| 308 { |
|
| 309 |
|
| 310 if (0 == strncmp(*message, MUSICMESSAGING_PREFIX, strlen(MUSICMESSAGING_PREFIX))) |
|
| 311 { |
|
| 312 gaim_debug_misc("gaim-musicmessaging", "Sent MM Message: %s\n", *message); |
|
| 313 message = 0; |
|
| 314 } |
|
| 315 else if (0 == strncmp(*message, MUSICMESSAGING_START_MSG, strlen(MUSICMESSAGING_START_MSG))) |
|
| 316 { |
|
| 317 gaim_debug_misc("gaim-musicmessaging", "Sent MM request.\n"); |
|
| 318 return FALSE; |
|
| 319 } |
|
| 320 else if (0 == strncmp(*message, MUSICMESSAGING_CONFIRM_MSG, strlen(MUSICMESSAGING_CONFIRM_MSG))) |
|
| 321 { |
|
| 322 gaim_debug_misc("gaim-musicmessaging", "Sent MM confirm.\n"); |
|
| 323 return FALSE; |
|
| 324 } |
|
| 325 else if (0 == strncmp(*message, "test1", strlen("test1"))) |
|
| 326 { |
|
| 327 gaim_debug_misc("gaim-musicmessaging", "\n\nTEST 1\n\n"); |
|
| 328 send_change_request(0, "test-id", "test-command", "test-parameters"); |
|
| 329 return FALSE; |
|
| 330 } |
|
| 331 else if (0 == strncmp(*message, "test2", strlen("test2"))) |
|
| 332 { |
|
| 333 gaim_debug_misc("gaim-musicmessaging", "\n\nTEST 2\n\n"); |
|
| 334 send_change_confirmed(1, "test-command", "test-parameters"); |
|
| 335 return FALSE; |
|
| 336 } |
|
| 337 else |
|
| 338 { |
|
| 339 return FALSE; |
|
| 340 /* Do nothing...procceed as normal */ |
|
| 341 } |
|
| 342 return TRUE; |
|
| 343 } |
|
| 344 |
|
| 345 static gboolean |
|
| 346 intercept_received(GaimAccount *account, char **sender, char **message, GaimConversation *conv, int *flags) |
|
| 347 { |
|
| 348 MMConversation *mmconv = mmconv_from_conv(conv); |
|
| 349 |
|
| 350 gaim_debug_misc("gaim-musicmessaging", "Intercepted: %s\n", *message); |
|
| 351 if (strstr(*message, MUSICMESSAGING_PREFIX)) |
|
| 352 { |
|
| 353 char *parsed_message = strtok(strstr(*message, MUSICMESSAGING_PREFIX), "<"); |
|
| 354 gaim_debug_misc("gaim-musicmessaging", "Received an MM Message: %s\n", parsed_message); |
|
| 355 |
|
| 356 if (mmconv->started) |
|
| 357 { |
|
| 358 if (strstr(parsed_message, "request")) |
|
| 359 { |
|
| 360 if (mmconv->originator) |
|
| 361 { |
|
| 362 int session = mmconv_from_conv_loc(conv); |
|
| 363 char *id = (mmconv->conv)->name; |
|
| 364 char *command; |
|
| 365 char *parameters; |
|
| 366 |
|
| 367 gaim_debug_misc("gaim-musicmessaging", "Sending request to gscore.\n"); |
|
| 368 |
|
| 369 /* Get past the first two terms - '##MM##' and 'request' */ |
|
| 370 strtok(parsed_message, " "); /* '##MM##' */ |
|
| 371 strtok(NULL, " "); /* 'request' */ |
|
| 372 |
|
| 373 command = strtok(NULL, " "); |
|
| 374 parameters = strtok(NULL, "#"); |
|
| 375 |
|
| 376 send_change_request (session, id, command, parameters); |
|
| 377 |
|
| 378 } |
|
| 379 } else if (strstr(parsed_message, "confirm")) |
|
| 380 { |
|
| 381 if (!mmconv->originator) |
|
| 382 { |
|
| 383 int session = mmconv_from_conv_loc(conv); |
|
| 384 char *command; |
|
| 385 char *parameters; |
|
| 386 |
|
| 387 gaim_debug_misc("gaim-musicmessaging", "Sending confirmation to gscore.\n"); |
|
| 388 |
|
| 389 /* Get past the first two terms - '##MM##' and 'confirm' */ |
|
| 390 strtok(parsed_message, " "); /* '##MM##' */ |
|
| 391 strtok(NULL, " "); /* 'confirm' */ |
|
| 392 |
|
| 393 command = strtok(NULL, " "); |
|
| 394 parameters = strtok(NULL, "#"); |
|
| 395 |
|
| 396 send_change_confirmed (session, command, parameters); |
|
| 397 } |
|
| 398 } else if (strstr(parsed_message, "failed")) |
|
| 399 { |
|
| 400 char *id; |
|
| 401 char *command; |
|
| 402 |
|
| 403 /* Get past the first two terms - '##MM##' and 'confirm' */ |
|
| 404 strtok(parsed_message, " "); /* '##MM##' */ |
|
| 405 strtok(NULL, " "); /* 'failed' */ |
|
| 406 |
|
| 407 id = strtok(NULL, " "); |
|
| 408 command = strtok(NULL, " "); |
|
| 409 /* char *parameters = strtok(NULL, "#"); DONT NEED PARAMETERS */ |
|
| 410 |
|
| 411 if ((mmconv->conv)->name == id) |
|
| 412 { |
|
| 413 gaim_notify_message(plugin_pointer, GAIM_NOTIFY_MSG_ERROR, "Music Messaging", |
|
| 414 "There was a conflict in running the command:", command, NULL, NULL); |
|
| 415 } |
|
| 416 } |
|
| 417 } |
|
| 418 |
|
| 419 message = 0; |
|
| 420 } |
|
| 421 else if (strstr(*message, MUSICMESSAGING_START_MSG)) |
|
| 422 { |
|
| 423 gaim_debug_misc("gaim-musicmessaging", "Received MM request.\n"); |
|
| 424 if (!(mmconv->originator)) |
|
| 425 { |
|
| 426 mmconv->requested = TRUE; |
|
| 427 return FALSE; |
|
| 428 } |
|
| 429 |
|
| 430 } |
|
| 431 else if (strstr(*message, MUSICMESSAGING_CONFIRM_MSG)) |
|
| 432 { |
|
| 433 gaim_debug_misc("gaim-musicmessagin", "Received MM confirm.\n"); |
|
| 434 |
|
| 435 if (mmconv->originator) |
|
| 436 { |
|
| 437 start_session(mmconv); |
|
| 438 return FALSE; |
|
| 439 } |
|
| 440 } |
|
| 441 else |
|
| 442 { |
|
| 443 return FALSE; |
|
| 444 /* Do nothing. */ |
|
| 445 } |
|
| 446 return TRUE; |
|
| 447 } |
|
| 448 |
|
| 449 static void send_request(MMConversation *mmconv) |
|
| 450 { |
|
| 451 GaimConnection *connection = gaim_conversation_get_gc(mmconv->conv); |
|
| 452 const char *convName = gaim_conversation_get_name(mmconv->conv); |
|
| 453 serv_send_im(connection, convName, MUSICMESSAGING_START_MSG, GAIM_MESSAGE_SEND); |
|
| 454 } |
|
| 455 |
|
| 456 static void send_request_confirmed(MMConversation *mmconv) |
|
| 457 { |
|
| 458 GaimConnection *connection = gaim_conversation_get_gc(mmconv->conv); |
|
| 459 const char *convName = gaim_conversation_get_name(mmconv->conv); |
|
| 460 serv_send_im(connection, convName, MUSICMESSAGING_CONFIRM_MSG, GAIM_MESSAGE_SEND); |
|
| 461 } |
|
| 462 |
|
| 463 |
|
| 464 static gboolean |
|
| 465 start_session(MMConversation *mmconv) |
|
| 466 { |
|
| 467 run_editor(mmconv); |
|
| 468 return TRUE; |
|
| 469 } |
|
| 470 |
|
| 471 static void session_end (MMConversation *mmconv) |
|
| 472 { |
|
| 473 mmconv->started = FALSE; |
|
| 474 mmconv->originator = FALSE; |
|
| 475 mmconv->requested = FALSE; |
|
| 476 kill_editor(mmconv); |
|
| 477 } |
|
| 478 |
|
| 479 static void music_button_toggled (GtkWidget *widget, gpointer data) |
|
| 480 { |
|
| 481 MMConversation *mmconv = mmconv_from_conv(((MMConversation *) data)->conv); |
|
| 482 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) |
|
| 483 { |
|
| 484 if (((MMConversation *) data)->requested) |
|
| 485 { |
|
| 486 start_session(mmconv); |
|
| 487 send_request_confirmed(mmconv); |
|
| 488 } |
|
| 489 else |
|
| 490 { |
|
| 491 ((MMConversation *) data)->originator = TRUE; |
|
| 492 send_request((MMConversation *) data); |
|
| 493 } |
|
| 494 } else { |
|
| 495 session_end((MMConversation *)data); |
|
| 496 } |
|
| 497 } |
|
| 498 |
|
| 499 static void set_editor_path (GtkWidget *button, GtkWidget *text_field) |
|
| 500 { |
|
| 501 const char * path = gtk_entry_get_text((GtkEntry*)text_field); |
|
| 502 gaim_prefs_set_string("/plugins/gtk/musicmessaging/editor_path", path); |
|
| 503 |
|
| 504 } |
|
| 505 |
|
| 506 static void run_editor (MMConversation *mmconv) |
|
| 507 { |
|
| 508 GError *spawn_error = NULL; |
|
| 509 GString *session_id; |
|
| 510 gchar * args[4]; |
|
| 511 args[0] = (gchar *)gaim_prefs_get_string("/plugins/gtk/musicmessaging/editor_path"); |
|
| 512 |
|
| 513 args[1] = "-session_id"; |
|
| 514 session_id = g_string_new(""); |
|
| 515 g_string_sprintfa(session_id, "%d", mmconv_from_conv_loc(mmconv->conv)); |
|
| 516 args[2] = session_id->str; |
|
| 517 |
|
| 518 args[3] = NULL; |
|
| 519 |
|
| 520 if (!(g_spawn_async (".", args, NULL, 4, NULL, NULL, &(mmconv->pid), &spawn_error))) |
|
| 521 { |
|
| 522 gaim_notify_error(plugin_pointer, "Error Running Editor", |
|
| 523 "The following error has occured:", spawn_error->message); |
|
| 524 mmconv->started = FALSE; |
|
| 525 } |
|
| 526 else |
|
| 527 { |
|
| 528 mmconv->started = TRUE; |
|
| 529 } |
|
| 530 } |
|
| 531 |
|
| 532 static void kill_editor (MMConversation *mmconv) |
|
| 533 { |
|
| 534 if (mmconv->pid) |
|
| 535 { |
|
| 536 kill(mmconv->pid, SIGINT); |
|
| 537 mmconv->pid = 0; |
|
| 538 } |
|
| 539 } |
|
| 540 |
|
| 541 static void init_conversation (GaimConversation *conv) |
|
| 542 { |
|
| 543 MMConversation *mmconv; |
|
| 544 mmconv = g_malloc(sizeof(MMConversation)); |
|
| 545 |
|
| 546 mmconv->conv = conv; |
|
| 547 mmconv->started = FALSE; |
|
| 548 mmconv->originator = FALSE; |
|
| 549 mmconv->requested = FALSE; |
|
| 550 |
|
| 551 add_button(mmconv); |
|
| 552 |
|
| 553 conversations = g_list_append(conversations, mmconv); |
|
| 554 } |
|
| 555 |
|
| 556 static void conv_destroyed (GaimConversation *conv) |
|
| 557 { |
|
| 558 MMConversation *mmconv = mmconv_from_conv(conv); |
|
| 559 |
|
| 560 remove_widget(mmconv->button); |
|
| 561 remove_widget(mmconv->seperator); |
|
| 562 if (mmconv->started) |
|
| 563 { |
|
| 564 kill_editor(mmconv); |
|
| 565 } |
|
| 566 conversations = g_list_remove(conversations, mmconv); |
|
| 567 } |
|
| 568 |
|
| 569 static void add_button (MMConversation *mmconv) |
|
| 570 { |
|
| 571 GaimConversation *conv = mmconv->conv; |
|
| 572 |
|
| 573 GtkWidget *button, *image, *sep; |
|
| 574 gchar *file_path; |
|
| 575 |
|
| 576 button = gtk_toggle_button_new(); |
|
| 577 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); |
|
| 578 |
|
| 579 g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(music_button_toggled), mmconv); |
|
| 580 |
|
| 581 file_path = g_build_filename(DATADIR, "pixmaps", "gaim", "buttons", |
|
| 582 "music.png", NULL); |
|
| 583 image = gtk_image_new_from_file(file_path); |
|
| 584 g_free(file_path); |
|
| 585 |
|
| 586 gtk_container_add((GtkContainer *)button, image); |
|
| 587 |
|
| 588 sep = gtk_vseparator_new(); |
|
| 589 |
|
| 590 mmconv->seperator = sep; |
|
| 591 mmconv->button = button; |
|
| 592 |
|
| 593 gtk_widget_show(sep); |
|
| 594 gtk_widget_show(image); |
|
| 595 gtk_widget_show(button); |
|
| 596 |
|
| 597 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), sep, FALSE, FALSE, 0); |
|
| 598 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), button, FALSE, FALSE, 0); |
|
| 599 } |
|
| 600 |
|
| 601 static void remove_widget (GtkWidget *button) |
|
| 602 { |
|
| 603 gtk_widget_hide(button); |
|
| 604 gtk_widget_destroy(button); |
|
| 605 } |
|
| 606 |
|
| 607 static GtkWidget * |
|
| 608 get_config_frame(GaimPlugin *plugin) |
|
| 609 { |
|
| 610 GtkWidget *ret; |
|
| 611 GtkWidget *vbox; |
|
| 612 |
|
| 613 GtkWidget *editor_path; |
|
| 614 GtkWidget *editor_path_label; |
|
| 615 GtkWidget *editor_path_button; |
|
| 616 |
|
| 617 /* Outside container */ |
|
| 618 ret = gtk_vbox_new(FALSE, 18); |
|
| 619 gtk_container_set_border_width(GTK_CONTAINER(ret), 10); |
|
| 620 |
|
| 621 /* Configuration frame */ |
|
| 622 vbox = gaim_gtk_make_frame(ret, _("Music Messaging Configuration")); |
|
| 623 |
|
| 624 /* Path to the score editor */ |
|
| 625 editor_path = gtk_entry_new(); |
|
| 626 editor_path_label = gtk_label_new("Score Editor Path"); |
|
| 627 editor_path_button = gtk_button_new_with_mnemonic(_("_Apply")); |
|
| 628 |
|
| 629 gtk_entry_set_text((GtkEntry*)editor_path, "/usr/local/bin/gscore"); |
|
| 630 |
|
| 631 g_signal_connect(G_OBJECT(editor_path_button), "clicked", |
|
| 632 G_CALLBACK(set_editor_path), editor_path); |
|
| 633 |
|
| 634 gtk_box_pack_start(GTK_BOX(vbox), editor_path_label, FALSE, FALSE, 0); |
|
| 635 gtk_box_pack_start(GTK_BOX(vbox), editor_path, FALSE, FALSE, 0); |
|
| 636 gtk_box_pack_start(GTK_BOX(vbox), editor_path_button, FALSE, FALSE, 0); |
|
| 637 |
|
| 638 gtk_widget_show_all(ret); |
|
| 639 |
|
| 640 return ret; |
|
| 641 } |
|
| 642 |
|
| 643 static GaimGtkPluginUiInfo ui_info = |
|
| 644 { |
|
| 645 get_config_frame, |
|
| 646 0 /* page_num (reserved) */ |
|
| 647 }; |
|
| 648 |
|
| 649 static GaimPluginInfo info = { |
|
| 650 GAIM_PLUGIN_MAGIC, |
|
| 651 GAIM_MAJOR_VERSION, |
|
| 652 GAIM_MINOR_VERSION, |
|
| 653 GAIM_PLUGIN_STANDARD, |
|
| 654 GAIM_GTK_PLUGIN_TYPE, |
|
| 655 0, |
|
| 656 NULL, |
|
| 657 GAIM_PRIORITY_DEFAULT, |
|
| 658 |
|
| 659 MUSICMESSAGING_PLUGIN_ID, |
|
| 660 "Music Messaging", |
|
| 661 VERSION, |
|
| 662 "Music Messaging Plugin for collabrative composition.", |
|
| 663 "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.", |
|
| 664 "Christian Muise <christian.muise@gmail.com>", |
|
| 665 GAIM_WEBSITE, |
|
| 666 plugin_load, |
|
| 667 plugin_unload, |
|
| 668 NULL, |
|
| 669 &ui_info, |
|
| 670 NULL, |
|
| 671 NULL, |
|
| 672 NULL |
|
| 673 }; |
|
| 674 |
|
| 675 static void |
|
| 676 init_plugin(GaimPlugin *plugin) { |
|
| 677 gaim_prefs_add_none("/plugins/gtk/musicmessaging"); |
|
| 678 gaim_prefs_add_string("/plugins/gtk/musicmessaging/editor_path", "/usr/local/bin/gscore"); |
|
| 679 } |
|
| 680 |
|
| 681 GAIM_INIT_PLUGIN(musicmessaging, init_plugin, info); |
|