summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/features.txt7
-rw-r--r--apps/lang/english-us.lang369
-rw-r--r--apps/lang/english.lang20
-rw-r--r--apps/lang/polski.lang199
-rw-r--r--apps/lang/slovak.lang319
-rw-r--r--apps/lang/srpski.lang1000
-rw-r--r--apps/main.c19
-rw-r--r--apps/menus/main_menu.c2
-rw-r--r--apps/menus/settings_menu.c15
-rw-r--r--apps/onplay.c14
-rw-r--r--apps/onplay.h8
-rw-r--r--apps/playlist_viewer.c300
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/doom/d_deh.c3
-rw-r--r--apps/plugins/lastfm_scrobbler.c350
-rw-r--r--apps/plugins/pictureflow/pictureflow.c47
-rw-r--r--apps/plugins/properties.c3
-rw-r--r--apps/plugins/sliding_puzzle.c4
-rw-r--r--apps/plugins/test_usb.c136
-rw-r--r--apps/plugins/xworld/engine.c2
-rw-r--r--apps/settings.h6
-rw-r--r--apps/settings_list.c33
-rw-r--r--bootloader/x1000/recovery.c2
-rw-r--r--bootloader/x1000/utils.c168
-rw-r--r--bootloader/x1000/x1000bootloader.h2
-rw-r--r--docs/CREDITS1
-rw-r--r--firmware/export/backtrace.h3
-rw-r--r--firmware/export/config.h3
-rw-r--r--firmware/export/config/ipod6g.h8
-rw-r--r--firmware/export/system.h3
-rw-r--r--firmware/export/usb.h1
-rw-r--r--firmware/include/rbendian.h237
-rw-r--r--firmware/panic.c10
-rw-r--r--firmware/target/mips/ingenic_jz47xx/crt0.S2
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4760.c251
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.c17
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.h4
-rw-r--r--firmware/target/mips/ingenic_x1000/crt0.S2
-rw-r--r--firmware/target/mips/ingenic_x1000/installer-x1000.c4
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c158
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.h101
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-nand-x1000.c4
-rw-r--r--firmware/usb.c25
-rw-r--r--lib/mipsunwinder/SOURCES2
-rw-r--r--lib/mipsunwinder/backtrace-mips32.c236
-rw-r--r--lib/mipsunwinder/backtrace-mipsunwinder.h65
-rw-r--r--lib/mipsunwinder/init_context_32.S12
-rw-r--r--lib/mipsunwinder/mipsunwinder.make23
-rw-r--r--lib/rbcodec/codecs/libgme/blip_buffer.c2
-rw-r--r--lib/rbcodec/codecs/libopus/silk/NLSF2A.c2
-rw-r--r--manual/appendix/config_file_options.tex11
-rw-r--r--manual/configure_rockbox/startup_shutdown_options.tex39
-rwxr-xr-xmanual/configure_rockbox/system_options.tex11
-rw-r--r--manual/plugins/pictureflow.tex7
-rw-r--r--manual/rockbox_interface/hotkeys.tex11
-rw-r--r--manual/rockbox_interface/main.tex15
-rw-r--r--tools/root.make6
-rw-r--r--uisimulator/common/sim_tasks.c4
-rw-r--r--utils/rbutilqt/CMakeLists.txt66
-rw-r--r--utils/rbutilqt/base/ziputil.cpp6
-rw-r--r--utils/rbutilqt/base/ziputil.h6
-rw-r--r--utils/rbutilqt/lang/rbutil_cs.ts205
63 files changed, 3426 insertions, 1167 deletions
diff --git a/apps/features.txt b/apps/features.txt
index 45e06e5e64..2262f7502e 100644
--- a/apps/features.txt
+++ b/apps/features.txt
@@ -289,3 +289,10 @@ multi_boot
#if defined(HIBY_LINUX)
hibylinux
#endif
+
+#if defined(BUTTON_REC) || \
+ (CONFIG_KEYPAD == GIGABEAT_PAD) || \
+ (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ (CONFIG_KEYPAD == IRIVER_H10_PAD)
+clear_settings_on_hold
+#endif
diff --git a/apps/lang/english-us.lang b/apps/lang/english-us.lang
index cc35e2b4a0..bf5e9e93ce 100644
--- a/apps/lang/english-us.lang
+++ b/apps/lang/english-us.lang
@@ -254,8 +254,7 @@
<dest>
*: "PLAY = Yes"
cowond2*: "MENU, or top-right = Yes"
- creativezen*: "SELECT = Yes"
- gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes"
+ creativezen*,gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes"
iriverh100,iriverh120,iriverh300: "NAVI = Yes"
mrobe500: "PLAY, POWER, or top-right = Yes"
vibe500: "OK = Yes"
@@ -1695,12 +1694,18 @@
*: "Random"
</voice>
</phrase>
+### The 'desc' field for 'LANG_AUDIOSCROBBLER' differs from the english!
+### the previously used desc is commented below:
+### desc: "Last.fm Log" in the playback menu
+### The <source> section for 'LANG_AUDIOSCROBBLER:*' differs from the english!
+### the previously used one is commented below:
+### Last.fm Logger
<phrase>
id: LANG_AUDIOSCROBBLER
- desc: "Last.fm Log" in the playback menu
+ desc: "Last.fm Logger" in Plugin/apps/scrobbler
user: core
<source>
- *: "Last.fm Log"
+ *: "Last.fm Logger"
</source>
<dest>
*: "Last.fm Log"
@@ -4108,31 +4113,16 @@
</phrase>
<phrase>
id: LANG_ALARM_MOD_KEYS
- desc: Shown key functions in alarm menu (for the RTC alarm mod).
+ desc: deprecated
user: core
<source>
- *: none
- alarm: "PLAY=Set OFF=Cancel"
- gigabeats: "SELECT=Set POWER=Cancel"
- ipod*: "SELECT=Set MENU=Cancel"
- iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel"
- mpiohd300: "ENTER=Set MENU=Cancel"
- sansafuzeplus: "SELECT=Set BACK=Cancel"
- vibe500: "OK=Set C=Cancel"
+ *: ""
</source>
<dest>
- *: none
- alarm: "PLAY=Set OFF=Cancel"
- gigabeats: "SELECT=Set POWER=Cancel"
- ipod*: "SELECT=Set MENU=Cancel"
- iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel"
- mpiohd300: "ENTER=Set MENU=Cancel"
- sansafuzeplus: "SELECT=Set BACK=Cancel"
- vibe500: "OK=Set C=Cancel"
+ *: ""
</dest>
<voice>
- *: none
- alarm,ipod*: ""
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14307,16 +14297,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_TITLE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Title]"
+ *: ""
</source>
<dest>
- *: "[Title]"
+ *: ""
</dest>
<voice>
- *: "Title"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14433,16 +14423,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_DURATION
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Duration]"
+ *: ""
</source>
<dest>
- *: "[Duration]"
+ *: ""
</dest>
<voice>
- *: "Duration"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14489,16 +14479,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Artist]"
+ *: ""
</source>
<dest>
- *: "[Artist]"
+ *: ""
</dest>
<voice>
- *: "Artist"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14545,16 +14535,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album]"
+ *: ""
</source>
<dest>
- *: "[Album]"
+ *: ""
</dest>
<voice>
- *: "Album"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15594,16 +15584,16 @@
</phrase>
<phrase>
id: LANG_CLEAR_LIST_AND_PLAY_NEXT
- desc: in onplay menu. Replace current playlist with selected tracks
+ desc: deprecated
user: core
<source>
- *: "Clear List & Play Next"
+ *: ""
</source>
<dest>
- *: "Clear List & Play Next"
+ *: ""
</dest>
<voice>
- *: "Clear List & Play Next"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15664,16 +15654,16 @@
</phrase>
<phrase>
id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED
- desc: in onplay menu. Replace current playlist with selected tracks in random order.
+ desc: deprecated
user: core
<source>
- *: "Clear List & Play Shuffled"
+ *: ""
</source>
<dest>
- *: "Clear List & Play Shuffled"
+ *: ""
</dest>
<voice>
- *: "Clear List & Play Shuffled"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15887,128 +15877,128 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUMARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album Artist]"
+ *: ""
</source>
<dest>
- *: "[Album Artist]"
+ *: ""
</dest>
<voice>
- *: "Album Artist"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_GENRE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Genre]"
+ *: ""
</source>
<dest>
- *: "[Genre]"
+ *: ""
</dest>
<voice>
- *: "Genre"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMMENT
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Comment]"
+ *: ""
</source>
<dest>
- *: "[Comment]"
+ *: ""
</dest>
<voice>
- *: "Comment"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMPOSER
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Composer]"
+ *: ""
</source>
<dest>
- *: "[Composer]"
+ *: ""
</dest>
<voice>
- *: "Composer"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_YEAR
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Year]"
+ *: ""
</source>
<dest>
- *: "[Year]"
+ *: ""
</dest>
<voice>
- *: "Year"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_TRACKNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Tracknum]"
+ *: ""
</source>
<dest>
- *: "[Tracknum]"
+ *: ""
</dest>
<voice>
- *: "Track number"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_DISCNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Discnum]"
+ *: ""
</source>
<dest>
- *: "[Discnum]"
+ *: ""
</dest>
<voice>
- *: "Disc number"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_FREQUENCY
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Frequency]"
+ *: ""
</source>
<dest>
- *: "[Frequency]"
+ *: ""
</dest>
<voice>
- *: "Frequency"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_BITRATE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Bitrate]"
+ *: ""
</source>
<dest>
- *: "[Bitrate]"
+ *: ""
</dest>
<voice>
- *: "Bit rate"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -16109,3 +16099,216 @@
*: "Descending"
</voice>
</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_ALBUM_ART
+ desc: in Settings
+ user: core
+ <source>
+ *: "Album Art"
+ </source>
+ <dest>
+ *: "Album Art"
+ </dest>
+ <voice>
+ *: "Album Art"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_PREFER_EMBEDDED
+ desc: in Settings
+ user: core
+ <source>
+ *: "Prefer Embedded"
+ </source>
+ <dest>
+ *: "Prefer Embedded"
+ </dest>
+ <voice>
+ *: "Prefer Embedded"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_PREFER_IMAGE_FILE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Prefer Image File"
+ </source>
+ <dest>
+ *: "Prefer Image File"
+ </dest>
+ <voice>
+ *: "Prefer Image File"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_FM_SYNC_RDS_TIME
+ desc: in radio screen and Settings
+ user: core
+ <source>
+ *: none
+ rds: "Sync RDS Time"
+ </source>
+ <dest>
+ *: none
+ rds: "Sync RDS Time"
+ </dest>
+ <voice>
+ *: none
+ rds: "Sync RDS Time"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_SORT_ALBUMS_BY
+ desc: in Settings
+ user: core
+ <source>
+ *: "Sort albums by"
+ </source>
+ <dest>
+ *: "Sort albums by"
+ </dest>
+ <voice>
+ *: "Sort albums by"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_ARTIST_PLUS_NAME
+ desc: in Settings
+ user: core
+ <source>
+ *: "Artist + Name"
+ </source>
+ <dest>
+ *: "Artist + Name"
+ </dest>
+ <voice>
+ *: "Artist And Name"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_ARTIST_PLUS_YEAR
+ desc: in Settings
+ user: core
+ <source>
+ *: "Artist + Year"
+ </source>
+ <dest>
+ *: "Artist + Year"
+ </dest>
+ <voice>
+ *: "Artist And Year"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_YEAR_SORT_ORDER
+ desc: in Settings
+ user: core
+ <source>
+ *: "Year sort order"
+ </source>
+ <dest>
+ *: "Year sort order"
+ </dest>
+ <voice>
+ *: "Year sort order"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_SHOW_YEAR_IN_ALBUM_TITLE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Show year in album title"
+ </source>
+ <dest>
+ *: "Show year in album title"
+ </dest>
+ <voice>
+ *: "Show year in album title"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_WAIT_FOR_CACHE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Cache needs to finish updating first!"
+ </source>
+ <dest>
+ *: "Cache needs to finish updating first!"
+ </dest>
+ <voice>
+ *: "Cache needs to finish updating first!"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_TRACK_INFO
+ desc: Track Info Title
+ user: core
+ <source>
+ *: "Track Info"
+ </source>
+ <dest>
+ *: "Track Info"
+ </dest>
+ <voice>
+ *: "Track Info"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_PLAY
+ desc: play selected file/directory, in playlist context menu
+ user: core
+ <source>
+ *: "Play"
+ </source>
+ <dest>
+ *: "Play"
+ </dest>
+ <voice>
+ *: "Play"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_PLAY_SHUFFLED
+ desc: play selected files in shuffled order, in playlist context menu
+ user: core
+ <source>
+ *: "Play Shuffled"
+ </source>
+ <dest>
+ *: "Play Shuffled"
+ </dest>
+ <voice>
+ *: "Play Shuffled"
+ </voice>
+</phrase>
+### This phrase is missing entirely, copying from english!
+<phrase>
+ id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE
+ desc: used in the playlist settings menu
+ user: core
+ <source>
+ *: "Keep Current Track When Replacing Playlist"
+ </source>
+ <dest>
+ *: "Keep Current Track When Replacing Playlist"
+ </dest>
+ <voice>
+ *: "Keep Current Track When Replacing Playlist"
+ </voice>
+</phrase>
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 3b505bb9a2..e8d646b258 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -16368,3 +16368,23 @@
*: "Keep Current Track When Replacing Playlist"
</voice>
</phrase>
+<phrase>
+ id: LANG_CLEAR_SETTINGS_ON_HOLD
+ desc: in the system sub menu
+ user: core
+ <source>
+ *: none
+ ipodcolor,ipodnano1g,ipodvideo,ipod4g,ipodmini1g,ipodmini2g: "Clear settings when hold switch is on during startup"
+ clear_settings_on_hold, iriverh10: "Clear settings when reset button is held during startup"
+ </source>
+ <dest>
+ *: none
+ ipodcolor,ipodnano1g,ipodvideo,ipod4g,ipodmini1g,ipodmini2g: "Clear settings when hold switch is on during startup"
+ clear_settings_on_hold, iriverh10: "Clear settings when reset button is held during startup"
+ </dest>
+ <voice>
+ *: none
+ ipodcolor,ipodnano1g,ipodvideo,ipod4g,ipodmini1g,ipodmini2g: "Clear settings when hold switch is on during startup"
+ clear_settings_on_hold, iriverh10: "Clear settings when reset button is held during startup"
+ </voice>
+</phrase>
diff --git a/apps/lang/polski.lang b/apps/lang/polski.lang
index 91998e8eb1..4cef4ba59a 100644
--- a/apps/lang/polski.lang
+++ b/apps/lang/polski.lang
@@ -4102,31 +4102,16 @@
</phrase>
<phrase>
id: LANG_ALARM_MOD_KEYS
- desc: Shown key functions in alarm menu (for the RTC alarm mod).
+ desc: deprecated
user: core
<source>
- *: none
- alarm: "PLAY=Set OFF=Cancel"
- gigabeats: "SELECT=Set POWER=Cancel"
- ipod*: "SELECT=Set MENU=Cancel"
- iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel"
- mpiohd300: "ENTER=Set MENU=Cancel"
- sansafuzeplus: "SELECT=Set BACK=Cancel"
- vibe500: "OK=Set C=Cancel"
+ *: ""
</source>
<dest>
- *: none
- alarm: "PLAY=Ustaw OFF=Anuluj"
- gigabeats: "WYBIERZ=Ustaw POWER=Anuluj"
- ipod*: "WYBIERZ=Ustaw MENU=Anuluj"
- iriverh10,iriverh10_5gb: "WYBIERZ=Ustaw COFNIJ=Anuluj"
- mpiohd300: "ENTER=Ustaw MENU=Anuluj"
- sansafuzeplus: "SELECT=Ustaw BACK=Anuluj"
- vibe500: "OK=Ustaw C=Anuluj"
+ *: ""
</dest>
<voice>
- *: none
- alarm,ipod*: ""
+ *: ""
</voice>
</phrase>
<phrase>
@@ -13182,16 +13167,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album]"
+ *: ""
</source>
<dest>
- *: "[Album]"
+ *: ""
</dest>
<voice>
- *: "Album"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -13654,16 +13639,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_DURATION
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Duration]"
+ *: ""
</source>
<dest>
- *: "[Czas trwania]"
+ *: ""
</dest>
<voice>
- *: "Czas trwania"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14224,16 +14209,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Artist]"
+ *: ""
</source>
<dest>
- *: "[Artysta]"
+ *: ""
</dest>
<voice>
- *: "Artysta"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14900,16 +14885,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_TITLE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Title]"
+ *: ""
</source>
<dest>
- *: "[Tytuł]"
+ *: ""
</dest>
<voice>
- *: "Tytuł"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15528,16 +15513,16 @@
</phrase>
<phrase>
id: LANG_CLEAR_LIST_AND_PLAY_NEXT
- desc: in onplay menu. Replace current playlist with selected tracks
+ desc: deprecated
user: core
<source>
- *: "Clear List & Play Next"
+ *: ""
</source>
<dest>
- *: "Wyczyść listę i odtwarzaj następne"
+ *: ""
</dest>
<voice>
- *: "Wyczyść listę i odtwarzaj następne"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15598,16 +15583,16 @@
</phrase>
<phrase>
id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED
- desc: in onplay menu. Replace current playlist with selected tracks in random order.
+ desc: deprecated
user: core
<source>
- *: "Clear List & Play Shuffled"
+ *: ""
</source>
<dest>
- *: "Wyczyść listę i odtwarzaj losowe"
+ *: ""
</dest>
<voice>
- *: "Wyczyść listę i odtwarzaj losowe"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15881,128 +15866,128 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUMARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album Artist]"
+ *: ""
</source>
<dest>
- *: "[Wykonawca albumu]"
+ *: ""
</dest>
<voice>
- *: "Wykonawca albumu"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_GENRE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Genre]"
+ *: ""
</source>
<dest>
- *: "[Gatunek]"
+ *: ""
</dest>
<voice>
- *: "Gatunek"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMMENT
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Comment]"
+ *: ""
</source>
<dest>
- *: "[Komentarz]"
+ *: ""
</dest>
<voice>
- *: "Komentarz"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMPOSER
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Composer]"
+ *: ""
</source>
<dest>
- *: "[Kompozytor]"
+ *: ""
</dest>
<voice>
- *: "Kompozytor"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_YEAR
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Year]"
+ *: ""
</source>
<dest>
- *: "[Rok]"
+ *: ""
</dest>
<voice>
- *: "Rok"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_TRACKNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Tracknum]"
+ *: ""
</source>
<dest>
- *: "[Nr utworu]"
+ *: ""
</dest>
<voice>
- *: "Numer utworu"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_DISCNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Discnum]"
+ *: ""
</source>
<dest>
- *: "[Nr płyty]"
+ *: ""
</dest>
<voice>
- *: "Numer płyty"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_FREQUENCY
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Frequency]"
+ *: ""
</source>
<dest>
- *: "[Częstotliwość]"
+ *: ""
</dest>
<voice>
- *: "Częstotliwość"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_BITRATE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Bitrate]"
+ *: ""
</source>
<dest>
- *: "[Prędkość transmisji]"
+ *: ""
</dest>
<voice>
- *: "Prędkość transmisji"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -16260,3 +16245,59 @@
*: "Pamięć podręczna musi najpierw zakończyć aktualizację!"
</voice>
</phrase>
+<phrase>
+ id: LANG_TRACK_INFO
+ desc: Track Info Title
+ user: core
+ <source>
+ *: "Track Info"
+ </source>
+ <dest>
+ *: "Informacje o utworze"
+ </dest>
+ <voice>
+ *: "Informacje o utworze"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PLAY
+ desc: play selected file/directory, in playlist context menu
+ user: core
+ <source>
+ *: "Play"
+ </source>
+ <dest>
+ *: "Odtwarzaj"
+ </dest>
+ <voice>
+ *: "Odtwarzaj"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PLAY_SHUFFLED
+ desc: play selected files in shuffled order, in playlist context menu
+ user: core
+ <source>
+ *: "Play Shuffled"
+ </source>
+ <dest>
+ *: "Odtwarzaj losowe"
+ </dest>
+ <voice>
+ *: "Odtwarzaj losowe"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE
+ desc: used in the playlist settings menu
+ user: core
+ <source>
+ *: "Keep Current Track When Replacing Playlist"
+ </source>
+ <dest>
+ *: "Zachowaj bieżący utwór podczas zastępowania listy odtwarzania"
+ </dest>
+ <voice>
+ *: "Zachowaj bieżący utwór podczas zastępowania listy odtwarzania"
+ </voice>
+</phrase>
diff --git a/apps/lang/slovak.lang b/apps/lang/slovak.lang
index f68b7e12f8..2efe3b7b35 100644
--- a/apps/lang/slovak.lang
+++ b/apps/lang/slovak.lang
@@ -1683,10 +1683,10 @@
</phrase>
<phrase>
id: LANG_AUDIOSCROBBLER
- desc: "Last.fm Log" in the playback menu
+ desc: "Last.fm Logger" in Plugin/apps/scrobbler
user: core
<source>
- *: "Last.fm Log"
+ *: "Last.fm Logger"
</source>
<dest>
*: "Denník Last.fm"
@@ -3576,7 +3576,7 @@
</dest>
<voice>
*: none
- gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansae200*,gogearsa9200,samsungyh*,iriverh100,iriverh120,iriverh300,rtc: ""
+ gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,samsungyh*,sansac200*,sansae200*: ""
</voice>
</phrase>
<phrase>
@@ -3613,7 +3613,7 @@
</dest>
<voice>
*: none
- gogearsa9200,iaudiom5,iaudiox5,ipod*,sansac200*,iriverh10,iriverh10_5gb,sansae200*,iriverh100,iriverh120,iriverh300,mrobe100,rtc,samsungyh*: ""
+ gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,samsungyh*,sansac200*,sansae200*: ""
</voice>
</phrase>
<phrase>
@@ -4094,31 +4094,16 @@
</phrase>
<phrase>
id: LANG_ALARM_MOD_KEYS
- desc: Shown key functions in alarm menu (for the RTC alarm mod).
+ desc: deprecated
user: core
<source>
- *: none
- alarm: "PLAY=Set OFF=Cancel"
- gigabeats: "SELECT=Set POWER=Cancel"
- ipod*: "SELECT=Set MENU=Cancel"
- iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel"
- mpiohd300: "ENTER=Set MENU=Cancel"
- sansafuzeplus: "SELECT=Set BACK=Cancel"
- vibe500: "OK=Set C=Cancel"
+ *: ""
</source>
<dest>
- *: none
- alarm: "PLAY=Nastaviť OFF=Zrušiť"
- gigabeats: "SELECT=Nastaviť POWER=Zrušiť"
- ipod*: "SELECT=Nastaviť MENU=Zrušiť"
- iriverh10,iriverh10_5gb: "SELECT=Nastaviť PREV=Zrušiť"
- mpiohd300: "ENTER=Nastaviť MENU=Zrušiť"
- sansafuzeplus: "SELECT=Nastaviť BACK=Zrušiť"
- vibe500: "OK=Nastaviť C=Zrušiť"
+ *: ""
</dest>
<voice>
- *: none
- alarm,ipod*: ""
+ *: ""
</voice>
</phrase>
<phrase>
@@ -7672,10 +7657,10 @@
*: "."
</source>
<dest>
- *: "."
+ *: ","
</dest>
<voice>
- *: "bodka"
+ *: "čiarka"
</voice>
</phrase>
<phrase>
@@ -12664,16 +12649,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_TITLE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Title]"
+ *: ""
</source>
<dest>
- *: "[Názov]"
+ *: ""
</dest>
<voice>
- *: "Názov"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -13419,16 +13404,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_DURATION
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Duration]"
+ *: ""
</source>
<dest>
- *: "[Trvanie]"
+ *: ""
</dest>
<voice>
- *: "Trvanie"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14267,16 +14252,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Artist]"
+ *: ""
</source>
<dest>
- *: "[Interpret]"
+ *: ""
</dest>
<voice>
- *: "Interpret"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -14427,16 +14412,16 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album]"
+ *: ""
</source>
<dest>
- *: "[Album]"
+ *: ""
</dest>
<voice>
- *: "Album"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15313,10 +15298,10 @@
*: "Single Mode"
</source>
<dest>
- *: "Single Mode"
+ *: "Single režim"
</dest>
<voice>
- *: "Single Mode"
+ *: "Single režim"
</voice>
</phrase>
<phrase>
@@ -15588,10 +15573,10 @@
*: "Open Plugin"
</source>
<dest>
- *: "Open Plugin"
+ *: "Otvoriť plugin"
</dest>
<voice>
- *: "Open Plugin"
+ *: "Otvoriť plugin"
</voice>
</phrase>
<phrase>
@@ -15750,16 +15735,16 @@
</phrase>
<phrase>
id: LANG_CLEAR_LIST_AND_PLAY_NEXT
- desc: in onplay menu. Replace current playlist with selected tracks
+ desc: deprecated
user: core
<source>
- *: "Clear List & Play Next"
+ *: ""
</source>
<dest>
- *: "Vymazať zoznam a prehrať ako ďalšie"
+ *: ""
</dest>
<voice>
- *: "Vymazať zoznam a prehrať ako ďalšie"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15770,10 +15755,10 @@
*: "Queue..."
</source>
<dest>
- *: "Queue..."
+ *: "Poradovník..."
</dest>
<voice>
- *: "Queue..."
+ *: "Poradovník..."
</voice>
</phrase>
<phrase>
@@ -15784,10 +15769,10 @@
*: "Show Queue Options"
</source>
<dest>
- *: "Show Queue Options"
+ *: "Ukázať voľby poradovníka"
</dest>
<voice>
- *: "Show Queue Options"
+ *: "Ukázať voľby poradovníka"
</voice>
</phrase>
<phrase>
@@ -15798,10 +15783,10 @@
*: "Show Shuffled Adding Options"
</source>
<dest>
- *: "Show Shuffled Adding Options"
+ *: "Ukázať voľby pridávania zamiešane"
</dest>
<voice>
- *: "Show Shuffled Adding Options"
+ *: "Ukázať voľby pridávania zamiešane"
</voice>
</phrase>
<phrase>
@@ -15820,16 +15805,16 @@
</phrase>
<phrase>
id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED
- desc: in onplay menu. Replace current playlist with selected tracks in random order.
+ desc: deprecated
user: core
<source>
- *: "Clear List & Play Shuffled"
+ *: ""
</source>
<dest>
- *: "Vymazať zoznam a prehrať zamiešané"
+ *: ""
</dest>
<voice>
- *: "Vymazať zoznam a prehrať zamiešané"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15890,128 +15875,128 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUMARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album Artist]"
+ *: ""
</source>
<dest>
- *: "[Interpret albumu]"
+ *: ""
</dest>
<voice>
- *: "Interpret albumu"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_GENRE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Genre]"
+ *: ""
</source>
<dest>
- *: "[Žáner]"
+ *: ""
</dest>
<voice>
- *: "Žáner"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMMENT
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Comment]"
+ *: ""
</source>
<dest>
- *: "[Komentár]"
+ *: ""
</dest>
<voice>
- *: "Komentár"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMPOSER
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Composer]"
+ *: ""
</source>
<dest>
- *: "[Skladateľ]"
+ *: ""
</dest>
<voice>
- *: "Skladateľ"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_YEAR
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Year]"
+ *: ""
</source>
<dest>
- *: "[Rok]"
+ *: ""
</dest>
<voice>
- *: "Rok"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_TRACKNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Tracknum]"
+ *: ""
</source>
<dest>
- *: "[Čstopy]"
+ *: ""
</dest>
<voice>
- *: "Č. stopy"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_DISCNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Discnum]"
+ *: ""
</source>
<dest>
- *: "[Čdisku]"
+ *: ""
</dest>
<voice>
- *: "Č. disku"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_FREQUENCY
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Frequency]"
+ *: ""
</source>
<dest>
- *: "[Frekvencia]"
+ *: ""
</dest>
<voice>
- *: "Frekvencia"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_BITRATE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Bitrate]"
+ *: ""
</source>
<dest>
- *: "[Početbitov]"
+ *: ""
</dest>
<voice>
- *: "Počet bitov"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -16050,10 +16035,10 @@
*: "List Wraparound"
</source>
<dest>
- *: "List Wraparound"
+ *: "Otáčať zoznam"
</dest>
<voice>
- *: "List Wraparound"
+ *: "Otáčať zoznam"
</voice>
</phrase>
<phrase>
@@ -16171,3 +16156,143 @@
rds: "Synchronizovať s časom RDS"
</voice>
</phrase>
+<phrase>
+ id: LANG_SORT_ALBUMS_BY
+ desc: in Settings
+ user: core
+ <source>
+ *: "Sort albums by"
+ </source>
+ <dest>
+ *: "Triediť albumy podľa"
+ </dest>
+ <voice>
+ *: "Triediť albumy podľa"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ARTIST_PLUS_NAME
+ desc: in Settings
+ user: core
+ <source>
+ *: "Artist + Name"
+ </source>
+ <dest>
+ *: "Interpret + názov"
+ </dest>
+ <voice>
+ *: "Interpret a názov"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ARTIST_PLUS_YEAR
+ desc: in Settings
+ user: core
+ <source>
+ *: "Artist + Year"
+ </source>
+ <dest>
+ *: "Interpret + rok"
+ </dest>
+ <voice>
+ *: "Interpret a rok"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_YEAR_SORT_ORDER
+ desc: in Settings
+ user: core
+ <source>
+ *: "Year sort order"
+ </source>
+ <dest>
+ *: "Triediť podľa roku"
+ </dest>
+ <voice>
+ *: "Triediť podľa roku"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SHOW_YEAR_IN_ALBUM_TITLE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Show year in album title"
+ </source>
+ <dest>
+ *: "Ukázať rok v názve albumu"
+ </dest>
+ <voice>
+ *: "Ukázať rok v názve albumu"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_WAIT_FOR_CACHE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Cache needs to finish updating first!"
+ </source>
+ <dest>
+ *: "Najprv sa musí dokončiť aktualizácia cache!"
+ </dest>
+ <voice>
+ *: "Najprv sa musí dokončiť aktualizácia cache!"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_TRACK_INFO
+ desc: Track Info Title
+ user: core
+ <source>
+ *: "Track Info"
+ </source>
+ <dest>
+ *: "Info o stope"
+ </dest>
+ <voice>
+ *: "Info o stope"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PLAY
+ desc: play selected file/directory, in playlist context menu
+ user: core
+ <source>
+ *: "Play"
+ </source>
+ <dest>
+ *: "Prehrať"
+ </dest>
+ <voice>
+ *: "Prehrať"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PLAY_SHUFFLED
+ desc: play selected files in shuffled order, in playlist context menu
+ user: core
+ <source>
+ *: "Play Shuffled"
+ </source>
+ <dest>
+ *: "Prehrať zamiešané"
+ </dest>
+ <voice>
+ *: "Prehrať zamiešané"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE
+ desc: used in the playlist settings menu
+ user: core
+ <source>
+ *: "Keep Current Track When Replacing Playlist"
+ </source>
+ <dest>
+ *: "Ponechať aktuálnu stopu pri nahradení playlistu"
+ </dest>
+ <voice>
+ *: "Ponechať aktuálnu stopu pri nahradení playlistu"
+ </voice>
+</phrase>
diff --git a/apps/lang/srpski.lang b/apps/lang/srpski.lang
index cdd7f51321..8e64e3f938 100644
--- a/apps/lang/srpski.lang
+++ b/apps/lang/srpski.lang
@@ -247,8 +247,7 @@
<source>
*: "PLAY = Yes"
cowond2*: "MENU, or top-right = Yes"
- creativezen*: "SELECT = Yes"
- gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes"
+ creativezen*,gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes"
iriverh100,iriverh120,iriverh300: "NAVI = Yes"
mrobe500: "PLAY, POWER, or top-right = Yes"
vibe500: "OK = Yes"
@@ -256,8 +255,7 @@
<dest>
*: "PLAY = Да"
cowond2*: "MENU, или горе-десно = Да"
- creativezen*: "SELECT = Да"
- gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Да"
+ creativezen*,gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Да"
iriverh100,iriverh120,iriverh300: "NAVI = Да"
mrobe500: "PLAY, POWER, или горе-десно = Да"
vibe500: "OK = Да"
@@ -278,7 +276,6 @@
</dest>
<voice>
*: ""
- archosplayer: none
</voice>
</phrase>
<phrase>
@@ -799,10 +796,10 @@
*: "Crossfeed"
</source>
<dest>
- *: "Crossfeed"
+ *: "Кросфид"
</dest>
<voice>
- *: "Crossfeed"
+ *: "Кросфид"
</voice>
</phrase>
<phrase>
@@ -981,7 +978,7 @@
*: "Edit mode: %s"
</source>
<dest>
- *: "Мод подешавања: %s"
+ *: "Режим уређивања: %s"
</dest>
<voice>
*: ""
@@ -1292,10 +1289,10 @@
*: "Party Mode"
</source>
<dest>
- *: "Мод за журке"
+ *: "Режим за журке"
</dest>
<voice>
- *: "Мод за журке"
+ *: "Режим за журке"
</voice>
</phrase>
<phrase>
@@ -1308,11 +1305,11 @@
</source>
<dest>
*: none
- crossfade: "Crossfade"
+ crossfade: "Претапање"
</dest>
<voice>
*: none
- crossfade: "Crossfade"
+ crossfade: "Претапање"
</voice>
</phrase>
<phrase>
@@ -1325,11 +1322,11 @@
</source>
<dest>
*: none
- crossfade: "Укључи Crossfade"
+ crossfade: "Укључи претапање"
</dest>
<voice>
*: none
- crossfade: "Укључи Crossfade"
+ crossfade: "Укључи претапање"
</voice>
</phrase>
<phrase>
@@ -1444,11 +1441,11 @@
</source>
<dest>
*: none
- crossfade: "Fade-Out мод"
+ crossfade: "Fade-Out режим"
</dest>
<voice>
*: none
- crossfade: "Fade-Out мод"
+ crossfade: "Fade-Out режим"
</voice>
</phrase>
<phrase>
@@ -1461,11 +1458,11 @@
</source>
<dest>
*: none
- crossfade: "Mix"
+ crossfade: "Микс"
</dest>
<voice>
*: none
- crossfade: "Mix"
+ crossfade: "Микс"
</voice>
</phrase>
<phrase>
@@ -1669,16 +1666,16 @@
</phrase>
<phrase>
id: LANG_AUDIOSCROBBLER
- desc: "Last.fm Log" in the playback menu
+ desc: "Last.fm Logger" in Plugin/apps/scrobbler
user: core
<source>
- *: "Last.fm Log"
+ *: "Last.fm Logger"
</source>
<dest>
- *: "Last.fm дневник"
+ *: "Креатор Last.fm дневника"
</dest>
<voice>
- *: "Last.fm дневник"
+ *: "Креатор Last.fm дневника"
</voice>
</phrase>
<phrase>
@@ -2376,11 +2373,11 @@
</source>
<dest>
*: none
- lcd_invert,remote_lcd_invert: "LCD мод"
+ lcd_invert,remote_lcd_invert: "LCD режим"
</dest>
<voice>
*: none
- lcd_invert,remote_lcd_invert: "LCD мод"
+ lcd_invert,remote_lcd_invert: "LCD режим"
</voice>
</phrase>
<phrase>
@@ -3599,7 +3596,7 @@
</dest>
<voice>
*: none
- gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,sansac200*,sansae200*: ""
+ gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,samsungyh*,sansac200*,sansae200*: ""
</voice>
</phrase>
<phrase>
@@ -3969,11 +3966,11 @@
</source>
<dest>
*: none
- charging: "Мод за адаптер у аутомобилу"
+ charging: "Режим за адаптер у аутомобилу"
</dest>
<voice>
*: none
- charging: "Мод за адаптер у аутомобилу"
+ charging: "Режим за адаптер у аутомобилу"
</voice>
</phrase>
<phrase>
@@ -4080,31 +4077,16 @@
</phrase>
<phrase>
id: LANG_ALARM_MOD_KEYS
- desc: Shown key functions in alarm menu (for the RTC alarm mod).
+ desc: deprecated
user: core
<source>
- *: none
- alarm: "PLAY=Set OFF=Cancel"
- gigabeats: "SELECT=Set POWER=Cancel"
- ipod*: "SELECT=Set MENU=Cancel"
- iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel"
- mpiohd300: "ENTER=Set MENU=Cancel"
- sansafuzeplus: "SELECT=Set BACK=Cancel"
- vibe500: "OK=Set C=Cancel"
+ *: ""
</source>
<dest>
- *: none
- alarm: "PLAY=Постави OFF=Одустани"
- gigabeats: "SELECT=Постави POWER=Одустани"
- ipod*: "SELECT=Постави MENU=Одустани"
- iriverh10,iriverh10_5gb: "SELECT=Постави PREV=Одустани"
- mpiohd300: "ENTER=Постави MENU=Одустани"
- sansafuzeplus: "SELECT=Постави BACK=Одустани"
- vibe500: "OK=Постави C=Одустани"
+ *: ""
</dest>
<voice>
- *: none
- alarm,ipod*: ""
+ *: ""
</voice>
</phrase>
<phrase>
@@ -5974,12 +5956,10 @@
<source>
*: "Battery: %d%% %dh %dm"
ipodmini1g,ipodmini2g,iriverh10: "Batt: %d%% %dh %dm"
- iriverifp7xx: "%d%% %dh %dm"
</source>
<dest>
*: "Батерија: %d%% %dч %dм"
ipodmini1g,ipodmini2g,iriverh10: "Бат: %d%% %dч %dм"
- iriverifp7xx: "%d%% %dч %dм"
</dest>
<voice>
*: "Ниво батерије"
@@ -6019,14 +5999,17 @@
user: core
<source>
*: "Int:"
+ hibylinux: "mSD:"
xduoox3: "mSD1:"
</source>
<dest>
*: "Инт:"
+ hibylinux: "mSD:"
xduoox3: "mSD1:"
</dest>
<voice>
*: "Интерни"
+ hibylinux: "мајкро Ес Де"
xduoox3: "мајкро Ес Де 1"
</voice>
</phrase>
@@ -6251,16 +6234,16 @@
</phrase>
<phrase>
id: LANG_REPLACE
- desc: in onplay menu. Replace the current playlist with a new one.
+ desc: deprecated
user: core
<source>
- *: "Play Next"
+ *: ""
</source>
<dest>
- *: "Репродукуј следећу"
+ *: ""
</dest>
<voice>
- *: "Репродукуј следећу"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -7241,10 +7224,10 @@
*: "Mode:"
</source>
<dest>
- *: "Мод:"
+ *: "Режим:"
</dest>
<voice>
- *: "Мод:"
+ *: "Режим:"
</voice>
</phrase>
<phrase>
@@ -7345,7 +7328,7 @@
</dest>
<voice>
*: none
- iaudiom5,iaudiox5,iriverh100,iriverh120,iriverh300,recording,sansac200*,sansae200*: ""
+ iaudiom5,iaudiox5,iriverh100,iriverh120,iriverh300,recording,samsungyh*,sansac200*,sansae200*,vibe500: ""
</voice>
</phrase>
<phrase>
@@ -7483,7 +7466,7 @@
*: "Incompatible model"
</source>
<dest>
- *: "Модел није одговарајући"
+ *: "Овај модел није подржан"
</dest>
<voice>
*: "Неодговарајући модел"
@@ -8304,7 +8287,7 @@
*: ""
</dest>
<voice>
- *: "pixel"
+ *: "пиксела"
</voice>
</phrase>
<phrase>
@@ -8332,7 +8315,7 @@
*: ""
</dest>
<voice>
- *: "херц"
+ *: "херца"
</voice>
</phrase>
<phrase>
@@ -8808,7 +8791,7 @@
*: ""
</dest>
<voice>
- *: "while-playing-screen"
+ *: "екран-током-репродукције"
</voice>
</phrase>
<phrase>
@@ -8864,7 +8847,7 @@
*: ""
</dest>
<voice>
- *: "firmware"
+ *: "фирмвер"
</voice>
</phrase>
<phrase>
@@ -8909,7 +8892,7 @@
*: ""
</dest>
<voice>
- *: "cuesheet"
+ *: "кјулиста"
</voice>
</phrase>
<phrase>
@@ -9108,7 +9091,7 @@
*: ""
</dest>
<voice>
- *: "units per tick"
+ *: "јединица по подеоку"
</voice>
</phrase>
<phrase>
@@ -9122,7 +9105,7 @@
*: ""
</dest>
<voice>
- *: "o'clock"
+ *: "сати"
</voice>
</phrase>
<phrase>
@@ -9136,7 +9119,7 @@
*: ""
</dest>
<voice>
- *: "P M"
+ *: "поподне"
</voice>
</phrase>
<phrase>
@@ -9150,7 +9133,7 @@
*: ""
</dest>
<voice>
- *: "A M"
+ *: "преподне"
</voice>
</phrase>
<phrase>
@@ -9164,7 +9147,7 @@
*: ""
</dest>
<voice>
- *: "oh"
+ *: "о"
</voice>
</phrase>
<phrase>
@@ -9342,7 +9325,7 @@
*: ""
</dest>
<voice>
- *: "Edit"
+ *: "Уреди"
</voice>
</phrase>
<phrase>
@@ -9356,7 +9339,7 @@
*: ""
</dest>
<voice>
- *: "Blank"
+ *: "Празно"
</voice>
</phrase>
<phrase>
@@ -9370,7 +9353,7 @@
*: ""
</dest>
<voice>
- *: "Empty list"
+ *: "Празна листа"
</voice>
</phrase>
<phrase>
@@ -9536,7 +9519,7 @@
*: ""
</dest>
<voice>
- *: "Quick screen"
+ *: "Брзи екран"
</voice>
</phrase>
<phrase>
@@ -9564,7 +9547,7 @@
*: ""
</dest>
<voice>
- *: "OK"
+ *: "О Кеј"
</voice>
</phrase>
<phrase>
@@ -9598,7 +9581,7 @@
</dest>
<voice>
*: none
- recording: ""
+ recording: "величина"
</voice>
</phrase>
<phrase>
@@ -9691,7 +9674,7 @@
</dest>
<voice>
*: none
- recording: ""
+ recording: "време дељења"
</voice>
</phrase>
<phrase>
@@ -9722,7 +9705,7 @@
</dest>
<voice>
*: none
- recording: ""
+ recording: "клип"
</voice>
</phrase>
<phrase>
@@ -9756,7 +9739,7 @@
</dest>
<voice>
*: none
- recording: ""
+ recording: "фајл"
</voice>
</phrase>
<phrase>
@@ -9975,11 +9958,11 @@
</source>
<dest>
*: none
- recording: "Моно мод"
+ recording: "Моно режим"
</dest>
<voice>
*: none
- recording: "Моно мод"
+ recording: "Моно режим"
</voice>
</phrase>
<phrase>
@@ -10201,11 +10184,11 @@
</source>
<dest>
*: none
- touchscreen: "Тачскрин мод"
+ touchscreen: "Тачскрин режим"
</dest>
<voice>
*: none
- touchscreen: "Тачскрин мод"
+ touchscreen: "Тачскрин режим"
</voice>
</phrase>
<phrase>
@@ -10247,7 +10230,7 @@
*: ""
</dest>
<voice>
- *: "statusbar skin"
+ *: "изглед статусне линије"
</voice>
</phrase>
<phrase>
@@ -10337,7 +10320,7 @@
</dest>
<voice>
*: none
- remote: "remote statusbar skin"
+ remote: "изглед удаљене статусне линије"
</voice>
</phrase>
<phrase>
@@ -10348,10 +10331,10 @@
*: "Knee"
</source>
<dest>
- *: "Knee"
+ *: "Колено"
</dest>
<voice>
- *: "Ни"
+ *: "колено"
</voice>
</phrase>
<phrase>
@@ -10390,10 +10373,10 @@
*: "Soft Knee"
</source>
<dest>
- *: "Soft Knee"
+ *: "Меко колено"
</dest>
<voice>
- *: "Софт ни"
+ *: "меко колено"
</voice>
</phrase>
<phrase>
@@ -10434,11 +10417,11 @@
</source>
<dest>
*: none
- usb_hid: "Мод USB тастатуре"
+ usb_hid: "Режим USB тастатуре"
</dest>
<voice>
*: none
- usb_hid: "Мод USB тастатуре"
+ usb_hid: "режим у ес бе тастатуре"
</voice>
</phrase>
<phrase>
@@ -10449,10 +10432,10 @@
*: "Hard Knee"
</source>
<dest>
- *: "Hard Knee"
+ *: "Тврдо колено"
</dest>
<voice>
- *: "Хард ни"
+ *: "тврдо колено"
</voice>
</phrase>
<phrase>
@@ -10813,10 +10796,10 @@
*: "Timestretch"
</source>
<dest>
- *: "Timestretch"
+ *: "Временско растезање"
</dest>
<voice>
- *: "Timestretch"
+ *: "Временско растезање"
</voice>
</phrase>
<phrase>
@@ -10975,11 +10958,11 @@
</source>
<dest>
*: none
- touchscreen: "OK"
+ touchscreen: "ОК"
</dest>
<voice>
*: none
- touchscreen: "OK"
+ touchscreen: "О Кеј"
</voice>
</phrase>
<phrase>
@@ -11979,7 +11962,7 @@
*: "Q"
</dest>
<voice>
- *: "Q"
+ *: "Ку фактор"
</voice>
</phrase>
<phrase>
@@ -12122,13 +12105,13 @@
desc: Selective Actions
user: core
<source>
- *: "Play"
+ *: "Exempt Play"
</source>
<dest>
- *: "Репродукуј"
+ *: "Изузми репродукцију"
</dest>
<voice>
- *: "Репродукуј"
+ *: "Изузми репродукцију"
</voice>
</phrase>
<phrase>
@@ -12136,13 +12119,13 @@
desc: Softlock behaviour setting
user: core
<source>
- *: "Disable Notify"
+ *: "Disable Locked Reminders"
</source>
<dest>
- *: "Онемогући обавештење"
+ *: "Онемогући закључана обавештења"
</dest>
<voice>
- *: "Онемогући обавештење"
+ *: "Онемогући закључана обавештења"
</voice>
</phrase>
<phrase>
@@ -12181,10 +12164,10 @@
*: "USB Mode"
</source>
<dest>
- *: "USB Мод"
+ *: "USB режим"
</dest>
<voice>
- *: "USB Мод"
+ *: "USB режим"
</voice>
</phrase>
<phrase>
@@ -12248,13 +12231,13 @@
desc: Selective Actions
user: core
<source>
- *: "Skip"
+ *: "Exempt Skip"
</source>
<dest>
- *: "Прескочи"
+ *: "Изузми прескакање"
</dest>
<voice>
- *: "Прескочи"
+ *: "Изузми прескакање"
</voice>
</phrase>
<phrase>
@@ -12276,13 +12259,13 @@
desc: Selective Actions
user: core
<source>
- *: "Seek"
+ *: "Exempt Seek"
</source>
<dest>
- *: "Премотај"
+ *: "Изузми премотавање"
</dest>
<voice>
- *: "Премотај"
+ *: "Изузми премотавање"
</voice>
</phrase>
<phrase>
@@ -14299,7 +14282,7 @@
*: ""
</dest>
<voice>
- *: ""
+ *: "Притисните репродукцију за покретање теста батерије или стоп за отказивање"
</voice>
</phrase>
<phrase>
@@ -14583,7 +14566,7 @@
*: ""
</dest>
<voice>
- *: ""
+ *: "Обележено"
</voice>
</phrase>
<phrase>
@@ -15349,7 +15332,6 @@
mpiohd200: "Дупли тап REC за прекид."
mpiohd300: "Дупли тап MENU за прекид."
rx27generic: "Притисните VOLUME за прекид."
- sonynwza860: "Мапе тастера нису комплетне."
touchscreen: "Притисните Middle Left за прекид."
vibe500: "Притисните PREV за прекид."
xduoox20,xduoox3,xduoox3ii: "Дупли тап HOME за прекид."
@@ -15459,3 +15441,799 @@
hotkey: "Објављивање укључено"
</voice>
</phrase>
+<phrase>
+ id: LANG_SINGLE_MODE
+ desc: single mode
+ user: core
+ <source>
+ *: "Single Mode"
+ </source>
+ <dest>
+ *: "Режим само једне"
+ </dest>
+ <voice>
+ *: "режим само једне"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_TALK_MIXER_LEVEL
+ desc: Relative volume of voice prompts
+ user: core
+ <source>
+ *: "Voice prompt volume"
+ </source>
+ <dest>
+ *: "Јачина гласа"
+ </dest>
+ <voice>
+ *: "јачина гласа"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_SHORT_SHARP
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ filter_roll_off: "Short Sharp"
+ </source>
+ <dest>
+ *: none
+ filter_roll_off: "Кратки оштар"
+ </dest>
+ <voice>
+ *: none
+ filter_roll_off: "кратки оштар"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_SHORT_SLOW
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ filter_roll_off: "Short Slow"
+ </source>
+ <dest>
+ *: none
+ filter_roll_off: "Кратки спори"
+ </dest>
+ <voice>
+ *: none
+ filter_roll_off: "Кратки спори"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_SUPER_SLOW
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ filter_roll_off: "Super Slow"
+ </source>
+ <dest>
+ *: none
+ filter_roll_off: "Супер спори"
+ </dest>
+ <voice>
+ *: none
+ filter_roll_off: "Супер спори"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_LINEAR_FAST
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Linear Fast"
+ </source>
+ <dest>
+ *: none
+ es9218: "Линеарни брзи"
+ </dest>
+ <voice>
+ *: none
+ es9218: "линеарни брзи"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_LINEAR_SLOW
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Linear Slow"
+ </source>
+ <dest>
+ *: none
+ es9218: "Линеарни спори"
+ </dest>
+ <voice>
+ *: none
+ es9218: "линеарни спори"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_MINIMUM_FAST
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Minimum Fast"
+ </source>
+ <dest>
+ *: none
+ es9218: "Минимални брзи"
+ </dest>
+ <voice>
+ *: none
+ es9218: "минимални брзи"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_MINIMUM_SLOW
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Minimum Slow"
+ </source>
+ <dest>
+ *: none
+ es9218: "Минимални спори"
+ </dest>
+ <voice>
+ *: none
+ es9218: "минимални спори"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_APODIZING_1
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Apodizing type 1"
+ </source>
+ <dest>
+ *: none
+ es9218: "Аподизацијски тип 1"
+ </dest>
+ <voice>
+ *: none
+ es9218: "Аподизацијски тип 1"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_APODIZING_2
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Apodizing type 2"
+ </source>
+ <dest>
+ *: none
+ es9218: "Аподизацијски тип 2"
+ </dest>
+ <voice>
+ *: none
+ es9218: "Аподизацијски тип 2"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_HYBRID_FAST
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Hybrid Fast"
+ </source>
+ <dest>
+ *: none
+ es9218: "Хибридни брзи"
+ </dest>
+ <voice>
+ *: none
+ es9218: "Хибридни брзи"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FILTER_BRICK_WALL
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ es9218: "Brick Wall"
+ </source>
+ <dest>
+ *: none
+ es9218: "Зид"
+ </dest>
+ <voice>
+ *: none
+ es9218: "Зид"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_DAC_POWER_MODE
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ dac_power_mode: "DAC's power mode"
+ es9218: "DAC's output level"
+ </source>
+ <dest>
+ *: none
+ dac_power_mode: "Режим напајања ДАК"
+ es9218: "Излазни ниво ДАК"
+ </dest>
+ <voice>
+ *: none
+ dac_power_mode: "Режим напајања ДАК"
+ es9218: "Излазни ниво ДАК"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_DAC_POWER_HIGH
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ dac_power_mode: "High performance"
+ es9218: "High Gain (2 Vrms)"
+ </source>
+ <dest>
+ *: none
+ dac_power_mode: "Високе перформансе"
+ es9218: "Високо појачање (2 Vrms)"
+ </dest>
+ <voice>
+ *: none
+ dac_power_mode: "Високе перформансе"
+ es9218: "Високо појачање (2 Vrms)"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_DAC_POWER_LOW
+ desc: in sound settings
+ user: core
+ <source>
+ *: none
+ dac_power_mode: "Save battery"
+ es9218: "Low Gain (1 Vrms)"
+ </source>
+ <dest>
+ *: none
+ dac_power_mode: "Штедња батерије"
+ es9218: "Ниско појачање (1 Vrms)"
+ </dest>
+ <voice>
+ *: none
+ dac_power_mode: "Штедња батерије"
+ es9218: "Ниско појачање (1 Vrms)"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ENTER_USB_STORAGE_MODE_QUERY
+ desc: upon plugging in USB
+ user: core
+ <source>
+ *: "Enter USB mass storage mode?"
+ </source>
+ <dest>
+ *: "Да пређем у режим USB масовне меморије?"
+ </dest>
+ <voice>
+ *: "Да пређем у режим USB масовне меморије?"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_CLEAR_LIST_AND_PLAY_NEXT
+ desc: in onplay menu. Replace current playlist with selected tracks
+ user: core
+ <source>
+ *: "Clear List & Play Next"
+ </source>
+ <dest>
+ *: "Очисти листу & репродукуј наредну"
+ </dest>
+ <voice>
+ *: "Очисти листу и репродукуј наредну"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_QUEUE_MENU
+ desc: in onplay menu
+ user: core
+ <source>
+ *: "Queue..."
+ </source>
+ <dest>
+ *: "Ред..."
+ </dest>
+ <voice>
+ *: "ред..."
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SHOW_QUEUE_OPTIONS
+ desc: in Current Playlist settings
+ user: core
+ <source>
+ *: "Show Queue Options"
+ </source>
+ <dest>
+ *: "Прикажи опције реда"
+ </dest>
+ <voice>
+ *: "Прикажи опције реда"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SHOW_SHUFFLED_ADDING_OPTIONS
+ desc: in Current Playlist settings
+ user: core
+ <source>
+ *: "Show Shuffled Adding Options"
+ </source>
+ <dest>
+ *: "Прикажи опције измешаног додавања"
+ </dest>
+ <voice>
+ *: "Прикажи опције измешаног додавања"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_IN_SUBMENU
+ desc: in Settings
+ user: core
+ <source>
+ *: "In Submenu"
+ </source>
+ <dest>
+ *: "У подменију"
+ </dest>
+ <voice>
+ *: "У подменију"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED
+ desc: in onplay menu. Replace current playlist with selected tracks in random order.
+ user: core
+ <source>
+ *: "Clear List & Play Shuffled"
+ </source>
+ <dest>
+ *: "Очисти листу & репродукуј измешано"
+ </dest>
+ <voice>
+ *: "Очисти листу & репродукуј измешано"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SOFTLOCK_DISABLE_ALL_NOTIFY
+ desc: disable all softlock notifications
+ user: core
+ <source>
+ *: "Disable All Lock Notifications"
+ </source>
+ <dest>
+ *: "Искључи сва закључана обавештења"
+ </dest>
+ <voice>
+ *: "Искључи сва закључана обавештења"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ACTION_VOLUME
+ desc: exempt volume from softlock
+ user: core
+ <source>
+ *: "Exempt Volume"
+ </source>
+ <dest>
+ *: "Изузми јачину"
+ </dest>
+ <voice>
+ *: "Изузми јачину"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ACTION_ALWAYSAUTOLOCK
+ desc: always prime autolock
+ user: core
+ <source>
+ *: "Always Autolock"
+ </source>
+ <dest>
+ *: "Увек аутоматски закључај"
+ </dest>
+ <voice>
+ *: "Увек аутоматски закључај"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PLAYLIST_RELOAD_AFTER_SAVE
+ desc: reload playlist after saving
+ user: core
+ <source>
+ *: "Reload After Saving"
+ </source>
+ <dest>
+ *: "Поново учитај након чувања"
+ </dest>
+ <voice>
+ *: "Поново учитај након чувања"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_ALBUMARTIST
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Album Artist]"
+ </source>
+ <dest>
+ *: "[Уметник албума]"
+ </dest>
+ <voice>
+ *: "Уметник албума"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_GENRE
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Genre]"
+ </source>
+ <dest>
+ *: "[Жанр]"
+ </dest>
+ <voice>
+ *: "Жанр"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_COMMENT
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Comment]"
+ </source>
+ <dest>
+ *: "[Коментар]"
+ </dest>
+ <voice>
+ *: "Коментар"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_COMPOSER
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Composer]"
+ </source>
+ <dest>
+ *: "[Композитор]"
+ </dest>
+ <voice>
+ *: "Композитор"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_YEAR
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Year]"
+ </source>
+ <dest>
+ *: "[Година]"
+ </dest>
+ <voice>
+ *: "Година"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_TRACKNUM
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Tracknum]"
+ </source>
+ <dest>
+ *: "[Брнумере]"
+ </dest>
+ <voice>
+ *: "Број нумере"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_DISCNUM
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Discnum]"
+ </source>
+ <dest>
+ *: "[Брдиска]"
+ </dest>
+ <voice>
+ *: "Број диска"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_FREQUENCY
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Frequency]"
+ </source>
+ <dest>
+ *: "[Фреквенција]"
+ </dest>
+ <voice>
+ *: "Фреквенција"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PROPERTIES_BITRATE
+ desc: in properties plugin
+ user: core
+ <source>
+ *: "[Bitrate]"
+ </source>
+ <dest>
+ *: "[Битски_проток]"
+ </dest>
+ <voice>
+ *: "Битски проток"
+ </voice>
+</phrase>
+<phrase>
+ id: VOICE_NUMERIC_TENS_SWAP_SEPARATOR
+ desc: voice only, for speaking numbers in languages that swap the tens and ones fields. Leave blank for languages that do not need it, such as English ("231" => "two hundred thirty one") but other languages may speak it as "two hundred one [AND] thirty"
+ user: core
+ <source>
+ *: ""
+ </source>
+ <dest>
+ *: ""
+ </dest>
+ <voice>
+ *: ""
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_VOICED_DATE_FORMAT
+ desc: format string for how dates will be read back. Y == 4-digit year, A == month name, m == numeric month, d == numeric day. For example, "AdY" will read "January 21 2021"
+ user: core
+ <source>
+ *: "dAY"
+ </source>
+ <dest>
+ *: "dAY"
+ </dest>
+ <voice>
+ *: ""
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_LIST_WRAPAROUND
+ desc: in Settings
+ user: core
+ <source>
+ *: "List Wraparound"
+ </source>
+ <dest>
+ *: "Обмотавање листе"
+ </dest>
+ <voice>
+ *: "Обмотавање листе"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SHOW_SHUTDOWN_MESSAGE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Show Shutdown Message"
+ </source>
+ <dest>
+ *: "Прикажи поруку искључивања"
+ </dest>
+ <voice>
+ *: "Прикажи поруку искључивања"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_LIST_ORDER
+ desc: in Settings
+ user: core
+ <source>
+ *: "List Order"
+ </source>
+ <dest>
+ *: "Редослед листе"
+ </dest>
+ <voice>
+ *: "Редослед листе"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ASCENDING
+ desc: in Settings
+ user: core
+ <source>
+ *: "Ascending"
+ </source>
+ <dest>
+ *: "Растући"
+ </dest>
+ <voice>
+ *: "растући"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_DESCENDING
+ desc: in Settings
+ user: core
+ <source>
+ *: "Descending"
+ </source>
+ <dest>
+ *: "Опадајући"
+ </dest>
+ <voice>
+ *: "опадајући"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ALBUM_ART
+ desc: in Settings
+ user: core
+ <source>
+ *: "Album Art"
+ </source>
+ <dest>
+ *: "Слика омота"
+ </dest>
+ <voice>
+ *: "слика омота"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PREFER_EMBEDDED
+ desc: in Settings
+ user: core
+ <source>
+ *: "Prefer Embedded"
+ </source>
+ <dest>
+ *: "Предност има уграђена"
+ </dest>
+ <voice>
+ *: "Предност има уграђена"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_PREFER_IMAGE_FILE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Prefer Image File"
+ </source>
+ <dest>
+ *: "Предност има фајл слике"
+ </dest>
+ <voice>
+ *: "Предност има фајл слике"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_FM_SYNC_RDS_TIME
+ desc: in radio screen and Settings
+ user: core
+ <source>
+ *: none
+ rds: "Sync RDS Time"
+ </source>
+ <dest>
+ *: none
+ rds: "Синхронизуј са RDS временом"
+ </dest>
+ <voice>
+ *: none
+ rds: "Синхронизуј са RDS временом"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SORT_ALBUMS_BY
+ desc: in Settings
+ user: core
+ <source>
+ *: "Sort albums by"
+ </source>
+ <dest>
+ *: "Сортирај албуме по"
+ </dest>
+ <voice>
+ *: "Сортирај албуме по"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ARTIST_PLUS_NAME
+ desc: in Settings
+ user: core
+ <source>
+ *: "Artist + Name"
+ </source>
+ <dest>
+ *: "Уметник + Име"
+ </dest>
+ <voice>
+ *: "Уметник и име"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_ARTIST_PLUS_YEAR
+ desc: in Settings
+ user: core
+ <source>
+ *: "Artist + Year"
+ </source>
+ <dest>
+ *: "Уметник + Година"
+ </dest>
+ <voice>
+ *: "Ументик и година"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_YEAR_SORT_ORDER
+ desc: in Settings
+ user: core
+ <source>
+ *: "Year sort order"
+ </source>
+ <dest>
+ *: "Редослед сортирања године"
+ </dest>
+ <voice>
+ *: "Редослед сортирања године"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_SHOW_YEAR_IN_ALBUM_TITLE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Show year in album title"
+ </source>
+ <dest>
+ *: "Приказуј годину у наслову албума"
+ </dest>
+ <voice>
+ *: "Приказуј годину у наслову албума"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_WAIT_FOR_CACHE
+ desc: in Settings
+ user: core
+ <source>
+ *: "Cache needs to finish updating first!"
+ </source>
+ <dest>
+ *: "Најпре мора да се освежи кеш!"
+ </dest>
+ <voice>
+ *: "Најпре мора да се освежи кеш!"
+ </voice>
+</phrase>
diff --git a/apps/main.c b/apps/main.c
index dff9dc5778..59932d6185 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -566,27 +566,28 @@ static void init(void)
pcm_init();
dsp_init();
-#if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ CHART(">settings_load(ALL)");
+ settings_load(SETTINGS_ALL);
+ CHART("<settings_load(ALL)");
+
+#if defined(BUTTON_REC) || \
+ (CONFIG_KEYPAD == GIGABEAT_PAD) || \
+ (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IRIVER_H10_PAD)
+ if (global_settings.clear_settings_on_hold &&
#ifdef SETTINGS_RESET
/* Reset settings if holding the reset button. (Rec on Archos,
A on Gigabeat) */
- if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
+ ((button_status() & SETTINGS_RESET) == SETTINGS_RESET))
#else
/* Reset settings if the hold button is turned on */
- if (button_hold())
+ (button_hold()))
#endif
{
splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
settings_reset();
}
- else
#endif
- {
- CHART(">settings_load(ALL)");
- settings_load(SETTINGS_ALL);
- CHART("<settings_load(ALL)");
- }
#ifdef HAVE_DIRCACHE
CHART(">init_dircache(true)");
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 5e9b935937..321f2cdec4 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -338,7 +338,7 @@ static int info_speak_item(int selected_item, void * data)
#ifdef HAVE_RECORDING
case INFO_REC_DIR:
talk_id(LANG_REC_DIR, false);
- if (global_settings.rec_directory && global_settings.rec_directory[0])
+ if (global_settings.rec_directory[0])
{
long *pathsep = NULL;
char rec_directory[MAX_PATHNAME+1];
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 2539f17860..460909318a 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -584,6 +584,15 @@ MENUITEM_SETTING(keypress_restarts_sleeptimer,
&global_settings.keypress_restarts_sleeptimer, NULL);
MENUITEM_SETTING(show_shutdown_message, &global_settings.show_shutdown_message, NULL);
+#if defined(BUTTON_REC) || \
+ (CONFIG_KEYPAD == GIGABEAT_PAD) || \
+ (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ (CONFIG_KEYPAD == IRIVER_H10_PAD)
+#define SETTINGS_CLEAR_ON_HOLD
+MENUITEM_SETTING(clear_settings_on_hold,
+ &global_settings.clear_settings_on_hold, NULL);
+#endif
+
MAKE_MENU(startup_shutdown_menu, ID2P(LANG_STARTUP_SHUTDOWN),
0, Icon_System_menu,
&show_shutdown_message,
@@ -592,7 +601,11 @@ MAKE_MENU(startup_shutdown_menu, ID2P(LANG_STARTUP_SHUTDOWN),
&sleeptimer_toggle,
&sleeptimer_duration,
&sleeptimer_on_startup,
- &keypress_restarts_sleeptimer
+ &keypress_restarts_sleeptimer,
+#if defined(SETTINGS_CLEAR_ON_HOLD)
+ &clear_settings_on_hold,
+#undef SETTINGS_CLEAR_ON_HOLD
+#endif
);
/* STARTUP/SHUTDOWN MENU */
diff --git a/apps/onplay.c b/apps/onplay.c
index 4ffa6deece..e44e81ee5d 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -497,7 +497,7 @@ static struct add_to_pl_param addtopl_queue_shuf = {PLAYLIST_INSERT_SHUFFL
static struct add_to_pl_param addtopl_queue_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, 1, 0};
static struct add_to_pl_param addtopl_replace = {PLAYLIST_INSERT, 0, 1};
-static struct add_to_pl_param addtopl_replace_shuffled = {PLAYLIST_INSERT_SHUFFLED, 0, 1};
+static struct add_to_pl_param addtopl_replace_shuffled = {PLAYLIST_INSERT_LAST_SHUFFLED, 0, 1};
/* CONTEXT_[TREE|ID3DB|STD] playlist options */
static int add_to_playlist(void* arg)
@@ -1860,12 +1860,20 @@ static struct hotkey_assignment hotkey_items[] = {
{ HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED,
HOTKEY_FUNC(playlist_insert_shuffled, NULL),
ONPLAY_RELOAD_DIR },
- { HOTKEY_PLUGIN, LANG_OPEN_PLUGIN,
+ { HOTKEY_PLUGIN, LANG_OPEN_PLUGIN,
HOTKEY_FUNC(hotkey_run_plugin, NULL),
ONPLAY_OK },
- { HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE,
+ { HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE,
HOTKEY_FUNC(bookmark_create_menu, NULL),
ONPLAY_OK },
+ { HOTKEY_PROPERTIES, LANG_PROPERTIES,
+ HOTKEY_FUNC(onplay_load_plugin, (void *)"properties"),
+ ONPLAY_RELOAD_DIR },
+#ifdef HAVE_TAGCACHE
+ { HOTKEY_PICTUREFLOW, LANG_ONPLAY_PICTUREFLOW,
+ HOTKEY_FUNC(onplay_load_plugin, (void *)"pictureflow"),
+ ONPLAY_RELOAD_DIR },
+#endif
};
/* Return the language ID for this action */
diff --git a/apps/onplay.h b/apps/onplay.h
index 3a259d68e6..3121c918ac 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -39,14 +39,18 @@ int get_hotkey_lang_id(int action);
enum hotkey_action {
HOTKEY_OFF = 0,
HOTKEY_VIEW_PLAYLIST,
+ HOTKEY_PROPERTIES,
+#ifdef HAVE_TAGCACHE
+ HOTKEY_PICTUREFLOW,
+#endif
HOTKEY_SHOW_TRACK_INFO,
HOTKEY_PITCHSCREEN,
HOTKEY_OPEN_WITH,
HOTKEY_DELETE,
+ HOTKEY_BOOKMARK,
+ HOTKEY_PLUGIN,
HOTKEY_INSERT,
HOTKEY_INSERT_SHUFFLED,
- HOTKEY_PLUGIN,
- HOTKEY_BOOKMARK,
};
#endif
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index a94e07643e..fd6a01117f 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -73,6 +73,15 @@ enum direction
BACKWARD
};
+enum pv_onplay_result {
+ PV_ONPLAY_USB,
+ PV_ONPLAY_USB_CLOSED,
+ PV_ONPLAY_CLOSED,
+ PV_ONPLAY_ITEM_REMOVED,
+ PV_ONPLAY_CHANGED,
+ PV_ONPLAY_UNCHANGED,
+};
+
struct playlist_buffer
{
char *name_buffer; /* Buffer used to store track names */
@@ -108,6 +117,8 @@ static struct playlist_viewer viewer;
/* Used when viewing playlists on disk */
static struct playlist_info temp_playlist;
+static bool dirty = false;
+
static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
int names_buffer_size);
static void playlist_buffer_load_entries(struct playlist_buffer * pb, int index,
@@ -126,7 +137,9 @@ static void format_line(const struct playlist_entry* track, char* str,
int len);
static bool update_playlist(bool force);
-static int onplay_menu(int index);
+static enum pv_onplay_result onplay_menu(int index);
+
+static void close_playlist_viewer(void);
static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
int names_buffer_size)
@@ -479,7 +492,7 @@ static bool update_playlist(bool force)
return true;
}
-static int show_track_info(struct playlist_entry *current_track)
+static enum pv_onplay_result show_track_info(const struct playlist_entry *current_track)
{
struct mp3entry id3;
bool id3_retrieval_successful = false;
@@ -494,15 +507,63 @@ static int show_track_info(struct playlist_entry *current_track)
return id3_retrieval_successful &&
browse_id3(&id3, current_track->index + 1,
- viewer.num_tracks) ? -1 : 0;
+ viewer.num_tracks) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED;
+}
+
+
+#ifdef HAVE_HOTKEY
+static enum pv_onplay_result open_with(const struct playlist_entry *current_track)
+{
+ char selected_track[MAX_PATH];
+ close_playlist_viewer();
+ snprintf(selected_track, sizeof(selected_track), "%s", current_track->name);
+
+ return (filetype_list_viewers(selected_track) ==
+ PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED);
+}
+#endif /* HAVE_HOTKEY */
+
+#ifdef HAVE_TAGCACHE
+static enum pv_onplay_result open_pictureflow(const struct playlist_entry *current_track)
+{
+ char selected_track[MAX_PATH];
+ close_playlist_viewer();
+ snprintf(selected_track, sizeof(selected_track), "%s", current_track->name);
+
+ return (filetype_load_plugin((void *)"pictureflow", selected_track) ==
+ PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED);
+}
+#endif
+
+static enum pv_onplay_result delete_track(int current_track_index,
+ int index, bool current_was_playing)
+{
+ playlist_delete(viewer.playlist, current_track_index);
+ if (current_was_playing)
+ {
+ if (playlist_amount_ex(viewer.playlist) <= 0)
+ audio_stop();
+ else
+ {
+ /* Start playing new track except if it's the lasttrack
+ track in the playlist and repeat mode is disabled */
+ struct playlist_entry *current_track =
+ playlist_buffer_get_track(&viewer.buffer, index);
+ if (current_track->display_index != viewer.num_tracks ||
+ global_settings.repeat_mode == REPEAT_ALL)
+ {
+ audio_play(0, 0);
+ viewer.current_playing_track = -1;
+ }
+ }
+ }
+ return PV_ONPLAY_ITEM_REMOVED;
}
-/* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
- Returns -1 if USB attached, 0 if no playlist change, 1 if playlist
- changed, 2 if a track was removed from the playlist */
-static int onplay_menu(int index)
+/* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen. */
+static enum pv_onplay_result onplay_menu(int index)
{
- int result, ret = 0;
+ int result, ret = PV_ONPLAY_UNCHANGED;
struct playlist_entry * current_track =
playlist_buffer_get_track(&viewer.buffer, index);
MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL,
@@ -510,13 +571,18 @@ static int onplay_menu(int index)
ID2P(LANG_REMOVE), ID2P(LANG_MOVE), ID2P(LANG_MENU_SHOW_ID3_INFO),
ID2P(LANG_SHUFFLE),
ID2P(LANG_SAVE),
- ID2P(LANG_PLAYLISTVIEWER_SETTINGS));
- bool current = (current_track->index == viewer.current_playing_track);
+ ID2P(LANG_PLAYLISTVIEWER_SETTINGS)
+#ifdef HAVE_TAGCACHE
+ ,ID2P(LANG_ONPLAY_PICTUREFLOW)
+#endif
+ );
+
+ bool current_was_playing = (current_track->index == viewer.current_playing_track);
result = do_menu(&menu_items, NULL, NULL, false);
if (result == MENU_ATTACHED_USB)
{
- ret = -1;
+ ret = PV_ONPLAY_USB;
}
else if (result >= 0)
{
@@ -529,41 +595,21 @@ static int onplay_menu(int index)
case 0:
/* playlist */
onplay_show_playlist_menu(current_track->name, NULL);
- ret = 0;
+ ret = PV_ONPLAY_UNCHANGED;
break;
case 1:
/* add to catalog */
onplay_show_playlist_cat_menu(current_track->name);
- ret = 0;
+ ret = PV_ONPLAY_UNCHANGED;
break;
case 2:
- /* delete track */
- playlist_delete(viewer.playlist, current_track->index);
- if (current)
- {
- if (playlist_amount_ex(viewer.playlist) <= 0)
- audio_stop();
- else
- {
- /* Start playing new track except if it's the lasttrack
- track in the playlist and repeat mode is disabled */
- current_track =
- playlist_buffer_get_track(&viewer.buffer, index);
- if (current_track->display_index!=viewer.num_tracks ||
- global_settings.repeat_mode == REPEAT_ALL)
- {
- audio_play(0, 0);
- viewer.current_playing_track = -1;
- }
- }
- }
- ret = 2;
+ ret = delete_track(current_track->index, index, current_was_playing);
break;
case 3:
/* move track */
viewer.moving_track = index;
viewer.moving_playlist_index = current_track->index;
- ret = 0;
+ ret = PV_ONPLAY_UNCHANGED;
break;
case 4:
ret = show_track_info(current_track);
@@ -571,18 +617,23 @@ static int onplay_menu(int index)
case 5:
/* shuffle */
playlist_randomise(viewer.playlist, current_tick, false);
- ret = 1;
+ ret = PV_ONPLAY_CHANGED;
break;
case 6:
/* save playlist */
save_playlist_screen(viewer.playlist);
- ret = 0;
+ ret = PV_ONPLAY_UNCHANGED;
break;
case 7:
/* playlist viewer settings */
result = do_menu(&viewer_settings_menu, NULL, NULL, false);
- ret = (result == MENU_ATTACHED_USB) ? -1 : 0;
+ ret = (result == MENU_ATTACHED_USB) ? PV_ONPLAY_USB : PV_ONPLAY_UNCHANGED;
break;
+#ifdef HAVE_TAGCACHE
+ case 8:
+ ret = open_pictureflow(current_track);
+ break;
+#endif
}
}
return ret;
@@ -691,6 +742,71 @@ static int playlist_callback_voice(int selected_item, void *data)
return 0;
}
+static void update_lists(struct gui_synclist * playlist_lists)
+{
+ gui_synclist_set_voice_callback(playlist_lists,
+ global_settings.talk_file?
+ &playlist_callback_voice:NULL);
+ gui_synclist_set_icon_callback(playlist_lists,
+ global_settings.playlist_viewer_icons?
+ &playlist_callback_icons:NULL);
+ gui_synclist_set_title(playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
+ gui_synclist_draw(playlist_lists);
+ gui_synclist_speak_item(playlist_lists);
+}
+
+static bool update_viewer_with_changes(struct gui_synclist *playlist_lists, enum pv_onplay_result res)
+{
+ bool exit = false;
+ if (res == PV_ONPLAY_CHANGED ||
+ res == PV_ONPLAY_ITEM_REMOVED)
+ {
+ if (res == PV_ONPLAY_ITEM_REMOVED)
+ gui_synclist_del_item(playlist_lists);
+ update_playlist(true);
+ if (viewer.num_tracks <= 0)
+ exit = true;
+ if (viewer.selected_track >= viewer.num_tracks)
+ viewer.selected_track = viewer.num_tracks-1;
+ dirty = true;
+ }
+ /* the show_icons option in the playlist viewer settings
+ * menu might have changed */
+ update_lists(playlist_lists);
+ return exit;
+}
+
+static void prepare_lists(struct gui_synclist * playlist_lists)
+{
+ gui_synclist_init(playlist_lists, playlist_callback_name,
+ &viewer, false, 1, NULL);
+ gui_synclist_set_voice_callback(playlist_lists,
+ global_settings.talk_file ?
+ &playlist_callback_voice : NULL);
+ gui_synclist_set_icon_callback(playlist_lists,
+ global_settings.playlist_viewer_icons ?
+ &playlist_callback_icons : NULL);
+ gui_synclist_set_nb_items(playlist_lists, viewer.num_tracks);
+ gui_synclist_set_title(playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
+ gui_synclist_select_item(playlist_lists, viewer.selected_track);
+ gui_synclist_draw(playlist_lists);
+ gui_synclist_speak_item(playlist_lists);
+}
+
+static bool open_playlist_viewer(const char* filename,
+ struct gui_synclist *playlist_lists,
+ bool reload)
+{
+ push_current_activity(ACTIVITY_PLAYLISTVIEWER);
+
+ if (!playlist_viewer_init(&viewer, filename, reload))
+ return false;
+
+ prepare_lists(playlist_lists);
+
+ return true;
+}
+
/* Main viewer function. Filename identifies playlist to be viewed. If NULL,
view current playlist. */
enum playlist_viewer_result playlist_viewer_ex(const char* filename)
@@ -698,25 +814,11 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
enum playlist_viewer_result ret = PLAYLIST_VIEWER_OK;
bool exit = false; /* exit viewer */
int button;
- bool dirty = false;
struct gui_synclist playlist_lists;
- if (!playlist_viewer_init(&viewer, filename, false))
+
+ if (!open_playlist_viewer(filename, &playlist_lists, false))
goto exit;
- push_current_activity(ACTIVITY_PLAYLISTVIEWER);
- gui_synclist_init(&playlist_lists, playlist_callback_name,
- &viewer, false, 1, NULL);
- gui_synclist_set_voice_callback(&playlist_lists,
- global_settings.talk_file?
- &playlist_callback_voice:NULL);
- gui_synclist_set_icon_callback(&playlist_lists,
- global_settings.playlist_viewer_icons?
- &playlist_callback_icons:NULL);
- gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks);
- gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
- gui_synclist_select_item(&playlist_lists, viewer.selected_track);
- gui_synclist_draw(&playlist_lists);
- gui_synclist_speak_item(&playlist_lists);
while (!exit)
{
int track;
@@ -842,36 +944,22 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
}
case ACTION_STD_CONTEXT:
{
- /* ON+PLAY menu */
- int ret_val;
-
- ret_val = onplay_menu(viewer.selected_track);
+ int pv_onplay_result = onplay_menu(viewer.selected_track);
- if (ret_val < 0)
+ if (pv_onplay_result == PV_ONPLAY_USB)
{
ret = PLAYLIST_VIEWER_USB;
goto exit;
}
- else if (ret_val > 0)
+ else if (pv_onplay_result == PV_ONPLAY_USB_CLOSED)
+ return PLAYLIST_VIEWER_USB;
+ else if (pv_onplay_result == PV_ONPLAY_CLOSED)
{
- /* Playlist changed */
- if (ret_val == 2)
- gui_synclist_del_item(&playlist_lists);
- update_playlist(true);
- if (viewer.num_tracks <= 0)
- exit = true;
- if (viewer.selected_track >= viewer.num_tracks)
- viewer.selected_track = viewer.num_tracks-1;
- dirty = true;
+ if (!open_playlist_viewer(filename, &playlist_lists, true))
+ goto exit;
+ break;
}
- /* the show_icons option in the playlist viewer settings
- * menu might have changed */
- gui_synclist_set_icon_callback(&playlist_lists,
- global_settings.playlist_viewer_icons?
- &playlist_callback_icons:NULL);
- gui_synclist_set_title(&playlist_lists, playlist_lists.title, playlist_lists.title_icon);
- gui_synclist_draw(&playlist_lists);
- gui_synclist_speak_item(&playlist_lists);
+ exit = update_viewer_with_changes(&playlist_lists, pv_onplay_result);
break;
}
case ACTION_STD_MENU:
@@ -883,18 +971,50 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
{
quick_screen_quick(button);
update_playlist(true);
- gui_synclist_set_voice_callback(&playlist_lists,
- global_settings.talk_file?
- &playlist_callback_voice:NULL);
- gui_synclist_set_icon_callback(&playlist_lists,
- global_settings.playlist_viewer_icons?
- &playlist_callback_icons:NULL);
- gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
- gui_synclist_draw(&playlist_lists);
- gui_synclist_speak_item(&playlist_lists);
+ update_lists(&playlist_lists);
break;
}
#endif
+#ifdef HAVE_HOTKEY
+ case ACTION_TREE_HOTKEY:
+ {
+ struct playlist_entry *current_track = playlist_buffer_get_track(
+ &viewer.buffer,
+ viewer.selected_track);
+ enum pv_onplay_result (*do_plugin)(const struct playlist_entry *) = NULL;
+#ifdef HAVE_TAGCACHE
+ if (global_settings.hotkey_tree == HOTKEY_PICTUREFLOW)
+ do_plugin = &open_pictureflow;
+#endif
+ if (global_settings.hotkey_tree == HOTKEY_OPEN_WITH)
+ do_plugin = &open_with;
+
+ if (do_plugin != NULL)
+ {
+ if (do_plugin(current_track) == PV_ONPLAY_USB_CLOSED)
+ return PLAYLIST_VIEWER_USB;
+ else if (!open_playlist_viewer(filename, &playlist_lists, true))
+ goto exit;
+ }
+ else if (global_settings.hotkey_tree == HOTKEY_PROPERTIES)
+ {
+ if (show_track_info(current_track) == PV_ONPLAY_USB)
+ {
+ ret = PLAYLIST_VIEWER_USB;
+ goto exit;
+ }
+ update_lists(&playlist_lists);
+ }
+ else if (global_settings.hotkey_tree == HOTKEY_DELETE)
+ exit = update_viewer_with_changes(&playlist_lists,
+ delete_track(current_track->index,
+ viewer.selected_track,
+ (current_track->index == viewer.current_playing_track)));
+ else
+ onplay(current_track->name, FILE_ATTR_AUDIO, CONTEXT_STD, true);
+ break;
+ }
+#endif /* HAVE_HOTKEY */
default:
if(default_event_handler(button) == SYS_USB_CONNECTED)
{
@@ -906,6 +1026,12 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
}
exit:
+ close_playlist_viewer();
+ return ret;
+}
+
+static void close_playlist_viewer(void)
+{
talk_shutup();
pop_current_activity();
if (viewer.playlist)
@@ -914,7 +1040,7 @@ exit:
save_playlist_screen(viewer.playlist);
playlist_close(viewer.playlist);
}
- return ret;
+ dirty = false;
}
static const char* playlist_search_callback_name(int selected_item, void * data,
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 332dd1bde4..f2ab4843c2 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -178,6 +178,7 @@ test_resize,apps
test_sampr,apps
test_scanrate,apps
test_touchscreen,apps
+test_usb,apps
test_viewports,apps
test_greylib_bitmap_scale,viewers
text_editor,apps
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index c169b61cd1..942f9a5b20 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -226,5 +226,6 @@ test_sampr.c
#ifdef HAVE_TOUCHSCREEN
test_touchscreen.c
#endif
+test_usb.c
test_viewports.c
#endif /* HAVE_TEST_PLUGINS */
diff --git a/apps/plugins/doom/d_deh.c b/apps/plugins/doom/d_deh.c
index 1a399e3b49..0a67aa0aad 100644
--- a/apps/plugins/doom/d_deh.c
+++ b/apps/plugins/doom/d_deh.c
@@ -63,7 +63,7 @@ char* strlwr(char* str)
typedef struct {
const byte *inp; // Pointer to string
size_t size; // Bytes remaining in string
- int fd; // Current file descriptor
+ int fd; // Current file descriptor
} DEHFILE;
// killough 10/98: emulate IO whether input really comes from a file or not
@@ -2868,6 +2868,7 @@ boolean deh_GetData(char *s, char *k, uint_64_t *l, char **strval, int fpout)
if (*t == '=') break;
buffer[i] = *t; // copy it
}
+ if (i == 0) i = 1; /* Just in case */
buffer[--i] = '\0'; // terminate the key before the '='
if (!*t) // end of string with no equal sign
{
diff --git a/apps/plugins/lastfm_scrobbler.c b/apps/plugins/lastfm_scrobbler.c
index 7bd213b6d2..3269f1820b 100644
--- a/apps/plugins/lastfm_scrobbler.c
+++ b/apps/plugins/lastfm_scrobbler.c
@@ -26,6 +26,7 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
*/
#include "plugin.h"
+#include "lib/configfile.h"
#ifndef UNTAGGED
#define UNTAGGED "<UNTAGGED>"
@@ -39,7 +40,7 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
/****************** constants ******************/
#define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF)
-#define EV_OTHINSTANCE MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFE)
+#define EV_FLUSHCACHE MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFE)
#define EV_STARTUP MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x01)
#define EV_TRACKCHANGE MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x02)
#define EV_TRACKFINISH MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x03)
@@ -55,6 +56,9 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
#define ITEM_HDR "#ARTIST #ALBUM #TITLE #TRACKNUM #LENGTH #RATING #TIMESTAMP #MUSICBRAINZ_TRACKID\n"
+#define CFG_FILE "/lastfm_scrobbler.cfg"
+#define CFG_VER 1
+
#if CONFIG_RTC
static time_t timestamp;
#define BASE_FILENAME HOME_DIR "/.scrobbler.log"
@@ -70,125 +74,7 @@ static time_t timestamp;
#define THREAD_STACK_SIZE 4*DEFAULT_STACK_SIZE
-#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
- (CONFIG_KEYPAD == IRIVER_H300_PAD)
-#define SCROBBLE_OFF BUTTON_OFF
-#define SCROBBLE_OFF_TXT "STOP"
-#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
- (CONFIG_KEYPAD == IPOD_3G_PAD) || \
- (CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define SCROBBLE_OFF BUTTON_MENU
-#define SCROBBLE_OFF_TXT "MENU"
-#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD || \
- CONFIG_KEYPAD == AGPTEK_ROCKER_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
- (CONFIG_KEYPAD == SANSA_C200_PAD) || \
- (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
- (CONFIG_KEYPAD == SANSA_M200_PAD)
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
-#define SCROBBLE_OFF BUTTON_HOME
-#define SCROBBLE_OFF_TXT "HOME"
-#elif (CONFIG_KEYPAD == IRIVER_H10_PAD || \
- CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD || \
- CONFIG_KEYPAD == SONY_NWZ_PAD || \
- CONFIG_KEYPAD == XDUOO_X3_PAD || \
- CONFIG_KEYPAD == IHIFI_770_PAD || \
- CONFIG_KEYPAD == IHIFI_800_PAD || \
- CONFIG_KEYPAD == XDUOO_X3II_PAD || \
- CONFIG_KEYPAD == XDUOO_X20_PAD || \
- CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD || \
- CONFIG_KEYPAD == EROSQ_PAD)
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == GIGABEAT_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \
- || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD \
- || CONFIG_KEYPAD == CREATIVE_ZEN_PAD
-#define SCROBBLE_OFF BUTTON_BACK
-#define SCROBBLE_OFF_TXT "BACK"
-#elif CONFIG_KEYPAD == MROBE500_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == MROBE100_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define BATTERY_RC_OFF BUTTON_RC_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == COWON_D2_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
-#define SCROBBLE_OFF BUTTON_BACK
-#define SCROBBLE_OFF_TXT "BACK"
-#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == ONDAVX747_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == ONDAVX777_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
- (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
-#define SCROBBLE_OFF BUTTON_RIGHT
-#define SCROBBLE_OFF_TXT "RIGHT"
-#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == MPIO_HD200_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == MPIO_HD300_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == HM60X_PAD) || (CONFIG_KEYPAD == HM801_PAD)
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == DX50_PAD
-#define SCROBBLE_OFF BUTTON_POWER_LONG
-#define SCROBBLE_OFF_TXT "Power Long"
-#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "Power"
-#elif CONFIG_KEYPAD == FIIO_M3K_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "Power"
-#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
-/* use touchscreen */
-#else
-#error "No keymap defined!"
-#endif
-#if defined(HAVE_TOUCHSCREEN)
-#ifndef SCROBBLE_OFF
-#define SCROBBLE_OFF BUTTON_TOPLEFT
-#endif
-#ifndef SCROBBLE_OFF_TXT
-#define SCROBBLE_OFF_TXT "TOPLEFT"
-#endif
-#endif
/****************** prototypes ******************/
-int plugin_main(const void* parameter); /* main loop */
enum plugin_status plugin_start(const void* parameter); /* entry */
/****************** globals ******************/
@@ -198,7 +84,8 @@ static struct
{
bool exiting; /* signal to the thread that we want to exit */
unsigned int id; /* worker thread id */
- struct event_queue queue; /* thread event queue */
+ struct event_queue queue; /* thread event queue */
+ struct queue_sender_list queue_send;
long stack[THREAD_STACK_SIZE / sizeof(long)];
} gThread;
@@ -211,6 +98,86 @@ static struct
bool force_flush;
} gCache;
+static struct
+{
+ int savepct;
+ bool playback;
+ bool verbose;
+} gConfig;
+
+static struct configdata config[] =
+{
+ {TYPE_INT, 0, 100, { .int_p = &gConfig.savepct }, "SavePct", NULL},
+ {TYPE_BOOL, 0, 1, { .bool_p = &gConfig.playback }, "Playback", NULL},
+ {TYPE_BOOL, 0, 1, { .bool_p = &gConfig.verbose }, "Verbose", NULL},
+};
+const int gCfg_sz = sizeof(config)/sizeof(*config);
+/****************** config functions *****************/
+static void config_set_defaults(void)
+{
+ gConfig.savepct = 50;
+ gConfig.playback = false;
+ gConfig.verbose = true;
+}
+
+static int config_settings_menu(void)
+{
+ int selection = 0;
+
+ struct viewport parentvp[NB_SCREENS];
+ FOR_NB_SCREENS(l)
+ {
+ rb->viewport_set_defaults(&parentvp[l], l);
+ rb->viewport_set_fullscreen(&parentvp[l], l);
+ }
+
+ MENUITEM_STRINGLIST(settings_menu, ID2P(LANG_SETTINGS), NULL,
+ ID2P(LANG_RESUME_PLAYBACK),
+ "Save Threshold",
+ "Verbose",
+ ID2P(VOICE_BLANK),
+ ID2P(LANG_CANCEL_0),
+ ID2P(LANG_SAVE_EXIT));
+
+ do {
+ selection=rb->do_menu(&settings_menu,&selection, parentvp, true);
+ switch(selection) {
+
+ case 0:
+ rb->set_bool(str(LANG_RESUME_PLAYBACK), &gConfig.playback);
+ break;
+ case 1:
+ rb->set_int("Save Threshold", "%", UNIT_PERCENT,
+ &gConfig.savepct, NULL, 10, 0, 100, NULL );
+ break;
+ case 2:
+ rb->set_bool("Verbose", &gConfig.verbose);
+ break;
+ case 3: /*sep*/
+ continue;
+ case 4:
+ return -1;
+ break;
+ case 5:
+ {
+ int res = configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+ if (res >= 0)
+ {
+ logf("Scrobbler cfg saved %s %d bytes", CFG_FILE, gCfg_sz);
+ return PLUGIN_OK;
+ }
+ logf("Scrobbler cfg FAILED (%d) %s", res, CFG_FILE);
+ return PLUGIN_ERROR;
+ }
+ case MENU_ATTACHED_USB:
+ return PLUGIN_USB_CONNECTED;
+ default:
+ return PLUGIN_OK;
+ }
+ } while ( selection >= 0 );
+ return 0;
+}
+
/****************** helper fuctions ******************/
int scrobbler_init(void)
@@ -326,6 +293,13 @@ static inline char* str_chk_valid(char *s, char *alt)
return (s != NULL ? s : alt);
}
+static unsigned long scrobbler_get_threshold(unsigned long length)
+{
+ /* length is assumed to be in miliseconds */
+ return length / 100 * gConfig.savepct;
+
+}
+
static void scrobbler_add_to_cache(const struct mp3entry *id)
{
static uint32_t last_crc = 0;
@@ -339,7 +313,7 @@ static void scrobbler_add_to_cache(const struct mp3entry *id)
logf("SCROBBLER: add_to_cache[%d]", gCache.pos);
- if (id->elapsed > id->length / 2)
+ if (id->elapsed >= scrobbler_get_threshold(id->length))
rating = 'L'; /* Listened */
char tracknum[11] = { "" };
@@ -410,9 +384,9 @@ static void scrobbler_change_event(unsigned short id, void *ev_data)
logf("%s", __func__);
struct mp3entry *id3 = ((struct track_event *)ev_data)->id3;
- /* check if track was resumed > %50 played ( likely got saved )
+ /* check if track was resumed > %threshold played ( likely got saved )
check for blank artist or track name */
- if ((id3->elapsed > id3->length / 2)
+ if ((id3->elapsed > scrobbler_get_threshold(id3->length))
|| (!id3->artist && !id3->albumartist) || !id3->title)
{
gCache.pending = false;
@@ -448,25 +422,32 @@ static void scrobbler_finish_event(unsigned short id, void *ev_data)
{
(void)id;
struct track_event *te = ((struct track_event *)ev_data);
- struct mp3entry *id3 = te->id3;
logf("%s %s %s", __func__, gCache.pending?"True":"False", track_event_info(te));
/* add entry using the currently ending track */
if (gCache.pending && (te->flags & TEF_CURRENT) && !(te->flags & TEF_REWIND))
{
gCache.pending = false;
- if (id3->elapsed*2 >= id3->length)
- scrobbler_add_to_cache(te->id3);
- else
- {
- logf("%s Discarding < 50%% played", __func__);
- }
+ scrobbler_add_to_cache(te->id3);
}
}
-/****************** main thread + helper ******************/
+/****************** main thread + helpers ******************/
+static void events_unregister(void)
+{
+ /* we don't want any more events */
+ rb->remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
+ rb->remove_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
+}
+
+static void events_register(void)
+{
+ rb->add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
+ rb->add_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
+}
+
void thread(void)
{
bool in_usb = false;
@@ -487,6 +468,7 @@ void thread(void)
in_usb = false;
/*fall through*/
case EV_STARTUP:
+ events_register();
rb->beep_play(1500, 100, 1000);
break;
case SYS_POWEROFF:
@@ -500,10 +482,11 @@ void thread(void)
if (!in_usb)
scrobbler_flush_cache();
#endif
+ events_unregister();
return;
- case EV_OTHINSTANCE:
+ case EV_FLUSHCACHE:
scrobbler_flush_cache();
- rb->splashf(HZ * 2, "%s Cache Flushed", str(LANG_AUDIOSCROBBLER));
+ rb->queue_reply(&gThread.queue, 0);
break;
default:
logf("default %ld", ev.id);
@@ -520,6 +503,7 @@ void thread_create(void)
0, "Last.Fm_TSR"
IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU));
+ rb->queue_enable_queue_send(&gThread.queue, &gThread.queue_send, gThread.id);
rb->queue_post(&gThread.queue, EV_STARTUP, 0);
rb->yield();
}
@@ -527,79 +511,77 @@ void thread_create(void)
void thread_quit(void)
{
if (!gThread.exiting) {
+ gThread.exiting = true;
rb->queue_post(&gThread.queue, EV_EXIT, 0);
rb->thread_wait(gThread.id);
- /* we don't want any more events */
- rb->remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
- rb->remove_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
/* remove the thread's queue from the broadcast list */
rb->queue_delete(&gThread.queue);
- gThread.exiting = true;
}
}
/* callback to end the TSR plugin, called before a new one gets loaded */
static bool exit_tsr(bool reenter)
{
- logf("%s", __func__);
- bool is_exit = false;
- int button;
- if (reenter)
- {
- logf(" reenter other instance ");
- rb->queue_post(&gThread.queue, EV_OTHINSTANCE, 0);
- return false; /* dont let it start again */
- }
- rb->lcd_clear_display();
- rb->lcd_puts_scroll(0, 0, "Scrobbler is currently running.");
- rb->lcd_puts_scroll(0, 1, "Press " SCROBBLE_OFF_TXT " to exit");
- rb->lcd_puts_scroll(0, 2, "Anything else will resume");
-
- rb->lcd_update();
- rb->button_clear_queue();
- while (1)
+ MENUITEM_STRINGLIST(menu, ID2P(LANG_AUDIOSCROBBLER), NULL, ID2P(LANG_SETTINGS),
+ "Flush Cache", "Exit Plugin", ID2P(LANG_BACK));
+
+ const struct text_message quit_prompt = {
+ (const char*[]){ ID2P(LANG_AUDIOSCROBBLER),
+ "is currently running.",
+ "Quit scrobbler?" }, 3
+ };
+
+ while(true)
{
- button = rb->button_get(true);
- if (IS_SYSEVENT(button))
- continue;
- if (button == SCROBBLE_OFF)
+ int result = reenter ? rb->do_menu(&menu, NULL, NULL, false) : 2;
+ switch(result)
{
- rb->queue_post(&gThread.queue, EV_EXIT, 0);
- rb->thread_wait(gThread.id);
- /* remove the thread's queue from the broadcast list */
- rb->queue_delete(&gThread.queue);
- is_exit = true;
- }
- else is_exit = false;
+ case 0: /* settings */
+ config_settings_menu();
+ break;
+ case 1: /* flush cache */
+ rb->queue_send(&gThread.queue, EV_FLUSHCACHE, 0);
+ if (gConfig.verbose)
+ rb->splashf(2*HZ, "%s Cache Flushed", str(LANG_AUDIOSCROBBLER));
+ break;
- break;
- }
- FOR_NB_SCREENS(idx)
- rb->screens[idx]->scroll_stop();
+ case 2: /* exit plugin - quit */
+ if(rb->gui_syncyesno_run(&quit_prompt, NULL, NULL) == YESNO_YES)
+ {
+ thread_quit();
+ if (reenter)
+ rb->plugin_tsr(NULL); /* remove TSR cb */
+ return !reenter;
+ }
- if (is_exit)
- thread_quit();
+ if(!reenter)
+ return false;
- return is_exit;
+ break;
+
+ case 3: /* back to menu */
+ return false;
+ }
+ }
}
/****************** main ******************/
-
-int plugin_main(const void* parameter)
+static int plugin_main(const void* parameter)
{
(void)parameter;
rb->memset(&gThread, 0, sizeof(gThread));
- rb->splashf(HZ / 2, "%s Started",str(LANG_AUDIOSCROBBLER));
+ if (gConfig.verbose)
+ rb->splashf(HZ / 2, "%s Started",str(LANG_AUDIOSCROBBLER));
logf("%s: %s Started", __func__, str(LANG_AUDIOSCROBBLER));
rb->plugin_tsr(exit_tsr); /* stay resident */
- rb->add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
- rb->add_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
thread_create();
- return 0;
+ if (gConfig.playback)
+ return PLUGIN_GOTO_WPS;
+ return PLUGIN_OK;
}
/***************** Plugin Entry Point *****************/
@@ -612,6 +594,16 @@ enum plugin_status plugin_start(const void* parameter)
language_strings = rb->language_strings;
if (scrobbler_init() < 0)
return PLUGIN_ERROR;
+
+ if (configfile_load(CFG_FILE, config, gCfg_sz, CFG_VER) < 0)
+ {
+ /* If the loading failed, save a new config file */
+ config_set_defaults();
+ configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+
+ rb->splash(HZ, ID2P(LANG_REVERT_TO_DEFAULT_SETTINGS));
+ }
+
int ret = plugin_main(parameter);
- return (ret==0) ? PLUGIN_OK : PLUGIN_ERROR;
+ return ret;
}
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index a2782b6a2b..2f075a7e61 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -268,7 +268,6 @@ typedef fb_data pix_t;
/* some magic numbers for cache_version. */
#define CACHE_REBUILD 0
-#define CACHE_UPDATE 1
/* Error return values */
#define SUCCESS 0
@@ -306,6 +305,8 @@ struct pf_config_t
bool resize;
bool show_fps;
+
+ bool update_albumart;
};
struct pf_index_t {
@@ -511,6 +512,7 @@ static struct configdata config[] =
{ TYPE_ENUM, 0, 2, { .int_p = &pf_cfg.year_sort_order }, "year order",
year_sort_order_conf },
{ TYPE_BOOL, 0, 1, { .bool_p = &pf_cfg.show_year }, "show year", NULL },
+ { TYPE_BOOL, 0, 1, { .bool_p = &pf_cfg.update_albumart }, "update albumart", NULL }
};
#define CONFIG_NUM_ITEMS (sizeof(config) / sizeof(struct configdata))
@@ -667,9 +669,10 @@ static bool confirm_quit(void)
return true;
}
-static void config_save(int cache_version)
+static void config_save(int cache_version, bool update_albumart)
{
pf_cfg.cache_version = cache_version;
+ pf_cfg.update_albumart = update_albumart;
configfile_save(CONFIG_FILE, config, CONFIG_NUM_ITEMS, CONFIG_VERSION);
}
@@ -684,12 +687,13 @@ static void config_set_defaults(struct pf_config_t *cfg)
cfg->last_album = 0;
cfg->backlight_mode = 0;
cfg->resize = true;
- cfg->cache_version = 0;
+ cfg->cache_version = CACHE_REBUILD;
cfg->show_album_name = (LCD_HEIGHT > 100)
? ALBUM_NAME_TOP : ALBUM_NAME_BOTTOM;
cfg->sort_albums_by = SORT_BY_ARTIST_AND_NAME;
cfg->year_sort_order = ASCENDING;
cfg->show_year = false;
+ cfg->update_albumart = false;
}
static inline PFreal fmul(PFreal a, PFreal b)
@@ -2250,8 +2254,6 @@ static bool incremental_albumart_cache(bool verbose)
unsigned int hash_artist, hash_album;
unsigned int format = FORMAT_NATIVE;
- bool update = (pf_cfg.cache_version == CACHE_UPDATE);
-
if (pf_cfg.resize)
format |= FORMAT_RESIZE|FORMAT_KEEP_ASPECT;
@@ -2263,8 +2265,6 @@ static bool incremental_albumart_cache(bool verbose)
aa_cache.inspected++;
if (aa_cache.idx >= pf_idx.album_ct) { aa_cache.idx = 0; } /* Rollover */
- if (!get_albumart_for_index_from_db(idx, aa_cache.file, sizeof(aa_cache.file)))
- goto aa_failure; //rb->strcpy(aa_cache.file, EMPTY_SLIDE_BMP);
hash_artist = mfnv(get_album_artist(idx));
hash_album = mfnv(get_album_name(idx));
@@ -2272,13 +2272,15 @@ static bool incremental_albumart_cache(bool verbose)
rb->snprintf(aa_cache.pfraw_file, sizeof(aa_cache.pfraw_file),
CACHE_PREFIX "/%x%x.pfraw", hash_album, hash_artist);
- if(rb->file_exists(aa_cache.pfraw_file)) {
- if(update) {
- aa_cache.slides++;
- goto aa_success;
- }
+ if(pf_cfg.update_albumart && rb->file_exists(aa_cache.pfraw_file)) {
+ aa_cache.slides++;
+ goto aa_success;
}
+ if (!get_albumart_for_index_from_db(idx, aa_cache.file, sizeof(aa_cache.file)))
+ goto aa_failure; //rb->strcpy(aa_cache.file, EMPTY_SLIDE_BMP);
+
+
aa_cache.input_bmp.data = aa_cache.buf;
aa_cache.input_bmp.width = DISPLAY_WIDTH;
aa_cache.input_bmp.height = DISPLAY_HEIGHT;
@@ -3169,14 +3171,14 @@ static inline void set_current_slide(const int slide_index)
{
int old_center_index = center_index;
step = 0;
- center_index = fbound(slide_index, 0, number_of_slides - 1);
+ center_index = fbound(0, slide_index, number_of_slides - 1);
if (old_center_index != center_index)
{
rb->queue_remove_from_head(&thread_q, EV_WAKEUP);
rb->queue_post(&thread_q, EV_WAKEUP, 0);
}
target = center_index;
- slide_frame = slide_index << 16;
+ slide_frame = center_index << 16;
reset_slides();
}
@@ -3609,6 +3611,7 @@ static int settings_menu(void)
break;
/* fallthrough if changed, since cache needs to be rebuilt */
case 10:
+ pf_cfg.update_albumart = false;
pf_cfg.cache_version = CACHE_REBUILD;
rb->remove(EMPTY_SLIDE);
configfile_save(CONFIG_FILE, config,
@@ -3616,7 +3619,8 @@ static int settings_menu(void)
rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
break;
case 11:
- pf_cfg.cache_version = CACHE_UPDATE;
+ pf_cfg.update_albumart = true;
+ pf_cfg.cache_version = CACHE_REBUILD;
rb->remove(EMPTY_SLIDE);
configfile_save(CONFIG_FILE, config,
CONFIG_NUM_ITEMS, CONFIG_VERSION);
@@ -4319,13 +4323,13 @@ static int pictureflow_main(const char* selected_file)
pf_idx.buf_sz -= aa_bufsz;
if (!create_empty_slide(pf_cfg.cache_version != CACHE_VERSION)) {
- config_save(CACHE_REBUILD);
+ config_save(CACHE_REBUILD, false);
error_wait("Could not load the empty slide");
return PLUGIN_ERROR;
}
if ((pf_cfg.cache_version != CACHE_VERSION) && !create_albumart_cache()) {
- config_save(CACHE_REBUILD);
+ config_save(CACHE_REBUILD, false);
error_wait("Could not create album art cache");
} else if(aa_cache.inspected < pf_idx.album_ct) {
rb->splash(HZ * 2, "Updating album art cache in background");
@@ -4333,7 +4337,7 @@ static int pictureflow_main(const char* selected_file)
if (pf_cfg.cache_version != CACHE_VERSION)
{
- config_save(CACHE_VERSION);
+ config_save(CACHE_VERSION, pf_cfg.update_albumart);
}
rb->buflib_init(&buf_ctx, (void *)pf_idx.buf, pf_idx.buf_sz);
@@ -4416,7 +4420,12 @@ static int pictureflow_main(const char* selected_file)
break;
case pf_idle:
render_all_slides();
- incremental_albumart_cache(false);
+ if (aa_cache.inspected < pf_idx.album_ct)
+ {
+ buf_ctx_lock();
+ incremental_albumart_cache(false);
+ buf_ctx_unlock();
+ }
break;
}
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c
index e5f00e307b..c4378a0356 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -313,7 +313,8 @@ enum plugin_status plugin_start(const void* parameter)
int button;
bool quit = false, usb = false;
const char *file = parameter;
- if(!parameter) return PLUGIN_ERROR;
+ if(!parameter || (file[0] != '/')) return PLUGIN_ERROR;
+
#ifdef HAVE_TOUCHSCREEN
rb->touchscreen_set_mode(rb->global_settings->touch_mode);
#endif
diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c
index a34cb77669..af6aa40ea0 100644
--- a/apps/plugins/sliding_puzzle.c
+++ b/apps/plugins/sliding_puzzle.c
@@ -468,8 +468,8 @@ static const char * initial_bmp_path=NULL;
static const char * get_albumart_bmp_path(void)
{
struct mp3entry* track = rb->audio_current_track();
-
- if (!track || !track->path || track->path[0] == '\0')
+ /* Note rb->audio_current_track->path should never be null */
+ if (!track || track->path[0] == '\0')
return NULL;
if (!rb->search_albumart_files(track, "", albumart_path, MAX_PATH ) )
diff --git a/apps/plugins/test_usb.c b/apps/plugins/test_usb.c
new file mode 100644
index 0000000000..6bb77c40be
--- /dev/null
+++ b/apps/plugins/test_usb.c
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2022 Aidan MacDonald
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "plugin.h"
+#include "logf.h"
+
+#undef DEBUGF
+#define DEBUGF(...)
+//#define DEBUGF printf
+
+#define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF)
+
+unsigned char stack[DEFAULT_STACK_SIZE];
+struct event_queue queue;
+int thread_id;
+const char* state = "none";
+const char* prev_state = "none";
+
+static void main_loop(void)
+{
+ bool exiting = false;
+ struct queue_event ev;
+
+ while(true) {
+ rb->queue_wait(&queue, &ev);
+
+ /* events that are handled whether exiting or not */
+ switch(ev.id) {
+ case EV_EXIT:
+ return;
+ }
+
+ if(exiting)
+ continue;
+
+ /* events handled only when not exiting */
+ switch(ev.id) {
+ case SYS_USB_CONNECTED:
+ prev_state = state;
+ state = "connected";
+ logf("test_usb: connect ack %ld", *rb->current_tick);
+ DEBUGF("test_usb: connect ack %ld\n", *rb->current_tick);
+ rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ break;
+
+ case SYS_USB_DISCONNECTED:
+ prev_state = state;
+ state = "disconnected";
+ logf("test_usb: disconnect %ld", *rb->current_tick);
+ DEBUGF("test_usb: disconnect %ld\n", *rb->current_tick);
+ break;
+
+ case SYS_POWEROFF:
+ case SYS_REBOOT:
+ prev_state = state;
+ state = "exiting";
+ exiting = true;
+ break;
+ }
+ }
+}
+
+static void kill_tsr(void)
+{
+ rb->queue_post(&queue, EV_EXIT, 0);
+ rb->thread_wait(thread_id);
+ rb->queue_delete(&queue);
+}
+
+static bool exit_tsr(bool reenter)
+{
+ MENUITEM_STRINGLIST(menu, "USB test menu", NULL,
+ "Status", "Stop plugin", "Back");
+
+ while(true) {
+ int result = reenter ? rb->do_menu(&menu, NULL, NULL, false) : 1;
+ switch(result) {
+ case 0:
+ rb->splashf(HZ, "State: %s", state);
+ rb->splashf(HZ, "Prev: %s", prev_state);
+ break;
+ case 1:
+ rb->splashf(HZ, "Stopping USB test thread");
+ kill_tsr();
+ return true;
+ case 2:
+ return false;
+ }
+ }
+}
+
+static void run_tsr(void)
+{
+ rb->queue_init(&queue, true);
+ thread_id = rb->create_thread(main_loop, stack, sizeof(stack),
+ 0, "test_usb TSR"
+ IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU));
+ rb->plugin_tsr(exit_tsr);
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ (void)parameter;
+ MENUITEM_STRINGLIST(menu, "USB test menu", NULL,
+ "Start", "Quit");
+
+ switch(rb->do_menu(&menu, NULL, NULL, false)) {
+ case 0:
+ run_tsr();
+ rb->splashf(HZ, "Thread started");
+ return PLUGIN_OK;
+ case 1:
+ return PLUGIN_OK;
+ default:
+ return PLUGIN_ERROR;
+ }
+}
diff --git a/apps/plugins/xworld/engine.c b/apps/plugins/xworld/engine.c
index b09e320078..d99d9df6c6 100644
--- a/apps/plugins/xworld/engine.c
+++ b/apps/plugins/xworld/engine.c
@@ -293,7 +293,7 @@ void engine_processInput(struct Engine* e) {
e->sys->input.save = false;
}
if (e->sys->input.fastMode) {
- e->vm._fastMode = !&e->vm._fastMode;
+ e->vm._fastMode = !e->vm._fastMode;
e->sys->input.fastMode = false;
}
if (e->sys->input.stateSlot != 0) {
diff --git a/apps/settings.h b/apps/settings.h
index 9af8e27e5e..092c04a76b 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -868,6 +868,12 @@ struct user_settings
#if defined(DX50) || defined(DX90) || (defined(HAVE_USB_POWER) && !defined(USB_NONE) && !defined(SIMULATOR))
int usb_mode;
#endif
+#if defined(BUTTON_REC) || \
+ (CONFIG_KEYPAD == GIGABEAT_PAD) || \
+ (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ (CONFIG_KEYPAD == IRIVER_H10_PAD)
+ bool clear_settings_on_hold;
+#endif
};
/** global variables **/
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 0e39a58b1a..5fd7e0459b 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -2113,10 +2113,23 @@ const struct settings_list settings[] = {
HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK, HOTKEY_PLUGIN),
TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree,
LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree",
- "off,open with,delete,insert,insert shuffled",
- UNIT_INT, hotkey_formatter, hotkey_getlang, NULL, 5, HOTKEY_OFF,
- HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_INSERT, HOTKEY_INSERT_SHUFFLED),
+#ifdef HAVE_TAGCACHE
+ "off,properties,pictureflow,open with,delete,insert,insert shuffled",
+#else
+ "off,properties,open with,delete,insert,insert shuffled",
+#endif
+ UNIT_INT, hotkey_formatter, hotkey_getlang, NULL,
+#ifdef HAVE_TAGCACHE
+ 7,
+#else
+ 6,
+#endif
+ HOTKEY_OFF,HOTKEY_PROPERTIES,
+#ifdef HAVE_TAGCACHE
+ HOTKEY_PICTUREFLOW,
#endif
+ HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_INSERT, HOTKEY_INSERT_SHUFFLED),
+#endif /* HAVE_HOTKEY */
INT_SETTING(F_TIME_SETTING, resume_rewind, LANG_RESUME_REWIND, 0,
"resume rewind", UNIT_SEC, 0, 60, 5,
@@ -2148,19 +2161,18 @@ const struct settings_list settings[] = {
LANG_USB_MODE,
USBMODE_DEFAULT,
"usb mode",
- "ask,mass storage,charge"
+ "mass storage,charge"
#if defined(DX50) || defined(DX90)
",adb"
#endif
,
#if defined(DX50) || defined(DX90)
ibasso_set_usb_mode,
- 4,
+ 3,
#else
usb_set_mode,
- 3,
+ 2,
#endif
- ID2P(LANG_ASK),
ID2P(LANG_USB_MODE_MASS_STORAGE),
ID2P(LANG_USB_MODE_CHARGE)
#if defined(DX50) || defined(DX90)
@@ -2168,6 +2180,13 @@ const struct settings_list settings[] = {
#endif
),
#endif
+#if defined(BUTTON_REC) || \
+ (CONFIG_KEYPAD == GIGABEAT_PAD) || \
+ (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ (CONFIG_KEYPAD == IRIVER_H10_PAD)
+ OFFON_SETTING(0, clear_settings_on_hold, LANG_CLEAR_SETTINGS_ON_HOLD,
+ true, "clear settings on hold", NULL),
+#endif
};
const int nb_settings = sizeof(settings)/sizeof(*settings);
diff --git a/bootloader/x1000/recovery.c b/bootloader/x1000/recovery.c
index c53fa376b9..371500826f 100644
--- a/bootloader/x1000/recovery.c
+++ b/bootloader/x1000/recovery.c
@@ -68,6 +68,8 @@ static const struct menuitem debug_menu_items[] = {
#ifdef HAVE_SCREENDUMP
{MENUITEM_ACTION, "Enable screenshots", &screenshot_enable},
#endif
+ {MENUITEM_ACTION, "Flash info", &show_flash_info},
+ {MENUITEM_ACTION, "Flash ONFI info", &show_flash_onfi_info},
#ifdef OF_PLAYER_ADDR
{MENUITEM_ACTION, "Dump OF player", &dump_of_player},
#endif
diff --git a/bootloader/x1000/utils.c b/bootloader/x1000/utils.c
index 4d3fb69e57..a2fd500f5d 100644
--- a/bootloader/x1000/utils.c
+++ b/bootloader/x1000/utils.c
@@ -31,6 +31,7 @@
#include "linuxboot.h"
#include "screendump.h"
#include "nand-x1000.h"
+#include "sfc-x1000.h"
/* Set to true if a SYS_USB_CONNECTED event is seen
* Set to false if a SYS_USB_DISCONNECTED event is seen
@@ -145,14 +146,15 @@ int load_uimage_file(const char* filename,
struct nand_reader_data
{
- nand_drv* ndrv;
+ struct nand_drv* ndrv;
nand_page_t page;
nand_page_t end_page;
unsigned offset;
uint32_t count;
};
-static int uimage_nand_reader_init(struct nand_reader_data* d, nand_drv* ndrv,
+static int uimage_nand_reader_init(struct nand_reader_data* d,
+ struct nand_drv* ndrv,
uint32_t addr, uint32_t length)
{
unsigned pg_size = ndrv->chip->page_size;
@@ -176,7 +178,7 @@ static int uimage_nand_reader_init(struct nand_reader_data* d, nand_drv* ndrv,
static ssize_t uimage_nand_reader(void* buf, size_t count, void* rctx)
{
struct nand_reader_data* d = rctx;
- nand_drv* ndrv = d->ndrv;
+ struct nand_drv* ndrv = d->ndrv;
unsigned pg_size = ndrv->chip->page_size;
size_t read_count = 0;
int rc;
@@ -187,6 +189,15 @@ static ssize_t uimage_nand_reader(void* buf, size_t count, void* rctx)
while(d->page < d->end_page && read_count < count) {
rc = nand_page_read(ndrv, d->page, ndrv->page_buf);
+
+ /* Ignore ECC errors on the first page of a block. This may
+ * indicate a bad block. */
+ if(rc == NAND_ERR_ECC_FAIL &&
+ d->page % ndrv->ppb == 0 && d->offset == 0) {
+ d->page += ndrv->ppb;
+ continue;
+ }
+
if(rc < 0)
return -1;
@@ -222,7 +233,7 @@ static ssize_t uimage_nand_reader(void* buf, size_t count, void* rctx)
int load_uimage_flash(uint32_t addr, uint32_t length,
struct uimage_header* uh, size_t* sizep)
{
- nand_drv* ndrv = nand_init();
+ struct nand_drv* ndrv = nand_init();
nand_lock(ndrv);
if(nand_open(ndrv) != NAND_SUCCESS) {
splashf(5*HZ, "NAND open failed");
@@ -258,7 +269,7 @@ int dump_flash(int fd, uint32_t addr, uint32_t length)
static char buf[8192];
int ret = 0;
- nand_drv* ndrv = nand_init();
+ struct nand_drv* ndrv = nand_init();
nand_lock(ndrv);
ret = nand_open(ndrv);
@@ -338,3 +349,150 @@ void dump_entire_flash(void)
dump_flash_file("/flash.img", 0, 2048 * 64 * 1024);
#endif
}
+
+static void probe_flash(int log_fd)
+{
+ static uint8_t buffer[CACHEALIGN_UP(32)] CACHEALIGN_ATTR;
+
+ /* Use parameters from maskrom */
+ const uint32_t clock_freq = X1000_EXCLK_FREQ; /* a guess */
+ const uint32_t dev_conf = jz_orf(SFC_DEV_CONF,
+ CE_DL(1), HOLD_DL(1), WP_DL(1),
+ CPHA(0), CPOL(0),
+ TSH(0), TSETUP(0), THOLD(0),
+ STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS),
+ SMP_DELAY(0));
+ const size_t readid_len = 4;
+
+ /* NOTE: This assumes the NAND driver is inactive. If this is not true,
+ * this will seriously mess up the NAND driver. */
+ sfc_open();
+ sfc_set_dev_conf(dev_conf);
+ sfc_set_clock(clock_freq);
+
+ /* Issue reset */
+ sfc_exec(NANDCMD_RESET, 0, NULL, 0);
+ mdelay(10);
+
+ /* Try various read ID commands (cf. Linux's SPI NAND identify routine) */
+ sfc_exec(NANDCMD_READID_OPCODE, 0, buffer, readid_len|SFC_READ);
+ fdprintf(log_fd, "readID opcode = %02x %02x %02x %02x\n",
+ buffer[0], buffer[1], buffer[2], buffer[3]);
+
+ sfc_exec(NANDCMD_READID_ADDR, 0, buffer, readid_len|SFC_READ);
+ fdprintf(log_fd, "readID address = %02x %02x %02x %02x\n",
+ buffer[0], buffer[1], buffer[2], buffer[3]);
+
+ sfc_exec(NANDCMD_READID_DUMMY, 0, buffer, readid_len|SFC_READ);
+ fdprintf(log_fd, "readID dummy = %02x %02x %02x %02x\n",
+ buffer[0], buffer[1], buffer[2], buffer[3]);
+
+ /* Try reading Ingenic SFC boot block */
+ sfc_exec(NANDCMD_PAGE_READ, 0, NULL, 0);
+ mdelay(500);
+ sfc_exec(NANDCMD_READ_CACHE_SLOW, 0, buffer, 16|SFC_READ);
+
+ fdprintf(log_fd, "sfc params0 = %02x %02x %02x %02x\n",
+ buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3]);
+ fdprintf(log_fd, "sfc params1 = %02x %02x %02x %02x\n",
+ buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7]);
+ fdprintf(log_fd, "sfc params2 = %02x %02x %02x %02x\n",
+ buffer[ 8], buffer[ 9], buffer[10], buffer[11]);
+ fdprintf(log_fd, "sfc params3 = %02x %02x %02x %02x\n",
+ buffer[12], buffer[13], buffer[14], buffer[15]);
+
+ sfc_close();
+}
+
+void show_flash_info(void)
+{
+ if(check_disk(true) != DISK_PRESENT)
+ return;
+
+ int fd = open("/flash_info.txt", O_WRONLY|O_CREAT|O_TRUNC);
+ if(fd < 0) {
+ splashf(5*HZ, "Cannot create log file");
+ return;
+ }
+
+ splashf(0, "Probing flash...");
+ probe_flash(fd);
+
+ close(fd);
+ splashf(3*HZ, "Dumped flash info\nSee flash_info.txt");
+}
+
+static int dump_flash_onfi_info(int fd)
+{
+ struct nand_drv* ndrv = nand_init();
+ nand_lock(ndrv);
+
+ int ret = nand_open(ndrv);
+ if(ret != NAND_SUCCESS) {
+ splashf(5*HZ, "NAND open failed\n");
+ nand_unlock(ndrv);
+ return ret;
+ }
+
+ nand_enable_otp(ndrv, true);
+
+ /* read ONFI parameter page */
+ ret = nand_page_read(ndrv, 0x01, ndrv->page_buf);
+ if(ret != NAND_SUCCESS) {
+ splashf(5*HZ, "Dump failed\nNAND read error");
+ goto out;
+ }
+
+ uint8_t* buf = ndrv->page_buf;
+
+ fdprintf(fd, "signature = %08lx\n", load_le32(buf));
+ fdprintf(fd, "revision = %04x\n", load_le16(buf+4));
+
+ char strbuf[32];
+ memcpy(strbuf, &buf[32], 12);
+ strbuf[12] = '\0';
+ fdprintf(fd, "manufacturer = \"%s\"\n", strbuf);
+
+ memcpy(strbuf, &buf[44], 20);
+ strbuf[20] = '\0';
+ fdprintf(fd, "device model = \"%s\"\n", strbuf);
+
+ fdprintf(fd, "JEDEC mf. id = %02x\n", buf[64]);
+
+ fdprintf(fd, "data bytes per page = %lu\n", load_le32(buf+80));
+ fdprintf(fd, "spare bytes per page = %u\n", load_le16(buf+84));
+ fdprintf(fd, "pages per block = %lu\n", load_le32(buf+92));
+ fdprintf(fd, "blocks per lun = %lu\n", load_le32(buf+96));
+ fdprintf(fd, "number of luns = %u\n", buf[100]);
+ fdprintf(fd, "bits per cell = %u\n", buf[102]);
+ fdprintf(fd, "max bad blocks = %u\n", load_le16(buf+103));
+ fdprintf(fd, "block endurance = %u\n", load_le16(buf+105));
+ fdprintf(fd, "programs per page = %u\n", buf[110]);
+ fdprintf(fd, "page program time = %u\n", load_le16(buf+133));
+ fdprintf(fd, "block erase time = %u\n", load_le16(buf+135));
+ fdprintf(fd, "page read time = %u\n", load_le16(buf+137));
+
+ out:
+ nand_enable_otp(ndrv, false);
+ nand_close(ndrv);
+ nand_unlock(ndrv);
+ return ret;
+}
+
+void show_flash_onfi_info(void)
+{
+ if(check_disk(true) != DISK_PRESENT)
+ return;
+
+ int fd = open("/flash_onfi_info.txt", O_WRONLY|O_CREAT|O_TRUNC);
+ if(fd < 0) {
+ splashf(5*HZ, "Cannot create log file");
+ return;
+ }
+
+ splashf(0, "Reading ONFI info...");
+ dump_flash_onfi_info(fd);
+
+ close(fd);
+ splashf(3*HZ, "Dumped flash ONFI info\nSee flash_onfi_info.txt");
+}
diff --git a/bootloader/x1000/x1000bootloader.h b/bootloader/x1000/x1000bootloader.h
index 81c7f2aaa4..ba2baa33b5 100644
--- a/bootloader/x1000/x1000bootloader.h
+++ b/bootloader/x1000/x1000bootloader.h
@@ -197,6 +197,8 @@ int dump_flash_file(const char* file, uint32_t addr, uint32_t length);
void dump_of_player(void);
void dump_of_recovery(void);
void dump_entire_flash(void);
+void show_flash_info(void);
+void show_flash_onfi_info(void);
void recovery_menu(void) __attribute__((noreturn));
diff --git a/docs/CREDITS b/docs/CREDITS
index 6f7c23fc7e..3a6fcb83b9 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -710,6 +710,7 @@ Marc Aarts
Fabrice Bellard
Selami Dinçer
Matej Golian
+James Le Cuirot
The libmad team
The wavpack team
diff --git a/firmware/export/backtrace.h b/firmware/export/backtrace.h
index 283e293b2a..fb007ab004 100644
--- a/firmware/export/backtrace.h
+++ b/firmware/export/backtrace.h
@@ -25,6 +25,9 @@
#ifdef BACKTRACE_UNWARMINDER
#include "backtrace-unwarminder.h"
#endif
+#ifdef BACKTRACE_MIPSUNWINDER
+#include "backtrace-mipsunwinder.h"
+#endif
/* Print a backtrace using lcd_* functions, starting at the given line and updating
* the line number. On targets that support it (typically native targets), the
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 6465bdcb0e..a640a47b9c 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -926,6 +926,9 @@ Lyre prototype 1 */
#define INCLUDE_TIMEOUT_API
#define USB_DRIVER_CLOSE
#endif
+#if CONFIG_CPU == X1000
+#define USB_DRIVER_CLOSE
+#endif
#endif
#else /* !BOOTLOADER */
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h
index 2e4afbdf63..b03b1131bd 100644
--- a/firmware/export/config/ipod6g.h
+++ b/firmware/export/config/ipod6g.h
@@ -133,11 +133,9 @@
/* Define this if you have a software controlled poweroff */
#define HAVE_SW_POWEROFF
-/* The number of bytes reserved for loadable codecs */
-#define CODEC_SIZE 0x100000
-
-/* The number of bytes reserved for loadable plugins */
-#define PLUGIN_BUFFER_SIZE 0x80000
+/* Buffer for plugins and codecs. */
+#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */
+#define CODEC_SIZE 0x100000 /* 1 MiB */
/* 6g has a standard battery of 550mAh, except for the thick 6g (2007 160gb)
* which has a standard battery of 850mAh.
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 9558be559a..def3122205 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -258,7 +258,8 @@ static inline void cpu_boost_unlock(void)
#endif
/* Define this if target has support for generating backtraces */
-#ifdef CPU_ARM
+#if defined(CPU_ARM) || \
+ (defined(CPU_MIPS) && (CONFIG_PLATFORM & PLATFORM_NATIVE))
#define HAVE_RB_BACKTRACE
#endif
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index fe9f3bcfa1..c075fa83ec 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -134,7 +134,6 @@ enum
/* Supported usb modes. */
enum
{
- USB_MODE_ASK = 0,
USB_MODE_MASS_STORAGE,
USB_MODE_CHARGE,
USB_MODE_ADB
diff --git a/firmware/include/rbendian.h b/firmware/include/rbendian.h
index 8adcb544f9..8a6bb43a05 100644
--- a/firmware/include/rbendian.h
+++ b/firmware/include/rbendian.h
@@ -184,4 +184,241 @@ static inline uint32_t swaw32_hw(uint32_t value)
#error "Unknown endianness!"
#endif
+/*
+ * Generic unaligned loads
+ */
+static inline uint16_t _generic_load_le16(const void* p)
+{
+ const uint8_t* d = p;
+ return d[0] | (d[1] << 8);
+}
+
+static inline uint32_t _generic_load_le32(const void* p)
+{
+ const uint8_t* d = p;
+ return d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
+}
+
+static inline uint64_t _generic_load_le64(const void* p)
+{
+ const uint8_t* d = p;
+ return (((uint64_t)d[0] << 0) | ((uint64_t)d[1] << 8) |
+ ((uint64_t)d[2] << 16) | ((uint64_t)d[3] << 24) |
+ ((uint64_t)d[4] << 32) | ((uint64_t)d[5] << 40) |
+ ((uint64_t)d[6] << 48) | ((uint64_t)d[7] << 56));
+}
+
+static inline uint16_t _generic_load_be16(const void* p)
+{
+ const uint8_t* d = p;
+ return (d[0] << 8) | d[1];
+}
+
+static inline uint32_t _generic_load_be32(const void* p)
+{
+ const uint8_t* d = p;
+ return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+static inline uint64_t _generic_load_be64(const void* p)
+{
+ const uint8_t* d = p;
+ return (((uint64_t)d[0] << 56) | ((uint64_t)d[1] << 48) |
+ ((uint64_t)d[2] << 40) | ((uint64_t)d[3] << 32) |
+ ((uint64_t)d[4] << 24) | ((uint64_t)d[5] << 16) |
+ ((uint64_t)d[6] << 8) | ((uint64_t)d[7] << 0));
+}
+
+static inline void _generic_store_le16(void* p, uint16_t val)
+{
+ uint8_t* d = p;
+ d[0] = val & 0xff;
+ d[1] = (val >> 8) & 0xff;
+}
+
+static inline void _generic_store_le32(void* p, uint32_t val)
+{
+ uint8_t* d = p;
+ d[0] = val & 0xff;
+ d[1] = (val >> 8) & 0xff;
+ d[2] = (val >> 16) & 0xff;
+ d[3] = (val >> 24) & 0xff;
+}
+
+static inline void _generic_store_le64(void* p, uint64_t val)
+{
+ uint8_t* d = p;
+ d[0] = val & 0xff;
+ d[1] = (val >> 8) & 0xff;
+ d[2] = (val >> 16) & 0xff;
+ d[3] = (val >> 24) & 0xff;
+ d[4] = (val >> 32) & 0xff;
+ d[5] = (val >> 40) & 0xff;
+ d[6] = (val >> 48) & 0xff;
+ d[7] = (val >> 56) & 0xff;
+}
+
+static inline void _generic_store_be16(void* p, uint16_t val)
+{
+ uint8_t* d = p;
+ d[0] = (val >> 8) & 0xff;
+ d[1] = val & 0xff;
+}
+
+static inline void _generic_store_be32(void* p, uint32_t val)
+{
+ uint8_t* d = p;
+ d[0] = (val >> 24) & 0xff;
+ d[1] = (val >> 16) & 0xff;
+ d[2] = (val >> 8) & 0xff;
+ d[3] = val & 0xff;
+}
+
+static inline void _generic_store_be64(void* p, uint64_t val)
+{
+ uint8_t* d = p;
+ d[0] = (val >> 56) & 0xff;
+ d[1] = (val >> 48) & 0xff;
+ d[2] = (val >> 40) & 0xff;
+ d[3] = (val >> 32) & 0xff;
+ d[4] = (val >> 24) & 0xff;
+ d[5] = (val >> 16) & 0xff;
+ d[6] = (val >> 8) & 0xff;
+ d[7] = val & 0xff;
+}
+
+#if !defined(HAVE_UNALIGNED_LOAD_STORE)
+
+/* Use generic unaligned loads */
+#define load_le16 _generic_load_le16
+#define load_le32 _generic_load_le32
+#define load_le64 _generic_load_le64
+#define load_be16 _generic_load_be16
+#define load_be32 _generic_load_be32
+#define load_be64 _generic_load_be64
+#define store_le16 _generic_store_le16
+#define store_le32 _generic_store_le32
+#define store_le64 _generic_store_le64
+#define store_be16 _generic_store_be16
+#define store_be32 _generic_store_be32
+#define store_be64 _generic_store_be64
+
+/* Define host byte order unaligned load */
+#if defined(ROCKBOX_LITTLE_ENDIAN)
+# define load_h16 load_le16
+# define load_h32 load_le32
+# define load_h64 load_le64
+# define store_h16 store_le16
+# define store_h32 store_le32
+# define store_h64 store_le64
+#elif defined(ROCKBOX_BIG_ENDIAN)
+# define load_h16 load_be16
+# define load_h32 load_be32
+# define load_h64 load_be64
+# define store_h16 store_be16
+# define store_h32 store_be32
+# define store_h64 store_be64
+#else
+# error
+#endif
+
+#else /* HAVE_UNALIGNED_LOAD_STORE */
+
+/* The arch should define unaligned loads in host byte order */
+#if defined(ROCKBOX_LITTLE_ENDIAN)
+# define load_le16 load_h16
+# define load_le32 load_h32
+# define load_le64 load_h64
+# define load_be16(p) swap16(load_h16((p)))
+# define load_be32(p) swap32(load_h32((p)))
+# define load_be64(p) swap64(load_h64((p)))
+# define store_le16 store_h16
+# define store_le32 store_h32
+# define store_le64 store_h64
+# define store_be16(p,v) store_h16((p),swap16((v)))
+# define store_be32(p,v) store_h32((p),swap32((v)))
+# define store_be64(p,v) store_h64((p),swap64((v)))
+#elif defined(ROCKBOX_BIG_ENDIAN)
+# define load_le16(p) swap16(load_h16((p)))
+# define load_le32(p) swap32(load_h32((p)))
+# define load_le64(p) swap64(load_h64((p)))
+# define load_be16 load_h16
+# define load_be32 load_h32
+# define load_be64 load_h64
+# define store_le16(p,v) store_h16((p),swap16((v)))
+# define store_le32(p,v) store_h32((p),swap32((v)))
+# define store_le64(p,v) store_h64((p),swap64((v)))
+# define store_be16 store_h16
+# define store_be32 store_h32
+# define store_be64 store_h64
+#else
+# error
+#endif
+
+#endif /* HAVE_UNALIGNED_LOAD_STORE */
+
+/*
+ * Aligned loads
+ */
+
+static inline uint16_t load_h16_aligned(const void* p)
+{
+ return *(const uint16_t*)p;
+}
+
+static inline uint32_t load_h32_aligned(const void* p)
+{
+ return *(const uint32_t*)p;
+}
+
+static inline uint64_t load_h64_aligned(const void* p)
+{
+ return *(const uint64_t*)p;
+}
+
+static inline void store_h16_aligned(void* p, uint16_t val)
+{
+ *(uint16_t*)p = val;
+}
+
+static inline void store_h32_aligned(void* p, uint32_t val)
+{
+ *(uint32_t*)p = val;
+}
+
+static inline void store_h64_aligned(void* p, uint64_t val)
+{
+ *(uint64_t*)p = val;
+}
+
+#if defined(ROCKBOX_LITTLE_ENDIAN)
+# define load_le16_aligned load_h16_aligned
+# define load_le32_aligned load_h32_aligned
+# define load_le64_aligned load_h64_aligned
+# define load_be16_aligned(p) swap16(load_h16_aligned((p)))
+# define load_be32_aligned(p) swap32(load_h32_aligned((p)))
+# define load_be64_aligned(p) swap64(load_h64_aligned((p)))
+# define store_le16_aligned store_h16_aligned
+# define store_le32_aligned store_h32_aligned
+# define store_le64_aligned store_h64_aligned
+# define store_be16_aligned(p,v) store_h16_aligned((p),swap16((v)))
+# define store_be32_aligned(p,v) store_h32_aligned((p),swap32((v)))
+# define store_be64_aligned(p,v) store_h64_aligned((p),swap64((v)))
+#elif defined(ROCKBOX_BIG_ENDIAN)
+# define load_le16_aligned(p) swap16(load_h16_aligned((p)))
+# define load_le32_aligned(p) swap32(load_h32_aligned((p)))
+# define load_le64_aligned(p) swap64(load_h64_aligned((p)))
+# define load_be16_aligned load_h16_aligned
+# define load_be32_aligned load_h32_aligned
+# define load_be64_aligned load_h64_aligned
+# define store_le16_aligned(p,v) store_h16_aligned((p),swap16((v)))
+# define store_le32_aligned(p,v) store_h32_aligned((p),swap32((v)))
+# define store_le64_aligned(p,v) store_h64_aligned((p),swap64((v)))
+# define store_be16_aligned store_h16_aligned
+# define store_be32_aligned store_h32_aligned
+# define store_be64_aligned store_h64_aligned
+#else
+# error "Unknown endian!"
+#endif
+
#endif /* _RBENDIAN_H_ */
diff --git a/firmware/panic.c b/firmware/panic.c
index fcfa8b2bb8..586ecb6e0a 100644
--- a/firmware/panic.c
+++ b/firmware/panic.c
@@ -32,9 +32,9 @@
#include "system.h"
#include "logf.h"
-#if defined(CPU_ARM)
+#ifdef HAVE_RB_BACKTRACE
#include "gcc_extensions.h"
-#include <backtrace.h>
+#include "backtrace.h"
#endif
static char panic_buf[128];
@@ -65,6 +65,12 @@ void panicf_f( const char *fmt, ...)
);
int pc = (int)__builtin_return_address(0);
+#elif defined(BACKTRACE_MIPSUNWINDER)
+void panicf( const char *fmt, ... )
+{
+ /* NOTE: these are obtained by the backtrace lib */
+ const int pc = 0;
+ const int sp = 0;
#else
void panicf( const char *fmt, ...)
{
diff --git a/firmware/target/mips/ingenic_jz47xx/crt0.S b/firmware/target/mips/ingenic_jz47xx/crt0.S
index 258a5c02fc..1652bea8e5 100644
--- a/firmware/target/mips/ingenic_jz47xx/crt0.S
+++ b/firmware/target/mips/ingenic_jz47xx/crt0.S
@@ -185,7 +185,7 @@ _irq_stack_loop:
jal system_main /* Init clocks etc first */
ssnop
j main
- ssnop
+ move ra, zero /* init backtrace root */
/*
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
index 474d45edee..8ff6d4bc1e 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
@@ -54,16 +54,14 @@
OUT = HOST->DEV, (ie we recv)
*/
-enum ep_type
-{
+enum ep_type {
ep_control,
ep_bulk,
ep_interrupt,
ep_isochronous
};
-struct usb_endpoint
-{
+struct usb_endpoint {
const enum ep_type type;
const long fifo_addr;
unsigned short fifo_size;
@@ -76,8 +74,7 @@ struct usb_endpoint
volatile void *buf;
volatile size_t length;
- union
- {
+ union {
volatile size_t sent;
volatile size_t received;
};
@@ -94,8 +91,7 @@ struct usb_endpoint
#define short_not_ok 1 /* only works for mass storage.. */
#define ep_doublebuf(__ep) 0
-static union
-{
+static union {
int buf[64 / sizeof(int)];
struct usb_ctrlrequest request;
} ep0_rx;
@@ -106,7 +102,7 @@ static volatile bool ep0_data_requested = false;
static struct usb_endpoint endpoints[] =
{
EP_INIT(ep_control, USB_FIFO_EP(0), 64, NULL),
- EP_INIT(ep_control, USB_FIFO_EP(0), 64, ep0_rx.buf),
+ EP_INIT(ep_control, USB_FIFO_EP(0), 64, NULL),
EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL),
EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL),
EP_INIT(ep_interrupt, USB_FIFO_EP(2), 512, NULL),
@@ -127,19 +123,14 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size)
register unsigned int s = size >> 2;
register unsigned int x;
- if(size > 0)
- {
- if( ((unsigned int)ptr & 3) == 0 )
- {
- while(s--)
+ if(size > 0) {
+ if (((unsigned int)ptr & 3) == 0) {
+ while(s--) {
*ptr32++ = REG32(ep->fifo_addr);
-
+ }
ptr = (unsigned char*)ptr32;
- }
- else
- {
- while(s--)
- {
+ } else {
+ while(s--) {
x = REG32(ep->fifo_addr);
*ptr++ = x & 0xFF; x >>= 8;
*ptr++ = x & 0xFF; x >>= 8;
@@ -147,10 +138,10 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size)
*ptr++ = x;
}
}
-
s = size & 3;
- while(s--)
+ while(s--) {
*ptr++ = REG8(ep->fifo_addr);
+ }
}
}
@@ -163,18 +154,14 @@ static void writeFIFO(struct usb_endpoint *ep, size_t size)
register size_t s = size >> 2;
register unsigned int x;
- if(size > 0)
- {
- if( ((unsigned int)d8 & 3) == 0 )
- {
- while (s--)
+ if (size > 0) {
+ if (((unsigned int)d8 & 3) == 0) {
+ while (s--) {
REG32(ep->fifo_addr) = *d32++;
+ }
d8 = (unsigned char *)d32;
- }
- else
- {
- while (s--)
- {
+ } else {
+ while (s--) {
x = (unsigned int)(*d8++) & 0xff;
x |= ((unsigned int)(*d8++) & 0xff) << 8;
x |= ((unsigned int)(*d8++) & 0xff) << 16;
@@ -182,11 +169,9 @@ static void writeFIFO(struct usb_endpoint *ep, size_t size)
REG32(ep->fifo_addr) = x;
}
}
-
- if( (s = size & 3) )
- {
- while (s--)
- REG8(ep->fifo_addr) = *d8++;
+ s = size & 3;
+ while (s--) {
+ REG8(ep->fifo_addr) = *d8++;
}
}
}
@@ -195,18 +180,17 @@ static void flushFIFO(struct usb_endpoint *ep)
{
logf("%s(%d)", __func__, EP_NUMBER(ep));
- switch (ep->type)
- {
- case ep_control:
+ switch (ep->type) {
+ case ep_control:
break;
-
- case ep_bulk:
- case ep_interrupt:
- case ep_isochronous:
- if(EP_IS_IN(ep))
- REG_USB_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT);
- else
- REG_USB_OUTCSR |= (USB_OUTCSR_FF | USB_OUTCSR_CDT);
+ case ep_bulk:
+ case ep_interrupt:
+ case ep_isochronous:
+ if (EP_IS_IN(ep)) {
+ REG_USB_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT);
+ } else {
+ REG_USB_OUTCSR |= (USB_OUTCSR_FF | USB_OUTCSR_CDT);
+ }
break;
}
}
@@ -217,8 +201,9 @@ static inline void ep_transfer_completed(struct usb_endpoint* ep)
ep->length = 0;
ep->buf = NULL;
ep->busy = false;
- if(ep->wait)
+ if (ep->wait) {
semaphore_release(&ep->complete);
+ }
}
static void EP0_send(void)
@@ -232,27 +217,26 @@ static void EP0_send(void)
logf("%s(): 0x%x %d %d", __func__, csr0, ep->sent, ep->length);
- if(ep->sent == 0)
- {
+ if (ep->sent == 0) {
length = MIN(ep->length, ep->fifo_size);
REG_USB_CSR0 = (csr0 | USB_CSR0_FLUSHFIFO);
- }
- else
+ } else {
length = MIN(EP_BUF_LEFT(ep), ep->fifo_size);
+ }
writeFIFO(ep, length);
ep->sent += length;
- if(ep->sent >= ep->length)
- {
+ if (ep->sent >= ep->length) {
REG_USB_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */
- if (!ep->wait)
+ if (!ep->wait) {
usb_core_transfer_complete(EP_CONTROL, USB_DIR_IN, 0, ep->sent);
+ }
ep->rc = 0;
ep_transfer_completed(ep);
- }
- else
+ } else {
REG_USB_CSR0 = (csr0 | USB_CSR0_INPKTRDY);
+ }
}
static void EP0_handler(void)
@@ -270,8 +254,7 @@ static void EP0_handler(void)
/* Check for SentStall:
This bit is set when a STALL handshake is transmitted. The CPU should clear this bit.
*/
- if(csr0 & USB_CSR0_SENTSTALL)
- {
+ if (csr0 & USB_CSR0_SENTSTALL) {
REG_USB_CSR0 = csr0 & ~USB_CSR0_SENTSTALL;
return;
}
@@ -281,68 +264,62 @@ static void EP0_handler(void)
An interrupt will be generated and the FIFO flushed at this time.
The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit.
*/
- if(csr0 & USB_CSR0_SETUPEND)
- {
+ if (csr0 & USB_CSR0_SETUPEND) {
csr0 |= USB_CSR0_SVDSETUPEND;
REG_USB_CSR0 = csr0;
ep0_data_supplied = false;
ep0_data_requested = false;
- if (ep_send->busy)
- {
+ if (ep_send->busy) {
if (!ep_send->wait)
usb_core_transfer_complete(EP_CONTROL, USB_DIR_IN, -1, 0);
ep_transfer_completed(ep_send);
}
- if (ep_recv->busy)
- {
+ if (ep_recv->busy) {
usb_core_transfer_complete(EP_CONTROL, USB_DIR_OUT, -1, 0);
ep_transfer_completed(ep_recv);
}
}
/* Call relevant routines for endpoint 0 state */
- if(csr0 & USB_CSR0_OUTPKTRDY) /* There is a packet in the fifo */
- {
- if (ep_send->busy)
- {
- if (!ep_send->wait)
+ if (csr0 & USB_CSR0_OUTPKTRDY) { /* There is a packet in the fifo */
+ if (ep_send->busy) {
+ if (!ep_send->wait) {
usb_core_transfer_complete(EP_CONTROL, USB_DIR_IN, -1, 0);
+ }
ep_transfer_completed(ep_send);
}
- if (ep_recv->busy && ep_recv->buf && ep_recv->length)
- {
+ if (ep_recv->busy && ep_recv->buf && ep_recv->length) {
unsigned int size = REG_USB_COUNT0;
readFIFO(ep_recv, size);
ep_recv->received += size;
- if (size < ep_recv->fifo_size || ep_recv->received >= ep_recv->length)
- {
+ if (size < ep_recv->fifo_size || ep_recv->received >= ep_recv->length) {
REG_USB_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND; /* Set data end! */
usb_core_transfer_complete(EP_CONTROL, USB_DIR_OUT, 0, ep_recv->received);
ep_transfer_completed(ep_recv);
+ } else {
+ REG_USB_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */
}
- else REG_USB_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */
- }
- else if (!ep0_data_supplied)
- {
+ } else if (!ep0_data_supplied) {
ep_recv->buf = ep0_rx.buf;
readFIFO(ep_recv, REG_USB_COUNT0);
csr0 |= USB_CSR0_SVDOUTPKTRDY;
- if (!ep0_rx.request.wLength)
- {
+ if (!ep0_rx.request.wLength) {
csr0 |= USB_CSR0_DATAEND; /* Set data end! */
ep0_data_requested = false;
ep0_data_supplied = false;
- }
- else if (ep0_rx.request.bRequestType & USB_DIR_IN)
+ } else if (ep0_rx.request.bRequestType & USB_DIR_IN) {
ep0_data_requested = true;
- else ep0_data_supplied = true;
+ } else {
+ ep0_data_supplied = true;
+ }
REG_USB_CSR0 = csr0;
usb_core_legacy_control_request(&ep0_rx.request);
ep_transfer_completed(ep_recv);
}
}
- else if (ep_send->busy)
+ else if (ep_send->busy) {
EP0_send();
+ }
}
/* Does new work */
@@ -429,7 +406,7 @@ static void EPIN_send(unsigned int endpoint)
#endif
/* Non-DMA code */
- if(ep->sent == 0)
+ if (ep->sent == 0)
length = MIN(ep->length, ep->fifo_size);
else
length = MIN(EP_BUF_LEFT(ep), ep->fifo_size);
@@ -494,7 +471,7 @@ static void EPIN_complete(unsigned int endpoint)
logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
- if(ep->sent >= ep->length) {
+ if (ep->sent >= ep->length) {
if (!ep->wait)
usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent);
ep->rc = 0;
@@ -516,9 +493,9 @@ static void EPOUT_handler(unsigned int endpoint)
}
select_endpoint(endpoint);
- while((csr = REG_USB_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY)) {
+ while ((csr = REG_USB_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY)) {
logf("%s(%d): 0x%x", __func__, endpoint, csr);
- if(csr & USB_OUTCSR_SENTSTALL) {
+ if (csr & USB_OUTCSR_SENTSTALL) {
logf("stall sent, flushing fifo..");
flushFIFO(ep);
REG_USB_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL;
@@ -593,7 +570,7 @@ static void EPOUT_handler(unsigned int endpoint)
logf("received: %d max length: %d", ep->received, ep->length);
- if(size < ep->fifo_size || ep->received >= ep->length) {
+ if (size < ep->fifo_size || ep->received >= ep->length) {
usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received);
ep_transfer_completed(ep);
logf("receive transfer_complete");
@@ -613,8 +590,7 @@ static void EPOUT_ready(unsigned int endpoint)
select_endpoint(endpoint);
csr = REG_USB_OUTCSR;
- if(!ep->busy)
- {
+ if (!ep->busy) {
logf("Entered EPOUT handler without work!");
return;
}
@@ -717,15 +693,15 @@ static void setup_endpoint(struct usb_endpoint *ep)
select_endpoint(endpoint);
- if (ep->busy)
- {
- if(EP_IS_IN(ep))
- {
+ if (ep->busy) {
+ if (EP_IS_IN(ep)) {
if (ep->wait)
semaphore_release(&ep->complete);
- else usb_core_transfer_complete(endpoint, USB_DIR_IN, -1, 0);
+ else
+ usb_core_transfer_complete(endpoint, USB_DIR_IN, -1, 0);
+ } else {
+ usb_core_transfer_complete(endpoint, USB_DIR_OUT, -1, 0);
}
- else usb_core_transfer_complete(endpoint, USB_DIR_OUT, -1, 0);
}
ep->busy = false;
@@ -733,17 +709,16 @@ static void setup_endpoint(struct usb_endpoint *ep)
ep->sent = 0;
ep->length = 0;
- if(ep->type != ep_control)
+ if (ep->type != ep_control)
ep->fifo_size = usb_drv_port_speed() ? 512 : 64;
ep->config = REG_USB_CONFIGDATA;
- if(EP_IS_IN(ep))
- {
+ if(EP_IS_IN(ep)) {
csr = (USB_INCSR_FF | USB_INCSR_CDT);
csrh = USB_INCSRH_MODE;
- if(ep->type == ep_interrupt)
+ if (ep->type == ep_interrupt)
csrh |= USB_INCSRH_FRCDATATOG;
REG_USB_INMAXP = ep->fifo_size;
@@ -754,9 +729,7 @@ static void setup_endpoint(struct usb_endpoint *ep)
if (ep->allocated)
REG_USB_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep));
- }
- else
- {
+ } else {
csr = (USB_OUTCSR_FF | USB_OUTCSR_CDT);
csrh = 0;
@@ -813,8 +786,7 @@ static void udc_reset(void)
endpoints[0].config = REG_USB_CONFIGDATA;
endpoints[1].config = REG_USB_CONFIGDATA;
- if (endpoints[0].busy)
- {
+ if (endpoints[0].busy) {
if (endpoints[0].wait)
semaphore_release(&endpoints[0].complete);
else
@@ -837,7 +809,7 @@ static void udc_reset(void)
endpoints[1].allocated = true;
/* Reset other endpoints */
- for(i=2; i<TOTAL_EP(); i++)
+ for (i=2; i<TOTAL_EP(); i++)
setup_endpoint(&endpoints[i]);
ep0_data_supplied = false;
@@ -864,26 +836,26 @@ void OTG(void)
logf("IRQ %x %x %x %x", intrUSB, intrIn, intrOut, intrDMA);
/* EPIN & EPOUT are all handled in DMA */
- if(intrIn & USB_INTR_EP(0))
+ if (intrIn & USB_INTR_EP(0))
EP0_handler();
- if(intrIn & USB_INTR_EP(1))
+ if (intrIn & USB_INTR_EP(1))
EPIN_complete(1);
- if(intrIn & USB_INTR_EP(2))
+ if (intrIn & USB_INTR_EP(2))
EPIN_complete(2);
- if(intrOut & USB_INTR_EP(1))
+ if (intrOut & USB_INTR_EP(1))
EPOUT_ready(1);
- if(intrOut & USB_INTR_EP(2))
+ if (intrOut & USB_INTR_EP(2))
EPOUT_ready(2);
- if(intrUSB & USB_INTR_RESET)
+ if (intrUSB & USB_INTR_RESET)
udc_reset();
- if(intrUSB & USB_INTR_SUSPEND)
+ if (intrUSB & USB_INTR_SUSPEND)
logf("USB suspend");
- if(intrUSB & USB_INTR_RESUME)
+ if (intrUSB & USB_INTR_RESUME)
logf("USB resume");
#ifdef USE_USB_DMA
- if(intrDMA & (1<<USB_INTR_DMA_BULKIN))
+ if (intrDMA & (1<<USB_INTR_DMA_BULKIN))
EPDMA_handler(USB_INTR_DMA_BULKIN);
- if(intrDMA & (1<<USB_INTR_DMA_BULKOUT))
+ if (intrDMA & (1<<USB_INTR_DMA_BULKOUT))
EPDMA_handler(USB_INTR_DMA_BULKOUT);
#endif
}
@@ -896,11 +868,10 @@ bool usb_drv_stalled(int endpoint, bool in)
select_endpoint(endpoint);
- if(endpoint == EP_CONTROL)
+ if (endpoint == EP_CONTROL) {
return (REG_USB_CSR0 & USB_CSR0_SENDSTALL) != 0;
- else
- {
- if(in)
+ } else {
+ if (in)
return (REG_USB_INCSR & USB_INCSR_SENDSTALL) != 0;
else
return (REG_USB_OUTCSR & USB_OUTCSR_SENDSTALL) != 0;
@@ -915,24 +886,18 @@ void usb_drv_stall(int endpoint, bool stall, bool in)
select_endpoint(endpoint);
- if(endpoint == EP_CONTROL)
- {
+ if(endpoint == EP_CONTROL) {
if(stall)
REG_USB_CSR0 |= USB_CSR0_SENDSTALL;
else
REG_USB_CSR0 &= ~USB_CSR0_SENDSTALL;
- }
- else
- {
- if(in)
- {
+ } else {
+ if(in) {
if(stall)
REG_USB_INCSR |= USB_INCSR_SENDSTALL;
else
REG_USB_INCSR = (REG_USB_INCSR & ~USB_INCSR_SENDSTALL) | USB_INCSR_CDT;
- }
- else
- {
+ } else {
if(stall)
REG_USB_OUTCSR |= USB_OUTCSR_SENDSTALL;
else
@@ -965,7 +930,7 @@ void usb_init_device(void)
system_enable_irq(IRQ_OTG);
- for(unsigned i=0; i<TOTAL_EP(); i++)
+ for (unsigned i=0; i<TOTAL_EP(); i++)
semaphore_init(&endpoints[i].complete, 1, 0);
}
@@ -979,7 +944,7 @@ static int usb_oneshot_callback(struct timeout *tmo)
* and post appropriate event. */
usb_status_event(state);
- if(state == USB_EXTRACTED)
+ if (state == USB_EXTRACTED)
__gpio_as_irq_rise_edge(PIN_USB_DET);
else
__gpio_as_irq_fall_edge(PIN_USB_DET);
@@ -996,7 +961,7 @@ void GPIO_USB_DET(void)
void usb_enable(bool on)
{
- if(on)
+ if (on)
usb_core_init();
else
usb_core_exit();
@@ -1070,7 +1035,7 @@ static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length
ep->sent = 0;
ep->length = length;
ep->busy = true;
- if(blocking) {
+ if (blocking) {
ep->rc = -1;
ep->wait = true;
} else {
@@ -1085,7 +1050,7 @@ static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length
restore_irq(flags);
- if(blocking) {
+ if (blocking) {
semaphore_wait(&ep->complete, HZ);
ep->wait = false;
}
@@ -1097,8 +1062,7 @@ int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length);
- if (ep->allocated)
- {
+ if (ep->allocated) {
usb_drv_send_internal(ep, ptr, length, false);
return 0;
}
@@ -1112,8 +1076,7 @@ int usb_drv_send(int endpoint, void* ptr, int length)
logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length);
- if (ep->allocated)
- {
+ if (ep->allocated) {
usb_drv_send_internal(ep, ptr, length, true);
return ep->rc;
}
@@ -1188,7 +1151,8 @@ void usb_drv_cancel_all_transfers(void)
{
logf("%s()", __func__);
- unsigned int i, flags = disable_irq_save();
+ unsigned int i;
+ unsigned int flags = disable_irq_save();
#ifdef USE_USB_DMA
/* Disable DMA */
@@ -1204,7 +1168,8 @@ void usb_drv_cancel_all_transfers(void)
usb_core_transfer_complete(i >> 1, USB_DIR_OUT, -1, 0);
else if (endpoints[i].wait)
semaphore_release(&endpoints[i].complete);
- else usb_core_transfer_complete(i >> 1, USB_DIR_IN, -1, 0);
+ else
+ usb_core_transfer_complete(i >> 1, USB_DIR_IN, -1, 0);
}
if(i != 1) /* ep0 out needs special handling */
diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.c b/firmware/target/mips/ingenic_x1000/boot-x1000.c
index aa97bfcd85..2f2714c67a 100644
--- a/firmware/target/mips/ingenic_x1000/boot-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/boot-x1000.c
@@ -20,6 +20,7 @@
****************************************************************************/
#include "system.h"
+#include "usb.h"
#include "boot-x1000.h"
#include "nand-x1000.h"
#include "gpio-x1000.h"
@@ -113,6 +114,14 @@ void x1000_boot_linux(const void* source, size_t length,
{
size_t args_len = strlen(args);
+ /* Shut off USB to avoid "irq 21 nobody cared" error */
+ usb_close();
+ usb_enable(false);
+
+ /* clear USB PHY voodoo bits, not all kernels use them */
+ jz_writef(CPM_OPCR, GATE_USBPHY_CLK(0));
+ jz_writef(CPM_USBCDR, PHY_GATE(0));
+
disable_irq();
/* --- Beyond this point, do not call into DRAM --- */
@@ -121,7 +130,7 @@ void x1000_boot_linux(const void* source, size_t length,
/* copy argument string to a safe location */
char* args_copy = safe_mem + 32;
- iram_memmove(args_copy, args, args_len);
+ iram_memmove(args_copy, args, args_len+1);
/* generate argv array */
char** argv = safe_mem;
@@ -151,10 +160,6 @@ void x1000_dualboot_cleanup(void)
jz_writef(LCD_CTRL, BEDN(0), EOFM(0), SOFM(0), IFUM(0), QDM(0));
jz_writef(CPM_CLKGR, LCD(1));
- /* clear USB PHY voodoo bits, not all kernels use them */
- jz_writef(CPM_OPCR, GATE_USBPHY_CLK(0));
- jz_writef(CPM_USBCDR, PHY_GATE(0));
-
#if defined(FIIO_M3K) || defined(EROS_QN)
/*
* Need to bring up MPLL before booting Linux
@@ -262,7 +267,7 @@ void x1000_dualboot_init_uart2(void)
int x1000_dualboot_load_pdma_fw(void)
{
- nand_drv* n = nand_init();
+ struct nand_drv* n = nand_init();
nand_lock(n);
int ret = nand_open(n);
diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.h b/firmware/target/mips/ingenic_x1000/boot-x1000.h
index 1b7a0db1e9..eb476c513d 100644
--- a/firmware/target/mips/ingenic_x1000/boot-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/boot-x1000.h
@@ -36,10 +36,10 @@ enum {
};
void x1000_boot_rockbox(const void* source, size_t length)
- __attribute__((section(".icode")));
+ __attribute__((section(".icode.x1000_boot_rockbox")));
void x1000_boot_linux(const void* source, size_t length,
void* load, void* entry, const char* args)
- __attribute__((section(".icode")));
+ __attribute__((section(".icode.x1000_boot_linux")));
/* dual boot support code */
void x1000_dualboot_cleanup(void);
diff --git a/firmware/target/mips/ingenic_x1000/crt0.S b/firmware/target/mips/ingenic_x1000/crt0.S
index d079b01e2a..9d89ac1227 100644
--- a/firmware/target/mips/ingenic_x1000/crt0.S
+++ b/firmware/target/mips/ingenic_x1000/crt0.S
@@ -110,7 +110,7 @@ _realstart:
jal system_early_init
nop
j main
- nop
+ move ra, zero /* init backtrace root */
/* copy(void* src, void* dst, void* dst_end) */
_copy:
diff --git a/firmware/target/mips/ingenic_x1000/installer-x1000.c b/firmware/target/mips/ingenic_x1000/installer-x1000.c
index 66aa42d4a1..48850f8a62 100644
--- a/firmware/target/mips/ingenic_x1000/installer-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/installer-x1000.c
@@ -65,7 +65,7 @@ static const int num_updates = sizeof(updates) / sizeof(struct update_part);
/* calculate the offset and length of the update image; this is constant
* for a given target, based on the update parts and the NAND chip geometry.
*/
-static void get_image_loc(nand_drv* ndrv, size_t* offptr, size_t* lenptr)
+static void get_image_loc(struct nand_drv* ndrv, size_t* offptr, size_t* lenptr)
{
size_t blk_size = ndrv->chip->page_size << ndrv->chip->log2_ppb;
size_t img_off = 0;
@@ -119,7 +119,7 @@ struct updater {
size_t img_len; /* image length in flash = size of the buffer */
mtar_t* tar;
- nand_drv* ndrv;
+ struct nand_drv* ndrv;
};
static int updater_init(struct updater* u)
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c
index 5838b21b39..827a79ebce 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c
@@ -22,49 +22,15 @@
#include "nand-x1000.h"
#include "sfc-x1000.h"
#include "system.h"
+#include "logf.h"
#include <string.h>
-/* cmd mode a d phase format has data */
-#define NANDCMD_RESET SFC_CMD(0xff, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
-#define NANDCMD_READID(x,y) SFC_CMD(0x9f, SFC_TMODE_1_1_1, x, y, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_WR_EN SFC_CMD(0x06, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
-#define NANDCMD_GET_FEATURE SFC_CMD(0x0f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_SET_FEATURE SFC_CMD(0x1f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_PAGE_READ(x) SFC_CMD(0x13, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 0)
-#define NANDCMD_READ_CACHE(x) SFC_CMD(0x0b, SFC_TMODE_1_1_1, x, 8, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_READ_CACHE_x4(x) SFC_CMD(0x6b, SFC_TMODE_1_1_4, x, 8, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_PROGRAM_LOAD(x) SFC_CMD(0x02, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_PROGRAM_LOAD_x4(x) SFC_CMD(0x32, SFC_TMODE_1_1_4, x, 0, SFC_PFMT_ADDR_FIRST, 1)
-#define NANDCMD_PROGRAM_EXECUTE(x) SFC_CMD(0x10, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 0)
-#define NANDCMD_BLOCK_ERASE(x) SFC_CMD(0xd8, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 0)
-
-/* Feature registers are found in linux/mtd/spinand.h,
- * apparently these are pretty standardized */
-#define FREG_PROT 0xa0
-#define FREG_PROT_UNLOCK 0x00
-
-#define FREG_CFG 0xb0
-#define FREG_CFG_OTP_ENABLE (1 << 6)
-#define FREG_CFG_ECC_ENABLE (1 << 4)
-#define FREG_CFG_QUAD_ENABLE (1 << 0)
-
-#define FREG_STATUS 0xc0
-#define FREG_STATUS_BUSY (1 << 0)
-#define FREG_STATUS_EFAIL (1 << 2)
-#define FREG_STATUS_PFAIL (1 << 3)
-#define FREG_STATUS_ECC_MASK (3 << 4)
-#define FREG_STATUS_ECC_NO_FLIPS (0 << 4)
-#define FREG_STATUS_ECC_HAS_FLIPS (1 << 4)
-#define FREG_STATUS_ECC_UNCOR_ERR (2 << 4)
-
-const nand_chip supported_nand_chips[] = {
+const struct nand_chip supported_nand_chips[] = {
#if defined(FIIO_M3K) || defined(SHANLING_Q1) || defined(EROS_QN)
{
/* ATO25D1GA */
.mf_id = 0x9b,
.dev_id = 0x12,
- .row_cycles = 3,
- .col_cycles = 2,
.log2_ppb = 6, /* 64 pages */
.page_size = 2048,
.oob_size = 64,
@@ -78,20 +44,24 @@ const nand_chip supported_nand_chips[] = {
STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS),
SMP_DELAY(1)),
.flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT,
+ .cmd_page_read = NANDCMD_PAGE_READ,
+ .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE,
+ .cmd_block_erase = NANDCMD_BLOCK_ERASE,
+ .cmd_read_cache = NANDCMD_READ_CACHE_x4,
+ .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4,
},
#else
{ 0 },
#endif
};
-const size_t nr_supported_nand_chips =
- sizeof(supported_nand_chips) / sizeof(nand_chip);
+const size_t nr_supported_nand_chips = ARRAYLEN(supported_nand_chips);
-static nand_drv static_nand_drv;
+static struct nand_drv static_nand_drv;
static uint8_t static_scratch_buf[NAND_DRV_SCRATCHSIZE] CACHEALIGN_ATTR;
static uint8_t static_page_buf[NAND_DRV_MAXPAGESIZE] CACHEALIGN_ATTR;
-nand_drv* nand_init(void)
+struct nand_drv* nand_init(void)
{
static bool inited = false;
if(!inited) {
@@ -104,19 +74,19 @@ nand_drv* nand_init(void)
return &static_nand_drv;
}
-static uint8_t nand_get_reg(nand_drv* drv, uint8_t reg)
+static uint8_t nand_get_reg(struct nand_drv* drv, uint8_t reg)
{
sfc_exec(NANDCMD_GET_FEATURE, reg, drv->scratch_buf, 1|SFC_READ);
return drv->scratch_buf[0];
}
-static void nand_set_reg(nand_drv* drv, uint8_t reg, uint8_t val)
+static void nand_set_reg(struct nand_drv* drv, uint8_t reg, uint8_t val)
{
drv->scratch_buf[0] = val;
sfc_exec(NANDCMD_SET_FEATURE, reg, drv->scratch_buf, 1|SFC_WRITE);
}
-static void nand_upd_reg(nand_drv* drv, uint8_t reg, uint8_t msk, uint8_t val)
+static void nand_upd_reg(struct nand_drv* drv, uint8_t reg, uint8_t msk, uint8_t val)
{
uint8_t x = nand_get_reg(drv, reg);
x &= ~msk;
@@ -124,56 +94,43 @@ static void nand_upd_reg(nand_drv* drv, uint8_t reg, uint8_t msk, uint8_t val)
nand_set_reg(drv, reg, x);
}
-static bool identify_chip(nand_drv* drv)
+static bool identify_chip(struct nand_drv* drv)
{
/* Read ID command has some variations; Linux handles these 3:
* - no address or dummy bytes
* - 1 byte address, no dummy byte
* - no address byte, 1 byte dummy
*
- * Right now there is only a need for the 2nd variation, as that is
- * the method used by the ATO25D1GA.
- *
- * Some chips also output more than 2 ID bytes.
+ * Currently we use the 2nd method, aka. address read ID.
*/
- sfc_exec(NANDCMD_READID(1, 0), 0, drv->scratch_buf, 2|SFC_READ);
+ sfc_exec(NANDCMD_READID_ADDR, 0, drv->scratch_buf, 4|SFC_READ);
drv->mf_id = drv->scratch_buf[0];
drv->dev_id = drv->scratch_buf[1];
+ drv->dev_id2 = drv->scratch_buf[2];
for(size_t i = 0; i < nr_supported_nand_chips; ++i) {
- const nand_chip* chip = &supported_nand_chips[i];
- if(chip->mf_id == drv->mf_id && chip->dev_id == drv->dev_id) {
- drv->chip = chip;
- return true;
- }
+ const struct nand_chip* chip = &supported_nand_chips[i];
+ if(chip->mf_id != drv->mf_id || chip->dev_id != drv->dev_id)
+ continue;
+
+ if((chip->flags & NAND_CHIPFLAG_HAS_DEVID2) &&
+ chip->dev_id2 != drv->dev_id2)
+ continue;
+
+ drv->chip = chip;
+ return true;
}
return false;
}
-static void setup_chip_data(nand_drv* drv)
+static void setup_chip_data(struct nand_drv* drv)
{
drv->ppb = 1 << drv->chip->log2_ppb;
drv->fpage_size = drv->chip->page_size + drv->chip->oob_size;
}
-static void setup_chip_commands(nand_drv* drv)
-{
- /* Select commands appropriate for the chip */
- drv->cmd_page_read = NANDCMD_PAGE_READ(drv->chip->row_cycles);
- drv->cmd_program_execute = NANDCMD_PROGRAM_EXECUTE(drv->chip->row_cycles);
- drv->cmd_block_erase = NANDCMD_BLOCK_ERASE(drv->chip->row_cycles);
-
- if(drv->chip->flags & NAND_CHIPFLAG_QUAD) {
- drv->cmd_read_cache = NANDCMD_READ_CACHE_x4(drv->chip->col_cycles);
- drv->cmd_program_load = NANDCMD_PROGRAM_LOAD_x4(drv->chip->col_cycles);
- } else {
- drv->cmd_read_cache = NANDCMD_READ_CACHE(drv->chip->col_cycles);
- drv->cmd_program_load = NANDCMD_PROGRAM_LOAD(drv->chip->col_cycles);
- }
-}
-
-static void setup_chip_registers(nand_drv* drv)
+static void setup_chip_registers(struct nand_drv* drv)
{
/* Set chip registers to enter normal operation */
if(drv->chip->flags & NAND_CHIPFLAG_HAS_QE_BIT) {
@@ -182,14 +139,23 @@ static void setup_chip_registers(nand_drv* drv)
en ? FREG_CFG_QUAD_ENABLE : 0);
}
+ if(drv->chip->flags & NAND_CHIPFLAG_ON_DIE_ECC) {
+ /* Enable on-die ECC */
+ nand_upd_reg(drv, FREG_CFG, FREG_CFG_ECC_ENABLE, FREG_CFG_ECC_ENABLE);
+ }
+
/* Clear OTP bit to access the main data array */
nand_upd_reg(drv, FREG_CFG, FREG_CFG_OTP_ENABLE, 0);
/* Clear write protection bits */
nand_set_reg(drv, FREG_PROT, FREG_PROT_UNLOCK);
+
+ /* Call any chip-specific hooks */
+ if(drv->chip->setup_chip)
+ drv->chip->setup_chip(drv);
}
-int nand_open(nand_drv* drv)
+int nand_open(struct nand_drv* drv)
{
if(drv->refcount > 0) {
drv->refcount++;
@@ -210,7 +176,6 @@ int nand_open(nand_drv* drv)
return NAND_ERR_UNKNOWN_CHIP;
setup_chip_data(drv);
- setup_chip_commands(drv);
/* Set new SFC parameters */
sfc_set_dev_conf(drv->chip->dev_conf);
@@ -223,7 +188,7 @@ int nand_open(nand_drv* drv)
return NAND_SUCCESS;
}
-void nand_close(nand_drv* drv)
+void nand_close(struct nand_drv* drv)
{
--drv->refcount;
if(drv->refcount > 0)
@@ -237,7 +202,13 @@ void nand_close(nand_drv* drv)
sfc_close();
}
-static uint8_t nand_wait_busy(nand_drv* drv)
+void nand_enable_otp(struct nand_drv* drv, bool enable)
+{
+ nand_upd_reg(drv, FREG_CFG, FREG_CFG_OTP_ENABLE,
+ enable ? FREG_CFG_OTP_ENABLE : 0);
+}
+
+static uint8_t nand_wait_busy(struct nand_drv* drv)
{
uint8_t reg;
do {
@@ -246,10 +217,10 @@ static uint8_t nand_wait_busy(nand_drv* drv)
return reg;
}
-int nand_block_erase(nand_drv* drv, nand_block_t block)
+int nand_block_erase(struct nand_drv* drv, nand_block_t block)
{
sfc_exec(NANDCMD_WR_EN, 0, NULL, 0);
- sfc_exec(drv->cmd_block_erase, block, NULL, 0);
+ sfc_exec(drv->chip->cmd_block_erase, block, NULL, 0);
uint8_t status = nand_wait_busy(drv);
if(status & FREG_STATUS_EFAIL)
@@ -258,11 +229,12 @@ int nand_block_erase(nand_drv* drv, nand_block_t block)
return NAND_SUCCESS;
}
-int nand_page_program(nand_drv* drv, nand_page_t page, const void* buffer)
+int nand_page_program(struct nand_drv* drv, nand_page_t page, const void* buffer)
{
sfc_exec(NANDCMD_WR_EN, 0, NULL, 0);
- sfc_exec(drv->cmd_program_load, 0, (void*)buffer, drv->fpage_size|SFC_WRITE);
- sfc_exec(drv->cmd_program_execute, page, NULL, 0);
+ sfc_exec(drv->chip->cmd_program_load,
+ 0, (void*)buffer, drv->fpage_size|SFC_WRITE);
+ sfc_exec(drv->chip->cmd_program_execute, page, NULL, 0);
uint8_t status = nand_wait_busy(drv);
if(status & FREG_STATUS_PFAIL)
@@ -271,15 +243,29 @@ int nand_page_program(nand_drv* drv, nand_page_t page, const void* buffer)
return NAND_SUCCESS;
}
-int nand_page_read(nand_drv* drv, nand_page_t page, void* buffer)
+int nand_page_read(struct nand_drv* drv, nand_page_t page, void* buffer)
{
- sfc_exec(drv->cmd_page_read, page, NULL, 0);
+ sfc_exec(drv->chip->cmd_page_read, page, NULL, 0);
nand_wait_busy(drv);
- sfc_exec(drv->cmd_read_cache, 0, buffer, drv->fpage_size|SFC_READ);
+ sfc_exec(drv->chip->cmd_read_cache, 0, buffer, drv->fpage_size|SFC_READ);
+
+ if(drv->chip->flags & NAND_CHIPFLAG_ON_DIE_ECC) {
+ uint8_t status = nand_get_reg(drv, FREG_STATUS);
+
+ if(status & FREG_STATUS_ECC_UNCOR_ERR) {
+ logf("ecc uncorrectable error on page %08lx", (unsigned long)page);
+ return NAND_ERR_ECC_FAIL;
+ }
+
+ if(status & FREG_STATUS_ECC_HAS_FLIPS) {
+ logf("ecc corrected bitflips on page %08lx", (unsigned long)page);
+ }
+ }
+
return NAND_SUCCESS;
}
-int nand_read_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void* buffer)
+int nand_read_bytes(struct nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void* buffer)
{
if(byte_len == 0)
return NAND_SUCCESS;
@@ -307,7 +293,7 @@ int nand_read_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void*
return NAND_SUCCESS;
}
-int nand_write_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, const void* buffer)
+int nand_write_bytes(struct nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, const void* buffer)
{
if(byte_len == 0)
return NAND_SUCCESS;
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h
index 668b3e3f82..227c71e3f4 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h
@@ -32,6 +32,7 @@
#define NAND_ERR_PROGRAM_FAIL (-2)
#define NAND_ERR_ERASE_FAIL (-3)
#define NAND_ERR_UNALIGNED (-4)
+#define NAND_ERR_ECC_FAIL (-5)
/* keep max page size in sync with the NAND chip table in the .c file */
#define NAND_DRV_SCRATCHSIZE 32
@@ -41,6 +42,46 @@
#define NAND_CHIPFLAG_QUAD 0x0001
/* Chip requires QE bit set to enable quad I/O mode */
#define NAND_CHIPFLAG_HAS_QE_BIT 0x0002
+/* Chip has 2nd device ID byte */
+#define NAND_CHIPFLAG_HAS_DEVID2 0x0004
+/* True if the chip has on-die ECC */
+#define NAND_CHIPFLAG_ON_DIE_ECC 0x0008
+
+/* cmd mode a d phase format has data */
+#define NANDCMD_RESET SFC_CMD(0xff, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
+#define NANDCMD_READID_OPCODE SFC_CMD(0x9f, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_READID_ADDR SFC_CMD(0x9f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_READID_DUMMY SFC_CMD(0x9f, SFC_TMODE_1_1_1, 0, 8, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_WR_EN SFC_CMD(0x06, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
+#define NANDCMD_GET_FEATURE SFC_CMD(0x0f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_SET_FEATURE SFC_CMD(0x1f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_PAGE_READ SFC_CMD(0x13, SFC_TMODE_1_1_1, 3, 0, SFC_PFMT_ADDR_FIRST, 0)
+#define NANDCMD_READ_CACHE_SLOW SFC_CMD(0x03, SFC_TMODE_1_1_1, 2, 8, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_READ_CACHE SFC_CMD(0x0b, SFC_TMODE_1_1_1, 2, 8, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_READ_CACHE_x4 SFC_CMD(0x6b, SFC_TMODE_1_1_4, 2, 8, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_PROGRAM_EXECUTE SFC_CMD(0x10, SFC_TMODE_1_1_1, 3, 0, SFC_PFMT_ADDR_FIRST, 0)
+#define NANDCMD_PROGRAM_LOAD SFC_CMD(0x02, SFC_TMODE_1_1_1, 2, 0, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_PROGRAM_LOAD_x4 SFC_CMD(0x32, SFC_TMODE_1_1_4, 2, 0, SFC_PFMT_ADDR_FIRST, 1)
+#define NANDCMD_BLOCK_ERASE SFC_CMD(0xd8, SFC_TMODE_1_1_1, 3, 0, SFC_PFMT_ADDR_FIRST, 0)
+
+/* Feature registers are found in linux/mtd/spinand.h,
+ * apparently these are pretty standardized */
+#define FREG_PROT 0xa0
+#define FREG_PROT_UNLOCK 0x00
+
+#define FREG_CFG 0xb0
+#define FREG_CFG_OTP_ENABLE (1 << 6)
+#define FREG_CFG_ECC_ENABLE (1 << 4)
+#define FREG_CFG_QUAD_ENABLE (1 << 0)
+
+#define FREG_STATUS 0xc0
+#define FREG_STATUS_BUSY (1 << 0)
+#define FREG_STATUS_EFAIL (1 << 2)
+#define FREG_STATUS_PFAIL (1 << 3)
+#define FREG_STATUS_ECC_MASK (3 << 4)
+#define FREG_STATUS_ECC_NO_FLIPS (0 << 4)
+#define FREG_STATUS_ECC_HAS_FLIPS (1 << 4)
+#define FREG_STATUS_ECC_UNCOR_ERR (2 << 4)
/* Types to distinguish between block & page addresses in the API.
*
@@ -59,14 +100,13 @@
typedef uint32_t nand_block_t;
typedef uint32_t nand_page_t;
-typedef struct nand_chip {
+struct nand_drv;
+
+struct nand_chip {
/* Manufacturer and device ID bytes */
uint8_t mf_id;
uint8_t dev_id;
-
- /* Row/column address width */
- uint8_t row_cycles;
- uint8_t col_cycles;
+ uint8_t dev_id2;
/* Base2 logarithm of the number of pages per block */
unsigned log2_ppb;
@@ -89,9 +129,19 @@ typedef struct nand_chip {
/* Chip specific flags */
uint32_t flags;
-} nand_chip;
-typedef struct nand_drv {
+ /* SFC commands for issuing I/O ops */
+ uint32_t cmd_page_read;
+ uint32_t cmd_program_execute;
+ uint32_t cmd_block_erase;
+ uint32_t cmd_read_cache;
+ uint32_t cmd_program_load;
+
+ /* Chip-specific setup routine */
+ void(*setup_chip)(struct nand_drv* drv);
+};
+
+struct nand_drv {
/* NAND access lock. Needs to be held during any operations. */
struct mutex mutex;
@@ -113,7 +163,7 @@ typedef struct nand_drv {
uint8_t* page_buf;
/* Pointer to the chip data. */
- const nand_chip* chip;
+ const struct nand_chip* chip;
/* Pages per block = 1 << chip->log2_ppb */
unsigned ppb;
@@ -124,16 +174,10 @@ typedef struct nand_drv {
/* Probed mf_id / dev_id for debugging, in case identification fails. */
uint8_t mf_id;
uint8_t dev_id;
+ uint8_t dev_id2;
+};
- /* SFC commands used for I/O, these are set based on chip data */
- uint32_t cmd_page_read;
- uint32_t cmd_read_cache;
- uint32_t cmd_program_load;
- uint32_t cmd_program_execute;
- uint32_t cmd_block_erase;
-} nand_drv;
-
-extern const nand_chip supported_nand_chips[];
+extern const struct nand_chip supported_nand_chips[];
extern const size_t nr_supported_nand_chips;
/* Return the static NAND driver instance.
@@ -141,14 +185,14 @@ extern const size_t nr_supported_nand_chips;
* ALL normal Rockbox code should use this instance. The SPL does not
* use it, because it needs to manually place buffers in external RAM.
*/
-extern nand_drv* nand_init(void);
+extern struct nand_drv* nand_init(void);
-static inline void nand_lock(nand_drv* drv)
+static inline void nand_lock(struct nand_drv* drv)
{
mutex_lock(&drv->mutex);
}
-static inline void nand_unlock(nand_drv* drv)
+static inline void nand_unlock(struct nand_drv* drv)
{
mutex_unlock(&drv->mutex);
}
@@ -162,8 +206,11 @@ static inline void nand_unlock(nand_drv* drv)
*
* These functions require the lock to be held.
*/
-extern int nand_open(nand_drv* drv);
-extern void nand_close(nand_drv* drv);
+extern int nand_open(struct nand_drv* drv);
+extern void nand_close(struct nand_drv* drv);
+
+/* Enable/disable OTP access. OTP data pages are usually vendor-specific. */
+void nand_enable_otp(struct nand_drv* drv, bool enable);
/* Read / program / erase operations. Buffer needs to be cache-aligned for DMA.
* Read and program operate on full page data, ie. including OOB data areas.
@@ -171,15 +218,15 @@ extern void nand_close(nand_drv* drv);
* NOTE: ECC is not implemented. If it ever needs to be, these functions will
* probably use ECC transparently. All code should be written to expect this.
*/
-extern int nand_block_erase(nand_drv* drv, nand_block_t block);
-extern int nand_page_program(nand_drv* drv, nand_page_t page, const void* buffer);
-extern int nand_page_read(nand_drv* drv, nand_page_t page, void* buffer);
+extern int nand_block_erase(struct nand_drv* drv, nand_block_t block);
+extern int nand_page_program(struct nand_drv* drv, nand_page_t page, const void* buffer);
+extern int nand_page_read(struct nand_drv* drv, nand_page_t page, void* buffer);
/* Wrappers to read/write bytes. For simple access to the main data area only.
* The write address / length must align to a block boundary. Reads do not have
* any alignment requirement. OOB data is never read, and is written as 0xff.
*/
-extern int nand_read_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void* buffer);
-extern int nand_write_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, const void* buffer);
+extern int nand_read_bytes(struct nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void* buffer);
+extern int nand_write_bytes(struct nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, const void* buffer);
#endif /* __NAND_X1000_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/spl-nand-x1000.c b/firmware/target/mips/ingenic_x1000/spl-nand-x1000.c
index 82a05abf75..24eb42081e 100644
--- a/firmware/target/mips/ingenic_x1000/spl-nand-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/spl-nand-x1000.c
@@ -23,7 +23,7 @@
#include "gpio-x1000.h"
#include "nand-x1000.h"
-static nand_drv* ndrv = NULL;
+static struct nand_drv* ndrv = NULL;
int spl_storage_open(void)
{
@@ -31,7 +31,7 @@ int spl_storage_open(void)
gpioz_configure(GPIO_A, 0x3f << 26, GPIOF_DEVICE(1));
/* Allocate NAND driver manually in DRAM */
- ndrv = spl_alloc(sizeof(nand_drv));
+ ndrv = spl_alloc(sizeof(struct nand_drv));
ndrv->page_buf = spl_alloc(NAND_DRV_MAXPAGESIZE);
ndrv->scratch_buf = spl_alloc(NAND_DRV_SCRATCHSIZE);
ndrv->refcount = 0;
diff --git a/firmware/usb.c b/firmware/usb.c
index 4c122e8eea..c4d07c5533 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -491,37 +491,12 @@ static void NORETURN_ATTR usb_thread(void)
if (button_status() & ~USBPOWER_BTN_IGNORE)
new_usbmode = USB_MODE_MASS_STORAGE;
break;
-#ifndef BOOTLOADER
- case USB_MODE_ASK:
- new_usbmode = USB_MODE_ASK;
- break;
-#endif
default:
case USB_MODE_MASS_STORAGE:
if (button_status() & ~USBPOWER_BTN_IGNORE)
new_usbmode = USB_MODE_CHARGE;
break;
}
-
-#ifndef BOOTLOADER
- if (new_usbmode == USB_MODE_ASK)
- {
- push_current_activity(ACTIVITY_USBSCREEN);
- if (yesno_pop(ID2P(LANG_ENTER_USB_STORAGE_MODE_QUERY)))
- new_usbmode = USB_MODE_MASS_STORAGE;
- else
- new_usbmode = USB_MODE_CHARGE;
- pop_current_activity();
- /* Force full redraw */
-// queue_post(&button_queue, BUTTON_REDRAW, 0);
-// Alternative approach, as above is supposedly inadequate by design.
- FOR_NB_SCREENS(i)
- {
- struct screen *screen = &screens[i];
- screen->set_viewport(NULL);
- }
- }
-#endif
#endif
#ifndef USB_DETECT_BY_REQUEST
diff --git a/lib/mipsunwinder/SOURCES b/lib/mipsunwinder/SOURCES
new file mode 100644
index 0000000000..32fa57d157
--- /dev/null
+++ b/lib/mipsunwinder/SOURCES
@@ -0,0 +1,2 @@
+backtrace-mips32.c
+init_context_32.S
diff --git a/lib/mipsunwinder/backtrace-mips32.c b/lib/mipsunwinder/backtrace-mips32.c
new file mode 100644
index 0000000000..c5ab41e628
--- /dev/null
+++ b/lib/mipsunwinder/backtrace-mips32.c
@@ -0,0 +1,236 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * MIPS32 backtrace implementation
+ * Copyright (C) 2022 Aidan MacDonald
+ *
+ * References:
+ * https://yosefk.com/blog/getting-the-call-stack-without-a-frame-pointer.html
+ * https://elinux.org/images/6/68/ELC2008_-_Back-tracing_in_MIPS-based_Linux_Systems.pdf
+ * System V ABI MIPS Supplement, 3rd edition
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "backtrace.h"
+#include "lcd.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdalign.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#define MIN_ADDR 0x80000000ul
+#define MAX_ADDR (MIN_ADDR + (MEMORYSIZE * 1024 * 1024) - 1)
+
+static bool read_check(const void* addr, size_t alignment)
+{
+ if(addr < (const void*)MIN_ADDR ||
+ addr > (const void*)MAX_ADDR)
+ return false;
+
+ if((uintptr_t)addr & (alignment - 1))
+ return false;
+
+ return true;
+}
+
+static bool read32(const void* addr, uint32_t* val)
+{
+ if(!read_check(addr, alignof(uint32_t)))
+ return false;
+
+ *val = *(const uint32_t*)addr;
+ return true;
+}
+
+#if 0
+static bool read16(const void* addr, uint16_t* val)
+{
+ if(!read_check(addr, alignof(uint16_t)))
+ return false;
+
+ *val = *(const uint16_t*)addr;
+ return true;
+}
+
+static bool read8(const void* addr, uint8_t* val)
+{
+ if(!read_check(addr, alignof(uint8_t)))
+ return false;
+
+ *val = *(const uint8_t*)addr;
+ return true;
+}
+#endif
+
+static long extract_s16(uint32_t val)
+{
+#if 1
+ /* not ISO C, but gets GCC to emit 'seh' which is more compact */
+ return (int32_t)(val << 16) >> 16;
+#else
+ val &= 0xffff;
+
+ if(val > 0x7fff)
+ return (long)val - 0x10000l;
+ else
+ return val;
+#endif
+}
+
+/* TODO - cases not handled by the backtrace algorithm
+ *
+ * 1. functions that save the frame pointer will not be handled correctly
+ * (need to implement the algorithm specified by the System V ABI).
+ *
+ * 2. GCC can generate functions with a "false" stack pointer decrement,
+ * for some examples see read_bmp_fd and walk_path. those functions
+ * seem to be more difficult to deal with and the SysV algorithm will
+ * also get confused by them, but they are not common.
+ */
+int mips_bt_step(struct mips_bt_context* ctx)
+{
+ /* go backward and look for the stack pointer decrement */
+ uint32_t* pc = ctx->pc;
+ uint32_t insn;
+ long sp_off;
+
+ while(true) {
+ if(!read32(pc, &insn))
+ return 0;
+
+ /* addiu sp, sp, sp_off */
+ if((insn >> 16) == 0x27bd) {
+ sp_off = extract_s16(insn);
+ if(sp_off < 0)
+ break;
+ }
+
+ /* jr ra */
+ if(insn == 0x03e00008) {
+ /* end if this is not a leaf or we lack register info */
+ if(ctx->depth > 0 || !(ctx->valid & (1 << MIPSBT_RA))) {
+ mips_bt_debug(ctx, "unexpected leaf function");
+ return 0;
+ }
+
+ /* this is a leaf function - ra contains the return address
+ * and sp is unchanged */
+ ctx->pc = (void*)ctx->reg[MIPSBT_RA] - 8;
+ ctx->depth++;
+ return 1;
+ }
+
+ --pc;
+ }
+
+ mips_bt_debug(ctx, "found sp_off=%ld at %p", sp_off, pc);
+
+ /* now go forward and find the saved return address */
+ while((void*)pc < ctx->pc) {
+ if(!read32(pc, &insn))
+ return 0;
+
+ /* sw ra, ra_off(sp) */
+ if((insn >> 16) == 0xafbf) {
+ long ra_off = extract_s16(insn);
+ uint32_t save_ra;
+
+ /* load the saved return address */
+ mips_bt_debug(ctx, "load ra from %p+%ld", ctx->sp, ra_off);
+ if(!read32(ctx->sp + ra_off, &save_ra))
+ return 0;
+
+ if(save_ra == 0) {
+ mips_bt_debug("hit root");
+ return 0;
+ }
+
+ /* update bt context */
+ ctx->pc = (void*)save_ra - 8;
+ ctx->sp -= sp_off;
+
+ /* update saved register info */
+ ctx->reg[MIPSBT_RA] = save_ra;
+ ctx->valid |= (1 << MIPSBT_RA);
+
+ ctx->depth++;
+ return 1;
+ }
+
+ ++pc;
+ }
+
+ /* sometimes an exception occurs before ra is saved - in this case
+ * the ra register should contain the caller PC, but we still need
+ * to adjust the stack frame. */
+ if(ctx->depth == 0 && (ctx->valid & (1 << MIPSBT_RA))) {
+ ctx->pc = (void*)ctx->reg[MIPSBT_RA] - 8;
+ ctx->sp -= sp_off;
+
+ ctx->depth++;
+ return 1;
+ }
+
+ mips_bt_debug(ctx, "ra not found");
+ return 0;
+}
+
+#ifdef MIPSUNWINDER_DEBUG
+static void rb_backtrace_debugf(void* arg, const char* fmt, ...)
+{
+ static char buf[64];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ unsigned int* line = arg;
+ lcd_putsf(4, (*line)++, "%s", buf);
+ lcd_update();
+}
+#endif
+
+void rb_backtrace_ctx(void* arg, unsigned* line)
+{
+ struct mips_bt_context* ctx = arg;
+#ifdef MIPSUNWINDER_DEBUG
+ ctx->debugf = rb_backtrace_debugf;
+ ctx->debug_arg = line;
+#endif
+
+ do {
+ lcd_putsf(0, (*line)++, "%02d pc:%08lx sp:%08lx",
+ ctx->depth, (unsigned long)ctx->pc, (unsigned long)ctx->sp);
+ lcd_update();
+ } while(mips_bt_step(ctx));
+
+ lcd_puts(0, (*line)++, "bt end");
+ lcd_update();
+}
+
+void rb_backtrace(int pcAddr, int spAddr, unsigned* line)
+{
+ (void)pcAddr;
+ (void)spAddr;
+
+ struct mips_bt_context ctx;
+ mips_bt_start(&ctx);
+ mips_bt_step(&ctx); /* step over this function */
+
+ rb_backtrace_ctx(&ctx, line);
+}
diff --git a/lib/mipsunwinder/backtrace-mipsunwinder.h b/lib/mipsunwinder/backtrace-mipsunwinder.h
new file mode 100644
index 0000000000..4d6288b5fe
--- /dev/null
+++ b/lib/mipsunwinder/backtrace-mipsunwinder.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2022 Aidan MacDonald
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef BACKTRACE_MIPSUNWINDER_H
+#define BACKTRACE_MIPSUNWINDER_H
+
+/*#define MIPSUNWINDER_DEBUG*/
+
+#include <stdint.h>
+
+enum {
+ MIPSBT_RA,
+ MIPSBT_NREG,
+};
+
+struct mips_bt_context {
+ void* pc;
+ void* sp;
+ int depth;
+ uint32_t valid;
+ uint32_t reg[MIPSBT_NREG];
+#ifdef MIPSUNWINDER_DEBUG
+ void(*debugf)(void*, const char*, ...);
+ void* debug_arg;
+#endif
+};
+
+int mips_bt_step(struct mips_bt_context* ctx);
+void mips_bt_start(struct mips_bt_context* ctx);
+
+#ifdef MIPSUNWINDER_DEBUG
+# define mips_bt_debug(ctx, ...) \
+ do { struct mips_bt_context* __ctx = ctx; \
+ if(__ctx->debugf) \
+ __ctx->debugf(__ctx->debug_arg, __VA_ARGS__);\
+ } while(0)
+#else
+# define mips_bt_debug(...) do { } while(0)
+#endif
+
+/* NOTE: ignores pcAddr and spAddr, backtrace starts from caller */
+void rb_backtrace(int pcAddr, int spAddr, unsigned* line);
+
+/* given struct mips_bt_context argument, print stack traceback */
+void rb_backtrace_ctx(void* arg, unsigned* line);
+
+#endif /* BACKTRACE_MIPSUNWINDER_H */
diff --git a/lib/mipsunwinder/init_context_32.S b/lib/mipsunwinder/init_context_32.S
new file mode 100644
index 0000000000..a943d13dc3
--- /dev/null
+++ b/lib/mipsunwinder/init_context_32.S
@@ -0,0 +1,12 @@
+#include "mips.h"
+
+ .text
+ .global mips_bt_start
+
+mips_bt_start:
+ addiu v0, ra, -8
+ sw v0, 0(a0) /* ctx->pc = ra - 8 */
+ sw sp, 4(a0) /* ctx->sp = sp */
+ sw zero, 8(a0) /* ctx->depth = 0 */
+ sw zero, 12(a0) /* ctx->valid = 0 */
+ jr ra
diff --git a/lib/mipsunwinder/mipsunwinder.make b/lib/mipsunwinder/mipsunwinder.make
new file mode 100644
index 0000000000..ddd1ce078f
--- /dev/null
+++ b/lib/mipsunwinder/mipsunwinder.make
@@ -0,0 +1,23 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+#
+
+MIPSUNWINDERLIB_DIR = $(ROOTDIR)/lib/mipsunwinder
+MIPSUNWINDERLIB_SRC = $(call preprocess, $(MIPSUNWINDERLIB_DIR)/SOURCES)
+MIPSUNWINDERLIB_OBJ := $(call c2obj, $(MIPSUNWINDERLIB_SRC))
+
+OTHER_SRC += $(MIPSUNWINDERLIB_SRC)
+
+MIPSUNWINDERLIB = $(BUILDDIR)/lib/libmipsunwinder.a
+CORE_LIBS += $(MIPSUNWINDERLIB)
+
+INCLUDES += -I$(MIPSUNWINDERLIB_DIR)
+DEFINES += -DBACKTRACE_MIPSUNWINDER
+
+$(MIPSUNWINDERLIB): $(MIPSUNWINDERLIB_OBJ)
+ $(SILENT)$(shell rm -f $@)
+ $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/blip_buffer.c b/lib/rbcodec/codecs/libgme/blip_buffer.c
index ba0a6558d2..9aaa9d2482 100644
--- a/lib/rbcodec/codecs/libgme/blip_buffer.c
+++ b/lib/rbcodec/codecs/libgme/blip_buffer.c
@@ -53,7 +53,9 @@ void Blip_clear( struct Blip_Buffer* this )
this->reader_accum_ = 0;
this->modified = false;
+#if 0 // this is redundant as buffer is static and triggers -Waddress
if ( this->buffer_ )
+#endif
{
int count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this ));
memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (delta_t) );
diff --git a/lib/rbcodec/codecs/libopus/silk/NLSF2A.c b/lib/rbcodec/codecs/libopus/silk/NLSF2A.c
index d5b7730638..8f472f25f7 100644
--- a/lib/rbcodec/codecs/libopus/silk/NLSF2A.c
+++ b/lib/rbcodec/codecs/libopus/silk/NLSF2A.c
@@ -80,7 +80,7 @@ void silk_NLSF2A(
};
const unsigned char *ordering;
opus_int k, i, dd;
- opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
+ opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ] = {0};
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
diff --git a/manual/appendix/config_file_options.tex b/manual/appendix/config_file_options.tex
index b188c953f8..bf231de46c 100644
--- a/manual/appendix/config_file_options.tex
+++ b/manual/appendix/config_file_options.tex
@@ -124,6 +124,8 @@
wps & /path/filename.wps & N/A\\
autocreate bookmarks
& off, on & N/A\\
+ autoupdate bookmarks
+ & off, on & N/A\\
autoload bookmarks
& off, on & N/A\\
use most-recent-bookmarks
@@ -146,8 +148,8 @@
\opt{hotkey}{
hotkey wps & off, view playlist, show track info,
pitchscreen, open with, delete & N/A\\
- \nopt{touchscreen}{hotkey tree & off, open with, delete, insert,
- insert shuffled & N/A\\}
+ \nopt{touchscreen}{hotkey tree & off, properties, pictureflow, open with,
+ delete, insert, insert shuffled & N/A\\}
}
sort files & alpha, oldest, newest, type & N/A\\
sort dirs & alpha, oldest, newest & N/A\\
@@ -374,7 +376,10 @@
sync RDS time
& off, on & N/A\\
}%
-
+ \opt{clear_settings_on_hold}{
+ clear settings on hold
+ & off, on & N/A\\
+ }%
\bottomrule
\end{longtable}
\end{center}
diff --git a/manual/configure_rockbox/startup_shutdown_options.tex b/manual/configure_rockbox/startup_shutdown_options.tex
index 7952985ece..e4639079b5 100644
--- a/manual/configure_rockbox/startup_shutdown_options.tex
+++ b/manual/configure_rockbox/startup_shutdown_options.tex
@@ -36,6 +36,45 @@ are run at startup, or initiate a shutdown when conditions are met.
to be enabled.
\end{description}
+\opt{clear_settings_on_hold}{
+ \opt{ipod}{
+ \subsection{\label{ref:ClearOnHold}Hold switch clears settings on startup }
+ This option controls whether Rockbox clears its configuration if the hold
+ switch is enabled during startup.
+
+ \begin{description}
+ \item[Yes.]
+ Clear the settings if the hold switch is enabled during startup.
+ \item[No.]
+ Do not clear the settings, regardless of the hold switch's position.
+ \end{description}
+ }
+ \nopt{ipod}{
+ \opt{GIGABEAT_S_PAD}{
+ \subsection{\label{ref:ClearOnHold}BUTTON A clears settings on startup }
+ This option controls whether Rockbox clears its configuration if BUTTON_A
+ is held during startup.
+ \begin{description}
+ \item[Yes.]
+ Clear the settings if the BUTTON A is held.
+ \item[No.]
+ Do not clear the settings, regardless of BUTTON A.
+ \end{description}
+ }
+ \nopt{GIGABEAT_S_PAD}{
+ \subsection{\label{ref:ClearOnHold}BUTTON REC clears settings on startup }
+ This option controls whether Rockbox clears its configuration if BUTTON REC
+ is held during startup.
+ \begin{description}
+ \item[Yes.]
+ Clear the settings if the BUTTON REC is held.
+ \item[No.]
+ Do not clear the settings, regardless of BUTTON REC.
+ \end{description}
+ }
+ }
+}
+
\subsection{\label{ref:IdlePoweroffSetting}Idle Poweroff}
Rockbox can be configured to turn off power after the unit has been idle for
a defined number of minutes. The \dap{} is idle when playback is stopped or
diff --git a/manual/configure_rockbox/system_options.tex b/manual/configure_rockbox/system_options.tex
index 5a95df27b1..85e6a6b7d6 100755
--- a/manual/configure_rockbox/system_options.tex
+++ b/manual/configure_rockbox/system_options.tex
@@ -870,8 +870,15 @@ therefore result in better runtime.
\opt{usb_power}{
\subsection{USB Mode}
This controls what happens with the \dap{}'s USB port is connected.
- \setting{Charge Only} and \setting{Mass Storage} will automatically enter
- that mode, and \setting{Ask} will prompt the user each time.
+ \setting{Mass Storage} allows you to transfer files, while
+ \setting{Charge Only} will only charge the battery (and allow you to keep
+ using the player). You can choose the opposite behavior by holding down any
+ button while plugging in the USB cable.
+ \nopt{fuzeplus}{
+ \note{Be aware that holding a button may still perform its normal function,
+ so it is recommended to use a button without harmful side effects, such as
+ \ActionStdUsbCharge{}.}
+ }
}
\opt{multidrive_usb}{
\subsection{USB Hide Internal Drive}
diff --git a/manual/plugins/pictureflow.tex b/manual/plugins/pictureflow.tex
index 1fb9f28c29..2c83a3941f 100644
--- a/manual/plugins/pictureflow.tex
+++ b/manual/plugins/pictureflow.tex
@@ -221,10 +221,9 @@ reduces the time it takes for cover art to be displayed.}}
\item[Zoom.] Changes the distance at which slides are rendered from the ``camera''.
\item[Resize Covers.] Set whether to automatically resize the covers or to leave
them at their original size.
- \item[Rebuild cache.] Rebuild the PictureFlow cache. This is needed in order
- for PictureFlow to pick up new albums, and may occasionally be needed if albums
- are removed.
- \item[Update cache.] Update the PictureFlow cache. New albumart will be added.
+ \item[Rebuild cache.] Creates a fresh album index and builds the artwork cache from scratch.
+ \item[Update cache.] Creates a fresh album index and updates the existing artwork cache to
+ include newly added albums.
\item[WPS integration.] Integrate PictureFlow with the While Playing Screen and enable
the Current Playlist context menu.
\item[Backlight.] Force backlight on while running pictureflow.
diff --git a/manual/rockbox_interface/hotkeys.tex b/manual/rockbox_interface/hotkeys.tex
index ec12bd00ca..28c8091a05 100644
--- a/manual/rockbox_interface/hotkeys.tex
+++ b/manual/rockbox_interface/hotkeys.tex
@@ -1,19 +1,20 @@
% $Id$ %
\opt{hotkey}{
\section{\label{ref:Hotkeys}Hotkeys}
- Hotkeys are shortcut keys for use in the \nopt{touchscreen}{\setting{File Browser}
- and }\setting{WPS} screen. To use one, press
- \nopt{touchscreen}{\ActionTreeHotkey{} within the \setting{File Browser} or}
+ Hotkeys are shortcut keys for use in the \nopt{touchscreen}{\setting{File Browser},
+ \setting{Database}, \setting{Playlist Viewer}, and }\setting{WPS} screen. To use one, press
+ \nopt{touchscreen}{\ActionTreeHotkey{} within the \setting{File Browser},
+ \setting{Database}, or \setting{Playlist Viewer}, or}
\ActionWpsHotkey{} within the \setting{WPS}
screen.\nopt{touchscreen}{ The assigned function will launch with reference
to the current file or directory, if applicable. Each screen has its own
assignment.} If there is no assignment for a given screen,
the hotkey is ignored.
-
+
The default assignment for the \nopt{touchscreen}{File Browser hotkey is
\setting{Off}, while the default for the }WPS hotkey is
\setting{View Playlist}.
-
+
The hotkey assignments are changed in the Hotkey menu (see
\reference{ref:HotkeySettings}) under \setting{General Settings}.
}
diff --git a/manual/rockbox_interface/main.tex b/manual/rockbox_interface/main.tex
index 20aa8c833e..82192829fd 100644
--- a/manual/rockbox_interface/main.tex
+++ b/manual/rockbox_interface/main.tex
@@ -848,16 +848,13 @@ properly.}
\opt{usb_power}{
\section{USB Charging}
- Whenever your \dap{} is connected to USB, it will automatically charge.
- However, depending on the \config{usb\_mode} setting, the \dap{} may also
- enter mass storage mode or prompt the user for what action to take.
- When the \dap{} is configured to enter mass storage mode or automatically
- charge, you may trigger the opposite behavior by holding down any button
- while plugging it in. Your \dap{} must already be in Rockbox for this to
- function.
+ Your \dap{} will automatically charge when connected to USB. By default
+ Rockbox will connect in mass storage mode to transfer files, but you can
+ prevent this by holding down any button while plugging in the USB cable,
+ or by changing the \setting{USB Mode} setting to \setting{Charge Only}.
\nopt{fuzeplus}{
- \note{Be aware that this button may still perform its normal function, so
- it is recommended to use a button without harmful side effects, such as
+ \note{Be aware that holding a button may still perform its normal function,
+ so it is recommended to use a button without harmful side effects, such as
\ActionStdUsbCharge{}.}
}
}
diff --git a/tools/root.make b/tools/root.make
index 2a83a32292..03c4d48986 100644
--- a/tools/root.make
+++ b/tools/root.make
@@ -75,6 +75,12 @@ ifeq (,$(findstring checkwps,$(APP_TYPE)))
include $(ROOTDIR)/lib/unwarminder/unwarminder.make
endif
endif
+ ifeq (arch_mips,$(ARCH))
+ # mips unwinder is only usable on native ports
+ ifeq (,$(APP_TYPE))
+ include $(ROOTDIR)/lib/mipsunwinder/mipsunwinder.make
+ endif
+ endif
ifeq (,$(findstring bootloader,$(APPSDIR)))
include $(ROOTDIR)/lib/skin_parser/skin_parser.make
include $(ROOTDIR)/lib/tlsf/libtlsf.make
diff --git a/uisimulator/common/sim_tasks.c b/uisimulator/common/sim_tasks.c
index 8c1f193080..c53b9990fd 100644
--- a/uisimulator/common/sim_tasks.c
+++ b/uisimulator/common/sim_tasks.c
@@ -92,7 +92,9 @@ void sim_thread(void)
last_broadcast_tick = current_tick;
}
- num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
+ /* NOTE: Unlike the USB code, we do not subtract one here
+ * because the sim_queue is not registered for broadcasts! */
+ num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0);
DEBUGF("USB inserted. Waiting for %d acks...\n",
num_acks_to_expect);
break;
diff --git a/utils/rbutilqt/CMakeLists.txt b/utils/rbutilqt/CMakeLists.txt
index 41954cb9ee..24e15ac1b4 100644
--- a/utils/rbutilqt/CMakeLists.txt
+++ b/utils/rbutilqt/CMakeLists.txt
@@ -255,9 +255,44 @@ if(APPLE)
${CMAKE_CURRENT_LIST_DIR}/base/ttscarbon.h)
endif()
+find_package(QuaZip-Qt${QT_VERSION_MAJOR} QUIET)
+if(QuaZip-Qt${QT_VERSION_MAJOR}_FOUND)
+ message("-- Found QuaZip")
+ set(QUAZIP_LIBRARY QuaZip::QuaZip)
+else()
+ message("-- QuaZip not found, building our own")
+ # TODO: Upstream has cmake support, use that instead.
+ add_library(quazip
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/ioapi.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/minizip_crypt.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/qioapi.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfile.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfile.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfileinfo.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfileinfo.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip_global.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipnewinfo.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipnewinfo.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/unzip.c
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/unzip.h
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/zip.c
+ ${CMAKE_CURRENT_LIST_DIR}/quazip/zip.h
+ )
+ target_include_directories(quazip PUBLIC ${CMAKE_CURRENT_LIST_DIR}/quazip)
+ target_link_libraries(quazip z Qt${QT_VERSION_MAJOR}::Core)
+ if(QT_VERSION_MAJOR EQUAL 6)
+ target_link_libraries(quazip Qt${QT_VERSION_MAJOR}::Core5Compat)
+ endif()
+ target_compile_definitions(quazip PUBLIC QUAZIP_STATIC)
+ set_property(TARGET quazip PROPERTY AUTOMOC ON)
+ set(QUAZIP_LIBRARY quazip)
+endif()
+
target_link_libraries(rbbase
- cutelogger quazip mspack bspatch rbspeex voicefont
- sansapatcher ipodpatcher chinachippatcher
+ cutelogger ${QUAZIP_LIBRARY} mspack bspatch rbspeex
+ voicefont sansapatcher ipodpatcher chinachippatcher
mkamsboot mkimxboot mkmpioboot mktccboot mks5lboot
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network)
target_include_directories(rbbase PUBLIC ${CMAKE_CURRENT_LIST_DIR}/base)
@@ -298,33 +333,6 @@ target_link_libraries(cutelogger PUBLIC Qt${QT_VERSION_MAJOR}::Core)
target_compile_definitions(cutelogger PUBLIC CUTELOGGER_STATIC)
set_property(TARGET cutelogger PROPERTY AUTOMOC ON)
-# TODO: Upstream has cmake support, use that instead.
-add_library(quazip
- ${CMAKE_CURRENT_LIST_DIR}/quazip/ioapi.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/minizip_crypt.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/qioapi.cpp
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip.cpp
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfile.cpp
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfile.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfileinfo.cpp
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfileinfo.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip_global.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipnewinfo.cpp
- ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipnewinfo.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/unzip.c
- ${CMAKE_CURRENT_LIST_DIR}/quazip/unzip.h
- ${CMAKE_CURRENT_LIST_DIR}/quazip/zip.c
- ${CMAKE_CURRENT_LIST_DIR}/quazip/zip.h
- )
-target_include_directories(quazip PUBLIC ${CMAKE_CURRENT_LIST_DIR}/quazip)
-target_link_libraries(quazip z Qt${QT_VERSION_MAJOR}::Core)
-if(QT_VERSION_MAJOR EQUAL 6)
- target_link_libraries(quazip Qt${QT_VERSION_MAJOR}::Core5Compat)
-endif()
-target_compile_definitions(quazip PUBLIC QUAZIP_STATIC)
-set_property(TARGET quazip PROPERTY AUTOMOC ON)
-
add_library(mspack
#mspack/cabc.c
mspack/cabd.c
diff --git a/utils/rbutilqt/base/ziputil.cpp b/utils/rbutilqt/base/ziputil.cpp
index e285446711..877a861253 100644
--- a/utils/rbutilqt/base/ziputil.cpp
+++ b/utils/rbutilqt/base/ziputil.cpp
@@ -22,9 +22,9 @@
#include "progressloglevels.h"
#include "Logger.h"
-#include "quazip/quazip.h"
-#include "quazip/quazipfile.h"
-#include "quazip/quazipfileinfo.h"
+#include <quazip.h>
+#include <quazipfile.h>
+#include <quazipfileinfo.h>
ZipUtil::ZipUtil(QObject* parent) : ArchiveUtil(parent)
diff --git a/utils/rbutilqt/base/ziputil.h b/utils/rbutilqt/base/ziputil.h
index 73a87a820a..ea32ca42c3 100644
--- a/utils/rbutilqt/base/ziputil.h
+++ b/utils/rbutilqt/base/ziputil.h
@@ -21,9 +21,9 @@
#include <QtCore>
#include "archiveutil.h"
-#include "quazip/quazip.h"
-#include "quazip/quazipfile.h"
-#include "quazip/quazipfileinfo.h"
+#include <quazip.h>
+#include <quazipfile.h>
+#include <quazipfileinfo.h>
class ZipUtil : public ArchiveUtil
{
diff --git a/utils/rbutilqt/lang/rbutil_cs.ts b/utils/rbutilqt/lang/rbutil_cs.ts
index d36cc89aee..aca73ab84c 100644
--- a/utils/rbutilqt/lang/rbutil_cs.ts
+++ b/utils/rbutilqt/lang/rbutil_cs.ts
@@ -134,47 +134,47 @@
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="65"/>
<source>Bootloader installation requires you to provide the correct verrsion of the original firmware file. This file will be patched with the Rockbox bootloader and installed to your player. You need to download this file yourself due to legal reasons. Please refer to the &lt;a href=&apos;http://www.rockbox.org/wiki/&apos;&gt;rockbox wiki&lt;/a&gt; pages on how to obtain this file.&lt;br/&gt;Press Ok to continue and browse your computer for the firmware file.</source>
- <translation type="unfinished"></translation>
+ <translation>Instalace zavaděče vyžaduje správnou verzi souboru původního firmware. Ten bude doplněn zavaděčem Rockboxu a instalován na váš přehrávač.Z právních důvodů si tento soubor musíte stáhnou sami. Podívejte se prosím na &lt;a href=&apos;http://www.rockbox.org/wiki/&apos;&gt;rockbox wiki&lt;/a&gt; &gt; stránky jak ho získat. &lt;br/&gt;Vyberte OK pro pokračování a vyberte umístění souboru ve vašem počítači.</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="84"/>
<source>Could not read original firmware file</source>
- <translation type="unfinished">Nepodařilo se přečíst původní firmware</translation>
+ <translation>Nepodařilo se přečíst původní firmware</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="90"/>
<source>Downloading bootloader file</source>
- <translation type="unfinished">Stahuji soubor zavaděče</translation>
+ <translation>Stahuji soubor zavaděče</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="99"/>
<source>Patching file...</source>
- <translation type="unfinished">Patchuji soubor...</translation>
+ <translation>Patchuji soubor...</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="124"/>
<source>Patching the original firmware failed</source>
- <translation type="unfinished">Patchování původního firmware selhalo</translation>
+ <translation>Patchování původního firmware selhalo</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="130"/>
<source>Succesfully patched firmware file</source>
- <translation type="unfinished">Soubor firmware úspěšně opatchován</translation>
+ <translation>Soubor firmware úspěšně opatchován</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="145"/>
<source>Bootloader successful installed</source>
- <translation type="unfinished"></translation>
+ <translation>Zavaděč úspěšně nainstalován</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="151"/>
<source>Patched bootloader could not be installed</source>
- <translation type="unfinished">Opatchovaný zavaděč nemohl být nainstalován</translation>
+ <translation>Opatchovaný zavaděč nemohl být nainstalován</translation>
</message>
<message>
<location filename="../base/bootloaderinstallbspatch.cpp" line="161"/>
<source>To uninstall, perform a normal upgrade with an unmodified original firmware.</source>
- <translation type="unfinished">Pro odinstalaci proveďte běžnou aktualizaci s neupravovaným původním firmware.</translation>
+ <translation>Pro odinstalaci proveďte běžnou aktualizaci s neupravovaným původním firmware.</translation>
</message>
</context>
<context>
@@ -898,72 +898,84 @@ Viz http://www.rockbox.org/wiki/IpodConversionToFAT32</translation>
<source>Action required:
Please make sure no programs are accessing files on the device. If ejecting still fails please use your computers eject functionality.</source>
- <translation type="unfinished"></translation>
+ <translation>Je nutný zásah:
+
+Přesvědčte se prosím, že žádné programy nepracuj se soubory na zařízení. Jestliže odpojení přesto selže využijte prosím funkci odpojení vašeho počítače.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="171"/>
<source>Action required:
Quit iTunes application.</source>
- <translation type="unfinished"></translation>
+ <translation>Je nutný zásah:
+
+Ukončete aplikaci iTunes.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="192"/>
<source>Could not suspend iTunesHelper. Stop it using the Task Manager, and try again.</source>
- <translation type="unfinished"></translation>
+ <translation>Nepodařilo se zavřít iTunesHelper. Ukončete ho prostřednictvím Správce úloh a zkuste to znovu.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="218"/>
<source>Action required:
Press and hold SELECT+MENU buttons, after about 12 seconds a new action will require you to release the buttons, DO IT QUICKLY, otherwise the process could fail.</source>
- <translation type="unfinished"></translation>
+ <translation>Je nutný zásah:
+
+Zmáčkněte a držte tlačítka SELECT+MENU, po zhruba 12 sekundách bude nutné tlačítka pustit UDĚLEJTE TO RYCHLE, jinak může proces selhat.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="243"/>
<source>Action required:
Release SELECT+MENU buttons and wait...</source>
- <translation type="unfinished"></translation>
+ <translation>Je nutný zásah:
+
+Pusťte tlačítka SELECT+MENU a čekejte...</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="268"/>
<source>Device is not in DFU mode. It seems that the previous required action failed, please try again.</source>
- <translation type="unfinished"></translation>
+ <translation>Zařízení není v DFU režimu. Zdá se, že předchozí potřebný zásah selhal. Prosím, zkuste to znovu.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="285"/>
<source>No valid DFU USB driver found.
Install iTunes (or the Apple Device Driver) and try again.</source>
- <translation type="unfinished"></translation>
+ <translation>Nebyl nalezen platný DFU USB ovladač.
+
+Instalujte iTunes (nebo Apple Device Driver) a zkuste to znovu.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="321"/>
<source>Action required:
Could not remount the device, try to do it manually. If the iPod didn&apos;t restart, force a reset by pressing SELECT+MENU buttons for about 5 seconds. If the problem could not be solved then click &apos;Abort&apos; to cancel.</source>
- <translation type="unfinished"></translation>
+ <translation>Je nutný zásah:
+
+Zařízení se nepodařilo znovu připojit, zkuste to prosím ručně. Jestliže se iPod nerestartoval, vynuťte restart stisknutím tlačítek SELECT+MENU na 5 sekund. Jestliže se problém nepodařilo vyřešit, klikněte na &apos;Zrušit&apos; pro přerušení.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="336"/>
<source>Bootloader successfully installed.</source>
- <translation type="unfinished"></translation>
+ <translation>Zavaděč úspěšně nainstalován.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="338"/>
<source>Bootloader successfully uninstalled.</source>
- <translation type="unfinished"></translation>
+ <translation>Zavaděč úspěšně odinstalován.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="368"/>
<source>Install aborted by user.</source>
- <translation type="unfinished"></translation>
+ <translation>Instalace přerušena uživatelem.</translation>
</message>
<message>
<location filename="../base/bootloaderinstalls5l.cpp" line="370"/>
<source>Uninstall aborted by user.</source>
- <translation type="unfinished"></translation>
+ <translation>Odstalace přerušena uživatelem.</translation>
</message>
<message>
<source>Action required:
@@ -1973,7 +1985,7 @@ Prosím nastavte engine syntézy řeči.</translation>
<message>
<location filename="../gui/infowidget.cpp" line="47"/>
<source>Loading, please wait ...</source>
- <translation type="unfinished"></translation>
+ <translation>Načítám, prosím čekejte...</translation>
</message>
</context>
<context>
@@ -2165,27 +2177,27 @@ Prosím nastavte engine syntézy řeči.</translation>
<message>
<location filename="../base/playerbuildinfo.cpp" line="337"/>
<source>Stable (Retired)</source>
- <translation type="unfinished"></translation>
+ <translation>Stabilní (historická)</translation>
</message>
<message>
<location filename="../base/playerbuildinfo.cpp" line="340"/>
<source>Unusable</source>
- <translation type="unfinished">Nepoužitelný</translation>
+ <translation>Nepoužitelný</translation>
</message>
<message>
<location filename="../base/playerbuildinfo.cpp" line="343"/>
<source>Unstable</source>
- <translation type="unfinished">Nestabilní</translation>
+ <translation>Nestabilní</translation>
</message>
<message>
<location filename="../base/playerbuildinfo.cpp" line="346"/>
<source>Stable</source>
- <translation type="unfinished">Stabilní</translation>
+ <translation>Stabilní</translation>
</message>
<message>
<location filename="../base/playerbuildinfo.cpp" line="349"/>
<source>Unknown</source>
- <translation type="unfinished">Neznámý</translation>
+ <translation>Neznámý</translation>
</message>
</context>
<context>
@@ -2299,53 +2311,9 @@ Prosím nastavte engine syntézy řeči.</translation>
</message>
</context>
<context>
- <name>QuaGzipFile</name>
- <message>
- <location filename="../quazip/quagzipfile.cpp" line="60"/>
- <location filename="../quazip-1.2/quazip/quagzipfile.cpp" line="60"/>
- <source>QIODevice::Append is not supported for GZIP</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../quazip/quagzipfile.cpp" line="66"/>
- <location filename="../quazip-1.2/quazip/quagzipfile.cpp" line="66"/>
- <source>Opening gzip for both reading and writing is not supported</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../quazip/quagzipfile.cpp" line="74"/>
- <location filename="../quazip-1.2/quazip/quagzipfile.cpp" line="74"/>
- <source>You can open a gzip either for reading or for writing. Which is it?</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../quazip/quagzipfile.cpp" line="80"/>
- <location filename="../quazip-1.2/quazip/quagzipfile.cpp" line="80"/>
- <source>Could not gzopen() file</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
- <name>QuaZIODevice</name>
- <message>
- <location filename="../quazip/quaziodevice.cpp" line="188"/>
- <location filename="../quazip-1.2/quazip/quaziodevice.cpp" line="188"/>
- <source>QIODevice::Append is not supported for QuaZIODevice</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../quazip/quaziodevice.cpp" line="193"/>
- <location filename="../quazip-1.2/quazip/quaziodevice.cpp" line="193"/>
- <source>QIODevice::ReadWrite is not supported for QuaZIODevice</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
<name>QuaZipFile</name>
<message>
<location filename="../quazip/quazipfile.cpp" line="251"/>
- <location filename="../quazip-1.2/quazip/quazipfile.cpp" line="251"/>
- <location filename="../quazip_/quazipfile.cpp" line="251"/>
<source>ZIP/UNZIP API error %1</source>
<translation>Chyba %1 API ZIP/UNZIP</translation>
</message>
@@ -2360,7 +2328,7 @@ Prosím nastavte engine syntézy řeči.</translation>
<message>
<location filename="../rbutilqt.cpp" line="304"/>
<source>Libraries used</source>
- <translation type="unfinished"></translation>
+ <translation>Použité knihovny</translation>
</message>
<message>
<location filename="../rbutilqt.cpp" line="383"/>
@@ -2401,7 +2369,7 @@ Prosím nastavte engine syntézy řeči.</translation>
<message>
<location filename="../rbutilqt.cpp" line="227"/>
<source>Certificate error</source>
- <translation type="unfinished"></translation>
+ <translation>Chyba certifikátu</translation>
</message>
<message>
<location filename="../rbutilqt.cpp" line="229"/>
@@ -2413,7 +2381,14 @@ Valid since: %4
Valid until: %5
Temporarily trust certificate?</source>
- <translation type="unfinished"></translation>
+ <translation>%1
+
+Vydal: %2
+Vydáno pro: %3
+Platný od: %4
+Platný do: %5
+
+Dočasně důvěřovat certifikátu?</translation>
</message>
<message>
<location filename="../rbutilqt.cpp" line="261"/>
@@ -2497,7 +2472,7 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
</message>
<message>
<source>The installed version of Rockbox is a development version. Pre-built voices are only available for release versions of Rockbox. Please generate a voice yourself using the &quot;Create voice file&quot; functionality.</source>
- <translation type="vanished">Je instalována vývojářská verze Rockboxu. Předpřipravené hlasy jsou k dispozici jen pro stabilní vydání. Prosím vytvořte si hlas pomocí funkce &quot;Vytvoření hlasového souboru&quot;.</translation>
+ <translation type="vanished">Je instalována vývojová verze Rockboxu. Předpřipravené hlasy jsou k dispozici jen pro stabilní vydání. Prosím vytvořte si hlas pomocí funkce &quot;Vytvoření hlasového souboru&quot;.</translation>
</message>
<message>
<location filename="../rbutilqt.cpp" line="518"/>
@@ -2793,12 +2768,12 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
<message>
<location filename="../rbutilqtfrm.ui" line="43"/>
<source>Welcome to Rockbox Utility, the installation and housekeeping tool for Rockbox.</source>
- <translation type="unfinished"></translation>
+ <translation>Vítá Vás Rockbox Utilita, nástroj pro instalaci a údržbu Rockboxu.</translation>
</message>
<message>
<location filename="../rbutilqtfrm.ui" line="46"/>
<source>Rockbox Logo</source>
- <translation type="unfinished"></translation>
+ <translation>Logo Rockboxu</translation>
</message>
<message>
<location filename="../rbutilqtfrm.ui" line="131"/>
@@ -2941,27 +2916,27 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="151"/>
<source>Some plugins require additional data files.</source>
- <translation type="unfinished"></translation>
+ <translation>Některé doplňky potřebují dodatečné datové soubory.</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="188"/>
<source>Install prerendered voice file.</source>
- <translation type="unfinished"></translation>
+ <translation>Instalace sestavených hlasových souborů.</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="195"/>
<source>Plugin Data</source>
- <translation type="unfinished"></translation>
+ <translation>Doplňkové soubory</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="222"/>
<source>&amp;Manual</source>
- <translation type="unfinished">&amp;Příručka</translation>
+ <translation>&amp;Příručka</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="233"/>
<source>&amp;Voice File</source>
- <translation type="unfinished"></translation>
+ <translation>&amp;Soubor hlasů</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="253"/>
@@ -3014,7 +2989,7 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="263"/>
<source>Save a copy of the manual on the player.</source>
- <translation type="unfinished"></translation>
+ <translation>Uložit kopii manuálu do přehrávače.</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidgetfrm.ui" line="292"/>
@@ -3028,7 +3003,7 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
</message>
<message>
<source>The development version is updated on every code change. Last update was on %1</source>
- <translation type="vanished">Vývojářská verze je aktualizována při každé změně kódu. Poslední aktualizace proběhla %1</translation>
+ <translation type="vanished">Vývojová verze je aktualizována při každé změně kódu. Poslední aktualizace proběhla %1</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="88"/>
@@ -3043,7 +3018,7 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="131"/>
<source>Development Version (Revison %1)</source>
- <translation>Vývojářská verze (Revize %1)</translation>
+ <translation>Vývojová verze (Revize %1)</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="129"/>
@@ -3053,22 +3028,22 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="83"/>
<source>The development version is updated on every code change.</source>
- <translation type="unfinished"></translation>
+ <translation>Vývojová verze je aktualizována při každé změně zdrojového kódu.</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="93"/>
<source>Daily updated development version.</source>
- <translation type="unfinished"></translation>
+ <translation>Každodenně aktualizovaná vývojová verze.</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="100"/>
<source>Not available for the selected version</source>
- <translation type="unfinished"></translation>
+ <translation>Není dostupný pro vybranou verzi</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="130"/>
<source>Daily Build (%1)</source>
- <translation type="unfinished"></translation>
+ <translation>Denní sestavení (%1)</translation>
</message>
<message>
<location filename="../gui/selectiveinstallwidget.cpp" line="158"/>
@@ -3091,91 +3066,91 @@ Chyba sítě: %1. Prosím zkontrolujte vaše nastavení sítě a proxy.</transla
<translation>Není známý žádný způsob instalace.</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="319"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="318"/>
<source>Bootloader detected</source>
<translation>Zavaděč nalezen</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="320"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="319"/>
<source>Bootloader already installed. Do you want to reinstall the bootloader?</source>
<translation>Zavaděč je již instalován. Opravdu chcete přeinstalovat zavaděč?</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="324"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="323"/>
<source>Bootloader installation skipped</source>
<translation>Instalace zavaděče přeskočena</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="338"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="337"/>
<source>Create Bootloader backup</source>
<translation>Vytváří se záloha zavaděče</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="339"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="338"/>
<source>You can create a backup of the original bootloader file. Press &quot;Yes&quot; to select an output folder on your computer to save the file to. The file will get placed in a new folder &quot;%1&quot; created below the selected folder.
Press &quot;No&quot; to skip this step.</source>
<translation>Můžete vytvořit zálohu původního souboru zavaděče. Stiskněte &quot;Ano&quot; pro výběr adresáře na vašem počítači, kam se má tento soubor uložit. Soubor bude umístěn do nového podadresáře &quot;%1&quot; vytvořeného v tomto adresáři.
Stiskněte &quot;Ne&quot; pro přeskočení tohoto kroku.</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="346"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="345"/>
<source>Browse backup folder</source>
<translation>Vybrat zálohovací adresář</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="358"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="357"/>
<source>Prerequisites</source>
<translation>Předpoklady</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="363"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="362"/>
<source>Bootloader installation aborted</source>
<translation>Instalace zavaděče přerušena</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="373"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="372"/>
<source>Bootloader files (%1)</source>
<translation>Soubory zavaděče (%1)</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="375"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="374"/>
<source>All files (*)</source>
<translation>Všechny soubory (*)</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="377"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="376"/>
<source>Select firmware file</source>
<translation>Vyberte soubor firmware</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="379"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="378"/>
<source>Error opening firmware file</source>
<translation>Chyba otevírání souboru firmware</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="385"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="384"/>
<source>Error reading firmware file</source>
<translation>Chyba čtení souboru firmware</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="395"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="394"/>
<source>Backup error</source>
<translation>Chyba zálohování</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="396"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="395"/>
<source>Could not create backup file. Continue?</source>
<translation>Nelze vytvořit soubor se zálohou. Pokračovat?</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="420"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="419"/>
<source>Manual steps required</source>
<translation>Nutné ruční kroky</translation>
</message>
<message>
- <location filename="../gui/selectiveinstallwidget.cpp" line="641"/>
+ <location filename="../gui/selectiveinstallwidget.cpp" line="640"/>
<source>Your installation doesn&apos;t require any plugin data files, skipping.</source>
- <translation type="unfinished"></translation>
+ <translation>Vaše instalace nepotřebuje žádné dodatečné soubory, přeskakuji.</translation>
</message>
<message>
<source>Your installation doesn&apos;t require any game files, skipping.</source>
@@ -3316,7 +3291,7 @@ Stiskněte &quot;Ne&quot; pro přeskočení tohoto kroku.</translation>
<message>
<location filename="../sysinfo.cpp" line="69"/>
<source>Type</source>
- <translation type="unfinished"></translation>
+ <translation>Typ</translation>
</message>
<message>
<source>Cluster Size</source>
@@ -3384,12 +3359,12 @@ Stiskněte &quot;Ne&quot; pro přeskočení tohoto kroku.</translation>
<message>
<location filename="../base/ttsbase.cpp" line="48"/>
<source>Espeak-ng TTS Engine</source>
- <translation type="unfinished"></translation>
+ <translation>Syntéza řeči Espeak-ng</translation>
</message>
<message>
<location filename="../base/ttsbase.cpp" line="49"/>
<source>Mimic TTS Engine</source>
- <translation type="unfinished"></translation>
+ <translation>Syntéza řeči Mimic</translation>
</message>
<message>
<location filename="../base/ttsbase.cpp" line="51"/>
@@ -3493,7 +3468,7 @@ Stiskněte &quot;Ne&quot; pro přeskočení tohoto kroku.</translation>
<message>
<location filename="../base/ttsfestival.cpp" line="173"/>
<source>Festival could not be started</source>
- <translation type="unfinished"></translation>
+ <translation>Festival nemohl být spuštěn</translation>
</message>
<message>
<location filename="../base/ttsfestival.cpp" line="207"/>
@@ -4043,13 +4018,13 @@ Jsou nutná administrátorská práva.&lt;/li&gt;</translation>
<location filename="../base/zipinstaller.cpp" line="113"/>
<source>Download error: received HTTP error %1
%2</source>
- <translation type="unfinished">Chyba stahování: HTTP chyba %1. {1
-%2?}</translation>
+ <translation>Chyba stahování: nastala HTTP chyba %1
+%2</translation>
</message>
<message>
<location filename="../base/zipinstaller.cpp" line="125"/>
<source>Download finished (cache used).</source>
- <translation type="unfinished">Stahování dokončeno (použita vyrovnávací paměť).</translation>
+ <translation>Stahování dokončeno (použita vyrovnávací paměť).</translation>
</message>
<message>
<location filename="../base/zipinstaller.cpp" line="168"/>
@@ -4115,7 +4090,7 @@ Jsou nutná administrátorská práva.&lt;/li&gt;</translation>
<message>
<location filename="../aboutbox.ui" line="132"/>
<source>L&amp;ibraries</source>
- <translation type="unfinished"></translation>
+ <translation>K&amp;nihovny</translation>
</message>
<message>
<source>&amp;Speex License</source>