Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
dbus.c
Go to the documentation of this file.
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 }