summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/properties.c236
1 files changed, 72 insertions, 164 deletions
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 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "plugin.h" 21#include "plugin.h"
22 22
23#if !defined(ARRAY_SIZE)
24 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
25#endif
26
27enum props_types {
28 PROPS_FILE = 0,
29 PROPS_ID3,
30 PROPS_DIR
31};
23 32
33static int props_type = PROPS_FILE;
24 34
25bool its_a_dir = false; 35static struct mp3entry id3;
26 36
27char str_filename[MAX_PATH]; 37char str_filename[MAX_PATH];
28char str_dirname[MAX_PATH]; 38char str_dirname[MAX_PATH];
@@ -32,27 +42,12 @@ char str_filecount[64];
32char str_date[64]; 42char str_date[64];
33char str_time[64]; 43char str_time[64];
34 44
35char str_title[MAX_PATH];
36char str_composer[MAX_PATH];
37char str_artist[MAX_PATH];
38char str_albumartist[MAX_PATH];
39char str_album[MAX_PATH];
40char str_genre[MAX_PATH];
41char str_comment[MAX_PATH];
42char str_year[MAX_PATH];
43char str_discnum[MAX_PATH];
44char str_tracknum[MAX_PATH];
45char str_duration[32];
46char str_bitrate[32];
47char str_frequency[32];
48
49unsigned nseconds; 45unsigned nseconds;
50unsigned long nsize; 46unsigned long nsize;
51int32_t size_unit; 47int32_t size_unit;
52struct tm tm; 48struct tm tm;
53 49
54int num_properties; 50#define NUM_FILE_PROPERTIES 5
55
56static const unsigned char* const props_file[] = 51static const unsigned char* const props_file[] =
57{ 52{
58 ID2P(LANG_PROPERTIES_PATH), str_dirname, 53 ID2P(LANG_PROPERTIES_PATH), str_dirname,
@@ -60,20 +55,9 @@ static const unsigned char* const props_file[] =
60 ID2P(LANG_PROPERTIES_SIZE), str_size, 55 ID2P(LANG_PROPERTIES_SIZE), str_size,
61 ID2P(LANG_PROPERTIES_DATE), str_date, 56 ID2P(LANG_PROPERTIES_DATE), str_date,
62 ID2P(LANG_PROPERTIES_TIME), str_time, 57 ID2P(LANG_PROPERTIES_TIME), str_time,
63 ID2P(LANG_PROPERTIES_COMPOSER), str_composer,
64 ID2P(LANG_PROPERTIES_ARTIST), str_artist,
65 ID2P(LANG_PROPERTIES_ALBUMARTIST), str_albumartist,
66 ID2P(LANG_PROPERTIES_TITLE), str_title,
67 ID2P(LANG_PROPERTIES_ALBUM), str_album,
68 ID2P(LANG_PROPERTIES_GENRE), str_genre,
69 ID2P(LANG_PROPERTIES_COMMENT), str_comment,
70 ID2P(LANG_PROPERTIES_YEAR), str_year,
71 ID2P(LANG_PROPERTIES_DISCNUM), str_discnum,
72 ID2P(LANG_PROPERTIES_TRACKNUM), str_tracknum,
73 ID2P(LANG_PROPERTIES_DURATION), str_duration,
74 ID2P(LANG_PROPERTIES_BITRATE), str_bitrate,
75 ID2P(LANG_PROPERTIES_FREQUENCY), str_frequency,
76}; 58};
59
60#define NUM_DIR_PROPERTIES 4
77static const unsigned char* const props_dir[] = 61static const unsigned char* const props_dir[] =
78{ 62{
79 ID2P(LANG_PROPERTIES_PATH), str_dirname, 63 ID2P(LANG_PROPERTIES_PATH), str_dirname,
@@ -107,7 +91,6 @@ static bool file_properties(const char* selected_file)
107 bool found = false; 91 bool found = false;
108 DIR* dir; 92 DIR* dir;
109 struct dirent* entry; 93 struct dirent* entry;
110 static struct mp3entry id3;
111 94
112 dir = rb->opendir(str_dirname); 95 dir = rb->opendir(str_dirname);
113 if (dir) 96 if (dir)
@@ -128,81 +111,14 @@ static bool file_properties(const char* selected_file)
128 rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d", 111 rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d",
129 tm.tm_hour, tm.tm_min, tm.tm_sec); 112 tm.tm_hour, tm.tm_min, tm.tm_sec);
130 113
131 num_properties = 5;
132
133 int fd = rb->open(selected_file, O_RDONLY); 114 int fd = rb->open(selected_file, O_RDONLY);
134 if (fd >= 0 && 115 if (fd >= 0)
135 rb->get_metadata(&id3, fd, selected_file))
136 { 116 {
137 long dur = id3.length / 1000; /* seconds */ 117 if (rb->get_metadata(&id3, fd, selected_file))
138 rb->snprintf(str_composer, sizeof str_composer, 118 props_type = PROPS_ID3;
139 "%s", id3.composer ? id3.composer : ""); 119
140 rb->snprintf(str_artist, sizeof str_artist, 120 rb->close(fd);
141 "%s", id3.artist ? id3.artist : "");
142 rb->snprintf(str_albumartist, sizeof str_albumartist,
143 "%s", id3.albumartist ? id3.albumartist : "");
144 rb->snprintf(str_title, sizeof str_title,
145 "%s", id3.title ? id3.title : "");
146 rb->snprintf(str_album, sizeof str_album,
147 "%s", id3.album ? id3.album : "");
148 rb->snprintf(str_genre, sizeof str_genre,
149 "%s", id3.genre_string ? id3.genre_string : "");
150 rb->snprintf(str_comment, sizeof str_comment,
151 "%s", id3.comment ? id3.comment : "");
152
153 if (id3.year_string)
154 rb->snprintf(str_year, sizeof str_year,
155 "%s", id3.year_string);
156 else if (id3.year)
157 rb->snprintf(str_year, sizeof str_year,
158 "%d", id3.year);
159 else
160 rb->snprintf(str_year, sizeof str_year,
161 "%s", "");
162
163 if (id3.disc_string)
164 rb->snprintf(str_discnum, sizeof str_discnum,
165 "%s", id3.disc_string);
166 else if (id3.discnum)
167 rb->snprintf(str_discnum, sizeof str_discnum,
168 "%d", id3.discnum);
169 else
170 rb->snprintf(str_discnum, sizeof str_discnum,
171 "%s", "");
172
173 if (id3.track_string)
174 rb->snprintf(str_tracknum, sizeof str_tracknum,
175 "%s", id3.track_string);
176 else if(id3.tracknum)
177 rb->snprintf(str_tracknum, sizeof str_tracknum,
178 "%d", id3.tracknum);
179 else
180 rb->snprintf(str_tracknum, sizeof str_tracknum,
181 "%s", "");
182
183 rb->snprintf(str_bitrate, sizeof str_bitrate,
184 "%d kbps", id3.bitrate ? : 0);
185 rb->snprintf(str_frequency, sizeof str_frequency,
186 "%ld Hz", id3.frequency ? : 0);
187 num_properties += 12;
188
189 if (dur > 0)
190 {
191 nseconds = dur;
192 if (dur < 3600)
193 rb->snprintf(str_duration, sizeof str_duration,
194 "%d:%02d", (int)(dur / 60),
195 (int)(dur % 60));
196 else
197 rb->snprintf(str_duration, sizeof str_duration,
198 "%d:%02d:%02d",
199 (int)(dur / 3600),
200 (int)(dur % 3600 / 60),
201 (int)(dur % 60));
202 num_properties++;
203 }
204 } 121 }
205 rb->close(fd);
206 found = true; 122 found = true;
207 break; 123 break;
208 } 124 }
@@ -265,7 +181,7 @@ static bool _dir_properties(DPS *dps)
265 rb->lcd_putsf(0,3,"Files: %d", dps->fc); 181 rb->lcd_putsf(0,3,"Files: %d", dps->fc);
266 log = human_size_log(dps->bc); 182 log = human_size_log(dps->bc);
267 rb->lcd_putsf(0,4,"Size: %lu %cB", (unsigned long)(dps->bc >> (10*log)), 183 rb->lcd_putsf(0,4,"Size: %lu %cB", (unsigned long)(dps->bc >> (10*log)),
268 rb->str(units[log])); 184 rb->str(units[log]));
269 rb->lcd_update(); 185 rb->lcd_update();
270 } 186 }
271 187
@@ -314,7 +230,6 @@ static bool dir_properties(const char* selected_file, DPS *dps)
314 nsize = (long) (dps->bc >> (log*10)); 230 nsize = (long) (dps->bc >> (log*10));
315 size_unit = units[log]; 231 size_unit = units[log];
316 rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit)); 232 rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit));
317 num_properties = 4;
318 return true; 233 return true;
319} 234}
320 235
@@ -328,35 +243,20 @@ static const char * get_props(int selected_item, void* data,
328 char *buffer, size_t buffer_len) 243 char *buffer, size_t buffer_len)
329{ 244{
330 (void)data; 245 (void)data;
331 if(its_a_dir) 246 if (PROPS_DIR == props_type)
332 { 247 rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_dir)) ? "ERROR" :
333 if(selected_item >= (int)(sizeof(props_dir) / sizeof(props_dir[0]))) 248 (char *) p2str(props_dir[selected_item]), buffer_len);
334 { 249 else if (PROPS_FILE == props_type)
335 rb->strlcpy(buffer, "ERROR", buffer_len); 250 rb->strlcpy(buffer, selected_item >= (int)(ARRAY_SIZE(props_file)) ? "ERROR" :
336 } 251 (char *) p2str(props_file[selected_item]), buffer_len);
337 else 252
338 {
339 rb->strlcpy(buffer, p2str(props_dir[selected_item]), buffer_len);
340 }
341 }
342 else
343 {
344 if(selected_item >= (int)(sizeof(props_file) / sizeof(props_file[0])))
345 {
346 rb->strlcpy(buffer, "ERROR", buffer_len);
347 }
348 else
349 {
350 rb->strlcpy(buffer, p2str(props_file[selected_item]), buffer_len);
351 }
352 }
353 return buffer; 253 return buffer;
354} 254}
355 255
356static int speak_property_selection(int selected_item, void *data) 256static int speak_property_selection(int selected_item, void *data)
357{ 257{
358 DPS *dps = data; 258 DPS *dps = data;
359 int32_t id = P2ID((its_a_dir ? props_dir : props_file)[selected_item]); 259 int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]);
360 rb->talk_id(id, false); 260 rb->talk_id(id, false);
361 switch (id) 261 switch (id)
362 { 262 {
@@ -394,9 +294,6 @@ static int speak_property_selection(int selected_item, void *data)
394 case LANG_PROPERTIES_TIME: 294 case LANG_PROPERTIES_TIME:
395 rb->talk_time(&tm, true); 295 rb->talk_time(&tm, true);
396 break; 296 break;
397 case LANG_PROPERTIES_DURATION:
398 rb->talk_value_decimal(nseconds, UNIT_TIME, 0, true);
399 break;
400 case LANG_PROPERTIES_SUBDIRS: 297 case LANG_PROPERTIES_SUBDIRS:
401 rb->talk_number(dps->dc, true); 298 rb->talk_number(dps->dc, true);
402 break; 299 break;
@@ -422,10 +319,10 @@ enum plugin_status plugin_start(const void* parameter)
422#endif 319#endif
423 320
424 static DPS dps = { 321 static DPS dps = {
425 .len = MAX_PATH, 322 .len = MAX_PATH,
426 .dc = 0, 323 .dc = 0,
427 .fc = 0, 324 .fc = 0,
428 .bc = 0, 325 .bc = 0,
429 }; 326 };
430 327
431 /* determine if it's a file or a directory */ 328 /* determine if it's a file or a directory */
@@ -446,7 +343,7 @@ enum plugin_status plugin_start(const void* parameter)
446 if(!rb->strcmp(entry->d_name, str_filename)) 343 if(!rb->strcmp(entry->d_name, str_filename))
447 { 344 {
448 struct dirinfo info = rb->dir_get_info(dir, entry); 345 struct dirinfo info = rb->dir_get_info(dir, entry);
449 its_a_dir = info.attribute & ATTR_DIRECTORY ? true : false; 346 props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE;
450 found = true; 347 found = true;
451 break; 348 break;
452 } 349 }
@@ -464,7 +361,7 @@ enum plugin_status plugin_start(const void* parameter)
464 } 361 }
465 362
466 /* get the info depending on its_a_dir */ 363 /* get the info depending on its_a_dir */
467 if(!(its_a_dir ? dir_properties(file, &dps) : file_properties(file))) 364 if(!(props_type == PROPS_DIR ? dir_properties(file, &dps) : file_properties(file)))
468 { 365 {
469 /* something went wrong (to do: tell user what it was (nesting,...) */ 366 /* something went wrong (to do: tell user what it was (nesting,...) */
470 rb->splash(0, ID2P(LANG_PROPERTIES_FAIL)); 367 rb->splash(0, ID2P(LANG_PROPERTIES_FAIL));
@@ -475,40 +372,51 @@ enum plugin_status plugin_start(const void* parameter)
475 FOR_NB_SCREENS(i) 372 FOR_NB_SCREENS(i)
476 rb->viewportmanager_theme_enable(i, true, NULL); 373 rb->viewportmanager_theme_enable(i, true, NULL);
477 374
478 rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL); 375 if (props_type == PROPS_ID3)
479 rb->gui_synclist_set_title(&properties_lists, rb->str(its_a_dir ? LANG_PROPERTIES_DIRECTORY_PROPERTIES : LANG_PROPERTIES_FILE_PROPERTIES), NOICON); 376 usb = rb->browse_id3(&id3, 0, 0);
480 rb->gui_synclist_set_icon_callback(&properties_lists, NULL); 377 else
481 if (rb->global_settings->talk_menu)
482 rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
483 rb->gui_synclist_set_nb_items(&properties_lists, num_properties * 2);
484 rb->gui_synclist_limit_scroll(&properties_lists, true);
485 rb->gui_synclist_select_item(&properties_lists, 0);
486 rb->gui_synclist_draw(&properties_lists);
487 rb->gui_synclist_speak_item(&properties_lists);
488
489 while(!quit)
490 { 378 {
491 button = rb->get_action(CONTEXT_LIST, HZ); 379 rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL);
492 /* HZ so the status bar redraws corectly */ 380 rb->gui_synclist_set_title(&properties_lists,
493 if (rb->gui_synclist_do_button(&properties_lists,&button,LIST_WRAP_UNLESS_HELD)) 381 rb->str(props_type == PROPS_DIR ?
494 continue; 382 LANG_PROPERTIES_DIRECTORY_PROPERTIES :
495 switch(button) 383 LANG_PROPERTIES_FILE_PROPERTIES),
384 NOICON);
385 rb->gui_synclist_set_icon_callback(&properties_lists, NULL);
386 if (rb->global_settings->talk_menu)
387 rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
388 rb->gui_synclist_set_nb_items(&properties_lists,
389 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES :
390 NUM_DIR_PROPERTIES));
391 rb->gui_synclist_limit_scroll(&properties_lists, true);
392 rb->gui_synclist_select_item(&properties_lists, 0);
393 rb->gui_synclist_draw(&properties_lists);
394 rb->gui_synclist_speak_item(&properties_lists);
395
396 while(!quit)
496 { 397 {
497 case ACTION_STD_CANCEL: 398 button = rb->get_action(CONTEXT_LIST, HZ);
498 quit = true; 399 /* HZ so the status bar redraws corectly */
499 break; 400 if (rb->gui_synclist_do_button(&properties_lists,&button,LIST_WRAP_UNLESS_HELD))
500 default: 401 continue;
501 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) 402 switch(button)
502 { 403 {
404 case ACTION_STD_CANCEL:
503 quit = true; 405 quit = true;
504 usb = true; 406 break;
505 } 407 default:
506 break; 408 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
409 {
410 quit = true;
411 usb = true;
412 }
413 break;
414 }
507 } 415 }
508 } 416 }
509 417
510 FOR_NB_SCREENS(i) 418 FOR_NB_SCREENS(i)
511 rb->viewportmanager_theme_undo(i, false); 419 rb->viewportmanager_theme_undo(i, false);
512 420
513 return usb? PLUGIN_USB_CONNECTED: PLUGIN_OK; 421 return usb ? PLUGIN_USB_CONNECTED : PLUGIN_OK;
514} 422}