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 const gchar *filename, *title, *pltitle; 00404 00405 g_mutex_lock(info_mutex); 00406 00407 real_position(&request->playlist, &request->entry); 00408 filename = playlist_entry_get_filename(request->playlist, request->entry); 00409 request->filename = (filename == NULL) ? NULL : g_strdup(filename); 00410 title = playlist_entry_get_title (request->playlist, request->entry, FALSE); 00411 request->title = (title == NULL) ? NULL : g_strdup(title); 00412 request->length = playlist_entry_get_length (request->playlist, 00413 request->entry, FALSE); 00414 pltitle = playlist_get_title(request->playlist); 00415 request->pltitle = (pltitle == NULL) ? NULL : g_strdup(pltitle); 00416 00417 g_cond_signal(info_cond); 00418 g_mutex_unlock(info_mutex); 00419 return FALSE; 00420 } 00421 00422 static void get_info(struct InfoRequest *request) 00423 { 00424 if (g_thread_self() == main_thread) 00425 get_info_cb(request); 00426 else 00427 { 00428 g_mutex_lock(info_mutex); 00429 g_timeout_add(0, get_info_cb, request); 00430 g_cond_wait(info_cond, info_mutex); 00431 g_mutex_unlock(info_mutex); 00432 } 00433 } 00434 00435 static gboolean get_field_cb(void *data) 00436 { 00437 struct FieldRequest *request = data; 00438 const Tuple *tuple; 00439 00440 g_mutex_lock(info_mutex); 00441 00442 real_position(&request->playlist, &request->entry); 00443 tuple = playlist_entry_get_tuple (request->playlist, request->entry, FALSE); 00444 request->value = (tuple == NULL) ? NULL : tuple_value_to_gvalue(tuple, request->field); 00445 00446 g_cond_signal(info_cond); 00447 g_mutex_unlock(info_mutex); 00448 return FALSE; 00449 } 00450 00451 static void get_field(struct FieldRequest *request) 00452 { 00453 if (g_thread_self() == main_thread) 00454 get_field_cb(request); 00455 else 00456 { 00457 g_mutex_lock(info_mutex); 00458 g_timeout_add(0, get_field_cb, request); 00459 g_cond_wait(info_cond, info_mutex); 00460 g_mutex_unlock(info_mutex); 00461 } 00462 } 00463 00464 static gboolean play_cb(void *unused) 00465 { 00466 /* Only the active playlist is visible through DBUS interface, so make sure 00467 * to play from it, not another playlist. --jlindgren */ 00468 if (playlist_get_playing () != playlist_get_active ()) 00469 playlist_set_playing (playlist_get_active ()); 00470 00471 drct_play(); 00472 return FALSE; 00473 } 00474 00475 static gboolean pause_cb(void *unused) 00476 { 00477 playback_pause(); 00478 return FALSE; 00479 } 00480 00481 static gboolean play_pause_cb(void *unused) 00482 { 00483 if (playback_get_playing()) 00484 playback_pause(); 00485 else 00486 playback_play (0, FALSE); 00487 00488 return FALSE; 00489 } 00490 00491 static gboolean seek_cb(void *data) 00492 { 00493 playback_seek (GPOINTER_TO_INT (data)); 00494 return FALSE; 00495 } 00496 00497 static gboolean stop_cb(void *unused) 00498 { 00499 playback_stop(); 00500 return FALSE; 00501 } 00502 00503 static gboolean prev_cb(void *unused) 00504 { 00505 drct_pl_prev(); 00506 return FALSE; 00507 } 00508 00509 static gboolean next_cb(void *unused) 00510 { 00511 drct_pl_next(); 00512 return FALSE; 00513 } 00514 00515 static gboolean jump_cb(void *data) 00516 { 00517 drct_pl_set_pos(GPOINTER_TO_INT(data)); 00518 return FALSE; 00519 } 00520 00521 static gboolean add_cb(void *data) 00522 { 00523 struct AddRequest *request = data; 00524 gint playlist = playlist_get_active(); 00525 00526 if (request->position < 0) 00527 request->position = playlist_entry_count (playlist); 00528 00529 drct_pl_add (request->filename, request->position); 00530 00531 if (request->play) 00532 { 00533 playlist_set_playing(playlist); 00534 playlist_set_position(playlist, request->position); 00535 playback_play (0, FALSE); 00536 } 00537 00538 g_free(request); 00539 return FALSE; 00540 } 00541 00542 static gboolean delete_cb(void *data) 00543 { 00544 drct_pl_delete(GPOINTER_TO_INT(data)); 00545 return FALSE; 00546 } 00547 00548 static gboolean clear_cb(void *unused) 00549 { 00550 drct_pl_clear(); 00551 return FALSE; 00552 } 00553 00554 static gboolean add_to_queue_cb(void *data) 00555 { 00556 drct_pq_add(GPOINTER_TO_INT(data)); 00557 return FALSE; 00558 } 00559 00560 static gboolean remove_from_queue_cb(void *data) 00561 { 00562 drct_pq_remove(GPOINTER_TO_INT(data)); 00563 return FALSE; 00564 } 00565 00566 static gboolean clear_queue_cb(void *unused) 00567 { 00568 drct_pq_clear(); 00569 return FALSE; 00570 } 00571 00572 static gboolean queue_get_entry_cb(void *data) 00573 { 00574 g_mutex_lock(info_mutex); 00575 00576 * (gint *) data = drct_pq_get_entry (* (gint *) data); 00577 00578 g_cond_signal(info_cond); 00579 g_mutex_unlock(info_mutex); 00580 return FALSE; 00581 } 00582 00583 static gint queue_get_entry(gint position) 00584 { 00585 if (g_thread_self() == main_thread) 00586 queue_get_entry_cb(&position); 00587 else 00588 { 00589 g_mutex_lock(info_mutex); 00590 g_timeout_add(0, queue_get_entry_cb, &position); 00591 g_cond_wait(info_cond, info_mutex); 00592 g_mutex_unlock(info_mutex); 00593 } 00594 00595 return position; 00596 } 00597 00598 static gboolean queue_find_entry_cb(void *data) 00599 { 00600 g_mutex_lock(info_mutex); 00601 00602 *(gint *) data = drct_pq_get_queue_position(*(gint *) data); 00603 00604 g_cond_signal(info_cond); 00605 g_mutex_unlock(info_mutex); 00606 return FALSE; 00607 } 00608 00609 static gint queue_find_entry(gint position) 00610 { 00611 if (g_thread_self() == main_thread) 00612 queue_find_entry_cb(&position); 00613 else 00614 { 00615 g_mutex_lock(info_mutex); 00616 g_timeout_add(0, queue_find_entry_cb, &position); 00617 g_cond_wait(info_cond, info_mutex); 00618 g_mutex_unlock(info_mutex); 00619 } 00620 00621 return position; 00622 } 00623 00624 gboolean add_to_new_playlist_cb(void *data) 00625 { 00626 drct_pl_open_temp (data); 00627 g_free(data); 00628 return FALSE; 00629 } 00630 00631 static gboolean get_mpris_metadata_cb(void *data) 00632 { 00633 struct MprisMetadataRequest *request = data; 00634 const gchar *filename; 00635 00636 g_mutex_lock(info_mutex); 00637 00638 real_position(&request->playlist, &request->entry); 00639 filename = playlist_entry_get_filename(request->playlist, request->entry); 00640 00641 if (filename == NULL) 00642 request->metadata = NULL; 00643 else 00644 request->metadata = make_mpris_metadata (filename, 00645 playlist_entry_get_tuple (request->playlist, request->entry, FALSE)); 00646 00647 g_cond_signal(info_cond); 00648 g_mutex_unlock(info_mutex); 00649 return FALSE; 00650 } 00651 00652 static void get_mpris_metadata(struct MprisMetadataRequest *request) 00653 { 00654 if (g_thread_self() == main_thread) 00655 get_mpris_metadata_cb(request); 00656 else 00657 { 00658 g_mutex_lock(info_mutex); 00659 g_timeout_add(0, get_mpris_metadata_cb, request); 00660 g_cond_wait(info_cond, info_mutex); 00661 g_mutex_unlock(info_mutex); 00662 } 00663 } 00664 00665 static gboolean set_shuffle_cb (void * shuffle) 00666 { 00667 cfg.shuffle = GPOINTER_TO_INT (shuffle); 00668 event_queue ("toggle shuffle", NULL); 00669 return FALSE; 00670 } 00671 00672 static gboolean set_repeat_cb (void * repeat) 00673 { 00674 cfg.repeat = GPOINTER_TO_INT (repeat); 00675 event_queue ("toggle repeat", NULL); 00676 return FALSE; 00677 } 00678 00679 /* MPRIS API */ 00680 // MPRIS / 00681 gboolean mpris_root_identity(MprisRoot * obj, gchar ** identity, GError ** error) 00682 { 00683 *identity = g_strdup_printf("Audacious %s", VERSION); 00684 return TRUE; 00685 } 00686 00687 gboolean mpris_root_quit(MprisPlayer * obj, GError ** error) 00688 { 00689 event_queue("quit", NULL); 00690 return TRUE; 00691 } 00692 00693 // MPRIS /Player 00694 00695 gboolean mpris_player_next(MprisPlayer * obj, GError * *error) 00696 { 00697 g_timeout_add(0, next_cb, NULL); 00698 return TRUE; 00699 } 00700 00701 gboolean mpris_player_prev(MprisPlayer * obj, GError * *error) 00702 { 00703 g_timeout_add(0, prev_cb, NULL); 00704 return TRUE; 00705 } 00706 00707 gboolean mpris_player_pause(MprisPlayer * obj, GError * *error) 00708 { 00709 g_timeout_add(0, pause_cb, NULL); 00710 return TRUE; 00711 } 00712 00713 gboolean mpris_player_stop(MprisPlayer * obj, GError * *error) 00714 { 00715 g_timeout_add(0, stop_cb, NULL); 00716 return TRUE; 00717 } 00718 00719 gboolean mpris_player_play(MprisPlayer * obj, GError * *error) 00720 { 00721 g_timeout_add(0, play_cb, NULL); 00722 return TRUE; 00723 } 00724 00725 gboolean mpris_player_repeat(MprisPlayer * obj, gboolean rpt, GError ** error) 00726 { 00727 fprintf (stderr, "implement me\n"); 00728 return TRUE; 00729 } 00730 00731 static void append_int_value(GValueArray * ar, gint tmp) 00732 { 00733 GValue value; 00734 memset(&value, 0, sizeof(value)); 00735 g_value_init(&value, G_TYPE_INT); 00736 g_value_set_int(&value, tmp); 00737 g_value_array_append(ar, &value); 00738 } 00739 00740 static gint get_playback_status(void) 00741 { 00742 struct StatusRequest request; 00743 get_status(&request); 00744 00745 return (!request.playing ? MPRIS_STATUS_STOP : request.paused ? MPRIS_STATUS_PAUSE : MPRIS_STATUS_PLAY); 00746 } 00747 00748 gboolean mpris_player_get_status(MprisPlayer * obj, GValueArray * *status, GError * *error) 00749 { 00750 *status = g_value_array_new(4); 00751 00752 append_int_value(*status, (gint) get_playback_status()); 00753 append_int_value(*status, (gint) cfg.shuffle); 00754 append_int_value(*status, (gint) cfg.no_playlist_advance); 00755 append_int_value(*status, (gint) cfg.repeat); 00756 return TRUE; 00757 } 00758 00759 gboolean mpris_player_get_metadata(MprisPlayer * obj, GHashTable * *metadata, GError * *error) 00760 { 00761 struct MprisMetadataRequest request = {.playlist = -1,.entry = -1 }; 00762 00763 get_mpris_metadata(&request); 00764 *metadata = request.metadata; 00765 return TRUE; 00766 } 00767 00768 gboolean mpris_player_get_caps(MprisPlayer * obj, gint * capabilities, GError ** error) 00769 { 00770 *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; 00771 return TRUE; 00772 } 00773 00774 gboolean mpris_player_volume_set(MprisPlayer * obj, gint vol, GError ** error) 00775 { 00776 drct_set_volume_main (vol); 00777 return TRUE; 00778 } 00779 00780 gboolean mpris_player_volume_get(MprisPlayer * obj, gint * vol, GError ** error) 00781 { 00782 drct_get_volume_main (vol); 00783 return TRUE; 00784 } 00785 00786 gboolean mpris_player_position_set(MprisPlayer * obj, gint pos, GError * *error) 00787 { 00788 g_timeout_add(0, seek_cb, GINT_TO_POINTER(pos)); 00789 return TRUE; 00790 } 00791 00792 gboolean mpris_player_position_get(MprisPlayer * obj, gint * pos, GError * *error) 00793 { 00794 struct StatusRequest request; 00795 00796 get_status(&request); 00797 *pos = request.time; 00798 return TRUE; 00799 } 00800 00801 // MPRIS /Player signals 00802 gboolean mpris_emit_caps_change(MprisPlayer * obj) 00803 { 00804 g_signal_emit(obj, signals[CAPS_CHANGE_SIG], 0, 0); 00805 return TRUE; 00806 } 00807 00808 gboolean mpris_emit_track_change(MprisPlayer * obj) 00809 { 00810 gint playlist, entry; 00811 const gchar *filename; 00812 GHashTable *metadata; 00813 00814 playlist = playlist_get_playing(); 00815 entry = playlist_get_position(playlist); 00816 filename = playlist_entry_get_filename(playlist, entry); 00817 00818 if (filename == NULL) 00819 return FALSE; 00820 00821 metadata = make_mpris_metadata (filename, playlist_entry_get_tuple 00822 (playlist, entry, FALSE)); 00823 00824 g_signal_emit(obj, signals[TRACK_CHANGE_SIG], 0, metadata); 00825 g_hash_table_destroy(metadata); 00826 return TRUE; 00827 } 00828 00829 gboolean mpris_emit_status_change(MprisPlayer * obj, PlaybackStatus status) 00830 { 00831 GValueArray *ar = g_value_array_new(4); 00832 00833 if (status == MPRIS_STATUS_INVALID) 00834 status = get_playback_status (); 00835 00836 append_int_value(ar, (gint) status); 00837 append_int_value(ar, (gint) cfg.shuffle); 00838 append_int_value(ar, (gint) cfg.no_playlist_advance); 00839 append_int_value(ar, (gint) cfg.repeat); 00840 00841 g_signal_emit(obj, signals[STATUS_CHANGE_SIG], 0, ar); 00842 g_value_array_free(ar); 00843 return TRUE; 00844 } 00845 00846 // MPRIS /TrackList 00847 gboolean mpris_emit_tracklist_change(MprisTrackList * obj, gint playlist) 00848 { 00849 g_signal_emit(obj, tracklist_signals[TRACKLIST_CHANGE_SIG], 0, playlist_entry_count(playlist)); 00850 return TRUE; 00851 } 00852 00853 static void mpris_playlist_update_hook(gpointer unused, MprisTrackList * obj) 00854 { 00855 gint playlist = playlist_get_active(); 00856 00857 mpris_emit_tracklist_change(obj, playlist); 00858 } 00859 00860 gboolean mpris_tracklist_get_metadata(MprisTrackList * obj, gint pos, GHashTable * *metadata, GError * *error) 00861 { 00862 struct MprisMetadataRequest request = {.playlist = -1,.entry = pos }; 00863 00864 get_mpris_metadata(&request); 00865 *metadata = request.metadata; 00866 return TRUE; 00867 } 00868 00869 gboolean mpris_tracklist_get_current_track(MprisTrackList * obj, gint * pos, GError * *error) 00870 { 00871 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 00872 00873 get_position(&request); 00874 *pos = request.entry; 00875 return TRUE; 00876 } 00877 00878 gboolean mpris_tracklist_get_length(MprisTrackList * obj, gint * length, GError * *error) 00879 { 00880 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 00881 00882 get_position(&request); 00883 *length = request.entry_count; 00884 return TRUE; 00885 } 00886 00887 gboolean mpris_tracklist_add_track(MprisTrackList * obj, gchar * uri, gboolean play, GError * *error) 00888 { 00889 struct AddRequest *request = g_malloc(sizeof(struct AddRequest)); 00890 00891 request->position = -1; 00892 request->filename = g_strdup(uri); 00893 request->play = play; 00894 00895 g_timeout_add(0, add_cb, request); 00896 return TRUE; 00897 } 00898 00899 gboolean mpris_tracklist_del_track(MprisTrackList * obj, gint pos, GError * *error) 00900 { 00901 g_timeout_add(0, delete_cb, GINT_TO_POINTER(pos)); 00902 return TRUE; 00903 } 00904 00905 gboolean mpris_tracklist_loop (MprisTrackList * obj, gboolean loop, GError * * 00906 error) 00907 { 00908 g_timeout_add (0, set_repeat_cb, GINT_TO_POINTER (loop)); 00909 return TRUE; 00910 } 00911 00912 gboolean mpris_tracklist_random (MprisTrackList * obj, gboolean random, 00913 GError * * error) 00914 { 00915 g_timeout_add (0, set_shuffle_cb, GINT_TO_POINTER (random)); 00916 return TRUE; 00917 } 00918 00919 // Audacious General Information 00920 gboolean audacious_rc_version(RemoteObject * obj, gchar ** version, GError ** error) 00921 { 00922 *version = g_strdup(VERSION); 00923 return TRUE; 00924 } 00925 00926 gboolean audacious_rc_quit(RemoteObject * obj, GError * *error) 00927 { 00928 event_queue("quit", NULL); 00929 return TRUE; 00930 } 00931 00932 gboolean audacious_rc_eject(RemoteObject * obj, GError ** error) 00933 { 00934 interface_run_filebrowser (TRUE); 00935 return TRUE; 00936 } 00937 00938 gboolean audacious_rc_main_win_visible(RemoteObject * obj, gboolean * is_main_win, GError ** error) 00939 { 00940 *is_main_win = cfg.player_visible; 00941 return TRUE; 00942 } 00943 00944 gboolean audacious_rc_show_main_win(RemoteObject * obj, gboolean show, GError ** error) 00945 { 00946 interface_toggle_visibility (); 00947 return TRUE; 00948 } 00949 00950 gboolean audacious_rc_equalizer_visible(RemoteObject * obj, gboolean * is_eq_win, GError ** error) 00951 { 00952 *is_eq_win = cfg.equalizer_visible; 00953 return TRUE; 00954 } 00955 00956 gboolean audacious_rc_show_equalizer(RemoteObject * obj, gboolean show, GError ** error) 00957 { 00958 #if 0 00959 drct_eq_win_toggle(show); 00960 #endif 00961 return TRUE; 00962 } 00963 00964 gboolean audacious_rc_playlist_visible(RemoteObject * obj, gboolean * is_pl_win, GError ** error) 00965 { 00966 *is_pl_win = cfg.playlist_visible; 00967 return TRUE; 00968 } 00969 00970 gboolean audacious_rc_show_playlist(RemoteObject * obj, gboolean show, GError ** error) 00971 { 00972 #if 0 00973 drct_pl_win_toggle(show); 00974 #endif 00975 return TRUE; 00976 } 00977 00978 gboolean audacious_rc_get_tuple_fields(RemoteObject * obj, gchar *** fields, GError ** error) 00979 { 00980 gchar **res = g_new0(gchar *, FIELD_LAST + 1); 00981 gint i; 00982 for (i = 0; i < FIELD_LAST; i++) 00983 { 00984 res[i] = g_strdup(tuple_fields[i].name); 00985 } 00986 *fields = res; 00987 00988 return TRUE; 00989 } 00990 00991 00992 // Playback Information/Manipulation 00993 00994 gboolean audacious_rc_play(RemoteObject * obj, GError * *error) 00995 { 00996 g_timeout_add(0, play_cb, NULL); 00997 return TRUE; 00998 } 00999 01000 gboolean audacious_rc_pause(RemoteObject * obj, GError * *error) 01001 { 01002 g_timeout_add(0, pause_cb, NULL); 01003 return TRUE; 01004 } 01005 01006 gboolean audacious_rc_stop(RemoteObject * obj, GError * *error) 01007 { 01008 g_timeout_add(0, stop_cb, NULL); 01009 return TRUE; 01010 } 01011 01012 gboolean audacious_rc_playing(RemoteObject * obj, gboolean * is_playing, GError * *error) 01013 { 01014 struct StatusRequest request; 01015 01016 get_status(&request); 01017 *is_playing = request.playing; 01018 return TRUE; 01019 } 01020 01021 gboolean audacious_rc_paused(RemoteObject * obj, gboolean * is_paused, GError * *error) 01022 { 01023 struct StatusRequest request; 01024 01025 get_status(&request); 01026 *is_paused = request.paused; 01027 return TRUE; 01028 } 01029 01030 gboolean audacious_rc_stopped(RemoteObject * obj, gboolean * is_stopped, GError * *error) 01031 { 01032 struct StatusRequest request; 01033 01034 get_status(&request); 01035 *is_stopped = !request.playing; 01036 return TRUE; 01037 } 01038 01039 gboolean audacious_rc_status(RemoteObject * obj, gchar * *status, GError * *error) 01040 { 01041 struct StatusRequest request; 01042 01043 get_status(&request); 01044 *status = g_strdup(!request.playing ? "stopped" : request.paused ? "paused" : "playing"); 01045 return TRUE; 01046 } 01047 01048 gboolean audacious_rc_info(RemoteObject * obj, gint * rate, gint * freq, gint * nch, GError * *error) 01049 { 01050 struct StatusRequest request; 01051 01052 get_status(&request); 01053 *rate = request.bitrate; 01054 *freq = request.samplerate; 01055 *nch = request.channels; 01056 return TRUE; 01057 } 01058 01059 gboolean audacious_rc_time(RemoteObject * obj, gint * time, GError * *error) 01060 { 01061 struct StatusRequest request; 01062 01063 get_status(&request); 01064 *time = request.time; 01065 return TRUE; 01066 } 01067 01068 gboolean audacious_rc_seek(RemoteObject * obj, guint pos, GError * *error) 01069 { 01070 g_timeout_add(0, seek_cb, GINT_TO_POINTER(pos)); 01071 return TRUE; 01072 } 01073 01074 gboolean audacious_rc_volume(RemoteObject * obj, gint * vl, gint * vr, GError ** error) 01075 { 01076 drct_get_volume (vl, vr); 01077 return TRUE; 01078 } 01079 01080 gboolean audacious_rc_set_volume(RemoteObject * obj, gint vl, gint vr, GError ** error) 01081 { 01082 drct_set_volume (vl, vr); 01083 return TRUE; 01084 } 01085 01086 gboolean audacious_rc_balance(RemoteObject * obj, gint * balance, GError ** error) 01087 { 01088 drct_get_volume_balance (balance); 01089 return TRUE; 01090 } 01091 01092 // Playlist Information/Manipulation 01093 01094 gboolean audacious_rc_position(RemoteObject * obj, gint * pos, GError * *error) 01095 { 01096 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 01097 01098 get_position(&request); 01099 *pos = request.entry; 01100 return TRUE; 01101 } 01102 01103 gboolean audacious_rc_advance(RemoteObject * obj, GError * *error) 01104 { 01105 g_timeout_add(0, next_cb, NULL); 01106 return TRUE; 01107 } 01108 01109 gboolean audacious_rc_reverse(RemoteObject * obj, GError * *error) 01110 { 01111 g_timeout_add(0, prev_cb, NULL); 01112 return TRUE; 01113 } 01114 01115 gboolean audacious_rc_length(RemoteObject * obj, gint * length, GError * *error) 01116 { 01117 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 01118 01119 get_position(&request); 01120 *length = request.entry_count; 01121 return TRUE; 01122 } 01123 01124 gboolean audacious_rc_song_title(RemoteObject * obj, guint pos, gchar * *title, GError * *error) 01125 { 01126 struct InfoRequest request = {.playlist = -1,.entry = pos }; 01127 01128 get_info(&request); 01129 g_free(request.filename); 01130 g_free(request.pltitle); 01131 *title = request.title; 01132 return TRUE; 01133 } 01134 01135 gboolean audacious_rc_song_filename(RemoteObject * obj, guint pos, gchar * *filename, GError * *error) 01136 { 01137 struct InfoRequest request = {.playlist = -1,.entry = pos }; 01138 01139 get_info(&request); 01140 *filename = request.filename; 01141 g_free(request.title); 01142 g_free(request.pltitle); 01143 return TRUE; 01144 } 01145 01146 gboolean audacious_rc_song_length(RemoteObject * obj, guint pos, gint * length, GError * *error) 01147 { 01148 audacious_rc_song_frames(obj, pos, length, error); 01149 *length /= 1000; 01150 return TRUE; 01151 } 01152 01153 gboolean audacious_rc_song_frames(RemoteObject * obj, guint pos, gint * length, GError * *error) 01154 { 01155 struct InfoRequest request = {.playlist = -1,.entry = pos }; 01156 01157 get_info(&request); 01158 g_free(request.filename); 01159 g_free(request.title); 01160 g_free(request.pltitle); 01161 *length = request.length; 01162 return TRUE; 01163 } 01164 01165 gboolean audacious_rc_song_tuple(RemoteObject * obj, guint pos, gchar * field, GValue * value, GError * *error) 01166 { 01167 struct FieldRequest request = {.playlist = -1,.entry = pos,.field = field }; 01168 01169 get_field(&request); 01170 01171 if (request.value == NULL) 01172 return FALSE; 01173 01174 memset(value, 0, sizeof(GValue)); 01175 g_value_init(value, G_VALUE_TYPE(request.value)); 01176 g_value_copy(request.value, value); 01177 g_value_unset(request.value); 01178 g_free(request.value); 01179 return TRUE; 01180 } 01181 01182 gboolean audacious_rc_jump(RemoteObject * obj, guint pos, GError * *error) 01183 { 01184 g_timeout_add(0, jump_cb, GINT_TO_POINTER(pos)); 01185 return TRUE; 01186 } 01187 01188 gboolean audacious_rc_add(RemoteObject * obj, gchar * file, GError * *error) 01189 { 01190 return audacious_rc_playlist_ins_url_string(obj, file, -1, error); 01191 } 01192 01193 gboolean audacious_rc_add_url(RemoteObject * obj, gchar * file, GError * *error) 01194 { 01195 return audacious_rc_playlist_ins_url_string(obj, file, -1, error); 01196 } 01197 01198 static GList * string_array_to_list (gchar * * strings) 01199 { 01200 GList * list = NULL; 01201 01202 while (* strings != NULL) 01203 list = g_list_prepend (list, * strings ++); 01204 01205 return g_list_reverse (list); 01206 } 01207 01208 gboolean audacious_rc_add_list (RemoteObject * obj, gchar * * filenames, 01209 GError * * error) 01210 { 01211 GList * list = string_array_to_list (filenames); 01212 01213 drct_pl_add_list (list, -1); 01214 g_list_free (list); 01215 return TRUE; 01216 } 01217 01218 gboolean audacious_rc_open_list (RemoteObject * obj, gchar * * filenames, 01219 GError * * error) 01220 { 01221 GList * list = string_array_to_list (filenames); 01222 01223 drct_pl_open_list (list); 01224 g_list_free (list); 01225 return TRUE; 01226 } 01227 01228 gboolean audacious_rc_open_list_to_temp (RemoteObject * obj, gchar * * 01229 filenames, GError * * error) 01230 { 01231 GList * list = string_array_to_list (filenames); 01232 01233 drct_pl_open_temp_list (list); 01234 g_list_free (list); 01235 return TRUE; 01236 } 01237 01238 gboolean audacious_rc_delete(RemoteObject * obj, guint pos, GError * *error) 01239 { 01240 g_timeout_add(0, delete_cb, GINT_TO_POINTER(pos)); 01241 return TRUE; 01242 } 01243 01244 gboolean audacious_rc_clear(RemoteObject * obj, GError * *error) 01245 { 01246 g_timeout_add(0, clear_cb, NULL); 01247 return TRUE; 01248 } 01249 01250 gboolean audacious_rc_auto_advance(RemoteObject * obj, gboolean * is_advance, GError ** error) 01251 { 01252 *is_advance = !cfg.no_playlist_advance; 01253 return TRUE; 01254 } 01255 01256 gboolean audacious_rc_toggle_auto_advance(RemoteObject * obj, GError ** error) 01257 { 01258 cfg.no_playlist_advance = !cfg.no_playlist_advance; 01259 return TRUE; 01260 } 01261 01262 gboolean audacious_rc_repeat(RemoteObject * obj, gboolean * is_repeating, GError ** error) 01263 { 01264 *is_repeating = cfg.repeat; 01265 return TRUE; 01266 } 01267 01268 gboolean audacious_rc_toggle_repeat (RemoteObject * obj, GError * * error) 01269 { 01270 g_timeout_add (0, set_repeat_cb, GINT_TO_POINTER (! cfg.repeat)); 01271 return TRUE; 01272 } 01273 01274 gboolean audacious_rc_shuffle(RemoteObject * obj, gboolean * is_shuffling, GError ** error) 01275 { 01276 *is_shuffling = cfg.shuffle; 01277 return TRUE; 01278 } 01279 01280 gboolean audacious_rc_toggle_shuffle (RemoteObject * obj, GError * * error) 01281 { 01282 g_timeout_add (0, set_shuffle_cb, GINT_TO_POINTER (! cfg.shuffle)); 01283 return TRUE; 01284 } 01285 01286 /* New on Oct 5 */ 01287 gboolean audacious_rc_show_prefs_box(RemoteObject * obj, gboolean show, GError ** error) 01288 { 01289 event_queue("prefswin show", GINT_TO_POINTER(show)); 01290 return TRUE; 01291 } 01292 01293 gboolean audacious_rc_show_about_box(RemoteObject * obj, gboolean show, GError ** error) 01294 { 01295 event_queue("aboutwin show", GINT_TO_POINTER(show)); 01296 return TRUE; 01297 } 01298 01299 gboolean audacious_rc_show_jtf_box(RemoteObject * obj, gboolean show, GError ** error) 01300 { 01301 if (show) 01302 event_queue("interface show jump to track", NULL); 01303 else 01304 event_queue("interface hide jump to track", NULL); 01305 return TRUE; 01306 } 01307 01308 gboolean audacious_rc_show_filebrowser(RemoteObject * obj, gboolean show, GError ** error) 01309 { 01310 if (show) 01311 event_queue("filebrowser show", GINT_TO_POINTER(FALSE)); 01312 else 01313 event_queue("filebrowser hide", NULL); 01314 return TRUE; 01315 } 01316 01317 gboolean audacious_rc_play_pause(RemoteObject * obj, GError * *error) 01318 { 01319 g_timeout_add(0, play_pause_cb, NULL); 01320 return TRUE; 01321 } 01322 01323 gboolean audacious_rc_activate(RemoteObject * obj, GError ** error) 01324 { 01325 fprintf (stderr, "implement me\n"); 01326 return TRUE; 01327 } 01328 01329 gboolean audacious_rc_get_info(RemoteObject * obj, gint * rate, gint * freq, gint * nch, GError * *error) 01330 { 01331 struct StatusRequest request; 01332 01333 get_status(&request); 01334 *rate = request.bitrate; 01335 *freq = request.samplerate; 01336 *nch = request.channels; 01337 return TRUE; 01338 } 01339 01340 gboolean audacious_rc_toggle_aot(RemoteObject * obj, gboolean ontop, GError ** error) 01341 { 01342 hook_call("mainwin set always on top", &ontop); 01343 return TRUE; 01344 } 01345 01346 gboolean audacious_rc_playqueue_add(RemoteObject * obj, gint pos, GError * *error) 01347 { 01348 g_timeout_add(0, add_to_queue_cb, GINT_TO_POINTER(pos)); 01349 return TRUE; 01350 } 01351 01352 gboolean audacious_rc_playqueue_remove(RemoteObject * obj, gint pos, GError * *error) 01353 { 01354 g_timeout_add(0, remove_from_queue_cb, GINT_TO_POINTER(pos)); 01355 return TRUE; 01356 } 01357 01358 gboolean audacious_rc_playqueue_clear(RemoteObject * obj, GError * *error) 01359 { 01360 g_timeout_add(0, clear_queue_cb, NULL); 01361 return TRUE; 01362 } 01363 01364 gboolean audacious_rc_get_playqueue_length(RemoteObject * obj, gint * length, GError * *error) 01365 { 01366 struct PositionRequest request = {.playlist = -1,.entry = -1 }; 01367 01368 get_position(&request); 01369 *length = request.queue_count; 01370 return TRUE; 01371 } 01372 01373 gboolean audacious_rc_queue_get_list_pos(RemoteObject * obj, gint qpos, gint * pos, GError * *error) 01374 { 01375 *pos = queue_get_entry(qpos); 01376 return TRUE; 01377 } 01378 01379 gboolean audacious_rc_queue_get_queue_pos(RemoteObject * obj, gint pos, gint * qpos, GError * *error) 01380 { 01381 *qpos = queue_find_entry(pos); 01382 return TRUE; 01383 } 01384 01385 gboolean audacious_rc_playqueue_is_queued(RemoteObject * obj, gint pos, gboolean * is_queued, GError * *error) 01386 { 01387 *is_queued = (queue_find_entry(pos) != -1); 01388 return TRUE; 01389 } 01390 01391 gboolean audacious_rc_playlist_ins_url_string(RemoteObject * obj, gchar * url, gint pos, GError * *error) 01392 { 01393 struct AddRequest *request = g_malloc(sizeof(struct AddRequest)); 01394 01395 request->position = pos; 01396 request->filename = g_strdup(url); 01397 request->play = FALSE; 01398 01399 g_timeout_add(0, add_cb, request); 01400 return TRUE; 01401 } 01402 01403 gboolean audacious_rc_playlist_add(RemoteObject * obj, void *list, GError * *error) 01404 { 01405 return audacious_rc_playlist_ins_url_string(obj, list, -1, error); 01406 } 01407 01408 gboolean audacious_rc_playlist_enqueue_to_temp(RemoteObject * obj, gchar * url, GError * *error) 01409 { 01410 g_timeout_add(0, add_to_new_playlist_cb, g_strdup(url)); 01411 return TRUE; 01412 } 01413 01414 /* New on Nov 7: Equalizer */ 01415 gboolean audacious_rc_get_eq(RemoteObject * obj, gdouble * preamp, GArray ** bands, GError ** error) 01416 { 01417 int i; 01418 01419 * preamp = cfg.equalizer_preamp; 01420 *bands = g_array_sized_new(FALSE, FALSE, sizeof(gdouble), AUD_EQUALIZER_NBANDS); 01421 01422 for (i = 0; i < AUD_EQUALIZER_NBANDS; i++) 01423 g_array_append_val (* bands, cfg.equalizer_bands[i]); 01424 01425 return TRUE; 01426 } 01427 01428 gboolean audacious_rc_get_eq_preamp(RemoteObject * obj, gdouble * preamp, GError ** error) 01429 { 01430 * preamp = cfg.equalizer_preamp; 01431 return TRUE; 01432 } 01433 01434 gboolean audacious_rc_get_eq_band(RemoteObject * obj, gint band, gdouble * value, GError ** error) 01435 { 01436 * value = cfg.equalizer_bands[band]; 01437 return TRUE; 01438 } 01439 01440 gboolean audacious_rc_set_eq(RemoteObject * obj, gdouble preamp, GArray * bands, GError ** error) 01441 { 01442 int i; 01443 01444 cfg.equalizer_preamp = preamp; 01445 01446 for (i = 0; i < AUD_EQUALIZER_NBANDS; i++) 01447 cfg.equalizer_bands[i] = g_array_index (bands, gdouble, i); 01448 01449 hook_call ("equalizer changed", NULL); 01450 return TRUE; 01451 } 01452 01453 gboolean audacious_rc_set_eq_preamp(RemoteObject * obj, gdouble preamp, GError ** error) 01454 { 01455 cfg.equalizer_preamp = preamp; 01456 hook_call ("equalizer changed", NULL); 01457 return TRUE; 01458 } 01459 01460 gboolean audacious_rc_set_eq_band(RemoteObject * obj, gint band, gdouble value, GError ** error) 01461 { 01462 cfg.equalizer_bands[band] = value; 01463 hook_call ("equalizer changed", NULL); 01464 return TRUE; 01465 } 01466 01467 gboolean audacious_rc_equalizer_activate(RemoteObject * obj, gboolean active, GError ** error) 01468 { 01469 cfg.equalizer_active = active; 01470 hook_call ("equalizer changed", NULL); 01471 return TRUE; 01472 } 01473 01474 gboolean audacious_rc_get_active_playlist_name(RemoteObject * obj, gchar * *title, GError * *error) 01475 { 01476 struct InfoRequest request = {.playlist = -2 }; 01477 01478 get_info(&request); 01479 g_free(request.title); 01480 g_free(request.filename); 01481 *title = request.pltitle; 01482 return TRUE; 01483 } 01484 01485 DBusGProxy *audacious_get_dbus_proxy(void) 01486 { 01487 DBusGConnection *connection = NULL; 01488 GError *error = NULL; 01489 connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); 01490 g_clear_error(&error); 01491 return dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); 01492 }