1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
2 * vim: ts=4 sw=4 noet ai cindent syntax=c
4 * audacious.c: conky support for audacious music player
6 * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
28 #include "audacious.h"
31 #ifndef AUDACIOUS_LEGACY
32 #include <glib-object.h>
33 #include <audacious/audctrl.h>
34 #include <audacious/dbus.h>
36 #include <audacious/beepctrl.h>
37 #define audacious_remote_is_running(x) \
38 xmms_remote_is_running(x)
39 #define audacious_remote_is_paused(x) \
40 xmms_remote_is_paused(x)
41 #define audacious_remote_is_playing(x) \
42 xmms_remote_is_playing(x)
43 #define audacious_remote_get_playlist_pos(x) \
44 xmms_remote_get_playlist_pos(x)
45 #define audacious_remote_get_playlist_title(x, y) \
46 xmms_remote_get_playlist_title(x, y)
47 #define audacious_remote_get_playlist_time(x, y) \
48 xmms_remote_get_playlist_time(x, y)
49 #define audacious_remote_get_output_time(x) \
50 xmms_remote_get_output_time(x)
51 #define audacious_remote_get_info(w, x, y, z) \
52 xmms_remote_get_info(w, x, y, z)
53 #define audacious_remote_get_playlist_file(x, y) \
54 xmms_remote_get_playlist_file(x, y)
55 #define audacious_remote_get_playlist_length(x) \
56 xmms_remote_get_playlist_length(x)
59 /* access to this item array is synchronized */
60 static audacious_t audacious_items;
62 /* -----------------------------------------
63 * Conky update function for audacious data.
64 * ----------------------------------------- */
65 void update_audacious(void)
67 /* The worker thread is updating audacious_items array asynchronously
68 * to the main conky thread.
69 * We merely copy the audacious_items array into the main thread's info
70 * structure when the main thread's update cycle fires. */
71 if (!info.audacious.p_timed_thread) {
72 if (create_audacious_thread() != 0) {
73 CRIT_ERR(NULL, NULL, "unable to create audacious thread!");
75 timed_thread_register(info.audacious.p_timed_thread,
76 &info.audacious.p_timed_thread);
79 timed_thread_lock(info.audacious.p_timed_thread);
80 memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items));
81 timed_thread_unlock(info.audacious.p_timed_thread);
84 /* ---------------------------------------------------------
85 * Create a worker thread for audacious media player status.
87 * Returns 0 on success, -1 on error.
88 * --------------------------------------------------------- */
89 int create_audacious_thread(void)
91 if (!info.audacious.p_timed_thread) {
92 info.audacious.p_timed_thread =
93 timed_thread_create(audacious_thread_func, NULL,
94 info.music_player_interval * 1000000);
97 if (!info.audacious.p_timed_thread
98 || timed_thread_run(info.audacious.p_timed_thread)) {
105 /* ---------------------------------------
106 * Destroy audacious player status thread.
108 * Returns 0 on success, -1 on error.
109 * --------------------------------------- */
110 int destroy_audacious_thread(void)
112 /* Is a worker is thread running? If not, no error. */
113 if (info.audacious.p_timed_thread) {
114 timed_thread_destroy(info.audacious.p_timed_thread,
115 &info.audacious.p_timed_thread);
121 /* ---------------------------------------------------
122 * Worker thread function for audacious data sampling.
123 * --------------------------------------------------- */
124 __attribute((noreturn))
125 void *audacious_thread_func(void *pvoid)
127 static audacious_t items;
128 gint playpos, frames, length;
129 gint rate, freq, chans, vol;
130 gchar *psong, *pfilename;
132 #ifndef AUDACIOUS_LEGACY
133 DBusGProxy *session = NULL;
134 DBusGConnection *connection = NULL;
139 pvoid = (void *) pvoid; /* avoid warning */
144 #ifndef AUDACIOUS_LEGACY
146 connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
148 CRIT_ERR(NULL, NULL, "unable to establish dbus connection");
150 session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
151 AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE);
153 CRIT_ERR(NULL, NULL, "unable to create dbus proxy");
155 #endif /* AUDACIOUS_LEGACY */
157 /* Loop until the main thread resets the runnable signal. */
161 if (!audacious_remote_is_running(session)) {
162 memset(&items, 0, sizeof(items));
163 strcpy(items[AUDACIOUS_STATUS], "Not running");
168 if (audacious_remote_is_paused(session)) {
169 strcpy(items[AUDACIOUS_STATUS], "Paused");
170 } else if (audacious_remote_is_playing(session)) {
171 strcpy(items[AUDACIOUS_STATUS], "Playing");
173 strcpy(items[AUDACIOUS_STATUS], "Stopped");
176 /* Current song title */
177 playpos = audacious_remote_get_playlist_pos(session);
178 psong = audacious_remote_get_playlist_title(session, playpos);
180 strncpy(items[AUDACIOUS_TITLE], psong,
181 sizeof(items[AUDACIOUS_TITLE]) - 1);
186 /* Current song length as MM:SS */
187 frames = audacious_remote_get_playlist_time(session, playpos);
188 length = frames / 1000;
189 snprintf(items[AUDACIOUS_LENGTH], sizeof(items[AUDACIOUS_LENGTH]) - 1,
190 "%d:%.2d", length / 60, length % 60);
192 /* Current song length in seconds */
193 snprintf(items[AUDACIOUS_LENGTH_SECONDS],
194 sizeof(items[AUDACIOUS_LENGTH_SECONDS]) - 1, "%d", length);
196 /* Current song position as MM:SS */
197 frames = audacious_remote_get_output_time(session);
198 length = frames / 1000;
199 snprintf(items[AUDACIOUS_POSITION],
200 sizeof(items[AUDACIOUS_POSITION]) - 1, "%d:%.2d", length / 60,
203 /* Current song position in seconds */
204 snprintf(items[AUDACIOUS_POSITION_SECONDS],
205 sizeof(items[AUDACIOUS_POSITION_SECONDS]) - 1, "%d", length);
207 /* Current song bitrate */
208 audacious_remote_get_info(session, &rate, &freq, &chans);
209 snprintf(items[AUDACIOUS_BITRATE], sizeof(items[AUDACIOUS_BITRATE]) - 1,
212 /* Current song frequency */
213 snprintf(items[AUDACIOUS_FREQUENCY],
214 sizeof(items[AUDACIOUS_FREQUENCY]) - 1, "%d", freq);
216 /* Current song channels */
217 snprintf(items[AUDACIOUS_CHANNELS],
218 sizeof(items[AUDACIOUS_CHANNELS]) - 1, "%d", chans);
220 /* Current song filename */
221 pfilename = audacious_remote_get_playlist_file(session, playpos);
223 strncpy(items[AUDACIOUS_FILENAME], pfilename,
224 sizeof(items[AUDACIOUS_FILENAME]) - 1);
229 /* Length of the Playlist (number of songs) */
230 length = audacious_remote_get_playlist_length(session);
231 snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],
232 sizeof(items[AUDACIOUS_PLAYLIST_LENGTH]) - 1, "%d", length);
234 /* Playlist position (index of song) */
235 snprintf(items[AUDACIOUS_PLAYLIST_POSITION],
236 sizeof(items[AUDACIOUS_PLAYLIST_POSITION]) - 1, "%d", playpos + 1);
238 vol = audacious_remote_get_main_volume(session);
239 snprintf(items[AUDACIOUS_MAIN_VOLUME],
240 sizeof(items[AUDACIOUS_MAIN_VOLUME]) - 1, "%d", vol);
243 /* Deliver the refreshed items array to audacious_items. */
244 timed_thread_lock(info.audacious.p_timed_thread);
245 memcpy(&audacious_items, items, sizeof(items));
246 timed_thread_unlock(info.audacious.p_timed_thread);
248 if (timed_thread_test(info.audacious.p_timed_thread, 0)) {
249 #ifndef AUDACIOUS_LEGACY
250 /* release reference to dbus proxy */
251 g_object_unref(session);
253 timed_thread_exit(info.audacious.p_timed_thread);