mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
166 lines
No EOL
4.9 KiB
C++
166 lines
No EOL
4.9 KiB
C++
/*
|
|
** 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);
|
|
}
|
|
} |