1 /* audacious.c: conky support for audacious music player
3 * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 #include "audacious.h"
26 #ifndef AUDACIOUS_LEGACY
27 #include <glib-object.h>
28 #include <audacious/audctrl.h>
29 #include <audacious/dbus.h>
31 #include <audacious/beepctrl.h>
32 #define audacious_remote_is_running(x) \
33 xmms_remote_is_running(x)
34 #define audacious_remote_is_paused(x) \
35 xmms_remote_is_paused(x)
36 #define audacious_remote_is_playing(x) \
37 xmms_remote_is_playing(x)
38 #define audacious_remote_get_playlist_pos(x) \
39 xmms_remote_get_playlist_pos(x)
40 #define audacious_remote_get_playlist_title(x, y) \
41 xmms_remote_get_playlist_title(x, y)
42 #define audacious_remote_get_playlist_time(x, y) \
43 xmms_remote_get_playlist_time(x, y)
44 #define audacious_remote_get_output_time(x) \
45 xmms_remote_get_output_time(x)
46 #define audacious_remote_get_info(w, x, y, z) \
47 xmms_remote_get_info(w, x, y, z)
48 #define audacious_remote_get_playlist_file(x, y) \
49 xmms_remote_get_playlist_file(x, y)
50 #define audacious_remote_get_playlist_length(x) \
51 xmms_remote_get_playlist_length(x)
54 /* access to this item array is synchronized */
55 static audacious_t audacious_items;
57 /* -----------------------------------------
58 * Conky update function for audacious data.
59 * ----------------------------------------- */
60 void update_audacious(void)
62 /* The worker thread is updating audacious_items array asynchronously
63 * to the main conky thread.
64 * We merely copy the audacious_items array into the main thread's info
65 * structure when the main thread's update cycle fires. */
66 if (!info.audacious.p_timed_thread) {
67 if (create_audacious_thread() != 0) {
68 CRIT_ERR(NULL, NULL, "unable to create audacious thread!");
70 timed_thread_register(info.audacious.p_timed_thread,
71 &info.audacious.p_timed_thread);
74 timed_thread_lock(info.audacious.p_timed_thread);
75 memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items));
76 timed_thread_unlock(info.audacious.p_timed_thread);
79 /* ---------------------------------------------------------
80 * Create a worker thread for audacious media player status.
82 * Returns 0 on success, -1 on error.
83 * --------------------------------------------------------- */
84 int create_audacious_thread(void)
86 if (!info.audacious.p_timed_thread) {
87 info.audacious.p_timed_thread =
88 timed_thread_create(audacious_thread_func, NULL,
89 info.music_player_interval * 1000000);
92 if (!info.audacious.p_timed_thread
93 || timed_thread_run(info.audacious.p_timed_thread)) {
100 /* ---------------------------------------
101 * Destroy audacious player status thread.
103 * Returns 0 on success, -1 on error.
104 * --------------------------------------- */
105 int destroy_audacious_thread(void)
107 /* Is a worker is thread running? If not, no error. */
108 if (info.audacious.p_timed_thread) {
109 timed_thread_destroy(info.audacious.p_timed_thread,
110 &info.audacious.p_timed_thread);
116 /* ---------------------------------------------------
117 * Worker thread function for audacious data sampling.
118 * --------------------------------------------------- */
119 __attribute((noreturn))
120 void *audacious_thread_func(void *pvoid)
122 static audacious_t items;
123 gint playpos, frames, length;
124 gint rate, freq, chans, vol;
125 gchar *psong, *pfilename;
127 #ifndef AUDACIOUS_LEGACY
128 DBusGProxy *session = NULL;
129 DBusGConnection *connection = NULL;
134 pvoid = (void *) pvoid; /* avoid warning */
139 #ifndef AUDACIOUS_LEGACY
141 connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
143 CRIT_ERR(NULL, NULL, "unable to establish dbus connection");
145 session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
146 AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE);
148 CRIT_ERR(NULL, NULL, "unable to create dbus proxy");
150 #endif /* AUDACIOUS_LEGACY */
152 /* Loop until the main thread resets the runnable signal. */
156 if (!audacious_remote_is_running(session)) {
157 memset(&items, 0, sizeof(items));
158 strcpy(items[AUDACIOUS_STATUS], "Not running");
163 if (audacious_remote_is_paused(session)) {
164 strcpy(items[AUDACIOUS_STATUS], "Paused");
165 } else if (audacious_remote_is_playing(session)) {
166 strcpy(items[AUDACIOUS_STATUS], "Playing");
168 strcpy(items[AUDACIOUS_STATUS], "Stopped");
171 /* Current song title */
172 playpos = audacious_remote_get_playlist_pos(session);
173 psong = audacious_remote_get_playlist_title(session, playpos);
175 strncpy(items[AUDACIOUS_TITLE], psong,
176 sizeof(items[AUDACIOUS_TITLE]) - 1);
181 /* Current song length as MM:SS */
182 frames = audacious_remote_get_playlist_time(session, playpos);
183 length = frames / 1000;
184 snprintf(items[AUDACIOUS_LENGTH], sizeof(items[AUDACIOUS_LENGTH]) - 1,
185 "%d:%.2d", length / 60, length % 60);
187 /* Current song length in seconds */
188 snprintf(items[AUDACIOUS_LENGTH_SECONDS],
189 sizeof(items[AUDACIOUS_LENGTH_SECONDS]) - 1, "%d", length);
191 /* Current song position as MM:SS */
192 frames = audacious_remote_get_output_time(session);
193 length = frames / 1000;
194 snprintf(items[AUDACIOUS_POSITION],
195 sizeof(items[AUDACIOUS_POSITION]) - 1, "%d:%.2d", length / 60,
198 /* Current song position in seconds */
199 snprintf(items[AUDACIOUS_POSITION_SECONDS],
200 sizeof(items[AUDACIOUS_POSITION_SECONDS]) - 1, "%d", length);
202 /* Current song bitrate */
203 audacious_remote_get_info(session, &rate, &freq, &chans);
204 snprintf(items[AUDACIOUS_BITRATE], sizeof(items[AUDACIOUS_BITRATE]) - 1,
207 /* Current song frequency */
208 snprintf(items[AUDACIOUS_FREQUENCY],
209 sizeof(items[AUDACIOUS_FREQUENCY]) - 1, "%d", freq);
211 /* Current song channels */
212 snprintf(items[AUDACIOUS_CHANNELS],
213 sizeof(items[AUDACIOUS_CHANNELS]) - 1, "%d", chans);
215 /* Current song filename */
216 pfilename = audacious_remote_get_playlist_file(session, playpos);
218 strncpy(items[AUDACIOUS_FILENAME], pfilename,
219 sizeof(items[AUDACIOUS_FILENAME]) - 1);
224 /* Length of the Playlist (number of songs) */
225 length = audacious_remote_get_playlist_length(session);
226 snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],
227 sizeof(items[AUDACIOUS_PLAYLIST_LENGTH]) - 1, "%d", length);
229 /* Playlist position (index of song) */
230 snprintf(items[AUDACIOUS_PLAYLIST_POSITION],
231 sizeof(items[AUDACIOUS_PLAYLIST_POSITION]) - 1, "%d", playpos + 1);
233 vol = audacious_remote_get_main_volume(session);
234 snprintf(items[AUDACIOUS_MAIN_VOLUME],
235 sizeof(items[AUDACIOUS_MAIN_VOLUME]) - 1, "%d", vol);
238 /* Deliver the refreshed items array to audacious_items. */
239 timed_thread_lock(info.audacious.p_timed_thread);
240 memcpy(&audacious_items, items, sizeof(items));
241 timed_thread_unlock(info.audacious.p_timed_thread);
243 if (timed_thread_test(info.audacious.p_timed_thread, 0)) {
244 #ifndef AUDACIOUS_LEGACY
245 /* release reference to dbus proxy */
246 g_object_unref(session);
248 timed_thread_exit(info.audacious.p_timed_thread);