blob: 8c662b7359f8b0d8ce782e81471889c3fa96a1e9 [file] [log] [blame]
Maurus Cuelenaerecf875972009-05-21 19:01:41 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 Dan Everton (safetydan)
11 * Copyright (C) 2009 Maurus Cuelenaere
William Wilgusf6e10b82018-11-01 14:20:33 -040012 * Copyright (C) 2018 William Wilgus
Maurus Cuelenaerecf875972009-05-21 19:01:41 +000013 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#define lrocklib_c
25#define LUA_LIB
26
27#include "lua.h"
William Wilgusc6fcb1c2018-11-11 18:27:19 -050028#include "lstring.h"
Maurus Cuelenaerecf875972009-05-21 19:01:41 +000029
30#include "lauxlib.h"
31#include "rocklib.h"
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +000032#include "lib/helper.h"
Maurus Cuelenaerecf875972009-05-21 19:01:41 +000033
Maurus Cuelenaerea9b2d1b2009-05-21 19:42:14 +000034/*
35 * http://www.lua.org/manual/5.1/manual.html#lua_CFunction
36 *
37 * In order to communicate properly with Lua, a C function must use the following protocol,
38 * which defines the way parameters and results are passed: a C function receives its arguments
39 * from Lua in its stack in direct order (the first argument is pushed first). To return values to Lua,
40 * a C function just pushes them onto the stack, in direct order (the first result is pushed first),
41 * and returns the number of results. Any other value in the stack below the results will be properly
William Wilgus4508ee92018-05-31 14:15:05 +020042 * discarded by Lua. Like a Lua function, a C function called by Lua can also return many results.
Maurus Cuelenaered8cef9c2010-06-18 12:28:34 +000043 *
44 * When porting new functions, don't forget to check rocklib_aux.pl whether it automatically creates
45 * wrappers for the function and if so, add the function names to @forbidden_functions. This is to
46 * prevent namespace collisions and adding duplicate wrappers.
Maurus Cuelenaerea9b2d1b2009-05-21 19:42:14 +000047 */
Maurus Cuelenaere86fe1e82009-05-24 01:54:15 +000048
Maurus Cuelenaere86fe1e82009-05-24 01:54:15 +000049/*
50 * -----------------------------
51 *
52 * Rockbox wrappers start here!
53 *
54 * -----------------------------
55 */
56
William Wilguse4b84332018-09-17 19:28:10 +020057#define RB_WRAP(func) static int rock_##func(lua_State UNUSED_ATTR *L)
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +000058#define SIMPLE_VOID_WRAPPER(func) RB_WRAP(func) { (void)L; func(); return 0; }
Maurus Cuelenaerecf875972009-05-21 19:01:41 +000059
Maurus Cuelenaerecf875972009-05-21 19:01:41 +000060RB_WRAP(current_tick)
61{
62 lua_pushinteger(L, *rb->current_tick);
63 return 1;
64}
65
William Wilgusf6e10b82018-11-01 14:20:33 -040066#ifdef HAVE_SCHEDULER_BOOSTCTRL
67RB_WRAP(schedule_cpu_boost)
68{
69 bool boost = luaL_checkboolean(L, 1);
70
71 if(boost)
72 rb->trigger_cpu_boost();
73 else
74 rb->cancel_cpu_boost();
75
76 return 0;
77}
78#endif
79
Franklin Wei8379b232019-07-28 14:56:59 -040080#ifdef HAVE_PRIORITY_SCHEDULING
William Wilgusddf612c2019-07-28 07:26:20 -050081RB_WRAP(thread_set_priority)
82{
83 unsigned int thread_id = rb->thread_self();
84 int priority = (int) luaL_checkint(L, 1);
85 int result = rb->thread_set_priority(thread_id, priority);
86 lua_pushinteger(L, result);
87 return 1;
88}
Franklin Wei8379b232019-07-28 14:56:59 -040089#endif
William Wilgusddf612c2019-07-28 07:26:20 -050090
William Wilgusf6e10b82018-11-01 14:20:33 -040091RB_WRAP(current_path)
92{
93 return get_current_path(L, 1);
94}
95
96
97/* DEVICE INPUT CONTROL */
98
99RB_WRAP(get_plugin_action)
100{
William Wilgusf6e10b82018-11-01 14:20:33 -0400101 int timeout = luaL_checkint(L, 1);
William Wilgusf6e10b82018-11-01 14:20:33 -0400102 bool with_remote = luaL_optint(L, 2, 0);
William Wilgus3e2b50e2019-06-27 11:28:34 -0500103 int btn = get_plugin_action(timeout, with_remote);
William Wilgusf6e10b82018-11-01 14:20:33 -0400104 lua_pushinteger(L, btn);
105 return 1;
106}
107
108#ifdef HAVE_TOUCHSCREEN
109RB_WRAP(action_get_touchscreen_press)
110{
111 short x, y;
112 int result = rb->action_get_touchscreen_press(&x, &y);
113
114 lua_pushinteger(L, result);
115 lua_pushinteger(L, x);
116 lua_pushinteger(L, y);
117 return 3;
118}
119
120RB_WRAP(touchscreen_mode)
121{
122 int origmode = rb->touchscreen_get_mode();
123 if(!lua_isnoneornil(L, 1))
124 {
125 enum touchscreen_mode mode = luaL_checkint(L, 1);
126 rb->touchscreen_set_mode(mode);
127 }
128 lua_pushinteger(L, origmode);
129 return 1;
130}
131
132#endif
133
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000134RB_WRAP(kbd_input)
135{
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000136 luaL_Buffer b;
137 luaL_buffinit(L, &b);
138
William Wilguse4b84332018-09-17 19:28:10 +0200139 const char *input = lua_tostring(L, 1);
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000140 char *buffer = luaL_prepbuffer(&b);
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000141
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000142 if(input != NULL)
William Wilgus55533c42018-10-25 06:28:23 -0400143 rb->strlcpy(buffer, input, LUAL_BUFFERSIZE);
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000144 else
145 buffer[0] = '\0';
146
147 if(!rb->kbd_input(buffer, LUAL_BUFFERSIZE))
148 {
William Wilgusb5786de2018-10-23 01:57:41 -0400149 luaL_addstring(&b, buffer);
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000150 luaL_pushresult(&b);
151 }
152 else
William Wilgusb5786de2018-10-23 01:57:41 -0400153 return 0;
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000154
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000155 return 1;
156}
157
William Wilgusb5786de2018-10-23 01:57:41 -0400158static const char ** get_table_items(lua_State *L, int pos, int *count)
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000159{
160 int i;
161 luaL_checktype(L, pos, LUA_TTABLE);
William Wilgusb5786de2018-10-23 01:57:41 -0400162 *count = lua_objlen(L, pos);
163 int n = *count;
William Wilguse4b84332018-09-17 19:28:10 +0200164
William Wilgusb5786de2018-10-23 01:57:41 -0400165 /* newuserdata will be pushed onto stack after args*/
166 const char **items = (const char**) lua_newuserdata(L, n * sizeof(const char*));
William Wilguse4b84332018-09-17 19:28:10 +0200167
William Wilgusb5786de2018-10-23 01:57:41 -0400168 for(i=1; i<= n; i++)
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000169 {
William Wilgusb5786de2018-10-23 01:57:41 -0400170 lua_rawgeti(L, pos, i); /* Push item on the stack */
171 items[i-1] = lua_tostring(L, -1);
172 lua_pop(L, 1); /* Pop it */
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000173 }
William Wilgusb5786de2018-10-23 01:57:41 -0400174
175 return items;
176}
177
178static inline void fill_text_message(lua_State *L, struct text_message * message,
179 int pos)
180{
181 int n;
182 /* newuserdata will be pushed onto stack after args*/
183 message->message_lines = get_table_items(L, pos, &n);
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000184 message->nb_lines = n;
185}
186
187RB_WRAP(gui_syncyesno_run)
188{
189 struct text_message main_message, yes_message, no_message;
190 struct text_message *yes = NULL, *no = NULL;
191
William Wilguse4b84332018-09-17 19:28:10 +0200192 lua_settop(L, 3); /* newuserdata will be pushed onto stack after args*/
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000193 fill_text_message(L, &main_message, 1);
194 if(!lua_isnoneornil(L, 2))
195 fill_text_message(L, (yes = &yes_message), 2);
196 if(!lua_isnoneornil(L, 3))
197 fill_text_message(L, (no = &no_message), 3);
198
199 enum yesno_res result = rb->gui_syncyesno_run(&main_message, yes, no);
200
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000201 lua_pushinteger(L, result);
202 return 1;
203}
204
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000205RB_WRAP(do_menu)
206{
207 struct menu_callback_with_desc menu_desc = {NULL, NULL, Icon_NOICON};
208 struct menu_item_ex menu = {MT_RETURN_ID | MENU_HAS_DESC, {.strings = NULL},
209 {.callback_and_desc = &menu_desc}};
William Wilgusb5786de2018-10-23 01:57:41 -0400210 int n, start_selected;
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000211 const char **items, *title;
212
213 title = luaL_checkstring(L, 1);
William Wilgusb5786de2018-10-23 01:57:41 -0400214
William Wilguse4b84332018-09-17 19:28:10 +0200215 start_selected = lua_tointeger(L, 3);
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000216
William Wilguse4b84332018-09-17 19:28:10 +0200217 /* newuserdata will be pushed onto stack after args*/
William Wilgusb5786de2018-10-23 01:57:41 -0400218 items = get_table_items(L, 2, &n);
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000219
220 menu.strings = items;
221 menu.flags |= MENU_ITEM_COUNT(n);
222 menu_desc.desc = (unsigned char*) title;
223
224 int result = rb->do_menu(&menu, &start_selected, NULL, false);
225
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000226 lua_pushinteger(L, result);
227 return 1;
228}
229
William Wilgusf6e10b82018-11-01 14:20:33 -0400230
231/* DEVICE AUDIO / PLAYLIST CONTROL */
232
William Wilguse4c5f5d2018-10-24 21:40:01 -0400233RB_WRAP(playlist)
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500234{
William Wilguse4c5f5d2018-10-24 21:40:01 -0400235 /* just passes NULL to work with the current playlist */
236 enum e_playlist {PLAYL_AMOUNT = 0, PLAYL_ADD, PLAYL_CREATE,
237 PLAYL_START, PLAYL_RESUMETRACK, PLAYL_RESUME,
238 PLAYL_SHUFFLE, PLAYL_SYNC, PLAYL_REMOVEALLTRACKS,
239 PLAYL_INSERTTRACK, PLAYL_INSERTDIRECTORY, PLAYL_ECOUNT};
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500240
William Wilgusbbfe4772018-10-31 09:23:00 -0400241 const char *playlist_option[] = {"amount", "add", "create", "start", "resume_track",
242 "resume", "shuffle", "sync", "remove_all_tracks",
243 "insert_track", "insert_directory", NULL};
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500244
William Wilguse4c5f5d2018-10-24 21:40:01 -0400245 const char *filename, *dir;
246 int result = 0;
247 bool queue, recurse, sync;
248 int pos, crc, index, random_seed;
249 unsigned long elapsed, offset;
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500250
William Wilguse4c5f5d2018-10-24 21:40:01 -0400251 int option = luaL_checkoption (L, 1, NULL, playlist_option);
252 switch(option)
253 {
William Wilguse4c5f5d2018-10-24 21:40:01 -0400254 case PLAYL_AMOUNT:
255 result = rb->playlist_amount();
256 break;
257 case PLAYL_ADD:
258 filename = luaL_checkstring(L, 2);
259 result = rb->playlist_add(filename);
260 break;
261 case PLAYL_CREATE:
262 dir = luaL_checkstring(L, 2);
263 filename = luaL_checkstring(L, 3);
264 result = rb->playlist_create(dir, filename);
265 break;
266 case PLAYL_START:
267 index = luaL_checkint(L, 2);
268 elapsed = luaL_checkint(L, 3);
269 offset = luaL_checkint(L, 4);
270 rb->playlist_start(index, elapsed, offset);
271 break;
272 case PLAYL_RESUMETRACK:
273 index = luaL_checkint(L, 2);
274 crc = luaL_checkint(L, 3);
275 elapsed = luaL_checkint(L, 4);
276 offset = luaL_checkint(L, 5);
277 rb->playlist_resume_track(index, (unsigned) crc, elapsed, offset);
278 break;
279 case PLAYL_RESUME:
280 result = rb->playlist_resume();
281 break;
282 case PLAYL_SHUFFLE:
283 random_seed = luaL_checkint(L, 2);
284 index = luaL_checkint(L, 3);
285 result = rb->playlist_shuffle(random_seed, index);
286 break;
287 case PLAYL_SYNC:
288 rb->playlist_sync(NULL);
289 break;
290 case PLAYL_REMOVEALLTRACKS:
291 result = rb->playlist_remove_all_tracks(NULL);
292 break;
293 case PLAYL_INSERTTRACK:
294 filename = luaL_checkstring(L, 2); /* only required parameter */
295 pos = luaL_optint(L, 3, PLAYLIST_INSERT);
296 queue = lua_toboolean(L, 4); /* default to false */
297 sync = lua_toboolean(L, 5); /* default to false */
298 result = rb->playlist_insert_track(NULL, filename, pos, queue, sync);
299 break;
300 case PLAYL_INSERTDIRECTORY:
301 dir = luaL_checkstring(L, 2); /* only required parameter */
302 pos = luaL_optint(L, 3, PLAYLIST_INSERT);
303 queue = lua_toboolean(L, 4); /* default to false */
304 recurse = lua_toboolean(L, 5); /* default to false */
305 result = rb->playlist_insert_directory(NULL, dir, pos, queue, recurse);
306 break;
307 }
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500308
William Wilgus45bd14b2019-07-12 05:23:52 -0500309 yield();
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500310 lua_pushinteger(L, result);
311 return 1;
312}
313
William Wilgusb670fcd2018-10-24 10:49:52 -0400314RB_WRAP(audio)
315{
316 enum e_audio {AUDIO_STATUS = 0, AUDIO_PLAY, AUDIO_STOP, AUDIO_PAUSE,
317 AUDIO_RESUME, AUDIO_NEXT, AUDIO_PREV, AUDIO_FFREWIND,
William Wilgusc0dbfc82019-07-09 11:10:08 -0500318 AUDIO_FLUSHANDRELOADTRACKS, AUDIO_GETPOS, AUDIO_LENGTH,
319 AUDIO_ELAPSED, AUDIO_ECOUNT};
320 const char *audio_option[] = {"status", "play", "stop",
321 "pause", "resume", "next",
322 "prev", "ff_rewind",
323 "flush_and_reload_tracks",
324 "get_file_pos", "length",
325 "elapsed", NULL};
William Wilgusb670fcd2018-10-24 10:49:52 -0400326 long elapsed, offset, newtime;
327 int status = rb->audio_status();
328
329 int option = luaL_checkoption (L, 1, NULL, audio_option);
330 switch(option)
331 {
William Wilgusb670fcd2018-10-24 10:49:52 -0400332 case AUDIO_STATUS:
333 break;
334 case AUDIO_PLAY:
335 elapsed = luaL_checkint(L, 2);
336 offset = luaL_checkint(L, 3);
337
338 if (status == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE))
339 {
340 /* not perfect but provides a decent compromise */
341 rb->audio_ff_rewind(elapsed + offset);
342 rb->audio_resume();
343 }
344 else if (status != AUDIO_STATUS_PLAY)
345 rb->audio_play((unsigned long) elapsed, (unsigned long) offset);
346
347 break;
348 case AUDIO_STOP:
349 rb->audio_stop();
350 break;
351 case AUDIO_PAUSE:
352 rb->audio_pause();
353 break;
354 case AUDIO_RESUME:
355 rb->audio_resume();
356 break;
357 case AUDIO_NEXT:
358 rb->audio_next();
359 break;
360 case AUDIO_PREV:
361 rb->audio_prev();
362 break;
363 case AUDIO_FFREWIND:
364 newtime = (long) luaL_checkint(L, 2);
365 rb->audio_ff_rewind(newtime);
366 break;
367 case AUDIO_FLUSHANDRELOADTRACKS:
368 rb->audio_flush_and_reload_tracks();
369 break;
370 case AUDIO_GETPOS:
371 lua_pushinteger(L, rb->audio_get_file_pos());
372 return 1;
William Wilgusc0dbfc82019-07-09 11:10:08 -0500373 case AUDIO_LENGTH:
374 if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
375 lua_pushinteger(L, rb->audio_current_track()->length);
376 else
377 lua_pushnil(L);
378 return 1;
379 case AUDIO_ELAPSED:
380 if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
381 lua_pushinteger(L, rb->audio_current_track()->elapsed);
382 else
383 lua_pushnil(L);
384 return 1;
William Wilgusb670fcd2018-10-24 10:49:52 -0400385 }
386
William Wilgus45bd14b2019-07-12 05:23:52 -0500387 yield();
William Wilgusb670fcd2018-10-24 10:49:52 -0400388 lua_pushinteger(L, status); /* return previous (or current) audio status */
389 return 1;
390}
391
William Wilgus6e32e062019-07-25 10:17:40 -0500392RB_WRAP(sound)
393{
394 enum e_snd {SOUND_SET = 0, SOUND_CURRENT, SOUND_DEFAULT,
395 SOUND_MIN, SOUND_MAX, SOUND_UNIT, SOUND_SET_PITCH,
396 SOUND_VAL2PHYS, SOUND_ECOUNT};
397
398 const char *snd_option[] = {"set", "current", "default",
399 "min", "max", "unit", "pitch",
400 "val2phys", NULL};
401
402 lua_pushnil(L); /*push nil so options w/o return have something to return */
403
404 int option = luaL_checkoption (L, 1, NULL, snd_option);
405 int setting = luaL_checkint(L, 2);
406 int value, result;
407 switch(option)
408 {
409 case SOUND_SET:
410 value = luaL_checkint(L, 3);
411 rb->sound_set(setting, value);
412 return 1; /*nil*/
413 break;
414 case SOUND_CURRENT:
415 result = rb->sound_current(setting);
416 break;
417 case SOUND_DEFAULT:
418 result = rb->sound_default(setting);
419 break;
420 case SOUND_MIN:
421 result = rb->sound_min(setting);
422 break;
423 case SOUND_MAX:
424 result = rb->sound_max(setting);
425 break;
426 case SOUND_UNIT:
427 lua_pushstring (L, rb->sound_unit(setting));
428 return 1;
429 break;
430#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
431 (CONFIG_CODEC == SWCODEC)) && defined (HAVE_PITCHCONTROL)
432 case SOUND_SET_PITCH:
433 rb->sound_set_pitch(setting);
434 return 1;/*nil*/
435 break;
436#endif
437 case SOUND_VAL2PHYS:
438 value = luaL_checkint(L, 3);
439 result = rb->sound_val2phys(setting, value);
440 break;
441
442 default:
443 return 1;
444 break;
445 }
446
447 lua_pushinteger(L, result);
448 return 1;
449}
450
William Wilgus74fe5202018-10-30 13:56:36 -0400451#if CONFIG_CODEC == SWCODEC
452RB_WRAP(pcm)
453{
454 enum e_pcm {PCM_APPLYSETTINGS = 0, PCM_ISPLAYING, PCM_ISPAUSED,
455 PCM_PLAYSTOP, PCM_PLAYPAUSE, PCM_PLAYLOCK, PCM_PLAYUNLOCK,
456 PCM_CALCULATEPEAKS, PCM_SETFREQUENCY, PCM_GETBYTESWAITING, PCM_ECOUNT};
457
William Wilgusbbfe4772018-10-31 09:23:00 -0400458 const char *pcm_option[] = {"apply_settings", "is_playing", "is_paused",
459 "play_stop", "play_pause", "play_lock", "play_unlock",
460 "calculate_peaks", "set_frequency", "get_bytes_waiting", NULL};
William Wilgus74fe5202018-10-30 13:56:36 -0400461 bool b_result;
462 int left, right;
463 size_t byteswait;
464
465 lua_pushnil(L); /*push nil so options w/o return have something to return */
466
467 int option = luaL_checkoption (L, 1, NULL, pcm_option);
468 switch(option)
469 {
William Wilgus74fe5202018-10-30 13:56:36 -0400470 case PCM_APPLYSETTINGS:
471 rb->pcm_apply_settings();
472 break;
473 case PCM_ISPLAYING:
474 b_result = rb->pcm_is_playing();
475 lua_pushboolean(L, b_result);
476 break;
477 case PCM_ISPAUSED:
478 b_result = rb->pcm_is_paused();
479 lua_pushboolean(L, b_result);
480 break;
481 case PCM_PLAYPAUSE:
William Wilgus9b385f32018-11-01 18:18:46 -0400482 rb->pcm_play_pause(luaL_checkboolean(L, 2));
William Wilgus74fe5202018-10-30 13:56:36 -0400483 break;
484 case PCM_PLAYSTOP:
485 rb->pcm_play_stop();
486 break;
487 case PCM_PLAYLOCK:
488 rb->pcm_play_lock();
489 break;
490 case PCM_PLAYUNLOCK:
491 rb->pcm_play_unlock();
492 break;
493 case PCM_CALCULATEPEAKS:
494 rb->pcm_calculate_peaks(&left, &right);
495 lua_pushinteger(L, left);
496 lua_pushinteger(L, right);
497 return 2;
498 case PCM_SETFREQUENCY:
William Wilgus9b385f32018-11-01 18:18:46 -0400499 rb->pcm_set_frequency((unsigned int) luaL_checkint(L, 2));
William Wilgus74fe5202018-10-30 13:56:36 -0400500 break;
501 case PCM_GETBYTESWAITING:
502 byteswait = rb->pcm_get_bytes_waiting();
503 lua_pushinteger(L, byteswait);
504 break;
505 }
506
William Wilgus45bd14b2019-07-12 05:23:52 -0500507 yield();
William Wilgus74fe5202018-10-30 13:56:36 -0400508 return 1;
509}
William Wilgusf6e10b82018-11-01 14:20:33 -0400510
511RB_WRAP(mixer_frequency)
512{
513 unsigned int result = rb->mixer_get_frequency();
514
515 if(!lua_isnoneornil(L, 1))
516 {
517 unsigned int samplerate = (unsigned int) luaL_checkint(L, 1);
518 rb->mixer_set_frequency(samplerate);
519 }
520 lua_pushinteger(L, result);
521 return 1;
522}
William Wilgus74fe5202018-10-30 13:56:36 -0400523#endif /*CONFIG_CODEC == SWCODEC*/
524
William Wilgusf6e10b82018-11-01 14:20:33 -0400525/* DEVICE LIGHTING CONTROL */
526RB_WRAP(backlight_onoff)
527{
528 bool on = luaL_checkboolean(L, 1);
529 if(on)
530 rb->backlight_on();
531 else
532 rb->backlight_off();
533
534 return 0;
535}
536
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000537SIMPLE_VOID_WRAPPER(backlight_force_on);
538SIMPLE_VOID_WRAPPER(backlight_use_settings);
William Wilguse4b84332018-09-17 19:28:10 +0200539
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000540#ifdef HAVE_REMOTE_LCD
541SIMPLE_VOID_WRAPPER(remote_backlight_force_on);
542SIMPLE_VOID_WRAPPER(remote_backlight_use_settings);
543#endif
William Wilguse4b84332018-09-17 19:28:10 +0200544
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000545#ifdef HAVE_BUTTON_LIGHT
546SIMPLE_VOID_WRAPPER(buttonlight_force_on);
547SIMPLE_VOID_WRAPPER(buttonlight_use_settings);
548#endif
William Wilguse4b84332018-09-17 19:28:10 +0200549
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000550#ifdef HAVE_BACKLIGHT_BRIGHTNESS
551RB_WRAP(backlight_brightness_set)
552{
William Wilgusf6e10b82018-11-01 14:20:33 -0400553 if(lua_isnoneornil(L, 1))
554 backlight_brightness_use_setting();
555 else
556 {
557 int brightness = luaL_checkint(L, 1);
558 backlight_brightness_set(brightness);
559 }
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000560
561 return 0;
562}
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000563#endif
564
William Wilgusf6e10b82018-11-01 14:20:33 -0400565#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
566RB_WRAP(buttonlight_brightness_set)
Thomas Martitzc406f942012-01-27 00:05:20 +0100567{
William Wilgusf6e10b82018-11-01 14:20:33 -0400568 if(lua_isnoneornil(L, 1))
569 buttonlight_brightness_use_setting();
Thomas Martitzc406f942012-01-27 00:05:20 +0100570 else
William Wilgusf6e10b82018-11-01 14:20:33 -0400571 {
572 int brightness = luaL_checkint(L, 1);
573 buttonlight_brightness_set(brightness);
574 }
Thomas Martitzc406f942012-01-27 00:05:20 +0100575
William Wilgusf6e10b82018-11-01 14:20:33 -0400576 return 0;
Thomas Martitzc406f942012-01-27 00:05:20 +0100577}
William Wilgusf6e10b82018-11-01 14:20:33 -0400578#endif
579
580
581/* DEVICE STRING / FILENAME MANIPULATION */
Thomas Martitzc406f942012-01-27 00:05:20 +0100582
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400583RB_WRAP(strip_extension)
584{
585 const char* filename = luaL_checkstring(L, -1);
586 const char* pos = rb->strrchr(filename, '.');
587 if(pos != NULL)
588 lua_pushlstring (L, filename, pos - filename);
589
590 return 1;
591}
592
593RB_WRAP(create_numbered_filename)
594{
595 luaL_Buffer b;
596 luaL_buffinit(L, &b);
597 char *buffer = luaL_prepbuffer(&b);
598 buffer[0] = '\0';
599
600 const char * path = luaL_checkstring(L, 1);
601 const char * prefix = luaL_checkstring(L, 2);
602 const char * suffix = luaL_checkstring(L, 3);
William Wilgus20b98f62018-10-24 11:09:17 -0400603 int numberlen = luaL_checkint(L, 4);
604 int num = luaL_optint(L, 5, -1);
605 (void) num;
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400606
William Wilgus20b98f62018-10-24 11:09:17 -0400607 if(rb->create_numbered_filename(buffer, path, prefix, suffix, numberlen
608 IF_CNFN_NUM_(, &num)))
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400609 {
610 luaL_addstring(&b, buffer);
611 luaL_pushresult(&b);
612 }
613 else
614 return 0;
615
616 return 1;
617}
618
William Wilgusbe7a58c2018-10-30 22:40:23 -0400619RB_WRAP(utf8encode)
620{
621 unsigned long ucs = (unsigned long) luaL_checkint(L, 1);
622 unsigned char tmp[9];
623 unsigned char *end = rb->utf8encode(ucs, tmp);
624 *end = '\0';
625 lua_pushstring(L, tmp);
626 return 1;
627}
628
William Wilgusf6e10b82018-11-01 14:20:33 -0400629RB_WRAP(strncasecmp)
630{
631 int result;
632 const char * s1 = luaL_checkstring(L, 1);
633 const char * s2 = luaL_checkstring(L, 2);
634 if(lua_isnoneornil(L, 3))
635 result = rb->strcasecmp(s1, s2);
636 else
637 result = rb->strncasecmp(s1, s2, (size_t) luaL_checkint(L, 3));
638
639 lua_pushinteger(L, result);
640 return 1;
641}
642
William Wilgus9d66b542018-12-15 13:50:00 -0600643static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize)
644{
645 intptr_t offset = (intptr_t) luaL_optint(L, 1, 0);
646 size_t size = (size_t) luaL_optint(L, 2, maxsize);
647 size_t written;
648 int type = lua_type(L, 3);
649
650 if(offset < 0)
651 {
652 /* allows pointer within structure to be calculated offset */
653 offset = -(address + offset);
654 size = (size_t) maxsize - offset;
655 }
656
657 luaL_argcheck(L, ((uintptr_t) offset) + size <= maxsize, 2, ERR_IDX_RANGE);
658
659 char *mem = (char*) address + ((uintptr_t) offset);
660 const void *value = NULL;
661
662 lua_Integer var_luaint;
663#ifdef UINT64_MAX
664 int64_t var_64;
665#endif
666 int32_t var_32;
667 int16_t var_16;
668 int8_t var_8;
669 bool var_bool;
670
671 switch(type)
672 {
673 case LUA_TSTRING:
674 {
675 size_t len;
676 const char* str = lua_tolstring (L, 3, &len);
677
678 luaL_argcheck(L, len + 1 <= size, 3, ERR_DATA_OVF);
679 size = len + 1; /* include \0 */
680 value = str;
681 break;
682 }
683 case LUA_TBOOLEAN:
684 {
685 var_bool = (bool) lua_toboolean(L, 3);
686 value = &var_bool;
687 break;
688 }
689 case LUA_TNUMBER:
690 {
691 var_luaint = lua_tointeger(L, 3);
692 switch(size)
693 {
694 case sizeof(var_8):
695 var_8 = (int8_t) var_luaint;
696 value = &var_8;
697 break;
698 case sizeof(var_16):
699 var_16 = (int16_t) var_luaint;
700 value = &var_16;
701 break;
702 case sizeof(var_32):
703 var_32 = (int32_t) var_luaint;
704 value = &var_32;
705 break;
706#ifdef UINT64_MAX
707 case sizeof(var_64):
708 var_64 = (int64_t) var_luaint;
709 value = &var_64;
710 break;
711#endif
712 } /* switch size */
713 break;
714 }
715 case LUA_TNIL:
716 case LUA_TNONE: /* reader */
717 {
718 luaL_Buffer b;
719 luaL_buffinit(L, &b);
720 while(size > 0)
721 {
722 written = MIN(LUAL_BUFFERSIZE, size);
723 luaL_addlstring (&b, mem, written);
724 mem += written;
725 size -= written;
726 }
727
728 luaL_pushresult(&b);
729 return 1;
730 }
731
732 default:
733 break;
734 } /* switch type */
735
736 /* writer */
737 luaL_argcheck(L, value != NULL, 3, "Unknown Type");
738 rb->memcpy(mem, value, size);
739 lua_pushinteger(L, 1);
740
741 return 1;
742}
743
744RB_WRAP(global_status)
745{
746 const uintptr_t address = (uintptr_t) rb->global_status;
747 const size_t maxsize = sizeof(struct system_status);
748 return mem_read_write(L, address, maxsize);
749}
750
751RB_WRAP(global_settings)
752{
753 const uintptr_t address = (uintptr_t) rb->global_settings;
754 const size_t maxsize = sizeof(struct user_settings);
755 return mem_read_write(L, address, maxsize);
756}
757
758RB_WRAP(audio_next_track)
759{
760 lua_settop(L, 2); /* no writes allowed */
761 const uintptr_t address = (uintptr_t) rb->audio_next_track();
762 const size_t maxsize = sizeof(struct mp3entry);
763 return mem_read_write(L, address, maxsize);
764}
765
766RB_WRAP(audio_current_track)
767{
768 lua_settop(L, 2); /* no writes allowed */
769 const uintptr_t address = (uintptr_t) rb->audio_current_track();
770 const size_t maxsize = sizeof(struct mp3entry);
771 return mem_read_write(L, address, maxsize);
772}
773
William Wilgus90118f12019-07-26 01:30:00 -0500774RB_WRAP(restart_lua)
775{
776 /*close lua state, open a new lua state, load script @ filename */
777 luaL_checktype (L, 1, LUA_TSTRING);
778 lua_settop(L, 1);
779 lua_pushlightuserdata(L, L); /* signal exit handler */
780 exit(1); /* atexit in rocklua.c */
781 return -1;
782}
783
784
William Wilguse4b84332018-09-17 19:28:10 +0200785#define RB_FUNC(func) {#func, rock_##func}
William Wilgusf6e10b82018-11-01 14:20:33 -0400786#define RB_ALIAS(name, func) {name, rock_##func}
Maurus Cuelenaerea9b2d1b2009-05-21 19:42:14 +0000787static const luaL_Reg rocklib[] =
788{
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000789 /* Kernel */
William Wilguse4b84332018-09-17 19:28:10 +0200790 RB_FUNC(current_tick),
William Wilgusf6e10b82018-11-01 14:20:33 -0400791#ifdef HAVE_SCHEDULER_BOOSTCTRL
792 RB_FUNC(schedule_cpu_boost),
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000793#endif
Franklin Wei8379b232019-07-28 14:56:59 -0400794
795#ifdef HAVE_PRIORITY_SCHEDULING
William Wilgusddf612c2019-07-28 07:26:20 -0500796 RB_FUNC(thread_set_priority),
Franklin Wei8379b232019-07-28 14:56:59 -0400797#endif
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000798
William Wilguse4b84332018-09-17 19:28:10 +0200799 RB_FUNC(current_path),
William Wilgusf6e10b82018-11-01 14:20:33 -0400800
801 /* DEVICE INPUT CONTROL */
802 RB_FUNC(get_plugin_action),
803#ifdef HAVE_TOUCHSCREEN
804 RB_FUNC(action_get_touchscreen_press),
805 RB_FUNC(touchscreen_mode),
806#endif
807 RB_FUNC(kbd_input),
William Wilguse4b84332018-09-17 19:28:10 +0200808 RB_FUNC(gui_syncyesno_run),
William Wilguse4b84332018-09-17 19:28:10 +0200809 RB_FUNC(do_menu),
Maurus Cuelenaere86fe1e82009-05-24 01:54:15 +0000810
William Wilgus6e32e062019-07-25 10:17:40 -0500811 /* DEVICE AUDIO / SOUND / PLAYLIST CONTROL */
William Wilgusf6e10b82018-11-01 14:20:33 -0400812 RB_FUNC(audio),
813 RB_FUNC(playlist),
William Wilgus6e32e062019-07-25 10:17:40 -0500814 RB_FUNC(sound),
William Wilgusf6e10b82018-11-01 14:20:33 -0400815#if CONFIG_CODEC == SWCODEC
816 RB_FUNC(pcm),
817 RB_FUNC(mixer_frequency),
818#endif
819
820 /* DEVICE LIGHTING CONTROL */
821 RB_FUNC(backlight_onoff),
822
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000823 /* Backlight helper */
William Wilguse4b84332018-09-17 19:28:10 +0200824 RB_FUNC(backlight_force_on),
825 RB_FUNC(backlight_use_settings),
826
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000827#ifdef HAVE_REMOTE_LCD
William Wilguse4b84332018-09-17 19:28:10 +0200828 RB_FUNC(remote_backlight_force_on),
829 RB_FUNC(remote_backlight_use_settings),
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000830#endif
William Wilguse4b84332018-09-17 19:28:10 +0200831
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000832#ifdef HAVE_BUTTON_LIGHT
William Wilguse4b84332018-09-17 19:28:10 +0200833 RB_FUNC(buttonlight_force_on),
834 RB_FUNC(buttonlight_use_settings),
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000835#endif
William Wilguse4b84332018-09-17 19:28:10 +0200836
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000837#ifdef HAVE_BACKLIGHT_BRIGHTNESS
William Wilguse4b84332018-09-17 19:28:10 +0200838 RB_FUNC(backlight_brightness_set),
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000839#endif
William Wilguse4b84332018-09-17 19:28:10 +0200840
William Wilgusf6e10b82018-11-01 14:20:33 -0400841#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
842 RB_FUNC(buttonlight_brightness_set),
843#endif
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000844
William Wilgusf6e10b82018-11-01 14:20:33 -0400845 /* DEVICE STRING / FILENAME MANIPULATION */
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400846 RB_FUNC(strip_extension),
847 RB_FUNC(create_numbered_filename),
William Wilgusbe7a58c2018-10-30 22:40:23 -0400848 RB_FUNC(utf8encode),
William Wilgusf6e10b82018-11-01 14:20:33 -0400849 RB_FUNC(strncasecmp),
William Wilgusbe7a58c2018-10-30 22:40:23 -0400850
William Wilgus9d66b542018-12-15 13:50:00 -0600851 /* ROCKBOX SETTINGS / INFO */
852 RB_FUNC(global_status),
853 RB_FUNC(global_settings),
854 RB_FUNC(audio_next_track),
855 RB_FUNC(audio_current_track),
856
William Wilgus90118f12019-07-26 01:30:00 -0500857 RB_FUNC(restart_lua),
858
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000859 {NULL, NULL}
860};
William Wilguse4b84332018-09-17 19:28:10 +0200861#undef RB_FUNC
William Wilgusf6e10b82018-11-01 14:20:33 -0400862#undef RB_ALIAS
William Wilguse4b84332018-09-17 19:28:10 +0200863
Maurus Cuelenaered755a5a2009-07-05 15:33:08 +0000864extern const luaL_Reg rocklib_aux[];
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000865
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000866/*
867 ** Open Rockbox library
868 */
869LUALIB_API int luaopen_rock(lua_State *L)
870{
Marcin Bukatbfd01792014-04-02 20:46:06 +0200871 luaL_register(L, LUA_ROCKLIBNAME, rocklib);
872 luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux);
William Wilgusc9aeb422019-07-18 08:42:00 -0500873 lua_getglobal(L, "require");
874 lua_pushstring(L, "rb_defines");
875 if (lua_pcall (L, 1, 0, 0))
876 lua_pop(L, 1);
William Wilgusddf612c2019-07-28 07:26:20 -0500877#if 0 /* see rb_defines.lua */
William Wilgusdc6f23e2018-09-14 01:13:22 +0200878 static const struct lua_int_reg rlib_const_int[] =
879 {
880 /* useful integer constants */
881 RB_CONSTANT(HZ),
Maurus Cuelenaere2cd4a942009-05-22 00:06:45 +0000882
William Wilgusdc6f23e2018-09-14 01:13:22 +0200883 RB_CONSTANT(LCD_DEPTH),
William Wilguse4b84332018-09-17 19:28:10 +0200884 RB_CONSTANT(LCD_HEIGHT),
885 RB_CONSTANT(LCD_WIDTH),
William Wilgusf6e10b82018-11-01 14:20:33 -0400886 RB_CONSTANT(SCREEN_MAIN),
William Wilgus9ed486b2018-11-24 16:40:23 -0500887#if LCD_DEPTH > 1
888 RB_CONSTANT(LCD_DEFAULT_FG),
889 RB_CONSTANT(LCD_DEFAULT_BG),
890#endif
William Wilgusdf8233e2018-10-27 06:24:27 -0400891#ifdef HAVE_REMOTE_LCD
892 RB_CONSTANT(LCD_REMOTE_DEPTH),
893 RB_CONSTANT(LCD_REMOTE_HEIGHT),
894 RB_CONSTANT(LCD_REMOTE_WIDTH),
William Wilgusf6e10b82018-11-01 14:20:33 -0400895 RB_CONSTANT(SCREEN_REMOTE),
William Wilgusdf8233e2018-10-27 06:24:27 -0400896#endif
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000897
William Wilgusdc6f23e2018-09-14 01:13:22 +0200898 RB_CONSTANT(FONT_SYSFIXED),
899 RB_CONSTANT(FONT_UI),
Maurus Cuelenaere2cd4a942009-05-22 00:06:45 +0000900
William Wilgusdc6f23e2018-09-14 01:13:22 +0200901 RB_CONSTANT(PLAYLIST_INSERT),
902 RB_CONSTANT(PLAYLIST_INSERT_LAST),
903 RB_CONSTANT(PLAYLIST_INSERT_FIRST),
William Wilgusdc6f23e2018-09-14 01:13:22 +0200904 RB_CONSTANT(PLAYLIST_INSERT_LAST_SHUFFLED),
William Wilguse4b84332018-09-17 19:28:10 +0200905 RB_CONSTANT(PLAYLIST_INSERT_SHUFFLED),
906 RB_CONSTANT(PLAYLIST_PREPEND),
907 RB_CONSTANT(PLAYLIST_REPLACE),
908
William Wilgus3e2b50e2019-06-27 11:28:34 -0500909/* queue sys events */
910 RB_CONSTANT(SYS_USB_CONNECTED),
911 RB_CONSTANT(SYS_USB_DISCONNECTED),
912 RB_CONSTANT(SYS_TIMEOUT),
913 RB_CONSTANT(SYS_POWEROFF),
914 RB_CONSTANT(SYS_CHARGER_CONNECTED),
915 RB_CONSTANT(SYS_CHARGER_DISCONNECTED),
916
Maurus Cuelenaere9c3e6792009-06-01 22:31:32 +0000917#ifdef HAVE_TOUCHSCREEN
William Wilgusdc6f23e2018-09-14 01:13:22 +0200918 RB_CONSTANT(TOUCHSCREEN_POINT),
919 RB_CONSTANT(TOUCHSCREEN_BUTTON),
Maurus Cuelenaere9c3e6792009-06-01 22:31:32 +0000920#endif
921
William Wilgusdc6f23e2018-09-14 01:13:22 +0200922 {NULL, 0}
923 };
Maurus Cuelenaere59c4b682009-07-08 11:59:05 +0000924
William Wilgusdc6f23e2018-09-14 01:13:22 +0200925 static const struct lua_int_reg* rlci = rlib_const_int;
926 for (; rlci->name; rlci++) {
927 lua_pushinteger(L, rlci->value);
William Wilgusc6fcb1c2018-11-11 18:27:19 -0500928 luaS_newlloc(L, rlci->name, TSTR_INBIN);
William Wilgusdc6f23e2018-09-14 01:13:22 +0200929 lua_setfield(L, -2, rlci->name);
930 }
931
932 static const struct lua_str_reg rlib_const_str[] =
933 {
934 /* some useful paths constants */
William Wilgusdc6f23e2018-09-14 01:13:22 +0200935 RB_STRING_CONSTANT(HOME_DIR),
936 RB_STRING_CONSTANT(PLUGIN_DIR),
937 RB_STRING_CONSTANT(PLUGIN_APPS_DATA_DIR),
938 RB_STRING_CONSTANT(PLUGIN_GAMES_DATA_DIR),
939 RB_STRING_CONSTANT(PLUGIN_DATA_DIR),
William Wilguse4b84332018-09-17 19:28:10 +0200940 RB_STRING_CONSTANT(ROCKBOX_DIR),
William Wilgusdc6f23e2018-09-14 01:13:22 +0200941 RB_STRING_CONSTANT(VIEWERS_DATA_DIR),
942 {NULL,NULL}
943 };
944
945 static const struct lua_str_reg* rlcs = rlib_const_str;
946 for (; rlcs->name; rlcs++) {
William Wilgusc6fcb1c2018-11-11 18:27:19 -0500947 luaS_newlloc(L, rlcs->value, TSTR_INBIN);
William Wilgusdc6f23e2018-09-14 01:13:22 +0200948 lua_pushstring(L, rlcs->value);
William Wilgusc6fcb1c2018-11-11 18:27:19 -0500949 luaS_newlloc(L, rlcs->name, TSTR_INBIN);
William Wilgusdc6f23e2018-09-14 01:13:22 +0200950 lua_setfield(L, -2, rlcs->name);
951 }
William Wilgusc9aeb422019-07-18 08:42:00 -0500952#endif
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000953 return 1;
954}