Code

screen_play, status_bar: update scrolling with a GLib timer
[ncmpc.git] / src / status_bar.c
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2009 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 #ifndef NCMPC_MINI
35 static gboolean
36 scroll_timer_callback(gpointer data)
37 {
38         struct status_bar *p = data;
40         p->scroll_source_id = 0;
42         hscroll_step(&p->hscroll);
43         status_bar_paint(p, p->prev_status, p->prev_song);
44         doupdate();
45         return false;
46 }
47 #endif
49 static gboolean
50 status_bar_clear_message(gpointer data)
51 {
52         struct status_bar *p = data;
53         WINDOW *w = p->window.w;
55         assert(p != NULL);
56         assert(p->message_source_id != 0);
58         p->message_source_id = 0;
60         wmove(w, 0, 0);
61         wclrtoeol(w);
62         wrefresh(w);
64         return false;
65 }
67 void
68 status_bar_paint(struct status_bar *p, const struct mpd_status *status,
69                  const struct mpd_song *song)
70 {
71         WINDOW *w = p->window.w;
72         enum mpd_state state;
73         int elapsedTime = 0;
74 #ifdef NCMPC_MINI
75         static char bitrate[1];
76 #else
77         char bitrate[16];
78 #endif
79         const char *str = NULL;
80         int x = 0;
81         char buffer[p->window.cols * 4 + 1];
83 #ifndef NCMPC_MINI
84         p->prev_status = status;
85         p->prev_song = song;
86 #endif
88         if (p->message_source_id != 0)
89                 return;
91         wmove(w, 0, 0);
92         wclrtoeol(w);
93         colors_use(w, COLOR_STATUS_BOLD);
95         state = status == NULL ? MPD_STATE_UNKNOWN
96                 : mpd_status_get_state(status);
98         switch (state) {
99         case MPD_STATE_PLAY:
100                 str = _("Playing:");
101                 break;
102         case MPD_STATE_PAUSE:
103                 str = _("[Paused]");
104                 break;
105         case MPD_STATE_STOP:
106         default:
107                 break;
108         }
110         if (str) {
111                 waddstr(w, str);
112                 x += utf8_width(str) + 1;
113         }
115         /* create time string */
116         if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE) {
117                 int total_time = mpd_status_get_total_time(status);
118                 if (total_time > 0) {
119                         char elapsed_string[32], duration_string[32];
121                         /*checks the conf to see whether to display elapsed or remaining time */
122                         if(!strcmp(options.timedisplay_type,"elapsed"))
123                                 elapsedTime = mpd_status_get_elapsed_time(status);
124                         else if(!strcmp(options.timedisplay_type,"remaining"))
125                                 elapsedTime = total_time -
126                                         mpd_status_get_elapsed_time(status);
128                         if (song != NULL &&
129                             seek_id == (int)mpd_song_get_id(song))
130                                 elapsedTime = seek_target_time;
132                         /* display bitrate if visible-bitrate is true */
133 #ifndef NCMPC_MINI
134                         if (options.visible_bitrate) {
135                                 g_snprintf(bitrate, 16,
136                                            " [%d kbps]",
137                                            mpd_status_get_kbit_rate(status));
138                         } else {
139                                 bitrate[0] = '\0';
140                         }
141 #endif
143                         /* write out the time */
144                         format_duration_short(elapsed_string,
145                                               sizeof(elapsed_string),
146                                               elapsedTime);
147                         format_duration_short(duration_string,
148                                               sizeof(duration_string),
149                                               total_time);
151                         g_snprintf(buffer, sizeof(buffer), "%s [%s/%s]",
152                                    bitrate, elapsed_string, duration_string);
153 #ifndef NCMPC_MINI
154                 } else {
155                         g_snprintf(buffer, sizeof(buffer),
156                                    " [%d kbps]",
157                                    mpd_status_get_kbit_rate(status));
158 #endif
159                 }
160 #ifndef NCMPC_MINI
161         } else {
162                 if (options.display_time) {
163                         time_t timep;
165                         time(&timep);
166                         strftime(buffer, sizeof(buffer), "%X ",localtime(&timep));
167                 } else
168 #endif
169                         buffer[0] = 0;
170         }
172         /* display song */
173         if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE) {
174                 char songname[p->window.cols * 4 + 1];
175 #ifndef NCMPC_MINI
176                 int width = COLS - x - utf8_width(buffer);
177 #endif
179                 if (song)
180                         strfsong(songname, sizeof(songname),
181                                  options.status_format, song);
182                 else
183                         songname[0] = '\0';
185                 colors_use(w, COLOR_STATUS);
186                 /* scroll if the song name is to long */
187 #ifndef NCMPC_MINI
188                 if (options.scroll && utf8_width(songname) > (unsigned)width) {
189                         char *tmp = strscroll(&p->hscroll, songname,
190                                               options.scroll_sep, width);
192                         g_strlcpy(songname, tmp, sizeof(songname));
193                         g_free(tmp);
195                         if (p->scroll_source_id == 0)
196                                 p->scroll_source_id =
197                                         g_timeout_add(1000,
198                                                       scroll_timer_callback,
199                                                       p);
200                 } else if (p->scroll_source_id != 0) {
201                         g_source_remove(p->scroll_source_id);
202                         p->scroll_source_id = 0;
203                 }
204 #endif
205                 //mvwaddnstr(w, 0, x, songname, width);
206                 mvwaddstr(w, 0, x, songname);
207 #ifndef NCMPC_MINI
208         } else if (p->scroll_source_id != 0) {
209                 g_source_remove(p->scroll_source_id);
210                 p->scroll_source_id = 0;
211 #endif
212         }
214         /* display time string */
215         if (buffer[0] != 0) {
216                 x = p->window.cols - strlen(buffer);
217                 colors_use(w, COLOR_STATUS_TIME);
218                 mvwaddstr(w, 0, x, buffer);
219         }
221         wnoutrefresh(w);
224 void
225 status_bar_resize(struct status_bar *p, unsigned width, int y, int x)
227         p->window.cols = width;
228         wresize(p->window.w, 1, width);
229         mvwin(p->window.w, y, x);
232 void
233 status_bar_message(struct status_bar *p, const char *msg)
235         WINDOW *w = p->window.w;
237         wmove(w, 0, 0);
238         wclrtoeol(w);
239         colors_use(w, COLOR_STATUS_ALERT);
240         waddstr(w, msg);
241         wnoutrefresh(w);
243         if (p->message_source_id != 0)
244                 g_source_remove(p->message_source_id);
245         p->message_source_id = g_timeout_add(options.status_message_time * 1000,
246                                              status_bar_clear_message, p);