summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Soffke <christian.soffke@gmail.com>2022-03-20 21:35:41 +0100
committerAidan MacDonald <amachronic@protonmail.com>2022-03-27 08:51:58 -0400
commitdf3afcfa3b63b8f4ca012a428e35dfb24bba4bb9 (patch)
treeca9f52010ac4ccf547d557b8694badd796096a9c
parentaec8b363482ef603cb1d3d9e6c089ce5e8706399 (diff)
downloadrockbox-df3afcfa3b63b8f4ca012a428e35dfb24bba4bb9.tar.gz
rockbox-df3afcfa3b63b8f4ca012a428e35dfb24bba4bb9.zip
PictureFlow: Configurable album sorting
Now offers sorting by: - Album artist, then album name - Album artist, then album year - Album year - Album name Years are determined by the most recently released track appearing on an album, if the value differs between tracks. On the M3K, instead of by going into Settings, volume buttons can also be used for quickly adjusting the current sorting Change-Id: I2c50059617114fb418336c466fdd37415473ac7d
-rw-r--r--apps/lang/english.lang84
-rw-r--r--apps/plugins/pictureflow/pictureflow.c450
2 files changed, 485 insertions, 49 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 04bbf70a6f..aa23647fd2 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -16246,3 +16246,87 @@
16246 rds: "Sync RDS Time" 16246 rds: "Sync RDS Time"
16247 </voice> 16247 </voice>
16248</phrase> 16248</phrase>
16249<phrase>
16250 id: LANG_SORT_ALBUMS_BY
16251 desc: in Settings
16252 user: core
16253 <source>
16254 *: "Sort albums by"
16255 </source>
16256 <dest>
16257 *: "Sort albums by"
16258 </dest>
16259 <voice>
16260 *: "Sort albums by"
16261 </voice>
16262</phrase>
16263<phrase>
16264 id: LANG_ARTIST_PLUS_NAME
16265 desc: in Settings
16266 user: core
16267 <source>
16268 *: "Artist + Name"
16269 </source>
16270 <dest>
16271 *: "Artist + Name"
16272 </dest>
16273 <voice>
16274 *: "Artist And Name"
16275 </voice>
16276</phrase>
16277<phrase>
16278 id: LANG_ARTIST_PLUS_YEAR
16279 desc: in Settings
16280 user: core
16281 <source>
16282 *: "Artist + Year"
16283 </source>
16284 <dest>
16285 *: "Artist + Year"
16286 </dest>
16287 <voice>
16288 *: "Artist And Year"
16289 </voice>
16290</phrase>
16291<phrase>
16292 id: LANG_YEAR_SORT_ORDER
16293 desc: in Settings
16294 user: core
16295 <source>
16296 *: "Year sort order"
16297 </source>
16298 <dest>
16299 *: "Year sort order"
16300 </dest>
16301 <voice>
16302 *: "Year sort order"
16303 </voice>
16304</phrase>
16305<phrase>
16306 id: LANG_SHOW_YEAR_IN_ALBUM_TITLE
16307 desc: in Settings
16308 user: core
16309 <source>
16310 *: "Show year in album title"
16311 </source>
16312 <dest>
16313 *: "Show year in album title"
16314 </dest>
16315 <voice>
16316 *: "Show year in album title"
16317 </voice>
16318</phrase>
16319<phrase>
16320 id: LANG_WAIT_FOR_CACHE
16321 desc: in Settings
16322 user: core
16323 <source>
16324 *: "Cache needs to finish updating first!"
16325 </source>
16326 <dest>
16327 *: "Cache needs to finish updating first!"
16328 </dest>
16329 <voice>
16330 *: "Cache needs to finish updating first!"
16331 </voice>
16332</phrase>
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index 39213e5cb7..ae1ec2b224 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -60,6 +60,8 @@ static fb_data *lcd_fb;
60 60
61#define PF_QUIT (LAST_ACTION_PLACEHOLDER + 1) 61#define PF_QUIT (LAST_ACTION_PLACEHOLDER + 1)
62#define PF_TRACKLIST (LAST_ACTION_PLACEHOLDER + 2) 62#define PF_TRACKLIST (LAST_ACTION_PLACEHOLDER + 2)
63#define PF_SORTING_NEXT (LAST_ACTION_PLACEHOLDER + 3)
64#define PF_SORTING_PREV (LAST_ACTION_PLACEHOLDER + 4)
63 65
64#if defined(HAVE_SCROLLWHEEL) || CONFIG_KEYPAD == IRIVER_H10_PAD || \ 66#if defined(HAVE_SCROLLWHEEL) || CONFIG_KEYPAD == IRIVER_H10_PAD || \
65 CONFIG_KEYPAD == MPIO_HD300_PAD 67 CONFIG_KEYPAD == MPIO_HD300_PAD
@@ -173,6 +175,8 @@ const struct button_mapping pf_context_buttons[] =
173 {PF_JMP, BUTTON_RIGHT, BUTTON_NONE}, 175 {PF_JMP, BUTTON_RIGHT, BUTTON_NONE},
174 {PF_JMP, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, 176 {PF_JMP, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE},
175 {PF_MENU, BUTTON_POWER|BUTTON_REL, BUTTON_POWER}, 177 {PF_MENU, BUTTON_POWER|BUTTON_REL, BUTTON_POWER},
178 {PF_SORTING_NEXT, BUTTON_VOL_UP, BUTTON_NONE},
179 {PF_SORTING_PREV, BUTTON_VOL_DOWN, BUTTON_NONE},
176 {PF_QUIT, BUTTON_POWER|BUTTON_REPEAT, BUTTON_POWER}, 180 {PF_QUIT, BUTTON_POWER|BUTTON_REPEAT, BUTTON_POWER},
177 {PF_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, 181 {PF_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU},
178 {PF_TRACKLIST, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, 182 {PF_TRACKLIST, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU},
@@ -274,7 +278,7 @@ typedef fb_data pix_t;
274#define ERROR_USER_ABORT -4 278#define ERROR_USER_ABORT -4
275 279
276/* current version for cover cache */ 280/* current version for cover cache */
277#define CACHE_VERSION 3 281#define CACHE_VERSION 4
278#define CONFIG_VERSION 1 282#define CONFIG_VERSION 1
279#define CONFIG_FILE "pictureflow.cfg" 283#define CONFIG_FILE "pictureflow.cfg"
280#define INDEX_HDR "PFID" 284#define INDEX_HDR "PFID"
@@ -296,6 +300,10 @@ struct pf_config_t
296 int cache_version; 300 int cache_version;
297 301
298 int show_album_name; 302 int show_album_name;
303 int sort_albums_by;
304 int year_sort_order;
305 bool show_year;
306
299 bool resize; 307 bool resize;
300 bool show_fps; 308 bool show_fps;
301}; 309};
@@ -364,6 +372,7 @@ struct slide_cache {
364struct album_data { 372struct album_data {
365 int name_idx; /* offset to the album name */ 373 int name_idx; /* offset to the album name */
366 int artist_idx; /* offset to the artist name */ 374 int artist_idx; /* offset to the artist name */
375 int year; /* album year */
367 long artist_seek; /* artist taglist position */ 376 long artist_seek; /* artist taglist position */
368 long seek; /* album taglist position */ 377 long seek; /* album taglist position */
369}; 378};
@@ -447,6 +456,31 @@ static char* show_album_name_conf[] =
447 "both bottom", 456 "both bottom",
448}; 457};
449 458
459enum sort_albums_by_values {
460 SORT_BY_ARTIST_AND_NAME = 0,
461 SORT_BY_ARTIST_AND_YEAR,
462 SORT_BY_YEAR,
463 SORT_BY_NAME,
464
465 SORT_VALUES_SIZE
466};
467static char* sort_albums_by_conf[] =
468{
469 "artist + name",
470 "artist + year",
471 "year",
472 "name"
473};
474enum year_sort_order_values {
475 ASCENDING = 0,
476 DESCENDING
477};
478static char* year_sort_order_conf[] =
479{
480 "ascending",
481 "descending"
482};
483
450#define MAX_SPACING 40 484#define MAX_SPACING 40
451#define MAX_MARGIN 80 485#define MAX_MARGIN 80
452 486
@@ -471,7 +505,12 @@ static struct configdata config[] =
471 { TYPE_INT, 0, 999999, { .int_p = &pf_cfg.last_album }, "last album", NULL }, 505 { TYPE_INT, 0, 999999, { .int_p = &pf_cfg.last_album }, "last album", NULL },
472 { TYPE_INT, 0, 1, { .int_p = &pf_cfg.backlight_mode }, "backlight", NULL }, 506 { TYPE_INT, 0, 1, { .int_p = &pf_cfg.backlight_mode }, "backlight", NULL },
473 { TYPE_INT, 0, 999999, { .int_p = &aa_cache.idx }, "art cache pos", NULL }, 507 { TYPE_INT, 0, 999999, { .int_p = &aa_cache.idx }, "art cache pos", NULL },
474 { TYPE_INT, 0, 999999, { .int_p = &aa_cache.inspected }, "art cache inspected", NULL } 508 { TYPE_INT, 0, 999999, { .int_p = &aa_cache.inspected }, "art cache inspected", NULL },
509 { TYPE_ENUM, 0, 4, { .int_p = &pf_cfg.sort_albums_by }, "sort albums by",
510 sort_albums_by_conf },
511 { TYPE_ENUM, 0, 2, { .int_p = &pf_cfg.year_sort_order }, "year order",
512 year_sort_order_conf },
513 { TYPE_BOOL, 0, 1, { .bool_p = &pf_cfg.show_year }, "show year", NULL },
475}; 514};
476 515
477#define CONFIG_NUM_ITEMS (sizeof(config) / sizeof(struct configdata)) 516#define CONFIG_NUM_ITEMS (sizeof(config) / sizeof(struct configdata))
@@ -647,6 +686,9 @@ static void config_set_defaults(struct pf_config_t *cfg)
647 cfg->cache_version = 0; 686 cfg->cache_version = 0;
648 cfg->show_album_name = (LCD_HEIGHT > 100) 687 cfg->show_album_name = (LCD_HEIGHT > 100)
649 ? ALBUM_NAME_TOP : ALBUM_NAME_BOTTOM; 688 ? ALBUM_NAME_TOP : ALBUM_NAME_BOTTOM;
689 cfg->sort_albums_by = SORT_BY_ARTIST_AND_NAME;
690 cfg->year_sort_order = ASCENDING;
691 cfg->show_year = false;
650} 692}
651 693
652static inline PFreal fmul(PFreal a, PFreal b) 694static inline PFreal fmul(PFreal a, PFreal b)
@@ -997,6 +1039,51 @@ static void init_reflect_table(void)
997 (5 * REFLECT_HEIGHT); 1039 (5 * REFLECT_HEIGHT);
998} 1040}
999 1041
1042
1043static int compare_albums (const void *a_v, const void *b_v)
1044{
1045 uint32_t artist_a = ((struct album_data *)a_v)->artist_idx;
1046 uint32_t artist_b = ((struct album_data *)b_v)->artist_idx;
1047
1048 uint32_t album_a = ((struct album_data *)a_v)->name_idx;
1049 uint32_t album_b = ((struct album_data *)b_v)->name_idx;
1050
1051 int year_a = ((struct album_data *)a_v)->year;
1052 int year_b = ((struct album_data *)b_v)->year;
1053
1054 switch (pf_cfg.sort_albums_by)
1055 {
1056 case SORT_BY_ARTIST_AND_NAME:
1057 if (artist_a - artist_b == 0)
1058 return (int)(album_a - album_b);
1059 break;
1060 case SORT_BY_ARTIST_AND_YEAR:
1061 if (artist_a - artist_b == 0)
1062 {
1063 if (pf_cfg.year_sort_order == ASCENDING)
1064 return year_a - year_b;
1065 else
1066 return year_b - year_a;
1067 }
1068 break;
1069 case SORT_BY_YEAR:
1070 if (year_a - year_b != 0)
1071 {
1072 if (pf_cfg.year_sort_order == ASCENDING)
1073 return year_a - year_b;
1074 else
1075 return year_b - year_a;
1076 }
1077 break;
1078 case SORT_BY_NAME:
1079 if (album_a - album_b != 0)
1080 return (int)(album_a - album_b);
1081 break;
1082 }
1083
1084 return (int)(artist_a - artist_b);
1085}
1086
1000static int compare_album_artists (const void *a_v, const void *b_v) 1087static int compare_album_artists (const void *a_v, const void *b_v)
1001{ 1088{
1002 uint32_t a = ((struct album_data *)a_v)->artist_idx; 1089 uint32_t a = ((struct album_data *)a_v)->artist_idx;
@@ -1011,6 +1098,7 @@ static void write_album_index(int idx, int name_idx,
1011 pf_idx.album_index[idx].seek = album_seek; 1098 pf_idx.album_index[idx].seek = album_seek;
1012 pf_idx.album_index[idx].artist_idx = artist_idx; 1099 pf_idx.album_index[idx].artist_idx = artist_idx;
1013 pf_idx.album_index[idx].artist_seek = artist_seek; 1100 pf_idx.album_index[idx].artist_seek = artist_seek;
1101 pf_idx.album_index[idx].year = 0;
1014} 1102}
1015 1103
1016static inline void write_album_entry(struct tagcache_search *tcs, 1104static inline void write_album_entry(struct tagcache_search *tcs,
@@ -1238,6 +1326,49 @@ static int build_artist_index(struct tagcache_search *tcs,
1238} 1326}
1239 1327
1240 1328
1329static int assign_album_year(void)
1330{
1331 draw_progressbar(0, pf_idx.album_ct, "Assigning Album Year");
1332 for (int album_idx = 0; album_idx < pf_idx.album_ct; album_idx++)
1333 {
1334 /* Prevent idle poweroff */
1335 rb->reset_poweroff_timer();
1336
1337 if (rb->button_get(false) > BUTTON_NONE)
1338 {
1339 if (confirm_quit())
1340 return ERROR_USER_ABORT;
1341 else
1342 {
1343 rb->lcd_clear_display();
1344 draw_progressbar(album_idx, pf_idx.album_ct, "Assigning Album Year");
1345 }
1346 }
1347 draw_progressbar(album_idx, pf_idx.album_ct, NULL);
1348 int album_year = 0;
1349
1350 if (rb->tagcache_search(&tcs, tag_year))
1351 {
1352 rb->tagcache_search_add_filter(&tcs, tag_album,
1353 pf_idx.album_index[album_idx].seek);
1354
1355 if (pf_idx.album_index[album_idx].artist_idx >= 0)
1356 rb->tagcache_search_add_filter(&tcs, tag_albumartist,
1357 pf_idx.album_index[album_idx].artist_seek);
1358
1359 while (rb->tagcache_get_next(&tcs)) {
1360 int track_year = rb->tagcache_get_numeric(&tcs, tag_year);
1361 if (track_year > album_year)
1362 album_year = track_year;
1363 }
1364 }
1365 rb->tagcache_search_finish(&tcs);
1366
1367 pf_idx.album_index[album_idx].year = album_year;
1368 }
1369 return SUCCESS;
1370}
1371
1241/** 1372/**
1242 Create an index of all artists and albums from the database. 1373 Create an index of all artists and albums from the database.
1243 Also store the artists and album names so we can access them later. 1374 Also store the artists and album names so we can access them later.
@@ -1352,6 +1483,14 @@ retry_artist_lookup:
1352 } 1483 }
1353 rb->tagcache_search_finish(&tcs); 1484 rb->tagcache_search_finish(&tcs);
1354 } 1485 }
1486
1487 draw_splashscreen(buf, buf_size);
1488
1489 res = assign_album_year();
1490
1491 if (res < SUCCESS)
1492 return res;
1493
1355 /* sort list order to find duplicates */ 1494 /* sort list order to find duplicates */
1356 rb->qsort(pf_idx.album_index, pf_idx.album_ct, 1495 rb->qsort(pf_idx.album_index, pf_idx.album_ct,
1357 sizeof(struct album_data), compare_album_artists); 1496 sizeof(struct album_data), compare_album_artists);
@@ -1406,6 +1545,9 @@ retry_artist_lookup:
1406 pf_idx.buf_sz = buf_size; 1545 pf_idx.buf_sz = buf_size;
1407 pf_idx.artist_index = 0; 1546 pf_idx.artist_index = 0;
1408 1547
1548 rb->qsort(pf_idx.album_index, pf_idx.album_ct,
1549 sizeof(struct album_data), compare_albums);
1550
1409 return (pf_idx.album_ct > 0) ? 0 : ERROR_NO_ALBUMS; 1551 return (pf_idx.album_ct > 0) ? 0 : ERROR_NO_ALBUMS;
1410} 1552}
1411 1553
@@ -1519,6 +1661,9 @@ static int load_album_index(void){
1519 pf_idx.buf = buf; 1661 pf_idx.buf = buf;
1520 pf_idx.buf_sz = buf_size; 1662 pf_idx.buf_sz = buf_size;
1521 1663
1664 rb->qsort(pf_idx.album_index, pf_idx.album_ct,
1665 sizeof(struct album_data), compare_albums);
1666
1522 return 0; 1667 return 0;
1523 } 1668 }
1524 } 1669 }
@@ -1572,6 +1717,14 @@ static char* get_album_artist(const int slide_index)
1572} 1717}
1573 1718
1574 1719
1720static char* get_slide_name(const int slide_index, bool artist)
1721{
1722 if (artist)
1723 return get_album_artist(slide_index);
1724
1725 return get_album_name(slide_index);
1726}
1727
1575/** 1728/**
1576 Return a pointer to the track name of the active album 1729 Return a pointer to the track name of the active album
1577 create_track_index has to be called first. 1730 create_track_index has to be called first.
@@ -1593,29 +1746,91 @@ static char* get_track_filename(const int track_index)
1593 1746
1594 1747
1595 1748
1596static int get_album_artist_alpha_prev_index(void) 1749static int jmp_idx_prev(void)
1597{ 1750{
1598 char* current_album_artist = get_album_artist(center_index); 1751 if (aa_cache.inspected < pf_idx.album_ct)
1599 for (int i = center_index - 1; i > 0; i-- ) 1752 {
1753#ifdef USEGSLIB
1754 grey_show(false);
1755 rb->lcd_clear_display();
1756 rb->lcd_update();
1757#endif
1758 rb->splash(HZ*2, rb->str(LANG_WAIT_FOR_CACHE));
1759#ifdef USEGSLIB
1760 grey_show(true);
1761#endif
1762 return center_index;
1763 }
1764
1765 if (pf_cfg.sort_albums_by == SORT_BY_YEAR)
1600 { 1766 {
1601 int artist_idx = pf_idx.album_index[i].artist_idx; 1767 int current_year = pf_idx.album_index[center_index].year;
1602 if(rb->strncmp(pf_idx.artist_names + artist_idx, current_album_artist, 1)) 1768
1603 current_album_artist = pf_idx.artist_names + artist_idx; 1769 for (int i = center_index - 1; i > 0; i-- )
1604 while (i > 0 && !rb->strncmp(pf_idx.artist_names + pf_idx.album_index[i-1].artist_idx, current_album_artist, 1)) 1770 {
1605 i--; 1771 if(pf_idx.album_index[i].year != current_year)
1606 return i; 1772 current_year = pf_idx.album_index[i].year;
1773 while (i > 0)
1774 {
1775 if (pf_idx.album_index[i-1].year != current_year)
1776 break;
1777 i--;
1778 }
1779 return i;
1780 }
1607 } 1781 }
1782 else
1783 {
1784 bool by_artist = pf_cfg.sort_albums_by != SORT_BY_NAME;
1785 char *current_selection = get_slide_name(center_index, by_artist);
1786
1787 for (int i = center_index - 1; i > 0; i-- )
1788 {
1789 if(rb->strncmp(get_slide_name(i, by_artist), current_selection, 1))
1790 current_selection = get_slide_name(i, by_artist);
1791 while (i > 0)
1792 {
1793 if (rb->strncmp(get_slide_name(i-1, by_artist), current_selection, 1))
1794 break;
1795 i--;
1796 }
1797 return i;
1798 }
1799 }
1800
1608 return 0; 1801 return 0;
1609} 1802}
1610 1803
1611static int get_album_artist_alpha_next_index(void) 1804static int jmp_idx_next(void)
1612{ 1805{
1613 char* current_album_artist = get_album_artist(center_index); 1806 if (aa_cache.inspected < pf_idx.album_ct)
1614 for (int i = center_index + 1; i < pf_idx.album_ct; i++ )
1615 { 1807 {
1616 int artist_idx = pf_idx.album_index[i].artist_idx; 1808#ifdef USEGSLIB
1617 if(rb->strncmp(pf_idx.artist_names + artist_idx, current_album_artist, 1)) 1809 grey_show(false);
1618 return i; 1810 rb->lcd_clear_display();
1811 rb->lcd_update();
1812#endif
1813 rb->splash(HZ*2, rb->str(LANG_WAIT_FOR_CACHE));
1814#ifdef USEGSLIB
1815 grey_show(true);
1816#endif
1817 return center_index;
1818 }
1819
1820 if (pf_cfg.sort_albums_by == SORT_BY_YEAR)
1821 {
1822 int current_year = pf_idx.album_index[center_index].year;
1823 for (int i = center_index + 1; i < pf_idx.album_ct; i++ )
1824 if(pf_idx.album_index[i].year != current_year)
1825 return i;
1826 }
1827 else
1828 {
1829 bool by_artist = pf_cfg.sort_albums_by != SORT_BY_NAME;
1830 char *current_selection = get_slide_name(center_index, by_artist);
1831 for (int i = center_index + 1; i < pf_idx.album_ct; i++ )
1832 if(rb->strncmp(get_slide_name(i, by_artist), current_selection, 1))
1833 return i;
1619 } 1834 }
1620 return pf_idx.album_ct - 1; 1835 return pf_idx.album_ct - 1;
1621} 1836}
@@ -2966,6 +3181,85 @@ static inline void set_current_slide(const int slide_index)
2966 reset_slides(); 3181 reset_slides();
2967} 3182}
2968 3183
3184
3185static void interrupt_cover_out_animation(void);
3186static bool sort_albums(int new_sorting, bool from_settings)
3187{
3188 int i, album_idx, artist_idx;
3189 char* current_album_name = NULL;
3190 char* current_album_artist = NULL;
3191 static const char* sort_options[] = {
3192 ID2P(LANG_ARTIST_PLUS_NAME),
3193 ID2P(LANG_ARTIST_PLUS_YEAR),
3194 ID2P(LANG_ID3_YEAR),
3195 ID2P(LANG_NAME)
3196 };
3197
3198 /* Only change sorting once artwork has been inspected */
3199 if (aa_cache.inspected < pf_idx.album_ct)
3200 {
3201#ifdef USEGSLIB
3202 if (!from_settings)
3203 grey_show(false);
3204#endif
3205 rb->splash(HZ*2, rb->str(LANG_WAIT_FOR_CACHE));
3206#ifdef USEGSLIB
3207 if (!from_settings)
3208 grey_show(true);
3209#endif
3210 return false;
3211 }
3212
3213 /* set idle state */
3214 if (pf_state == pf_show_tracks)
3215 free_borrowed_tracks();
3216 if (pf_state == pf_show_tracks ||
3217 pf_state == pf_cover_in ||
3218 pf_state == pf_cover_out)
3219 interrupt_cover_out_animation();
3220 else if (pf_state == pf_scrolling)
3221 set_current_slide(target);
3222 pf_state = pf_idle;
3223
3224 pf_cfg.sort_albums_by = new_sorting;
3225 if (!from_settings)
3226 {
3227#ifdef USEGSLIB
3228 grey_show(false);
3229#endif
3230 rb->splash(HZ, sort_options[pf_cfg.sort_albums_by]);
3231#ifdef USEGSLIB
3232 grey_show(true);
3233#endif
3234 }
3235
3236 current_album_artist = get_album_artist(center_index);
3237 current_album_name = get_album_name(center_index);
3238
3239 end_pf_thread(); /* stop loading of covers */
3240
3241 rb->qsort(pf_idx.album_index, pf_idx.album_ct,
3242 sizeof(struct album_data), compare_albums);
3243
3244 /* Empty cache and restart cover loading thread */
3245 rb->buflib_init(&buf_ctx, (void *)pf_idx.buf, pf_idx.buf_sz);
3246 empty_slide_hid = read_pfraw(EMPTY_SLIDE, 0);
3247 initialize_slide_cache();
3248 create_pf_thread();
3249
3250 /* Go to previously selected slide */
3251 for (i = 0; i < pf_idx.album_ct; i++ )
3252 {
3253 album_idx = pf_idx.album_index[i].name_idx;
3254 artist_idx = pf_idx.album_index[i].artist_idx;
3255
3256 if(!rb->strcmp(pf_idx.album_names + album_idx, current_album_name) &&
3257 !rb->strcmp(pf_idx.artist_names + artist_idx, current_album_artist))
3258 set_current_slide(i);
3259 }
3260 return true;
3261}
3262
2969/** 3263/**
2970 Start the animation for changing slides 3264 Start the animation for changing slides
2971 */ 3265 */
@@ -3199,15 +3493,18 @@ static void cleanup(void)
3199static int settings_menu(void) 3493static int settings_menu(void)
3200{ 3494{
3201 int selection = 0; 3495 int selection = 0;
3202 bool old_val; 3496 int old_val;
3203 3497
3204 MENUITEM_STRINGLIST(settings_menu, "PictureFlow Settings", NULL, 3498 MENUITEM_STRINGLIST(settings_menu, "PictureFlow Settings", NULL,
3499 ID2P(LANG_SHOW_ALBUM_TITLE),
3500 ID2P(LANG_SHOW_YEAR_IN_ALBUM_TITLE),
3501 ID2P(LANG_SORT_ALBUMS_BY),
3502 ID2P(LANG_YEAR_SORT_ORDER),
3205 ID2P(LANG_DISPLAY_FPS), 3503 ID2P(LANG_DISPLAY_FPS),
3206 ID2P(LANG_SPACING), 3504 ID2P(LANG_SPACING),
3207 ID2P(LANG_CENTRE_MARGIN), 3505 ID2P(LANG_CENTRE_MARGIN),
3208 ID2P(LANG_NUMBER_OF_SLIDES), 3506 ID2P(LANG_NUMBER_OF_SLIDES),
3209 ID2P(LANG_ZOOM), 3507 ID2P(LANG_ZOOM),
3210 ID2P(LANG_SHOW_ALBUM_TITLE),
3211 ID2P(LANG_RESIZE_COVERS), 3508 ID2P(LANG_RESIZE_COVERS),
3212 ID2P(LANG_REBUILD_CACHE), 3509 ID2P(LANG_REBUILD_CACHE),
3213 ID2P(LANG_UPDATE_CACHE), 3510 ID2P(LANG_UPDATE_CACHE),
@@ -3221,6 +3518,16 @@ static int settings_menu(void)
3221 { STR(LANG_SHOW_ALL_AT_THE_TOP) }, 3518 { STR(LANG_SHOW_ALL_AT_THE_TOP) },
3222 { STR(LANG_SHOW_ALL_AT_THE_BOTTOM) }, 3519 { STR(LANG_SHOW_ALL_AT_THE_BOTTOM) },
3223 }; 3520 };
3521 static const struct opt_items sort_options[] = {
3522 { STR(LANG_ARTIST_PLUS_NAME) },
3523 { STR(LANG_ARTIST_PLUS_YEAR) },
3524 { STR(LANG_ID3_YEAR) },
3525 { STR(LANG_NAME) }
3526 };
3527 static const struct opt_items year_sort_order_options[] = {
3528 { STR(LANG_ASCENDING) },
3529 { STR(LANG_DESCENDING) }
3530 };
3224 static const struct opt_items wps_options[] = { 3531 static const struct opt_items wps_options[] = {
3225 { STR(LANG_OFF) }, 3532 { STR(LANG_OFF) },
3226 { STR(LANG_DIRECT) }, 3533 { STR(LANG_DIRECT) },
@@ -3235,11 +3542,37 @@ static int settings_menu(void)
3235 selection=rb->do_menu(&settings_menu,&selection, NULL, false); 3542 selection=rb->do_menu(&settings_menu,&selection, NULL, false);
3236 switch(selection) { 3543 switch(selection) {
3237 case 0: 3544 case 0:
3545 rb->set_option(rb->str(LANG_SHOW_ALBUM_TITLE),
3546 &pf_cfg.show_album_name, INT, album_name_options, 5, NULL);
3547 reset_track_list();
3548 recalc_offsets();
3549 reset_slides();
3550 break;
3551 case 1:
3552 rb->set_bool(rb->str(LANG_SHOW_YEAR_IN_ALBUM_TITLE), &pf_cfg.show_year);
3553 break;
3554 case 2:
3555 old_val = pf_cfg.sort_albums_by;
3556 rb->set_option(rb->str(LANG_SORT_ALBUMS_BY),
3557 &pf_cfg.sort_albums_by, INT, sort_options, 4, NULL);
3558 if (old_val != pf_cfg.sort_albums_by &&
3559 !sort_albums(pf_cfg.sort_albums_by, true))
3560 pf_cfg.sort_albums_by = old_val;
3561 break;
3562 case 3:
3563 old_val = pf_cfg.year_sort_order;
3564 rb->set_option(rb->str(LANG_YEAR_SORT_ORDER),
3565 &pf_cfg.year_sort_order, INT, year_sort_order_options, 2, NULL);
3566 if (old_val != pf_cfg.year_sort_order &&
3567 !sort_albums(pf_cfg.sort_albums_by, true))
3568 pf_cfg.year_sort_order = old_val;
3569 break;
3570 case 4:
3238 rb->set_bool(rb->str(LANG_DISPLAY_FPS), &pf_cfg.show_fps); 3571 rb->set_bool(rb->str(LANG_DISPLAY_FPS), &pf_cfg.show_fps);
3239 reset_track_list(); 3572 reset_track_list();
3240 break; 3573 break;
3241 3574
3242 case 1: 3575 case 5:
3243 rb->set_int(rb->str(LANG_SPACING), "", 1, 3576 rb->set_int(rb->str(LANG_SPACING), "", 1,
3244 &pf_cfg.slide_spacing, 3577 &pf_cfg.slide_spacing,
3245 NULL, 1, 0, 100, NULL ); 3578 NULL, 1, 0, 100, NULL );
@@ -3247,7 +3580,7 @@ static int settings_menu(void)
3247 reset_slides(); 3580 reset_slides();
3248 break; 3581 break;
3249 3582
3250 case 2: 3583 case 6:
3251 rb->set_int(rb->str(LANG_CENTRE_MARGIN), "", 1, 3584 rb->set_int(rb->str(LANG_CENTRE_MARGIN), "", 1,
3252 &pf_cfg.center_margin, 3585 &pf_cfg.center_margin,
3253 NULL, 1, 0, 80, NULL ); 3586 NULL, 1, 0, 80, NULL );
@@ -3255,51 +3588,45 @@ static int settings_menu(void)
3255 reset_slides(); 3588 reset_slides();
3256 break; 3589 break;
3257 3590
3258 case 3: 3591 case 7:
3259 rb->set_int(rb->str(LANG_NUMBER_OF_SLIDES), "", 1, 3592 rb->set_int(rb->str(LANG_NUMBER_OF_SLIDES), "", 1,
3260 &pf_cfg.num_slides, NULL, 1, 1, MAX_SLIDES_COUNT, NULL ); 3593 &pf_cfg.num_slides, NULL, 1, 1, MAX_SLIDES_COUNT, NULL );
3261 recalc_offsets(); 3594 recalc_offsets();
3262 reset_slides(); 3595 reset_slides();
3263 break; 3596 break;
3264 3597
3265 case 4: 3598 case 8:
3266 rb->set_int(rb->str(LANG_ZOOM), "", 1, &pf_cfg.zoom, 3599 rb->set_int(rb->str(LANG_ZOOM), "", 1, &pf_cfg.zoom,
3267 NULL, 1, 10, 300, NULL ); 3600 NULL, 1, 10, 300, NULL );
3268 recalc_offsets(); 3601 recalc_offsets();
3269 reset_slides(); 3602 reset_slides();
3270 break; 3603 break;
3271 case 5: 3604
3272 rb->set_option(rb->str(LANG_SHOW_ALBUM_TITLE), 3605 case 9:
3273 &pf_cfg.show_album_name, INT, album_name_options, 5, NULL);
3274 reset_track_list();
3275 recalc_offsets();
3276 reset_slides();
3277 break;
3278 case 6:
3279 old_val = pf_cfg.resize; 3606 old_val = pf_cfg.resize;
3280 rb->set_bool(rb->str(LANG_RESIZE_COVERS), &pf_cfg.resize); 3607 rb->set_bool(rb->str(LANG_RESIZE_COVERS), &pf_cfg.resize);
3281 if (old_val == pf_cfg.resize) /* changed? */ 3608 if (old_val == pf_cfg.resize) /* changed? */
3282 break; 3609 break;
3283 /* fallthrough if changed, since cache needs to be rebuilt */ 3610 /* fallthrough if changed, since cache needs to be rebuilt */
3284 case 7: 3611 case 10:
3285 pf_cfg.cache_version = CACHE_REBUILD; 3612 pf_cfg.cache_version = CACHE_REBUILD;
3286 rb->remove(EMPTY_SLIDE); 3613 rb->remove(EMPTY_SLIDE);
3287 configfile_save(CONFIG_FILE, config, 3614 configfile_save(CONFIG_FILE, config,
3288 CONFIG_NUM_ITEMS, CONFIG_VERSION); 3615 CONFIG_NUM_ITEMS, CONFIG_VERSION);
3289 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART)); 3616 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
3290 break; 3617 break;
3291 case 8: 3618 case 11:
3292 pf_cfg.cache_version = CACHE_UPDATE; 3619 pf_cfg.cache_version = CACHE_UPDATE;
3293 rb->remove(EMPTY_SLIDE); 3620 rb->remove(EMPTY_SLIDE);
3294 configfile_save(CONFIG_FILE, config, 3621 configfile_save(CONFIG_FILE, config,
3295 CONFIG_NUM_ITEMS, CONFIG_VERSION); 3622 CONFIG_NUM_ITEMS, CONFIG_VERSION);
3296 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART)); 3623 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
3297 break; 3624 break;
3298 case 9: 3625 case 12:
3299 rb->set_option(rb->str(LANG_WPS_INTEGRATION), 3626 rb->set_option(rb->str(LANG_WPS_INTEGRATION),
3300 &pf_cfg.auto_wps, INT, wps_options, 3, NULL); 3627 &pf_cfg.auto_wps, INT, wps_options, 3, NULL);
3301 break; 3628 break;
3302 case 10: 3629 case 13:
3303 rb->set_option(rb->str(LANG_BACKLIGHT), 3630 rb->set_option(rb->str(LANG_BACKLIGHT),
3304 &pf_cfg.backlight_mode, INT, backlight_options, 2, NULL); 3631 &pf_cfg.backlight_mode, INT, backlight_options, 2, NULL);
3305 break; 3632 break;
@@ -3792,10 +4119,13 @@ static bool start_playback(bool return_to_WPS)
3792 */ 4119 */
3793static void draw_album_text(void) 4120static void draw_album_text(void)
3794{ 4121{
4122 char album_and_year[MAX_PATH];
4123
3795 if (pf_cfg.show_album_name == ALBUM_NAME_HIDE) 4124 if (pf_cfg.show_album_name == ALBUM_NAME_HIDE)
3796 return; 4125 return;
3797 4126
3798 static int prev_albumtxt_index = -1; 4127 static int prev_albumtxt_index = -1;
4128 static bool prev_show_year = false;
3799 int albumtxt_index; 4129 int albumtxt_index;
3800 int char_height; 4130 int char_height;
3801 int albumtxt_x, albumtxt_y, artisttxt_x; 4131 int albumtxt_x, albumtxt_y, artisttxt_x;
@@ -3823,10 +4153,18 @@ static void draw_album_text(void)
3823 } 4153 }
3824 albumtxt = get_album_name_idx(albumtxt_index, &album_idx); 4154 albumtxt = get_album_name_idx(albumtxt_index, &album_idx);
3825 4155
4156 if (pf_cfg.show_year && pf_idx.album_index[albumtxt_index].year > 0)
4157 {
4158 rb->snprintf(album_and_year, sizeof(album_and_year), "%s – %d",
4159 albumtxt, pf_idx.album_index[albumtxt_index].year);
4160 } else
4161 rb->snprintf(album_and_year, sizeof(album_and_year), "%s", albumtxt);
4162
3826 mylcd_set_foreground(G_BRIGHT(c)); 4163 mylcd_set_foreground(G_BRIGHT(c));
3827 if (albumtxt_index != prev_albumtxt_index) { 4164 if (albumtxt_index != prev_albumtxt_index || pf_cfg.show_year != prev_show_year) {
3828 set_scroll_line(albumtxt, PF_SCROLL_ALBUM); 4165 set_scroll_line(album_and_year, PF_SCROLL_ALBUM);
3829 prev_albumtxt_index = albumtxt_index; 4166 prev_albumtxt_index = albumtxt_index;
4167 prev_show_year = pf_cfg.show_year;
3830 } 4168 }
3831 4169
3832 char_height = rb->screens[SCREEN_MAIN]->getcharheight(); 4170 char_height = rb->screens[SCREEN_MAIN]->getcharheight();
@@ -3851,7 +4189,7 @@ static void draw_album_text(void)
3851 || (pf_cfg.show_album_name == ALBUM_AND_ARTIST_BOTTOM)){ 4189 || (pf_cfg.show_album_name == ALBUM_AND_ARTIST_BOTTOM)){
3852 4190
3853 if (album_idx != (int) pf_idx.album_untagged_idx) 4191 if (album_idx != (int) pf_idx.album_untagged_idx)
3854 mylcd_putsxy(albumtxt_x, albumtxt_y, albumtxt); 4192 mylcd_putsxy(albumtxt_x, albumtxt_y, album_and_year);
3855 4193
3856 artisttxt = get_album_artist(albumtxt_index); 4194 artisttxt = get_album_artist(albumtxt_index);
3857 set_scroll_line(artisttxt, PF_SCROLL_ARTIST); 4195 set_scroll_line(artisttxt, PF_SCROLL_ARTIST);
@@ -3859,7 +4197,7 @@ static void draw_album_text(void)
3859 int y_offset = char_height + char_height/2; 4197 int y_offset = char_height + char_height/2;
3860 mylcd_putsxy(artisttxt_x, albumtxt_y + y_offset, artisttxt); 4198 mylcd_putsxy(artisttxt_x, albumtxt_y + y_offset, artisttxt);
3861 } else { 4199 } else {
3862 mylcd_putsxy(albumtxt_x, albumtxt_y, albumtxt); 4200 mylcd_putsxy(albumtxt_x, albumtxt_y, album_and_year);
3863 } 4201 }
3864} 4202}
3865 4203
@@ -4189,24 +4527,38 @@ static int pictureflow_main(const char* selected_file)
4189 if ( pf_state == pf_idle || pf_state == pf_scrolling ) 4527 if ( pf_state == pf_idle || pf_state == pf_scrolling )
4190 show_previous_slide(); 4528 show_previous_slide();
4191 break; 4529 break;
4530 case PF_SORTING_NEXT:
4531 sort_albums((pf_cfg.sort_albums_by + 1) % SORT_VALUES_SIZE, false);
4532 break;
4533 case PF_SORTING_PREV:
4534 sort_albums((pf_cfg.sort_albums_by + (SORT_VALUES_SIZE - 1)) % SORT_VALUES_SIZE, false);
4535 break;
4192 case PF_JMP: 4536 case PF_JMP:
4193 if (pf_state == pf_idle || pf_state == pf_scrolling) 4537 if (pf_state == pf_idle || pf_state == pf_scrolling)
4538 {
4539 int new_idx = jmp_idx_next();
4540 if (new_idx != center_index)
4194 { 4541 {
4195 pf_state = pf_idle; 4542 pf_state = pf_idle;
4196 set_current_slide(get_album_artist_alpha_next_index()); 4543 set_current_slide(new_idx);
4197 } 4544 }
4198 else if ( pf_state == pf_show_tracks ) 4545 }
4199 select_next_album(); 4546 else if ( pf_state == pf_show_tracks )
4200 break; 4547 select_next_album();
4548 break;
4201 case PF_JMP_PREV: 4549 case PF_JMP_PREV:
4202 if (pf_state == pf_idle || pf_state == pf_scrolling) 4550 if (pf_state == pf_idle || pf_state == pf_scrolling)
4551 {
4552 int new_idx = jmp_idx_prev();
4553 if (new_idx != center_index)
4203 { 4554 {
4204 pf_state = pf_idle; 4555 pf_state = pf_idle;
4205 set_current_slide(get_album_artist_alpha_prev_index()); 4556 set_current_slide(new_idx);
4206 } 4557 }
4207 else if ( pf_state == pf_show_tracks ) 4558 }
4208 select_prev_album(); 4559 else if ( pf_state == pf_show_tracks )
4209 break; 4560 select_prev_album();
4561 break;
4210#if PF_PLAYBACK_CAPABLE 4562#if PF_PLAYBACK_CAPABLE
4211 case PF_CONTEXT: 4563 case PF_CONTEXT:
4212 if (pf_cfg.auto_wps != 0 && 4564 if (pf_cfg.auto_wps != 0 &&