From ad8dfc0853084e631cbe8a4578ed7cd63829c057 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 25 Mar 2011 15:06:26 +0100 Subject: [PATCH] Make audacious vars use the new update system --- src/audacious.cc | 297 +++++++++++++++++++++-------------------------- src/audacious.h | 40 ------- src/conky.h | 7 -- src/core.cc | 37 +++--- 4 files changed, 150 insertions(+), 231 deletions(-) diff --git a/src/audacious.cc b/src/audacious.cc index b310d503..88de9b0f 100644 --- a/src/audacious.cc +++ b/src/audacious.cc @@ -23,10 +23,14 @@ */ #include + +#include + #include "conky.h" #include "logging.h" #include "audacious.h" #include +#include "update-cb.hh" #include #ifdef NEW_AUDACIOUS_FOUND @@ -57,231 +61,190 @@ xmms_remote_get_playlist_length(x) #endif /* NEW_AUDACIOUS_FOUND */ -/* access to this item array is synchronized */ -static audacious_t audacious_items; +namespace { -/* ----------------------------------------- - * Conky update function for audacious data. - * ----------------------------------------- */ -int update_audacious(void) -{ - /* The worker thread is updating audacious_items array asynchronously - * to the main conky thread. - * We merely copy the audacious_items array into the main thread's info - * structure when the main thread's update cycle fires. */ - if (!info.audacious.p_timed_thread) { - if (create_audacious_thread() != 0) { - CRIT_ERR(NULL, NULL, "unable to create audacious thread!"); - } - } + enum aud_status { AS_NOT_RUNNING, AS_PAUSED, AS_PLAYING, AS_STOPPED }; + const char * const as_message[] = { "Not running", "Paused", "Playing", "Stopped" }; - std::lock_guard lock(info.audacious.p_timed_thread->mutex()); - memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items)); - return 0; -} + struct aud_result { + std::string title; + std::string filename; + int length; // in ms + int position; // in ms + int bitrate; + int frequency; + int channels; + int playlist_length; + int playlist_position; + int main_volume; + aud_status status; -/* --------------------------------------------------------- - * Create a worker thread for audacious media player status. - * - * Returns 0 on success, -1 on error. - * --------------------------------------------------------- */ -int create_audacious_thread(void) -{ - if (!info.audacious.p_timed_thread) { - info.audacious.p_timed_thread = - timed_thread::create(std::bind(audacious_thread_func, std::placeholders::_1), - std::chrono::microseconds(long(music_player_interval.get(*state) * 1000000))); - } + aud_result() + : length(0), position(0), bitrate(0), frequency(0), channels(0), playlist_length(0), + playlist_position(0), main_volume(0), status(AS_NOT_RUNNING) + {} + }; - if (!info.audacious.p_timed_thread) { - return -1; - } - - return 0; -} - -/* --------------------------------------- - * Destroy audacious player status thread. - * - * Returns 0 on success, -1 on error. - * --------------------------------------- */ -int destroy_audacious_thread(void) -{ - /* Is a worker is thread running? If not, no error. */ - if (info.audacious.p_timed_thread) { - info.audacious.p_timed_thread.reset(); - } - - return 0; -} - -/* --------------------------------------------------- - * Worker thread function for audacious data sampling. - * --------------------------------------------------- */ -void audacious_thread_func(thread_handle &handle) -{ - static audacious_t items; - gint playpos, frames, length; - gint rate, freq, chans, vol; - gchar *psong, *pfilename; + class audacious_cb: public conky::callback { + typedef conky::callback Base; #ifdef NEW_AUDACIOUS_FOUND - DBusGProxy *session = NULL; - DBusGConnection *connection = NULL; + DBusGProxy *session; #else - gint session; + gint session; #endif - session = 0; - psong = NULL; - pfilename = NULL; + protected: + virtual void work(); + + public: + audacious_cb(uint32_t period) + : Base(period, false, Tuple()) + { +#ifdef NEW_AUDACIOUS_FOUND + g_type_init(); + DBusGConnection *connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + if (!connection) + throw std::runtime_error("unable to establish dbus connection"); + + session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, + AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); + if (!session) + throw std::runtime_error("unable to create dbus proxy"); +#else + session = 0; +#endif /* NEW_AUDACIOUS_FOUND */ + } #ifdef NEW_AUDACIOUS_FOUND - g_type_init(); - connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - if (!connection) { - CRIT_ERR(NULL, NULL, "unable to establish dbus connection"); - } - session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, - AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE); - if (!session) { - CRIT_ERR(NULL, NULL, "unable to create dbus proxy"); - } -#endif /* NEW_AUDACIOUS_FOUND */ + ~audacious_cb() + { + /* release reference to dbus proxy */ + g_object_unref(session); + } +#endif + }; - /* Loop until the main thread resets the runnable signal. */ - while (1) { + /* --------------------------------------------------- + * Worker thread function for audacious data sampling. + * --------------------------------------------------- */ + void audacious_cb::work() + { + aud_result tmp; + gchar *psong, *pfilename; + psong = NULL; + pfilename = NULL; do { if (!audacious_remote_is_running(session)) { - memset(&items, 0, sizeof(items)); - strcpy(items[AUDACIOUS_STATUS], "Not running"); + tmp.status = AS_NOT_RUNNING; break; } /* Player status */ if (audacious_remote_is_paused(session)) { - strcpy(items[AUDACIOUS_STATUS], "Paused"); + tmp.status = AS_PAUSED; } else if (audacious_remote_is_playing(session)) { - strcpy(items[AUDACIOUS_STATUS], "Playing"); + tmp.status = AS_PLAYING; } else { - strcpy(items[AUDACIOUS_STATUS], "Stopped"); + tmp.status = AS_STOPPED; } /* Current song title */ - playpos = audacious_remote_get_playlist_pos(session); - psong = audacious_remote_get_playlist_title(session, playpos); + tmp.playlist_position = audacious_remote_get_playlist_pos(session); + psong = audacious_remote_get_playlist_title(session, tmp.playlist_position); if (psong) { - strncpy(items[AUDACIOUS_TITLE], psong, - sizeof(items[AUDACIOUS_TITLE]) - 1); + tmp.title = psong; g_free(psong); - psong = NULL; } - /* Current song length as MM:SS */ - frames = audacious_remote_get_playlist_time(session, playpos); - length = frames / 1000; - snprintf(items[AUDACIOUS_LENGTH], sizeof(items[AUDACIOUS_LENGTH]) - 1, - "%d:%.2d", length / 60, length % 60); + /* Current song length */ + tmp.length = audacious_remote_get_playlist_time(session, tmp.playlist_position); - /* Current song length in seconds */ - snprintf(items[AUDACIOUS_LENGTH_SECONDS], - sizeof(items[AUDACIOUS_LENGTH_SECONDS]) - 1, "%d", length); + /* Current song position */ + tmp.position = audacious_remote_get_output_time(session); - /* Current song position as MM:SS */ - frames = audacious_remote_get_output_time(session); - length = frames / 1000; - snprintf(items[AUDACIOUS_POSITION], - sizeof(items[AUDACIOUS_POSITION]) - 1, "%d:%.2d", length / 60, - length % 60); - - /* Current song position in seconds */ - snprintf(items[AUDACIOUS_POSITION_SECONDS], - sizeof(items[AUDACIOUS_POSITION_SECONDS]) - 1, "%d", length); - - /* Current song bitrate */ - audacious_remote_get_info(session, &rate, &freq, &chans); - snprintf(items[AUDACIOUS_BITRATE], sizeof(items[AUDACIOUS_BITRATE]) - 1, - "%d", rate); - - /* Current song frequency */ - snprintf(items[AUDACIOUS_FREQUENCY], - sizeof(items[AUDACIOUS_FREQUENCY]) - 1, "%d", freq); - - /* Current song channels */ - snprintf(items[AUDACIOUS_CHANNELS], - sizeof(items[AUDACIOUS_CHANNELS]) - 1, "%d", chans); + /* Current song bitrate, frequency, channels */ + audacious_remote_get_info(session, &tmp.bitrate, &tmp.frequency, &tmp.channels); /* Current song filename */ - pfilename = audacious_remote_get_playlist_file(session, playpos); + pfilename = audacious_remote_get_playlist_file(session, tmp.playlist_position); if (pfilename) { - strncpy(items[AUDACIOUS_FILENAME], pfilename, - sizeof(items[AUDACIOUS_FILENAME]) - 1); + tmp.filename = pfilename; g_free(pfilename); - pfilename = NULL; } /* Length of the Playlist (number of songs) */ - length = audacious_remote_get_playlist_length(session); - snprintf(items[AUDACIOUS_PLAYLIST_LENGTH], - sizeof(items[AUDACIOUS_PLAYLIST_LENGTH]) - 1, "%d", length); + tmp.playlist_length = audacious_remote_get_playlist_length(session); - /* Playlist position (index of song) */ - snprintf(items[AUDACIOUS_PLAYLIST_POSITION], - sizeof(items[AUDACIOUS_PLAYLIST_POSITION]) - 1, "%d", playpos + 1); /* Main volume */ - vol = audacious_remote_get_main_volume(session); - snprintf(items[AUDACIOUS_MAIN_VOLUME], - sizeof(items[AUDACIOUS_MAIN_VOLUME]) - 1, "%d", vol); - + tmp.main_volume = audacious_remote_get_main_volume(session); } while (0); { /* Deliver the refreshed items array to audacious_items. */ - std::lock_guard lock(handle.mutex()); - memcpy(&audacious_items, items, sizeof(items)); + std::lock_guard lock(result_mutex); + result = tmp; } + } - if (handle.test(0)) { -#ifdef NEW_AUDACIOUS_FOUND - /* release reference to dbus proxy */ - g_object_unref(session); -#endif - return; - } + aud_result get_res() + { + uint32_t period = std::max( + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l + ); + return conky::register_cb(period)->get_result_copy(); } } -void print_audacious_title(struct text_object *, char *p, int p_max_size) +void print_audacious_status(struct text_object *, char *p, int p_max_size) { - snprintf(p, info.audacious.max_title_len > 0 - ? info.audacious.max_title_len : p_max_size, "%s", - info.audacious.items[AUDACIOUS_TITLE]); + const aud_result &res = get_res(); + snprintf(p, p_max_size, "%s", as_message[res.status]); +} + +void print_audacious_title(struct text_object *obj, char *p, int p_max_size) +{ + snprintf(p, std::min(obj->data.i, p_max_size), "%s", get_res().title.c_str()); +} + +void print_audacious_filename(struct text_object *obj, char *p, int p_max_size) +{ + snprintf(p, std::min(obj->data.i, p_max_size), "%s", get_res().filename.c_str()); } double audacious_barval(struct text_object *) { - - return atof(info.audacious.items[AUDACIOUS_POSITION_SECONDS]) / - atof(info.audacious.items[AUDACIOUS_LENGTH_SECONDS]); + const aud_result &res = get_res(); + return (double)res.position / res.length; } -#define AUDACIOUS_PRINT_GENERATOR(name, idx) \ +#define AUDACIOUS_TIME_GENERATOR(name) \ void print_audacious_##name(struct text_object *, char *p, int p_max_size) \ { \ - snprintf(p, p_max_size, "%s", info.audacious.items[AUDACIOUS_##idx]); \ + const aud_result &res = get_res(); \ + int sec = res.name / 1000; \ + snprintf(p, p_max_size, "%d:%.2d", sec/60, sec%60); \ +} \ + \ +void print_audacious_##name##_seconds(struct text_object *, char *p, int p_max_size) \ +{ \ + snprintf(p, p_max_size, "%d", get_res().name); \ } -AUDACIOUS_PRINT_GENERATOR(status, STATUS) -AUDACIOUS_PRINT_GENERATOR(length, LENGTH) -AUDACIOUS_PRINT_GENERATOR(length_seconds, LENGTH_SECONDS) -AUDACIOUS_PRINT_GENERATOR(position, POSITION) -AUDACIOUS_PRINT_GENERATOR(position_seconds, POSITION_SECONDS) -AUDACIOUS_PRINT_GENERATOR(bitrate, BITRATE) -AUDACIOUS_PRINT_GENERATOR(frequency, FREQUENCY) -AUDACIOUS_PRINT_GENERATOR(channels, CHANNELS) -AUDACIOUS_PRINT_GENERATOR(filename, FILENAME) -AUDACIOUS_PRINT_GENERATOR(playlist_length, PLAYLIST_LENGTH) -AUDACIOUS_PRINT_GENERATOR(playlist_position, PLAYLIST_POSITION) -AUDACIOUS_PRINT_GENERATOR(main_volume, MAIN_VOLUME) +AUDACIOUS_TIME_GENERATOR(length) +AUDACIOUS_TIME_GENERATOR(position) + +#define AUDACIOUS_INT_GENERATOR(name, offset) \ +void print_audacious_##name(struct text_object *, char *p, int p_max_size) \ +{ \ + snprintf(p, p_max_size, "%d", get_res().name + offset); \ +} + +AUDACIOUS_INT_GENERATOR(bitrate, 0) +AUDACIOUS_INT_GENERATOR(frequency, 0) +AUDACIOUS_INT_GENERATOR(channels, 0) +AUDACIOUS_INT_GENERATOR(playlist_length, 0) +AUDACIOUS_INT_GENERATOR(playlist_position, 1) +AUDACIOUS_INT_GENERATOR(main_volume, 0) #undef AUDACIOUS_PRINT_GENERATOR diff --git a/src/audacious.h b/src/audacious.h index c7667716..c66e9e04 100644 --- a/src/audacious.h +++ b/src/audacious.h @@ -25,46 +25,6 @@ #ifndef AUDACIOUS_H #define AUDACIOUS_H -#include "timed-thread.h" - -enum _audacious_items { - AUDACIOUS_STATUS = 0, - AUDACIOUS_TITLE, - AUDACIOUS_LENGTH, - AUDACIOUS_LENGTH_SECONDS, - AUDACIOUS_POSITION, - AUDACIOUS_POSITION_SECONDS, - AUDACIOUS_BITRATE, - AUDACIOUS_FREQUENCY, - AUDACIOUS_CHANNELS, - AUDACIOUS_FILENAME, - AUDACIOUS_PLAYLIST_LENGTH, - AUDACIOUS_PLAYLIST_POSITION, - AUDACIOUS_MAIN_VOLUME -}; - -/* 12 slots for the audacious values */ -typedef char audacious_t[13][128]; - -/* type for data exchange with main thread */ -typedef struct audacious_s { - audacious_t items; /* e.g. items[BUILD_AUDACIOUS_STATUS] */ - int max_title_len; /* e.g. ${audacious_title 50} */ - timed_thread_ptr p_timed_thread; -} audacious_s; - -/* create a worker thread for audacious media player status */ -int create_audacious_thread(void); - -/* destroy audacious media player worker thread */ -int destroy_audacious_thread(void); - -/* Service routine for the conky main thread */ -int update_audacious(void); - -/* Thread functions */ -void audacious_thread_func(thread_handle &handle); - void print_audacious_status(struct text_object *, char *, int); void print_audacious_title(struct text_object *, char *, int); void print_audacious_length(struct text_object *, char *, int); diff --git a/src/conky.h b/src/conky.h index bb8e7fe9..c996f9de 100644 --- a/src/conky.h +++ b/src/conky.h @@ -94,10 +94,6 @@ struct text_object; #include "mysql.h" #endif /* BUILD_MYSQL */ -#ifdef BUILD_AUDACIOUS -#include "audacious.h" -#endif /* BUILD_AUDACIOUS */ - #ifdef BUILD_WEATHER_XOAP #ifndef BUILD_WEATHER_METAR #error "BUILD_WEATHER_METAR needs to be defined if XOAP is defined" @@ -201,9 +197,6 @@ struct information { #ifdef BUILD_XMMS2 struct xmms2_s xmms2; #endif /* BUILD_XMMS2 */ -#ifdef BUILD_AUDACIOUS - audacious_s audacious; -#endif #ifdef BUILD_BMPX struct bmpx_s bmpx; #endif /* BUILD_BMPX */ diff --git a/src/core.cc b/src/core.cc index 7d8ae428..1410fa35 100644 --- a/src/core.cc +++ b/src/core.cc @@ -93,6 +93,9 @@ #ifdef BUILD_RSS #include "rss.h" #endif /* BUILD_RSS */ +#ifdef BUILD_AUDACIOUS +#include "audacious.h" +#endif /* check for OS and include appropriate headers */ #if defined(__linux__) @@ -1567,39 +1570,39 @@ struct text_object *construct_text_object(char *s, const char *arg, long obj->callbacks.free = &free_xmms2; #endif /* BUILD_XMMS2 */ #ifdef BUILD_AUDACIOUS - END OBJ(audacious_status, &update_audacious) + END OBJ(audacious_status, 0) obj->callbacks.print = &print_audacious_status; - END OBJ_ARG(audacious_title, &update_audacious, "audacious_title needs an argument") - sscanf(arg, "%d", &info.audacious.max_title_len); - if (info.audacious.max_title_len > 0) { - info.audacious.max_title_len++; + END OBJ_ARG(audacious_title, 0, "audacious_title needs an argument") + sscanf(arg, "%d", &obj->data.i); + if (obj->data.i > 0) { + ++ obj->data.i; } else { CRIT_ERR(obj, free_at_crash, "audacious_title: invalid length argument"); } obj->callbacks.print = &print_audacious_title; - END OBJ(audacious_length, &update_audacious) + END OBJ(audacious_length, 0) obj->callbacks.print = &print_audacious_length; - END OBJ(audacious_length_seconds, &update_audacious) + END OBJ(audacious_length_seconds, 0) obj->callbacks.print = &print_audacious_length_seconds; - END OBJ(audacious_position, &update_audacious) + END OBJ(audacious_position, 0) obj->callbacks.print = &print_audacious_position; - END OBJ(audacious_position_seconds, &update_audacious) + END OBJ(audacious_position_seconds, 0) obj->callbacks.print = &print_audacious_position_seconds; - END OBJ(audacious_bitrate, &update_audacious) + END OBJ(audacious_bitrate, 0) obj->callbacks.print = &print_audacious_bitrate; - END OBJ(audacious_frequency, &update_audacious) + END OBJ(audacious_frequency, 0) obj->callbacks.print = &print_audacious_frequency; - END OBJ(audacious_channels, &update_audacious) + END OBJ(audacious_channels, 0) obj->callbacks.print = &print_audacious_channels; - END OBJ(audacious_filename, &update_audacious) + END OBJ(audacious_filename, 0) obj->callbacks.print = &print_audacious_filename; - END OBJ(audacious_playlist_length, &update_audacious) + END OBJ(audacious_playlist_length, 0) obj->callbacks.print = &print_audacious_playlist_length; - END OBJ(audacious_playlist_position, &update_audacious) + END OBJ(audacious_playlist_position, 0) obj->callbacks.print = &print_audacious_playlist_position; - END OBJ(audacious_main_volume, &update_audacious) + END OBJ(audacious_main_volume, 0) obj->callbacks.print = &print_audacious_main_volume; - END OBJ(audacious_bar, &update_audacious) + END OBJ(audacious_bar, 0) scan_bar(obj, arg, 1); obj->callbacks.barval = &audacious_barval; #endif /* BUILD_AUDACIOUS */