aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_flac/ExtendedRead.cpp
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/Plugins/Input/in_flac/ExtendedRead.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_flac/ExtendedRead.cpp')
-rw-r--r--Src/Plugins/Input/in_flac/ExtendedRead.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_flac/ExtendedRead.cpp b/Src/Plugins/Input/in_flac/ExtendedRead.cpp
new file mode 100644
index 00000000..d3c08fc8
--- /dev/null
+++ b/Src/Plugins/Input/in_flac/ExtendedRead.cpp
@@ -0,0 +1,166 @@
+/*
+** Copyright (C) 2007-2011 Nullsoft, Inc.
+**
+** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
+** liable for any damages arising from the use of this software.
+**
+** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
+** alter it and redistribute it freely, subject to the following restrictions:
+**
+** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
+** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+**
+** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+**
+** 3. This notice may not be removed or altered from any source distribution.
+**
+** Author: Ben Allison benski@winamp.com
+** Created: March 1, 2007
+**
+*/
+
+#include "main.h"
+#include <FLAC/all.h>
+#include "StreamFileWin32.h"
+#include "QuickBuf.h"
+#include <bfc/platform/types.h>
+#include <assert.h>
+#include "FLACFileCallbacks.h"
+#include "nswasabi/ReferenceCounted.h"
+
+struct ExtendedRead
+{
+ int bps, channels, samplerate, truebps;
+ uint64_t samples;
+ QuickBuf output;
+ FLAC__StreamDecoder *decoder;
+ size_t used;
+ FLACClientData client_data;
+};
+
+static void OnError(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+ //client_data=client_data; // dummy line so i can set a breakpoint
+}
+
+static void OnMetadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+ ExtendedRead *ext = FLAC_GetObject<ExtendedRead>(client_data);
+
+ switch(metadata->type)
+ {
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ {
+ ext->truebps=metadata->data.stream_info.bits_per_sample;
+ ext->bps = (ext->truebps +7) & (~7);
+ ext->channels=metadata->data.stream_info.channels;
+ ext->samplerate=metadata->data.stream_info.sample_rate;
+ ext->samples=metadata->data.stream_info.total_samples;
+ }
+ break;
+ }
+}
+
+static FLAC__StreamDecoderWriteStatus OnAudio(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
+{
+ ExtendedRead *ext = FLAC_GetObject<ExtendedRead>(client_data);
+
+ int byteLength = (ext->bps/8) * ext->channels * frame->header.blocksize;
+ ext->output.Reserve(byteLength);
+ InterleaveAndTruncate(buffer, ext->output, ext->bps, ext->channels, frame->header.blocksize);
+ ext->used = byteLength;
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+extern "C"
+{
+ __declspec( dllexport ) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
+ {
+ nx_file_t file;
+ ReferenceCountedNXString filename_nx;
+ ReferenceCountedNXURI filename_uri;
+ NXStringCreateWithUTF16(&filename_nx, fn);
+ NXURICreateWithNXString(&filename_uri, filename_nx);
+
+ int ret = NXFileOpenFile(&file, filename_uri, nx_file_FILE_read_binary);
+ if (ret != NErr_Success)
+ return 0;
+
+ ExtendedRead * e = (ExtendedRead *)calloc(sizeof(ExtendedRead), 1);
+ e->decoder = FLAC__stream_decoder_new();
+ if (e->decoder == 0)
+ {
+ NXFileRelease(file);
+ free(e);
+ return 0;
+ }
+
+ e->client_data.SetFile(file);
+ e->client_data.SetObject(e);
+
+ FLAC__stream_decoder_set_md5_checking(e->decoder, true);
+ if(FLAC__stream_decoder_init_stream(
+ e->decoder,
+ FLAC_NXFile_Read,
+ FLAC_NXFile_Seek,
+ FLAC_NXFile_Tell,
+ FLAC_NXFile_Length,
+ FLAC_NXFile_EOF,
+ OnAudio,
+ OnMetadata,
+ OnError,
+ &e->client_data
+ ) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+ {
+ FLAC__stream_decoder_delete(e->decoder);
+ NXFileRelease(file);
+ free(e);
+ return 0;
+ }
+
+ FLAC__stream_decoder_process_until_end_of_metadata(e->decoder);
+ *bps = e->truebps;
+ *nch = e->channels;
+ *srate = e->samplerate;
+ *size = (int)(e->samples * (e->bps/8) * e->channels);
+ return (intptr_t) e;
+ }
+
+ __declspec( dllexport ) intptr_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch)
+ {
+ ExtendedRead *ext = (ExtendedRead *)handle;
+
+ while(!ext->used) // loop until we get some data
+ {
+ if (FLAC__stream_decoder_process_single(ext->decoder) == 0)
+ break; // break out if there's an error
+
+ FLAC__StreamDecoderState FLACstate = FLAC__stream_decoder_get_state(ext->decoder);
+ if (FLACstate == FLAC__STREAM_DECODER_END_OF_STREAM) // break out if we hit EOF
+ break;
+ }
+
+ if (ext->used)
+ {
+ size_t toCopy = min(len, ext->used);
+ memcpy(dest, ext->output, toCopy);
+ if (toCopy < ext->used)
+ ext->output.Move(toCopy);
+ ext->used-=toCopy;
+ return toCopy;
+ }
+
+ return 0;
+ }
+
+ __declspec( dllexport ) void winampGetExtendedRead_close(intptr_t handle)
+ {
+ ExtendedRead *ext = (ExtendedRead *)handle;
+
+ ext->output.Free();
+ FLAC__stream_decoder_finish(ext->decoder);
+ FLAC__stream_decoder_delete(ext->decoder);
+ NXFileRelease(ext->client_data.GetFile());
+ free(ext);
+ }
+} \ No newline at end of file