blob: 54451992a76367584b5f58c971e369c2f65e3739 [file] [log] [blame]
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +00001/***************************************************************************
2 *
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2003 Hardeep Sidhu
12 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000013 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000017 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
Kevin Ferrare8517ed82005-11-16 02:12:25 +000022/*
23 * Kevin Ferrare 2005/10/16
24 * multi-screen support, rewrote a lot of code
25 */
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000026#include <string.h>
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000027#include "playlist.h"
Linus Nielsen Feltzing8a237a82005-04-04 12:06:29 +000028#include "audio.h"
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000029#include "screens.h"
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000030#include "settings.h"
31#include "icons.h"
32#include "menu.h"
33#include "plugin.h"
Hardeep Sidhu107ebc52004-01-26 17:05:21 +000034#include "keyboard.h"
Jonathan Gordon36a2e302007-04-18 13:03:01 +000035#include "filetypes.h"
Hardeep Sidhu107ebc52004-01-26 17:05:21 +000036#include "onplay.h"
Jörg Hohensohnfa97f162004-03-19 22:15:53 +000037#include "talk.h"
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +000038#include "misc.h"
Linus Nielsen Feltzing6e0436f2005-06-23 01:31:26 +000039#include "action.h"
Linus Nielsen Feltzing2f56ee92006-01-17 14:15:47 +000040#include "debug.h"
Tomas Salfischberger4ec9dbd2006-03-05 00:16:34 +000041#include "backlight.h"
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000042
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000043#include "lang.h"
44
Hardeep Sidhu107ebc52004-01-26 17:05:21 +000045#include "playlist_viewer.h"
Jonathan Gordonce584282007-02-12 05:02:42 +000046#include "playlist_catalog.h"
Kevin Ferrare8517ed82005-11-16 02:12:25 +000047#include "icon.h"
48#include "list.h"
Kevin Ferrare8517ed82005-11-16 02:12:25 +000049#include "splash.h"
Hardeep Sidhu0cca6ca2006-02-09 09:09:32 +000050#include "playlist_menu.h"
Thomas Martitz2d4bf622014-01-11 10:46:37 +010051#include "menus/exported_menus.h"
Jonathan Gordond1fd4f02011-07-21 06:40:21 +000052#include "yesno.h"
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000053
54/* Maximum number of tracks we can have loaded at one time */
Kevin Ferrare6a53c332005-11-16 02:55:26 +000055#define MAX_PLAYLIST_ENTRIES 200
Kevin Ferrare8517ed82005-11-16 02:12:25 +000056
57/* The number of items between the selected one and the end/start of
58 * the buffer under which the buffer must reload */
Peter D'Hoye3c1e9ca2008-09-07 20:09:11 +000059#define MIN_BUFFER_MARGIN (screens[0].getnblines()+1)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000060
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000061/* Information about a specific track */
62struct playlist_entry {
63 char *name; /* Formatted track name */
64 int index; /* Playlist index */
65 int display_index; /* Display index */
66 bool queued; /* Is track queued? */
Miika Pekkarinenc52f7f12005-10-21 06:40:45 +000067 bool skipped; /* Is track marked as bad? */
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +000068};
69
Kevin Ferrare8517ed82005-11-16 02:12:25 +000070enum direction
71{
72 FORWARD,
73 BACKWARD
74};
75
76struct playlist_buffer
77{
78 char *name_buffer; /* Buffer used to store track names */
79 int buffer_size; /* Size of name buffer */
80
81 int first_index; /* Real index of first track loaded inside
82 the buffer */
83
84 enum direction direction; /* Direction of the buffer (if the buffer
85 was loaded BACKWARD, the last track in
86 the buffer has a real index < to the
87 real index of the the first track)*/
88
89 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
90 int num_loaded; /* Number of track entries loaded in buffer */
91};
92
93/* Global playlist viewer settings */
94struct playlist_viewer {
Dave Hooper11925212009-07-02 23:03:46 +000095 struct playlist_info* playlist; /* playlist being viewed */
96 int num_tracks; /* Number of tracks in playlist */
97 int current_playing_track; /* Index of current playing track */
98 int selected_track; /* The selected track, relative (first is 0) */
99 int moving_track; /* The track to move, relative (first is 0)
100 or -1 if nothing is currently being moved */
101 int moving_playlist_index; /* Playlist-relative index (as opposed to
102 viewer-relative index) of moving track */
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000103 struct playlist_buffer buffer;
104};
105
106static struct playlist_viewer viewer;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000107
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000108/* Used when viewing playlists on disk */
Hardeep Sidhu30743942005-11-19 18:19:46 +0000109static struct playlist_info temp_playlist;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000110
Jens Arnold2597a132006-12-25 14:01:47 +0000111static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
112 int names_buffer_size);
113static void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
114 enum direction direction);
115static int playlist_entry_load(struct playlist_entry *entry, int index,
116 char* name_buffer, int remaining_size);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000117
Jens Arnold2597a132006-12-25 14:01:47 +0000118static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
119 int index);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000120
121static bool playlist_viewer_init(struct playlist_viewer * viewer,
Steve Bavinad95df22008-05-12 17:52:50 +0000122 const char* filename, bool reload);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000123
Jens Arnold8fb33612004-08-18 01:09:31 +0000124static void format_name(char* dest, const char* src);
Hardeep Sidhu30743942005-11-19 18:19:46 +0000125static void format_line(const struct playlist_entry* track, char* str,
126 int len);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000127
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000128static bool update_playlist(bool force);
129static int onplay_menu(int index);
130
Jens Arnold2597a132006-12-25 14:01:47 +0000131static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
132 int names_buffer_size)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000133{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000134 pb->name_buffer = names_buffer;
135 pb->buffer_size = names_buffer_size;
136 pb->first_index = 0;
137 pb->num_loaded = 0;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000138}
Hardeep Sidhu30743942005-11-19 18:19:46 +0000139
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000140/*
141 * Loads the entries following 'index' in the playlist buffer
142 */
Jens Arnold2597a132006-12-25 14:01:47 +0000143static void playlist_buffer_load_entries(struct playlist_buffer *pb, int index,
144 enum direction direction)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000145{
146 int num_entries = viewer.num_tracks;
147 char* p = pb->name_buffer;
148 int remaining = pb->buffer_size;
149 int i;
150
151 pb->first_index = index;
152 if (num_entries > MAX_PLAYLIST_ENTRIES)
153 num_entries = MAX_PLAYLIST_ENTRIES;
154
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000155 for (i = 0; i < num_entries; i++)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000156 {
157 int len = playlist_entry_load(&(pb->tracks[i]), index, p, remaining);
158 if (len < 0)
159 {
160 /* Out of name buffer space */
161 num_entries = i;
162 break;
163 }
164
165 p += len;
166 remaining -= len;
167
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000168 if(direction == FORWARD)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000169 index++;
170 else
171 index--;
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000172 index += viewer.num_tracks;
173 index %= viewer.num_tracks;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000174 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000175 pb->direction = direction;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000176 pb->num_loaded = i;
177}
178
Purdea Andrei323282f2012-06-18 12:37:22 +0300179/* playlist_buffer_load_entries_screen()
180 * This function is called when the currently selected item gets too close
181 * to the start or the end of the loaded part of the playlis, or when
182 * the list callback requests a playlist item that has not been loaded yet
183 *
184 * reference_track is either the currently selected track, or the track that
185 * has been requested by the callback, and has not been loaded yet.
186 */
Jens Arnold2597a132006-12-25 14:01:47 +0000187static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
Purdea Andrei323282f2012-06-18 12:37:22 +0300188 enum direction direction,
189 int reference_track)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000190{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000191 if (direction == FORWARD)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000192 {
Purdea Andrei323282f2012-06-18 12:37:22 +0300193 int min_start = reference_track-2*screens[0].getnblines();
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000194 while (min_start < 0)
195 min_start += viewer.num_tracks;
Linus Nielsen Feltzing2f56ee92006-01-17 14:15:47 +0000196 min_start %= viewer.num_tracks;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000197 playlist_buffer_load_entries(pb, min_start, FORWARD);
198 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000199 else
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000200 {
Purdea Andrei323282f2012-06-18 12:37:22 +0300201 int max_start = reference_track+2*screens[0].getnblines();
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000202 max_start %= viewer.num_tracks;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000203 playlist_buffer_load_entries(pb, max_start, BACKWARD);
204 }
205}
206
Jens Arnold2597a132006-12-25 14:01:47 +0000207static int playlist_entry_load(struct playlist_entry *entry, int index,
208 char* name_buffer, int remaining_size)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000209{
210 struct playlist_track_info info;
211 int len;
212
213 /* Playlist viewer orders songs based on display index. We need to
214 convert to real playlist index to access track */
215 index = (index + playlist_get_first_index(viewer.playlist)) %
216 viewer.num_tracks;
217 if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
218 return -1;
219
220 len = strlen(info.filename) + 1;
221
222 if (len <= remaining_size)
223 {
224 strcpy(name_buffer, info.filename);
225
226 entry->name = name_buffer;
227 entry->index = info.index;
228 entry->display_index = info.display_index;
229 entry->queued = info.attr & PLAYLIST_ATTR_QUEUED;
230 entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
231 return len;
232 }
233 return -1;
234}
235
Nils Wallménius791e0922008-04-09 21:47:43 +0000236static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000237{
238 int buffer_index;
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000239 if (pb->direction == FORWARD)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000240 {
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000241 if (index >= pb->first_index)
242 buffer_index = index-pb->first_index;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000243 else /* rotation : track0 in buffer + requested track */
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000244 buffer_index = viewer.num_tracks-pb->first_index+index;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000245 }
246 else
247 {
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000248 if (index <= pb->first_index)
249 buffer_index = pb->first_index-index;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000250 else /* rotation : track0 in buffer + dist from the last track
251 to the requested track (num_tracks-requested track) */
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000252 buffer_index = pb->first_index+viewer.num_tracks-index;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000253 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000254 return buffer_index;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000255}
256
257#define distance(a, b) \
258 a>b? (a) - (b) : (b) - (a)
Nils Wallménius791e0922008-04-09 21:47:43 +0000259static bool playlist_buffer_needs_reload(struct playlist_buffer* pb,
260 int track_index)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000261{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000262 if (pb->num_loaded == viewer.num_tracks)
263 return false;
264 int selected_index = playlist_buffer_get_index(pb, track_index);
265 int first_buffer_index = playlist_buffer_get_index(pb, pb->first_index);
266 int distance_beginning = distance(selected_index, first_buffer_index);
267 if (distance_beginning < MIN_BUFFER_MARGIN)
268 return true;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000269
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000270 if (pb->num_loaded - distance_beginning < MIN_BUFFER_MARGIN)
271 return true;
272 return false;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000273}
274
Jens Arnold2597a132006-12-25 14:01:47 +0000275static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer *pb,
276 int index)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000277{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000278 int buffer_index = playlist_buffer_get_index(pb, index);
Purdea Andrei323282f2012-06-18 12:37:22 +0300279 /* Make sure that we are not returning an invalid pointer.
280 In some cases, when scrolling really fast, it could happen that a reqested track
281 has not been pre-loaded */
282 if (buffer_index < 0) {
283 playlist_buffer_load_entries_screen(&viewer.buffer,
284 pb->direction == FORWARD ? BACKWARD : FORWARD,
285 index);
286
287 } else if (buffer_index >= pb->num_loaded) {
288 playlist_buffer_load_entries_screen(&viewer.buffer,
289 pb->direction,
290 index);
291 }
292 buffer_index = playlist_buffer_get_index(pb, index);
293 if (buffer_index < 0 || buffer_index >= pb->num_loaded) {
294 /* This really shouldn't happen. If this happens, then
295 the name_buffer is probably too small to store enough
296 titles to fill the screen, and preload data in the short
297 direction.
298
299 If this happens then scrolling performance will probably
300 be quite low, but it's better then having Data Abort errors */
301 playlist_buffer_load_entries(pb, index, FORWARD);
302 buffer_index = playlist_buffer_get_index(pb, index);
303 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000304 return &(pb->tracks[buffer_index]);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000305}
306
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000307/* Initialize the playlist viewer. */
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000308static bool playlist_viewer_init(struct playlist_viewer * viewer,
Steve Bavinad95df22008-05-12 17:52:50 +0000309 const char* filename, bool reload)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000310{
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000311 char* buffer;
Michael Sevakiseb85f142007-04-21 19:20:20 +0000312 size_t buffer_size;
Jonathan Gordon3d44a202007-04-26 08:21:29 +0000313 bool is_playing = audio_status() & (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE);
314 bool have_list = filename || is_playing;
Frank Gevaerts94b4a8b2011-08-01 08:38:32 +0000315 if (!have_list && (global_status.resume_index != -1))
Jonathan Gordon3d44a202007-04-26 08:21:29 +0000316 {
317 /* Try to restore the list from control file */
318 have_list = (playlist_resume() != -1);
319 }
Peter D'Hoyeb8ded7d2007-08-25 16:05:58 +0000320 if (!have_list && (playlist_amount() > 0))
321 {
322 /*If dynamic playlist still exists, view it anyway even
323 if playback has reached the end of the playlist */
324 have_list = true;
325 }
Jonathan Gordon3d44a202007-04-26 08:21:29 +0000326 if (!have_list)
327 {
328 /* Nothing to view, exit */
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400329 splash(HZ, ID2P(LANG_CATALOG_NO_PLAYLISTS));
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000330 return false;
Jonathan Gordon3d44a202007-04-26 08:21:29 +0000331 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000332
Michael Sevakiseb85f142007-04-21 19:20:20 +0000333 buffer = plugin_get_buffer(&buffer_size);
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000334 if (!buffer)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000335 return false;
336
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000337 if (!filename)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000338 viewer->playlist = NULL;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000339 else
340 {
341 /* Viewing playlist on disk */
Steve Bavinad95df22008-05-12 17:52:50 +0000342 const char *dir, *file;
343 char *temp_ptr;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000344 char *index_buffer = NULL;
Michael Sevakis26d242a2007-04-21 18:38:25 +0000345 ssize_t index_buffer_size = 0;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000346
347 viewer->playlist = &temp_playlist;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000348
349 /* Separate directory from filename */
350 temp_ptr = strrchr(filename+1,'/');
351 if (temp_ptr)
352 {
353 *temp_ptr = 0;
354 dir = filename;
355 file = temp_ptr + 1;
356 }
357 else
358 {
359 dir = "/";
360 file = filename+1;
361 }
362
363 if (is_playing)
364 {
365 /* Something is playing, use half the plugin buffer for playlist
366 indices */
367 index_buffer_size = buffer_size / 2;
368 index_buffer = buffer;
369 }
370
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000371 playlist_create_ex(viewer->playlist, dir, file, index_buffer,
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000372 index_buffer_size, buffer+index_buffer_size,
373 buffer_size-index_buffer_size);
374
375 if (temp_ptr)
376 *temp_ptr = '/';
377
378 buffer += index_buffer_size;
379 buffer_size -= index_buffer_size;
380 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000381 playlist_buffer_init(&viewer->buffer, buffer, buffer_size);
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000382
Dave Hooper11925212009-07-02 23:03:46 +0000383 viewer->moving_track = -1;
Dave Hooperbe0cd732009-07-07 22:40:47 +0000384 viewer->moving_playlist_index = -1;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000385
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000386 if (!reload)
Hardeep Sidhu30743942005-11-19 18:19:46 +0000387 {
Linus Nielsen Feltzing0b8149f2006-01-17 12:30:03 +0000388 if (viewer->playlist)
Hardeep Sidhu30743942005-11-19 18:19:46 +0000389 viewer->selected_track = 0;
Linus Nielsen Feltzing0b8149f2006-01-17 12:30:03 +0000390 else
391 viewer->selected_track = playlist_get_display_index() - 1;
Hardeep Sidhu30743942005-11-19 18:19:46 +0000392 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000393
394 if (!update_playlist(true))
395 return false;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000396 return true;
397}
398
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000399/* Format trackname for display purposes */
Jens Arnold8fb33612004-08-18 01:09:31 +0000400static void format_name(char* dest, const char* src)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000401{
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000402 switch (global_settings.playlist_viewer_track_display)
403 {
404 case 0:
405 default:
406 {
Antoine Cellerier59dc18d2006-08-10 21:08:44 +0000407 /* Only display the filename */
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000408 char* p = strrchr(src, '/');
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000409
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000410 strcpy(dest, p+1);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000411
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000412 /* Remove the extension */
Nils Wallménius4acae4d2007-11-18 14:12:01 +0000413 strrsplt(dest, '.');
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000414
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000415 break;
416 }
417 case 1:
418 /* Full path */
419 strcpy(dest, src);
420 break;
421 }
422}
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000423
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000424/* Format display line */
Hardeep Sidhu30743942005-11-19 18:19:46 +0000425static void format_line(const struct playlist_entry* track, char* str,
426 int len)
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000427{
428 char name[MAX_PATH];
Miika Pekkarinenc52f7f12005-10-21 06:40:45 +0000429 char *skipped = "";
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000430
431 format_name(name, track->name);
432
Miika Pekkarinenc52f7f12005-10-21 06:40:45 +0000433 if (track->skipped)
434 skipped = "(ERR) ";
Zakk Roberts34ad56d2006-04-03 04:13:26 +0000435
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000436 if (global_settings.playlist_viewer_indices)
437 /* Display playlist index */
Miika Pekkarinenc52f7f12005-10-21 06:40:45 +0000438 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000439 else
Miika Pekkarinenc52f7f12005-10-21 06:40:45 +0000440 snprintf(str, len, "%s%s", skipped, name);
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000441
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000442}
443
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000444/* Update playlist in case something has changed or forced */
445static bool update_playlist(bool force)
446{
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000447 if (!viewer.playlist)
448 playlist_get_resume_info(&viewer.current_playing_track);
449 else
450 viewer.current_playing_track = -1;
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000451 int nb_tracks = playlist_amount_ex(viewer.playlist);
452 force = force || nb_tracks != viewer.num_tracks;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000453 if (force)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000454 {
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000455 /* Reload tracks */
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000456 viewer.num_tracks = nb_tracks;
Hardeep Sidhuc7f304e2006-04-20 07:30:28 +0000457 if (viewer.num_tracks <= 0)
Dave Hooper40444992009-07-02 22:45:00 +0000458 {
459 global_status.resume_index = -1;
460 global_status.resume_offset = -1;
Michael Sevakis31b71222013-07-14 07:59:39 -0400461 global_status.resume_elapsed = -1;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000462 return false;
Dave Hooper40444992009-07-02 22:45:00 +0000463 }
Purdea Andrei323282f2012-06-18 12:37:22 +0300464 playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD,
465 viewer.selected_track);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000466 if (viewer.buffer.num_loaded <= 0)
Dave Hooper40444992009-07-02 22:45:00 +0000467 {
468 global_status.resume_index = -1;
469 global_status.resume_offset = -1;
Michael Sevakis31b71222013-07-14 07:59:39 -0400470 global_status.resume_elapsed = -1;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000471 return false;
Dave Hooper40444992009-07-02 22:45:00 +0000472 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000473 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000474 return true;
475}
476
477/* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
Thomas Whited5ead5c2015-03-11 22:43:42 +0100478 Returns -1 if USB attached, 0 if no playlist change, 1 if playlist
479 changed, 2 if a track was removed from the playlist */
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000480static int onplay_menu(int index)
481{
Jonathan Gordona2740d92007-04-25 11:20:19 +0000482 int result, ret = 0;
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000483 struct playlist_entry * current_track =
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000484 playlist_buffer_get_track(&viewer.buffer, index);
Nils Wallméniusb3113672007-08-05 19:19:39 +0000485 MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL,
Jonathan Gordon061ff422011-07-20 14:54:10 +0000486 ID2P(LANG_CURRENT_PLAYLIST), ID2P(LANG_CATALOG),
Jonathan Gordone03faf82011-09-17 09:29:19 +0000487 ID2P(LANG_REMOVE), ID2P(LANG_MOVE), ID2P(LANG_SHUFFLE),
Thomas Martitz2d4bf622014-01-11 10:46:37 +0100488 ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
489 ID2P(LANG_PLAYLISTVIEWER_SETTINGS));
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000490 bool current = (current_track->index == viewer.current_playing_track);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000491
Jonathan Gordon5ca15392008-03-26 03:35:24 +0000492 result = do_menu(&menu_items, NULL, NULL, false);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000493 if (result == MENU_ATTACHED_USB)
Jonathan Gordonce584282007-02-12 05:02:42 +0000494 {
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000495 ret = -1;
Jonathan Gordonce584282007-02-12 05:02:42 +0000496 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000497 else if (result >= 0)
498 {
499 /* Abort current move */
Dave Hooper11925212009-07-02 23:03:46 +0000500 viewer.moving_track = -1;
Dave Hooperbe0cd732009-07-07 22:40:47 +0000501 viewer.moving_playlist_index = -1;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000502
503 switch (result)
504 {
505 case 0:
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000506 /* playlist */
507 onplay_show_playlist_menu(current_track->name);
508 ret = 0;
509 break;
510 case 1:
511 /* add to catalog */
512 onplay_show_playlist_cat_menu(current_track->name);
513 ret = 0;
514 break;
515 case 2:
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000516 /* delete track */
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000517 playlist_delete(viewer.playlist, current_track->index);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000518 if (current)
519 {
Hardeep Sidhuc7f304e2006-04-20 07:30:28 +0000520 if (playlist_amount_ex(viewer.playlist) <= 0)
521 audio_stop();
522 else
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000523 {
Hardeep Sidhuc7f304e2006-04-20 07:30:28 +0000524 /* Start playing new track except if it's the lasttrack
525 track in the playlist and repeat mode is disabled */
526 current_track =
527 playlist_buffer_get_track(&viewer.buffer, index);
528 if (current_track->display_index!=viewer.num_tracks ||
529 global_settings.repeat_mode == REPEAT_ALL)
530 {
Michael Sevakis31b71222013-07-14 07:59:39 -0400531 audio_play(0, 0);
Hardeep Sidhuc7f304e2006-04-20 07:30:28 +0000532 viewer.current_playing_track = -1;
533 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000534 }
535 }
Thomas Whited5ead5c2015-03-11 22:43:42 +0100536 ret = 2;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000537 break;
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000538 case 3:
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000539 /* move track */
Dave Hooper11925212009-07-02 23:03:46 +0000540 viewer.moving_track = index;
541 viewer.moving_playlist_index = current_track->index;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000542 ret = 0;
543 break;
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000544 case 4:
Jonathan Gordone03faf82011-09-17 09:29:19 +0000545 /* shuffle */
546 playlist_randomise(viewer.playlist, current_tick, false);
547 ret = 1;
548 break;
549 case 5:
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000550 /* save playlist */
551 save_playlist_screen(viewer.playlist);
Jonathan Gordonce584282007-02-12 05:02:42 +0000552 ret = 0;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000553 break;
Thomas Martitz2d4bf622014-01-11 10:46:37 +0100554 case 6:
555 /* playlist viewer settings */
556 result = do_menu(&viewer_settings_menu, NULL, NULL, false);
557 ret = (result == MENU_ATTACHED_USB) ? -1 : 0;
558 break;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000559 }
560 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000561 return ret;
562}
563
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000564/* View current playlist */
Thomas Martitzc19e5362010-02-20 19:06:39 +0000565enum playlist_viewer_result playlist_viewer(void)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000566{
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000567 return playlist_viewer_ex(NULL);
568}
569
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000570static int get_track_num(struct playlist_viewer *local_viewer,
571 int selected_item)
Antoine Cellerier24907002007-10-15 20:34:02 +0000572{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000573 if (local_viewer->moving_track >= 0)
Antoine Cellerier24907002007-10-15 20:34:02 +0000574 {
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000575 if (local_viewer->selected_track == selected_item)
Antoine Cellerier24907002007-10-15 20:34:02 +0000576 {
Dave Hooper11925212009-07-02 23:03:46 +0000577 return local_viewer->moving_track;
Antoine Cellerier24907002007-10-15 20:34:02 +0000578 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000579 else if (local_viewer->selected_track > selected_item
580 && selected_item >= local_viewer->moving_track)
Antoine Cellerier24907002007-10-15 20:34:02 +0000581 {
Dave Hooper11925212009-07-02 23:03:46 +0000582 return selected_item+1; /* move down */
Antoine Cellerier24907002007-10-15 20:34:02 +0000583 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000584 else if (local_viewer->selected_track < selected_item
585 && selected_item <= local_viewer->moving_track)
Antoine Cellerier24907002007-10-15 20:34:02 +0000586 {
Dave Hooper11925212009-07-02 23:03:46 +0000587 return selected_item-1; /* move up */
Antoine Cellerier24907002007-10-15 20:34:02 +0000588 }
589 }
590 return selected_item;
591}
592
Nils Wallménius3200d042009-08-20 16:47:44 +0000593static const char* playlist_callback_name(int selected_item,
594 void *data,
595 char *buffer,
596 size_t buffer_len)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000597{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000598 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data;
Nils Wallménius791e0922008-04-09 21:47:43 +0000599
600 int track_num = get_track_num(local_viewer, selected_item);
601 struct playlist_entry *track =
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000602 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
Nils Wallménius791e0922008-04-09 21:47:43 +0000603
Nils Wallménius68489612008-04-09 15:25:17 +0000604 format_line(track, buffer, buffer_len);
Nils Wallménius791e0922008-04-09 21:47:43 +0000605
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000606 return(buffer);
607}
608
609
Andrew Mahone1bc67c82009-07-11 00:22:26 +0000610static enum themable_icons playlist_callback_icons(int selected_item,
611 void *data)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000612{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000613 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data;
Nils Wallménius791e0922008-04-09 21:47:43 +0000614
615 int track_num = get_track_num(local_viewer, selected_item);
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000616 struct playlist_entry *track =
Nils Wallménius791e0922008-04-09 21:47:43 +0000617 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
618
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000619 if (track->index == local_viewer->current_playing_track)
620 {
621 /* Current playing track */
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000622 return Icon_Audio;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000623 }
Dave Hooper11925212009-07-02 23:03:46 +0000624 else if (track->index == local_viewer->moving_playlist_index)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000625 {
626 /* Track we are moving */
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000627 return Icon_Moving;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000628 }
629 else if (track->queued)
630 {
631 /* Queued track */
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000632 return Icon_Queued;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000633 }
634 else
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000635 return Icon_NOICON;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000636}
637
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000638static int playlist_callback_voice(int selected_item, void *data)
Nils Wallméniusa0791172011-04-08 13:10:32 +0000639{
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000640 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400641 struct playlist_entry *track=
642 playlist_buffer_get_track(&(local_viewer->buffer),
643 selected_item);
644 (void)selected_item;
645 if(global_settings.playlist_viewer_icons) {
646 if (track->index == local_viewer->current_playing_track)
647 talk_id(LANG_NOW_PLAYING, true);
648 if (track->index == local_viewer->moving_track)
649 talk_id(VOICE_TRACK_TO_MOVE, true);
650 if (track->queued)
651 talk_id(VOICE_QUEUED, true);
Nils Wallméniusa0791172011-04-08 13:10:32 +0000652 }
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400653 if (track->skipped)
654 talk_id(VOICE_BAD_TRACK, true);
655 if (global_settings.playlist_viewer_indices)
Nils Wallméniusa0791172011-04-08 13:10:32 +0000656 talk_number(track->display_index, true);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400657
658 if(global_settings.playlist_viewer_track_display)
659 talk_fullpath(track->name, true);
660 else talk_file_or_spell(NULL, track->name, NULL, true);
661 if (viewer.moving_track != -1)
662 talk_ids(true,VOICE_PAUSE, VOICE_MOVING_TRACK);
Nils Wallméniusa0791172011-04-08 13:10:32 +0000663
664 return 0;
665}
666
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000667/* Main viewer function. Filename identifies playlist to be viewed. If NULL,
668 view current playlist. */
Thomas Martitzc19e5362010-02-20 19:06:39 +0000669enum playlist_viewer_result playlist_viewer_ex(const char* filename)
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000670{
Thomas Martitzc19e5362010-02-20 19:06:39 +0000671 enum playlist_viewer_result ret = PLAYLIST_VIEWER_OK;
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000672 bool exit = false; /* exit viewer */
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000673 int button;
Jonathan Gordond1fd4f02011-07-21 06:40:21 +0000674 bool dirty = false;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000675 struct gui_synclist playlist_lists;
676 if (!playlist_viewer_init(&viewer, filename, false))
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000677 goto exit;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000678
Jonathan Gordon835683b2011-08-07 08:39:56 +0000679 push_current_activity(ACTIVITY_PLAYLISTVIEWER);
Jonathan Gordon5ca15392008-03-26 03:35:24 +0000680 gui_synclist_init(&playlist_lists, playlist_callback_name,
681 &viewer, false, 1, NULL);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400682 gui_synclist_set_voice_callback(&playlist_lists,
683 global_settings.talk_file?
684 &playlist_callback_voice:NULL);
Kevin Ferrare15046f92005-11-16 17:23:49 +0000685 gui_synclist_set_icon_callback(&playlist_lists,
Hardeep Sidhu30743942005-11-19 18:19:46 +0000686 global_settings.playlist_viewer_icons?
687 &playlist_callback_icons:NULL);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000688 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
Nils Wallméniusb3113672007-08-05 19:19:39 +0000689 gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
Jonathan Gordoneeb1f3e2009-12-24 07:13:04 +0000690 gui_synclist_select_item(&playlist_lists, viewer.selected_track);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000691 gui_synclist_draw(&playlist_lists);
Nils Wallméniusa0791172011-04-08 13:10:32 +0000692 gui_synclist_speak_item(&playlist_lists);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000693 while (!exit)
694 {
Björn Stenberga108ec22004-01-14 00:13:04 +0000695 int track;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000696
Peter D'Hoyedf328132007-08-21 23:50:26 +0000697 if (global_status.resume_index != -1 && !viewer.playlist)
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000698 playlist_get_resume_info(&track);
699 else
700 track = -1;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000701
702 if (track != viewer.current_playing_track ||
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000703 playlist_amount_ex(viewer.playlist) != viewer.num_tracks)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000704 {
705 /* Playlist has changed (new track started?) */
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000706 if (!update_playlist(false))
Hardeep Sidhu1b446322004-04-15 06:12:02 +0000707 goto exit;
Peter D'Hoyedf328132007-08-21 23:50:26 +0000708 /*Needed because update_playlist gives wrong value when
709 playing is stopped*/
710 viewer.current_playing_track = track;
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000711 gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
Dave Hooper6c62b1b2009-11-25 22:48:15 +0000712
Hardeep Sidhu9a681dd2006-06-12 23:25:12 +0000713 gui_synclist_draw(&playlist_lists);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400714 gui_synclist_speak_item(&playlist_lists);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000715 }
716
Hardeep Sidhu1b446322004-04-15 06:12:02 +0000717 /* Timeout so we can determine if play status has changed */
Thomas Martitz16d44e92010-11-23 07:39:16 +0000718 bool res = list_do_action(CONTEXT_TREE, HZ/2,
Thomas Martitz30131032010-09-21 22:56:12 +0000719 &playlist_lists, &button, LIST_WRAP_UNLESS_HELD);
Thomas Martitzc4925f12010-10-02 20:15:35 +0000720 /* during moving, another redraw is going to be needed,
721 * since viewer.selected_track is updated too late (after the first draw)
722 * drawing the moving item needs it */
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000723 viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists);
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000724 if (res)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000725 {
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000726 bool reload = playlist_buffer_needs_reload(&viewer.buffer,
727 viewer.selected_track);
Thomas Martitzc4925f12010-10-02 20:15:35 +0000728 if (reload)
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000729 playlist_buffer_load_entries_screen(&viewer.buffer,
Purdea Andrei323282f2012-06-18 12:37:22 +0300730 button == ACTION_STD_NEXT ? FORWARD : BACKWARD,
731 viewer.selected_track);
Thomas Martitzc4925f12010-10-02 20:15:35 +0000732 if (reload || viewer.moving_track >= 0)
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000733 gui_synclist_draw(&playlist_lists);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000734 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000735 switch (button)
736 {
Peter D'Hoye734278b2007-04-12 21:28:58 +0000737 case ACTION_TREE_WPS:
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000738 case ACTION_STD_CANCEL:
Antoine Celleriera6d4e532007-12-15 17:14:04 +0000739 {
Dave Hooper11925212009-07-02 23:03:46 +0000740 if (viewer.moving_track >= 0)
Antoine Celleriera6d4e532007-12-15 17:14:04 +0000741 {
Dave Hooper11925212009-07-02 23:03:46 +0000742 viewer.selected_track = viewer.moving_track;
743 gui_synclist_select_item(&playlist_lists, viewer.moving_track);
744 viewer.moving_track = -1;
Dave Hooperbe0cd732009-07-07 22:40:47 +0000745 viewer.moving_playlist_index = -1;
Antoine Celleriera6d4e532007-12-15 17:14:04 +0000746 gui_synclist_draw(&playlist_lists);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400747 gui_synclist_speak_item(&playlist_lists);
Antoine Celleriera6d4e532007-12-15 17:14:04 +0000748 }
749 else
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000750 {
Antoine Celleriera6d4e532007-12-15 17:14:04 +0000751 exit = true;
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000752 ret = PLAYLIST_VIEWER_CANCEL;
753 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000754 break;
Antoine Celleriera6d4e532007-12-15 17:14:04 +0000755 }
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000756 case ACTION_STD_OK:
757 {
Hardeep Sidhu30743942005-11-19 18:19:46 +0000758 struct playlist_entry * current_track =
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000759 playlist_buffer_get_track(&viewer.buffer,
760 viewer.selected_track);
761
Dave Hooper11925212009-07-02 23:03:46 +0000762 if (viewer.moving_track >= 0)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000763 {
764 /* Move track */
Jonathan Gordon52ba1c62007-04-26 10:28:32 +0000765 int ret_val;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000766
Dave Hooper11925212009-07-02 23:03:46 +0000767 ret_val = playlist_move(viewer.playlist,
768 viewer.moving_playlist_index,
769 current_track->index);
Jonathan Gordon52ba1c62007-04-26 10:28:32 +0000770 if (ret_val < 0)
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400771 {
772 cond_talk_ids_fq(LANG_MOVE, LANG_FAILED);
Nils Wallménius01729e72008-08-15 08:27:39 +0000773 splashf(HZ, (unsigned char *)"%s %s", str(LANG_MOVE),
774 str(LANG_FAILED));
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400775 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000776 update_playlist(true);
Dave Hooper11925212009-07-02 23:03:46 +0000777 viewer.moving_track = -1;
Dave Hooperbe0cd732009-07-07 22:40:47 +0000778 viewer.moving_playlist_index = -1;
Jonathan Gordond1fd4f02011-07-21 06:40:21 +0000779 dirty = true;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000780 }
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000781 else if (!viewer.playlist)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000782 {
Hardeep Sidhu05741512005-06-23 17:31:44 +0000783 /* play new track */
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000784 if (!global_settings.party_mode)
785 {
Michael Sevakis31b71222013-07-14 07:59:39 -0400786 playlist_start(current_track->index, 0, 0);
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000787 update_playlist(false);
788 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000789 }
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000790 else if (!global_settings.party_mode)
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000791 {
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000792 int start_index = current_track->index;
793 if (!warn_on_pl_erase())
794 {
795 gui_synclist_draw(&playlist_lists);
796 break;
797 }
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000798 /* New playlist */
799 if (playlist_set_current(viewer.playlist) < 0)
800 goto exit;
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000801 if (global_settings.playlist_shuffle)
802 start_index = playlist_shuffle(current_tick, start_index);
Michael Sevakis31b71222013-07-14 07:59:39 -0400803 playlist_start(start_index, 0, 0);
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000804
805 /* Our playlist is now the current list */
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000806 if (!playlist_viewer_init(&viewer, NULL, true))
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000807 goto exit;
Jonathan Gordon97a4c1e2011-07-20 14:11:15 +0000808 exit = true;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000809 }
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000810 gui_synclist_draw(&playlist_lists);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400811 gui_synclist_speak_item(&playlist_lists);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000812
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000813 break;
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000814 }
815 case ACTION_STD_CONTEXT:
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000816 {
817 /* ON+PLAY menu */
Jonathan Gordon52ba1c62007-04-26 10:28:32 +0000818 int ret_val;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000819
Jonathan Gordon52ba1c62007-04-26 10:28:32 +0000820 ret_val = onplay_menu(viewer.selected_track);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000821
Jonathan Gordon52ba1c62007-04-26 10:28:32 +0000822 if (ret_val < 0)
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000823 {
Thomas Martitzc19e5362010-02-20 19:06:39 +0000824 ret = PLAYLIST_VIEWER_USB;
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000825 goto exit;
826 }
Dave Hooper40444992009-07-02 22:45:00 +0000827 else if (ret_val > 0)
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000828 {
829 /* Playlist changed */
Thomas Whited5ead5c2015-03-11 22:43:42 +0100830 if (ret_val == 2)
831 gui_synclist_del_item(&playlist_lists);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000832 update_playlist(true);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000833 if (viewer.num_tracks <= 0)
834 exit = true;
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000835 if (viewer.selected_track >= viewer.num_tracks)
Peter D'Hoyeb16137e2007-04-11 22:39:12 +0000836 viewer.selected_track = viewer.num_tracks-1;
Jonathan Gordond1fd4f02011-07-21 06:40:21 +0000837 dirty = true;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000838 }
Thomas Martitzfe73d752014-01-11 10:49:45 +0100839 /* the show_icons option in the playlist viewer settings
840 * menu might have changed */
841 gui_synclist_set_icon_callback(&playlist_lists,
842 global_settings.playlist_viewer_icons?
843 &playlist_callback_icons:NULL);
Kevin Ferrare8517ed82005-11-16 02:12:25 +0000844 gui_synclist_draw(&playlist_lists);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400845 gui_synclist_speak_item(&playlist_lists);
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000846 break;
847 }
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000848 case ACTION_STD_MENU:
Thomas Martitzc19e5362010-02-20 19:06:39 +0000849 ret = PLAYLIST_VIEWER_MAINMENU;
850 goto exit;
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000851 default:
852 if(default_event_handler(button) == SYS_USB_CONNECTED)
853 {
Thomas Martitzc19e5362010-02-20 19:06:39 +0000854 ret = PLAYLIST_VIEWER_USB;
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000855 goto exit;
856 }
857 break;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000858 }
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000859 }
860
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000861exit:
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400862 talk_shutup();
Jonathan Gordon835683b2011-08-07 08:39:56 +0000863 pop_current_activity();
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000864 if (viewer.playlist)
Jonathan Gordond1fd4f02011-07-21 06:40:21 +0000865 {
866 if(dirty && yesno_pop(ID2P(LANG_SAVE_CHANGES)))
867 save_playlist_screen(viewer.playlist);
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000868 playlist_close(viewer.playlist);
Jonathan Gordond1fd4f02011-07-21 06:40:21 +0000869 }
Hardeep Sidhu107ebc52004-01-26 17:05:21 +0000870 return ret;
Hardeep Sidhu00acdfa2003-12-10 00:11:25 +0000871}
Jens Arnold2597a132006-12-25 14:01:47 +0000872
Nils Wallménius3200d042009-08-20 16:47:44 +0000873static const char* playlist_search_callback_name(int selected_item, void * data,
874 char *buffer, size_t buffer_len)
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000875{
Nils Wallménius68489612008-04-09 15:25:17 +0000876 (void)buffer_len; /* this should probably be used */
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000877 int *found_indicies = (int*)data;
Zakk Roberts34ad56d2006-04-03 04:13:26 +0000878 static struct playlist_track_info track;
Nils Wallménius68489612008-04-09 15:25:17 +0000879 playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track);
880 format_name(buffer, track.filename);
Nils Wallménius3200d042009-08-20 16:47:44 +0000881 return buffer;
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000882}
883
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400884static int say_search_item(int selected_item, void *data)
885{
886 int *found_indicies = (int*)data;
887 static struct playlist_track_info track;
888 playlist_get_track_info(viewer.playlist,found_indicies[selected_item],&track);
889 if(global_settings.playlist_viewer_track_display)
890 talk_fullpath(track.filename, false);
891 else talk_file_or_spell(NULL, track.filename, NULL, false);
892 return 0;
893}
894
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000895bool search_playlist(void)
896{
897 char search_str[32] = "";
898 bool ret = false, exit = false;
899 int i, playlist_count;
Nils Wallméniusda012192008-10-10 21:19:56 +0000900 int found_indicies[MAX_PLAYLIST_ENTRIES];
901 int found_indicies_count = 0, last_found_count = -1;
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000902 int button;
903 struct gui_synclist playlist_lists;
904 struct playlist_track_info track;
Zakk Roberts34ad56d2006-04-03 04:13:26 +0000905
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000906 if (!playlist_viewer_init(&viewer, 0, false))
907 return ret;
Thomas Martitz18e40e02009-08-12 14:38:25 +0000908 if (kbd_input(search_str, sizeof(search_str)) < 0)
Zakk Roberts34ad56d2006-04-03 04:13:26 +0000909 return ret;
910 lcd_clear_display();
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000911 playlist_count = playlist_amount_ex(viewer.playlist);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400912 cond_talk_ids_fq(LANG_WAIT);
Nils Wallméniusda012192008-10-10 21:19:56 +0000913
914 cpu_boost(true);
915
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000916 for (i = 0; i < playlist_count &&
917 found_indicies_count < MAX_PLAYLIST_ENTRIES; i++)
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000918 {
Nils Wallméniusda012192008-10-10 21:19:56 +0000919 if (found_indicies_count != last_found_count)
920 {
921 splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), found_indicies_count,
922 str(LANG_OFF_ABORT));
923 last_found_count = found_indicies_count;
924 }
925
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000926 if (action_userabort(TIMEOUT_NOBLOCK))
Jonathan Gordon88882a82007-08-04 09:36:47 +0000927 break;
Nils Wallméniusda012192008-10-10 21:19:56 +0000928
929 playlist_get_track_info(viewer.playlist, i, &track);
930
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000931 if (strcasestr(track.filename,search_str))
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000932 found_indicies[found_indicies_count++] = track.index;
Nils Wallméniusda012192008-10-10 21:19:56 +0000933
Nils Wallménius173b4112008-09-29 19:29:42 +0000934 yield();
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000935 }
Nils Wallméniusda012192008-10-10 21:19:56 +0000936
937 cpu_boost(false);
938
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400939 cond_talk_ids_fq(TALK_ID(found_indicies_count, UNIT_INT),
940 LANG_PLAYLIST_SEARCH_MSG);
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000941 if (!found_indicies_count)
942 {
943 return ret;
944 }
945 backlight_on();
Nils Wallméniusda012192008-10-10 21:19:56 +0000946
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000947 gui_synclist_init(&playlist_lists, playlist_search_callback_name,
Jonathan Gordon5ca15392008-03-26 03:35:24 +0000948 found_indicies, false, 1, NULL);
Nils Wallméniusda012192008-10-10 21:19:56 +0000949 gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON);
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000950 gui_synclist_set_icon_callback(&playlist_lists, NULL);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400951 if(global_settings.talk_file)
952 gui_synclist_set_voice_callback(&playlist_lists,
953 global_settings.talk_file?
954 &say_search_item:NULL);
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000955 gui_synclist_set_nb_items(&playlist_lists, found_indicies_count);
956 gui_synclist_select_item(&playlist_lists, 0);
957 gui_synclist_draw(&playlist_lists);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400958 gui_synclist_speak_item(&playlist_lists);
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000959 while (!exit)
960 {
Thomas Martitz138ee632010-09-21 22:55:24 +0000961 if (list_do_action(CONTEXT_LIST, HZ/4,
962 &playlist_lists, &button, LIST_WRAP_UNLESS_HELD))
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000963 continue;
964 switch (button)
965 {
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000966 case ACTION_STD_CANCEL:
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000967 exit = true;
968 break;
969
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000970 case ACTION_STD_OK:
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000971 {
972 int sel = gui_synclist_get_sel_pos(&playlist_lists);
Michael Sevakis31b71222013-07-14 07:59:39 -0400973 playlist_start(found_indicies[sel], 0, 0);
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000974 exit = 1;
Thomas Martitzaa01ee32010-09-20 23:10:19 +0000975 }
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000976 break;
Nils Wallméniusda012192008-10-10 21:19:56 +0000977
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000978 default:
Nils Wallméniuse7c6ba62011-04-08 13:39:56 +0000979 if (default_event_handler(button) == SYS_USB_CONNECTED)
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000980 {
981 ret = true;
982 exit = true;
983 }
984 break;
985 }
986 }
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400987 talk_shutup();
Tomas Salfischbergerc2e86cd2006-03-04 23:53:09 +0000988 return ret;
989}