diff options
Diffstat (limited to 'apps/plugins/properties.c')
-rw-r--r-- | apps/plugins/properties.c | 433 |
1 files changed, 143 insertions, 290 deletions
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c index 32bc8b9150..dcd3d89edf 100644 --- a/apps/plugins/properties.c +++ b/apps/plugins/properties.c | |||
@@ -25,14 +25,6 @@ | |||
25 | #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) | 25 | #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | struct dir_stats { | ||
29 | char dirname[MAX_PATH]; | ||
30 | int len; | ||
31 | unsigned int dir_count; | ||
32 | unsigned int file_count; | ||
33 | unsigned long long byte_count; | ||
34 | }; | ||
35 | |||
36 | enum props_types { | 28 | enum props_types { |
37 | PROPS_FILE = 0, | 29 | PROPS_FILE = 0, |
38 | PROPS_PLAYLIST, | 30 | PROPS_PLAYLIST, |
@@ -41,26 +33,20 @@ enum props_types { | |||
41 | PROPS_DIR | 33 | PROPS_DIR |
42 | }; | 34 | }; |
43 | 35 | ||
44 | static int props_type = PROPS_FILE; | 36 | static struct gui_synclist properties_lists; |
45 | |||
46 | static struct mp3entry id3; | 37 | static struct mp3entry id3; |
47 | static int mul_id3_count; | 38 | static struct tm tm; |
48 | static int skipped_count; | 39 | static unsigned long display_size; |
40 | static int32_t lang_size_unit; | ||
41 | static int props_type, mul_id3_count, skipped_count; | ||
49 | 42 | ||
50 | static char str_filename[MAX_PATH]; | 43 | static char str_filename[MAX_PATH], str_dirname[MAX_PATH], |
51 | static char str_dirname[MAX_PATH]; | 44 | str_size[64], str_dircount[64], str_filecount[64], |
52 | static char str_size[64]; | 45 | str_audio_filecount[64], str_date[64], str_time[64]; |
53 | static char str_dircount[64]; | ||
54 | static char str_filecount[64]; | ||
55 | static char str_date[64]; | ||
56 | static char str_time[64]; | ||
57 | 46 | ||
58 | static unsigned long nsize; | ||
59 | static int32_t size_unit; | ||
60 | static struct tm tm; | ||
61 | 47 | ||
62 | #define NUM_FILE_PROPERTIES 5 | 48 | #define NUM_FILE_PROPERTIES 5 |
63 | #define NUM_PLAYLIST_PROPERTIES 1 + NUM_FILE_PROPERTIES | 49 | #define NUM_PLAYLIST_PROPERTIES (1 + NUM_FILE_PROPERTIES) |
64 | static const unsigned char* const props_file[] = | 50 | static const unsigned char* const props_file[] = |
65 | { | 51 | { |
66 | ID2P(LANG_PROPERTIES_PATH), str_dirname, | 52 | ID2P(LANG_PROPERTIES_PATH), str_dirname, |
@@ -68,170 +54,44 @@ static const unsigned char* const props_file[] = | |||
68 | ID2P(LANG_PROPERTIES_SIZE), str_size, | 54 | ID2P(LANG_PROPERTIES_SIZE), str_size, |
69 | ID2P(LANG_PROPERTIES_DATE), str_date, | 55 | ID2P(LANG_PROPERTIES_DATE), str_date, |
70 | ID2P(LANG_PROPERTIES_TIME), str_time, | 56 | ID2P(LANG_PROPERTIES_TIME), str_time, |
57 | |||
71 | ID2P(LANG_MENU_SHOW_ID3_INFO), "...", | 58 | ID2P(LANG_MENU_SHOW_ID3_INFO), "...", |
72 | }; | 59 | }; |
73 | 60 | ||
74 | #define NUM_DIR_PROPERTIES 4 | 61 | #define NUM_DIR_PROPERTIES 4 |
62 | #define NUM_AUDIODIR_PROPERTIES (1 + NUM_DIR_PROPERTIES) | ||
75 | static const unsigned char* const props_dir[] = | 63 | static const unsigned char* const props_dir[] = |
76 | { | 64 | { |
77 | ID2P(LANG_PROPERTIES_PATH), str_dirname, | 65 | ID2P(LANG_PROPERTIES_PATH), str_dirname, |
78 | ID2P(LANG_PROPERTIES_SUBDIRS), str_dircount, | 66 | ID2P(LANG_PROPERTIES_SUBDIRS), str_dircount, |
79 | ID2P(LANG_PROPERTIES_FILES), str_filecount, | 67 | ID2P(LANG_PROPERTIES_FILES), str_filecount, |
80 | ID2P(LANG_PROPERTIES_SIZE), str_size, | 68 | ID2P(LANG_PROPERTIES_SIZE), str_size, |
81 | }; | ||
82 | 69 | ||
83 | static const int32_t units[] = | 70 | ID2P(LANG_MENU_SHOW_ID3_INFO), str_audio_filecount, |
84 | { | ||
85 | LANG_BYTE, | ||
86 | LANG_KIBIBYTE, | ||
87 | LANG_MEBIBYTE, | ||
88 | LANG_GIBIBYTE | ||
89 | }; | 71 | }; |
90 | 72 | ||
91 | static unsigned human_size_log(unsigned long long size) | ||
92 | { | ||
93 | const size_t n = sizeof(units)/sizeof(units[0]); | ||
94 | |||
95 | unsigned i; | ||
96 | /* margin set at 10K boundary: 10239 B +1 => 10 KB */ | ||
97 | for(i=0; i < n-1 && size >= 10*1024; i++) | ||
98 | size >>= 10; /* div by 1024 */ | ||
99 | |||
100 | return i; | ||
101 | } | ||
102 | |||
103 | static bool file_properties(const char* selected_file) | ||
104 | { | ||
105 | bool found = false; | ||
106 | DIR* dir; | ||
107 | struct dirent* entry; | ||
108 | |||
109 | dir = rb->opendir(str_dirname); | ||
110 | if (dir) | ||
111 | { | ||
112 | while(0 != (entry = rb->readdir(dir))) | ||
113 | { | ||
114 | struct dirinfo info = rb->dir_get_info(dir, entry); | ||
115 | if(!rb->strcmp(entry->d_name, str_filename)) | ||
116 | { | ||
117 | unsigned log; | ||
118 | log = human_size_log((unsigned long)info.size); | ||
119 | nsize = ((unsigned long)info.size) >> (log*10); | ||
120 | size_unit = units[log]; | ||
121 | rb->snprintf(str_size, sizeof str_size, "%lu %s", | ||
122 | nsize, rb->str(size_unit)); | ||
123 | rb->gmtime_r(&info.mtime, &tm); | ||
124 | rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", | ||
125 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | ||
126 | rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d", | ||
127 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
128 | |||
129 | if (!rb->mp3info(&id3, selected_file)) | ||
130 | props_type = PROPS_ID3; | ||
131 | found = true; | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | rb->closedir(dir); | ||
136 | } | ||
137 | return found; | ||
138 | } | ||
139 | |||
140 | static bool _dir_properties(struct dir_stats *stats) | ||
141 | { | ||
142 | /* recursively scan directories in search of files | ||
143 | and informs the user of the progress */ | ||
144 | bool result; | ||
145 | static long lasttick=0; | ||
146 | int dirlen; | ||
147 | DIR* dir; | ||
148 | struct dirent* entry; | ||
149 | |||
150 | result = true; | ||
151 | dirlen = rb->strlen(stats->dirname); | ||
152 | dir = rb->opendir(stats->dirname); | ||
153 | if (!dir) | ||
154 | { | ||
155 | rb->splashf(HZ*2, "%s", stats->dirname); | ||
156 | return false; /* open error */ | ||
157 | } | ||
158 | |||
159 | /* walk through the directory content */ | ||
160 | while(result && (0 != (entry = rb->readdir(dir)))) | ||
161 | { | ||
162 | struct dirinfo info = rb->dir_get_info(dir, entry); | ||
163 | /* append name to current directory */ | ||
164 | rb->snprintf(stats->dirname+dirlen, stats->len-dirlen, "/%s", | ||
165 | entry->d_name); | ||
166 | |||
167 | if (info.attribute & ATTR_DIRECTORY) | ||
168 | { | ||
169 | if (!rb->strcmp((char *)entry->d_name, ".") || | ||
170 | !rb->strcmp((char *)entry->d_name, "..")) | ||
171 | continue; /* skip these */ | ||
172 | |||
173 | stats->dir_count++; /* new directory */ | ||
174 | if (*rb->current_tick - lasttick > (HZ/8)) | ||
175 | { | ||
176 | unsigned log; | ||
177 | lasttick = *rb->current_tick; | ||
178 | rb->lcd_clear_display(); | ||
179 | rb->lcd_puts(0,0,"SCANNING..."); | ||
180 | rb->lcd_puts(0,1,stats->dirname); | ||
181 | rb->lcd_putsf(0,2,"Directories: %d", stats->dir_count); | ||
182 | rb->lcd_putsf(0,3,"Files: %d", stats->file_count); | ||
183 | log = human_size_log(stats->byte_count); | ||
184 | rb->lcd_putsf(0,4,"Size: %lu %s", | ||
185 | (unsigned long)(stats->byte_count >> (10*log)), | ||
186 | rb->str(units[log])); | ||
187 | rb->lcd_update(); | ||
188 | } | ||
189 | |||
190 | /* recursion */ | ||
191 | result = _dir_properties(stats); | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | stats->file_count++; /* new file */ | ||
196 | stats->byte_count += info.size; | ||
197 | } | ||
198 | if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK)) | ||
199 | result = false; | ||
200 | rb->yield(); | ||
201 | } | ||
202 | rb->closedir(dir); | ||
203 | return result; | ||
204 | } | ||
205 | |||
206 | static bool dir_properties(const char* selected_file, struct dir_stats *stats) | 73 | static bool dir_properties(const char* selected_file, struct dir_stats *stats) |
207 | { | 74 | { |
208 | unsigned log; | 75 | rb->strlcpy(stats->dirname, selected_file, sizeof(stats->dirname)); |
209 | |||
210 | rb->strlcpy(stats->dirname, selected_file, MAX_PATH); | ||
211 | 76 | ||
212 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 77 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
213 | rb->cpu_boost(true); | 78 | rb->cpu_boost(true); |
214 | #endif | 79 | #endif |
215 | 80 | bool success = collect_dir_stats(stats, NULL); | |
216 | if (!_dir_properties(stats)) | ||
217 | { | ||
218 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 81 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
219 | rb->cpu_boost(false); | 82 | rb->cpu_boost(false); |
220 | #endif | 83 | #endif |
84 | if (!success) | ||
221 | return false; | 85 | return false; |
222 | } | ||
223 | 86 | ||
224 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 87 | rb->strlcpy(str_dirname, selected_file, sizeof(str_dirname)); |
225 | rb->cpu_boost(false); | ||
226 | #endif | ||
227 | |||
228 | rb->strlcpy(str_dirname, selected_file, MAX_PATH); | ||
229 | rb->snprintf(str_dircount, sizeof str_dircount, "%d", stats->dir_count); | 88 | rb->snprintf(str_dircount, sizeof str_dircount, "%d", stats->dir_count); |
230 | rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count); | 89 | rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count); |
231 | log = human_size_log(stats->byte_count); | 90 | rb->snprintf(str_audio_filecount, sizeof str_filecount, "%d", |
232 | nsize = (long) (stats->byte_count >> (log*10)); | 91 | stats->audio_file_count); |
233 | size_unit = units[log]; | 92 | display_size = human_size(stats->byte_count, &lang_size_unit); |
234 | rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit)); | 93 | rb->snprintf(str_size, sizeof str_size, "%lu %s", display_size, |
94 | rb->str(lang_size_unit)); | ||
235 | return true; | 95 | return true; |
236 | } | 96 | } |
237 | 97 | ||
@@ -246,12 +106,11 @@ static const char * get_props(int selected_item, void* data, | |||
246 | { | 106 | { |
247 | (void)data; | 107 | (void)data; |
248 | if (PROPS_DIR == props_type) | 108 | if (PROPS_DIR == props_type) |
249 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" : | 109 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? |
250 | (char *) p2str(props_dir[selected_item]), buffer_len); | 110 | "ERROR" : (char *) p2str(props_dir[selected_item]), buffer_len); |
251 | else | 111 | else |
252 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" : | 112 | rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? |
253 | (char *) p2str(props_file[selected_item]), buffer_len); | 113 | "ERROR" : (char *) p2str(props_file[selected_item]), buffer_len); |
254 | |||
255 | return buffer; | 114 | return buffer; |
256 | } | 115 | } |
257 | 116 | ||
@@ -264,32 +123,14 @@ static int speak_property_selection(int selected_item, void *data) | |||
264 | switch (id) | 123 | switch (id) |
265 | { | 124 | { |
266 | case LANG_PROPERTIES_PATH: | 125 | case LANG_PROPERTIES_PATH: |
267 | if (str_dirname[0] == '/') | 126 | rb->talk_fullpath(str_dirname, true); |
268 | { | ||
269 | char *start = str_dirname; | ||
270 | char *ptr; | ||
271 | while (0 != (ptr = rb->strchr(start, '/'))) | ||
272 | { | ||
273 | *ptr = '\0'; | ||
274 | rb->talk_dir_or_spell(str_dirname, NULL, true); | ||
275 | *ptr = '/'; | ||
276 | rb->talk_id(VOICE_CHAR_SLASH, true); | ||
277 | start = ptr + 1; | ||
278 | } | ||
279 | if (*start) | ||
280 | rb->talk_dir_or_spell(str_dirname, NULL, true); | ||
281 | } | ||
282 | else | ||
283 | { | ||
284 | rb->talk_spell(str_dirname, true); | ||
285 | } | ||
286 | break; | 127 | break; |
287 | case LANG_PROPERTIES_FILENAME: | 128 | case LANG_PROPERTIES_FILENAME: |
288 | rb->talk_file_or_spell(str_dirname, str_filename, NULL, true); | 129 | rb->talk_file_or_spell(str_dirname, str_filename, NULL, true); |
289 | break; | 130 | break; |
290 | case LANG_PROPERTIES_SIZE: | 131 | case LANG_PROPERTIES_SIZE: |
291 | rb->talk_number(nsize, true); | 132 | rb->talk_number(display_size, true); |
292 | rb->talk_id(size_unit, true); | 133 | rb->talk_id(lang_size_unit, true); |
293 | break; | 134 | break; |
294 | case LANG_PROPERTIES_DATE: | 135 | case LANG_PROPERTIES_DATE: |
295 | rb->talk_date(&tm, true); | 136 | rb->talk_date(&tm, true); |
@@ -310,40 +151,46 @@ static int speak_property_selection(int selected_item, void *data) | |||
310 | return 0; | 151 | return 0; |
311 | } | 152 | } |
312 | 153 | ||
313 | static int browse_file_or_dir(struct dir_stats *stats) | 154 | static void setup_properties_list(struct dir_stats *stats) |
314 | { | 155 | { |
315 | struct gui_synclist properties_lists; | 156 | int nb_props; |
316 | int button; | 157 | if (props_type == PROPS_FILE) |
158 | nb_props = NUM_FILE_PROPERTIES; | ||
159 | else if (props_type == PROPS_PLAYLIST) | ||
160 | nb_props = NUM_PLAYLIST_PROPERTIES; | ||
161 | else | ||
162 | nb_props = NUM_DIR_PROPERTIES; | ||
317 | 163 | ||
318 | rb->gui_synclist_init(&properties_lists, &get_props, stats, false, 2, NULL); | 164 | rb->gui_synclist_init(&properties_lists, &get_props, stats, false, 2, NULL); |
319 | rb->gui_synclist_set_title(&properties_lists, | 165 | rb->gui_synclist_set_title(&properties_lists, |
320 | rb->str(props_type == PROPS_DIR ? | 166 | rb->str(props_type == PROPS_DIR ? |
321 | LANG_PROPERTIES_DIRECTORY_PROPERTIES : | 167 | LANG_PROPERTIES_DIRECTORY_PROPERTIES : |
322 | LANG_PROPERTIES_FILE_PROPERTIES), | 168 | LANG_PROPERTIES_FILE_PROPERTIES), |
323 | NOICON); | 169 | NOICON); |
324 | rb->gui_synclist_set_icon_callback(&properties_lists, NULL); | ||
325 | if (rb->global_settings->talk_menu) | 170 | if (rb->global_settings->talk_menu) |
326 | rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); | 171 | rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection); |
327 | rb->gui_synclist_set_nb_items(&properties_lists, | 172 | rb->gui_synclist_set_nb_items(&properties_lists, nb_props*2); |
328 | 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES : | 173 | } |
329 | props_type == PROPS_PLAYLIST ? | 174 | |
330 | NUM_PLAYLIST_PROPERTIES : NUM_DIR_PROPERTIES)); | 175 | static int browse_file_or_dir(struct dir_stats *stats) |
331 | rb->gui_synclist_select_item(&properties_lists, 0); | 176 | { |
177 | if (props_type == PROPS_DIR && stats->audio_file_count) | ||
178 | rb->gui_synclist_set_nb_items(&properties_lists, NUM_AUDIODIR_PROPERTIES*2); | ||
332 | rb->gui_synclist_draw(&properties_lists); | 179 | rb->gui_synclist_draw(&properties_lists); |
333 | rb->gui_synclist_speak_item(&properties_lists); | 180 | rb->gui_synclist_speak_item(&properties_lists); |
334 | |||
335 | while(true) | 181 | while(true) |
336 | { | 182 | { |
337 | button = rb->get_action(CONTEXT_LIST, HZ); | 183 | int button = rb->get_action(CONTEXT_LIST, HZ); |
338 | /* HZ so the status bar redraws corectly */ | 184 | /* HZ so the status bar redraws corectly */ |
339 | if (rb->gui_synclist_do_button(&properties_lists,&button)) | 185 | if (rb->gui_synclist_do_button(&properties_lists, &button)) |
340 | continue; | 186 | continue; |
341 | switch(button) | 187 | switch(button) |
342 | { | 188 | { |
343 | case ACTION_STD_OK: | 189 | case ACTION_STD_OK: |
344 | if (props_type == PROPS_PLAYLIST && | 190 | if ((props_type == PROPS_PLAYLIST || props_type == PROPS_DIR) && |
345 | rb->gui_synclist_get_sel_pos(&properties_lists) | 191 | rb->gui_synclist_get_sel_pos(&properties_lists) |
346 | == ARRAY_SIZE(props_file) - 2) | 192 | == (props_type == PROPS_DIR ? |
193 | ARRAY_SIZE(props_dir) : ARRAY_SIZE(props_file)) - 2) | ||
347 | return -1; | 194 | return -1; |
348 | break; | 195 | break; |
349 | case ACTION_STD_CANCEL: | 196 | case ACTION_STD_CANCEL: |
@@ -356,60 +203,101 @@ static int browse_file_or_dir(struct dir_stats *stats) | |||
356 | } | 203 | } |
357 | } | 204 | } |
358 | 205 | ||
359 | static bool determine_file_or_dir(void) | 206 | static bool determine_props_type(const char *file) |
360 | { | 207 | { |
361 | DIR* dir; | 208 | if (file[0] == PATH_SEPCH) |
362 | struct dirent* entry; | ||
363 | |||
364 | dir = rb->opendir(str_dirname); | ||
365 | if (dir) | ||
366 | { | 209 | { |
210 | const char* basename = rb->strrchr(file, PATH_SEPCH) + 1; | ||
211 | const int dir_len = (basename - file); | ||
212 | if ((int) sizeof(str_dirname) <= dir_len) | ||
213 | return false; | ||
214 | rb->strlcpy(str_dirname, file, dir_len + 1); | ||
215 | rb->strlcpy(str_filename, basename, sizeof str_filename); | ||
216 | struct dirent* entry; | ||
217 | DIR* dir = rb->opendir(str_dirname); | ||
218 | if (!dir) | ||
219 | return false; | ||
367 | while(0 != (entry = rb->readdir(dir))) | 220 | while(0 != (entry = rb->readdir(dir))) |
368 | { | 221 | { |
369 | if(!rb->strcmp(entry->d_name, str_filename)) | 222 | if(rb->strcmp(entry->d_name, str_filename)) |
223 | continue; | ||
224 | |||
225 | struct dirinfo info = rb->dir_get_info(dir, entry); | ||
226 | if (info.attribute & ATTR_DIRECTORY) | ||
227 | props_type = PROPS_DIR; | ||
228 | else | ||
370 | { | 229 | { |
371 | struct dirinfo info = rb->dir_get_info(dir, entry); | 230 | display_size = human_size(info.size, &lang_size_unit); |
372 | props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE; | 231 | rb->snprintf(str_size, sizeof str_size, "%lu %s", |
373 | rb->closedir(dir); | 232 | display_size, rb->str(lang_size_unit)); |
374 | return true; | 233 | rb->gmtime_r(&info.mtime, &tm); |
234 | rb->snprintf(str_date, sizeof str_date, "%04d/%02d/%02d", | ||
235 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | ||
236 | rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d", | ||
237 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
238 | |||
239 | if (rb->filetype_get_attr(entry->d_name) == FILE_ATTR_M3U) | ||
240 | props_type = PROPS_PLAYLIST; | ||
241 | else | ||
242 | props_type = rb->get_metadata(&id3, -1, file) ? | ||
243 | PROPS_ID3 : PROPS_FILE; | ||
375 | } | 244 | } |
245 | rb->closedir(dir); | ||
246 | return true; | ||
376 | } | 247 | } |
377 | rb->closedir(dir); | 248 | rb->closedir(dir); |
378 | } | 249 | } |
250 | else if (!rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))) | ||
251 | { | ||
252 | props_type = PROPS_MUL_ID3; | ||
253 | return true; | ||
254 | } | ||
379 | return false; | 255 | return false; |
380 | } | 256 | } |
381 | 257 | ||
382 | bool mul_id3_add(const char *file_name) | 258 | bool mul_id3_add(const char *file_name) |
383 | { | 259 | { |
384 | if (!file_name || rb->mp3info(&id3, file_name)) | 260 | if (!file_name || !rb->get_metadata(&id3, -1, file_name)) |
385 | skipped_count++; | 261 | skipped_count++; |
386 | else | 262 | else |
387 | { | 263 | { |
388 | collect_id3(&id3, mul_id3_count == 0); | 264 | collect_id3(&id3, mul_id3_count == 0); |
389 | mul_id3_count++; | 265 | mul_id3_count++; |
390 | } | 266 | } |
391 | |||
392 | return true; | 267 | return true; |
393 | } | 268 | } |
394 | 269 | ||
395 | static bool has_pl_extension(const char* filename) | 270 | /* Assemble track info from a dir, a playlist, or a database table */ |
396 | { | 271 | static bool assemble_track_info(const char *filename, struct dir_stats *stats) |
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 | { | 272 | { |
404 | props_type = PROPS_MUL_ID3; | 273 | if (props_type == PROPS_DIR) |
405 | mul_id3_count = skipped_count = 0; | 274 | { |
406 | 275 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | |
407 | if ( (filename && !rb->playlist_entries_iterate(filename, NULL, &mul_id3_add)) | 276 | rb->cpu_boost(true); |
277 | #endif | ||
278 | rb->strlcpy(stats->dirname, filename, sizeof(stats->dirname)); | ||
279 | rb->splash_progress_set_delay(HZ/2); /* hide progress bar for 0.5s */ | ||
280 | bool success = collect_dir_stats(stats, &mul_id3_add); | ||
281 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
282 | rb->cpu_boost(false); | ||
283 | #endif | ||
284 | if (!success) | ||
285 | return false; | ||
286 | } | ||
287 | else if(props_type == PROPS_PLAYLIST && | ||
288 | !rb->playlist_entries_iterate(filename, NULL, &mul_id3_add)) | ||
289 | return false; | ||
408 | #ifdef HAVE_TAGCACHE | 290 | #ifdef HAVE_TAGCACHE |
409 | || (!filename && !rb->tagtree_subentries_do_action(&mul_id3_add)) | 291 | else if (props_type == PROPS_MUL_ID3 && |
292 | !rb->tagtree_subentries_do_action(&mul_id3_add)) | ||
293 | return false; | ||
410 | #endif | 294 | #endif |
411 | || mul_id3_count == 0) | 295 | |
296 | if (mul_id3_count == 0) | ||
297 | { | ||
298 | rb->splashf(HZ*2, "None found"); | ||
412 | return false; | 299 | return false; |
300 | } | ||
413 | else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */ | 301 | else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */ |
414 | finalize_id3(&id3); | 302 | finalize_id3(&id3); |
415 | 303 | ||
@@ -421,78 +309,43 @@ static bool assemble_track_info(const char *filename) | |||
421 | 309 | ||
422 | enum plugin_status plugin_start(const void* parameter) | 310 | enum plugin_status plugin_start(const void* parameter) |
423 | { | 311 | { |
424 | int ret; | 312 | static struct dir_stats stats; |
425 | static struct dir_stats stats = | ||
426 | { | ||
427 | .len = MAX_PATH, | ||
428 | .dir_count = 0, | ||
429 | .file_count = 0, | ||
430 | .byte_count = 0, | ||
431 | }; | ||
432 | |||
433 | const char *file = parameter; | 313 | const char *file = parameter; |
434 | if(!parameter) | ||
435 | return PLUGIN_ERROR; | ||
436 | |||
437 | #ifdef HAVE_TOUCHSCREEN | 314 | #ifdef HAVE_TOUCHSCREEN |
438 | rb->touchscreen_set_mode(rb->global_settings->touch_mode); | 315 | rb->touchscreen_set_mode(rb->global_settings->touch_mode); |
439 | #endif | 316 | #endif |
440 | 317 | int ret = file && determine_props_type(file); | |
441 | if (file[0] == '/') /* single file selected */ | 318 | if (!ret) |
442 | { | 319 | { |
443 | const char* file_name = rb->strrchr(file, '/') + 1; | 320 | rb->splashf(0, "Could not find: %s", file ?: "(NULL)"); |
444 | int dirlen = (file_name - file); | 321 | rb->action_userabort(TIMEOUT_BLOCK); |
445 | 322 | return PLUGIN_OK; | |
446 | rb->strlcpy(str_dirname, file, dirlen + 1); | 323 | } |
447 | rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen); | ||
448 | |||
449 | if(!determine_file_or_dir()) | ||
450 | { | ||
451 | /* weird: we couldn't find the entry. This Should Never Happen (TM) */ | ||
452 | rb->splashf(0, "File/Dir not found: %s", file); | ||
453 | rb->action_userabort(TIMEOUT_BLOCK); | ||
454 | return PLUGIN_OK; | ||
455 | } | ||
456 | |||
457 | if (props_type == PROPS_FILE && has_pl_extension(file)) | ||
458 | props_type = PROPS_PLAYLIST; | ||
459 | 324 | ||
460 | /* get the info depending on its_a_dir */ | 325 | if (props_type == PROPS_MUL_ID3) |
461 | if(!(props_type == PROPS_DIR ? | 326 | ret = assemble_track_info(NULL, NULL); |
462 | dir_properties(file, &stats) : file_properties(file))) | 327 | else if (props_type != PROPS_ID3) |
328 | { | ||
329 | setup_properties_list(&stats); /* Show title during dir scan */ | ||
330 | if (props_type == PROPS_DIR) | ||
331 | ret = dir_properties(file, &stats); | ||
332 | } | ||
333 | if (!ret) | ||
334 | { | ||
335 | if (!stats.canceled) | ||
463 | { | 336 | { |
464 | /* something went wrong (to do: tell user what it was (nesting,...) */ | 337 | rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); /* TODO: describe error */ |
465 | rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); | ||
466 | rb->action_userabort(TIMEOUT_BLOCK); | 338 | rb->action_userabort(TIMEOUT_BLOCK); |
467 | return PLUGIN_OK; | ||
468 | } | 339 | } |
469 | } | 340 | } |
470 | /* database table selected */ | 341 | else if (props_type == PROPS_ID3) |
471 | else if (rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER)) | ||
472 | || !assemble_track_info(NULL)) | ||
473 | return PLUGIN_ERROR; | ||
474 | |||
475 | FOR_NB_SCREENS(i) | ||
476 | rb->viewportmanager_theme_enable(i, true, NULL); | ||
477 | |||
478 | if (props_type == PROPS_ID3) | ||
479 | ret = rb->browse_id3(&id3, 0, 0, &tm, 1); /* Track Info for single file */ | 342 | ret = rb->browse_id3(&id3, 0, 0, &tm, 1); /* Track Info for single file */ |
480 | else if (props_type == PROPS_MUL_ID3) | 343 | else if (props_type == PROPS_MUL_ID3) |
481 | ret = rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count); /* database tracks */ | 344 | ret = rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count); /* database tracks */ |
482 | else if ((ret = browse_file_or_dir(&stats)) < 0) | 345 | else if ((ret = browse_file_or_dir(&stats)) < 0) |
483 | ret = assemble_track_info(file) ? /* playlist tracks */ | 346 | ret = assemble_track_info(file, &stats) ? /* playlist or folder tracks */ |
484 | rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) : -1; | 347 | rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) : |
348 | (stats.canceled ? 0 : -1); | ||
485 | 349 | ||
486 | FOR_NB_SCREENS(i) | 350 | return ret == -1 ? PLUGIN_ERROR : ret == 1 ? PLUGIN_USB_CONNECTED : PLUGIN_OK; |
487 | rb->viewportmanager_theme_undo(i, false); | ||
488 | |||
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 | } | ||
498 | } | 351 | } |