2 * Copyright (c) 2006-2011 Ed Schouten <ed@80386.nl>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * @brief Playlist management for textual user interface.
33 #include "audio_file.h"
34 #include "audio_output.h"
36 #include "gui_internal.h"
37 #include "gui_vfslist.h"
42 * @brief Buffer containing a string representation of the playback time
43 * of the current song in the form of " [x:xx/y:yy]".
45 static GString
*str_time
;
47 * @brief Pointer to string containing playback status.
49 static const char *str_status
= NULL
;
51 * @brief Buffer containing a string representation of the artist and
52 * title of the current song.
54 static GString
*str_song
;
56 * @brief Window object of the status bar at the top of the screen.
58 static WINDOW
*win_statbar
;
60 * @brief Reference to the window used to display the playlist.
62 static struct gui_vfslist
*win_playq
;
65 * @brief Fills the str_song with the artist and song value of the audio
69 gui_playq_statbar_song(struct audio_file
*fd
)
74 g_string_assign(str_song
, "");
76 /* Smash strings down to the correct charset */
77 g_assert(fd
->title
!= NULL
);
78 title
= g_convert_with_fallback(fd
->title
,
79 -1, "", "UTF-8", "?", NULL
, NULL
, NULL
);
81 /* Conversion error - don't convert charset */
82 title
= g_strdup(fd
->title
);
84 if (fd
->artist
== NULL
) {
85 /* Only show the title */
86 g_string_assign(str_song
, title
);
88 /* Print artist and title */
89 artist
= g_convert_with_fallback(fd
->artist
,
90 -1, "", "UTF-8", "?", NULL
, NULL
, NULL
);
92 /* Conversion error */
93 artist
= g_strdup(fd
->artist
);
94 g_string_printf(str_song
, "%s - %s",
103 * @brief Set str_status to the current playback status.
106 gui_playq_statbar_status(struct audio_file
*fd
, int paused
)
109 str_status
= _("Idle");
112 str_status
= _("Paused");
114 str_status
= _("Playing");
119 * @brief Append a formatted string representation of a timestamp to a
123 gui_playq_statbar_time_calc(GString
*str
, unsigned int time
)
126 /* Only show minutes and seconds */
127 g_string_append_printf(str
, "%u:%02u",
128 time
/ 60, time
% 60);
130 /* Show hours as well */
131 g_string_append_printf(str
, "%u:%02u:%02u",
132 time
/ 3600, (time
/ 60) % 60, time
% 60);
136 * @brief Fills the str_time with the time value of the audio file.
137 * audio file. It also checks if the times are the same as
138 * before, useful to discard useless refreshes.
141 gui_playq_statbar_time(struct audio_file
*fd
)
144 g_string_assign(str_time
, "");
146 g_string_assign(str_time
, " [");
147 gui_playq_statbar_time_calc(str_time
, fd
->time_cur
);
149 g_string_append_c(str_time
, '/');
150 gui_playq_statbar_time_calc(str_time
, fd
->time_len
);
152 g_string_append_c(str_time
, ']');
157 * @brief Set the name of the song and time showed in the status bar.
160 gui_playq_song_set(struct audio_file
*fd
, int paused
, int timeonly
)
164 gui_playq_statbar_song(fd
);
165 gui_playq_statbar_time(fd
);
166 gui_playq_statbar_status(fd
, paused
);
171 * @brief Refresh the bar above the playlist to show the correct title
172 * and time of the current track and the percentage of the
176 gui_playq_statbar_refresh(void)
185 /* Put the content back */
186 mvwaddstr(win_statbar
, 0, 1, str_status
);
187 waddstr(win_statbar
, " | ");
188 waddstr(win_statbar
, str_song
->str
);
190 percent
= gui_vfslist_getpercentage(win_playq
);
191 plen
= strlen(percent
);
192 mvwaddstr(win_statbar
, 0, COLS
- str_time
->len
- plen
, str_time
->str
);
193 waddstr(win_statbar
, percent
);
196 wnoutrefresh(win_statbar
);
203 win_statbar
= newwin(1, 0, 0, 0);
204 clearok(win_statbar
, TRUE
);
206 wbkgdset(win_statbar
, COLOR_PAIR(GUI_COLOR_BAR
));
208 wbkgdset(win_statbar
, A_REVERSE
);
210 str_time
= g_string_sized_new(24);
211 str_song
= g_string_sized_new(128);
213 gui_playq_song_set(NULL
, 0, 0);
215 win_playq
= gui_vfslist_new(1);
216 gui_vfslist_setcallback(win_playq
, gui_playq_statbar_refresh
);
217 gui_vfslist_setlist(win_playq
, &playq_list
);
218 gui_vfslist_move(win_playq
, 0, 1, COLS
, GUI_SIZE_PLAYQ_HEIGHT
);
222 gui_playq_destroy(void)
225 gui_vfslist_destroy(win_playq
);
227 g_string_free(str_time
, TRUE
);
228 g_string_free(str_song
, TRUE
);
232 gui_playq_song_update(struct audio_file
*fd
, int paused
, int timeonly
)
234 gui_playq_song_set(fd
, paused
, timeonly
);
236 #ifdef BUILD_SETPROCTITLE
237 /* Print same message in ps(1) */
238 setproctitle("%s %s%s", str_status
, str_song
->str
, str_time
->str
);
239 #endif /* BUILD_SETPROCTITLE */
241 gui_playq_statbar_refresh();
246 gui_playq_resize(void)
249 wresize(win_statbar
, 1, COLS
);
250 clearok(win_statbar
, TRUE
);
254 gui_vfslist_move(win_playq
, 0, 1, COLS
, GUI_SIZE_PLAYQ_HEIGHT
);
259 gui_playq_notify_pre_removal(unsigned int index
)
261 gui_vfslist_notify_pre_removal(win_playq
, index
);
265 gui_playq_notify_post_insertion(unsigned int index
)
267 gui_vfslist_notify_post_insertion(win_playq
, index
);
271 gui_playq_notify_post_randomization(void)
273 gui_vfslist_notify_post_randomization(win_playq
);
277 gui_playq_notify_done(void)
279 gui_vfslist_notify_done(win_playq
);
284 gui_playq_cursor_up(void)
287 gui_vfslist_cursor_up(win_playq
);
292 gui_playq_cursor_down(void)
295 gui_vfslist_cursor_down(win_playq
, 0);
300 gui_playq_cursor_pageup(void)
303 gui_vfslist_cursor_pageup(win_playq
);
308 gui_playq_cursor_pagedown(void)
311 gui_vfslist_cursor_pagedown(win_playq
);
316 gui_playq_cursor_head(void)
319 gui_vfslist_cursor_head(win_playq
);
324 gui_playq_cursor_tail(void)
327 gui_vfslist_cursor_tail(win_playq
);
332 gui_playq_song_remove(void)
337 if (!gui_vfslist_warn_isempty(win_playq
)) {
338 vr
= gui_vfslist_getselected(win_playq
);
339 playq_song_fast_remove(vr
,
340 gui_vfslist_getselectedidx(win_playq
));
346 gui_playq_song_remove_all(void)
348 /* Don't care about locking here */
349 if (gui_vfslist_warn_isempty(win_playq
))
352 if (gui_input_askyesno(_("Remove all songs from the playlist?")) == 0)
353 playq_song_remove_all();
357 gui_playq_song_randomize(void)
359 /* Don't care about locking here */
360 if (gui_vfslist_warn_isempty(win_playq
))
363 if (gui_input_askyesno(_("Randomize the playlist?")) == 0)
364 playq_song_randomize();
368 gui_playq_song_add_before(struct vfsref
*vr
)
370 struct vfsref
*vr_selected
;
373 vr_selected
= gui_vfslist_getselected(win_playq
);
374 if (vr_selected
== vfs_list_first(&playq_list
)) {
376 /* List is empty or adding before the first node */
377 playq_song_add_head(vr
);
379 playq_song_fast_add_before(vr
, vr_selected
,
380 gui_vfslist_getselectedidx(win_playq
));
386 gui_playq_song_add_after(struct vfsref
*vr
)
388 struct vfsref
*vr_selected
;
391 vr_selected
= gui_vfslist_getselected(win_playq
);
392 if (vr_selected
== vfs_list_last(&playq_list
)) {
394 /* List is empty or appending after the last node */
395 playq_song_add_tail(vr
);
397 playq_song_fast_add_after(vr
, vr_selected
,
398 gui_vfslist_getselectedidx(win_playq
));
404 gui_playq_song_move_up(void)
406 struct vfsref
*vr_selected
;
409 if (!gui_vfslist_warn_isempty(win_playq
)) {
410 vr_selected
= gui_vfslist_getselected(win_playq
);
411 if (vr_selected
== vfs_list_first(&playq_list
)) {
412 gui_msgbar_warn(_("The song is already at the "
413 "top of the playlist."));
415 playq_song_fast_move_up(vr_selected
,
416 gui_vfslist_getselectedidx(win_playq
));
423 gui_playq_song_move_down(void)
425 struct vfsref
*vr_selected
;
428 if (!gui_vfslist_warn_isempty(win_playq
)) {
429 vr_selected
= gui_vfslist_getselected(win_playq
);
430 if (vr_selected
== vfs_list_last(&playq_list
)) {
431 gui_msgbar_warn(_("The song is already at the "
432 "bottom of the playlist."));
434 playq_song_fast_move_down(vr_selected
,
435 gui_vfslist_getselectedidx(win_playq
));
442 gui_playq_song_move_head(void)
444 struct vfsref
*vr_selected
;
447 if (!gui_vfslist_warn_isempty(win_playq
)) {
448 vr_selected
= gui_vfslist_getselected(win_playq
);
449 if (vr_selected
== vfs_list_first(&playq_list
)) {
450 gui_msgbar_warn(_("The song is already at the "
451 "top of the playlist."));
453 playq_song_fast_move_head(vr_selected
,
454 gui_vfslist_getselectedidx(win_playq
));
461 gui_playq_song_move_tail(void)
463 struct vfsref
*vr_selected
;
466 if (!gui_vfslist_warn_isempty(win_playq
)) {
467 vr_selected
= gui_vfslist_getselected(win_playq
);
468 if (vr_selected
== vfs_list_last(&playq_list
)) {
469 gui_msgbar_warn(_("The song is already at the "
470 "bottom of the playlist."));
472 playq_song_fast_move_tail(vr_selected
,
473 gui_vfslist_getselectedidx(win_playq
));
480 gui_playq_song_select(void)
483 if (!gui_vfslist_warn_isempty(win_playq
))
484 playq_song_fast_select(gui_vfslist_getselected(win_playq
));
489 gui_playq_searchnext(const struct vfsmatch
*vm
)
494 ret
= gui_vfslist_searchnext(win_playq
, vm
);
501 gui_playq_setfocus(int focus
)
504 gui_vfslist_setfocus(win_playq
, focus
);
509 gui_playq_fullpath(void)
512 gui_vfslist_fullpath(win_playq
);
518 * @brief Show the result of the volume setting routines.
521 gui_playq_volume_show(int nval
)
526 gui_msgbar_warn(_("Failed to adjust the volume."));
528 str
= g_strdup_printf(_("Volume: %d%%"), nval
);
529 gui_msgbar_warn(str
);
535 gui_playq_volume_up(void)
539 nval
= audio_output_volume_up();
540 gui_playq_volume_show(nval
);
544 gui_playq_volume_down(void)
548 nval
= audio_output_volume_down();
549 gui_playq_volume_show(nval
);
551 #endif /* BUILD_VOLUME */
554 gui_playq_gotofolder(void)
559 if (gui_vfslist_warn_isempty(win_playq
)) {
562 vr
= gui_vfslist_getselected(win_playq
);
565 gui_browser_gotofile(vr
);