check in new version of the winamp3 plugin

This commit is contained in:
Josh Coalson 2001-11-08 23:54:10 +00:00
parent 8c13e6526e
commit 53ad911a1d
8 changed files with 885 additions and 3 deletions

View File

@ -15,6 +15,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
EXTRA_DIST = Makefile.vc \
core_api.h \
in_flac.cpp
EXTRA_DIST = \
README.txt \
cnv_flacpcm.cpp \
cnv_flacpcm.dsp \
cnv_flacpcm.dsw \
cnv_flacpcm.h \
flacpcm.cpp \
flacpcm.h

View File

@ -0,0 +1,6 @@
This plugin require the Wasabi SDK, and the project assumes that you have it
installed in the standard place: \Wasabi SDK. If not, you will have to edit
the .dsp file to change the path.
Also, you must build libFLAC first; if you haven't, cd to src\libFLAC and
run 'nmake /f Makefile.vc'

View File

@ -0,0 +1,101 @@
/* FLAC input plugin for Winamp3
* Copyright (C) 2000,2001 Josh Coalson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* NOTE: this code is derived from the 'rawpcm' example by
* Nullsoft; the original license for the 'rawpcm' example follows.
*/
/*
Nullsoft WASABI Source File License
Copyright 1999-2001 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.
Brennan Underwood
brennan@nullsoft.com
*/
#include "cnv_flacpcm.h"
#include "flacpcm.h"
static WACNAME wac;
WAComponentClient *the = &wac;
#include "studio/services/servicei.h"
static waServiceT<svc_mediaConverter, FlacPcm> flacpcm;
// {683FA153-4055-467c-ABEE-5E35FA03C51E}
static const GUID guid =
{ 0x683fa153, 0x4055, 0x467c, { 0xab, 0xee, 0x5e, 0x35, 0xfa, 0x3, 0xc5, 0x1e } };
_int nch;
_int samplerate;
_int bps;
WACNAME::WACNAME() : CfgItemI("RAW files support") {
#ifdef FORTIFY
FortifySetName("cnv_flacpcm.wac");
FortifyEnterScope();
#endif
}
WACNAME::~WACNAME() {
#ifdef FORTIFY
FortifyLeaveScope();
#endif
}
GUID WACNAME::getGUID() {
return guid;
}
void WACNAME::onRegisterServices() {
api->service_register(&flacpcm);
api->core_registerExtension("*.flac","FLAC Files");
nch.setName("# of channels");
nch=2;
registerAttribute(&nch);
samplerate.setName("Sample rate");
samplerate=44100;
registerAttribute(&samplerate);
bps.setName("Bits per second");
bps=16;
registerAttribute(&bps);
}
void WACNAME::onDestroy() {
api->service_deregister(&flacpcm);
WAComponentClient::onDestroy();
}

View File

@ -0,0 +1,205 @@
# Microsoft Developer Studio Project File - Name="cnv_flacpcm" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=cnv_flacpcm - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "cnv_flacpcm.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "cnv_flacpcm.mak" CFG="cnv_flacpcm - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "cnv_flacpcm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "cnv_flacpcm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName "$/Studio/cnv_flacpcm"
# PROP Scc_LocalPath "."
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "cnv_flacpcm - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "cnv_flacpcm_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /I "\Wasabi SDK\studio" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "cnv_flacpcm_EXPORTS" /D "USE_ASM" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 libFLAC.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib msacm32.lib winmm.lib /nologo /dll /machine:I386 /out:"../../obj/bin/cnv_flacpcm.wac" /libpath:"../../obj/lib"
# SUBTRACT LINK32 /nodefaultlib
!ELSEIF "$(CFG)" == "cnv_flacpcm - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "cnv_flacpcm_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "\Wasabi SDK\studio" /D "_DEBUG" /D "WACLIENT_NOICONSUPPORT" /D "REAL_STDIO" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "cnv_flacpcm_EXPORTS" /D "USE_ASM" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 libFLAC.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib msacm32.lib winmm.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libc.lib" /out:"../../obj/bin/cnv_flacpcm.wac" /pdbtype:sept /libpath:"../../obj/lib"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "cnv_flacpcm - Win32 Release"
# Name "cnv_flacpcm - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Group "Wasabi SDK"
# PROP Default_Filter ""
# Begin Source File
SOURCE="\Wasabi SDK\studio\studio\assert.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\attribs\attribute.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\attribs\attrint.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\bitmap.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\blending.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\canvas.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\attribs\cfgitemi.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\studio\corecb.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\depend.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\nsGUID.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\pathparse.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\ptrlist.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\region.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\studio\services\servicei.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\std.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\common\string.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\studio\services\svc_mediaconverter.cpp"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\studio\services\svc_mediaconverter.h"
# End Source File
# Begin Source File
SOURCE="\Wasabi SDK\studio\studio\waclient.cpp"
# End Source File
# End Group
# Begin Source File
SOURCE=.\cnv_flacpcm.cpp
# End Source File
# Begin Source File
SOURCE=.\flacpcm.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\cnv_flacpcm.h
# End Source File
# Begin Source File
SOURCE=.\flacpcm.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\README.txt
# End Source File
# End Target
# End Project

View File

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "cnv_flacpcm"=.\cnv_flacpcm.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -0,0 +1,75 @@
/* FLAC input plugin for Winamp3
* Copyright (C) 2000,2001 Josh Coalson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* NOTE: this code is derived from the 'rawpcm' example by
* Nullsoft; the original license for the 'rawpcm' example follows.
*/
/*
Nullsoft WASABI Source File License
Copyright 1999-2001 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.
Brennan Underwood
brennan@nullsoft.com
*/
#ifndef _CNV_FLACPCM_H
#define _CNV_FLACPCM_H
#include "studio/wac.h"
#include "common/rootcomp.h"
#include "attribs/cfgitemi.h"
#include "attribs/attrint.h"
#define WACNAME WACcnv_flacpcm
class WACNAME : public WAComponentClient, public CfgItemI {
public:
WACNAME();
virtual ~WACNAME();
virtual const char *getName() { return "FLAC to PCM converter"; };
virtual GUID getGUID();
virtual void onRegisterServices();
virtual void onDestroy();
virtual int getDisplayComponent() { return FALSE; };
virtual CfgItem *getCfgInterface(int n) { return this; }
};
#endif

View File

@ -0,0 +1,354 @@
/* FLAC input plugin for Winamp3
* Copyright (C) 2000,2001 Josh Coalson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* NOTE: this code is derived from the 'rawpcm' example by
* Nullsoft; the original license for the 'rawpcm' example follows.
*/
/*
Nullsoft WASABI Source File License
Copyright 1999-2001 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.
Brennan Underwood
brennan@nullsoft.com
*/
#include "flacpcm.h"
extern "C" {
#include "FLAC/utility.h"
};
struct id3v1_struct {
FLAC__byte raw[128];
char title[31];
char artist[31];
char album[31];
char comment[31];
unsigned year;
unsigned track; /* may be 0 if v1 (not v1.1) tag */
unsigned genre;
char description[1024]; /* the formatted description passed to the gui */
};
static bool get_id3v1_tag_(const char *filename, id3v1_struct *tag);
FlacPcm::FlacPcm():
needs_seek(false),
seek_sample(0),
samples_in_reservoir(0),
abort_flag(false),
reader(0),
decoder(0)
{
}
FlacPcm::~FlacPcm()
{
cleanup();
}
int FlacPcm::getInfos(MediaInfo *infos)
{
reader = infos->getReader();
if(!reader) return 0;
//@@@ to be really "clean" we should go through the reader instead of directly to the file...
if(!FLAC__utility_get_streaminfo(infos->getFilename(), &stream_info))
return 1;
id3v1_struct tag;
//@@@ ditto here...
bool has_tag = get_id3v1_tag_(infos->getFilename(), &tag);
infos->setLength(lengthInMsec());
//@@@ infos->setTitle(Std::filename(infos->getFilename()));
infos->setTitle(tag.description);
infos->setInfo(StringPrintf("FLAC:<%ihz:%ibps:%dch>", stream_info.sample_rate, stream_info.bits_per_sample, stream_info.channels)); //@@@ fix later
if(has_tag) {
infos->setData("Title", tag.title);
infos->setData("Artist", tag.artist);
infos->setData("Album", tag.album);
}
return 0;
}
int FlacPcm::processData(MediaInfo *infos, ChunkList *chunk_list, bool *killswitch)
{
reader = infos->getReader();
if(reader == 0)
return 0;
if(decoder == 0) {
decoder = FLAC__seekable_stream_decoder_new();
if(decoder == 0)
return 0;
FLAC__seekable_stream_decoder_set_md5_checking(decoder, false);
FLAC__seekable_stream_decoder_set_read_callback(decoder, readCallback_);
FLAC__seekable_stream_decoder_set_seek_callback(decoder, seekCallback_);
FLAC__seekable_stream_decoder_set_tell_callback(decoder, tellCallback_);
FLAC__seekable_stream_decoder_set_length_callback(decoder, lengthCallback_);
FLAC__seekable_stream_decoder_set_eof_callback(decoder, eofCallback_);
FLAC__seekable_stream_decoder_set_write_callback(decoder, writeCallback_);
FLAC__seekable_stream_decoder_set_metadata_callback(decoder, metadataCallback_);
FLAC__seekable_stream_decoder_set_error_callback(decoder, errorCallback_);
FLAC__seekable_stream_decoder_set_client_data(decoder, this);
if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) {
cleanup();
return 0;
}
if(!FLAC__seekable_stream_decoder_process_metadata(decoder)) {
cleanup();
return 0;
}
}
if(needs_seek) {
FLAC__seekable_stream_decoder_seek_absolute(decoder, seek_sample);
needs_seek = false;
}
bool eof = false;
while(samples_in_reservoir < 576) {
if(FLAC__seekable_stream_decoder_get_state(decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
eof = true;
break;
}
else if(!FLAC__seekable_stream_decoder_process_one_frame(decoder))
break;
}
if(samples_in_reservoir == 0) {
eof = true;
}
else {
const unsigned channels = stream_info.channels;
const unsigned bits_per_sample = stream_info.bits_per_sample;
const unsigned bytes_per_sample = (bits_per_sample+7)/8;
const unsigned sample_rate = stream_info.sample_rate;
unsigned i, n = min(samples_in_reservoir, 576), delta;
signed short *ssbuffer = (signed short*)output;
for(i = 0; i < n*channels; i++)
ssbuffer[i] = reservoir[i];
delta = i;
for( ; i < samples_in_reservoir*channels; i++)
reservoir[i-delta] = reservoir[i];
samples_in_reservoir -= n;
const int bytes = n * channels * bytes_per_sample;
ChunkInfosI *ci=new ChunkInfosI();
ci->addInfo("srate", sample_rate);
ci->addInfo("bps", bits_per_sample);
ci->addInfo("nch", channels);
chunk_list->setChunk("PCM", output, bytes, ci);
}
if(eof)
return 0;
return 1;
}
int FlacPcm::corecb_onSeeked(int newpos)
{
if(stream_info.total_samples == 0 || newpos < 0)
return 1;
needs_seek = true;
seek_sample = (FLAC__uint64)((double)newpos / (double)lengthInMsec() * (double)(FLAC__int64)stream_info.total_samples);
return 0;
}
void FlacPcm::cleanup()
{
if(decoder) {
if(FLAC__seekable_stream_decoder_get_state(decoder) != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
FLAC__seekable_stream_decoder_finish(decoder);
FLAC__seekable_stream_decoder_delete(decoder);
decoder = 0;
}
}
FLAC__SeekableStreamDecoderReadStatus FlacPcm::readCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
*bytes = instance->reader->read((char*)buffer, *bytes);
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
}
FLAC__SeekableStreamDecoderSeekStatus FlacPcm::seekCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
if(instance->reader->seek((int)absolute_byte_offset) < 0)
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
else
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
}
FLAC__SeekableStreamDecoderTellStatus FlacPcm::tellCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
int pos = instance->reader->getPos();
if(pos < 0)
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
else {
*absolute_byte_offset = pos;
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
}
}
FLAC__SeekableStreamDecoderLengthStatus FlacPcm::lengthCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
int length = instance->reader->getPos();
if(length < 0)
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
else {
*stream_length = length;
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
}
}
FLAC__bool FlacPcm::eofCallback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
return instance->reader->getPos() == instance->reader->getLength();
}
FLAC__StreamDecoderWriteStatus FlacPcm::writeCallback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
const unsigned bps = instance->stream_info.bits_per_sample, channels = instance->stream_info.channels, wide_samples = frame->header.blocksize;
unsigned wide_sample, sample, channel;
(void)decoder;
if(instance->abort_flag)
return FLAC__STREAM_DECODER_WRITE_ABORT;
for(sample = instance->samples_in_reservoir*channels, wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
instance->reservoir[sample] = (FLAC__int16)buffer[channel][wide_sample];
instance->samples_in_reservoir += wide_samples;
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
}
void FlacPcm::metadataCallback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
(void)decoder;
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
instance->stream_info = metadata->data.stream_info;
if(instance->stream_info.bits_per_sample != 16) {
//@@@ how to do this? MessageBox(mod.hMainWindow, "ERROR: plugin can only handle 16-bit samples\n", "ERROR: plugin can only handle 16-bit samples", 0);
instance->abort_flag = true;
return;
}
}
}
void FlacPcm::errorCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
FlacPcm *instance = (FlacPcm*)client_data;
(void)decoder;
if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
instance->abort_flag = true;
}
/***********************************************************************
* local routines
**********************************************************************/
bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
{
const char *temp;
FILE *f = fopen(filename, "rb");
memset(tag, 0, sizeof(id3v1_struct));
strcpy(tag->title,"Sonata K.42");
strcpy(tag->artist,"Domenico Scarlatti");
strcpy(tag->album,"Narcisso Yepes Plays Scarlatti");
sprintf(tag->description, "%s - %s", tag->artist, tag->title);
/* set the title and description to the filename by default */
temp = strrchr(filename, '/');
if(!temp)
temp = filename;
else
temp++;
strcpy(tag->description, temp);
*strrchr(tag->description, '.') = '\0';
strncpy(tag->title, tag->description, 30); tag->title[30] = '\0';
if(0 == f)
return false;
if(-1 == fseek(f, -128, SEEK_END)) {
fclose(f);
return false;
}
if(fread(tag->raw, 1, 128, f) < 128) {
fclose(f);
return false;
}
fclose(f);
if(strncmp((const char*)tag->raw, "TAG", 3))
return false;
else {
char year_str[5];
memcpy(tag->title, tag->raw+3, 30);
memcpy(tag->artist, tag->raw+33, 30);
memcpy(tag->album, tag->raw+63, 30);
memcpy(year_str, tag->raw+93, 4); year_str[4] = '\0'; tag->year = atoi(year_str);
memcpy(tag->comment, tag->raw+97, 30);
tag->genre = (unsigned)((FLAC__byte)tag->raw[127]);
tag->track = (unsigned)((FLAC__byte)tag->raw[126]);
sprintf(tag->description, "%s - %s", tag->artist, tag->title);
return true;
}
}

View File

@ -0,0 +1,107 @@
/* FLAC input plugin for Winamp3
* Copyright (C) 2000,2001 Josh Coalson
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* NOTE: this code is derived from the 'rawpcm' example by
* Nullsoft; the original license for the 'rawpcm' example follows.
*/
/*
Nullsoft WASABI Source File License
Copyright 1999-2001 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.
Brennan Underwood
brennan@nullsoft.com
*/
#ifndef _FLACPCM_H
#define _FLACPCM_H
#include "studio/services/svc_mediaconverter.h"
#include "studio/services/servicei.h"
#include "studio/corecb.h"
#include "studio/wac.h"
#include "attribs/cfgitemi.h"
#include "attribs/attrint.h"
extern "C" {
#include "FLAC/seekable_stream_decoder.h"
};
class FlacPcm : public svc_mediaConverterI {
public:
FlacPcm();
virtual ~FlacPcm();
// service
static const char *getServiceName() { return "FLAC to PCM converter service"; }
virtual int canConvertFrom(svc_fileReader *reader, const char *name, const char *chunktype)
{ return name && !STRICMP(Std::extension(name), "flac"); } // only accepts *.flac files
virtual const char *getConverterTo() { return "PCM"; }
virtual int getInfos(MediaInfo *infos);
virtual int processData(MediaInfo *infos, ChunkList *chunk_list, bool *killswitch);
virtual int getLatency(void) { return 0; }
// callbacks
virtual int corecb_onSeeked(int newpos);
protected:
bool needs_seek;
FLAC__uint64 seek_sample;
unsigned samples_in_reservoir;
bool abort_flag;
svc_fileReader *reader;
FLAC__SeekableStreamDecoder *decoder;
FLAC__StreamMetaData_StreamInfo stream_info;
FLAC__int16 reservoir[FLAC__MAX_BLOCK_SIZE * 2 * 2]; // *2 for max channels, another *2 for overflow
unsigned char output[576 * 2 * (16/8)]; // *2 for max channels, (16/8) for max bytes per sample
unsigned lengthInMsec() { return (unsigned)((FLAC__uint64)1000 * stream_info.total_samples / stream_info.sample_rate); }
private:
void cleanup();
static FLAC__SeekableStreamDecoderReadStatus readCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
static FLAC__SeekableStreamDecoderSeekStatus seekCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
static FLAC__SeekableStreamDecoderTellStatus tellCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
static FLAC__SeekableStreamDecoderLengthStatus lengthCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
static FLAC__bool eofCallback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
static FLAC__StreamDecoderWriteStatus writeCallback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
static void metadataCallback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
static void errorCallback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
};
#endif