summaryrefslogtreecommitdiff
path: root/apps/playlist_viewer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playlist_viewer.c')
-rw-r--r--apps/playlist_viewer.c397
1 files changed, 255 insertions, 142 deletions
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 579eba5a61..d556f3b557 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -50,6 +50,7 @@
50#include "playlist_menu.h" 50#include "playlist_menu.h"
51#include "menus/exported_menus.h" 51#include "menus/exported_menus.h"
52#include "yesno.h" 52#include "yesno.h"
53#include "playback.h"
53 54
54/* Maximum number of tracks we can have loaded at one time */ 55/* Maximum number of tracks we can have loaded at one time */
55#define MAX_PLAYLIST_ENTRIES 200 56#define MAX_PLAYLIST_ENTRIES 200
@@ -60,11 +61,10 @@
60 61
61/* Information about a specific track */ 62/* Information about a specific track */
62struct playlist_entry { 63struct playlist_entry {
63 char *name; /* Formatted track name */ 64 char *name; /* track path */
64 int index; /* Playlist index */ 65 int index; /* Playlist index */
65 int display_index; /* Display index */ 66 int display_index; /* Display index */
66 bool queued; /* Is track queued? */ 67 int attr; /* Is track queued?; Is track marked as bad?*/
67 bool skipped; /* Is track marked as bad? */
68}; 68};
69 69
70enum direction 70enum direction
@@ -86,6 +86,8 @@ enum pv_onplay_result {
86 86
87struct playlist_buffer 87struct playlist_buffer
88{ 88{
89 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
90
89 char *name_buffer; /* Buffer used to store track names */ 91 char *name_buffer; /* Buffer used to store track names */
90 int buffer_size; /* Size of name buffer */ 92 int buffer_size; /* Size of name buffer */
91 93
@@ -97,7 +99,6 @@ struct playlist_buffer
97 the buffer has a real index < to the 99 the buffer has a real index < to the
98 real index of the the first track)*/ 100 real index of the the first track)*/
99 101
100 struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
101 int num_loaded; /* Number of track entries loaded in buffer */ 102 int num_loaded; /* Number of track entries loaded in buffer */
102}; 103};
103 104
@@ -116,6 +117,12 @@ struct playlist_viewer {
116 struct playlist_buffer buffer; 117 struct playlist_buffer buffer;
117}; 118};
118 119
120struct playlist_search_data
121{
122 struct playlist_track_info *track;
123 int *found_indicies;
124};
125
119static struct playlist_viewer viewer; 126static struct playlist_viewer viewer;
120 127
121/* Used when viewing playlists on disk */ 128/* Used when viewing playlists on disk */
@@ -136,8 +143,7 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer,
136 const char* filename, bool reload, 143 const char* filename, bool reload,
137 int *most_recent_selection); 144 int *most_recent_selection);
138 145
139static void format_name(char* dest, const char* src); 146static void format_line(struct playlist_entry* track, char* str,
140static void format_line(const struct playlist_entry* track, char* str,
141 int len); 147 int len);
142 148
143static bool update_playlist(bool force); 149static bool update_playlist(bool force);
@@ -154,6 +160,27 @@ static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
154 pb->num_loaded = 0; 160 pb->num_loaded = 0;
155} 161}
156 162
163static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
164{
165 int buffer_index;
166 if (pb->direction == FORWARD)
167 {
168 if (index >= pb->first_index)
169 buffer_index = index-pb->first_index;
170 else /* rotation : track0 in buffer + requested track */
171 buffer_index = viewer.num_tracks-pb->first_index+index;
172 }
173 else
174 {
175 if (index <= pb->first_index)
176 buffer_index = pb->first_index-index;
177 else /* rotation : track0 in buffer + dist from the last track
178 to the requested track (num_tracks-requested track) */
179 buffer_index = pb->first_index+viewer.num_tracks-index;
180 }
181 return buffer_index;
182}
183
157/* 184/*
158 * Loads the entries following 'index' in the playlist buffer 185 * Loads the entries following 'index' in the playlist buffer
159 */ 186 */
@@ -195,7 +222,7 @@ static void playlist_buffer_load_entries(struct playlist_buffer *pb, int index,
195 222
196/* playlist_buffer_load_entries_screen() 223/* playlist_buffer_load_entries_screen()
197 * This function is called when the currently selected item gets too close 224 * This function is called when the currently selected item gets too close
198 * to the start or the end of the loaded part of the playlis, or when 225 * to the start or the end of the loaded part of the playlist, or when
199 * the list callback requests a playlist item that has not been loaded yet 226 * the list callback requests a playlist item that has not been loaded yet
200 * 227 *
201 * reference_track is either the currently selected track, or the track that 228 * reference_track is either the currently selected track, or the track that
@@ -205,20 +232,40 @@ static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
205 enum direction direction, 232 enum direction direction,
206 int reference_track) 233 int reference_track)
207{ 234{
235 int start;
208 if (direction == FORWARD) 236 if (direction == FORWARD)
209 { 237 {
210 int min_start = reference_track-2*screens[0].getnblines(); 238 int min_start = reference_track-2*screens[0].getnblines();
211 while (min_start < 0) 239 while (min_start < 0)
212 min_start += viewer.num_tracks; 240 min_start += viewer.num_tracks;
213 min_start %= viewer.num_tracks; 241 start = min_start % viewer.num_tracks;
214 playlist_buffer_load_entries(pb, min_start, FORWARD);
215 } 242 }
216 else 243 else
217 { 244 {
218 int max_start = reference_track+2*screens[0].getnblines(); 245 int max_start = reference_track+2*screens[0].getnblines();
219 max_start %= viewer.num_tracks; 246 start = max_start % viewer.num_tracks;
220 playlist_buffer_load_entries(pb, max_start, BACKWARD);
221 } 247 }
248
249 playlist_buffer_load_entries(pb, start, direction);
250}
251
252static bool retrieve_id3_tags(const int index, const char* name, struct mp3entry *id3, int flags)
253{
254 bool id3_retrieval_successful = false;
255
256 if (!viewer.playlist &&
257 (audio_status() & AUDIO_STATUS_PLAY) &&
258 (playlist_get_resume_info(&viewer.current_playing_track) == index))
259 {
260 copy_mp3entry(id3, audio_current_track()); /* retrieve id3 from RAM */
261 id3_retrieval_successful = true;
262 }
263 else
264 {
265 /* Read from disk, the database, doesn't store frequency, file size or codec (g4470) ChrisS*/
266 id3_retrieval_successful = get_metadata_ex(id3, -1, name, flags);
267 }
268 return id3_retrieval_successful;
222} 269}
223 270
224static int playlist_entry_load(struct playlist_entry *entry, int index, 271static int playlist_entry_load(struct playlist_entry *entry, int index,
@@ -234,43 +281,26 @@ static int playlist_entry_load(struct playlist_entry *entry, int index,
234 if (playlist_get_track_info(viewer.playlist, index, &info) < 0) 281 if (playlist_get_track_info(viewer.playlist, index, &info) < 0)
235 return -1; 282 return -1;
236 283
237 len = strlen(info.filename) + 1; 284 len = strlcpy(name_buffer, info.filename, remaining_size) + 1;
238 285
239 if (len <= remaining_size) 286 if (global_settings.playlist_viewer_track_display >
287 PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH && len <= remaining_size)
240 { 288 {
241 strcpy(name_buffer, info.filename); 289 /* Allocate space for the id3viewc if the option is enabled */
290 len += MAX_PATH + 1;
291 }
242 292
293 if (len <= remaining_size)
294 {
243 entry->name = name_buffer; 295 entry->name = name_buffer;
244 entry->index = info.index; 296 entry->index = info.index;
245 entry->display_index = info.display_index; 297 entry->display_index = info.display_index;
246 entry->queued = info.attr & PLAYLIST_ATTR_QUEUED; 298 entry->attr = info.attr & (PLAYLIST_ATTR_SKIPPED | PLAYLIST_ATTR_QUEUED);
247 entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED;
248 return len; 299 return len;
249 } 300 }
250 return -1; 301 return -1;
251} 302}
252 303
253static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
254{
255 int buffer_index;
256 if (pb->direction == FORWARD)
257 {
258 if (index >= pb->first_index)
259 buffer_index = index-pb->first_index;
260 else /* rotation : track0 in buffer + requested track */
261 buffer_index = viewer.num_tracks-pb->first_index+index;
262 }
263 else
264 {
265 if (index <= pb->first_index)
266 buffer_index = pb->first_index-index;
267 else /* rotation : track0 in buffer + dist from the last track
268 to the requested track (num_tracks-requested track) */
269 buffer_index = pb->first_index+viewer.num_tracks-index;
270 }
271 return buffer_index;
272}
273
274#define distance(a, b) \ 304#define distance(a, b) \
275 a>b? (a) - (b) : (b) - (a) 305 a>b? (a) - (b) : (b) - (a)
276static bool playlist_buffer_needs_reload(struct playlist_buffer* pb, 306static bool playlist_buffer_needs_reload(struct playlist_buffer* pb,
@@ -433,48 +463,123 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer,
433} 463}
434 464
435/* Format trackname for display purposes */ 465/* Format trackname for display purposes */
436static void format_name(char* dest, const char* src) 466static void format_name(char* dest, const char* src, size_t bufsz)
437{ 467{
438 switch (global_settings.playlist_viewer_track_display) 468 switch (global_settings.playlist_viewer_track_display)
439 { 469 {
440 case 0: 470 case PLAYLIST_VIEWER_ENTRY_SHOW_FILE_NAME:
471 case PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM: /* If loading from tags failed, only display the file name */
472 case PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE: /* If loading from tags failed, only display the file name */
441 default: 473 default:
442 { 474 {
443 /* Only display the filename */ 475 /* Only display the filename */
444 char* p = strrchr(src, '/'); 476 char* p = strrchr(src, '/');
445 477 strlcpy(dest, p+1, bufsz);
446 strcpy(dest, p+1);
447
448 /* Remove the extension */ 478 /* Remove the extension */
449 strrsplt(dest, '.'); 479 strrsplt(dest, '.');
450
451 break; 480 break;
452 } 481 }
453 case 1: 482 case PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH:
454 /* Full path */ 483 /* Full path */
455 strcpy(dest, src); 484 strlcpy(dest, src, bufsz);
456 break; 485 break;
457 } 486 }
458} 487}
459 488
460/* Format display line */ 489/* Format display line */
461static void format_line(const struct playlist_entry* track, char* str, 490static void format_line(struct playlist_entry* track, char* str,
462 int len) 491 int len)
463{ 492{
464 char name[MAX_PATH]; 493 char *id3viewc = NULL;
465 char *skipped = ""; 494 char *skipped = "";
466 495 if (track->attr & PLAYLIST_ATTR_SKIPPED)
467 format_name(name, track->name);
468
469 if (track->skipped)
470 skipped = "(ERR) "; 496 skipped = "(ERR) ";
471 497 if (!(track->attr & PLAYLIST_ATTR_RETRIEVE_ID3_ATTEMPTED) &&
472 if (global_settings.playlist_viewer_indices) 498 (global_settings.playlist_viewer_track_display ==
473 /* Display playlist index */ 499 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM ||
474 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name); 500 global_settings.playlist_viewer_track_display ==
501 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE
502 ))
503 {
504 track->attr |= PLAYLIST_ATTR_RETRIEVE_ID3_ATTEMPTED;
505 struct mp3entry id3;
506 bool retrieve_success = retrieve_id3_tags(track->index, track->name,
507 &id3, METADATA_EXCLUDE_ID3_PATH);
508 if (retrieve_success)
509 {
510 if (!id3viewc)
511 {
512 id3viewc = track->name + strlen(track->name) + 1;
513 }
514 struct mp3entry * pid3 = &id3;
515 id3viewc[0] = '\0';
516 if (global_settings.playlist_viewer_track_display ==
517 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM)
518 {
519 /* Title & Album */
520 if (pid3->title && pid3->title[0] != '\0')
521 {
522 char* cur_str = id3viewc;
523 int title_len = strlen(pid3->title);
524 int rem_space = MAX_PATH;
525 for (int i = 0; i < title_len && rem_space > 0; i++)
526 {
527 cur_str[0] = pid3->title[i];
528 cur_str++;
529 rem_space--;
530 }
531 if (rem_space > 10)
532 {
533 cur_str[0] = (char) ' ';
534 cur_str[1] = (char) '-';
535 cur_str[2] = (char) ' ';
536 cur_str += 3;
537 rem_space -= 3;
538 cur_str = strmemccpy(cur_str, pid3->album && pid3->album[0] != '\0' ?
539 pid3->album : (char*) str(LANG_TAGNAVI_UNTAGGED), rem_space);
540 if (cur_str)
541 track->attr |= PLAYLIST_ATTR_RETRIEVE_ID3_SUCCEEDED;
542 }
543 }
544 }
545 else if (global_settings.playlist_viewer_track_display ==
546 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE)
547 {
548 /* Just the title */
549 if (pid3->title && pid3->title[0] != '\0' &&
550 strmemccpy(id3viewc, pid3->title, MAX_PATH)
551 )
552 track->attr |= PLAYLIST_ATTR_RETRIEVE_ID3_SUCCEEDED;
553 }
554 /* Yield to reduce as much as possible the perceived UI lag,
555 because retrieving id3 tags is an expensive operation */
556 yield();
557 }
558 }
559
560 if (!(track->attr & PLAYLIST_ATTR_RETRIEVE_ID3_SUCCEEDED))
561 {
562 /* Simply use a formatted file name */
563 char name[MAX_PATH];
564 format_name(name, track->name, sizeof(name));
565 if (global_settings.playlist_viewer_indices)
566 /* Display playlist index */
567 snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
568 else
569 snprintf(str, len, "%s%s", skipped, name);
570 }
475 else 571 else
476 snprintf(str, len, "%s%s", skipped, name); 572 {
477 573 if (!id3viewc)
574 {
575 id3viewc = track->name + strlen(track->name) + 1;
576 }
577 if (global_settings.playlist_viewer_indices)
578 /* Display playlist index */
579 snprintf(str, len, "%d. %s%s", track->display_index, skipped, id3viewc);
580 else
581 snprintf(str, len, "%s%s", skipped, id3viewc);
582 }
478} 583}
479 584
480/* Update playlist in case something has changed or forced */ 585/* Update playlist in case something has changed or forced */
@@ -485,8 +590,8 @@ static bool update_playlist(bool force)
485 else 590 else
486 viewer.current_playing_track = -1; 591 viewer.current_playing_track = -1;
487 int nb_tracks = playlist_amount_ex(viewer.playlist); 592 int nb_tracks = playlist_amount_ex(viewer.playlist);
488 force = force || nb_tracks != viewer.num_tracks; 593
489 if (force) 594 if (force || nb_tracks != viewer.num_tracks)
490 { 595 {
491 /* Reload tracks */ 596 /* Reload tracks */
492 viewer.num_tracks = nb_tracks; 597 viewer.num_tracks = nb_tracks;
@@ -513,41 +618,25 @@ static bool update_playlist(bool force)
513static enum pv_onplay_result show_track_info(const struct playlist_entry *current_track) 618static enum pv_onplay_result show_track_info(const struct playlist_entry *current_track)
514{ 619{
515 struct mp3entry id3; 620 struct mp3entry id3;
516 bool id3_retrieval_successful = false; 621 bool id3_retrieval_successful = retrieve_id3_tags(current_track->index, current_track->name, &id3, 0);
517
518 if (!viewer.playlist &&
519 (audio_status() & AUDIO_STATUS_PLAY) &&
520 (playlist_get_resume_info(&viewer.current_playing_track) == current_track->index))
521 {
522 copy_mp3entry(&id3, audio_current_track()); /* retrieve id3 from RAM */
523 id3_retrieval_successful = true;
524 }
525 else
526 {
527 int fd = open(current_track->name, O_RDONLY);
528 if (fd >= 0)
529 {
530 if (get_metadata(&id3, fd, current_track->name))
531 id3_retrieval_successful = true;
532 close(fd);
533 }
534 }
535 622
536 return id3_retrieval_successful && 623 return id3_retrieval_successful &&
537 browse_id3_ex(&id3, viewer.playlist, current_track->display_index, 624 browse_id3_ex(&id3, viewer.playlist, current_track->display_index,
538 viewer.num_tracks, NULL, 1) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED; 625 viewer.num_tracks, NULL, 1) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED;
539} 626}
540 627
541 628#if defined(HAVE_HOTKEY) || defined(HAVE_TAGCACHE)
542#ifdef HAVE_HOTKEY 629static enum pv_onplay_result
543static enum pv_onplay_result open_with(const struct playlist_entry *current_track) 630 open_with_plugin(const struct playlist_entry *current_track,
631 const char* plugin_name,
632 int (*loadplugin)(const char* plugin, const char* file))
544{ 633{
545 char selected_track[MAX_PATH]; 634 char selected_track[MAX_PATH];
546 close_playlist_viewer(); /* don't pop activity yet – relevant for plugin_load */ 635 close_playlist_viewer(); /* don't pop activity yet – relevant for plugin_load */
547 636
548 strmemccpy(selected_track, current_track->name, sizeof(selected_track)); 637 strmemccpy(selected_track, current_track->name, sizeof(selected_track));
549 638
550 int plugin_return = filetype_list_viewers(selected_track); 639 int plugin_return = loadplugin(plugin_name, selected_track);
551 pop_current_activity_without_refresh(); 640 pop_current_activity_without_refresh();
552 641
553 switch (plugin_return) 642 switch (plugin_return)
@@ -560,29 +649,27 @@ static enum pv_onplay_result open_with(const struct playlist_entry *current_trac
560 return PV_ONPLAY_CLOSED; 649 return PV_ONPLAY_CLOSED;
561 } 650 }
562} 651}
652
653#ifdef HAVE_HOTKEY
654static int list_viewers(const char* plugin, const char* file)
655{
656 /* dummy function to match prototype with filetype_load_plugin */
657 (void)plugin;
658 return filetype_list_viewers(file);
659}
660static enum pv_onplay_result open_with(const struct playlist_entry *current_track)
661{
662 return open_with_plugin(current_track, "", &list_viewers);
663}
563#endif /* HAVE_HOTKEY */ 664#endif /* HAVE_HOTKEY */
564 665
565#ifdef HAVE_TAGCACHE 666#ifdef HAVE_TAGCACHE
566static enum pv_onplay_result open_pictureflow(const struct playlist_entry *current_track) 667static enum pv_onplay_result open_pictureflow(const struct playlist_entry *current_track)
567{ 668{
568 char selected_track[MAX_PATH]; 669 return open_with_plugin(current_track, "pictureflow", &filetype_load_plugin);
569 close_playlist_viewer(); /* don't pop activity yet – relevant for plugin_load */
570
571 strmemccpy(selected_track, current_track->name, sizeof(selected_track));
572 int plugin_return = filetype_load_plugin((void *)"pictureflow", selected_track);
573 pop_current_activity_without_refresh();
574
575 switch (plugin_return)
576 {
577 case PLUGIN_USB_CONNECTED:
578 return PV_ONPLAY_USB_CLOSED;
579 case PLUGIN_GOTO_WPS:
580 return PV_ONPLAY_WPS_CLOSED;
581 default:
582 return PV_ONPLAY_CLOSED;
583 }
584} 670}
585#endif 671#endif
672#endif /*defined(HAVE_HOTKEY) || defined(HAVE_TAGCACHE)*/
586 673
587static enum pv_onplay_result delete_track(int current_track_index, 674static enum pv_onplay_result delete_track(int current_track_index,
588 int index, bool current_was_playing) 675 int index, bool current_was_playing)
@@ -676,10 +763,23 @@ static enum pv_onplay_result onplay_menu(int index)
676 ret = viewer.playlist ? PV_ONPLAY_UNCHANGED : PV_ONPLAY_SAVED; 763 ret = viewer.playlist ? PV_ONPLAY_UNCHANGED : PV_ONPLAY_SAVED;
677 break; 764 break;
678 case 7: 765 case 7:
766 {
767 int last_display = global_settings.playlist_viewer_track_display;
679 /* playlist viewer settings */ 768 /* playlist viewer settings */
680 result = do_menu(&viewer_settings_menu, NULL, NULL, false); 769 result = do_menu(&viewer_settings_menu, NULL, NULL, false);
681 ret = (result == MENU_ATTACHED_USB) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED; 770
771
772 if (result == MENU_ATTACHED_USB)
773 ret = PV_ONPLAY_USB;
774 else
775 {
776 if (last_display != global_settings.playlist_viewer_track_display)
777 update_playlist(true);/* reload buffer */
778
779 ret = PV_ONPLAY_UNCHANGED;
780 }
682 break; 781 break;
782 }
683#ifdef HAVE_TAGCACHE 783#ifdef HAVE_TAGCACHE
684 case 8: 784 case 8:
685 ret = open_pictureflow(current_track); 785 ret = open_pictureflow(current_track);
@@ -719,16 +819,18 @@ static int get_track_num(struct playlist_viewer *local_viewer,
719 return selected_item; 819 return selected_item;
720} 820}
721 821
822static struct playlist_entry* pv_get_track(struct playlist_viewer *local_viewer, int selected_item)
823{
824 int track_num = get_track_num(local_viewer, selected_item);
825 return playlist_buffer_get_track(&(local_viewer->buffer), track_num);
826}
827
722static const char* playlist_callback_name(int selected_item, 828static const char* playlist_callback_name(int selected_item,
723 void *data, 829 void *data,
724 char *buffer, 830 char *buffer,
725 size_t buffer_len) 831 size_t buffer_len)
726{ 832{
727 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data; 833 struct playlist_entry *track = pv_get_track(data, selected_item);
728
729 int track_num = get_track_num(local_viewer, selected_item);
730 struct playlist_entry *track =
731 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
732 834
733 format_line(track, buffer, buffer_len); 835 format_line(track, buffer, buffer_len);
734 836
@@ -740,10 +842,7 @@ static enum themable_icons playlist_callback_icons(int selected_item,
740 void *data) 842 void *data)
741{ 843{
742 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data; 844 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data;
743 845 struct playlist_entry *track = pv_get_track(local_viewer, selected_item);
744 int track_num = get_track_num(local_viewer, selected_item);
745 struct playlist_entry *track =
746 playlist_buffer_get_track(&(local_viewer->buffer), track_num);
747 846
748 if (track->index == local_viewer->current_playing_track) 847 if (track->index == local_viewer->current_playing_track)
749 { 848 {
@@ -755,7 +854,7 @@ static enum themable_icons playlist_callback_icons(int selected_item,
755 /* Track we are moving */ 854 /* Track we are moving */
756 return Icon_Moving; 855 return Icon_Moving;
757 } 856 }
758 else if (track->queued) 857 else if (track->attr & PLAYLIST_ATTR_QUEUED)
759 { 858 {
760 /* Queued track */ 859 /* Queued track */
761 return Icon_Queued; 860 return Icon_Queued;
@@ -767,26 +866,37 @@ static enum themable_icons playlist_callback_icons(int selected_item,
767static int playlist_callback_voice(int selected_item, void *data) 866static int playlist_callback_voice(int selected_item, void *data)
768{ 867{
769 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data; 868 struct playlist_viewer *local_viewer = (struct playlist_viewer *)data;
770 struct playlist_entry *track= 869 struct playlist_entry *track = pv_get_track(local_viewer, selected_item);
771 playlist_buffer_get_track(&(local_viewer->buffer), 870
772 selected_item);
773 (void)selected_item;
774 if(global_settings.playlist_viewer_icons) { 871 if(global_settings.playlist_viewer_icons) {
775 if (track->index == local_viewer->current_playing_track) 872 if (track->index == local_viewer->current_playing_track)
776 talk_id(LANG_NOW_PLAYING, true); 873 talk_id(LANG_NOW_PLAYING, true);
777 if (track->index == local_viewer->moving_track) 874 if (track->index == local_viewer->moving_track)
778 talk_id(VOICE_TRACK_TO_MOVE, true); 875 talk_id(VOICE_TRACK_TO_MOVE, true);
779 if (track->queued) 876 if (track->attr & PLAYLIST_ATTR_QUEUED)
780 talk_id(VOICE_QUEUED, true); 877 talk_id(VOICE_QUEUED, true);
781 } 878 }
782 if (track->skipped) 879 if (track->attr & PLAYLIST_ATTR_SKIPPED)
783 talk_id(VOICE_BAD_TRACK, true); 880 talk_id(VOICE_BAD_TRACK, true);
784 if (global_settings.playlist_viewer_indices) 881 if (global_settings.playlist_viewer_indices)
785 talk_number(track->display_index, true); 882 talk_number(track->display_index, true);
786 883
787 if(global_settings.playlist_viewer_track_display) 884 switch(global_settings.playlist_viewer_track_display)
788 talk_fullpath(track->name, true); 885 {
789 else talk_file_or_spell(NULL, track->name, NULL, true); 886 case PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH:
887 /*full path*/
888 talk_fullpath(track->name, true);
889 break;
890 default:
891 case PLAYLIST_VIEWER_ENTRY_SHOW_FILE_NAME:
892 /*filename only*/
893 case PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM:
894 /* If loading from tags failed, only talk the file name */
895 case PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE:
896 /* If loading from tags failed, only talk the file name */
897 talk_file_or_spell(NULL, track->name, NULL, true);
898 break;
899 }
790 if (viewer.moving_track != -1) 900 if (viewer.moving_track != -1)
791 talk_ids(true,VOICE_PAUSE, VOICE_MOVING_TRACK); 901 talk_ids(true,VOICE_PAUSE, VOICE_MOVING_TRACK);
792 902
@@ -959,16 +1069,17 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename,
959 viewer.moving_track = -1; 1069 viewer.moving_track = -1;
960 viewer.moving_playlist_index = -1; 1070 viewer.moving_playlist_index = -1;
961 } 1071 }
1072 else if (global_settings.party_mode)
1073 {
1074 /* Nothing to do */
1075 }
962 else if (!viewer.playlist) 1076 else if (!viewer.playlist)
963 { 1077 {
964 /* play new track */ 1078 /* play new track */
965 if (!global_settings.party_mode) 1079 playlist_start(current_track->index, 0, 0);
966 { 1080 update_playlist(false);
967 playlist_start(current_track->index, 0, 0);
968 update_playlist(false);
969 }
970 } 1081 }
971 else if (!global_settings.party_mode) 1082 else
972 { 1083 {
973 int start_index = current_track->index; 1084 int start_index = current_track->index;
974 if (!warn_on_pl_erase()) 1085 if (!warn_on_pl_erase())
@@ -1095,7 +1206,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename,
1095 } 1206 }
1096 } 1207 }
1097 else 1208 else
1098 onplay(current_track->name, FILE_ATTR_AUDIO, CONTEXT_STD, true); 1209 onplay(current_track->name, FILE_ATTR_AUDIO, CONTEXT_STD, true, ONPLAY_NO_CUSTOMACTION);
1099 break; 1210 break;
1100 } 1211 }
1101#endif /* HAVE_HOTKEY */ 1212#endif /* HAVE_HOTKEY */
@@ -1132,22 +1243,20 @@ static void close_playlist_viewer(void)
1132static const char* playlist_search_callback_name(int selected_item, void * data, 1243static const char* playlist_search_callback_name(int selected_item, void * data,
1133 char *buffer, size_t buffer_len) 1244 char *buffer, size_t buffer_len)
1134{ 1245{
1135 (void)buffer_len; /* this should probably be used */ 1246 struct playlist_search_data *s_data = data;
1136 int *found_indicies = (int*)data; 1247 playlist_get_track_info(viewer.playlist, s_data->found_indicies[selected_item], s_data->track);
1137 static struct playlist_track_info track; 1248 format_name(buffer, s_data->track->filename, buffer_len);
1138 playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track);
1139 format_name(buffer, track.filename);
1140 return buffer; 1249 return buffer;
1141} 1250}
1142 1251
1143static int say_search_item(int selected_item, void *data) 1252static int say_search_item(int selected_item, void *data)
1144{ 1253{
1145 int *found_indicies = (int*)data; 1254 struct playlist_search_data *s_data = data;
1146 static struct playlist_track_info track; 1255 playlist_get_track_info(viewer.playlist, s_data->found_indicies[selected_item], s_data->track);
1147 playlist_get_track_info(viewer.playlist,found_indicies[selected_item],&track); 1256 if(global_settings.playlist_viewer_track_display == PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH)
1148 if(global_settings.playlist_viewer_track_display) 1257 /* full path*/
1149 talk_fullpath(track.filename, false); 1258 talk_fullpath(s_data->track->filename, false);
1150 else talk_file_or_spell(NULL, track.filename, NULL, false); 1259 else talk_file_or_spell(NULL, s_data->track->filename, NULL, false);
1151 return 0; 1260 return 0;
1152} 1261}
1153 1262
@@ -1159,6 +1268,7 @@ bool search_playlist(void)
1159 int found_indicies[MAX_PLAYLIST_ENTRIES]; 1268 int found_indicies[MAX_PLAYLIST_ENTRIES];
1160 int found_indicies_count = 0, last_found_count = -1; 1269 int found_indicies_count = 0, last_found_count = -1;
1161 int button; 1270 int button;
1271 int track_display = global_settings.playlist_viewer_track_display;
1162 struct gui_synclist playlist_lists; 1272 struct gui_synclist playlist_lists;
1163 struct playlist_track_info track; 1273 struct playlist_track_info track;
1164 1274
@@ -1186,8 +1296,12 @@ bool search_playlist(void)
1186 break; 1296 break;
1187 1297
1188 playlist_get_track_info(viewer.playlist, i, &track); 1298 playlist_get_track_info(viewer.playlist, i, &track);
1299 const char *trackname = track.filename;
1300 if (track_display != PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH)
1301 /* if we only display filename only search filename */
1302 trackname = strrchr(track.filename, '/');
1189 1303
1190 if (strcasestr(track.filename,search_str)) 1304 if (trackname && strcasestr(trackname, search_str))
1191 found_indicies[found_indicies_count++] = track.index; 1305 found_indicies[found_indicies_count++] = track.index;
1192 1306
1193 yield(); 1307 yield();
@@ -1202,11 +1316,10 @@ bool search_playlist(void)
1202 return ret; 1316 return ret;
1203 } 1317 }
1204 backlight_on(); 1318 backlight_on();
1205 1319 struct playlist_search_data s_data = {.track = &track, .found_indicies = found_indicies};
1206 gui_synclist_init(&playlist_lists, playlist_search_callback_name, 1320 gui_synclist_init(&playlist_lists, playlist_search_callback_name,
1207 found_indicies, false, 1, NULL); 1321 &s_data, false, 1, NULL);
1208 gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON); 1322 gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON);
1209 gui_synclist_set_icon_callback(&playlist_lists, NULL);
1210 if(global_settings.talk_file) 1323 if(global_settings.talk_file)
1211 gui_synclist_set_voice_callback(&playlist_lists, 1324 gui_synclist_set_voice_callback(&playlist_lists,
1212 global_settings.talk_file? 1325 global_settings.talk_file?