summaryrefslogtreecommitdiff
path: root/src/audacious/dbus-server.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/audacious/dbus-server.cc')
-rw-r--r--src/audacious/dbus-server.cc815
1 files changed, 815 insertions, 0 deletions
diff --git a/src/audacious/dbus-server.cc b/src/audacious/dbus-server.cc
new file mode 100644
index 0000000..90f464e
--- /dev/null
+++ b/src/audacious/dbus-server.cc
@@ -0,0 +1,815 @@
+/*
+ * dbus-server.c
+ * Copyright 2013 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include <libaudcore/drct.h>
+#include <libaudcore/equalizer.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/tuple.h>
+
+#include "aud-dbus.h"
+#include "main.h"
+
+typedef ObjAudacious Obj;
+typedef GDBusMethodInvocation Invoc;
+
+#define FINISH(name) \
+ obj_audacious_complete_##name (obj, invoc)
+
+#define FINISH2(name, ...) \
+ obj_audacious_complete_##name (obj, invoc, __VA_ARGS__)
+
+static Index<PlaylistAddItem> strv_to_index (const char * const * strv)
+{
+ Index<PlaylistAddItem> index;
+ while (* strv)
+ index.append (String (* strv ++));
+
+ return index;
+}
+
+static gboolean do_add (Obj * obj, Invoc * invoc, const char * file)
+{
+ aud_playlist_entry_insert (aud_playlist_get_active (), -1, file, Tuple (), false);
+ FINISH (add);
+ return true;
+}
+
+static gboolean do_add_list (Obj * obj, Invoc * invoc, const char * const * filenames)
+{
+ aud_playlist_entry_insert_batch (aud_playlist_get_active (), -1,
+ strv_to_index (filenames), false);
+ FINISH (add_list);
+ return true;
+}
+
+static gboolean do_add_url (Obj * obj, Invoc * invoc, const char * url)
+{
+ aud_playlist_entry_insert (aud_playlist_get_active (), -1, url, Tuple (), false);
+ FINISH (add_url);
+ return true;
+}
+
+static gboolean do_advance (Obj * obj, Invoc * invoc)
+{
+ aud_drct_pl_next ();
+ FINISH (advance);
+ return true;
+}
+
+static gboolean do_auto_advance (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (auto_advance, ! aud_get_bool (nullptr, "no_playlist_advance"));
+ return true;
+}
+
+static gboolean do_balance (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (balance, aud_drct_get_volume_balance ());
+ return true;
+}
+
+static gboolean do_clear (Obj * obj, Invoc * invoc)
+{
+ int playlist = aud_playlist_get_active ();
+ aud_playlist_entry_delete (playlist, 0, aud_playlist_entry_count (playlist));
+ FINISH (clear);
+ return true;
+}
+
+static gboolean do_delete (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ aud_playlist_entry_delete (aud_playlist_get_active (), pos, 1);
+ FINISH (delete);
+ return true;
+}
+
+static gboolean do_delete_active_playlist (Obj * obj, Invoc * invoc)
+{
+ aud_playlist_delete (aud_playlist_get_active ());
+ FINISH (delete_active_playlist);
+ return true;
+}
+
+static gboolean do_eject (Obj * obj, Invoc * invoc)
+{
+ if (! aud_get_headless_mode ())
+ aud_ui_show_filebrowser (true);
+
+ FINISH (eject);
+ return true;
+}
+
+static gboolean do_equalizer_activate (Obj * obj, Invoc * invoc, gboolean active)
+{
+ aud_set_bool (nullptr, "equalizer_active", active);
+ FINISH (equalizer_activate);
+ return true;
+}
+
+static gboolean do_get_active_playlist (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (get_active_playlist, aud_playlist_get_active ());
+ return true;
+}
+
+static gboolean do_get_active_playlist_name (Obj * obj, Invoc * invoc)
+{
+ String title = aud_playlist_get_title (aud_playlist_get_active ());
+ FINISH2 (get_active_playlist_name, title ? title : "");
+ return true;
+}
+
+static gboolean do_get_eq (Obj * obj, Invoc * invoc)
+{
+ double preamp = aud_get_double (nullptr, "equalizer_preamp");
+ double bands[AUD_EQ_NBANDS];
+ aud_eq_get_bands (bands);
+
+ GVariant * var = g_variant_new_fixed_array (G_VARIANT_TYPE_DOUBLE, bands,
+ AUD_EQ_NBANDS, sizeof (double));
+ FINISH2 (get_eq, preamp, var);
+ return true;
+}
+
+static gboolean do_get_eq_band (Obj * obj, Invoc * invoc, int band)
+{
+ FINISH2 (get_eq_band, aud_eq_get_band (band));
+ return true;
+}
+
+static gboolean do_get_eq_preamp (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (get_eq_preamp, aud_get_double (nullptr, "equalizer_preamp"));
+ return true;
+}
+
+static gboolean do_get_info (Obj * obj, Invoc * invoc)
+{
+ int bitrate, samplerate, channels;
+ aud_drct_get_info (bitrate, samplerate, channels);
+ FINISH2 (get_info, bitrate, samplerate, channels);
+ return true;
+}
+
+static gboolean do_get_playqueue_length (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (get_playqueue_length, aud_playlist_queue_count (aud_playlist_get_active ()));
+ return true;
+}
+
+static gboolean do_get_tuple_fields (Obj * obj, Invoc * invoc)
+{
+ const char * fields[Tuple::n_fields + 1];
+
+ for (auto f : Tuple::all_fields ())
+ fields[f] = Tuple::field_get_name (f);
+
+ fields[Tuple::n_fields] = nullptr;
+
+ FINISH2 (get_tuple_fields, fields);
+ return true;
+}
+
+static gboolean do_info (Obj * obj, Invoc * invoc)
+{
+ int bitrate, samplerate, channels;
+ aud_drct_get_info (bitrate, samplerate, channels);
+ FINISH2 (info, bitrate, samplerate, channels);
+ return true;
+}
+
+static gboolean do_jump (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ aud_playlist_set_position (aud_playlist_get_active (), pos);
+ FINISH (jump);
+ return true;
+}
+
+static gboolean do_length (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (length, aud_playlist_entry_count (aud_playlist_get_active ()));
+ return true;
+}
+
+static gboolean do_main_win_visible (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (main_win_visible, ! aud_get_headless_mode () && aud_ui_is_shown ());
+ return true;
+}
+
+static gboolean do_new_playlist (Obj * obj, Invoc * invoc)
+{
+ aud_playlist_insert (-1);
+ aud_playlist_set_active (aud_playlist_count () - 1);
+ FINISH (new_playlist);
+ return true;
+}
+
+static gboolean do_number_of_playlists (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (number_of_playlists, aud_playlist_count ());
+ return true;
+}
+
+static gboolean do_open_list (Obj * obj, Invoc * invoc, const char * const * filenames)
+{
+ aud_drct_pl_open_list (strv_to_index (filenames));
+ FINISH (open_list);
+ return true;
+}
+
+static gboolean do_open_list_to_temp (Obj * obj, Invoc * invoc, const char * const * filenames)
+{
+ aud_drct_pl_open_temp_list (strv_to_index (filenames));
+ FINISH (open_list_to_temp);
+ return true;
+}
+
+static gboolean do_pause (Obj * obj, Invoc * invoc)
+{
+ aud_drct_pause ();
+ FINISH (pause);
+ return true;
+}
+
+static gboolean do_paused (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (paused, aud_drct_get_paused ());
+ return true;
+}
+
+static gboolean do_play (Obj * obj, Invoc * invoc)
+{
+ aud_drct_play ();
+ FINISH (play);
+ return true;
+}
+
+static gboolean do_play_active_playlist (Obj * obj, Invoc * invoc)
+{
+ aud_playlist_play (aud_playlist_get_active ());
+ FINISH (play_active_playlist);
+ return true;
+}
+
+static gboolean do_play_pause (Obj * obj, Invoc * invoc)
+{
+ aud_drct_play_pause ();
+ FINISH (play_pause);
+ return true;
+}
+
+static gboolean do_playing (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (playing, aud_drct_get_playing ());
+ return true;
+}
+
+static gboolean do_playlist_add (Obj * obj, Invoc * invoc, const char * list)
+{
+ aud_playlist_entry_insert (aud_playlist_get_active (), -1, list, Tuple (), false);
+ FINISH (playlist_add);
+ return true;
+}
+
+static gboolean do_playlist_enqueue_to_temp (Obj * obj, Invoc * invoc, const char * url)
+{
+ aud_drct_pl_open_temp (url);
+ FINISH (playlist_enqueue_to_temp);
+ return true;
+}
+
+static gboolean do_playlist_ins_url_string (Obj * obj, Invoc * invoc, const char * url, int pos)
+{
+ aud_playlist_entry_insert (aud_playlist_get_active (), pos, url, Tuple (), false);
+ FINISH (playlist_ins_url_string);
+ return true;
+}
+
+static gboolean do_playqueue_add (Obj * obj, Invoc * invoc, int pos)
+{
+ aud_playlist_queue_insert (aud_playlist_get_active (), -1, pos);
+ FINISH (playqueue_add);
+ return true;
+}
+
+static gboolean do_playqueue_clear (Obj * obj, Invoc * invoc)
+{
+ int playlist = aud_playlist_get_active ();
+ aud_playlist_queue_delete (playlist, 0, aud_playlist_queue_count (playlist));
+ FINISH (playqueue_clear);
+ return true;
+}
+
+static gboolean do_playqueue_is_queued (Obj * obj, Invoc * invoc, int pos)
+{
+ bool queued = (aud_playlist_queue_find_entry (aud_playlist_get_active (), pos) >= 0);
+ FINISH2 (playqueue_is_queued, queued);
+ return true;
+}
+
+static gboolean do_playqueue_remove (Obj * obj, Invoc * invoc, int pos)
+{
+ int playlist = aud_playlist_get_active ();
+ int qpos = aud_playlist_queue_find_entry (playlist, pos);
+
+ if (qpos >= 0)
+ aud_playlist_queue_delete (playlist, qpos, 1);
+
+ FINISH (playqueue_remove);
+ return true;
+}
+
+static gboolean do_position (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (position, aud_playlist_get_position (aud_playlist_get_active ()));
+ return true;
+}
+
+static gboolean do_queue_get_list_pos (Obj * obj, Invoc * invoc, unsigned qpos)
+{
+ FINISH2 (queue_get_list_pos, aud_playlist_queue_get_entry (aud_playlist_get_active (), qpos));
+ return true;
+}
+
+static gboolean do_queue_get_queue_pos (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ FINISH2 (queue_get_queue_pos, aud_playlist_queue_find_entry (aud_playlist_get_active (), pos));
+ return true;
+}
+
+static gboolean do_quit (Obj * obj, Invoc * invoc)
+{
+ aud_quit ();
+ FINISH (quit);
+ return true;
+}
+
+static gboolean do_repeat (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (repeat, aud_get_bool (nullptr, "repeat"));
+ return true;
+}
+
+static gboolean do_reverse (Obj * obj, Invoc * invoc)
+{
+ aud_drct_pl_prev ();
+ FINISH (reverse);
+ return true;
+}
+
+static gboolean do_seek (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ aud_drct_seek (pos);
+ FINISH (seek);
+ return true;
+}
+
+static gboolean do_set_active_playlist (Obj * obj, Invoc * invoc, int playlist)
+{
+ aud_playlist_set_active (playlist);
+ FINISH (set_active_playlist);
+ return true;
+}
+
+static gboolean do_set_active_playlist_name (Obj * obj, Invoc * invoc, const char * title)
+{
+ aud_playlist_set_title (aud_playlist_get_active (), title);
+ FINISH (set_active_playlist_name);
+ return true;
+}
+
+static gboolean do_set_eq (Obj * obj, Invoc * invoc, double preamp, GVariant * var)
+{
+ if (! g_variant_is_of_type (var, G_VARIANT_TYPE ("ad")))
+ return false;
+
+ size_t nbands = 0;
+ const double * bands = (double *) g_variant_get_fixed_array (var, & nbands, sizeof (double));
+
+ if (nbands != AUD_EQ_NBANDS)
+ return false;
+
+ aud_set_double (nullptr, "equalizer_preamp", preamp);
+ aud_eq_set_bands (bands);
+ FINISH (set_eq);
+ return true;
+}
+
+static gboolean do_set_eq_band (Obj * obj, Invoc * invoc, int band, double value)
+{
+ aud_eq_set_band (band, value);
+ FINISH (set_eq_band);
+ return true;
+}
+
+static gboolean do_set_eq_preamp (Obj * obj, Invoc * invoc, double preamp)
+{
+ aud_set_double (nullptr, "equalizer_preamp", preamp);
+ FINISH (set_eq_preamp);
+ return true;
+}
+
+static gboolean do_set_volume (Obj * obj, Invoc * invoc, int vl, int vr)
+{
+ aud_drct_set_volume ({vl, vr});
+ FINISH (set_volume);
+ return true;
+}
+
+static gboolean do_show_about_box (Obj * obj, Invoc * invoc, gboolean show)
+{
+ if (! aud_get_headless_mode ())
+ {
+ if (show)
+ aud_ui_show_about_window ();
+ else
+ aud_ui_hide_about_window ();
+ }
+
+ FINISH (show_about_box);
+ return true;
+}
+
+static gboolean do_show_filebrowser (Obj * obj, Invoc * invoc, gboolean show)
+{
+ if (! aud_get_headless_mode ())
+ {
+ if (show)
+ aud_ui_show_filebrowser (false);
+ else
+ aud_ui_hide_filebrowser ();
+ }
+
+ FINISH (show_filebrowser);
+ return true;
+}
+
+static gboolean do_show_jtf_box (Obj * obj, Invoc * invoc, gboolean show)
+{
+ if (! aud_get_headless_mode ())
+ {
+ if (show)
+ aud_ui_show_jump_to_song ();
+ else
+ aud_ui_hide_jump_to_song ();
+ }
+
+ FINISH (show_jtf_box);
+ return true;
+}
+
+static gboolean do_show_main_win (Obj * obj, Invoc * invoc, gboolean show)
+{
+ if (! aud_get_headless_mode ())
+ aud_ui_show (show);
+
+ FINISH (show_main_win);
+ return true;
+}
+
+static gboolean do_show_prefs_box (Obj * obj, Invoc * invoc, gboolean show)
+{
+ if (! aud_get_headless_mode ())
+ {
+ if (show)
+ aud_ui_show_prefs_window ();
+ else
+ aud_ui_hide_prefs_window ();
+ }
+
+ FINISH (show_prefs_box);
+ return true;
+}
+
+static gboolean do_shuffle (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (shuffle, aud_get_bool (nullptr, "shuffle"));
+ return true;
+}
+
+static gboolean do_song_filename (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ String filename = aud_playlist_entry_get_filename (aud_playlist_get_active (), pos);
+ FINISH2 (song_filename, filename ? filename : "");
+ return true;
+}
+
+static gboolean do_song_frames (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ Tuple tuple = aud_playlist_entry_get_tuple (aud_playlist_get_active (), pos);
+ FINISH2 (song_frames, aud::max (0, tuple.get_int (Tuple::Length)));
+ return true;
+}
+
+static gboolean do_song_length (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ Tuple tuple = aud_playlist_entry_get_tuple (aud_playlist_get_active (), pos);
+ int length = aud::max (0, tuple.get_int (Tuple::Length));
+ FINISH2 (song_length, length / 1000);
+ return true;
+}
+
+static gboolean do_song_title (Obj * obj, Invoc * invoc, unsigned pos)
+{
+ Tuple tuple = aud_playlist_entry_get_tuple (aud_playlist_get_active (), pos);
+ String title = tuple.get_str (Tuple::FormattedTitle);
+ FINISH2 (song_title, title ? title : "");
+ return true;
+}
+
+static gboolean do_song_tuple (Obj * obj, Invoc * invoc, unsigned pos, const char * key)
+{
+ Tuple::Field field = Tuple::field_by_name (key);
+ Tuple tuple;
+ GVariant * var = nullptr;
+
+ if (field >= 0)
+ tuple = aud_playlist_entry_get_tuple (aud_playlist_get_active (), pos);
+
+ if (tuple)
+ {
+ switch (tuple.get_value_type (field))
+ {
+ case Tuple::String:
+ var = g_variant_new_string (tuple.get_str (field));
+ break;
+
+ case Tuple::Int:
+ var = g_variant_new_int32 (tuple.get_int (field));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (! var)
+ var = g_variant_new_string ("");
+
+ FINISH2 (song_tuple, g_variant_new_variant (var));
+ return true;
+}
+
+static gboolean do_status (Obj * obj, Invoc * invoc)
+{
+ const char * status = "stopped";
+ if (aud_drct_get_playing ())
+ status = aud_drct_get_paused () ? "paused" : "playing";
+
+ FINISH2 (status, status);
+ return true;
+}
+
+static gboolean do_stop (Obj * obj, Invoc * invoc)
+{
+ aud_drct_stop ();
+ FINISH (stop);
+ return true;
+}
+
+static gboolean do_stop_after (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (stop_after, aud_get_bool (nullptr, "stop_after_current_song"));
+ return true;
+}
+
+static gboolean do_stopped (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (stopped, ! aud_drct_get_playing ());
+ return true;
+}
+
+static gboolean do_time (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (time, aud_drct_get_time ());
+ return true;
+}
+
+static gboolean do_toggle_auto_advance (Obj * obj, Invoc * invoc)
+{
+ aud_set_bool (nullptr, "no_playlist_advance", ! aud_get_bool (nullptr, "no_playlist_advance"));
+ FINISH (toggle_auto_advance);
+ return true;
+}
+
+static gboolean do_toggle_repeat (Obj * obj, Invoc * invoc)
+{
+ aud_set_bool (nullptr, "repeat", ! aud_get_bool (nullptr, "repeat"));
+ FINISH (toggle_repeat);
+ return true;
+}
+
+static gboolean do_toggle_shuffle (Obj * obj, Invoc * invoc)
+{
+ aud_set_bool (nullptr, "shuffle", ! aud_get_bool (nullptr, "shuffle"));
+ FINISH (toggle_shuffle);
+ return true;
+}
+
+static gboolean do_toggle_stop_after (Obj * obj, Invoc * invoc)
+{
+ aud_set_bool (nullptr, "stop_after_current_song", ! aud_get_bool (nullptr, "stop_after_current_song"));
+ FINISH (toggle_stop_after);
+ return true;
+}
+
+static gboolean do_version (Obj * obj, Invoc * invoc)
+{
+ FINISH2 (version, VERSION);
+ return true;
+}
+
+static gboolean do_volume (Obj * obj, Invoc * invoc)
+{
+ StereoVolume volume = aud_drct_get_volume ();
+ FINISH2 (volume, volume.left, volume.right);
+ return true;
+}
+
+static const struct
+{
+ const char * signal;
+ GCallback callback;
+}
+handlers[] =
+{
+ {"handle-add", (GCallback) do_add},
+ {"handle-add-list", (GCallback) do_add_list},
+ {"handle-add-url", (GCallback) do_add_url},
+ {"handle-advance", (GCallback) do_advance},
+ {"handle-auto-advance", (GCallback) do_auto_advance},
+ {"handle-balance", (GCallback) do_balance},
+ {"handle-clear", (GCallback) do_clear},
+ {"handle-delete", (GCallback) do_delete},
+ {"handle-delete-active-playlist", (GCallback) do_delete_active_playlist},
+ {"handle-eject", (GCallback) do_eject},
+ {"handle-equalizer-activate", (GCallback) do_equalizer_activate},
+ {"handle-get-active-playlist", (GCallback) do_get_active_playlist},
+ {"handle-get-active-playlist-name", (GCallback) do_get_active_playlist_name},
+ {"handle-get-eq", (GCallback) do_get_eq},
+ {"handle-get-eq-band", (GCallback) do_get_eq_band},
+ {"handle-get-eq-preamp", (GCallback) do_get_eq_preamp},
+ {"handle-get-info", (GCallback) do_get_info},
+ {"handle-get-playqueue-length", (GCallback) do_get_playqueue_length},
+ {"handle-get-tuple-fields", (GCallback) do_get_tuple_fields},
+ {"handle-info", (GCallback) do_info},
+ {"handle-jump", (GCallback) do_jump},
+ {"handle-length", (GCallback) do_length},
+ {"handle-main-win-visible", (GCallback) do_main_win_visible},
+ {"handle-new-playlist", (GCallback) do_new_playlist},
+ {"handle-number-of-playlists", (GCallback) do_number_of_playlists},
+ {"handle-open-list", (GCallback) do_open_list},
+ {"handle-open-list-to-temp", (GCallback) do_open_list_to_temp},
+ {"handle-pause", (GCallback) do_pause},
+ {"handle-paused", (GCallback) do_paused},
+ {"handle-play", (GCallback) do_play},
+ {"handle-play-active-playlist", (GCallback) do_play_active_playlist},
+ {"handle-play-pause", (GCallback) do_play_pause},
+ {"handle-playing", (GCallback) do_playing},
+ {"handle-playlist-add", (GCallback) do_playlist_add},
+ {"handle-playlist-enqueue-to-temp", (GCallback) do_playlist_enqueue_to_temp},
+ {"handle-playlist-ins-url-string", (GCallback) do_playlist_ins_url_string},
+ {"handle-playqueue-add", (GCallback) do_playqueue_add},
+ {"handle-playqueue-clear", (GCallback) do_playqueue_clear},
+ {"handle-playqueue-is-queued", (GCallback) do_playqueue_is_queued},
+ {"handle-playqueue-remove", (GCallback) do_playqueue_remove},
+ {"handle-position", (GCallback) do_position},
+ {"handle-queue-get-list-pos", (GCallback) do_queue_get_list_pos},
+ {"handle-queue-get-queue-pos", (GCallback) do_queue_get_queue_pos},
+ {"handle-quit", (GCallback) do_quit},
+ {"handle-repeat", (GCallback) do_repeat},
+ {"handle-reverse", (GCallback) do_reverse},
+ {"handle-seek", (GCallback) do_seek},
+ {"handle-set-active-playlist", (GCallback) do_set_active_playlist},
+ {"handle-set-active-playlist-name", (GCallback) do_set_active_playlist_name},
+ {"handle-set-eq", (GCallback) do_set_eq},
+ {"handle-set-eq-band", (GCallback) do_set_eq_band},
+ {"handle-set-eq-preamp", (GCallback) do_set_eq_preamp},
+ {"handle-set-volume", (GCallback) do_set_volume},
+ {"handle-show-about-box", (GCallback) do_show_about_box},
+ {"handle-show-filebrowser", (GCallback) do_show_filebrowser},
+ {"handle-show-jtf-box", (GCallback) do_show_jtf_box},
+ {"handle-show-main-win", (GCallback) do_show_main_win},
+ {"handle-show-prefs-box", (GCallback) do_show_prefs_box},
+ {"handle-shuffle", (GCallback) do_shuffle},
+ {"handle-song-filename", (GCallback) do_song_filename},
+ {"handle-song-frames", (GCallback) do_song_frames},
+ {"handle-song-length", (GCallback) do_song_length},
+ {"handle-song-title", (GCallback) do_song_title},
+ {"handle-song-tuple", (GCallback) do_song_tuple},
+ {"handle-status", (GCallback) do_status},
+ {"handle-stop", (GCallback) do_stop},
+ {"handle-stop-after", (GCallback) do_stop_after},
+ {"handle-stopped", (GCallback) do_stopped},
+ {"handle-time", (GCallback) do_time},
+ {"handle-toggle-auto-advance", (GCallback) do_toggle_auto_advance},
+ {"handle-toggle-repeat", (GCallback) do_toggle_repeat},
+ {"handle-toggle-shuffle", (GCallback) do_toggle_shuffle},
+ {"handle-toggle-stop-after", (GCallback) do_toggle_stop_after},
+ {"handle-version", (GCallback) do_version},
+ {"handle-volume", (GCallback) do_volume}
+};
+
+static GMainLoop * mainloop = nullptr;
+static unsigned owner_id = 0;
+
+static GDBusInterfaceSkeleton * skeleton = nullptr;
+
+static void name_acquired (GDBusConnection *, const char *, void *)
+{
+ AUDINFO ("Owned D-Bus name (org.atheme.audacious) on session bus.\n");
+
+ g_main_loop_quit (mainloop);
+}
+
+static void name_lost (GDBusConnection *, const char *, void *)
+{
+ AUDINFO ("Owning D-Bus name (org.atheme.audacious) failed, already taken?\n");
+
+ g_bus_unown_name (owner_id);
+ owner_id = 0;
+
+ g_main_loop_quit (mainloop);
+}
+
+StartupType dbus_server_init (void)
+{
+ GError * error = nullptr;
+ GDBusConnection * bus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, & error);
+ GMainContext * context;
+
+ if (! bus)
+ goto ERROR;
+
+ skeleton = (GDBusInterfaceSkeleton *) obj_audacious_skeleton_new ();
+
+ for (auto & handler : handlers)
+ g_signal_connect (skeleton, handler.signal, handler.callback, nullptr);
+
+ if (! g_dbus_interface_skeleton_export (skeleton, bus, "/org/atheme/audacious", & error))
+ goto ERROR;
+
+ context = g_main_context_new ();
+ g_main_context_push_thread_default (context);
+
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, "org.atheme.audacious",
+ (GBusNameOwnerFlags) 0, nullptr, name_acquired, name_lost, nullptr, nullptr);
+
+ mainloop = g_main_loop_new (context, true);
+ g_main_loop_run (mainloop);
+ g_main_loop_unref (mainloop);
+ mainloop = nullptr;
+
+ g_main_context_pop_thread_default (context);
+ g_main_context_unref (context);
+
+ if (owner_id)
+ return StartupType::Server;
+
+ dbus_server_cleanup ();
+ return StartupType::Client;
+
+ERROR:
+ if (error)
+ {
+ AUDERR ("D-Bus error: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ dbus_server_cleanup ();
+ return StartupType::Unknown;
+}
+
+void dbus_server_cleanup (void)
+{
+ if (owner_id)
+ {
+ g_bus_unown_name (owner_id);
+ owner_id = 0;
+ }
+
+ if (skeleton)
+ {
+ g_object_unref (skeleton);
+ skeleton = nullptr;
+ }
+}