summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/misc.h3
-rw-r--r--apps/onplay.c35
-rw-r--r--apps/plugin.c3
-rw-r--r--apps/plugin.h6
-rw-r--r--apps/plugins/properties.c94
-rw-r--r--apps/tagtree.c138
-rw-r--r--apps/tagtree.h2
7 files changed, 205 insertions, 76 deletions
diff --git a/apps/misc.h b/apps/misc.h
index 51684cb658..403a8c53ac 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -187,6 +187,9 @@ enum current_activity {
187 ACTIVITY_USBSCREEN 187 ACTIVITY_USBSCREEN
188}; 188};
189 189
190/* custom string representation of activity */
191#define MAKE_ACT_STR(act) ((char[3]){'>', 'A'+ (act), 0x0})
192
190void beep_play(unsigned int frequency, unsigned int duration, 193void beep_play(unsigned int frequency, unsigned int duration,
191 unsigned int amplitude); 194 unsigned int amplitude);
192 195
diff --git a/apps/onplay.c b/apps/onplay.c
index f92ed76050..96c2ddd4e3 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -1611,8 +1611,33 @@ static bool list_viewers(void)
1611 return false; 1611 return false;
1612} 1612}
1613 1613
1614#ifdef HAVE_TAGCACHE
1615static bool prepare_database_sel(void *param)
1616{
1617 if (context == CONTEXT_ID3DB &&
1618 (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
1619 {
1620 if (!strcmp(param, "properties"))
1621 strmemccpy(selected_file_path, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER),
1622 sizeof(selected_file_path));
1623 else if (!tagtree_get_subentry_filename(selected_file_path, MAX_PATH))
1624 {
1625 onplay_result = ONPLAY_RELOAD_DIR;
1626 return false;
1627 }
1628
1629 selected_file = selected_file_path;
1630 }
1631 return true;
1632}
1633#endif
1634
1614static bool onplay_load_plugin(void *param) 1635static bool onplay_load_plugin(void *param)
1615{ 1636{
1637#ifdef HAVE_TAGCACHE
1638 if (!prepare_database_sel(param))
1639 return false;
1640#endif
1616 int ret = filetype_load_plugin((const char*)param, selected_file); 1641 int ret = filetype_load_plugin((const char*)param, selected_file);
1617 if (ret == PLUGIN_USB_CONNECTED) 1642 if (ret == PLUGIN_USB_CONNECTED)
1618 onplay_result = ONPLAY_RELOAD_DIR; 1643 onplay_result = ONPLAY_RELOAD_DIR;
@@ -1717,10 +1742,8 @@ static int clipboard_callback(int action,
1717#ifdef HAVE_TAGCACHE 1742#ifdef HAVE_TAGCACHE
1718 if (context == CONTEXT_ID3DB) 1743 if (context == CONTEXT_ID3DB)
1719 { 1744 {
1720 if (((selected_file_attr & FILE_ATTR_MASK) == 1745 if (this_item == &track_info_item ||
1721 FILE_ATTR_AUDIO) && 1746 this_item == &pictureflow_item)
1722 (this_item == &track_info_item ||
1723 this_item == &pictureflow_item))
1724 return action; 1747 return action;
1725 return ACTION_EXIT_MENUITEM; 1748 return ACTION_EXIT_MENUITEM;
1726 } 1749 }
@@ -1895,6 +1918,10 @@ static int hotkey_tree_pl_insert_shuffled(void)
1895 1918
1896static int hotkey_tree_run_plugin(void *param) 1919static int hotkey_tree_run_plugin(void *param)
1897{ 1920{
1921#ifdef HAVE_TAGCACHE
1922 if (!prepare_database_sel(param))
1923 return ONPLAY_RELOAD_DIR;
1924#endif
1898 if (filetype_load_plugin((const char*)param, selected_file) == PLUGIN_GOTO_WPS) 1925 if (filetype_load_plugin((const char*)param, selected_file) == PLUGIN_GOTO_WPS)
1899 return ONPLAY_START_PLAY; 1926 return ONPLAY_START_PLAY;
1900 1927
diff --git a/apps/plugin.c b/apps/plugin.c
index c28954e9eb..00fac21b8d 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -825,6 +825,9 @@ static const struct plugin_api rockbox_api = {
825 splash_progress_set_delay, 825 splash_progress_set_delay,
826 fix_path_part, 826 fix_path_part,
827 onplay_show_playlist_cat_menu, 827 onplay_show_playlist_cat_menu,
828#if defined(HAVE_TAGCACHE)
829 tagtree_subentries_do_action,
830#endif
828}; 831};
829 832
830static int plugin_buffer_handle; 833static int plugin_buffer_handle;
diff --git a/apps/plugin.h b/apps/plugin.h
index 850e7484d9..20df7e72f2 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -103,6 +103,7 @@ int plugin_open(const char *plugin, const char *parameter);
103#include "buflib.h" 103#include "buflib.h"
104#include "buffering.h" 104#include "buffering.h"
105#include "tagcache.h" 105#include "tagcache.h"
106#include "tagtree.h"
106#include "viewport.h" 107#include "viewport.h"
107#include "ata_idle_notify.h" 108#include "ata_idle_notify.h"
108#include "settings_list.h" 109#include "settings_list.h"
@@ -157,7 +158,7 @@ int plugin_open(const char *plugin, const char *parameter);
157#define PLUGIN_MAGIC 0x526F634B /* RocK */ 158#define PLUGIN_MAGIC 0x526F634B /* RocK */
158 159
159/* increase this every time the api struct changes */ 160/* increase this every time the api struct changes */
160#define PLUGIN_API_VERSION 263 161#define PLUGIN_API_VERSION 264
161 162
162/* update this to latest version if a change to the api struct breaks 163/* update this to latest version if a change to the api struct breaks
163 backwards compatibility (and please take the opportunity to sort in any 164 backwards compatibility (and please take the opportunity to sort in any
@@ -950,6 +951,9 @@ struct plugin_api {
950 void (*fix_path_part)(char* path, int offset, int count); 951 void (*fix_path_part)(char* path, int offset, int count);
951 void (*onplay_show_playlist_cat_menu)(const char* track_name, int attr, 952 void (*onplay_show_playlist_cat_menu)(const char* track_name, int attr,
952 void (*add_to_pl_cb)); 953 void (*add_to_pl_cb));
954#ifdef HAVE_TAGCACHE
955 bool (*tagtree_subentries_do_action)(bool (*action_cb)(const char *file_name));
956#endif
953}; 957};
954 958
955/* plugin header */ 959/* plugin header */
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c
index 46cf818fb4..7dacda3579 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -19,6 +19,11 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "plugin.h" 21#include "plugin.h"
22#include "lib/id3.h"
23
24#ifdef HAVE_TAGCACHE
25#include "lib/mul_id3.h"
26#endif
22 27
23#if !defined(ARRAY_SIZE) 28#if !defined(ARRAY_SIZE)
24 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) 29 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
@@ -35,12 +40,16 @@ struct dir_stats {
35enum props_types { 40enum props_types {
36 PROPS_FILE = 0, 41 PROPS_FILE = 0,
37 PROPS_ID3, 42 PROPS_ID3,
43 PROPS_MUL_ID3,
38 PROPS_DIR 44 PROPS_DIR
39}; 45};
40 46
41static int props_type = PROPS_FILE; 47static int props_type = PROPS_FILE;
42 48
43static struct mp3entry id3; 49static struct mp3entry id3;
50#ifdef HAVE_TAGCACHE
51static int mul_id3_count;
52#endif
44 53
45static char str_filename[MAX_PATH]; 54static char str_filename[MAX_PATH];
46static char str_dirname[MAX_PATH]; 55static char str_dirname[MAX_PATH];
@@ -118,14 +127,8 @@ static bool file_properties(const char* selected_file)
118 rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d", 127 rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d",
119 tm.tm_hour, tm.tm_min, tm.tm_sec); 128 tm.tm_hour, tm.tm_min, tm.tm_sec);
120 129
121 int fd = rb->open(selected_file, O_RDONLY); 130 if (retrieve_id3(&id3, selected_file, false))
122 if (fd >= 0) 131 props_type = PROPS_ID3;
123 {
124 if (rb->get_metadata(&id3, fd, selected_file))
125 props_type = PROPS_ID3;
126
127 rb->close(fd);
128 }
129 found = true; 132 found = true;
130 break; 133 break;
131 } 134 }
@@ -369,6 +372,19 @@ static bool determine_file_or_dir(void)
369 return false; 372 return false;
370} 373}
371 374
375#ifdef HAVE_TAGCACHE
376bool mul_id3_add(const char *file_name)
377{
378 if (!retrieve_id3(&id3, file_name, false))
379 return false;
380
381 collect_id3(&id3, mul_id3_count == 0);
382 mul_id3_count++;
383
384 return true;
385}
386#endif
387
372enum plugin_status plugin_start(const void* parameter) 388enum plugin_status plugin_start(const void* parameter)
373{ 389{
374 static struct dir_stats stats = 390 static struct dir_stats stats =
@@ -380,40 +396,62 @@ enum plugin_status plugin_start(const void* parameter)
380 }; 396 };
381 397
382 const char *file = parameter; 398 const char *file = parameter;
383 if(!parameter || (file[0] != '/')) return PLUGIN_ERROR; 399 if(!parameter)
400 return PLUGIN_ERROR;
384 401
385#ifdef HAVE_TOUCHSCREEN 402#ifdef HAVE_TOUCHSCREEN
386 rb->touchscreen_set_mode(rb->global_settings->touch_mode); 403 rb->touchscreen_set_mode(rb->global_settings->touch_mode);
387#endif 404#endif
388 405
389 const char* file_name = rb->strrchr(file, '/') + 1; 406#ifdef HAVE_TAGCACHE
390 int dirlen = (file_name - file); 407 if (!rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))) /* db table selected */
408 {
409 props_type = PROPS_MUL_ID3;
410 init_mul_id3();
411 mul_id3_count = 0;
391 412
392 rb->strlcpy(str_dirname, file, dirlen + 1); 413 if (!rb->tagtree_subentries_do_action(&mul_id3_add) || mul_id3_count == 0)
393 rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen); 414 return PLUGIN_ERROR;
394 415
395 if(!determine_file_or_dir()) 416 if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */
396 { 417 write_id3_mul_tracks(&id3);
397 /* weird: we couldn't find the entry. This Should Never Happen (TM) */
398 rb->splashf(0, "File/Dir not found: %s", file);
399 rb->action_userabort(TIMEOUT_BLOCK);
400 return PLUGIN_OK;
401 } 418 }
402 419 else
403 /* get the info depending on its_a_dir */ 420#endif
404 if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file))) 421 if (file[0] == '/') /* single track selected */
405 { 422 {
406 /* something went wrong (to do: tell user what it was (nesting,...) */ 423 const char* file_name = rb->strrchr(file, '/') + 1;
407 rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); 424 int dirlen = (file_name - file);
408 rb->action_userabort(TIMEOUT_BLOCK); 425
409 return PLUGIN_OK; 426 rb->strlcpy(str_dirname, file, dirlen + 1);
427 rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen);
428
429 if(!determine_file_or_dir())
430 {
431 /* weird: we couldn't find the entry. This Should Never Happen (TM) */
432 rb->splashf(0, "File/Dir not found: %s", file);
433 rb->action_userabort(TIMEOUT_BLOCK);
434 return PLUGIN_OK;
435 }
436
437 /* get the info depending on its_a_dir */
438 if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file)))
439 {
440 /* something went wrong (to do: tell user what it was (nesting,...) */
441 rb->splash(0, ID2P(LANG_PROPERTIES_FAIL));
442 rb->action_userabort(TIMEOUT_BLOCK);
443 return PLUGIN_OK;
444 }
410 } 445 }
446 else
447 return PLUGIN_ERROR;
411 448
412 FOR_NB_SCREENS(i) 449 FOR_NB_SCREENS(i)
413 rb->viewportmanager_theme_enable(i, true, NULL); 450 rb->viewportmanager_theme_enable(i, true, NULL);
414 451
415 bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm) : 452 bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm) :
416 browse_file_or_dir(&stats); 453 (props_type == PROPS_MUL_ID3 ? rb->browse_id3(&id3, 0, 0, NULL) :
454 browse_file_or_dir(&stats));
417 455
418 FOR_NB_SCREENS(i) 456 FOR_NB_SCREENS(i)
419 rb->viewportmanager_theme_undo(i, false); 457 rb->viewportmanager_theme_undo(i, false);
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 85359cac04..4248538f77 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -407,7 +407,7 @@ static int get_tag(int *tag)
407 407
408static int get_clause(int *condition) 408static int get_clause(int *condition)
409{ 409{
410 /* one or two operator conditionals */ 410 /* one or two operator conditionals */
411 #define OPS2VAL(op1, op2) ((int)op1 << 8 | (int)op2) 411 #define OPS2VAL(op1, op2) ((int)op1 << 8 | (int)op2)
412 #define CLAUSE(op1, op2, symbol) {OPS2VAL(op1, op2), symbol } 412 #define CLAUSE(op1, op2, symbol) {OPS2VAL(op1, op2), symbol }
413 413
@@ -2160,6 +2160,27 @@ static bool insert_all_playlist(struct tree_context *c,
2160 return true; 2160 return true;
2161} 2161}
2162 2162
2163static bool goto_allsubentries(int newtable)
2164{
2165 int i = 0;
2166 while (i < 2 && (newtable == NAVIBROWSE || newtable == ALLSUBENTRIES))
2167 {
2168 tagtree_enter(tc, false);
2169 tagtree_load(tc);
2170 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2171 i++;
2172 }
2173 return (newtable == PLAYTRACK);
2174}
2175
2176static void reset_tc_to_prev(int dirlevel, int selected_item)
2177{
2178 while (tc->dirlevel > dirlevel)
2179 tagtree_exit(tc, false);
2180 tc->selected_item = selected_item;
2181 tagtree_load(tc);
2182}
2183
2163static bool tagtree_insert_selection(int position, bool queue, 2184static bool tagtree_insert_selection(int position, bool queue,
2164 const char* playlist, bool new_playlist) 2185 const char* playlist, bool new_playlist)
2165{ 2186{
@@ -2167,6 +2188,7 @@ static bool tagtree_insert_selection(int position, bool queue,
2167 int dirlevel = tc->dirlevel; 2188 int dirlevel = tc->dirlevel;
2168 int selected_item = tc->selected_item; 2189 int selected_item = tc->selected_item;
2169 int newtable; 2190 int newtable;
2191 int ret;
2170 2192
2171 show_search_progress( 2193 show_search_progress(
2172#ifdef HAVE_DISK_STORAGE 2194#ifdef HAVE_DISK_STORAGE
@@ -2176,71 +2198,101 @@ static bool tagtree_insert_selection(int position, bool queue,
2176#endif 2198#endif
2177 , 0); 2199 , 0);
2178 2200
2179
2180 /* We need to set the table to allsubentries. */
2181 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; 2201 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2182 2202
2183 /* Insert a single track? */ 2203 if (newtable == PLAYTRACK) /* Insert a single track? */
2184 if (newtable == PLAYTRACK)
2185 { 2204 {
2186 if (tagtree_get_filename(tc, buf, sizeof buf) < 0) 2205 if (tagtree_get_filename(tc, buf, sizeof buf) < 0)
2187 {
2188 logf("tagtree_get_filename failed");
2189 return false; 2206 return false;
2190 } 2207
2191 playlist_insert_track(NULL, buf, position, queue, true); 2208 playlist_insert_track(NULL, buf, position, queue, true);
2192 2209
2193 return true; 2210 return true;
2194 } 2211 }
2195 2212
2196 if (newtable == NAVIBROWSE) 2213 ret = goto_allsubentries(newtable);
2197 { 2214 if (ret)
2198 tagtree_enter(tc, false);
2199 tagtree_load(tc);
2200 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2201 }
2202 else if (newtable != ALLSUBENTRIES)
2203 { 2215 {
2204 logf("unsupported table: %d", newtable); 2216 if (tc->filesindir <= 0)
2205 return false; 2217 splash(HZ, ID2P(LANG_END_PLAYLIST));
2218 else if (!insert_all_playlist(tc, playlist, new_playlist, position, queue))
2219 splash(HZ*2, ID2P(LANG_FAILED));
2206 } 2220 }
2207 2221
2208 /* Now the current table should be allsubentries. */ 2222 reset_tc_to_prev(dirlevel, selected_item);
2209 if (newtable != PLAYTRACK) 2223 return ret;
2210 { 2224}
2211 tagtree_enter(tc, false); 2225
2212 tagtree_load(tc); 2226/* Execute action_cb for all subentries of the current table's
2213 newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; 2227 * selected item, handing over each entry's filename in the
2228 * callback function parameter.
2229 */
2230bool tagtree_subentries_do_action(bool (*action_cb)(const char *file_name))
2231{
2232 struct tagcache_search tcs;
2233 int i, n;
2234 unsigned long last_tick;
2235 char buf[MAX_PATH];
2236 int ret = true;
2237 int dirlevel = tc->dirlevel;
2238 int selected_item = tc->selected_item;
2239 int newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2214 2240
2215 /* And now the newtable should be playtrack. */ 2241 cpu_boost(true);
2216 if (newtable != PLAYTRACK) 2242 if (!goto_allsubentries(newtable))
2243 ret = false;
2244 else if (tagcache_search(&tcs, tag_filename))
2245 {
2246 last_tick = current_tick + HZ/2;
2247 splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
2248 n = tc->filesindir;
2249 for (i = 0; i < n; i++)
2217 { 2250 {
2218 logf("newtable: %d !!", newtable); 2251 splash_progress(i, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
2219 while (tc->dirlevel > dirlevel) 2252 if (TIME_AFTER(current_tick, last_tick + HZ/4))
2220 tagtree_exit(tc, false); 2253 {
2221 tagtree_load(tc); 2254 if (action_userabort(TIMEOUT_NOBLOCK))
2222 return false; 2255 break;
2256 last_tick = current_tick;
2257 }
2258
2259 if (!tagcache_retrieve(&tcs, tagtree_get_entry(tc, i)->extraseek,
2260 tcs.type, buf, sizeof buf)
2261 || !action_cb(buf))
2262 {
2263 ret = false;
2264 break;
2265 }
2266 yield();
2223 } 2267 }
2224 }
2225 2268
2226 if (tc->filesindir <= 0) 2269 tagcache_search_finish(&tcs);
2227 splash(HZ, ID2P(LANG_END_PLAYLIST)); 2270 }
2228 else 2271 else
2229 { 2272 {
2230 logf("insert_all_playlist"); 2273 splash(HZ, ID2P(LANG_TAGCACHE_BUSY));
2231 if (!insert_all_playlist(tc, playlist, new_playlist, position, queue)) 2274 ret = false;
2232 splash(HZ*2, ID2P(LANG_FAILED));
2233 } 2275 }
2276 reset_tc_to_prev(dirlevel, selected_item);
2277 cpu_boost(false);
2278 return ret;
2279}
2234 2280
2235 /* Finally return the dirlevel to its original value. */ 2281/* Try to return first subentry's filename for current selection
2236 while (tc->dirlevel > dirlevel) 2282 */
2237 tagtree_exit(tc, false); 2283bool tagtree_get_subentry_filename(char *buf, size_t bufsize)
2238 tc->selected_item = selected_item; 2284{
2239 tagtree_load(tc); 2285 int ret = true;
2286 int dirlevel = tc->dirlevel;
2287 int selected_item = tc->selected_item;
2288 int newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
2240 2289
2241 return true; 2290 if (!goto_allsubentries(newtable) || tagtree_get_filename(tc, buf, bufsize) < 0)
2242} 2291 ret = false;
2243 2292
2293 reset_tc_to_prev(dirlevel, selected_item);
2294 return ret;
2295}
2244 2296
2245bool tagtree_current_playlist_insert(int position, bool queue) 2297bool tagtree_current_playlist_insert(int position, bool queue)
2246{ 2298{
diff --git a/apps/tagtree.h b/apps/tagtree.h
index 6eaaf3dfac..39ab545bd0 100644
--- a/apps/tagtree.h
+++ b/apps/tagtree.h
@@ -45,6 +45,8 @@ char *tagtree_get_title(struct tree_context* c);
45int tagtree_get_attr(struct tree_context* c); 45int tagtree_get_attr(struct tree_context* c);
46int tagtree_get_icon(struct tree_context* c); 46int tagtree_get_icon(struct tree_context* c);
47int tagtree_get_filename(struct tree_context* c, char *buf, int buflen); 47int tagtree_get_filename(struct tree_context* c, char *buf, int buflen);
48bool tagtree_get_subentry_filename(char *buf, size_t bufsize);
49bool tagtree_subentries_do_action(bool (*action_cb)(const char *file_name));
48 50
49#endif 51#endif
50#endif 52#endif