1 /* -------------------------------------------------------------------------
2 * audacious.c: conky support for audacious music player
4 * Copyright (C) 2005 Philip Kovacs kovacsp3@comcast.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 USA
21 * --------------------------------------------------------------------------- */
30 #include <audacious/beepctrl.h>
34 #include "audacious.h"
36 /* access to this item array is synchronized */
37 static audacious_t audacious_items;
39 /* -----------------------------------------
40 * Conky update function for audacious data.
41 * ----------------------------------------- */
42 void update_audacious(void)
45 The worker thread is updating audacious_items array asynchronously to the main
46 conky thread. We merely copy the audacious_items array into the main thread's
47 info structure when the main thread's update cycle fires.
49 pthread_mutex_lock(&info.audacious.item_mutex);
50 memcpy(&info.audacious.items,audacious_items,sizeof(audacious_items));
51 pthread_mutex_unlock(&info.audacious.item_mutex);
55 /* ------------------------------------------------------------
56 * Create a worker thread for audacious media player status.
58 * Returns 0 on success, -1 on error.
59 * ------------------------------------------------------------*/
60 int create_audacious_thread(void)
62 /* Is a worker is thread already running? */
63 if (info.audacious.thread)
66 /* Joinable thread for audacious activity */
67 pthread_attr_init(&info.audacious.thread_attr);
68 pthread_attr_setdetachstate(&info.audacious.thread_attr, PTHREAD_CREATE_JOINABLE);
70 pthread_mutex_init(&info.audacious.item_mutex, NULL);
71 pthread_mutex_init(&info.audacious.runnable_mutex, NULL);
72 /* Init runnable condition for worker thread */
73 pthread_cond_init(&info.audacious.runnable_cond, NULL);
74 if (pthread_create(&info.audacious.thread, &info.audacious.thread_attr, audacious_thread_func, NULL))
80 /* ------------------------------------------------
81 * Destroy audacious player status thread.
83 * Returns 0 on success, -1 on error.
84 * ------------------------------------------------ */
85 int destroy_audacious_thread(void)
87 /* Is a worker is thread running? If not, no error. */
88 if (!info.audacious.thread)
91 /* Signal audacious thread to terminate */
92 pthread_mutex_lock (&info.audacious.runnable_mutex);
93 pthread_cond_signal (&info.audacious.runnable_cond);
94 pthread_mutex_unlock (&info.audacious.runnable_mutex);
96 /* Destroy thread attribute and wait for thread */
97 pthread_attr_destroy(&info.audacious.thread_attr);
98 if (pthread_join(info.audacious.thread, NULL))
101 /* Destroy mutexes and cond */
102 pthread_mutex_destroy(&info.audacious.item_mutex);
103 pthread_mutex_destroy(&info.audacious.runnable_mutex);
104 pthread_cond_destroy(&info.audacious.runnable_cond);
106 info.audacious.thread=(pthread_t)0;
110 /* ---------------------------------------------------
111 * Worker thread function for audacious data sampling.
112 * --------------------------------------------------- */
113 void *audacious_thread_func(void *pvoid)
116 static audacious_t items;
117 gint session,playpos,frames,length;
118 gint rate,freq,chans;
119 gchar *psong,*pfilename;
120 struct timespec abstime;
122 pvoid=(void *)pvoid; /* avoid warning */
127 /* Loop until the main thread sets the runnable signal to 0. */
130 for (;;) { /* convenience loop so we can break below */
132 if (!xmms_remote_is_running (session)) {
133 memset(&items,0,sizeof(items));
134 strcpy(items[AUDACIOUS_STATUS],"Not running");
139 if (xmms_remote_is_paused (session))
140 strcpy(items[AUDACIOUS_STATUS],"Paused");
141 else if (xmms_remote_is_playing (session))
142 strcpy(items[AUDACIOUS_STATUS],"Playing");
144 strcpy(items[AUDACIOUS_STATUS],"Stopped");
146 /* Current song title */
147 playpos = xmms_remote_get_playlist_pos (session);
148 psong = xmms_remote_get_playlist_title (session, playpos);
150 strncpy(items[AUDACIOUS_TITLE],psong,sizeof(items[AUDACIOUS_TITLE])-1);
155 /* Current song length as MM:SS */
156 frames = xmms_remote_get_playlist_time (session,playpos);
157 length = frames / 1000;
158 snprintf(items[AUDACIOUS_LENGTH],sizeof(items[AUDACIOUS_LENGTH])-1,
159 "%d:%.2d", length / 60, length % 60);
161 /* Current song length in seconds */
162 snprintf(items[AUDACIOUS_LENGTH_SECONDS],sizeof(items[AUDACIOUS_LENGTH_SECONDS])-1,
165 /* Current song position as MM:SS */
166 frames = xmms_remote_get_output_time (session);
167 length = frames / 1000;
168 snprintf(items[AUDACIOUS_POSITION],sizeof(items[AUDACIOUS_POSITION])-1,
169 "%d:%.2d", length / 60, length % 60);
171 /* Current song position in seconds */
172 snprintf(items[AUDACIOUS_POSITION_SECONDS],sizeof(items[AUDACIOUS_POSITION_SECONDS])-1,
175 /* Current song bitrate */
176 xmms_remote_get_info (session, &rate, &freq, &chans);
177 snprintf(items[AUDACIOUS_BITRATE],sizeof(items[AUDACIOUS_BITRATE])-1, "%d", rate);
179 /* Current song frequency */
180 snprintf(items[AUDACIOUS_FREQUENCY],sizeof(items[AUDACIOUS_FREQUENCY])-1, "%d", freq);
182 /* Current song channels */
183 snprintf(items[AUDACIOUS_CHANNELS],sizeof(items[AUDACIOUS_CHANNELS])-1, "%d", chans);
185 /* Current song filename */
186 pfilename = xmms_remote_get_playlist_file (session,playpos);
188 strncpy(items[AUDACIOUS_FILENAME],pfilename,sizeof(items[AUDACIOUS_FILENAME])-1);
193 /* Length of the Playlist (number of songs) */
194 length = xmms_remote_get_playlist_length (session);
195 snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],sizeof(items[AUDACIOUS_PLAYLIST_LENGTH])-1, "%d", length);
197 /* Playlist position (index of song) */
198 snprintf(items[AUDACIOUS_PLAYLIST_POSITION],sizeof(items[AUDACIOUS_PLAYLIST_POSITION])-1, "%d", playpos+1);
203 /* Deliver the refreshed items array to audacious_items. */
204 pthread_mutex_lock(&info.audacious.item_mutex);
205 memcpy(&audacious_items,items,sizeof(items));
206 pthread_mutex_unlock(&info.audacious.item_mutex);
208 /* Get absolute time 1 sec in the future. */
209 clock_gettime (CLOCK_REALTIME, &abstime);
212 /* Wait for a second before looping or until signalled to stop. */
213 if (pthread_cond_timedwait (&info.audacious.runnable_cond,
214 &info.audacious.runnable_mutex,
215 &abstime) != ETIMEDOUT)
218 (void) pthread_mutex_unlock (&info.audacious.runnable_mutex);