plugin api: Add audio_pre_ff_rewind to plugin's API

According to wps code audio_pre_ff_rewind function should be called
before any rewinding. It stops playback and automatically resumes it
after audio_ff_rewind call

So, let's add audio_pre_ff_rewind to plugin's API

Lua scipts were tested:
```lua
-- has issue with rewinding
rb.audio("ff_rewind", 0)
```

```lua
-- no issue with rewinding
rb.audio("pre_ff_rewind")
rb.audio("ff_rewind", 0)
```

Change-Id: I2ad6b9c396760b2086bc0a28633a1c80c3512739
This commit is contained in:
Petr Mikhalicin 2025-12-28 00:17:06 +05:00
parent 06badb81b4
commit 6f7d70797e
7 changed files with 73 additions and 60 deletions

View file

@ -356,6 +356,8 @@ static const struct plugin_api rockbox_api = {
simplelist_info_init,
simplelist_show_list,
yesno_pop,
yesno_pop_confirm,
sb_set_title_text,
/* action handling */
get_custom_action,
@ -363,6 +365,18 @@ static const struct plugin_api rockbox_api = {
#ifdef HAVE_TOUCHSCREEN
action_get_touchscreen_press,
action_get_touchscreen_press_in_vp,
action_get_touch_event,
action_gesture_reset,
action_gesture_get_event_in_vp,
action_gesture_get_event,
action_gesture_is_valid,
action_gesture_is_pressed,
gesture_reset,
gesture_process,
gesture_get_event_in_vp,
gesture_vel_reset,
gesture_vel_process,
gesture_vel_get,
#endif
action_userabort,
core_set_keyremap,
@ -428,6 +442,9 @@ static const struct plugin_api rockbox_api = {
crc_32r,
filetype_get_attr,
filetype_get_plugin,
#ifdef HAVE_DIRCACHE
dircache_wait,
#endif
/* dir */
FS_PREFIX(opendir),
@ -565,6 +582,7 @@ static const struct plugin_api rockbox_api = {
strncmp,
strcasecmp,
strncasecmp,
strstr,
memset,
memcpy,
memmove,
@ -729,6 +747,7 @@ static const struct plugin_api rockbox_api = {
audio_resume,
audio_next,
audio_prev,
audio_pre_ff_rewind,
audio_ff_rewind,
audio_next_track,
audio_status,
@ -738,6 +757,7 @@ static const struct plugin_api rockbox_api = {
#ifdef PLUGIN_USE_IRAM
audio_hard_stop,
#endif
add_playbacklog,
/* menu */
root_menu_get_options,
@ -761,6 +781,7 @@ static const struct plugin_api rockbox_api = {
#endif
/* power */
&device_battery_tables,
battery_level,
battery_level_safe,
battery_time,
@ -772,12 +793,17 @@ static const struct plugin_api rockbox_api = {
charging_state,
# endif
#endif
/* usb */
usb_inserted,
usb_acknowledge,
#ifdef USB_ENABLE_HID
usb_hid_send,
#endif
#ifdef USB_ENABLE_AUDIO
usb_audio_get_playing,
#endif
/* misc */
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
__errno,
@ -849,31 +875,6 @@ static const struct plugin_api rockbox_api = {
/* new stuff at the end, sort into place next time
the API gets incompatible */
add_playbacklog,
&device_battery_tables,
yesno_pop_confirm,
#ifdef USB_ENABLE_AUDIO
usb_audio_get_playing,
#endif
#ifdef HAVE_TOUCHSCREEN
action_get_touch_event,
action_gesture_reset,
action_gesture_get_event_in_vp,
action_gesture_get_event,
action_gesture_is_valid,
action_gesture_is_pressed,
gesture_reset,
gesture_process,
gesture_get_event_in_vp,
gesture_vel_reset,
gesture_vel_process,
gesture_vel_get,
#endif
strstr,
sb_set_title_text,
#ifdef HAVE_DIRCACHE
dircache_wait,
#endif
};
static int plugin_buffer_handle;

View file

@ -178,7 +178,7 @@ int plugin_open(const char *plugin, const char *parameter);
* when this happens please take the opportunity to sort in
* any new functions "waiting" at the end of the list.
*/
#define PLUGIN_API_VERSION 274
#define PLUGIN_API_VERSION 275
/* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */
@ -418,6 +418,8 @@ struct plugin_api {
int count, void* data);
bool (*simplelist_show_list)(struct simplelist_info *info);
bool (*yesno_pop)(const char* text);
bool (*yesno_pop_confirm)(const char* text);
bool (*sb_set_title_text)(const char* title, enum themable_icons icon, enum screen_type screen);
/* action handling */
int (*get_custom_action)(int context,int timeout,
@ -426,6 +428,22 @@ struct plugin_api {
#ifdef HAVE_TOUCHSCREEN
int (*action_get_touchscreen_press)(short *x, short *y);
int (*action_get_touchscreen_press_in_vp)(short *x1, short *y1, struct viewport *vp);
int (*action_get_touch_event)(struct touchevent *ev);
void (*action_gesture_reset)(void);
bool (*action_gesture_get_event_in_vp)(struct gesture_event *gevt,
const struct viewport *vp);
bool (*action_gesture_get_event)(struct gesture_event *gevt);
bool (*action_gesture_is_valid)(void);
bool (*action_gesture_is_pressed)(void);
void (*gesture_reset)(struct gesture *g);
void (*gesture_process)(struct gesture *g, const struct touchevent *ev);
bool (*gesture_get_event_in_vp)(struct gesture *g,
struct gesture_event *gevt,
const struct viewport *vp);
void (*gesture_vel_reset)(struct gesture_vel *gv);
void (*gesture_vel_process)(struct gesture_vel *gv,
const struct touchevent *ev);
bool (*gesture_vel_get)(struct gesture_vel *gv, int *xvel, int *yvel);
#endif
bool (*action_userabort)(int timeout);
int (*core_set_keyremap)(struct button_mapping* core_keymap, int count);
@ -493,6 +511,9 @@ struct plugin_api {
int (*filetype_get_attr)(const char* file);
char* (*filetype_get_plugin)(int attr, char *buffer, size_t buffer_len);
#ifdef HAVE_DIRCACHE
void (*dircache_wait)(void);
#endif
/* dir */
DIR * (*opendir)(const char *dirname);
@ -652,6 +673,7 @@ struct plugin_api {
int (*strncmp)(const char *, const char *, size_t);
int (*strcasecmp)(const char *, const char *);
int (*strncasecmp)(const char *s1, const char *s2, size_t n);
char* (*strstr)(const char *s1, const char *s2);
void* (*memset)(void *dst, int c, size_t length);
void* (*memcpy)(void *out, const void *in, size_t n);
void* (*memmove)(void *out, const void *in, size_t n);
@ -853,6 +875,7 @@ struct plugin_api {
void (*audio_resume)(void);
void (*audio_next)(void);
void (*audio_prev)(void);
void (*audio_pre_ff_rewind)(void);
void (*audio_ff_rewind)(long newtime);
struct mp3entry* (*audio_next_track)(void);
int (*audio_status)(void);
@ -862,6 +885,7 @@ struct plugin_api {
#ifdef PLUGIN_USE_IRAM
void (*audio_hard_stop)(void);
#endif
void (*add_playbacklog)(struct mp3entry *id3);
/* menu */
struct menu_table *(*root_menu_get_options)(int *nb_options);
@ -902,6 +926,7 @@ struct plugin_api {
#endif
/* power */
struct battery_tables_t *device_battery_tables;
int (*battery_level)(void);
bool (*battery_level_safe)(void);
int (*battery_time)(void);
@ -913,12 +938,17 @@ struct plugin_api {
bool (*charging_state)(void);
# endif
#endif
/* usb */
bool (*usb_inserted)(void);
void (*usb_acknowledge)(long id);
#ifdef USB_ENABLE_HID
void (*usb_hid_send)(usage_page_t usage_page, int id);
#endif
#ifdef USB_ENABLE_AUDIO
bool (*usb_audio_get_playing)(void);
#endif
/* misc */
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
int * (*__errno)(void);
@ -994,37 +1024,9 @@ struct plugin_api {
#ifdef HAVE_MULTIVOLUME
int (*path_strip_volume)(const char *name, const char **nameptr, bool greedy);
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
void (*add_playbacklog)(struct mp3entry *id3);
struct battery_tables_t *device_battery_tables;
bool (*yesno_pop_confirm)(const char* text);
#ifdef USB_ENABLE_AUDIO
bool (*usb_audio_get_playing)(void);
#endif
#ifdef HAVE_TOUCHSCREEN
int (*action_get_touch_event)(struct touchevent *ev);
void (*action_gesture_reset)(void);
bool (*action_gesture_get_event_in_vp)(struct gesture_event *gevt,
const struct viewport *vp);
bool (*action_gesture_get_event)(struct gesture_event *gevt);
bool (*action_gesture_is_valid)(void);
bool (*action_gesture_is_pressed)(void);
void (*gesture_reset)(struct gesture *g);
void (*gesture_process)(struct gesture *g, const struct touchevent *ev);
bool (*gesture_get_event_in_vp)(struct gesture *g,
struct gesture_event *gevt,
const struct viewport *vp);
void (*gesture_vel_reset)(struct gesture_vel *gv);
void (*gesture_vel_process)(struct gesture_vel *gv,
const struct touchevent *ev);
bool (*gesture_vel_get)(struct gesture_vel *gv, int *xvel, int *yvel);
#endif
char* (*strstr)(const char *s1, const char *s2);
bool (*sb_set_title_text)(const char* title, enum themable_icons icon, enum screen_type screen);
#ifdef HAVE_DIRCACHE
void (*dircache_wait)(void);
#endif
};
/* plugin header */

View file

@ -31,6 +31,7 @@ rb.audio_pause = function() rb.audio("pause") end
rb.audio_resume = function() rb.audio("resume") end
rb.audio_next = function() rb.audio("next") end
rb.audio_prev = function() rb.audio("prev") end
rb.audio_pre_ff_rewind = function () rb.audio("pre_ff_rewind") end
rb.audio_ff_rewind = function (newtime) rb.audio("ff_rewind", newtime) end
rb.audio_flush_and_reload_tracks = function() rb.audio("flush_and_reload_tracks") end
rb.audio_get_file_pos = function() return rb.audio("get_file_pos") end

View file

@ -410,12 +410,12 @@ RB_WRAP(playlist)
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_LENGTH,
AUDIO_ELAPSED, AUDIO_ECOUNT};
AUDIO_RESUME, AUDIO_NEXT, AUDIO_PREV, AUDIO_PREFFREWIND,
AUDIO_FFREWIND, AUDIO_FLUSHANDRELOADTRACKS, AUDIO_GETPOS,
AUDIO_LENGTH, AUDIO_ELAPSED, AUDIO_ECOUNT};
const char *audio_option[] = {"status", "play", "stop",
"pause", "resume", "next",
"prev", "ff_rewind",
"prev", "pre_ff_rewind", "ff_rewind",
"flush_and_reload_tracks",
"get_file_pos", "length",
"elapsed", NULL};
@ -434,6 +434,7 @@ RB_WRAP(audio)
if (status == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE))
{
/* not perfect but provides a decent compromise */
rb->audio_pre_ff_rewind();
rb->audio_ff_rewind(elapsed + offset);
rb->audio_resume();
}
@ -456,6 +457,9 @@ RB_WRAP(audio)
case AUDIO_PREV:
rb->audio_prev();
break;
case AUDIO_PREFFREWIND:
rb->audio_pre_ff_rewind();
break;
case AUDIO_FFREWIND:
newtime = (long) luaL_checkint(L, 2);
rb->audio_ff_rewind(newtime);

View file

@ -97,7 +97,7 @@ my @forbidden_functions = ('^atoi$',
'^__.+$',
'^.+_(un)?cached$',
'^audio_(status|get_file_pos|flush_and_reload_tracks)$',
'^audio_(ff_rewind|next|prev|play|pause|resume|stop)$',
'^audio_(pre_ff_rewind|ff_rewind|next|prev|play|pause|resume|stop)$',
'^playlist_(amount|add|create|start|resume|shuffle)$',
'^playlist_(sync|resume_track|remove_all_tracks)$',
'^playlist_(insert_track|insert_directory)$',

View file

@ -89,6 +89,10 @@ struct mp3entry* audio_current_track(void)
\description
\see [S[firmware/export/id3.h]]
void audio_pre_ff_rewind(void)
\group playback control
\description prepare playback for rewinding. Playback will be paused
void audio_ff_rewind(long newtime)
\group playback control
\param newtime

View file

@ -61,6 +61,7 @@ size_t audio_buffer_size(void);
/* size of the buffer available for allocating memory from the audio buffer using core_*()
* returns core_available() if audio buffer is not allocated yet */
size_t audio_buffer_available(void);
void audio_pre_ff_rewind(void);
void audio_ff_rewind(long newpos);
void audio_flush_and_reload_tracks(void);
struct mp3entry* audio_current_track(void);