summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 @@
*
****************************************************************************/
]]
+--[[ random_playlist
+ This script opens the users database file containg track path + filenames
+ first it reads the database file making an index of tracks
+ [for large playlists it only saves an index every [10|100|1000] tracks.
+ tracks will be incrementally loaded along with the results of the entries
+ traversed but the garbage collector will erase them when needed]
+
+ next tracks are choosen at random and added either to an in-ram playlist
+ using plugin functions OR
+ to a on disk playlist using a table as a write buffer
+ the user can also choose to play the playlist in either case
+]]
+
require ("actions")
require("dbgettags")
get_tags = nil -- unneeded
@@ -29,6 +42,7 @@ local playlistpath = "/Playlists"
local max_tracks = 500; -- size of playlist to create
local min_repeat = 500; -- this many songs before a repeat
local play_on_success = true;
+local playlist_name = "random_playback.m3u8"
--program vars
local playlist_handle
local t_playlistbuf -- table for playlist write buffer
@@ -63,12 +77,15 @@ local function text_extent(msg, font)
return rb.font_getstringsize(msg, font)
end
-local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount)
+local function _setup_random_playlist(tag_entries, play, savepl, min_repeat, trackcount)
-- Setup string tables
local tPLAYTEXT = {"Play? [ %s ] (up/dn)", "true = play tracks on success"}
+ local tSAVETEXT = {"Save to disk? [ %s ] (up/dn)",
+ "true = tracks saved to",
+ playlist_name};
local tREPEATTEXT = {"Repeat hist? [ %d ] (up/dn)","higher = less repeated songs"}
local tPLSIZETEXT = {"Find [ %d ] tracks? (up/dn)",
- "Warning overwrites dynamic playlist",
+ "Warning may overwrite dynamic playlist",
"Press back to cancel"};
-- how many lines can we fit on the screen?
local res, w, h = text_extent("I")
@@ -125,6 +142,22 @@ local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount)
end
end
+ -- Save the playlist to disk true/false?
+ function setup_get_save()
+ action = ask_user_action(tdesc,
+ string.format(tSAVETEXT[1], tostring(savepl)),
+ tSAVETEXT[2], tSAVETEXT[3]);
+ if action == ADD_BUTTON then
+ savepl = true
+ elseif action == SUB_BUTTON then
+ savepl = false
+ elseif action == OK_BUTTON then
+ ask = setup_get_play;
+ setup_get_save = nil
+ action = 0
+ end
+ end
+
-- Repeat song buffer list of previously added tracks 0-??
function setup_get_repeat()
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)
min_repeat = min_repeat - increment
if min_repeat < 0 then min_repeat = 0 end
elseif action == OK_BUTTON then
- ask = setup_get_play;
+ ask = setup_get_save;
setup_get_repeat = nil
action = 0
end
@@ -173,9 +206,11 @@ local function _setup_random_playlist(tag_entries, play, min_repeat, trackcount)
if action == CANCEL_BUTTON then rb.lcd_scroll_stop(); return nil end
until (action == OK_BUTTON)
- return play, min_repeat, trackcount;
+ return play, savepl, min_repeat, trackcount;
end
-
+--[[ manually create a playlist
+playlist is created initially by creating a new file (or erasing old)
+and adding the BOM]]
--deletes existing file and creates a new playlist
local function playlist_create(filename)
local filehandle = io.open(filename, "w+") --overwrite
@@ -184,47 +219,42 @@ local function playlist_create(filename)
return false
end
t_playlistbuf = {}
- filehandle:write("\239\187\191") -- Write BOM --"\xEF\xBB\xBF"
+ filehandle:write("\239\187\191") -- Write BOM --"\xEF\xBB\xBF"
playlist_handle = filehandle
return true
- --os.remove( playlistpath .. "/" .. playlist)
- --rb.playlist("remove_all_tracks")
- --rb.playlist("create", playlistpath .. "/", playlist)
end
--- writes track path to a buffer must be flushed
-local function playlist_write(trackpath)
- t_playlistbuf[#t_playlistbuf + 1] = trackpath
- t_playlistbuf[#t_playlistbuf + 1] = "\n"
- --[[if rb.playlist("insert_track", str) < 0 then
- rb.splash(rb.HZ, sPLAYLISTERROR)
- break; -- ERROR, PLAYLIST FULL?
- end]]
+-- writes track path to a buffer must be later flushed to playlist file
+local function playlist_insert(trackpath)
+ local bufp = #t_playlistbuf + 1
+ t_playlistbuf[bufp] = trackpath
+ bufp = bufp + 1
+ t_playlistbuf[bufp] = "\n"
+ return bufp
end
-- flushes playlist buffer to file
local function playlist_flush()
playlist_handle:write(table.concat(t_playlistbuf))
t_playlistbuf = {}
- --[[if rb.playlist("insert_track", str) < 0 then
- rb.splash(rb.HZ, sPLAYLISTERROR)
- break; -- ERROR, PLAYLIST FULL?
- end]]
end
-- closes playlist file descriptor
local function playlist_finalize()
playlist_handle:close()
+ return true
end
--[[ Given the filenameDB file [database]
creates a random dynamic playlist with a default savename of [playlist]
containing [trackcount] tracks, played on completion if [play] is true]]
-local function create_random_playlist(database, playlist, trackcount, play)
+local function create_random_playlist(database, playlist, trackcount, play, savepl)
if not database or not playlist or not trackcount then return end
if not play then play = false end
+ if not savepl then savepl = false end
local playlist_handle
+ local playlistisfinalized = false
local file = io.open('/' .. database or "", "r") --read
if not file then rb.splash(100, string.format(sERROROPENFMT, database)) return end
@@ -258,11 +288,25 @@ local function create_random_playlist(database, playlist, trackcount, play)
end
local tag_entries = bytesLE_n(tagcache_entries)
- if tag_entries > 50000 then play = false end
- play, min_repeat, trackcount = _setup_random_playlist(
- tag_entries, play, min_repeat, trackcount);
+ play, savepl, min_repeat, trackcount = _setup_random_playlist(
+ tag_entries, play, savepl, min_repeat, trackcount);
_setup_random_playlist = nil
+
+ if savepl == false then
+ -- Use the rockbox playlist functions to add tracks to in-ram playlist
+ playlist_create = function(filename)
+ return (rb.playlist("create", playlistpath .. "/", playlist) >= 0)
+ end
+ playlist_insert = function(str)
+ return rb.playlist("insert_track", str)
+ end
+ playlist_flush = function() end
+ playlist_finalize = function()
+ return (rb.playlist("amount") >= trackcount)
+ end
+ end
+ if not playlist_create(playlistpath .. "/" .. playlist) then return end
collectgarbage("collect")
-- how many lines can we fit on the screen?
@@ -344,7 +388,7 @@ local function create_random_playlist(database, playlist, trackcount, play)
end
get_index() --init get_index fn
- -- Playlist insert loop
+ -- Playlist insert loop
while true do
str = nil
tries = 0
@@ -365,7 +409,11 @@ local function create_random_playlist(database, playlist, trackcount, play)
tracks = tracks + 1
show_progress()
push_lru(idxp) -- add to repeat list
- playlist_write(str)
+ if playlist_insert(str) < 0 then
+ rb.sleep(rb.HZ) --rb playlist fn display own message wait for that
+ rb.splash(rb.HZ, sPLAYLISTERROR)
+ break; -- ERROR, PLAYLIST FULL?
+ end
end
if tracks >= trackcount then
@@ -384,7 +432,7 @@ local function create_random_playlist(database, playlist, trackcount, play)
function build_anchor_index()
-- index every n files
ANCHOR_INTV = 1 -- for small db we can put all the entries in ram
- local ent = tag_entries / 1000 -- more than 10,000 will be incrementally loaded
+ local ent = tag_entries / 100 -- more than 1000 will be incrementally loaded
while ent >= 10 do -- need to reduce the size of the anchor index?
ent = ent / 10
ANCHOR_INTV = ANCHOR_INTV * 10
@@ -442,8 +490,6 @@ local function create_random_playlist(database, playlist, trackcount, play)
track_index = anchor_index
anchor_index = nil
end
-
- if not playlist_create(playlistpath .. "/" .. playlist) then return end
--[[ --profiling
local starttime = rb.current_tick();
get_tracks_random()
@@ -453,16 +499,19 @@ local function create_random_playlist(database, playlist, trackcount, play)
if (false) then
--]]
get_tracks_random()
- playlist_finalize(playlist_handle)
+ playlistisfinalized = playlist_finalize(playlist_handle)
end
file:close()
collectgarbage("collect")
- if trackcount and play == true then
+ if trackcount and play == true and playlistisfinalized == true then
rb.audio("stop")
rb.yield()
- rb.playlist("create", playlistpath .. "/", "dynamic_playlist.m3u8")
- rb.playlist("insert_playlist", playlistpath .. "/" .. playlist)
+ if savepl == true then
+ rb.playlist("create", playlistpath .. "/", playlist)
+ rb.playlist("insert_playlist", playlistpath .. "/" .. playlist)
+ rb.sleep(rb.HZ)
+ end
rb.playlist("start", 0, 0, 0)
end
@@ -482,13 +531,13 @@ local function main()
rb.lcd_update()
collectgarbage("collect")
create_random_playlist(rb.ROCKBOX_DIR .. "/database_4.tcd",
- "random_playback.m3u8", max_tracks, play_on_success);
- rb.splash(rb.HZ * 2, sGOODBYE)
+ playlist_name, max_tracks, play_on_success);
-- Restore user backlight settings
rb.backlight_use_settings()
if rb.cpu_boost then rb.cpu_boost(false) end
-
---[[
+ rb.sleep(rb.HZ)
+ rb.splash(rb.HZ * 2, sGOODBYE)
+--[[
local used, allocd, free = rb.mem_stats()
local lu = collectgarbage("count")
local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end