diff options
-rw-r--r-- | apps/SOURCES | 1 | ||||
-rw-r--r-- | apps/abrepeat.c | 251 | ||||
-rw-r--r-- | apps/abrepeat.h | 48 | ||||
-rw-r--r-- | apps/bookmark.c | 7 | ||||
-rw-r--r-- | apps/lang/english.lang | 6 | ||||
-rw-r--r-- | apps/playlist.c | 10 | ||||
-rw-r--r-- | apps/recorder/icons.c | 1 | ||||
-rw-r--r-- | apps/recorder/icons.h | 1 | ||||
-rw-r--r-- | apps/screens.c | 9 | ||||
-rw-r--r-- | apps/settings.c | 4 | ||||
-rw-r--r-- | apps/settings.h | 16 | ||||
-rw-r--r-- | apps/settings_menu.c | 6 | ||||
-rw-r--r-- | apps/status.c | 7 | ||||
-rw-r--r-- | apps/wps-display.c | 20 | ||||
-rw-r--r-- | apps/wps.c | 74 | ||||
-rw-r--r-- | apps/wps.h | 12 | ||||
-rw-r--r-- | firmware/export/audio.h | 40 | ||||
-rw-r--r-- | firmware/export/config-fmrecorder.h | 2 | ||||
-rw-r--r-- | firmware/export/config-player.h | 2 | ||||
-rw-r--r-- | firmware/export/config-recorder.h | 2 | ||||
-rw-r--r-- | firmware/export/config-recorderv2.h | 2 | ||||
-rw-r--r-- | firmware/mpeg.c | 68 |
22 files changed, 566 insertions, 23 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index e8fd2d2ddb..3c933d22b6 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -2,6 +2,7 @@ | |||
2 | logfdisp.c | 2 | logfdisp.c |
3 | #endif | 3 | #endif |
4 | alarm_menu.c | 4 | alarm_menu.c |
5 | abrepeat.c | ||
5 | bookmark.c | 6 | bookmark.c |
6 | credits.c | 7 | credits.c |
7 | debug_menu.c | 8 | debug_menu.c |
diff --git a/apps/abrepeat.c b/apps/abrepeat.c new file mode 100644 index 0000000000..3a3d5b394d --- /dev/null +++ b/apps/abrepeat.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Ray Lambert | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "abrepeat.h" | ||
21 | |||
22 | #include "settings.h" | ||
23 | #include "audio.h" | ||
24 | #include "kernel.h" | ||
25 | |||
26 | #ifdef HAVE_LCD_BITMAP | ||
27 | #include "lcd.h" | ||
28 | #endif | ||
29 | |||
30 | #ifdef AB_REPEAT_ENABLE | ||
31 | |||
32 | static int ab_audio_event_handler(unsigned short event, unsigned long data) | ||
33 | { | ||
34 | int rc = AUDIO_EVENT_RC_IGNORED; | ||
35 | if ( ab_repeat_mode_enabled() ) | ||
36 | { | ||
37 | switch(event) | ||
38 | { | ||
39 | case AUDIO_EVENT_POS_REPORT: | ||
40 | { | ||
41 | if ( ! (audio_status() & AUDIO_STATUS_PAUSE) && ab_reached_B_marker(data) ) | ||
42 | { | ||
43 | ab_jump_to_A_marker(); | ||
44 | rc = AUDIO_EVENT_RC_HANDLED; | ||
45 | } | ||
46 | break; | ||
47 | } | ||
48 | case AUDIO_EVENT_END_OF_TRACK: | ||
49 | { | ||
50 | if ( ab_A_marker_set() && ! ab_B_marker_set() ) | ||
51 | { | ||
52 | ab_jump_to_A_marker(); | ||
53 | rc = AUDIO_EVENT_RC_HANDLED; | ||
54 | } | ||
55 | break; | ||
56 | } | ||
57 | } | ||
58 | } | ||
59 | return rc; | ||
60 | } | ||
61 | |||
62 | void ab_repeat_init(void) | ||
63 | { | ||
64 | static bool ab_initialized = false; | ||
65 | if ( ! ab_initialized ) | ||
66 | { | ||
67 | ab_initialized = true; | ||
68 | audio_register_event_handler(ab_audio_event_handler, | ||
69 | AUDIO_EVENT_POS_REPORT | AUDIO_EVENT_END_OF_TRACK ); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static unsigned int ab_A_marker = AB_MARKER_NONE; | ||
74 | static unsigned int ab_B_marker = AB_MARKER_NONE; | ||
75 | |||
76 | bool ab_repeat_mode_enabled(void) | ||
77 | { | ||
78 | extern struct user_settings global_settings; | ||
79 | return global_settings.repeat_mode == REPEAT_AB; | ||
80 | } | ||
81 | |||
82 | bool ab_A_marker_set(void) | ||
83 | { | ||
84 | return ab_A_marker != AB_MARKER_NONE; | ||
85 | } | ||
86 | |||
87 | bool ab_B_marker_set(void) | ||
88 | { | ||
89 | return ab_B_marker != AB_MARKER_NONE; | ||
90 | } | ||
91 | |||
92 | unsigned int ab_get_A_marker(void) | ||
93 | { | ||
94 | return ab_A_marker; | ||
95 | } | ||
96 | |||
97 | unsigned int ab_get_B_marker(void) | ||
98 | { | ||
99 | return ab_B_marker; | ||
100 | } | ||
101 | |||
102 | bool ab_reached_B_marker(unsigned int song_position) | ||
103 | { | ||
104 | /* following is the size of the window in which we'll detect that the B marker | ||
105 | was hit; it must be larger than the frequency (in milliseconds) at which this | ||
106 | function is called otherwise detection of the B marker will be unreliable; | ||
107 | we assume that this function will be called on each system tick and derive | ||
108 | the window size from this with a generous margin of error (note: the number | ||
109 | of ticks per second is given by HZ) */ | ||
110 | #define B_MARKER_DETECT_WINDOW ((1000/HZ)*10) | ||
111 | if (ab_B_marker != AB_MARKER_NONE) | ||
112 | { | ||
113 | if ( (song_position >= ab_B_marker) | ||
114 | && (song_position <= (ab_B_marker+B_MARKER_DETECT_WINDOW)) ) | ||
115 | return true; | ||
116 | } | ||
117 | return false; | ||
118 | } | ||
119 | |||
120 | /* determines if the given song position is earlier than the A mark; | ||
121 | intended for use in handling the jump NEXT and PREV commands */ | ||
122 | bool ab_before_A_marker(unsigned int song_position) | ||
123 | { | ||
124 | return (ab_A_marker != AB_MARKER_NONE) | ||
125 | && (song_position < ab_A_marker); | ||
126 | } | ||
127 | |||
128 | /* determines if the given song position is later than the A mark; | ||
129 | intended for use in handling the jump PREV command */ | ||
130 | bool ab_after_A_marker(unsigned int song_position) | ||
131 | { | ||
132 | /* following is the size of the virtual A marker; we pretend that the A marker is | ||
133 | larger than a single instant in order to give the user time to hit PREV again to | ||
134 | jump back to the start of the song; it should be large enough to allow a | ||
135 | reasonable amount of time for the typical user to react */ | ||
136 | #define A_MARKER_VIRTUAL_SIZE 1000 | ||
137 | return (ab_A_marker != AB_MARKER_NONE) | ||
138 | && (song_position > (ab_A_marker+A_MARKER_VIRTUAL_SIZE)); | ||
139 | } | ||
140 | |||
141 | void ab_jump_to_A_marker(void) | ||
142 | { | ||
143 | bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0; | ||
144 | if ( ! paused ) | ||
145 | audio_pause(); | ||
146 | audio_ff_rewind(ab_A_marker); | ||
147 | if ( ! paused ) | ||
148 | audio_resume(); | ||
149 | } | ||
150 | |||
151 | void ab_reset_markers(void) | ||
152 | { | ||
153 | ab_A_marker = AB_MARKER_NONE; | ||
154 | ab_B_marker = AB_MARKER_NONE; | ||
155 | } | ||
156 | |||
157 | /* following is a fudge factor to help overcome the latency between | ||
158 | the time the user hears the passage they want to mark and the time | ||
159 | they actually press the button; the actual song position is adjusted | ||
160 | by this fudge factor when setting a mark */ | ||
161 | #define EAR_TO_HAND_LATENCY_FUDGE 200 | ||
162 | |||
163 | void ab_set_A_marker(unsigned int song_position) | ||
164 | { | ||
165 | ab_A_marker = song_position; | ||
166 | ab_A_marker = (ab_A_marker >= EAR_TO_HAND_LATENCY_FUDGE) | ||
167 | ? (ab_A_marker - EAR_TO_HAND_LATENCY_FUDGE) : 0; | ||
168 | /* check if markers are out of order */ | ||
169 | if ( (ab_B_marker != AB_MARKER_NONE) && (ab_A_marker > ab_B_marker) ) | ||
170 | ab_B_marker = AB_MARKER_NONE; | ||
171 | } | ||
172 | |||
173 | void ab_set_B_marker(unsigned int song_position) | ||
174 | { | ||
175 | ab_B_marker = song_position; | ||
176 | ab_B_marker = (ab_B_marker >= EAR_TO_HAND_LATENCY_FUDGE) | ||
177 | ? (ab_B_marker - EAR_TO_HAND_LATENCY_FUDGE) : 0; | ||
178 | /* check if markers are out of order */ | ||
179 | if ( (ab_A_marker != AB_MARKER_NONE) && (ab_B_marker < ab_A_marker) ) | ||
180 | ab_A_marker = AB_MARKER_NONE; | ||
181 | } | ||
182 | |||
183 | #ifdef HAVE_LCD_BITMAP | ||
184 | |||
185 | static int ab_calc_mark_x_pos(int mark, int capacity, int offset, int size) | ||
186 | { | ||
187 | int w = size - offset; | ||
188 | return offset + ( (w * mark) / capacity ); | ||
189 | } | ||
190 | |||
191 | static void ab_draw_veritcal_line_mark(int x, int y, int h) | ||
192 | { | ||
193 | lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
194 | lcd_vline(x, y, y+h-1); | ||
195 | } | ||
196 | |||
197 | #define DIRECTION_RIGHT 1 | ||
198 | #define DIRECTION_LEFT -1 | ||
199 | |||
200 | static void ab_draw_arrow_mark(int x, int y, int h, int direction) | ||
201 | { | ||
202 | /* draw lines in decreasing size until a height of zero is reached */ | ||
203 | lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
204 | while( h > 0 ) | ||
205 | { | ||
206 | lcd_vline(x, y, y+h-1); | ||
207 | h -= 2; | ||
208 | y++; | ||
209 | x += direction; | ||
210 | lcd_set_drawmode(DRMODE_COMPLEMENT); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | void ab_draw_markers(int capacity, int x, int y, int w, int h) | ||
215 | { | ||
216 | /* if both markers are set, determine if they're far enough apart | ||
217 | to draw arrows */ | ||
218 | if ( ab_A_marker_set() && ab_B_marker_set() ) | ||
219 | { | ||
220 | int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w); | ||
221 | int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w); | ||
222 | int arrow_width = (h+1) / 2; | ||
223 | if ( (xb-xa) < (arrow_width*2) ) | ||
224 | { | ||
225 | ab_draw_veritcal_line_mark(xa, y, h); | ||
226 | ab_draw_veritcal_line_mark(xb, y, h); | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | ab_draw_arrow_mark(xa, y, h, DIRECTION_RIGHT); | ||
231 | ab_draw_arrow_mark(xb, y, h, DIRECTION_LEFT); | ||
232 | } | ||
233 | } | ||
234 | else | ||
235 | { | ||
236 | if (ab_A_marker_set()) | ||
237 | { | ||
238 | int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w); | ||
239 | ab_draw_arrow_mark(xa, y, h, DIRECTION_RIGHT); | ||
240 | } | ||
241 | if (ab_B_marker_set()) | ||
242 | { | ||
243 | int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w); | ||
244 | ab_draw_arrow_mark(xb, y, h, DIRECTION_LEFT); | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | #endif /* HAVE_LCD_BITMAP */ | ||
250 | |||
251 | #endif /* AB_REPEAT_ENABLE */ | ||
diff --git a/apps/abrepeat.h b/apps/abrepeat.h new file mode 100644 index 0000000000..113a1f5ee6 --- /dev/null +++ b/apps/abrepeat.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Ray Lambert | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef _ABREPEAT_H_ | ||
20 | #define _ABREPEAT_H_ | ||
21 | |||
22 | #include "system.h" | ||
23 | #include <stdbool.h> | ||
24 | |||
25 | #ifdef AB_REPEAT_ENABLE | ||
26 | |||
27 | #define AB_MARKER_NONE 0 | ||
28 | |||
29 | void ab_repeat_init(void); | ||
30 | bool ab_repeat_mode_enabled(void); // test if a/b repeat is enabled | ||
31 | bool ab_A_marker_set(void); | ||
32 | bool ab_B_marker_set(void); | ||
33 | unsigned int ab_get_A_marker(void); | ||
34 | unsigned int ab_get_B_marker(void); | ||
35 | bool ab_reached_B_marker(unsigned int song_position); | ||
36 | bool ab_before_A_marker(unsigned int song_position); | ||
37 | bool ab_after_A_marker(unsigned int song_position); | ||
38 | void ab_jump_to_A_marker(void); | ||
39 | void ab_reset_markers(void); | ||
40 | void ab_set_A_marker(unsigned int song_position); | ||
41 | void ab_set_B_marker(unsigned int song_position); | ||
42 | #ifdef HAVE_LCD_BITMAP | ||
43 | void ab_draw_markers(int capacity, int x, int y, int w, int h); | ||
44 | #endif | ||
45 | |||
46 | #endif | ||
47 | |||
48 | #endif /* _ABREPEAT_H_ */ | ||
diff --git a/apps/bookmark.c b/apps/bookmark.c index 4afba78d14..c157d01662 100644 --- a/apps/bookmark.c +++ b/apps/bookmark.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include "sprintf.h" | 47 | #include "sprintf.h" |
48 | #include "talk.h" | 48 | #include "talk.h" |
49 | #include "misc.h" | 49 | #include "misc.h" |
50 | #include "abrepeat.h" | ||
50 | 51 | ||
51 | #define MAX_BOOKMARKS 10 | 52 | #define MAX_BOOKMARKS 10 |
52 | #define MAX_BOOKMARK_SIZE 350 | 53 | #define MAX_BOOKMARK_SIZE 350 |
@@ -778,6 +779,12 @@ static void display_bookmark(const char* bookmark, | |||
778 | /* bookmark shuffle and repeat states*/ | 779 | /* bookmark shuffle and repeat states*/ |
779 | switch (repeat_mode) | 780 | switch (repeat_mode) |
780 | { | 781 | { |
782 | #ifdef AB_REPEAT_ENABLE | ||
783 | case REPEAT_AB: | ||
784 | statusbar_icon_play_mode(Icon_RepeatAB); | ||
785 | break; | ||
786 | #endif | ||
787 | |||
781 | case REPEAT_ONE: | 788 | case REPEAT_ONE: |
782 | statusbar_icon_play_mode(Icon_RepeatOne); | 789 | statusbar_icon_play_mode(Icon_RepeatOne); |
783 | break; | 790 | break; |
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index eb1c887fae..75601c858b 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -3286,3 +3286,9 @@ desc: in beep volume in playback settings | |||
3286 | eng: "Strong" | 3286 | eng: "Strong" |
3287 | voice "Strong" | 3287 | voice "Strong" |
3288 | new: | 3288 | new: |
3289 | |||
3290 | id: LANG_REPEAT_AB | ||
3291 | desc: repeat one song | ||
3292 | eng: "A-B" | ||
3293 | voice: "A-B" | ||
3294 | new: | ||
diff --git a/apps/playlist.c b/apps/playlist.c index bd443e4f38..bc2bd05905 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -85,6 +85,7 @@ | |||
85 | #include "misc.h" | 85 | #include "misc.h" |
86 | #include "button.h" | 86 | #include "button.h" |
87 | #include "filetree.h" | 87 | #include "filetree.h" |
88 | #include "abrepeat.h" | ||
88 | #ifdef HAVE_LCD_BITMAP | 89 | #ifdef HAVE_LCD_BITMAP |
89 | #include "icons.h" | 90 | #include "icons.h" |
90 | #include "widgets.h" | 91 | #include "widgets.h" |
@@ -867,6 +868,9 @@ static int get_next_index(const struct playlist_info* playlist, int steps, | |||
867 | } | 868 | } |
868 | 869 | ||
869 | case REPEAT_ONE: | 870 | case REPEAT_ONE: |
871 | #ifdef AB_REPEAT_ENABLE | ||
872 | case REPEAT_AB: | ||
873 | #endif | ||
870 | next_index = current_index; | 874 | next_index = current_index; |
871 | break; | 875 | break; |
872 | 876 | ||
@@ -1916,7 +1920,11 @@ int playlist_next(int steps) | |||
1916 | struct playlist_info* playlist = ¤t_playlist; | 1920 | struct playlist_info* playlist = ¤t_playlist; |
1917 | int index; | 1921 | int index; |
1918 | 1922 | ||
1919 | if (steps > 0 && global_settings.repeat_mode != REPEAT_ONE) | 1923 | if ( (steps > 0) |
1924 | #ifdef AB_REPEAT_ENABLE | ||
1925 | && (global_settings.repeat_mode != REPEAT_AB) | ||
1926 | #endif | ||
1927 | && (global_settings.repeat_mode != REPEAT_ONE) ) | ||
1920 | { | 1928 | { |
1921 | int i, j; | 1929 | int i, j; |
1922 | 1930 | ||
diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c index 6e60905478..78f3039df2 100644 --- a/apps/recorder/icons.c +++ b/apps/recorder/icons.c | |||
@@ -73,6 +73,7 @@ const unsigned char bitmap_icons_7x8[][7] = | |||
73 | {0x3e,0x41,0x51,0x41,0x45,0x41,0x3e}, /* Shuffle playmode (dice) */ | 73 | {0x3e,0x41,0x51,0x41,0x45,0x41,0x3e}, /* Shuffle playmode (dice) */ |
74 | {0x04,0x0c,0x1c,0x3c,0x1c,0x0c,0x04}, /* Down-arrow */ | 74 | {0x04,0x0c,0x1c,0x3c,0x1c,0x0c,0x04}, /* Down-arrow */ |
75 | {0x20,0x30,0x38,0x3c,0x38,0x30,0x20}, /* Up-arrow */ | 75 | {0x20,0x30,0x38,0x3c,0x38,0x30,0x20}, /* Up-arrow */ |
76 | {0x7f,0x04,0x4e,0x5f,0x44,0x38,0x7f}, /* Repeat-AB playmode */ | ||
76 | }; | 77 | }; |
77 | 78 | ||
78 | #if CONFIG_LED == LED_VIRTUAL | 79 | #if CONFIG_LED == LED_VIRTUAL |
diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h index c0b870fbb6..0ea29bb324 100644 --- a/apps/recorder/icons.h +++ b/apps/recorder/icons.h | |||
@@ -58,6 +58,7 @@ enum icons_7x8 { | |||
58 | Icon_Shuffle, | 58 | Icon_Shuffle, |
59 | Icon_DownArrow, | 59 | Icon_DownArrow, |
60 | Icon_UpArrow, | 60 | Icon_UpArrow, |
61 | Icon_RepeatAB, | ||
61 | Icon_Last | 62 | Icon_Last |
62 | }; | 63 | }; |
63 | 64 | ||
diff --git a/apps/screens.c b/apps/screens.c index e259c03407..c9acfa6a05 100644 --- a/apps/screens.c +++ b/apps/screens.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2002 Björn Stenberg | 10 | * Copyright (C) 2002 Bj�n Stenberg |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 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. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -45,6 +45,7 @@ | |||
45 | #include "debug.h" | 45 | #include "debug.h" |
46 | #include "led.h" | 46 | #include "led.h" |
47 | #include "sound.h" | 47 | #include "sound.h" |
48 | #include "abrepeat.h" | ||
48 | #include "wps-display.h" | 49 | #include "wps-display.h" |
49 | #if defined(HAVE_LCD_BITMAP) | 50 | #if defined(HAVE_LCD_BITMAP) |
50 | #include "widgets.h" | 51 | #include "widgets.h" |
@@ -593,6 +594,12 @@ bool quick_screen(int context, int button) | |||
593 | case REPEAT_SHUFFLE: | 594 | case REPEAT_SHUFFLE: |
594 | ptr = str(LANG_SHUFFLE); | 595 | ptr = str(LANG_SHUFFLE); |
595 | break; | 596 | break; |
597 | |||
598 | #ifdef AB_REPEAT_ENABLE | ||
599 | case REPEAT_AB: | ||
600 | ptr = str(LANG_REPEAT_AB); | ||
601 | break; | ||
602 | #endif | ||
596 | } | 603 | } |
597 | 604 | ||
598 | lcd_getstringsize(str(LANG_REPEAT),&w,&h); | 605 | lcd_getstringsize(str(LANG_REPEAT),&w,&h); |
diff --git a/apps/settings.c b/apps/settings.c index 9bcdc558a2..4811ad2320 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -78,7 +78,7 @@ const char rec_base_directory[] = REC_BASE_DIR; | |||
78 | #include "pcm_playback.h" | 78 | #include "pcm_playback.h" |
79 | #endif | 79 | #endif |
80 | 80 | ||
81 | #define CONFIG_BLOCK_VERSION 24 | 81 | #define CONFIG_BLOCK_VERSION 25 |
82 | #define CONFIG_BLOCK_SIZE 512 | 82 | #define CONFIG_BLOCK_SIZE 512 |
83 | #define RTC_BLOCK_SIZE 44 | 83 | #define RTC_BLOCK_SIZE 44 |
84 | 84 | ||
@@ -205,7 +205,7 @@ static const struct bit_entry rtc_bits[] = | |||
205 | {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL }, | 205 | {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL }, |
206 | {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL }, | 206 | {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL }, |
207 | {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL }, | 207 | {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL }, |
208 | {2, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one,shuffle" }, | 208 | {3, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one,shuffle,ab" }, |
209 | /* LCD */ | 209 | /* LCD */ |
210 | {6, S_O(contrast), 40, "contrast", NULL }, | 210 | {6, S_O(contrast), 40, "contrast", NULL }, |
211 | #ifdef CONFIG_BACKLIGHT | 211 | #ifdef CONFIG_BACKLIGHT |
diff --git a/apps/settings.h b/apps/settings.h index 767fa49463..d0041d2e99 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "file.h" | 25 | #include "file.h" |
26 | #include "timefuncs.h" | 26 | #include "timefuncs.h" |
27 | #include "abrepeat.h" | ||
27 | 28 | ||
28 | #define ROCKBOX_DIR "/.rockbox" | 29 | #define ROCKBOX_DIR "/.rockbox" |
29 | #define FONT_DIR "/fonts" | 30 | #define FONT_DIR "/fonts" |
@@ -229,7 +230,7 @@ struct user_settings | |||
229 | 230 | ||
230 | /* misc options */ | 231 | /* misc options */ |
231 | 232 | ||
232 | int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle */ | 233 | int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle 4=ab */ |
233 | int dirfilter; /* 0=display all, 1=only supported, 2=only music, | 234 | int dirfilter; /* 0=display all, 1=only supported, 2=only music, |
234 | 3=dirs+playlists, 4=ID3 database */ | 235 | 3=dirs+playlists, 4=ID3 database */ |
235 | bool sort_case; /* dir sort order: 0=case insensitive, 1=sensitive */ | 236 | bool sort_case; /* dir sort order: 0=case insensitive, 1=sensitive */ |
@@ -403,8 +404,17 @@ extern const char rec_base_directory[]; | |||
403 | #define SETTINGS_ALL 3 /* both */ | 404 | #define SETTINGS_ALL 3 /* both */ |
404 | 405 | ||
405 | /* repeat mode options */ | 406 | /* repeat mode options */ |
406 | enum { REPEAT_OFF, REPEAT_ALL, REPEAT_ONE, REPEAT_SHUFFLE, | 407 | enum |
407 | NUM_REPEAT_MODES }; | 408 | { |
409 | REPEAT_OFF, | ||
410 | REPEAT_ALL, | ||
411 | REPEAT_ONE, | ||
412 | REPEAT_SHUFFLE, | ||
413 | #ifdef AB_REPEAT_ENABLE | ||
414 | REPEAT_AB, | ||
415 | #endif | ||
416 | NUM_REPEAT_MODES | ||
417 | }; | ||
408 | 418 | ||
409 | /* dir filter options */ | 419 | /* dir filter options */ |
410 | /* Note: Any new filter modes need to be added before NUM_FILTER_MODES. | 420 | /* Note: Any new filter modes need to be added before NUM_FILTER_MODES. |
diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 780c2940b4..9f7259620e 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "talk.h" | 46 | #include "talk.h" |
47 | #include "timefuncs.h" | 47 | #include "timefuncs.h" |
48 | #include "misc.h" | 48 | #include "misc.h" |
49 | #include "abrepeat.h" | ||
49 | #include "power.h" | 50 | #include "power.h" |
50 | #include "database.h" | 51 | #include "database.h" |
51 | 52 | ||
@@ -604,11 +605,14 @@ static bool repeat_mode(void) | |||
604 | { STR(LANG_REPEAT_ALL) }, | 605 | { STR(LANG_REPEAT_ALL) }, |
605 | { STR(LANG_REPEAT_ONE) }, | 606 | { STR(LANG_REPEAT_ONE) }, |
606 | { STR(LANG_SHUFFLE) }, | 607 | { STR(LANG_SHUFFLE) }, |
608 | #ifdef AB_REPEAT_ENABLE | ||
609 | { STR(LANG_REPEAT_AB) } | ||
610 | #endif | ||
607 | }; | 611 | }; |
608 | int old_repeat = global_settings.repeat_mode; | 612 | int old_repeat = global_settings.repeat_mode; |
609 | 613 | ||
610 | result = set_option( str(LANG_REPEAT), &global_settings.repeat_mode, | 614 | result = set_option( str(LANG_REPEAT), &global_settings.repeat_mode, |
611 | INT, names, 4, NULL ); | 615 | INT, names, NUM_REPEAT_MODES, NULL ); |
612 | 616 | ||
613 | if (old_repeat != global_settings.repeat_mode && | 617 | if (old_repeat != global_settings.repeat_mode && |
614 | (audio_status() & AUDIO_STATUS_PLAY)) | 618 | (audio_status() & AUDIO_STATUS_PLAY)) |
diff --git a/apps/status.c b/apps/status.c index c7f46db6fb..923b549bf0 100644 --- a/apps/status.c +++ b/apps/status.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "mp3_playback.h" | 27 | #include "mp3_playback.h" |
28 | #include "audio.h" | 28 | #include "audio.h" |
29 | #include "wps.h" | 29 | #include "wps.h" |
30 | #include "abrepeat.h" | ||
30 | #ifdef HAVE_RTC | 31 | #ifdef HAVE_RTC |
31 | #include "timefuncs.h" | 32 | #include "timefuncs.h" |
32 | #endif | 33 | #endif |
@@ -262,6 +263,12 @@ void status_draw(bool force_redraw) | |||
262 | info.redraw_volume = statusbar_icon_volume(info.volume); | 263 | info.redraw_volume = statusbar_icon_volume(info.volume); |
263 | statusbar_icon_play_state(current_playmode() + Icon_Play); | 264 | statusbar_icon_play_state(current_playmode() + Icon_Play); |
264 | switch (info.repeat) { | 265 | switch (info.repeat) { |
266 | #ifdef AB_REPEAT_ENABLE | ||
267 | case REPEAT_AB: | ||
268 | statusbar_icon_play_mode(Icon_RepeatAB); | ||
269 | break; | ||
270 | #endif | ||
271 | |||
265 | case REPEAT_ONE: | 272 | case REPEAT_ONE: |
266 | statusbar_icon_play_mode(Icon_RepeatOne); | 273 | statusbar_icon_play_mode(Icon_RepeatOne); |
267 | break; | 274 | break; |
diff --git a/apps/wps-display.c b/apps/wps-display.c index f6fda70377..892db8ce1a 100644 --- a/apps/wps-display.c +++ b/apps/wps-display.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2002 Björn Stenberg | 10 | * Copyright (C) 2002 Bj�n Stenberg |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 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. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -44,6 +44,7 @@ | |||
44 | #include "sprintf.h" | 44 | #include "sprintf.h" |
45 | #include "backlight.h" | 45 | #include "backlight.h" |
46 | #include "button.h" | 46 | #include "button.h" |
47 | #include "abrepeat.h" | ||
47 | 48 | ||
48 | #ifdef HAVE_LCD_BITMAP | 49 | #ifdef HAVE_LCD_BITMAP |
49 | #include "icons.h" | 50 | #include "icons.h" |
@@ -1214,11 +1215,18 @@ bool wps_refresh(struct mp3entry* id3, | |||
1214 | 1215 | ||
1215 | #ifdef HAVE_LCD_BITMAP | 1216 | #ifdef HAVE_LCD_BITMAP |
1216 | /* progress */ | 1217 | /* progress */ |
1217 | if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) { | 1218 | if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) |
1218 | scrollbar(0, i*h + offset + (h > 7 ? (h - 6) / 2 : 1), LCD_WIDTH, 6, | 1219 | { |
1219 | id3->length?id3->length:1, 0, | 1220 | #define PROGRESS_BAR_HEIGHT 6 /* this should probably be defined elsewhere; config-*.h perhaps? */ |
1220 | id3->length?id3->elapsed + ff_rewind_count:0, | 1221 | int sby = i*h + offset + (h > 7 ? (h - 6) / 2 : 1); |
1221 | HORIZONTAL); | 1222 | scrollbar(0, sby, LCD_WIDTH, PROGRESS_BAR_HEIGHT, |
1223 | id3->length?id3->length:1, 0, | ||
1224 | id3->length?id3->elapsed + ff_rewind_count:0, | ||
1225 | HORIZONTAL); | ||
1226 | #ifdef AB_REPEAT_ENABLE | ||
1227 | if ( ab_repeat_mode_enabled() ) | ||
1228 | ab_draw_markers(id3->length, 0, sby, LCD_WIDTH, PROGRESS_BAR_HEIGHT); | ||
1229 | #endif | ||
1222 | update_line = true; | 1230 | update_line = true; |
1223 | } | 1231 | } |
1224 | if (flags & refresh_mode & WPS_REFRESH_PEAK_METER) { | 1232 | if (flags & refresh_mode & WPS_REFRESH_PEAK_METER) { |
diff --git a/apps/wps.c b/apps/wps.c index 6302626004..bf0283015f 100644 --- a/apps/wps.c +++ b/apps/wps.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "misc.h" | 51 | #include "misc.h" |
52 | #include "sound.h" | 52 | #include "sound.h" |
53 | #include "onplay.h" | 53 | #include "onplay.h" |
54 | #include "abrepeat.h" | ||
54 | 55 | ||
55 | #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */ | 56 | #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */ |
56 | /* 3% of 30min file == 54s step size */ | 57 | /* 3% of 30min file == 54s step size */ |
@@ -347,6 +348,11 @@ long wps_show(void) | |||
347 | lcd_setmargins(0, 0); | 348 | lcd_setmargins(0, 0); |
348 | #endif | 349 | #endif |
349 | 350 | ||
351 | #ifdef AB_REPEAT_ENABLE | ||
352 | ab_repeat_init(); | ||
353 | ab_reset_markers(); | ||
354 | #endif | ||
355 | |||
350 | ff_rewind = false; | 356 | ff_rewind = false; |
351 | 357 | ||
352 | if(audio_status() & AUDIO_STATUS_PLAY) | 358 | if(audio_status() & AUDIO_STATUS_PLAY) |
@@ -585,6 +591,19 @@ long wps_show(void) | |||
585 | break; | 591 | break; |
586 | #endif | 592 | #endif |
587 | #endif | 593 | #endif |
594 | |||
595 | #ifdef AB_REPEAT_ENABLE | ||
596 | /* if we're in A/B repeat mode and the current position | ||
597 | is past the A marker, jump back to the A marker... */ | ||
598 | if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3->elapsed) ) | ||
599 | { | ||
600 | ab_jump_to_A_marker(); | ||
601 | update_track = true; | ||
602 | break; | ||
603 | } | ||
604 | /* ...otherwise, do it normally */ | ||
605 | #endif | ||
606 | |||
588 | if (!id3 || (id3->elapsed < 3*1000)) { | 607 | if (!id3 || (id3->elapsed < 3*1000)) { |
589 | audio_prev(); | 608 | audio_prev(); |
590 | } | 609 | } |
@@ -612,6 +631,19 @@ long wps_show(void) | |||
612 | break; | 631 | break; |
613 | #endif | 632 | #endif |
614 | #endif | 633 | #endif |
634 | |||
635 | #ifdef AB_REPEAT_ENABLE | ||
636 | /* if we're in A/B repeat mode and the current position is | ||
637 | before the A marker, jump to the A marker... */ | ||
638 | if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3->elapsed) ) | ||
639 | { | ||
640 | ab_jump_to_A_marker(); | ||
641 | update_track = true; | ||
642 | break; | ||
643 | } | ||
644 | /* ...otherwise, do it normally */ | ||
645 | #endif | ||
646 | |||
615 | audio_next(); | 647 | audio_next(); |
616 | break; | 648 | break; |
617 | 649 | ||
@@ -674,7 +706,8 @@ long wps_show(void) | |||
674 | 706 | ||
675 | /* pitch screen */ | 707 | /* pitch screen */ |
676 | #if CONFIG_KEYPAD == RECORDER_PAD | 708 | #if CONFIG_KEYPAD == RECORDER_PAD |
677 | case BUTTON_ON | BUTTON_REPEAT: | 709 | case BUTTON_ON | BUTTON_UP: |
710 | case BUTTON_ON | BUTTON_DOWN: | ||
678 | if (2 == pitch_screen()) | 711 | if (2 == pitch_screen()) |
679 | return SYS_USB_CONNECTED; | 712 | return SYS_USB_CONNECTED; |
680 | restore = true; | 713 | restore = true; |
@@ -682,6 +715,41 @@ long wps_show(void) | |||
682 | #endif | 715 | #endif |
683 | #endif | 716 | #endif |
684 | 717 | ||
718 | #ifdef AB_REPEAT_ENABLE | ||
719 | |||
720 | #ifdef WPS_AB_SET_A_MARKER | ||
721 | /* set A marker for A-B repeat */ | ||
722 | case WPS_AB_SET_A_MARKER: | ||
723 | if (ab_repeat_mode_enabled()) | ||
724 | ab_set_A_marker(id3->elapsed); | ||
725 | break; | ||
726 | #endif | ||
727 | |||
728 | #ifdef WPS_AB_SET_B_MARKER | ||
729 | /* set B marker for A-B repeat and jump to A */ | ||
730 | case WPS_AB_SET_B_MARKER: | ||
731 | if (ab_repeat_mode_enabled()) | ||
732 | { | ||
733 | ab_set_B_marker(id3->elapsed); | ||
734 | ab_jump_to_A_marker(); | ||
735 | update_track = true; | ||
736 | } | ||
737 | break; | ||
738 | #endif | ||
739 | |||
740 | #ifdef WPS_AB_RESET_AB_MARKERS | ||
741 | /* reset A&B markers */ | ||
742 | case WPS_AB_RESET_AB_MARKERS: | ||
743 | if (ab_repeat_mode_enabled()) | ||
744 | { | ||
745 | ab_reset_markers(); | ||
746 | update_track = true; | ||
747 | } | ||
748 | break; | ||
749 | #endif | ||
750 | |||
751 | #endif /* AB_REPEAT_ENABLE */ | ||
752 | |||
685 | /* stop and exit wps */ | 753 | /* stop and exit wps */ |
686 | #ifdef WPS_EXIT | 754 | #ifdef WPS_EXIT |
687 | case WPS_EXIT: | 755 | case WPS_EXIT: |
@@ -706,6 +774,7 @@ long wps_show(void) | |||
706 | default: | 774 | default: |
707 | if(default_event_handler(button) == SYS_USB_CONNECTED) | 775 | if(default_event_handler(button) == SYS_USB_CONNECTED) |
708 | return SYS_USB_CONNECTED; | 776 | return SYS_USB_CONNECTED; |
777 | update_track = true; | ||
709 | break; | 778 | break; |
710 | } | 779 | } |
711 | 780 | ||
@@ -734,6 +803,9 @@ long wps_show(void) | |||
734 | lcd_stop_scroll(); | 803 | lcd_stop_scroll(); |
735 | bookmark_autobookmark(); | 804 | bookmark_autobookmark(); |
736 | audio_stop(); | 805 | audio_stop(); |
806 | #ifdef AB_REPEAT_ENABLE | ||
807 | ab_reset_markers(); | ||
808 | #endif | ||
737 | 809 | ||
738 | /* Keys can be locked when exiting, so either unlock here | 810 | /* Keys can be locked when exiting, so either unlock here |
739 | or implement key locking in tree.c too */ | 811 | or implement key locking in tree.c too */ |
diff --git a/apps/wps.h b/apps/wps.h index 1779ce425d..6f0d601876 100644 --- a/apps/wps.h +++ b/apps/wps.h | |||
@@ -79,6 +79,12 @@ | |||
79 | #define WPS_CONTEXT (BUTTON_PLAY | BUTTON_REPEAT) | 79 | #define WPS_CONTEXT (BUTTON_PLAY | BUTTON_REPEAT) |
80 | #define WPS_QUICK BUTTON_F2 | 80 | #define WPS_QUICK BUTTON_F2 |
81 | 81 | ||
82 | #ifdef AB_REPEAT_ENABLE | ||
83 | #define WPS_AB_SET_A_MARKER (BUTTON_ON | BUTTON_LEFT) | ||
84 | #define WPS_AB_SET_B_MARKER (BUTTON_ON | BUTTON_RIGHT) | ||
85 | #define WPS_AB_RESET_AB_MARKERS (BUTTON_ON | BUTTON_OFF) | ||
86 | #endif | ||
87 | |||
82 | #define WPS_RC_NEXT BUTTON_RC_RIGHT | 88 | #define WPS_RC_NEXT BUTTON_RC_RIGHT |
83 | #define WPS_RC_PREV BUTTON_RC_LEFT | 89 | #define WPS_RC_PREV BUTTON_RC_LEFT |
84 | #define WPS_RC_PAUSE BUTTON_RC_PLAY | 90 | #define WPS_RC_PAUSE BUTTON_RC_PLAY |
@@ -106,6 +112,12 @@ | |||
106 | #define WPS_ID3 (BUTTON_MENU | BUTTON_ON) | 112 | #define WPS_ID3 (BUTTON_MENU | BUTTON_ON) |
107 | #define WPS_CONTEXT (BUTTON_PLAY | BUTTON_REPEAT) | 113 | #define WPS_CONTEXT (BUTTON_PLAY | BUTTON_REPEAT) |
108 | 114 | ||
115 | #ifdef AB_REPEAT_ENABLE | ||
116 | #define WPS_AB_SET_A_MARKER (BUTTON_ON | BUTTON_LEFT) | ||
117 | #define WPS_AB_SET_B_MARKER (BUTTON_ON | BUTTON_RIGHT) | ||
118 | #define WPS_AB_RESET_AB_MARKERS (BUTTON_ON | BUTTON_STOP) | ||
119 | #endif | ||
120 | |||
109 | #define WPS_RC_NEXT BUTTON_RC_RIGHT | 121 | #define WPS_RC_NEXT BUTTON_RC_RIGHT |
110 | #define WPS_RC_PREV BUTTON_RC_LEFT | 122 | #define WPS_RC_PREV BUTTON_RC_LEFT |
111 | #define WPS_RC_PAUSE BUTTON_RC_PLAY | 123 | #define WPS_RC_PAUSE BUTTON_RC_PLAY |
diff --git a/firmware/export/audio.h b/firmware/export/audio.h index 17de7f077d..67ed052f2b 100644 --- a/firmware/export/audio.h +++ b/firmware/export/audio.h | |||
@@ -79,4 +79,44 @@ int audio_get_file_pos(void); | |||
79 | void audio_beep(int duration); | 79 | void audio_beep(int duration); |
80 | void audio_init_playback(void); | 80 | void audio_init_playback(void); |
81 | 81 | ||
82 | /***********************************************************************/ | ||
83 | /* audio event handling */ | ||
84 | |||
85 | /* subscribe to one or more audio event(s) by OR'ing together the desired */ | ||
86 | /* event IDs (defined below); a handler is called with a solitary event ID */ | ||
87 | /* (so switch() is okay) and possibly some useful data (depending on the */ | ||
88 | /* event); a handler must return one of the return codes defined below */ | ||
89 | |||
90 | typedef int (*AUDIO_EVENT_HANDLER)(unsigned short event, unsigned long data); | ||
91 | |||
92 | void audio_register_event_handler(AUDIO_EVENT_HANDLER handler, unsigned short mask); | ||
93 | |||
94 | /***********************************************************************/ | ||
95 | /* handler return codes */ | ||
96 | |||
97 | #define AUDIO_EVENT_RC_IGNORED 200 | ||
98 | /* indicates that no action was taken or the event was not recognized */ | ||
99 | |||
100 | #define AUDIO_EVENT_RC_HANDLED 201 | ||
101 | /* indicates that the event was handled and some action was taken which renders | ||
102 | the original event invalid; USE WITH CARE!; this return code aborts all further | ||
103 | processing of the given event */ | ||
104 | |||
105 | /***********************************************************************/ | ||
106 | /* audio event IDs */ | ||
107 | |||
108 | #define AUDIO_EVENT_POS_REPORT (1<<0) | ||
109 | /* sends a periodic song position report to handlers; a report is sent on | ||
110 | each kernal tick; the number of ticks per second is defined by HZ; on each | ||
111 | report the current song position is passed in 'data'; if a handler takes an | ||
112 | action that changes the song or the song position it must return | ||
113 | AUDIO_EVENT_RC_HANDLED which suppresses the event for any remaining handlers */ | ||
114 | |||
115 | #define AUDIO_EVENT_END_OF_TRACK (1<<1) | ||
116 | /* generated when the end of the currently playing track is reached; no | ||
117 | data is passed; if the handler implements some alternate end-of-track | ||
118 | processing it should return AUDIO_EVENT_RC_HANDLED which suppresses the | ||
119 | event for any remaining handlers as well as the normal end-of-track | ||
120 | processing */ | ||
121 | |||
82 | #endif | 122 | #endif |
diff --git a/firmware/export/config-fmrecorder.h b/firmware/export/config-fmrecorder.h index 40ba404a82..c53388984f 100644 --- a/firmware/export/config-fmrecorder.h +++ b/firmware/export/config-fmrecorder.h | |||
@@ -24,6 +24,8 @@ | |||
24 | /* Define this if you have an FM Radio */ | 24 | /* Define this if you have an FM Radio */ |
25 | #define CONFIG_TUNER S1A0903X01 | 25 | #define CONFIG_TUNER S1A0903X01 |
26 | 26 | ||
27 | #define AB_REPEAT_ENABLE 1 | ||
28 | |||
27 | #ifndef SIMULATOR | 29 | #ifndef SIMULATOR |
28 | 30 | ||
29 | /* Define this if you have a MAS3587F */ | 31 | /* Define this if you have a MAS3587F */ |
diff --git a/firmware/export/config-player.h b/firmware/export/config-player.h index 57fd7d8d92..70858a1636 100644 --- a/firmware/export/config-player.h +++ b/firmware/export/config-player.h | |||
@@ -12,6 +12,8 @@ | |||
12 | /* The number of bytes reserved for loadable plugins */ | 12 | /* The number of bytes reserved for loadable plugins */ |
13 | #define PLUGIN_BUFFER_SIZE 0x8000 | 13 | #define PLUGIN_BUFFER_SIZE 0x8000 |
14 | 14 | ||
15 | #define AB_REPEAT_ENABLE 1 | ||
16 | |||
15 | #ifndef SIMULATOR | 17 | #ifndef SIMULATOR |
16 | 18 | ||
17 | /* Define this if you have a SH7034 */ | 19 | /* Define this if you have a SH7034 */ |
diff --git a/firmware/export/config-recorder.h b/firmware/export/config-recorder.h index bab6cd17c0..51cdb79321 100644 --- a/firmware/export/config-recorder.h +++ b/firmware/export/config-recorder.h | |||
@@ -18,6 +18,8 @@ | |||
18 | /* The number of bytes reserved for loadable plugins */ | 18 | /* The number of bytes reserved for loadable plugins */ |
19 | #define PLUGIN_BUFFER_SIZE 0x8000 | 19 | #define PLUGIN_BUFFER_SIZE 0x8000 |
20 | 20 | ||
21 | #define AB_REPEAT_ENABLE 1 | ||
22 | |||
21 | #ifndef SIMULATOR | 23 | #ifndef SIMULATOR |
22 | 24 | ||
23 | /* Define this if you have a MAS3587F */ | 25 | /* Define this if you have a MAS3587F */ |
diff --git a/firmware/export/config-recorderv2.h b/firmware/export/config-recorderv2.h index 058495e894..b2d6d01669 100644 --- a/firmware/export/config-recorderv2.h +++ b/firmware/export/config-recorderv2.h | |||
@@ -21,6 +21,8 @@ | |||
21 | /* The number of bytes reserved for loadable plugins */ | 21 | /* The number of bytes reserved for loadable plugins */ |
22 | #define PLUGIN_BUFFER_SIZE 0x8000 | 22 | #define PLUGIN_BUFFER_SIZE 0x8000 |
23 | 23 | ||
24 | #define AB_REPEAT_ENABLE 1 | ||
25 | |||
24 | #ifndef SIMULATOR | 26 | #ifndef SIMULATOR |
25 | 27 | ||
26 | /* Define this if you have a SH7034 */ | 28 | /* Define this if you have a SH7034 */ |
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index 575ba29fe3..721a4acbcc 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -280,6 +280,52 @@ static struct trackdata *get_trackdata(int offset) | |||
280 | } | 280 | } |
281 | #endif /* !SIMULATOR */ | 281 | #endif /* !SIMULATOR */ |
282 | 282 | ||
283 | /***********************************************************************/ | ||
284 | /* audio event handling */ | ||
285 | |||
286 | #define MAX_EVENT_HANDLERS 10 | ||
287 | struct event_handlers_table | ||
288 | { | ||
289 | AUDIO_EVENT_HANDLER handler; | ||
290 | unsigned short mask; | ||
291 | }; | ||
292 | static struct event_handlers_table event_handlers[MAX_EVENT_HANDLERS]; | ||
293 | static int event_handlers_count = 0; | ||
294 | |||
295 | void audio_register_event_handler(AUDIO_EVENT_HANDLER handler, unsigned short mask) | ||
296 | { | ||
297 | if (event_handlers_count < MAX_EVENT_HANDLERS) | ||
298 | { | ||
299 | event_handlers[event_handlers_count].handler = handler; | ||
300 | event_handlers[event_handlers_count].mask = mask; | ||
301 | event_handlers_count++; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /* dispatch calls each handler in the order registered and returns after some | ||
306 | handler actually handles the event (the event is assumed to no longer be valid | ||
307 | after this, due to the handler changing some condition); returns true if someone | ||
308 | handled the event, which is expected to cause the caller to skip its own handling | ||
309 | of the event */ | ||
310 | #ifndef SIMULATOR | ||
311 | static bool audio_dispatch_event(unsigned short event, unsigned long data) | ||
312 | { | ||
313 | int i = 0; | ||
314 | for(i=0; i < event_handlers_count; i++) | ||
315 | { | ||
316 | if ( event_handlers[i].mask & event ) | ||
317 | { | ||
318 | int rc = event_handlers[i].handler(event, data); | ||
319 | if ( rc == AUDIO_EVENT_RC_HANDLED ) | ||
320 | return true; | ||
321 | } | ||
322 | } | ||
323 | return false; | ||
324 | } | ||
325 | #endif | ||
326 | |||
327 | /***********************************************************************/ | ||
328 | |||
283 | static void set_elapsed(struct mp3entry* id3) | 329 | static void set_elapsed(struct mp3entry* id3) |
284 | { | 330 | { |
285 | if ( id3->vbr ) { | 331 | if ( id3->vbr ) { |
@@ -730,9 +776,10 @@ void rec_tick(void) | |||
730 | 776 | ||
731 | void playback_tick(void) | 777 | void playback_tick(void) |
732 | { | 778 | { |
733 | get_trackdata(0)->id3.elapsed += | 779 | struct trackdata *ptd = get_trackdata(0); |
734 | (current_tick - last_dma_tick) * 1000 / HZ; | 780 | ptd->id3.elapsed += (current_tick - last_dma_tick) * 1000 / HZ; |
735 | last_dma_tick = current_tick; | 781 | last_dma_tick = current_tick; |
782 | audio_dispatch_event(AUDIO_EVENT_POS_REPORT, (unsigned long)ptd->id3.elapsed); | ||
736 | } | 783 | } |
737 | 784 | ||
738 | static void reset_mp3_buffer(void) | 785 | static void reset_mp3_buffer(void) |
@@ -762,8 +809,11 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
762 | { | 809 | { |
763 | if (audiobuf_read == get_trackdata(track_offset)->mempos) | 810 | if (audiobuf_read == get_trackdata(track_offset)->mempos) |
764 | { | 811 | { |
765 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); | 812 | if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK, 0) ) |
766 | track_offset++; | 813 | { |
814 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); | ||
815 | track_offset++; | ||
816 | } | ||
767 | } | 817 | } |
768 | } | 818 | } |
769 | 819 | ||
@@ -823,10 +873,12 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
823 | } | 873 | } |
824 | else | 874 | else |
825 | { | 875 | { |
826 | DEBUGF("No more MP3 data. Stopping.\n"); | 876 | if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK, 0) ) |
827 | 877 | { | |
828 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); | 878 | DEBUGF("No more MP3 data. Stopping.\n"); |
829 | playing = false; | 879 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); |
880 | playing = false; | ||
881 | } | ||
830 | } | 882 | } |
831 | *psize = 0; /* no more transfer */ | 883 | *psize = 0; /* no more transfer */ |
832 | } | 884 | } |