summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/lang/english.lang28
-rw-r--r--apps/lang/francais.lang28
-rw-r--r--apps/playlist.h2
-rw-r--r--apps/playlist_viewer.c205
-rw-r--r--apps/settings.h7
-rw-r--r--apps/settings_list.c8
6 files changed, 223 insertions, 55 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index c518d3573c..1ee1ffac0f 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -2032,6 +2032,34 @@
2032 </voice> 2032 </voice>
2033</phrase> 2033</phrase>
2034<phrase> 2034<phrase>
2035 id: LANG_DISPLAY_TITLEALBUM_FROMTAGS
2036 desc: track display options
2037 user: core
2038 <source>
2039 *: "Title & Album from ID3 tags"
2040 </source>
2041 <dest>
2042 *: "Title & Album from ID3 tags"
2043 </dest>
2044 <voice>
2045 *: "Title and Album from tags"
2046 </voice>
2047</phrase>
2048<phrase>
2049 id: LANG_DISPLAY_TITLE_FROMTAGS
2050 desc: track display options
2051 user: core
2052 <source>
2053 *: "Title from ID3 tags"
2054 </source>
2055 <dest>
2056 *: "Title from ID3 tags"
2057 </dest>
2058 <voice>
2059 *: "Title from tags"
2060 </voice>
2061</phrase>
2062<phrase>
2035 id: LANG_BUILDING_DATABASE 2063 id: LANG_BUILDING_DATABASE
2036 desc: splash database building progress 2064 desc: splash database building progress
2037 user: core 2065 user: core
diff --git a/apps/lang/francais.lang b/apps/lang/francais.lang
index 518b48fb96..b8883d4997 100644
--- a/apps/lang/francais.lang
+++ b/apps/lang/francais.lang
@@ -2005,6 +2005,34 @@
2005 </voice> 2005 </voice>
2006</phrase> 2006</phrase>
2007<phrase> 2007<phrase>
2008 id: LANG_DISPLAY_TITLEALBUM_FROMTAGS
2009 desc: track display options
2010 user: core
2011 <source>
2012 *: "Title & Album from ID3 tags"
2013 </source>
2014 <dest>
2015 *: "Titre & Album depuis les tags ID3"
2016 </dest>
2017 <voice>
2018 *: "Titre et Album depuis les tags"
2019 </voice>
2020</phrase>
2021<phrase>
2022 id: LANG_DISPLAY_TITLE_FROMTAGS
2023 desc: track display options
2024 user: core
2025 <source>
2026 *: "Title from ID3 tags"
2027 </source>
2028 <dest>
2029 *: "Titre depuis les tags ID3"
2030 </dest>
2031 <voice>
2032 *: "Titre depuis les tags"
2033 </voice>
2034</phrase>
2035<phrase>
2008 id: LANG_BUILDING_DATABASE 2036 id: LANG_BUILDING_DATABASE
2009 desc: splash database building progress 2037 desc: splash database building progress
2010 user: core 2038 user: core
diff --git a/apps/playlist.h b/apps/playlist.h
index f7426df9a3..2fb1ce100e 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -33,6 +33,8 @@
33#define PLAYLIST_ATTR_QUEUED 0x01 33#define PLAYLIST_ATTR_QUEUED 0x01
34#define PLAYLIST_ATTR_INSERTED 0x02 34#define PLAYLIST_ATTR_INSERTED 0x02
35#define PLAYLIST_ATTR_SKIPPED 0x04 35#define PLAYLIST_ATTR_SKIPPED 0x04
36#define PLAYLIST_ATTR_RETRIEVE_ID3_ATTEMPTED 0x08
37#define PLAYLIST_ATTR_RETRIEVE_ID3_SUCCEEDED 0x10
36 38
37#define PLAYLIST_DISPLAY_COUNT 10 39#define PLAYLIST_DISPLAY_COUNT 10
38 40
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 5bf547a3fc..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
@@ -142,7 +143,7 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer,
142 const char* filename, bool reload, 143 const char* filename, bool reload,
143 int *most_recent_selection); 144 int *most_recent_selection);
144 145
145static void format_line(const struct playlist_entry* track, char* str, 146static void format_line(struct playlist_entry* track, char* str,
146 int len); 147 int len);
147 148
148static bool update_playlist(bool force); 149static bool update_playlist(bool force);
@@ -159,6 +160,27 @@ static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
159 pb->num_loaded = 0; 160 pb->num_loaded = 0;
160} 161}
161 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
162/* 184/*
163 * Loads the entries following 'index' in the playlist buffer 185 * Loads the entries following 'index' in the playlist buffer
164 */ 186 */
@@ -227,6 +249,25 @@ static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb,
227 playlist_buffer_load_entries(pb, start, direction); 249 playlist_buffer_load_entries(pb, start, direction);
228} 250}
229 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;
269}
270
230static int playlist_entry_load(struct playlist_entry *entry, int index, 271static int playlist_entry_load(struct playlist_entry *entry, int index,
231 char* name_buffer, int remaining_size) 272 char* name_buffer, int remaining_size)
232{ 273{
@@ -242,6 +283,13 @@ static int playlist_entry_load(struct playlist_entry *entry, int index,
242 283
243 len = strlcpy(name_buffer, info.filename, remaining_size) + 1; 284 len = strlcpy(name_buffer, info.filename, remaining_size) + 1;
244 285
286 if (global_settings.playlist_viewer_track_display >
287 PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH && len <= remaining_size)
288 {
289 /* Allocate space for the id3viewc if the option is enabled */
290 len += MAX_PATH + 1;
291 }
292
245 if (len <= remaining_size) 293 if (len <= remaining_size)
246 { 294 {
247 entry->name = name_buffer; 295 entry->name = name_buffer;
@@ -253,27 +301,6 @@ static int playlist_entry_load(struct playlist_entry *entry, int index,
253 return -1; 301 return -1;
254} 302}
255 303
256static int playlist_buffer_get_index(struct playlist_buffer *pb, int index)
257{
258 int buffer_index;
259 if (pb->direction == FORWARD)
260 {
261 if (index >= pb->first_index)
262 buffer_index = index-pb->first_index;
263 else /* rotation : track0 in buffer + requested track */
264 buffer_index = viewer.num_tracks-pb->first_index+index;
265 }
266 else
267 {
268 if (index <= pb->first_index)
269 buffer_index = pb->first_index-index;
270 else /* rotation : track0 in buffer + dist from the last track
271 to the requested track (num_tracks-requested track) */
272 buffer_index = pb->first_index+viewer.num_tracks-index;
273 }
274 return buffer_index;
275}
276
277#define distance(a, b) \ 304#define distance(a, b) \
278 a>b? (a) - (b) : (b) - (a) 305 a>b? (a) - (b) : (b) - (a)
279static bool playlist_buffer_needs_reload(struct playlist_buffer* pb, 306static bool playlist_buffer_needs_reload(struct playlist_buffer* pb,
@@ -440,7 +467,9 @@ static void format_name(char* dest, const char* src, size_t bufsz)
440{ 467{
441 switch (global_settings.playlist_viewer_track_display) 468 switch (global_settings.playlist_viewer_track_display)
442 { 469 {
443 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 */
444 default: 473 default:
445 { 474 {
446 /* Only display the filename */ 475 /* Only display the filename */
@@ -450,7 +479,7 @@ static void format_name(char* dest, const char* src, size_t bufsz)
450 strrsplt(dest, '.'); 479 strrsplt(dest, '.');
451 break; 480 break;
452 } 481 }
453 case 1: 482 case PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH:
454 /* Full path */ 483 /* Full path */
455 strlcpy(dest, src, bufsz); 484 strlcpy(dest, src, bufsz);
456 break; 485 break;
@@ -458,22 +487,99 @@ static void format_name(char* dest, const char* src, size_t bufsz)
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 format_name(name, track->name, sizeof(name));
467
468 if (track->attr & PLAYLIST_ATTR_SKIPPED) 495 if (track->attr & PLAYLIST_ATTR_SKIPPED)
469 skipped = "(ERR) "; 496 skipped = "(ERR) ";
470 497 if (!(track->attr & PLAYLIST_ATTR_RETRIEVE_ID3_ATTEMPTED) &&
471 if (global_settings.playlist_viewer_indices) 498 (global_settings.playlist_viewer_track_display ==
472 /* Display playlist index */ 499 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM ||
473 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 }
474 else 571 else
475 snprintf(str, len, "%s%s", skipped, name); 572 {
476 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 }
477} 583}
478 584
479/* Update playlist in case something has changed or forced */ 585/* Update playlist in case something has changed or forced */
@@ -512,20 +618,7 @@ static bool update_playlist(bool force)
512static 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)
513{ 619{
514 struct mp3entry id3; 620 struct mp3entry id3;
515 bool id3_retrieval_successful = false; 621 bool id3_retrieval_successful = retrieve_id3_tags(current_track->index, current_track->name, &id3, 0);
516
517 if (!viewer.playlist &&
518 (audio_status() & AUDIO_STATUS_PLAY) &&
519 (playlist_get_resume_info(&viewer.current_playing_track) == current_track->index))
520 {
521 copy_mp3entry(&id3, audio_current_track()); /* retrieve id3 from RAM */
522 id3_retrieval_successful = true;
523 }
524 else
525 {
526 /* Read from disk, the database, doesn't store frequency, file size or codec (g4470) ChrisS*/
527 id3_retrieval_successful = get_metadata(&id3, -1, current_track->name);
528 }
529 622
530 return id3_retrieval_successful && 623 return id3_retrieval_successful &&
531 browse_id3_ex(&id3, viewer.playlist, current_track->display_index, 624 browse_id3_ex(&id3, viewer.playlist, current_track->display_index,
@@ -790,11 +883,17 @@ static int playlist_callback_voice(int selected_item, void *data)
790 883
791 switch(global_settings.playlist_viewer_track_display) 884 switch(global_settings.playlist_viewer_track_display)
792 { 885 {
793 case 1: /*full path*/ 886 case PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH:
887 /*full path*/
794 talk_fullpath(track->name, true); 888 talk_fullpath(track->name, true);
795 break; 889 break;
796 default: 890 default:
797 case 0: /*filename only*/ 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 */
798 talk_file_or_spell(NULL, track->name, NULL, true); 897 talk_file_or_spell(NULL, track->name, NULL, true);
799 break; 898 break;
800 } 899 }
@@ -1154,7 +1253,8 @@ static int say_search_item(int selected_item, void *data)
1154{ 1253{
1155 struct playlist_search_data *s_data = data; 1254 struct playlist_search_data *s_data = data;
1156 playlist_get_track_info(viewer.playlist, s_data->found_indicies[selected_item], s_data->track); 1255 playlist_get_track_info(viewer.playlist, s_data->found_indicies[selected_item], s_data->track);
1157 if(global_settings.playlist_viewer_track_display == 1) /* full path*/ 1256 if(global_settings.playlist_viewer_track_display == PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH)
1257 /* full path*/
1158 talk_fullpath(s_data->track->filename, false); 1258 talk_fullpath(s_data->track->filename, false);
1159 else talk_file_or_spell(NULL, s_data->track->filename, NULL, false); 1259 else talk_file_or_spell(NULL, s_data->track->filename, NULL, false);
1160 return 0; 1260 return 0;
@@ -1197,7 +1297,8 @@ bool search_playlist(void)
1197 1297
1198 playlist_get_track_info(viewer.playlist, i, &track); 1298 playlist_get_track_info(viewer.playlist, i, &track);
1199 const char *trackname = track.filename; 1299 const char *trackname = track.filename;
1200 if (track_display == 0) /* if we only display filename only search filename */ 1300 if (track_display != PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH)
1301 /* if we only display filename only search filename */
1201 trackname = strrchr(track.filename, '/'); 1302 trackname = strrchr(track.filename, '/');
1202 1303
1203 if (trackname && strcasestr(trackname, search_str)) 1304 if (trackname && strcasestr(trackname, search_str))
diff --git a/apps/settings.h b/apps/settings.h
index 1343538b0b..a9a9f647e3 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -78,6 +78,13 @@ enum
78 TRIG_TYPE_NEW_FILE 78 TRIG_TYPE_NEW_FILE
79}; 79};
80 80
81enum {
82 PLAYLIST_VIEWER_ENTRY_SHOW_FILE_NAME = 0,
83 PLAYLIST_VIEWER_ENTRY_SHOW_FULL_PATH = 1,
84 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM = 2,
85 PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE = 3
86};
87
81#ifdef HAVE_CROSSFADE 88#ifdef HAVE_CROSSFADE
82enum { 89enum {
83 CROSSFADE_ENABLE_OFF = 0, 90 CROSSFADE_ENABLE_OFF = 0,
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 3b29703fe9..a9f627bfa6 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -1421,9 +1421,11 @@ const struct settings_list settings[] = {
1421 OFFON_SETTING(0,playlist_viewer_indices,LANG_SHOW_INDICES,true, 1421 OFFON_SETTING(0,playlist_viewer_indices,LANG_SHOW_INDICES,true,
1422 "playlist viewer indices",NULL), 1422 "playlist viewer indices",NULL),
1423 CHOICE_SETTING(0, playlist_viewer_track_display, LANG_TRACK_DISPLAY, 0, 1423 CHOICE_SETTING(0, playlist_viewer_track_display, LANG_TRACK_DISPLAY, 0,
1424 "playlist viewer track display","track name,full path", 1424 "playlist viewer track display",
1425 NULL, 2, ID2P(LANG_DISPLAY_TRACK_NAME_ONLY), 1425 "track name,full path,title and album from tags,title from tags",
1426 ID2P(LANG_DISPLAY_FULL_PATH)), 1426 NULL, 4, ID2P(LANG_DISPLAY_TRACK_NAME_ONLY),
1427 ID2P(LANG_DISPLAY_FULL_PATH),ID2P(LANG_DISPLAY_TITLEALBUM_FROMTAGS),
1428 ID2P(LANG_DISPLAY_TITLE_FROMTAGS)),
1427 CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON, 1429 CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON,
1428 "recursive directory insert", off_on_ask, NULL , 3 , 1430 "recursive directory insert", off_on_ask, NULL , 3 ,
1429 ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)), 1431 ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)),