Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * Audacious: A cross-platform multimedia player 00003 * Copyright (c) 2007 Ben Tucker 00004 * Copyright 2009-2010 Audacious development team 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; under version 3 of the License. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses>. 00017 * 00018 * The Audacious team does not consider modular code linking to 00019 * Audacious or using our public API to be a derived work. 00020 */ 00021 00022 #include "config.h" 00023 00024 #include <glib.h> 00025 #include <dbus/dbus.h> 00026 #include <dbus/dbus-glib.h> 00027 #include <dbus/dbus-glib-bindings.h> 00028 #include <dbus/dbus-glib-lowlevel.h> 00029 #include "dbus.h" 00030 #include "dbus-service.h" 00031 #include "dbus-server-bindings.h" 00032 00033 #include <math.h> 00034 #include <libaudcore/eventqueue.h> 00035 00036 #include "audconfig.h" 00037 #include "debug.h" 00038 #include "drct.h" 00039 #include "equalizer.h" 00040 #include "playback.h" 00041 #include "playlist.h" 00042 #include "interface.h" 00043 00044 struct StatusRequest 00045 { 00046 gboolean playing, paused; 00047 gint time, length; 00048 gint bitrate, samplerate, channels; 00049 }; 00050 00051 struct PositionRequest 00052 { 00053 gint playlist; /* -1 = active, -2 = playing */ 00054 gint entry; /* -1 = current */ 00055 gint entry_count, queue_count; 00056 }; 00057 00058 struct InfoRequest 00059 { 00060 gint playlist; /* -1 = active, -2 = playing */ 00061 gint entry; /* -1 = current */ 00062 gchar *filename, *title, *pltitle; 00063 gint length; 00064 }; 00065 00066 struct FieldRequest 00067 { 00068 gint playlist; /* -1 = active, -2 = playing */ 00069 gint entry; /* -1 = current */ 00070 const gchar *field; 00071 GValue *value; 00072 }; 00073 00074 struct AddRequest 00075 { 00076 gint position; /* -1 = at end */ 00077 gchar *filename; 00078 gboolean play; 00079 }; 00080 00081 struct MprisMetadataRequest 00082 { 00083 gint playlist; /* -1 = active, -2 = playing */ 00084 gint entry; /* -1 = current */ 00085 GHashTable *metadata; 00086 }; 00087 00088 static DBusGConnection *dbus_conn = NULL; 00089 static guint signals[LAST_SIG] = { 0 }; 00090 static guint tracklist_signals[LAST_TRACKLIST_SIG] = { 0 }; 00091 00092 MprisPlayer * mpris = NULL; 00093 00094 static GThread *main_thread; 00095 static GMutex *info_mutex; 00096 static GCond *info_cond; 00097 00098 G_DEFINE_TYPE (RemoteObject, audacious_rc, G_TYPE_OBJECT) 00099 G_DEFINE_TYPE (MprisRoot, mpris_root, G_TYPE_OBJECT) 00100 G_DEFINE_TYPE (MprisPlayer, mpris_player, G_TYPE_OBJECT) 00101 G_DEFINE_TYPE (MprisTrackList, mpris_tracklist, G_TYPE_OBJECT) 00102 00103 #define DBUS_TYPE_G_STRING_VALUE_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) 00104 00105 static void mpris_playlist_update_hook(gpointer unused, MprisTrackList *obj); 00106 00107 void audacious_rc_class_init(RemoteObjectClass * klass) 00108 { 00109 } 00110 00111 void mpris_root_class_init(MprisRootClass * klass) 00112 { 00113 } 00114 00115 void mpris_player_class_init(MprisPlayerClass * klass) 00116 { 00117 signals[CAPS_CHANGE_SIG] = g_signal_new("caps_change", G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); 00118 signals[TRACK_CHANGE_SIG] = 00119 g_signal_new("track_change", 00120 G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_VALUE_HASHTABLE); 00121 signals[STATUS_CHANGE_SIG] = 00122 g_signal_new("status_change", G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_VALUE_ARRAY); 00123 } 00124 00125 void mpris_tracklist_class_init(MprisTrackListClass * klass) 00126 { 00127 tracklist_signals[TRACKLIST_CHANGE_SIG] = g_signal_new("track_list_change", G_OBJECT_CLASS_TYPE(klass), 00128 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); 00129 } 00130 00131 void audacious_rc_init(RemoteObject * object) 00132 { 00133 GError *error = NULL; 00134 DBusGProxy *driver_proxy; 00135 guint request_ret; 00136 00137 AUDDBG ("Registering remote D-Bus interfaces.\n"); 00138 00139 dbus_g_object_type_install_info(audacious_rc_get_type(), &dbus_glib_audacious_rc_object_info); 00140 00141 // Register DBUS path 00142 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH, G_OBJECT(object)); 00143 00144 // Register the service name, the constants here are defined in 00145 // dbus-glib-bindings.h 00146 driver_proxy = dbus_g_proxy_new_for_name(dbus_conn, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); 00147 00148 if (!org_freedesktop_DBus_request_name(driver_proxy, AUDACIOUS_DBUS_SERVICE, 0, &request_ret, &error)) 00149 { 00150 g_warning("Unable to register service: %s", error->message); 00151 g_error_free(error); 00152 } 00153 00154 if (!org_freedesktop_DBus_request_name(driver_proxy, AUDACIOUS_DBUS_SERVICE_MPRIS, 0, &request_ret, &error)) 00155 { 00156 g_warning("Unable to register service: %s", error->message); 00157 g_error_free(error); 00158 } 00159 00160 g_object_unref(driver_proxy); 00161 } 00162 00163 void mpris_root_init(MprisRoot * object) 00164 { 00165 dbus_g_object_type_install_info(mpris_root_get_type(), &dbus_glib_mpris_root_object_info); 00166 00167 // Register DBUS path 00168 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_ROOT, G_OBJECT(object)); 00169 } 00170 00171 void mpris_player_init(MprisPlayer * object) 00172 { 00173 dbus_g_object_type_install_info(mpris_player_get_type(), &dbus_glib_mpris_player_object_info); 00174 00175 // Register DBUS path 00176 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_PLAYER, G_OBJECT(object)); 00177 00178 // Add signals 00179 DBusGProxy *proxy = object->proxy; 00180 if (proxy != NULL) 00181 { 00182 dbus_g_proxy_add_signal (proxy, "StatusChange", dbus_g_type_get_struct 00183 ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 00184 G_TYPE_INVALID), G_TYPE_INVALID); 00185 dbus_g_proxy_add_signal (proxy, "CapsChange", G_TYPE_INT, G_TYPE_INVALID); 00186 dbus_g_proxy_add_signal(proxy, "TrackChange", DBUS_TYPE_G_STRING_VALUE_HASHTABLE, G_TYPE_INVALID); 00187 } 00188 else 00189 { 00190 /* XXX / FIXME: Why does this happen? -- ccr */ 00191 AUDDBG ("object->proxy == NULL; not adding some signals.\n"); 00192 } 00193 } 00194 00195 void mpris_tracklist_init(MprisTrackList * object) 00196 { 00197 dbus_g_object_type_install_info(mpris_tracklist_get_type(), &dbus_glib_mpris_tracklist_object_info); 00198 00199 // Register DBUS path 00200 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_TRACKLIST, G_OBJECT(object)); 00201 00202 // Add signals 00203 DBusGProxy *proxy = object->proxy; 00204 if (proxy != NULL) 00205 { 00206 dbus_g_proxy_add_signal(proxy, "TrackListChange", G_TYPE_INT, G_TYPE_INVALID); 00207 } 00208 else 00209 { 00210 /* XXX / FIXME: Why does this happen? -- ccr */ 00211 AUDDBG ("object->proxy == NULL, not adding some signals.\n"); 00212 } 00213 00214 hook_associate("playlist update", (HookFunction) mpris_playlist_update_hook, object); 00215 } 00216 00217 void init_dbus() 00218 { 00219 GError *error = NULL; 00220 DBusConnection *local_conn; 00221 00222 main_thread = g_thread_self(); 00223 info_mutex = g_mutex_new(); 00224 info_cond = g_cond_new(); 00225 00226 AUDDBG ("Trying to initialize D-Bus.\n"); 00227 dbus_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); 00228 if (dbus_conn == NULL) 00229 { 00230 g_warning("Unable to connect to dbus: %s", error->message); 00231 g_error_free(error); 00232 return; 00233 } 00234 00235 g_type_init(); 00236 g_object_new(audacious_rc_get_type(), NULL); 00237 g_object_new(mpris_root_get_type(), NULL); 00238 mpris = g_object_new(mpris_player_get_type(), NULL); 00239 g_object_new(mpris_tracklist_get_type(), NULL); 00240 00241 local_conn = dbus_g_connection_get_connection(dbus_conn); 00242 dbus_connection_set_exit_on_disconnect(local_conn, FALSE); 00243 } 00244 00245 static GValue *tuple_value_to_gvalue(const Tuple * tuple, const gchar * key) 00246 { 00247 GValue *val; 00248 TupleValueType type = tuple_get_value_type((Tuple *) tuple, -1, key); 00249 00250 if (type == TUPLE_STRING) 00251 { 00252 val = g_new0(GValue, 1); 00253 g_value_init(val, G_TYPE_STRING); 00254 g_value_take_string(val, g_strdup(tuple_get_string((Tuple *) tuple, -1, key))); 00255 return val; 00256 } 00257 else if (type == TUPLE_INT) 00258 { 00259 val = g_new0(GValue, 1); 00260 g_value_init(val, G_TYPE_INT); 00261 g_value_set_int(val, tuple_get_int((Tuple *) tuple, -1, key)); 00262 return val; 00263 } 00264 return NULL; 00265 } 00266 00275 static void tuple_insert_to_hash_full(GHashTable * md, const Tuple * tuple, 00276 const gchar * tuple_key, const gchar *key) 00277 { 00278 GValue *value = tuple_value_to_gvalue(tuple, tuple_key); 00279 if (value != NULL) 00280 g_hash_table_insert (md, (void *) key, value); 00281 } 00282 00283 static void tuple_insert_to_hash(GHashTable * md, const Tuple * tuple, 00284 const gchar *key) 00285 { 00286 tuple_insert_to_hash_full(md, tuple, key, key); 00287 } 00288 00289 static void remove_metadata_value(gpointer value) 00290 { 00291 g_value_unset((GValue *) value); 00292 g_free((GValue *) value); 00293 } 00294 00295 static GHashTable *make_mpris_metadata(const gchar * filename, const Tuple * tuple) 00296 { 00297 GHashTable *md = NULL; 00298 gpointer value; 00299 00300 md = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, remove_metadata_value); 00301 00302 value = g_malloc(sizeof(GValue)); 00303 memset(value, 0, sizeof(GValue)); 00304 g_value_init(value, G_TYPE_STRING); 00305 g_value_take_string(value, g_strdup(filename)); 00306 g_hash_table_insert(md, "location", value); 00307 00308 if (tuple != NULL) 00309 { 00310 tuple_insert_to_hash_full(md, tuple, "length", "mtime"); 00311 tuple_insert_to_hash(md, tuple, "title"); 00312 tuple_insert_to_hash(md, tuple, "artist"); 00313 tuple_insert_to_hash(md, tuple, "album"); 00314 tuple_insert_to_hash(md, tuple, "comment"); 00315 tuple_insert_to_hash(md, tuple, "genre"); 00316 tuple_insert_to_hash(md, tuple, "year"); 00317 tuple_insert_to_hash(md, tuple, "codec"); 00318 tuple_insert_to_hash(md, tuple, "quality"); 00319 tuple_insert_to_hash_full(md, tuple, "track-number", "tracknumber"); 00320 tuple_insert_to_hash_full(md, tuple, "bitrate", "audio-bitrate"); 00321 } 00322 00323 return md; 00324 } 00325 00326 static void real_position(gint * playlist, gint * entry) 00327 { 00328 if (*playlist == -2) 00329 *playlist = playlist_get_playing(); 00330 if (*playlist == -1) 00331 *playlist = playlist_get_active(); 00332 if (*entry == -1) 00333 *entry = playlist_get_position(*playlist); 00334 } 00335 00336 static gboolean get_status_cb(void *data) 00337 { 00338 struct StatusRequest *request = data; 00339 00340 g_mutex_lock(info_mutex); 00341 00342 memset (request, 0, sizeof (* request)); 00343 request->playing = playback_get_playing(); 00344 00345 if (request->playing) 00346 { 00347 request->paused = playback_get_paused (); 00348 request->time = playback_get_time (); 00349 request->length = playback_get_length (); 00350 playback_get_info (& request->bitrate, & request->samplerate, 00351 & request->channels); 00352 } 00353 00354 g_cond_signal(info_cond); 00355 g_mutex_unlock(info_mutex); 00356 return FALSE; 00357 } 00358 00359 static void get_status(struct StatusRequest *request) 00360 { 00361 if (g_thread_self() == main_thread) 00362 get_status_cb(request); 00363 else 00364 { 00365 g_mutex_lock(info_mutex); 00366 g_timeout_add(0, get_status_cb, request); 00367 g_cond_wait(info_cond, info_mutex); 00368 g_mutex_unlock(info_mutex); 00369 } 00370 } 00371 00372 static gboolean get_position_cb(void *data) 00373 { 00374 struct PositionRequest *request = data; 00375 00376 g_mutex_lock(info_mutex); 00377 00378 real_position(&request->playlist, &request->entry); 00379 request->entry_count = playlist_entry_count(request->playlist); 00380 request->queue_count = playlist_queue_count(request->playlist); 00381 00382 g_cond_signal(info_cond); 00383 g_mutex_unlock(info_mutex); 00384 return FALSE; 00385 } 00386 00387 static void get_position(struct PositionRequest *request) 00388 { 00389 if (g_thread_self() == main_thread) 00390 get_position_cb(request); 00391 else 00392 { 00393 g_mutex_lock(info_mutex); 00394 g_timeout_add(0, get_position_cb, request); 00395 g_cond_wait(info_cond, info_mutex); 00396 g_mutex_unlock(info_mutex); 00397 } 00398 } 00399 00400 static gboolean get_info_cb(void *data) 00401 { 00402 struct InfoRequest *request = data; 00403 00404 g_mutex_lock(info_mutex); 00405 00406 real_position(&request->playlist, &request->entry); 00407 request->filename = playlist_entry_get_filename (request->playlist, 00408 request->entry); 00409 request->title = playlist_entry_get_title (request->playlist, 00410 request->entry, FALSE); 00411 request->length = playlist_entry_get_length (request->playlist, 00412 request->entry, FALSE); 00413 request->pltitle = playlist_get_title (request->playlist); 00414 00415 g_cond_signal(info_cond); 00416 g_mutex_unlock(info_mutex); 00417 return FALSE; 00418 } 00419 00420 static void get_info(struct InfoRequest *request) 00421 { 00422 if (g_thread_self() == main_thread) 00423 get_info_cb(request); 00424 else 00425 { 00426 g_mutex_lock(info_mutex); 00427 g_timeout_add(0, get_info_cb, request); 00428 g_cond_wait(info_cond, info_mutex); 00429 g_mutex_unlock(info_mutex); 00430 } 00431 } 00432 00433 static gboolean get_field_cb(void *data) 00434 { 00435 struct FieldRequest *request = data; 00436 00437 g_mutex_lock(info_mutex); 00438 00439 real_position(&request->playlist, &request->entry); 00440 Tuple * tuple = playlist_entry_get_tuple (request->playlist, request->entry, FALSE); 00441 request->value = (tuple == NULL) ? NULL : tuple_value_to_gvalue(tuple, request->field); 00442 if (tuple) 00443 tuple_free (tuple) 00444 00445 g_cond_signal(info_cond); 00446 g_mutex_unlock(info_mutex); 00447 return FALSE; 00448 } 00449 00450 static void get_field(struct FieldRequest *request) 00451 { 00452 if (g_thread_self() == main_thread) 00453 get_field_cb(request); 00454 else 00455 { 00456 g_mutex_lock(info_mutex); 00457 g_timeout_add(0, get_field_cb, request); 00458 g_cond_wait(info_cond, info_mutex); 00459 g_mutex_unlock(info_mutex); 00460 } 00461 } 00462 00463 static gboolean play_cb(void *unused) 00464 { 00465 /* Only the active playlist is visible through DBUS interface, so make sure 00466 * to play from it, not another playlist. --jlindgren */ 00467 if (playlist_get_playing () != playlist_get_active ()) 00468 playlist_set_playing (playlist_get_active ()); 00469 00470 drct_play(); 00471 return FALSE; 00472 } 00473 00474 static gboolean pause_cb(void *unused) 00475 { 00476 playback_pause(); 00477 return FALSE; 00478 } 00479 00480 static gboolean play_pause_cb(void *unused) 00481 { 00482 if (playback_get_playing()) 00483 playback_pause(); 00484 else 00485 playback_play (0, FALSE); 00486 00487 return FALSE; 00488 } 00489 00490 static gboolean seek_cb(void *data) 00491 { 00492 playback_seek (GPOINTER_TO_INT (data)); 00493 return FALSE; 00494 } 00495 00496 static gboolean stop_cb(void *unused) 00497 { 00498 playback_stop(); 00499 return FALSE; 00500 } 00501 00502 static gboolean prev_cb(void *unused) 00503 { 00504 drct_pl_prev(); 00505 return FALSE; 00506 } 00507 00508 static gboolean next_cb(void *unused) 00509 { 00510 drct_pl_next(); 00511 return FALSE; 00512 } 00513 00514 static gboolean jump_cb(void *data) 00515 { 00516 drct_pl_set_pos(GPOINTER_TO_INT(data)); 00517 return FALSE; 00518 } 00519 00520 static gboolean add_cb(void *data) 00521 { 00522 struct AddRequest *request = data; 00523 gint playlist = playlist_get_active(); 00524 00525 if (request->position < 0) 00526 request->position = playlist_entry_count (playlist); 00527 00528 drct_pl_add (request->filename, request->position); 00529 00530 if (request->play) 00531 { 00532 playlist_set_playing(playlist); 00533 playlist_set_position(playlist, request->position); 00534 playback_play (0, FALSE); 00535 } 00536 00537 g_free(request); 00538 return FALSE; 00539 } 00540 00541 static gboolean delete_cb(void *data) 00542 { 00543 drct_pl_delete(GPOINTER_TO_INT(data)); 00544 return FALSE; 00545 } 00546 00547 static gboolean clear_cb(void *unused) 00548 { 00549 drct_pl_clear(); 00550 return FALSE; 00551 } 00552 00553 static gboolean add_to_queue_cb(void *data) 00554 { 00555 drct_pq_add(GPOINTER_TO_INT(data)); 00556 return FALSE; 00557 } 00558 00559 static gboolean remove_from_queue_cb(void *data) 00560 { 00561 drct_pq_remove(GPOINTER_TO_INT(data)); 00562 return FALSE; 00563 } 00564 00565 static gboolean clear_queue_cb(void *unused) 00566 { 00567 drct_pq_clear(); 00568 return FALSE; 00569 } 00570 00571 static gboolean queue_get_entry_cb(void *data) 00572 { 00573 g_mutex_lock(info_mutex); 00574 00575 * (gint *) data = drct_pq_get_entry (* (gint *) data); 00576 00577 g_cond_signal(info_cond); 00578 g_mutex_unlock(info_mutex); 00579 return FALSE; 00580 } 00581 00582 static gint queue_get_entry(gint position) 00583 { 00584 if (g_thread_self() == main_thread) 00585 queue_get_entry_cb(&position); 00586 else 00587 { 00588 g_mutex_lock(info_mutex); 00589 g_timeout_add(0, queue_get_entry_cb, &position); 00590 g_cond_wait(info_cond, info_mutex); 00591 g_mutex_unlock(info_mutex); 00592 } 00593 00594 return position; 00595 } 00596 00597 static gboolean queue_find_entry_cb(void *data) 00598 { 00599 g_mutex_lock(info_mutex); 00600 00601 *(gint *) data = drct_pq_get_queue_position(*(gint *) data); 00602 00603 g_cond_signal(info_cond); 00604 g_mutex_unlock(info_mutex); 00605 return FALSE; 00606 } 00607 00608 static gint queue_find_entry(gint position) 00609 { 00610 if (g_thread_self() == main_thread) 00611 queue_find_entry_cb(&position); 00612 else 00613 { 00614 g_mutex_lock(info_mutex); 00615 g_timeout_add(0, queue_find_entry_cb, &position); 00616 g_cond_wait(info_cond, info_mutex); 00617 g_mutex_unlock(info_mutex); 00618 } 00619 00620 return position; 00621 } 00622 00623 gboolean add_to_new_playlist_cb(void *data) 00624 { 00625 drct_pl_open_temp (data); 00626 g_free(data); 00627 return FALSE; 00628 } 00629 00630 static gboolean get_mpris_metadata_cb(void *data) 00631 { 00632 struct MprisMetadataRequest *request = data; 00633 00634 g_mutex_lock(info_mutex); 00635 00636 real_position(&request->playlist, &request->entry); 00637 gchar * filename = playlist_entry_get_filename (request->playlist, 00638 request->entry); 00639 Tuple * tuple = playlist_entry_get_tuple (request->playlist, request->entry, 00640 FALSE); 00641 00642 if (filename && tuple) 00643 request->metadata = make_mpris_metadata (filename, tuple); 00644 else 00645 request->metadata = NULL; 00646 00647 g_free (filename); 00648 if (tuple) 00649 tuple_free (tuple); 00650 00651 g_cond_signal(info_cond); 00652 g_mutex_unlock(info_mutex); 00653 return FALSE; 00654 } 00655 00656 static void get_mpris_metadata(struct MprisMetadataRequest *request) 00657 { 00658 if (g_thread_self() == main_thread) 00659 get_mpris_metadata_cb(request); 00660 else 00661 { 00662 g_mutex_lock(info_mutex); 00663 g_timeout_add(0, get_mpris_metadata_cb, request); 00664 g_cond_wait(info_cond, info_mutex); 00665 g_mutex_unlock(info_mutex); 00666 } 00667 } 00668 00669 static gboolean set_no_playlist_advance_cb (void * no_advance) 00670 { 00671 cfg.no_playlist_advance = GPOINTER_TO_INT (no_advance); 00672 event_queue ("toggle no playlist advance", NULL); 00673 return FALSE; 00674 } 00675 00676 static gboolean set_shuffle_cb (void * shuffle) 00677 { 00678 cfg.shuffle = GPOINTER_TO_INT (shuffle); 00679 event_queue ("toggle shuffle", NULL); 00680 return FALSE; 00681 } 00682 00683 static gboolean set_repeat_cb (void * repeat) 00684 { 00685 cfg.repeat = GPOINTER_TO_INT (repeat); 00686 event_queue ("toggle repeat", NULL); 00687 return FALSE; 00688 } 00689 00690 /* MPRIS API */ 00691 // MPRIS / 00692 gboolean mpris_root_identity(MprisRoot * obj, gchar ** identity, GError ** error) 00693 { 00694 *identity = g_strdup_printf("Audacious %s", VERSION); 00695 return TRUE; 00696 } 00697 00698 gboolean mpris_root_quit(MprisPlayer * obj, GError ** error) 00699 { 00700 event_queue("quit", NULL); 00701 return TRUE; 00702 } 00703 00704 // MPRIS /Player 00705 00706 gboolean mpris_player_next(MprisPlayer * obj, GError * *error) 00707 { 00708 g_timeout_add(0, next_cb, NULL); 00709 return TRUE; 00710 } 00711 00712 gboolean mpris_player_prev(MprisPlayer * obj, GError * *error) 00713 { 00714 g_timeout_add(0, prev_cb, NULL); 00715 return TRUE; 00716 } 00717 00718 gboolean mpris_player_pause(MprisPlayer * obj, GError * *error) 00719 { 00720 g_timeout_add(0, pause_cb, NULL); 00721 return TRUE; 00722 } 00723 00724 gboolean mpris_player_stop(MprisPlayer * obj, GError * *error) 00725 { 00726 g_timeout_add(0, stop_cb, NULL); 00727 return TRUE; 00728 } 00729 00730 gboolean mpris_player_play(MprisPlayer * obj, GError * *error) 00731 { 00732 g_timeout_add(0, play_cb, NULL); 00733 return TRUE; 00734 } 00735 00736 gboolean mpris_player_repeat(MprisPlayer * obj, gboolean rpt, GError ** error) 00737 { 00738 fprintf (stderr, "implement me\n"); 00739 return TRUE; 00740 } 00741 00742 static void append_int_value(GValueArray * ar, gint tmp) 00743 { 00744 GValue value; 00745 memset(&value, 0, sizeof(value)); 00746 g_value_init(&value, G_TYPE_INT); 00747 g_value_set_int(&value, tmp); 00748 g_value_array_append(ar, &value); 00749 } 00750 00751 static gint get_playback_status(void) 00752 { 00753 struct StatusRequest request; 00754 get_status(&request); 00755 00756 return (!request.playing ? MPRIS_STATUS_STOP : request.paused ? MPRIS_STATUS_PAUSE : MPRIS_STATUS_PLAY); 00757 } 00758 00759 gboolean mpris_player_get_status(MprisPlayer * obj, GValueArray * *status, GError * *error) 00760 { 00761 *status = g_value_array_new(4); 00762 00763 append_int_value(*status, (gint) get_playback_status()); 00764 append_int_value(*status, (gint) cfg.shuffle); 00765 append_int_value(*status, (gint) cfg.no_playlist_advance); 00766 append_int_value(*status, (gint) cfg.repeat); 00767 return TRUE; 00768 } 00769 00770 gboolean mpris_player_get_metadata(MprisPlayer * obj, GHashTable * *metadata, GError * *error) 00771 { 00772 struct MprisMetadataRequest request = {.playlist = -1,.entry = -1 }; 00773 00774 get_mpris_metadata(&request); 00775 *metadata = request.metadata; 00776 return TRUE; 00777 } 00778 00779 gboolean mpris_player_get_caps(MprisPlayer * obj, gint * capabilities, GError ** error) 00780 { 00781 *capabilities = MPRIS_CAPS_CAN_GO_NEXT | MPRIS_CAPS_CAN_GO_PREV | MPRIS_CAPS_CAN_PAUSE | MPRIS_CAPS_CAN_PLAY | MPRIS_CAPS_CAN_SEEK | MPRIS_CAPS_CAN_PROVIDE_METADATA | MPRIS_CAPS_PROVIDES_TIMING; 00782 return TRUE; 00783 } 00784 00785 gboolean mpris_player_volume_set(MprisPlayer * obj, gint vol, GError ** error) 00786 { 00787 drct_set_volume_main (vol); 00788 return TRUE; 00789 } 00790 00791 gboolean mpris_player_volume_get(MprisPlayer * obj, gint * vol, GError ** error) 00792 { 00793 drct_get_volume_main (vol); 00794 return TRUE; 00795 } 00796 00797 gboolean mpris_player_position_set(MprisPlayer * obj, gint pos, GError * *error) 00798 { 00799 g_timeout_add(0, seek_cb, GINT_TO_POINTER(pos)); 00800 return TRUE; 00801 } 00802 00803 gboolean mpris_player_position_get(MprisPlayer * obj, gint * pos, GError * *error) 00804 { 00805 struct StatusRequest request; 00806 00807 get_status(&request); 00808 *pos = request.time; 00809 return TRUE; 00810 } 00811 00812 // MPRIS /Player signals 00813 gboolean mpris_emit_caps_change(MprisPlayer * obj) 00814 { 00815 g_signal_emit(obj, signals[CAPS_CHANGE_SIG], 0, 0); 00816 return TRUE; 00817 } 00818 00819 gboolean mpris_emit_track_change(MprisPlayer * obj) 00820 { 00821 gint playlist, entry; 00822 GHashTable *metadata; 00823 00824 playlist = playlist_get_playing(); 00825 entry = playlist_get_position(playlist); 00826 gchar * filename = playlist_entry_get_filename (playlist, entry); 00827 Tuple * tuple = playlist_entry_get_tuple (playlist, entry, FALSE); 00828 00829 if (filename && tuple) 00830 { 00831 metadata = make_mpris_metadata (filename, tuple); 00832 g_signal_emit (obj, signals[TRACK_CHANGE_SIG], 0, metadata); 00833 g_hash_table_destroy (metadata); 00834 } 00835 00836 g_free (filename); 00837 if (tuple) 00838 tuple_free (tuple); 00839 00840 return (filename && tuple); 00841 } 00842 00843 gboolean mpris_emit_status_change(MprisPlayer * obj, PlaybackStatus status) 00844 { 00845 GValueArray *ar = g_value_array_new(4); 00846 00847 if (status == MPRIS_STATUS_INVALID) 00848 status = get_playback_status (); 00849 00850 append_int_value(ar, (gint) status); 00851 append_int_value(ar, (gint) cfg.shuffle); 00852 append_int_value(ar, (gint) cfg.no_playlist_advance); 00853 append_int_value(ar, (gint) cfg.repeat); 00854 00855 g_signal_emit(obj, signals[STATUS_CHANGE_SIG], 0, ar); 00856 g_value_array_free(ar); 00857 return TRUE; 00858 } 00859 00860 // MPRIS /TrackList 00861 gboolean mpris_emit_tracklist_change(MprisTrackList * obj, gint playlist) 00862 { 00863 g_signal_emit(obj, tracklist_signals[TRACKLIST_CHANGE_SIG], 0, playlist_entry_count(playlist)); 00864 return TRUE; 00865 } 00866 00867 static void mpris_playlist_update_hook(gpointer unused, MprisTrackList * obj) 00868 { 00869 gint playlist = playlist_get_active(); 00870 00871 mpris_emit_tracklist_change(obj, playlist); 00872 } 00873 00874 gboolean mpris_tracklist_get_metadata(MprisTrackList * obj, gint pos, GHashTable * *metadata, GError * *error) 00875 { 00876 struct MprisMetadataRequest request = {.playlist = -1,.entry = pos }; 00877 00878 get_mpris_metadata(&request); 00879 *metadata = request.metadata; 00880 return TRUE; 00881 } 00882 00883 gboolean mpris_tracklist_get_current_track(MprisTrackList * obj, gint * pos, GError * *error) 00884 { 00885 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 00886 00887 get_position(&request); 00888 *pos = request.entry; 00889 return TRUE; 00890 } 00891 00892 gboolean mpris_tracklist_get_length(MprisTrackList * obj, gint * length, GError * *error) 00893 { 00894 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 00895 00896 get_position(&request); 00897 *length = request.entry_count; 00898 return TRUE; 00899 } 00900 00901 gboolean mpris_tracklist_add_track(MprisTrackList * obj, gchar * uri, gboolean play, GError * *error) 00902 { 00903 struct AddRequest *request = g_malloc(sizeof(struct AddRequest)); 00904 00905 request->position = -1; 00906 request->filename = g_strdup(uri); 00907 request->play = play; 00908 00909 g_timeout_add(0, add_cb, request); 00910 return TRUE; 00911 } 00912 00913 gboolean mpris_tracklist_del_track(MprisTrackList * obj, gint pos, GError * *error) 00914 { 00915 g_timeout_add(0, delete_cb, GINT_TO_POINTER(pos)); 00916 return TRUE; 00917 } 00918 00919 gboolean mpris_tracklist_loop (MprisTrackList * obj, gboolean loop, GError * * 00920 error) 00921 { 00922 g_timeout_add (0, set_repeat_cb, GINT_TO_POINTER (loop)); 00923 return TRUE; 00924 } 00925 00926 gboolean mpris_tracklist_random (MprisTrackList * obj, gboolean random, 00927 GError * * error) 00928 { 00929 g_timeout_add (0, set_shuffle_cb, GINT_TO_POINTER (random)); 00930 return TRUE; 00931 } 00932 00933 // Audacious General Information 00934 gboolean audacious_rc_version(RemoteObject * obj, gchar ** version, GError ** error) 00935 { 00936 *version = g_strdup(VERSION); 00937 return TRUE; 00938 } 00939 00940 gboolean audacious_rc_quit(RemoteObject * obj, GError * *error) 00941 { 00942 event_queue("quit", NULL); 00943 return TRUE; 00944 } 00945 00946 gboolean audacious_rc_eject(RemoteObject * obj, GError ** error) 00947 { 00948 interface_show_filebrowser (TRUE); 00949 return TRUE; 00950 } 00951 00952 gboolean audacious_rc_main_win_visible (RemoteObject * obj, 00953 gboolean * visible, GError ** error) 00954 { 00955 * visible = interface_is_shown (); 00956 return TRUE; 00957 } 00958 00959 gboolean audacious_rc_show_main_win (RemoteObject * obj, gboolean show, 00960 GError * * error) 00961 { 00962 interface_show (show); 00963 return TRUE; 00964 } 00965 00966 gboolean audacious_rc_get_tuple_fields(RemoteObject * obj, gchar *** fields, GError ** error) 00967 { 00968 gchar **res = g_new0(gchar *, FIELD_LAST + 1); 00969 gint i; 00970 for (i = 0; i < FIELD_LAST; i++) 00971 { 00972 res[i] = g_strdup(tuple_fields[i].name); 00973 } 00974 *fields = res; 00975 00976 return TRUE; 00977 } 00978 00979 00980 // Playback Information/Manipulation 00981 00982 gboolean audacious_rc_play(RemoteObject * obj, GError * *error) 00983 { 00984 g_timeout_add(0, play_cb, NULL); 00985 return TRUE; 00986 } 00987 00988 gboolean audacious_rc_pause(RemoteObject * obj, GError * *error) 00989 { 00990 g_timeout_add(0, pause_cb, NULL); 00991 return TRUE; 00992 } 00993 00994 gboolean audacious_rc_stop(RemoteObject * obj, GError * *error) 00995 { 00996 g_timeout_add(0, stop_cb, NULL); 00997 return TRUE; 00998 } 00999 01000 gboolean audacious_rc_playing(RemoteObject * obj, gboolean * is_playing, GError * *error) 01001 { 01002 struct StatusRequest request; 01003 01004 get_status(&request); 01005 *is_playing = request.playing; 01006 return TRUE; 01007 } 01008 01009 gboolean audacious_rc_paused(RemoteObject * obj, gboolean * is_paused, GError * *error) 01010 { 01011 struct StatusRequest request; 01012 01013 get_status(&request); 01014 *is_paused = request.paused; 01015 return TRUE; 01016 } 01017 01018 gboolean audacious_rc_stopped(RemoteObject * obj, gboolean * is_stopped, GError * *error) 01019 { 01020 struct StatusRequest request; 01021 01022 get_status(&request); 01023 *is_stopped = !request.playing; 01024 return TRUE; 01025 } 01026 01027 gboolean audacious_rc_status(RemoteObject * obj, gchar * *status, GError * *error) 01028 { 01029 struct StatusRequest request; 01030 01031 get_status(&request); 01032 *status = g_strdup(!request.playing ? "stopped" : request.paused ? "paused" : "playing"); 01033 return TRUE; 01034 } 01035 01036 gboolean audacious_rc_info(RemoteObject * obj, gint * rate, gint * freq, gint * nch, GError * *error) 01037 { 01038 struct StatusRequest request; 01039 01040 get_status(&request); 01041 *rate = request.bitrate; 01042 *freq = request.samplerate; 01043 *nch = request.channels; 01044 return TRUE; 01045 } 01046 01047 gboolean audacious_rc_time(RemoteObject * obj, gint * time, GError * *error) 01048 { 01049 struct StatusRequest request; 01050 01051 get_status(&request); 01052 *time = request.time; 01053 return TRUE; 01054 } 01055 01056 gboolean audacious_rc_seek(RemoteObject * obj, guint pos, GError * *error) 01057 { 01058 g_timeout_add(0, seek_cb, GINT_TO_POINTER(pos)); 01059 return TRUE; 01060 } 01061 01062 gboolean audacious_rc_volume(RemoteObject * obj, gint * vl, gint * vr, GError ** error) 01063 { 01064 drct_get_volume (vl, vr); 01065 return TRUE; 01066 } 01067 01068 gboolean audacious_rc_set_volume(RemoteObject * obj, gint vl, gint vr, GError ** error) 01069 { 01070 drct_set_volume (vl, vr); 01071 return TRUE; 01072 } 01073 01074 gboolean audacious_rc_balance(RemoteObject * obj, gint * balance, GError ** error) 01075 { 01076 drct_get_volume_balance (balance); 01077 return TRUE; 01078 } 01079 01080 // Playlist Information/Manipulation 01081 01082 gboolean audacious_rc_position(RemoteObject * obj, gint * pos, GError * *error) 01083 { 01084 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 01085 01086 get_position(&request); 01087 *pos = request.entry; 01088 return TRUE; 01089 } 01090 01091 gboolean audacious_rc_advance(RemoteObject * obj, GError * *error) 01092 { 01093 g_timeout_add(0, next_cb, NULL); 01094 return TRUE; 01095 } 01096 01097 gboolean audacious_rc_reverse(RemoteObject * obj, GError * *error) 01098 { 01099 g_timeout_add(0, prev_cb, NULL); 01100 return TRUE; 01101 } 01102 01103 gboolean audacious_rc_length(RemoteObject * obj, gint * length, GError * *error) 01104 { 01105 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 01106 01107 get_position(&request); 01108 *length = request.entry_count; 01109 return TRUE; 01110 } 01111 01112 gboolean audacious_rc_song_title(RemoteObject * obj, guint pos, gchar * *title, GError * *error) 01113 { 01114 struct InfoRequest request = {.playlist = -1,.entry = pos }; 01115 01116 get_info(&request); 01117 g_free(request.filename); 01118 g_free(request.pltitle); 01119 *title = request.title; 01120 return TRUE; 01121 } 01122 01123 gboolean audacious_rc_song_filename(RemoteObject * obj, guint pos, gchar * *filename, GError * *error) 01124 { 01125 struct InfoRequest request = {.playlist = -1,.entry = pos }; 01126 01127 get_info(&request); 01128 *filename = request.filename; 01129 g_free(request.title); 01130 g_free(request.pltitle); 01131 return TRUE; 01132 } 01133 01134 gboolean audacious_rc_song_length(RemoteObject * obj, guint pos, gint * length, GError * *error) 01135 { 01136 audacious_rc_song_frames(obj, pos, length, error); 01137 *length /= 1000; 01138 return TRUE; 01139 } 01140 01141 gboolean audacious_rc_song_frames(RemoteObject * obj, guint pos, gint * length, GError * *error) 01142 { 01143 struct InfoRequest request = {.playlist = -1,.entry = pos }; 01144 01145 get_info(&request); 01146 g_free(request.filename); 01147 g_free(request.title); 01148 g_free(request.pltitle); 01149 *length = request.length; 01150 return TRUE; 01151 } 01152 01153 gboolean audacious_rc_song_tuple(RemoteObject * obj, guint pos, gchar * field, GValue * value, GError * *error) 01154 { 01155 struct FieldRequest request = {.playlist = -1,.entry = pos,.field = field }; 01156 01157 get_field(&request); 01158 01159 if (request.value == NULL) 01160 return FALSE; 01161 01162 memset(value, 0, sizeof(GValue)); 01163 g_value_init(value, G_VALUE_TYPE(request.value)); 01164 g_value_copy(request.value, value); 01165 g_value_unset(request.value); 01166 g_free(request.value); 01167 return TRUE; 01168 } 01169 01170 gboolean audacious_rc_jump(RemoteObject * obj, guint pos, GError * *error) 01171 { 01172 g_timeout_add(0, jump_cb, GINT_TO_POINTER(pos)); 01173 return TRUE; 01174 } 01175 01176 gboolean audacious_rc_add(RemoteObject * obj, gchar * file, GError * *error) 01177 { 01178 return audacious_rc_playlist_ins_url_string(obj, file, -1, error); 01179 } 01180 01181 gboolean audacious_rc_add_url(RemoteObject * obj, gchar * file, GError * *error) 01182 { 01183 return audacious_rc_playlist_ins_url_string(obj, file, -1, error); 01184 } 01185 01186 static GList * string_array_to_list (gchar * * strings) 01187 { 01188 GList * list = NULL; 01189 01190 while (* strings != NULL) 01191 list = g_list_prepend (list, * strings ++); 01192 01193 return g_list_reverse (list); 01194 } 01195 01196 gboolean audacious_rc_add_list (RemoteObject * obj, gchar * * filenames, 01197 GError * * error) 01198 { 01199 GList * list = string_array_to_list (filenames); 01200 01201 drct_pl_add_list (list, -1); 01202 g_list_free (list); 01203 return TRUE; 01204 } 01205 01206 gboolean audacious_rc_open_list (RemoteObject * obj, gchar * * filenames, 01207 GError * * error) 01208 { 01209 GList * list = string_array_to_list (filenames); 01210 01211 drct_pl_open_list (list); 01212 g_list_free (list); 01213 return TRUE; 01214 } 01215 01216 gboolean audacious_rc_open_list_to_temp (RemoteObject * obj, gchar * * 01217 filenames, GError * * error) 01218 { 01219 GList * list = string_array_to_list (filenames); 01220 01221 drct_pl_open_temp_list (list); 01222 g_list_free (list); 01223 return TRUE; 01224 } 01225 01226 gboolean audacious_rc_delete(RemoteObject * obj, guint pos, GError * *error) 01227 { 01228 g_timeout_add(0, delete_cb, GINT_TO_POINTER(pos)); 01229 return TRUE; 01230 } 01231 01232 gboolean audacious_rc_clear(RemoteObject * obj, GError * *error) 01233 { 01234 g_timeout_add(0, clear_cb, NULL); 01235 return TRUE; 01236 } 01237 01238 gboolean audacious_rc_auto_advance(RemoteObject * obj, gboolean * is_advance, GError ** error) 01239 { 01240 *is_advance = !cfg.no_playlist_advance; 01241 return TRUE; 01242 } 01243 01244 gboolean audacious_rc_toggle_auto_advance(RemoteObject * obj, GError ** error) 01245 { 01246 g_timeout_add (0, set_no_playlist_advance_cb, 01247 GINT_TO_POINTER (! cfg.no_playlist_advance)); 01248 return TRUE; 01249 } 01250 01251 gboolean audacious_rc_repeat(RemoteObject * obj, gboolean * is_repeating, GError ** error) 01252 { 01253 *is_repeating = cfg.repeat; 01254 return TRUE; 01255 } 01256 01257 gboolean audacious_rc_toggle_repeat (RemoteObject * obj, GError * * error) 01258 { 01259 g_timeout_add (0, set_repeat_cb, GINT_TO_POINTER (! cfg.repeat)); 01260 return TRUE; 01261 } 01262 01263 gboolean audacious_rc_shuffle(RemoteObject * obj, gboolean * is_shuffling, GError ** error) 01264 { 01265 *is_shuffling = cfg.shuffle; 01266 return TRUE; 01267 } 01268 01269 gboolean audacious_rc_toggle_shuffle (RemoteObject * obj, GError * * error) 01270 { 01271 g_timeout_add (0, set_shuffle_cb, GINT_TO_POINTER (! cfg.shuffle)); 01272 return TRUE; 01273 } 01274 01275 /* New on Oct 5 */ 01276 gboolean audacious_rc_show_prefs_box(RemoteObject * obj, gboolean show, GError ** error) 01277 { 01278 event_queue("prefswin show", GINT_TO_POINTER(show)); 01279 return TRUE; 01280 } 01281 01282 gboolean audacious_rc_show_about_box(RemoteObject * obj, gboolean show, GError ** error) 01283 { 01284 event_queue("aboutwin show", GINT_TO_POINTER(show)); 01285 return TRUE; 01286 } 01287 01288 gboolean audacious_rc_show_jtf_box(RemoteObject * obj, gboolean show, GError ** error) 01289 { 01290 if (show) 01291 event_queue("interface show jump to track", NULL); 01292 else 01293 event_queue("interface hide jump to track", NULL); 01294 return TRUE; 01295 } 01296 01297 gboolean audacious_rc_show_filebrowser(RemoteObject * obj, gboolean show, GError ** error) 01298 { 01299 if (show) 01300 event_queue("filebrowser show", GINT_TO_POINTER(FALSE)); 01301 else 01302 event_queue("filebrowser hide", NULL); 01303 return TRUE; 01304 } 01305 01306 gboolean audacious_rc_play_pause(RemoteObject * obj, GError * *error) 01307 { 01308 g_timeout_add(0, play_pause_cb, NULL); 01309 return TRUE; 01310 } 01311 01312 gboolean audacious_rc_get_info(RemoteObject * obj, gint * rate, gint * freq, gint * nch, GError * *error) 01313 { 01314 struct StatusRequest request; 01315 01316 get_status(&request); 01317 *rate = request.bitrate; 01318 *freq = request.samplerate; 01319 *nch = request.channels; 01320 return TRUE; 01321 } 01322 01323 gboolean audacious_rc_toggle_aot(RemoteObject * obj, gboolean ontop, GError ** error) 01324 { 01325 hook_call("mainwin set always on top", &ontop); 01326 return TRUE; 01327 } 01328 01329 gboolean audacious_rc_playqueue_add(RemoteObject * obj, gint pos, GError * *error) 01330 { 01331 g_timeout_add(0, add_to_queue_cb, GINT_TO_POINTER(pos)); 01332 return TRUE; 01333 } 01334 01335 gboolean audacious_rc_playqueue_remove(RemoteObject * obj, gint pos, GError * *error) 01336 { 01337 g_timeout_add(0, remove_from_queue_cb, GINT_TO_POINTER(pos)); 01338 return TRUE; 01339 } 01340 01341 gboolean audacious_rc_playqueue_clear(RemoteObject * obj, GError * *error) 01342 { 01343 g_timeout_add(0, clear_queue_cb, NULL); 01344 return TRUE; 01345 } 01346 01347 gboolean audacious_rc_get_playqueue_length(RemoteObject * obj, gint * length, GError * *error) 01348 { 01349 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 01350 01351 get_position(&request); 01352 *length = request.queue_count; 01353 return TRUE; 01354 } 01355 01356 gboolean audacious_rc_queue_get_list_pos(RemoteObject * obj, gint qpos, gint * pos, GError * *error) 01357 { 01358 *pos = queue_get_entry(qpos); 01359 return TRUE; 01360 } 01361 01362 gboolean audacious_rc_queue_get_queue_pos(RemoteObject * obj, gint pos, gint * qpos, GError * *error) 01363 { 01364 *qpos = queue_find_entry(pos); 01365 return TRUE; 01366 } 01367 01368 gboolean audacious_rc_playqueue_is_queued(RemoteObject * obj, gint pos, gboolean * is_queued, GError * *error) 01369 { 01370 *is_queued = (queue_find_entry(pos) != -1); 01371 return TRUE; 01372 } 01373 01374 gboolean audacious_rc_playlist_ins_url_string(RemoteObject * obj, gchar * url, gint pos, GError * *error) 01375 { 01376 struct AddRequest *request = g_malloc(sizeof(struct AddRequest)); 01377 01378 request->position = pos; 01379 request->filename = g_strdup(url); 01380 request->play = FALSE; 01381 01382 g_timeout_add(0, add_cb, request); 01383 return TRUE; 01384 } 01385 01386 gboolean audacious_rc_playlist_add(RemoteObject * obj, void *list, GError * *error) 01387 { 01388 return audacious_rc_playlist_ins_url_string(obj, list, -1, error); 01389 } 01390 01391 gboolean audacious_rc_playlist_enqueue_to_temp(RemoteObject * obj, gchar * url, GError * *error) 01392 { 01393 g_timeout_add(0, add_to_new_playlist_cb, g_strdup(url)); 01394 return TRUE; 01395 } 01396 01397 /* New on Nov 7: Equalizer */ 01398 gboolean audacious_rc_get_eq(RemoteObject * obj, gdouble * preamp, GArray ** bands, GError ** error) 01399 { 01400 int i; 01401 01402 * preamp = cfg.equalizer_preamp; 01403 *bands = g_array_sized_new(FALSE, FALSE, sizeof(gdouble), AUD_EQUALIZER_NBANDS); 01404 01405 for (i = 0; i < AUD_EQUALIZER_NBANDS; i++) 01406 g_array_append_val (* bands, cfg.equalizer_bands[i]); 01407 01408 return TRUE; 01409 } 01410 01411 gboolean audacious_rc_get_eq_preamp(RemoteObject * obj, gdouble * preamp, GError ** error) 01412 { 01413 * preamp = cfg.equalizer_preamp; 01414 return TRUE; 01415 } 01416 01417 gboolean audacious_rc_get_eq_band(RemoteObject * obj, gint band, gdouble * value, GError ** error) 01418 { 01419 * value = cfg.equalizer_bands[band]; 01420 return TRUE; 01421 } 01422 01423 gboolean audacious_rc_set_eq(RemoteObject * obj, gdouble preamp, GArray * bands, GError ** error) 01424 { 01425 int i; 01426 01427 cfg.equalizer_preamp = preamp; 01428 01429 for (i = 0; i < AUD_EQUALIZER_NBANDS; i++) 01430 cfg.equalizer_bands[i] = g_array_index (bands, gdouble, i); 01431 01432 hook_call ("equalizer changed", NULL); 01433 return TRUE; 01434 } 01435 01436 gboolean audacious_rc_set_eq_preamp(RemoteObject * obj, gdouble preamp, GError ** error) 01437 { 01438 cfg.equalizer_preamp = preamp; 01439 hook_call ("equalizer changed", NULL); 01440 return TRUE; 01441 } 01442 01443 gboolean audacious_rc_set_eq_band(RemoteObject * obj, gint band, gdouble value, GError ** error) 01444 { 01445 cfg.equalizer_bands[band] = value; 01446 hook_call ("equalizer changed", NULL); 01447 return TRUE; 01448 } 01449 01450 gboolean audacious_rc_equalizer_activate(RemoteObject * obj, gboolean active, GError ** error) 01451 { 01452 cfg.equalizer_active = active; 01453 hook_call ("equalizer changed", NULL); 01454 return TRUE; 01455 } 01456 01457 gboolean audacious_rc_get_active_playlist_name(RemoteObject * obj, gchar * *title, GError * *error) 01458 { 01459 struct InfoRequest request = {.playlist = -2 }; 01460 01461 get_info(&request); 01462 g_free(request.title); 01463 g_free(request.filename); 01464 *title = request.pltitle; 01465 return TRUE; 01466 } 01467 01468 DBusGProxy *audacious_get_dbus_proxy(void) 01469 { 01470 DBusGConnection *connection = NULL; 01471 GError *error = NULL; 01472 connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); 01473 g_clear_error(&error); 01474 return dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); 01475 }