rockbox/apps/codecs.c
Nicolas Pennequin b838a62adf Make bufread and bufgetdata blocking. They now return when enough data is available or when EOF is reached. This improves the API and removes the need for several duplicate waiting loops.
Also fix a few logfqueue messages.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15412 a1c6a512-1295-4272-9138-f99709370657
2007-11-02 19:13:03 +00:00

267 lines
6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 Björn Stenberg
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <atoi.h>
#include <timefuncs.h>
#include <ctype.h>
#include "debug.h"
#include "button.h"
#include "dir.h"
#include "file.h"
#include "kernel.h"
#include "sprintf.h"
#include "screens.h"
#include "misc.h"
#include "mas.h"
#include "codecs.h"
#include "lang.h"
#include "keyboard.h"
#include "mpeg.h"
#include "buffer.h"
#include "buffering.h"
#include "mp3_playback.h"
#include "playback.h"
#include "backlight.h"
#include "ata.h"
#include "talk.h"
#include "mp3data.h"
#include "powermgmt.h"
#include "system.h"
#include "sound.h"
#include "splash.h"
#include "general.h"
#define LOGF_ENABLE
#include "logf.h"
#ifdef SIMULATOR
#if CONFIG_CODEC == SWCODEC
unsigned char codecbuf[CODEC_SIZE];
#endif
void *sim_codec_load_ram(char* codecptr, int size, void **pd);
void sim_codec_close(void *pd);
#else
#define sim_codec_close(x)
extern unsigned char codecbuf[];
#endif
extern void* plugin_get_audio_buffer(size_t *buffer_size);
struct codec_api ci_voice;
struct codec_api ci = {
0, /* filesize */
0, /* curpos */
NULL, /* id3 */
NULL, /* taginfo_ready */
false, /* stop_codec */
0, /* new_track */
0, /* seek_time */
NULL, /* get_codec_memory */
NULL, /* pcmbuf_insert */
NULL, /* set_elapsed */
NULL, /* read_filebuf */
NULL, /* request_buffer */
NULL, /* advance_buffer */
NULL, /* advance_buffer_loc */
NULL, /* seek_buffer */
NULL, /* seek_complete */
NULL, /* mp3_get_filepos */
NULL, /* request_next_track */
NULL, /* discard_codec */
NULL, /* set_offset */
NULL, /* configure */
/* kernel/ system */
PREFIX(sleep),
yield,
/* strings and memory */
strcpy,
strncpy,
strlen,
strcmp,
strcat,
memset,
memcpy,
memmove,
memcmp,
memchr,
#if defined(DEBUG) || defined(SIMULATOR)
debugf,
#endif
#ifdef ROCKBOX_HAS_LOGF
logf,
#endif
(qsort_func)qsort,
&global_settings,
#ifdef RB_PROFILE
profile_thread,
profstop,
profile_func_enter,
profile_func_exit,
#endif
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
false, /* stop_encoder */
0, /* enc_codec_loaded */
enc_get_inputs,
enc_set_parameters,
enc_get_chunk,
enc_finish_chunk,
enc_pcm_buf_near_empty,
enc_get_pcm_data,
enc_unget_pcm_data,
/* file */
(open_func)PREFIX(open),
close,
(read_func)read,
PREFIX(lseek),
(write_func)write,
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#ifdef CPU_BOOST_LOGGING
cpu_boost_,
#else
cpu_boost,
#endif
#endif
round_value_to_list32,
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
#ifdef CACHE_FUNCTIONS_AS_CALL
flush_icache,
invalidate_icache,
#endif
};
void codec_get_full_path(char *path, const char *codec_root_fn)
{
snprintf(path, MAX_PATH-1, CODECS_DIR "/%s." CODEC_EXTENSION,
codec_root_fn);
}
static int codec_load_ram(int size, struct codec_api *api)
{
struct codec_header *hdr;
int status;
#ifndef SIMULATOR
hdr = (struct codec_header *)codecbuf;
if (size <= (signed)sizeof(struct codec_header)
|| (hdr->magic != CODEC_MAGIC
#ifdef HAVE_RECORDING
&& hdr->magic != CODEC_ENC_MAGIC
#endif
)
|| hdr->target_id != TARGET_ID
|| hdr->load_addr != codecbuf
|| hdr->end_addr > codecbuf + CODEC_SIZE)
{
logf("codec header error");
return CODEC_ERROR;
}
#else /* SIMULATOR */
void *pd;
hdr = sim_codec_load_ram(codecbuf, size, &pd);
if (pd == NULL)
return CODEC_ERROR;
if (hdr == NULL
|| (hdr->magic != CODEC_MAGIC
#ifdef HAVE_RECORDING
&& hdr->magic != CODEC_ENC_MAGIC
#endif
)
|| hdr->target_id != TARGET_ID) {
sim_codec_close(pd);
return CODEC_ERROR;
}
#endif /* SIMULATOR */
if (hdr->api_version > CODEC_API_VERSION
|| hdr->api_version < CODEC_MIN_API_VERSION) {
sim_codec_close(pd);
return CODEC_ERROR;
}
invalidate_icache();
status = hdr->entry_point(api);
sim_codec_close(pd);
return status;
}
int codec_load_buf(unsigned int hid, int size, struct codec_api *api) {
int rc;
rc = bufread(hid, size, codecbuf);
if (rc < 0) {
logf("error loading codec");
return CODEC_ERROR;
}
if (rc < size) {
logf("codec ended %d early",size - rc);
return CODEC_ERROR;
}
api->discard_codec();
return codec_load_ram(size, api);
}
int codec_load_file(const char *plugin, struct codec_api *api)
{
char msgbuf[80];
char path[MAX_PATH];
int fd;
int rc;
codec_get_full_path(path, plugin);
fd = open(path, O_RDONLY);
if (fd < 0) {
snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", path);
logf("Codec load error:%d", fd);
gui_syncsplash(HZ*2, msgbuf);
return fd;
}
rc = read(fd, &codecbuf[0], CODEC_SIZE);
close(fd);
if (rc <= 0) {
logf("Codec read error");
return CODEC_ERROR;
}
return codec_load_ram((size_t)rc, api);
}