| -- BILGUS 2018 |
| |
| --local scrpath = rb.current_path()" |
| |
| --package.path = scrpath .. "/?.lua;" .. package.path --add lua_scripts directory to path |
| require("printmenu") |
| require("printtable") |
| require("dbgettags") |
| |
| local _print = require("print") |
| |
| rb.actions = nil |
| package.loaded["actions"] = nil |
| |
| local sERROROPENING = "Error opening" |
| local sERRORMENUENTRY = "Error finding menu entry" |
| |
| local sBLANKLINE = "##sBLANKLINE##" |
| local sDEFAULTMENU = "customfilter" |
| |
| local sFILEOUT = "/.rockbox/tagnavi_custom.config" |
| local sFILEHEADER = "#! rockbox/tagbrowser/2.0" |
| local sMENUSTART = "%menu_start \"custom\" \"Database\"" |
| local sMENUTITLE = "title = \"fmt_title\"" |
| |
| local TAG_ARTIST, TAG_ALBARTIST, TAG_ALBUM, TAG_GENRE, TAG_COMPOSER = 1, 2, 3, 4, 5 |
| local ts_TAGTYPE = {"Artist", "AlbumArtist", "Album", "Genre", "Composer"} |
| local ts_DBPATH = {"database_0.tcd", "database_7.tcd", "database_1.tcd", "database_2.tcd", "database_5.tcd"} |
| |
| local COND_OR, COND_AND, COND_NOR, COND_NAND = 1, 2, 3, 4 |
| local ts_CONDITIONALS = {"OR", "AND", "!, OR", "!, AND"} |
| local ts_CONDSYMBOLS = {"|", "&", "|", "&"} |
| |
| local ts_YESNO = {"", "Yes", "No"} |
| local s_OVERWRITE = "Overwrite" |
| local s_EXISTS = "Exists" |
| |
| |
| local function question(tInquiry, start) |
| settings = {} |
| settings.justify = "center" |
| settings.wrap = true |
| settings.msel = false |
| settings.hasheader = true |
| settings.co_routine = nil |
| settings.curpos = start or 1 |
| local sel = print_table(tInquiry, #tInquiry, settings) |
| return sel |
| end |
| |
| local function find_linepos(t_lines, search, startline) |
| startline = startline or 1 |
| |
| for i = startline, #t_lines do |
| if string.match (t_lines[i], search) then |
| return i |
| end |
| end |
| |
| return -1 |
| end |
| |
| local function replacelines(t_lines, search, replace, startline) |
| startline = startline or 1 |
| repcount = 0 |
| for i = startline, #t_lines do |
| if string.match (t_lines[i], search) then |
| t_lines[i] = replace |
| repcount = repcount + 1 |
| end |
| end |
| return repcount |
| end |
| |
| local function replaceemptylines(t_lines, replace, startline) |
| startline = startline or 1 |
| replace = replace or nil |
| repcount = 0 |
| for i = startline, #t_lines do |
| if t_lines[i] == "" then |
| t_lines[i] = replace |
| repcount = repcount + 1 |
| end |
| end |
| return repcount |
| end |
| |
| local function checkexistingmenu(t_lines, menuname) |
| local pos = find_linepos(t_lines, "^\"" .. menuname .. "\"%s*%->.+") |
| local sel = 0 |
| if pos > 0 then |
| ts_YESNO[1] = menuname .. " " .. s_EXISTS .. ", " .. s_OVERWRITE .. "?" |
| sel = question(ts_YESNO, 3) |
| if sel == 3 then |
| pos = nil |
| elseif sel < 2 then |
| pos = 0 |
| end |
| else |
| pos = nil |
| end |
| return pos |
| end |
| |
| local function savedata(filename, ts_tags, cond, menuname) |
| menuname = menuname or sDEFAULTMENU |
| |
| local lines = {} |
| local curline = 0 |
| local function lines_next(str, pos) |
| pos = pos or #lines + 1 |
| lines[pos] = str or "" |
| curline = pos |
| end |
| |
| local function lines_append(str, pos) |
| pos = pos or curline or #lines |
| lines[pos] = lines[pos] .. str or "" |
| end |
| |
| if rb.file_exists(filename) ~= true then |
| lines_next(sFILEHEADER) |
| lines_next("#") |
| lines_next("# MAIN MENU") |
| lines_next(sMENUSTART) |
| else |
| local file = io.open(filename, "r") -- read |
| if not file then |
| rb.splash(rb.HZ, "Error opening" .. " " .. filename) |
| return |
| end |
| |
| for line in file:lines() do |
| lines_next(line) |
| end |
| file:close() |
| end |
| |
| local menupos = find_linepos(lines, sMENUSTART) |
| if menupos < 1 then |
| rb.splash(rb.HZ, sERRORMENUENTRY) |
| return |
| end |
| |
| replaceemptylines(lines, sBLANKLINE, menupos) |
| |
| local existmenupos = checkexistingmenu(lines, menuname) |
| if existmenupos and existmenupos < 1 then return end -- user canceled |
| |
| local lastcond = "" |
| local n_cond = COND_OR |
| local tags, tagtype |
| |
| local function buildtag(e_tagtype) |
| if ts_tags[e_tagtype] then |
| n_cond = (cond[e_tagtype] or COND_OR) |
| if e_tagtype > 1 then |
| lines_append(" " .. ts_CONDSYMBOLS[n_cond]) |
| end |
| tags = ts_tags[e_tagtype] |
| tagtype = string.lower(ts_TAGTYPE[e_tagtype]) |
| |
| if n_cond <= COND_AND then |
| lines_append(" " .. tagtype) |
| lines_append(" @ \"".. table.concat(tags, "|") .. "\"") |
| else |
| for k = 1, #tags do |
| lines_append(" " .. tagtype) |
| lines_append(" !~ \"".. tags[k] .. "\"") |
| if k < #tags then lines_append(" &") end |
| end |
| end |
| end |
| end |
| |
| if ts_tags[TAG_ARTIST] or ts_tags[TAG_ALBARTIST] or ts_tags[TAG_ALBUM] or |
| ts_tags[TAG_GENRE] or ts_tags[TAG_COMPOSER] then |
| |
| lines_next("\"" .. menuname .. "\" -> " .. sMENUTITLE .. " ?", existmenupos) |
| |
| buildtag(TAG_ARTIST) |
| buildtag(TAG_ALBARTIST) |
| buildtag(TAG_ALBUM) |
| buildtag(TAG_GENRE) |
| buildtag(TAG_COMPOSER) |
| |
| lines_next("\n") |
| else |
| rb.splash(rb.HZ, "Nothing to save") |
| end |
| |
| local file = io.open(filename, "w+") -- overwrite |
| if not file then |
| rb.splash(rb.HZ, "Error writing " .. filename) |
| return |
| end |
| |
| for i = 1, #lines do |
| if lines[i] and lines[i] ~= sBLANKLINE then |
| file:write(lines[i], "\n") |
| end |
| end |
| |
| file:close() |
| end |
| |
| -- uses print_table to display database tags |
| local function print_tags(ftable, settings, t_selected) |
| if not s_cond then s_sep = "|" end |
| ftable = ftable or {} |
| |
| if t_selected then |
| for k = 1, #t_selected do |
| ftable[t_selected[k]] = ftable[t_selected[k]] .. "\0" |
| end |
| end |
| rb.lcd_clear_display() |
| _print.clear() |
| |
| if not settings then |
| settings = {} |
| settings.justify = "center" |
| settings.wrap = true |
| settings.msel = true |
| end |
| |
| settings.hasheader = true |
| settings.co_routine = nil |
| |
| local sel = print_table(ftable, #ftable, settings) |
| |
| --_lcd:splashf(rb.HZ * 2, "%d items {%s}", #sel, table.concat(sel, ", ")) |
| local selected = {} |
| local str = "" |
| for k = 1,#sel do |
| str = ftable[sel[k]] or "" |
| selected[#selected + 1] = string.sub(str, 1, -2) -- REMOVE \0 |
| end |
| |
| ftable = nil |
| |
| if #sel == 0 then |
| return nil, nil |
| end |
| |
| return sel, selected |
| end -- print_tags |
| |
| -- uses print_table to display a menu |
| function main_menu() |
| local menuname = sDEFAULTMENU |
| local t_tags |
| local ts_tags = {} |
| local cond = {} |
| local sel = {} |
| local mt = { |
| [1] = "TagNav Customizer", |
| [2] = "", --ts_CONDITIONALS[cond[TAG_ARTIST] or COND_OR], |
| [3] = ts_TAGTYPE[TAG_ARTIST], |
| [4] = ts_CONDITIONALS[cond[TAG_ALBARTIST] or COND_OR], |
| [5] = ts_TAGTYPE[TAG_ALBARTIST], |
| [6] = ts_CONDITIONALS[cond[TAG_ALBUM] or COND_OR], |
| [7] = ts_TAGTYPE[TAG_ALBUM], |
| [8] = ts_CONDITIONALS[cond[TAG_GENRE] or COND_OR], |
| [9] = ts_TAGTYPE[TAG_GENRE], |
| [10] = ts_CONDITIONALS[cond[TAG_COMPOSER] or COND_OR], |
| [11] = ts_TAGTYPE[TAG_COMPOSER], |
| [12] = "Save to Tagnav", |
| [13] = "Exit" |
| } |
| |
| local function sel_cond(item, item_mt) |
| cond[item] = cond[item] or 1 |
| cond[item] = cond[item] + 1 |
| if cond[item] > #ts_CONDITIONALS then cond[item] = 1 end |
| mt[item_mt] = ts_CONDITIONALS[cond[item]] |
| end |
| |
| local function sel_tag(item, item_mt, t_tags) |
| t_tags = get_tags(rb.ROCKBOX_DIR .. "/" .. ts_DBPATH[item], ts_TAGTYPE[item]) |
| sel[item], ts_tags[item] = print_tags(t_tags, nil, sel[item]) |
| if ts_tags[item] then |
| mt[item_mt] = ts_TAGTYPE[item] .. " [" .. #sel[item] .. "]" |
| else |
| mt[item_mt] = ts_TAGTYPE[item] |
| end |
| end |
| |
| local ft = { |
| [0] = exit_now, --if user cancels do this function |
| [1] = function(TITLE) return true end, -- shouldn't happen title occupies this slot |
| [2] = function(ARTCOND) |
| sel_cond(TAG_ARTIST, ARTCOND) |
| end, |
| [3] = function(ART) |
| sel_tag(TAG_ARTIST, ART, t_tags) |
| end, |
| [4] = function(ALBARTCOND) |
| sel_cond(TAG_ALBARTIST, ALBARTCOND) |
| end, |
| [5] = function(ALBART) |
| sel_tag(TAG_ALBARTIST, ALBART, t_tags) |
| end, |
| [6] = function(ALBCOND) |
| sel_cond(TAG_ALBUM, ALBCOND) |
| end, |
| [7] = function(ALB) |
| sel_tag(TAG_ALBUM, ALB, t_tags) |
| end, |
| [8] = function(GENRECOND) |
| sel_cond(TAG_GENRE, GENRECOND) |
| end, |
| [9] = function(GENRE) |
| sel_tag(TAG_GENRE, GENRE, t_tags) |
| end, |
| [10] = function(COMPCOND) |
| sel_cond(TAG_COMPOSER, COMPCOND) |
| end, |
| [11] = function(COMP) |
| sel_tag(TAG_COMPOSER, COMP, t_tags) |
| end, |
| |
| [12] = function(SAVET) |
| menuname = menuname or sDEFAULTMENU |
| menuname = rb.kbd_input(menuname) |
| menuname = string.match(menuname, "%w+") |
| if menuname == "" then menuname = nil end |
| menuname = menuname or sDEFAULTMENU |
| savedata(sFILEOUT, ts_tags, cond, menuname) |
| end, |
| [13] = function(EXIT_) return true end |
| } |
| |
| print_menu(mt, ft, 2) --start at item 2 |
| |
| end |
| |
| function exit_now() |
| rb.lcd_update() |
| os.exit() |
| end -- exit_now |
| |
| main_menu() |
| exit_now() |