summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/plugin.c3
-rw-r--r--apps/plugin.h5
-rw-r--r--apps/plugins/pictureflow/pictureflow.c258
-rw-r--r--apps/screens.c6
4 files changed, 256 insertions, 16 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index b017db017b..7c6e91424a 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -821,6 +821,9 @@ static const struct plugin_api rockbox_api = {
821 821
822 /* new stuff at the end, sort into place next time 822 /* new stuff at the end, sort into place next time
823 the API gets incompatible */ 823 the API gets incompatible */
824
825 splash_progress,
826 splash_progress_set_delay,
824}; 827};
825 828
826static int plugin_buffer_handle; 829static int plugin_buffer_handle;
diff --git a/apps/plugin.h b/apps/plugin.h
index ed688eb753..768fc0ff27 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -157,7 +157,7 @@ int plugin_open(const char *plugin, const char *parameter);
157#define PLUGIN_MAGIC 0x526F634B /* RocK */ 157#define PLUGIN_MAGIC 0x526F634B /* RocK */
158 158
159/* increase this every time the api struct changes */ 159/* increase this every time the api struct changes */
160#define PLUGIN_API_VERSION 260 160#define PLUGIN_API_VERSION 261
161 161
162/* update this to latest version if a change to the api struct breaks 162/* 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 163 backwards compatibility (and please take the opportunity to sort in any
@@ -945,6 +945,9 @@ struct plugin_api {
945#endif 945#endif
946 /* new stuff at the end, sort into place next time 946 /* new stuff at the end, sort into place next time
947 the API gets incompatible */ 947 the API gets incompatible */
948
949 void (*splash_progress)(int current, int total, const char *fmt, ...) ATTRIBUTE_PRINTF(3, 4);
950 void (*splash_progress_set_delay)(long delay_ticks);
948}; 951};
949 952
950/* plugin header */ 953/* plugin header */
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index 54497d8306..61d0b64e94 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -397,6 +397,26 @@ struct track_data {
397#endif 397#endif
398}; 398};
399 399
400#if PF_PLAYBACK_CAPABLE
401struct multiple_tracks_id3 {
402 unsigned long length;
403 unsigned long filesize;
404 unsigned long frequency;
405 unsigned int artist_hash;
406 unsigned int composer_hash;
407 unsigned int albumartist_hash;
408 unsigned int grouping_hash;
409 unsigned int comment_hash;
410 unsigned int album_hash;
411 unsigned int genre_hash;
412 unsigned int codectype;
413 unsigned int bitrate;
414 bool filesize_ovf;
415 bool length_ovf;
416 bool vbr;
417};
418#endif
419
400struct rect { 420struct rect {
401 int left; 421 int left;
402 int right; 422 int right;
@@ -558,6 +578,8 @@ static struct pf_index_t pf_idx;
558 578
559static struct pf_track_t pf_tracks; 579static struct pf_track_t pf_tracks;
560 580
581static struct mp3entry id3;
582
561void reset_track_list(void); 583void reset_track_list(void);
562 584
563static bool thread_is_running; 585static bool thread_is_running;
@@ -2093,7 +2115,6 @@ static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
2093 pf_idx.album_index[slide_index].artist_seek); 2115 pf_idx.album_index[slide_index].artist_seek);
2094 2116
2095 if ( rb->tagcache_get_next(&tcs) ) { 2117 if ( rb->tagcache_get_next(&tcs) ) {
2096 struct mp3entry id3;
2097 int fd; 2118 int fd;
2098 2119
2099#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) 2120#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
@@ -2218,6 +2239,9 @@ static unsigned int mfnv(char *str)
2218 const unsigned int p = 16777619; 2239 const unsigned int p = 16777619;
2219 unsigned int hash = 0x811C9DC5; // 2166136261; 2240 unsigned int hash = 0x811C9DC5; // 2166136261;
2220 2241
2242 if (!str)
2243 return 0;
2244
2221 while(*str) 2245 while(*str)
2222 hash = (hash ^ *str++) * p; 2246 hash = (hash ^ *str++) * p;
2223 hash += hash << 13; 2247 hash += hash << 13;
@@ -4010,6 +4034,169 @@ static void select_prev_album(void)
4010} 4034}
4011 4035
4012#if PF_PLAYBACK_CAPABLE 4036#if PF_PLAYBACK_CAPABLE
4037static void collect_id3(struct multiple_tracks_id3 *mul_id3, bool is_first_track)
4038{
4039 if (is_first_track)
4040 {
4041 mul_id3->artist_hash = mfnv(id3.artist);
4042 mul_id3->album_hash = mfnv(id3.album);
4043 mul_id3->genre_hash = mfnv(id3.genre_string);
4044 mul_id3->composer_hash = mfnv(id3.composer);
4045 mul_id3->albumartist_hash = mfnv(id3.albumartist);
4046 mul_id3->grouping_hash = mfnv(id3.grouping);
4047 mul_id3->comment_hash = mfnv(id3.comment);
4048 mul_id3->codectype = id3.codectype;
4049 mul_id3->vbr = id3.vbr;
4050 mul_id3->bitrate = id3.bitrate;
4051 mul_id3->frequency = id3.frequency;
4052 }
4053 else
4054 {
4055 if (mul_id3->artist_hash && (mfnv(id3.artist) != mul_id3->artist_hash))
4056 mul_id3->artist_hash = 0;
4057 if (mul_id3->album_hash && (mfnv(id3.album) != mul_id3->album_hash))
4058 mul_id3->album_hash = 0;
4059 if (mul_id3->genre_hash && (mfnv(id3.genre_string) != mul_id3->genre_hash))
4060 mul_id3->genre_hash = 0;
4061 if (mul_id3->composer_hash && (mfnv(id3.composer) != mul_id3->composer_hash))
4062 mul_id3->composer_hash = 0;
4063 if (mul_id3->albumartist_hash && (mfnv(id3.albumartist) !=
4064 mul_id3->albumartist_hash))
4065 mul_id3->albumartist_hash = 0;
4066 if (mul_id3->grouping_hash && (mfnv(id3.grouping) != mul_id3->grouping_hash))
4067 mul_id3->grouping_hash = 0;
4068 if (mul_id3->comment_hash && (mfnv(id3.comment) != mul_id3->comment_hash))
4069 mul_id3->comment_hash = 0;
4070
4071 if (mul_id3->codectype && (id3.codectype != mul_id3->codectype))
4072 mul_id3->codectype = AFMT_UNKNOWN;
4073 if (mul_id3->bitrate && (id3.bitrate != mul_id3->bitrate ||
4074 id3.vbr != mul_id3->vbr))
4075 mul_id3->bitrate = 0;
4076 if (mul_id3->frequency && (id3.frequency != mul_id3->frequency))
4077 mul_id3->frequency = 0;
4078 }
4079
4080 if (ULONG_MAX - mul_id3->length < id3.length)
4081 {
4082 mul_id3->length_ovf = true;
4083 mul_id3->length = 0;
4084 }
4085 else if (!mul_id3->length_ovf)
4086 mul_id3->length += id3.length;
4087
4088 if (INT_MAX - mul_id3->filesize < id3.filesize) /* output_dyn_value expects int */
4089 {
4090 mul_id3->filesize_ovf = true;
4091 mul_id3->filesize = 0;
4092 }
4093 else if (!mul_id3->filesize_ovf)
4094 mul_id3->filesize += id3.filesize;
4095}
4096
4097
4098static void write_id3_mul_tracks(struct multiple_tracks_id3 *mul_id3)
4099{
4100 id3.path[0] = '\0';
4101 id3.title = NULL;
4102 if (!mul_id3->artist_hash)
4103 id3.artist = NULL;
4104 if (!mul_id3->album_hash)
4105 id3.album = NULL;
4106 if (!mul_id3->genre_hash)
4107 id3.genre_string = NULL;
4108 if (!mul_id3->composer_hash)
4109 id3.composer = NULL;
4110 if (!mul_id3->albumartist_hash)
4111 id3.albumartist = NULL;
4112 if (!mul_id3->grouping_hash)
4113 id3.grouping = NULL;
4114 if (!mul_id3->comment_hash)
4115 id3.comment = NULL;
4116 id3.disc_string = NULL;
4117 id3.track_string = NULL;
4118 id3.year_string = NULL;
4119 id3.year = pf_idx.album_index[center_index].year;
4120 id3.length = mul_id3->length;
4121 id3.filesize = mul_id3->filesize;
4122 id3.frequency = mul_id3->frequency;
4123 id3.bitrate = mul_id3->bitrate;
4124 id3.codectype = mul_id3->codectype;
4125 id3.vbr = mul_id3->vbr;
4126 id3.discnum = 0;
4127 id3.tracknum = 0;
4128 id3.track_level = 0;
4129 id3.album_level = 0;
4130}
4131
4132static void init_mul_id3(struct multiple_tracks_id3 *mul_id3)
4133{
4134 mul_id3->artist_hash = 0;
4135 mul_id3->album_hash = 0;
4136 mul_id3->genre_hash = 0;
4137 mul_id3->composer_hash = 0;
4138 mul_id3->albumartist_hash = 0;
4139 mul_id3->grouping_hash = 0;
4140 mul_id3->comment_hash = 0;
4141 mul_id3->codectype = 0;
4142 mul_id3->vbr = false;
4143 mul_id3->bitrate = 0;
4144 mul_id3->frequency = 0;
4145 mul_id3->length = 0;
4146 mul_id3->filesize = 0;
4147 mul_id3->length_ovf = false;
4148 mul_id3->filesize_ovf = false;
4149}
4150
4151static int show_id3_info(const char *selected_file)
4152{
4153 int fd, i;
4154 unsigned long last_tick;
4155 const char *file_name;
4156 bool id3_retrieval_successful;
4157 bool is_multiple_tracks = insert_whole_album && pf_tracks.count > 1;
4158 struct multiple_tracks_id3 mul_id3;
4159
4160 init_mul_id3(&mul_id3);
4161
4162 last_tick = *(rb->current_tick) + HZ/2;
4163 rb->splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
4164 i = 0;
4165 do {
4166 id3_retrieval_successful = false;
4167 file_name = i == 0 ? selected_file : get_track_filename(i);
4168 fd = rb->open(file_name, O_RDONLY);
4169 if (fd >= 0)
4170 {
4171 if (rb->get_metadata(&id3, fd, file_name))
4172 id3_retrieval_successful = true;
4173 rb->close(fd);
4174 }
4175 if (!id3_retrieval_successful)
4176 return 0;
4177
4178 if (is_multiple_tracks)
4179 {
4180 rb->splash_progress(i, pf_tracks.count,
4181 "%s (%s)", rb->str(LANG_WAIT), rb->str(LANG_OFF_ABORT));
4182 if (TIME_AFTER(*(rb->current_tick), last_tick + HZ/4))
4183 {
4184 if (rb->action_userabort(TIMEOUT_NOBLOCK))
4185 return 0;
4186 last_tick = *(rb->current_tick);
4187 }
4188
4189 collect_id3(&mul_id3, i == 0);
4190 rb->yield();
4191 }
4192 } while (++i < pf_tracks.count && is_multiple_tracks);
4193
4194 if (is_multiple_tracks)
4195 write_id3_mul_tracks(&mul_id3);
4196
4197 return rb->browse_id3(&id3, 0, 0, NULL) ? PLUGIN_USB_CONNECTED : 0;
4198}
4199
4013 4200
4014static bool playlist_insert(int position, bool queue, bool create_new) 4201static bool playlist_insert(int position, bool queue, bool create_new)
4015{ 4202{
@@ -4061,14 +4248,8 @@ static bool track_list_ready(void)
4061 return true; 4248 return true;
4062} 4249}
4063 4250
4064/**
4065 Brings up "Current Playlist" menu with first
4066 track of selection.
4067 4251
4068 Onplay menu code calls back playlist_insert for 4252static bool context_menu_ready(void)
4069 adding all of the tracks.
4070*/
4071static void show_current_playlist_menu(void)
4072{ 4253{
4073#ifdef USEGSLIB 4254#ifdef USEGSLIB
4074 grey_show(false); 4255 grey_show(false);
@@ -4080,13 +4261,23 @@ static void show_current_playlist_menu(void)
4080#ifdef USEGSLIB 4261#ifdef USEGSLIB
4081 grey_show(true); 4262 grey_show(true);
4082#endif 4263#endif
4083 return; 4264 return false;
4084 } 4265 }
4266#if LCD_DEPTH > 1
4267#ifdef USEGSLIB
4268 rb->lcd_set_foreground(N_BRIGHT(0));
4269 rb->lcd_set_background(N_BRIGHT(255));
4270#endif
4271#endif
4085 insert_whole_album = pf_state != pf_show_tracks; 4272 insert_whole_album = pf_state != pf_show_tracks;
4086 FOR_NB_SCREENS(i) 4273 FOR_NB_SCREENS(i)
4087 rb->viewportmanager_theme_enable(i, true, NULL); 4274 rb->viewportmanager_theme_enable(i, true, NULL);
4088 rb->onplay_show_playlist_menu(get_track_filename(pf_tracks.sel), 4275
4089 &playlist_insert); 4276 return true;
4277}
4278
4279static void context_menu_cleanup(void)
4280{
4090 FOR_NB_SCREENS(i) 4281 FOR_NB_SCREENS(i)
4091 rb->viewportmanager_theme_undo(i, false); 4282 rb->viewportmanager_theme_undo(i, false);
4092 if (insert_whole_album) 4283 if (insert_whole_album)
@@ -4098,6 +4289,39 @@ static void show_current_playlist_menu(void)
4098} 4289}
4099 4290
4100 4291
4292static int context_menu(void)
4293{
4294 char *file_name = get_track_filename(pf_tracks.sel);
4295
4296 enum {
4297 PF_CURRENT_PLAYLIST = 0,
4298 PF_ID3_INFO
4299 };
4300 MENUITEM_STRINGLIST(context_menu, ID2P(LANG_ONPLAY_MENU_TITLE), NULL,
4301 ID2P(LANG_PLAYING_NEXT),
4302 ID2P(LANG_MENU_SHOW_ID3_INFO));
4303
4304 while (1) {
4305 switch (rb->do_menu(&context_menu,
4306 NULL, NULL, false)) {
4307
4308 case PF_CURRENT_PLAYLIST:
4309 rb->onplay_show_playlist_menu(file_name,
4310 &playlist_insert);
4311 return 0;
4312 case PF_ID3_INFO:
4313 return show_id3_info(file_name);
4314 case MENU_ATTACHED_USB:
4315 return PLUGIN_USB_CONNECTED;
4316 default:
4317 return 0;
4318
4319 }
4320 }
4321}
4322
4323
4324
4101/* 4325/*
4102 * Puts selected album's tracks into a newly created playlist and starts playing 4326 * Puts selected album's tracks into a newly created playlist and starts playing
4103 */ 4327 */
@@ -4247,7 +4471,6 @@ static void set_initial_slide(const char* selected_file)
4247 pf_cfg.last_album); 4471 pf_cfg.last_album);
4248 else 4472 else
4249 { 4473 {
4250 static struct mp3entry id3;
4251#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) 4474#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
4252 if (rb->tagcache_fill_tags(&id3, selected_file)) 4475 if (rb->tagcache_fill_tags(&id3, selected_file))
4253 set_current_slide(id3_get_index(&id3)); 4476 set_current_slide(id3_get_index(&id3));
@@ -4601,8 +4824,8 @@ static int pictureflow_main(const char* selected_file)
4601#if PF_PLAYBACK_CAPABLE 4824#if PF_PLAYBACK_CAPABLE
4602 case PF_CONTEXT: 4825 case PF_CONTEXT:
4603 if (pf_state == pf_idle || pf_state == pf_scrolling || 4826 if (pf_state == pf_idle || pf_state == pf_scrolling ||
4604 pf_state == pf_show_tracks || pf_state == pf_cover_out) { 4827 pf_state == pf_show_tracks || pf_state == pf_cover_out)
4605 4828 {
4606 if ( pf_state == pf_scrolling) 4829 if ( pf_state == pf_scrolling)
4607 { 4830 {
4608 set_current_slide(target); 4831 set_current_slide(target);
@@ -4611,7 +4834,12 @@ static int pictureflow_main(const char* selected_file)
4611 else if (pf_state == pf_cover_out) 4834 else if (pf_state == pf_cover_out)
4612 interrupt_cover_out_animation(); 4835 interrupt_cover_out_animation();
4613 4836
4614 show_current_playlist_menu(); 4837 if (context_menu_ready())
4838 {
4839 ret = context_menu();
4840 context_menu_cleanup();
4841 if ( ret != 0 ) return ret;
4842 }
4615 } 4843 }
4616 break; 4844 break;
4617#endif 4845#endif
diff --git a/apps/screens.c b/apps/screens.c
index 91280a72f1..869d081498 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -622,6 +622,8 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
622 talk_spell(val, true); 622 talk_spell(val, true);
623 break; 623 break;
624 case LANG_ID3_BITRATE: 624 case LANG_ID3_BITRATE:
625 if (!id3->bitrate)
626 return NULL;
625 snprintf(buffer, buffer_len, "%d kbps%s", id3->bitrate, 627 snprintf(buffer, buffer_len, "%d kbps%s", id3->bitrate,
626 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) ""); 628 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) "");
627 val=buffer; 629 val=buffer;
@@ -633,6 +635,8 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
633 } 635 }
634 break; 636 break;
635 case LANG_ID3_FREQUENCY: 637 case LANG_ID3_FREQUENCY:
638 if (!id3->frequency)
639 return NULL;
636 snprintf(buffer, buffer_len, "%ld Hz", id3->frequency); 640 snprintf(buffer, buffer_len, "%ld Hz", id3->frequency);
637 val=buffer; 641 val=buffer;
638 if(say_it) 642 if(say_it)
@@ -661,6 +665,8 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
661 talk_spell(val, true); 665 talk_spell(val, true);
662 break; 666 break;
663 case LANG_FILESIZE: /* not LANG_ID3_FILESIZE because the string is shared */ 667 case LANG_FILESIZE: /* not LANG_ID3_FILESIZE because the string is shared */
668 if (!id3->filesize)
669 return NULL;
664 output_dyn_value(buffer, buffer_len, id3->filesize, byte_units, 4, true); 670 output_dyn_value(buffer, buffer_len, id3->filesize, byte_units, 4, true);
665 val=buffer; 671 val=buffer;
666 if(say_it && val) 672 if(say_it && val)