small mpd fix (fixes minor breakage in recent mpd improvements)
[monky] / src / mpd.c
1 /*
2  * Conky, a system monitor, based on torsmo
3  *
4  * Any original torsmo code is licensed under the BSD license
5  *
6  * All code written since the fork of torsmo is licensed under the GPL
7  *
8  * Please see COPYING for details
9  *
10  * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al. (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
28 #include "conky.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include "libmpdclient.h"
33
34 timed_thread *mpd_timed_thread = NULL;
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         if (current_info->mpd.album == NULL)
42                 current_info->mpd.album = malloc(TEXT_BUFFER_SIZE);
43         if (current_info->mpd.title == NULL)
44                 current_info->mpd.title = malloc(TEXT_BUFFER_SIZE);
45         if (current_info->mpd.random == NULL)
46                 current_info->mpd.random = malloc(TEXT_BUFFER_SIZE);
47         if (current_info->mpd.repeat == NULL)
48                 current_info->mpd.repeat = malloc(TEXT_BUFFER_SIZE);
49         if (current_info->mpd.track == NULL)
50                 current_info->mpd.track = malloc(TEXT_BUFFER_SIZE);
51         if (current_info->mpd.status == NULL)
52                 current_info->mpd.status = malloc(TEXT_BUFFER_SIZE);
53         if (current_info->mpd.name == NULL)
54                 current_info->mpd.name = malloc(TEXT_BUFFER_SIZE);
55         if (current_info->mpd.file == NULL)
56                 current_info->mpd.file = malloc(TEXT_BUFFER_SIZE);
57         clear_mpd_stats(current_info);
58 }
59
60 void clear_mpd_stats(struct information *current_info)
61 {
62         *current_info->mpd.name=0;
63         *current_info->mpd.file=0;
64         *current_info->mpd.artist=0;
65         *current_info->mpd.album=0;
66         *current_info->mpd.title=0;
67         *current_info->mpd.random=0;
68         *current_info->mpd.repeat=0;
69         *current_info->mpd.track=0;
70         *current_info->mpd.status=0;
71         current_info->mpd.bitrate = 0;
72         current_info->mpd.progress = 0;
73         current_info->mpd.elapsed = 0;
74         current_info->mpd.length = 0;
75 }
76
77 void *update_mpd(void)
78 {
79         struct information *current_info = &info;
80         while (1) {
81                 if (!current_info->conn) {
82                         current_info->conn = mpd_newConnection(current_info->mpd.host, current_info->mpd.port, 10);
83                 }
84                 if (strlen(current_info->mpd.password) > 1) {
85                         mpd_sendPasswordCommand(current_info->conn,
86                                         current_info->mpd.password);
87                         mpd_finishCommand(current_info->conn);
88                 }
89                 
90                 timed_thread_lock(mpd_timed_thread);
91
92                 if (current_info->conn->error || current_info->conn == NULL) {
93                         //ERR("%MPD error: s\n", current_info->conn->errorStr);
94                         mpd_closeConnection(current_info->conn);
95                         current_info->conn = 0;
96                         clear_mpd_stats(current_info);
97
98                         strncpy(current_info->mpd.status, "MPD not responding", TEXT_BUFFER_SIZE - 1);
99                         timed_thread_unlock(mpd_timed_thread);
100                         if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
101                         continue;
102                 }
103
104                 mpd_Status *status;
105                 mpd_InfoEntity *entity;
106                 mpd_sendStatusCommand(current_info->conn);
107                 if ((status = mpd_getStatus(current_info->conn)) == NULL) {
108                         //ERR("MPD error: %s\n", current_info->conn->errorStr);
109                         mpd_closeConnection(current_info->conn);
110                         current_info->conn = 0;
111                         clear_mpd_stats(current_info);
112
113                         strncpy(current_info->mpd.status, "MPD not responding", TEXT_BUFFER_SIZE - 1);
114                         timed_thread_unlock(mpd_timed_thread);
115                         if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
116                         continue;
117                 }
118                 mpd_finishCommand(current_info->conn);
119                 if (current_info->conn->error) {
120                         //fprintf(stderr, "%s\n", current_info->conn->errorStr);
121                         mpd_closeConnection(current_info->conn);
122                         current_info->conn = 0;
123                         timed_thread_unlock(mpd_timed_thread);
124                         if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
125                         continue;
126                 }
127
128                 current_info->mpd.volume = status->volume;
129                 //if (status->error)
130                 //printf("error: %s\n", status->error);
131
132                 if (status->state == MPD_STATUS_STATE_PLAY) {
133                         strncpy(current_info->mpd.status, "Playing",
134                                         TEXT_BUFFER_SIZE - 1);
135                 }
136                 if (status->state == MPD_STATUS_STATE_STOP) {
137                         strncpy(current_info->mpd.status, "Stopped",
138                                         TEXT_BUFFER_SIZE - 1);
139                         clear_mpd_stats(current_info);
140                 }
141                 if (status->state == MPD_STATUS_STATE_PAUSE) {
142                         strncpy(current_info->mpd.status, "Paused",
143                                         TEXT_BUFFER_SIZE - 1);
144                 }
145                 if (status->state == MPD_STATUS_STATE_UNKNOWN) {
146                         clear_mpd_stats(current_info);
147                         *current_info->mpd.status=0;
148                 }
149                 if (status->state == MPD_STATUS_STATE_PLAY ||
150                                 status->state == MPD_STATUS_STATE_PAUSE) {
151                         current_info->mpd.bitrate = status->bitRate;
152                         current_info->mpd.progress =
153                                 (float) status->elapsedTime / status->totalTime;
154                         current_info->mpd.elapsed = status->elapsedTime;
155                         current_info->mpd.length = status->totalTime;
156                         if (status->random == 0) {
157                                 strcpy(current_info->mpd.random, "Off");
158                         } else if (status->random == 1) {
159                                 strcpy(current_info->mpd.random, "On");
160                         } else {
161                                 *current_info->mpd.random=0;
162                         }
163                         if (status->repeat == 0) {
164                                 strcpy(current_info->mpd.repeat, "Off");
165                         } else if (status->repeat == 1) {
166                                 strcpy(current_info->mpd.repeat, "On");
167                         } else {
168                                 *current_info->mpd.repeat=0;
169                         }
170                 }
171
172                 if (current_info->conn->error) {
173                         //fprintf(stderr, "%s\n", current_info->conn->errorStr);
174                         mpd_closeConnection(current_info->conn);
175                         current_info->conn = 0;
176                         timed_thread_unlock(mpd_timed_thread);
177                         if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
178                         continue;
179                 }
180
181                 mpd_sendCurrentSongCommand(current_info->conn);
182                 while ((entity = mpd_getNextInfoEntity(current_info->conn))) {
183                         mpd_Song *song = entity->info.song;
184                         if (entity->type != MPD_INFO_ENTITY_TYPE_SONG) {
185                                 mpd_freeInfoEntity(entity);
186                                 continue;
187                         }
188
189                         if (song->artist) {
190                                 strncpy(current_info->mpd.artist, song->artist,
191                                                 TEXT_BUFFER_SIZE - 1);
192                         } else {
193                                 *current_info->mpd.artist=0;
194                         }
195                         if (song->album) {
196                                 strncpy(current_info->mpd.album, song->album,
197                                                 TEXT_BUFFER_SIZE - 1);
198                         } else {
199                                 *current_info->mpd.album=0;
200                         }
201                         if (song->title) {
202                                 strncpy(current_info->mpd.title, song->title,
203                                                 TEXT_BUFFER_SIZE - 1);
204                         } else {
205                                 *current_info->mpd.title=0;
206                         }
207                         if (song->track) {
208                                 strncpy(current_info->mpd.track, song->track,
209                                                 TEXT_BUFFER_SIZE - 1);
210                         } else {
211                                 *current_info->mpd.track=0;
212                         }
213                         if (song->name) {
214                                 strncpy(current_info->mpd.name, song->name,
215                                                 TEXT_BUFFER_SIZE - 1);
216                         } else {
217                                 *current_info->mpd.name=0;
218                         }
219                         if (song->file) {
220                                 strncpy(current_info->mpd.file,
221                                                 song->file, TEXT_BUFFER_SIZE - 1);
222                         } else {
223                                 *current_info->mpd.file=0;
224                         }
225                         if (entity != NULL) {
226                                 mpd_freeInfoEntity(entity);
227                                 entity = NULL;
228                         }
229                 }
230                 if (entity != NULL) {
231                         mpd_freeInfoEntity(entity);
232                         entity = NULL;
233                 }
234                 mpd_finishCommand(current_info->conn);
235                 if (current_info->conn->error) {
236                         //fprintf(stderr, "%s\n", current_info->conn->errorStr);
237                         mpd_closeConnection(current_info->conn);
238                         current_info->conn = 0;
239                         timed_thread_unlock(mpd_timed_thread);
240                         if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
241                         continue;
242                 }
243
244                 timed_thread_unlock(mpd_timed_thread);
245                 if (current_info->conn->error) {
246                         //fprintf(stderr, "%s\n", current_info->conn->errorStr);
247                         mpd_closeConnection(current_info->conn);
248                         current_info->conn = 0;
249                         if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
250                         continue;
251                 }
252
253                 mpd_freeStatus(status);
254 /*              if (current_info->conn) {
255                         mpd_closeConnection(current_info->conn);
256                         current_info->conn = 0;
257                 }*/
258                 if (timed_thread_test(mpd_timed_thread)) timed_thread_exit(mpd_timed_thread);
259                 continue;
260         }
261         return 0;
262 }