diff --git a/apps/gui/wps.c b/apps/gui/wps.c index d35a5ac6d2..d87f78de2d 100644 --- a/apps/gui/wps.c +++ b/apps/gui/wps.c @@ -1035,7 +1035,7 @@ long gui_wps_show(void) gwps_leave_wps(true); if (browse_id3(audio_current_track(), playlist_get_display_index(), - playlist_amount(), NULL)) + playlist_amount(), NULL, false)) return GO_TO_ROOT; restore = true; } diff --git a/apps/onplay.c b/apps/onplay.c index 9dd780fd6e..4b6171746c 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -1569,7 +1569,7 @@ static int browse_id3_wrapper(void) if (browse_id3(audio_current_track(), playlist_get_display_index(), - playlist_amount(), NULL)) + playlist_amount(), NULL, false)) return GO_TO_ROOT; return GO_TO_PREVIOUS; } diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 8761f0dbc9..d9bfee343f 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c @@ -526,7 +526,7 @@ static enum pv_onplay_result show_track_info(const struct playlist_entry *curren return id3_retrieval_successful && browse_id3(&id3, current_track->index + 1, - viewer.num_tracks, NULL) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED; + viewer.num_tracks, NULL, false) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED; } diff --git a/apps/plugin.h b/apps/plugin.h index 3eb4101cbe..835063e25f 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -162,7 +162,7 @@ int plugin_open(const char *plugin, const char *parameter); * when this happens please take the opportunity to sort in * any new functions "waiting" at the end of the list. */ -#define PLUGIN_API_VERSION 267 +#define PLUGIN_API_VERSION 268 /* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */ @@ -500,7 +500,7 @@ struct plugin_api { void (*add_to_pl_cb)); bool (*browse_id3)(struct mp3entry *id3, int playlist_display_index, int playlist_amount, - struct tm *modified); + struct tm *modified, bool multiple_tracks); /* talking */ int (*talk_id)(int32_t id, bool enqueue); diff --git a/apps/plugins/lib/mul_id3.c b/apps/plugins/lib/mul_id3.c index 5c8f4d9d9c..c40a495ecd 100644 --- a/apps/plugins/lib/mul_id3.c +++ b/apps/plugins/lib/mul_id3.c @@ -22,8 +22,8 @@ #include "mul_id3.h" struct multiple_tracks_id3 { - unsigned long length; - unsigned long filesize; + unsigned long long filesize; + unsigned long long length; unsigned long frequency; unsigned int artist_hash; unsigned int composer_hash; @@ -35,8 +35,6 @@ struct multiple_tracks_id3 { unsigned int codectype; unsigned int bitrate; int year; - bool filesize_ovf; - bool length_ovf; bool vbr; }; @@ -64,7 +62,7 @@ static unsigned int mfnv(char *str) return hash; } -void init_mul_id3(void) +static void init_mul_id3(void) { mul_id3.artist_hash = 0; mul_id3.album_hash = 0; @@ -80,14 +78,13 @@ void init_mul_id3(void) mul_id3.length = 0; mul_id3.filesize = 0; mul_id3.year = 0; - mul_id3.length_ovf = false; - mul_id3.filesize_ovf = false; } void collect_id3(struct mp3entry *id3, bool is_first_track) { if (is_first_track) { + init_mul_id3(); mul_id3.artist_hash = mfnv(id3->artist); mul_id3.album_hash = mfnv(id3->album); mul_id3.genre_hash = mfnv(id3->genre_string); @@ -129,25 +126,18 @@ void collect_id3(struct mp3entry *id3, bool is_first_track) if (mul_id3.year && (id3->year != mul_id3.year)) mul_id3.year = 0; } - - if (ULONG_MAX - mul_id3.length < id3->length) - { - mul_id3.length_ovf = true; - mul_id3.length = 0; - } - else if (!mul_id3.length_ovf) - mul_id3.length += id3->length; - - if (INT_MAX - mul_id3.filesize < id3->filesize) /* output_dyn_value expects int */ - { - mul_id3.filesize_ovf = true; - mul_id3.filesize = 0; - } - else if (!mul_id3.filesize_ovf) - mul_id3.filesize += id3->filesize; + mul_id3.length += id3->length; + mul_id3.filesize += id3->filesize; } -void write_id3_mul_tracks(struct mp3entry *id3) +/* (!) Note scale factor applied to returned metadata: + * - Unit for filesize will be KiB instead of Bytes + * - Unit for length will be s instead of ms + * + * Use result only as input for browse_id3, + * and set multiple_tracks parameter to true. + */ +void finalize_id3(struct mp3entry *id3) { id3->path[0] = '\0'; id3->title = NULL; @@ -169,8 +159,10 @@ void write_id3_mul_tracks(struct mp3entry *id3) id3->track_string = NULL; id3->year_string = NULL; id3->year = mul_id3.year; - id3->length = mul_id3.length; - id3->filesize = mul_id3.filesize; + mul_id3.length /= 1000; + mul_id3.filesize >>= 10; + id3->length = mul_id3.length > ULONG_MAX ? 0 : mul_id3.length; + id3->filesize = mul_id3.filesize > INT_MAX ? 0 : mul_id3.filesize; id3->frequency = mul_id3.frequency; id3->bitrate = mul_id3.bitrate; id3->codectype = mul_id3.codectype; diff --git a/apps/plugins/lib/mul_id3.h b/apps/plugins/lib/mul_id3.h index 40d7fa7822..d08095de5c 100644 --- a/apps/plugins/lib/mul_id3.h +++ b/apps/plugins/lib/mul_id3.h @@ -21,8 +21,7 @@ #ifndef MUL_ID3_H #define MUL_ID3_H -void init_mul_id3(void); void collect_id3(struct mp3entry *id3, bool is_first_track); -void write_id3_mul_tracks(struct mp3entry *id3); +void finalize_id3(struct mp3entry *id3); #endif /* MUL_ID3_H */ diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index 3b308d1866..52f87355b2 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c @@ -4000,8 +4000,6 @@ static int show_id3_info(const char *selected_file) const char *file_name; bool is_multiple_tracks = insert_whole_album && pf_tracks.count > 1; - init_mul_id3(); - last_tick = *(rb->current_tick) + HZ/2; rb->splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */ i = 0; @@ -4027,9 +4025,9 @@ static int show_id3_info(const char *selected_file) } while (++i < pf_tracks.count && is_multiple_tracks); if (is_multiple_tracks) - write_id3_mul_tracks(&id3); + finalize_id3(&id3); - return rb->browse_id3(&id3, 0, 0, NULL) ? PLUGIN_USB_CONNECTED : 0; + return rb->browse_id3(&id3, 0, 0, NULL, i > 1) ? PLUGIN_USB_CONNECTED : 0; } diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c index 27bfe9181a..638d7380a5 100644 --- a/apps/plugins/properties.c +++ b/apps/plugins/properties.c @@ -406,14 +406,12 @@ enum plugin_status plugin_start(const void* parameter) if (!rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))) /* db table selected */ { props_type = PROPS_MUL_ID3; - init_mul_id3(); mul_id3_count = 0; if (!rb->tagtree_subentries_do_action(&mul_id3_add) || mul_id3_count == 0) return PLUGIN_ERROR; - - if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */ - write_id3_mul_tracks(&id3); + else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */ + finalize_id3(&id3); } else #endif @@ -448,8 +446,8 @@ enum plugin_status plugin_start(const void* parameter) FOR_NB_SCREENS(i) rb->viewportmanager_theme_enable(i, true, NULL); - bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm) : - (props_type == PROPS_MUL_ID3 ? rb->browse_id3(&id3, 0, 0, NULL) : + bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm, false) : + (props_type == PROPS_MUL_ID3 ? rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count > 1) : browse_file_or_dir(&stats)); FOR_NB_SCREENS(i) diff --git a/apps/screens.c b/apps/screens.c index 869d081498..c519da9353 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -394,6 +394,7 @@ static const int id3_headers[]= struct id3view_info { struct mp3entry* id3; struct tm *modified; + bool multiple_tracks; int count; int playlist_display_index; int playlist_amount; @@ -491,6 +492,9 @@ static const char * id3_get_or_speak_info(int selected_item, void* data, { struct id3view_info *info = (struct id3view_info*)data; struct mp3entry* id3 =info->id3; + const unsigned char * const *unit; + unsigned int unit_ct; + unsigned long length; struct tm *tm = info->modified; int info_no=selected_item/2; if(!(selected_item%2)) @@ -593,10 +597,13 @@ static const char * id3_get_or_speak_info(int selected_item, void* data, } break; case LANG_ID3_LENGTH: - format_time(buffer, buffer_len, id3->length); + length = info->multiple_tracks ? id3->length : id3->length / 1000; + + format_time_auto(buffer, buffer_len, + length, UNIT_SEC | UNIT_TRIM_ZERO, true); val=buffer; if(say_it) - talk_value(id3->length /1000, UNIT_TIME, true); + talk_value(length, UNIT_TIME, true); break; case LANG_ID3_PLAYLIST: if (info->playlist_display_index == 0 || info->playlist_amount == 0 ) @@ -667,10 +674,20 @@ static const char * id3_get_or_speak_info(int selected_item, void* data, case LANG_FILESIZE: /* not LANG_ID3_FILESIZE because the string is shared */ if (!id3->filesize) return NULL; - output_dyn_value(buffer, buffer_len, id3->filesize, byte_units, 4, true); + if (info->multiple_tracks) + { + unit = kibyte_units; + unit_ct = 3; + } + else + { + unit = byte_units; + unit_ct = 4; + } + output_dyn_value(buffer, buffer_len, id3->filesize, unit, unit_ct, true); val=buffer; if(say_it && val) - output_dyn_value(NULL, 0, id3->filesize, byte_units, 4, true); + output_dyn_value(NULL, 0, id3->filesize, unit, unit_ct, true); break; case LANG_DATE: if (!tm) @@ -720,8 +737,11 @@ static int id3_speak_item(int selected_item, void* data) return 0; } +/* Note: Setting multiple_tracks parameter to true causes filesize value + * to be treated as KiB (instead of Bytes), and length as s instead of ms. + */ bool browse_id3(struct mp3entry *id3, int playlist_display_index, int playlist_amount, - struct tm *modified) + struct tm *modified, bool multiple_tracks) { struct gui_synclist id3_lists; int key; @@ -730,6 +750,7 @@ bool browse_id3(struct mp3entry *id3, int playlist_display_index, int playlist_a info.count = 0; info.id3 = id3; info.modified = modified; + info.multiple_tracks = multiple_tracks; info.playlist_display_index = playlist_display_index; info.playlist_amount = playlist_amount; bool ret = false; diff --git a/apps/screens.h b/apps/screens.h index 47dc1375ca..2dc0530f3a 100644 --- a/apps/screens.h +++ b/apps/screens.h @@ -40,7 +40,7 @@ bool set_time_screen(const char* title, struct tm *tm, bool set_date); #endif bool browse_id3(struct mp3entry *id3, int playlist_display_index, int playlist_amount, - struct tm *modified); + struct tm *modified, bool multiple_tracks); int view_runtime(void); #ifdef HAVE_TOUCHSCREEN