summaryrefslogtreecommitdiff
path: root/apps/abrepeat.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/abrepeat.c')
-rw-r--r--apps/abrepeat.c108
1 files changed, 44 insertions, 64 deletions
diff --git a/apps/abrepeat.c b/apps/abrepeat.c
index 3a3d5b394d..b83a7b6aa3 100644
--- a/apps/abrepeat.c
+++ b/apps/abrepeat.c
@@ -19,16 +19,20 @@
19 19
20#include "abrepeat.h" 20#include "abrepeat.h"
21 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 22#ifdef AB_REPEAT_ENABLE
31 23
24unsigned int ab_A_marker IDATA_ATTR = AB_MARKER_NONE;
25unsigned int ab_B_marker IDATA_ATTR = AB_MARKER_NONE;
26
27#if (CONFIG_CODEC == SWCODEC)
28void ab_end_of_track_report(void)
29{
30 if ( ab_A_marker_set() && ! ab_B_marker_set() )
31 {
32 ab_jump_to_A_marker();
33 }
34}
35#else
32static int ab_audio_event_handler(unsigned short event, unsigned long data) 36static int ab_audio_event_handler(unsigned short event, unsigned long data)
33{ 37{
34 int rc = AUDIO_EVENT_RC_IGNORED; 38 int rc = AUDIO_EVENT_RC_IGNORED;
@@ -38,7 +42,8 @@ static int ab_audio_event_handler(unsigned short event, unsigned long data)
38 { 42 {
39 case AUDIO_EVENT_POS_REPORT: 43 case AUDIO_EVENT_POS_REPORT:
40 { 44 {
41 if ( ! (audio_status() & AUDIO_STATUS_PAUSE) && ab_reached_B_marker(data) ) 45 if ( ! (audio_status() & AUDIO_STATUS_PAUSE) &&
46 ab_reached_B_marker(data) )
42 { 47 {
43 ab_jump_to_A_marker(); 48 ab_jump_to_A_marker();
44 rc = AUDIO_EVENT_RC_HANDLED; 49 rc = AUDIO_EVENT_RC_HANDLED;
@@ -58,6 +63,7 @@ static int ab_audio_event_handler(unsigned short event, unsigned long data)
58 } 63 }
59 return rc; 64 return rc;
60} 65}
66#endif
61 67
62void ab_repeat_init(void) 68void ab_repeat_init(void)
63{ 69{
@@ -65,30 +71,13 @@ void ab_repeat_init(void)
65 if ( ! ab_initialized ) 71 if ( ! ab_initialized )
66 { 72 {
67 ab_initialized = true; 73 ab_initialized = true;
74#if (CONFIG_CODEC != SWCODEC)
68 audio_register_event_handler(ab_audio_event_handler, 75 audio_register_event_handler(ab_audio_event_handler,
69 AUDIO_EVENT_POS_REPORT | AUDIO_EVENT_END_OF_TRACK ); 76 AUDIO_EVENT_POS_REPORT | AUDIO_EVENT_END_OF_TRACK );
77#endif
70 } 78 }
71} 79}
72 80
73static unsigned int ab_A_marker = AB_MARKER_NONE;
74static unsigned int ab_B_marker = AB_MARKER_NONE;
75
76bool ab_repeat_mode_enabled(void)
77{
78 extern struct user_settings global_settings;
79 return global_settings.repeat_mode == REPEAT_AB;
80}
81
82bool ab_A_marker_set(void)
83{
84 return ab_A_marker != AB_MARKER_NONE;
85}
86
87bool ab_B_marker_set(void)
88{
89 return ab_B_marker != AB_MARKER_NONE;
90}
91
92unsigned int ab_get_A_marker(void) 81unsigned int ab_get_A_marker(void)
93{ 82{
94 return ab_A_marker; 83 return ab_A_marker;
@@ -99,24 +88,6 @@ unsigned int ab_get_B_marker(void)
99 return ab_B_marker; 88 return ab_B_marker;
100} 89}
101 90
102bool 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
105was hit; it must be larger than the frequency (in milliseconds) at which this
106function is called otherwise detection of the B marker will be unreliable;
107we assume that this function will be called on each system tick and derive
108the window size from this with a generous margin of error (note: the number
109of 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; 91/* determines if the given song position is earlier than the A mark;
121intended for use in handling the jump NEXT and PREV commands */ 92intended for use in handling the jump NEXT and PREV commands */
122bool ab_before_A_marker(unsigned int song_position) 93bool ab_before_A_marker(unsigned int song_position)
@@ -129,9 +100,9 @@ bool ab_before_A_marker(unsigned int song_position)
129intended for use in handling the jump PREV command */ 100intended for use in handling the jump PREV command */
130bool ab_after_A_marker(unsigned int song_position) 101bool ab_after_A_marker(unsigned int song_position)
131{ 102{
132/* following is the size of the virtual A marker; we pretend that the A marker is 103/* following is the size of the virtual A marker; we pretend that the A marker
133larger than a single instant in order to give the user time to hit PREV again to 104is larger than a single instant in order to give the user time to hit PREV again
134jump back to the start of the song; it should be large enough to allow a 105to jump back to the start of the song; it should be large enough to allow a
135reasonable amount of time for the typical user to react */ 106reasonable amount of time for the typical user to react */
136#define A_MARKER_VIRTUAL_SIZE 1000 107#define A_MARKER_VIRTUAL_SIZE 1000
137 return (ab_A_marker != AB_MARKER_NONE) 108 return (ab_A_marker != AB_MARKER_NONE)
@@ -140,12 +111,16 @@ reasonable amount of time for the typical user to react */
140 111
141void ab_jump_to_A_marker(void) 112void ab_jump_to_A_marker(void)
142{ 113{
114#if (CONFIG_CODEC == SWCODEC)
115 audio_seamless_seek(ab_A_marker);
116#else
143 bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0; 117 bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0;
144 if ( ! paused ) 118 if ( ! paused )
145 audio_pause(); 119 audio_pause();
146 audio_ff_rewind(ab_A_marker); 120 audio_ff_rewind(ab_A_marker);
147 if ( ! paused ) 121 if ( ! paused )
148 audio_resume(); 122 audio_resume();
123#endif
149} 124}
150 125
151void ab_reset_markers(void) 126void ab_reset_markers(void)
@@ -182,37 +157,42 @@ void ab_set_B_marker(unsigned int song_position)
182 157
183#ifdef HAVE_LCD_BITMAP 158#ifdef HAVE_LCD_BITMAP
184 159
185static int ab_calc_mark_x_pos(int mark, int capacity, int offset, int size) 160static inline int ab_calc_mark_x_pos(int mark, int capacity,
161 int offset, int size)
186{ 162{
187 int w = size - offset; 163 int w = size - offset;
188 return offset + ( (w * mark) / capacity ); 164 return offset + ( (w * mark) / capacity );
189} 165}
190 166
191static void ab_draw_veritcal_line_mark(int x, int y, int h) 167static inline void ab_draw_veritcal_line_mark(struct screen * screen,
168 int x, int y, int h)
192{ 169{
193 lcd_set_drawmode(DRMODE_COMPLEMENT); 170 screen->set_drawmode(DRMODE_COMPLEMENT);
194 lcd_vline(x, y, y+h-1); 171 screen->vline(x, y, y+h-1);
195} 172}
196 173
197#define DIRECTION_RIGHT 1 174#define DIRECTION_RIGHT 1
198#define DIRECTION_LEFT -1 175#define DIRECTION_LEFT -1
199 176
200static void ab_draw_arrow_mark(int x, int y, int h, int direction) 177static inline void ab_draw_arrow_mark(struct screen * screen,
178 int x, int y, int h, int direction)
201{ 179{
202 /* draw lines in decreasing size until a height of zero is reached */ 180 /* draw lines in decreasing size until a height of zero is reached */
203 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 181 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
204 while( h > 0 ) 182 while( h > 0 )
205 { 183 {
206 lcd_vline(x, y, y+h-1); 184 screen->vline(x, y, y+h-1);
207 h -= 2; 185 h -= 2;
208 y++; 186 y++;
209 x += direction; 187 x += direction;
210 lcd_set_drawmode(DRMODE_COMPLEMENT); 188 screen->set_drawmode(DRMODE_COMPLEMENT);
211 } 189 }
212} 190}
213 191
214void ab_draw_markers(int capacity, int x, int y, int w, int h) 192void ab_draw_markers(struct screen * screen, int capacity,
193 int x, int y, int h)
215{ 194{
195 int w = screen->width;
216 /* if both markers are set, determine if they're far enough apart 196 /* if both markers are set, determine if they're far enough apart
217 to draw arrows */ 197 to draw arrows */
218 if ( ab_A_marker_set() && ab_B_marker_set() ) 198 if ( ab_A_marker_set() && ab_B_marker_set() )
@@ -222,13 +202,13 @@ void ab_draw_markers(int capacity, int x, int y, int w, int h)
222 int arrow_width = (h+1) / 2; 202 int arrow_width = (h+1) / 2;
223 if ( (xb-xa) < (arrow_width*2) ) 203 if ( (xb-xa) < (arrow_width*2) )
224 { 204 {
225 ab_draw_veritcal_line_mark(xa, y, h); 205 ab_draw_veritcal_line_mark(screen, xa, y, h);
226 ab_draw_veritcal_line_mark(xb, y, h); 206 ab_draw_veritcal_line_mark(screen, xb, y, h);
227 } 207 }
228 else 208 else
229 { 209 {
230 ab_draw_arrow_mark(xa, y, h, DIRECTION_RIGHT); 210 ab_draw_arrow_mark(screen, xa, y, h, DIRECTION_RIGHT);
231 ab_draw_arrow_mark(xb, y, h, DIRECTION_LEFT); 211 ab_draw_arrow_mark(screen, xb, y, h, DIRECTION_LEFT);
232 } 212 }
233 } 213 }
234 else 214 else
@@ -236,12 +216,12 @@ void ab_draw_markers(int capacity, int x, int y, int w, int h)
236 if (ab_A_marker_set()) 216 if (ab_A_marker_set())
237 { 217 {
238 int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w); 218 int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w);
239 ab_draw_arrow_mark(xa, y, h, DIRECTION_RIGHT); 219 ab_draw_arrow_mark(screen, xa, y, h, DIRECTION_RIGHT);
240 } 220 }
241 if (ab_B_marker_set()) 221 if (ab_B_marker_set())
242 { 222 {
243 int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w); 223 int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w);
244 ab_draw_arrow_mark(xb, y, h, DIRECTION_LEFT); 224 ab_draw_arrow_mark(screen, xb, y, h, DIRECTION_LEFT);
245 } 225 }
246 } 226 }
247} 227}