1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Jerome Kuptz
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
27 #include "backlight.h"
35 #include "wps-display.h"
37 #include "mp3_playback.h"
40 #include "main_menu.h"
44 #ifdef HAVE_LCD_BITMAP
46 #include "peakmeter.h"
57 #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
58 /* 3% of 30min file == 54s step size */
59 #define MIN_FF_REWIND_STEP 500
61 bool keys_locked
= false;
62 static bool ff_rewind
= false;
63 static bool paused
= false;
64 static struct mp3entry
* id3
= NULL
;
65 static struct mp3entry
* nid3
= NULL
;
66 static char current_track_path
[MAX_PATH
+1];
69 return true if screen restore is needed
70 return false otherwise
72 static bool setvol(void)
74 if (global_settings
.volume
< sound_min(SOUND_VOLUME
))
75 global_settings
.volume
= sound_min(SOUND_VOLUME
);
76 if (global_settings
.volume
> sound_max(SOUND_VOLUME
))
77 global_settings
.volume
= sound_max(SOUND_VOLUME
);
78 sound_set_volume(global_settings
.volume
);
80 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
82 #ifdef HAVE_LCD_CHARCELLS
83 splash(0, false, "Vol: %d %% ",
84 sound_val2phys(SOUND_VOLUME
, global_settings
.volume
));
90 static bool ffwd_rew(int button
)
92 static const int ff_rew_steps
[] = {
93 1000, 2000, 3000, 4000,
94 5000, 6000, 8000, 10000,
95 15000, 20000, 25000, 30000,
99 unsigned int step
= 0; /* current ff/rewind step */
100 unsigned int max_step
= 0; /* maximum ff/rewind step */
101 int ff_rewind_count
= 0; /* current ff/rewind count (in ticks) */
102 int direction
= -1; /* forward=1 or backward=-1 */
103 long accel_tick
= 0; /* next time at which to bump the step size */
122 /* fast forwarding, calc max step relative to end */
124 (id3
->length
- (id3
->elapsed
+ ff_rewind_count
)) *
125 FF_REWIND_MAX_PERCENT
/ 100;
129 /* rewinding, calc max step relative to start */
130 max_step
= (id3
->elapsed
+ ff_rewind_count
) *
131 FF_REWIND_MAX_PERCENT
/ 100;
134 max_step
= MAX(max_step
, MIN_FF_REWIND_STEP
);
139 ff_rewind_count
+= step
* direction
;
141 if (global_settings
.ff_rewind_accel
!= 0 &&
142 current_tick
>= accel_tick
)
145 accel_tick
= current_tick
+
146 global_settings
.ff_rewind_accel
*HZ
;
151 if ( (audio_status() & AUDIO_STATUS_PLAY
) &&
156 #if CONFIG_KEYPAD == PLAYER_PAD
160 status_set_ffmode(STATUS_FASTFORWARD
);
162 status_set_ffmode(STATUS_FASTBACKWARD
);
166 step
= ff_rew_steps
[global_settings
.ff_rewind_min_step
];
168 accel_tick
= current_tick
+
169 global_settings
.ff_rewind_accel
*HZ
;
176 if ((id3
->elapsed
+ ff_rewind_count
) > id3
->length
)
177 ff_rewind_count
= id3
->length
- id3
->elapsed
;
180 if ((int)(id3
->elapsed
+ ff_rewind_count
) < 0)
181 ff_rewind_count
= -id3
->elapsed
;
184 if(wps_time_countup
== false)
185 wps_refresh(id3
, nid3
, -ff_rewind_count
,
186 WPS_REFRESH_PLAYER_PROGRESS
|
187 WPS_REFRESH_DYNAMIC
);
189 wps_refresh(id3
, nid3
, ff_rewind_count
,
190 WPS_REFRESH_PLAYER_PROGRESS
|
191 WPS_REFRESH_DYNAMIC
);
201 audio_ff_rewind(id3
->elapsed
+ff_rewind_count
);
204 status_set_ffmode(0);
207 #ifdef HAVE_LCD_CHARCELLS
208 wps_display(id3
, nid3
);
214 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
215 status_set_ffmode(0);
222 button
= button_get(true);
225 /* let audio thread update id3->elapsed before calling wps_refresh */
227 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
231 static bool update(void)
233 bool track_changed
= audio_has_changed_track();
234 bool retcode
= false;
236 nid3
= audio_next_track();
240 id3
= audio_current_track();
241 if (wps_display(id3
, nid3
))
244 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
247 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
251 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
258 static void fade(bool fade_in
)
260 unsigned fp_global_vol
= global_settings
.volume
<< 8;
261 unsigned fp_step
= fp_global_vol
/ 30;
265 unsigned fp_volume
= 0;
267 /* zero out the sound */
270 sleep(HZ
/10); /* let audio thread run */
273 while (fp_volume
< fp_global_vol
) {
274 fp_volume
+= fp_step
;
276 sound_set_volume(fp_volume
>> 8);
278 sound_set_volume(global_settings
.volume
);
282 unsigned fp_volume
= fp_global_vol
;
284 while (fp_volume
> fp_step
) {
285 fp_volume
-= fp_step
;
287 sound_set_volume(fp_volume
>> 8);
291 /* let audio thread run and wait for the mas to run out of data */
292 while (!mp3_pause_done())
296 /* reset volume to what it was before the fade */
297 sound_set_volume(global_settings
.volume
);
303 static void display_keylock_text(bool locked
)
307 #ifdef HAVE_LCD_CHARCELLS
309 s
= str(LANG_KEYLOCK_ON_PLAYER
);
311 s
= str(LANG_KEYLOCK_OFF_PLAYER
);
314 s
= str(LANG_KEYLOCK_ON_RECORDER
);
316 s
= str(LANG_KEYLOCK_OFF_RECORDER
);
321 static void waitfor_nokey(void)
323 /* wait until all keys are released */
324 while (button_get(false) != BUTTON_NONE
)
329 /* demonstrates showing different formats from playtune */
332 long button
= 0, lastbutton
= 0;
333 bool ignore_keyup
= true;
334 bool restore
= false;
335 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
337 bool update_track
= false;
338 unsigned long right_lastclick
= 0;
339 unsigned long left_lastclick
= 0;
342 current_track_path
[0] = '\0';
344 #ifdef HAVE_LCD_CHARCELLS
345 status_set_audio(true);
346 status_set_param(false);
348 if(global_settings
.statusbar
)
349 lcd_setmargins(0, STATUSBAR_HEIGHT
);
351 lcd_setmargins(0, 0);
354 #ifdef AB_REPEAT_ENABLE
361 if(audio_status() & AUDIO_STATUS_PLAY
)
363 id3
= audio_current_track();
364 nid3
= audio_next_track();
366 if (wps_display(id3
, nid3
))
368 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
370 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
378 bool audio_paused
= (audio_status() & AUDIO_STATUS_PAUSE
)?true:false;
380 /* did someone else (i.e power thread) change audio pause mode? */
381 if (paused
!= audio_paused
) {
382 paused
= audio_paused
;
384 /* if another thread paused audio, we are probably in car mode,
385 about to shut down. lets save the settings. */
388 #if !defined(HAVE_RTC) && !defined(HAVE_SW_POWEROFF)
394 #ifdef HAVE_LCD_BITMAP
395 /* when the peak meter is enabled we want to have a
396 few extra updates to make it look smooth. On the
397 other hand we don't want to waste energy if it
399 if (peak_meter_enabled
) {
400 long next_refresh
= current_tick
;
401 long next_big_refresh
= current_tick
+ HZ
/ 5;
402 button
= BUTTON_NONE
;
403 while (TIME_BEFORE(current_tick
, next_big_refresh
)) {
404 button
= button_get(false);
405 if (button
!= BUTTON_NONE
) {
409 sleep(0); /* Sleep until end of current tick. */
411 if (TIME_AFTER(current_tick
, next_refresh
)) {
412 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
413 next_refresh
+= HZ
/ PEAK_METER_FPS
;
419 /* The peak meter is disabled
420 -> no additional screen updates needed */
422 button
= button_get_w_tmo(HZ
/5);
425 button
= button_get_w_tmo(HZ
/5);
428 /* discard first event if it's a button release */
429 if (button
&& ignore_keyup
)
431 ignore_keyup
= false;
432 /* Negative events are system events */
433 if (button
>= 0 && button
& BUTTON_REL
)
438 /* ignore non-remote buttons when keys are locked */
441 (button
== BUTTON_NONE
) ||
442 ((button
& WPS_KEYLOCK
) == WPS_KEYLOCK
) ||
443 (button
& BUTTON_REMOTE
)
446 if (!(button
& BUTTON_REL
))
447 display_keylock_text(true);
449 button
= BUTTON_NONE
;
453 /* Exit if audio has stopped playing. This can happen if using the
454 sleep timer with the charger plugged or if starting a recording
463 onplay(id3
->path
, TREE_ATTR_MPA
, CONTEXT_WPS
);
472 #ifdef WPS_BROWSE_PRE
473 if ((lastbutton
!= WPS_BROWSE_PRE
)
474 #ifdef WPS_RC_BROWSE_PRE
475 && (lastbutton
!= WPS_RC_BROWSE_PRE
)
480 #ifdef HAVE_LCD_CHARCELLS
481 status_set_record(false);
482 status_set_audio(false);
486 /* set dir browser to current playing song */
487 if (global_settings
.browse_current
&&
488 current_track_path
[0] != '\0')
489 set_current_file(current_track_path
);
497 if (lastbutton
!= WPS_PAUSE_PRE
)
502 #ifdef WPS_RC_PAUSE_PRE
503 if ((button
== WPS_RC_PAUSE
) && (lastbutton
!= WPS_RC_PAUSE_PRE
))
510 if ( global_settings
.fade_on_stop
)
518 if ( global_settings
.fade_on_stop
)
523 #if !defined(HAVE_RTC) && !defined(HAVE_SW_POWEROFF)
524 ata_flush(); /* make sure resume info is saved */
531 case WPS_INCVOL
| BUTTON_REPEAT
:
534 case WPS_RC_INCVOL
| BUTTON_REPEAT
:
536 global_settings
.volume
++;
539 restoretimer
= current_tick
+ HZ
;
545 case WPS_DECVOL
| BUTTON_REPEAT
:
548 case WPS_RC_DECVOL
| BUTTON_REPEAT
:
550 global_settings
.volume
--;
553 restoretimer
= current_tick
+ HZ
;
557 /* fast forward / rewind */
563 if (current_tick
- right_lastclick
< HZ
)
575 if (current_tick
- left_lastclick
< HZ
)
588 if (lastbutton
!= WPS_PREV_PRE
)
593 #ifdef WPS_RC_PREV_PRE
594 if ((button
== WPS_RC_PREV
) && (lastbutton
!= WPS_RC_PREV_PRE
))
598 left_lastclick
= current_tick
;
600 #ifdef AB_REPEAT_ENABLE
601 /* if we're in A/B repeat mode and the current position
602 is past the A marker, jump back to the A marker... */
603 if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3
->elapsed
) )
605 ab_jump_to_A_marker();
609 /* ...otherwise, do it normally */
612 if (!id3
|| (id3
->elapsed
< 3*1000)) {
627 #ifdef WPS_RC_NEXT_DIR
628 case WPS_RC_NEXT_DIR
:
635 #ifdef WPS_RC_PREV_DIR
636 case WPS_RC_PREV_DIR
:
646 if (lastbutton
!= WPS_NEXT_PRE
)
651 #ifdef WPS_RC_NEXT_PRE
652 if ((button
== WPS_RC_NEXT
) && (lastbutton
!= WPS_RC_NEXT_PRE
))
656 right_lastclick
= current_tick
;
658 #ifdef AB_REPEAT_ENABLE
659 /* if we're in A/B repeat mode and the current position is
660 before the A marker, jump to the A marker... */
661 if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3
->elapsed
) )
663 ab_jump_to_A_marker();
667 /* ...otherwise, do it normally */
674 /* menu key functions */
677 if (lastbutton
!= WPS_MENU_PRE
)
682 #ifdef WPS_RC_MENU_PRE
683 if ((button
== WPS_RC_MENU
) && (lastbutton
!= WPS_RC_MENU_PRE
))
691 #ifdef HAVE_LCD_BITMAP
692 if (global_settings
.statusbar
)
693 lcd_setmargins(0, STATUSBAR_HEIGHT
);
695 lcd_setmargins(0, 0);
699 #endif /* WPS_MENU */
704 case WPS_KEYLOCK
| BUTTON_REPEAT
:
705 keys_locked
= !keys_locked
;
706 display_keylock_text(keys_locked
);
712 #if (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD)
715 if (quick_screen(CONTEXT_WPS
, WPS_QUICK
))
716 return SYS_USB_CONNECTED
;
721 /* screen settings */
724 if (quick_screen(CONTEXT_WPS
, BUTTON_F3
))
725 return SYS_USB_CONNECTED
;
731 #if CONFIG_KEYPAD == RECORDER_PAD
732 case BUTTON_ON
| BUTTON_UP
:
733 case BUTTON_ON
| BUTTON_DOWN
:
734 if (2 == pitch_screen())
735 return SYS_USB_CONNECTED
;
741 #ifdef AB_REPEAT_ENABLE
743 #ifdef WPS_AB_SET_A_MARKER
744 /* set A marker for A-B repeat */
745 case WPS_AB_SET_A_MARKER
:
746 if (ab_repeat_mode_enabled())
747 ab_set_A_marker(id3
->elapsed
);
751 #ifdef WPS_AB_SET_B_MARKER
752 /* set B marker for A-B repeat and jump to A */
753 case WPS_AB_SET_B_MARKER
:
754 if (ab_repeat_mode_enabled())
756 ab_set_B_marker(id3
->elapsed
);
757 ab_jump_to_A_marker();
763 #ifdef WPS_AB_RESET_AB_MARKERS
764 /* reset A&B markers */
765 case WPS_AB_RESET_AB_MARKERS
:
766 if (ab_repeat_mode_enabled())
774 #endif /* AB_REPEAT_ENABLE */
776 /* stop and exit wps */
780 if (lastbutton
!= WPS_EXIT_PRE
)
787 # ifdef WPS_RC_EXIT_PRE
788 if (lastbutton
!= WPS_RC_EXIT_PRE
)
803 case BUTTON_NONE
: /* Timeout */
808 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
809 return SYS_USB_CONNECTED
;
818 /* set dir browser to current playing song */
819 if (global_settings
.browse_current
&&
820 current_track_path
[0] != '\0')
821 set_current_file(current_track_path
);
825 update_track
= false;
829 #ifdef HAVE_LCD_CHARCELLS
830 status_set_record(false);
831 status_set_audio(false);
833 if (global_settings
.fade_on_stop
)
837 bookmark_autobookmark();
839 #ifdef AB_REPEAT_ENABLE
843 /* Keys can be locked when exiting, so either unlock here
844 or implement key locking in tree.c too */
847 /* set dir browser to current playing song */
848 if (global_settings
.browse_current
&&
849 current_track_path
[0] != '\0')
850 set_current_file(current_track_path
);
859 ((restoretimer
== 0) ||
860 (restoretimer
< current_tick
)))
864 if (wps_display(id3
, nid3
))
866 /* set dir browser to current playing song */
867 if (global_settings
.browse_current
&&
868 current_track_path
[0] != '\0')
869 set_current_file(current_track_path
);
875 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
877 if (button
!= BUTTON_NONE
)
880 return 0; /* unreachable - just to reduce compiler warnings */