summaryrefslogtreecommitdiff
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
parentce61be4d59607c579594a66e59db1569c775f3da (diff)
downloadrockbox-e8a3ade0eae65a962993d1d70b6aa6d74ac639a6.tar.gz
rockbox-e8a3ade0eae65a962993d1d70b6aa6d74ac639a6.zip
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
-rw-r--r--apps/lang/english.lang99
-rw-r--r--apps/lang/espanol.lang573
-rw-r--r--apps/plugins/pictureflow/pictureflow.c263
-rw-r--r--docs/CREDITS1
4 files changed, 890 insertions, 46 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index fd7f2778c5..bc27a9fb4c 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -16433,3 +16433,102 @@ id: VOICE_BAT_BENCH_KEYS
16433 *: "File error" 16433 *: "File error"
16434 </voice> 16434 </voice>
16435</phrase> 16435</phrase>
16436<phrase>
16437 id: LANG_UPDATE_CACHE
16438 desc: in pictureflow
16439 user: core
16440 <source>
16441 *: "Update cache"
16442 </source>
16443 <dest>
16444 *: "Update cache"
16445 </dest>
16446 <voice>
16447 *: "Update cache"
16448 </voice>
16449</phrase>
16450<phrase>
16451 id: LANG_HIDE_ALBUM_TITLE_NEW
16452 desc: in the pictureflow settings
16453 user: core
16454 <source>
16455 *: none
16456 lcd_bitmap: "Hide information"
16457 </source>
16458 <dest>
16459 *: none
16460 lcd_bitmap: "Hide information"
16461 </dest>
16462 <voice>
16463 *: none
16464 lcd_bitmap: "Hide information"
16465 </voice>
16466</phrase>
16467<phrase>
16468 id: LANG_SHOW_AT_THE_BOTTOM_NEW
16469 desc: in the pictureflow settings
16470 user: core
16471 <source>
16472 *: none
16473 lcd_bitmap: "Show album at the bottom"
16474 </source>
16475 <dest>
16476 *: none
16477 lcd_bitmap: "Show album at the bottom"
16478 </dest>
16479 <voice>
16480 *: none
16481 lcd_bitmap: "Show album at the bottom"
16482 </voice>
16483</phrase>
16484<phrase>
16485 id: LANG_SHOW_AT_THE_TOP_NEW
16486 desc: in the pictureflow settings
16487 user: core
16488 <source>
16489 *: none
16490 lcd_bitmap: "Show album at the top"
16491 </source>
16492 <dest>
16493 *: none
16494 lcd_bitmap: "Show album at the top"
16495 </dest>
16496 <voice>
16497 *: none
16498 lcd_bitmap: "Show album at the top"
16499 </voice>
16500</phrase>
16501<phrase>
16502 id: LANG_SHOW_ALL_AT_THE_TOP
16503 desc: in the pictureflow settings
16504 user: core
16505 <source>
16506 *: none
16507 lcd_bitmap: "Show album and artist at the top"
16508 </source>
16509 <dest>
16510 *: none
16511 lcd_bitmap: "Show album and artist at the top"
16512 </dest>
16513 <voice>
16514 *: none
16515 lcd_bitmap: "Show album and artist at the top"
16516 </voice>
16517</phrase>
16518<phrase>
16519 id: LANG_SHOW_ALL_AT_THE_BOTTOM
16520 desc: in the pictureflow settings
16521 user: core
16522 <source>
16523 *: none
16524 lcd_bitmap: "Show album and artist at the bottom"
16525 </source>
16526 <dest>
16527 *: none
16528 lcd_bitmap: "Show album and artist at the bottom"
16529 </dest>
16530 <voice>
16531 *: none
16532 lcd_bitmap: "Show album and artist at the bottom"
16533 </voice>
16534</phrase> \ No newline at end of file
diff --git a/apps/lang/espanol.lang b/apps/lang/espanol.lang
index f4ce6fc02a..ba91ddf734 100644
--- a/apps/lang/espanol.lang
+++ b/apps/lang/espanol.lang
@@ -5726,10 +5726,10 @@
5726 *: "Committing database" 5726 *: "Committing database"
5727 </source> 5727 </source>
5728 <dest> 5728 <dest>
5729 *: "Grabando TagCache" 5729 *: "Grabando Base de Datos"
5730 </dest> 5730 </dest>
5731 <voice> 5731 <voice>
5732 *: "Grabando Tag Cache" 5732 *: "Grabando Base de Datos"
5733 </voice> 5733 </voice>
5734</phrase> 5734</phrase>
5735<phrase> 5735<phrase>
@@ -6217,10 +6217,10 @@
6217 *: "Database is not ready" 6217 *: "Database is not ready"
6218 </source> 6218 </source>
6219 <dest> 6219 <dest>
6220 *: "TagCache no ha finalizado" 6220 *: "La Base de Datos no esta lista"
6221 </dest> 6221 </dest>
6222 <voice> 6222 <voice>
6223 *: "TagCache no ha finalizado" 6223 *: "La Base de Datos no esta lista"
6224 </voice> 6224 </voice>
6225</phrase> 6225</phrase>
6226<phrase> 6226<phrase>
@@ -7396,10 +7396,10 @@
7396 *: "Database" 7396 *: "Database"
7397 </source> 7397 </source>
7398 <dest> 7398 <dest>
7399 *: "Tag Cache" 7399 *: "Música (Base de Datos)"
7400 </dest> 7400 </dest>
7401 <voice> 7401 <voice>
7402 *: "Tag Cache" 7402 *: "Música (Base de Datos)"
7403 </voice> 7403 </voice>
7404</phrase> 7404</phrase>
7405<phrase> 7405<phrase>
@@ -8254,10 +8254,10 @@
8254 *: "Album Artist" 8254 *: "Album Artist"
8255 </source> 8255 </source>
8256 <dest> 8256 <dest>
8257 *: "Álbum Artista" 8257 *: "Artista del Album"
8258 </dest> 8258 </dest>
8259 <voice> 8259 <voice>
8260 *: "Álbum Artista" 8260 *: "Artista del Album"
8261 </voice> 8261 </voice>
8262</phrase> 8262</phrase>
8263<phrase> 8263<phrase>
@@ -12399,7 +12399,7 @@
12399 *: "PictureFlow" 12399 *: "PictureFlow"
12400 </source> 12400 </source>
12401 <dest> 12401 <dest>
12402 *: "Pase de carátulas" 12402 *: "PictureFlow"
12403 </dest> 12403 </dest>
12404 <voice> 12404 <voice>
12405 *: "Abrir pase de carátulas" 12405 *: "Abrir pase de carátulas"
@@ -12978,9 +12978,560 @@
12978 *: "Select directories to scan" 12978 *: "Select directories to scan"
12979 </source> 12979 </source>
12980 <dest> 12980 <dest>
12981 *: "Seleccione los directorios que explorar" 12981 *: "Seleccione los directorios a escanear"
12982 </dest>
12983 <voice>
12984 *: "Seleccione los directorios a escanear"
12985 </voice>
12986</phrase>
12987<phrase>
12988 id: LANG_HIDE_ALBUM_TITLE
12989 desc: in the pictureflow settings
12990 user: core
12991 <source>
12992 *: none
12993 lcd_bitmap: "Hide information"
12994 </source>
12995 <dest>
12996 *: none
12997 lcd_bitmap: "Ocutar información"
12998 </dest>
12999 <voice>
13000 *: none
13001 lcd_bitmap: "Ocultar información"
13002 </voice>
13003</phrase>
13004<phrase>
13005 id: LANG_SHOW_AT_THE_TOP
13006 desc: in the pictureflow settings
13007 user: core
13008 <source>
13009 *: none
13010 lcd_bitmap: "Show album at the top"
13011 </source>
13012 <dest>
13013 *: none
13014 lcd_bitmap: "Mostrar album en la parte superior"
13015 </dest>
13016 <voice>
13017 *: none
13018 lcd_bitmap: "Mostrar album en la parte superior"
13019 </voice>
13020</phrase>
13021<phrase>
13022 id: LANG_SHOW_ALL_AT_THE_TOP
13023 desc: in the pictureflow settings
13024 user: core
13025 <source>
13026 *: none
13027 lcd_bitmap: "Show album and artist at the top"
13028 </source>
13029 <dest>
13030 *: none
13031 lcd_bitmap: "Mostrar album y artista en la parte superior"
13032 </dest>
13033 <voice>
13034 *: none
13035 lcd_bitmap: "Mostrar album y artista en la parte superior"
13036 </voice>
13037</phrase>
13038<phrase>
13039 id: LANG_SHOW_ALL_AT_THE_BOTTOM
13040 desc: in the pictureflow settings
13041 user: core
13042 <source>
13043 *: none
13044 lcd_bitmap: "Show album and artist at the bottom"
13045 </source>
13046 <dest>
13047 *: none
13048 lcd_bitmap: "Mostrar album y artista en la parte inferior"
13049 </dest>
13050 <voice>
13051 *: none
13052 lcd_bitmap: "Mostrar album y artista en la parte inferior"
13053 </voice>
13054</phrase>
13055<phrase>
13056 id: LANG_NUMBER_OF_SLIDES
13057 desc: in the pictureflow settings menu
13058 user: core
13059 <source>
13060 *: none
13061 lcd_bitmap: "Number of slides"
13062 </source>
13063 <dest>
13064 *: none
13065 lcd_bitmap: "Número de carátulas"
13066 </dest>
13067 <voice>
13068 *: none
13069 lcd_bitmap: "Número de carátulas"
13070 </voice>
13071</phrase>
13072<phrase>
13073 id: LANG_ALWAYS_ON
13074 desc: in the pictureflow settings menu
13075 user: core
13076 <source>
13077 *: none
13078 lcd_bitmap: "Always On"
13079 </source>
13080 <dest>
13081 *: none
13082 lcd_bitmap: "Siempre encendida"
13083 </dest>
13084 <voice>
13085 *: none
13086 lcd_bitmap: "Siempre encendida"
13087 </voice>
13088</phrase>
13089<phrase>
13090 id: LANG_ZOOM
13091 desc: in the pictureflow settings menu
13092 user: core
13093 <source>
13094 *: none
13095 lcd_bitmap: "Zoom"
13096 </source>
13097 <dest>
13098 *: none
13099 lcd_bitmap: "Zoom"
13100 </dest>
13101 <voice>
13102 *: none
13103 lcd_bitmap: "Zoom"
13104 </voice>
13105</phrase>
13106<phrase>
13107 id: LANG_VIA_TRACK_LIST
13108 desc: in the pictureflow settings
13109 user: core
13110 <source>
13111 *: none
13112 lcd_bitmap: "Via Track list"
13113 </source>
13114 <dest>
13115 *: none
13116 lcd_bitmap: "A través de la lista de canciones"
13117 </dest>
13118 <voice>
13119 *: none
13120 lcd_bitmap: "A través de la lista de canciones"
13121 </voice>
13122</phrase>
13123<phrase>
13124 id: LANG_SHOW_ALBUM_TITLE
13125 desc: in the pictureflow settings menu
13126 user: core
13127 <source>
13128 *: none
13129 lcd_bitmap: "Show album title"
13130 </source>
13131 <dest>
13132 *: none
13133 lcd_bitmap: "Mostrar título del album"
13134 </dest>
13135 <voice>
13136 *: none
13137 lcd_bitmap: "Mostrar título del album"
13138 </voice>
13139</phrase>
13140<phrase>
13141 id: LANG_GOTO_WPS
13142 desc: in the pictureflow main menu
13143 user: core
13144 <source>
13145 *: none
13146 lcd_bitmap: "Go to WPS"
13147 </source>
13148 <dest>
13149 *: none
13150 lcd_bitmap: "Ir a Pantalla de Reproducción"
13151 </dest>
13152 <voice>
13153 *: none
13154 lcd_bitmap: "Ir a Pantalla de Reproducción"
13155 </voice>
13156</phrase>
13157<phrase>
13158 id: LANG_CACHE_REBUILT_NEXT_RESTART
13159 desc: in the pictureflow splash messages
13160 user: core
13161 <source>
13162 *: none
13163 lcd_bitmap: "Cache will be rebuilt on next restart"
13164 </source>
13165 <dest>
13166 *: none
13167 lcd_bitmap: "El caché se reconstruirá después de reiniciar"
13168 </dest>
13169 <voice>
13170 *: none
13171 lcd_bitmap: "El caché se reconstruirá después de reiniciar"
13172 </voice>
13173</phrase>
13174<phrase>
13175 id: LANG_REBUILD_CACHE
13176 desc: in the pictureflow settings menu
13177 user: core
13178 <source>
13179 *: none
13180 lcd_bitmap: "Rebuild cache"
13181 </source>
13182 <dest>
13183 *: none
13184 lcd_bitmap: "Reconstruir caché"
13185 </dest>
13186 <voice>
13187 *: none
13188 lcd_bitmap: "Reconstruir caché"
13189 </voice>
13190</phrase>
13191<phrase>
13192 id: LANG_ERROR_WRITING_CONFIG
13193 desc: in the pictureflow splash messages
13194 user: core
13195 <source>
13196 *: none
13197 lcd_bitmap: "Error writing config"
13198 </source>
13199 <dest>
13200 *: none
13201 lcd_bitmap: "Error guardando la configuración"
13202 </dest>
13203 <voice>
13204 *: none
13205 lcd_bitmap: "Error guardando la configuración"
13206 </voice>
13207</phrase>
13208<phrase>
13209 id: LANG_PLAYLIST_CLEARED
13210 desc: in the pictureflow splash messages
13211 user: core
13212 <source>
13213 *: none
13214 lcd_bitmap: "Playlist Cleared"
13215 </source>
13216 <dest>
13217 *: none
13218 lcd_bitmap: "Lista de Reproducción Borrada"
13219 </dest>
13220 <voice>
13221 *: none
13222 lcd_bitmap: "Lista de Reproducción Borrada"
13223 </voice>
13224</phrase>
13225<phrase>
13226 id: LANG_CENTRE_MARGIN
13227 desc: in the pictureflow settings menu
13228 user: core
13229 <source>
13230 *: none
13231 lcd_bitmap: "Centre margin"
13232 </source>
13233 <dest>
13234 *: none
13235 lcd_bitmap: "Margen central"
13236 </dest>
13237 <voice>
13238 *: none
13239 lcd_bitmap: "Margen central"
13240 </voice>
13241</phrase>
13242<phrase>
13243 id: LANG_SPACING
13244 desc: in the pictureflow settings menu
13245 user: core
13246 <source>
13247 *: none
13248 lcd_bitmap: "Spacing"
13249 </source>
13250 <dest>
13251 *: none
13252 lcd_bitmap: "Separación"
13253 </dest>
13254 <voice>
13255 *: none
13256 lcd_bitmap: "Separación"
13257 </voice>
13258</phrase>
13259<phrase>
13260 id: LANG_WPS_INTEGRATION
13261 desc: in the pictureflow settings menu
13262 user: core
13263 <source>
13264 *: none
13265 lcd_bitmap: "WPS Integration"
13266 </source>
13267 <dest>
13268 *: none
13269 lcd_bitmap: "Integración en WPS"
13270 </dest>
13271 <voice>
13272 *: none
13273 lcd_bitmap: "Integración en WPS"
13274 </voice>
13275</phrase>
13276<phrase>
13277 id: LANG_DIRECT
13278 desc: in the pictureflow settings
13279 user: core
13280 <source>
13281 *: none
13282 lcd_bitmap: "Direct"
13283 </source>
13284 <dest>
13285 *: none
13286 lcd_bitmap: "Directa"
13287 </dest>
13288 <voice>
13289 *: none
13290 lcd_bitmap: "Directa"
13291 </voice>
13292</phrase>
13293<phrase>
13294 id: LANG_RESIZE_COVERS
13295 desc: in the pictureflow settings menu
13296 user: core
13297 <source>
13298 *: none
13299 lcd_bitmap: "Resize Covers"
13300 </source>
13301 <dest>
13302 *: none
13303 lcd_bitmap: "Reescalar Carátulas"
13304 </dest>
13305 <voice>
13306 *: none
13307 lcd_bitmap: "Resize Carátulas"
13308 </voice>
13309</phrase>
13310<phrase>
13311 id: LANG_NO_ALBUMART_FOUND
13312 desc: in the pictureflow splash messages
13313 user: core
13314 <source>
13315 *: none
13316 lcd_bitmap: "No album art found"
13317 </source>
13318 <dest>
13319 *: none
13320 lcd_bitmap: "No se encontró carátula para el album"
13321 </dest>
13322 <voice>
13323 *: none
13324 lcd_bitmap: "No se encontró carátula para el album"
13325 </voice>
13326</phrase>
13327<phrase>
13328 id: LANG_DISPLAY_FPS
13329 desc: in the mpegplayer and pictureflow settings menus
13330 user: core
13331 <source>
13332 *: none
13333 swcodec: "Display FPS"
13334 lcd_bitmap: "Display FPS"
13335 </source>
13336 <dest>
13337 *: none
13338 swcodec: "Display FPS"
13339 lcd_bitmap: "Mostrar FPS"
13340 </dest>
13341 <voice>
13342 *: none
13343 swcodec: "Display FPS"
13344 lcd_bitmap: "Mostrar FPS"
13345 </voice>
13346</phrase>
13347<phrase>
13348 id: LANG_SHOW_AT_THE_BOTTOM
13349 desc: in the pictureflow settings
13350 user: core
13351 <source>
13352 *: none
13353 lcd_bitmap: "Show album at the bottom"
13354 </source>
13355 <dest>
13356 *: none
13357 lcd_bitmap: "Mostrar album en la parte inferior"
13358 </dest>
13359 <voice>
13360 *: none
13361 lcd_bitmap: "Mostrar album en la parte inferior"
13362 </voice>
13363</phrase>
13364<phrase>
13365 id: LANG_ADDED_TO_PLAYLIST
13366 desc: in the pictureflow splash messages
13367 user: core
13368 <source>
13369 *: none
13370 lcd_bitmap: "Added to playlist"
13371 </source>
13372 <dest>
13373 *: none
13374 lcd_bitmap: "Añadida a la Lista de Reproducción"
13375 </dest>
13376 <voice>
13377 *: none
13378 lcd_bitmap: "Añadida a la Lista de Reproducción"
13379 </voice>
13380</phrase>
13381<phrase>
13382 id: LANG_CLEAR_PLAYLIST
13383 desc: in the pictureflow main menu
13384 user: core
13385 <source>
13386 *: none
13387 lcd_bitmap: "Clear playlist"
13388 </source>
13389 <dest>
13390 *: none
13391 lcd_bitmap: "Borrar Lista de Reproducción"
13392 </dest>
13393 <voice>
13394 *: none
13395 lcd_bitmap: "Borrar Lista de Reproducción"
13396 </voice>
13397</phrase>
13398<phrase>
13399 id: LANG_PLAYBACK_CONTROL
13400 desc: in playback control menu
13401 user: core
13402 <source>
13403 *: "Playback Control"
13404 </source>
13405 <dest>
13406 *: "Control de Reproducción"
13407 </dest>
13408 <voice>
13409 *: "Control de Reproducción"
13410 </voice>
13411</phrase>
13412<phrase>
13413 id: LANG_PREVTRACK
13414 desc: in playback control menu
13415 user: core
13416 <source>
13417 *: "Previous Track"
13418 </source>
13419 <dest>
13420 *: "Pista Anterior"
13421 </dest>
13422 <voice>
13423 *: "Pista Anterior"
13424 </voice>
13425</phrase>
13426<phrase>
13427 id: LANG_PLAYPAUSE
13428 desc: in playback control menu
13429 user: core
13430 <source>
13431 *: "Pause / Play"
13432 </source>
13433 <dest>
13434 *: "Pausar / Reproducir"
13435 </dest>
13436 <voice>
13437 *: "Pausar / Reproducir"
13438 </voice>
13439</phrase>
13440<phrase>
13441 id: LANG_STOP_PLAYBACK
13442 desc: in playback control menu
13443 user: core
13444 <source>
13445 *: "Stop Playback"
13446 </source>
13447 <dest>
13448 *: "Detener Reproducción"
13449 </dest>
13450 <voice>
13451 *: "Detener Reproducción"
13452 </voice>
13453</phrase>
13454<phrase>
13455 id: LANG_NEXTTRACK
13456 desc: in playback control menu
13457 user: core
13458 <source>
13459 *: "Next Track"
13460 </source>
13461 <dest>
13462 *: "Siguiente Pista"
13463 </dest>
13464 <voice>
13465 *: "Siguiente Pista"
13466 </voice>
13467</phrase>
13468<phrase>
13469 id: LANG_CHANGE_VOLUME
13470 desc: in playback control menu
13471 user: core
13472 <source>
13473 *: "Change Volume"
13474 </source>
13475 <dest>
13476 *: "Cambiar Volumen"
13477 </dest>
13478 <voice>
13479 *: "Cambiar Volumen"
13480 </voice>
13481</phrase>
13482<phrase>
13483 id: LANG_CHANGE_SHUFFLE_MODE
13484 desc: in playback control menu
13485 user: core
13486 <source>
13487 *: "Shuffle Mode"
13488 </source>
13489 <dest>
13490 *: "Modo Aleatorio"
13491 </dest>
13492 <voice>
13493 *: "Modo Aleatorio"
13494 </voice>
13495</phrase>
13496<phrase>
13497 id: LANG_MENU_QUIT
13498 desc: in various menus
13499 user: core
13500 <source>
13501 *: "Quit"
13502 </source>
13503 <dest>
13504 *: "Salir"
13505 </dest>
13506 <voice>
13507 *: "Salir"
13508 </voice>
13509</phrase>
13510<phrase>
13511 id: LANG_RETURN
13512 desc: in various plugin menus
13513 user: core
13514 <source>
13515 *: "Return"
13516 </source>
13517 <dest>
13518 *: "Volver"
13519 </dest>
13520 <voice>
13521 *: "Volver"
13522 </voice>
13523</phrase>
13524<phrase>
13525 id: LANG_UPDATE_CACHE
13526 desc: in pictureflow
13527 user: core
13528 <source>
13529 *: "Update cache"
13530 </source>
13531 <dest>
13532 *: "Actualizar caché"
12982 </dest> 13533 </dest>
12983 <voice> 13534 <voice>
12984 *: "Seleccione los directorios que explorar" 13535 *: "Actualizar caché"
12985 </voice> 13536 </voice>
12986</phrase> 13537</phrase>
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 @@
36 36
37 37
38 38
39
40/* Capacity 10 000 entries (for example 10k different albums) */
41#define UNIQBUF_SIZE (64*1024)
42static long uniqbuf[UNIQBUF_SIZE / sizeof(long)];
43
39/******************************* Globals ***********************************/ 44/******************************* Globals ***********************************/
40 45
41/* 46/*
@@ -254,6 +259,7 @@ typedef fb_data pix_t;
254/* Error return values */ 259/* Error return values */
255#define ERROR_NO_ALBUMS -1 260#define ERROR_NO_ALBUMS -1
256#define ERROR_BUFFER_FULL -2 261#define ERROR_BUFFER_FULL -2
262#define ERROR_NO_ARTISTS -3
257 263
258/* current version for cover cache */ 264/* current version for cover cache */
259#define CACHE_VERSION 3 265#define CACHE_VERSION 3
@@ -279,6 +285,12 @@ struct slide_cache {
279 285
280struct album_data { 286struct album_data {
281 int name_idx; 287 int name_idx;
288 int artist_idx;
289 long seek;
290};
291
292struct artist_data {
293 int name_idx;
282 long seek; 294 long seek;
283}; 295};
284 296
@@ -307,6 +319,7 @@ struct load_slide_event_data {
307enum pf_scroll_line_type { 319enum pf_scroll_line_type {
308 PF_SCROLL_TRACK = 0, 320 PF_SCROLL_TRACK = 0,
309 PF_SCROLL_ALBUM, 321 PF_SCROLL_ALBUM,
322 PF_SCROLL_ARTIST,
310 PF_MAX_SCROLL_LINES 323 PF_MAX_SCROLL_LINES
311}; 324};
312 325
@@ -332,13 +345,17 @@ struct pfraw_header {
332enum show_album_name_values { 345enum show_album_name_values {
333 ALBUM_NAME_HIDE = 0, 346 ALBUM_NAME_HIDE = 0,
334 ALBUM_NAME_BOTTOM, 347 ALBUM_NAME_BOTTOM,
335 ALBUM_NAME_TOP 348 ALBUM_NAME_TOP,
349 ALBUM_AND_ARTIST_TOP,
350 ALBUM_AND_ARTIST_BOTTOM
336}; 351};
337static char* show_album_name_conf[] = 352static char* show_album_name_conf[] =
338{ 353{
339 "hide", 354 "hide",
340 "bottom", 355 "bottom",
341 "top" 356 "top",
357 "both top",
358 "both bottom",
342}; 359};
343 360
344#define MAX_SPACING 40 361#define MAX_SPACING 40
@@ -370,7 +387,7 @@ static struct configdata config[] =
370 { TYPE_BOOL, 0, 1, { .bool_p = &show_fps }, "show fps", NULL }, 387 { TYPE_BOOL, 0, 1, { .bool_p = &show_fps }, "show fps", NULL },
371 { TYPE_BOOL, 0, 1, { .bool_p = &resize }, "resize", NULL }, 388 { TYPE_BOOL, 0, 1, { .bool_p = &resize }, "resize", NULL },
372 { TYPE_INT, 0, 100, { .int_p = &cache_version }, "cache version", NULL }, 389 { TYPE_INT, 0, 100, { .int_p = &cache_version }, "cache version", NULL },
373 { TYPE_ENUM, 0, 3, { .int_p = &show_album_name }, "show album name", 390 { TYPE_ENUM, 0, 5, { .int_p = &show_album_name }, "show album name",
374 show_album_name_conf }, 391 show_album_name_conf },
375 { TYPE_INT, 0, 2, { .int_p = &auto_wps }, "auto wps", NULL }, 392 { TYPE_INT, 0, 2, { .int_p = &auto_wps }, "auto wps", NULL },
376 { TYPE_INT, 0, 999999, { .int_p = &last_album }, "last album", NULL }, 393 { TYPE_INT, 0, 999999, { .int_p = &last_album }, "last album", NULL },
@@ -417,9 +434,14 @@ static struct tagcache_search tcs;
417static struct buflib_context buf_ctx; 434static struct buflib_context buf_ctx;
418 435
419static struct album_data *album; 436static struct album_data *album;
437static struct artist_data *artist;
438
420static char *album_names; 439static char *album_names;
421static int album_count; 440static int album_count;
422 441
442static char *artist_names;
443static int artist_count;
444
423static struct track_data *tracks; 445static struct track_data *tracks;
424static char *track_names; 446static char *track_names;
425static size_t borrowed = 0; 447static size_t borrowed = 0;
@@ -833,45 +855,137 @@ static void init_reflect_table(void)
833} 855}
834 856
835/** 857/**
836 Create an index of all albums from the database. 858 Create an index of all artists and albums from the database.
837 Also store the album names so we can access them later. 859 Also store the artists and album names so we can access them later.
838 */ 860 */
839static int create_album_index(void) 861static int create_album_index(void)
840{ 862{
841 album = ((struct album_data *)(buf_size + (char *) buf)) - 1; 863 artist = ((struct artist_data *)(buf_size + (char *) buf)) - 1;
842 rb->memset(&tcs, 0, sizeof(struct tagcache_search) ); 864 rb->memset(&tcs, 0, sizeof(struct tagcache_search) );
843 album_count = 0; 865 artist_count = 0;
844 rb->tagcache_search(&tcs, tag_album); 866 rb->tagcache_search(&tcs, tag_albumartist);
845 unsigned int l, name_idx = 0; 867 unsigned int l, name_idx = 0;
846 album_names = buf; 868 artist_names = buf;
847 while (rb->tagcache_get_next(&tcs)) 869 while (rb->tagcache_get_next(&tcs))
848 { 870 {
849 buf_size -= sizeof(struct album_data); 871 buf_size -= sizeof(struct artist_data);
850 l = tcs.result_len; 872 l = tcs.result_len;
851 album[-album_count].name_idx = name_idx; 873 artist[-artist_count].name_idx = name_idx;
852 874 artist[-artist_count].seek = tcs.result_seek;
853 if ( l > buf_size ) 875 if ( l > buf_size )
854 /* not enough memory */ 876 /* not enough memory */
855 return ERROR_BUFFER_FULL; 877 return ERROR_BUFFER_FULL;
856
857 rb->strcpy(buf, tcs.result); 878 rb->strcpy(buf, tcs.result);
858 buf_size -= l; 879 buf_size -= l;
859 buf = l + (char *)buf; 880 buf = l + (char *)buf;
860 album[-album_count].seek = tcs.result_seek;
861 name_idx += l; 881 name_idx += l;
862 album_count++; 882 artist_count++;
863 } 883 }
864 rb->tagcache_search_finish(&tcs); 884 rb->tagcache_search_finish(&tcs);
865 ALIGN_BUFFER(buf, buf_size, 4); 885 ALIGN_BUFFER(buf, buf_size, 4);
866 int i; 886 int i;
887 struct artist_data* tmp_artist = (struct artist_data*)buf;
888 for (i = artist_count - 1; i >= 0; i--)
889 tmp_artist[i] = artist[-i];
890 artist = tmp_artist;
891 buf = artist + artist_count;
892
893 long artist_seek = 0;
894 int j = 0;
895 album_count = 0;
896 name_idx = 0;
897 album = ((struct album_data *)(buf_size + (char *) buf)) - 1;
898 album_names = buf;
899 for (j = 0; j < artist_count; j++){
900 artist_seek = artist[j].seek;
901 rb->memset(&tcs, 0, sizeof(struct tagcache_search) );
902 rb->tagcache_search(&tcs, tag_album);
903 /* Prevent duplicate entries in the search list. */
904 rb->tagcache_search_set_uniqbuf(&tcs, uniqbuf, UNIQBUF_SIZE);
905 rb->tagcache_search_add_filter(&tcs, tag_albumartist, artist_seek);
906 while (rb->tagcache_get_next(&tcs))
907 {
908 buf_size -= sizeof(struct album_data);
909 l = tcs.result_len;
910 album[-album_count].name_idx = name_idx;
911 album[-album_count].seek = tcs.result_seek;
912 album[-album_count].artist_idx = j;
913 if ( l > buf_size )
914 /* not enough memory */
915 return ERROR_BUFFER_FULL;
916
917 rb->strcpy(buf, tcs.result);
918 buf_size -= l;
919 buf = l + (char *)buf;
920 name_idx += l;
921 album_count++;
922 }
923 rb->tagcache_search_finish(&tcs);
924 }
925 ALIGN_BUFFER(buf, buf_size, 4);
867 struct album_data* tmp_album = (struct album_data*)buf; 926 struct album_data* tmp_album = (struct album_data*)buf;
868 for (i = album_count - 1; i >= 0; i--) 927 for (i = album_count - 1; i >= 0; i--)
869 tmp_album[i] = album[-i]; 928 tmp_album[i] = album[-i];
870 album = tmp_album; 929 album = tmp_album;
871 buf = album + album_count; 930 buf = album + album_count;
931
872 return (album_count > 0) ? 0 : ERROR_NO_ALBUMS; 932 return (album_count > 0) ? 0 : ERROR_NO_ALBUMS;
873} 933}
874 934
935
936/*Saves the artists+albums index into a binary file to be recovered the
937 next time PictureFlow is launched*/
938
939static int save_album_index(void){
940 int fd;
941 fd = rb->creat(PLUGIN_DIR "/demos/album_ndx.tmp",0666);
942 if(fd >= 0)
943 {
944 int unsigned_size = sizeof(unsigned int);
945 int int_size = sizeof(int);
946 rb->write(fd, artist_names, ((char *)buf - (char *)artist_names));
947 unsigned int artist_pos = (char *)artist - (char *)artist_names;
948 rb->write(fd, &artist_pos, unsigned_size);
949 unsigned int album_names_pos = (char *)album_names - (char *)artist_names;
950 rb->write(fd, &album_names_pos, unsigned_size);
951 unsigned int album_pos = (char *)album - (char *)artist_names;
952 rb->write(fd, &album_pos, unsigned_size);
953 rb->write(fd, &artist_count, int_size);
954 rb->write(fd, &album_count, int_size);
955 rb->close(fd);
956 return 0;
957 }
958 return -1;
959}
960
961/*Loads the artists+albums index information stored in the hard drive*/
962
963static int load_album_index(void){
964 int fr = rb->open(PLUGIN_DIR "/demos/album_ndx.tmp", O_RDONLY);
965 if (fr >= 0){
966 int unsigned_size = sizeof(unsigned int);
967 int int_size = sizeof(int);
968 unsigned long filesize = rb->filesize(fr);
969 unsigned int pos = 0;
970 unsigned int extra_data_size = (sizeof(unsigned int)*3) + (sizeof(int)*2);
971 rb->read(fr,buf ,filesize-extra_data_size);
972 artist_names = buf;
973 buf = (char *)buf + (filesize-extra_data_size);
974 buf_size = buf_size-(filesize-extra_data_size);
975 rb->read(fr,&pos ,unsigned_size);
976 artist = (void *)artist_names + pos;
977 rb->read(fr,&pos ,unsigned_size);
978 album_names = (void *)artist_names + pos;
979 rb->read(fr,&pos ,unsigned_size);
980 album = (void *)artist_names + pos;
981 rb->read(fr,&artist_count ,int_size);
982 rb->read(fr,&album_count ,int_size);
983 rb->close(fr);
984 return 0;
985 }
986 return -1;
987}
988
875/** 989/**
876 Return a pointer to the album name of the given slide_index 990 Return a pointer to the album name of the given slide_index
877 */ 991 */
@@ -881,6 +995,21 @@ static char* get_album_name(const int slide_index)
881} 995}
882 996
883/** 997/**
998 Return a pointer to the album artist of the given slide_index
999 */
1000static char* get_album_artist(const int slide_index)
1001{
1002 if (slide_index < album_count && slide_index >= 0){
1003 int artist_pos = album[slide_index].artist_idx;
1004 if (artist_pos < artist_count && artist_pos >= 0){
1005 return artist_names + artist[artist_pos].name_idx;
1006 }
1007 }
1008 return NULL;
1009}
1010
1011
1012/**
884 Return a pointer to the track name of the active album 1013 Return a pointer to the track name of the active album
885 create_track_index has to be called first. 1014 create_track_index has to be called first.
886 */ 1015 */
@@ -902,11 +1031,13 @@ static char* get_track_filename(const int track_index)
902static int get_wps_current_index(void) 1031static int get_wps_current_index(void)
903{ 1032{
904 struct mp3entry *id3 = rb->audio_current_track(); 1033 struct mp3entry *id3 = rb->audio_current_track();
1034
905 if(id3 && id3->album) { 1035 if(id3 && id3->album) {
906 int i; 1036 int i;
907 for( i=0; i < album_count; i++ ) 1037 for( i=0; i < album_count; i++ )
908 { 1038 {
909 if(!rb->strcmp(album_names + album[i].name_idx, id3->album)) 1039 if(!rb->strcmp(album_names + album[i].name_idx, id3->album) &&
1040 !rb->strcmp(artist_names + artist[album[i].artist_idx].name_idx, id3->albumartist))
910 return i; 1041 return i;
911 } 1042 }
912 } 1043 }
@@ -936,6 +1067,7 @@ static void create_track_index(const int slide_index)
936 goto fail; 1067 goto fail;
937 1068
938 rb->tagcache_search_add_filter(&tcs, tag_album, album[slide_index].seek); 1069 rb->tagcache_search_add_filter(&tcs, tag_album, album[slide_index].seek);
1070 rb->tagcache_search_add_filter(&tcs, tag_albumartist, artist[album[slide_index].artist_idx].seek);
939 track_count=0; 1071 track_count=0;
940 int string_index = 0, track_num; 1072 int string_index = 0, track_num;
941 int disc_num; 1073 int disc_num;
@@ -1051,6 +1183,7 @@ static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
1051 bool result; 1183 bool result;
1052 /* find the first track of the album */ 1184 /* find the first track of the album */
1053 rb->tagcache_search_add_filter(&tcs, tag_album, album[slide_index].seek); 1185 rb->tagcache_search_add_filter(&tcs, tag_album, album[slide_index].seek);
1186 rb->tagcache_search_add_filter(&tcs, tag_albumartist, artist[album[slide_index].artist_idx].seek);
1054 1187
1055 if ( rb->tagcache_get_next(&tcs) ) { 1188 if ( rb->tagcache_get_next(&tcs) ) {
1056 struct mp3entry id3; 1189 struct mp3entry id3;
@@ -1138,6 +1271,13 @@ static void draw_progressbar(int step)
1138 const int w = LCD_WIDTH - 20; 1271 const int w = LCD_WIDTH - 20;
1139 const int x = 10; 1272 const int x = 10;
1140 1273
1274#if LCD_DEPTH > 1
1275 rb->lcd_set_background(N_BRIGHT(0));
1276 rb->lcd_set_foreground(N_BRIGHT(255));
1277#else
1278 rb->lcd_set_drawmode(PICTUREFLOW_DRMODE);
1279#endif
1280 rb->lcd_clear_display();
1141 rb->lcd_getstringsize("Preparing album artwork", &txt_w, &txt_h); 1281 rb->lcd_getstringsize("Preparing album artwork", &txt_w, &txt_h);
1142 1282
1143 int y = (LCD_HEIGHT - txt_h)/2; 1283 int y = (LCD_HEIGHT - txt_h)/2;
@@ -1221,9 +1361,8 @@ static bool create_albumart_cache(void)
1221 for (i=0; i < album_count; i++) 1361 for (i=0; i < album_count; i++)
1222 { 1362 {
1223 draw_progressbar(i); 1363 draw_progressbar(i);
1224 1364 rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x%x.pfraw",
1225 rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x.pfraw", 1365 mfnv(get_album_name(i)),mfnv(get_album_artist(i)));
1226 mfnv(get_album_name(i)));
1227 /* delete existing cache, so it's a true rebuild */ 1366 /* delete existing cache, so it's a true rebuild */
1228 if(rb->file_exists(pfraw_file)) { 1367 if(rb->file_exists(pfraw_file)) {
1229 if(update) { 1368 if(update) {
@@ -1572,8 +1711,10 @@ static inline bool load_and_prepare_surface(const int slide_index,
1572 const int prio) 1711 const int prio)
1573{ 1712{
1574 char pfraw_file[MAX_PATH]; 1713 char pfraw_file[MAX_PATH];
1575 rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x.pfraw", 1714
1576 mfnv(get_album_name(slide_index))); 1715
1716 rb->snprintf(pfraw_file, sizeof(pfraw_file), CACHE_PREFIX "/%x%x.pfraw",
1717 mfnv(get_album_name(slide_index)),mfnv(get_album_artist(slide_index)));
1577 1718
1578 int hid = read_pfraw(pfraw_file, prio); 1719 int hid = read_pfraw(pfraw_file, prio);
1579 if (!hid) 1720 if (!hid)
@@ -2243,13 +2384,16 @@ static int settings_menu(void)
2243 ID2P(LANG_SHOW_ALBUM_TITLE), 2384 ID2P(LANG_SHOW_ALBUM_TITLE),
2244 ID2P(LANG_RESIZE_COVERS), 2385 ID2P(LANG_RESIZE_COVERS),
2245 ID2P(LANG_REBUILD_CACHE), 2386 ID2P(LANG_REBUILD_CACHE),
2387 ID2P(LANG_UPDATE_CACHE),
2246 ID2P(LANG_WPS_INTEGRATION), 2388 ID2P(LANG_WPS_INTEGRATION),
2247 ID2P(LANG_BACKLIGHT)); 2389 ID2P(LANG_BACKLIGHT));
2248 2390
2249 static const struct opt_items album_name_options[] = { 2391 static const struct opt_items album_name_options[] = {
2250 { STR(LANG_HIDE_ALBUM_TITLE) }, 2392 { STR(LANG_HIDE_ALBUM_TITLE_NEW) },
2251 { STR(LANG_SHOW_AT_THE_BOTTOM) }, 2393 { STR(LANG_SHOW_AT_THE_BOTTOM_NEW) },
2252 { STR(LANG_SHOW_AT_THE_TOP) } 2394 { STR(LANG_SHOW_AT_THE_TOP_NEW) },
2395 { STR(LANG_SHOW_ALL_AT_THE_TOP) },
2396 { STR(LANG_SHOW_ALL_AT_THE_BOTTOM) },
2253 }; 2397 };
2254 static const struct opt_items wps_options[] = { 2398 static const struct opt_items wps_options[] = {
2255 { STR(LANG_OFF) }, 2399 { STR(LANG_OFF) },
@@ -2300,7 +2444,7 @@ static int settings_menu(void)
2300 break; 2444 break;
2301 case 5: 2445 case 5:
2302 rb->set_option(rb->str(LANG_SHOW_ALBUM_TITLE), &show_album_name, 2446 rb->set_option(rb->str(LANG_SHOW_ALBUM_TITLE), &show_album_name,
2303 INT, album_name_options, 3, NULL); 2447 INT, album_name_options, 5, NULL);
2304 reset_track_list(); 2448 reset_track_list();
2305 recalc_offsets(); 2449 recalc_offsets();
2306 reset_slides(); 2450 reset_slides();
@@ -2319,9 +2463,16 @@ static int settings_menu(void)
2319 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART)); 2463 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
2320 break; 2464 break;
2321 case 8: 2465 case 8:
2322 rb->set_option(rb->str(LANG_WPS_INTEGRATION), &auto_wps, INT, wps_options, 3, NULL); 2466 cache_version = CACHE_UPDATE;
2467 rb->remove(EMPTY_SLIDE);
2468 configfile_save(CONFIG_FILE, config,
2469 CONFIG_NUM_ITEMS, CONFIG_VERSION);
2470 rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
2323 break; 2471 break;
2324 case 9: 2472 case 9:
2473 rb->set_option(rb->str(LANG_WPS_INTEGRATION), &auto_wps, INT, wps_options, 3, NULL);
2474 break;
2475 case 10:
2325 rb->set_option(rb->str(LANG_BACKLIGHT), &backlight_mode, INT, backlight_options, 2, NULL); 2476 rb->set_option(rb->str(LANG_BACKLIGHT), &backlight_mode, INT, backlight_options, 2, NULL);
2326 break; 2477 break;
2327 2478
@@ -2473,11 +2624,20 @@ static void track_list_yh(int char_height)
2473 break; 2624 break;
2474 case ALBUM_NAME_BOTTOM: 2625 case ALBUM_NAME_BOTTOM:
2475 track_list_y = (show_fps ? char_height : 0); 2626 track_list_y = (show_fps ? char_height : 0);
2476 track_list_h = LCD_HEIGHT - track_list_y - char_height * 2; 2627 track_list_h = LCD_HEIGHT - track_list_y - (char_height * 3);
2628 break;
2629 case ALBUM_AND_ARTIST_TOP:
2630 track_list_y = char_height * 3;
2631 track_list_h = LCD_HEIGHT - track_list_y -
2632 (show_fps ? char_height : 0);
2633 break;
2634 case ALBUM_AND_ARTIST_BOTTOM:
2635 track_list_y = (show_fps ? char_height : 0);
2636 track_list_h = LCD_HEIGHT - track_list_y - (char_height * 3);
2477 break; 2637 break;
2478 case ALBUM_NAME_TOP: 2638 case ALBUM_NAME_TOP:
2479 default: 2639 default:
2480 track_list_y = char_height * 2; 2640 track_list_y = char_height * 3;
2481 track_list_h = LCD_HEIGHT - track_list_y - 2641 track_list_h = LCD_HEIGHT - track_list_y -
2482 (show_fps ? char_height : 0); 2642 (show_fps ? char_height : 0);
2483 break; 2643 break;
@@ -2620,9 +2780,10 @@ static void draw_album_text(void)
2620 2780
2621 int albumtxt_index; 2781 int albumtxt_index;
2622 int char_height; 2782 int char_height;
2623 int albumtxt_x, albumtxt_y; 2783 int albumtxt_x, albumtxt_y, artisttxt_x;
2624 2784
2625 char *albumtxt; 2785 char *albumtxt;
2786 char *artisttxt;
2626 int c; 2787 int c;
2627 /* Draw album text */ 2788 /* Draw album text */
2628 if ( pf_state == pf_scrolling ) { 2789 if ( pf_state == pf_scrolling ) {
@@ -2650,13 +2811,33 @@ static void draw_album_text(void)
2650 } 2811 }
2651 2812
2652 char_height = rb->screens[SCREEN_MAIN]->getcharheight(); 2813 char_height = rb->screens[SCREEN_MAIN]->getcharheight();
2653 if (show_album_name == ALBUM_NAME_TOP) 2814 switch(show_album_name){
2654 albumtxt_y = char_height / 2; 2815 case ALBUM_AND_ARTIST_TOP:
2655 else 2816 albumtxt_y = 0;
2656 albumtxt_y = LCD_HEIGHT - char_height - char_height/2; 2817 break;
2818 case ALBUM_NAME_BOTTOM:
2819 albumtxt_y = (LCD_HEIGHT - char_height - char_height/2 - 10);
2820 break;
2821 case ALBUM_AND_ARTIST_BOTTOM:
2822 albumtxt_y = (LCD_HEIGHT - char_height - char_height/2 - 20);
2823 break;
2824 case ALBUM_NAME_TOP:
2825 default:
2826 albumtxt_y = char_height / 2;
2827 break;
2828 }
2657 2829
2658 albumtxt_x = get_scroll_line_offset(PF_SCROLL_ALBUM); 2830 albumtxt_x = get_scroll_line_offset(PF_SCROLL_ALBUM);
2659 mylcd_putsxy(albumtxt_x, albumtxt_y, albumtxt); 2831 mylcd_putsxy(albumtxt_x, albumtxt_y, albumtxt);
2832 set_scroll_line(artisttxt, PF_SCROLL_ARTIST);
2833 if ((show_album_name == ALBUM_AND_ARTIST_TOP)
2834 || (show_album_name == ALBUM_AND_ARTIST_BOTTOM)){
2835
2836 artisttxt = get_album_artist(albumtxt_index);
2837 set_scroll_line(artisttxt, PF_SCROLL_ARTIST);
2838 artisttxt_x = get_scroll_line_offset(PF_SCROLL_ARTIST);
2839 mylcd_putsxy(artisttxt_x, albumtxt_y+20, artisttxt);
2840 }
2660} 2841}
2661 2842
2662/** 2843/**
@@ -2699,7 +2880,19 @@ static int pictureflow_main(void)
2699 init_reflect_table(); 2880 init_reflect_table();
2700 2881
2701 ALIGN_BUFFER(buf, buf_size, 4); 2882 ALIGN_BUFFER(buf, buf_size, 4);
2702 ret = create_album_index(); 2883
2884 /*Scan will trigger when no file is found or the option was activated*/
2885 if ((cache_version != CACHE_VERSION)||(load_album_index() < 0)){
2886 rb->splash(HZ/2,"Creating album index, please wait");
2887 ret = create_album_index();
2888 if (ret == 0){
2889 save_album_index();
2890 }
2891 }
2892 else{
2893 ret = 0;
2894 }
2895
2703 if (ret == ERROR_BUFFER_FULL) { 2896 if (ret == ERROR_BUFFER_FULL) {
2704 error_wait("Not enough memory for album names"); 2897 error_wait("Not enough memory for album names");
2705 return PLUGIN_ERROR; 2898 return PLUGIN_ERROR;
diff --git a/docs/CREDITS b/docs/CREDITS
index d51beff8ab..bae0254709 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -693,6 +693,7 @@ James D. Smith
693Howard Richardson 693Howard Richardson
694Aurélien Coudurier 694Aurélien Coudurier
695Sylvain Saubier 695Sylvain Saubier
696Adrián Tinoco
696 697
697The libmad team 698The libmad team
698The wavpack team 699The wavpack team