3 /* audacious.c: conky support for audacious music player
5 * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
27 #ifndef AUDACIOUS_LEGACY
28 #include <glib-object.h>
29 #include <audacious/audctrl.h>
30 #include <audacious/dbus.h>
32 #include <audacious/beepctrl.h>
33 #define audacious_remote_is_running(x) \
34 xmms_remote_is_running(x)
35 #define audacious_remote_is_paused(x) \
36 xmms_remote_is_paused(x)
37 #define audacious_remote_is_playing(x) \
38 xmms_remote_is_playing(x)
39 #define audacious_remote_get_playlist_pos(x) \
40 xmms_remote_get_playlist_pos(x)
41 #define audacious_remote_get_playlist_title(x, y) \
42 xmms_remote_get_playlist_title(x, y)
43 #define audacious_remote_get_playlist_time(x, y) \
44 xmms_remote_get_playlist_time(x, y)
45 #define audacious_remote_get_output_time(x) \
46 xmms_remote_get_output_time(x)
47 #define audacious_remote_get_info(w, x, y, z) \
48 xmms_remote_get_info(w, x, y, z)
49 #define audacious_remote_get_playlist_file(x, y) \
50 xmms_remote_get_playlist_file(x, y)
51 #define audacious_remote_get_playlist_length(x) \
52 xmms_remote_get_playlist_length(x)
56 #include "audacious.h"
58 /* access to this item array is synchronized */
59 static audacious_t audacious_items;
61 /* -----------------------------------------
62 * Conky update function for audacious data.
63 * ----------------------------------------- */
64 void update_audacious(void)
66 /* The worker thread is updating audacious_items array asynchronously
67 * to the main conky thread.
68 * We merely copy the audacious_items array into the main thread's info
69 * structure when the main thread's update cycle fires. */
70 if (!info.audacious.p_timed_thread) {
71 if (create_audacious_thread() != 0) {
72 CRIT_ERR("unable to create audacious thread!");
74 timed_thread_register(info.audacious.p_timed_thread,
75 &info.audacious.p_timed_thread);
78 timed_thread_lock(info.audacious.p_timed_thread);
79 memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items));
80 timed_thread_unlock(info.audacious.p_timed_thread);
83 /* ---------------------------------------------------------
84 * Create a worker thread for audacious media player status.
86 * Returns 0 on success, -1 on error.
87 * --------------------------------------------------------- */
88 int create_audacious_thread(void)
90 if (!info.audacious.p_timed_thread) {
91 info.audacious.p_timed_thread =
92 timed_thread_create(audacious_thread_func, NULL,
93 info.music_player_interval * 1000000);
96 if (!info.audacious.p_timed_thread
97 || timed_thread_run(info.audacious.p_timed_thread)) {
104 /* ---------------------------------------
105 * Destroy audacious player status thread.
107 * Returns 0 on success, -1 on error.
108 * --------------------------------------- */
109 int destroy_audacious_thread(void)
111 /* Is a worker is thread running? If not, no error. */
112 if (!info.audacious.p_timed_thread) {
116 timed_thread_destroy(info.audacious.p_timed_thread,
117 &info.audacious.p_timed_thread);
122 /* ---------------------------------------------------
123 * Worker thread function for audacious data sampling.
124 * --------------------------------------------------- */
125 __attribute((noreturn))
126 void *audacious_thread_func(void *pvoid)
128 static audacious_t items;
129 gint playpos, frames, length;
130 gint rate, freq, chans;
131 gchar *psong, *pfilename;
133 #ifndef AUDACIOUS_LEGACY
134 DBusGProxy *session = NULL;
135 DBusGConnection *connection = NULL;
140 pvoid = (void *) pvoid; /* avoid warning */
145 #ifndef AUDACIOUS_LEGACY
147 connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
149 CRIT_ERR("unable to establish dbus connection");
151 session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
152 AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE);
154 CRIT_ERR("unable to create dbus proxy");
156 #endif /* AUDACIOUS_LEGACY */
158 /* Loop until the main thread resets the runnable signal. */
162 if (!audacious_remote_is_running(session)) {
163 memset(&items, 0, sizeof(items));
164 strcpy(items[AUDACIOUS_STATUS], "Not running");
169 if (audacious_remote_is_paused(session)) {
170 strcpy(items[AUDACIOUS_STATUS], "Paused");
171 } else if (audacious_remote_is_playing(session)) {
172 strcpy(items[AUDACIOUS_STATUS], "Playing");
174 strcpy(items[AUDACIOUS_STATUS], "Stopped");
177 /* Current song title */
178 playpos = audacious_remote_get_playlist_pos(session);
179 psong = audacious_remote_get_playlist_title(session, playpos);
181 strncpy(items[AUDACIOUS_TITLE], psong,
182 sizeof(items[AUDACIOUS_TITLE]) - 1);
187 /* Current song length as MM:SS */
188 frames = audacious_remote_get_playlist_time(session, playpos);
189 length = frames / 1000;
190 snprintf(items[AUDACIOUS_LENGTH], sizeof(items[AUDACIOUS_LENGTH]) - 1,
191 "%d:%.2d", length / 60, length % 60);
193 /* Current song length in seconds */
194 snprintf(items[AUDACIOUS_LENGTH_SECONDS],
195 sizeof(items[AUDACIOUS_LENGTH_SECONDS]) - 1, "%d", length);
197 /* Current song position as MM:SS */
198 frames = audacious_remote_get_output_time(session);
199 length = frames / 1000;
200 snprintf(items[AUDACIOUS_POSITION],
201 sizeof(items[AUDACIOUS_POSITION]) - 1, "%d:%.2d", length / 60,
204 /* Current song position in seconds */
205 snprintf(items[AUDACIOUS_POSITION_SECONDS],
206 sizeof(items[AUDACIOUS_POSITION_SECONDS]) - 1, "%d", length);
208 /* Current song bitrate */
209 audacious_remote_get_info(session, &rate, &freq, &chans);
210 snprintf(items[AUDACIOUS_BITRATE], sizeof(items[AUDACIOUS_BITRATE]) - 1,
213 /* Current song frequency */
214 snprintf(items[AUDACIOUS_FREQUENCY],
215 sizeof(items[AUDACIOUS_FREQUENCY]) - 1, "%d", freq);
217 /* Current song channels */
218 snprintf(items[AUDACIOUS_CHANNELS],
219 sizeof(items[AUDACIOUS_CHANNELS]) - 1, "%d", chans);
221 /* Current song filename */
222 pfilename = audacious_remote_get_playlist_file(session, playpos);
224 strncpy(items[AUDACIOUS_FILENAME], pfilename,
225 sizeof(items[AUDACIOUS_FILENAME]) - 1);
230 /* Length of the Playlist (number of songs) */
231 length = audacious_remote_get_playlist_length(session);
232 snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],
233 sizeof(items[AUDACIOUS_PLAYLIST_LENGTH]) - 1, "%d", length);
235 /* Playlist position (index of song) */
236 snprintf(items[AUDACIOUS_PLAYLIST_POSITION],
237 sizeof(items[AUDACIOUS_PLAYLIST_POSITION]) - 1, "%d", playpos + 1);
239 /* Deliver the refreshed items array to audacious_items. */
240 timed_thread_lock(info.audacious.p_timed_thread);
241 memcpy(&audacious_items, items, sizeof(items));
242 timed_thread_unlock(info.audacious.p_timed_thread);
244 if (timed_thread_test(info.audacious.p_timed_thread)) {
245 #ifndef AUDACIOUS_LEGACY
246 /* release reference to dbus proxy */
247 g_object_unref(session);
249 timed_thread_exit(info.audacious.p_timed_thread);