/* * Audio Codecs: Adapted from ioq3 with changes. * For now, only handles streaming music, not sound effects. * * Copyright (C) 1999-2005 Id Software, Inc. * Copyright (C) 2005 Stuart Dalton * Copyright (C) 2010-2012 O.Sezer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "q_defs.h" #include "snd_codec.h" #include "snd_codeci.h" static snd_codec_t *codecs[] = { #define snd_codec__xmac(x, y) &x##_codec, #include "snd_codec.h" NULL }; /* ================= S_CodecInit ================= */ void S_CodecInit(void) { snd_codec_t **codec; for(codec = codecs; *codec; codec++) { (*codec)->initialize(); } } /* ================= S_CodecShutdown ================= */ void S_CodecShutdown(void) { snd_codec_t **codec; for(codec = codecs; *codec; codec++) { (*codec)->shutdown(); } } /* ================= S_CodecOpenStream ================= */ snd_stream_t *S_CodecOpenStreamType(const char *filename, uint32_t type) { snd_codec_t **codec; snd_stream_t *stream; if(type == CODECTYPE_NONE) { Con_Printf("Bad type for %s\n", filename); return NULL; } for(codec = codecs; *codec; codec++) { if((*codec)->type == type) break; } if(!*codec) { Con_Printf("Unknown type for %s\n", filename); return NULL; } stream = S_CodecUtilOpen(filename, *codec); if(stream) { if((*codec)->codec_open(stream)) stream->status = STREAM_PLAY; else S_CodecUtilClose(&stream); } return stream; } snd_stream_t *S_CodecOpenStreamExt(const char *filename) { snd_codec_t **codec; snd_stream_t *stream; const char *ext; ext = COM_FileGetExtension(filename); if(! *ext) { Con_Printf("No extension for %s\n", filename); return NULL; } for(codec = codecs; *codec; codec++) { if(!q_strcasecmp(ext, (*codec)->ext)) break; } if(!*codec) { Con_Printf("Unknown extension for %s\n", filename); return NULL; } stream = S_CodecUtilOpen(filename, *codec); if(stream) { if((*codec)->codec_open(stream)) stream->status = STREAM_PLAY; else S_CodecUtilClose(&stream); } return stream; } snd_stream_t *S_CodecOpenStreamAny(const char *filename) { snd_codec_t **codec; snd_stream_t *stream; const char *ext; ext = COM_FileGetExtension(filename); if(!*ext) /* try all available */ { char tmp[MAX_QPATH]; for(codec = codecs; *codec; codec++) { q_snprintf(tmp, sizeof(tmp), "%s.%s", filename, (*codec)->ext); stream = S_CodecUtilOpen(tmp, *codec); if(stream) { if((*codec)->codec_open(stream)) { stream->status = STREAM_PLAY; return stream; } S_CodecUtilClose(&stream); } } return NULL; } else /* use the name as is */ { for(codec = codecs; *codec; codec++) { if(!q_strcasecmp(ext, (*codec)->ext)) break; } if(!*codec) { Con_Printf("Unknown extension for %s\n", filename); return NULL; } stream = S_CodecUtilOpen(filename, *codec); if(stream) { if((*codec)->codec_open(stream)) stream->status = STREAM_PLAY; else S_CodecUtilClose(&stream); } return stream; } } bool S_CodecForwardStream(snd_stream_t *stream, uint32_t type) { snd_codec_t **codec; for(codec = codecs; *codec; codec++) { if((*codec)->type == type) break; } if(!*codec) return false; stream->codec = *codec; return (*codec)->codec_open(stream); } void S_CodecCloseStream(snd_stream_t *stream) { stream->status = STREAM_NONE; stream->codec->codec_close(stream); } int32_t S_CodecRewindStream(snd_stream_t *stream) { return stream->codec->codec_rewind(stream); } int32_t S_CodecReadStream(snd_stream_t *stream, int32_t bytes, void *buffer) { return stream->codec->codec_read(stream, bytes, buffer); } /* Util functions (used by codecs) */ snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec) { snd_stream_t *stream; FILE *handle; bool pak; long length; /* Try to open the file */ length = (long) COM_FOpenFile(filename, &handle, NULL); pak = file_from_pak; if(length == -1) { Con_DPrintf("Couldn't open %s\n", filename); return NULL; } /* Allocate a stream, Z_Malloc zeroes its content */ stream = (snd_stream_t *) Z_Malloc(sizeof(snd_stream_t)); stream->codec = codec; stream->fh.file = handle; stream->fh.start = ftell(handle); stream->fh.pos = 0; stream->fh.length = length; stream->fh.pak = stream->pak = pak; q_strlcpy(stream->name, filename, MAX_QPATH); return stream; } void S_CodecUtilClose(snd_stream_t **stream) { fclose((*stream)->fh.file); Z_Free(*stream); *stream = NULL; }