Added support for Audacious 1.4.0 via --enable-audacious=yes|no|legacy:
[monky] / src / audacious.c
1 /* $Id$ */
2
3 /*
4  * audacious.c:  conky support for audacious music player
5  *
6  * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net
7  * 
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.
12  *
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.
17  *
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
21  * USA.
22  *
23  */
24
25 #include <stdio.h>
26 #include <string.h>
27
28 #include <glib.h>
29 #ifndef AUDACIOUS_LEGACY
30 #include <glib-object.h>
31 #include <audacious/audctrl.h>
32 #include <audacious/dbus.h>
33 #else
34 #include <audacious/beepctrl.h>
35 #define audacious_remote_is_running(x)          xmms_remote_is_running(x) 
36 #define audacious_remote_is_paused(x)           xmms_remote_is_paused(x)
37 #define audacious_remote_is_playing(x)          xmms_remote_is_playing(x)
38 #define audacious_remote_get_playlist_pos(x)    xmms_remote_get_playlist_pos(x)
39 #define audacious_remote_get_playlist_title(x)  xmms_remote_get_playlist_title(x)
40 #define audacious_remote_get_playlist_time(x)   xmms_remote_get_playlist_time(x)
41 #define audacious_remote_get_output_time(x)     xmms_remote_get_output_time(x)
42 #define audacious_remote_get_info(x)            xmms_remote_get_info(x)
43 #define audacious_remote_get_playlist_file(x)   xmms_remote_get_playlist_file(x)
44 #define audacious_remote_get_playlist_length(x) xmms_remote_get_playlist_length(x)
45 #endif
46
47 #include "config.h"
48 #include "conky.h"
49 #include "audacious.h"
50 #include "timed_thread.h"
51
52 /* access to this item array is synchronized */
53 static audacious_t audacious_items;
54
55 /* -----------------------------------------
56  * Conky update function for audacious data.
57  * ----------------------------------------- */
58 void update_audacious(void)
59 {
60   /* 
61     The worker thread is updating audacious_items array asynchronously to the main 
62     conky thread.  We merely copy the audacious_items array into the main thread's 
63     info structure when the main thread's update cycle fires. 
64   */
65   if (!info.audacious.p_timed_thread)
66     return;
67
68   timed_thread_lock (info.audacious.p_timed_thread);
69   memcpy(&info.audacious.items,audacious_items,sizeof(audacious_items));
70   timed_thread_unlock (info.audacious.p_timed_thread);
71 }
72
73
74 /* ------------------------------------------------------------
75  * Create a worker thread for audacious media player status.
76  *
77  * Returns 0 on success, -1 on error. 
78  * ------------------------------------------------------------*/
79 int create_audacious_thread(void)
80 {
81   if (!info.audacious.p_timed_thread)
82     info.audacious.p_timed_thread = 
83       timed_thread_create (audacious_thread_func, NULL, info.music_player_interval * 1000000);
84
85   if (!info.audacious.p_timed_thread || timed_thread_run (info.audacious.p_timed_thread))
86     return (-1);
87
88   return 0;
89 }
90
91 /* ------------------------------------------------
92  * Destroy audacious player status thread. 
93  *
94  * Returns 0 on success, -1 on error.
95  * ------------------------------------------------ */
96 int destroy_audacious_thread(void)
97 {
98   /* Is a worker is thread running? If not, no error. */
99   if (!info.audacious.p_timed_thread)
100     return(0);
101
102   timed_thread_destroy (info.audacious.p_timed_thread, &info.audacious.p_timed_thread);
103
104   return 0;
105 }
106
107 /* ---------------------------------------------------
108  * Worker thread function for audacious data sampling.
109  * --------------------------------------------------- */ 
110 void *audacious_thread_func(void *pvoid)
111 {
112   static audacious_t items;
113   gint playpos,frames,length;
114   gint rate,freq,chans;
115   gchar *psong,*pfilename;
116
117 #ifndef AUDACIOUS_LEGACY
118   DBusGProxy *session = NULL;
119   DBusGConnection *connection = NULL;
120 #else
121   gint session;
122 #endif
123
124
125   pvoid=(void *)pvoid;  /* avoid warning */
126   session=0;
127   psong=NULL;
128   pfilename=NULL;
129
130 #ifndef AUDACIOUS_LEGACY
131   g_type_init ();
132   connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
133   if (!connection) {
134     CRIT_ERR ("unable to establish dbus connection");
135   }
136   session = dbus_g_proxy_new_for_name (connection, 
137                                        AUDACIOUS_DBUS_SERVICE,
138                                        AUDACIOUS_DBUS_PATH,
139                                        AUDACIOUS_DBUS_INTERFACE);
140   if (!session) {
141     CRIT_ERR ("unable to establish dbus proxy");
142   }
143 #endif /* AUDACIOUS_LEGACY */
144
145   /* Loop until the main thread sets the runnable signal to 0i via timed_thread_destroy. */
146   while (1) {
147
148     if (!audacious_remote_is_running (session)) 
149     {
150       memset(&items,0,sizeof(items));
151       strcpy(items[AUDACIOUS_STATUS],"Not running");
152         goto next_iter;
153     }
154
155     /* Player status */
156     if (audacious_remote_is_paused (session))
157       strcpy(items[AUDACIOUS_STATUS],"Paused");
158     else if (audacious_remote_is_playing (session))
159       strcpy(items[AUDACIOUS_STATUS],"Playing");
160     else
161       strcpy(items[AUDACIOUS_STATUS],"Stopped");
162
163     /* Current song title */
164     playpos = audacious_remote_get_playlist_pos (session);
165     psong = audacious_remote_get_playlist_title (session, playpos);
166     if (psong) 
167     {
168       strncpy(items[AUDACIOUS_TITLE],psong,sizeof(items[AUDACIOUS_TITLE])-1);
169       g_free (psong);
170       psong=NULL;
171     }
172
173     /* Current song length as MM:SS */
174     frames = audacious_remote_get_playlist_time (session,playpos);
175     length = frames / 1000;
176     snprintf(items[AUDACIOUS_LENGTH],sizeof(items[AUDACIOUS_LENGTH])-1, "%d:%.2d", length / 60, length % 60);
177
178     /* Current song length in seconds */
179     snprintf(items[AUDACIOUS_LENGTH_SECONDS],sizeof(items[AUDACIOUS_LENGTH_SECONDS])-1, "%d", length);
180
181     /* Current song position as MM:SS */
182     frames = audacious_remote_get_output_time (session);
183     length = frames / 1000;
184     snprintf(items[AUDACIOUS_POSITION],sizeof(items[AUDACIOUS_POSITION])-1,
185              "%d:%.2d", length / 60, length % 60);
186
187     /* Current song position in seconds */
188     snprintf(items[AUDACIOUS_POSITION_SECONDS],sizeof(items[AUDACIOUS_POSITION_SECONDS])-1, "%d", length);
189
190     /* Current song bitrate */
191     audacious_remote_get_info (session, &rate, &freq, &chans);
192     snprintf(items[AUDACIOUS_BITRATE],sizeof(items[AUDACIOUS_BITRATE])-1, "%d", rate);
193
194     /* Current song frequency */
195     snprintf(items[AUDACIOUS_FREQUENCY],sizeof(items[AUDACIOUS_FREQUENCY])-1, "%d", freq);
196
197     /* Current song channels */
198     snprintf(items[AUDACIOUS_CHANNELS],sizeof(items[AUDACIOUS_CHANNELS])-1, "%d", chans);
199
200     /* Current song filename */
201     pfilename = audacious_remote_get_playlist_file (session,playpos);
202     if (pfilename) 
203     {
204       strncpy(items[AUDACIOUS_FILENAME],pfilename,sizeof(items[AUDACIOUS_FILENAME])-1);
205       g_free (pfilename);
206       pfilename=NULL;
207     }
208
209     /* Length of the Playlist (number of songs) */
210     length = audacious_remote_get_playlist_length (session);
211     snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],sizeof(items[AUDACIOUS_PLAYLIST_LENGTH])-1, "%d", length);
212
213     /* Playlist position (index of song) */
214     snprintf(items[AUDACIOUS_PLAYLIST_POSITION],sizeof(items[AUDACIOUS_PLAYLIST_POSITION])-1, 
215            "%d", playpos+1);
216
217 next_iter:
218
219     /* Deliver the refreshed items array to audacious_items. */
220     timed_thread_lock (info.audacious.p_timed_thread);
221     memcpy(&audacious_items,items,sizeof(items));
222     timed_thread_unlock (info.audacious.p_timed_thread);
223
224     if (timed_thread_test (info.audacious.p_timed_thread))
225       timed_thread_exit (info.audacious.p_timed_thread);
226   }
227 }