diff options
Diffstat (limited to 'apps/playlist_viewer.c')
-rw-r--r-- | apps/playlist_viewer.c | 397 |
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 */ |
62 | struct playlist_entry { | 63 | struct 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 | ||
70 | enum direction | 70 | enum direction |
@@ -86,6 +86,8 @@ enum pv_onplay_result { | |||
86 | 86 | ||
87 | struct playlist_buffer | 87 | struct 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 | ||
120 | struct playlist_search_data | ||
121 | { | ||
122 | struct playlist_track_info *track; | ||
123 | int *found_indicies; | ||
124 | }; | ||
125 | |||
119 | static struct playlist_viewer viewer; | 126 | static 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 | ||
139 | static void format_name(char* dest, const char* src); | 146 | static void format_line(struct playlist_entry* track, char* str, |
140 | static void format_line(const struct playlist_entry* track, char* str, | ||
141 | int len); | 147 | int len); |
142 | 148 | ||
143 | static bool update_playlist(bool force); | 149 | static 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 | ||
163 | static 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 | |||
252 | static 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 | ||
224 | static int playlist_entry_load(struct playlist_entry *entry, int index, | 271 | static 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 | ||
253 | static 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) |
276 | static bool playlist_buffer_needs_reload(struct playlist_buffer* pb, | 306 | static 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 */ |
436 | static void format_name(char* dest, const char* src) | 466 | static 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 */ |
461 | static void format_line(const struct playlist_entry* track, char* str, | 490 | static 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) | |||
513 | static enum pv_onplay_result show_track_info(const struct playlist_entry *current_track) | 618 | static 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 | 629 | static enum pv_onplay_result |
543 | static 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 | ||
654 | static 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 | } | ||
660 | static 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 |
566 | static enum pv_onplay_result open_pictureflow(const struct playlist_entry *current_track) | 667 | static 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 | ||
587 | static enum pv_onplay_result delete_track(int current_track_index, | 674 | static 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 | ||
822 | static 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 | |||
722 | static const char* playlist_callback_name(int selected_item, | 828 | static 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, | |||
767 | static int playlist_callback_voice(int selected_item, void *data) | 866 | static 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) | |||
1132 | static const char* playlist_search_callback_name(int selected_item, void * data, | 1243 | static 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 | ||
1143 | static int say_search_item(int selected_item, void *data) | 1252 | static 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? |