summaryrefslogtreecommitdiff
path: root/src/client/snd_codec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/snd_codec.cpp')
-rw-r--r--src/client/snd_codec.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/client/snd_codec.cpp b/src/client/snd_codec.cpp
new file mode 100644
index 0000000..a794b90
--- /dev/null
+++ b/src/client/snd_codec.cpp
@@ -0,0 +1,239 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2000-2013 Darklegion Development
+Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
+Copyright (C) 2015-2019 GrangerHub
+
+This file is part of Tremulous.
+
+Tremulous 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 3 of the License,
+or (at your option) any later version.
+
+Tremulous 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 Tremulous; if not, see <https://www.gnu.org/licenses/>
+
+===========================================================================
+*/
+
+#include "client.h"
+#include "snd_codec.h"
+
+static snd_codec_t *codecs;
+
+/*
+=================
+S_CodecGetSound
+
+Opens/loads a sound, tries codec based on the sound's file extension
+then tries all supported codecs.
+=================
+*/
+static void *S_CodecGetSound(const char *filename, snd_info_t *info)
+{
+ snd_codec_t *codec;
+ snd_codec_t *orgCodec = NULL;
+ bool orgNameFailed = false;
+ char localName[ MAX_QPATH ];
+ const char *ext;
+ char altName[ MAX_QPATH ];
+ void *rtn = NULL;
+
+ Q_strncpyz(localName, filename, MAX_QPATH);
+
+ ext = COM_GetExtension(localName);
+
+ if( *ext )
+ {
+ // Look for the correct loader and use it
+ for( codec = codecs; codec; codec = codec->next )
+ {
+ if( !Q_stricmp( ext, codec->ext ) )
+ {
+ // Load
+ if( info )
+ rtn = codec->load(localName, info);
+ else
+ rtn = codec->open(localName);
+ break;
+ }
+ }
+
+ // A loader was found
+ if( codec )
+ {
+ if( !rtn )
+ {
+ // Loader failed, most likely because the file isn't there;
+ // try again without the extension
+ orgNameFailed = true;
+ orgCodec = codec;
+ COM_StripExtension( filename, localName, MAX_QPATH );
+ }
+ else
+ {
+ // Something loaded
+ return rtn;
+ }
+ }
+ }
+
+ // Try and find a suitable match using all
+ // the sound codecs supported
+ for( codec = codecs; codec; codec = codec->next )
+ {
+ if( codec == orgCodec )
+ continue;
+
+ Com_sprintf( altName, sizeof (altName), "%s.%s", localName, codec->ext );
+
+ // Load
+ if( info )
+ rtn = codec->load(altName, info);
+ else
+ rtn = codec->open(altName);
+
+ if( rtn )
+ {
+ if( orgNameFailed )
+ {
+ Com_DPrintf(S_COLOR_YELLOW "WARNING: %s not present, using %s instead\n",
+ filename, altName );
+ }
+
+ return rtn;
+ }
+ }
+
+ Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename);
+
+ return NULL;
+}
+
+/*
+=================
+S_CodecInit
+=================
+*/
+void S_CodecInit()
+{
+ codecs = NULL;
+
+#ifdef USE_CODEC_OPUS
+ S_CodecRegister(&opus_codec);
+#endif
+
+#ifdef USE_CODEC_VORBIS
+ S_CodecRegister(&ogg_codec);
+#endif
+
+// Register wav codec last so that it is always tried first when a file extension was not found
+ S_CodecRegister(&wav_codec);
+}
+
+/*
+=================
+S_CodecShutdown
+=================
+*/
+void S_CodecShutdown()
+{
+ codecs = NULL;
+}
+
+/*
+=================
+S_CodecRegister
+=================
+*/
+void S_CodecRegister(snd_codec_t *codec)
+{
+ codec->next = codecs;
+ codecs = codec;
+}
+
+/*
+=================
+S_CodecLoad
+=================
+*/
+void *S_CodecLoad(const char *filename, snd_info_t *info)
+{
+ return S_CodecGetSound(filename, info);
+}
+
+/*
+=================
+S_CodecOpenStream
+=================
+*/
+snd_stream_t *S_CodecOpenStream(const char *filename)
+{
+ return (snd_stream_t*)S_CodecGetSound(filename, NULL);
+}
+
+void S_CodecCloseStream(snd_stream_t *stream)
+{
+ stream->codec->close(stream);
+}
+
+int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
+{
+ return stream->codec->read(stream, bytes, buffer);
+}
+
+//=======================================================================
+// Util functions (used by codecs)
+
+/*
+=================
+S_CodecUtilOpen
+=================
+*/
+snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
+{
+ snd_stream_t *stream;
+ fileHandle_t hnd;
+ int length;
+
+ // Try to open the file
+ length = FS_FOpenFileRead(filename, &hnd, true);
+ if(!hnd)
+ {
+ Com_DPrintf("Can't read sound file %s\n", filename);
+ return NULL;
+ }
+
+ // Allocate a stream
+ stream = (snd_stream_t*)Z_Malloc(sizeof(snd_stream_t));
+ if(!stream)
+ {
+ FS_FCloseFile(hnd);
+ return NULL;
+ }
+
+ // Copy over, return
+ stream->codec = codec;
+ stream->file = hnd;
+ stream->length = length;
+ return stream;
+}
+
+/*
+=================
+S_CodecUtilClose
+=================
+*/
+void S_CodecUtilClose(snd_stream_t **stream)
+{
+ FS_FCloseFile((*stream)->file);
+ Z_Free(*stream);
+ *stream = NULL;
+}