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 "gwps-common.h"
39 #include "main_menu.h"
43 #ifdef HAVE_LCD_BITMAP
45 #include "peakmeter.h"
58 #define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
59 #define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps"
60 /* currently only on wps_state is needed */
61 struct wps_state wps_state
;
62 struct gui_wps gui_wps
[NB_SCREENS
];
63 static struct wps_data wps_datas
[NB_SCREENS
];
65 bool keys_locked
= false;
67 /* change the path to the current played track */
68 static void wps_state_update_ctp(const char *path
);
70 #ifdef HAVE_LCD_BITMAP
71 static void gui_wps_set_margin(struct gui_wps
*gwps
)
74 struct wps_data
*data
= gwps
->data
;
75 if(data
->wps_sb_tag
&& data
->show_sb_on_wps
)
76 offset
= STATUSBAR_HEIGHT
;
77 else if ( global_settings
.statusbar
&& !data
->wps_sb_tag
)
78 offset
= STATUSBAR_HEIGHT
;
79 gwps
->display
->setmargins(0, offset
);
83 long gui_wps_show(void)
85 long button
= 0, lastbutton
= 0;
86 bool ignore_keyup
= true;
88 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
90 bool update_track
= false;
91 unsigned long right_lastclick
= 0;
92 unsigned long left_lastclick
= 0;
97 #ifdef HAVE_LCD_CHARCELLS
98 status_set_audio(true);
99 status_set_param(false);
103 gui_wps_set_margin(&gui_wps
[i
]);
107 #ifdef AB_REPEAT_ENABLE
112 if(audio_status() & AUDIO_STATUS_PLAY
)
114 wps_state
.id3
= audio_current_track();
115 wps_state
.nid3
= audio_next_track();
117 if (gui_wps_display())
120 gui_wps_refresh(&gui_wps
[i
], 0, WPS_REFRESH_ALL
);
121 wps_state_update_ctp(wps_state
.id3
->path
);
128 bool audio_paused
= (audio_status() & AUDIO_STATUS_PAUSE
)?true:false;
130 /* did someone else (i.e power thread) change audio pause mode? */
131 if (wps_state
.paused
!= audio_paused
) {
132 wps_state
.paused
= audio_paused
;
134 /* if another thread paused audio, we are probably in car mode,
135 about to shut down. lets save the settings. */
136 if (wps_state
.paused
) {
138 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
144 #ifdef HAVE_LCD_BITMAP
145 /* when the peak meter is enabled we want to have a
146 few extra updates to make it look smooth. On the
147 other hand we don't want to waste energy if it
152 if(gui_wps
[i
].data
->peak_meter_enabled
)
157 long next_refresh
= current_tick
;
158 long next_big_refresh
= current_tick
+ HZ
/ 5;
159 button
= BUTTON_NONE
;
160 while (TIME_BEFORE(current_tick
, next_big_refresh
)) {
161 button
= button_get(false);
162 if (button
!= BUTTON_NONE
) {
166 sleep(0); /* Sleep until end of current tick. */
168 if (TIME_AFTER(current_tick
, next_refresh
)) {
171 if(gui_wps
[i
].data
->peak_meter_enabled
)
172 gui_wps_refresh(&gui_wps
[i
], 0,
173 WPS_REFRESH_PEAK_METER
);
174 next_refresh
+= HZ
/ PEAK_METER_FPS
;
181 /* The peak meter is disabled
182 -> no additional screen updates needed */
184 button
= button_get_w_tmo(HZ
/5);
187 button
= button_get_w_tmo(HZ
/5);
190 /* discard first event if it's a button release */
191 if (button
&& ignore_keyup
)
193 ignore_keyup
= false;
194 /* Negative events are system events */
195 if (button
>= 0 && button
& BUTTON_REL
)
200 /* ignore non-remote buttons when keys are locked */
203 (button
== BUTTON_NONE
) ||
204 ((button
& WPS_KEYLOCK
) == WPS_KEYLOCK
) ||
205 (button
& BUTTON_REMOTE
)
208 if (!(button
& BUTTON_REL
))
209 display_keylock_text(true);
211 button
= BUTTON_NONE
;
215 /* Exit if audio has stopped playing. This can happen if using the
216 sleep timer with the charger plugged or if starting a recording
225 #ifdef WPS_RC_CONTEXT
228 onplay(wps_state
.id3
->path
, TREE_ATTR_MPA
, CONTEXT_WPS
);
229 #ifdef HAVE_LCD_BITMAP
232 gui_wps_set_margin(&gui_wps
[i
]);
243 #ifdef WPS_BROWSE_PRE
244 if ((lastbutton
!= WPS_BROWSE_PRE
)
245 #ifdef WPS_RC_BROWSE_PRE
246 && (lastbutton
!= WPS_RC_BROWSE_PRE
)
251 #ifdef HAVE_LCD_CHARCELLS
252 status_set_record(false);
253 status_set_audio(false);
256 gui_wps
[i
].display
->stop_scroll();
258 /* set dir browser to current playing song */
259 if (global_settings
.browse_current
&&
260 wps_state
.current_track_path
[0] != '\0')
261 set_current_file(wps_state
.current_track_path
);
269 if (lastbutton
!= WPS_PAUSE_PRE
)
274 #ifdef WPS_RC_PAUSE_PRE
275 if ((button
== WPS_RC_PAUSE
) &&
276 (lastbutton
!= WPS_RC_PAUSE_PRE
))
280 if ( wps_state
.paused
)
282 wps_state
.paused
= false;
283 if ( global_settings
.fade_on_stop
)
290 wps_state
.paused
= true;
291 if ( global_settings
.fade_on_stop
)
296 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
297 ata_flush(); /* make sure resume info is saved */
304 case WPS_INCVOL
| BUTTON_REPEAT
:
307 case WPS_RC_INCVOL
| BUTTON_REPEAT
:
310 global_settings
.volume
++;
315 if(update_onvol_change(&gui_wps
[i
]))
320 restoretimer
= current_tick
+ HZ
;
327 case WPS_DECVOL
| BUTTON_REPEAT
:
330 case WPS_RC_DECVOL
| BUTTON_REPEAT
:
333 global_settings
.volume
--;
338 if(update_onvol_change(&gui_wps
[i
]))
343 restoretimer
= current_tick
+ HZ
;
348 /* fast forward / rewind */
354 if (current_tick
- right_lastclick
< HZ
)
366 if (current_tick
- left_lastclick
< HZ
)
379 if (lastbutton
!= WPS_PREV_PRE
)
384 #ifdef WPS_RC_PREV_PRE
385 if ((button
== WPS_RC_PREV
) && (lastbutton
!= WPS_RC_PREV_PRE
))
389 left_lastclick
= current_tick
;
392 #ifdef AB_REPEAT_ENABLE
393 /* if we're in A/B repeat mode and the current position
394 is past the A marker, jump back to the A marker... */
395 if ( ab_repeat_mode_enabled()
396 && ab_after_A_marker(wps_state
.id3
->elapsed
) )
398 ab_jump_to_A_marker();
401 /* ...otherwise, do it normally */
404 if (!wps_state
.id3
|| (wps_state
.id3
->elapsed
< 3*1000)) {
408 if (!wps_state
.paused
)
413 if (!wps_state
.paused
)
419 #ifdef WPS_RC_NEXT_DIR
420 case WPS_RC_NEXT_DIR
:
427 #ifdef WPS_RC_PREV_DIR
428 case WPS_RC_PREV_DIR
:
438 if (lastbutton
!= WPS_NEXT_PRE
)
443 #ifdef WPS_RC_NEXT_PRE
444 if ((button
== WPS_RC_NEXT
) && (lastbutton
!= WPS_RC_NEXT_PRE
))
448 right_lastclick
= current_tick
;
451 #ifdef AB_REPEAT_ENABLE
452 /* if we're in A/B repeat mode and the current position is
453 before the A marker, jump to the A marker... */
454 if ( ab_repeat_mode_enabled()
455 && ab_before_A_marker(wps_state
.id3
->elapsed
) )
457 ab_jump_to_A_marker();
460 /* ...otherwise, do it normally */
467 /* menu key functions */
470 if (lastbutton
!= WPS_MENU_PRE
)
475 #ifdef WPS_RC_MENU_PRE
476 if ((button
== WPS_RC_MENU
) && (lastbutton
!= WPS_RC_MENU_PRE
))
481 gui_wps
[i
].display
->stop_scroll();
485 #ifdef HAVE_LCD_BITMAP
488 gui_wps_set_margin(&gui_wps
[i
]);
493 #endif /* WPS_MENU */
498 case WPS_KEYLOCK
| BUTTON_REPEAT
:
499 keys_locked
= !keys_locked
;
500 display_keylock_text(keys_locked
);
506 #if (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD) \
507 || (CONFIG_KEYPAD == IRIVER_H300_PAD)
513 if (quick_screen_quick(button
))
514 return SYS_USB_CONNECTED
;
515 #ifdef HAVE_LCD_BITMAP
518 gui_wps_set_margin(&gui_wps
[i
]);
525 /* screen settings */
528 if (quick_screen_f3(button
))
529 return SYS_USB_CONNECTED
;
535 #if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD \
536 || CONFIG_KEYPAD == IRIVER_H300_PAD
537 case BUTTON_ON
| BUTTON_UP
:
538 case BUTTON_ON
| BUTTON_DOWN
:
539 if (2 == pitch_screen())
540 return SYS_USB_CONNECTED
;
546 #ifdef AB_REPEAT_ENABLE
548 #ifdef WPS_AB_SET_A_MARKER
549 /* set A marker for A-B repeat */
550 case WPS_AB_SET_A_MARKER
:
551 if (ab_repeat_mode_enabled())
552 ab_set_A_marker(wps_state
.id3
->elapsed
);
556 #ifdef WPS_AB_SET_B_MARKER
557 /* set B marker for A-B repeat and jump to A */
558 case WPS_AB_SET_B_MARKER
:
559 if (ab_repeat_mode_enabled())
561 ab_set_B_marker(wps_state
.id3
->elapsed
);
562 ab_jump_to_A_marker();
568 #ifdef WPS_AB_RESET_AB_MARKERS
569 /* reset A&B markers */
570 case WPS_AB_RESET_AB_MARKERS
:
571 if (ab_repeat_mode_enabled())
579 #endif /* AB_REPEAT_ENABLE */
581 /* stop and exit wps */
585 if (lastbutton
!= WPS_EXIT_PRE
)
591 #ifdef WPS_RC_EXIT_PRE
592 if (lastbutton
!= WPS_RC_EXIT_PRE
)
607 case BUTTON_NONE
: /* Timeout */
612 bookmark_autobookmark();
613 default_event_handler(SYS_POWEROFF
);
617 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
618 return SYS_USB_CONNECTED
;
625 bool update_failed
= false;
628 if(update(&gui_wps
[i
]))
629 update_failed
= true;
633 /* set dir browser to current playing song */
634 if (global_settings
.browse_current
&&
635 wps_state
.current_track_path
[0] != '\0')
636 set_current_file(wps_state
.current_track_path
);
640 update_track
= false;
644 #ifdef HAVE_LCD_CHARCELLS
645 status_set_record(false);
646 status_set_audio(false);
648 if (global_settings
.fade_on_stop
)
652 gui_wps
[i
].display
->stop_scroll();
653 bookmark_autobookmark();
655 #ifdef AB_REPEAT_ENABLE
659 /* Keys can be locked when exiting, so either unlock here
660 or implement key locking in tree.c too */
663 /* set dir browser to current playing song */
664 if (global_settings
.browse_current
&&
665 wps_state
.current_track_path
[0] != '\0')
666 set_current_file(wps_state
.current_track_path
);
675 ((restoretimer
== 0) ||
676 (restoretimer
< current_tick
)))
680 if (gui_wps_display())
682 /* set dir browser to current playing song */
683 if (global_settings
.browse_current
&&
684 wps_state
.current_track_path
[0] != '\0')
685 set_current_file(wps_state
.current_track_path
);
692 gui_wps_refresh(&gui_wps
[i
], 0, WPS_REFRESH_NON_STATIC
);
695 if (button
!= BUTTON_NONE
)
698 return 0; /* unreachable - just to reduce compiler warnings */
701 /* needs checking if needed end*/
704 /* initial setup of wps_data */
705 void wps_data_init(struct wps_data
*wps_data
)
708 #ifdef HAVE_LCD_BITMAP
709 for (i
= 0; i
< MAX_IMAGES
; i
++) {
710 wps_data
->img
[i
].loaded
= false;
711 wps_data
->img
[i
].display
= false;
712 wps_data
->img
[i
].always_display
= false;
714 wps_data
->wps_sb_tag
= false;
715 wps_data
->show_sb_on_wps
= false;
716 #else /* HAVE_LCD_CHARCELLS */
717 for(i
= 0; i
< 8; i
++)
718 wps_data
->wps_progress_pat
[i
] = 0;
719 wps_data
->full_line_progressbar
= 0;
721 wps_data
->format_buffer
[0] = '\0';
722 wps_data
->wps_loaded
= false;
723 wps_data
->peak_meter_enabled
= false;
726 #ifdef HAVE_LCD_BITMAP
727 /* Clear the WPS image cache */
728 static void wps_clear(struct wps_data
*data
)
731 /* set images to unloaded and not displayed */
732 for (i
= 0; i
< MAX_IMAGES
; i
++) {
733 data
->img
[i
].loaded
= false;
734 data
->img
[i
].display
= false;
735 data
->img
[i
].always_display
= false;
737 data
->wps_sb_tag
= false;
738 data
->show_sb_on_wps
= false;
744 static void wps_reset(struct wps_data
*data
)
746 data
->wps_loaded
= false;
747 memset(&data
->format_buffer
, 0, sizeof data
->format_buffer
);
751 /* to setup up the wps-data from a format-buffer (isfile = false)
752 from a (wps-)file (isfile = true)*/
753 bool wps_data_load(struct wps_data
*wps_data
,
761 if(!wps_data
|| !buf
)
767 strncpy(wps_data
->format_buffer
, buf
, sizeof(wps_data
->format_buffer
));
768 wps_data
->format_buffer
[sizeof(wps_data
->format_buffer
) - 1] = 0;
769 gui_wps_format(wps_data
);
775 * Hardcode loading WPS_DEFAULTCFG to cause a reset ideally this
776 * wants to be a virtual file. Feel free to modify dirbrowse()
777 * if you're feeling brave.
779 if (! strcmp(buf
, WPS_DEFAULTCFG
) )
782 global_settings
.wps_file
[0] = 0;
786 #ifdef HAVE_REMOTE_LCD
787 if (! strcmp(buf
, RWPS_DEFAULTCFG
) )
790 global_settings
.rwps_file
[0] = 0;
796 char *bmpdir
= strrchr(buf
, '.');
797 bmpdirlen
= bmpdir
- buf
;
799 fd
= open(buf
, O_RDONLY
);
803 unsigned int start
= 0;
806 #ifdef HAVE_LCD_BITMAP
807 wps_data
->img_buf_ptr
= wps_data
->img_buf
; /* where in image buffer */
809 wps_data
->img_buf_free
= IMG_BUFSIZE
; /* free space in image buffer */
811 while( ( read_line(fd
, &wps_data
->format_buffer
[start
],
812 sizeof(wps_data
->format_buffer
)-start
) ) > 0 )
814 if(!wps_data_preload_tags(wps_data
,
815 &wps_data
->format_buffer
[start
],
818 start
+= strlen(&wps_data
->format_buffer
[start
]);
820 if (start
< sizeof(wps_data
->format_buffer
) - 1)
822 wps_data
->format_buffer
[start
++] = '\n';
823 wps_data
->format_buffer
[start
] = 0;
830 gui_wps_format(wps_data
);
836 bool any_defined_line
;
839 screens
[z
].clear_display();
840 #ifdef HAVE_LCD_BITMAP
842 screens
[z
].setmargins(0,0);
844 for (s
=0; s
<WPS_MAX_SUBLINES
; s
++)
846 any_defined_line
= false;
847 for (i
=0; i
<WPS_MAX_LINES
; i
++)
849 if (wps_data
->format_lines
[i
][s
] &&
850 wps_data
->format_lines
[i
][s
][0])
853 screens
[z
].puts(0, i
,
856 any_defined_line
= true;
861 screens
[z
].puts(0, i
, " ");
864 if (any_defined_line
)
866 #ifdef HAVE_LCD_BITMAP
874 wps_data
->wps_loaded
= true;
887 void wps_state_init(void)
889 wps_state
.ff_rewind
= false;
890 wps_state
.paused
= false;
891 wps_state
.id3
= NULL
;
892 wps_state
.nid3
= NULL
;
893 wps_state
.current_track_path
[0] = '\0';
897 /* these are obviously not used? */
899 void wps_state_update_ff_rew(bool ff_rew
)
901 wps_state
.ff_rewind
= ff_rew
;
904 void wps_state_update_paused(bool paused
)
906 wps_state
.paused
= paused
;
908 void wps_state_update_id3_nid3(struct mp3entry
*id3
, struct mp3entry
*nid3
)
911 wps_state
.nid3
= nid3
;
915 static void wps_state_update_ctp(const char *path
)
917 memcpy(wps_state
.current_track_path
, path
,
918 sizeof(wps_state
.current_track_path
));
922 /* initial setup of a wps */
923 void gui_wps_init(struct gui_wps
*gui_wps
)
925 gui_wps
->data
= NULL
;
926 gui_wps
->display
= NULL
;
927 gui_wps
->statusbar
= NULL
;
928 /* Currently no seperate wps_state needed/possible
929 so use the only aviable ( "global" ) one */
930 gui_wps
->state
= &wps_state
;
933 /* connects a wps with a format-description of the displayed content */
934 void gui_wps_set_data(struct gui_wps
*gui_wps
, struct wps_data
*data
)
936 gui_wps
->data
= data
;
939 /* connects a wps with a screen */
940 void gui_wps_set_disp(struct gui_wps
*gui_wps
, struct screen
*display
)
942 gui_wps
->display
= display
;
945 void gui_wps_set_statusbar(struct gui_wps
*gui_wps
, struct gui_statusbar
*statusbar
)
947 gui_wps
->statusbar
= statusbar
;
951 void gui_sync_wps_screen_init(void)
955 gui_wps_set_disp(&gui_wps
[i
], &screens
[i
]);
958 void gui_sync_wps_init(void)
963 wps_data_init(&wps_datas
[i
]);
964 gui_wps_init(&gui_wps
[i
]);
965 gui_wps_set_data(&gui_wps
[i
], &wps_datas
[i
]);
966 gui_wps_set_statusbar(&gui_wps
[i
], &statusbars
.statusbars
[i
]);