Small build fix & zero playtime and progress bars when XMMS2 playback is stopped.
[monky] / src / xmms2.c
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
3  *
4  * Conky, a system monitor, based on torsmo
5  *
6  * Any original torsmo code is licensed under the BSD license
7  *
8  * All code written since the fork of torsmo is licensed under the GPL
9  *
10  * Please see COPYING for details
11  *
12  * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al.
13  *      (see AUTHORS)
14  * All rights reserved.
15  *
16  * This program is free software: you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  * You should have received a copy of the GNU General Public License
26  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27  *
28  */
29
30 #include "conky.h"
31
32 xmmsc_connection_t *xmms2_conn;
33
34 #define CONN_INIT       0
35 #define CONN_OK         1
36 #define CONN_NO         2
37
38 static void xmms_alloc(struct information *ptr)
39 {
40
41         if (ptr->xmms2.artist == NULL) {
42                 ptr->xmms2.artist = malloc(text_buffer_size);
43         }
44
45         if (ptr->xmms2.album == NULL) {
46                 ptr->xmms2.album = malloc(text_buffer_size);
47         }
48
49         if (ptr->xmms2.title == NULL) {
50                 ptr->xmms2.title = malloc(text_buffer_size);
51         }
52
53         if (ptr->xmms2.genre == NULL) {
54                 ptr->xmms2.genre = malloc(text_buffer_size);
55         }
56
57         if (ptr->xmms2.comment == NULL) {
58                 ptr->xmms2.comment = malloc(text_buffer_size);
59         }
60
61         if (ptr->xmms2.url == NULL) {
62                 ptr->xmms2.url = malloc(text_buffer_size);
63         }
64
65         if (ptr->xmms2.date == NULL) {
66                 ptr->xmms2.date = malloc(text_buffer_size);
67         }
68
69         ptr->xmms2.artist[0] = '\0';
70         ptr->xmms2.album[0] = '\0';
71         ptr->xmms2.title[0] = '\0';
72         ptr->xmms2.genre[0] = '\0';
73         ptr->xmms2.comment[0] = '\0';
74         ptr->xmms2.url[0] = '\0';
75         ptr->xmms2.date[0] = '\0';
76
77         ptr->xmms2.tracknr = 0;
78         ptr->xmms2.id = 0;
79         ptr->xmms2.bitrate = 0;
80         ptr->xmms2.duration = 0;
81         ptr->xmms2.elapsed = 0;
82         ptr->xmms2.size = 0;
83         ptr->xmms2.progress = 0;
84         ptr->xmms2.timesplayed = -1;
85 }
86
87 void connection_lost(void *p)
88 {
89         struct information *ptr = p;
90         ptr->xmms2.conn_state = CONN_NO;
91
92         fprintf(stderr,"XMMS2 connection failed. %s\n", xmmsc_get_last_error(xmms2_conn));
93
94         xmms_alloc(ptr);
95         strncpy(ptr->xmms2.status, "Disocnnected", text_buffer_size - 1);
96         ptr->xmms2.playlist[0] = '\0';
97         ptr->xmms2.id = 0;
98 }
99
100
101 int handle_curent_id(xmmsv_t *value, void *p)
102 {
103         struct information *ptr = p;
104         xmmsv_t *val, *infos, *dict_entry;
105         xmmsc_result_t *res;
106         const char *errbuf;
107         int current_id;
108
109         const char *charval;
110         int intval;
111
112
113         if (xmmsv_get_error(value, &errbuf)) {
114                 fprintf(stderr,"XMMS2 server error. %s\n", errbuf);
115                 return TRUE;
116         }
117
118         if (xmmsv_get_int(value, &current_id) && current_id > 0) {
119
120                 res = xmmsc_medialib_get_info(xmms2_conn, current_id);
121                 xmmsc_result_wait(res);
122                 val = xmmsc_result_get_value(res);
123
124                 if (xmmsv_get_error(val, &errbuf)) {
125                         fprintf(stderr,"XMMS2 server error. %s\n", errbuf);
126                         return TRUE;
127                 }
128
129                 xmms_alloc(ptr);
130
131
132                 ptr->xmms2.id = current_id;
133
134                 infos = xmmsv_propdict_to_dict(val, NULL);
135
136                 if (xmmsv_dict_get(infos, "artist", &dict_entry) && xmmsv_get_string(dict_entry, &charval))
137                         strncpy(ptr->xmms2.artist, charval, text_buffer_size - 1);
138
139                 if (xmmsv_dict_get(infos, "title", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) 
140                         strncpy(ptr->xmms2.title, charval, text_buffer_size - 1);
141
142                 if (xmmsv_dict_get(infos, "album", &dict_entry) && xmmsv_get_string(dict_entry, &charval)) 
143                         strncpy(ptr->xmms2.album, charval, text_buffer_size - 1);
144
145                 if (xmmsv_dict_get(infos, "genre", &dict_entry) && xmmsv_get_string(dict_entry, &charval))
146                         strncpy(ptr->xmms2.genre, charval, text_buffer_size - 1);
147
148                 if (xmmsv_dict_get(infos, "comment", &dict_entry) && xmmsv_get_string(dict_entry, &charval))
149                         strncpy(ptr->xmms2.comment, charval, text_buffer_size - 1);
150
151                 if (xmmsv_dict_get(infos, "url", &dict_entry) && xmmsv_get_string(dict_entry, &charval))
152                         strncpy(ptr->xmms2.url, charval, text_buffer_size - 1);
153
154                 if (xmmsv_dict_get(infos, "date", &dict_entry) && xmmsv_get_string(dict_entry, &charval))
155                         strncpy(ptr->xmms2.date, charval, text_buffer_size - 1);
156
157
158
159                 if (xmmsv_dict_get(infos, "tracknr", &dict_entry) && xmmsv_get_int(dict_entry, &intval))
160                         ptr->xmms2.tracknr = intval;
161
162                 if (xmmsv_dict_get(infos, "duration", &dict_entry) && xmmsv_get_int(dict_entry, &intval))
163                         ptr->xmms2.duration = intval;
164
165                 if (xmmsv_dict_get(infos, "bitrate", &dict_entry) && xmmsv_get_int(dict_entry, &intval))
166                         ptr->xmms2.bitrate = intval / 1000;
167
168                 if (xmmsv_dict_get(infos, "size", &dict_entry) && xmmsv_get_int(dict_entry, &intval))
169                         ptr->xmms2.size = (float) intval / 1048576;
170
171                 if (xmmsv_dict_get(infos, "timesplayed", &dict_entry) && xmmsv_get_int(dict_entry, &intval))
172                         ptr->xmms2.timesplayed = intval;
173
174
175                 xmmsv_unref(infos);
176                 xmmsc_result_unref(res);
177         }
178         return TRUE;
179 }
180
181 int handle_playtime(xmmsv_t *value, void *p)
182 {
183         struct information *ptr = p;
184         int play_time;
185         const char *errbuf;
186
187         if (xmmsv_get_error(value, &errbuf)) {
188                 fprintf(stderr,"XMMS2 server error. %s\n", errbuf);
189                 return TRUE;
190         }
191
192         if (xmmsv_get_int(value, &play_time)) {
193                 ptr->xmms2.elapsed = play_time;
194                 ptr->xmms2.progress = (float) play_time / ptr->xmms2.duration;
195         }
196
197         return TRUE;
198 }
199
200 int handle_playback_state_change(xmmsv_t *value, void *p)
201 {
202         struct information *ptr = p;
203         int pb_state = 0;
204         const char *errbuf;
205
206         if (xmmsv_get_error(value, &errbuf)) {
207                 fprintf(stderr,"XMMS2 server error. %s\n", errbuf);
208                 return TRUE;
209         }
210
211         if (ptr->xmms2.status == NULL) {
212                 ptr->xmms2.status = malloc(text_buffer_size);
213                 ptr->xmms2.status[0] = '\0';
214         }
215
216         if (xmmsv_get_int(value, &pb_state)) {
217                 switch (pb_state) {
218                         case XMMS_PLAYBACK_STATUS_PLAY:
219                                 strncpy(ptr->xmms2.status, "Playing", text_buffer_size - 1);
220                                 break;
221                         case XMMS_PLAYBACK_STATUS_PAUSE:
222                                 strncpy(ptr->xmms2.status, "Paused", text_buffer_size - 1);
223                                 break;
224                         case XMMS_PLAYBACK_STATUS_STOP:
225                                 strncpy(ptr->xmms2.status, "Stopped", text_buffer_size - 1);
226                                 ptr->xmms2.elapsed = ptr->xmms2.progress = ptr->xmms2.percent = 0;
227                                 break;
228                         default:
229                                 strncpy(ptr->xmms2.status, "Unknown", text_buffer_size - 1);
230                 }
231         }
232         return TRUE;
233 }
234
235 int handle_playlist_loaded(xmmsv_t *value, void *p) 
236 {
237         struct information *ptr = p;
238         const char *c, *errbuf;
239
240         if (xmmsv_get_error(value, &errbuf)) {
241                 fprintf(stderr,"XMMS2 server error. %s\n", errbuf);
242                 return TRUE;
243         }
244
245         if (ptr->xmms2.playlist == NULL) {
246                 ptr->xmms2.playlist = malloc(text_buffer_size);
247                 ptr->xmms2.playlist[0] = '\0';
248         }
249
250         if (xmmsv_get_string(value, &c))  {
251                 strncpy(ptr->xmms2.playlist, c, text_buffer_size - 1);
252         }
253         return TRUE;
254 }
255
256 int update_xmms2(void)
257 {
258         struct information *current_info = &info;
259
260         /* initialize connection */
261         if (current_info->xmms2.conn_state == CONN_INIT) {
262
263                 if (xmms2_conn == NULL) {
264                         xmms2_conn = xmmsc_init(PACKAGE);
265                 }
266
267                 /* did init fail? */
268                 if (xmms2_conn == NULL) {
269                         fprintf(stderr,"XMMS2 init failed. %s\n", xmmsc_get_last_error(xmms2_conn));
270                         return 0;
271                 }
272
273                 /* init ok but not connected yet.. */
274                 current_info->xmms2.conn_state = CONN_NO;
275
276                 /* clear all values */
277                 xmms_alloc(current_info);
278         }
279
280         /* connect */
281         if (current_info->xmms2.conn_state == CONN_NO) {
282
283                 char *path = getenv("XMMS_PATH");
284
285                 if (!xmmsc_connect(xmms2_conn, path)) {
286                         fprintf(stderr,"XMMS2 connection failed. %s\n", xmmsc_get_last_error(xmms2_conn));
287                         current_info->xmms2.conn_state = CONN_NO;
288                         return 0;
289                 }
290
291                 /* set callbacks */
292                 xmmsc_disconnect_callback_set(xmms2_conn, connection_lost, current_info);
293                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_playback_current_id, 
294                                 handle_curent_id, current_info);
295                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_signal_playback_playtime, 
296                                 handle_playtime, current_info);
297                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_playback_status, 
298                                 handle_playback_state_change, current_info);
299                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_broadcast_playlist_loaded, 
300                                 handle_playlist_loaded, current_info);
301
302                 /* get playback status, current id and active playlist */
303                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_playback_current_id, 
304                                 handle_curent_id, current_info);
305                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_playback_status, 
306                                 handle_playback_state_change, current_info);
307                 XMMS_CALLBACK_SET(xmms2_conn, xmmsc_playlist_current_active, 
308                                 handle_playlist_loaded, current_info);
309
310                 /* everything seems to be ok */
311                 current_info->xmms2.conn_state = CONN_OK;
312         }
313
314         /* handle callbacks */
315         if (current_info->xmms2.conn_state == CONN_OK) {
316
317                 xmmsc_io_in_handle(xmms2_conn);
318                 if (xmmsc_io_want_out(xmms2_conn))
319                         xmmsc_io_out_handle(xmms2_conn);
320
321         }
322         return 0;
323 }
324
325