summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorAdrián Tinoco <atinocoher@gmail.com>2020-06-08 21:04:25 +0200
committerWilliam Wilgus <me.theuser@yahoo.com>2020-06-25 14:56:07 +0000
commite8a3ade0eae65a962993d1d70b6aa6d74ac639a6 (patch)
treef5cfffd2a25d807fc1dc633e4bb69f8a0c797949 /apps/plugins
parentce61be4d59607c579594a66e59db1569c775f3da (diff)
PictureFlow fixes:
- Extra data structure to store artist info. - Create_album_index modified to perform a different query. - Added load and save functions to store the data index in HDD. - Album collisions fixed. - New config options to perform rescans. - Extra fields added to lang files: english and spanish. Update CREDITS Change-Id: I31814b38d8b4e7fa4b65f5e6e51aa5f00d271ece
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/pictureflow/pictureflow.c263
1 files changed, 228 insertions, 35 deletions
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index 0efba4f5cb..d6ab0f3e99 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -36,6 +36,11 @@
+
+/* Capacity 10 000 entries (for example 10k different albums) */
+#define UNIQBUF_SIZE (64*1024)
+static long uniqbuf[UNIQBUF_SIZE / sizeof(long)];
+
/******************************* Globals ***********************************/
/*
@@ -254,6 +259,7 @@ typedef fb_data pix_t;
/* Error return values */
#define ERROR_NO_ALBUMS -1
#define ERROR_BUFFER_FULL -2
+#define ERROR_NO_ARTISTS -3
/* current version for cover cache */
#define CACHE_VERSION 3
@@ -279,6 +285,12 @@ struct slide_cache {
struct album_data {
int name_idx;
+ int artist_idx;
+ long seek;
+};
+
+struct artist_data {
+ int name_idx;
long seek;
};
@@ -307,6 +319,7 @@ struct load_slide_event_data {
enum pf_scroll_line_type {
PF_SCROLL_TRACK = 0,
PF_SCROLL_ALBUM,
+ PF_SCROLL_ARTIST,
PF_MAX_SCROLL_LINES
};
@@ -332,13 +345,17 @@ struct pfraw_header {
enum show_album_name_values {
ALBUM_NAME_HIDE = 0,
ALBUM_NAME_BOTTOM,
- ALBUM_NAME_TOP
+ ALBUM_NAME_TOP,
+ ALBUM_AND_ARTIST_TOP,
+ ALBUM_AND_ARTIST_BOTTOM
};
static char* show_album_name_conf[] =
{
"hide",
"bottom",
- "top"
+ "top",
+ "both top",
+ "both bottom",
};
#define MAX_SPACING 40
@@ -370,7 +387,7 @@ static struct configdata config[] =
{ TYPE_BOOL, 0, 1, { .bool_p = &show_fps }, "show fps", NULL },
{ TYPE_BOOL, 0, 1, { .bool_p = &resize }, "resize", NULL },
{ TYPE_INT, 0, 100, { .int_p = &cache_version }, "cache version", NULL },
- { TYPE_ENUM, 0, 3, { .int_p = &show_album_name }, "show album name",
+ { TYPE_ENUM, 0, 5, { .int_p = &show_album_name }, "show album name",
show_album_name_conf },
{ TYPE_INT, 0, 2, { .int_p = &auto_wps }, "auto wps", NULL },
{ TYPE_INT, 0, 999999, { .int_p = &last_album }, "last album", NULL },
@@ -417,9 +434,14 @@ static struct tagcache_search tcs;
static struct buflib_context buf_ctx;
static struct album_data *album;
+static struct artist_data *artist;
+
static char *album_names;
static int album_count;
+static char *artist_names;
+static int artist_count;
+
static struct track_data *tracks;
static char *track_names;
static size_t borrowed = 0;
@@ -833,45 +855,137 @@ static void init_reflect_table(void)
}
/**
- Create an index of all albums from the database.
- Also store the album names so we can access them later.
+ Create an index of all artists and albums from the database.
+ Also store the artists and album names so we can access them later.
*/
static int create_album_index(void)
{
- album = ((struct album_data *)(buf_size + (char *) buf)) - 1;
+ artist = ((struct artist_data *)(buf_size + (char *) buf)) - 1;
rb->memset(&tcs, 0, sizeof(struct tagcache_search) );
- album_count = 0;
- rb->tagcache_search(&tcs, tag_album);
+ artist_count = 0;
+ rb->tagcache_search(&tcs, tag_albumartist);
unsigned int l, name_idx = 0;
- album_names = buf;
+ artist_names = buf;
while (rb->tagcache_get_next(&tcs))
{
- buf_size -= sizeof(struct album_data);
+ buf_size -= sizeof(struct artist_data);
l = tcs.result_len;
- album[-album_count].name_idx = name_idx;
-
+ artist[-artist_count].name_idx = name_idx;
+ artist[-artist_count].seek = tcs.result_seek;
if ( l > buf_size )
/* not enough memory */
return ERROR_BUFFER_FULL;
-
rb->strcpy(buf, tcs.result);
buf_size -= l;
buf = l + (char *)buf;
- album[-album_count].seek = tcs.result_seek;
name_idx += l;
- album_count++;
+ artist_count++;
}
rb->tagcache_search_finish(&tcs);
ALIGN_BUFFER(buf, buf_size, 4);
int i;
+ struct artist_data* tmp_artist = (struct artist_data*)buf;
+ for (i = artist_count - 1; i >= 0; i--)
+ tmp_artist[i] = artist[-i];
+ artist = tmp_artist;
+ buf = artist + artist_count;
+
+ long artist_seek = 0;
+ int j = 0;
+ album_count = 0;
+ name_idx = 0;
+ album = ((struct album_data *)(buf_size + (char *) buf)) - 1;
+ album_names = buf;
+ for (j = 0; j < artist_count; j++){
+ artist_seek = artist[j].seek;
+ rb->memset(&tcs, 0, sizeof(struct tagcache_search) );
+ rb->tagcache_search(&tcs, tag_album);
+ /* Prevent duplicate entries in the search list. */
+ rb->tagcache_search_set_uniqbuf(&tcs, uniqbuf, UNIQBUF_SIZE);
+ rb->tagcache_search_add_filter(&tcs, tag_albumartist, artist_seek);
+ while (rb->tagcache_get_next(&tcs))
+ {
+ buf_size -= sizeof(struct album_data);
+ l = tcs.result_len;
+ album[-album_count].name_idx = name_idx;
+ album[-album_count].seek = tcs.result_seek;
+ album[-album_count].artist_idx = j;
+ if ( l > buf_size )
+ /* not enough memory */
+ return ERROR_BUFFER_FULL;
+
+ rb->strcpy(buf, tcs.result);
+ buf_size -= l;
+ buf = l + (char *)buf;
+ name_idx += l;
+ album_count++;
+ }
+ rb->tagcache_search_finish(&tcs);
+ }
+ ALIGN_BUFFER(buf, buf_size, 4);
struct album_data* tmp_album = (struct album_data*)buf;
for (i = album_count - 1; i >= 0; i--)
tmp_album[i] = album[-i];
album = tmp_album;
buf = album + album_count;
+
return (album_count > 0) ? 0 : ERROR_NO_ALBUMS;
}
+
+/*Saves the artists+albums index into a binary file to be recovered the
+ next time PictureFlow is launched*/
+
+static int save_album_index(void){
+ int fd;
+ fd = rb->creat(PLUGIN_DIR "/demos/album_ndx.tmp",0666);
+ if(fd >= 0)
+ {
+ int unsigned_size = sizeof(unsigned int);
+ int int_size = sizeof(int);
+ rb->write(fd, artist_names, ((char *)buf - (char *)artist_names));
+ unsigned int artist_pos = (char *)artist - (char *)artist_names;
+ rb->write(fd, &artist_pos, unsigned_size);
+ unsigned int album_names_pos = (char *)album_names - (char *)artist_names;
+ rb->write(fd, &album_names_pos, unsigned_size);
+ unsigned int album_pos = (char *)album - (char *)artist_names;
+ rb->write(fd, &album_pos, unsigned_size);
+ rb->write(fd, &artist_count, int_size);
+ rb->write(fd, &album_count, int_size);
+ rb->close(fd);
+ return 0;
+ }
+ return -1;
+}
+
+/*Loads the artists+albums index information stored in the hard drive*/
+
+static int load_album_index(void){
+ int fr = rb->open(PLUGIN_DIR "/demos/album_ndx.tmp", O_RDONLY);
+ if (fr >= 0){
+ int unsigned_size = sizeof(unsigned int);
+ int int_size = sizeof(int);
+ unsigned long filesize = rb->filesize(fr);
+ unsigned int pos = 0;
+ unsigned int extra_data_size = (sizeof(unsigned int)*3) + (sizeof(int)*2);
+ rb->read(fr,buf ,filesize-extra_data_size);
+ artist_names = buf;
+ buf = (char *)buf + (filesize-extra_data_size);
+ buf_size = buf_size-(filesize-extra_data_size);
+ rb->read(fr,&pos ,unsigned_size);
+ artist = (void *)artist_names + pos;
+ rb->read(fr,&pos ,unsigned_size);
+ album_names = (void *)artist_names + pos;
+ rb->read(fr,&pos ,unsigned_size);
+ album = (void *)artist_names + pos;
+ rb->read(fr,&artist_count ,int_size);
+ rb->read(fr,&album_count ,int_size);
+ rb->close(fr);
+ return 0;
+ }
+ return -1;
+}
+
/**
Return a pointer to the album name of the given slide_index
*/
@@ -881,6 +995,21 @@ static char* get_album_name(const int slide_index)
}
/**
+ Return a pointer to the album artist of the given slide_index
+ */
+static char* get_album_artist(const int slide_index)
+{
+ if (slide_index < album_count && slide_index >= 0){
+ int artist_pos = album[slide_index].artist_idx;
+ if (artist_pos < artist_count && artist_pos >= 0){
+ return artist_names + artist[artist_pos].name_idx;
+ }
+ }
+ return NULL;
+}
+
+
+/**
Return a pointer to the track name of the active album
create_track_index has to be called first.
*/
@@ -902,11 +1031,13 @@ static char* get_track_filename(const int track_index)
static int get_wps_current_index(void)
{
struct mp3entry *id3 = rb->audio_current_track();
+
if(id3 && id3->album) {
int i;
for( i=0; i < album_count; i++ )
{
- if(!rb->strcmp(album_names + album[i].name_idx, id3->album))
+ if(!rb->strcmp(album_names + album[i].name_idx, id3->album) &&
+ !rb->strcmp(artist_names + artist[album[i].artist_idx].name_idx, id3->albumartist))
return i;
}
}
@@ -936,6 +1067,7 @@ static void create_track_index(const int slide_index)
goto fail;
rb->tagcache_search_add_filter(&tcs, tag_album, album[slide_index].seek);
+ rb->tagcache_search_add_filter(&tcs, tag_albumartist, artist[album[slide_index].artist_idx].seek);
track_count=0;
int string_index = 0, track_num;
int disc_num;
@@ -1051,6 +1183,7 @@ static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
bool result;
/* find the first track of the album */
rb->tagcache_search_add_filter(&tcs, tag_album, album[slide_index].seek);
+ rb->tagcache_search_add_filter(&tcs, tag_albumartist, artist[album[slide_index].artist_idx].seek);
if ( rb->tagcache_get_next(&tcs) ) {
struct mp3entry id3;
@@ -1138,6 +1271,13 @@ static void draw_progressbar(int step)
const int w = LCD_WIDTH - 20;
const int x = 10;
+#if LCD_DEPTH > 1
+ rb->lcd_set_background(N_BRIGHT(0));
+ rb->lcd_set_foreground(N_BRIGHT(255));
+#else
+ rb->lcd_set_drawmode(PICTUREFLOW_DRMODE);
+#endif
+ rb->lcd_clear_display();
rb->lcd_getstringsize("Preparing album artwork", &txt_w, &txt_h);
int y = (LCD_HEIGHT - txt_h)/2;
@@ -1221,9 +1361,8 @@ static bool create_albumart_cache(void)
for (i=0; i < album_count; i++)
{
draw_progressbar(i);
-
- rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x.pfraw",
- mfnv(get_album_name(i)));
+ rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x%x.pfraw",
+ mfnv(get_album_name(i)),mfnv(get_album_artist(i)));
/* delete existing cache, so it's a true rebuild */
if(rb->file_exists(pfraw_file)) {
if(update) {
@@ -1572,8 +1711,10 @@ static inline bool load_and_prepare_surface(const int slide_index,
const int prio)
{
char pfraw_file[MAX_PATH];
- rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x.pfraw",
- mfnv(get_album_name(slide_index)));
+
+
+ rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x%x.pfraw",
+ mfnv(get_album_name(slide_index)),mfnv(get_album_artist(slide_index)));
int hid = read_pfraw(pfraw_file, prio);
if (!hid)
@@ -2243,13 +2384,16 @@ static int settings_menu(void)
ID2P(LANG_SHOW_ALBUM_TITLE),
ID2P(LANG_RESIZE_COVERS),
ID2P(LANG_REBUILD_CACHE),
+ ID2P(LANG_UPDATE_CACHE),
ID2P(LANG_WPS_INTEGRATION),
ID2P(LANG_BACKLIGHT));
static const struct opt_items album_name_options[] = {
- { STR(LANG_HIDE_ALBUM_TITLE) },
- { STR(LANG_SHOW_AT_THE_BOTTOM) },
- { STR(LANG_SHOW_AT_THE_TOP) }
+ { STR(LANG_HIDE_ALBUM_TITLE_NEW) },
+ { STR(LANG_SHOW_AT_THE_BOTTOM_NEW) },
+ { STR(LANG_SHOW_AT_THE_TOP_NEW) },
+ { STR(LANG_SHOW_ALL_AT_THE_TOP) },
+ { STR(LANG_SHOW_ALL_AT_THE_BOTTOM) },
};
static const struct opt_items wps_options[] = {
{ STR(LANG_OFF) },
@@ -2300,7 +2444,7 @@ static int settings_menu(void)
break;
case 5:
rb->set_option(rb->str(LANG_SHOW_ALBUM_TITLE), &show_album_name,
- INT, album_name_options, 3, NULL);
+ INT, album_name_options, 5, NULL);
reset_track_list();
recalc_offsets();
reset_slides();
@@ -2319,9 +2463,16 @@ static int settings_menu(void)
rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
break;
case 8:
- rb->set_option(rb->str(LANG_WPS_INTEGRATION), &auto_wps, INT, wps_options, 3, NULL);
+ cache_version = CACHE_UPDATE;
+ rb->remove(EMPTY_SLIDE);
+ configfile_save(CONFIG_FILE, config,
+ CONFIG_NUM_ITEMS, CONFIG_VERSION);
+ rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
break;
case 9:
+ rb->set_option(rb->str(LANG_WPS_INTEGRATION), &auto_wps, INT, wps_options, 3, NULL);
+ break;
+ case 10:
rb->set_option(rb->str(LANG_BACKLIGHT), &backlight_mode, INT, backlight_options, 2, NULL);
break;
@@ -2473,11 +2624,20 @@ static void track_list_yh(int char_height)
break;
case ALBUM_NAME_BOTTOM:
track_list_y = (show_fps ? char_height : 0);
- track_list_h = LCD_HEIGHT - track_list_y - char_height * 2;
+ track_list_h = LCD_HEIGHT - track_list_y - (char_height * 3);
+ break;
+ case ALBUM_AND_ARTIST_TOP:
+ track_list_y = char_height * 3;
+ track_list_h = LCD_HEIGHT - track_list_y -
+ (show_fps ? char_height : 0);
+ break;
+ case ALBUM_AND_ARTIST_BOTTOM:
+ track_list_y = (show_fps ? char_height : 0);
+ track_list_h = LCD_HEIGHT - track_list_y - (char_height * 3);
break;
case ALBUM_NAME_TOP:
default:
- track_list_y = char_height * 2;
+ track_list_y = char_height * 3;
track_list_h = LCD_HEIGHT - track_list_y -
(show_fps ? char_height : 0);
break;
@@ -2620,9 +2780,10 @@ static void draw_album_text(void)
int albumtxt_index;
int char_height;
- int albumtxt_x, albumtxt_y;
+ int albumtxt_x, albumtxt_y, artisttxt_x;
char *albumtxt;
+ char *artisttxt;
int c;
/* Draw album text */
if ( pf_state == pf_scrolling ) {
@@ -2650,13 +2811,33 @@ static void draw_album_text(void)
}
char_height = rb->screens[SCREEN_MAIN]->getcharheight();
- if (show_album_name == ALBUM_NAME_TOP)
- albumtxt_y = char_height / 2;
- else
- albumtxt_y = LCD_HEIGHT - char_height - char_height/2;
+ switch(show_album_name){
+ case ALBUM_AND_ARTIST_TOP:
+ albumtxt_y = 0;
+ break;
+ case ALBUM_NAME_BOTTOM:
+ albumtxt_y = (LCD_HEIGHT - char_height - char_height/2 - 10);
+ break;
+ case ALBUM_AND_ARTIST_BOTTOM:
+ albumtxt_y = (LCD_HEIGHT - char_height - char_height/2 - 20);
+ break;
+ case ALBUM_NAME_TOP:
+ default:
+ albumtxt_y = char_height / 2;
+ break;
+ }
albumtxt_x = get_scroll_line_offset(PF_SCROLL_ALBUM);
- mylcd_putsxy(albumtxt_x, albumtxt_y, albumtxt);
+ mylcd_putsxy(albumtxt_x, albumtxt_y, albumtxt);
+ set_scroll_line(artisttxt, PF_SCROLL_ARTIST);
+ if ((show_album_name == ALBUM_AND_ARTIST_TOP)
+ || (show_album_name == ALBUM_AND_ARTIST_BOTTOM)){
+
+ artisttxt = get_album_artist(albumtxt_index);
+ set_scroll_line(artisttxt, PF_SCROLL_ARTIST);
+ artisttxt_x = get_scroll_line_offset(PF_SCROLL_ARTIST);
+ mylcd_putsxy(artisttxt_x, albumtxt_y+20, artisttxt);
+ }
}
/**
@@ -2699,7 +2880,19 @@ static int pictureflow_main(void)
init_reflect_table();
ALIGN_BUFFER(buf, buf_size, 4);
- ret = create_album_index();
+
+ /*Scan will trigger when no file is found or the option was activated*/
+ if ((cache_version != CACHE_VERSION)||(load_album_index() < 0)){
+ rb->splash(HZ/2,"Creating album index, please wait");
+ ret = create_album_index();
+ if (ret == 0){
+ save_album_index();
+ }
+ }
+ else{
+ ret = 0;
+ }
+
if (ret == ERROR_BUFFER_FULL) {
error_wait("Not enough memory for album names");
return PLUGIN_ERROR;