summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2024-07-05 17:13:10 -0400
committerWilliam Wilgus <me.theuser@yahoo.com>2024-07-09 01:40:02 -0400
commitfdbaf7df597b404be04cecbdc83dbc0551a5b996 (patch)
treef4254d2ed63ce1174d9710a315678aeaf921399b
parent07cf87419189f8730eff53bb74669856a42a2016 (diff)
downloadrockbox-fdbaf7df597b404be04cecbdc83dbc0551a5b996.tar.gz
rockbox-fdbaf7df597b404be04cecbdc83dbc0551a5b996.zip
[Feature] playlist_viewer id3 title display
Not sure this is a great idea from disk and battery standpoint but there is no reason you can't.. using the name buffer to fill title data prevent hitting the disk for each screen scroll add get_metadata_ex to allow flags METADATA_EXCLUDE_ID3_PATH prevent copying the filename to the ID3 struct METADATA_CLOSE_FD_ON_EXIT instead of seeking to the beginning the file is closed before get_metadata returns add logic to allow a invalid fd to signal that get_metadata should open and close the file within its call bugfix per Chris_s don't use the tagcache for the trackinfo Change-Id: Ic7a595b39a8d7a57f975312bc9c8bb4111f22a88
-rw-r--r--apps/buffering.c8
-rw-r--r--apps/iap/iap-core.c7
-rw-r--r--apps/iap/iap-lingo4.c7
-rw-r--r--apps/playback.c3
-rw-r--r--apps/playlist_viewer.c122
-rw-r--r--apps/settings_list.c6
-rw-r--r--apps/tagcache.c16
-rw-r--r--lib/rbcodec/metadata/metadata.c62
-rw-r--r--lib/rbcodec/metadata/metadata.h3
9 files changed, 145 insertions, 89 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index bf41544c56..b9f30fc6df 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -652,11 +652,9 @@ static bool buffer_handle(int handle_id, size_t to_buffer)
652 trigger_cpu_boost(); 652 trigger_cpu_boost();
653 653
654 if (h->type == TYPE_ID3) { 654 if (h->type == TYPE_ID3) {
655 if (!get_metadata(ringbuf_ptr(h->data), h->fd, h->path)) { 655 get_metadata_ex(ringbuf_ptr(h->data),
656 /* metadata parsing failed: clear the buffer. */ 656 h->fd, h->path, METADATA_CLOSE_FD_ON_EXIT);
657 wipe_mp3entry(ringbuf_ptr(h->data)); 657 h->fd = -1; /* with above, behavior same as close_fd */
658 }
659 close_fd(&h->fd);
660 h->widx = ringbuf_add(h->data, h->filesize); 658 h->widx = ringbuf_add(h->data, h->filesize);
661 h->end = h->filesize; 659 h->end = h->filesize;
662 send_event(BUFFER_EVENT_FINISHED, &handle_id); 660 send_event(BUFFER_EVENT_FINISHED, &handle_id);
diff --git a/apps/iap/iap-core.c b/apps/iap/iap-core.c
index da04a67311..3faf8237bf 100644
--- a/apps/iap/iap-core.c
+++ b/apps/iap/iap-core.c
@@ -685,7 +685,6 @@ bool iap_getc(const unsigned char x)
685void iap_get_trackinfo(const unsigned int track, struct mp3entry* id3) 685void iap_get_trackinfo(const unsigned int track, struct mp3entry* id3)
686{ 686{
687 int tracknum; 687 int tracknum;
688 int fd;
689 struct playlist_track_info info; 688 struct playlist_track_info info;
690 689
691 tracknum = track; 690 tracknum = track;
@@ -699,10 +698,8 @@ void iap_get_trackinfo(const unsigned int track, struct mp3entry* id3)
699 if(playlist_next(0) != tracknum) 698 if(playlist_next(0) != tracknum)
700 { 699 {
701 playlist_get_track_info(NULL, tracknum, &info); 700 playlist_get_track_info(NULL, tracknum, &info);
702 fd = open(info.filename, O_RDONLY); 701 /* memset(id3, 0, sizeof(*id3)) --get_metadata does this for us */
703 memset(id3, 0, sizeof(*id3)); 702 get_metadata(id3, -1, info.filename);
704 get_metadata(id3, fd, info.filename);
705 close(fd);
706 } else { 703 } else {
707 memcpy(id3, audio_current_track(), sizeof(*id3)); 704 memcpy(id3, audio_current_track(), sizeof(*id3));
708 } 705 }
diff --git a/apps/iap/iap-lingo4.c b/apps/iap/iap-lingo4.c
index e1ab150fd9..6eb63003a5 100644
--- a/apps/iap/iap-lingo4.c
+++ b/apps/iap/iap-lingo4.c
@@ -1787,7 +1787,6 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
1787 { 1787 {
1788 unsigned char data[70] = {0x04, 0x00, 0xFF}; 1788 unsigned char data[70] = {0x04, 0x00, 0xFF};
1789 struct mp3entry id3; 1789 struct mp3entry id3;
1790 int fd;
1791 size_t len; 1790 size_t len;
1792 long tracknum = get_u32(&buf[3]); 1791 long tracknum = get_u32(&buf[3]);
1793 1792
@@ -1802,10 +1801,8 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf)
1802 { 1801 {
1803 struct playlist_track_info info; 1802 struct playlist_track_info info;
1804 playlist_get_track_info(NULL, tracknum, &info); 1803 playlist_get_track_info(NULL, tracknum, &info);
1805 fd = open(info.filename, O_RDONLY); 1804 /* memset(&id3, 0, sizeof(struct mp3entry)); --get_metadata does this for us */
1806 memset(&id3, 0, sizeof(struct mp3entry)); 1805 get_metadata(&id3, -1, info.filename);
1807 get_metadata(&id3, fd, info.filename);
1808 close(fd);
1809 } 1806 }
1810 /* Return the requested track data */ 1807 /* Return the requested track data */
1811 switch(cmd) 1808 switch(cmd)
diff --git a/apps/playback.c b/apps/playback.c
index 18f62fb69b..8a30af5199 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -2022,8 +2022,7 @@ static int audio_load_track(void)
2022 if (fd >= 0) 2022 if (fd >= 0)
2023 { 2023 {
2024 id3_mutex_lock(); 2024 id3_mutex_lock();
2025 if(!get_metadata(ub_id3, fd, path)) 2025 get_metadata(ub_id3, fd, path);
2026 wipe_mp3entry(ub_id3);
2027 id3_mutex_unlock(); 2026 id3_mutex_unlock();
2028 } 2027 }
2029 2028
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 */
62struct playlist_entry { 66struct 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
70enum direction 74enum direction
@@ -86,6 +90,8 @@ enum pv_onplay_result {
86 90
87struct playlist_buffer 91struct 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
139static void format_name(char* dest, const char* src);
140static void format_line(const struct playlist_entry* track, char* str, 144static 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
228static 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
243static 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
224static int playlist_entry_load(struct playlist_entry *entry, int index, 262static 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 */
436static void format_name(char* dest, const char* src) 486static 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)
1132static const char* playlist_search_callback_name(int selected_item, void * data, 1184static 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;
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 09a45f1faa..60a2735e90 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -1415,9 +1415,9 @@ const struct settings_list settings[] = {
1415 OFFON_SETTING(0,playlist_viewer_indices,LANG_SHOW_INDICES,true, 1415 OFFON_SETTING(0,playlist_viewer_indices,LANG_SHOW_INDICES,true,
1416 "playlist viewer indices",NULL), 1416 "playlist viewer indices",NULL),
1417 CHOICE_SETTING(0, playlist_viewer_track_display, LANG_TRACK_DISPLAY, 0, 1417 CHOICE_SETTING(0, playlist_viewer_track_display, LANG_TRACK_DISPLAY, 0,
1418 "playlist viewer track display","track name,full path", 1418 "playlist viewer track display","track name,full path,id3 title",
1419 NULL, 2, ID2P(LANG_DISPLAY_TRACK_NAME_ONLY), 1419 NULL, 3, ID2P(LANG_DISPLAY_TRACK_NAME_ONLY),
1420 ID2P(LANG_DISPLAY_FULL_PATH)), 1420 ID2P(LANG_DISPLAY_FULL_PATH), ID2P(LANG_ID3_TITLE)),
1421 CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON, 1421 CHOICE_SETTING(0, recursive_dir_insert, LANG_RECURSE_DIRECTORY , RECURSE_ON,
1422 "recursive directory insert", off_on_ask, NULL , 3 , 1422 "recursive directory insert", off_on_ask, NULL , 3 ,
1423 ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)), 1423 ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_ASK)),
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 5413e2def0..1412647368 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -2193,7 +2193,6 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
2193 struct mp3entry id3; 2193 struct mp3entry id3;
2194 struct temp_file_entry entry; 2194 struct temp_file_entry entry;
2195 bool ret; 2195 bool ret;
2196 int fd;
2197 int idx_id = -1; 2196 int idx_id = -1;
2198 char tracknumfix[3]; 2197 char tracknumfix[3];
2199 int offset = 0; 2198 int offset = 0;
@@ -2266,21 +2265,16 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
2266 } 2265 }
2267 } 2266 }
2268 2267
2269 fd = open(path, O_RDONLY); 2268 /*memset(&id3, 0, sizeof(struct mp3entry)); -- get_metadata does this for us */
2270 if (fd < 0)
2271 {
2272 logf("open fail: %s", path);
2273 return ;
2274 }
2275
2276 memset(&id3, 0, sizeof(struct mp3entry));
2277 memset(&entry, 0, sizeof(struct temp_file_entry)); 2269 memset(&entry, 0, sizeof(struct temp_file_entry));
2278 memset(&tracknumfix, 0, sizeof(tracknumfix)); 2270 memset(&tracknumfix, 0, sizeof(tracknumfix));
2279 ret = get_metadata(&id3, fd, path); 2271 ret = get_metadata_ex(&id3, -1, path, METADATA_EXCLUDE_ID3_PATH);
2280 close(fd);
2281 2272
2282 if (!ret) 2273 if (!ret)
2274 {
2275 logf("get_metadata fail: %s", path);
2283 return ; 2276 return ;
2277 }
2284 2278
2285 logf("-> %s", path); 2279 logf("-> %s", path);
2286 2280
diff --git a/lib/rbcodec/metadata/metadata.c b/lib/rbcodec/metadata/metadata.c
index 19147ccdb3..28cef46d92 100644
--- a/lib/rbcodec/metadata/metadata.c
+++ b/lib/rbcodec/metadata/metadata.c
@@ -394,25 +394,19 @@ unsigned int probe_file_format(const char *filename)
394/* Note, that this returns false for successful, true for error! */ 394/* Note, that this returns false for successful, true for error! */
395bool mp3info(struct mp3entry *entry, const char *filename) 395bool mp3info(struct mp3entry *entry, const char *filename)
396{ 396{
397 int fd; 397 return !get_metadata(entry, -1, filename);
398 bool result;
399
400 fd = open(filename, O_RDONLY);
401 if (fd < 0)
402 return true;
403
404 result = !get_metadata(entry, fd, filename);
405
406 close(fd);
407
408 return result;
409} 398}
410 399
411/* Get metadata for track - return false if parsing showed problems with the 400/* Get metadata for track - return false if parsing showed problems with the
412 * file that would prevent playback. 401 * file that would prevent playback. supply a filedescriptor <0 and the file will be opened
402 * and closed automatically within the get_metadata call
403 * get_metadata_ex allows flags to change the way get_metadata behaves
404 * METADATA_EXCLUDE_ID3_PATH won't copy filename path to the id3 path buffer
405 * METADATA_CLOSE_FD_ON_EXIT closes the open filedescriptor on exit
413 */ 406 */
414bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) 407bool get_metadata_ex(struct mp3entry* id3, int fd, const char* trackname, int flags)
415{ 408{
409 bool success = true;
416 const struct afmt_entry *entry; 410 const struct afmt_entry *entry;
417 int logfd = 0; 411 int logfd = 0;
418 DEBUGF("Read metadata for %s\n", trackname); 412 DEBUGF("Read metadata for %s\n", trackname);
@@ -426,10 +420,20 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
426 close(logfd); 420 close(logfd);
427 } 421 }
428 } 422 }
429
430 /* Clear the mp3entry to avoid having bogus pointers appear */ 423 /* Clear the mp3entry to avoid having bogus pointers appear */
431 wipe_mp3entry(id3); 424 wipe_mp3entry(id3);
432 425
426 if (fd < 0)
427 {
428 fd = open(trackname, O_RDONLY);
429 flags |= METADATA_CLOSE_FD_ON_EXIT;
430 if (fd < 0)
431 {
432 DEBUGF("Error opening %s\n", trackname);
433 return false; /*Failure*/
434 }
435 }
436
433 /* Take our best guess at the codec type based on file extension */ 437 /* Take our best guess at the codec type based on file extension */
434 id3->codectype = probe_file_format(trackname); 438 id3->codectype = probe_file_format(trackname);
435 439
@@ -443,19 +447,31 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
443 if (!entry->parse_func) 447 if (!entry->parse_func)
444 { 448 {
445 DEBUGF("nothing to parse for %s (format %s)\n", trackname, entry->label); 449 DEBUGF("nothing to parse for %s (format %s)\n", trackname, entry->label);
446 return false; 450 success = false;
447 } 451 }
448 452 else if (!entry->parse_func(fd, id3))
449 if (!entry->parse_func(fd, id3))
450 { 453 {
451 DEBUGF("parsing %s failed (format: %s)\n", trackname, entry->label); 454 DEBUGF("parsing %s failed (format: %s)\n", trackname, entry->label);
452 return false; 455 success = false;
456 wipe_mp3entry(id3); /* ensure the mp3entry is clear */
453 } 457 }
454 458
455 lseek(fd, 0, SEEK_SET); 459 if ((flags & METADATA_CLOSE_FD_ON_EXIT))
456 strlcpy(id3->path, trackname, sizeof(id3->path)); 460 close(fd);
457 /* We have successfully read the metadata from the file */ 461 else
458 return true; 462 lseek(fd, 0, SEEK_SET);
463
464 if (success && (flags & METADATA_EXCLUDE_ID3_PATH) == 0)
465 {
466 strlcpy(id3->path, trackname, sizeof(id3->path));
467 }
468 /* have we successfully read the metadata from the file? */
469 return success;
470}
471
472bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
473{
474 return get_metadata_ex(id3, fd, trackname, 0);
459} 475}
460 476
461#define MOVE_ENTRY(x) if (x) x += offset; 477#define MOVE_ENTRY(x) if (x) x += offset;
diff --git a/lib/rbcodec/metadata/metadata.h b/lib/rbcodec/metadata/metadata.h
index b30979334a..a0ba0376c6 100644
--- a/lib/rbcodec/metadata/metadata.h
+++ b/lib/rbcodec/metadata/metadata.h
@@ -24,6 +24,8 @@
24 24
25#include "platform.h" 25#include "platform.h"
26 26
27#define METADATA_EXCLUDE_ID3_PATH (0x01) /* don't copy filename path to the id3 path buffer */
28#define METADATA_CLOSE_FD_ON_EXIT (0x02) /* close the filedescriptor when finished */
27/* Audio file types. */ 29/* Audio file types. */
28/* NOTE: The values of the AFMT_* items are used for the %fc tag in the WPS 30/* NOTE: The values of the AFMT_* items are used for the %fc tag in the WPS
29 - so new entries MUST be added to the end to maintain compatibility. 31 - so new entries MUST be added to the end to maintain compatibility.
@@ -323,6 +325,7 @@ struct mp3entry {
323 325
324unsigned int probe_file_format(const char *filename); 326unsigned int probe_file_format(const char *filename);
325bool get_metadata(struct mp3entry* id3, int fd, const char* trackname); 327bool get_metadata(struct mp3entry* id3, int fd, const char* trackname);
328bool get_metadata_ex(struct mp3entry* id3, int fd, const char* trackname, int flags);
326bool mp3info(struct mp3entry *entry, const char *filename); 329bool mp3info(struct mp3entry *entry, const char *filename);
327void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig); 330void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig);
328void copy_mp3entry(struct mp3entry *dest, const struct mp3entry *orig); 331void copy_mp3entry(struct mp3entry *dest, const struct mp3entry *orig);