| 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 /* 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, "sending-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, const char *who, 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, |
|
| 414 _("Music Messaging"), |
|
| 415 _("There was a conflict in running the command:"), command, NULL, NULL); |
|
| 416 } |
|
| 417 } |
|
| 418 } |
|
| 419 |
|
| 420 message = 0; |
|
| 421 } |
|
| 422 else if (strstr(*message, MUSICMESSAGING_START_MSG)) |
|
| 423 { |
|
| 424 gaim_debug_misc("gaim-musicmessaging", "Received MM request.\n"); |
|
| 425 if (!(mmconv->originator)) |
|
| 426 { |
|
| 427 mmconv->requested = TRUE; |
|
| 428 return FALSE; |
|
| 429 } |
|
| 430 |
|
| 431 } |
|
| 432 else if (strstr(*message, MUSICMESSAGING_CONFIRM_MSG)) |
|
| 433 { |
|
| 434 gaim_debug_misc("gaim-musicmessagin", "Received MM confirm.\n"); |
|
| 435 |
|
| 436 if (mmconv->originator) |
|
| 437 { |
|
| 438 start_session(mmconv); |
|
| 439 return FALSE; |
|
| 440 } |
|
| 441 } |
|
| 442 else |
|
| 443 { |
|
| 444 return FALSE; |
|
| 445 /* Do nothing. */ |
|
| 446 } |
|
| 447 return TRUE; |
|
| 448 } |
|
| 449 |
|
| 450 static void send_request(MMConversation *mmconv) |
|
| 451 { |
|
| 452 GaimConnection *connection = gaim_conversation_get_gc(mmconv->conv); |
|
| 453 const char *convName = gaim_conversation_get_name(mmconv->conv); |
|
| 454 serv_send_im(connection, convName, MUSICMESSAGING_START_MSG, GAIM_MESSAGE_SEND); |
|
| 455 } |
|
| 456 |
|
| 457 static void send_request_confirmed(MMConversation *mmconv) |
|
| 458 { |
|
| 459 GaimConnection *connection = gaim_conversation_get_gc(mmconv->conv); |
|
| 460 const char *convName = gaim_conversation_get_name(mmconv->conv); |
|
| 461 serv_send_im(connection, convName, MUSICMESSAGING_CONFIRM_MSG, GAIM_MESSAGE_SEND); |
|
| 462 } |
|
| 463 |
|
| 464 |
|
| 465 static gboolean |
|
| 466 start_session(MMConversation *mmconv) |
|
| 467 { |
|
| 468 run_editor(mmconv); |
|
| 469 return TRUE; |
|
| 470 } |
|
| 471 |
|
| 472 static void session_end (MMConversation *mmconv) |
|
| 473 { |
|
| 474 mmconv->started = FALSE; |
|
| 475 mmconv->originator = FALSE; |
|
| 476 mmconv->requested = FALSE; |
|
| 477 kill_editor(mmconv); |
|
| 478 } |
|
| 479 |
|
| 480 static void music_button_toggled (GtkWidget *widget, gpointer data) |
|
| 481 { |
|
| 482 MMConversation *mmconv = mmconv_from_conv(((MMConversation *) data)->conv); |
|
| 483 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) |
|
| 484 { |
|
| 485 if (((MMConversation *) data)->requested) |
|
| 486 { |
|
| 487 start_session(mmconv); |
|
| 488 send_request_confirmed(mmconv); |
|
| 489 } |
|
| 490 else |
|
| 491 { |
|
| 492 ((MMConversation *) data)->originator = TRUE; |
|
| 493 send_request((MMConversation *) data); |
|
| 494 } |
|
| 495 } else { |
|
| 496 session_end((MMConversation *)data); |
|
| 497 } |
|
| 498 } |
|
| 499 |
|
| 500 static void set_editor_path (GtkWidget *button, GtkWidget *text_field) |
|
| 501 { |
|
| 502 const char * path = gtk_entry_get_text((GtkEntry*)text_field); |
|
| 503 gaim_prefs_set_string("/plugins/gtk/musicmessaging/editor_path", path); |
|
| 504 |
|
| 505 } |
|
| 506 |
|
| 507 static void run_editor (MMConversation *mmconv) |
|
| 508 { |
|
| 509 GError *spawn_error = NULL; |
|
| 510 GString *session_id; |
|
| 511 gchar * args[4]; |
|
| 512 args[0] = (gchar *)gaim_prefs_get_string("/plugins/gtk/musicmessaging/editor_path"); |
|
| 513 |
|
| 514 args[1] = "-session_id"; |
|
| 515 session_id = g_string_new(""); |
|
| 516 g_string_sprintfa(session_id, "%d", mmconv_from_conv_loc(mmconv->conv)); |
|
| 517 args[2] = session_id->str; |
|
| 518 |
|
| 519 args[3] = NULL; |
|
| 520 |
|
| 521 if (!(g_spawn_async (".", args, NULL, 4, NULL, NULL, &(mmconv->pid), &spawn_error))) |
|
| 522 { |
|
| 523 gaim_notify_error(plugin_pointer, _("Error Running Editor"), |
|
| 524 _("The following error has occured:"), spawn_error->message); |
|
| 525 mmconv->started = FALSE; |
|
| 526 } |
|
| 527 else |
|
| 528 { |
|
| 529 mmconv->started = TRUE; |
|
| 530 } |
|
| 531 } |
|
| 532 |
|
| 533 static void kill_editor (MMConversation *mmconv) |
|
| 534 { |
|
| 535 if (mmconv->pid) |
|
| 536 { |
|
| 537 kill(mmconv->pid, SIGINT); |
|
| 538 mmconv->pid = 0; |
|
| 539 } |
|
| 540 } |
|
| 541 |
|
| 542 static void init_conversation (GaimConversation *conv) |
|
| 543 { |
|
| 544 MMConversation *mmconv; |
|
| 545 mmconv = g_malloc(sizeof(MMConversation)); |
|
| 546 |
|
| 547 mmconv->conv = conv; |
|
| 548 mmconv->started = FALSE; |
|
| 549 mmconv->originator = FALSE; |
|
| 550 mmconv->requested = FALSE; |
|
| 551 |
|
| 552 add_button(mmconv); |
|
| 553 |
|
| 554 conversations = g_list_append(conversations, mmconv); |
|
| 555 } |
|
| 556 |
|
| 557 static void conv_destroyed (GaimConversation *conv) |
|
| 558 { |
|
| 559 MMConversation *mmconv = mmconv_from_conv(conv); |
|
| 560 |
|
| 561 remove_widget(mmconv->button); |
|
| 562 remove_widget(mmconv->seperator); |
|
| 563 if (mmconv->started) |
|
| 564 { |
|
| 565 kill_editor(mmconv); |
|
| 566 } |
|
| 567 conversations = g_list_remove(conversations, mmconv); |
|
| 568 } |
|
| 569 |
|
| 570 static void add_button (MMConversation *mmconv) |
|
| 571 { |
|
| 572 GaimConversation *conv = mmconv->conv; |
|
| 573 |
|
| 574 GtkWidget *button, *image, *sep; |
|
| 575 gchar *file_path; |
|
| 576 |
|
| 577 button = gtk_toggle_button_new(); |
|
| 578 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); |
|
| 579 |
|
| 580 g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(music_button_toggled), mmconv); |
|
| 581 |
|
| 582 file_path = g_build_filename(DATADIR, "pixmaps", "gaim", "buttons", |
|
| 583 "music.png", NULL); |
|
| 584 image = gtk_image_new_from_file(file_path); |
|
| 585 g_free(file_path); |
|
| 586 |
|
| 587 gtk_container_add((GtkContainer *)button, image); |
|
| 588 |
|
| 589 sep = gtk_vseparator_new(); |
|
| 590 |
|
| 591 mmconv->seperator = sep; |
|
| 592 mmconv->button = button; |
|
| 593 |
|
| 594 gtk_widget_show(sep); |
|
| 595 gtk_widget_show(image); |
|
| 596 gtk_widget_show(button); |
|
| 597 |
|
| 598 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), sep, FALSE, FALSE, 0); |
|
| 599 gtk_box_pack_start(GTK_BOX(GAIM_GTK_CONVERSATION(conv)->toolbar), button, FALSE, FALSE, 0); |
|
| 600 } |
|
| 601 |
|
| 602 static void remove_widget (GtkWidget *button) |
|
| 603 { |
|
| 604 gtk_widget_hide(button); |
|
| 605 gtk_widget_destroy(button); |
|
| 606 } |
|
| 607 |
|
| 608 static GtkWidget * |
|
| 609 get_config_frame(GaimPlugin *plugin) |
|
| 610 { |
|
| 611 GtkWidget *ret; |
|
| 612 GtkWidget *vbox; |
|
| 613 |
|
| 614 GtkWidget *editor_path; |
|
| 615 GtkWidget *editor_path_label; |
|
| 616 GtkWidget *editor_path_button; |
|
| 617 |
|
| 618 /* Outside container */ |
|
| 619 ret = gtk_vbox_new(FALSE, 18); |
|
| 620 gtk_container_set_border_width(GTK_CONTAINER(ret), 10); |
|
| 621 |
|
| 622 /* Configuration frame */ |
|
| 623 vbox = gaim_gtk_make_frame(ret, _("Music Messaging Configuration")); |
|
| 624 |
|
| 625 /* Path to the score editor */ |
|
| 626 editor_path = gtk_entry_new(); |
|
| 627 editor_path_label = gtk_label_new(_("Score Editor Path")); |
|
| 628 editor_path_button = gtk_button_new_with_mnemonic(_("_Apply")); |
|
| 629 |
|
| 630 gtk_entry_set_text((GtkEntry*)editor_path, "/usr/local/bin/gscore"); |
|
| 631 |
|
| 632 g_signal_connect(G_OBJECT(editor_path_button), "clicked", |
|
| 633 G_CALLBACK(set_editor_path), editor_path); |
|
| 634 |
|
| 635 gtk_box_pack_start(GTK_BOX(vbox), editor_path_label, FALSE, FALSE, 0); |
|
| 636 gtk_box_pack_start(GTK_BOX(vbox), editor_path, FALSE, FALSE, 0); |
|
| 637 gtk_box_pack_start(GTK_BOX(vbox), editor_path_button, FALSE, FALSE, 0); |
|
| 638 |
|
| 639 gtk_widget_show_all(ret); |
|
| 640 |
|
| 641 return ret; |
|
| 642 } |
|
| 643 |
|
| 644 static GaimGtkPluginUiInfo ui_info = |
|
| 645 { |
|
| 646 get_config_frame, |
|
| 647 0 /* page_num (reserved) */ |
|
| 648 }; |
|
| 649 |
|
| 650 static GaimPluginInfo info = { |
|
| 651 GAIM_PLUGIN_MAGIC, |
|
| 652 GAIM_MAJOR_VERSION, |
|
| 653 GAIM_MINOR_VERSION, |
|
| 654 GAIM_PLUGIN_STANDARD, /**< type */ |
|
| 655 GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ |
|
| 656 0, /**< flags */ |
|
| 657 NULL, /**< dependencies */ |
|
| 658 GAIM_PRIORITY_DEFAULT, /**< priority */ |
|
| 659 |
|
| 660 MUSICMESSAGING_PLUGIN_ID, /**< id */ |
|
| 661 "Music Messaging", /**< name */ |
|
| 662 VERSION, /**< version */ |
|
| 663 N_("Music Messaging Plugin for collaborative composition."), |
|
| 664 /** summary */ |
|
| 665 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."), |
|
| 666 /** description */ |
|
| 667 "Christian Muise <christian.muise@gmail.com>", /**< author */ |
|
| 668 GAIM_WEBSITE, /**< homepage */ |
|
| 669 plugin_load, /**< load */ |
|
| 670 plugin_unload, /**< unload */ |
|
| 671 NULL, /**< destroy */ |
|
| 672 &ui_info, /**< ui_info */ |
|
| 673 NULL, /**< extra_info */ |
|
| 674 NULL, |
|
| 675 NULL |
|
| 676 }; |
|
| 677 |
|
| 678 static void |
|
| 679 init_plugin(GaimPlugin *plugin) { |
|
| 680 gaim_prefs_add_none("/plugins/gtk/musicmessaging"); |
|
| 681 gaim_prefs_add_string("/plugins/gtk/musicmessaging/editor_path", "/usr/local/bin/gscore"); |
|
| 682 } |
|
| 683 |
|
| 684 GAIM_INIT_PLUGIN(musicmessaging, init_plugin, info); |
|