* Added $if_mpd_playing patch (thanks tarpman)
[monky] / src / mpd.c
1 /* Conky, a system monitor, based on torsmo
2  *
3  * Any original torsmo code is licensed under the BSD license
4  *
5  * All code written since the fork of torsmo is licensed under the GPL
6  *
7  * Please see COPYING for details
8  *
9  * Copyright (c) 2005-2008 Brenden Matthews, Philip Kovacs, et. al.
10  *      (see AUTHORS)
11  * All rights reserved.
12  *
13  * This program is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  *
25  * $Id$ */
26
27 #include "conky.h"
28
29 void init_mpd_stats(struct mpd_s *mpd)
30 {
31         if (mpd->artist == NULL) {
32                 mpd->artist = malloc(text_buffer_size);
33         }
34         if (mpd->album == NULL) {
35                 mpd->album = malloc(text_buffer_size);
36         }
37         if (mpd->title == NULL) {
38                 mpd->title = malloc(text_buffer_size);
39         }
40         if (mpd->random == NULL) {
41                 mpd->random = malloc(text_buffer_size);
42         }
43         if (mpd->repeat == NULL) {
44                 mpd->repeat = malloc(text_buffer_size);
45         }
46         if (mpd->track == NULL) {
47                 mpd->track = malloc(text_buffer_size);
48         }
49         if (mpd->status == NULL) {
50                 mpd->status = malloc(text_buffer_size);
51         }
52         if (mpd->name == NULL) {
53                 mpd->name = malloc(text_buffer_size);
54         }
55         if (mpd->file == NULL) {
56                 mpd->file = malloc(text_buffer_size);
57         }
58         clear_mpd_stats(mpd);
59 }
60
61 void free_mpd_vars(struct mpd_s *mpd)
62 {
63         if (mpd->title) {
64                 free(mpd->title);
65                 mpd->title = NULL;
66         }
67         if (mpd->artist) {
68                 free(mpd->artist);
69                 mpd->artist = NULL;
70         }
71         if (mpd->album) {
72                 free(mpd->album);
73                 mpd->album = NULL;
74         }
75         if (mpd->random) {
76                 free(mpd->random);
77                 mpd->random = NULL;
78         }
79         if (mpd->repeat) {
80                 free(mpd->repeat);
81                 mpd->repeat = NULL;
82         }
83         if (mpd->track) {
84                 free(mpd->track);
85                 mpd->track = NULL;
86         }
87         if (mpd->name) {
88                 free(mpd->name);
89                 mpd->name = NULL;
90         }
91         if (mpd->file) {
92                 free(mpd->file);
93                 mpd->file = NULL;
94         }
95         if (mpd->status) {
96                 free(mpd->status);
97                 mpd->status = NULL;
98         }
99         if (mpd->conn) {
100                 mpd_closeConnection(mpd->conn);
101                 mpd->conn = 0;
102         }
103 }
104
105 void clear_mpd_stats(struct mpd_s *mpd)
106 {
107         *mpd->name = 0;
108         *mpd->file = 0;
109         *mpd->artist = 0;
110         *mpd->album = 0;
111         *mpd->title = 0;
112         *mpd->random = 0;
113         *mpd->repeat = 0;
114         *mpd->track = 0;
115         *mpd->status = 0;
116         mpd->is_playing = 0;
117         mpd->bitrate = 0;
118         mpd->progress = 0;
119         mpd->elapsed = 0;
120         mpd->length = 0;
121 }
122
123 void *update_mpd(void *arg)
124 {
125         struct mpd_s *mpd;
126
127         if (arg == NULL) {
128                 CRIT_ERR("update_mpd called with a null argument!");
129         }
130
131         mpd = (struct mpd_s *) arg;
132
133         while (1) {
134                 mpd_Status *status;
135                 mpd_InfoEntity *entity;
136
137                 if (!mpd->conn) {
138                         mpd->conn = mpd_newConnection(mpd->host,
139                                 mpd->port, 10);
140                 }
141                 if (strlen(mpd->password) > 1) {
142                         mpd_sendPasswordCommand(mpd->conn,
143                                 mpd->password);
144                         mpd_finishCommand(mpd->conn);
145                 }
146
147                 timed_thread_lock(mpd->timed_thread);
148
149                 if (mpd->conn->error || mpd->conn == NULL) {
150                         ERR("MPD error: %s\n", mpd->conn->errorStr);
151                         mpd_closeConnection(mpd->conn);
152                         mpd->conn = 0;
153                         clear_mpd_stats(mpd);
154
155                         strncpy(mpd->status, "MPD not responding",
156                                 text_buffer_size - 1);
157                         timed_thread_unlock(mpd->timed_thread);
158                         if (timed_thread_test(mpd->timed_thread)) {
159                                 timed_thread_exit(mpd->timed_thread);
160                         }
161                         continue;
162                 }
163
164                 mpd_sendStatusCommand(mpd->conn);
165                 if ((status = mpd_getStatus(mpd->conn)) == NULL) {
166                         ERR("MPD error: %s\n", mpd->conn->errorStr);
167                         mpd_closeConnection(mpd->conn);
168                         mpd->conn = 0;
169                         clear_mpd_stats(mpd);
170
171                         strncpy(mpd->status, "MPD not responding",
172                                 text_buffer_size - 1);
173                         timed_thread_unlock(mpd->timed_thread);
174                         if (timed_thread_test(mpd->timed_thread)) {
175                                 timed_thread_exit(mpd->timed_thread);
176                         }
177                         continue;
178                 }
179                 mpd_finishCommand(mpd->conn);
180                 if (mpd->conn->error) {
181                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
182                         mpd_closeConnection(mpd->conn);
183                         mpd->conn = 0;
184                         timed_thread_unlock(mpd->timed_thread);
185                         if (timed_thread_test(mpd->timed_thread)) {
186                                 timed_thread_exit(mpd->timed_thread);
187                         }
188                         continue;
189                 }
190
191                 mpd->volume = status->volume;
192                 /* if (status->error) {
193                         printf("error: %s\n", status->error);
194                 } */
195
196                 if (status->state == MPD_STATUS_STATE_PLAY) {
197                         strncpy(mpd->status, "Playing", text_buffer_size - 1);
198                 }
199                 if (status->state == MPD_STATUS_STATE_STOP) {
200                         clear_mpd_stats(mpd);
201                         strncpy(mpd->status, "Stopped", text_buffer_size - 1);
202                 }
203                 if (status->state == MPD_STATUS_STATE_PAUSE) {
204                         strncpy(mpd->status, "Paused", text_buffer_size - 1);
205                 }
206                 if (status->state == MPD_STATUS_STATE_UNKNOWN) {
207                         clear_mpd_stats(mpd);
208                         *mpd->status = 0;
209                 }
210                 if (status->state == MPD_STATUS_STATE_PLAY
211                                 || status->state == MPD_STATUS_STATE_PAUSE) {
212                         mpd->is_playing = 1;
213                         mpd->bitrate = status->bitRate;
214                         mpd->progress = (float) status->elapsedTime /
215                                 status->totalTime;
216                         mpd->elapsed = status->elapsedTime;
217                         mpd->length = status->totalTime;
218                         if (status->random == 0) {
219                                 strcpy(mpd->random, "Off");
220                         } else if (status->random == 1) {
221                                 strcpy(mpd->random, "On");
222                         } else {
223                                 *mpd->random = 0;
224                         }
225                         if (status->repeat == 0) {
226                                 strcpy(mpd->repeat, "Off");
227                         } else if (status->repeat == 1) {
228                                 strcpy(mpd->repeat, "On");
229                         } else {
230                                 *mpd->repeat = 0;
231                         }
232                 }
233
234                 if (mpd->conn->error) {
235                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
236                         mpd_closeConnection(mpd->conn);
237                         mpd->conn = 0;
238                         timed_thread_unlock(mpd->timed_thread);
239                         if (timed_thread_test(mpd->timed_thread)) {
240                                 timed_thread_exit(mpd->timed_thread);
241                         }
242                         continue;
243                 }
244
245                 mpd_sendCurrentSongCommand(mpd->conn);
246                 while ((entity = mpd_getNextInfoEntity(mpd->conn))) {
247                         mpd_Song *song = entity->info.song;
248
249                         if (entity->type != MPD_INFO_ENTITY_TYPE_SONG) {
250                                 mpd_freeInfoEntity(entity);
251                                 continue;
252                         }
253
254                         if (song->artist) {
255                                 strncpy(mpd->artist, song->artist,
256                                         text_buffer_size - 1);
257                         } else {
258                                 *mpd->artist = 0;
259                         }
260                         if (song->album) {
261                                 strncpy(mpd->album, song->album,
262                                         text_buffer_size - 1);
263                         } else {
264                                 *mpd->album = 0;
265                         }
266                         if (song->title) {
267                                 strncpy(mpd->title, song->title,
268                                         text_buffer_size - 1);
269                         } else {
270                                 *mpd->title = 0;
271                         }
272                         if (song->track) {
273                                 strncpy(mpd->track, song->track,
274                                         text_buffer_size - 1);
275                         } else {
276                                 *mpd->track = 0;
277                         }
278                         if (song->name) {
279                                 strncpy(mpd->name, song->name,
280                                         text_buffer_size - 1);
281                         } else {
282                                 *mpd->name = 0;
283                         }
284                         if (song->file) {
285                                 strncpy(mpd->file, song->file,
286                                         text_buffer_size - 1);
287                         } else {
288                                 *mpd->file = 0;
289                         }
290                         if (entity != NULL) {
291                                 mpd_freeInfoEntity(entity);
292                                 entity = NULL;
293                         }
294                 }
295                 if (entity != NULL) {
296                         mpd_freeInfoEntity(entity);
297                         entity = NULL;
298                 }
299                 mpd_finishCommand(mpd->conn);
300                 if (mpd->conn->error) {
301                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
302                         mpd_closeConnection(mpd->conn);
303                         mpd->conn = 0;
304                         timed_thread_unlock(mpd->timed_thread);
305                         if (timed_thread_test(mpd->timed_thread)) {
306                                 timed_thread_exit(mpd->timed_thread);
307                         }
308                         continue;
309                 }
310
311                 timed_thread_unlock(mpd->timed_thread);
312                 if (mpd->conn->error) {
313                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
314                         mpd_closeConnection(mpd->conn);
315                         mpd->conn = 0;
316                         if (timed_thread_test(mpd->timed_thread)) {
317                                 timed_thread_exit(mpd->timed_thread);
318                         }
319                         continue;
320                 }
321
322                 mpd_freeStatus(status);
323                 /* if (mpd->conn) {
324                         mpd_closeConnection(mpd->conn);
325                         mpd->conn = 0;
326                 } */
327                 if (timed_thread_test(mpd->timed_thread)) {
328                         timed_thread_exit(mpd->timed_thread);
329                 }
330                 continue;
331         }
332         /* never reached */
333 }