diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-12-22 11:20:07 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-12-22 11:20:07 +0000 |
commit | 9b4522bacec8cf1eb8ff69684cf959c0bb732c0d (patch) | |
tree | a939f4cd549f7def0feed75d9d5728a213bd5c22 | |
parent | 303aefc406a99cb47f41ed39283a3881f4c7f401 (diff) | |
download | rockbox-9b4522bacec8cf1eb8ff69684cf959c0bb732c0d.tar.gz rockbox-9b4522bacec8cf1eb8ff69684cf959c0bb732c0d.zip |
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
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_misc.c | 55 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_misc.h | 26 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.c | 79 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.h | 5 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpegplayer.c | 403 |
5 files changed, 353 insertions, 215 deletions
diff --git a/apps/plugins/mpegplayer/mpeg_misc.c b/apps/plugins/mpegplayer/mpeg_misc.c index e201aa69c7..d9e033322e 100644 --- a/apps/plugins/mpegplayer/mpeg_misc.c +++ b/apps/plugins/mpegplayer/mpeg_misc.c | |||
@@ -162,3 +162,58 @@ void list_enum_items(void **list, | |||
162 | list++; /* Item still there */ | 162 | list++; /* Item still there */ |
163 | } | 163 | } |
164 | } | 164 | } |
165 | |||
166 | |||
167 | /** System events **/ | ||
168 | static long mpeg_sysevent_id; | ||
169 | |||
170 | void mpeg_sysevent_clear(void) | ||
171 | { | ||
172 | mpeg_sysevent_id = 0; | ||
173 | } | ||
174 | |||
175 | void mpeg_sysevent_set(void) | ||
176 | { | ||
177 | /* Nonzero and won't invoke anything in default event handler */ | ||
178 | mpeg_sysevent_id = ACTION_STD_CANCEL; | ||
179 | } | ||
180 | |||
181 | long mpeg_sysevent(void) | ||
182 | { | ||
183 | return mpeg_sysevent_id; | ||
184 | } | ||
185 | |||
186 | int mpeg_sysevent_callback(int btn, const struct menu_item_ex *menu) | ||
187 | { | ||
188 | switch (btn) | ||
189 | { | ||
190 | case SYS_USB_CONNECTED: | ||
191 | case SYS_POWEROFF: | ||
192 | mpeg_sysevent_id = btn; | ||
193 | return ACTION_STD_CANCEL; | ||
194 | } | ||
195 | |||
196 | return btn; | ||
197 | (void)menu; | ||
198 | } | ||
199 | |||
200 | void mpeg_sysevent_handle(void) | ||
201 | { | ||
202 | long id = mpeg_sysevent(); | ||
203 | if (id != 0) | ||
204 | rb->default_event_handler(id); | ||
205 | } | ||
206 | |||
207 | |||
208 | /** Buttons **/ | ||
209 | |||
210 | int mpeg_button_get(int timeout) | ||
211 | { | ||
212 | int button; | ||
213 | |||
214 | mpeg_sysevent_clear(); | ||
215 | button = timeout == TIMEOUT_BLOCK ? rb->button_get(true) : | ||
216 | rb->button_get_w_tmo(timeout); | ||
217 | return mpeg_sysevent_callback(button, NULL); | ||
218 | } | ||
219 | |||
diff --git a/apps/plugins/mpegplayer/mpeg_misc.h b/apps/plugins/mpegplayer/mpeg_misc.h index c36f4faddc..6996f27987 100644 --- a/apps/plugins/mpegplayer/mpeg_misc.h +++ b/apps/plugins/mpegplayer/mpeg_misc.h | |||
@@ -228,4 +228,30 @@ void list_enum_items(void **list, | |||
228 | list_enum_callback_t callback, | 228 | list_enum_callback_t callback, |
229 | intptr_t data); | 229 | intptr_t data); |
230 | 230 | ||
231 | |||
232 | /** System events **/ | ||
233 | |||
234 | /* Clear event */ | ||
235 | void mpeg_sysevent_clear(void); | ||
236 | |||
237 | /* Set to ACTION_STD_CANCEL */ | ||
238 | void mpeg_sysevent_set(void); | ||
239 | |||
240 | /* Get event code */ | ||
241 | long mpeg_sysevent(void); | ||
242 | |||
243 | /* Call with a system event code and used as menu callback */ | ||
244 | int mpeg_sysevent_callback(int btn, const struct menu_item_ex *menu); | ||
245 | |||
246 | /* Handle recorded event */ | ||
247 | void mpeg_sysevent_handle(void); | ||
248 | |||
249 | |||
250 | /** Buttons **/ | ||
251 | |||
252 | /* Get button codes while remembering important events for later | ||
253 | * processing; return of ACTION_STD_CANCEL means plugin should | ||
254 | * abort and handle the event */ | ||
255 | int mpeg_button_get(int timeout); | ||
256 | |||
231 | #endif /* MPEG_MISC_H */ | 257 | #endif /* MPEG_MISC_H */ |
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 3daba2c928..f84a30ddfe 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c | |||
@@ -315,39 +315,6 @@ static const struct opt_items globaloff[2] = { | |||
315 | #endif | 315 | #endif |
316 | 316 | ||
317 | static void mpeg_settings(void); | 317 | static void mpeg_settings(void); |
318 | static long mpeg_menu_sysevent_id; | ||
319 | |||
320 | void mpeg_menu_sysevent_clear(void) | ||
321 | { | ||
322 | mpeg_menu_sysevent_id = 0; | ||
323 | } | ||
324 | |||
325 | int mpeg_menu_sysevent_callback(int btn, const struct menu_item_ex *menu) | ||
326 | { | ||
327 | switch (btn) | ||
328 | { | ||
329 | case SYS_USB_CONNECTED: | ||
330 | case SYS_POWEROFF: | ||
331 | mpeg_menu_sysevent_id = btn; | ||
332 | return ACTION_STD_CANCEL; | ||
333 | } | ||
334 | |||
335 | return btn; | ||
336 | (void)menu; | ||
337 | } | ||
338 | |||
339 | long mpeg_menu_sysevent(void) | ||
340 | { | ||
341 | return mpeg_menu_sysevent_id; | ||
342 | } | ||
343 | |||
344 | void mpeg_menu_sysevent_handle(void) | ||
345 | { | ||
346 | long id = mpeg_menu_sysevent(); | ||
347 | if (id != 0) | ||
348 | rb->default_event_handler(id); | ||
349 | } | ||
350 | |||
351 | static bool mpeg_set_option(const char* string, | 318 | static bool mpeg_set_option(const char* string, |
352 | void* variable, | 319 | void* variable, |
353 | enum optiontype type, | 320 | enum optiontype type, |
@@ -355,14 +322,14 @@ static bool mpeg_set_option(const char* string, | |||
355 | int numoptions, | 322 | int numoptions, |
356 | void (*function)(int)) | 323 | void (*function)(int)) |
357 | { | 324 | { |
358 | mpeg_menu_sysevent_clear(); | 325 | mpeg_sysevent_clear(); |
359 | 326 | ||
360 | /* This eats SYS_POWEROFF - :\ */ | 327 | /* This eats SYS_POWEROFF - :\ */ |
361 | bool usb = rb->set_option(string, variable, type, options, numoptions, | 328 | bool usb = rb->set_option(string, variable, type, options, numoptions, |
362 | function); | 329 | function); |
363 | 330 | ||
364 | if (usb) | 331 | if (usb) |
365 | mpeg_menu_sysevent_id = ACTION_STD_CANCEL; | 332 | mpeg_sysevent_set(); |
366 | 333 | ||
367 | return usb; | 334 | return usb; |
368 | } | 335 | } |
@@ -375,13 +342,13 @@ static bool mpeg_set_int(const char *string, const char *unit, | |||
375 | int max, | 342 | int max, |
376 | const char* (*formatter)(char*, size_t, int, const char*)) | 343 | const char* (*formatter)(char*, size_t, int, const char*)) |
377 | { | 344 | { |
378 | mpeg_menu_sysevent_clear(); | 345 | mpeg_sysevent_clear(); |
379 | 346 | ||
380 | bool usb = rb->set_int(string, unit, voice_unit, variable, function, | 347 | bool usb = rb->set_int(string, unit, voice_unit, variable, function, |
381 | step, min, max, formatter); | 348 | step, min, max, formatter); |
382 | 349 | ||
383 | if (usb) | 350 | if (usb) |
384 | mpeg_menu_sysevent_id = ACTION_STD_CANCEL; | 351 | mpeg_sysevent_set(); |
385 | 352 | ||
386 | return usb; | 353 | return usb; |
387 | } | 354 | } |
@@ -778,11 +745,7 @@ static int get_start_time(uint32_t duration) | |||
778 | 745 | ||
779 | while (slider_state < STATE9) | 746 | while (slider_state < STATE9) |
780 | { | 747 | { |
781 | mpeg_menu_sysevent_clear(); | 748 | button = mpeg_button_get(tmo); |
782 | button = tmo == TIMEOUT_BLOCK ? | ||
783 | rb->button_get(true) : rb->button_get_w_tmo(tmo); | ||
784 | |||
785 | button = mpeg_menu_sysevent_callback(button, NULL); | ||
786 | 749 | ||
787 | switch (button) | 750 | switch (button) |
788 | { | 751 | { |
@@ -922,7 +885,7 @@ static int show_start_menu(uint32_t duration) | |||
922 | char hms_str[32]; | 885 | char hms_str[32]; |
923 | struct hms hms; | 886 | struct hms hms; |
924 | 887 | ||
925 | MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_menu_sysevent_callback, | 888 | MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, |
926 | "Play from beginning", resume_str, "Set start time", | 889 | "Play from beginning", resume_str, "Set start time", |
927 | "Settings", "Quit mpegplayer"); | 890 | "Settings", "Quit mpegplayer"); |
928 | 891 | ||
@@ -935,7 +898,7 @@ static int show_start_menu(uint32_t duration) | |||
935 | 898 | ||
936 | while (!menu_quit) | 899 | while (!menu_quit) |
937 | { | 900 | { |
938 | mpeg_menu_sysevent_clear(); | 901 | mpeg_sysevent_clear(); |
939 | result = rb->do_menu(&menu, &selected, NULL, false); | 902 | result = rb->do_menu(&menu, &selected, NULL, false); |
940 | 903 | ||
941 | switch (result) | 904 | switch (result) |
@@ -972,7 +935,7 @@ static int show_start_menu(uint32_t duration) | |||
972 | break; | 935 | break; |
973 | } | 936 | } |
974 | 937 | ||
975 | if (mpeg_menu_sysevent() != 0) | 938 | if (mpeg_sysevent() != 0) |
976 | { | 939 | { |
977 | result = MPEG_START_QUIT; | 940 | result = MPEG_START_QUIT; |
978 | menu_quit = true; | 941 | menu_quit = true; |
@@ -985,7 +948,7 @@ static int show_start_menu(uint32_t duration) | |||
985 | /* Return the desired resume action */ | 948 | /* Return the desired resume action */ |
986 | int mpeg_start_menu(uint32_t duration) | 949 | int mpeg_start_menu(uint32_t duration) |
987 | { | 950 | { |
988 | mpeg_menu_sysevent_clear(); | 951 | mpeg_sysevent_clear(); |
989 | 952 | ||
990 | switch (settings.resume_options) | 953 | switch (settings.resume_options) |
991 | { | 954 | { |
@@ -1008,12 +971,12 @@ int mpeg_menu(void) | |||
1008 | { | 971 | { |
1009 | int result; | 972 | int result; |
1010 | 973 | ||
1011 | MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_menu_sysevent_callback, | 974 | MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, |
1012 | "Settings", "Resume playback", "Quit mpegplayer"); | 975 | "Settings", "Resume playback", "Quit mpegplayer"); |
1013 | 976 | ||
1014 | rb->button_clear_queue(); | 977 | rb->button_clear_queue(); |
1015 | 978 | ||
1016 | mpeg_menu_sysevent_clear(); | 979 | mpeg_sysevent_clear(); |
1017 | 980 | ||
1018 | result = rb->do_menu(&menu, NULL, NULL, false); | 981 | result = rb->do_menu(&menu, NULL, NULL, false); |
1019 | 982 | ||
@@ -1033,7 +996,7 @@ int mpeg_menu(void) | |||
1033 | break; | 996 | break; |
1034 | } | 997 | } |
1035 | 998 | ||
1036 | if (mpeg_menu_sysevent() != 0) | 999 | if (mpeg_sysevent() != 0) |
1037 | result = MPEG_MENU_QUIT; | 1000 | result = MPEG_MENU_QUIT; |
1038 | 1001 | ||
1039 | return result; | 1002 | return result; |
@@ -1045,7 +1008,7 @@ static void display_options(void) | |||
1045 | int result; | 1008 | int result; |
1046 | bool menu_quit = false; | 1009 | bool menu_quit = false; |
1047 | 1010 | ||
1048 | MENUITEM_STRINGLIST(menu, "Display Options", mpeg_menu_sysevent_callback, | 1011 | MENUITEM_STRINGLIST(menu, "Display Options", mpeg_sysevent_callback, |
1049 | #if MPEG_OPTION_DITHERING_ENABLED | 1012 | #if MPEG_OPTION_DITHERING_ENABLED |
1050 | "Dithering", | 1013 | "Dithering", |
1051 | #endif | 1014 | #endif |
@@ -1059,7 +1022,7 @@ static void display_options(void) | |||
1059 | 1022 | ||
1060 | while (!menu_quit) | 1023 | while (!menu_quit) |
1061 | { | 1024 | { |
1062 | mpeg_menu_sysevent_clear(); | 1025 | mpeg_sysevent_clear(); |
1063 | result = rb->do_menu(&menu, &selected, NULL, false); | 1026 | result = rb->do_menu(&menu, &selected, NULL, false); |
1064 | 1027 | ||
1065 | switch (result) | 1028 | switch (result) |
@@ -1108,7 +1071,7 @@ static void display_options(void) | |||
1108 | break; | 1071 | break; |
1109 | } | 1072 | } |
1110 | 1073 | ||
1111 | if (mpeg_menu_sysevent() != 0) | 1074 | if (mpeg_sysevent() != 0) |
1112 | menu_quit = true; | 1075 | menu_quit = true; |
1113 | } | 1076 | } |
1114 | } | 1077 | } |
@@ -1119,7 +1082,7 @@ static void audio_options(void) | |||
1119 | int result; | 1082 | int result; |
1120 | bool menu_quit = false; | 1083 | bool menu_quit = false; |
1121 | 1084 | ||
1122 | MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_menu_sysevent_callback, | 1085 | MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_sysevent_callback, |
1123 | "Tone Controls", "Channel Modes", "Crossfeed", | 1086 | "Tone Controls", "Channel Modes", "Crossfeed", |
1124 | "Equalizer", "Dithering"); | 1087 | "Equalizer", "Dithering"); |
1125 | 1088 | ||
@@ -1127,7 +1090,7 @@ static void audio_options(void) | |||
1127 | 1090 | ||
1128 | while (!menu_quit) | 1091 | while (!menu_quit) |
1129 | { | 1092 | { |
1130 | mpeg_menu_sysevent_clear(); | 1093 | mpeg_sysevent_clear(); |
1131 | result = rb->do_menu(&menu, &selected, NULL, false); | 1094 | result = rb->do_menu(&menu, &selected, NULL, false); |
1132 | 1095 | ||
1133 | switch (result) | 1096 | switch (result) |
@@ -1167,7 +1130,7 @@ static void audio_options(void) | |||
1167 | break; | 1130 | break; |
1168 | } | 1131 | } |
1169 | 1132 | ||
1170 | if (mpeg_menu_sysevent() != 0) | 1133 | if (mpeg_sysevent() != 0) |
1171 | menu_quit = true; | 1134 | menu_quit = true; |
1172 | } | 1135 | } |
1173 | } | 1136 | } |
@@ -1203,7 +1166,7 @@ static void mpeg_settings(void) | |||
1203 | bool menu_quit = false; | 1166 | bool menu_quit = false; |
1204 | static char clear_str[32]; | 1167 | static char clear_str[32]; |
1205 | 1168 | ||
1206 | MENUITEM_STRINGLIST(menu, "Settings", mpeg_menu_sysevent_callback, | 1169 | MENUITEM_STRINGLIST(menu, "Settings", mpeg_sysevent_callback, |
1207 | "Display Options", "Audio Options", | 1170 | "Display Options", "Audio Options", |
1208 | "Resume Options", "Play Mode", clear_str); | 1171 | "Resume Options", "Play Mode", clear_str); |
1209 | 1172 | ||
@@ -1211,7 +1174,7 @@ static void mpeg_settings(void) | |||
1211 | 1174 | ||
1212 | while (!menu_quit) | 1175 | while (!menu_quit) |
1213 | { | 1176 | { |
1214 | mpeg_menu_sysevent_clear(); | 1177 | mpeg_sysevent_clear(); |
1215 | 1178 | ||
1216 | /* Format and add resume option to the menu display */ | 1179 | /* Format and add resume option to the menu display */ |
1217 | rb->snprintf(clear_str, sizeof(clear_str), | 1180 | rb->snprintf(clear_str, sizeof(clear_str), |
@@ -1247,7 +1210,7 @@ static void mpeg_settings(void) | |||
1247 | break; | 1210 | break; |
1248 | } | 1211 | } |
1249 | 1212 | ||
1250 | if (mpeg_menu_sysevent() != 0) | 1213 | if (mpeg_sysevent() != 0) |
1251 | menu_quit = true; | 1214 | menu_quit = true; |
1252 | } | 1215 | } |
1253 | } | 1216 | } |
diff --git a/apps/plugins/mpegplayer/mpeg_settings.h b/apps/plugins/mpegplayer/mpeg_settings.h index 0910116615..6287f664d3 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.h +++ b/apps/plugins/mpegplayer/mpeg_settings.h | |||
@@ -102,11 +102,6 @@ extern struct mpeg_settings settings; | |||
102 | int mpeg_start_menu(uint32_t duration); | 102 | int mpeg_start_menu(uint32_t duration); |
103 | int mpeg_menu(void); | 103 | int mpeg_menu(void); |
104 | 104 | ||
105 | void mpeg_menu_sysevent_clear(void); | ||
106 | long mpeg_menu_sysevent(void); | ||
107 | int mpeg_menu_sysevent_callback(int btn, const struct menu_item_ex *menu); | ||
108 | void mpeg_menu_sysevent_handle(void); | ||
109 | |||
110 | void init_settings(const char* filename); | 105 | void init_settings(const char* filename); |
111 | void save_settings(void); | 106 | void save_settings(void); |
112 | 107 | ||
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 7a2b457aec..d21907f607 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c | |||
@@ -412,7 +412,9 @@ enum osd_bits | |||
412 | OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */ | 412 | OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */ |
413 | OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */ | 413 | OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */ |
414 | OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */ | 414 | OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */ |
415 | OSD_HP_PAUSE = 0x2000, | 415 | #ifdef HAVE_HEADPHONE_DETECTION |
416 | OSD_HP_PAUSE = 0x2000, /* OR bitflag - headphones caused pause */ | ||
417 | #endif | ||
416 | OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */ | 418 | OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */ |
417 | OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */ | 419 | OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */ |
418 | }; | 420 | }; |
@@ -835,6 +837,18 @@ static void osd_init(void) | |||
835 | osd_text_init(); | 837 | osd_text_init(); |
836 | } | 838 | } |
837 | 839 | ||
840 | #ifdef HAVE_HEADPHONE_DETECTION | ||
841 | static void osd_set_hp_pause_flag(bool set) | ||
842 | { | ||
843 | if (set) | ||
844 | osd.flags |= OSD_HP_PAUSE; | ||
845 | else | ||
846 | osd.flags &= ~OSD_HP_PAUSE; | ||
847 | } | ||
848 | #else | ||
849 | #define osd_set_hp_pause_flag(set) | ||
850 | #endif /* HAVE_HEADPHONE_DETECTION */ | ||
851 | |||
838 | static void osd_schedule_refresh(unsigned refresh) | 852 | static void osd_schedule_refresh(unsigned refresh) |
839 | { | 853 | { |
840 | long tick = *rb->current_tick; | 854 | long tick = *rb->current_tick; |
@@ -1213,8 +1227,10 @@ static int osd_get_status(void) | |||
1213 | return osd.status & OSD_STATUS_MASK; | 1227 | return osd.status & OSD_STATUS_MASK; |
1214 | } | 1228 | } |
1215 | 1229 | ||
1216 | /* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;) */ | 1230 | /* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;) |
1217 | static uint32_t osd_ff_rw(int btn, unsigned refresh) | 1231 | * Returns last button code |
1232 | */ | ||
1233 | static int osd_ff_rw(int btn, unsigned refresh, uint32_t *new_time) | ||
1218 | { | 1234 | { |
1219 | unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step; | 1235 | unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step; |
1220 | const long ff_rw_accel = (rb->global_settings->ff_rewind_accel + 3); | 1236 | 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) | |||
1224 | unsigned int max_step = 0; | 1240 | unsigned int max_step = 0; |
1225 | uint32_t ff_rw_count = 0; | 1241 | uint32_t ff_rw_count = 0; |
1226 | unsigned status = osd.status; | 1242 | unsigned status = osd.status; |
1243 | int new_btn; | ||
1227 | 1244 | ||
1228 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME | | 1245 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME | |
1229 | OSD_REFRESH_TIME); | 1246 | OSD_REFRESH_TIME); |
@@ -1239,9 +1256,8 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh) | |||
1239 | #ifdef MPEG_RC_FF | 1256 | #ifdef MPEG_RC_FF |
1240 | case MPEG_RC_FF: | 1257 | case MPEG_RC_FF: |
1241 | #endif | 1258 | #endif |
1242 | if (!(btn & BUTTON_REPEAT)) | 1259 | osd_set_status(OSD_STATUS_FF); |
1243 | osd_set_status(OSD_STATUS_FF); | 1260 | new_btn = btn | BUTTON_REPEAT; /* simplify code below */ |
1244 | btn = MPEG_FF | BUTTON_REPEAT; /* simplify code below */ | ||
1245 | break; | 1261 | break; |
1246 | case MPEG_RW: | 1262 | case MPEG_RW: |
1247 | #ifdef MPEG_RW2 | 1263 | #ifdef MPEG_RW2 |
@@ -1250,103 +1266,75 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh) | |||
1250 | #ifdef MPEG_RC_RW | 1266 | #ifdef MPEG_RC_RW |
1251 | case MPEG_RC_RW: | 1267 | case MPEG_RC_RW: |
1252 | #endif | 1268 | #endif |
1253 | if (!(btn & BUTTON_REPEAT)) | 1269 | osd_set_status(OSD_STATUS_RW); |
1254 | osd_set_status(OSD_STATUS_RW); | 1270 | new_btn = btn | BUTTON_REPEAT; /* simplify code below */ |
1255 | btn = MPEG_RW | BUTTON_REPEAT; /* simplify code below */ | ||
1256 | break; | 1271 | break; |
1257 | default: | 1272 | default: |
1258 | btn = -1; | 1273 | new_btn = BUTTON_NONE; /* Fail tests below but still do proper exit */ |
1259 | } | 1274 | } |
1260 | 1275 | ||
1261 | while (1) | 1276 | while (1) |
1262 | { | 1277 | { |
1263 | stream_keep_disk_active(); | 1278 | stream_keep_disk_active(); |
1264 | 1279 | ||
1265 | switch (btn) | 1280 | if (new_btn == (btn | BUTTON_REPEAT)) { |
1266 | { | 1281 | if (osd.status == OSD_STATUS_FF) { |
1267 | case BUTTON_NONE: | 1282 | /* fast forwarding, calc max step relative to end */ |
1268 | osd_refresh(OSD_REFRESH_DEFAULT); | 1283 | max_step = muldiv_uint32(duration - (time + ff_rw_count), |
1269 | break; | 1284 | FF_REWIND_MAX_PERCENT, 100); |
1270 | 1285 | } else { | |
1271 | case MPEG_FF | BUTTON_REPEAT: | 1286 | /* rewinding, calc max step relative to start */ |
1272 | case MPEG_RW | BUTTON_REPEAT: | 1287 | max_step = muldiv_uint32(time - ff_rw_count, |
1273 | #ifdef MPEG_FF2 | 1288 | FF_REWIND_MAX_PERCENT, 100); |
1274 | case MPEG_FF2 | BUTTON_REPEAT: | 1289 | } |
1275 | #endif | ||
1276 | #ifdef MPEG_RW2 | ||
1277 | case MPEG_RW2 | BUTTON_REPEAT: | ||
1278 | #endif | ||
1279 | #ifdef MPEG_RC_FF | ||
1280 | case MPEG_RC_FF | BUTTON_REPEAT: | ||
1281 | case MPEG_RC_RW | BUTTON_REPEAT: | ||
1282 | #endif | ||
1283 | break; | ||
1284 | 1290 | ||
1285 | case MPEG_FF | BUTTON_REL: | 1291 | max_step = MAX(max_step, MIN_FF_REWIND_STEP); |
1286 | case MPEG_RW | BUTTON_REL: | ||
1287 | #ifdef MPEG_FF2 | ||
1288 | case MPEG_FF2 | BUTTON_REL: | ||
1289 | #endif | ||
1290 | #ifdef MPEG_RW2 | ||
1291 | case MPEG_RW2 | BUTTON_REL: | ||
1292 | #endif | ||
1293 | #ifdef MPEG_RC_FF | ||
1294 | case MPEG_RC_FF | BUTTON_REL: | ||
1295 | case MPEG_RC_RW | BUTTON_REL: | ||
1296 | #endif | ||
1297 | if (osd.status == OSD_STATUS_FF) | ||
1298 | time += ff_rw_count; | ||
1299 | else if (osd.status == OSD_STATUS_RW) | ||
1300 | time -= ff_rw_count; | ||
1301 | 1292 | ||
1302 | /* Fall-through */ | 1293 | if (step > max_step) |
1303 | case -1: | 1294 | step = max_step; |
1304 | default: | ||
1305 | osd_schedule_refresh(refresh); | ||
1306 | osd_set_status(status); | ||
1307 | osd_schedule_refresh(OSD_REFRESH_TIME); | ||
1308 | return time; | ||
1309 | } | ||
1310 | 1295 | ||
1311 | if (osd.status == OSD_STATUS_FF) { | 1296 | ff_rw_count += step; |
1312 | /* fast forwarding, calc max step relative to end */ | ||
1313 | max_step = muldiv_uint32(duration - (time + ff_rw_count), | ||
1314 | FF_REWIND_MAX_PERCENT, 100); | ||
1315 | } else { | ||
1316 | /* rewinding, calc max step relative to start */ | ||
1317 | max_step = muldiv_uint32(time - ff_rw_count, | ||
1318 | FF_REWIND_MAX_PERCENT, 100); | ||
1319 | } | ||
1320 | 1297 | ||
1321 | max_step = MAX(max_step, MIN_FF_REWIND_STEP); | 1298 | /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */ |
1299 | step += step >> ff_rw_accel; | ||
1322 | 1300 | ||
1323 | if (step > max_step) | 1301 | if (osd.status == OSD_STATUS_FF) { |
1324 | step = max_step; | 1302 | if (duration - time <= ff_rw_count) |
1303 | ff_rw_count = duration - time; | ||
1325 | 1304 | ||
1326 | ff_rw_count += step; | 1305 | osd.curr_time = time + ff_rw_count; |
1306 | } else { | ||
1307 | if (time <= ff_rw_count) | ||
1308 | ff_rw_count = time; | ||
1327 | 1309 | ||
1328 | /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */ | 1310 | osd.curr_time = time - ff_rw_count; |
1329 | step += step >> ff_rw_accel; | 1311 | } |
1330 | 1312 | ||
1331 | if (osd.status == OSD_STATUS_FF) { | 1313 | osd_refresh(OSD_REFRESH_TIME); |
1332 | if (duration - time <= ff_rw_count) | ||
1333 | ff_rw_count = duration - time; | ||
1334 | 1314 | ||
1335 | osd.curr_time = time + ff_rw_count; | 1315 | new_btn = mpeg_button_get(TIMEOUT_BLOCK); |
1336 | } else { | ||
1337 | if (time <= ff_rw_count) | ||
1338 | ff_rw_count = time; | ||
1339 | |||
1340 | osd.curr_time = time - ff_rw_count; | ||
1341 | } | 1316 | } |
1317 | else { | ||
1318 | if (new_btn == (btn | BUTTON_REL)) { | ||
1319 | if (osd.status == OSD_STATUS_FF) | ||
1320 | time += ff_rw_count; | ||
1321 | else if (osd.status == OSD_STATUS_RW) | ||
1322 | time -= ff_rw_count; | ||
1323 | } | ||
1342 | 1324 | ||
1343 | osd_refresh(OSD_REFRESH_TIME); | 1325 | *new_time = time; |
1326 | |||
1327 | osd_schedule_refresh(refresh); | ||
1328 | osd_set_status(status); | ||
1329 | osd_schedule_refresh(OSD_REFRESH_TIME); | ||
1344 | 1330 | ||
1345 | btn = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL); | 1331 | return new_btn; |
1332 | } | ||
1346 | } | 1333 | } |
1347 | } | 1334 | } |
1348 | 1335 | ||
1349 | static int osd_status(void) | 1336 | /* Return adjusted STREAM_* status */ |
1337 | static int osd_stream_status(void) | ||
1350 | { | 1338 | { |
1351 | int status = stream_status(); | 1339 | int status = stream_status(); |
1352 | 1340 | ||
@@ -1394,6 +1382,7 @@ static int osd_play(uint32_t time) | |||
1394 | { | 1382 | { |
1395 | int retval; | 1383 | int retval; |
1396 | 1384 | ||
1385 | osd_set_hp_pause_flag(false); | ||
1397 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); | 1386 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); |
1398 | 1387 | ||
1399 | retval = stream_seek(time, SEEK_SET); | 1388 | retval = stream_seek(time, SEEK_SET); |
@@ -1436,6 +1425,8 @@ static int osd_pause(void) | |||
1436 | unsigned refresh = osd.auto_refresh; | 1425 | unsigned refresh = osd.auto_refresh; |
1437 | int status = osd_halt(); | 1426 | int status = osd_halt(); |
1438 | 1427 | ||
1428 | osd_set_hp_pause_flag(false); | ||
1429 | |||
1439 | if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) { | 1430 | if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) { |
1440 | /* Resume pending - change to a still video frame update */ | 1431 | /* Resume pending - change to a still video frame update */ |
1441 | osd_schedule_refresh(OSD_REFRESH_VIDEO); | 1432 | osd_schedule_refresh(OSD_REFRESH_VIDEO); |
@@ -1454,6 +1445,7 @@ static void osd_resume(void) | |||
1454 | { | 1445 | { |
1455 | /* Cancel video and resume auto refresh - the resyc when starting | 1446 | /* Cancel video and resume auto refresh - the resyc when starting |
1456 | * playback will perform those tasks */ | 1447 | * playback will perform those tasks */ |
1448 | osd_set_hp_pause_flag(false); | ||
1457 | osd_backlight_on_video_mode(true); | 1449 | osd_backlight_on_video_mode(true); |
1458 | osd_backlight_brightness_video_mode(true); | 1450 | osd_backlight_brightness_video_mode(true); |
1459 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); | 1451 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); |
@@ -1466,6 +1458,7 @@ static void osd_stop(void) | |||
1466 | { | 1458 | { |
1467 | uint32_t resume_time; | 1459 | uint32_t resume_time; |
1468 | 1460 | ||
1461 | osd_set_hp_pause_flag(false); | ||
1469 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); | 1462 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); |
1470 | osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW); | 1463 | osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW); |
1471 | osd_show(OSD_HIDE); | 1464 | osd_show(OSD_HIDE); |
@@ -1481,35 +1474,81 @@ static void osd_stop(void) | |||
1481 | osd_backlight_brightness_video_mode(false); | 1474 | osd_backlight_brightness_video_mode(false); |
1482 | } | 1475 | } |
1483 | 1476 | ||
1484 | /* Perform a seek if seeking is possible for this stream - if playing, a delay | 1477 | /* Perform a seek by button if seeking is possible for this stream. |
1485 | * will be inserted before restarting in case the user decides to seek again */ | 1478 | * |
1486 | static void osd_seek(int btn) | 1479 | * A delay will be inserted before restarting in case the user decides to |
1480 | * seek again soon after. | ||
1481 | * | ||
1482 | * Returns last button code | ||
1483 | */ | ||
1484 | static int osd_seek_btn(int btn) | ||
1487 | { | 1485 | { |
1488 | int status; | 1486 | int status; |
1489 | unsigned refresh; | 1487 | unsigned refresh = 0; |
1490 | uint32_t time; | 1488 | uint32_t time; |
1491 | 1489 | ||
1492 | if (!stream_can_seek()) | 1490 | if (!stream_can_seek()) |
1493 | return; | 1491 | return true; |
1494 | 1492 | ||
1495 | /* Halt playback - not strictly nescessary but nice */ | 1493 | /* Halt playback - not strictly necessary but nice when doing |
1494 | * buttons */ | ||
1496 | status = osd_halt(); | 1495 | status = osd_halt(); |
1497 | 1496 | ||
1498 | if (status == STREAM_STOPPED) | 1497 | if (status == STREAM_STOPPED) |
1499 | return; | 1498 | return true; |
1500 | 1499 | ||
1501 | osd_show(OSD_SHOW); | 1500 | osd_show(OSD_SHOW); |
1502 | 1501 | ||
1502 | /* Obtain a new playback point according to the buttons */ | ||
1503 | if (status == STREAM_PLAYING) | 1503 | if (status == STREAM_PLAYING) |
1504 | refresh = OSD_REFRESH_RESUME; /* delay resume if playing */ | 1504 | refresh = OSD_REFRESH_RESUME; /* delay resume if playing */ |
1505 | else | 1505 | else |
1506 | refresh = OSD_REFRESH_VIDEO; /* refresh if paused */ | 1506 | refresh = OSD_REFRESH_VIDEO; /* refresh if paused */ |
1507 | 1507 | ||
1508 | /* Obtain a new playback point */ | 1508 | btn = osd_ff_rw(btn, refresh, &time); |
1509 | time = osd_ff_rw(btn, refresh); | ||
1510 | 1509 | ||
1511 | /* Tell engine to resume at that time */ | 1510 | /* Tell engine to resume at that time */ |
1512 | stream_seek(time, SEEK_SET); | 1511 | stream_seek(time, SEEK_SET); |
1512 | |||
1513 | return btn; | ||
1514 | } | ||
1515 | |||
1516 | /* Perform a seek by time if seeking is possible for this stream | ||
1517 | * | ||
1518 | * If playing, the seeking is immediate, otherise a delay is added to showing | ||
1519 | * a still if paused in case the user does another seek soon after. | ||
1520 | * | ||
1521 | * If seeking isn't possible, a time of zero performs a skip to the | ||
1522 | * beginning. | ||
1523 | */ | ||
1524 | static void osd_seek_time(uint32_t time) | ||
1525 | { | ||
1526 | int status; | ||
1527 | unsigned refresh = 0; | ||
1528 | |||
1529 | if (!stream_can_seek() && time != 0) | ||
1530 | return; | ||
1531 | |||
1532 | stream_wait_status(); | ||
1533 | status = osd_stream_status(); | ||
1534 | |||
1535 | if (status == STREAM_STOPPED) | ||
1536 | return; | ||
1537 | |||
1538 | if (status == STREAM_PLAYING) /* merely preserve resume */ | ||
1539 | refresh = osd.auto_refresh & OSD_REFRESH_RESUME; | ||
1540 | else | ||
1541 | refresh = OSD_REFRESH_VIDEO; /* refresh if paused */ | ||
1542 | |||
1543 | /* Cancel print or resume if pending */ | ||
1544 | osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); | ||
1545 | |||
1546 | /* Tell engine to seek to the given time - no state change */ | ||
1547 | stream_seek(time, SEEK_SET); | ||
1548 | |||
1549 | osd_update_time(); | ||
1550 | osd_refresh(OSD_REFRESH_TIME); | ||
1551 | osd_schedule_refresh(refresh); | ||
1513 | } | 1552 | } |
1514 | 1553 | ||
1515 | /* Has this file one of the supported extensions? */ | 1554 | /* Has this file one of the supported extensions? */ |
@@ -1537,7 +1576,7 @@ static bool is_videofile(const char* file) | |||
1537 | } | 1576 | } |
1538 | 1577 | ||
1539 | /* deliver the next/previous video file in the current directory. | 1578 | /* deliver the next/previous video file in the current directory. |
1540 | returns 0 if there is none. */ | 1579 | returns false if there is none. */ |
1541 | static bool get_videofile(int direction, char* videofile, size_t bufsize) | 1580 | static bool get_videofile(int direction, char* videofile, size_t bufsize) |
1542 | { | 1581 | { |
1543 | struct tree_context *tree = rb->tree_get_context(); | 1582 | struct tree_context *tree = rb->tree_get_context(); |
@@ -1583,11 +1622,12 @@ static void osd_handle_phone_plug(bool inserted) | |||
1583 | /* Wait for any incomplete state transition to complete first */ | 1622 | /* Wait for any incomplete state transition to complete first */ |
1584 | stream_wait_status(); | 1623 | stream_wait_status(); |
1585 | 1624 | ||
1586 | int status = osd_status(); | 1625 | int status = osd_stream_status(); |
1587 | 1626 | ||
1588 | if (inserted) { | 1627 | if (inserted) { |
1589 | if (rb->global_settings->unplug_mode > 1) { | 1628 | if (rb->global_settings->unplug_mode > 1) { |
1590 | if (status == STREAM_PAUSED) { | 1629 | if (status == STREAM_PAUSED && |
1630 | (osd.flags & OSD_HP_PAUSE)) { | ||
1591 | osd_resume(); | 1631 | osd_resume(); |
1592 | } | 1632 | } |
1593 | } | 1633 | } |
@@ -1595,6 +1635,8 @@ static void osd_handle_phone_plug(bool inserted) | |||
1595 | if (status == STREAM_PLAYING) { | 1635 | if (status == STREAM_PLAYING) { |
1596 | osd_pause(); | 1636 | osd_pause(); |
1597 | 1637 | ||
1638 | osd_set_hp_pause_flag(true); | ||
1639 | |||
1598 | if (stream_can_seek() && rb->global_settings->unplug_rw) { | 1640 | if (stream_can_seek() && rb->global_settings->unplug_rw) { |
1599 | stream_seek(-rb->global_settings->unplug_rw*TS_SECOND, | 1641 | stream_seek(-rb->global_settings->unplug_rw*TS_SECOND, |
1600 | SEEK_CUR); | 1642 | SEEK_CUR); |
@@ -1635,12 +1677,7 @@ static int button_loop(void) | |||
1635 | /* Gently poll the video player for EOS and handle UI */ | 1677 | /* Gently poll the video player for EOS and handle UI */ |
1636 | while (stream_status() != STREAM_STOPPED) | 1678 | while (stream_status() != STREAM_STOPPED) |
1637 | { | 1679 | { |
1638 | int button; | 1680 | int button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL/2); |
1639 | |||
1640 | mpeg_menu_sysevent_clear(); | ||
1641 | button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL/2); | ||
1642 | |||
1643 | button = mpeg_menu_sysevent_callback(button, NULL); | ||
1644 | 1681 | ||
1645 | switch (button) | 1682 | switch (button) |
1646 | { | 1683 | { |
@@ -1761,6 +1798,7 @@ static int button_loop(void) | |||
1761 | #endif | 1798 | #endif |
1762 | case ACTION_STD_CANCEL: | 1799 | case ACTION_STD_CANCEL: |
1763 | { | 1800 | { |
1801 | cancel_playback: | ||
1764 | next_action = VIDEO_STOP; | 1802 | next_action = VIDEO_STOP; |
1765 | osd_stop(); | 1803 | osd_stop(); |
1766 | break; | 1804 | break; |
@@ -1774,7 +1812,7 @@ static int button_loop(void) | |||
1774 | case MPEG_RC_PAUSE: | 1812 | case MPEG_RC_PAUSE: |
1775 | #endif | 1813 | #endif |
1776 | { | 1814 | { |
1777 | int status = osd_status(); | 1815 | int status = osd_stream_status(); |
1778 | 1816 | ||
1779 | if (status == STREAM_PLAYING) { | 1817 | if (status == STREAM_PLAYING) { |
1780 | /* Playing => Paused */ | 1818 | /* Playing => Paused */ |
@@ -1789,54 +1827,72 @@ static int button_loop(void) | |||
1789 | } /* MPEG_PAUSE*: */ | 1827 | } /* MPEG_PAUSE*: */ |
1790 | 1828 | ||
1791 | case MPEG_RW: | 1829 | case MPEG_RW: |
1792 | case MPEG_FF: | ||
1793 | #ifdef MPEG_RW2 | 1830 | #ifdef MPEG_RW2 |
1794 | case MPEG_RW2: | 1831 | case MPEG_RW2: |
1795 | #endif | 1832 | #endif |
1833 | #ifdef MPEG_RC_RW | ||
1834 | case MPEG_RC_RW: | ||
1835 | #endif | ||
1836 | { | ||
1837 | int old_button = button; | ||
1838 | |||
1839 | /* If button has been released: skip to next/previous file */ | ||
1840 | button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL); | ||
1841 | |||
1842 | if ((old_button | BUTTON_REL) == button) { | ||
1843 | /* Check current playback position */ | ||
1844 | osd_update_time(); | ||
1845 | |||
1846 | if (settings.play_mode == 0 || osd.curr_time >= 3*TS_SECOND) { | ||
1847 | /* Start the current video from the beginning */ | ||
1848 | osd_seek_time(0*TS_SECOND); | ||
1849 | } | ||
1850 | else { | ||
1851 | /* Release within 3 seconds of start: skip to previous | ||
1852 | * file */ | ||
1853 | osd_stop(); | ||
1854 | next_action = VIDEO_PREV; | ||
1855 | } | ||
1856 | } | ||
1857 | else if ((button & ~BUTTON_REPEAT) == old_button) { | ||
1858 | button = osd_seek_btn(old_button); | ||
1859 | } | ||
1860 | |||
1861 | if (button == ACTION_STD_CANCEL) | ||
1862 | goto cancel_playback; /* jump to stop handling above */ | ||
1863 | |||
1864 | rb->default_event_handler(button); | ||
1865 | break; | ||
1866 | } /* MPEG_RW: */ | ||
1867 | |||
1868 | case MPEG_FF: | ||
1796 | #ifdef MPEG_FF2 | 1869 | #ifdef MPEG_FF2 |
1797 | case MPEG_FF2: | 1870 | case MPEG_FF2: |
1798 | #endif | 1871 | #endif |
1799 | #ifdef MPEG_RC_RW | 1872 | #ifdef MPEG_RC_FF |
1800 | case MPEG_RC_RW: | ||
1801 | case MPEG_RC_FF: | 1873 | case MPEG_RC_FF: |
1802 | #endif | 1874 | #endif |
1803 | { | 1875 | { |
1804 | int old_button = button; | 1876 | int old_button = button; |
1877 | |||
1805 | if (settings.play_mode != 0) | 1878 | if (settings.play_mode != 0) |
1806 | { | 1879 | button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL); |
1807 | /* if button has been released: skip to next/previous file */ | 1880 | |
1808 | button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL); | 1881 | if ((old_button | BUTTON_REL) == button) { |
1809 | } | 1882 | /* If button has been released: skip to next file */ |
1810 | switch (button) | ||
1811 | { | ||
1812 | case MPEG_RW | BUTTON_REL: | ||
1813 | { | ||
1814 | /* release within 3 seconds: skip to previous file, else | ||
1815 | start the current video from the beginning */ | ||
1816 | osd_stop(); | ||
1817 | if ( stream_get_resume_time() > 3*TS_SECOND ) { | ||
1818 | osd_play(0); | ||
1819 | osd_show(OSD_SHOW); | ||
1820 | } else { | ||
1821 | next_action = VIDEO_PREV; | ||
1822 | } | ||
1823 | break; | ||
1824 | } | ||
1825 | case MPEG_FF | BUTTON_REL: | ||
1826 | { | ||
1827 | osd_stop(); | 1883 | osd_stop(); |
1828 | next_action = VIDEO_NEXT; | 1884 | next_action = VIDEO_NEXT; |
1829 | break; | ||
1830 | } | ||
1831 | default: | ||
1832 | { | ||
1833 | button = old_button; | ||
1834 | osd_seek(button); | ||
1835 | break; | ||
1836 | } | ||
1837 | } | 1885 | } |
1886 | else if ((button & ~BUTTON_REPEAT) == old_button) { | ||
1887 | button = osd_seek_btn(old_button); | ||
1888 | } | ||
1889 | |||
1890 | if (button == ACTION_STD_CANCEL) | ||
1891 | goto cancel_playback; /* jump to stop handling above */ | ||
1892 | |||
1893 | rb->default_event_handler(button); | ||
1838 | break; | 1894 | break; |
1839 | } /* MPEG_RW: MPEG_FF: */ | 1895 | } /* MPEG_FF: */ |
1840 | 1896 | ||
1841 | #ifdef HAVE_HEADPHONE_DETECTION | 1897 | #ifdef HAVE_HEADPHONE_DETECTION |
1842 | case SYS_PHONE_PLUGGED: | 1898 | case SYS_PHONE_PLUGGED: |
@@ -1849,6 +1905,7 @@ static int button_loop(void) | |||
1849 | 1905 | ||
1850 | default: | 1906 | default: |
1851 | { | 1907 | { |
1908 | osd_refresh(OSD_REFRESH_DEFAULT); | ||
1852 | rb->default_event_handler(button); | 1909 | rb->default_event_handler(button); |
1853 | break; | 1910 | break; |
1854 | } /* default: */ | 1911 | } /* default: */ |
@@ -1874,10 +1931,7 @@ enum plugin_status plugin_start(const void* parameter) | |||
1874 | { | 1931 | { |
1875 | static char videofile[MAX_PATH]; | 1932 | static char videofile[MAX_PATH]; |
1876 | int status = PLUGIN_OK; /* assume success */ | 1933 | int status = PLUGIN_OK; /* assume success */ |
1877 | int result; | ||
1878 | int err; | ||
1879 | bool quit = false; | 1934 | bool quit = false; |
1880 | const char *errstring; | ||
1881 | 1935 | ||
1882 | if (parameter == NULL) { | 1936 | if (parameter == NULL) { |
1883 | /* No file = GTFO */ | 1937 | /* No file = GTFO */ |
@@ -1904,19 +1958,24 @@ enum plugin_status plugin_start(const void* parameter) | |||
1904 | DEBUGF("Could not initialize streams\n"); | 1958 | DEBUGF("Could not initialize streams\n"); |
1905 | status = PLUGIN_ERROR; | 1959 | status = PLUGIN_ERROR; |
1906 | } else { | 1960 | } else { |
1961 | int next_action = VIDEO_STOP; | ||
1962 | bool get_videofile_says = true; | ||
1963 | |||
1907 | while (!quit) | 1964 | while (!quit) |
1908 | { | 1965 | { |
1909 | int next_action = VIDEO_STOP; | 1966 | int result; |
1910 | 1967 | ||
1911 | init_settings(videofile); | 1968 | init_settings(videofile); |
1912 | err = stream_open(videofile); | ||
1913 | 1969 | ||
1914 | if (err >= STREAM_OK) { | 1970 | result = stream_open(videofile); |
1971 | |||
1972 | if (result >= STREAM_OK) { | ||
1915 | /* start menu */ | 1973 | /* start menu */ |
1916 | rb->lcd_clear_display(); | 1974 | rb->lcd_clear_display(); |
1917 | rb->lcd_update(); | 1975 | rb->lcd_update(); |
1918 | result = mpeg_start_menu(stream_get_duration()); | 1976 | result = mpeg_start_menu(stream_get_duration()); |
1919 | 1977 | ||
1978 | next_action = VIDEO_STOP; | ||
1920 | if (result != MPEG_START_QUIT) { | 1979 | if (result != MPEG_START_QUIT) { |
1921 | /* Enter button loop and process UI */ | 1980 | /* Enter button loop and process UI */ |
1922 | next_action = button_loop(); | 1981 | next_action = button_loop(); |
@@ -1928,13 +1987,14 @@ enum plugin_status plugin_start(const void* parameter) | |||
1928 | rb->lcd_update(); | 1987 | rb->lcd_update(); |
1929 | 1988 | ||
1930 | save_settings(); | 1989 | save_settings(); |
1931 | |||
1932 | mpeg_menu_sysevent_handle(); | ||
1933 | } else { | 1990 | } else { |
1934 | /* Problem with file; display message about it - not | 1991 | /* Problem with file; display message about it - not |
1935 | * considered a plugin error */ | 1992 | * considered a plugin error */ |
1993 | long tick; | ||
1994 | const char *errstring; | ||
1995 | |||
1936 | DEBUGF("Could not open %s\n", videofile); | 1996 | DEBUGF("Could not open %s\n", videofile); |
1937 | switch (err) | 1997 | switch (result) |
1938 | { | 1998 | { |
1939 | case STREAM_UNSUPPORTED: | 1999 | case STREAM_UNSUPPORTED: |
1940 | errstring = "Unsupported format"; | 2000 | errstring = "Unsupported format"; |
@@ -1943,12 +2003,45 @@ enum plugin_status plugin_start(const void* parameter) | |||
1943 | errstring = "Error opening file: %d"; | 2003 | errstring = "Error opening file: %d"; |
1944 | } | 2004 | } |
1945 | 2005 | ||
1946 | rb->splashf(HZ*2, errstring, err); | 2006 | tick = *rb->current_tick + HZ*2; |
1947 | 2007 | ||
1948 | if (settings.play_mode != 0) { | 2008 | rb->splashf(0, errstring, result); |
1949 | /* Try the next file if the play mode is not single play */ | 2009 | |
1950 | next_action = VIDEO_NEXT; | 2010 | /* Be sure it doesn't get stuck in an unbreakable loop of bad |
1951 | } | 2011 | * files, just in case! Otherwise, keep searching in the |
2012 | * chosen direction until a good one is found. */ | ||
2013 | while (!quit && TIME_BEFORE(*rb->current_tick, tick)) | ||
2014 | { | ||
2015 | int button = mpeg_button_get(HZ*2); | ||
2016 | |||
2017 | switch (button) | ||
2018 | { | ||
2019 | case MPEG_STOP: | ||
2020 | case ACTION_STD_CANCEL: | ||
2021 | /* Abort the search and exit */ | ||
2022 | next_action = VIDEO_STOP; | ||
2023 | quit = true; | ||
2024 | break; | ||
2025 | |||
2026 | case BUTTON_NONE: | ||
2027 | if (settings.play_mode != 0) { | ||
2028 | if (next_action == VIDEO_STOP) { | ||
2029 | /* Default to next file */ | ||
2030 | next_action = VIDEO_NEXT; | ||
2031 | } | ||
2032 | else if (next_action == VIDEO_PREV && | ||
2033 | !get_videofile_says) { | ||
2034 | /* Was first file already; avoid endlessly | ||
2035 | * retrying it */ | ||
2036 | next_action = VIDEO_STOP; | ||
2037 | } | ||
2038 | } | ||
2039 | break; | ||
2040 | |||
2041 | default: | ||
2042 | rb->default_event_handler(button); | ||
2043 | } /* switch */ | ||
2044 | } /* while */ | ||
1952 | } | 2045 | } |
1953 | 2046 | ||
1954 | /* return value of button_loop says, what's next */ | 2047 | /* return value of button_loop says, what's next */ |
@@ -1956,15 +2049,16 @@ enum plugin_status plugin_start(const void* parameter) | |||
1956 | { | 2049 | { |
1957 | case VIDEO_NEXT: | 2050 | case VIDEO_NEXT: |
1958 | { | 2051 | { |
1959 | if (!get_videofile(VIDEO_NEXT, videofile, sizeof(videofile))) { | 2052 | get_videofile_says = get_videofile(VIDEO_NEXT, videofile, |
1960 | /* quit after finished the last videofile */ | 2053 | sizeof(videofile)); |
1961 | quit = true; | 2054 | /* quit after finished the last videofile */ |
1962 | } | 2055 | quit = !get_videofile_says; |
1963 | break; | 2056 | break; |
1964 | } | 2057 | } |
1965 | case VIDEO_PREV: | 2058 | case VIDEO_PREV: |
1966 | { | 2059 | { |
1967 | get_videofile(VIDEO_PREV, videofile, sizeof(videofile)); | 2060 | get_videofile_says = get_videofile(VIDEO_PREV, videofile, |
2061 | sizeof(videofile)); | ||
1968 | /* if there is no previous file, play the same videofile */ | 2062 | /* if there is no previous file, play the same videofile */ |
1969 | break; | 2063 | break; |
1970 | } | 2064 | } |
@@ -1974,7 +2068,7 @@ enum plugin_status plugin_start(const void* parameter) | |||
1974 | break; | 2068 | break; |
1975 | } | 2069 | } |
1976 | } | 2070 | } |
1977 | } | 2071 | } /* while */ |
1978 | } | 2072 | } |
1979 | 2073 | ||
1980 | #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) | 2074 | #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) |
@@ -1984,5 +2078,10 @@ enum plugin_status plugin_start(const void* parameter) | |||
1984 | stream_exit(); | 2078 | stream_exit(); |
1985 | 2079 | ||
1986 | rb->talk_disable(false); | 2080 | rb->talk_disable(false); |
2081 | |||
2082 | /* Actually handle delayed processing of system events of interest | ||
2083 | * that were captured in other button loops */ | ||
2084 | mpeg_sysevent_handle(); | ||
2085 | |||
1987 | return status; | 2086 | return status; |
1988 | } | 2087 | } |