mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
MPEGPlayer: Some UI tweaking and bugfixing
* Allow skip-to-beginning in single-play mode; there is no 3-second delay in that case. * Properly handle and keep track of pauses caused by headphone removal. * Improve skipping over bad files - search in skip direction and allow it to be ended with the stop key. * Add the system message processing done elsewhere to all button queue waits. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28875 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
303aefc406
commit
9b4522bace
5 changed files with 358 additions and 220 deletions
|
@ -162,3 +162,58 @@ void list_enum_items(void **list,
|
||||||
list++; /* Item still there */
|
list++; /* Item still there */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** System events **/
|
||||||
|
static long mpeg_sysevent_id;
|
||||||
|
|
||||||
|
void mpeg_sysevent_clear(void)
|
||||||
|
{
|
||||||
|
mpeg_sysevent_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpeg_sysevent_set(void)
|
||||||
|
{
|
||||||
|
/* Nonzero and won't invoke anything in default event handler */
|
||||||
|
mpeg_sysevent_id = ACTION_STD_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long mpeg_sysevent(void)
|
||||||
|
{
|
||||||
|
return mpeg_sysevent_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mpeg_sysevent_callback(int btn, const struct menu_item_ex *menu)
|
||||||
|
{
|
||||||
|
switch (btn)
|
||||||
|
{
|
||||||
|
case SYS_USB_CONNECTED:
|
||||||
|
case SYS_POWEROFF:
|
||||||
|
mpeg_sysevent_id = btn;
|
||||||
|
return ACTION_STD_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return btn;
|
||||||
|
(void)menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpeg_sysevent_handle(void)
|
||||||
|
{
|
||||||
|
long id = mpeg_sysevent();
|
||||||
|
if (id != 0)
|
||||||
|
rb->default_event_handler(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Buttons **/
|
||||||
|
|
||||||
|
int mpeg_button_get(int timeout)
|
||||||
|
{
|
||||||
|
int button;
|
||||||
|
|
||||||
|
mpeg_sysevent_clear();
|
||||||
|
button = timeout == TIMEOUT_BLOCK ? rb->button_get(true) :
|
||||||
|
rb->button_get_w_tmo(timeout);
|
||||||
|
return mpeg_sysevent_callback(button, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,4 +228,30 @@ void list_enum_items(void **list,
|
||||||
list_enum_callback_t callback,
|
list_enum_callback_t callback,
|
||||||
intptr_t data);
|
intptr_t data);
|
||||||
|
|
||||||
|
|
||||||
|
/** System events **/
|
||||||
|
|
||||||
|
/* Clear event */
|
||||||
|
void mpeg_sysevent_clear(void);
|
||||||
|
|
||||||
|
/* Set to ACTION_STD_CANCEL */
|
||||||
|
void mpeg_sysevent_set(void);
|
||||||
|
|
||||||
|
/* Get event code */
|
||||||
|
long mpeg_sysevent(void);
|
||||||
|
|
||||||
|
/* Call with a system event code and used as menu callback */
|
||||||
|
int mpeg_sysevent_callback(int btn, const struct menu_item_ex *menu);
|
||||||
|
|
||||||
|
/* Handle recorded event */
|
||||||
|
void mpeg_sysevent_handle(void);
|
||||||
|
|
||||||
|
|
||||||
|
/** Buttons **/
|
||||||
|
|
||||||
|
/* Get button codes while remembering important events for later
|
||||||
|
* processing; return of ACTION_STD_CANCEL means plugin should
|
||||||
|
* abort and handle the event */
|
||||||
|
int mpeg_button_get(int timeout);
|
||||||
|
|
||||||
#endif /* MPEG_MISC_H */
|
#endif /* MPEG_MISC_H */
|
||||||
|
|
|
@ -315,39 +315,6 @@ static const struct opt_items globaloff[2] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void mpeg_settings(void);
|
static void mpeg_settings(void);
|
||||||
static long mpeg_menu_sysevent_id;
|
|
||||||
|
|
||||||
void mpeg_menu_sysevent_clear(void)
|
|
||||||
{
|
|
||||||
mpeg_menu_sysevent_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mpeg_menu_sysevent_callback(int btn, const struct menu_item_ex *menu)
|
|
||||||
{
|
|
||||||
switch (btn)
|
|
||||||
{
|
|
||||||
case SYS_USB_CONNECTED:
|
|
||||||
case SYS_POWEROFF:
|
|
||||||
mpeg_menu_sysevent_id = btn;
|
|
||||||
return ACTION_STD_CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return btn;
|
|
||||||
(void)menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
long mpeg_menu_sysevent(void)
|
|
||||||
{
|
|
||||||
return mpeg_menu_sysevent_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mpeg_menu_sysevent_handle(void)
|
|
||||||
{
|
|
||||||
long id = mpeg_menu_sysevent();
|
|
||||||
if (id != 0)
|
|
||||||
rb->default_event_handler(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool mpeg_set_option(const char* string,
|
static bool mpeg_set_option(const char* string,
|
||||||
void* variable,
|
void* variable,
|
||||||
enum optiontype type,
|
enum optiontype type,
|
||||||
|
@ -355,14 +322,14 @@ static bool mpeg_set_option(const char* string,
|
||||||
int numoptions,
|
int numoptions,
|
||||||
void (*function)(int))
|
void (*function)(int))
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
|
|
||||||
/* This eats SYS_POWEROFF - :\ */
|
/* This eats SYS_POWEROFF - :\ */
|
||||||
bool usb = rb->set_option(string, variable, type, options, numoptions,
|
bool usb = rb->set_option(string, variable, type, options, numoptions,
|
||||||
function);
|
function);
|
||||||
|
|
||||||
if (usb)
|
if (usb)
|
||||||
mpeg_menu_sysevent_id = ACTION_STD_CANCEL;
|
mpeg_sysevent_set();
|
||||||
|
|
||||||
return usb;
|
return usb;
|
||||||
}
|
}
|
||||||
|
@ -375,13 +342,13 @@ static bool mpeg_set_int(const char *string, const char *unit,
|
||||||
int max,
|
int max,
|
||||||
const char* (*formatter)(char*, size_t, int, const char*))
|
const char* (*formatter)(char*, size_t, int, const char*))
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
|
|
||||||
bool usb = rb->set_int(string, unit, voice_unit, variable, function,
|
bool usb = rb->set_int(string, unit, voice_unit, variable, function,
|
||||||
step, min, max, formatter);
|
step, min, max, formatter);
|
||||||
|
|
||||||
if (usb)
|
if (usb)
|
||||||
mpeg_menu_sysevent_id = ACTION_STD_CANCEL;
|
mpeg_sysevent_set();
|
||||||
|
|
||||||
return usb;
|
return usb;
|
||||||
}
|
}
|
||||||
|
@ -778,11 +745,7 @@ static int get_start_time(uint32_t duration)
|
||||||
|
|
||||||
while (slider_state < STATE9)
|
while (slider_state < STATE9)
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
button = mpeg_button_get(tmo);
|
||||||
button = tmo == TIMEOUT_BLOCK ?
|
|
||||||
rb->button_get(true) : rb->button_get_w_tmo(tmo);
|
|
||||||
|
|
||||||
button = mpeg_menu_sysevent_callback(button, NULL);
|
|
||||||
|
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
|
@ -922,7 +885,7 @@ static int show_start_menu(uint32_t duration)
|
||||||
char hms_str[32];
|
char hms_str[32];
|
||||||
struct hms hms;
|
struct hms hms;
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_menu_sysevent_callback,
|
MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback,
|
||||||
"Play from beginning", resume_str, "Set start time",
|
"Play from beginning", resume_str, "Set start time",
|
||||||
"Settings", "Quit mpegplayer");
|
"Settings", "Quit mpegplayer");
|
||||||
|
|
||||||
|
@ -935,7 +898,7 @@ static int show_start_menu(uint32_t duration)
|
||||||
|
|
||||||
while (!menu_quit)
|
while (!menu_quit)
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
result = rb->do_menu(&menu, &selected, NULL, false);
|
result = rb->do_menu(&menu, &selected, NULL, false);
|
||||||
|
|
||||||
switch (result)
|
switch (result)
|
||||||
|
@ -972,7 +935,7 @@ static int show_start_menu(uint32_t duration)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpeg_menu_sysevent() != 0)
|
if (mpeg_sysevent() != 0)
|
||||||
{
|
{
|
||||||
result = MPEG_START_QUIT;
|
result = MPEG_START_QUIT;
|
||||||
menu_quit = true;
|
menu_quit = true;
|
||||||
|
@ -985,7 +948,7 @@ static int show_start_menu(uint32_t duration)
|
||||||
/* Return the desired resume action */
|
/* Return the desired resume action */
|
||||||
int mpeg_start_menu(uint32_t duration)
|
int mpeg_start_menu(uint32_t duration)
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
|
|
||||||
switch (settings.resume_options)
|
switch (settings.resume_options)
|
||||||
{
|
{
|
||||||
|
@ -1008,12 +971,12 @@ int mpeg_menu(void)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_menu_sysevent_callback,
|
MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback,
|
||||||
"Settings", "Resume playback", "Quit mpegplayer");
|
"Settings", "Resume playback", "Quit mpegplayer");
|
||||||
|
|
||||||
rb->button_clear_queue();
|
rb->button_clear_queue();
|
||||||
|
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
|
|
||||||
result = rb->do_menu(&menu, NULL, NULL, false);
|
result = rb->do_menu(&menu, NULL, NULL, false);
|
||||||
|
|
||||||
|
@ -1033,7 +996,7 @@ int mpeg_menu(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpeg_menu_sysevent() != 0)
|
if (mpeg_sysevent() != 0)
|
||||||
result = MPEG_MENU_QUIT;
|
result = MPEG_MENU_QUIT;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1045,7 +1008,7 @@ static void display_options(void)
|
||||||
int result;
|
int result;
|
||||||
bool menu_quit = false;
|
bool menu_quit = false;
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu, "Display Options", mpeg_menu_sysevent_callback,
|
MENUITEM_STRINGLIST(menu, "Display Options", mpeg_sysevent_callback,
|
||||||
#if MPEG_OPTION_DITHERING_ENABLED
|
#if MPEG_OPTION_DITHERING_ENABLED
|
||||||
"Dithering",
|
"Dithering",
|
||||||
#endif
|
#endif
|
||||||
|
@ -1059,7 +1022,7 @@ static void display_options(void)
|
||||||
|
|
||||||
while (!menu_quit)
|
while (!menu_quit)
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
result = rb->do_menu(&menu, &selected, NULL, false);
|
result = rb->do_menu(&menu, &selected, NULL, false);
|
||||||
|
|
||||||
switch (result)
|
switch (result)
|
||||||
|
@ -1108,7 +1071,7 @@ static void display_options(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpeg_menu_sysevent() != 0)
|
if (mpeg_sysevent() != 0)
|
||||||
menu_quit = true;
|
menu_quit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1082,7 @@ static void audio_options(void)
|
||||||
int result;
|
int result;
|
||||||
bool menu_quit = false;
|
bool menu_quit = false;
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_menu_sysevent_callback,
|
MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_sysevent_callback,
|
||||||
"Tone Controls", "Channel Modes", "Crossfeed",
|
"Tone Controls", "Channel Modes", "Crossfeed",
|
||||||
"Equalizer", "Dithering");
|
"Equalizer", "Dithering");
|
||||||
|
|
||||||
|
@ -1127,7 +1090,7 @@ static void audio_options(void)
|
||||||
|
|
||||||
while (!menu_quit)
|
while (!menu_quit)
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
result = rb->do_menu(&menu, &selected, NULL, false);
|
result = rb->do_menu(&menu, &selected, NULL, false);
|
||||||
|
|
||||||
switch (result)
|
switch (result)
|
||||||
|
@ -1167,7 +1130,7 @@ static void audio_options(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpeg_menu_sysevent() != 0)
|
if (mpeg_sysevent() != 0)
|
||||||
menu_quit = true;
|
menu_quit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1203,7 +1166,7 @@ static void mpeg_settings(void)
|
||||||
bool menu_quit = false;
|
bool menu_quit = false;
|
||||||
static char clear_str[32];
|
static char clear_str[32];
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu, "Settings", mpeg_menu_sysevent_callback,
|
MENUITEM_STRINGLIST(menu, "Settings", mpeg_sysevent_callback,
|
||||||
"Display Options", "Audio Options",
|
"Display Options", "Audio Options",
|
||||||
"Resume Options", "Play Mode", clear_str);
|
"Resume Options", "Play Mode", clear_str);
|
||||||
|
|
||||||
|
@ -1211,7 +1174,7 @@ static void mpeg_settings(void)
|
||||||
|
|
||||||
while (!menu_quit)
|
while (!menu_quit)
|
||||||
{
|
{
|
||||||
mpeg_menu_sysevent_clear();
|
mpeg_sysevent_clear();
|
||||||
|
|
||||||
/* Format and add resume option to the menu display */
|
/* Format and add resume option to the menu display */
|
||||||
rb->snprintf(clear_str, sizeof(clear_str),
|
rb->snprintf(clear_str, sizeof(clear_str),
|
||||||
|
@ -1247,7 +1210,7 @@ static void mpeg_settings(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpeg_menu_sysevent() != 0)
|
if (mpeg_sysevent() != 0)
|
||||||
menu_quit = true;
|
menu_quit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,11 +102,6 @@ extern struct mpeg_settings settings;
|
||||||
int mpeg_start_menu(uint32_t duration);
|
int mpeg_start_menu(uint32_t duration);
|
||||||
int mpeg_menu(void);
|
int mpeg_menu(void);
|
||||||
|
|
||||||
void mpeg_menu_sysevent_clear(void);
|
|
||||||
long mpeg_menu_sysevent(void);
|
|
||||||
int mpeg_menu_sysevent_callback(int btn, const struct menu_item_ex *menu);
|
|
||||||
void mpeg_menu_sysevent_handle(void);
|
|
||||||
|
|
||||||
void init_settings(const char* filename);
|
void init_settings(const char* filename);
|
||||||
void save_settings(void);
|
void save_settings(void);
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,9 @@ enum osd_bits
|
||||||
OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */
|
OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */
|
||||||
OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */
|
OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */
|
||||||
OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */
|
OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */
|
||||||
OSD_HP_PAUSE = 0x2000,
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
|
OSD_HP_PAUSE = 0x2000, /* OR bitflag - headphones caused pause */
|
||||||
|
#endif
|
||||||
OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */
|
OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */
|
||||||
OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */
|
OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */
|
||||||
};
|
};
|
||||||
|
@ -835,6 +837,18 @@ static void osd_init(void)
|
||||||
osd_text_init();
|
osd_text_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
|
static void osd_set_hp_pause_flag(bool set)
|
||||||
|
{
|
||||||
|
if (set)
|
||||||
|
osd.flags |= OSD_HP_PAUSE;
|
||||||
|
else
|
||||||
|
osd.flags &= ~OSD_HP_PAUSE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define osd_set_hp_pause_flag(set)
|
||||||
|
#endif /* HAVE_HEADPHONE_DETECTION */
|
||||||
|
|
||||||
static void osd_schedule_refresh(unsigned refresh)
|
static void osd_schedule_refresh(unsigned refresh)
|
||||||
{
|
{
|
||||||
long tick = *rb->current_tick;
|
long tick = *rb->current_tick;
|
||||||
|
@ -1213,8 +1227,10 @@ static int osd_get_status(void)
|
||||||
return osd.status & OSD_STATUS_MASK;
|
return osd.status & OSD_STATUS_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;) */
|
/* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;)
|
||||||
static uint32_t osd_ff_rw(int btn, unsigned refresh)
|
* Returns last button code
|
||||||
|
*/
|
||||||
|
static int osd_ff_rw(int btn, unsigned refresh, uint32_t *new_time)
|
||||||
{
|
{
|
||||||
unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step;
|
unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step;
|
||||||
const long ff_rw_accel = (rb->global_settings->ff_rewind_accel + 3);
|
const long ff_rw_accel = (rb->global_settings->ff_rewind_accel + 3);
|
||||||
|
@ -1224,6 +1240,7 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh)
|
||||||
unsigned int max_step = 0;
|
unsigned int max_step = 0;
|
||||||
uint32_t ff_rw_count = 0;
|
uint32_t ff_rw_count = 0;
|
||||||
unsigned status = osd.status;
|
unsigned status = osd.status;
|
||||||
|
int new_btn;
|
||||||
|
|
||||||
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME |
|
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME |
|
||||||
OSD_REFRESH_TIME);
|
OSD_REFRESH_TIME);
|
||||||
|
@ -1239,9 +1256,8 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh)
|
||||||
#ifdef MPEG_RC_FF
|
#ifdef MPEG_RC_FF
|
||||||
case MPEG_RC_FF:
|
case MPEG_RC_FF:
|
||||||
#endif
|
#endif
|
||||||
if (!(btn & BUTTON_REPEAT))
|
osd_set_status(OSD_STATUS_FF);
|
||||||
osd_set_status(OSD_STATUS_FF);
|
new_btn = btn | BUTTON_REPEAT; /* simplify code below */
|
||||||
btn = MPEG_FF | BUTTON_REPEAT; /* simplify code below */
|
|
||||||
break;
|
break;
|
||||||
case MPEG_RW:
|
case MPEG_RW:
|
||||||
#ifdef MPEG_RW2
|
#ifdef MPEG_RW2
|
||||||
|
@ -1250,103 +1266,75 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh)
|
||||||
#ifdef MPEG_RC_RW
|
#ifdef MPEG_RC_RW
|
||||||
case MPEG_RC_RW:
|
case MPEG_RC_RW:
|
||||||
#endif
|
#endif
|
||||||
if (!(btn & BUTTON_REPEAT))
|
osd_set_status(OSD_STATUS_RW);
|
||||||
osd_set_status(OSD_STATUS_RW);
|
new_btn = btn | BUTTON_REPEAT; /* simplify code below */
|
||||||
btn = MPEG_RW | BUTTON_REPEAT; /* simplify code below */
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
btn = -1;
|
new_btn = BUTTON_NONE; /* Fail tests below but still do proper exit */
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
stream_keep_disk_active();
|
stream_keep_disk_active();
|
||||||
|
|
||||||
switch (btn)
|
if (new_btn == (btn | BUTTON_REPEAT)) {
|
||||||
{
|
if (osd.status == OSD_STATUS_FF) {
|
||||||
case BUTTON_NONE:
|
/* fast forwarding, calc max step relative to end */
|
||||||
osd_refresh(OSD_REFRESH_DEFAULT);
|
max_step = muldiv_uint32(duration - (time + ff_rw_count),
|
||||||
break;
|
FF_REWIND_MAX_PERCENT, 100);
|
||||||
|
} else {
|
||||||
|
/* rewinding, calc max step relative to start */
|
||||||
|
max_step = muldiv_uint32(time - ff_rw_count,
|
||||||
|
FF_REWIND_MAX_PERCENT, 100);
|
||||||
|
}
|
||||||
|
|
||||||
case MPEG_FF | BUTTON_REPEAT:
|
max_step = MAX(max_step, MIN_FF_REWIND_STEP);
|
||||||
case MPEG_RW | BUTTON_REPEAT:
|
|
||||||
#ifdef MPEG_FF2
|
|
||||||
case MPEG_FF2 | BUTTON_REPEAT:
|
|
||||||
#endif
|
|
||||||
#ifdef MPEG_RW2
|
|
||||||
case MPEG_RW2 | BUTTON_REPEAT:
|
|
||||||
#endif
|
|
||||||
#ifdef MPEG_RC_FF
|
|
||||||
case MPEG_RC_FF | BUTTON_REPEAT:
|
|
||||||
case MPEG_RC_RW | BUTTON_REPEAT:
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MPEG_FF | BUTTON_REL:
|
if (step > max_step)
|
||||||
case MPEG_RW | BUTTON_REL:
|
step = max_step;
|
||||||
#ifdef MPEG_FF2
|
|
||||||
case MPEG_FF2 | BUTTON_REL:
|
ff_rw_count += step;
|
||||||
#endif
|
|
||||||
#ifdef MPEG_RW2
|
/* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */
|
||||||
case MPEG_RW2 | BUTTON_REL:
|
step += step >> ff_rw_accel;
|
||||||
#endif
|
|
||||||
#ifdef MPEG_RC_FF
|
if (osd.status == OSD_STATUS_FF) {
|
||||||
case MPEG_RC_FF | BUTTON_REL:
|
if (duration - time <= ff_rw_count)
|
||||||
case MPEG_RC_RW | BUTTON_REL:
|
ff_rw_count = duration - time;
|
||||||
#endif
|
|
||||||
if (osd.status == OSD_STATUS_FF)
|
osd.curr_time = time + ff_rw_count;
|
||||||
time += ff_rw_count;
|
} else {
|
||||||
else if (osd.status == OSD_STATUS_RW)
|
if (time <= ff_rw_count)
|
||||||
time -= ff_rw_count;
|
ff_rw_count = time;
|
||||||
|
|
||||||
|
osd.curr_time = time - ff_rw_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
osd_refresh(OSD_REFRESH_TIME);
|
||||||
|
|
||||||
|
new_btn = mpeg_button_get(TIMEOUT_BLOCK);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (new_btn == (btn | BUTTON_REL)) {
|
||||||
|
if (osd.status == OSD_STATUS_FF)
|
||||||
|
time += ff_rw_count;
|
||||||
|
else if (osd.status == OSD_STATUS_RW)
|
||||||
|
time -= ff_rw_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
*new_time = time;
|
||||||
|
|
||||||
/* Fall-through */
|
|
||||||
case -1:
|
|
||||||
default:
|
|
||||||
osd_schedule_refresh(refresh);
|
osd_schedule_refresh(refresh);
|
||||||
osd_set_status(status);
|
osd_set_status(status);
|
||||||
osd_schedule_refresh(OSD_REFRESH_TIME);
|
osd_schedule_refresh(OSD_REFRESH_TIME);
|
||||||
return time;
|
|
||||||
|
return new_btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (osd.status == OSD_STATUS_FF) {
|
|
||||||
/* fast forwarding, calc max step relative to end */
|
|
||||||
max_step = muldiv_uint32(duration - (time + ff_rw_count),
|
|
||||||
FF_REWIND_MAX_PERCENT, 100);
|
|
||||||
} else {
|
|
||||||
/* rewinding, calc max step relative to start */
|
|
||||||
max_step = muldiv_uint32(time - ff_rw_count,
|
|
||||||
FF_REWIND_MAX_PERCENT, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
max_step = MAX(max_step, MIN_FF_REWIND_STEP);
|
|
||||||
|
|
||||||
if (step > max_step)
|
|
||||||
step = max_step;
|
|
||||||
|
|
||||||
ff_rw_count += step;
|
|
||||||
|
|
||||||
/* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */
|
|
||||||
step += step >> ff_rw_accel;
|
|
||||||
|
|
||||||
if (osd.status == OSD_STATUS_FF) {
|
|
||||||
if (duration - time <= ff_rw_count)
|
|
||||||
ff_rw_count = duration - time;
|
|
||||||
|
|
||||||
osd.curr_time = time + ff_rw_count;
|
|
||||||
} else {
|
|
||||||
if (time <= ff_rw_count)
|
|
||||||
ff_rw_count = time;
|
|
||||||
|
|
||||||
osd.curr_time = time - ff_rw_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
osd_refresh(OSD_REFRESH_TIME);
|
|
||||||
|
|
||||||
btn = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int osd_status(void)
|
/* Return adjusted STREAM_* status */
|
||||||
|
static int osd_stream_status(void)
|
||||||
{
|
{
|
||||||
int status = stream_status();
|
int status = stream_status();
|
||||||
|
|
||||||
|
@ -1394,6 +1382,7 @@ static int osd_play(uint32_t time)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
osd_set_hp_pause_flag(false);
|
||||||
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
||||||
|
|
||||||
retval = stream_seek(time, SEEK_SET);
|
retval = stream_seek(time, SEEK_SET);
|
||||||
|
@ -1436,6 +1425,8 @@ static int osd_pause(void)
|
||||||
unsigned refresh = osd.auto_refresh;
|
unsigned refresh = osd.auto_refresh;
|
||||||
int status = osd_halt();
|
int status = osd_halt();
|
||||||
|
|
||||||
|
osd_set_hp_pause_flag(false);
|
||||||
|
|
||||||
if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) {
|
if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) {
|
||||||
/* Resume pending - change to a still video frame update */
|
/* Resume pending - change to a still video frame update */
|
||||||
osd_schedule_refresh(OSD_REFRESH_VIDEO);
|
osd_schedule_refresh(OSD_REFRESH_VIDEO);
|
||||||
|
@ -1454,6 +1445,7 @@ static void osd_resume(void)
|
||||||
{
|
{
|
||||||
/* Cancel video and resume auto refresh - the resyc when starting
|
/* Cancel video and resume auto refresh - the resyc when starting
|
||||||
* playback will perform those tasks */
|
* playback will perform those tasks */
|
||||||
|
osd_set_hp_pause_flag(false);
|
||||||
osd_backlight_on_video_mode(true);
|
osd_backlight_on_video_mode(true);
|
||||||
osd_backlight_brightness_video_mode(true);
|
osd_backlight_brightness_video_mode(true);
|
||||||
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
||||||
|
@ -1466,6 +1458,7 @@ static void osd_stop(void)
|
||||||
{
|
{
|
||||||
uint32_t resume_time;
|
uint32_t resume_time;
|
||||||
|
|
||||||
|
osd_set_hp_pause_flag(false);
|
||||||
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
||||||
osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW);
|
osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW);
|
||||||
osd_show(OSD_HIDE);
|
osd_show(OSD_HIDE);
|
||||||
|
@ -1481,35 +1474,81 @@ static void osd_stop(void)
|
||||||
osd_backlight_brightness_video_mode(false);
|
osd_backlight_brightness_video_mode(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform a seek if seeking is possible for this stream - if playing, a delay
|
/* Perform a seek by button if seeking is possible for this stream.
|
||||||
* will be inserted before restarting in case the user decides to seek again */
|
*
|
||||||
static void osd_seek(int btn)
|
* A delay will be inserted before restarting in case the user decides to
|
||||||
|
* seek again soon after.
|
||||||
|
*
|
||||||
|
* Returns last button code
|
||||||
|
*/
|
||||||
|
static int osd_seek_btn(int btn)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
unsigned refresh;
|
unsigned refresh = 0;
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
|
|
||||||
if (!stream_can_seek())
|
if (!stream_can_seek())
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
/* Halt playback - not strictly nescessary but nice */
|
/* Halt playback - not strictly necessary but nice when doing
|
||||||
|
* buttons */
|
||||||
status = osd_halt();
|
status = osd_halt();
|
||||||
|
|
||||||
if (status == STREAM_STOPPED)
|
if (status == STREAM_STOPPED)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
osd_show(OSD_SHOW);
|
osd_show(OSD_SHOW);
|
||||||
|
|
||||||
|
/* Obtain a new playback point according to the buttons */
|
||||||
if (status == STREAM_PLAYING)
|
if (status == STREAM_PLAYING)
|
||||||
refresh = OSD_REFRESH_RESUME; /* delay resume if playing */
|
refresh = OSD_REFRESH_RESUME; /* delay resume if playing */
|
||||||
else
|
else
|
||||||
refresh = OSD_REFRESH_VIDEO; /* refresh if paused */
|
refresh = OSD_REFRESH_VIDEO; /* refresh if paused */
|
||||||
|
|
||||||
/* Obtain a new playback point */
|
btn = osd_ff_rw(btn, refresh, &time);
|
||||||
time = osd_ff_rw(btn, refresh);
|
|
||||||
|
|
||||||
/* Tell engine to resume at that time */
|
/* Tell engine to resume at that time */
|
||||||
stream_seek(time, SEEK_SET);
|
stream_seek(time, SEEK_SET);
|
||||||
|
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform a seek by time if seeking is possible for this stream
|
||||||
|
*
|
||||||
|
* If playing, the seeking is immediate, otherise a delay is added to showing
|
||||||
|
* a still if paused in case the user does another seek soon after.
|
||||||
|
*
|
||||||
|
* If seeking isn't possible, a time of zero performs a skip to the
|
||||||
|
* beginning.
|
||||||
|
*/
|
||||||
|
static void osd_seek_time(uint32_t time)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
unsigned refresh = 0;
|
||||||
|
|
||||||
|
if (!stream_can_seek() && time != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
stream_wait_status();
|
||||||
|
status = osd_stream_status();
|
||||||
|
|
||||||
|
if (status == STREAM_STOPPED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (status == STREAM_PLAYING) /* merely preserve resume */
|
||||||
|
refresh = osd.auto_refresh & OSD_REFRESH_RESUME;
|
||||||
|
else
|
||||||
|
refresh = OSD_REFRESH_VIDEO; /* refresh if paused */
|
||||||
|
|
||||||
|
/* Cancel print or resume if pending */
|
||||||
|
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
|
||||||
|
|
||||||
|
/* Tell engine to seek to the given time - no state change */
|
||||||
|
stream_seek(time, SEEK_SET);
|
||||||
|
|
||||||
|
osd_update_time();
|
||||||
|
osd_refresh(OSD_REFRESH_TIME);
|
||||||
|
osd_schedule_refresh(refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Has this file one of the supported extensions? */
|
/* Has this file one of the supported extensions? */
|
||||||
|
@ -1537,7 +1576,7 @@ static bool is_videofile(const char* file)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deliver the next/previous video file in the current directory.
|
/* deliver the next/previous video file in the current directory.
|
||||||
returns 0 if there is none. */
|
returns false if there is none. */
|
||||||
static bool get_videofile(int direction, char* videofile, size_t bufsize)
|
static bool get_videofile(int direction, char* videofile, size_t bufsize)
|
||||||
{
|
{
|
||||||
struct tree_context *tree = rb->tree_get_context();
|
struct tree_context *tree = rb->tree_get_context();
|
||||||
|
@ -1583,11 +1622,12 @@ static void osd_handle_phone_plug(bool inserted)
|
||||||
/* Wait for any incomplete state transition to complete first */
|
/* Wait for any incomplete state transition to complete first */
|
||||||
stream_wait_status();
|
stream_wait_status();
|
||||||
|
|
||||||
int status = osd_status();
|
int status = osd_stream_status();
|
||||||
|
|
||||||
if (inserted) {
|
if (inserted) {
|
||||||
if (rb->global_settings->unplug_mode > 1) {
|
if (rb->global_settings->unplug_mode > 1) {
|
||||||
if (status == STREAM_PAUSED) {
|
if (status == STREAM_PAUSED &&
|
||||||
|
(osd.flags & OSD_HP_PAUSE)) {
|
||||||
osd_resume();
|
osd_resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1595,6 +1635,8 @@ static void osd_handle_phone_plug(bool inserted)
|
||||||
if (status == STREAM_PLAYING) {
|
if (status == STREAM_PLAYING) {
|
||||||
osd_pause();
|
osd_pause();
|
||||||
|
|
||||||
|
osd_set_hp_pause_flag(true);
|
||||||
|
|
||||||
if (stream_can_seek() && rb->global_settings->unplug_rw) {
|
if (stream_can_seek() && rb->global_settings->unplug_rw) {
|
||||||
stream_seek(-rb->global_settings->unplug_rw*TS_SECOND,
|
stream_seek(-rb->global_settings->unplug_rw*TS_SECOND,
|
||||||
SEEK_CUR);
|
SEEK_CUR);
|
||||||
|
@ -1635,12 +1677,7 @@ static int button_loop(void)
|
||||||
/* Gently poll the video player for EOS and handle UI */
|
/* Gently poll the video player for EOS and handle UI */
|
||||||
while (stream_status() != STREAM_STOPPED)
|
while (stream_status() != STREAM_STOPPED)
|
||||||
{
|
{
|
||||||
int button;
|
int button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL/2);
|
||||||
|
|
||||||
mpeg_menu_sysevent_clear();
|
|
||||||
button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL/2);
|
|
||||||
|
|
||||||
button = mpeg_menu_sysevent_callback(button, NULL);
|
|
||||||
|
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
|
@ -1761,6 +1798,7 @@ static int button_loop(void)
|
||||||
#endif
|
#endif
|
||||||
case ACTION_STD_CANCEL:
|
case ACTION_STD_CANCEL:
|
||||||
{
|
{
|
||||||
|
cancel_playback:
|
||||||
next_action = VIDEO_STOP;
|
next_action = VIDEO_STOP;
|
||||||
osd_stop();
|
osd_stop();
|
||||||
break;
|
break;
|
||||||
|
@ -1774,7 +1812,7 @@ static int button_loop(void)
|
||||||
case MPEG_RC_PAUSE:
|
case MPEG_RC_PAUSE:
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int status = osd_status();
|
int status = osd_stream_status();
|
||||||
|
|
||||||
if (status == STREAM_PLAYING) {
|
if (status == STREAM_PLAYING) {
|
||||||
/* Playing => Paused */
|
/* Playing => Paused */
|
||||||
|
@ -1789,54 +1827,72 @@ static int button_loop(void)
|
||||||
} /* MPEG_PAUSE*: */
|
} /* MPEG_PAUSE*: */
|
||||||
|
|
||||||
case MPEG_RW:
|
case MPEG_RW:
|
||||||
case MPEG_FF:
|
|
||||||
#ifdef MPEG_RW2
|
#ifdef MPEG_RW2
|
||||||
case MPEG_RW2:
|
case MPEG_RW2:
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MPEG_RC_RW
|
||||||
|
case MPEG_RC_RW:
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int old_button = button;
|
||||||
|
|
||||||
|
/* If button has been released: skip to next/previous file */
|
||||||
|
button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL);
|
||||||
|
|
||||||
|
if ((old_button | BUTTON_REL) == button) {
|
||||||
|
/* Check current playback position */
|
||||||
|
osd_update_time();
|
||||||
|
|
||||||
|
if (settings.play_mode == 0 || osd.curr_time >= 3*TS_SECOND) {
|
||||||
|
/* Start the current video from the beginning */
|
||||||
|
osd_seek_time(0*TS_SECOND);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Release within 3 seconds of start: skip to previous
|
||||||
|
* file */
|
||||||
|
osd_stop();
|
||||||
|
next_action = VIDEO_PREV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((button & ~BUTTON_REPEAT) == old_button) {
|
||||||
|
button = osd_seek_btn(old_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == ACTION_STD_CANCEL)
|
||||||
|
goto cancel_playback; /* jump to stop handling above */
|
||||||
|
|
||||||
|
rb->default_event_handler(button);
|
||||||
|
break;
|
||||||
|
} /* MPEG_RW: */
|
||||||
|
|
||||||
|
case MPEG_FF:
|
||||||
#ifdef MPEG_FF2
|
#ifdef MPEG_FF2
|
||||||
case MPEG_FF2:
|
case MPEG_FF2:
|
||||||
#endif
|
#endif
|
||||||
#ifdef MPEG_RC_RW
|
#ifdef MPEG_RC_FF
|
||||||
case MPEG_RC_RW:
|
|
||||||
case MPEG_RC_FF:
|
case MPEG_RC_FF:
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int old_button = button;
|
int old_button = button;
|
||||||
|
|
||||||
if (settings.play_mode != 0)
|
if (settings.play_mode != 0)
|
||||||
{
|
button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL);
|
||||||
/* if button has been released: skip to next/previous file */
|
|
||||||
button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL);
|
if ((old_button | BUTTON_REL) == button) {
|
||||||
}
|
/* If button has been released: skip to next file */
|
||||||
switch (button)
|
|
||||||
{
|
|
||||||
case MPEG_RW | BUTTON_REL:
|
|
||||||
{
|
|
||||||
/* release within 3 seconds: skip to previous file, else
|
|
||||||
start the current video from the beginning */
|
|
||||||
osd_stop();
|
|
||||||
if ( stream_get_resume_time() > 3*TS_SECOND ) {
|
|
||||||
osd_play(0);
|
|
||||||
osd_show(OSD_SHOW);
|
|
||||||
} else {
|
|
||||||
next_action = VIDEO_PREV;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MPEG_FF | BUTTON_REL:
|
|
||||||
{
|
|
||||||
osd_stop();
|
osd_stop();
|
||||||
next_action = VIDEO_NEXT;
|
next_action = VIDEO_NEXT;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
button = old_button;
|
|
||||||
osd_seek(button);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if ((button & ~BUTTON_REPEAT) == old_button) {
|
||||||
|
button = osd_seek_btn(old_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == ACTION_STD_CANCEL)
|
||||||
|
goto cancel_playback; /* jump to stop handling above */
|
||||||
|
|
||||||
|
rb->default_event_handler(button);
|
||||||
break;
|
break;
|
||||||
} /* MPEG_RW: MPEG_FF: */
|
} /* MPEG_FF: */
|
||||||
|
|
||||||
#ifdef HAVE_HEADPHONE_DETECTION
|
#ifdef HAVE_HEADPHONE_DETECTION
|
||||||
case SYS_PHONE_PLUGGED:
|
case SYS_PHONE_PLUGGED:
|
||||||
|
@ -1849,6 +1905,7 @@ static int button_loop(void)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
osd_refresh(OSD_REFRESH_DEFAULT);
|
||||||
rb->default_event_handler(button);
|
rb->default_event_handler(button);
|
||||||
break;
|
break;
|
||||||
} /* default: */
|
} /* default: */
|
||||||
|
@ -1874,10 +1931,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
{
|
{
|
||||||
static char videofile[MAX_PATH];
|
static char videofile[MAX_PATH];
|
||||||
int status = PLUGIN_OK; /* assume success */
|
int status = PLUGIN_OK; /* assume success */
|
||||||
int result;
|
|
||||||
int err;
|
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
const char *errstring;
|
|
||||||
|
|
||||||
if (parameter == NULL) {
|
if (parameter == NULL) {
|
||||||
/* No file = GTFO */
|
/* No file = GTFO */
|
||||||
|
@ -1904,19 +1958,24 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
DEBUGF("Could not initialize streams\n");
|
DEBUGF("Could not initialize streams\n");
|
||||||
status = PLUGIN_ERROR;
|
status = PLUGIN_ERROR;
|
||||||
} else {
|
} else {
|
||||||
|
int next_action = VIDEO_STOP;
|
||||||
|
bool get_videofile_says = true;
|
||||||
|
|
||||||
while (!quit)
|
while (!quit)
|
||||||
{
|
{
|
||||||
int next_action = VIDEO_STOP;
|
int result;
|
||||||
|
|
||||||
init_settings(videofile);
|
init_settings(videofile);
|
||||||
err = stream_open(videofile);
|
|
||||||
|
|
||||||
if (err >= STREAM_OK) {
|
result = stream_open(videofile);
|
||||||
|
|
||||||
|
if (result >= STREAM_OK) {
|
||||||
/* start menu */
|
/* start menu */
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
result = mpeg_start_menu(stream_get_duration());
|
result = mpeg_start_menu(stream_get_duration());
|
||||||
|
|
||||||
|
next_action = VIDEO_STOP;
|
||||||
if (result != MPEG_START_QUIT) {
|
if (result != MPEG_START_QUIT) {
|
||||||
/* Enter button loop and process UI */
|
/* Enter button loop and process UI */
|
||||||
next_action = button_loop();
|
next_action = button_loop();
|
||||||
|
@ -1928,13 +1987,14 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
|
|
||||||
save_settings();
|
save_settings();
|
||||||
|
|
||||||
mpeg_menu_sysevent_handle();
|
|
||||||
} else {
|
} else {
|
||||||
/* Problem with file; display message about it - not
|
/* Problem with file; display message about it - not
|
||||||
* considered a plugin error */
|
* considered a plugin error */
|
||||||
|
long tick;
|
||||||
|
const char *errstring;
|
||||||
|
|
||||||
DEBUGF("Could not open %s\n", videofile);
|
DEBUGF("Could not open %s\n", videofile);
|
||||||
switch (err)
|
switch (result)
|
||||||
{
|
{
|
||||||
case STREAM_UNSUPPORTED:
|
case STREAM_UNSUPPORTED:
|
||||||
errstring = "Unsupported format";
|
errstring = "Unsupported format";
|
||||||
|
@ -1943,12 +2003,45 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
errstring = "Error opening file: %d";
|
errstring = "Error opening file: %d";
|
||||||
}
|
}
|
||||||
|
|
||||||
rb->splashf(HZ*2, errstring, err);
|
tick = *rb->current_tick + HZ*2;
|
||||||
|
|
||||||
if (settings.play_mode != 0) {
|
rb->splashf(0, errstring, result);
|
||||||
/* Try the next file if the play mode is not single play */
|
|
||||||
next_action = VIDEO_NEXT;
|
/* Be sure it doesn't get stuck in an unbreakable loop of bad
|
||||||
}
|
* files, just in case! Otherwise, keep searching in the
|
||||||
|
* chosen direction until a good one is found. */
|
||||||
|
while (!quit && TIME_BEFORE(*rb->current_tick, tick))
|
||||||
|
{
|
||||||
|
int button = mpeg_button_get(HZ*2);
|
||||||
|
|
||||||
|
switch (button)
|
||||||
|
{
|
||||||
|
case MPEG_STOP:
|
||||||
|
case ACTION_STD_CANCEL:
|
||||||
|
/* Abort the search and exit */
|
||||||
|
next_action = VIDEO_STOP;
|
||||||
|
quit = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTON_NONE:
|
||||||
|
if (settings.play_mode != 0) {
|
||||||
|
if (next_action == VIDEO_STOP) {
|
||||||
|
/* Default to next file */
|
||||||
|
next_action = VIDEO_NEXT;
|
||||||
|
}
|
||||||
|
else if (next_action == VIDEO_PREV &&
|
||||||
|
!get_videofile_says) {
|
||||||
|
/* Was first file already; avoid endlessly
|
||||||
|
* retrying it */
|
||||||
|
next_action = VIDEO_STOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rb->default_event_handler(button);
|
||||||
|
} /* switch */
|
||||||
|
} /* while */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return value of button_loop says, what's next */
|
/* return value of button_loop says, what's next */
|
||||||
|
@ -1956,15 +2049,16 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
{
|
{
|
||||||
case VIDEO_NEXT:
|
case VIDEO_NEXT:
|
||||||
{
|
{
|
||||||
if (!get_videofile(VIDEO_NEXT, videofile, sizeof(videofile))) {
|
get_videofile_says = get_videofile(VIDEO_NEXT, videofile,
|
||||||
/* quit after finished the last videofile */
|
sizeof(videofile));
|
||||||
quit = true;
|
/* quit after finished the last videofile */
|
||||||
}
|
quit = !get_videofile_says;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VIDEO_PREV:
|
case VIDEO_PREV:
|
||||||
{
|
{
|
||||||
get_videofile(VIDEO_PREV, videofile, sizeof(videofile));
|
get_videofile_says = get_videofile(VIDEO_PREV, videofile,
|
||||||
|
sizeof(videofile));
|
||||||
/* if there is no previous file, play the same videofile */
|
/* if there is no previous file, play the same videofile */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1974,7 +2068,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} /* while */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV)
|
#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV)
|
||||||
|
@ -1984,5 +2078,10 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
stream_exit();
|
stream_exit();
|
||||||
|
|
||||||
rb->talk_disable(false);
|
rb->talk_disable(false);
|
||||||
|
|
||||||
|
/* Actually handle delayed processing of system events of interest
|
||||||
|
* that were captured in other button loops */
|
||||||
|
mpeg_sysevent_handle();
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue