e055dc3e676cb4953defe15a1ca4f65bda3a7732
[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-2007 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 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include "libmpdclient.h"
32
33 timed_thread *mpd_timed_thread = NULL;
34
35 void clear_mpd_stats(struct information *current_info);
36
37 void init_mpd_stats(struct information *current_info)
38 {
39         if (current_info->mpd.artist == NULL) {
40                 current_info->mpd.artist = malloc(TEXT_BUFFER_SIZE);
41         }
42         if (current_info->mpd.album == NULL) {
43                 current_info->mpd.album = malloc(TEXT_BUFFER_SIZE);
44         }
45         if (current_info->mpd.title == NULL) {
46                 current_info->mpd.title = malloc(TEXT_BUFFER_SIZE);
47         }
48         if (current_info->mpd.random == NULL) {
49                 current_info->mpd.random = malloc(TEXT_BUFFER_SIZE);
50         }
51         if (current_info->mpd.repeat == NULL) {
52                 current_info->mpd.repeat = malloc(TEXT_BUFFER_SIZE);
53         }
54         if (current_info->mpd.track == NULL) {
55                 current_info->mpd.track = malloc(TEXT_BUFFER_SIZE);
56         }
57         if (current_info->mpd.status == NULL) {
58                 current_info->mpd.status = malloc(TEXT_BUFFER_SIZE);
59         }
60         if (current_info->mpd.name == NULL) {
61                 current_info->mpd.name = malloc(TEXT_BUFFER_SIZE);
62         }
63         if (current_info->mpd.file == NULL) {
64                 current_info->mpd.file = malloc(TEXT_BUFFER_SIZE);
65         }
66         clear_mpd_stats(current_info);
67 }
68
69 void clear_mpd_stats(struct information *current_info)
70 {
71         *current_info->mpd.name = 0;
72         *current_info->mpd.file = 0;
73         *current_info->mpd.artist = 0;
74         *current_info->mpd.album = 0;
75         *current_info->mpd.title = 0;
76         *current_info->mpd.random = 0;
77         *current_info->mpd.repeat = 0;
78         *current_info->mpd.track = 0;
79         *current_info->mpd.status = 0;
80         current_info->mpd.bitrate = 0;
81         current_info->mpd.progress = 0;
82         current_info->mpd.elapsed = 0;
83         current_info->mpd.length = 0;
84 }
85
86 void *update_mpd(void)
87 {
88         struct information *current_info = &info;
89
90         while (1) {
91                 if (!current_info->conn) {
92                         current_info->conn = mpd_newConnection(current_info->mpd.host,
93                                 current_info->mpd.port, 10);
94                 }
95                 if (strlen(current_info->mpd.password) > 1) {
96                         mpd_sendPasswordCommand(current_info->conn,
97                                 current_info->mpd.password);
98                         mpd_finishCommand(current_info->conn);
99                 }
100
101                 timed_thread_lock(mpd_timed_thread);
102
103                 if (current_info->conn->error || current_info->conn == NULL) {
104                         // ERR("%MPD error: s\n", current_info->conn->errorStr);
105                         mpd_closeConnection(current_info->conn);
106                         current_info->conn = 0;
107                         clear_mpd_stats(current_info);
108
109                         strncpy(current_info->mpd.status, "MPD not responding",
110                                 TEXT_BUFFER_SIZE - 1);
111                         timed_thread_unlock(mpd_timed_thread);
112                         if (timed_thread_test(mpd_timed_thread)) {
113                                 timed_thread_exit(mpd_timed_thread);
114                         }
115                         continue;
116                 }
117
118                 mpd_Status *status;
119                 mpd_InfoEntity *entity;
120
121                 mpd_sendStatusCommand(current_info->conn);
122                 if ((status = mpd_getStatus(current_info->conn)) == NULL) {
123                         // ERR("MPD error: %s\n", current_info->conn->errorStr);
124                         mpd_closeConnection(current_info->conn);
125                         current_info->conn = 0;
126                         clear_mpd_stats(current_info);
127
128                         strncpy(current_info->mpd.status, "MPD not responding",
129                                 TEXT_BUFFER_SIZE - 1);
130                         timed_thread_unlock(mpd_timed_thread);
131                         if (timed_thread_test(mpd_timed_thread)) {
132                                 timed_thread_exit(mpd_timed_thread);
133                         }
134                         continue;
135                 }
136                 mpd_finishCommand(current_info->conn);
137                 if (current_info->conn->error) {
138                         // fprintf(stderr, "%s\n", current_info->conn->errorStr);
139                         mpd_closeConnection(current_info->conn);
140                         current_info->conn = 0;
141                         timed_thread_unlock(mpd_timed_thread);
142                         if (timed_thread_test(mpd_timed_thread)) {
143                                 timed_thread_exit(mpd_timed_thread);
144                         }
145                         continue;
146                 }
147
148                 current_info->mpd.volume = status->volume;
149                 /* if (status->error) {
150                         printf("error: %s\n", status->error);
151                 } */
152
153                 if (status->state == MPD_STATUS_STATE_PLAY) {
154                         strncpy(current_info->mpd.status, "Playing", TEXT_BUFFER_SIZE - 1);
155                 }
156                 if (status->state == MPD_STATUS_STATE_STOP) {
157                         clear_mpd_stats(current_info);
158                         strncpy(current_info->mpd.status, "Stopped", TEXT_BUFFER_SIZE - 1);
159                 }
160                 if (status->state == MPD_STATUS_STATE_PAUSE) {
161                         strncpy(current_info->mpd.status, "Paused", TEXT_BUFFER_SIZE - 1);
162                 }
163                 if (status->state == MPD_STATUS_STATE_UNKNOWN) {
164                         clear_mpd_stats(current_info);
165                         *current_info->mpd.status = 0;
166                 }
167                 if (status->state == MPD_STATUS_STATE_PLAY
168                                 || status->state == MPD_STATUS_STATE_PAUSE) {
169                         current_info->mpd.bitrate = status->bitRate;
170                         current_info->mpd.progress = (float) status->elapsedTime /
171                                 status->totalTime;
172                         current_info->mpd.elapsed = status->elapsedTime;
173                         current_info->mpd.length = status->totalTime;
174                         if (status->random == 0) {
175                                 strcpy(current_info->mpd.random, "Off");
176                         } else if (status->random == 1) {
177                                 strcpy(current_info->mpd.random, "On");
178                         } else {
179                                 *current_info->mpd.random = 0;
180                         }
181                         if (status->repeat == 0) {
182                                 strcpy(current_info->mpd.repeat, "Off");
183                         } else if (status->repeat == 1) {
184                                 strcpy(current_info->mpd.repeat, "On");
185                         } else {
186                                 *current_info->mpd.repeat = 0;
187                         }
188                 }
189
190                 if (current_info->conn->error) {
191                         // fprintf(stderr, "%s\n", current_info->conn->errorStr);
192                         mpd_closeConnection(current_info->conn);
193                         current_info->conn = 0;
194                         timed_thread_unlock(mpd_timed_thread);
195                         if (timed_thread_test(mpd_timed_thread)) {
196                                 timed_thread_exit(mpd_timed_thread);
197                         }
198                         continue;
199                 }
200
201                 mpd_sendCurrentSongCommand(current_info->conn);
202                 while ((entity = mpd_getNextInfoEntity(current_info->conn))) {
203                         mpd_Song *song = entity->info.song;
204
205                         if (entity->type != MPD_INFO_ENTITY_TYPE_SONG) {
206                                 mpd_freeInfoEntity(entity);
207                                 continue;
208                         }
209
210                         if (song->artist) {
211                                 strncpy(current_info->mpd.artist, song->artist,
212                                         TEXT_BUFFER_SIZE - 1);
213                         } else {
214                                 *current_info->mpd.artist = 0;
215                         }
216                         if (song->album) {
217                                 strncpy(current_info->mpd.album, song->album,
218                                         TEXT_BUFFER_SIZE - 1);
219                         } else {
220                                 *current_info->mpd.album = 0;
221                         }
222                         if (song->title) {
223                                 strncpy(current_info->mpd.title, song->title,
224                                         TEXT_BUFFER_SIZE - 1);
225                         } else {
226                                 *current_info->mpd.title = 0;
227                         }
228                         if (song->track) {
229                                 strncpy(current_info->mpd.track, song->track,
230                                         TEXT_BUFFER_SIZE - 1);
231                         } else {
232                                 *current_info->mpd.track = 0;
233                         }
234                         if (song->name) {
235                                 strncpy(current_info->mpd.name, song->name,
236                                         TEXT_BUFFER_SIZE - 1);
237                         } else {
238                                 *current_info->mpd.name = 0;
239                         }
240                         if (song->file) {
241                                 strncpy(current_info->mpd.file, song->file,
242                                         TEXT_BUFFER_SIZE - 1);
243                         } else {
244                                 *current_info->mpd.file = 0;
245                         }
246                         if (entity != NULL) {
247                                 mpd_freeInfoEntity(entity);
248                                 entity = NULL;
249                         }
250                 }
251                 if (entity != NULL) {
252                         mpd_freeInfoEntity(entity);
253                         entity = NULL;
254                 }
255                 mpd_finishCommand(current_info->conn);
256                 if (current_info->conn->error) {
257                         // fprintf(stderr, "%s\n", current_info->conn->errorStr);
258                         mpd_closeConnection(current_info->conn);
259                         current_info->conn = 0;
260                         timed_thread_unlock(mpd_timed_thread);
261                         if (timed_thread_test(mpd_timed_thread)) {
262                                 timed_thread_exit(mpd_timed_thread);
263                         }
264                         continue;
265                 }
266
267                 timed_thread_unlock(mpd_timed_thread);
268                 if (current_info->conn->error) {
269                         // fprintf(stderr, "%s\n", current_info->conn->errorStr);
270                         mpd_closeConnection(current_info->conn);
271                         current_info->conn = 0;
272                         if (timed_thread_test(mpd_timed_thread)) {
273                                 timed_thread_exit(mpd_timed_thread);
274                         }
275                         continue;
276                 }
277
278                 mpd_freeStatus(status);
279                 /* if (current_info->conn) {
280                         mpd_closeConnection(current_info->conn);
281                         current_info->conn = 0;
282                 } */
283                 if (timed_thread_test(mpd_timed_thread)) {
284                         timed_thread_exit(mpd_timed_thread);
285                 }
286                 continue;
287         }
288         return 0;
289 }