summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2005-07-02 16:52:30 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2005-07-02 16:52:30 +0000
commitd54811fe22c274ed31d897864ac0a33349f460e0 (patch)
treeb8c7928c46c4989f43eb1b63db07408daa70b4bb /apps/playback.c
parenta8cadd8181e53320109d2af61f0c7edea262d325 (diff)
Fixed mono playback support for mp3. Added two other event handlers in
playback.c. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6986 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 70cb36341b..3a5eeb328f 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -165,6 +165,8 @@ static int new_track;
/* Callback function to call when current track has really changed. */
void (*track_changed_callback)(struct track_info *ti);
+void (*track_buffer_callback)(struct mp3entry *id3, bool last_track);
+void (*track_unbuffer_callback)(struct mp3entry *id3, bool disk_spinning);
/* Configuration */
static int conf_bufferlimit;
@@ -266,10 +268,14 @@ bool codec_audiobuffer_insert_callback(char *buf, long length)
int factor;
int next_channel = 0;
int processed_length;
+ int mono = 0;
/* If non-interleaved stereo mode. */
- if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED) {
+ if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED)
next_channel = length / 2;
+ else if (dsp_config.stereo_mode == STEREO_MONO) {
+ length *= 2;
+ mono = 1;
}
if (dsp_config.sample_depth > 16) {
@@ -296,11 +302,11 @@ bool codec_audiobuffer_insert_callback(char *buf, long length)
processed_length = dsp_process(dest, buf, realsize / 4) * 2;
dsp_process(dest, buf + next_channel, realsize / 4);
} else {
- processed_length = dsp_process(dest, buf, realsize / 2);
+ processed_length = dsp_process(dest, buf, realsize >> (mono + 1));
}
pcm_flush_buffer(processed_length);
length -= realsize;
- buf += realsize << factor;
+ buf += realsize << (factor + mono);
}
return true;
@@ -589,6 +595,18 @@ void codec_configure_callback(int setting, void *value)
}
}
+void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
+ bool last_track))
+{
+ track_buffer_callback = handler;
+}
+
+void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
+ bool disk_spinning))
+{
+ track_unbuffer_callback = handler;
+}
+
void audio_set_track_changed_event(void (*handler)(struct track_info *ti))
{
track_changed_callback = handler;
@@ -934,6 +952,10 @@ void audio_play_start(int offset)
last_peek_offset = 0;
if (audio_load_track(offset, true, 0)) {
last_peek_offset++;
+ if (track_buffer_callback) {
+ cur_ti->event_sent = true;
+ track_buffer_callback(&cur_ti->id3, true);
+ }
ata_sleep();
} else {
logf("Failure");
@@ -950,10 +972,46 @@ void audio_clear_track_entries(void)
for (i = 0; i < MAX_TRACK - track_count; i++) {
if (++cur_idx >= MAX_TRACK)
cur_idx = 0;
+
+ /* Send event to notify that track has finished. */
+ if (track_unbuffer_callback && tracks[cur_idx].event_sent)
+ track_unbuffer_callback(&tracks[cur_idx].id3, filling);
memset(&tracks[cur_idx], 0, sizeof(struct track_info));
}
}
+/* Send callback events to notify about new tracks. */
+static void generate_postbuffer_events(void)
+{
+ int i;
+ int cur_ridx, event_count;
+
+ if (!track_buffer_callback)
+ return ;
+
+ /* At first determine how many unsent events we have. */
+ cur_ridx = track_ridx;
+ event_count = 0;
+ for (i = 0; i < track_count; i++) {
+ if (!tracks[cur_ridx].event_sent)
+ event_count++;
+ if (++cur_ridx >= MAX_TRACK)
+ cur_ridx -= MAX_TRACK;
+ }
+
+ /* Now sent these events. */
+ cur_ridx = track_ridx;
+ for (i = 0; i < track_count; i++) {
+ if (!tracks[cur_ridx].event_sent) {
+ tracks[cur_ridx].event_sent = true;
+ event_count--;
+ track_buffer_callback(&tracks[cur_ridx].id3, event_count == 0);
+ }
+ if (++cur_ridx >= MAX_TRACK)
+ cur_ridx -= MAX_TRACK;
+ }
+}
+
void initialize_buffer_fill(void)
{
int cur_idx, i;
@@ -1014,6 +1072,7 @@ void audio_check_buffer(void)
if (audio_load_track(0, false, last_peek_offset)) {
last_peek_offset++;
} else if (tracks[track_widx].filerem == 0 || fill_bytesleft == 0) {
+ generate_postbuffer_events();
filling = false;
conf_bufferlimit = 0;
pcm_set_boost_mode(false);
@@ -1069,6 +1128,8 @@ void audio_change_track(void)
logf("No more tracks");
while (pcm_is_playing())
yield();
+ track_count = 0;
+ audio_clear_track_entries();
playing = false;
return ;
}
@@ -1206,6 +1267,8 @@ void audio_thread(void)
}
pcm_play_stop();
pcm_play_pause(true);
+ track_count = 0;
+ audio_clear_track_entries();
break ;
case AUDIO_PAUSE:
@@ -1233,6 +1296,8 @@ void audio_thread(void)
#ifndef SIMULATOR
case SYS_USB_CONNECTED:
+ track_count = 0;
+ audio_clear_track_entries();
playing = false;
filling = false;
ci.stop_codec = true;
@@ -1269,6 +1334,8 @@ void codec_thread(void)
codecsize = cur_ti->codecsize;
if (codecsize == 0) {
logf("Codec slot is empty!");
+ track_count = 0;
+ audio_clear_track_entries();
playing = false;
break ;
}
@@ -1296,6 +1363,8 @@ void codec_thread(void)
if (status != CODEC_OK) {
logf("Codec failure");
splash(HZ*2, true, "Codec failure");
+ track_count = 0;
+ audio_clear_track_entries();
playing = false;
} else {
logf("Codec finished");
@@ -1597,6 +1666,18 @@ void mpeg_id3_options(bool _v1first)
v1first = _v1first;
}
+/*
+void test_buffer_event(struct mp3entry *id3, bool last_track)
+{
+ logf("be:%d%s", last_track, id3->title);
+}
+
+void test_unbuffer_event(struct mp3entry *id3, bool disk_spinning)
+{
+ logf("ube:%d%s", disk_spinning, id3->title);
+}
+*/
+
void audio_init(void)
{
logf("audio api init");
@@ -1611,12 +1692,19 @@ void audio_init(void)
paused = false;
track_changed = false;
current_fd = -1;
+ track_buffer_callback = NULL;
+ track_unbuffer_callback = NULL;
track_changed_callback = NULL;
logf("abuf:%0x", PCMBUF_SIZE);
logf("fbuf:%0x", codecbuflen);
logf("mbuf:%0x", MALLOC_BUFSIZE);
-
+
+ /*
+ audio_set_track_buffer_event(test_buffer_event);
+ audio_set_track_unbuffer_event(test_unbuffer_event);
+ */
+
/* Initialize codec api. */
ci.read_filebuf = codec_filebuf_callback;
ci.audiobuffer_insert = pcm_insert_buffer;