Rockbox Technical Forums

Support and General Use => Plugins/Viewers => Topic started by: Bilgus on October 11, 2018, 10:33:08 AM

Title: Lua Using audio_current_track/audio_next_track
Post by: Bilgus on October 11, 2018, 10:33:08 AM
This Patch adds access to rockbox global_settings, global_status, audio_current_track and audio_next_track
http://gerrit.rockbox.org/r/#/c/1901/

This is a continuation of the previous example provided here:
http://forums.rockbox.org/index.php/topic,52389.0.html

here is an example of how to use it:
Code: [Select]
require("settings") --settings.lua

local var = {offset = 1, size = 2, type = 3}

local function bytesLE_n(str)
    str = str or ""
    local tbyte={str:byte(1, -1)}
    local bpos = 1
    local num  = 0
    for k = 1,#tbyte do -- (k = #t, 1, -1 for BE)
        num = num + tbyte[k] * bpos
        bpos = bpos * 256
    end
    return num
end

local function format_cstr(val, var_type)
    local ret = val or ""
        ret = string.match(val, "^%Z+")
    return tostring(ret)
end

local function format_val(val, var_type)
    local ret = val or 0
    local s_bool = {"False", "True"}
    if var_type == "str" then
        ret = format_cstr(val)
    elseif string.find(var_type, "^b") then       
        if(bytesLE_n(val) <= 0) then
            ret = s_bool[1]
        else
            ret = s_bool[2]
        end
    elseif string.find(var_type, "^u_i") then
        -- Lua integers are signed so we need to do a bit of extra processing
        ret = string.format("%u", bytesLE_n(val))
    elseif string.find(var_type, "^u_l") then
        -- Lua integers are signed so we need to do a bit of extra processing
        ret = string.format("%u", bytesLE_n(val))
    elseif var_type ~= nil then
        ret = bytesLE_n(val)
    end

    return tostring(ret)
end

local function get_array_elems(st_type)
    --extract the number of elements
    local elems = string.match(st_type,".*%[(%d+)%]")
    return tonumber(elems) or 0
end

local function get_struct_name(st_type)
    --extract the name of a struct
    local name = string.match(st_type,"^s_([^%[%]%s]+)")
    return name
end

local function dump_struct(s_settings, group_name, struct_name, elems, k, v, t_output)
    --Internal function dumps structs
    local val, offset, fmtstr, s
    local s_g = rb[group_name]
    local s_t = s_g[struct_name]
    if elems > 0 then
        fmtstr = "%s[%d].%s = %s"
        local elem_size = (v[var.size] / elems)

        for i = 0, elems - 1 do
            for k1, v1 in pairs(s_t) do
                offset = v[var.offset] + v1[var.offset] + (elem_size * i)
                val = rb[s_settings](offset, v1[var.size])
                s = string.format (fmtstr, k, i, k1, format_val(val, v1[var.type]))
                t_output[#t_output + 1] = s
            end
        end
    else
        fmtstr = "%s.%s = %s"
        for k1, v1 in pairs(s_t) do
            offset = v[var.offset] + v1[var.offset]
            val = rb[s_settings](offset, v1[var.size])
            s = string.format (fmtstr, k, k1, format_val(val, v1[var.type]))
            t_output[#t_output + 1] = s
        end
    end
end

local function dump_settings(s_settings)
    local t_output = {}
    local val, offset, fmtstr, s

    for k, v in pairs(rb.system[s_settings]) do
        local elems = get_array_elems(v[var.type])
        local struct_name = get_struct_name(v[var.type])

        if struct_name then   
            dump_struct(s_settings, "system", struct_name, elems, k, v, t_output)
        else
            if elems > 0 then
                fmtstr = "%s[%d] = %s"
                local elem_size = (v[var.size] / elems)

                for i = 0, elems - 1 do
                    offset = v[var.offset] + (elem_size * i)
                    val = rb[s_settings](offset, elem_size)
                    s = string.format (fmtstr, k, i, format_val(val, v[var.type]))
                    t_output[#t_output + 1] = s
                end
            else
                fmtstr = "%s = %s"
                offset = v[var.offset]
                val = rb[s_settings](offset, v[var.size])
                s = string.format (fmtstr, k, format_val(val, v[var.type]))
                t_output[#t_output + 1] = s
            end
        end
    end
    return t_output
end

local function dump_metadata(s_settings)
    local t_output = {}
    local val, offset, type, fmtstr, s

    for k, v in pairs(rb.metadata["mp3_entry"]) do
        local elems = get_array_elems(v[var.type])
        local struct_name = get_struct_name(v[var.type])

        if struct_name then   
            dump_struct(s_settings, "metadata", struct_name, elems, k, v, t_output)
        else
            if elems > 0 then
                fmtstr = "%s[%d] = %s"
                local elem_size = (v[var.size] / elems)

                for i = 0, elems - 1 do
                    offset = v[var.offset] + (elem_size * i)
                    val = rb[s_settings](offset, elem_size)
                    s = string.format (fmtstr, k, i, format_val(val, v[var.type]))
                    t_output[#t_output + 1] = s
                end
            else
                fmtstr = "%s = %s"
                type = v[var.type]
                offset = v[var.offset]
                val = rb[s_settings](offset, v[var.size])
                if type == "ptr_char" then
                    local address = tonumber(string.format("%u", bytesLE_n(val)))
                    if address > 0 then
                        val = rb[s_settings](-address, nil) -- neg offset
                        type = "str"
                    end
                end
               
                s = string.format (fmtstr, k, format_val(val, type))

                t_output[#t_output + 1] = s
            end
        end
    end
    return t_output
end


local filename = "/settings.txt"
local file = io.open(filename, "w+") -- overwrite
local t_settings

if not file then
    rb.splash(rb.HZ, "Error writing " .. filename)
    return
end

t_settings = dump_metadata('audio_current_track')
file:write("audio_current_track:\n")
file:write(table.concat(t_settings, "\n"))
file:write("\n\n")

--[[
t_settings = dump_settings('global_status')
file:write("global_status:\n")
file:write(table.concat(t_settings, "\n"))
file:write("\n\n")

t_settings = dump_settings('global_settings')
file:write("global_settings:\n")
file:write(table.concat(t_settings, "\n"))
file:write("\n\n")
]]
file:close()

-- this is how you would write a setting and save it
--local start_directory = rb.system.global_settings.start_directory
--rb.global_settings(start_directory[1], start_directory[2], "/.rockbox")
--rb.settings_save()
--endoffile

Sample output:
Code: [Select]
audio_current_track:
tail_trim = 1728
comment = 'Deadmau5'
cuesheet = 0
elapsed = 6714
autoresumable = 0
track_string = 0
sim_filesize = 10157372
track_level = 0
bytesperframe = 0
length = 634827
discnum = 0
codectype = 3
year_string = 0
has_embedded_cuesheet = False
id3v2len = 174716
has_toc = True
has_embedded_albumart = True
embedded_cuesheet.encoding = 0
embedded_cuesheet.pos = 0
embedded_cuesheet.size = 0
first_frame_offset = 175133
track_gain = 0
bitrate = 128
frame_count = 24302
title = Cthulhu Sleeps
id3version = 4
album_peak = 0
album_gain = 0
year = 0
frequency = 44100
playtime = 0
path = /Cthulhu Sleeps - Deadmau5.mp3
needs_upsampling_correction = False
channels = 0
genre_string = House / Electronic
playcount = 0
lastplayed = 0
composer = 0
score = 0
id3v1buf = nil
tagcache_idx = 0
index = 0
offset = 282966
rating = 0
samples = 0
tracknum = 0
vbr = False
albumartist = 0
disc_string = 0
albumart.type = 2
albumart.pos = 302
albumart.size = 173390
toc = nil
layer = 2
artist = Deadmau5
mb_track_id = 0
album = 4x4=12
id3v2buf = Cthulhu Sleeps
lead_trim = 576
id3v1len = 0
track_peak = 0
album_level = 0
extradata_size = 0
grouping = 0

Here is a sample of the generated settings.lua file the patch creates...
Code: [Select]
-- Don't change this file!
-- It is automatically generated $Revision$
-- member = {offset, size, "type"}

--#pointer#= 'ptr_', const= 'const_', enum= 'e_', signed= '', struct= 's_', unsigned= 'u_',
--#string#= 'str', bool= 'b', char= 'c', double= 'd', int= 'i', long= 'l', uint= 'u_i',

rb.system = {
}

rb.system.global_status = {
resume_index = {0x0, 4, "i"},
resume_crc32 = {0x4, 4, "u_i"},
resume_elapsed = {0x8, 4, "u_i"},
resume_offset = {0xc, 4, "u_i"},
runtime = {0x10, 4, "i"},
topruntime = {0x14, 4, "i"},
last_frequency = {0x18, 4, "i"},
last_screen = {0x1c, 1, "c"},
viewer_icon_count = {0x20, 4, "i"},
last_volume_change = {0x24, 4, "i"},
font_id = {0x28, 4, "i[1]"},
}

rb.system.global_settings = {
volume = {0x0, 4, "i"},
balance = {0x4, 4, "i"},
bass = {0x8, 4, "i"},
treble = {0xc, 4, "i"},
channel_config = {0x10, 4, "i"},
stereo_width = {0x14, 4, "i"},
crossfade = {0x18, 4, "i"},
crossfade_fade_in_delay = {0x1c, 4, "i"},
crossfade_fade_out_delay = {0x20, 4, "i"},
crossfade_fade_in_duration = {0x24, 4, "i"},
crossfade_fade_out_duration = {0x28, 4, "i"},
crossfade_fade_out_mixmode = {0x2c, 4, "i"},
replaygain_settings = {0x30, 12, "s_replaygain_settings"},
crossfeed = {0x3c, 4, "i"},
crossfeed_direct_gain = {0x40, 4, "u_i"},
crossfeed_cross_gain = {0x44, 4, "u_i"},
crossfeed_hf_attenuation = {0x48, 4, "u_i"},
crossfeed_hf_cutoff = {0x4c, 4, "u_i"},
eq_enabled = {0x50, 1, "b"},
eq_precut = {0x54, 4, "u_i"},
eq_band_settings = {0x58, 120, "s_eq_band_setting[10]"},
beep = {0xd0, 4, "i"},
keyclick = {0xd4, 4, "i"},
keyclick_repeats = {0xd8, 4, "i"},
dithering_enabled = {0xdc, 1, "b"},
timestretch_enabled = {0xdd, 1, "b"},
rec_format = {0xe0, 4, "i"},
rec_mono_mode = {0xe4, 4, "i"},
mp3_enc_config = {0xe8, 4, "s_mp3_enc_config"},
rec_source = {0xec, 4, "i"},
rec_frequency = {0xf0, 4, "i"},
rec_channels = {0xf4, 4, "i"},
rec_mic_gain = {0xf8, 4, "i"},
rec_left_gain = {0xfc, 4, "i"},
rec_right_gain = {0x100, 4, "i"},
peak_meter_clipcounter = {0x104, 1, "b"},
rec_editable = {0x105, 1, "b"},
rec_timesplit = {0x108, 4, "i"},
rec_sizesplit = {0x10c, 4, "i"},
rec_split_type = {0x110, 4, "i"},
rec_split_method = {0x114, 4, "i"},
rec_prerecord_time = {0x118, 4, "i"},
rec_directory = {0x11c, 81, "str"},
cliplight = {0x170, 4, "i"},
rec_start_thres_db = {0x174, 4, "i"},
rec_start_thres_linear = {0x178, 4, "i"},
rec_start_duration = {0x17c, 4, "i"},
rec_stop_thres_db = {0x180, 4, "i"},
rec_stop_thres_linear = {0x184, 4, "i"},
rec_stop_postrec = {0x188, 4, "i"},
rec_stop_gap = {0x18c, 4, "i"},
rec_trigger_mode = {0x190, 4, "i"},
rec_trigger_type = {0x194, 4, "i"},
fm_region = {0x198, 4, "i"},
fm_force_mono = {0x19c, 1, "b"},
fmr_file = {0x19d, 33, "str"},
fms_file = {0x1be, 33, "str"},
list_accel_start_delay = {0x1e0, 4, "i"},
list_accel_wait = {0x1e4, 4, "i"},
touchpad_sensitivity = {0x1e8, 4, "i"},
pause_rewind = {0x1ec, 4, "i"},
qs_items = {0x1f0, 16, "i[4]"},
timeformat = {0x200, 4, "i"},
dirfilter = {0x204, 4, "i"},
show_filename_ext = {0x208, 4, "i"},
default_codepage = {0x20c, 4, "i"},
hold_lr_for_scroll_in_list = {0x210, 1, "b"},
play_selected = {0x211, 1, "b"},
party_mode = {0x212, 1, "b"},
audioscrobbler = {0x213, 1, "b"},
cuesheet = {0x214, 1, "b"},
car_adapter_mode = {0x215, 1, "b"},
start_in_screen = {0x218, 4, "i"},
alarm_wake_up_screen = {0x21c, 4, "i"},
ff_rewind_min_step = {0x220, 4, "i"},
ff_rewind_accel = {0x224, 4, "i"},
peak_meter_release = {0x228, 4, "i"},
peak_meter_hold = {0x22c, 4, "i"},
peak_meter_clip_hold = {0x230, 4, "i"},
peak_meter_dbfs = {0x234, 1, "b"},
peak_meter_min = {0x238, 4, "i"},
peak_meter_max = {0x23c, 4, "i"},
wps_file = {0x240, 33, "str"},
sbs_file = {0x261, 33, "str"},
lang_file = {0x282, 33, "str"},
playlist_catalog_dir = {0x2a3, 81, "str"},
skip_length = {0x2f4, 4, "i"},
max_files_in_dir = {0x2f8, 4, "i"},
max_files_in_playlist = {0x2fc, 4, "i"},
volume_type = {0x300, 4, "i"},
battery_display = {0x304, 4, "i"},
show_icons = {0x308, 1, "b"},
statusbar = {0x30c, 4, "i"},
scrollbar = {0x310, 4, "i"},
scrollbar_width = {0x314, 4, "i"},
list_separator_height = {0x318, 4, "i"},
list_separator_color = {0x31c, 4, "i"},
browse_current = {0x320, 1, "b"},
scroll_paginated = {0x321, 1, "b"},
scroll_speed = {0x324, 4, "i"},
bidir_limit = {0x328, 4, "i"},
scroll_delay = {0x32c, 4, "i"},
scroll_step = {0x330, 4, "i"},
autoloadbookmark = {0x334, 4, "i"},
autocreatebookmark = {0x338, 4, "i"},
autoupdatebookmark = {0x33c, 1, "b"},
usemrb = {0x340, 4, "i"},
tagcache_ram = {0x344, 1, "b"},
tagcache_autoupdate = {0x345, 1, "b"},
autoresume_enable = {0x346, 1, "b"},
autoresume_automatic = {0x348, 4, "i"},
autoresume_paths = {0x34c, 81, "str"},
runtimedb = {0x39d, 1, "b"},
tagcache_scan_paths = {0x39e, 81, "str"},
backdrop_file = {0x3ef, 81, "str"},
bg_color = {0x440, 4, "i"},
fg_color = {0x444, 4, "i"},
lss_color = {0x448, 4, "i"},
lse_color = {0x44c, 4, "i"},
lst_color = {0x450, 4, "i"},
colors_file = {0x454, 33, "str"},
repeat_mode = {0x478, 4, "i"},
next_folder = {0x47c, 4, "i"},
constrain_next_folder = {0x480, 1, "b"},
recursive_dir_insert = {0x484, 4, "i"},
fade_on_stop = {0x488, 1, "b"},
playlist_shuffle = {0x489, 1, "b"},
warnon_erase_dynplaylist = {0x48a, 1, "b"},
playlist_viewer_icons = {0x48b, 1, "b"},
playlist_viewer_indices = {0x48c, 1, "b"},
playlist_viewer_track_display = {0x490, 4, "i"},
talk_menu = {0x494, 1, "b"},
talk_dir = {0x498, 4, "i"},
talk_dir_clip = {0x49c, 1, "b"},
talk_file = {0x4a0, 4, "i"},
talk_file_clip = {0x4a4, 1, "b"},
talk_filetype = {0x4a5, 1, "b"},
talk_battery_level = {0x4a6, 1, "b"},
sort_case = {0x4a7, 1, "b"},
sort_dir = {0x4a8, 4, "i"},
sort_file = {0x4ac, 4, "i"},
interpret_numbers = {0x4b0, 4, "i"},
poweroff = {0x4b4, 4, "i"},
battery_capacity = {0x4b8, 4, "i"},
invert = {0x4bc, 1, "b"},
flip_display = {0x4bd, 1, "b"},
cursor_style = {0x4c0, 4, "i"},
screen_scroll_step = {0x4c4, 4, "i"},
show_path_in_browser = {0x4c8, 4, "i"},
offset_out_of_view = {0x4cc, 1, "b"},
icon_file = {0x4cd, 33, "str"},
viewers_icon_file = {0x4ee, 33, "str"},
font_file = {0x50f, 33, "str"},
glyphs_to_cache = {0x530, 4, "i"},
kbd_file = {0x534, 33, "str"},
backlight_timeout = {0x558, 4, "i"},
caption_backlight = {0x55c, 1, "b"},
bl_filter_first_keypress = {0x55d, 1, "b"},
backlight_timeout_plugged = {0x560, 4, "i"},
bt_selective_softlock_actions = {0x564, 1, "b"},
bt_selective_softlock_actions_mask = {0x568, 4, "i"},
bl_selective_actions = {0x56c, 1, "b"},
bl_selective_actions_mask = {0x570, 4, "i"},
backlight_fade_in = {0x574, 1, "b"},
backlight_fade_out = {0x575, 1, "b"},
brightness = {0x578, 4, "i"},
prevent_skip = {0x57c, 1, "b"},
pitch_mode_semitone = {0x57d, 1, "b"},
pitch_mode_timestretch = {0x57e, 1, "b"},
ui_vp_config = {0x57f, 64, "str"},
compressor_settings = {0x5c0, 24, "s_compressor_settings"},
sleeptimer_duration = {0x5d8, 4, "i"},
sleeptimer_on_startup = {0x5dc, 1, "b"},
keypress_restarts_sleeptimer = {0x5dd, 1, "b"},
morse_input = {0x5de, 1, "b"},
hotkey_wps = {0x5e0, 4, "i"},
hotkey_tree = {0x5e4, 4, "i"},
resume_rewind = {0x5e8, 4, "i"},
depth_3d = {0x5ec, 4, "i"},
start_directory = {0x5f0, 81, "str"},
root_menu_customized = {0x641, 1, "b"},
shortcuts_replaces_qs = {0x642, 1, "b"},
play_frequency = {0x644, 4, "i"},
volume_limit = {0x648, 4, "i"},
surround_enabled = {0x64c, 4, "i"},
surround_balance = {0x650, 4, "i"},
surround_fx1 = {0x654, 4, "i"},
surround_fx2 = {0x658, 4, "i"},
surround_method2 = {0x65c, 1, "b"},
surround_mix = {0x660, 4, "i"},
pbe = {0x664, 4, "i"},
pbe_precut = {0x668, 4, "i"},
afr_enabled = {0x66c, 4, "i"},
}

rb.system.replaygain_settings = {
noclip = {0x0, 1, "b"},
type = {0x4, 4, "i"},
preamp = {0x8, 4, "i"},
}

rb.system.eq_band_setting = {
cutoff = {0x0, 4, "i"},
q = {0x4, 4, "i"},
gain = {0x8, 4, "i"},
}

rb.system.compressor_settings = {
threshold = {0x0, 4, "i"},
makeup_gain = {0x4, 4, "i"},
ratio = {0x8, 4, "i"},
knee = {0xc, 4, "i"},
release_time = {0x10, 4, "i"},
attack_time = {0x14, 4, "i"},
}

rb.system.mp3_enc_config = {
bitrate = {0x0, 4, "u_l"},
}

rb.metadata = {
}

rb.metadata.mp3_entry = {
path = {0x0, 260, "str"},
title = {0x104, 4, "ptr_char"},
artist = {0x108, 4, "ptr_char"},
album = {0x10c, 4, "ptr_char"},
genre_string = {0x110, 4, "ptr_char"},
disc_string = {0x114, 4, "ptr_char"},
track_string = {0x118, 4, "ptr_char"},
year_string = {0x11c, 4, "ptr_char"},
composer = {0x120, 4, "ptr_char"},
comment = {0x124, 4, "ptr_char"},
albumartist = {0x128, 4, "ptr_char"},
grouping = {0x12c, 4, "ptr_char"},
discnum = {0x130, 4, "i"},
tracknum = {0x134, 4, "i"},
layer = {0x138, 4, "i"},
year = {0x13c, 4, "i"},
id3version = {0x140, 1, "u_c"},
codectype = {0x144, 4, "u_i"},
bitrate = {0x148, 4, "u_i"},
frequency = {0x14c, 4, "u_l"},
id3v2len = {0x150, 4, "u_l"},
id3v1len = {0x154, 4, "u_l"},
first_frame_offset = {0x158, 4, "u_l"},
sim_filesize = {0x15c, 4, "u_l"},
length = {0x160, 4, "u_l"},
elapsed = {0x164, 4, "u_l"},
lead_trim = {0x168, 4, "i"},
tail_trim = {0x16c, 4, "i"},
samples = {0x170, 4, "u_l"},
frame_count = {0x174, 4, "u_l"},
bytesperframe = {0x178, 4, "u_l"},
vbr = {0x17c, 1, "b"},
has_toc = {0x17d, 1, "b"},
toc = {0x17e, 100, "str"},
channels = {0x1e4, 4, "u_i"},
extradata_size = {0x1e8, 4, "u_i"},
needs_upsampling_correction = {0x1ec, 1, "b"},
id3v2buf = {0x1ed, 900, "str"},
id3v1buf = {0x571, 368, "str"},
offset = {0x6e4, 4, "u_l"},
index = {0x6e8, 4, "i"},
autoresumable = {0x6ec, 1, "u_c"},
tagcache_idx = {0x6f0, 4, "l"},
rating = {0x6f4, 4, "i"},
score = {0x6f8, 4, "i"},
playcount = {0x6fc, 4, "l"},
lastplayed = {0x700, 4, "l"},
playtime = {0x704, 4, "l"},
track_level = {0x708, 4, "l"},
album_level = {0x70c, 4, "l"},
track_gain = {0x710, 4, "l"},
album_gain = {0x714, 4, "l"},
track_peak = {0x718, 4, "l"},
album_peak = {0x71c, 4, "l"},
has_embedded_albumart = {0x720, 1, "b"},
albumart = {0x724, 12, "s_mp3_albumart"},
has_embedded_cuesheet = {0x730, 1, "b"},
embedded_cuesheet = {0x734, 12, "s_embedded_cuesheet"},
cuesheet = {0x740, 4, "ptr_s_cuesheet"},
mb_track_id = {0x744, 4, "ptr_char"},
}

rb.metadata.mp3_albumart = {
type = {0x0, 4, "e_mp3_aa_type"},
size = {0x4, 4, "i"},
pos = {0x8, 4, "off_t"},
}

rb.metadata.embedded_cuesheet = {
size = {0x0, 4, "i"},
pos = {0x4, 4, "off_t"},
encoding = {0x8, 4, "e_character_encoding"},
}

Title: Re: Lua Using audio_current_track/audio_next_track
Post by: rokboxyo on October 14, 2018, 11:00:21 PM
that sounds great
It sure is something I can make use of ;D
Title: Re: Lua Using audio_current_track/audio_next_track
Post by: rokboxyo on October 20, 2018, 11:43:37 PM
so if I download the latest dev release this will be in it right?
Or do I have to download something else?
Title: Re: Lua Using audio_current_track/audio_next_track
Post by: saratoga on October 20, 2018, 11:51:23 PM
so if I download the latest dev release this will be in it right?


Not yet because the task above is still in Gerrit and not yet committed to git. You would have to download the code from Gerrit and then compile.