1 is the correct value here. Not that it makes any difference... :)
[kugel-rb.git] / apps / abrepeat.c
blobfc1913d37b489f800c03c41634102af840dee38e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $$
10 * Copyright (C) 2005 Ray Lambert
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 ****************************************************************************/
20 #include "abrepeat.h"
22 #ifdef AB_REPEAT_ENABLE
24 unsigned int ab_A_marker IDATA_ATTR = AB_MARKER_NONE;
25 unsigned int ab_B_marker IDATA_ATTR = AB_MARKER_NONE;
27 #if (CONFIG_CODEC == SWCODEC)
28 void ab_end_of_track_report(void)
30 if ( ab_A_marker_set() && ! ab_B_marker_set() )
32 ab_jump_to_A_marker();
35 #else
36 static int ab_audio_event_handler(unsigned short event, unsigned long data)
38 int rc = AUDIO_EVENT_RC_IGNORED;
39 if ( ab_repeat_mode_enabled() )
41 switch(event)
43 case AUDIO_EVENT_POS_REPORT:
45 if ( ! (audio_status() & AUDIO_STATUS_PAUSE) &&
46 ab_reached_B_marker(data) )
48 ab_jump_to_A_marker();
49 rc = AUDIO_EVENT_RC_HANDLED;
51 break;
53 case AUDIO_EVENT_END_OF_TRACK:
55 if ( ab_A_marker_set() && ! ab_B_marker_set() )
57 ab_jump_to_A_marker();
58 rc = AUDIO_EVENT_RC_HANDLED;
60 break;
64 return rc;
66 #endif
68 void ab_repeat_init(void)
70 static bool ab_initialized = false;
71 if ( ! ab_initialized )
73 ab_initialized = true;
74 #if (CONFIG_CODEC != SWCODEC)
75 audio_register_event_handler(ab_audio_event_handler,
76 AUDIO_EVENT_POS_REPORT | AUDIO_EVENT_END_OF_TRACK );
77 #endif
81 unsigned int ab_get_A_marker(void)
83 return ab_A_marker;
86 unsigned int ab_get_B_marker(void)
88 return ab_B_marker;
91 /* determines if the given song position is earlier than the A mark;
92 intended for use in handling the jump NEXT and PREV commands */
93 bool ab_before_A_marker(unsigned int song_position)
95 return (ab_A_marker != AB_MARKER_NONE)
96 && (song_position < ab_A_marker);
99 /* determines if the given song position is later than the A mark;
100 intended for use in handling the jump PREV command */
101 bool ab_after_A_marker(unsigned int song_position)
103 /* following is the size of the virtual A marker; we pretend that the A marker
104 is larger than a single instant in order to give the user time to hit PREV again
105 to jump back to the start of the song; it should be large enough to allow a
106 reasonable amount of time for the typical user to react */
107 #define A_MARKER_VIRTUAL_SIZE 1000
108 return (ab_A_marker != AB_MARKER_NONE)
109 && (song_position > (ab_A_marker+A_MARKER_VIRTUAL_SIZE));
112 void ab_jump_to_A_marker(void)
114 #if (CONFIG_CODEC != SWCODEC)
115 bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0;
116 if ( ! paused )
117 audio_pause();
118 #endif
119 audio_ff_rewind(ab_A_marker);
120 #if (CONFIG_CODEC != SWCODEC)
121 if ( ! paused )
122 audio_resume();
123 #endif
126 void ab_reset_markers(void)
128 ab_A_marker = AB_MARKER_NONE;
129 ab_B_marker = AB_MARKER_NONE;
132 /* following is a fudge factor to help overcome the latency between
133 the time the user hears the passage they want to mark and the time
134 they actually press the button; the actual song position is adjusted
135 by this fudge factor when setting a mark */
136 #define EAR_TO_HAND_LATENCY_FUDGE 200
138 void ab_set_A_marker(unsigned int song_position)
140 ab_A_marker = song_position;
141 ab_A_marker = (ab_A_marker >= EAR_TO_HAND_LATENCY_FUDGE)
142 ? (ab_A_marker - EAR_TO_HAND_LATENCY_FUDGE) : 0;
143 /* check if markers are out of order */
144 if ( (ab_B_marker != AB_MARKER_NONE) && (ab_A_marker > ab_B_marker) )
145 ab_B_marker = AB_MARKER_NONE;
148 void ab_set_B_marker(unsigned int song_position)
150 ab_B_marker = song_position;
151 ab_B_marker = (ab_B_marker >= EAR_TO_HAND_LATENCY_FUDGE)
152 ? (ab_B_marker - EAR_TO_HAND_LATENCY_FUDGE) : 0;
153 /* check if markers are out of order */
154 if ( (ab_A_marker != AB_MARKER_NONE) && (ab_B_marker < ab_A_marker) )
155 ab_A_marker = AB_MARKER_NONE;
158 #ifdef HAVE_LCD_BITMAP
160 static inline int ab_calc_mark_x_pos(int mark, int capacity,
161 int offset, int size)
163 int w = size - offset;
164 return offset + ( (w * mark) / capacity );
167 static inline void ab_draw_veritcal_line_mark(struct screen * screen,
168 int x, int y, int h)
170 screen->set_drawmode(DRMODE_COMPLEMENT);
171 screen->vline(x, y, y+h-1);
174 #define DIRECTION_RIGHT 1
175 #define DIRECTION_LEFT -1
177 static inline void ab_draw_arrow_mark(struct screen * screen,
178 int x, int y, int h, int direction)
180 /* draw lines in decreasing size until a height of zero is reached */
181 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
182 while( h > 0 )
184 screen->vline(x, y, y+h-1);
185 h -= 2;
186 y++;
187 x += direction;
188 screen->set_drawmode(DRMODE_COMPLEMENT);
192 void ab_draw_markers(struct screen * screen, int capacity,
193 int x, int y, int h)
195 int w = screen->width;
196 /* if both markers are set, determine if they're far enough apart
197 to draw arrows */
198 if ( ab_A_marker_set() && ab_B_marker_set() )
200 int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w);
201 int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w);
202 int arrow_width = (h+1) / 2;
203 if ( (xb-xa) < (arrow_width*2) )
205 ab_draw_veritcal_line_mark(screen, xa, y, h);
206 ab_draw_veritcal_line_mark(screen, xb, y, h);
208 else
210 ab_draw_arrow_mark(screen, xa, y, h, DIRECTION_RIGHT);
211 ab_draw_arrow_mark(screen, xb, y, h, DIRECTION_LEFT);
214 else
216 if (ab_A_marker_set())
218 int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w);
219 ab_draw_arrow_mark(screen, xa, y, h, DIRECTION_RIGHT);
221 if (ab_B_marker_set())
223 int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w);
224 ab_draw_arrow_mark(screen, xb, y, h, DIRECTION_LEFT);
229 #endif /* HAVE_LCD_BITMAP */
231 #endif /* AB_REPEAT_ENABLE */