A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+87 -38
+87 -38
apps/plugins/lua_scripts/random_playlist.lua
··· 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 36 require ("actions") 24 37 require("dbgettags") 25 38 get_tags = nil -- unneeded ··· 29 42 local max_tracks = 500; -- size of playlist to create 30 43 local min_repeat = 500; -- this many songs before a repeat 31 44 local play_on_success = true; 45 + local playlist_name = "random_playback.m3u8" 32 46 --program vars 33 47 local playlist_handle 34 48 local t_playlistbuf -- table for playlist write buffer ··· 63 77 return rb.font_getstringsize(msg, font) 64 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 81 -- Setup string tables 68 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 86 local tREPEATTEXT = {"Repeat hist? [ %d ] (up/dn)","higher = less repeated songs"} 70 87 local tPLSIZETEXT = {"Find [ %d ] tracks? (up/dn)", 71 - "Warning overwrites dynamic playlist", 88 + "Warning may overwrite dynamic playlist", 72 89 "Press back to cancel"}; 73 90 -- how many lines can we fit on the screen? 74 91 local res, w, h = text_extent("I") ··· 125 142 end 126 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 161 -- Repeat song buffer list of previously added tracks 0-?? 129 162 function setup_get_repeat() 130 163 if min_repeat >= trackcount then min_repeat = trackcount - 1 end ··· 139 172 min_repeat = min_repeat - increment 140 173 if min_repeat < 0 then min_repeat = 0 end 141 174 elseif action == OK_BUTTON then 142 - ask = setup_get_play; 175 + ask = setup_get_save; 143 176 setup_get_repeat = nil 144 177 action = 0 145 178 end ··· 173 206 if action == CANCEL_BUTTON then rb.lcd_scroll_stop(); return nil end 174 207 until (action == OK_BUTTON) 175 208 176 - return play, min_repeat, trackcount; 209 + return play, savepl, min_repeat, trackcount; 177 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 214 --deletes existing file and creates a new playlist 180 215 local function playlist_create(filename) 181 216 local filehandle = io.open(filename, "w+") --overwrite ··· 184 219 return false 185 220 end 186 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 223 playlist_handle = filehandle 189 224 return true 190 - --os.remove( playlistpath .. "/" .. playlist) 191 - --rb.playlist("remove_all_tracks") 192 - --rb.playlist("create", playlistpath .. "/", playlist) 193 225 end 194 226 195 - -- writes track path to a buffer must be flushed 196 - local function playlist_write(trackpath) 197 - t_playlistbuf[#t_playlistbuf + 1] = trackpath 198 - t_playlistbuf[#t_playlistbuf + 1] = "\n" 199 - --[[if rb.playlist("insert_track", str) < 0 then 200 - rb.splash(rb.HZ, sPLAYLISTERROR) 201 - break; -- ERROR, PLAYLIST FULL? 202 - end]] 227 + -- writes track path to a buffer must be later flushed to playlist file 228 + local function playlist_insert(trackpath) 229 + local bufp = #t_playlistbuf + 1 230 + t_playlistbuf[bufp] = trackpath 231 + bufp = bufp + 1 232 + t_playlistbuf[bufp] = "\n" 233 + return bufp 203 234 end 204 235 205 236 -- flushes playlist buffer to file 206 237 local function playlist_flush() 207 238 playlist_handle:write(table.concat(t_playlistbuf)) 208 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 240 end 214 241 215 242 -- closes playlist file descriptor 216 243 local function playlist_finalize() 217 244 playlist_handle:close() 245 + return true 218 246 end 219 247 220 248 --[[ Given the filenameDB file [database] 221 249 creates a random dynamic playlist with a default savename of [playlist] 222 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 252 if not database or not playlist or not trackcount then return end 225 253 if not play then play = false end 254 + if not savepl then savepl = false end 226 255 227 256 local playlist_handle 257 + local playlistisfinalized = false 228 258 local file = io.open('/' .. database or "", "r") --read 229 259 if not file then rb.splash(100, string.format(sERROROPENFMT, database)) return end 230 260 ··· 258 288 end 259 289 260 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( 264 - tag_entries, play, min_repeat, trackcount); 292 + play, savepl, min_repeat, trackcount = _setup_random_playlist( 293 + tag_entries, play, savepl, min_repeat, trackcount); 265 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 310 collectgarbage("collect") 267 311 268 312 -- how many lines can we fit on the screen? ··· 344 388 end 345 389 346 390 get_index() --init get_index fn 347 - -- Playlist insert loop 391 + -- Playlist insert loop 348 392 while true do 349 393 str = nil 350 394 tries = 0 ··· 365 409 tracks = tracks + 1 366 410 show_progress() 367 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 417 end 370 418 371 419 if tracks >= trackcount then ··· 384 432 function build_anchor_index() 385 433 -- index every n files 386 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 436 while ent >= 10 do -- need to reduce the size of the anchor index? 389 437 ent = ent / 10 390 438 ANCHOR_INTV = ANCHOR_INTV * 10 ··· 442 490 track_index = anchor_index 443 491 anchor_index = nil 444 492 end 445 - 446 - if not playlist_create(playlistpath .. "/" .. playlist) then return end 447 493 --[[ --profiling 448 494 local starttime = rb.current_tick(); 449 495 get_tracks_random() ··· 453 499 if (false) then 454 500 --]] 455 501 get_tracks_random() 456 - playlist_finalize(playlist_handle) 502 + playlistisfinalized = playlist_finalize(playlist_handle) 457 503 end 458 504 459 505 file:close() 460 506 collectgarbage("collect") 461 - if trackcount and play == true then 507 + if trackcount and play == true and playlistisfinalized == true then 462 508 rb.audio("stop") 463 509 rb.yield() 464 - rb.playlist("create", playlistpath .. "/", "dynamic_playlist.m3u8") 465 - rb.playlist("insert_playlist", playlistpath .. "/" .. playlist) 510 + if savepl == true then 511 + rb.playlist("create", playlistpath .. "/", playlist) 512 + rb.playlist("insert_playlist", playlistpath .. "/" .. playlist) 513 + rb.sleep(rb.HZ) 514 + end 466 515 rb.playlist("start", 0, 0, 0) 467 516 end 468 517 ··· 482 531 rb.lcd_update() 483 532 collectgarbage("collect") 484 533 create_random_playlist(rb.ROCKBOX_DIR .. "/database_4.tcd", 485 - "random_playback.m3u8", max_tracks, play_on_success); 486 - rb.splash(rb.HZ * 2, sGOODBYE) 534 + playlist_name, max_tracks, play_on_success); 487 535 -- Restore user backlight settings 488 536 rb.backlight_use_settings() 489 537 if rb.cpu_boost then rb.cpu_boost(false) end 490 - 491 - --[[ 538 + rb.sleep(rb.HZ) 539 + rb.splash(rb.HZ * 2, sGOODBYE) 540 + --[[ 492 541 local used, allocd, free = rb.mem_stats() 493 542 local lu = collectgarbage("count") 494 543 local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end