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-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 }