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 ****************************************************************************/
28 #include "backlight.h"
31 #include "filetypes.h"
36 #include "gwps-common.h"
43 #ifdef HAVE_LCD_BITMAP
45 #include "peakmeter.h"
57 #include "ata_idle_notify.h"
58 #include "root_menu.h"
61 /* currently only on wps_state is needed */
62 struct wps_state wps_state
;
63 struct gui_wps gui_wps
[NB_SCREENS
];
64 static struct wps_data wps_datas
[NB_SCREENS
];
66 /* change the path to the current played track */
67 static void wps_state_update_ctp(const char *path
);
68 /* initial setup of wps_data */
69 static void wps_state_init(void);
70 /* initial setup of a wps */
71 static void gui_wps_init(struct gui_wps
*gui_wps
);
72 /* connects a wps with a format-description of the displayed content */
73 static void gui_wps_set_data(struct gui_wps
*gui_wps
, struct wps_data
*data
);
74 /* connects a wps with a screen */
75 static void gui_wps_set_disp(struct gui_wps
*gui_wps
, struct screen
*display
);
76 /* connects a wps with a statusbar*/
77 static void gui_wps_set_statusbar(struct gui_wps
*gui_wps
, struct gui_statusbar
*statusbar
);
79 #ifdef HAVE_LCD_BITMAP
80 static void gui_wps_set_margin(struct gui_wps
*gwps
)
83 struct wps_data
*data
= gwps
->data
;
84 if(data
->wps_sb_tag
&& data
->show_sb_on_wps
)
85 offset
= STATUSBAR_HEIGHT
;
86 else if ( global_settings
.statusbar
&& !data
->wps_sb_tag
)
87 offset
= STATUSBAR_HEIGHT
;
88 gwps
->display
->setmargins(0, offset
);
92 long gui_wps_show(void)
96 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
98 bool bookmark
= false;
99 bool update_track
= false;
101 long last_left
= 0, last_right
= 0;
105 #ifdef HAVE_LCD_CHARCELLS
106 status_set_audio(true);
107 status_set_param(false);
111 gui_wps_set_margin(&gui_wps
[i
]);
115 #endif /* LCD_DEPTH > 1 */
118 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
119 show_remote_wps_backdrop();
122 #ifdef AB_REPEAT_ENABLE
127 if(audio_status() & AUDIO_STATUS_PLAY
)
129 wps_state
.id3
= audio_current_track();
130 wps_state
.nid3
= audio_next_track();
132 if (gui_wps_display())
135 gui_wps_refresh(&gui_wps
[i
], 0, WPS_REFRESH_ALL
);
136 wps_state_update_ctp(wps_state
.id3
->path
);
143 bool audio_paused
= (audio_status() & AUDIO_STATUS_PAUSE
)?true:false;
145 /* did someone else (i.e power thread) change audio pause mode? */
146 if (wps_state
.paused
!= audio_paused
) {
147 wps_state
.paused
= audio_paused
;
149 /* if another thread paused audio, we are probably in car mode,
150 about to shut down. lets save the settings. */
151 if (wps_state
.paused
) {
153 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
154 call_ata_idle_notifys(true);
159 #ifdef HAVE_LCD_BITMAP
160 /* when the peak meter is enabled we want to have a
161 few extra updates to make it look smooth. On the
162 other hand we don't want to waste energy if it
167 if(gui_wps
[i
].data
->peak_meter_enabled
)
172 long next_refresh
= current_tick
;
173 long next_big_refresh
= current_tick
+ HZ
/ 5;
174 button
= BUTTON_NONE
;
175 while (TIME_BEFORE(current_tick
, next_big_refresh
)) {
176 button
= get_action(CONTEXT_WPS
|ALLOW_SOFTLOCK
,TIMEOUT_NOBLOCK
);
177 if (button
!= ACTION_NONE
) {
181 sleep(0); /* Sleep until end of current tick. */
183 if (TIME_AFTER(current_tick
, next_refresh
)) {
186 if(gui_wps
[i
].data
->peak_meter_enabled
)
187 gui_wps_refresh(&gui_wps
[i
], 0,
188 WPS_REFRESH_PEAK_METER
);
189 next_refresh
+= HZ
/ PEAK_METER_FPS
;
196 /* The peak meter is disabled
197 -> no additional screen updates needed */
199 button
= get_action(CONTEXT_WPS
|ALLOW_SOFTLOCK
,HZ
/5);
202 button
= get_action(CONTEXT_WPS
|ALLOW_SOFTLOCK
,HZ
/5);
205 /* Exit if audio has stopped playing. This can happen if using the
206 sleep timer with the charger plugged or if starting a recording
210 #ifdef ACTION_WPSAB_SINGLE
211 if (!global_settings
.party_mode
&& ab_repeat_mode_enabled())
213 static int wps_ab_state
= 0;
214 if (button
== ACTION_WPSAB_SINGLE
)
216 switch (wps_ab_state
)
218 case 0: /* set the A spot */
219 button
= ACTION_WPS_ABSETA_PREVDIR
;
221 case 1: /* set the B spot */
222 button
= ACTION_WPS_ABSETB_NEXTDIR
;
225 button
= ACTION_WPS_ABRESET
;
228 wps_ab_state
= (wps_ab_state
+1) % 3;
234 case ACTION_WPS_CONTEXT
:
236 show_main_backdrop();
238 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
239 show_remote_main_backdrop();
241 /* if music is stopped in the context menu we want to exit the wps */
242 if (onplay(wps_state
.id3
->path
,
243 FILE_ATTR_AUDIO
, CONTEXT_WPS
) == ONPLAY_MAINMENU
247 /* track might have changed */
253 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
254 show_remote_wps_backdrop();
256 #ifdef HAVE_LCD_BITMAP
259 gui_wps_set_margin(&gui_wps
[i
]);
265 case ACTION_WPS_BROWSE
:
266 #ifdef HAVE_LCD_CHARCELLS
267 status_set_record(false);
268 status_set_audio(false);
271 gui_wps
[i
].display
->stop_scroll();
272 return GO_TO_PREVIOUS_BROWSER
;
276 case ACTION_WPS_PLAY
:
277 if (global_settings
.party_mode
)
279 if ( wps_state
.paused
)
281 wps_state
.paused
= false;
282 if ( global_settings
.fade_on_stop
)
289 wps_state
.paused
= true;
290 if ( global_settings
.fade_on_stop
)
295 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
296 call_ata_idle_notifys(true); /* make sure resume info is saved */
302 case ACTION_WPS_VOLUP
:
304 global_settings
.volume
++;
309 if(update_onvol_change(&gui_wps
[i
]))
314 restoretimer
= current_tick
+ HZ
;
320 case ACTION_WPS_VOLDOWN
:
322 global_settings
.volume
--;
327 if(update_onvol_change(&gui_wps
[i
]))
332 restoretimer
= current_tick
+ HZ
;
337 OR next dir if this is straight after ACTION_WPS_SKIPNEXT */
338 case ACTION_WPS_SEEKFWD
:
339 if (global_settings
.party_mode
)
341 if (current_tick
-last_right
< HZ
)
343 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
352 else ffwd_rew(ACTION_WPS_SEEKFWD
);
356 OR prev dir if this is straight after ACTION_WPS_SKIPPREV */
357 case ACTION_WPS_SEEKBACK
:
358 if (global_settings
.party_mode
)
360 if (current_tick
-last_left
< HZ
)
362 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
364 if (!wps_state
.paused
)
365 #if (CONFIG_CODEC == SWCODEC)
366 audio_pre_ff_rewind();
377 else ffwd_rew(ACTION_WPS_SEEKBACK
);
382 case ACTION_WPS_SKIPPREV
:
383 if (global_settings
.party_mode
)
385 last_left
= current_tick
;
388 #ifdef AB_REPEAT_ENABLE
389 /* if we're in A/B repeat mode and the current position
390 is past the A marker, jump back to the A marker... */
391 if ( ab_repeat_mode_enabled() )
393 if ( ab_after_A_marker(wps_state
.id3
->elapsed
) )
395 ab_jump_to_A_marker();
397 #if (AB_REPEAT_ENABLE == 2)
403 /* ...otherwise, do it normally */
406 if (!wps_state
.id3
|| (wps_state
.id3
->elapsed
< 3*1000)) {
411 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
413 curr_cuesheet_skip(-1, wps_state
.id3
->elapsed
);
417 if (!wps_state
.paused
)
418 #if (CONFIG_CODEC == SWCODEC)
419 audio_pre_ff_rewind();
426 #if (CONFIG_CODEC != SWCODEC)
427 if (!wps_state
.paused
)
434 case ACTION_WPS_SKIPNEXT
:
435 if (global_settings
.party_mode
)
437 last_right
= current_tick
;
440 #ifdef AB_REPEAT_ENABLE
441 /* if we're in A/B repeat mode and the current position is
442 before the A marker, jump to the A marker... */
443 if ( ab_repeat_mode_enabled() )
445 if ( ab_before_A_marker(wps_state
.id3
->elapsed
) )
447 ab_jump_to_A_marker();
449 #if (AB_REPEAT_ENABLE == 2)
455 /* ...otherwise, do it normally */
458 /* take care of if we're playing a cuesheet */
459 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
461 if (curr_cuesheet_skip(1, wps_state
.id3
->elapsed
))
463 /* if the result was false, then we really want
464 to skip to the next track */
471 /* next / prev directories */
472 /* and set A-B markers if in a-b mode */
473 case ACTION_WPS_ABSETB_NEXTDIR
:
474 if (global_settings
.party_mode
)
476 #if defined(AB_REPEAT_ENABLE)
477 if (ab_repeat_mode_enabled())
479 ab_set_B_marker(wps_state
.id3
->elapsed
);
480 ab_jump_to_A_marker();
489 case ACTION_WPS_ABSETA_PREVDIR
:
490 if (global_settings
.party_mode
)
492 #if defined(AB_REPEAT_ENABLE)
493 if (ab_repeat_mode_enabled())
494 ab_set_A_marker(wps_state
.id3
->elapsed
);
501 /* menu key functions */
502 case ACTION_WPS_MENU
:
504 gui_wps
[i
].display
->stop_scroll();
509 #ifdef HAVE_QUICKSCREEN
510 case ACTION_WPS_QUICKSCREEN
:
512 show_main_backdrop();
514 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
515 show_remote_main_backdrop();
517 if (quick_screen_quick(button
))
518 return SYS_USB_CONNECTED
;
522 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
523 show_remote_wps_backdrop();
525 #ifdef HAVE_LCD_BITMAP
528 gui_wps_set_margin(&gui_wps
[i
]);
533 #endif /* HAVE_QUICKSCREEN */
535 /* screen settings */
539 show_main_backdrop();
541 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
542 show_remote_main_backdrop();
544 if (quick_screen_f3(BUTTON_F3
))
545 return SYS_USB_CONNECTED
;
546 #ifdef HAVE_LCD_BITMAP
549 gui_wps_set_margin(&gui_wps
[i
]);
554 #endif /* BUTTON_F3 */
557 #ifdef HAVE_PITCHSCREEN
558 case ACTION_WPS_PITCHSCREEN
:
560 show_main_backdrop();
562 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
563 show_remote_main_backdrop();
565 if (1 == pitch_screen())
566 return SYS_USB_CONNECTED
;
570 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
571 show_remote_wps_backdrop();
575 #endif /* HAVE_PITCHSCREEN */
577 #ifdef AB_REPEAT_ENABLE
578 /* reset A&B markers */
579 case ACTION_WPS_ABRESET
:
580 if (ab_repeat_mode_enabled())
586 #endif /* AB_REPEAT_ENABLE */
588 /* stop and exit wps */
589 case ACTION_WPS_STOP
:
590 if (global_settings
.party_mode
)
596 case ACTION_WPS_ID3SCREEN
:
598 show_main_backdrop();
600 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
601 show_remote_main_backdrop();
607 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
608 show_remote_wps_backdrop();
610 #ifdef HAVE_LCD_BITMAP
613 gui_wps_set_margin(&gui_wps
[i
]);
619 case ACTION_REDRAW
: /* yes are locked, just redraw */
622 case ACTION_NONE
: /* Timeout */
624 ffwd_rew(button
); /* hopefully fix the ffw/rwd bug */
626 #ifdef HAVE_RECORDING
633 show_main_backdrop();
635 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
636 show_remote_main_backdrop();
638 default_event_handler(SYS_POWEROFF
);
642 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
652 if(update(&gui_wps
[i
]))
655 update_track
= false;
659 ((restoretimer
== 0) ||
660 (restoretimer
< current_tick
)))
664 if (gui_wps_display()) {
667 else if (wps_state
.id3
){
669 gui_wps_refresh(&gui_wps
[i
], 0, WPS_REFRESH_NON_STATIC
);
674 #ifdef HAVE_LCD_CHARCELLS
675 status_set_record(false);
676 status_set_audio(false);
678 if (global_settings
.fade_on_stop
)
682 gui_wps
[i
].display
->stop_scroll();
684 bookmark_autobookmark();
686 #ifdef AB_REPEAT_ENABLE
689 #ifdef HAVE_RECORDING
690 if (button
== ACTION_WPS_REC
)
691 return GO_TO_RECSCREEN
;
693 if (global_settings
.browse_current
)
694 return GO_TO_PREVIOUS_BROWSER
;
695 return GO_TO_PREVIOUS
;
701 return GO_TO_ROOT
; /* unreachable - just to reduce compiler warnings */
704 /* needs checking if needed end*/
708 static void wps_state_init(void)
710 wps_state
.ff_rewind
= false;
711 wps_state
.paused
= false;
712 wps_state
.id3
= NULL
;
713 wps_state
.nid3
= NULL
;
714 wps_state
.current_track_path
[0] = '\0';
718 /* these are obviously not used? */
720 void wps_state_update_ff_rew(bool ff_rew
)
722 wps_state
.ff_rewind
= ff_rew
;
725 void wps_state_update_paused(bool paused
)
727 wps_state
.paused
= paused
;
729 void wps_state_update_id3_nid3(struct mp3entry
*id3
, struct mp3entry
*nid3
)
732 wps_state
.nid3
= nid3
;
736 static void wps_state_update_ctp(const char *path
)
738 strncpy(wps_state
.current_track_path
, path
,
739 sizeof(wps_state
.current_track_path
));
740 wps_state
.current_track_path
[sizeof(wps_state
.current_track_path
)-1] = '\0';
744 /* initial setup of a wps */
745 static void gui_wps_init(struct gui_wps
*gui_wps
)
747 gui_wps
->data
= NULL
;
748 gui_wps
->display
= NULL
;
749 gui_wps
->statusbar
= NULL
;
750 /* Currently no seperate wps_state needed/possible
751 so use the only aviable ( "global" ) one */
752 gui_wps
->state
= &wps_state
;
755 /* connects a wps with a format-description of the displayed content */
756 static void gui_wps_set_data(struct gui_wps
*gui_wps
, struct wps_data
*data
)
758 gui_wps
->data
= data
;
761 /* connects a wps with a screen */
762 static void gui_wps_set_disp(struct gui_wps
*gui_wps
, struct screen
*display
)
764 gui_wps
->display
= display
;
767 static void gui_wps_set_statusbar(struct gui_wps
*gui_wps
, struct gui_statusbar
*statusbar
)
769 gui_wps
->statusbar
= statusbar
;
773 void gui_sync_wps_screen_init(void)
777 gui_wps_set_disp(&gui_wps
[i
], &screens
[i
]);
780 void gui_sync_wps_init(void)
785 wps_data_init(&wps_datas
[i
]);
786 #ifdef HAVE_REMOTE_LCD
787 wps_datas
[i
].remote_wps
= (i
!= 0);
789 gui_wps_init(&gui_wps
[i
]);
790 gui_wps_set_data(&gui_wps
[i
], &wps_datas
[i
]);
791 gui_wps_set_statusbar(&gui_wps
[i
], &statusbars
.statusbars
[i
]);
794 unload_wps_backdrop();
796 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
797 unload_remote_wps_backdrop();
802 /* Returns true if at least one of the gui_wps screens has an album art
803 tag in its wps structure */
804 bool gui_sync_wps_uses_albumart(void)
808 struct gui_wps
*gwps
= &gui_wps
[i
];
809 if (gwps
->data
&& (gwps
->data
->wps_uses_albumart
!= WPS_ALBUMART_NONE
))