aboutsummaryrefslogtreecommitdiff
path: root/Src/Agave/DecodeFile
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Agave/DecodeFile
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Agave/DecodeFile')
-rw-r--r--Src/Agave/DecodeFile/api_decodefile.h104
-rw-r--r--Src/Agave/DecodeFile/ifc_audiostream.h65
-rw-r--r--Src/Agave/DecodeFile/ifc_raw_media_reader.h26
-rw-r--r--Src/Agave/DecodeFile/svc_raw_media_reader.h32
4 files changed, 227 insertions, 0 deletions
diff --git a/Src/Agave/DecodeFile/api_decodefile.h b/Src/Agave/DecodeFile/api_decodefile.h
new file mode 100644
index 00000000..c2b3c46a
--- /dev/null
+++ b/Src/Agave/DecodeFile/api_decodefile.h
@@ -0,0 +1,104 @@
+#ifndef NULLSOFT_AGAVE_API_DECODEFILE_H
+#define NULLSOFT_AGAVE_API_DECODEFILE_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+#include "ifc_audiostream.h"
+
+enum
+{
+ API_DECODEFILE_SUCCESS = 0,
+ API_DECODEFILE_FAILURE = 1,
+
+ API_DECODEFILE_UNSUPPORTED = 2, // type is unsupported
+ API_DECODEFILE_NO_INTERFACE = 3, // type is supported, but plugin does provide any interfaces for direct decoding
+ API_DECODEFILE_WINAMP_PRO = 4, // user has to pay $$$ to do this
+ API_DECODEFILE_NO_RIGHTS = 5, // user is not allowed to decode this file (e.g. DRM)
+ API_DECODEFILE_BAD_RESAMPLE = 6, // Winamp is unable to resample this file to CDDA format (stereo 16bit 44.1kHz)
+ API_DECODEFILE_FAIL_NO_WARN = 7, // we have already informed the user of an issue so do not show again e.g. CD playing so cannot also do a rip
+};
+
+enum
+{
+ AUDIOPARAMETERS_FLOAT = 1,
+ AUDIOPARAMETERS_MAXCHANNELS = 2, // set this if channels is meant to define an upper limit
+ // (e.g. setting channels=2 and flags |= AUDIOPARAMETERS_MAXCHANNELS means 1 or 2 channels is OK, but not more)
+ AUDIOPARAMETERS_MAXSAMPLERATE = 4, // like AUDIOPARAMETERS_MAXCHANNELS but for sample rate
+ AUDIOPARAMETERS_NON_INTERLEAVED = 8, // audio data is stored as separate buffers per channel. not currently implemented
+};
+
+struct AudioParameters
+{
+public:
+ AudioParameters() : bitsPerSample(0), channels(0), sampleRate(0), sampleRateReal(0.f), flags(0), sizeBytes((size_t) - 1), errorCode(API_DECODEFILE_SUCCESS)
+ {}
+ uint32_t bitsPerSample;
+ uint32_t channels;
+ uint32_t sampleRate;
+ float sampleRateReal; // yes this is duplicate.
+ int flags;
+ size_t sizeBytes; // total size of decoded file, (size_t)-1 means don't know
+ int errorCode;
+};
+
+class api_decodefile : public Dispatchable
+{
+public:
+ /* OpenAudioBackground gives you back an ifc_audiostream that you can use to get decompressed bits
+ * if it returns 0, check parameters->errorCode for the failure reason
+ * fill parameters with desired values (0 if you don't care)
+ * the decoder will _do its best_ to satisfy your passed-in audio parameters
+ * but this API does not guarantee them, so be sure to check the parameters struct after the function returns
+ * it's **UP TO YOU** to do any necessary conversion (sample rate, channels, bits-per-sample) if the decoder can't do it
+ */
+ ifc_audiostream *OpenAudioBackground(const wchar_t *filename, AudioParameters *parameters);
+ /* OpenAudio is the same as OpenAudioBackground
+ * but, it will use the input plugin system to decode if necessary
+ * so it's best to use this in a separate winamp.exe
+ * to be honest, it was designed for internal use in the CD burner
+ * so it's best not to use this one at all
+ */
+ ifc_audiostream *OpenAudio(const wchar_t *filename, AudioParameters *parameters);
+
+ void CloseAudio(ifc_audiostream *audioStream);
+ /* verifies that a decoder exists to decompress this filename.
+ this is not a guarantee that the file is openable, just that it can be matched to a decoder */
+ bool DecoderExists(const wchar_t *filename);
+
+public:
+ DISPATCH_CODES
+ {
+ API_DECODEFILE_OPENAUDIO = 10,
+ API_DECODEFILE_OPENAUDIO2 = 11,
+ API_DECODEFILE_CLOSEAUDIO = 20,
+ API_DECODEFILE_DECODEREXISTS = 30,
+ };
+};
+
+inline ifc_audiostream *api_decodefile::OpenAudio(const wchar_t *filename, AudioParameters *parameters)
+{
+ return _call(API_DECODEFILE_OPENAUDIO, (ifc_audiostream *)0, filename, parameters);
+}
+
+inline ifc_audiostream *api_decodefile::OpenAudioBackground(const wchar_t *filename, AudioParameters *parameters)
+{
+ return _call(API_DECODEFILE_OPENAUDIO2, (ifc_audiostream *)0, filename, parameters);
+}
+
+inline void api_decodefile::CloseAudio(ifc_audiostream *audioStream)
+{
+ _voidcall(API_DECODEFILE_CLOSEAUDIO, audioStream);
+}
+
+inline bool api_decodefile::DecoderExists(const wchar_t *filename)
+{
+ return _call(API_DECODEFILE_DECODEREXISTS, (bool)true, filename); // we default to true so that an old implementation doesn't break completely
+}
+
+// {9B4188F5-4295-48ab-B50C-F2B0BB56D242}
+static const GUID decodeFileGUID =
+{
+ 0x9b4188f5, 0x4295, 0x48ab, { 0xb5, 0xc, 0xf2, 0xb0, 0xbb, 0x56, 0xd2, 0x42 }
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Agave/DecodeFile/ifc_audiostream.h b/Src/Agave/DecodeFile/ifc_audiostream.h
new file mode 100644
index 00000000..586d704c
--- /dev/null
+++ b/Src/Agave/DecodeFile/ifc_audiostream.h
@@ -0,0 +1,65 @@
+#ifndef NULLSOFT_AGAVE_IFC_AUDIOSTREAM_H
+#define NULLSOFT_AGAVE_IFC_AUDIOSTREAM_H
+
+#include <bfc/dispatch.h>
+
+class ifc_audiostream : public Dispatchable
+{
+protected:
+ ifc_audiostream() {}
+ ~ifc_audiostream() {}
+public:
+ /* returns number of bytes written to buffer.
+ * a return value of 0 means EOF
+ */
+ size_t ReadAudio(void *buffer, size_t sizeBytes);
+
+ size_t ReadAudio(void *buffer, size_t, int *killswitch, int *errorCode);
+ /* Seeks to a point in the stream in milliseconds
+ * returns TRUE if successful, FALSE otherwise
+ */
+ int SeekToTimeMs(int millisecs);
+
+ /* returns 1 if this stream is seekable using SeekToTime, 0 otherwise
+ */
+ int CanSeek();
+public:
+ DISPATCH_CODES
+ {
+ IFC_AUDIOSTREAM_READAUDIO = 10,
+ IFC_AUDIOSTREAM_READAUDIO2 = 11,
+ IFC_AUDIOSTREAM_SEEKTOTIMEMS = 20,
+ IFC_AUDIOSTREAM_CANSEEK = 30,
+ };
+};
+
+inline size_t ifc_audiostream::ReadAudio(void *buffer, size_t sizeBytes)
+{
+ return _call(IFC_AUDIOSTREAM_READAUDIO, (size_t)0, buffer, sizeBytes);
+}
+
+inline size_t ifc_audiostream::ReadAudio(void *buffer, size_t sizeBytes, int *killswitch, int *errorCode)
+{
+ void *params[4] = { &buffer, &sizeBytes, &killswitch, &errorCode};
+ size_t retval;
+
+ if (_dispatch(IFC_AUDIOSTREAM_READAUDIO2, &retval, params, 4))
+ return retval;
+ else
+ {
+ *errorCode=0;
+ return ReadAudio(buffer, sizeBytes);
+ }
+}
+
+inline int ifc_audiostream::SeekToTimeMs(int millisecs)
+{
+ return _call(IFC_AUDIOSTREAM_SEEKTOTIMEMS, (int)0, millisecs);
+}
+
+inline int ifc_audiostream::CanSeek()
+{
+ return _call(IFC_AUDIOSTREAM_CANSEEK, (int)0);
+}
+
+#endif
diff --git a/Src/Agave/DecodeFile/ifc_raw_media_reader.h b/Src/Agave/DecodeFile/ifc_raw_media_reader.h
new file mode 100644
index 00000000..cc86f1a9
--- /dev/null
+++ b/Src/Agave/DecodeFile/ifc_raw_media_reader.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <bfc/dispatch.h>
+#include <bfc/error.h>
+
+class ifc_raw_media_reader : public Dispatchable
+{
+protected:
+ ifc_raw_media_reader() {}
+ ~ifc_raw_media_reader() {}
+
+public:
+ int Read(void *buffer, size_t buffer_size, size_t *bytes_read);
+ /* TODO: we'll probably need stuff in here like EndOfFile, determining a good buffer size, etc */
+
+ DISPATCH_CODES
+ {
+ RAW_READ
+ };
+};
+
+inline int ifc_raw_media_reader::Read(void *buffer, size_t buffer_size, size_t *bytes_read)
+{
+ return _call(RAW_READ, (int)NErr_NotImplemented, buffer, buffer_size, bytes_read);
+}
+
diff --git a/Src/Agave/DecodeFile/svc_raw_media_reader.h b/Src/Agave/DecodeFile/svc_raw_media_reader.h
new file mode 100644
index 00000000..c70c8085
--- /dev/null
+++ b/Src/Agave/DecodeFile/svc_raw_media_reader.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <bfc/dispatch.h>
+#include "ifc_raw_media_reader.h"
+#include <bfc/error.h>
+
+class svc_raw_media_reader : public Dispatchable
+{
+protected:
+ svc_raw_media_reader() {}
+ ~svc_raw_media_reader() {}
+public:
+ static FOURCC getServiceType() { return svc_raw_media_reader::SERVICETYPE; }
+ int CreateRawMediaReader(const wchar_t *filename, ifc_raw_media_reader **reader);
+public:
+ DISPATCH_CODES
+ {
+ CREATERAWMEDIAREADER = 0,
+ };
+
+
+ enum
+ {
+ SERVICETYPE = MK4CC('r','a','w','m')
+ };
+};
+
+inline int svc_raw_media_reader::CreateRawMediaReader(const wchar_t *filename, ifc_raw_media_reader **reader)
+{
+ return _call(CREATERAWMEDIAREADER, (int)NErr_NotImplemented, filename, reader);
+}
+