diff options
author | William Wilgus <wilgus.william@gmail.com> | 2021-12-08 21:47:29 -0500 |
---|---|---|
committer | William Wilgus <wilgus.william@gmail.com> | 2021-12-08 22:09:16 -0500 |
commit | 5433ea540555f18d3986c5067c6f26ddf497bd9b (patch) | |
tree | 0cefe4d7129708caa776d7111d26612d63092344 /apps/plugins/lua_scripts/random_playlist.lua | |
parent | 8c88d5c5e2fc0ea8656bfe0dd2a906a924a0c3d1 (diff) | |
download | rockbox-5433ea540555f18d3986c5067c6f26ddf497bd9b.tar.gz rockbox-5433ea540555f18d3986c5067c6f26ddf497bd9b.zip |
random_playlist.lua make index more sparse
The name of the game here is to load the database file without taking over the
audio buffer.
5mb database file will now successfully load
added an option to save playlist directly to disk and bypass the rb builtin function completely
however if you choose play the playlist will be loaded back from the disk into the inram dynamic playlist
Change-Id: I43e76f63379721f36ed082c0ad47a6f2539fb15f
Diffstat (limited to 'apps/plugins/lua_scripts/random_playlist.lua')
-rw-r--r-- | apps/plugins/lua_scripts/random_playlist.lua | 125 |
1 files changed, 87 insertions, 38 deletions
diff --git a/apps/plugins/lua_scripts/random_playlist.lua b/apps/plugins/lua_scripts/random_playlist.lua index 9d300025ac..b4fd216981 100644 --- a/apps/plugins/lua_scripts/random_playlist.lua +++ b/apps/plugins/lua_scripts/random_playlist.lua | |||
@@ -20,6 +20,19 @@ | |||
20 | * | 20 | * |
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | ]] | 22 | ]] |
23 | --[[ random_playlist | ||
24 | This script opens the users database file containg track path + filenames | ||
25 | first it reads the database file making an index of tracks | ||
26 | [for large playlists it only saves an index every [10|100|1000] tracks. | ||
27 | tracks will be incrementally loaded along with the results of the entries | ||
28 | traversed but the garbage collector will erase them when needed] | ||
29 | |||
30 | next tracks are choosen at random and added either to an in-ram playlist | ||
31 | using plugin functions OR | ||
32 | to a on disk playlist using a table as a write buffer | ||
33 | the user can also choose to play the playlist in either case | ||
34 | ]] | ||
35 | |||
23 | require ("actions") | 36 | require ("actions") |
24 | require("dbgettags") | 37 | require("dbgettags") |
25 | get_tags = nil -- unneeded | 38 | get_tags = nil -- unneeded |
@@ -29,6 +42,7 @@ local playlistpath = "/Playlists" | |||
29 | local max_tracks = 500; -- size of playlist to create | 42 | local max_tracks = 500; -- size of playlist to create |
30 | local min_repeat = 500; -- this many songs before a repeat | 43 | local min_repeat = 500; -- this many songs before a repeat |
31 | local play_on_success = true; | 44 | local play_on_success = true; |
45 | local playlist_name = "random_playback.m3u8" | ||
32 | --program vars | 46 | --program vars |
33 | local playlist_handle | 47 | local playlist_handle |
34 | local t_playlistbuf -- table for playlist write buffer | 48 | local t_playlistbuf -- table for playlist write buffer |
@@ -63,12 +77,15 @@ local function text_extent(msg, font) | |||
63 | return rb.font_getstringsize(msg, font) | 77 | return rb.font_getstringsize(msg, font) |
64 | end | 78 | end |
65 | 79 | ||
66 | local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount) | 80 | local function _setup_random_playlist(tag_entries, play, savepl, min_repeat, trackcount) |
67 | -- Setup string tables | 81 | -- Setup string tables |
68 | local tPLAYTEXT = {"Play? [ %s ] (up/dn)", "true = play tracks on success"} | 82 | local tPLAYTEXT = {"Play? [ %s ] (up/dn)", "true = play tracks on success"} |
83 | local tSAVETEXT = {"Save to disk? [ %s ] (up/dn)", | ||
84 | "true = tracks saved to", | ||
85 | playlist_name}; | ||
69 | local tREPEATTEXT = {"Repeat hist? [ %d ] (up/dn)","higher = less repeated songs"} | 86 | local tREPEATTEXT = {"Repeat hist? [ %d ] (up/dn)","higher = less repeated songs"} |
70 | local tPLSIZETEXT = {"Find [ %d ] tracks? (up/dn)", | 87 | local tPLSIZETEXT = {"Find [ %d ] tracks? (up/dn)", |
71 | "Warning overwrites dynamic playlist", | 88 | "Warning may overwrite dynamic playlist", |
72 | "Press back to cancel"}; | 89 | "Press back to cancel"}; |
73 | -- how many lines can we fit on the screen? | 90 | -- how many lines can we fit on the screen? |
74 | local res, w, h = text_extent("I") | 91 | local res, w, h = text_extent("I") |
@@ -125,6 +142,22 @@ local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount) | |||
125 | end | 142 | end |
126 | end | 143 | end |
127 | 144 | ||
145 | -- Save the playlist to disk true/false? | ||
146 | function setup_get_save() | ||
147 | action = ask_user_action(tdesc, | ||
148 | string.format(tSAVETEXT[1], tostring(savepl)), | ||
149 | tSAVETEXT[2], tSAVETEXT[3]); | ||
150 | if action == ADD_BUTTON then | ||
151 | savepl = true | ||
152 | elseif action == SUB_BUTTON then | ||
153 | savepl = false | ||
154 | elseif action == OK_BUTTON then | ||
155 | ask = setup_get_play; | ||
156 | setup_get_save = nil | ||
157 | action = 0 | ||
158 | end | ||
159 | end | ||
160 | |||
128 | -- Repeat song buffer list of previously added tracks 0-?? | 161 | -- Repeat song buffer list of previously added tracks 0-?? |
129 | function setup_get_repeat() | 162 | function setup_get_repeat() |
130 | if min_repeat >= trackcount then min_repeat = trackcount - 1 end | 163 | if min_repeat >= trackcount then min_repeat = trackcount - 1 end |
@@ -139,7 +172,7 @@ local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount) | |||
139 | min_repeat = min_repeat - increment | 172 | min_repeat = min_repeat - increment |
140 | if min_repeat < 0 then min_repeat = 0 end | 173 | if min_repeat < 0 then min_repeat = 0 end |
141 | elseif action == OK_BUTTON then | 174 | elseif action == OK_BUTTON then |
142 | ask = setup_get_play; | 175 | ask = setup_get_save; |
143 | setup_get_repeat = nil | 176 | setup_get_repeat = nil |
144 | action = 0 | 177 | action = 0 |
145 | end | 178 | end |
@@ -173,9 +206,11 @@ local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount) | |||
173 | if action == CANCEL_BUTTON then rb.lcd_scroll_stop(); return nil end | 206 | if action == CANCEL_BUTTON then rb.lcd_scroll_stop(); return nil end |
174 | until (action == OK_BUTTON) | 207 | until (action == OK_BUTTON) |
175 | 208 | ||
176 | return play, min_repeat, trackcount; | 209 | return play, savepl, min_repeat, trackcount; |
177 | end | 210 | end |
178 | 211 | --[[ manually create a playlist | |
212 | playlist is created initially by creating a new file (or erasing old) | ||
213 | and adding the BOM]] | ||
179 | --deletes existing file and creates a new playlist | 214 | --deletes existing file and creates a new playlist |
180 | local function playlist_create(filename) | 215 | local function playlist_create(filename) |
181 | local filehandle = io.open(filename, "w+") --overwrite | 216 | local filehandle = io.open(filename, "w+") --overwrite |
@@ -184,47 +219,42 @@ local function playlist_create(filename) | |||
184 | return false | 219 | return false |
185 | end | 220 | end |
186 | t_playlistbuf = {} | 221 | t_playlistbuf = {} |
187 | filehandle:write("\239\187\191") -- Write BOM --"\xEF\xBB\xBF" | 222 | filehandle:write("\239\187\191") -- Write BOM --"\xEF\xBB\xBF" |
188 | playlist_handle = filehandle | 223 | playlist_handle = filehandle |
189 | return true | 224 | return true |
190 | --os.remove( playlistpath .. "/" .. playlist) | ||
191 | --rb.playlist("remove_all_tracks") | ||
192 | --rb.playlist("create", playlistpath .. "/", playlist) | ||
193 | end | 225 | end |
194 | 226 | ||
195 | -- writes track path to a buffer must be flushed | 227 | -- writes track path to a buffer must be later flushed to playlist file |
196 | local function playlist_write(trackpath) | 228 | local function playlist_insert(trackpath) |
197 | t_playlistbuf[#t_playlistbuf + 1] = trackpath | 229 | local bufp = #t_playlistbuf + 1 |
198 | t_playlistbuf[#t_playlistbuf + 1] = "\n" | 230 | t_playlistbuf[bufp] = trackpath |
199 | --[[if rb.playlist("insert_track", str) < 0 then | 231 | bufp = bufp + 1 |
200 | rb.splash(rb.HZ, sPLAYLISTERROR) | 232 | t_playlistbuf[bufp] = "\n" |
201 | break; -- ERROR, PLAYLIST FULL? | 233 | return bufp |
202 | end]] | ||
203 | end | 234 | end |
204 | 235 | ||
205 | -- flushes playlist buffer to file | 236 | -- flushes playlist buffer to file |
206 | local function playlist_flush() | 237 | local function playlist_flush() |
207 | playlist_handle:write(table.concat(t_playlistbuf)) | 238 | playlist_handle:write(table.concat(t_playlistbuf)) |
208 | t_playlistbuf = {} | 239 | t_playlistbuf = {} |
209 | --[[if rb.playlist("insert_track", str) < 0 then | ||
210 | rb.splash(rb.HZ, sPLAYLISTERROR) | ||
211 | break; -- ERROR, PLAYLIST FULL? | ||
212 | end]] | ||
213 | end | 240 | end |
214 | 241 | ||
215 | -- closes playlist file descriptor | 242 | -- closes playlist file descriptor |
216 | local function playlist_finalize() | 243 | local function playlist_finalize() |
217 | playlist_handle:close() | 244 | playlist_handle:close() |
245 | return true | ||
218 | end | 246 | end |
219 | 247 | ||
220 | --[[ Given the filenameDB file [database] | 248 | --[[ Given the filenameDB file [database] |
221 | creates a random dynamic playlist with a default savename of [playlist] | 249 | creates a random dynamic playlist with a default savename of [playlist] |
222 | containing [trackcount] tracks, played on completion if [play] is true]] | 250 | containing [trackcount] tracks, played on completion if [play] is true]] |
223 | local function create_random_playlist(database, playlist, trackcount, play) | 251 | local function create_random_playlist(database, playlist, trackcount, play, savepl) |
224 | if not database or not playlist or not trackcount then return end | 252 | if not database or not playlist or not trackcount then return end |
225 | if not play then play = false end | 253 | if not play then play = false end |
254 | if not savepl then savepl = false end | ||
226 | 255 | ||
227 | local playlist_handle | 256 | local playlist_handle |
257 | local playlistisfinalized = false | ||
228 | local file = io.open('/' .. database or "", "r") --read | 258 | local file = io.open('/' .. database or "", "r") --read |
229 | if not file then rb.splash(100, string.format(sERROROPENFMT, database)) return end | 259 | if not file then rb.splash(100, string.format(sERROROPENFMT, database)) return end |
230 | 260 | ||
@@ -258,11 +288,25 @@ local function create_random_playlist(database, playlist, trackcount, play) | |||
258 | end | 288 | end |
259 | 289 | ||
260 | local tag_entries = bytesLE_n(tagcache_entries) | 290 | local tag_entries = bytesLE_n(tagcache_entries) |
261 | if tag_entries > 50000 then play = false end | ||
262 | 291 | ||
263 | play, min_repeat, trackcount = _setup_random_playlist( | 292 | play, savepl, min_repeat, trackcount = _setup_random_playlist( |
264 | tag_entries, play, min_repeat, trackcount); | 293 | tag_entries, play, savepl, min_repeat, trackcount); |
265 | _setup_random_playlist = nil | 294 | _setup_random_playlist = nil |
295 | |||
296 | if savepl == false then | ||
297 | -- Use the rockbox playlist functions to add tracks to in-ram playlist | ||
298 | playlist_create = function(filename) | ||
299 | return (rb.playlist("create", playlistpath .. "/", playlist) >= 0) | ||
300 | end | ||
301 | playlist_insert = function(str) | ||
302 | return rb.playlist("insert_track", str) | ||
303 | end | ||
304 | playlist_flush = function() end | ||
305 | playlist_finalize = function() | ||
306 | return (rb.playlist("amount") >= trackcount) | ||
307 | end | ||
308 | end | ||
309 | if not playlist_create(playlistpath .. "/" .. playlist) then return end | ||
266 | collectgarbage("collect") | 310 | collectgarbage("collect") |
267 | 311 | ||
268 | -- how many lines can we fit on the screen? | 312 | -- how many lines can we fit on the screen? |
@@ -344,7 +388,7 @@ local function create_random_playlist(database, playlist, trackcount, play) | |||
344 | end | 388 | end |
345 | 389 | ||
346 | get_index() --init get_index fn | 390 | get_index() --init get_index fn |
347 | -- Playlist insert loop | 391 | -- Playlist insert loop |
348 | while true do | 392 | while true do |
349 | str = nil | 393 | str = nil |
350 | tries = 0 | 394 | tries = 0 |
@@ -365,7 +409,11 @@ local function create_random_playlist(database, playlist, trackcount, play) | |||
365 | tracks = tracks + 1 | 409 | tracks = tracks + 1 |
366 | show_progress() | 410 | show_progress() |
367 | push_lru(idxp) -- add to repeat list | 411 | push_lru(idxp) -- add to repeat list |
368 | playlist_write(str) | 412 | if playlist_insert(str) < 0 then |
413 | rb.sleep(rb.HZ) --rb playlist fn display own message wait for that | ||
414 | rb.splash(rb.HZ, sPLAYLISTERROR) | ||
415 | break; -- ERROR, PLAYLIST FULL? | ||
416 | end | ||
369 | end | 417 | end |
370 | 418 | ||
371 | if tracks >= trackcount then | 419 | if tracks >= trackcount then |
@@ -384,7 +432,7 @@ local function create_random_playlist(database, playlist, trackcount, play) | |||
384 | function build_anchor_index() | 432 | function build_anchor_index() |
385 | -- index every n files | 433 | -- index every n files |
386 | ANCHOR_INTV = 1 -- for small db we can put all the entries in ram | 434 | ANCHOR_INTV = 1 -- for small db we can put all the entries in ram |
387 | local ent = tag_entries / 1000 -- more than 10,000 will be incrementally loaded | 435 | local ent = tag_entries / 100 -- more than 1000 will be incrementally loaded |
388 | while ent >= 10 do -- need to reduce the size of the anchor index? | 436 | while ent >= 10 do -- need to reduce the size of the anchor index? |
389 | ent = ent / 10 | 437 | ent = ent / 10 |
390 | ANCHOR_INTV = ANCHOR_INTV * 10 | 438 | ANCHOR_INTV = ANCHOR_INTV * 10 |
@@ -442,8 +490,6 @@ local function create_random_playlist(database, playlist, trackcount, play) | |||
442 | track_index = anchor_index | 490 | track_index = anchor_index |
443 | anchor_index = nil | 491 | anchor_index = nil |
444 | end | 492 | end |
445 | |||
446 | if not playlist_create(playlistpath .. "/" .. playlist) then return end | ||
447 | --[[ --profiling | 493 | --[[ --profiling |
448 | local starttime = rb.current_tick(); | 494 | local starttime = rb.current_tick(); |
449 | get_tracks_random() | 495 | get_tracks_random() |
@@ -453,16 +499,19 @@ local function create_random_playlist(database, playlist, trackcount, play) | |||
453 | if (false) then | 499 | if (false) then |
454 | --]] | 500 | --]] |
455 | get_tracks_random() | 501 | get_tracks_random() |
456 | playlist_finalize(playlist_handle) | 502 | playlistisfinalized = playlist_finalize(playlist_handle) |
457 | end | 503 | end |
458 | 504 | ||
459 | file:close() | 505 | file:close() |
460 | collectgarbage("collect") | 506 | collectgarbage("collect") |
461 | if trackcount and play == true then | 507 | if trackcount and play == true and playlistisfinalized == true then |
462 | rb.audio("stop") | 508 | rb.audio("stop") |
463 | rb.yield() | 509 | rb.yield() |
464 | rb.playlist("create", playlistpath .. "/", "dynamic_playlist.m3u8") | 510 | if savepl == true then |
465 | rb.playlist("insert_playlist", playlistpath .. "/" .. playlist) | 511 | rb.playlist("create", playlistpath .. "/", playlist) |
512 | rb.playlist("insert_playlist", playlistpath .. "/" .. playlist) | ||
513 | rb.sleep(rb.HZ) | ||
514 | end | ||
466 | rb.playlist("start", 0, 0, 0) | 515 | rb.playlist("start", 0, 0, 0) |
467 | end | 516 | end |
468 | 517 | ||
@@ -482,13 +531,13 @@ local function main() | |||
482 | rb.lcd_update() | 531 | rb.lcd_update() |
483 | collectgarbage("collect") | 532 | collectgarbage("collect") |
484 | create_random_playlist(rb.ROCKBOX_DIR .. "/database_4.tcd", | 533 | create_random_playlist(rb.ROCKBOX_DIR .. "/database_4.tcd", |
485 | "random_playback.m3u8", max_tracks, play_on_success); | 534 | playlist_name, max_tracks, play_on_success); |
486 | rb.splash(rb.HZ * 2, sGOODBYE) | ||
487 | -- Restore user backlight settings | 535 | -- Restore user backlight settings |
488 | rb.backlight_use_settings() | 536 | rb.backlight_use_settings() |
489 | if rb.cpu_boost then rb.cpu_boost(false) end | 537 | if rb.cpu_boost then rb.cpu_boost(false) end |
490 | 538 | rb.sleep(rb.HZ) | |
491 | --[[ | 539 | rb.splash(rb.HZ * 2, sGOODBYE) |
540 | --[[ | ||
492 | local used, allocd, free = rb.mem_stats() | 541 | local used, allocd, free = rb.mem_stats() |
493 | local lu = collectgarbage("count") | 542 | local lu = collectgarbage("count") |
494 | local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end | 543 | local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end |