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"
55 #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
56 /* 3% of 30min file == 54s step size */
57 #define MIN_FF_REWIND_STEP 500
59 bool keys_locked
= false;
60 static bool ff_rewind
= false;
61 static bool paused
= false;
62 static struct mp3entry
* id3
= NULL
;
63 static struct mp3entry
* nid3
= NULL
;
64 static char current_track_path
[MAX_PATH
+1];
67 return true if screen restore is needed
68 return false otherwise
70 static bool setvol(void)
72 if (global_settings
.volume
< sound_min(SOUND_VOLUME
))
73 global_settings
.volume
= sound_min(SOUND_VOLUME
);
74 if (global_settings
.volume
> sound_max(SOUND_VOLUME
))
75 global_settings
.volume
= sound_max(SOUND_VOLUME
);
76 sound_set(SOUND_VOLUME
, global_settings
.volume
);
78 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
80 #ifdef HAVE_LCD_CHARCELLS
81 splash(0, false, "Vol: %d %% ",
82 sound_val2phys(SOUND_VOLUME
, global_settings
.volume
));
88 static bool ffwd_rew(int button
)
90 static const int ff_rew_steps
[] = {
91 1000, 2000, 3000, 4000,
92 5000, 6000, 8000, 10000,
93 15000, 20000, 25000, 30000,
97 unsigned int step
= 0; /* current ff/rewind step */
98 unsigned int max_step
= 0; /* maximum ff/rewind step */
99 int ff_rewind_count
= 0; /* current ff/rewind count (in ticks) */
100 int direction
= -1; /* forward=1 or backward=-1 */
101 long accel_tick
= 0; /* next time at which to bump the step size */
120 /* fast forwarding, calc max step relative to end */
122 (id3
->length
- (id3
->elapsed
+ ff_rewind_count
)) *
123 FF_REWIND_MAX_PERCENT
/ 100;
127 /* rewinding, calc max step relative to start */
128 max_step
= (id3
->elapsed
+ ff_rewind_count
) *
129 FF_REWIND_MAX_PERCENT
/ 100;
132 max_step
= MAX(max_step
, MIN_FF_REWIND_STEP
);
137 ff_rewind_count
+= step
* direction
;
139 if (global_settings
.ff_rewind_accel
!= 0 &&
140 current_tick
>= accel_tick
)
143 accel_tick
= current_tick
+
144 global_settings
.ff_rewind_accel
*HZ
;
149 if ( (audio_status() & AUDIO_STATUS_PLAY
) &&
154 #if CONFIG_KEYPAD == PLAYER_PAD
158 status_set_ffmode(STATUS_FASTFORWARD
);
160 status_set_ffmode(STATUS_FASTBACKWARD
);
164 step
= ff_rew_steps
[global_settings
.ff_rewind_min_step
];
166 accel_tick
= current_tick
+
167 global_settings
.ff_rewind_accel
*HZ
;
174 if ((id3
->elapsed
+ ff_rewind_count
) > id3
->length
)
175 ff_rewind_count
= id3
->length
- id3
->elapsed
;
178 if ((int)(id3
->elapsed
+ ff_rewind_count
) < 0)
179 ff_rewind_count
= -id3
->elapsed
;
182 if(wps_time_countup
== false)
183 wps_refresh(id3
, nid3
, -ff_rewind_count
,
184 WPS_REFRESH_PLAYER_PROGRESS
|
185 WPS_REFRESH_DYNAMIC
);
187 wps_refresh(id3
, nid3
, ff_rewind_count
,
188 WPS_REFRESH_PLAYER_PROGRESS
|
189 WPS_REFRESH_DYNAMIC
);
199 audio_ff_rewind(id3
->elapsed
+ff_rewind_count
);
202 status_set_ffmode(0);
205 #ifdef HAVE_LCD_CHARCELLS
206 wps_display(id3
, nid3
);
212 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
213 status_set_ffmode(0);
220 button
= button_get(true);
223 /* let audio thread update id3->elapsed before calling wps_refresh */
225 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
229 static bool update(void)
231 bool track_changed
= audio_has_changed_track();
232 bool retcode
= false;
234 nid3
= audio_next_track();
238 id3
= audio_current_track();
239 if (wps_display(id3
, nid3
))
242 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
245 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
249 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
256 static void fade(bool fade_in
)
258 unsigned fp_global_vol
= global_settings
.volume
<< 8;
259 unsigned fp_step
= fp_global_vol
/ 30;
263 unsigned fp_volume
= 0;
265 /* zero out the sound */
266 sound_set(SOUND_VOLUME
, 0);
268 sleep(HZ
/10); /* let audio thread run */
271 while (fp_volume
< fp_global_vol
) {
272 fp_volume
+= fp_step
;
274 sound_set(SOUND_VOLUME
, fp_volume
>> 8);
276 sound_set(SOUND_VOLUME
, global_settings
.volume
);
280 unsigned fp_volume
= fp_global_vol
;
282 while (fp_volume
> fp_step
) {
283 fp_volume
-= fp_step
;
285 sound_set(SOUND_VOLUME
, fp_volume
>> 8);
289 /* let audio thread run and wait for the mas to run out of data */
290 while (!mp3_pause_done())
294 /* reset volume to what it was before the fade */
295 sound_set(SOUND_VOLUME
, global_settings
.volume
);
301 static void display_keylock_text(bool locked
)
305 #ifdef HAVE_LCD_CHARCELLS
307 s
= str(LANG_KEYLOCK_ON_PLAYER
);
309 s
= str(LANG_KEYLOCK_OFF_PLAYER
);
312 s
= str(LANG_KEYLOCK_ON_RECORDER
);
314 s
= str(LANG_KEYLOCK_OFF_RECORDER
);
319 static void waitfor_nokey(void)
321 /* wait until all keys are released */
322 while (button_get(false) != BUTTON_NONE
)
327 /* demonstrates showing different formats from playtune */
330 long button
= 0, lastbutton
= 0;
331 bool ignore_keyup
= true;
332 bool restore
= false;
333 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
335 bool update_track
= false;
338 current_track_path
[0] = '\0';
340 #ifdef HAVE_LCD_CHARCELLS
341 status_set_audio(true);
342 status_set_param(false);
344 if(global_settings
.statusbar
)
345 lcd_setmargins(0, STATUSBAR_HEIGHT
);
347 lcd_setmargins(0, 0);
352 if(audio_status() & AUDIO_STATUS_PLAY
)
354 id3
= audio_current_track();
355 nid3
= audio_next_track();
357 if (wps_display(id3
, nid3
))
359 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
361 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
369 bool audio_paused
= (audio_status() & AUDIO_STATUS_PAUSE
)?true:false;
371 /* did someone else (i.e power thread) change audio pause mode? */
372 if (paused
!= audio_paused
) {
373 paused
= audio_paused
;
375 /* if another thread paused audio, we are probably in car mode,
376 about to shut down. lets save the settings. */
379 #if !defined(HAVE_RTC) && !defined(HAVE_SW_POWEROFF)
385 #ifdef HAVE_LCD_BITMAP
386 /* when the peak meter is enabled we want to have a
387 few extra updates to make it look smooth. On the
388 other hand we don't want to waste energy if it
390 if (peak_meter_enabled
) {
393 /* In high performance mode we read out the mas as
394 often as we can. There is no sleep for cpu */
395 if (global_settings
.peak_meter_performance
) {
396 long next_refresh
= current_tick
;
397 long next_big_refresh
= current_tick
+ HZ
/ 5;
398 button
= BUTTON_NONE
;
399 while (!TIME_AFTER(current_tick
, next_big_refresh
)) {
400 button
= button_get(false);
401 if (button
!= BUTTON_NONE
) {
407 if (TIME_AFTER(current_tick
, next_refresh
)) {
408 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
409 next_refresh
= current_tick
+ HZ
/ peak_meter_fps
;
414 /* In energy saver mode the cpu may sleep a
415 little bit while waiting for buttons */
417 for (i
= 0; i
< 4; i
++) {
418 button
= button_get_w_tmo(HZ
/ peak_meter_fps
);
422 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
427 /* The peak meter is disabled
428 -> no additional screen updates needed */
430 button
= button_get_w_tmo(HZ
/5);
433 button
= button_get_w_tmo(HZ
/5);
436 /* discard first event if it's a button release */
437 if (button
&& ignore_keyup
)
439 ignore_keyup
= false;
440 /* Negative events are system events */
441 if (button
>= 0 && button
& BUTTON_REL
)
446 /* ignore non-remote buttons when keys are locked */
449 (button
== BUTTON_NONE
) ||
450 ((button
& WPS_KEYLOCK
) == WPS_KEYLOCK
) ||
451 (button
& BUTTON_REMOTE
)
454 if (!(button
& BUTTON_REL
))
455 display_keylock_text(true);
457 button
= BUTTON_NONE
;
461 /* Exit if audio has stopped playing. This can happen if using the
462 sleep timer with the charger plugged or if starting a recording
471 onplay(id3
->path
, TREE_ATTR_MPA
, CONTEXT_WPS
);
480 #ifdef WPS_BROWSE_PRE
481 if ((lastbutton
!= WPS_BROWSE_PRE
)
482 #ifdef WPS_RC_BROWSE_PRE
483 && (lastbutton
!= WPS_RC_BROWSE_PRE
)
488 #ifdef HAVE_LCD_CHARCELLS
489 status_set_record(false);
490 status_set_audio(false);
494 /* set dir browser to current playing song */
495 if (global_settings
.browse_current
&&
496 current_track_path
[0] != '\0')
497 set_current_file(current_track_path
);
505 if (lastbutton
!= WPS_PAUSE_PRE
)
510 #ifdef WPS_RC_PAUSE_PRE
511 if ((button
== WPS_RC_PAUSE
) && (lastbutton
!= WPS_RC_PAUSE_PRE
))
518 if ( global_settings
.fade_on_stop
)
526 if ( global_settings
.fade_on_stop
)
531 #if !defined(HAVE_RTC) && !defined(HAVE_SW_POWEROFF)
532 ata_flush(); /* make sure resume info is saved */
539 case WPS_INCVOL
| BUTTON_REPEAT
:
542 case WPS_RC_INCVOL
| BUTTON_REPEAT
:
544 global_settings
.volume
++;
547 restoretimer
= current_tick
+ HZ
;
553 case WPS_DECVOL
| BUTTON_REPEAT
:
556 case WPS_RC_DECVOL
| BUTTON_REPEAT
:
558 global_settings
.volume
--;
561 restoretimer
= current_tick
+ HZ
;
565 /* fast forward / rewind */
578 if (lastbutton
!= WPS_PREV_PRE
)
583 #ifdef WPS_RC_PREV_PRE
584 if ((button
== WPS_RC_PREV
) && (lastbutton
!= WPS_RC_PREV_PRE
))
588 if (!id3
|| (id3
->elapsed
< 3*1000)) {
605 if (lastbutton
!= WPS_NEXT_PRE
)
610 #ifdef WPS_RC_NEXT_PRE
611 if ((button
== WPS_RC_NEXT
) && (lastbutton
!= WPS_RC_NEXT_PRE
))
619 /* menu key functions */
622 if (lastbutton
!= WPS_MENU_PRE
)
627 #ifdef WPS_RC_MENU_PRE
628 if ((button
== WPS_RC_MENU
) && (lastbutton
!= WPS_RC_MENU_PRE
))
636 #ifdef HAVE_LCD_BITMAP
637 if (global_settings
.statusbar
)
638 lcd_setmargins(0, STATUSBAR_HEIGHT
);
640 lcd_setmargins(0, 0);
644 #endif /* WPS_MENU */
649 case WPS_KEYLOCK
| BUTTON_REPEAT
:
650 keys_locked
= !keys_locked
;
651 display_keylock_text(keys_locked
);
657 #if (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD)
660 if (quick_screen(CONTEXT_WPS
, WPS_QUICK
))
661 return SYS_USB_CONNECTED
;
666 /* screen settings */
669 if (quick_screen(CONTEXT_WPS
, BUTTON_F3
))
670 return SYS_USB_CONNECTED
;
676 #if CONFIG_KEYPAD == RECORDER_PAD
677 case BUTTON_ON
| BUTTON_REPEAT
:
678 if (2 == pitch_screen())
679 return SYS_USB_CONNECTED
;
685 /* stop and exit wps */
702 case BUTTON_NONE
: /* Timeout */
707 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
708 return SYS_USB_CONNECTED
;
716 /* set dir browser to current playing song */
717 if (global_settings
.browse_current
&&
718 current_track_path
[0] != '\0')
719 set_current_file(current_track_path
);
723 update_track
= false;
727 #ifdef HAVE_LCD_CHARCELLS
728 status_set_record(false);
729 status_set_audio(false);
731 if (global_settings
.fade_on_stop
)
735 bookmark_autobookmark();
738 /* Keys can be locked when exiting, so either unlock here
739 or implement key locking in tree.c too */
742 /* set dir browser to current playing song */
743 if (global_settings
.browse_current
&&
744 current_track_path
[0] != '\0')
745 set_current_file(current_track_path
);
754 ((restoretimer
== 0) ||
755 (restoretimer
< current_tick
)))
759 if (wps_display(id3
, nid3
))
761 /* set dir browser to current playing song */
762 if (global_settings
.browse_current
&&
763 current_track_path
[0] != '\0')
764 set_current_file(current_track_path
);
770 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
772 if (button
!= BUTTON_NONE
)
775 return 0; /* unreachable - just to reduce compiler warnings */