diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index e7264d65ea..c843471831 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -14722,58 +14722,58 @@
id: LANG_PROPERTIES_ARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Artist]"
+ *: ""
- *: "Artist"
+ *: ""
id: LANG_PROPERTIES_TITLE
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Title]"
+ *: ""
- *: "Title"
+ *: ""
id: LANG_PROPERTIES_ALBUM
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Album]"
+ *: ""
- *: "Album"
+ *: ""
id: LANG_PROPERTIES_DURATION
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Duration]"
+ *: ""
- *: "Duration"
+ *: ""
@@ -15947,128 +15947,128 @@
id: LANG_PROPERTIES_ALBUMARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Album Artist]"
+ *: ""
- *: "Album Artist"
+ *: ""
id: LANG_PROPERTIES_GENRE
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Genre]"
+ *: ""
- *: "Genre"
+ *: ""
id: LANG_PROPERTIES_COMMENT
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Comment]"
+ *: ""
- *: "Comment"
+ *: ""
id: LANG_PROPERTIES_COMPOSER
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Composer]"
+ *: ""
- *: "Composer"
+ *: ""
id: LANG_PROPERTIES_YEAR
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Year]"
+ *: ""
- *: "Year"
+ *: ""
id: LANG_PROPERTIES_TRACKNUM
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Tracknum]"
+ *: ""
- *: "Track number"
+ *: ""
id: LANG_PROPERTIES_DISCNUM
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Discnum]"
+ *: ""
- *: "Disc number"
+ *: ""
id: LANG_PROPERTIES_FREQUENCY
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Frequency]"
+ *: ""
- *: "Frequency"
+ *: ""
id: LANG_PROPERTIES_BITRATE
- desc: in properties plugin
+ desc: deprecated
user: core
- *: "[Bitrate]"
+ *: ""
- *: "Bit rate"
+ *: ""
@@ -16312,3 +16312,17 @@
*: "Cache needs to finish updating first!"
+
+ id: LANG_TRACK_INFO
+ desc: Track Info Title
+ user: core
+
+
+ *: "Track Info"
+
+
+ *: "Track Info"
+
+
diff --git a/apps/onplay.c b/apps/onplay.c
index 7245ac2016..a78cf7ceac 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -1595,6 +1595,9 @@ MENUITEM_FUNCTION(list_viewers_item, 0, ID2P(LANG_ONPLAY_OPEN_WITH),
MENUITEM_FUNCTION(properties_item, MENU_FUNC_USEPARAM, ID2P(LANG_PROPERTIES),
onplay_load_plugin, (void *)"properties",
clipboard_callback, Icon_NOICON);
+MENUITEM_FUNCTION(track_info_item, MENU_FUNC_USEPARAM, ID2P(LANG_MENU_SHOW_ID3_INFO),
+ onplay_load_plugin, (void *)"properties",
+ clipboard_callback, Icon_NOICON);
#ifdef HAVE_TAGCACHE
MENUITEM_FUNCTION(pictureflow_item, MENU_FUNC_USEPARAM, ID2P(LANG_ONPLAY_PICTUREFLOW),
onplay_load_plugin, (void *)"pictureflow",
@@ -1666,7 +1669,7 @@ static int clipboard_callback(int action,
{
if (((selected_file_attr & FILE_ATTR_MASK) ==
FILE_ATTR_AUDIO) &&
- (this_item == &properties_item ||
+ (this_item == &track_info_item ||
this_item == &pictureflow_item))
return action;
return ACTION_EXIT_MENUITEM;
@@ -1688,7 +1691,10 @@ static int clipboard_callback(int action,
if (this_item == &rename_file_item ||
this_item == &clipboard_cut_item ||
this_item == &clipboard_copy_item ||
- this_item == &properties_item ||
+ (this_item == &track_info_item &&
+ (selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) ||
+ (this_item == &properties_item &&
+ (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) ||
this_item == &add_to_faves_item)
{
return action;
@@ -1765,7 +1771,7 @@ MAKE_ONPLAYMENU( tree_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
#if LCD_DEPTH > 1
&set_backdrop_item,
#endif
- &list_viewers_item, &create_dir_item, &properties_item,
+ &list_viewers_item, &create_dir_item, &properties_item, &track_info_item,
#ifdef HAVE_TAGCACHE
&pictureflow_item,
#endif
diff --git a/apps/plugin.c b/apps/plugin.c
index 17b3c0214a..eb76eb7753 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * Copyright (C) 2002 Björn Stenberg
+ * Copyright (C) 2002 Björn Stenberg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -815,6 +815,7 @@ static const struct plugin_api rockbox_api = {
#endif
sys_poweroff,
sys_reboot,
+ browse_id3,
};
static int plugin_buffer_handle;
diff --git a/apps/plugin.h b/apps/plugin.h
index 89b8782cc7..a487f64168 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * Copyright (C) 2002 Björn Stenberg
+ * Copyright (C) 2002 Björn Stenberg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -112,6 +112,7 @@ int plugin_open(const char *plugin, const char *parameter);
#include "core_alloc.h"
#include "screen_access.h"
#include "onplay.h"
+#include "screens.h"
#ifdef HAVE_ALBUMART
#include "albumart.h"
@@ -156,7 +157,7 @@ int plugin_open(const char *plugin, const char *parameter);
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 250
+#define PLUGIN_API_VERSION 251
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
@@ -942,6 +943,8 @@ struct plugin_api {
#endif
void (*sys_poweroff)(void);
void (*sys_reboot)(void);
+ bool (*browse_id3)(struct mp3entry *id3,
+ int playlist_display_index, int playlist_amount);
};
/* plugin header */
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c
index fa3517726a..e5f00e307b 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -20,9 +20,19 @@
****************************************************************************/
#include "plugin.h"
+#if !defined(ARRAY_SIZE)
+ #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
+#endif
+enum props_types {
+ PROPS_FILE = 0,
+ PROPS_ID3,
+ PROPS_DIR
+};
-bool its_a_dir = false;
+static int props_type = PROPS_FILE;
+
+static struct mp3entry id3;
char str_filename[MAX_PATH];
char str_dirname[MAX_PATH];
@@ -32,27 +42,12 @@ char str_filecount[64];
char str_date[64];
char str_time[64];
-char str_title[MAX_PATH];
-char str_composer[MAX_PATH];
-char str_artist[MAX_PATH];
-char str_albumartist[MAX_PATH];
-char str_album[MAX_PATH];
-char str_genre[MAX_PATH];
-char str_comment[MAX_PATH];
-char str_year[MAX_PATH];
-char str_discnum[MAX_PATH];
-char str_tracknum[MAX_PATH];
-char str_duration[32];
-char str_bitrate[32];
-char str_frequency[32];
-
unsigned nseconds;
unsigned long nsize;
int32_t size_unit;
struct tm tm;
-int num_properties;
-
+#define NUM_FILE_PROPERTIES 5
static const unsigned char* const props_file[] =
{
ID2P(LANG_PROPERTIES_PATH), str_dirname,
@@ -60,20 +55,9 @@ static const unsigned char* const props_file[] =
ID2P(LANG_PROPERTIES_SIZE), str_size,
ID2P(LANG_PROPERTIES_DATE), str_date,
ID2P(LANG_PROPERTIES_TIME), str_time,
- ID2P(LANG_PROPERTIES_COMPOSER), str_composer,
- ID2P(LANG_PROPERTIES_ARTIST), str_artist,
- ID2P(LANG_PROPERTIES_ALBUMARTIST), str_albumartist,
- ID2P(LANG_PROPERTIES_TITLE), str_title,
- ID2P(LANG_PROPERTIES_ALBUM), str_album,
- ID2P(LANG_PROPERTIES_GENRE), str_genre,
- ID2P(LANG_PROPERTIES_COMMENT), str_comment,
- ID2P(LANG_PROPERTIES_YEAR), str_year,
- ID2P(LANG_PROPERTIES_DISCNUM), str_discnum,
- ID2P(LANG_PROPERTIES_TRACKNUM), str_tracknum,
- ID2P(LANG_PROPERTIES_DURATION), str_duration,
- ID2P(LANG_PROPERTIES_BITRATE), str_bitrate,
- ID2P(LANG_PROPERTIES_FREQUENCY), str_frequency,
};
+
+#define NUM_DIR_PROPERTIES 4
static const unsigned char* const props_dir[] =
{
ID2P(LANG_PROPERTIES_PATH), str_dirname,
@@ -107,7 +91,6 @@ static bool file_properties(const char* selected_file)
bool found = false;
DIR* dir;
struct dirent* entry;
- static struct mp3entry id3;
dir = rb->opendir(str_dirname);
if (dir)
@@ -128,81 +111,14 @@ static bool file_properties(const char* selected_file)
rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d",
tm.tm_hour, tm.tm_min, tm.tm_sec);
- num_properties = 5;
-
int fd = rb->open(selected_file, O_RDONLY);
- if (fd >= 0 &&
- rb->get_metadata(&id3, fd, selected_file))
+ if (fd >= 0)
{
- long dur = id3.length / 1000; /* seconds */
- rb->snprintf(str_composer, sizeof str_composer,
- "%s", id3.composer ? id3.composer : "");
- rb->snprintf(str_artist, sizeof str_artist,
- "%s", id3.artist ? id3.artist : "");
- rb->snprintf(str_albumartist, sizeof str_albumartist,
- "%s", id3.albumartist ? id3.albumartist : "");
- rb->snprintf(str_title, sizeof str_title,
- "%s", id3.title ? id3.title : "");
- rb->snprintf(str_album, sizeof str_album,
- "%s", id3.album ? id3.album : "");
- rb->snprintf(str_genre, sizeof str_genre,
- "%s", id3.genre_string ? id3.genre_string : "");
- rb->snprintf(str_comment, sizeof str_comment,
- "%s", id3.comment ? id3.comment : "");
+ if (rb->get_metadata(&id3, fd, selected_file))
+ props_type = PROPS_ID3;
- if (id3.year_string)
- rb->snprintf(str_year, sizeof str_year,
- "%s", id3.year_string);
- else if (id3.year)
- rb->snprintf(str_year, sizeof str_year,
- "%d", id3.year);
- else
- rb->snprintf(str_year, sizeof str_year,
- "%s", "");
-
- if (id3.disc_string)
- rb->snprintf(str_discnum, sizeof str_discnum,
- "%s", id3.disc_string);
- else if (id3.discnum)
- rb->snprintf(str_discnum, sizeof str_discnum,
- "%d", id3.discnum);
- else
- rb->snprintf(str_discnum, sizeof str_discnum,
- "%s", "");
-
- if (id3.track_string)
- rb->snprintf(str_tracknum, sizeof str_tracknum,
- "%s", id3.track_string);
- else if(id3.tracknum)
- rb->snprintf(str_tracknum, sizeof str_tracknum,
- "%d", id3.tracknum);
- else
- rb->snprintf(str_tracknum, sizeof str_tracknum,
- "%s", "");
-
- rb->snprintf(str_bitrate, sizeof str_bitrate,
- "%d kbps", id3.bitrate ? : 0);
- rb->snprintf(str_frequency, sizeof str_frequency,
- "%ld Hz", id3.frequency ? : 0);
- num_properties += 12;
-
- if (dur > 0)
- {
- nseconds = dur;
- if (dur < 3600)
- rb->snprintf(str_duration, sizeof str_duration,
- "%d:%02d", (int)(dur / 60),
- (int)(dur % 60));
- else
- rb->snprintf(str_duration, sizeof str_duration,
- "%d:%02d:%02d",
- (int)(dur / 3600),
- (int)(dur % 3600 / 60),
- (int)(dur % 60));
- num_properties++;
- }
+ rb->close(fd);
}
- rb->close(fd);
found = true;
break;
}
@@ -265,7 +181,7 @@ static bool _dir_properties(DPS *dps)
rb->lcd_putsf(0,3,"Files: %d", dps->fc);
log = human_size_log(dps->bc);
rb->lcd_putsf(0,4,"Size: %lu %cB", (unsigned long)(dps->bc >> (10*log)),
- rb->str(units[log]));
+ rb->str(units[log]));
rb->lcd_update();
}
@@ -314,7 +230,6 @@ static bool dir_properties(const char* selected_file, DPS *dps)
nsize = (long) (dps->bc >> (log*10));
size_unit = units[log];
rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit));
- num_properties = 4;
return true;
}
@@ -328,35 +243,20 @@ static const char * get_props(int selected_item, void* data,
char *buffer, size_t buffer_len)
{
(void)data;
- if(its_a_dir)
- {
- if(selected_item >= (int)(sizeof(props_dir) / sizeof(props_dir[0])))
- {
- rb->strlcpy(buffer, "ERROR", buffer_len);
- }
- else
- {
- rb->strlcpy(buffer, p2str(props_dir[selected_item]), buffer_len);
- }
- }
- else
- {
- if(selected_item >= (int)(sizeof(props_file) / sizeof(props_file[0])))
- {
- rb->strlcpy(buffer, "ERROR", buffer_len);
- }
- else
- {
- rb->strlcpy(buffer, p2str(props_file[selected_item]), buffer_len);
- }
- }
+ if (PROPS_DIR == props_type)
+ rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" :
+ (char *) p2str(props_dir[selected_item]), buffer_len);
+ else if (PROPS_FILE == props_type)
+ rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" :
+ (char *) p2str(props_file[selected_item]), buffer_len);
+
return buffer;
}
static int speak_property_selection(int selected_item, void *data)
{
DPS *dps = data;
- int32_t id = P2ID((its_a_dir ? props_dir : props_file)[selected_item]);
+ int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]);
rb->talk_id(id, false);
switch (id)
{
@@ -394,9 +294,6 @@ static int speak_property_selection(int selected_item, void *data)
case LANG_PROPERTIES_TIME:
rb->talk_time(&tm, true);
break;
- case LANG_PROPERTIES_DURATION:
- rb->talk_value_decimal(nseconds, UNIT_TIME, 0, true);
- break;
case LANG_PROPERTIES_SUBDIRS:
rb->talk_number(dps->dc, true);
break;
@@ -422,10 +319,10 @@ enum plugin_status plugin_start(const void* parameter)
#endif
static DPS dps = {
- .len = MAX_PATH,
- .dc = 0,
- .fc = 0,
- .bc = 0,
+ .len = MAX_PATH,
+ .dc = 0,
+ .fc = 0,
+ .bc = 0,
};
/* determine if it's a file or a directory */
@@ -446,7 +343,7 @@ enum plugin_status plugin_start(const void* parameter)
if(!rb->strcmp(entry->d_name, str_filename))
{
struct dirinfo info = rb->dir_get_info(dir, entry);
- its_a_dir = info.attribute & ATTR_DIRECTORY ? true : false;
+ props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE;
found = true;
break;
}
@@ -464,7 +361,7 @@ enum plugin_status plugin_start(const void* parameter)
}
/* get the info depending on its_a_dir */
- if(!(its_a_dir ? dir_properties(file, &dps) : file_properties(file)))
+ if(!(props_type == PROPS_DIR ? dir_properties(file, &dps) : file_properties(file)))
{
/* something went wrong (to do: tell user what it was (nesting,...) */
rb->splash(0, ID2P(LANG_PROPERTIES_FAIL));
@@ -475,40 +372,51 @@ enum plugin_status plugin_start(const void* parameter)
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_enable(i, true, NULL);
- rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL);
- rb->gui_synclist_set_title(&properties_lists, rb->str(its_a_dir ? LANG_PROPERTIES_DIRECTORY_PROPERTIES : LANG_PROPERTIES_FILE_PROPERTIES), NOICON);
- rb->gui_synclist_set_icon_callback(&properties_lists, NULL);
- if (rb->global_settings->talk_menu)
- rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
- rb->gui_synclist_set_nb_items(&properties_lists, num_properties * 2);
- rb->gui_synclist_limit_scroll(&properties_lists, true);
- rb->gui_synclist_select_item(&properties_lists, 0);
- rb->gui_synclist_draw(&properties_lists);
- rb->gui_synclist_speak_item(&properties_lists);
-
- while(!quit)
+ if (props_type == PROPS_ID3)
+ usb = rb->browse_id3(&id3, 0, 0);
+ else
{
- button = rb->get_action(CONTEXT_LIST, HZ);
- /* HZ so the status bar redraws corectly */
- if (rb->gui_synclist_do_button(&properties_lists,&button,LIST_WRAP_UNLESS_HELD))
- continue;
- switch(button)
+ rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL);
+ rb->gui_synclist_set_title(&properties_lists,
+ rb->str(props_type == PROPS_DIR ?
+ LANG_PROPERTIES_DIRECTORY_PROPERTIES :
+ LANG_PROPERTIES_FILE_PROPERTIES),
+ NOICON);
+ rb->gui_synclist_set_icon_callback(&properties_lists, NULL);
+ if (rb->global_settings->talk_menu)
+ rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
+ rb->gui_synclist_set_nb_items(&properties_lists,
+ 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES :
+ NUM_DIR_PROPERTIES));
+ rb->gui_synclist_limit_scroll(&properties_lists, true);
+ rb->gui_synclist_select_item(&properties_lists, 0);
+ rb->gui_synclist_draw(&properties_lists);
+ rb->gui_synclist_speak_item(&properties_lists);
+
+ while(!quit)
{
- case ACTION_STD_CANCEL:
- quit = true;
- break;
- default:
- if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
- {
+ button = rb->get_action(CONTEXT_LIST, HZ);
+ /* HZ so the status bar redraws corectly */
+ if (rb->gui_synclist_do_button(&properties_lists,&button,LIST_WRAP_UNLESS_HELD))
+ continue;
+ switch(button)
+ {
+ case ACTION_STD_CANCEL:
quit = true;
- usb = true;
- }
- break;
+ break;
+ default:
+ if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
+ {
+ quit = true;
+ usb = true;
+ }
+ break;
+ }
}
}
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_undo(i, false);
- return usb? PLUGIN_USB_CONNECTED: PLUGIN_OK;
+ return usb ? PLUGIN_USB_CONNECTED : PLUGIN_OK;
}
diff --git a/apps/screens.c b/apps/screens.c
index 5d56906b90..24d1fed915 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -595,6 +595,8 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
talk_value(id3->length /1000, UNIT_TIME, true);
break;
case LANG_ID3_PLAYLIST:
+ if (info->playlist_display_index == 0 || info->playlist_amount == 0 )
+ return NULL;
snprintf(buffer, buffer_len, "%d/%d",
info->playlist_display_index, info->playlist_amount);
val=buffer;
@@ -708,6 +710,7 @@ bool browse_id3(struct mp3entry *id3, int playlist_display_index, int playlist_a
if(global_settings.talk_menu)
gui_synclist_set_voice_callback(&id3_lists, id3_speak_item);
gui_synclist_set_nb_items(&id3_lists, info.count*2);
+ gui_synclist_set_title(&id3_lists, str(LANG_TRACK_INFO), NOICON);
gui_synclist_draw(&id3_lists);
gui_synclist_speak_item(&id3_lists);
while (true) {