diff options
Diffstat (limited to 'src/audacious/dbus-server.c')
-rw-r--r-- | src/audacious/dbus-server.c | 779 |
1 files changed, 779 insertions, 0 deletions
diff --git a/src/audacious/dbus-server.c b/src/audacious/dbus-server.c new file mode 100644 index 0000000..af55f20 --- /dev/null +++ b/src/audacious/dbus-server.c @@ -0,0 +1,779 @@ +/* + * 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 <stdio.h> + +#include <libaudgui/libaudgui.h> + +#include "aud-dbus.h" +#include "drct.h" +#include "main.h" +#include "misc.h" +#include "playlist.h" +#include "ui_preferences.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 * strv_to_index (const char * const * strv) +{ + Index * index = index_new (); + while (* strv) + index_insert (index, -1, str_get (* strv ++)); + + return index; +} + +static bool_t do_add (Obj * obj, Invoc * invoc, const char * file) +{ + playlist_entry_insert (playlist_get_active (), -1, file, NULL, FALSE); + FINISH (add); + return TRUE; +} + +static bool_t do_add_list (Obj * obj, Invoc * invoc, const char * const * filenames) +{ + playlist_entry_insert_batch (playlist_get_active (), -1, + strv_to_index (filenames), NULL, FALSE); + FINISH (add_list); + return TRUE; +} + +static bool_t do_add_url (Obj * obj, Invoc * invoc, const char * url) +{ + playlist_entry_insert (playlist_get_active (), -1, url, NULL, FALSE); + FINISH (add_url); + return TRUE; +} + +static bool_t do_advance (Obj * obj, Invoc * invoc) +{ + drct_pl_next (); + FINISH (advance); + return TRUE; +} + +static bool_t do_auto_advance (Obj * obj, Invoc * invoc) +{ + FINISH2 (auto_advance, ! get_bool (NULL, "no_playlist_advance")); + return TRUE; +} + +static bool_t do_balance (Obj * obj, Invoc * invoc) +{ + int balance; + drct_get_volume_balance (& balance); + FINISH2 (balance, balance); + return TRUE; +} + +static bool_t do_clear (Obj * obj, Invoc * invoc) +{ + int playlist = playlist_get_active (); + playlist_entry_delete (playlist, 0, playlist_entry_count (playlist)); + FINISH (clear); + return TRUE; +} + +static bool_t do_delete (Obj * obj, Invoc * invoc, unsigned pos) +{ + playlist_entry_delete (playlist_get_active (), pos, 1); + FINISH (delete); + return TRUE; +} + +static bool_t do_delete_active_playlist (Obj * obj, Invoc * invoc) +{ + playlist_delete (playlist_get_active ()); + FINISH (delete_active_playlist); + return TRUE; +} + +static bool_t do_eject (Obj * obj, Invoc * invoc) +{ + if (! headless_mode ()) + audgui_run_filebrowser (TRUE); + + FINISH (eject); + return TRUE; +} + +static bool_t do_equalizer_activate (Obj * obj, Invoc * invoc, bool_t active) +{ + set_bool (NULL, "equalizer_active", active); + FINISH (equalizer_activate); + return TRUE; +} + +static bool_t do_get_active_playlist (Obj * obj, Invoc * invoc) +{ + FINISH2 (get_active_playlist, playlist_get_active ()); + return TRUE; +} + +static bool_t do_get_active_playlist_name (Obj * obj, Invoc * invoc) +{ + char * title = playlist_get_title (playlist_get_active ()); + FINISH2 (get_active_playlist_name, title ? title : ""); + str_unref (title); + return TRUE; +} + +static bool_t do_get_eq (Obj * obj, Invoc * invoc) +{ + double preamp = get_double (NULL, "equalizer_preamp"); + double bands[AUD_EQUALIZER_NBANDS]; + eq_get_bands (bands); + + GVariant * var = g_variant_new_fixed_array (G_VARIANT_TYPE_DOUBLE, bands, + AUD_EQUALIZER_NBANDS, sizeof (double)); + FINISH2 (get_eq, preamp, var); + return TRUE; +} + +static bool_t do_get_eq_band (Obj * obj, Invoc * invoc, int band) +{ + FINISH2 (get_eq_band, eq_get_band (band)); + return TRUE; +} + +static bool_t do_get_eq_preamp (Obj * obj, Invoc * invoc) +{ + FINISH2 (get_eq_preamp, get_double (NULL, "equalizer_preamp")); + return TRUE; +} + +static bool_t do_get_info (Obj * obj, Invoc * invoc) +{ + int bitrate, samplerate, channels; + drct_get_info (& bitrate, & samplerate, & channels); + FINISH2 (get_info, bitrate, samplerate, channels); + return TRUE; +} + +static bool_t do_get_playqueue_length (Obj * obj, Invoc * invoc) +{ + FINISH2 (get_playqueue_length, playlist_queue_count (playlist_get_active ())); + return TRUE; +} + +static bool_t do_get_tuple_fields (Obj * obj, Invoc * invoc) +{ + const char * fields[TUPLE_FIELDS + 1]; + + for (int i = 0; i < TUPLE_FIELDS; i ++) + fields[i] = tuple_field_get_name (i); + + fields[TUPLE_FIELDS] = NULL; + + FINISH2 (get_tuple_fields, fields); + return TRUE; +} + +static bool_t do_info (Obj * obj, Invoc * invoc) +{ + int bitrate, samplerate, channels; + drct_get_info (& bitrate, & samplerate, & channels); + FINISH2 (info, bitrate, samplerate, channels); + return TRUE; +} + +static bool_t do_jump (Obj * obj, Invoc * invoc, unsigned pos) +{ + playlist_set_position (playlist_get_active (), pos); + FINISH (jump); + return TRUE; +} + +static bool_t do_length (Obj * obj, Invoc * invoc) +{ + FINISH2 (length, playlist_entry_count (playlist_get_active ())); + return TRUE; +} + +static bool_t do_main_win_visible (Obj * obj, Invoc * invoc) +{ + FINISH2 (main_win_visible, ! headless_mode () && interface_is_shown ()); + return TRUE; +} + +static bool_t do_new_playlist (Obj * obj, Invoc * invoc) +{ + playlist_insert (-1); + playlist_set_active (playlist_count () - 1); + FINISH (new_playlist); + return TRUE; +} + +static bool_t do_number_of_playlists (Obj * obj, Invoc * invoc) +{ + FINISH2 (number_of_playlists, playlist_count ()); + return TRUE; +} + +static bool_t do_open_list (Obj * obj, Invoc * invoc, const char * const * filenames) +{ + drct_pl_open_list (strv_to_index (filenames)); + FINISH (open_list); + return TRUE; +} + +static bool_t do_open_list_to_temp (Obj * obj, Invoc * invoc, const char * const * filenames) +{ + drct_pl_open_temp_list (strv_to_index (filenames)); + FINISH (open_list_to_temp); + return TRUE; +} + +static bool_t do_pause (Obj * obj, Invoc * invoc) +{ + drct_pause (); + FINISH (pause); + return TRUE; +} + +static bool_t do_paused (Obj * obj, Invoc * invoc) +{ + FINISH2 (paused, drct_get_paused ()); + return TRUE; +} + +static bool_t do_play (Obj * obj, Invoc * invoc) +{ + drct_play (); + FINISH (play); + return TRUE; +} + +static bool_t do_play_active_playlist (Obj * obj, Invoc * invoc) +{ + drct_play_playlist (playlist_get_active ()); + FINISH (play_active_playlist); + return TRUE; +} + +static bool_t do_play_pause (Obj * obj, Invoc * invoc) +{ + drct_play_pause (); + FINISH (play_pause); + return TRUE; +} + +static bool_t do_playing (Obj * obj, Invoc * invoc) +{ + FINISH2 (playing, drct_get_playing ()); + return TRUE; +} + +static bool_t do_playlist_add (Obj * obj, Invoc * invoc, const char * list) +{ + playlist_entry_insert (playlist_get_active (), -1, list, NULL, FALSE); + FINISH (playlist_add); + return TRUE; +} + +static bool_t do_playlist_enqueue_to_temp (Obj * obj, Invoc * invoc, const char * url) +{ + drct_pl_open_temp (url); + FINISH (playlist_enqueue_to_temp); + return TRUE; +} + +static bool_t do_playlist_ins_url_string (Obj * obj, Invoc * invoc, const char * url, int pos) +{ + playlist_entry_insert (playlist_get_active (), pos, url, NULL, FALSE); + FINISH (playlist_ins_url_string); + return TRUE; +} + +static bool_t do_playqueue_add (Obj * obj, Invoc * invoc, int pos) +{ + playlist_queue_insert (playlist_get_active (), -1, pos); + FINISH (playqueue_add); + return TRUE; +} + +static bool_t do_playqueue_clear (Obj * obj, Invoc * invoc) +{ + int playlist = playlist_get_active (); + playlist_queue_delete (playlist, 0, playlist_queue_count (playlist)); + FINISH (playqueue_clear); + return TRUE; +} + +static bool_t do_playqueue_is_queued (Obj * obj, Invoc * invoc, int pos) +{ + bool_t queued = (playlist_queue_find_entry (playlist_get_active (), pos) >= 0); + FINISH2 (playqueue_is_queued, queued); + return TRUE; +} + +static bool_t do_playqueue_remove (Obj * obj, Invoc * invoc, int pos) +{ + int playlist = playlist_get_active (); + int qpos = playlist_queue_find_entry (playlist, pos); + + if (qpos >= 0) + playlist_queue_delete (playlist, qpos, 1); + + FINISH (playqueue_remove); + return TRUE; +} + +static bool_t do_position (Obj * obj, Invoc * invoc) +{ + FINISH2 (position, playlist_get_position (playlist_get_active ())); + return TRUE; +} + +static bool_t do_queue_get_list_pos (Obj * obj, Invoc * invoc, unsigned qpos) +{ + FINISH2 (queue_get_list_pos, playlist_queue_get_entry (playlist_get_active (), qpos)); + return TRUE; +} + +static bool_t do_queue_get_queue_pos (Obj * obj, Invoc * invoc, unsigned pos) +{ + FINISH2 (queue_get_queue_pos, playlist_queue_find_entry (playlist_get_active (), pos)); + return TRUE; +} + +static bool_t do_quit (Obj * obj, Invoc * invoc) +{ + drct_quit (); + FINISH (quit); + return TRUE; +} + +static bool_t do_repeat (Obj * obj, Invoc * invoc) +{ + FINISH2 (repeat, get_bool (NULL, "repeat")); + return TRUE; +} + +static bool_t do_reverse (Obj * obj, Invoc * invoc) +{ + drct_pl_prev (); + FINISH (reverse); + return TRUE; +} + +static bool_t do_seek (Obj * obj, Invoc * invoc, unsigned pos) +{ + drct_seek (pos); + FINISH (seek); + return TRUE; +} + +static bool_t do_set_active_playlist (Obj * obj, Invoc * invoc, int playlist) +{ + playlist_set_active (playlist); + FINISH (set_active_playlist); + return TRUE; +} + +static bool_t do_set_active_playlist_name (Obj * obj, Invoc * invoc, const char * title) +{ + playlist_set_title (playlist_get_active (), title); + FINISH (set_active_playlist_name); + return TRUE; +} + +static bool_t 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 = g_variant_get_fixed_array (var, & nbands, sizeof (double)); + + if (nbands != AUD_EQUALIZER_NBANDS) + return FALSE; + + set_double (NULL, "equalizer_preamp", preamp); + eq_set_bands (bands); + FINISH (set_eq); + return TRUE; +} + +static bool_t do_set_eq_band (Obj * obj, Invoc * invoc, int band, double value) +{ + eq_set_band (band, value); + FINISH (set_eq_band); + return TRUE; +} + +static bool_t do_set_eq_preamp (Obj * obj, Invoc * invoc, double preamp) +{ + set_double (NULL, "equalizer_preamp", preamp); + FINISH (set_eq_preamp); + return TRUE; +} + +static bool_t do_set_volume (Obj * obj, Invoc * invoc, int vl, int vr) +{ + drct_set_volume (vl, vr); + FINISH (set_volume); + return TRUE; +} + +static bool_t do_show_about_box (Obj * obj, Invoc * invoc, bool_t show) +{ + if (! headless_mode ()) + { + if (show) + audgui_show_about_window (); + else + audgui_hide_about_window (); + } + + FINISH (show_about_box); + return TRUE; +} + +static bool_t do_show_filebrowser (Obj * obj, Invoc * invoc, bool_t show) +{ + if (! headless_mode ()) + { + if (show) + audgui_run_filebrowser (FALSE); + else + audgui_hide_filebrowser (); + } + + FINISH (show_filebrowser); + return TRUE; +} + +static bool_t do_show_jtf_box (Obj * obj, Invoc * invoc, bool_t show) +{ + if (! headless_mode ()) + { + if (show) + audgui_jump_to_track (); + else + audgui_jump_to_track_hide (); + } + + FINISH (show_jtf_box); + return TRUE; +} + +static bool_t do_show_main_win (Obj * obj, Invoc * invoc, bool_t show) +{ + if (! headless_mode ()) + interface_show (show); + + FINISH (show_main_win); + return TRUE; +} + +static bool_t do_show_prefs_box (Obj * obj, Invoc * invoc, bool_t show) +{ + if (! headless_mode ()) + { + if (show) + show_prefs_window (); + else + hide_prefs_window (); + } + + FINISH (show_prefs_box); + return TRUE; +} + +static bool_t do_shuffle (Obj * obj, Invoc * invoc) +{ + FINISH2 (shuffle, get_bool (NULL, "shuffle")); + return TRUE; +} + +static bool_t do_song_filename (Obj * obj, Invoc * invoc, unsigned pos) +{ + char * filename = playlist_entry_get_filename (playlist_get_active (), pos); + FINISH2 (song_filename, filename ? filename : ""); + str_unref (filename); + return TRUE; +} + +static bool_t do_song_frames (Obj * obj, Invoc * invoc, unsigned pos) +{ + FINISH2 (song_frames, playlist_entry_get_length (playlist_get_active (), pos, FALSE)); + return TRUE; +} + +static bool_t do_song_length (Obj * obj, Invoc * invoc, unsigned pos) +{ + int length = playlist_entry_get_length (playlist_get_active (), pos, FALSE); + FINISH2 (song_length, length >= 0 ? length / 1000 : -1); + return TRUE; +} + +static bool_t do_song_title (Obj * obj, Invoc * invoc, unsigned pos) +{ + char * title = playlist_entry_get_title (playlist_get_active (), pos, FALSE); + FINISH2 (song_title, title ? title : ""); + str_unref (title); + return TRUE; +} + +static bool_t do_song_tuple (Obj * obj, Invoc * invoc, unsigned pos, const char * key) +{ + int field = tuple_field_by_name (key); + Tuple * tuple = NULL; + GVariant * var = NULL; + + if (field >= 0) + tuple = playlist_entry_get_tuple (playlist_get_active (), pos, FALSE); + + if (tuple) + { + char * str; + + switch (tuple_get_value_type (tuple, field)) + { + case TUPLE_STRING: + str = tuple_get_str (tuple, field); + var = g_variant_new_string (str); + str_unref (str); + break; + + case TUPLE_INT: + var = g_variant_new_int32 (tuple_get_int (tuple, field)); + break; + + default: + break; + } + + tuple_unref (tuple); + } + + if (! var) + var = g_variant_new_string (""); + + FINISH2 (song_tuple, g_variant_new_variant (var)); + return TRUE; +} + +static bool_t do_status (Obj * obj, Invoc * invoc) +{ + const char * status = "stopped"; + if (drct_get_playing ()) + status = drct_get_paused () ? "paused" : "playing"; + + FINISH2 (status, status); + return TRUE; +} + +static bool_t do_stop (Obj * obj, Invoc * invoc) +{ + drct_stop (); + FINISH (stop); + return TRUE; +} + +static bool_t do_stop_after (Obj * obj, Invoc * invoc) +{ + FINISH2 (stop_after, get_bool (NULL, "stop_after_current_song")); + return TRUE; +} + +static bool_t do_stopped (Obj * obj, Invoc * invoc) +{ + FINISH2 (stopped, ! drct_get_playing ()); + return TRUE; +} + +static bool_t do_time (Obj * obj, Invoc * invoc) +{ + FINISH2 (time, drct_get_time ()); + return TRUE; +} + +static bool_t do_toggle_auto_advance (Obj * obj, Invoc * invoc) +{ + set_bool (NULL, "no_playlist_advance", ! get_bool (NULL, "no_playlist_advance")); + FINISH (toggle_auto_advance); + return TRUE; +} + +static bool_t do_toggle_repeat (Obj * obj, Invoc * invoc) +{ + set_bool (NULL, "repeat", ! get_bool (NULL, "repeat")); + FINISH (toggle_repeat); + return TRUE; +} + +static bool_t do_toggle_shuffle (Obj * obj, Invoc * invoc) +{ + set_bool (NULL, "shuffle", ! get_bool (NULL, "shuffle")); + FINISH (toggle_shuffle); + return TRUE; +} + +static bool_t do_toggle_stop_after (Obj * obj, Invoc * invoc) +{ + set_bool (NULL, "stop_after_current_song", ! get_bool (NULL, "stop_after_current_song")); + FINISH (toggle_stop_after); + return TRUE; +} + +static bool_t do_version (Obj * obj, Invoc * invoc) +{ + FINISH2 (version, VERSION); + return TRUE; +} + +static bool_t do_volume (Obj * obj, Invoc * invoc) +{ + int left, right; + drct_get_volume (& left, & right); + FINISH2 (volume, left, 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 GDBusInterfaceSkeleton * skeleton = NULL; + +void dbus_server_init (void) +{ + GError * error = NULL; + GDBusConnection * bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, & error); + + if (! bus) + goto ERROR; + + g_bus_own_name_on_connection (bus, "org.atheme.audacious", 0, NULL, NULL, NULL, NULL); + + skeleton = (GDBusInterfaceSkeleton *) obj_audacious_skeleton_new (); + + for (int i = 0; i < ARRAY_LEN (handlers); i ++) + g_signal_connect (skeleton, handlers[i].signal, handlers[i].callback, NULL); + + if (! g_dbus_interface_skeleton_export (skeleton, bus, "/org/atheme/audacious", & error)) + goto ERROR; + + return; + +ERROR: + if (error) + { + fprintf (stderr, "D-Bus error: %s\n", error->message); + g_error_free (error); + } +} + +void dbus_server_cleanup (void) +{ + if (skeleton) + { + g_object_unref (skeleton); + skeleton = NULL; + } +} |