Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * Audacious: A cross-platform multimedia player 00003 * Copyright (c) 2007 Ben Tucker 00004 * Copyright 2009-2011 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 <string.h> 00026 00027 #include <dbus/dbus.h> 00028 #include <dbus/dbus-glib.h> 00029 #include <dbus/dbus-glib-bindings.h> 00030 #include <dbus/dbus-glib-lowlevel.h> 00031 #include "dbus.h" 00032 #include "dbus-service.h" 00033 #include "dbus-server-bindings.h" 00034 00035 #include <math.h> 00036 00037 #include <libaudcore/hook.h> 00038 00039 #include "debug.h" 00040 #include "drct.h" 00041 #include "playlist.h" 00042 #include "interface.h" 00043 #include "misc.h" 00044 00045 static DBusGConnection *dbus_conn = NULL; 00046 static unsigned int signals[LAST_SIG] = { 0 }; 00047 static unsigned int tracklist_signals[LAST_TRACKLIST_SIG] = { 0 }; 00048 00049 MprisPlayer * mpris = NULL; 00050 MprisTrackList * mpris_tracklist = NULL; 00051 00052 G_DEFINE_TYPE (RemoteObject, audacious_rc, G_TYPE_OBJECT) 00053 G_DEFINE_TYPE (MprisRoot, mpris_root, G_TYPE_OBJECT) 00054 G_DEFINE_TYPE (MprisPlayer, mpris_player, G_TYPE_OBJECT) 00055 G_DEFINE_TYPE (MprisTrackList, mpris_tracklist, G_TYPE_OBJECT) 00056 00057 #define DBUS_TYPE_G_STRING_VALUE_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) 00058 00059 static void mpris_playlist_update_hook(gpointer unused, MprisTrackList *obj); 00060 00061 void audacious_rc_class_init(RemoteObjectClass * klass) 00062 { 00063 } 00064 00065 void mpris_root_class_init(MprisRootClass * klass) 00066 { 00067 } 00068 00069 void mpris_player_class_init(MprisPlayerClass * klass) 00070 { 00071 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); 00072 signals[TRACK_CHANGE_SIG] = 00073 g_signal_new("track_change", 00074 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); 00075 00076 GType status_type = dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, 00077 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID); 00078 signals[STATUS_CHANGE_SIG] = 00079 g_signal_new ("status_change", G_OBJECT_CLASS_TYPE (klass), 00080 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, 00081 g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, status_type); 00082 } 00083 00084 void mpris_tracklist_class_init(MprisTrackListClass * klass) 00085 { 00086 tracklist_signals[TRACKLIST_CHANGE_SIG] = g_signal_new("track_list_change", G_OBJECT_CLASS_TYPE(klass), 00087 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); 00088 } 00089 00090 void audacious_rc_init(RemoteObject * object) 00091 { 00092 GError *error = NULL; 00093 DBusGProxy *driver_proxy; 00094 unsigned int request_ret; 00095 00096 AUDDBG ("Registering remote D-Bus interfaces.\n"); 00097 00098 dbus_g_object_type_install_info(audacious_rc_get_type(), &dbus_glib_audacious_rc_object_info); 00099 00100 // Register DBUS path 00101 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH, G_OBJECT(object)); 00102 00103 // Register the service name, the constants here are defined in 00104 // dbus-glib-bindings.h 00105 driver_proxy = dbus_g_proxy_new_for_name(dbus_conn, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); 00106 00107 if (!org_freedesktop_DBus_request_name(driver_proxy, AUDACIOUS_DBUS_SERVICE, 0, &request_ret, &error)) 00108 { 00109 g_warning("Unable to register service: %s", error->message); 00110 g_error_free(error); 00111 } 00112 00113 if (!org_freedesktop_DBus_request_name(driver_proxy, AUDACIOUS_DBUS_SERVICE_MPRIS, 0, &request_ret, &error)) 00114 { 00115 g_warning("Unable to register service: %s", error->message); 00116 g_error_free(error); 00117 } 00118 00119 g_object_unref(driver_proxy); 00120 } 00121 00122 void mpris_root_init(MprisRoot * object) 00123 { 00124 dbus_g_object_type_install_info(mpris_root_get_type(), &dbus_glib_mpris_root_object_info); 00125 00126 // Register DBUS path 00127 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_ROOT, G_OBJECT(object)); 00128 } 00129 00130 void mpris_player_init(MprisPlayer * object) 00131 { 00132 dbus_g_object_type_install_info(mpris_player_get_type(), &dbus_glib_mpris_player_object_info); 00133 00134 // Register DBUS path 00135 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_PLAYER, G_OBJECT(object)); 00136 00137 // Add signals 00138 DBusGProxy *proxy = object->proxy; 00139 if (proxy != NULL) 00140 { 00141 dbus_g_proxy_add_signal (proxy, "StatusChange", dbus_g_type_get_struct 00142 ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, 00143 G_TYPE_INVALID), G_TYPE_INVALID); 00144 dbus_g_proxy_add_signal (proxy, "CapsChange", G_TYPE_INT, G_TYPE_INVALID); 00145 dbus_g_proxy_add_signal(proxy, "TrackChange", DBUS_TYPE_G_STRING_VALUE_HASHTABLE, G_TYPE_INVALID); 00146 } 00147 else 00148 { 00149 /* XXX / FIXME: Why does this happen? -- ccr */ 00150 AUDDBG ("object->proxy == NULL; not adding some signals.\n"); 00151 } 00152 } 00153 00154 void mpris_tracklist_init(MprisTrackList * object) 00155 { 00156 dbus_g_object_type_install_info(mpris_tracklist_get_type(), &dbus_glib_mpris_tracklist_object_info); 00157 00158 // Register DBUS path 00159 dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_TRACKLIST, G_OBJECT(object)); 00160 00161 // Add signals 00162 DBusGProxy *proxy = object->proxy; 00163 if (proxy != NULL) 00164 { 00165 dbus_g_proxy_add_signal(proxy, "TrackListChange", G_TYPE_INT, G_TYPE_INVALID); 00166 } 00167 else 00168 { 00169 /* XXX / FIXME: Why does this happen? -- ccr */ 00170 AUDDBG ("object->proxy == NULL, not adding some signals.\n"); 00171 } 00172 } 00173 00174 void init_dbus() 00175 { 00176 GError *error = NULL; 00177 DBusConnection *local_conn; 00178 00179 AUDDBG ("Trying to initialize D-Bus.\n"); 00180 dbus_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); 00181 if (dbus_conn == NULL) 00182 { 00183 g_warning("Unable to connect to dbus: %s", error->message); 00184 g_error_free(error); 00185 return; 00186 } 00187 00188 g_type_init(); 00189 g_object_new(audacious_rc_get_type(), NULL); 00190 g_object_new(mpris_root_get_type(), NULL); 00191 mpris = g_object_new(mpris_player_get_type(), NULL); 00192 mpris_tracklist = g_object_new(mpris_tracklist_get_type(), NULL); 00193 00194 local_conn = dbus_g_connection_get_connection(dbus_conn); 00195 dbus_connection_set_exit_on_disconnect(local_conn, FALSE); 00196 00197 hook_associate ("playlist update", 00198 (HookFunction) mpris_playlist_update_hook, mpris_tracklist); 00199 } 00200 00201 void cleanup_dbus (void) 00202 { 00203 hook_dissociate ("playlist update", (HookFunction) mpris_playlist_update_hook); 00204 } 00205 00206 static GValue *tuple_value_to_gvalue(const Tuple * tuple, const char * key) 00207 { 00208 GValue *val; 00209 TupleValueType type = tuple_get_value_type (tuple, -1, key); 00210 00211 if (type == TUPLE_STRING) 00212 { 00213 val = g_new0(GValue, 1); 00214 g_value_init(val, G_TYPE_STRING); 00215 char * str = tuple_get_str (tuple, -1, key); 00216 g_value_set_string (val, str); 00217 str_unref (str); 00218 return val; 00219 } 00220 else if (type == TUPLE_INT) 00221 { 00222 val = g_new0(GValue, 1); 00223 g_value_init(val, G_TYPE_INT); 00224 int x = tuple_get_int (tuple, -1, key); 00225 g_value_set_int (val, x); 00226 return val; 00227 } 00228 return NULL; 00229 } 00230 00239 static void tuple_insert_to_hash_full(GHashTable * md, const Tuple * tuple, 00240 const char * tuple_key, const char *key) 00241 { 00242 GValue *value = tuple_value_to_gvalue(tuple, tuple_key); 00243 if (value != NULL) 00244 g_hash_table_insert (md, (void *) key, value); 00245 } 00246 00247 static void tuple_insert_to_hash(GHashTable * md, const Tuple * tuple, 00248 const char *key) 00249 { 00250 tuple_insert_to_hash_full(md, tuple, key, key); 00251 } 00252 00253 static void remove_metadata_value(gpointer value) 00254 { 00255 g_value_unset((GValue *) value); 00256 g_free((GValue *) value); 00257 } 00258 00259 static GHashTable *make_mpris_metadata(const char * filename, const Tuple * tuple) 00260 { 00261 GHashTable *md = NULL; 00262 gpointer value; 00263 00264 md = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, remove_metadata_value); 00265 00266 value = g_malloc(sizeof(GValue)); 00267 memset(value, 0, sizeof(GValue)); 00268 g_value_init(value, G_TYPE_STRING); 00269 g_value_take_string(value, g_strdup(filename)); 00270 g_hash_table_insert(md, "location", value); 00271 00272 if (tuple != NULL) 00273 { 00274 tuple_insert_to_hash_full(md, tuple, "length", "mtime"); 00275 tuple_insert_to_hash(md, tuple, "title"); 00276 tuple_insert_to_hash(md, tuple, "artist"); 00277 tuple_insert_to_hash(md, tuple, "album"); 00278 tuple_insert_to_hash(md, tuple, "comment"); 00279 tuple_insert_to_hash(md, tuple, "genre"); 00280 tuple_insert_to_hash(md, tuple, "year"); 00281 tuple_insert_to_hash(md, tuple, "codec"); 00282 tuple_insert_to_hash(md, tuple, "quality"); 00283 tuple_insert_to_hash_full(md, tuple, "track-number", "tracknumber"); 00284 tuple_insert_to_hash_full(md, tuple, "bitrate", "audio-bitrate"); 00285 } 00286 00287 return md; 00288 } 00289 00290 static GValue * get_field (int playlist, int entry, const char * field) 00291 { 00292 Tuple * tuple = playlist_entry_get_tuple (playlist, entry, FALSE); 00293 GValue * value = tuple ? tuple_value_to_gvalue (tuple, field) : NULL; 00294 00295 if (tuple) 00296 tuple_unref (tuple); 00297 00298 return value; 00299 } 00300 00301 static GHashTable * get_mpris_metadata (int playlist, int entry) 00302 { 00303 char * filename = playlist_entry_get_filename (playlist, entry); 00304 Tuple * tuple = playlist_entry_get_tuple (playlist, entry, FALSE); 00305 00306 GHashTable * metadata = NULL; 00307 if (filename && tuple) 00308 metadata = make_mpris_metadata (filename, tuple); 00309 00310 str_unref (filename); 00311 if (tuple) 00312 tuple_unref (tuple); 00313 00314 return metadata; 00315 } 00316 00317 /* MPRIS API */ 00318 // MPRIS / 00319 bool_t mpris_root_identity(MprisRoot * obj, char ** identity, GError ** error) 00320 { 00321 *identity = g_strdup_printf("Audacious %s", VERSION); 00322 return TRUE; 00323 } 00324 00325 bool_t mpris_root_quit(MprisPlayer * obj, GError ** error) 00326 { 00327 event_queue("quit", NULL); 00328 return TRUE; 00329 } 00330 00331 // MPRIS /Player 00332 00333 bool_t mpris_player_next (MprisPlayer * obj, GError * * error) 00334 { 00335 drct_pl_next (); 00336 return TRUE; 00337 } 00338 00339 bool_t mpris_player_prev (MprisPlayer * obj, GError * * error) 00340 { 00341 drct_pl_prev (); 00342 return TRUE; 00343 } 00344 00345 bool_t mpris_player_pause (MprisPlayer * obj, GError * * error) 00346 { 00347 drct_pause (); 00348 return TRUE; 00349 } 00350 00351 bool_t mpris_player_stop (MprisPlayer * obj, GError * * error) 00352 { 00353 drct_stop (); 00354 return TRUE; 00355 } 00356 00357 bool_t mpris_player_play (MprisPlayer * obj, GError * * error) 00358 { 00359 drct_play (); 00360 return TRUE; 00361 } 00362 00363 bool_t mpris_player_repeat(MprisPlayer * obj, bool_t rpt, GError ** error) 00364 { 00365 fprintf (stderr, "implement me\n"); 00366 return TRUE; 00367 } 00368 00369 static void append_int_value(GValueArray * ar, int tmp) 00370 { 00371 GValue value; 00372 memset(&value, 0, sizeof(value)); 00373 g_value_init(&value, G_TYPE_INT); 00374 g_value_set_int(&value, tmp); 00375 g_value_array_append(ar, &value); 00376 } 00377 00378 static int get_playback_status (void) 00379 { 00380 if (! drct_get_playing ()) 00381 return MPRIS_STATUS_STOP; 00382 00383 return drct_get_paused () ? MPRIS_STATUS_PAUSE : MPRIS_STATUS_PLAY; 00384 } 00385 00386 bool_t mpris_player_get_status(MprisPlayer * obj, GValueArray * *status, GError * *error) 00387 { 00388 *status = g_value_array_new(4); 00389 00390 append_int_value(*status, (int) get_playback_status()); 00391 append_int_value (* status, get_bool (NULL, "shuffle")); 00392 append_int_value (* status, get_bool (NULL, "no_playlist_advance")); 00393 append_int_value (* status, get_bool (NULL, "repeat")); 00394 return TRUE; 00395 } 00396 00397 bool_t mpris_player_get_metadata (MprisPlayer * obj, GHashTable * * metadata, 00398 GError * * error) 00399 { 00400 int playlist = playlist_get_playing (); 00401 int entry = (playlist >= 0) ? playlist_get_position (playlist) : -1; 00402 00403 * metadata = (entry >= 0) ? get_mpris_metadata (playlist, entry) : NULL; 00404 if (! * metadata) 00405 * metadata = g_hash_table_new (g_str_hash, g_str_equal); 00406 00407 return TRUE; 00408 } 00409 00410 bool_t mpris_player_get_caps(MprisPlayer * obj, int * capabilities, GError ** error) 00411 { 00412 *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; 00413 return TRUE; 00414 } 00415 00416 bool_t mpris_player_volume_set(MprisPlayer * obj, int vol, GError ** error) 00417 { 00418 drct_set_volume_main (vol); 00419 return TRUE; 00420 } 00421 00422 bool_t mpris_player_volume_get(MprisPlayer * obj, int * vol, GError ** error) 00423 { 00424 drct_get_volume_main (vol); 00425 return TRUE; 00426 } 00427 00428 bool_t mpris_player_position_set (MprisPlayer * obj, int pos, GError * * error) 00429 { 00430 drct_seek (pos); 00431 return TRUE; 00432 } 00433 00434 bool_t mpris_player_position_get (MprisPlayer * obj, int * pos, GError * * error) 00435 { 00436 * pos = drct_get_time (); 00437 return TRUE; 00438 } 00439 00440 // MPRIS /Player signals 00441 bool_t mpris_emit_caps_change(MprisPlayer * obj) 00442 { 00443 g_signal_emit(obj, signals[CAPS_CHANGE_SIG], 0, 0); 00444 return TRUE; 00445 } 00446 00447 bool_t mpris_emit_track_change(MprisPlayer * obj) 00448 { 00449 int playlist, entry; 00450 GHashTable *metadata; 00451 00452 playlist = playlist_get_playing(); 00453 entry = playlist_get_position(playlist); 00454 char * filename = playlist_entry_get_filename (playlist, entry); 00455 Tuple * tuple = playlist_entry_get_tuple (playlist, entry, FALSE); 00456 00457 if (filename && tuple) 00458 { 00459 metadata = make_mpris_metadata (filename, tuple); 00460 g_signal_emit (obj, signals[TRACK_CHANGE_SIG], 0, metadata); 00461 g_hash_table_destroy (metadata); 00462 } 00463 00464 str_unref (filename); 00465 if (tuple) 00466 tuple_unref (tuple); 00467 00468 return (filename && tuple); 00469 } 00470 00471 bool_t mpris_emit_status_change(MprisPlayer * obj, PlaybackStatus status) 00472 { 00473 GValueArray *ar = g_value_array_new(4); 00474 00475 if (status == MPRIS_STATUS_INVALID) 00476 status = get_playback_status (); 00477 00478 append_int_value(ar, (int) status); 00479 append_int_value (ar, get_bool (NULL, "shuffle")); 00480 append_int_value (ar, get_bool (NULL, "no_playlist_advance")); 00481 append_int_value (ar, get_bool (NULL, "repeat")); 00482 00483 g_signal_emit(obj, signals[STATUS_CHANGE_SIG], 0, ar); 00484 g_value_array_free(ar); 00485 return TRUE; 00486 } 00487 00488 // MPRIS /TrackList 00489 bool_t mpris_emit_tracklist_change(MprisTrackList * obj, int playlist) 00490 { 00491 g_signal_emit(obj, tracklist_signals[TRACKLIST_CHANGE_SIG], 0, playlist_entry_count(playlist)); 00492 return TRUE; 00493 } 00494 00495 static void mpris_playlist_update_hook(gpointer unused, MprisTrackList * obj) 00496 { 00497 int playlist = playlist_get_active(); 00498 00499 mpris_emit_tracklist_change(obj, playlist); 00500 } 00501 00502 bool_t mpris_tracklist_get_metadata (MprisTrackList * obj, int pos, 00503 GHashTable * * metadata, GError * * error) 00504 { 00505 * metadata = get_mpris_metadata (playlist_get_active (), pos); 00506 if (! * metadata) 00507 * metadata = g_hash_table_new (g_str_hash, g_str_equal); 00508 00509 return TRUE; 00510 } 00511 00512 bool_t mpris_tracklist_get_current_track (MprisTrackList * obj, int * pos, 00513 GError * * error) 00514 { 00515 * pos = playlist_get_position (playlist_get_active ()); 00516 return TRUE; 00517 } 00518 00519 bool_t mpris_tracklist_get_length (MprisTrackList * obj, int * length, GError * * error) 00520 { 00521 * length = playlist_entry_count (playlist_get_active ()); 00522 return TRUE; 00523 } 00524 00525 bool_t mpris_tracklist_add_track (MprisTrackList * obj, char * uri, bool_t play, 00526 GError * * error) 00527 { 00528 playlist_entry_insert (playlist_get_active (), -1, uri, NULL, play); 00529 return TRUE; 00530 } 00531 00532 bool_t mpris_tracklist_del_track (MprisTrackList * obj, int pos, GError * * error) 00533 { 00534 playlist_entry_delete (playlist_get_active (), pos, 1); 00535 return TRUE; 00536 } 00537 00538 bool_t mpris_tracklist_loop (MprisTrackList * obj, bool_t loop, GError * * 00539 error) 00540 { 00541 set_bool (NULL, "repeat", loop); 00542 return TRUE; 00543 } 00544 00545 bool_t mpris_tracklist_random (MprisTrackList * obj, bool_t random, 00546 GError * * error) 00547 { 00548 set_bool (NULL, "shuffle", random); 00549 return TRUE; 00550 } 00551 00552 // Audacious General Information 00553 bool_t audacious_rc_version(RemoteObject * obj, char ** version, GError ** error) 00554 { 00555 *version = g_strdup(VERSION); 00556 return TRUE; 00557 } 00558 00559 bool_t audacious_rc_quit(RemoteObject * obj, GError * *error) 00560 { 00561 event_queue("quit", NULL); 00562 return TRUE; 00563 } 00564 00565 bool_t audacious_rc_eject(RemoteObject * obj, GError ** error) 00566 { 00567 interface_show_filebrowser (TRUE); 00568 return TRUE; 00569 } 00570 00571 bool_t audacious_rc_main_win_visible (RemoteObject * obj, 00572 bool_t * visible, GError ** error) 00573 { 00574 * visible = interface_is_shown (); 00575 return TRUE; 00576 } 00577 00578 bool_t audacious_rc_show_main_win (RemoteObject * obj, bool_t show, 00579 GError * * error) 00580 { 00581 interface_show (show); 00582 return TRUE; 00583 } 00584 00585 bool_t audacious_rc_get_tuple_fields(RemoteObject * obj, char *** fields, GError ** error) 00586 { 00587 * fields = g_new (char *, TUPLE_FIELDS); 00588 00589 for (int i = 0; i < TUPLE_FIELDS; i ++) 00590 (* fields)[i] = g_strdup (tuple_field_get_name (i)); 00591 00592 (* fields)[TUPLE_FIELDS] = NULL; 00593 return TRUE; 00594 } 00595 00596 00597 // Playback Information/Manipulation 00598 00599 bool_t audacious_rc_play (RemoteObject * obj, GError * * error) 00600 { 00601 drct_play (); 00602 return TRUE; 00603 } 00604 00605 bool_t audacious_rc_pause (RemoteObject * obj, GError * * error) 00606 { 00607 drct_pause (); 00608 return TRUE; 00609 } 00610 00611 bool_t audacious_rc_stop (RemoteObject * obj, GError * * error) 00612 { 00613 drct_stop (); 00614 return TRUE; 00615 } 00616 00617 bool_t audacious_rc_playing (RemoteObject * obj, bool_t * is_playing, GError * * error) 00618 { 00619 * is_playing = drct_get_playing (); 00620 return TRUE; 00621 } 00622 00623 bool_t audacious_rc_paused (RemoteObject * obj, bool_t * is_paused, GError * * error) 00624 { 00625 * is_paused = drct_get_paused (); 00626 return TRUE; 00627 } 00628 00629 bool_t audacious_rc_stopped (RemoteObject * obj, bool_t * is_stopped, GError * * error) 00630 { 00631 * is_stopped = ! drct_get_playing (); 00632 return TRUE; 00633 } 00634 00635 bool_t audacious_rc_status (RemoteObject * obj, char * * status, GError * * error) 00636 { 00637 if (drct_get_playing ()) 00638 * status = strdup (drct_get_paused () ? "paused" : "playing"); 00639 else 00640 * status = strdup ("stopped"); 00641 00642 return TRUE; 00643 } 00644 00645 bool_t audacious_rc_info (RemoteObject * obj, int * rate, int * freq, int * nch, 00646 GError * * error) 00647 { 00648 drct_get_info (rate, freq, nch); 00649 return TRUE; 00650 } 00651 00652 bool_t audacious_rc_time (RemoteObject * obj, int * time, GError * * error) 00653 { 00654 * time = drct_get_time (); 00655 return TRUE; 00656 } 00657 00658 bool_t audacious_rc_seek (RemoteObject * obj, unsigned int pos, GError * * error) 00659 { 00660 drct_seek (pos); 00661 return TRUE; 00662 } 00663 00664 bool_t audacious_rc_volume(RemoteObject * obj, int * vl, int * vr, GError ** error) 00665 { 00666 drct_get_volume (vl, vr); 00667 return TRUE; 00668 } 00669 00670 bool_t audacious_rc_set_volume(RemoteObject * obj, int vl, int vr, GError ** error) 00671 { 00672 drct_set_volume (vl, vr); 00673 return TRUE; 00674 } 00675 00676 bool_t audacious_rc_balance(RemoteObject * obj, int * balance, GError ** error) 00677 { 00678 drct_get_volume_balance (balance); 00679 return TRUE; 00680 } 00681 00682 // Playlist Information/Manipulation 00683 00684 bool_t audacious_rc_position (RemoteObject * obj, int * pos, GError * * error) 00685 { 00686 * pos = playlist_get_position (playlist_get_active ()); 00687 return TRUE; 00688 } 00689 00690 bool_t audacious_rc_advance(RemoteObject * obj, GError * *error) 00691 { 00692 drct_pl_next (); 00693 return TRUE; 00694 } 00695 00696 bool_t audacious_rc_reverse (RemoteObject * obj, GError * * error) 00697 { 00698 drct_pl_prev (); 00699 return TRUE; 00700 } 00701 00702 bool_t audacious_rc_length (RemoteObject * obj, int * length, GError * * error) 00703 { 00704 * length = playlist_entry_count (playlist_get_active ()); 00705 return TRUE; 00706 } 00707 00708 bool_t audacious_rc_song_title (RemoteObject * obj, unsigned int pos, char * * 00709 title, GError * * error) 00710 { 00711 char * title2 = playlist_entry_get_title (playlist_get_active (), pos, FALSE); 00712 * title = strdup (title2); 00713 str_unref (title2); 00714 return TRUE; 00715 } 00716 00717 bool_t audacious_rc_song_filename (RemoteObject * obj, unsigned int pos, 00718 char * * filename, GError * * error) 00719 { 00720 char * filename2 = playlist_entry_get_filename (playlist_get_active (), pos); 00721 * filename = strdup (filename2); 00722 str_unref (filename2); 00723 return TRUE; 00724 } 00725 00726 bool_t audacious_rc_song_length(RemoteObject * obj, unsigned int pos, int * length, GError * *error) 00727 { 00728 audacious_rc_song_frames(obj, pos, length, error); 00729 *length /= 1000; 00730 return TRUE; 00731 } 00732 00733 bool_t audacious_rc_song_frames (RemoteObject * obj, unsigned int pos, int * 00734 length, GError * * error) 00735 { 00736 * length = playlist_entry_get_length (playlist_get_active (), pos, FALSE); 00737 return TRUE; 00738 } 00739 00740 bool_t audacious_rc_song_tuple (RemoteObject * obj, unsigned int pos, char * 00741 field, GValue * value, GError * * error) 00742 { 00743 GValue * value2 = get_field (playlist_get_active (), pos, field); 00744 if (! value2) 00745 return FALSE; 00746 00747 memset (value, 0, sizeof (GValue)); 00748 g_value_init (value, G_VALUE_TYPE (value2)); 00749 g_value_copy (value2, value); 00750 g_value_unset (value2); 00751 g_free (value2); 00752 return TRUE; 00753 } 00754 00755 bool_t audacious_rc_jump (RemoteObject * obj, unsigned int pos, GError * * error) 00756 { 00757 playlist_set_position (playlist_get_active (), pos); 00758 return TRUE; 00759 } 00760 00761 bool_t audacious_rc_add(RemoteObject * obj, char * file, GError * *error) 00762 { 00763 return audacious_rc_playlist_ins_url_string(obj, file, -1, error); 00764 } 00765 00766 bool_t audacious_rc_add_url(RemoteObject * obj, char * file, GError * *error) 00767 { 00768 return audacious_rc_playlist_ins_url_string(obj, file, -1, error); 00769 } 00770 00771 static Index * strings_to_index (char * * strings) 00772 { 00773 Index * index = index_new (); 00774 00775 while (* strings) 00776 index_append (index, str_get (* strings ++)); 00777 00778 return index; 00779 } 00780 00781 bool_t audacious_rc_add_list (RemoteObject * obj, char * * filenames, 00782 GError * * error) 00783 { 00784 drct_pl_add_list (strings_to_index (filenames), -1); 00785 return TRUE; 00786 } 00787 00788 bool_t audacious_rc_open_list (RemoteObject * obj, char * * filenames, 00789 GError * * error) 00790 { 00791 drct_pl_open_list (strings_to_index (filenames)); 00792 return TRUE; 00793 } 00794 00795 bool_t audacious_rc_open_list_to_temp (RemoteObject * obj, char * * 00796 filenames, GError * * error) 00797 { 00798 drct_pl_open_temp_list (strings_to_index (filenames)); 00799 return TRUE; 00800 } 00801 00802 bool_t audacious_rc_delete (RemoteObject * obj, unsigned int pos, GError * * error) 00803 { 00804 playlist_entry_delete (playlist_get_active (), pos, 1); 00805 return TRUE; 00806 } 00807 00808 bool_t audacious_rc_clear (RemoteObject * obj, GError * * error) 00809 { 00810 int playlist = playlist_get_active (); 00811 playlist_entry_delete (playlist, 0, playlist_entry_count (playlist)); 00812 return TRUE; 00813 } 00814 00815 bool_t audacious_rc_auto_advance(RemoteObject * obj, bool_t * is_advance, GError ** error) 00816 { 00817 * is_advance = ! get_bool (NULL, "no_playlist_advance"); 00818 return TRUE; 00819 } 00820 00821 bool_t audacious_rc_toggle_auto_advance(RemoteObject * obj, GError ** error) 00822 { 00823 set_bool (NULL, "no_playlist_advance", ! get_bool (NULL, "no_playlist_advance")); 00824 return TRUE; 00825 } 00826 00827 bool_t audacious_rc_repeat(RemoteObject * obj, bool_t * is_repeating, GError ** error) 00828 { 00829 *is_repeating = get_bool (NULL, "repeat"); 00830 return TRUE; 00831 } 00832 00833 bool_t audacious_rc_toggle_repeat (RemoteObject * obj, GError * * error) 00834 { 00835 set_bool (NULL, "repeat", ! get_bool (NULL, "repeat")); 00836 return TRUE; 00837 } 00838 00839 bool_t audacious_rc_shuffle(RemoteObject * obj, bool_t * is_shuffling, GError ** error) 00840 { 00841 *is_shuffling = get_bool (NULL, "shuffle"); 00842 return TRUE; 00843 } 00844 00845 bool_t audacious_rc_toggle_shuffle (RemoteObject * obj, GError * * error) 00846 { 00847 set_bool (NULL, "shuffle", ! get_bool (NULL, "shuffle")); 00848 return TRUE; 00849 } 00850 00851 bool_t audacious_rc_stop_after (RemoteObject * obj, bool_t * is_stopping, GError * * error) 00852 { 00853 * is_stopping = get_bool (NULL, "stop_after_current_song"); 00854 return TRUE; 00855 } 00856 00857 bool_t audacious_rc_toggle_stop_after (RemoteObject * obj, GError * * error) 00858 { 00859 set_bool (NULL, "stop_after_current_song", ! get_bool (NULL, "stop_after_current_song")); 00860 return TRUE; 00861 } 00862 00863 /* New on Oct 5 */ 00864 bool_t audacious_rc_show_prefs_box(RemoteObject * obj, bool_t show, GError ** error) 00865 { 00866 event_queue("prefswin show", GINT_TO_POINTER(show)); 00867 return TRUE; 00868 } 00869 00870 bool_t audacious_rc_show_about_box(RemoteObject * obj, bool_t show, GError ** error) 00871 { 00872 event_queue("aboutwin show", GINT_TO_POINTER(show)); 00873 return TRUE; 00874 } 00875 00876 bool_t audacious_rc_show_jtf_box(RemoteObject * obj, bool_t show, GError ** error) 00877 { 00878 if (show) 00879 interface_show_jump_to_track (); 00880 00881 return TRUE; 00882 } 00883 00884 bool_t audacious_rc_show_filebrowser(RemoteObject * obj, bool_t show, GError ** error) 00885 { 00886 if (show) 00887 interface_show_filebrowser (FALSE); 00888 00889 return TRUE; 00890 } 00891 00892 bool_t audacious_rc_play_pause (RemoteObject * obj, GError * * error) 00893 { 00894 if (drct_get_playing ()) 00895 drct_pause (); 00896 else 00897 drct_play (); 00898 00899 return TRUE; 00900 } 00901 00902 bool_t audacious_rc_get_info (RemoteObject * obj, int * rate, int * freq, 00903 int * nch, GError * * error) 00904 { 00905 drct_get_info (rate, freq, nch); 00906 return TRUE; 00907 } 00908 00909 bool_t audacious_rc_toggle_aot(RemoteObject * obj, bool_t ontop, GError ** error) 00910 { 00911 hook_call("mainwin set always on top", &ontop); 00912 return TRUE; 00913 } 00914 00915 bool_t audacious_rc_playqueue_add (RemoteObject * obj, int pos, GError * * error) 00916 { 00917 playlist_queue_insert (playlist_get_active (), -1, pos); 00918 return TRUE; 00919 } 00920 00921 bool_t audacious_rc_playqueue_remove (RemoteObject * obj, int pos, GError * * error) 00922 { 00923 int playlist = playlist_get_active (); 00924 int at = playlist_queue_find_entry (playlist, pos); 00925 00926 if (at >= 0) 00927 playlist_queue_delete (playlist, at, 1); 00928 00929 return TRUE; 00930 } 00931 00932 bool_t audacious_rc_playqueue_clear (RemoteObject * obj, GError * * error) 00933 { 00934 int playlist = playlist_get_active (); 00935 playlist_queue_delete (playlist, 0, playlist_queue_count (playlist)); 00936 return TRUE; 00937 } 00938 00939 bool_t audacious_rc_get_playqueue_length (RemoteObject * obj, int * length, 00940 GError * * error) 00941 { 00942 * length = playlist_queue_count (playlist_get_active ()); 00943 return TRUE; 00944 } 00945 00946 bool_t audacious_rc_queue_get_list_pos (RemoteObject * obj, int qpos, int * pos, 00947 GError * * error) 00948 { 00949 * pos = playlist_queue_get_entry (playlist_get_active (), qpos); 00950 return TRUE; 00951 } 00952 00953 bool_t audacious_rc_queue_get_queue_pos (RemoteObject * obj, int pos, int * 00954 qpos, GError * * error) 00955 { 00956 * qpos = playlist_queue_find_entry (playlist_get_active (), pos); 00957 return TRUE; 00958 } 00959 00960 bool_t audacious_rc_playqueue_is_queued (RemoteObject * obj, int pos, bool_t * 00961 is_queued, GError * * error) 00962 { 00963 * is_queued = (playlist_queue_find_entry (playlist_get_active (), pos) >= 0); 00964 return TRUE; 00965 } 00966 00967 bool_t audacious_rc_playlist_ins_url_string (RemoteObject * obj, char * url, int 00968 pos, GError * * error) 00969 { 00970 playlist_entry_insert (playlist_get_active (), pos, url, NULL, FALSE); 00971 return TRUE; 00972 } 00973 00974 bool_t audacious_rc_playlist_add(RemoteObject * obj, void *list, GError * *error) 00975 { 00976 return audacious_rc_playlist_ins_url_string(obj, list, -1, error); 00977 } 00978 00979 bool_t audacious_rc_playlist_enqueue_to_temp (RemoteObject * obj, char * url, 00980 GError * * error) 00981 { 00982 drct_pl_open_temp (url); 00983 return TRUE; 00984 } 00985 00986 /* New on Nov 7: Equalizer */ 00987 bool_t audacious_rc_get_eq(RemoteObject * obj, double * preamp, GArray ** bands, GError ** error) 00988 { 00989 * preamp = get_double (NULL, "equalizer_preamp"); 00990 * bands = g_array_new (FALSE, FALSE, sizeof (double)); 00991 g_array_set_size (* bands, AUD_EQUALIZER_NBANDS); 00992 eq_get_bands ((double *) (* bands)->data); 00993 00994 return TRUE; 00995 } 00996 00997 bool_t audacious_rc_get_eq_preamp(RemoteObject * obj, double * preamp, GError ** error) 00998 { 00999 * preamp = get_double (NULL, "equalizer_preamp"); 01000 return TRUE; 01001 } 01002 01003 bool_t audacious_rc_get_eq_band(RemoteObject * obj, int band, double * value, GError ** error) 01004 { 01005 * value = eq_get_band (band); 01006 return TRUE; 01007 } 01008 01009 bool_t audacious_rc_set_eq(RemoteObject * obj, double preamp, GArray * bands, GError ** error) 01010 { 01011 set_double (NULL, "equalizer_preamp", preamp); 01012 eq_set_bands ((double *) bands->data); 01013 return TRUE; 01014 } 01015 01016 bool_t audacious_rc_set_eq_preamp(RemoteObject * obj, double preamp, GError ** error) 01017 { 01018 set_double (NULL, "equalizer_preamp", preamp); 01019 return TRUE; 01020 } 01021 01022 bool_t audacious_rc_set_eq_band(RemoteObject * obj, int band, double value, GError ** error) 01023 { 01024 eq_set_band (band, value); 01025 return TRUE; 01026 } 01027 01028 bool_t audacious_rc_equalizer_activate(RemoteObject * obj, bool_t active, GError ** error) 01029 { 01030 set_bool (NULL, "equalizer_active", active); 01031 return TRUE; 01032 } 01033 01034 bool_t audacious_rc_get_active_playlist_name (RemoteObject * obj, char * * 01035 title, GError * * error) 01036 { 01037 char * title2 = playlist_get_title (playlist_get_active ()); 01038 * title = strdup (title2); 01039 str_unref (title2); 01040 return TRUE; 01041 } 01042 01043 DBusGProxy *audacious_get_dbus_proxy(void) 01044 { 01045 DBusGConnection *connection = NULL; 01046 GError *error = NULL; 01047 connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); 01048 g_clear_error(&error); 01049 return dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); 01050 }