blob: b37f5245dc71ae1e7f28b913cd9fd2b9cf1238be [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
80RB_WRAP(current_path)
81{
82 return get_current_path(L, 1);
83}
84
85
86/* DEVICE INPUT CONTROL */
87
88RB_WRAP(get_plugin_action)
89{
William Wilgusf6e10b82018-11-01 14:20:33 -040090 int timeout = luaL_checkint(L, 1);
William Wilgusf6e10b82018-11-01 14:20:33 -040091 bool with_remote = luaL_optint(L, 2, 0);
William Wilgus3e2b50e2019-06-27 11:28:34 -050092 int btn = get_plugin_action(timeout, with_remote);
William Wilgusf6e10b82018-11-01 14:20:33 -040093 lua_pushinteger(L, btn);
94 return 1;
95}
96
97#ifdef HAVE_TOUCHSCREEN
98RB_WRAP(action_get_touchscreen_press)
99{
100 short x, y;
101 int result = rb->action_get_touchscreen_press(&x, &y);
102
103 lua_pushinteger(L, result);
104 lua_pushinteger(L, x);
105 lua_pushinteger(L, y);
106 return 3;
107}
108
109RB_WRAP(touchscreen_mode)
110{
111 int origmode = rb->touchscreen_get_mode();
112 if(!lua_isnoneornil(L, 1))
113 {
114 enum touchscreen_mode mode = luaL_checkint(L, 1);
115 rb->touchscreen_set_mode(mode);
116 }
117 lua_pushinteger(L, origmode);
118 return 1;
119}
120
121#endif
122
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000123RB_WRAP(kbd_input)
124{
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000125 luaL_Buffer b;
126 luaL_buffinit(L, &b);
127
William Wilguse4b84332018-09-17 19:28:10 +0200128 const char *input = lua_tostring(L, 1);
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000129 char *buffer = luaL_prepbuffer(&b);
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000130
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000131 if(input != NULL)
William Wilgus55533c42018-10-25 06:28:23 -0400132 rb->strlcpy(buffer, input, LUAL_BUFFERSIZE);
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000133 else
134 buffer[0] = '\0';
135
136 if(!rb->kbd_input(buffer, LUAL_BUFFERSIZE))
137 {
William Wilgusb5786de2018-10-23 01:57:41 -0400138 luaL_addstring(&b, buffer);
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000139 luaL_pushresult(&b);
140 }
141 else
William Wilgusb5786de2018-10-23 01:57:41 -0400142 return 0;
Maurus Cuelenaere1fde0dd2009-07-23 00:54:35 +0000143
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000144 return 1;
145}
146
William Wilgusb5786de2018-10-23 01:57:41 -0400147static const char ** get_table_items(lua_State *L, int pos, int *count)
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000148{
149 int i;
150 luaL_checktype(L, pos, LUA_TTABLE);
William Wilgusb5786de2018-10-23 01:57:41 -0400151 *count = lua_objlen(L, pos);
152 int n = *count;
William Wilguse4b84332018-09-17 19:28:10 +0200153
William Wilgusb5786de2018-10-23 01:57:41 -0400154 /* newuserdata will be pushed onto stack after args*/
155 const char **items = (const char**) lua_newuserdata(L, n * sizeof(const char*));
William Wilguse4b84332018-09-17 19:28:10 +0200156
William Wilgusb5786de2018-10-23 01:57:41 -0400157 for(i=1; i<= n; i++)
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000158 {
William Wilgusb5786de2018-10-23 01:57:41 -0400159 lua_rawgeti(L, pos, i); /* Push item on the stack */
160 items[i-1] = lua_tostring(L, -1);
161 lua_pop(L, 1); /* Pop it */
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000162 }
William Wilgusb5786de2018-10-23 01:57:41 -0400163
164 return items;
165}
166
167static inline void fill_text_message(lua_State *L, struct text_message * message,
168 int pos)
169{
170 int n;
171 /* newuserdata will be pushed onto stack after args*/
172 message->message_lines = get_table_items(L, pos, &n);
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000173 message->nb_lines = n;
174}
175
176RB_WRAP(gui_syncyesno_run)
177{
178 struct text_message main_message, yes_message, no_message;
179 struct text_message *yes = NULL, *no = NULL;
180
William Wilguse4b84332018-09-17 19:28:10 +0200181 lua_settop(L, 3); /* newuserdata will be pushed onto stack after args*/
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000182 fill_text_message(L, &main_message, 1);
183 if(!lua_isnoneornil(L, 2))
184 fill_text_message(L, (yes = &yes_message), 2);
185 if(!lua_isnoneornil(L, 3))
186 fill_text_message(L, (no = &no_message), 3);
187
188 enum yesno_res result = rb->gui_syncyesno_run(&main_message, yes, no);
189
Maurus Cuelenaerebeb90662009-07-05 16:41:16 +0000190 lua_pushinteger(L, result);
191 return 1;
192}
193
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000194RB_WRAP(do_menu)
195{
196 struct menu_callback_with_desc menu_desc = {NULL, NULL, Icon_NOICON};
197 struct menu_item_ex menu = {MT_RETURN_ID | MENU_HAS_DESC, {.strings = NULL},
198 {.callback_and_desc = &menu_desc}};
William Wilgusb5786de2018-10-23 01:57:41 -0400199 int n, start_selected;
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000200 const char **items, *title;
201
202 title = luaL_checkstring(L, 1);
William Wilgusb5786de2018-10-23 01:57:41 -0400203
William Wilguse4b84332018-09-17 19:28:10 +0200204 start_selected = lua_tointeger(L, 3);
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000205
William Wilguse4b84332018-09-17 19:28:10 +0200206 /* newuserdata will be pushed onto stack after args*/
William Wilgusb5786de2018-10-23 01:57:41 -0400207 items = get_table_items(L, 2, &n);
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000208
209 menu.strings = items;
210 menu.flags |= MENU_ITEM_COUNT(n);
211 menu_desc.desc = (unsigned char*) title;
212
213 int result = rb->do_menu(&menu, &start_selected, NULL, false);
214
Maurus Cuelenaere9dd25ad2009-10-23 10:38:20 +0000215 lua_pushinteger(L, result);
216 return 1;
217}
218
William Wilgusf6e10b82018-11-01 14:20:33 -0400219
220/* DEVICE AUDIO / PLAYLIST CONTROL */
221
William Wilguse4c5f5d2018-10-24 21:40:01 -0400222RB_WRAP(playlist)
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500223{
William Wilguse4c5f5d2018-10-24 21:40:01 -0400224 /* just passes NULL to work with the current playlist */
225 enum e_playlist {PLAYL_AMOUNT = 0, PLAYL_ADD, PLAYL_CREATE,
226 PLAYL_START, PLAYL_RESUMETRACK, PLAYL_RESUME,
227 PLAYL_SHUFFLE, PLAYL_SYNC, PLAYL_REMOVEALLTRACKS,
228 PLAYL_INSERTTRACK, PLAYL_INSERTDIRECTORY, PLAYL_ECOUNT};
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500229
William Wilgusbbfe4772018-10-31 09:23:00 -0400230 const char *playlist_option[] = {"amount", "add", "create", "start", "resume_track",
231 "resume", "shuffle", "sync", "remove_all_tracks",
232 "insert_track", "insert_directory", NULL};
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500233
William Wilguse4c5f5d2018-10-24 21:40:01 -0400234 const char *filename, *dir;
235 int result = 0;
236 bool queue, recurse, sync;
237 int pos, crc, index, random_seed;
238 unsigned long elapsed, offset;
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500239
William Wilguse4c5f5d2018-10-24 21:40:01 -0400240 int option = luaL_checkoption (L, 1, NULL, playlist_option);
241 switch(option)
242 {
William Wilguse4c5f5d2018-10-24 21:40:01 -0400243 case PLAYL_AMOUNT:
244 result = rb->playlist_amount();
245 break;
246 case PLAYL_ADD:
247 filename = luaL_checkstring(L, 2);
248 result = rb->playlist_add(filename);
249 break;
250 case PLAYL_CREATE:
251 dir = luaL_checkstring(L, 2);
252 filename = luaL_checkstring(L, 3);
253 result = rb->playlist_create(dir, filename);
254 break;
255 case PLAYL_START:
256 index = luaL_checkint(L, 2);
257 elapsed = luaL_checkint(L, 3);
258 offset = luaL_checkint(L, 4);
259 rb->playlist_start(index, elapsed, offset);
260 break;
261 case PLAYL_RESUMETRACK:
262 index = luaL_checkint(L, 2);
263 crc = luaL_checkint(L, 3);
264 elapsed = luaL_checkint(L, 4);
265 offset = luaL_checkint(L, 5);
266 rb->playlist_resume_track(index, (unsigned) crc, elapsed, offset);
267 break;
268 case PLAYL_RESUME:
269 result = rb->playlist_resume();
270 break;
271 case PLAYL_SHUFFLE:
272 random_seed = luaL_checkint(L, 2);
273 index = luaL_checkint(L, 3);
274 result = rb->playlist_shuffle(random_seed, index);
275 break;
276 case PLAYL_SYNC:
277 rb->playlist_sync(NULL);
278 break;
279 case PLAYL_REMOVEALLTRACKS:
280 result = rb->playlist_remove_all_tracks(NULL);
281 break;
282 case PLAYL_INSERTTRACK:
283 filename = luaL_checkstring(L, 2); /* only required parameter */
284 pos = luaL_optint(L, 3, PLAYLIST_INSERT);
285 queue = lua_toboolean(L, 4); /* default to false */
286 sync = lua_toboolean(L, 5); /* default to false */
287 result = rb->playlist_insert_track(NULL, filename, pos, queue, sync);
288 break;
289 case PLAYL_INSERTDIRECTORY:
290 dir = luaL_checkstring(L, 2); /* only required parameter */
291 pos = luaL_optint(L, 3, PLAYLIST_INSERT);
292 queue = lua_toboolean(L, 4); /* default to false */
293 recurse = lua_toboolean(L, 5); /* default to false */
294 result = rb->playlist_insert_directory(NULL, dir, pos, queue, recurse);
295 break;
296 }
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500297
William Wilguse4c5f5d2018-10-24 21:40:01 -0400298 rb->yield();
Albert Bloomfield885ecf82012-02-16 08:20:41 -0500299 lua_pushinteger(L, result);
300 return 1;
301}
302
William Wilgusb670fcd2018-10-24 10:49:52 -0400303RB_WRAP(audio)
304{
305 enum e_audio {AUDIO_STATUS = 0, AUDIO_PLAY, AUDIO_STOP, AUDIO_PAUSE,
306 AUDIO_RESUME, AUDIO_NEXT, AUDIO_PREV, AUDIO_FFREWIND,
William Wilgusc0dbfc82019-07-09 11:10:08 -0500307 AUDIO_FLUSHANDRELOADTRACKS, AUDIO_GETPOS, AUDIO_LENGTH,
308 AUDIO_ELAPSED, AUDIO_ECOUNT};
309 const char *audio_option[] = {"status", "play", "stop",
310 "pause", "resume", "next",
311 "prev", "ff_rewind",
312 "flush_and_reload_tracks",
313 "get_file_pos", "length",
314 "elapsed", NULL};
William Wilgusb670fcd2018-10-24 10:49:52 -0400315 long elapsed, offset, newtime;
316 int status = rb->audio_status();
317
318 int option = luaL_checkoption (L, 1, NULL, audio_option);
319 switch(option)
320 {
William Wilgusb670fcd2018-10-24 10:49:52 -0400321 case AUDIO_STATUS:
322 break;
323 case AUDIO_PLAY:
324 elapsed = luaL_checkint(L, 2);
325 offset = luaL_checkint(L, 3);
326
327 if (status == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE))
328 {
329 /* not perfect but provides a decent compromise */
330 rb->audio_ff_rewind(elapsed + offset);
331 rb->audio_resume();
332 }
333 else if (status != AUDIO_STATUS_PLAY)
334 rb->audio_play((unsigned long) elapsed, (unsigned long) offset);
335
336 break;
337 case AUDIO_STOP:
338 rb->audio_stop();
339 break;
340 case AUDIO_PAUSE:
341 rb->audio_pause();
342 break;
343 case AUDIO_RESUME:
344 rb->audio_resume();
345 break;
346 case AUDIO_NEXT:
347 rb->audio_next();
348 break;
349 case AUDIO_PREV:
350 rb->audio_prev();
351 break;
352 case AUDIO_FFREWIND:
353 newtime = (long) luaL_checkint(L, 2);
354 rb->audio_ff_rewind(newtime);
355 break;
356 case AUDIO_FLUSHANDRELOADTRACKS:
357 rb->audio_flush_and_reload_tracks();
358 break;
359 case AUDIO_GETPOS:
360 lua_pushinteger(L, rb->audio_get_file_pos());
361 return 1;
William Wilgusc0dbfc82019-07-09 11:10:08 -0500362 case AUDIO_LENGTH:
363 if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
364 lua_pushinteger(L, rb->audio_current_track()->length);
365 else
366 lua_pushnil(L);
367 return 1;
368 case AUDIO_ELAPSED:
369 if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
370 lua_pushinteger(L, rb->audio_current_track()->elapsed);
371 else
372 lua_pushnil(L);
373 return 1;
William Wilgusb670fcd2018-10-24 10:49:52 -0400374 }
375
376 rb->yield();
377 lua_pushinteger(L, status); /* return previous (or current) audio status */
378 return 1;
379}
380
William Wilgus6e32e062019-07-25 10:17:40 -0500381RB_WRAP(sound)
382{
383 enum e_snd {SOUND_SET = 0, SOUND_CURRENT, SOUND_DEFAULT,
384 SOUND_MIN, SOUND_MAX, SOUND_UNIT, SOUND_SET_PITCH,
385 SOUND_VAL2PHYS, SOUND_ECOUNT};
386
387 const char *snd_option[] = {"set", "current", "default",
388 "min", "max", "unit", "pitch",
389 "val2phys", NULL};
390
391 lua_pushnil(L); /*push nil so options w/o return have something to return */
392
393 int option = luaL_checkoption (L, 1, NULL, snd_option);
394 int setting = luaL_checkint(L, 2);
395 int value, result;
396 switch(option)
397 {
398 case SOUND_SET:
399 value = luaL_checkint(L, 3);
400 rb->sound_set(setting, value);
401 return 1; /*nil*/
402 break;
403 case SOUND_CURRENT:
404 result = rb->sound_current(setting);
405 break;
406 case SOUND_DEFAULT:
407 result = rb->sound_default(setting);
408 break;
409 case SOUND_MIN:
410 result = rb->sound_min(setting);
411 break;
412 case SOUND_MAX:
413 result = rb->sound_max(setting);
414 break;
415 case SOUND_UNIT:
416 lua_pushstring (L, rb->sound_unit(setting));
417 return 1;
418 break;
419#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
420 (CONFIG_CODEC == SWCODEC)) && defined (HAVE_PITCHCONTROL)
421 case SOUND_SET_PITCH:
422 rb->sound_set_pitch(setting);
423 return 1;/*nil*/
424 break;
425#endif
426 case SOUND_VAL2PHYS:
427 value = luaL_checkint(L, 3);
428 result = rb->sound_val2phys(setting, value);
429 break;
430
431 default:
432 return 1;
433 break;
434 }
435
436 lua_pushinteger(L, result);
437 return 1;
438}
439
William Wilgus74fe5202018-10-30 13:56:36 -0400440#if CONFIG_CODEC == SWCODEC
441RB_WRAP(pcm)
442{
443 enum e_pcm {PCM_APPLYSETTINGS = 0, PCM_ISPLAYING, PCM_ISPAUSED,
444 PCM_PLAYSTOP, PCM_PLAYPAUSE, PCM_PLAYLOCK, PCM_PLAYUNLOCK,
445 PCM_CALCULATEPEAKS, PCM_SETFREQUENCY, PCM_GETBYTESWAITING, PCM_ECOUNT};
446
William Wilgusbbfe4772018-10-31 09:23:00 -0400447 const char *pcm_option[] = {"apply_settings", "is_playing", "is_paused",
448 "play_stop", "play_pause", "play_lock", "play_unlock",
449 "calculate_peaks", "set_frequency", "get_bytes_waiting", NULL};
William Wilgus74fe5202018-10-30 13:56:36 -0400450 bool b_result;
451 int left, right;
452 size_t byteswait;
453
454 lua_pushnil(L); /*push nil so options w/o return have something to return */
455
456 int option = luaL_checkoption (L, 1, NULL, pcm_option);
457 switch(option)
458 {
William Wilgus74fe5202018-10-30 13:56:36 -0400459 case PCM_APPLYSETTINGS:
460 rb->pcm_apply_settings();
461 break;
462 case PCM_ISPLAYING:
463 b_result = rb->pcm_is_playing();
464 lua_pushboolean(L, b_result);
465 break;
466 case PCM_ISPAUSED:
467 b_result = rb->pcm_is_paused();
468 lua_pushboolean(L, b_result);
469 break;
470 case PCM_PLAYPAUSE:
William Wilgus9b385f32018-11-01 18:18:46 -0400471 rb->pcm_play_pause(luaL_checkboolean(L, 2));
William Wilgus74fe5202018-10-30 13:56:36 -0400472 break;
473 case PCM_PLAYSTOP:
474 rb->pcm_play_stop();
475 break;
476 case PCM_PLAYLOCK:
477 rb->pcm_play_lock();
478 break;
479 case PCM_PLAYUNLOCK:
480 rb->pcm_play_unlock();
481 break;
482 case PCM_CALCULATEPEAKS:
483 rb->pcm_calculate_peaks(&left, &right);
484 lua_pushinteger(L, left);
485 lua_pushinteger(L, right);
486 return 2;
487 case PCM_SETFREQUENCY:
William Wilgus9b385f32018-11-01 18:18:46 -0400488 rb->pcm_set_frequency((unsigned int) luaL_checkint(L, 2));
William Wilgus74fe5202018-10-30 13:56:36 -0400489 break;
490 case PCM_GETBYTESWAITING:
491 byteswait = rb->pcm_get_bytes_waiting();
492 lua_pushinteger(L, byteswait);
493 break;
494 }
495
496 rb->yield();
497 return 1;
498}
William Wilgusf6e10b82018-11-01 14:20:33 -0400499
500RB_WRAP(mixer_frequency)
501{
502 unsigned int result = rb->mixer_get_frequency();
503
504 if(!lua_isnoneornil(L, 1))
505 {
506 unsigned int samplerate = (unsigned int) luaL_checkint(L, 1);
507 rb->mixer_set_frequency(samplerate);
508 }
509 lua_pushinteger(L, result);
510 return 1;
511}
William Wilgus74fe5202018-10-30 13:56:36 -0400512#endif /*CONFIG_CODEC == SWCODEC*/
513
William Wilgusf6e10b82018-11-01 14:20:33 -0400514/* DEVICE LIGHTING CONTROL */
515RB_WRAP(backlight_onoff)
516{
517 bool on = luaL_checkboolean(L, 1);
518 if(on)
519 rb->backlight_on();
520 else
521 rb->backlight_off();
522
523 return 0;
524}
525
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000526SIMPLE_VOID_WRAPPER(backlight_force_on);
527SIMPLE_VOID_WRAPPER(backlight_use_settings);
William Wilguse4b84332018-09-17 19:28:10 +0200528
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000529#ifdef HAVE_REMOTE_LCD
530SIMPLE_VOID_WRAPPER(remote_backlight_force_on);
531SIMPLE_VOID_WRAPPER(remote_backlight_use_settings);
532#endif
William Wilguse4b84332018-09-17 19:28:10 +0200533
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000534#ifdef HAVE_BUTTON_LIGHT
535SIMPLE_VOID_WRAPPER(buttonlight_force_on);
536SIMPLE_VOID_WRAPPER(buttonlight_use_settings);
537#endif
William Wilguse4b84332018-09-17 19:28:10 +0200538
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000539#ifdef HAVE_BACKLIGHT_BRIGHTNESS
540RB_WRAP(backlight_brightness_set)
541{
William Wilgusf6e10b82018-11-01 14:20:33 -0400542 if(lua_isnoneornil(L, 1))
543 backlight_brightness_use_setting();
544 else
545 {
546 int brightness = luaL_checkint(L, 1);
547 backlight_brightness_set(brightness);
548 }
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000549
550 return 0;
551}
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000552#endif
553
William Wilgusf6e10b82018-11-01 14:20:33 -0400554#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
555RB_WRAP(buttonlight_brightness_set)
Thomas Martitzc406f942012-01-27 00:05:20 +0100556{
William Wilgusf6e10b82018-11-01 14:20:33 -0400557 if(lua_isnoneornil(L, 1))
558 buttonlight_brightness_use_setting();
Thomas Martitzc406f942012-01-27 00:05:20 +0100559 else
William Wilgusf6e10b82018-11-01 14:20:33 -0400560 {
561 int brightness = luaL_checkint(L, 1);
562 buttonlight_brightness_set(brightness);
563 }
Thomas Martitzc406f942012-01-27 00:05:20 +0100564
William Wilgusf6e10b82018-11-01 14:20:33 -0400565 return 0;
Thomas Martitzc406f942012-01-27 00:05:20 +0100566}
William Wilgusf6e10b82018-11-01 14:20:33 -0400567#endif
568
569
570/* DEVICE STRING / FILENAME MANIPULATION */
Thomas Martitzc406f942012-01-27 00:05:20 +0100571
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400572RB_WRAP(strip_extension)
573{
574 const char* filename = luaL_checkstring(L, -1);
575 const char* pos = rb->strrchr(filename, '.');
576 if(pos != NULL)
577 lua_pushlstring (L, filename, pos - filename);
578
579 return 1;
580}
581
582RB_WRAP(create_numbered_filename)
583{
584 luaL_Buffer b;
585 luaL_buffinit(L, &b);
586 char *buffer = luaL_prepbuffer(&b);
587 buffer[0] = '\0';
588
589 const char * path = luaL_checkstring(L, 1);
590 const char * prefix = luaL_checkstring(L, 2);
591 const char * suffix = luaL_checkstring(L, 3);
William Wilgus20b98f62018-10-24 11:09:17 -0400592 int numberlen = luaL_checkint(L, 4);
593 int num = luaL_optint(L, 5, -1);
594 (void) num;
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400595
William Wilgus20b98f62018-10-24 11:09:17 -0400596 if(rb->create_numbered_filename(buffer, path, prefix, suffix, numberlen
597 IF_CNFN_NUM_(, &num)))
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400598 {
599 luaL_addstring(&b, buffer);
600 luaL_pushresult(&b);
601 }
602 else
603 return 0;
604
605 return 1;
606}
607
William Wilgusbe7a58c2018-10-30 22:40:23 -0400608RB_WRAP(utf8encode)
609{
610 unsigned long ucs = (unsigned long) luaL_checkint(L, 1);
611 unsigned char tmp[9];
612 unsigned char *end = rb->utf8encode(ucs, tmp);
613 *end = '\0';
614 lua_pushstring(L, tmp);
615 return 1;
616}
617
William Wilgusf6e10b82018-11-01 14:20:33 -0400618RB_WRAP(strncasecmp)
619{
620 int result;
621 const char * s1 = luaL_checkstring(L, 1);
622 const char * s2 = luaL_checkstring(L, 2);
623 if(lua_isnoneornil(L, 3))
624 result = rb->strcasecmp(s1, s2);
625 else
626 result = rb->strncasecmp(s1, s2, (size_t) luaL_checkint(L, 3));
627
628 lua_pushinteger(L, result);
629 return 1;
630}
631
William Wilgus9d66b542018-12-15 13:50:00 -0600632static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize)
633{
634 intptr_t offset = (intptr_t) luaL_optint(L, 1, 0);
635 size_t size = (size_t) luaL_optint(L, 2, maxsize);
636 size_t written;
637 int type = lua_type(L, 3);
638
639 if(offset < 0)
640 {
641 /* allows pointer within structure to be calculated offset */
642 offset = -(address + offset);
643 size = (size_t) maxsize - offset;
644 }
645
646 luaL_argcheck(L, ((uintptr_t) offset) + size <= maxsize, 2, ERR_IDX_RANGE);
647
648 char *mem = (char*) address + ((uintptr_t) offset);
649 const void *value = NULL;
650
651 lua_Integer var_luaint;
652#ifdef UINT64_MAX
653 int64_t var_64;
654#endif
655 int32_t var_32;
656 int16_t var_16;
657 int8_t var_8;
658 bool var_bool;
659
660 switch(type)
661 {
662 case LUA_TSTRING:
663 {
664 size_t len;
665 const char* str = lua_tolstring (L, 3, &len);
666
667 luaL_argcheck(L, len + 1 <= size, 3, ERR_DATA_OVF);
668 size = len + 1; /* include \0 */
669 value = str;
670 break;
671 }
672 case LUA_TBOOLEAN:
673 {
674 var_bool = (bool) lua_toboolean(L, 3);
675 value = &var_bool;
676 break;
677 }
678 case LUA_TNUMBER:
679 {
680 var_luaint = lua_tointeger(L, 3);
681 switch(size)
682 {
683 case sizeof(var_8):
684 var_8 = (int8_t) var_luaint;
685 value = &var_8;
686 break;
687 case sizeof(var_16):
688 var_16 = (int16_t) var_luaint;
689 value = &var_16;
690 break;
691 case sizeof(var_32):
692 var_32 = (int32_t) var_luaint;
693 value = &var_32;
694 break;
695#ifdef UINT64_MAX
696 case sizeof(var_64):
697 var_64 = (int64_t) var_luaint;
698 value = &var_64;
699 break;
700#endif
701 } /* switch size */
702 break;
703 }
704 case LUA_TNIL:
705 case LUA_TNONE: /* reader */
706 {
707 luaL_Buffer b;
708 luaL_buffinit(L, &b);
709 while(size > 0)
710 {
711 written = MIN(LUAL_BUFFERSIZE, size);
712 luaL_addlstring (&b, mem, written);
713 mem += written;
714 size -= written;
715 }
716
717 luaL_pushresult(&b);
718 return 1;
719 }
720
721 default:
722 break;
723 } /* switch type */
724
725 /* writer */
726 luaL_argcheck(L, value != NULL, 3, "Unknown Type");
727 rb->memcpy(mem, value, size);
728 lua_pushinteger(L, 1);
729
730 return 1;
731}
732
733RB_WRAP(global_status)
734{
735 const uintptr_t address = (uintptr_t) rb->global_status;
736 const size_t maxsize = sizeof(struct system_status);
737 return mem_read_write(L, address, maxsize);
738}
739
740RB_WRAP(global_settings)
741{
742 const uintptr_t address = (uintptr_t) rb->global_settings;
743 const size_t maxsize = sizeof(struct user_settings);
744 return mem_read_write(L, address, maxsize);
745}
746
747RB_WRAP(audio_next_track)
748{
749 lua_settop(L, 2); /* no writes allowed */
750 const uintptr_t address = (uintptr_t) rb->audio_next_track();
751 const size_t maxsize = sizeof(struct mp3entry);
752 return mem_read_write(L, address, maxsize);
753}
754
755RB_WRAP(audio_current_track)
756{
757 lua_settop(L, 2); /* no writes allowed */
758 const uintptr_t address = (uintptr_t) rb->audio_current_track();
759 const size_t maxsize = sizeof(struct mp3entry);
760 return mem_read_write(L, address, maxsize);
761}
762
William Wilguse4b84332018-09-17 19:28:10 +0200763#define RB_FUNC(func) {#func, rock_##func}
William Wilgusf6e10b82018-11-01 14:20:33 -0400764#define RB_ALIAS(name, func) {name, rock_##func}
Maurus Cuelenaerea9b2d1b2009-05-21 19:42:14 +0000765static const luaL_Reg rocklib[] =
766{
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000767 /* Kernel */
William Wilguse4b84332018-09-17 19:28:10 +0200768 RB_FUNC(current_tick),
William Wilgusf6e10b82018-11-01 14:20:33 -0400769#ifdef HAVE_SCHEDULER_BOOSTCTRL
770 RB_FUNC(schedule_cpu_boost),
Maurus Cuelenaere0f7e4e32009-05-22 22:44:34 +0000771#endif
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000772
William Wilguse4b84332018-09-17 19:28:10 +0200773 RB_FUNC(current_path),
William Wilgusf6e10b82018-11-01 14:20:33 -0400774
775 /* DEVICE INPUT CONTROL */
776 RB_FUNC(get_plugin_action),
777#ifdef HAVE_TOUCHSCREEN
778 RB_FUNC(action_get_touchscreen_press),
779 RB_FUNC(touchscreen_mode),
780#endif
781 RB_FUNC(kbd_input),
William Wilguse4b84332018-09-17 19:28:10 +0200782 RB_FUNC(gui_syncyesno_run),
William Wilguse4b84332018-09-17 19:28:10 +0200783 RB_FUNC(do_menu),
Maurus Cuelenaere86fe1e82009-05-24 01:54:15 +0000784
William Wilgus6e32e062019-07-25 10:17:40 -0500785 /* DEVICE AUDIO / SOUND / PLAYLIST CONTROL */
William Wilgusf6e10b82018-11-01 14:20:33 -0400786 RB_FUNC(audio),
787 RB_FUNC(playlist),
William Wilgus6e32e062019-07-25 10:17:40 -0500788 RB_FUNC(sound),
William Wilgusf6e10b82018-11-01 14:20:33 -0400789#if CONFIG_CODEC == SWCODEC
790 RB_FUNC(pcm),
791 RB_FUNC(mixer_frequency),
792#endif
793
794 /* DEVICE LIGHTING CONTROL */
795 RB_FUNC(backlight_onoff),
796
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000797 /* Backlight helper */
William Wilguse4b84332018-09-17 19:28:10 +0200798 RB_FUNC(backlight_force_on),
799 RB_FUNC(backlight_use_settings),
800
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000801#ifdef HAVE_REMOTE_LCD
William Wilguse4b84332018-09-17 19:28:10 +0200802 RB_FUNC(remote_backlight_force_on),
803 RB_FUNC(remote_backlight_use_settings),
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000804#endif
William Wilguse4b84332018-09-17 19:28:10 +0200805
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000806#ifdef HAVE_BUTTON_LIGHT
William Wilguse4b84332018-09-17 19:28:10 +0200807 RB_FUNC(buttonlight_force_on),
808 RB_FUNC(buttonlight_use_settings),
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000809#endif
William Wilguse4b84332018-09-17 19:28:10 +0200810
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000811#ifdef HAVE_BACKLIGHT_BRIGHTNESS
William Wilguse4b84332018-09-17 19:28:10 +0200812 RB_FUNC(backlight_brightness_set),
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000813#endif
William Wilguse4b84332018-09-17 19:28:10 +0200814
William Wilgusf6e10b82018-11-01 14:20:33 -0400815#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
816 RB_FUNC(buttonlight_brightness_set),
817#endif
Maurus Cuelenaere8dbef6d2009-10-26 17:07:56 +0000818
William Wilgusf6e10b82018-11-01 14:20:33 -0400819 /* DEVICE STRING / FILENAME MANIPULATION */
William Wilgusdf4cb9b2018-10-23 00:11:34 -0400820 RB_FUNC(strip_extension),
821 RB_FUNC(create_numbered_filename),
William Wilgusbe7a58c2018-10-30 22:40:23 -0400822 RB_FUNC(utf8encode),
William Wilgusf6e10b82018-11-01 14:20:33 -0400823 RB_FUNC(strncasecmp),
William Wilgusbe7a58c2018-10-30 22:40:23 -0400824
William Wilgus9d66b542018-12-15 13:50:00 -0600825 /* ROCKBOX SETTINGS / INFO */
826 RB_FUNC(global_status),
827 RB_FUNC(global_settings),
828 RB_FUNC(audio_next_track),
829 RB_FUNC(audio_current_track),
830
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000831 {NULL, NULL}
832};
William Wilguse4b84332018-09-17 19:28:10 +0200833#undef RB_FUNC
William Wilgusf6e10b82018-11-01 14:20:33 -0400834#undef RB_ALIAS
William Wilguse4b84332018-09-17 19:28:10 +0200835
Maurus Cuelenaered755a5a2009-07-05 15:33:08 +0000836extern const luaL_Reg rocklib_aux[];
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000837
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000838/*
839 ** Open Rockbox library
840 */
841LUALIB_API int luaopen_rock(lua_State *L)
842{
Marcin Bukatbfd01792014-04-02 20:46:06 +0200843 luaL_register(L, LUA_ROCKLIBNAME, rocklib);
844 luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux);
William Wilgusc9aeb422019-07-18 08:42:00 -0500845 lua_getglobal(L, "require");
846 lua_pushstring(L, "rb_defines");
847 if (lua_pcall (L, 1, 0, 0))
848 lua_pop(L, 1);
849#if 0
William Wilgusdc6f23e2018-09-14 01:13:22 +0200850 static const struct lua_int_reg rlib_const_int[] =
851 {
852 /* useful integer constants */
853 RB_CONSTANT(HZ),
Maurus Cuelenaere2cd4a942009-05-22 00:06:45 +0000854
William Wilgusdc6f23e2018-09-14 01:13:22 +0200855 RB_CONSTANT(LCD_DEPTH),
William Wilguse4b84332018-09-17 19:28:10 +0200856 RB_CONSTANT(LCD_HEIGHT),
857 RB_CONSTANT(LCD_WIDTH),
William Wilgusf6e10b82018-11-01 14:20:33 -0400858 RB_CONSTANT(SCREEN_MAIN),
William Wilgus9ed486b2018-11-24 16:40:23 -0500859#if LCD_DEPTH > 1
860 RB_CONSTANT(LCD_DEFAULT_FG),
861 RB_CONSTANT(LCD_DEFAULT_BG),
862#endif
William Wilgusdf8233e2018-10-27 06:24:27 -0400863#ifdef HAVE_REMOTE_LCD
864 RB_CONSTANT(LCD_REMOTE_DEPTH),
865 RB_CONSTANT(LCD_REMOTE_HEIGHT),
866 RB_CONSTANT(LCD_REMOTE_WIDTH),
William Wilgusf6e10b82018-11-01 14:20:33 -0400867 RB_CONSTANT(SCREEN_REMOTE),
William Wilgusdf8233e2018-10-27 06:24:27 -0400868#endif
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000869
William Wilgusdc6f23e2018-09-14 01:13:22 +0200870 RB_CONSTANT(FONT_SYSFIXED),
871 RB_CONSTANT(FONT_UI),
Maurus Cuelenaere2cd4a942009-05-22 00:06:45 +0000872
William Wilgusdc6f23e2018-09-14 01:13:22 +0200873 RB_CONSTANT(PLAYLIST_INSERT),
874 RB_CONSTANT(PLAYLIST_INSERT_LAST),
875 RB_CONSTANT(PLAYLIST_INSERT_FIRST),
William Wilgusdc6f23e2018-09-14 01:13:22 +0200876 RB_CONSTANT(PLAYLIST_INSERT_LAST_SHUFFLED),
William Wilguse4b84332018-09-17 19:28:10 +0200877 RB_CONSTANT(PLAYLIST_INSERT_SHUFFLED),
878 RB_CONSTANT(PLAYLIST_PREPEND),
879 RB_CONSTANT(PLAYLIST_REPLACE),
880
William Wilgus3e2b50e2019-06-27 11:28:34 -0500881/* queue sys events */
882 RB_CONSTANT(SYS_USB_CONNECTED),
883 RB_CONSTANT(SYS_USB_DISCONNECTED),
884 RB_CONSTANT(SYS_TIMEOUT),
885 RB_CONSTANT(SYS_POWEROFF),
886 RB_CONSTANT(SYS_CHARGER_CONNECTED),
887 RB_CONSTANT(SYS_CHARGER_DISCONNECTED),
888
Maurus Cuelenaere9c3e6792009-06-01 22:31:32 +0000889#ifdef HAVE_TOUCHSCREEN
William Wilgusdc6f23e2018-09-14 01:13:22 +0200890 RB_CONSTANT(TOUCHSCREEN_POINT),
891 RB_CONSTANT(TOUCHSCREEN_BUTTON),
Maurus Cuelenaere9c3e6792009-06-01 22:31:32 +0000892#endif
893
William Wilgusdc6f23e2018-09-14 01:13:22 +0200894 {NULL, 0}
895 };
Maurus Cuelenaere59c4b682009-07-08 11:59:05 +0000896
William Wilgusdc6f23e2018-09-14 01:13:22 +0200897 static const struct lua_int_reg* rlci = rlib_const_int;
898 for (; rlci->name; rlci++) {
899 lua_pushinteger(L, rlci->value);
William Wilgusc6fcb1c2018-11-11 18:27:19 -0500900 luaS_newlloc(L, rlci->name, TSTR_INBIN);
William Wilgusdc6f23e2018-09-14 01:13:22 +0200901 lua_setfield(L, -2, rlci->name);
902 }
903
904 static const struct lua_str_reg rlib_const_str[] =
905 {
906 /* some useful paths constants */
William Wilgusdc6f23e2018-09-14 01:13:22 +0200907 RB_STRING_CONSTANT(HOME_DIR),
908 RB_STRING_CONSTANT(PLUGIN_DIR),
909 RB_STRING_CONSTANT(PLUGIN_APPS_DATA_DIR),
910 RB_STRING_CONSTANT(PLUGIN_GAMES_DATA_DIR),
911 RB_STRING_CONSTANT(PLUGIN_DATA_DIR),
William Wilguse4b84332018-09-17 19:28:10 +0200912 RB_STRING_CONSTANT(ROCKBOX_DIR),
William Wilgusdc6f23e2018-09-14 01:13:22 +0200913 RB_STRING_CONSTANT(VIEWERS_DATA_DIR),
914 {NULL,NULL}
915 };
916
917 static const struct lua_str_reg* rlcs = rlib_const_str;
918 for (; rlcs->name; rlcs++) {
William Wilgusc6fcb1c2018-11-11 18:27:19 -0500919 luaS_newlloc(L, rlcs->value, TSTR_INBIN);
William Wilgusdc6f23e2018-09-14 01:13:22 +0200920 lua_pushstring(L, rlcs->value);
William Wilgusc6fcb1c2018-11-11 18:27:19 -0500921 luaS_newlloc(L, rlcs->name, TSTR_INBIN);
William Wilgusdc6f23e2018-09-14 01:13:22 +0200922 lua_setfield(L, -2, rlcs->name);
923 }
William Wilgusc9aeb422019-07-18 08:42:00 -0500924#endif
Maurus Cuelenaerecf875972009-05-21 19:01:41 +0000925 return 1;
926}
William Wilgusaf35d192018-07-23 02:50:22 +0200927