diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/properties.c | 107 |
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 | ||
39 | enum props_types { | 36 | enum 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 { | |||
46 | static int props_type = PROPS_FILE; | 44 | static int props_type = PROPS_FILE; |
47 | 45 | ||
48 | static struct mp3entry id3; | 46 | static struct mp3entry id3; |
49 | #ifdef HAVE_TAGCACHE | ||
50 | static int mul_id3_count; | 47 | static int mul_id3_count; |
51 | static int skipped_count; | 48 | static int skipped_count; |
52 | #endif | ||
53 | 49 | ||
54 | static char str_filename[MAX_PATH]; | 50 | static char str_filename[MAX_PATH]; |
55 | static char str_dirname[MAX_PATH]; | 51 | static char str_dirname[MAX_PATH]; |
@@ -64,6 +60,7 @@ static int32_t size_unit; | |||
64 | static struct tm tm; | 60 | static 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 | ||
67 | static const unsigned char* const props_file[] = | 64 | static 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, | |||
259 | static int speak_property_selection(int selected_item, void *data) | 258 | static 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 | ||
376 | bool mul_id3_add(const char *file_name) | 382 | bool 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 | |||
395 | static 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 */ | ||
402 | static 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 | ||
390 | enum plugin_status plugin_start(const void* parameter) | 422 | enum 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 | } |