diff options
Diffstat (limited to 'apps/playlist_viewer.c')
-rw-r--r-- | apps/playlist_viewer.c | 122 |
1 files changed, 87 insertions, 35 deletions
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 579eba5a61..d06a3f3df6 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c | |||
@@ -51,6 +51,10 @@ | |||
51 | #include "menus/exported_menus.h" | 51 | #include "menus/exported_menus.h" |
52 | #include "yesno.h" | 52 | #include "yesno.h" |
53 | 53 | ||
54 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | ||
55 | #include "tagcache.h" | ||
56 | #endif | ||
57 | |||
54 | /* Maximum number of tracks we can have loaded at one time */ | 58 | /* Maximum number of tracks we can have loaded at one time */ |
55 | #define MAX_PLAYLIST_ENTRIES 200 | 59 | #define MAX_PLAYLIST_ENTRIES 200 |
56 | 60 | ||
@@ -60,11 +64,11 @@ | |||
60 | 64 | ||
61 | /* Information about a specific track */ | 65 | /* Information about a specific track */ |
62 | struct playlist_entry { | 66 | struct playlist_entry { |
63 | char *name; /* Formatted track name */ | 67 | char *name; /* track path */ |
68 | char *title; /* Formatted track name */ | ||
64 | int index; /* Playlist index */ | 69 | int index; /* Playlist index */ |
65 | int display_index; /* Display index */ | 70 | int display_index; /* Display index */ |
66 | bool queued; /* Is track queued? */ | 71 | int attr; /* Is track queued?; Is track marked as bad?*/ |
67 | bool skipped; /* Is track marked as bad? */ | ||
68 | }; | 72 | }; |
69 | 73 | ||
70 | enum direction | 74 | enum direction |
@@ -86,6 +90,8 @@ enum pv_onplay_result { | |||
86 | 90 | ||
87 | struct playlist_buffer | 91 | struct playlist_buffer |
88 | { | 92 | { |
93 | struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES]; | ||
94 | |||
89 | char *name_buffer; /* Buffer used to store track names */ | 95 | char *name_buffer; /* Buffer used to store track names */ |
90 | int buffer_size; /* Size of name buffer */ | 96 | int buffer_size; /* Size of name buffer */ |
91 | 97 | ||
@@ -97,7 +103,6 @@ struct playlist_buffer | |||
97 | the buffer has a real index < to the | 103 | the buffer has a real index < to the |
98 | real index of the the first track)*/ | 104 | real index of the the first track)*/ |
99 | 105 | ||
100 | struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES]; | ||
101 | int num_loaded; /* Number of track entries loaded in buffer */ | 106 | int num_loaded; /* Number of track entries loaded in buffer */ |
102 | }; | 107 | }; |
103 | 108 | ||
@@ -136,7 +141,6 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer, | |||
136 | const char* filename, bool reload, | 141 | const char* filename, bool reload, |
137 | int *most_recent_selection); | 142 | int *most_recent_selection); |
138 | 143 | ||
139 | static void format_name(char* dest, const char* src); | ||
140 | static void format_line(const struct playlist_entry* track, char* str, | 144 | static void format_line(const struct playlist_entry* track, char* str, |
141 | int len); | 145 | int len); |
142 | 146 | ||
@@ -221,6 +225,40 @@ static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb, | |||
221 | } | 225 | } |
222 | } | 226 | } |
223 | 227 | ||
228 | static bool retrieve_track_metadata(struct mp3entry *id3, const char *filename, int flags) | ||
229 | { | ||
230 | bool success = true; | ||
231 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | ||
232 | /* try to get the id3 data from the database */ | ||
233 | /* the database, doesn't store frequency, file size or codec (g4470) ChrisS*/ | ||
234 | if ((flags & METADATA_EXCLUDE_ID3_PATH) || !tagcache_fill_tags(id3, filename)) | ||
235 | #endif | ||
236 | /* fall back to reading the file from disk */ | ||
237 | { | ||
238 | success = get_metadata_ex(id3, -1, filename, flags); | ||
239 | } | ||
240 | return success; | ||
241 | } | ||
242 | |||
243 | static int load_track_title(char* buffer, size_t bufsz, char *filename) | ||
244 | { | ||
245 | struct mp3entry id3; | ||
246 | if (retrieve_track_metadata(&id3, filename, METADATA_EXCLUDE_ID3_PATH) | ||
247 | && id3.title && id3.title[0] != '\0') | ||
248 | { | ||
249 | const char *artist = id3.artist; | ||
250 | if (!artist) | ||
251 | artist = id3.albumartist; | ||
252 | if(!artist) | ||
253 | artist = str(LANG_TAGNAVI_UNTAGGED); | ||
254 | |||
255 | size_t len = snprintf(buffer, bufsz, "%s - %s", artist, id3.title) + 1; | ||
256 | if (len < bufsz) | ||
257 | return len; | ||
258 | } | ||
259 | return 0; /*Failure*/ | ||
260 | } | ||
261 | |||
224 | static int playlist_entry_load(struct playlist_entry *entry, int index, | 262 | static int playlist_entry_load(struct playlist_entry *entry, int index, |
225 | char* name_buffer, int remaining_size) | 263 | char* name_buffer, int remaining_size) |
226 | { | 264 | { |
@@ -234,17 +272,29 @@ static int playlist_entry_load(struct playlist_entry *entry, int index, | |||
234 | if (playlist_get_track_info(viewer.playlist, index, &info) < 0) | 272 | if (playlist_get_track_info(viewer.playlist, index, &info) < 0) |
235 | return -1; | 273 | return -1; |
236 | 274 | ||
237 | len = strlen(info.filename) + 1; | 275 | len = strlcpy(name_buffer, info.filename, remaining_size) + 1; |
238 | 276 | ||
239 | if (len <= remaining_size) | 277 | if (len <= remaining_size) |
240 | { | 278 | { |
241 | strcpy(name_buffer, info.filename); | ||
242 | |||
243 | entry->name = name_buffer; | 279 | entry->name = name_buffer; |
280 | entry->title = name_buffer; | ||
244 | entry->index = info.index; | 281 | entry->index = info.index; |
245 | entry->display_index = info.display_index; | 282 | entry->display_index = info.display_index; |
246 | entry->queued = info.attr & PLAYLIST_ATTR_QUEUED; | 283 | entry->attr = info.attr & (PLAYLIST_ATTR_SKIPPED | PLAYLIST_ATTR_QUEUED); |
247 | entry->skipped = info.attr & PLAYLIST_ATTR_SKIPPED; | 284 | |
285 | if (global_settings.playlist_viewer_track_display == 2) /* title */ | ||
286 | { | ||
287 | /* advance buffer position past filename, adjust length remaining */ | ||
288 | name_buffer += len; | ||
289 | remaining_size -= len; | ||
290 | int tlen = load_track_title(name_buffer, remaining_size, info.filename); | ||
291 | if (tlen > 0) | ||
292 | { | ||
293 | entry->title = name_buffer; | ||
294 | len += tlen; | ||
295 | } | ||
296 | } | ||
297 | |||
248 | return len; | 298 | return len; |
249 | } | 299 | } |
250 | return -1; | 300 | return -1; |
@@ -433,7 +483,7 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer, | |||
433 | } | 483 | } |
434 | 484 | ||
435 | /* Format trackname for display purposes */ | 485 | /* Format trackname for display purposes */ |
436 | static void format_name(char* dest, const char* src) | 486 | static void format_name(char* dest, const char* src, size_t bufsz) |
437 | { | 487 | { |
438 | switch (global_settings.playlist_viewer_track_display) | 488 | switch (global_settings.playlist_viewer_track_display) |
439 | { | 489 | { |
@@ -442,17 +492,16 @@ static void format_name(char* dest, const char* src) | |||
442 | { | 492 | { |
443 | /* Only display the filename */ | 493 | /* Only display the filename */ |
444 | char* p = strrchr(src, '/'); | 494 | char* p = strrchr(src, '/'); |
445 | 495 | strlcpy(dest, p+1, bufsz); | |
446 | strcpy(dest, p+1); | ||
447 | |||
448 | /* Remove the extension */ | 496 | /* Remove the extension */ |
449 | strrsplt(dest, '.'); | 497 | strrsplt(dest, '.'); |
450 | |||
451 | break; | 498 | break; |
452 | } | 499 | } |
500 | case 2: /* Artist - Title */ | ||
501 | /*fall-through*/ | ||
453 | case 1: | 502 | case 1: |
454 | /* Full path */ | 503 | /* Full path */ |
455 | strcpy(dest, src); | 504 | strlcpy(dest, src, bufsz); |
456 | break; | 505 | break; |
457 | } | 506 | } |
458 | } | 507 | } |
@@ -463,10 +512,9 @@ static void format_line(const struct playlist_entry* track, char* str, | |||
463 | { | 512 | { |
464 | char name[MAX_PATH]; | 513 | char name[MAX_PATH]; |
465 | char *skipped = ""; | 514 | char *skipped = ""; |
515 | format_name(name, track->title, sizeof(name)); | ||
466 | 516 | ||
467 | format_name(name, track->name); | 517 | if (track->attr & PLAYLIST_ATTR_SKIPPED) |
468 | |||
469 | if (track->skipped) | ||
470 | skipped = "(ERR) "; | 518 | skipped = "(ERR) "; |
471 | 519 | ||
472 | if (global_settings.playlist_viewer_indices) | 520 | if (global_settings.playlist_viewer_indices) |
@@ -524,13 +572,7 @@ static enum pv_onplay_result show_track_info(const struct playlist_entry *curren | |||
524 | } | 572 | } |
525 | else | 573 | else |
526 | { | 574 | { |
527 | int fd = open(current_track->name, O_RDONLY); | 575 | id3_retrieval_successful = retrieve_track_metadata(&id3, current_track->name, 0); |
528 | if (fd >= 0) | ||
529 | { | ||
530 | if (get_metadata(&id3, fd, current_track->name)) | ||
531 | id3_retrieval_successful = true; | ||
532 | close(fd); | ||
533 | } | ||
534 | } | 576 | } |
535 | 577 | ||
536 | return id3_retrieval_successful && | 578 | return id3_retrieval_successful && |
@@ -755,7 +797,7 @@ static enum themable_icons playlist_callback_icons(int selected_item, | |||
755 | /* Track we are moving */ | 797 | /* Track we are moving */ |
756 | return Icon_Moving; | 798 | return Icon_Moving; |
757 | } | 799 | } |
758 | else if (track->queued) | 800 | else if (track->attr & PLAYLIST_ATTR_QUEUED) |
759 | { | 801 | { |
760 | /* Queued track */ | 802 | /* Queued track */ |
761 | return Icon_Queued; | 803 | return Icon_Queued; |
@@ -776,17 +818,27 @@ static int playlist_callback_voice(int selected_item, void *data) | |||
776 | talk_id(LANG_NOW_PLAYING, true); | 818 | talk_id(LANG_NOW_PLAYING, true); |
777 | if (track->index == local_viewer->moving_track) | 819 | if (track->index == local_viewer->moving_track) |
778 | talk_id(VOICE_TRACK_TO_MOVE, true); | 820 | talk_id(VOICE_TRACK_TO_MOVE, true); |
779 | if (track->queued) | 821 | if (track->attr & PLAYLIST_ATTR_QUEUED) |
780 | talk_id(VOICE_QUEUED, true); | 822 | talk_id(VOICE_QUEUED, true); |
781 | } | 823 | } |
782 | if (track->skipped) | 824 | if (track->attr & PLAYLIST_ATTR_SKIPPED) |
783 | talk_id(VOICE_BAD_TRACK, true); | 825 | talk_id(VOICE_BAD_TRACK, true); |
784 | if (global_settings.playlist_viewer_indices) | 826 | if (global_settings.playlist_viewer_indices) |
785 | talk_number(track->display_index, true); | 827 | talk_number(track->display_index, true); |
786 | 828 | ||
787 | if(global_settings.playlist_viewer_track_display) | 829 | switch(global_settings.playlist_viewer_track_display) |
788 | talk_fullpath(track->name, true); | 830 | { |
789 | else talk_file_or_spell(NULL, track->name, NULL, true); | 831 | case 1: /*full path*/ |
832 | talk_fullpath(track->name, true); | ||
833 | break; | ||
834 | case 2: /*title*/ | ||
835 | talk_spell(track->title, true); | ||
836 | break; | ||
837 | default: | ||
838 | case 0: /*filename only*/ | ||
839 | talk_file_or_spell(NULL, track->name, NULL, true); | ||
840 | break; | ||
841 | } | ||
790 | if (viewer.moving_track != -1) | 842 | if (viewer.moving_track != -1) |
791 | talk_ids(true,VOICE_PAUSE, VOICE_MOVING_TRACK); | 843 | talk_ids(true,VOICE_PAUSE, VOICE_MOVING_TRACK); |
792 | 844 | ||
@@ -1132,11 +1184,11 @@ static void close_playlist_viewer(void) | |||
1132 | static const char* playlist_search_callback_name(int selected_item, void * data, | 1184 | static const char* playlist_search_callback_name(int selected_item, void * data, |
1133 | char *buffer, size_t buffer_len) | 1185 | char *buffer, size_t buffer_len) |
1134 | { | 1186 | { |
1135 | (void)buffer_len; /* this should probably be used */ | ||
1136 | int *found_indicies = (int*)data; | 1187 | int *found_indicies = (int*)data; |
1137 | static struct playlist_track_info track; | 1188 | static struct playlist_track_info track; |
1138 | playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track); | 1189 | playlist_get_track_info(viewer.playlist, found_indicies[selected_item], &track); |
1139 | format_name(buffer, track.filename); | 1190 | |
1191 | format_name(buffer, track.filename, buffer_len); | ||
1140 | return buffer; | 1192 | return buffer; |
1141 | } | 1193 | } |
1142 | 1194 | ||
@@ -1145,7 +1197,7 @@ static int say_search_item(int selected_item, void *data) | |||
1145 | int *found_indicies = (int*)data; | 1197 | int *found_indicies = (int*)data; |
1146 | static struct playlist_track_info track; | 1198 | static struct playlist_track_info track; |
1147 | playlist_get_track_info(viewer.playlist,found_indicies[selected_item],&track); | 1199 | playlist_get_track_info(viewer.playlist,found_indicies[selected_item],&track); |
1148 | if(global_settings.playlist_viewer_track_display) | 1200 | if(global_settings.playlist_viewer_track_display == 1) |
1149 | talk_fullpath(track.filename, false); | 1201 | talk_fullpath(track.filename, false); |
1150 | else talk_file_or_spell(NULL, track.filename, NULL, false); | 1202 | else talk_file_or_spell(NULL, track.filename, NULL, false); |
1151 | return 0; | 1203 | return 0; |