From: Josh Coalson Date: Thu, 8 Nov 2001 23:54:10 +0000 (+0000) Subject: check in new version of the winamp3 plugin X-Git-Tag: 1.2.0~2085 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=53ad911a1dae7663aa3c5a5c5b5a29fdf5fc962f;p=platform%2Fupstream%2Fflac.git check in new version of the winamp3 plugin --- diff --git a/src/plugin_winamp3/Makefile.am b/src/plugin_winamp3/Makefile.am index 0074ebf..f7a328a 100644 --- a/src/plugin_winamp3/Makefile.am +++ b/src/plugin_winamp3/Makefile.am @@ -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 diff --git a/src/plugin_winamp3/README.txt b/src/plugin_winamp3/README.txt new file mode 100644 index 0000000..ab7e9e2 --- /dev/null +++ b/src/plugin_winamp3/README.txt @@ -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' diff --git a/src/plugin_winamp3/cnv_flacpcm.cpp b/src/plugin_winamp3/cnv_flacpcm.cpp new file mode 100644 index 0000000..e0a6672 --- /dev/null +++ b/src/plugin_winamp3/cnv_flacpcm.cpp @@ -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 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(); +} diff --git a/src/plugin_winamp3/cnv_flacpcm.dsp b/src/plugin_winamp3/cnv_flacpcm.dsp new file mode 100644 index 0000000..7198a5f --- /dev/null +++ b/src/plugin_winamp3/cnv_flacpcm.dsp @@ -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 diff --git a/src/plugin_winamp3/cnv_flacpcm.dsw b/src/plugin_winamp3/cnv_flacpcm.dsw new file mode 100644 index 0000000..e1b42d0 --- /dev/null +++ b/src/plugin_winamp3/cnv_flacpcm.dsw @@ -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> +{{{ +}}} + +############################################################################### + diff --git a/src/plugin_winamp3/cnv_flacpcm.h b/src/plugin_winamp3/cnv_flacpcm.h new file mode 100644 index 0000000..bd06185 --- /dev/null +++ b/src/plugin_winamp3/cnv_flacpcm.h @@ -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 diff --git a/src/plugin_winamp3/flacpcm.cpp b/src/plugin_winamp3/flacpcm.cpp new file mode 100644 index 0000000..e1d7a37 --- /dev/null +++ b/src/plugin_winamp3/flacpcm.cpp @@ -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; + } +} diff --git a/src/plugin_winamp3/flacpcm.h b/src/plugin_winamp3/flacpcm.h new file mode 100644 index 0000000..b1f814f --- /dev/null +++ b/src/plugin_winamp3/flacpcm.h @@ -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