summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2021-12-08 21:47:29 -0500
committerWilliam Wilgus <wilgus.william@gmail.com>2021-12-08 22:09:16 -0500
commit5433ea540555f18d3986c5067c6f26ddf497bd9b (patch)
tree0cefe4d7129708caa776d7111d26612d63092344
parent8c88d5c5e2fc0ea8656bfe0dd2a906a924a0c3d1 (diff)
downloadrockbox-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
-rw-r--r--apps/plugins/lua_scripts/random_playlist.lua125
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
23require ("actions") 36require ("actions")
24require("dbgettags") 37require("dbgettags")
25get_tags = nil -- unneeded 38get_tags = nil -- unneeded
@@ -29,6 +42,7 @@ local playlistpath = "/Playlists"
29local max_tracks = 500; -- size of playlist to create 42local max_tracks = 500; -- size of playlist to create
30local min_repeat = 500; -- this many songs before a repeat 43local min_repeat = 500; -- this many songs before a repeat
31local play_on_success = true; 44local play_on_success = true;
45local playlist_name = "random_playback.m3u8"
32--program vars 46--program vars
33local playlist_handle 47local playlist_handle
34local t_playlistbuf -- table for playlist write buffer 48local 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)
64end 78end
65 79
66local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount) 80local 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;
177end 210end
178 211--[[ manually create a playlist
212playlist is created initially by creating a new file (or erasing old)
213and adding the BOM]]
179--deletes existing file and creates a new playlist 214--deletes existing file and creates a new playlist
180local function playlist_create(filename) 215local 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)
193end 225end
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
196local function playlist_write(trackpath) 228local 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]]
203end 234end
204 235
205-- flushes playlist buffer to file 236-- flushes playlist buffer to file
206local function playlist_flush() 237local 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]]
213end 240end
214 241
215-- closes playlist file descriptor 242-- closes playlist file descriptor
216local function playlist_finalize() 243local function playlist_finalize()
217 playlist_handle:close() 244 playlist_handle:close()
245 return true
218end 246end
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]]
223local function create_random_playlist(database, playlist, trackcount, play) 251local 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--[[
492local used, allocd, free = rb.mem_stats() 541local used, allocd, free = rb.mem_stats()
493local lu = collectgarbage("count") 542local lu = collectgarbage("count")
494local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end 543local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end