summaryrefslogtreecommitdiff
path: root/apps/plugins/properties.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/properties.c')
-rw-r--r--apps/plugins/properties.c107
1 files changed, 70 insertions, 37 deletions
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c
index ce3c03694c..32bc8b9150 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -19,10 +19,7 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "plugin.h" 21#include "plugin.h"
22
23#ifdef HAVE_TAGCACHE
24#include "lib/mul_id3.h" 22#include "lib/mul_id3.h"
25#endif
26 23
27#if !defined(ARRAY_SIZE) 24#if !defined(ARRAY_SIZE)
28 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) 25 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
@@ -38,6 +35,7 @@ struct dir_stats {
38 35
39enum props_types { 36enum props_types {
40 PROPS_FILE = 0, 37 PROPS_FILE = 0,
38 PROPS_PLAYLIST,
41 PROPS_ID3, 39 PROPS_ID3,
42 PROPS_MUL_ID3, 40 PROPS_MUL_ID3,
43 PROPS_DIR 41 PROPS_DIR
@@ -46,10 +44,8 @@ enum props_types {
46static int props_type = PROPS_FILE; 44static int props_type = PROPS_FILE;
47 45
48static struct mp3entry id3; 46static struct mp3entry id3;
49#ifdef HAVE_TAGCACHE
50static int mul_id3_count; 47static int mul_id3_count;
51static int skipped_count; 48static int skipped_count;
52#endif
53 49
54static char str_filename[MAX_PATH]; 50static char str_filename[MAX_PATH];
55static char str_dirname[MAX_PATH]; 51static char str_dirname[MAX_PATH];
@@ -64,6 +60,7 @@ static int32_t size_unit;
64static struct tm tm; 60static struct tm tm;
65 61
66#define NUM_FILE_PROPERTIES 5 62#define NUM_FILE_PROPERTIES 5
63#define NUM_PLAYLIST_PROPERTIES 1 + NUM_FILE_PROPERTIES
67static const unsigned char* const props_file[] = 64static const unsigned char* const props_file[] =
68{ 65{
69 ID2P(LANG_PROPERTIES_PATH), str_dirname, 66 ID2P(LANG_PROPERTIES_PATH), str_dirname,
@@ -71,6 +68,7 @@ static const unsigned char* const props_file[] =
71 ID2P(LANG_PROPERTIES_SIZE), str_size, 68 ID2P(LANG_PROPERTIES_SIZE), str_size,
72 ID2P(LANG_PROPERTIES_DATE), str_date, 69 ID2P(LANG_PROPERTIES_DATE), str_date,
73 ID2P(LANG_PROPERTIES_TIME), str_time, 70 ID2P(LANG_PROPERTIES_TIME), str_time,
71 ID2P(LANG_MENU_SHOW_ID3_INFO), "...",
74}; 72};
75 73
76#define NUM_DIR_PROPERTIES 4 74#define NUM_DIR_PROPERTIES 4
@@ -120,7 +118,8 @@ static bool file_properties(const char* selected_file)
120 log = human_size_log((unsigned long)info.size); 118 log = human_size_log((unsigned long)info.size);
121 nsize = ((unsigned long)info.size) >> (log*10); 119 nsize = ((unsigned long)info.size) >> (log*10);
122 size_unit = units[log]; 120 size_unit = units[log];
123 rb->snprintf(str_size, sizeof str_size, "%lu %s", nsize, rb->str(size_unit)); 121 rb->snprintf(str_size, sizeof str_size, "%lu %s",
122 nsize, rb->str(size_unit));
124 rb->gmtime_r(&info.mtime, &tm); 123 rb->gmtime_r(&info.mtime, &tm);
125 rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", 124 rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d",
126 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); 125 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
@@ -249,7 +248,7 @@ static const char * get_props(int selected_item, void* data,
249 if (PROPS_DIR == props_type) 248 if (PROPS_DIR == props_type)
250 rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" : 249 rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" :
251 (char *) p2str(props_dir[selected_item]), buffer_len); 250 (char *) p2str(props_dir[selected_item]), buffer_len);
252 else if (PROPS_FILE == props_type) 251 else
253 rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" : 252 rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" :
254 (char *) p2str(props_file[selected_item]), buffer_len); 253 (char *) p2str(props_file[selected_item]), buffer_len);
255 254
@@ -259,7 +258,8 @@ static const char * get_props(int selected_item, void* data,
259static int speak_property_selection(int selected_item, void *data) 258static int speak_property_selection(int selected_item, void *data)
260{ 259{
261 struct dir_stats *stats = data; 260 struct dir_stats *stats = data;
262 int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]); 261 int32_t id = P2ID((props_type == PROPS_DIR ?
262 props_dir : props_file)[selected_item]);
263 rb->talk_id(id, false); 263 rb->talk_id(id, false);
264 switch (id) 264 switch (id)
265 { 265 {
@@ -326,7 +326,8 @@ static int browse_file_or_dir(struct dir_stats *stats)
326 rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); 326 rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
327 rb->gui_synclist_set_nb_items(&properties_lists, 327 rb->gui_synclist_set_nb_items(&properties_lists,
328 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : 328 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES :
329 NUM_DIR_PROPERTIES)); 329 props_type == PROPS_PLAYLIST ?
330 NUM_PLAYLIST_PROPERTIES : NUM_DIR_PROPERTIES));
330 rb->gui_synclist_select_item(&properties_lists, 0); 331 rb->gui_synclist_select_item(&properties_lists, 0);
331 rb->gui_synclist_draw(&properties_lists); 332 rb->gui_synclist_draw(&properties_lists);
332 rb->gui_synclist_speak_item(&properties_lists); 333 rb->gui_synclist_speak_item(&properties_lists);
@@ -339,11 +340,17 @@ static int browse_file_or_dir(struct dir_stats *stats)
339 continue; 340 continue;
340 switch(button) 341 switch(button)
341 { 342 {
343 case ACTION_STD_OK:
344 if (props_type == PROPS_PLAYLIST &&
345 rb->gui_synclist_get_sel_pos(&properties_lists)
346 == ARRAY_SIZE(props_file) - 2)
347 return -1;
348 break;
342 case ACTION_STD_CANCEL: 349 case ACTION_STD_CANCEL:
343 return false; 350 return 0;
344 default: 351 default:
345 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) 352 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
346 return true; 353 return 1;
347 break; 354 break;
348 } 355 }
349 } 356 }
@@ -372,7 +379,6 @@ static bool determine_file_or_dir(void)
372 return false; 379 return false;
373} 380}
374 381
375#ifdef HAVE_TAGCACHE
376bool mul_id3_add(const char *file_name) 382bool mul_id3_add(const char *file_name)
377{ 383{
378 if (!file_name || rb->mp3info(&id3, file_name)) 384 if (!file_name || rb->mp3info(&id3, file_name))
@@ -385,10 +391,37 @@ bool mul_id3_add(const char *file_name)
385 391
386 return true; 392 return true;
387} 393}
394
395static bool has_pl_extension(const char* filename)
396{
397 char *dot = rb->strrchr(filename, '.');
398 return (dot && (!rb->strcasecmp(dot, ".m3u") || !rb->strcasecmp(dot, ".m3u8")));
399}
400
401/* Assemble track info from a database table or the contents of a playlist file */
402static bool assemble_track_info(const char *filename)
403{
404 props_type = PROPS_MUL_ID3;
405 mul_id3_count = skipped_count = 0;
406
407 if ( (filename && !rb->playlist_entries_iterate(filename, NULL, &mul_id3_add))
408#ifdef HAVE_TAGCACHE
409 || (!filename && !rb->tagtree_subentries_do_action(&mul_id3_add))
388#endif 410#endif
411 || mul_id3_count == 0)
412 return false;
413 else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */
414 finalize_id3(&id3);
415
416 if (skipped_count > 0)
417 rb->splashf(HZ*2, "Skipped %d", skipped_count);
418
419 return true;
420}
389 421
390enum plugin_status plugin_start(const void* parameter) 422enum plugin_status plugin_start(const void* parameter)
391{ 423{
424 int ret;
392 static struct dir_stats stats = 425 static struct dir_stats stats =
393 { 426 {
394 .len = MAX_PATH, 427 .len = MAX_PATH,
@@ -405,23 +438,7 @@ enum plugin_status plugin_start(const void* parameter)
405 rb->touchscreen_set_mode(rb->global_settings->touch_mode); 438 rb->touchscreen_set_mode(rb->global_settings->touch_mode);
406#endif 439#endif
407 440
408#ifdef HAVE_TAGCACHE 441 if (file[0] == '/') /* single file selected */
409 if (!rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))) /* db table selected */
410 {
411 props_type = PROPS_MUL_ID3;
412 mul_id3_count = skipped_count = 0;
413
414 if (!rb->tagtree_subentries_do_action(&mul_id3_add) || mul_id3_count == 0)
415 return PLUGIN_ERROR;
416 else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */
417 finalize_id3(&id3);
418
419 if (skipped_count > 0)
420 rb->splashf(HZ*2, "Skipped %d", skipped_count);
421 }
422 else
423#endif
424 if (file[0] == '/') /* single track selected */
425 { 442 {
426 const char* file_name = rb->strrchr(file, '/') + 1; 443 const char* file_name = rb->strrchr(file, '/') + 1;
427 int dirlen = (file_name - file); 444 int dirlen = (file_name - file);
@@ -437,8 +454,12 @@ enum plugin_status plugin_start(const void* parameter)
437 return PLUGIN_OK; 454 return PLUGIN_OK;
438 } 455 }
439 456
457 if (props_type == PROPS_FILE && has_pl_extension(file))
458 props_type = PROPS_PLAYLIST;
459
440 /* get the info depending on its_a_dir */ 460 /* get the info depending on its_a_dir */
441 if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file))) 461 if(!(props_type == PROPS_DIR ?
462 dir_properties(file, &stats) : file_properties(file)))
442 { 463 {
443 /* something went wrong (to do: tell user what it was (nesting,...) */ 464 /* something went wrong (to do: tell user what it was (nesting,...) */
444 rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); 465 rb->splash(0, ID2P(LANG_PROPERTIES_FAIL));
@@ -446,20 +467,32 @@ enum plugin_status plugin_start(const void* parameter)
446 return PLUGIN_OK; 467 return PLUGIN_OK;
447 } 468 }
448 } 469 }
449 else 470 /* database table selected */
471 else if (rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))
472 || !assemble_track_info(NULL))
450 return PLUGIN_ERROR; 473 return PLUGIN_ERROR;
451 474
452 FOR_NB_SCREENS(i) 475 FOR_NB_SCREENS(i)
453 rb->viewportmanager_theme_enable(i, true, NULL); 476 rb->viewportmanager_theme_enable(i, true, NULL);
454 477
455 bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm, 1) : 478 if (props_type == PROPS_ID3)
456#ifdef HAVE_TAGCACHE 479 ret = rb->browse_id3(&id3, 0, 0, &tm, 1); /* Track Info for single file */
457 props_type == PROPS_MUL_ID3 ? rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) : 480 else if (props_type == PROPS_MUL_ID3)
458#endif 481 ret = rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count); /* database tracks */
459 browse_file_or_dir(&stats); 482 else if ((ret = browse_file_or_dir(&stats)) < 0)
483 ret = assemble_track_info(file) ? /* playlist tracks */
484 rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) : -1;
460 485
461 FOR_NB_SCREENS(i) 486 FOR_NB_SCREENS(i)
462 rb->viewportmanager_theme_undo(i, false); 487 rb->viewportmanager_theme_undo(i, false);
463 488
464 return usb ? PLUGIN_USB_CONNECTED : PLUGIN_OK; 489 switch (ret)
490 {
491 case 1:
492 return PLUGIN_USB_CONNECTED;
493 case -1:
494 return PLUGIN_ERROR;
495 default:
496 return PLUGIN_OK;
497 }
465} 498}