9d66b5459e
moved items to rb.system added read access to audio_current_track and audio_next_track Change-Id: Ia055b8cb3848e540067818f596ffd1058da057fb
846 lines
23 KiB
C
846 lines
23 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2008 Dan Everton (safetydan)
|
|
* Copyright (C) 2009 Maurus Cuelenaere
|
|
* Copyright (C) 2018 William Wilgus
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#define lrocklib_c
|
|
#define LUA_LIB
|
|
|
|
#include "lua.h"
|
|
|
|
#include "lauxlib.h"
|
|
#include "rocklib.h"
|
|
#include "lib/helper.h"
|
|
#include "lib/pluginlib_actions.h"
|
|
|
|
/*
|
|
* http://www.lua.org/manual/5.1/manual.html#lua_CFunction
|
|
*
|
|
* In order to communicate properly with Lua, a C function must use the following protocol,
|
|
* which defines the way parameters and results are passed: a C function receives its arguments
|
|
* from Lua in its stack in direct order (the first argument is pushed first). To return values to Lua,
|
|
* a C function just pushes them onto the stack, in direct order (the first result is pushed first),
|
|
* and returns the number of results. Any other value in the stack below the results will be properly
|
|
* discarded by Lua. Like a Lua function, a C function called by Lua can also return many results.
|
|
*
|
|
* When porting new functions, don't forget to check rocklib_aux.pl whether it automatically creates
|
|
* wrappers for the function and if so, add the function names to @forbidden_functions. This is to
|
|
* prevent namespace collisions and adding duplicate wrappers.
|
|
*/
|
|
|
|
/*
|
|
* -----------------------------
|
|
*
|
|
* Rockbox wrappers start here!
|
|
*
|
|
* -----------------------------
|
|
*/
|
|
|
|
#define RB_WRAP(func) static int rock_##func(lua_State UNUSED_ATTR *L)
|
|
#define SIMPLE_VOID_WRAPPER(func) RB_WRAP(func) { (void)L; func(); return 0; }
|
|
|
|
RB_WRAP(current_tick)
|
|
{
|
|
lua_pushinteger(L, *rb->current_tick);
|
|
return 1;
|
|
}
|
|
|
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
|
RB_WRAP(schedule_cpu_boost)
|
|
{
|
|
bool boost = luaL_checkboolean(L, 1);
|
|
|
|
if(boost)
|
|
rb->trigger_cpu_boost();
|
|
else
|
|
rb->cancel_cpu_boost();
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
RB_WRAP(current_path)
|
|
{
|
|
return get_current_path(L, 1);
|
|
}
|
|
|
|
|
|
/* DEVICE INPUT CONTROL */
|
|
|
|
RB_WRAP(get_plugin_action)
|
|
{
|
|
static const struct button_mapping *m1[] = { pla_main_ctx };
|
|
int timeout = luaL_checkint(L, 1);
|
|
int btn;
|
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
static const struct button_mapping *m2[] = { pla_main_ctx, pla_remote_ctx };
|
|
bool with_remote = luaL_optint(L, 2, 0);
|
|
if (with_remote)
|
|
btn = pluginlib_getaction(timeout, m2, 2);
|
|
else
|
|
#endif
|
|
btn = pluginlib_getaction(timeout, m1, 1);
|
|
|
|
lua_pushinteger(L, btn);
|
|
return 1;
|
|
}
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
RB_WRAP(action_get_touchscreen_press)
|
|
{
|
|
short x, y;
|
|
int result = rb->action_get_touchscreen_press(&x, &y);
|
|
|
|
lua_pushinteger(L, result);
|
|
lua_pushinteger(L, x);
|
|
lua_pushinteger(L, y);
|
|
return 3;
|
|
}
|
|
|
|
RB_WRAP(touchscreen_mode)
|
|
{
|
|
int origmode = rb->touchscreen_get_mode();
|
|
if(!lua_isnoneornil(L, 1))
|
|
{
|
|
enum touchscreen_mode mode = luaL_checkint(L, 1);
|
|
rb->touchscreen_set_mode(mode);
|
|
}
|
|
lua_pushinteger(L, origmode);
|
|
return 1;
|
|
}
|
|
|
|
#endif
|
|
|
|
RB_WRAP(kbd_input)
|
|
{
|
|
luaL_Buffer b;
|
|
luaL_buffinit(L, &b);
|
|
|
|
const char *input = lua_tostring(L, 1);
|
|
char *buffer = luaL_prepbuffer(&b);
|
|
|
|
if(input != NULL)
|
|
rb->strlcpy(buffer, input, LUAL_BUFFERSIZE);
|
|
else
|
|
buffer[0] = '\0';
|
|
|
|
if(!rb->kbd_input(buffer, LUAL_BUFFERSIZE))
|
|
{
|
|
luaL_addstring(&b, buffer);
|
|
luaL_pushresult(&b);
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const char ** get_table_items(lua_State *L, int pos, int *count)
|
|
{
|
|
int i;
|
|
luaL_checktype(L, pos, LUA_TTABLE);
|
|
*count = lua_objlen(L, pos);
|
|
int n = *count;
|
|
|
|
/* newuserdata will be pushed onto stack after args*/
|
|
const char **items = (const char**) lua_newuserdata(L, n * sizeof(const char*));
|
|
|
|
for(i=1; i<= n; i++)
|
|
{
|
|
lua_rawgeti(L, pos, i); /* Push item on the stack */
|
|
items[i-1] = lua_tostring(L, -1);
|
|
lua_pop(L, 1); /* Pop it */
|
|
}
|
|
|
|
return items;
|
|
}
|
|
|
|
static inline void fill_text_message(lua_State *L, struct text_message * message,
|
|
int pos)
|
|
{
|
|
int n;
|
|
/* newuserdata will be pushed onto stack after args*/
|
|
message->message_lines = get_table_items(L, pos, &n);
|
|
message->nb_lines = n;
|
|
}
|
|
|
|
RB_WRAP(gui_syncyesno_run)
|
|
{
|
|
struct text_message main_message, yes_message, no_message;
|
|
struct text_message *yes = NULL, *no = NULL;
|
|
|
|
lua_settop(L, 3); /* newuserdata will be pushed onto stack after args*/
|
|
fill_text_message(L, &main_message, 1);
|
|
if(!lua_isnoneornil(L, 2))
|
|
fill_text_message(L, (yes = &yes_message), 2);
|
|
if(!lua_isnoneornil(L, 3))
|
|
fill_text_message(L, (no = &no_message), 3);
|
|
|
|
enum yesno_res result = rb->gui_syncyesno_run(&main_message, yes, no);
|
|
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(do_menu)
|
|
{
|
|
struct menu_callback_with_desc menu_desc = {NULL, NULL, Icon_NOICON};
|
|
struct menu_item_ex menu = {MT_RETURN_ID | MENU_HAS_DESC, {.strings = NULL},
|
|
{.callback_and_desc = &menu_desc}};
|
|
int n, start_selected;
|
|
const char **items, *title;
|
|
|
|
title = luaL_checkstring(L, 1);
|
|
|
|
start_selected = lua_tointeger(L, 3);
|
|
|
|
/* newuserdata will be pushed onto stack after args*/
|
|
items = get_table_items(L, 2, &n);
|
|
|
|
menu.strings = items;
|
|
menu.flags |= MENU_ITEM_COUNT(n);
|
|
menu_desc.desc = (unsigned char*) title;
|
|
|
|
int result = rb->do_menu(&menu, &start_selected, NULL, false);
|
|
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* DEVICE AUDIO / PLAYLIST CONTROL */
|
|
|
|
RB_WRAP(playlist)
|
|
{
|
|
/* just passes NULL to work with the current playlist */
|
|
enum e_playlist {PLAYL_AMOUNT = 0, PLAYL_ADD, PLAYL_CREATE,
|
|
PLAYL_START, PLAYL_RESUMETRACK, PLAYL_RESUME,
|
|
PLAYL_SHUFFLE, PLAYL_SYNC, PLAYL_REMOVEALLTRACKS,
|
|
PLAYL_INSERTTRACK, PLAYL_INSERTDIRECTORY, PLAYL_ECOUNT};
|
|
|
|
const char *playlist_option[] = {"amount", "add", "create", "start", "resume_track",
|
|
"resume", "shuffle", "sync", "remove_all_tracks",
|
|
"insert_track", "insert_directory", NULL};
|
|
|
|
const char *filename, *dir;
|
|
int result = 0;
|
|
bool queue, recurse, sync;
|
|
int pos, crc, index, random_seed;
|
|
unsigned long elapsed, offset;
|
|
|
|
int option = luaL_checkoption (L, 1, NULL, playlist_option);
|
|
switch(option)
|
|
{
|
|
case PLAYL_AMOUNT:
|
|
result = rb->playlist_amount();
|
|
break;
|
|
case PLAYL_ADD:
|
|
filename = luaL_checkstring(L, 2);
|
|
result = rb->playlist_add(filename);
|
|
break;
|
|
case PLAYL_CREATE:
|
|
dir = luaL_checkstring(L, 2);
|
|
filename = luaL_checkstring(L, 3);
|
|
result = rb->playlist_create(dir, filename);
|
|
break;
|
|
case PLAYL_START:
|
|
index = luaL_checkint(L, 2);
|
|
elapsed = luaL_checkint(L, 3);
|
|
offset = luaL_checkint(L, 4);
|
|
rb->playlist_start(index, elapsed, offset);
|
|
break;
|
|
case PLAYL_RESUMETRACK:
|
|
index = luaL_checkint(L, 2);
|
|
crc = luaL_checkint(L, 3);
|
|
elapsed = luaL_checkint(L, 4);
|
|
offset = luaL_checkint(L, 5);
|
|
rb->playlist_resume_track(index, (unsigned) crc, elapsed, offset);
|
|
break;
|
|
case PLAYL_RESUME:
|
|
result = rb->playlist_resume();
|
|
break;
|
|
case PLAYL_SHUFFLE:
|
|
random_seed = luaL_checkint(L, 2);
|
|
index = luaL_checkint(L, 3);
|
|
result = rb->playlist_shuffle(random_seed, index);
|
|
break;
|
|
case PLAYL_SYNC:
|
|
rb->playlist_sync(NULL);
|
|
break;
|
|
case PLAYL_REMOVEALLTRACKS:
|
|
result = rb->playlist_remove_all_tracks(NULL);
|
|
break;
|
|
case PLAYL_INSERTTRACK:
|
|
filename = luaL_checkstring(L, 2); /* only required parameter */
|
|
pos = luaL_optint(L, 3, PLAYLIST_INSERT);
|
|
queue = lua_toboolean(L, 4); /* default to false */
|
|
sync = lua_toboolean(L, 5); /* default to false */
|
|
result = rb->playlist_insert_track(NULL, filename, pos, queue, sync);
|
|
break;
|
|
case PLAYL_INSERTDIRECTORY:
|
|
dir = luaL_checkstring(L, 2); /* only required parameter */
|
|
pos = luaL_optint(L, 3, PLAYLIST_INSERT);
|
|
queue = lua_toboolean(L, 4); /* default to false */
|
|
recurse = lua_toboolean(L, 5); /* default to false */
|
|
result = rb->playlist_insert_directory(NULL, dir, pos, queue, recurse);
|
|
break;
|
|
}
|
|
|
|
rb->yield();
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(audio)
|
|
{
|
|
enum e_audio {AUDIO_STATUS = 0, AUDIO_PLAY, AUDIO_STOP, AUDIO_PAUSE,
|
|
AUDIO_RESUME, AUDIO_NEXT, AUDIO_PREV, AUDIO_FFREWIND,
|
|
AUDIO_FLUSHANDRELOADTRACKS, AUDIO_GETPOS, AUDIO_ECOUNT};
|
|
const char *audio_option[] = {"status", "play", "stop", "pause",
|
|
"resume", "next", "prev", "ff_rewind",
|
|
"flush_and_reload_tracks", "get_file_pos", NULL};
|
|
long elapsed, offset, newtime;
|
|
int status = rb->audio_status();
|
|
|
|
int option = luaL_checkoption (L, 1, NULL, audio_option);
|
|
switch(option)
|
|
{
|
|
case AUDIO_STATUS:
|
|
break;
|
|
case AUDIO_PLAY:
|
|
elapsed = luaL_checkint(L, 2);
|
|
offset = luaL_checkint(L, 3);
|
|
|
|
if (status == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE))
|
|
{
|
|
/* not perfect but provides a decent compromise */
|
|
rb->audio_ff_rewind(elapsed + offset);
|
|
rb->audio_resume();
|
|
}
|
|
else if (status != AUDIO_STATUS_PLAY)
|
|
rb->audio_play((unsigned long) elapsed, (unsigned long) offset);
|
|
|
|
break;
|
|
case AUDIO_STOP:
|
|
rb->audio_stop();
|
|
break;
|
|
case AUDIO_PAUSE:
|
|
rb->audio_pause();
|
|
break;
|
|
case AUDIO_RESUME:
|
|
rb->audio_resume();
|
|
break;
|
|
case AUDIO_NEXT:
|
|
rb->audio_next();
|
|
break;
|
|
case AUDIO_PREV:
|
|
rb->audio_prev();
|
|
break;
|
|
case AUDIO_FFREWIND:
|
|
newtime = (long) luaL_checkint(L, 2);
|
|
rb->audio_ff_rewind(newtime);
|
|
break;
|
|
case AUDIO_FLUSHANDRELOADTRACKS:
|
|
rb->audio_flush_and_reload_tracks();
|
|
break;
|
|
case AUDIO_GETPOS:
|
|
lua_pushinteger(L, rb->audio_get_file_pos());
|
|
return 1;
|
|
}
|
|
|
|
rb->yield();
|
|
lua_pushinteger(L, status); /* return previous (or current) audio status */
|
|
return 1;
|
|
}
|
|
|
|
#if CONFIG_CODEC == SWCODEC
|
|
RB_WRAP(pcm)
|
|
{
|
|
enum e_pcm {PCM_APPLYSETTINGS = 0, PCM_ISPLAYING, PCM_ISPAUSED,
|
|
PCM_PLAYSTOP, PCM_PLAYPAUSE, PCM_PLAYLOCK, PCM_PLAYUNLOCK,
|
|
PCM_CALCULATEPEAKS, PCM_SETFREQUENCY, PCM_GETBYTESWAITING, PCM_ECOUNT};
|
|
|
|
const char *pcm_option[] = {"apply_settings", "is_playing", "is_paused",
|
|
"play_stop", "play_pause", "play_lock", "play_unlock",
|
|
"calculate_peaks", "set_frequency", "get_bytes_waiting", NULL};
|
|
bool b_result;
|
|
int left, right;
|
|
size_t byteswait;
|
|
|
|
lua_pushnil(L); /*push nil so options w/o return have something to return */
|
|
|
|
int option = luaL_checkoption (L, 1, NULL, pcm_option);
|
|
switch(option)
|
|
{
|
|
case PCM_APPLYSETTINGS:
|
|
rb->pcm_apply_settings();
|
|
break;
|
|
case PCM_ISPLAYING:
|
|
b_result = rb->pcm_is_playing();
|
|
lua_pushboolean(L, b_result);
|
|
break;
|
|
case PCM_ISPAUSED:
|
|
b_result = rb->pcm_is_paused();
|
|
lua_pushboolean(L, b_result);
|
|
break;
|
|
case PCM_PLAYPAUSE:
|
|
rb->pcm_play_pause(luaL_checkboolean(L, 2));
|
|
break;
|
|
case PCM_PLAYSTOP:
|
|
rb->pcm_play_stop();
|
|
break;
|
|
case PCM_PLAYLOCK:
|
|
rb->pcm_play_lock();
|
|
break;
|
|
case PCM_PLAYUNLOCK:
|
|
rb->pcm_play_unlock();
|
|
break;
|
|
case PCM_CALCULATEPEAKS:
|
|
rb->pcm_calculate_peaks(&left, &right);
|
|
lua_pushinteger(L, left);
|
|
lua_pushinteger(L, right);
|
|
return 2;
|
|
case PCM_SETFREQUENCY:
|
|
rb->pcm_set_frequency((unsigned int) luaL_checkint(L, 2));
|
|
break;
|
|
case PCM_GETBYTESWAITING:
|
|
byteswait = rb->pcm_get_bytes_waiting();
|
|
lua_pushinteger(L, byteswait);
|
|
break;
|
|
}
|
|
|
|
rb->yield();
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(mixer_frequency)
|
|
{
|
|
unsigned int result = rb->mixer_get_frequency();
|
|
|
|
if(!lua_isnoneornil(L, 1))
|
|
{
|
|
unsigned int samplerate = (unsigned int) luaL_checkint(L, 1);
|
|
rb->mixer_set_frequency(samplerate);
|
|
}
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
#endif /*CONFIG_CODEC == SWCODEC*/
|
|
|
|
/* DEVICE LIGHTING CONTROL */
|
|
RB_WRAP(backlight_onoff)
|
|
{
|
|
bool on = luaL_checkboolean(L, 1);
|
|
if(on)
|
|
rb->backlight_on();
|
|
else
|
|
rb->backlight_off();
|
|
|
|
return 0;
|
|
}
|
|
|
|
SIMPLE_VOID_WRAPPER(backlight_force_on);
|
|
SIMPLE_VOID_WRAPPER(backlight_use_settings);
|
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
SIMPLE_VOID_WRAPPER(remote_backlight_force_on);
|
|
SIMPLE_VOID_WRAPPER(remote_backlight_use_settings);
|
|
#endif
|
|
|
|
#ifdef HAVE_BUTTON_LIGHT
|
|
SIMPLE_VOID_WRAPPER(buttonlight_force_on);
|
|
SIMPLE_VOID_WRAPPER(buttonlight_use_settings);
|
|
#endif
|
|
|
|
#ifdef HAVE_BACKLIGHT_BRIGHTNESS
|
|
RB_WRAP(backlight_brightness_set)
|
|
{
|
|
if(lua_isnoneornil(L, 1))
|
|
backlight_brightness_use_setting();
|
|
else
|
|
{
|
|
int brightness = luaL_checkint(L, 1);
|
|
backlight_brightness_set(brightness);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
|
|
RB_WRAP(buttonlight_brightness_set)
|
|
{
|
|
if(lua_isnoneornil(L, 1))
|
|
buttonlight_brightness_use_setting();
|
|
else
|
|
{
|
|
int brightness = luaL_checkint(L, 1);
|
|
buttonlight_brightness_set(brightness);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* DEVICE STRING / FILENAME MANIPULATION */
|
|
|
|
RB_WRAP(strip_extension)
|
|
{
|
|
const char* filename = luaL_checkstring(L, -1);
|
|
const char* pos = rb->strrchr(filename, '.');
|
|
if(pos != NULL)
|
|
lua_pushlstring (L, filename, pos - filename);
|
|
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(create_numbered_filename)
|
|
{
|
|
luaL_Buffer b;
|
|
luaL_buffinit(L, &b);
|
|
char *buffer = luaL_prepbuffer(&b);
|
|
buffer[0] = '\0';
|
|
|
|
const char * path = luaL_checkstring(L, 1);
|
|
const char * prefix = luaL_checkstring(L, 2);
|
|
const char * suffix = luaL_checkstring(L, 3);
|
|
int numberlen = luaL_checkint(L, 4);
|
|
int num = luaL_optint(L, 5, -1);
|
|
(void) num;
|
|
|
|
if(rb->create_numbered_filename(buffer, path, prefix, suffix, numberlen
|
|
IF_CNFN_NUM_(, &num)))
|
|
{
|
|
luaL_addstring(&b, buffer);
|
|
luaL_pushresult(&b);
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(utf8encode)
|
|
{
|
|
unsigned long ucs = (unsigned long) luaL_checkint(L, 1);
|
|
unsigned char tmp[9];
|
|
unsigned char *end = rb->utf8encode(ucs, tmp);
|
|
*end = '\0';
|
|
lua_pushstring(L, tmp);
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(strncasecmp)
|
|
{
|
|
int result;
|
|
const char * s1 = luaL_checkstring(L, 1);
|
|
const char * s2 = luaL_checkstring(L, 2);
|
|
if(lua_isnoneornil(L, 3))
|
|
result = rb->strcasecmp(s1, s2);
|
|
else
|
|
result = rb->strncasecmp(s1, s2, (size_t) luaL_checkint(L, 3));
|
|
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize)
|
|
{
|
|
intptr_t offset = (intptr_t) luaL_optint(L, 1, 0);
|
|
size_t size = (size_t) luaL_optint(L, 2, maxsize);
|
|
size_t written;
|
|
int type = lua_type(L, 3);
|
|
|
|
if(offset < 0)
|
|
{
|
|
/* allows pointer within structure to be calculated offset */
|
|
offset = -(address + offset);
|
|
size = (size_t) maxsize - offset;
|
|
}
|
|
|
|
luaL_argcheck(L, ((uintptr_t) offset) + size <= maxsize, 2, ERR_IDX_RANGE);
|
|
|
|
char *mem = (char*) address + ((uintptr_t) offset);
|
|
const void *value = NULL;
|
|
|
|
lua_Integer var_luaint;
|
|
#ifdef UINT64_MAX
|
|
int64_t var_64;
|
|
#endif
|
|
int32_t var_32;
|
|
int16_t var_16;
|
|
int8_t var_8;
|
|
bool var_bool;
|
|
|
|
switch(type)
|
|
{
|
|
case LUA_TSTRING:
|
|
{
|
|
size_t len;
|
|
const char* str = lua_tolstring (L, 3, &len);
|
|
|
|
luaL_argcheck(L, len + 1 <= size, 3, ERR_DATA_OVF);
|
|
size = len + 1; /* include \0 */
|
|
value = str;
|
|
break;
|
|
}
|
|
case LUA_TBOOLEAN:
|
|
{
|
|
var_bool = (bool) lua_toboolean(L, 3);
|
|
value = &var_bool;
|
|
break;
|
|
}
|
|
case LUA_TNUMBER:
|
|
{
|
|
var_luaint = lua_tointeger(L, 3);
|
|
switch(size)
|
|
{
|
|
case sizeof(var_8):
|
|
var_8 = (int8_t) var_luaint;
|
|
value = &var_8;
|
|
break;
|
|
case sizeof(var_16):
|
|
var_16 = (int16_t) var_luaint;
|
|
value = &var_16;
|
|
break;
|
|
case sizeof(var_32):
|
|
var_32 = (int32_t) var_luaint;
|
|
value = &var_32;
|
|
break;
|
|
#ifdef UINT64_MAX
|
|
case sizeof(var_64):
|
|
var_64 = (int64_t) var_luaint;
|
|
value = &var_64;
|
|
break;
|
|
#endif
|
|
} /* switch size */
|
|
break;
|
|
}
|
|
case LUA_TNIL:
|
|
case LUA_TNONE: /* reader */
|
|
{
|
|
luaL_Buffer b;
|
|
luaL_buffinit(L, &b);
|
|
while(size > 0)
|
|
{
|
|
written = MIN(LUAL_BUFFERSIZE, size);
|
|
luaL_addlstring (&b, mem, written);
|
|
mem += written;
|
|
size -= written;
|
|
}
|
|
|
|
luaL_pushresult(&b);
|
|
return 1;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
} /* switch type */
|
|
|
|
/* writer */
|
|
luaL_argcheck(L, value != NULL, 3, "Unknown Type");
|
|
rb->memcpy(mem, value, size);
|
|
lua_pushinteger(L, 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
RB_WRAP(global_status)
|
|
{
|
|
const uintptr_t address = (uintptr_t) rb->global_status;
|
|
const size_t maxsize = sizeof(struct system_status);
|
|
return mem_read_write(L, address, maxsize);
|
|
}
|
|
|
|
RB_WRAP(global_settings)
|
|
{
|
|
const uintptr_t address = (uintptr_t) rb->global_settings;
|
|
const size_t maxsize = sizeof(struct user_settings);
|
|
return mem_read_write(L, address, maxsize);
|
|
}
|
|
|
|
RB_WRAP(audio_next_track)
|
|
{
|
|
lua_settop(L, 2); /* no writes allowed */
|
|
const uintptr_t address = (uintptr_t) rb->audio_next_track();
|
|
const size_t maxsize = sizeof(struct mp3entry);
|
|
return mem_read_write(L, address, maxsize);
|
|
}
|
|
|
|
RB_WRAP(audio_current_track)
|
|
{
|
|
lua_settop(L, 2); /* no writes allowed */
|
|
const uintptr_t address = (uintptr_t) rb->audio_current_track();
|
|
const size_t maxsize = sizeof(struct mp3entry);
|
|
return mem_read_write(L, address, maxsize);
|
|
}
|
|
|
|
#define RB_FUNC(func) {#func, rock_##func}
|
|
#define RB_ALIAS(name, func) {name, rock_##func}
|
|
static const luaL_Reg rocklib[] =
|
|
{
|
|
/* Kernel */
|
|
RB_FUNC(current_tick),
|
|
#ifdef HAVE_SCHEDULER_BOOSTCTRL
|
|
RB_FUNC(schedule_cpu_boost),
|
|
#endif
|
|
|
|
RB_FUNC(current_path),
|
|
|
|
/* DEVICE INPUT CONTROL */
|
|
RB_FUNC(get_plugin_action),
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
RB_FUNC(action_get_touchscreen_press),
|
|
RB_FUNC(touchscreen_mode),
|
|
#endif
|
|
RB_FUNC(kbd_input),
|
|
RB_FUNC(gui_syncyesno_run),
|
|
RB_FUNC(do_menu),
|
|
|
|
/* DEVICE AUDIO / PLAYLIST CONTROL */
|
|
RB_FUNC(audio),
|
|
RB_FUNC(playlist),
|
|
#if CONFIG_CODEC == SWCODEC
|
|
RB_FUNC(pcm),
|
|
RB_FUNC(mixer_frequency),
|
|
#endif
|
|
|
|
/* DEVICE LIGHTING CONTROL */
|
|
RB_FUNC(backlight_onoff),
|
|
|
|
/* Backlight helper */
|
|
RB_FUNC(backlight_force_on),
|
|
RB_FUNC(backlight_use_settings),
|
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
RB_FUNC(remote_backlight_force_on),
|
|
RB_FUNC(remote_backlight_use_settings),
|
|
#endif
|
|
|
|
#ifdef HAVE_BUTTON_LIGHT
|
|
RB_FUNC(buttonlight_force_on),
|
|
RB_FUNC(buttonlight_use_settings),
|
|
#endif
|
|
|
|
#ifdef HAVE_BACKLIGHT_BRIGHTNESS
|
|
RB_FUNC(backlight_brightness_set),
|
|
#endif
|
|
|
|
#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
|
|
RB_FUNC(buttonlight_brightness_set),
|
|
#endif
|
|
|
|
/* DEVICE STRING / FILENAME MANIPULATION */
|
|
RB_FUNC(strip_extension),
|
|
RB_FUNC(create_numbered_filename),
|
|
RB_FUNC(utf8encode),
|
|
RB_FUNC(strncasecmp),
|
|
|
|
/* ROCKBOX SETTINGS / INFO */
|
|
RB_FUNC(global_status),
|
|
RB_FUNC(global_settings),
|
|
RB_FUNC(audio_next_track),
|
|
RB_FUNC(audio_current_track),
|
|
|
|
{NULL, NULL}
|
|
};
|
|
#undef RB_FUNC
|
|
#undef RB_ALIAS
|
|
|
|
extern const luaL_Reg rocklib_aux[];
|
|
|
|
/*
|
|
** Open Rockbox library
|
|
*/
|
|
LUALIB_API int luaopen_rock(lua_State *L)
|
|
{
|
|
luaL_register(L, LUA_ROCKLIBNAME, rocklib);
|
|
luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux);
|
|
|
|
static const struct lua_int_reg rlib_const_int[] =
|
|
{
|
|
/* useful integer constants */
|
|
RB_CONSTANT(HZ),
|
|
|
|
RB_CONSTANT(LCD_DEPTH),
|
|
RB_CONSTANT(LCD_HEIGHT),
|
|
RB_CONSTANT(LCD_WIDTH),
|
|
RB_CONSTANT(SCREEN_MAIN),
|
|
#if LCD_DEPTH > 1
|
|
RB_CONSTANT(LCD_DEFAULT_FG),
|
|
RB_CONSTANT(LCD_DEFAULT_BG),
|
|
#endif
|
|
#ifdef HAVE_REMOTE_LCD
|
|
RB_CONSTANT(LCD_REMOTE_DEPTH),
|
|
RB_CONSTANT(LCD_REMOTE_HEIGHT),
|
|
RB_CONSTANT(LCD_REMOTE_WIDTH),
|
|
RB_CONSTANT(SCREEN_REMOTE),
|
|
#endif
|
|
|
|
RB_CONSTANT(FONT_SYSFIXED),
|
|
RB_CONSTANT(FONT_UI),
|
|
|
|
RB_CONSTANT(PLAYLIST_INSERT),
|
|
RB_CONSTANT(PLAYLIST_INSERT_LAST),
|
|
RB_CONSTANT(PLAYLIST_INSERT_FIRST),
|
|
RB_CONSTANT(PLAYLIST_INSERT_LAST_SHUFFLED),
|
|
RB_CONSTANT(PLAYLIST_INSERT_SHUFFLED),
|
|
RB_CONSTANT(PLAYLIST_PREPEND),
|
|
RB_CONSTANT(PLAYLIST_REPLACE),
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
RB_CONSTANT(TOUCHSCREEN_POINT),
|
|
RB_CONSTANT(TOUCHSCREEN_BUTTON),
|
|
#endif
|
|
|
|
{NULL, 0}
|
|
};
|
|
|
|
static const struct lua_int_reg* rlci = rlib_const_int;
|
|
for (; rlci->name; rlci++) {
|
|
lua_pushinteger(L, rlci->value);
|
|
lua_setfield(L, -2, rlci->name);
|
|
}
|
|
|
|
static const struct lua_str_reg rlib_const_str[] =
|
|
{
|
|
/* some useful paths constants */
|
|
RB_STRING_CONSTANT(HOME_DIR),
|
|
RB_STRING_CONSTANT(PLUGIN_DIR),
|
|
RB_STRING_CONSTANT(PLUGIN_APPS_DATA_DIR),
|
|
RB_STRING_CONSTANT(PLUGIN_GAMES_DATA_DIR),
|
|
RB_STRING_CONSTANT(PLUGIN_DATA_DIR),
|
|
RB_STRING_CONSTANT(ROCKBOX_DIR),
|
|
RB_STRING_CONSTANT(VIEWERS_DATA_DIR),
|
|
{NULL,NULL}
|
|
};
|
|
|
|
static const struct lua_str_reg* rlcs = rlib_const_str;
|
|
for (; rlcs->name; rlcs++) {
|
|
lua_pushstring(L, rlcs->value);
|
|
lua_setfield(L, -2, rlcs->name);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|