Code

configure.ac: require libmpdclient 2.3
[ncmpc.git] / src / status_bar.c
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2010 The Music Player Daemon Project
3  * Project homepage: http://musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
20 #include "status_bar.h"
21 #include "options.h"
22 #include "colors.h"
23 #include "i18n.h"
24 #include "charset.h"
25 #include "strfsong.h"
26 #include "player_command.h"
27 #include "utils.h"
29 #include <mpd/client.h>
31 #include <assert.h>
32 #include <string.h>
34 void
35 status_bar_init(struct status_bar *p, unsigned width, int y, int x)
36 {
37         window_init(&p->window, 1, width, y, x);
39         leaveok(p->window.w, false);
40         keypad(p->window.w, true);
42         p->message_source_id = 0;
44 #ifndef NCMPC_MINI
45         if (options.scroll)
46                 hscroll_init(&p->hscroll, p->window.w, options.scroll_sep);
48         p->prev_status = NULL;
49         p->prev_song = NULL;
50 #endif
51 }
53 void
54 status_bar_deinit(struct status_bar *p)
55 {
56         delwin(p->window.w);
58 #ifndef NCMPC_MINI
59         if (options.scroll)
60                 hscroll_clear(&p->hscroll);
61 #endif
62 }
64 void
65 status_bar_clear_message(struct status_bar *p)
66 {
67         assert(p != NULL);
69         if (p->message_source_id != 0) {
70                 g_source_remove(p->message_source_id);
71                 p->message_source_id = 0;
72         }
74         WINDOW *w = p->window.w;
76         wmove(w, 0, 0);
77         wclrtoeol(w);
78         wrefresh(w);
79 }
81 #ifndef NCMPC_MINI
83 static void
84 format_bitrate(char *p, size_t max_length, const struct mpd_status *status)
85 {
86         if (options.visible_bitrate && mpd_status_get_kbit_rate(status) > 0)
87                 g_snprintf(p, max_length,
88                            " [%d kbps]",
89                            mpd_status_get_kbit_rate(status));
90         else
91                 p[0] = '\0';
92 }
94 #endif /* !NCMPC_MINI */
96 void
97 status_bar_paint(struct status_bar *p, const struct mpd_status *status,
98                  const struct mpd_song *song)
99 {
100         WINDOW *w = p->window.w;
101         enum mpd_state state;
102         const char *str = NULL;
103         int x = 0;
104         char buffer[p->window.cols * 4 + 1];
106 #ifndef NCMPC_MINI
107         p->prev_status = status;
108         p->prev_song = song;
109 #endif
111         if (p->message_source_id != 0)
112                 return;
114         wmove(w, 0, 0);
115         wclrtoeol(w);
116         colors_use(w, COLOR_STATUS_BOLD);
118         state = status == NULL ? MPD_STATE_UNKNOWN
119                 : mpd_status_get_state(status);
121         switch (state) {
122         case MPD_STATE_PLAY:
123                 str = _("Playing:");
124                 break;
125         case MPD_STATE_PAUSE:
126                 str = _("[Paused]");
127                 break;
128         case MPD_STATE_STOP:
129         default:
130                 break;
131         }
133         if (str) {
134                 waddstr(w, str);
135                 x += utf8_width(str) + 1;
136         }
138         /* create time string */
139         if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE) {
140                 int elapsedTime = seek_id >= 0 &&
141                         seek_id == mpd_status_get_song_id(status)
142                         ? (unsigned)seek_target_time
143                         : mpd_status_get_elapsed_time(status);
144                 int total_time = mpd_status_get_total_time(status);
145                 if (elapsedTime > 0 || total_time > 0) {
146 #ifdef NCMPC_MINI
147                         static const char bitrate[1];
148 #else
149                         char bitrate[16];
150 #endif
151                         char elapsed_string[32], duration_string[32];
153                         /*checks the conf to see whether to display elapsed or remaining time */
154                         if (options.display_remaining_time)
155                                 elapsedTime = elapsedTime < total_time
156                                         ? total_time - elapsedTime
157                                         : 0;
159                         /* display bitrate if visible-bitrate is true */
160 #ifndef NCMPC_MINI
161                         format_bitrate(bitrate, sizeof(bitrate), status);
162 #endif
164                         /* write out the time */
165                         format_duration_short(elapsed_string,
166                                               sizeof(elapsed_string),
167                                               elapsedTime);
168                         format_duration_short(duration_string,
169                                               sizeof(duration_string),
170                                               total_time);
172                         g_snprintf(buffer, sizeof(buffer), "%s [%s/%s]",
173                                    bitrate, elapsed_string, duration_string);
174 #ifndef NCMPC_MINI
175                 } else {
176                         format_bitrate(buffer, sizeof(buffer), status);
177 #else
178                         buffer[0] = 0;
179 #endif
180                 }
181         } else {
182 #ifndef NCMPC_MINI
183                 if (options.display_time) {
184                         time_t timep;
186                         time(&timep);
187                         strftime(buffer, sizeof(buffer), "%X ",localtime(&timep));
188                 } else
189 #endif
190                         buffer[0] = 0;
191         }
193         /* display song */
194         if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE) {
195                 char songname[p->window.cols * 4 + 1];
196 #ifndef NCMPC_MINI
197                 int width = COLS - x - utf8_width(buffer);
198 #endif
200                 if (song)
201                         strfsong(songname, sizeof(songname),
202                                  options.status_format, song);
203                 else
204                         songname[0] = '\0';
206                 colors_use(w, COLOR_STATUS);
207                 /* scroll if the song name is to long */
208 #ifndef NCMPC_MINI
209                 if (options.scroll && utf8_width(songname) > (unsigned)width) {
210                         hscroll_set(&p->hscroll, x, 0, width, songname);
211                         hscroll_draw(&p->hscroll);
212                 } else {
213                         if (options.scroll)
214                                 hscroll_clear(&p->hscroll);
215                         mvwaddstr(w, 0, x, songname);
216                 }
217 #else
218                 mvwaddstr(w, 0, x, songname);
219 #endif
220 #ifndef NCMPC_MINI
221         } else if (options.scroll) {
222                 hscroll_clear(&p->hscroll);
223 #endif
224         }
226         /* display time string */
227         if (buffer[0] != 0) {
228                 x = p->window.cols - strlen(buffer);
229                 colors_use(w, COLOR_STATUS_TIME);
230                 mvwaddstr(w, 0, x, buffer);
231         }
233         wnoutrefresh(w);
236 void
237 status_bar_resize(struct status_bar *p, unsigned width, int y, int x)
239         p->window.cols = width;
240         wresize(p->window.w, 1, width);
241         mvwin(p->window.w, y, x);
244 static gboolean
245 status_bar_clear_message_cb(gpointer data)
247         struct status_bar *p = data;
248         assert(p->message_source_id != 0);
249         p->message_source_id = 0;
251         status_bar_clear_message(p);
252         return false;
255 void
256 status_bar_message(struct status_bar *p, const char *msg)
258         WINDOW *w = p->window.w;
260 #ifndef NCMPC_MINI
261         if (options.scroll)
262                 hscroll_clear(&p->hscroll);
263 #endif
265         wmove(w, 0, 0);
266         wclrtoeol(w);
267         colors_use(w, COLOR_STATUS_ALERT);
268         waddstr(w, msg);
269         wnoutrefresh(w);
271         if (p->message_source_id != 0)
272                 g_source_remove(p->message_source_id);
273         p->message_source_id = g_timeout_add(options.status_message_time * 1000,
274                                              status_bar_clear_message_cb, p);