forked from len0rd/rockbox
Convert playback.c to use unsigned byte counters, and _minor_ refactoring of buffer callbacks
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9227 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
b1cd32913d
commit
86f1e2ead2
6 changed files with 125 additions and 124 deletions
|
@ -143,6 +143,7 @@ struct codec_api ci = {
|
||||||
strncasecmp,
|
strncasecmp,
|
||||||
memset,
|
memset,
|
||||||
memcpy,
|
memcpy,
|
||||||
|
memmove,
|
||||||
_ctype_,
|
_ctype_,
|
||||||
atoi,
|
atoi,
|
||||||
strchr,
|
strchr,
|
||||||
|
@ -215,7 +216,6 @@ struct codec_api ci = {
|
||||||
/* new stuff at the end, sort into place next time
|
/* new stuff at the end, sort into place next time
|
||||||
the API gets incompatible */
|
the API gets incompatible */
|
||||||
|
|
||||||
memmove,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
|
int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
|
||||||
|
|
|
@ -85,12 +85,12 @@
|
||||||
#define CODEC_MAGIC 0x52434F44 /* RCOD */
|
#define CODEC_MAGIC 0x52434F44 /* RCOD */
|
||||||
|
|
||||||
/* increase this every time the api struct changes */
|
/* increase this every time the api struct changes */
|
||||||
#define CODEC_API_VERSION 4
|
#define CODEC_API_VERSION 5
|
||||||
|
|
||||||
/* update this to latest version if a change to the api struct breaks
|
/* update this to latest version if a change to the api struct breaks
|
||||||
backwards compatibility (and please take the opportunity to sort in any
|
backwards compatibility (and please take the opportunity to sort in any
|
||||||
new function which are "waiting" at the end of the function table) */
|
new function which are "waiting" at the end of the function table) */
|
||||||
#define CODEC_MIN_API_VERSION 3
|
#define CODEC_MIN_API_VERSION 5
|
||||||
|
|
||||||
/* codec return codes */
|
/* codec return codes */
|
||||||
enum codec_status {
|
enum codec_status {
|
||||||
|
@ -125,7 +125,7 @@ struct codec_api {
|
||||||
long seek_time;
|
long seek_time;
|
||||||
|
|
||||||
/* Returns buffer to malloc array. Only codeclib should need this. */
|
/* Returns buffer to malloc array. Only codeclib should need this. */
|
||||||
void* (*get_codec_memory)(long *size);
|
void* (*get_codec_memory)(size_t *size);
|
||||||
/* Insert PCM data into audio buffer for playback. Playback will start
|
/* Insert PCM data into audio buffer for playback. Playback will start
|
||||||
automatically. */
|
automatically. */
|
||||||
bool (*pcmbuf_insert)(const char *data, size_t length);
|
bool (*pcmbuf_insert)(const char *data, size_t length);
|
||||||
|
@ -135,18 +135,18 @@ struct codec_api {
|
||||||
|
|
||||||
/* Read next <size> amount bytes from file buffer to <ptr>.
|
/* Read next <size> amount bytes from file buffer to <ptr>.
|
||||||
Will return number of bytes read or 0 if end of file. */
|
Will return number of bytes read or 0 if end of file. */
|
||||||
long (*read_filebuf)(void *ptr, long size);
|
size_t (*read_filebuf)(void *ptr, size_t size);
|
||||||
/* Request pointer to file buffer which can be used to read
|
/* Request pointer to file buffer which can be used to read
|
||||||
<realsize> amount of data. <reqsize> tells the buffer system
|
<realsize> amount of data. <reqsize> tells the buffer system
|
||||||
how much data it should try to allocate. If <realsize> is 0,
|
how much data it should try to allocate. If <realsize> is 0,
|
||||||
end of file is reached. */
|
end of file is reached. */
|
||||||
void* (*request_buffer)(long *realsize, long reqsize);
|
void* (*request_buffer)(size_t *realsize, size_t reqsize);
|
||||||
/* Advance file buffer position by <amount> amount of bytes. */
|
/* Advance file buffer position by <amount> amount of bytes. */
|
||||||
void (*advance_buffer)(long amount);
|
void (*advance_buffer)(size_t amount);
|
||||||
/* Advance file buffer to a pointer location inside file buffer. */
|
/* Advance file buffer to a pointer location inside file buffer. */
|
||||||
void (*advance_buffer_loc)(void *ptr);
|
void (*advance_buffer_loc)(void *ptr);
|
||||||
/* Seek file buffer to position <newpos> beginning of file. */
|
/* Seek file buffer to position <newpos> beginning of file. */
|
||||||
bool (*seek_buffer)(off_t newpos);
|
bool (*seek_buffer)(size_t newpos);
|
||||||
/* Codec should call this function when it has done the seeking. */
|
/* Codec should call this function when it has done the seeking. */
|
||||||
void (*seek_complete)(void);
|
void (*seek_complete)(void);
|
||||||
/* Calculate mp3 seek position from given time data in ms. */
|
/* Calculate mp3 seek position from given time data in ms. */
|
||||||
|
@ -156,7 +156,7 @@ struct codec_api {
|
||||||
codec should exit immediately with PLUGIN_OK status. */
|
codec should exit immediately with PLUGIN_OK status. */
|
||||||
bool (*request_next_track)(void);
|
bool (*request_next_track)(void);
|
||||||
|
|
||||||
void (*set_offset)(unsigned int value);
|
void (*set_offset)(size_t value);
|
||||||
/* Configure different codec buffer parameters. */
|
/* Configure different codec buffer parameters. */
|
||||||
void (*configure)(int setting, void *value);
|
void (*configure)(int setting, void *value);
|
||||||
|
|
||||||
|
@ -214,6 +214,7 @@ struct codec_api {
|
||||||
int (*strncasecmp)(const char *s1, const char *s2, size_t n);
|
int (*strncasecmp)(const char *s1, const char *s2, size_t n);
|
||||||
void* (*memset)(void *dst, int c, size_t length);
|
void* (*memset)(void *dst, int c, size_t length);
|
||||||
void* (*memcpy)(void *out, const void *in, size_t n);
|
void* (*memcpy)(void *out, const void *in, size_t n);
|
||||||
|
void* (*memmove)(void *out, const void *in, size_t n);
|
||||||
const char *_ctype_;
|
const char *_ctype_;
|
||||||
int (*atoi)(const char *str);
|
int (*atoi)(const char *str);
|
||||||
char *(*strchr)(const char *s, int c);
|
char *(*strchr)(const char *s, int c);
|
||||||
|
@ -292,7 +293,6 @@ struct codec_api {
|
||||||
/* new stuff at the end, sort into place next time
|
/* new stuff at the end, sort into place next time
|
||||||
the API gets incompatible */
|
the API gets incompatible */
|
||||||
|
|
||||||
void* (*memmove)(void *out, const void *in, size_t n);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* codec header */
|
/* codec header */
|
||||||
|
|
|
@ -118,11 +118,9 @@ static bool flac_init(FLACContext* fc, int first_frame_offset)
|
||||||
|
|
||||||
if ((buf[0] & 0x7f) == 0) /* 0 is the STREAMINFO block */
|
if ((buf[0] & 0x7f) == 0) /* 0 is the STREAMINFO block */
|
||||||
{
|
{
|
||||||
/* FIXME: Don't trust the value of blocklength */
|
/* FIXME: Don't trust the value of blocklength, use actual return
|
||||||
if (ci->read_filebuf(buf, blocklength) < 0)
|
* value in bytes instead */
|
||||||
{
|
ci->read_filebuf(buf, blocklength);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fc->filesize = ci->filesize;
|
fc->filesize = ci->filesize;
|
||||||
fc->min_blocksize = (buf[0] << 8) | buf[1];
|
fc->min_blocksize = (buf[0] << 8) | buf[1];
|
||||||
|
|
|
@ -401,8 +401,6 @@ void pcmbuf_pause(bool pause) {
|
||||||
/* Force playback. */
|
/* Force playback. */
|
||||||
void pcmbuf_play_start(void)
|
void pcmbuf_play_start(void)
|
||||||
{
|
{
|
||||||
mutex_lock(&pcmbuf_mutex);
|
|
||||||
|
|
||||||
if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
|
if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
|
||||||
{
|
{
|
||||||
/** Prevent a very tiny pop from happening by muting audio
|
/** Prevent a very tiny pop from happening by muting audio
|
||||||
|
@ -417,8 +415,6 @@ void pcmbuf_play_start(void)
|
||||||
/* Now unmute the audio. */
|
/* Now unmute the audio. */
|
||||||
pcm_mute(false);
|
pcm_mute(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&pcmbuf_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -426,27 +422,22 @@ void pcmbuf_play_start(void)
|
||||||
*/
|
*/
|
||||||
static void pcmbuf_flush_fillpos(void)
|
static void pcmbuf_flush_fillpos(void)
|
||||||
{
|
{
|
||||||
mutex_lock(&pcmbuf_mutex);
|
|
||||||
|
|
||||||
if (audiobuffer_fillpos) {
|
if (audiobuffer_fillpos) {
|
||||||
/* Never use the last buffer descriptor */
|
/* Never use the last buffer descriptor */
|
||||||
while (pcmbuf_write == pcmbuf_write_end) {
|
while (pcmbuf_write == pcmbuf_write_end) {
|
||||||
logf("pcmbuf_flush_fillpos no descriptors");
|
logf("pcmbuf_flush_fillpos no descriptors");
|
||||||
/* Deboost to let the playback catchup */
|
/* Deboost to let the playback catchup */
|
||||||
pcmbuf_boost(false);
|
pcmbuf_boost(false);
|
||||||
/* Let someone else have fun in the meantime */
|
/* If this happens, something is being stupid */
|
||||||
sleep(1);
|
|
||||||
/* This is a fatal error situation that should never happen. */
|
|
||||||
if (!pcm_is_playing()) {
|
if (!pcm_is_playing()) {
|
||||||
logf("pcmbuf_flush_fillpos error");
|
logf("pcmbuf_flush_fillpos error");
|
||||||
pcmbuf_play_start();
|
pcmbuf_play_start();
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
/* Let approximately one chunk of data playback */
|
||||||
|
sleep(PCMBUF_TARGET_CHUNK/(NATIVE_FREQUENCY * 4) / 5);
|
||||||
}
|
}
|
||||||
pcmbuf_add_chunk();
|
pcmbuf_add_chunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&pcmbuf_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
182
apps/playback.c
182
apps/playback.c
|
@ -145,7 +145,7 @@ static struct mutex mutex_codecthread;
|
||||||
static struct mp3entry id3_voice;
|
static struct mp3entry id3_voice;
|
||||||
|
|
||||||
static char *voicebuf;
|
static char *voicebuf;
|
||||||
static int voice_remaining;
|
static size_t voice_remaining;
|
||||||
static bool voice_is_playing;
|
static bool voice_is_playing;
|
||||||
static void (*voice_getmore)(unsigned char** start, int* size);
|
static void (*voice_getmore)(unsigned char** start, int* size);
|
||||||
|
|
||||||
|
@ -159,14 +159,14 @@ extern unsigned char codecbuf[];
|
||||||
static char *filebuf;
|
static char *filebuf;
|
||||||
|
|
||||||
/* Total size of the ring buffer. */
|
/* Total size of the ring buffer. */
|
||||||
int filebuflen;
|
size_t filebuflen;
|
||||||
|
|
||||||
/* Bytes available in the buffer. */
|
/* Bytes available in the buffer. */
|
||||||
int filebufused;
|
size_t filebufused;
|
||||||
|
|
||||||
/* Ring buffer read and write indexes. */
|
/* Ring buffer read and write indexes. */
|
||||||
static volatile int buf_ridx;
|
static volatile size_t buf_ridx;
|
||||||
static volatile int buf_widx;
|
static volatile size_t buf_widx;
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
static unsigned char *iram_buf[2];
|
static unsigned char *iram_buf[2];
|
||||||
|
@ -187,7 +187,7 @@ static bool track_changed;
|
||||||
static int current_fd;
|
static int current_fd;
|
||||||
|
|
||||||
/* Information about how many bytes left on the buffer re-fill run. */
|
/* Information about how many bytes left on the buffer re-fill run. */
|
||||||
static long fill_bytesleft;
|
static size_t fill_bytesleft;
|
||||||
|
|
||||||
/* Track info structure about songs in the file buffer. */
|
/* Track info structure about songs in the file buffer. */
|
||||||
static struct track_info tracks[MAX_TRACK];
|
static struct track_info tracks[MAX_TRACK];
|
||||||
|
@ -215,10 +215,10 @@ void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track);
|
||||||
static void playback_init(void);
|
static void playback_init(void);
|
||||||
|
|
||||||
/* Configuration */
|
/* Configuration */
|
||||||
static int conf_bufferlimit;
|
static size_t conf_bufferlimit;
|
||||||
static int conf_watermark;
|
static size_t conf_watermark;
|
||||||
static int conf_filechunk;
|
static size_t conf_filechunk;
|
||||||
static int buffer_margin;
|
static size_t buffer_margin;
|
||||||
|
|
||||||
static bool v1first = false;
|
static bool v1first = false;
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
|
||||||
length);
|
length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* get_codec_memory_callback(long *size)
|
void* get_codec_memory_callback(size_t *size)
|
||||||
{
|
{
|
||||||
*size = MALLOC_BUFSIZE;
|
*size = MALLOC_BUFSIZE;
|
||||||
if (voice_codec_loaded)
|
if (voice_codec_loaded)
|
||||||
|
@ -413,7 +413,8 @@ void codec_set_elapsed_callback(unsigned int value)
|
||||||
{
|
{
|
||||||
unsigned int latency;
|
unsigned int latency;
|
||||||
|
|
||||||
if (ci.stop_codec || current_codec == CODEC_IDX_VOICE)
|
/* We don't save or display offsets for voice */
|
||||||
|
if (current_codec == CODEC_IDX_VOICE)
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
#ifdef AB_REPEAT_ENABLE
|
#ifdef AB_REPEAT_ENABLE
|
||||||
|
@ -429,11 +430,12 @@ void codec_set_elapsed_callback(unsigned int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void codec_set_offset_callback(unsigned int value)
|
void codec_set_offset_callback(size_t value)
|
||||||
{
|
{
|
||||||
unsigned int latency;
|
unsigned int latency;
|
||||||
|
|
||||||
if (ci.stop_codec || current_codec == CODEC_IDX_VOICE)
|
/* We don't save or display offsets for voice */
|
||||||
|
if (current_codec == CODEC_IDX_VOICE)
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
|
latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
|
||||||
|
@ -445,43 +447,56 @@ void codec_set_offset_callback(unsigned int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long codec_filebuf_callback(void *ptr, long size)
|
static void advance_buffer_counters(size_t amount) {
|
||||||
|
buf_ridx += amount;
|
||||||
|
if (buf_ridx >= filebuflen)
|
||||||
|
buf_ridx -= filebuflen;
|
||||||
|
ci.curpos += amount;
|
||||||
|
cur_ti->available -= amount;
|
||||||
|
filebufused -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy up-to size bytes into ptr and return the actual size copied */
|
||||||
|
size_t codec_filebuf_callback(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
char *buf = (char *)ptr;
|
char *buf = (char *)ptr;
|
||||||
int copy_n;
|
size_t copy_n;
|
||||||
int part_n;
|
size_t part_n;
|
||||||
|
|
||||||
if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
|
if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem);
|
/* The ammount to copy is the lesser of the requested amount and the
|
||||||
|
* amount left of the current track (both on disk and already loaded) */
|
||||||
|
copy_n = MIN(size, cur_ti->available + cur_ti->filerem);
|
||||||
|
|
||||||
|
/* Nothing requested OR nothing left */
|
||||||
|
if (copy_n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Let the disk buffer catch fill until enough data is available */
|
||||||
while (copy_n > cur_ti->available) {
|
while (copy_n > cur_ti->available) {
|
||||||
yield();
|
yield();
|
||||||
if (ci.stop_codec || ci.reload_codec)
|
if (ci.stop_codec || ci.reload_codec)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_n == 0)
|
/* Copy as much as possible without wrapping */
|
||||||
return 0;
|
|
||||||
|
|
||||||
part_n = MIN(copy_n, filebuflen - buf_ridx);
|
part_n = MIN(copy_n, filebuflen - buf_ridx);
|
||||||
memcpy(buf, &filebuf[buf_ridx], part_n);
|
memcpy(buf, &filebuf[buf_ridx], part_n);
|
||||||
|
/* Copy the rest in the case of a wrap */
|
||||||
if (part_n < copy_n) {
|
if (part_n < copy_n) {
|
||||||
memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
|
memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_ridx += copy_n;
|
/* Update read and other position pointers */
|
||||||
if (buf_ridx >= filebuflen)
|
advance_buffer_counters(copy_n);
|
||||||
buf_ridx -= filebuflen;
|
|
||||||
ci.curpos += copy_n;
|
|
||||||
cur_ti->available -= copy_n;
|
|
||||||
filebufused -= copy_n;
|
|
||||||
|
|
||||||
|
/* Return the actual amount of data copied to the buffer */
|
||||||
return copy_n;
|
return copy_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* voice_request_data(long *realsize, long reqsize)
|
void* voice_request_data(size_t *realsize, size_t reqsize)
|
||||||
{
|
{
|
||||||
while (queue_empty(&voice_codec_queue) && (voice_remaining == 0
|
while (queue_empty(&voice_codec_queue) && (voice_remaining == 0
|
||||||
|| voicebuf == NULL) && !ci_voice.stop_codec)
|
|| voicebuf == NULL) && !ci_voice.stop_codec)
|
||||||
|
@ -503,10 +518,8 @@ void* voice_request_data(long *realsize, long reqsize)
|
||||||
if (voice_remaining)
|
if (voice_remaining)
|
||||||
{
|
{
|
||||||
voice_is_playing = true;
|
voice_is_playing = true;
|
||||||
break ;
|
|
||||||
}
|
}
|
||||||
|
else if (voice_getmore != NULL)
|
||||||
if (voice_getmore != NULL)
|
|
||||||
{
|
{
|
||||||
voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
|
voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
|
||||||
|
|
||||||
|
@ -519,13 +532,8 @@ void* voice_request_data(long *realsize, long reqsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reqsize < 0)
|
|
||||||
reqsize = 0;
|
|
||||||
|
|
||||||
voice_is_playing = true;
|
voice_is_playing = true;
|
||||||
*realsize = voice_remaining;
|
*realsize = MIN(voice_remaining, reqsize);
|
||||||
if (*realsize > reqsize)
|
|
||||||
*realsize = reqsize;
|
|
||||||
|
|
||||||
if (*realsize == 0)
|
if (*realsize == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -533,9 +541,9 @@ void* voice_request_data(long *realsize, long reqsize)
|
||||||
return voicebuf;
|
return voicebuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* codec_request_buffer_callback(long *realsize, long reqsize)
|
void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
|
||||||
{
|
{
|
||||||
long part_n;
|
size_t short_n, copy_n, buf_rem;
|
||||||
|
|
||||||
/* Voice codec. */
|
/* Voice codec. */
|
||||||
if (current_codec == CODEC_IDX_VOICE) {
|
if (current_codec == CODEC_IDX_VOICE) {
|
||||||
|
@ -547,12 +555,13 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*realsize = MIN((off_t)reqsize, (off_t)cur_ti->available + cur_ti->filerem);
|
copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem);
|
||||||
if (*realsize == 0) {
|
if (copy_n == 0) {
|
||||||
|
*realsize = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((int)*realsize > cur_ti->available) {
|
while (copy_n > cur_ti->available) {
|
||||||
yield();
|
yield();
|
||||||
if (ci.stop_codec || ci.reload_codec) {
|
if (ci.stop_codec || ci.reload_codec) {
|
||||||
*realsize = 0;
|
*realsize = 0;
|
||||||
|
@ -560,19 +569,24 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
part_n = MIN((int)*realsize, filebuflen - buf_ridx);
|
/* How much is left at the end of the file buffer before wrap? */
|
||||||
if (part_n < *realsize) {
|
buf_rem = filebuflen - buf_ridx;
|
||||||
part_n += GUARD_BUFSIZE;
|
/* If we can't satisfy the request without wrapping */
|
||||||
if (part_n < *realsize)
|
if (buf_rem < copy_n) {
|
||||||
*realsize = part_n;
|
/* How short are we? */
|
||||||
memcpy(&filebuf[filebuflen], &filebuf[0], *realsize -
|
short_n = copy_n - buf_rem;
|
||||||
(filebuflen - buf_ridx));
|
/* If we can fudge it with the guardbuf */
|
||||||
|
if (short_n < GUARD_BUFSIZE)
|
||||||
|
memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
|
||||||
|
else
|
||||||
|
copy_n = buf_rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*realsize = copy_n;
|
||||||
return (char *)&filebuf[buf_ridx];
|
return (char *)&filebuf[buf_ridx];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rebuffer_and_seek(int newpos)
|
static bool rebuffer_and_seek(size_t newpos)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -613,11 +627,11 @@ static bool rebuffer_and_seek(int newpos)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void codec_advance_buffer_callback(long amount)
|
void codec_advance_buffer_callback(size_t amount)
|
||||||
{
|
{
|
||||||
if (current_codec == CODEC_IDX_VOICE) {
|
if (current_codec == CODEC_IDX_VOICE) {
|
||||||
//logf("voice ad.buf:%d", amount);
|
//logf("voice ad.buf:%d", amount);
|
||||||
amount = MAX(0, MIN(amount, voice_remaining));
|
amount = MIN(amount, voice_remaining);
|
||||||
voicebuf += amount;
|
voicebuf += amount;
|
||||||
voice_remaining -= amount;
|
voice_remaining -= amount;
|
||||||
|
|
||||||
|
@ -636,23 +650,19 @@ void codec_advance_buffer_callback(long amount)
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_ridx += amount;
|
advance_buffer_counters(amount);
|
||||||
if (buf_ridx >= filebuflen)
|
|
||||||
buf_ridx -= filebuflen;
|
|
||||||
cur_ti->available -= amount;
|
|
||||||
filebufused -= amount;
|
|
||||||
ci.curpos += amount;
|
|
||||||
codec_set_offset_callback(ci.curpos);
|
codec_set_offset_callback(ci.curpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void codec_advance_buffer_loc_callback(void *ptr)
|
void codec_advance_buffer_loc_callback(void *ptr)
|
||||||
{
|
{
|
||||||
long amount;
|
size_t amount;
|
||||||
|
|
||||||
if (current_codec == CODEC_IDX_VOICE)
|
if (current_codec == CODEC_IDX_VOICE)
|
||||||
amount = (long)ptr - (long)voicebuf;
|
amount = (size_t)ptr - (size_t)voicebuf;
|
||||||
else
|
else
|
||||||
amount = (long)ptr - (long)&filebuf[buf_ridx];
|
amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
|
||||||
codec_advance_buffer_callback(amount);
|
codec_advance_buffer_callback(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,16 +682,13 @@ void codec_seek_complete_callback(void)
|
||||||
ci.seek_time = 0;
|
ci.seek_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool codec_seek_buffer_callback(off_t newpos)
|
bool codec_seek_buffer_callback(size_t newpos)
|
||||||
{
|
{
|
||||||
int difference;
|
int difference;
|
||||||
|
|
||||||
if (current_codec == CODEC_IDX_VOICE)
|
if (current_codec == CODEC_IDX_VOICE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (newpos < 0)
|
|
||||||
newpos = 0;
|
|
||||||
|
|
||||||
if (newpos >= cur_ti->filesize)
|
if (newpos >= cur_ti->filesize)
|
||||||
newpos = cur_ti->filesize - 1;
|
newpos = cur_ti->filesize - 1;
|
||||||
|
|
||||||
|
@ -706,9 +713,9 @@ bool codec_seek_buffer_callback(off_t newpos)
|
||||||
logf("seek: -%d", difference);
|
logf("seek: -%d", difference);
|
||||||
filebufused += difference;
|
filebufused += difference;
|
||||||
cur_ti->available += difference;
|
cur_ti->available += difference;
|
||||||
|
if (buf_ridx < (unsigned)difference)
|
||||||
|
buf_ridx += filebuflen;
|
||||||
buf_ridx -= difference;
|
buf_ridx -= difference;
|
||||||
if (buf_ridx < 0)
|
|
||||||
buf_ridx = filebuflen + buf_ridx;
|
|
||||||
ci.curpos -= difference;
|
ci.curpos -= difference;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -716,7 +723,7 @@ bool codec_seek_buffer_callback(off_t newpos)
|
||||||
|
|
||||||
static void set_filebuf_watermark(int seconds)
|
static void set_filebuf_watermark(int seconds)
|
||||||
{
|
{
|
||||||
long bytes;
|
size_t bytes;
|
||||||
|
|
||||||
if (current_codec == CODEC_IDX_VOICE)
|
if (current_codec == CODEC_IDX_VOICE)
|
||||||
return ;
|
return ;
|
||||||
|
@ -724,7 +731,7 @@ static void set_filebuf_watermark(int seconds)
|
||||||
if (!filebuf)
|
if (!filebuf)
|
||||||
return; /* Audio buffers not yet set up */
|
return; /* Audio buffers not yet set up */
|
||||||
|
|
||||||
bytes = MAX((int)cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
|
bytes = MAX(cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
|
||||||
bytes = MIN(bytes, filebuflen / 2);
|
bytes = MIN(bytes, filebuflen / 2);
|
||||||
conf_watermark = bytes;
|
conf_watermark = bytes;
|
||||||
}
|
}
|
||||||
|
@ -803,14 +810,15 @@ void strip_id3v1_tag(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
static const unsigned char tag[] = "TAG";
|
static const unsigned char tag[] = "TAG";
|
||||||
int tagptr;
|
size_t tagptr;
|
||||||
bool found = true;
|
bool found = true;
|
||||||
|
|
||||||
if (filebufused >= 128)
|
if (filebufused >= 128)
|
||||||
{
|
{
|
||||||
|
if (buf_widx < 128)
|
||||||
|
tagptr = filebuflen + buf_widx - 128;
|
||||||
|
else
|
||||||
tagptr = buf_widx - 128;
|
tagptr = buf_widx - 128;
|
||||||
if (tagptr < 0)
|
|
||||||
tagptr += filebuflen;
|
|
||||||
|
|
||||||
for(i = 0;i < 3;i++)
|
for(i = 0;i < 3;i++)
|
||||||
{
|
{
|
||||||
|
@ -839,7 +847,9 @@ void strip_id3v1_tag(void)
|
||||||
|
|
||||||
static void audio_fill_file_buffer(void)
|
static void audio_fill_file_buffer(void)
|
||||||
{
|
{
|
||||||
long i, size;
|
unsigned long i;
|
||||||
|
size_t size;
|
||||||
|
size_t copy_n;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (current_fd < 0)
|
if (current_fd < 0)
|
||||||
|
@ -858,9 +868,9 @@ static void audio_fill_file_buffer(void)
|
||||||
|
|
||||||
if (fill_bytesleft == 0)
|
if (fill_bytesleft == 0)
|
||||||
break ;
|
break ;
|
||||||
rc = MIN(conf_filechunk, filebuflen - buf_widx);
|
copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
|
||||||
rc = MIN(rc, fill_bytesleft);
|
copy_n = MIN(copy_n, fill_bytesleft);
|
||||||
rc = read(current_fd, &filebuf[buf_widx], rc);
|
rc = read(current_fd, &filebuf[buf_widx], copy_n);
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
tracks[track_widx].filerem = 0;
|
tracks[track_widx].filerem = 0;
|
||||||
break ;
|
break ;
|
||||||
|
@ -901,11 +911,12 @@ static int get_codec_base_type(int type)
|
||||||
|
|
||||||
static bool loadcodec(bool start_play)
|
static bool loadcodec(bool start_play)
|
||||||
{
|
{
|
||||||
off_t size;
|
size_t size;
|
||||||
int fd;
|
int fd;
|
||||||
int i, rc;
|
unsigned int i;
|
||||||
|
int rc;
|
||||||
const char *codec_path;
|
const char *codec_path;
|
||||||
int copy_n;
|
size_t copy_n;
|
||||||
int prev_track;
|
int prev_track;
|
||||||
|
|
||||||
switch (tracks[track_widx].id3.codectype) {
|
switch (tracks[track_widx].id3.codectype) {
|
||||||
|
@ -994,7 +1005,7 @@ static bool loadcodec(bool start_play)
|
||||||
}
|
}
|
||||||
|
|
||||||
size = filesize(fd);
|
size = filesize(fd);
|
||||||
if ((off_t)fill_bytesleft < size + conf_watermark) {
|
if (fill_bytesleft < size + conf_watermark) {
|
||||||
logf("Not enough space");
|
logf("Not enough space");
|
||||||
/* Set codectype back to zero to indicate no codec was loaded. */
|
/* Set codectype back to zero to indicate no codec was loaded. */
|
||||||
tracks[track_widx].id3.codectype = 0;
|
tracks[track_widx].id3.codectype = 0;
|
||||||
|
@ -1464,7 +1475,10 @@ static void audio_check_buffer(void)
|
||||||
/* Limit buffering size at first run. */
|
/* Limit buffering size at first run. */
|
||||||
if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit
|
if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit
|
||||||
- filebufused) {
|
- filebufused) {
|
||||||
fill_bytesleft = MAX(0, conf_bufferlimit - filebufused);
|
if (conf_bufferlimit > filebufused)
|
||||||
|
fill_bytesleft = conf_bufferlimit - filebufused;
|
||||||
|
else
|
||||||
|
fill_bytesleft = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to load remainings of the file. */
|
/* Try to load remainings of the file. */
|
||||||
|
@ -1631,11 +1645,11 @@ static int skip_previous_track(bool inside_codec_thread)
|
||||||
cur_ti->available = cur_ti->filesize - cur_ti->filerem;
|
cur_ti->available = cur_ti->filesize - cur_ti->filerem;
|
||||||
|
|
||||||
cur_ti = &tracks[track_ridx];
|
cur_ti = &tracks[track_ridx];
|
||||||
buf_ridx -= cur_ti->filesize;
|
|
||||||
filebufused += cur_ti->filesize;
|
filebufused += cur_ti->filesize;
|
||||||
cur_ti->available = cur_ti->filesize;
|
cur_ti->available = cur_ti->filesize;
|
||||||
if (buf_ridx < 0)
|
if (buf_ridx < cur_ti->filesize)
|
||||||
buf_ridx += filebuflen;
|
buf_ridx += filebuflen;
|
||||||
|
buf_ridx -= cur_ti->filesize;
|
||||||
|
|
||||||
audio_update_trackinfo();
|
audio_update_trackinfo();
|
||||||
|
|
||||||
|
@ -2096,8 +2110,6 @@ void voice_init(void)
|
||||||
{
|
{
|
||||||
logf("Terminating voice codec");
|
logf("Terminating voice codec");
|
||||||
ci_voice.stop_codec = true;
|
ci_voice.stop_codec = true;
|
||||||
if (current_codec != CODEC_IDX_VOICE)
|
|
||||||
swap_codec();
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,13 +37,13 @@
|
||||||
struct track_info {
|
struct track_info {
|
||||||
struct mp3entry id3; /* TAG metadata */
|
struct mp3entry id3; /* TAG metadata */
|
||||||
char *codecbuf; /* Pointer to codec buffer */
|
char *codecbuf; /* Pointer to codec buffer */
|
||||||
long codecsize; /* Codec length in bytes */
|
size_t codecsize; /* Codec length in bytes */
|
||||||
|
|
||||||
off_t filerem; /* Remaining bytes of file NOT in buffer */
|
size_t filerem; /* Remaining bytes of file NOT in buffer */
|
||||||
off_t filesize; /* File total length */
|
size_t filesize; /* File total length */
|
||||||
off_t filepos; /* Read position of file for next buffer fill */
|
size_t filepos; /* Read position of file for next buffer fill */
|
||||||
off_t start_pos; /* Position to first bytes of file in buffer */
|
size_t start_pos; /* Position to first bytes of file in buffer */
|
||||||
volatile int available; /* Available bytes to read from buffer */
|
volatile size_t available; /* Available bytes to read from buffer */
|
||||||
bool taginfo_ready; /* Is metadata read */
|
bool taginfo_ready; /* Is metadata read */
|
||||||
int playlist_offset; /* File location in playlist */
|
int playlist_offset; /* File location in playlist */
|
||||||
bool event_sent; /* Has event callback functions been called? */
|
bool event_sent; /* Has event callback functions been called? */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue