diff --git a/tools/vio2sf/foo_xsf8.dsp b/tools/vio2sf/foo_xsf8.dsp index 285722d7e..0e3dfb17f 100644 --- a/tools/vio2sf/foo_xsf8.dsp +++ b/tools/vio2sf/foo_xsf8.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # 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 "FOO_XSF8_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_XSF8_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /I "src/foobar8" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_XSF8_EXPORTS" /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x411 /d "NDEBUG" @@ -53,7 +53,7 @@ BSC32=bscmake.exe # 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 pfc.lib foobar2000_SDK.lib foobar2000_sdk_helpers.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 /nologo /dll /machine:I386 /out:"foo_8_vio2sf.dll" +# ADD 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 /out:"foo_8_vio2sf.dll" !ELSEIF "$(CFG)" == "foo_xsf8 - Win32 Debug" @@ -69,7 +69,7 @@ LINK32=link.exe # 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 "FOO_XSF8_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_XSF8_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src/foobar8" /I "src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_XSF8_EXPORTS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x411 /d "_DEBUG" @@ -79,7 +79,7 @@ BSC32=bscmake.exe # 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 pfcD.lib foobar2000_SDKD.lib foobar2000_sdk_helpersD.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 /nologo /dll /debug /machine:I386 /out:"C:\Program Files\foobar2000_8\components\foo_8_vio2sf.dll" /pdbtype:sept +# ADD 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 /out:"foo_8_vio2sf.dll" /pdbtype:sept !ENDIF diff --git a/tools/vio2sf/in_xsf.dsp b/tools/vio2sf/in_xsf.dsp index 667987fff..e798d895d 100644 --- a/tools/vio2sf/in_xsf.dsp +++ b/tools/vio2sf/in_xsf.dsp @@ -1,24 +1,24 @@ # Microsoft Developer Studio Project File - Name="in_xsf" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** 編集しないでください ** +# ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=in_xsf - Win32 Debug -!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 -!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください +!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 "in_xsf.mak". !MESSAGE -!MESSAGE NMAKE の実行時に構成を指定できます -!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 "in_xsf.mak" CFG="in_xsf - Win32 Debug" !MESSAGE -!MESSAGE 選択可能なビルド モード: +!MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "in_xsf - Win32 Release" ("Win32 (x86) Dynamic-Link Library" 用) -!MESSAGE "in_xsf - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" 用) +!MESSAGE "in_xsf - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "in_xsf - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -43,7 +43,7 @@ RSC=rc.exe # 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 "IN_XSF_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IN_XSF_EXPORTS" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IN_XSF_EXPORTS" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 @@ -70,7 +70,7 @@ LINK32=link.exe # 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 "IN_XSF_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "src/aosdk" /I "src/aosdk/zlib" /D "LSB_FIRST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IN_XSF_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "src/aosdk" /I "src/aosdk/zlib" /I "src" /D "LSB_FIRST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "IN_XSF_EXPORTS" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x411 /d "_DEBUG" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # 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 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 /out:"C:\Program Files\Winamp\Plugins/in_vio2sf.dll" /pdbtype:sept +# ADD 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 /out:"in_vio2sf.dll" /pdbtype:sept !ENDIF diff --git a/tools/vio2sf/in_xsfu.dsp b/tools/vio2sf/in_xsfu.dsp index ae228c583..fd2c9b015 100644 --- a/tools/vio2sf/in_xsfu.dsp +++ b/tools/vio2sf/in_xsfu.dsp @@ -54,7 +54,7 @@ BSC32=bscmake.exe # 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 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 /pdb:none /machine:I386 /out:"C:\Program Files\Winamp\Plugins/in_vio2sfu.dll" +# ADD 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 /pdb:none /machine:I386 /out:"in_vio2sfu.dll" !ELSEIF "$(CFG)" == "in_xsfu - Win32 Debug" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # 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 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 /out:"C:\Program Files\Winamp\Plugins/in_vio2sfu.dll" /pdbtype:sept +# ADD 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 /out:"in_vio2sfu.dll" /pdbtype:sept !ENDIF diff --git a/tools/vio2sf/kpixsf.dsp b/tools/vio2sf/kpixsf.dsp index 10a6cb4ae..c4e201bca 100644 --- a/tools/vio2sf/kpixsf.dsp +++ b/tools/vio2sf/kpixsf.dsp @@ -1,24 +1,24 @@ # Microsoft Developer Studio Project File - Name="kpixsf" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** 編集しないでください ** +# ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=kpixsf - Win32 Debug -!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 -!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください +!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 "kpixsf.mak". !MESSAGE -!MESSAGE NMAKE の実行時に構成を指定できます -!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 "kpixsf.mak" CFG="kpixsf - Win32 Debug" !MESSAGE -!MESSAGE 選択可能なビルド モード: +!MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "kpixsf - Win32 Release" ("Win32 (x86) Dynamic-Link Library" 用) -!MESSAGE "kpixsf - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" 用) +!MESSAGE "kpixsf - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "kpixsf - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -80,7 +80,7 @@ BSC32=bscmake.exe # 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib shlwapi.lib /nologo /dll /debug /machine:I386 /out:"C:\usr\bin\kbmed242_beta4\Plugins/vio2sf.kpi" /pdbtype:sept +# ADD 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 shlwapi.lib /nologo /dll /debug /machine:I386 /out:"vio2sf.kpi" /pdbtype:sept !ENDIF diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/audio_chunk.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/audio_chunk.cpp new file mode 100644 index 000000000..f28e69a48 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/audio_chunk.cpp @@ -0,0 +1,323 @@ +#include "foobar2000.h" + +bool audio_chunk::set_data(const audio_sample * src,unsigned samples,unsigned nch,unsigned srate) +{ + bool rv = false; + unsigned size = samples * nch; + audio_sample * out = check_data_size(size); + if (out) + { + if (src) + mem_ops::copy(out,src,size); + else + mem_ops::set(out,0,size); + set_sample_count(samples); + set_channels(nch); + set_srate(srate); + rv = true; + } + else reset(); + return rv; +} + +static bool check_exclusive(unsigned val, unsigned mask) +{ + return (val&mask)!=0 && (val&mask)!=mask; +} + +//leet superfast fixedpoint->floatingpoint convertah +//somewhat big though due to excess templating + +namespace { + + template class msvc6_sucks_v2 { public: + inline static void do_fixedpoint_convert(const void * source,unsigned bps,unsigned count,audio_sample* buffer) + { + const char * src = (const char *) source; + unsigned bytes = bps>>3; + unsigned n; + T max = ((T)1)<<(bps-1); + + T negmask = - max; + + ASSUME(bytes<=sizeof(T)); + + double div = 1.0 / (double)(1<<(bps-1)); + for(n=0;n(src); + } + + if (b_swap) byte_order_helper::swap_order(&temp,bytes); + + if (!b_signed) temp ^= max; + + if (b_pad) + { + if (temp & max) temp |= negmask; + } + + if (b_pad) + src += bytes; + else + src += sizeof(T); + + + buffer[n] = (audio_sample) ( (double)temp * div ); + } + } + }; + + template class msvc6_sucks { public: + inline static void do_fixedpoint_convert(bool b_swap,bool b_signed,const void * source,unsigned bps,unsigned count,audio_sample* buffer) + { + if (sizeof(T)==1) + { + if (b_signed) + { + msvc6_sucks_v2::do_fixedpoint_convert(source,bps,count,buffer); + } + else + { + msvc6_sucks_v2::do_fixedpoint_convert(source,bps,count,buffer); + } + } + else if (b_swap) + { + if (b_signed) + { + msvc6_sucks_v2::do_fixedpoint_convert(source,bps,count,buffer); + } + else + { + msvc6_sucks_v2::do_fixedpoint_convert(source,bps,count,buffer); + } + } + else + { + if (b_signed) + { + msvc6_sucks_v2::do_fixedpoint_convert(source,bps,count,buffer); + } + else + { + msvc6_sucks_v2::do_fixedpoint_convert(source,bps,count,buffer); + } + } + } + }; + + +}; + + +bool audio_chunk::set_data_fixedpoint_ex(const void * source,unsigned size,unsigned srate,unsigned nch,unsigned bps,unsigned flags) +{ + assert( check_exclusive(flags,FLAG_SIGNED|FLAG_UNSIGNED) ); + assert( check_exclusive(flags,FLAG_LITTLE_ENDIAN|FLAG_BIG_ENDIAN) ); + + bool need_swap = !!(flags & FLAG_BIG_ENDIAN); + if (byte_order_helper::machine_is_big_endian()) need_swap = !need_swap; + + unsigned count = size / (bps/8); + audio_sample * buffer = check_data_size(count); + if (buffer==0) {reset();return false;} + bool b_signed = !!(flags & FLAG_SIGNED); + + switch(bps) + { + case 8: + msvc6_sucks::do_fixedpoint_convert(need_swap,b_signed,source,bps,count,buffer); + break; + case 16: + msvc6_sucks::do_fixedpoint_convert(need_swap,b_signed,source,bps,count,buffer); + break; + case 24: + msvc6_sucks::do_fixedpoint_convert(need_swap,b_signed,source,bps,count,buffer); + break; + case 32: + msvc6_sucks::do_fixedpoint_convert(need_swap,b_signed,source,bps,count,buffer); + break; + case 40: + case 48: + case 56: + case 64: + msvc6_sucks<__int64,true>::do_fixedpoint_convert(need_swap,b_signed,source,bps,count,buffer); + break; +/* + additional template would bump size while i doubt if anyone playing PCM above 32bit would care about performance gain + msvc6_sucks<__int64,false>::do_fixedpoint_convert(need_swap,b_signed,source,bps,count,buffer); + break;*/ + default: + //unknown size, cant convert + mem_ops::setval(buffer,0,count); + break; + } + set_sample_count(count/nch); + set_srate(srate); + set_channels(nch); + return true; +} + +bool audio_chunk::set_data_floatingpoint_ex(const void * ptr,unsigned size,unsigned srate,unsigned nch,unsigned bps,unsigned flags) +{ + assert(bps==32 || bps==64); + assert( check_exclusive(flags,FLAG_LITTLE_ENDIAN|FLAG_BIG_ENDIAN) ); + assert( ! (flags & (FLAG_SIGNED|FLAG_UNSIGNED) ) ); + + void (* p_orderfunc)(void * ptr,unsigned bytes) = (flags & FLAG_BIG_ENDIAN) ? byte_order_helper::order_be_to_native : byte_order_helper::order_le_to_native; + + unsigned bytes_per_sample = bps>>3; + + unsigned count = size / bytes_per_sample; + audio_sample * out = check_data_size(count); + if (out==0) {reset();return false;} + unsigned char temp[64/8]; + const unsigned char * src = (const unsigned char *) ptr; + while(count) + { + audio_sample val; + memcpy(temp,src,bytes_per_sample); + p_orderfunc(temp,bytes_per_sample); + if (bps==32) val = (audio_sample) *(float*)&temp; + else val = (audio_sample) *(double*)&temp; + *(out++) = val; + src += bytes_per_sample; + count--; + } + return true; +} + +#if audio_sample_size == 64 +bool audio_chunk::set_data_32(const float * src,UINT samples,UINT nch,UINT srate) +{ + unsigned size = samples * nch; + audio_sample * out = check_data_size(size); + if (out==0) {reset();return false;} + dsp_util::convert_32_to_64(src,out,size); + set_sample_count(samples); + set_channels(nch); + set_srate(srate); + return true; +} +#else +bool audio_chunk::set_data_64(const double * src,UINT samples,UINT nch,UINT srate) +{ + unsigned size = samples * nch; + audio_sample * out = check_data_size(size); + if (out==0) {reset();return false;} + dsp_util::convert_64_to_32(src,out,size); + set_sample_count(samples); + set_channels(nch); + set_srate(srate); + return true; +} +#endif + +bool audio_chunk::is_valid() +{ + unsigned nch = get_channels(); + if (nch==0 || nch>256) return false; + unsigned srate = get_srate(); + if (srate<1000 || srate>1000000) return false; + unsigned samples = get_sample_count(); + if (samples==0 || samples >= 0x80000000 / (sizeof(audio_sample) * nch) ) return false; + unsigned size = get_data_size(); + if (samples * nch > size) return false; + if (!get_data()) return false; + return true; +} + + +bool audio_chunk::pad_with_silence_ex(unsigned samples,unsigned hint_nch,unsigned hint_srate) +{ + if (is_empty()) + { + if (hint_srate && hint_nch) + { + return set_data(0,samples,hint_nch,hint_srate); + } + else return false; + } + else + { + if (hint_srate && hint_srate != get_srate()) samples = MulDiv(samples,get_srate(),hint_srate); + if (samples > get_sample_count()) + { + unsigned old_size = get_sample_count() * get_channels(); + unsigned new_size = samples * get_channels(); + audio_sample * ptr = check_data_size(new_size); + if (ptr) + { + mem_ops::set(ptr + old_size,0,new_size - old_size); + set_sample_count(samples); + return true; + } + else return false; + } + else return true; + } +} + +bool audio_chunk::pad_with_silence(unsigned samples) +{ + if (samples > get_sample_count()) + { + unsigned old_size = get_sample_count() * get_channels(); + unsigned new_size = samples * get_channels(); + audio_sample * ptr = check_data_size(new_size); + if (ptr) + { + mem_ops::set(ptr + old_size,0,new_size - old_size); + set_sample_count(samples); + return true; + } + else return false; + } + else return true; +} + +bool audio_chunk::insert_silence_fromstart(unsigned samples) +{ + unsigned old_size = get_sample_count() * get_channels(); + unsigned delta = samples * get_channels(); + unsigned new_size = old_size + delta; + audio_sample * ptr = check_data_size(new_size); + if (ptr) + { + mem_ops::move(ptr+delta,ptr,old_size); + mem_ops::set(ptr,0,delta); + set_sample_count(get_sample_count() + samples); + return true; + } + else return false; +} + +unsigned audio_chunk::skip_first_samples(unsigned samples_delta) +{ + unsigned samples_old = get_sample_count(); + if (samples_delta >= samples_old) + { + set_sample_count(0); + set_data_size(0); + return samples_old; + } + else + { + unsigned samples_new = samples_old - samples_delta; + unsigned nch = get_channels(); + audio_sample * ptr = get_data(); + mem_ops::move(ptr,ptr+nch*samples_delta,nch*samples_new); + set_sample_count(samples_new); + set_data_size(nch*samples_new); + return samples_delta; + } +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/audio_chunk.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/audio_chunk.h new file mode 100644 index 000000000..3d8c3e288 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/audio_chunk.h @@ -0,0 +1,158 @@ +#ifndef _AUDIO_CHUNK_H_ +#define _AUDIO_CHUNK_H_ + +#define audio_sample_size 64 + +#if audio_sample_size == 32 +typedef float audio_sample; +#define audio_sample_asm dword +#elif audio_sample_size == 64 +typedef double audio_sample; +#define audio_sample_asm qword +#else +#error wrong audio_sample_size +#endif + +#define audio_sample_bytes (audio_sample_size/8) + + +//channel order same as in windows APIs - for 4ch: L/R/BL/BR, for 5.1: L/R/C/LF/BL/BR + +class NOVTABLE audio_chunk +{ +protected: + audio_chunk() {} + ~audio_chunk() {} +public: + + + virtual audio_sample * get_data()=0; + virtual const audio_sample * get_data() const = 0; + virtual unsigned get_data_size() const = 0;//buffer size in audio_samples; must be at least samples * nch; + virtual audio_sample * set_data_size(unsigned new_size)=0; + + virtual unsigned get_srate() const = 0; + virtual void set_srate(unsigned val)=0; + virtual unsigned get_channels() const = 0; + virtual void set_channels(unsigned val)=0; + + virtual unsigned get_sample_count() const = 0; + virtual void set_sample_count(unsigned val)=0; + + inline audio_sample * check_data_size(unsigned new_size) {if (new_size > get_data_size()) return set_data_size(new_size); else return get_data();} + + inline bool copy_from(const audio_chunk * src) + { + return set_data(src->get_data(),src->get_sample_count(),src->get_channels(),src->get_srate()); + } + + inline double get_duration() const + { + double rv = 0; + unsigned srate = get_srate (), samples = get_sample_count(); + if (srate>0 && samples>0) rv = (double)samples/(double)srate; + return rv; + } + + inline bool is_empty() const {return get_channels()==0 || get_srate()==0 || get_sample_count()==0;} + + bool is_valid(); + + inline unsigned get_data_length() const {return get_sample_count() * get_channels();}//actual amount of audio_samples in buffer + + inline void reset() + { + set_sample_count(0); + set_srate(0); + set_channels(0); + } + inline void reset_data() + { + reset(); + set_data_size(0); + } + + bool set_data(const audio_sample * src,unsigned samples,unsigned nch,unsigned srate);//returns false on failure (eg. memory error) + + + //helper routines for converting different input data formats + inline bool set_data_fixedpoint(const void * ptr,unsigned bytes,unsigned srate,unsigned nch,unsigned bps) + { + return set_data_fixedpoint_ex(ptr,bytes,srate,nch,bps,(bps==8 ? FLAG_UNSIGNED : FLAG_SIGNED) | flags_autoendian()); + } + + inline bool set_data_fixedpoint_unsigned(const void * ptr,unsigned bytes,unsigned srate,unsigned nch,unsigned bps) + { + return set_data_fixedpoint_ex(ptr,bytes,srate,nch,bps,FLAG_UNSIGNED | flags_autoendian()); + } + + inline bool set_data_fixedpoint_signed(const void * ptr,unsigned bytes,unsigned srate,unsigned nch,unsigned bps) + { + return set_data_fixedpoint_ex(ptr,bytes,srate,nch,bps,FLAG_SIGNED | flags_autoendian()); + } + + enum + { + FLAG_LITTLE_ENDIAN = 1, + FLAG_BIG_ENDIAN = 2, + FLAG_SIGNED = 4, + FLAG_UNSIGNED = 8, + }; + + inline static unsigned flags_autoendian() + { + return byte_order_helper::machine_is_big_endian() ? FLAG_BIG_ENDIAN : FLAG_LITTLE_ENDIAN; + } + + bool set_data_fixedpoint_ex(const void * ptr,unsigned bytes,unsigned srate,unsigned nch,unsigned bps,unsigned flags);//flags - see FLAG_* above + + bool set_data_floatingpoint_ex(const void * ptr,unsigned bytes,unsigned srate,unsigned nch,unsigned bps,unsigned flags);//signed/unsigned flags dont apply + +#if audio_sample_size == 64 + bool set_data_32(const float * src,unsigned samples,unsigned nch,unsigned srate); + inline bool set_data_64(const double * src,unsigned samples,unsigned nch,unsigned srate) {return set_data(src,samples,nch,srate);} +#else + inline bool set_data_32(const float * src,unsigned samples,unsigned nch,unsigned srate) {return set_data(src,samples,nch,srate);} + bool set_data_64(const double * src,unsigned samples,unsigned nch,unsigned srate); +#endif + + bool pad_with_silence_ex(unsigned samples,unsigned hint_nch,unsigned hint_srate); + bool pad_with_silence(unsigned samples); + bool insert_silence_fromstart(unsigned samples); + unsigned skip_first_samples(unsigned samples); +}; + +class audio_chunk_i : public audio_chunk +{ + mem_block_aligned_t m_data; + unsigned m_srate,m_nch,m_samples; +public: + audio_chunk_i() : m_srate(0), m_nch(0), m_samples(0) {} + audio_chunk_i(const audio_sample * src,unsigned samples,unsigned nch,unsigned srate) : m_srate(0), m_nch(0), m_samples(0) + {set_data(src,samples,nch,srate);} + + virtual audio_sample * get_data() {return m_data;} + virtual const audio_sample * get_data() const {return m_data;} + virtual unsigned get_data_size() const {return m_data.get_size();} + virtual audio_sample * set_data_size(unsigned new_size) {return m_data.set_size(new_size);} + + virtual unsigned get_srate() const {return m_srate;} + virtual void set_srate(unsigned val) {m_srate=val;} + virtual unsigned get_channels() const {return m_nch;} + virtual void set_channels(unsigned val) {m_nch = val;} + + virtual unsigned get_sample_count() const {return m_samples;} + virtual void set_sample_count(unsigned val) {m_samples = val;} + +}; + +struct output_chunk //used by float->pcm and output +{ + void * data; + int size;//in bytes + int srate; + int nch;//number of interleaved channels + int bps;//bits-per-sample +}; + +#endif //_AUDIO_CHUNK_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/commandline.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/commandline.cpp new file mode 100644 index 000000000..192547e89 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/commandline.cpp @@ -0,0 +1,13 @@ +#include "foobar2000.h" + +void commandline_handler_metadb_handle::on_file(const char * url) +{ + playlist_loader_callback_i callback; + + playlist_loader::process_path_ex(url,&callback); + + { + unsigned n,m=callback.get_count(); + for(n=0;n on_token() => deletion + scenario #2: + creation => on_token() returning RESULT_PROCESSED_EXPECT_FILES => on_file(), on_file().... => on_files_done() => deletion +*/ + +template +class commandline_handler_factory : public service_factory_t {}; + + + +#endif //_FOOBAR2000_SDK_COMMANDLINE_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/component.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/component.h new file mode 100644 index 000000000..547986e84 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/component.h @@ -0,0 +1,48 @@ +#ifndef _COMPONENT_H_ +#define _COMPONENT_H_ + +#include "foobar2000.h" + +class foobar2000_client +{ +public: + enum {FOOBAR2000_CLIENT_VERSION_COMPATIBLE = 27, FOOBAR2000_CLIENT_VERSION=35}; //changes everytime global compatibility is broken + virtual int get_version() {return FOOBAR2000_CLIENT_VERSION;} + virtual service_factory_base * get_service_list() {return service_factory_base::list_get_pointer();} + + virtual void get_config(cfg_var::write_config_callback * out) + { + cfg_var::config_write_file(out); + } + + virtual void set_config(const void * data,int size) + { + cfg_var::config_read_file(data,size); + } + + virtual void reset_config() + { + //0.8: deprecated + } + + virtual void set_library_path(const char * path,const char * name); + + virtual void services_init(bool val); + +}; + +class NOVTABLE foobar2000_api +{ +public: + virtual service_base * service_enum_create(const GUID &g,int n)=0; + virtual int service_enum_get_count(const GUID &g)=0; + virtual HWND get_main_window()=0; + virtual bool assert_main_thread()=0; + virtual bool is_main_thread()=0; + virtual const char * get_profile_path()=0; +}; + +extern foobar2000_client g_client; +extern foobar2000_api * g_api; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/component_client.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/component_client.h new file mode 100644 index 000000000..46aa84888 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/component_client.h @@ -0,0 +1,6 @@ +#ifndef _COMPONENT_CLIENT_H_ +#define _COMPONENT_CLIENT_H_ + + + +#endif //_COMPONENT_CLIENT_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/components_menu.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/components_menu.h new file mode 100644 index 000000000..835237331 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/components_menu.h @@ -0,0 +1,7 @@ +#ifndef _COMPONENTS_MENU_H_ +#define _COMPONENTS_MENU_H_ + +#error deprecated, see menu_item.h + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/componentversion.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/componentversion.h new file mode 100644 index 000000000..f56d93a8a --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/componentversion.h @@ -0,0 +1,56 @@ +#ifndef _COMPONENTVERSION_H_ +#define _COMPONENTVERSION_H_ + +#include "service.h" +#include "interface_helper.h" + +//reminder: all strings are UTF-8 + +class NOVTABLE componentversion : public service_base +{ +public: + virtual void get_file_name(string_base & out)=0; + virtual void get_component_name(string_base & out)=0; + virtual void get_component_version(string_base & out)=0; + virtual void get_about_message(string_base & out)=0;//about message uses "\n" for line separators + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class componentversion_i_simple : public componentversion +{ + const char * name,*version,*about; +public: + //do not derive/override + virtual void get_file_name(string_base & out) {out.set_string(service_factory_base::get_my_file_name());} + virtual void get_component_name(string_base & out) {out.set_string(name?name:"");} + virtual void get_component_version(string_base & out) {out.set_string(version?version:"");} + virtual void get_about_message(string_base & out) {out.set_string(about?about:"");} + componentversion_i_simple(const char * p_name,const char * p_version,const char * p_about) : name(p_name), version(p_version), about(p_about ? p_about : "") {} +}; + +class componentversion_i_copy : public componentversion +{ + string_simple name,version,about; +public: + //do not derive/override + virtual void get_file_name(string_base & out) {out.set_string(service_factory_base::get_my_file_name());} + virtual void get_component_name(string_base & out) {out.set_string(name);} + virtual void get_component_version(string_base & out) {out.set_string(version);} + virtual void get_about_message(string_base & out) {out.set_string(about);} + componentversion_i_copy(const char * p_name,const char * p_version,const char * p_about) : name(p_name), version(p_version), about(p_about ? p_about : "") {} +}; + + +#define DECLARE_COMPONENT_VERSION(NAME,VERSION,ABOUT) \ + static service_factory_single_transparent_p3_t g_componentversion_service(NAME,VERSION,ABOUT); + +#define DECLARE_COMPONENT_VERSION_COPY(NAME,VERSION,ABOUT) \ + static service_factory_single_transparent_p3_t g_componentversion_service(NAME,VERSION,ABOUT); + +//usage: DECLARE_COMPONENT_VERSION("blah","v1.337",0) +//about message is optional can be null +//_copy version copies strings around instead of keeping pointers (bigger but sometimes needed, eg. if strings are created as string_printf() or something inside constructor + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/config.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/config.h new file mode 100644 index 000000000..b0d96cd17 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/config.h @@ -0,0 +1,20 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include "service.h" + +class NOVTABLE config : public service_base +{ +public: //NOTE your config class instance will get deleted BEFORE returned window is destroyed or even used + virtual HWND create(HWND parent)=0; + virtual const char * get_name()=0; + virtual const char * get_parent_name() {return 0;}//optional, retuns name of parent config item + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +template +class config_factory : public service_factory_single_t {}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/config_var.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/config_var.h new file mode 100644 index 000000000..365b0f1bf --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/config_var.h @@ -0,0 +1,475 @@ +#ifndef _FOOBAR2000_CONFIG_VAR_H_ +#define _FOOBAR2000_CONFIG_VAR_H_ + +#include "service.h" + +#include "interface_helper.h" + +#include "initquit.h" + +// "externally visible" config vars that can be accessed by other components + +//note: callbacks from different threads are allowed, keep your stuff mt-safe + + +class config_var; + +class config_var_callback +{ +public: + virtual void on_changed(const config_var * ptr)=0; +}; + + +class callback_list +{ + ptr_list_simple< config_var_callback > list; +public: + void add(config_var_callback * ptr) {list.add_item(ptr);} + void remove(config_var_callback * ptr) {list.remove_item(ptr);} + void call(const config_var * ptr) const + { + int n,m=list.get_count(); + for(n=0;non_changed(ptr); + } +}; + + + +class config_var : public service_base +{ +public: + class NOVTABLE write_config_callback + { + public: + virtual void write(const void * ptr,int bytes)=0; + }; + + class write_config_callback_i : public write_config_callback + { + public: + mem_block data; + write_config_callback_i() {data.set_mem_logic(mem_block::ALLOC_FAST_DONTGODOWN);} + virtual void write(const void * ptr,int bytes) {data.append(ptr,bytes);} + }; + + virtual const char * get_name() const = 0; + virtual bool is_public() const {return true;} + virtual void get_raw_data(config_var::write_config_callback * out) const = 0; + virtual void set_raw_data(const void * data,int size) = 0; + virtual void reset()=0; + virtual GUID get_type() const = 0; + virtual void add_callback(config_var_callback * ptr,bool calloninit=false)=0; + virtual void remove_callback(config_var_callback * ptr)=0; + virtual const char * get_library() {return core_api::get_my_file_name();} + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static config_var * g_find(GUID type,const char * name) + { + service_enum_t e; + config_var * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==type && ptr->is_public() && !stricmp_utf8(name,ptr->get_name())) return ptr; + ptr->service_release(); + } + return 0; + } + + static void g_add_callback(GUID type,const char * name,config_var_callback * cb,bool calloninit=false) + { + config_var * ptr = g_find(type,name); + if (ptr) {ptr->add_callback(cb,calloninit);ptr->service_release();} + } + + static void g_remove_callback(GUID type,const char * name,config_var_callback * cb) + { + config_var * ptr = g_find(type,name); + if (ptr) {ptr->remove_callback(cb);ptr->service_release();} + } + +}; + +class NOVTABLE config_var_int : public config_var +{ +public: + static const GUID var_type; + inline static const GUID & get_var_type() {return var_type;} + + virtual const char * get_name() const = 0; + virtual void get_raw_data(config_var::write_config_callback * out) const = 0; + virtual void set_raw_data(const void * data,int size) = 0; + virtual void reset()=0; + virtual GUID get_type() const {return get_var_type();} + + virtual int get_value() const = 0; + virtual void set_value(int val) = 0; + + static config_var_int * g_find(const char * name) + { + return static_cast(config_var::g_find(get_var_type(),name)); + } + + static int g_get_value(const char * name) + { + int rv = 0; + config_var_int * ptr = g_find(name); + if (ptr) {rv = ptr->get_value();ptr->service_release();} + return rv; + } + + static void g_set_value(const char * name,int val) + { + config_var_int * ptr = g_find(name); + if (ptr) {ptr->set_value(val);ptr->service_release();} + } + + static void g_add_callback(const char * name,config_var_callback * cb,bool calloninit=false) + { + config_var_int * ptr = g_find(name); + if (ptr) {ptr->add_callback(cb,calloninit);ptr->service_release();} + } + + static void g_remove_callback(const char * name,config_var_callback * cb) + { + config_var_int * ptr = g_find(name); + if (ptr) {ptr->remove_callback(cb);ptr->service_release();} + } +}; + +extern const GUID config_var_struct_var_type; + +template +class NOVTABLE config_var_struct : public config_var +{ +public: + inline static const GUID & get_var_type() {return config_var_struct_var_type;} + + virtual const char * get_name() const = 0; + virtual void get_raw_data(config_var::write_config_callback * out) const = 0; + virtual void set_raw_data(const void * data,int size) = 0; + virtual void reset()=0; + virtual GUID get_type() const {return get_var_type();} + virtual unsigned get_struct_size() {return sizeof(T);} + + virtual void get_value(T & out) const = 0; + virtual void set_value(const T& src) = 0; + + static config_var_struct * g_find(const char * name) + { + config_var_struct * temp = static_cast*>(config_var::g_find(get_var_type(),name)); + assert(temp==0 || temp->get_struct_size() == sizeof(T) ); + return temp; + } + + static bool g_get_value(const char * name,T& out) + { + bool rv = false; + config_var_struct * ptr = g_find(name); + if (ptr) {ptr->get_value(out);ptr->service_release();rv=true;} + return rv; + } + + static void g_set_value(const char * name,const T& val) + { + config_var_struct * ptr = g_find(name); + if (ptr) {ptr->set_value(val);ptr->service_release();} + } + + static void g_add_callback(const char * name,config_var_callback * cb,bool calloninit=false) + { + config_var_struct * ptr = g_find(name); + if (ptr) {ptr->add_callback(cb,calloninit);ptr->service_release();} + } + + static void g_remove_callback(const char * name,config_var_callback * cb) + { + config_var_struct * ptr = g_find(name); + if (ptr) {ptr->remove_callback(cb);ptr->service_release();} + } +}; + +template +class config_var_struct_i : public config_var_struct +{ + string_simple name; + T value,def; + mutable critical_section sync; + callback_list callbacks; +public: + virtual const char * get_name() const {return name;} + virtual void get_raw_data(config_var::write_config_callback * out) const {insync(sync);out->write(&value,sizeof(value));} + virtual void set_raw_data(const void * data,int size) + { + insync(sync); + if (size==sizeof(value)) value = *(T*)data; + callbacks.call(this); + } + virtual void reset() + { + insync(sync); + value = def; + callbacks.call(this); + } + + virtual void add_callback(config_var_callback * ptr,bool calloninit=false) + { + insync(sync); + callbacks.add(ptr); + if (calloninit) ptr->on_changed(this); + } + virtual void remove_callback(config_var_callback * ptr) + { + insync(sync); + callbacks.remove(ptr); + } + + virtual void get_value(T & out) const {insync(sync);out = value;} + virtual void set_value(const T & p_val) + { + insync(sync); + if (memcmp(&value,&p_val,sizeof(value))) + { + value = p_val; + callbacks.call(this); + } + } + + config_var_struct_i(const char * p_name,T p_value) : name(p_name), value(p_value), def(p_value) {} + + void operator=(const T& v) {set_value(v);} + inline operator T() const {T temp;get_value(temp);return temp;} +}; + + +class NOVTABLE config_var_string : public config_var +{ +public: + static const GUID var_type; + inline static const GUID & get_var_type() {return var_type;} + + virtual const char * get_name() const = 0; + virtual void get_raw_data(config_var::write_config_callback * out) const = 0; + virtual void set_raw_data(const void * data,int size) = 0; + virtual void reset()=0; + virtual GUID get_type() const {return get_var_type();} + + virtual void get_value(string_base & out) const = 0; + virtual void set_value(const char * val) = 0; + + static config_var_string * g_find(const char * name) + { + return static_cast(config_var::g_find(get_var_type(),name)); + } + + static void g_get_value(const char * name,string_base & out) + { + config_var_string * ptr = g_find(name); + if (ptr) {ptr->get_value(out);ptr->service_release();} + } + + static void g_set_value(const char * name,const char * val) + { + config_var_string * ptr = g_find(name); + if (ptr) {ptr->set_value(val);ptr->service_release();} + } + + static void g_add_callback(const char * name,config_var_callback * cb,bool calloninit=false) + { + config_var_string * ptr = g_find(name); + if (ptr) {ptr->add_callback(cb,calloninit);ptr->service_release();} + } + + static void g_remove_callback(const char * name,config_var_callback * cb) + { + config_var_string * ptr = g_find(name); + if (ptr) {ptr->remove_callback(cb);ptr->service_release();} + } +}; + +class config_var_int_i : public config_var_int +{ + string_simple name; + int value,def; + mutable critical_section sync; + callback_list callbacks; +public: + virtual const char * get_name() const {return name;} + virtual void get_raw_data(config_var::write_config_callback * out) const {insync(sync);out->write(&value,sizeof(int));} + virtual void set_raw_data(const void * data,int size)//bah not endian safe + { + insync(sync); + if (size==sizeof(int)) value = *(int*)data; + callbacks.call(this); + } + virtual void reset() + { + insync(sync); + value = def; + callbacks.call(this); + } + + virtual void add_callback(config_var_callback * ptr,bool calloninit=false) + { + insync(sync); + callbacks.add(ptr); + if (calloninit) ptr->on_changed(this); + } + virtual void remove_callback(config_var_callback * ptr) + { + insync(sync); + callbacks.remove(ptr); + } + + virtual int get_value() const {insync(sync);return value;} + virtual void set_value(int p_val) + { + insync(sync); + if (value!=p_val) + { + value = p_val; + callbacks.call(this); + } + } + + config_var_int_i(const char * p_name,int p_value) : name(p_name), value(p_value), def(p_value) {} + + int operator=(int v) {set_value(v);return v;} + operator int() const {return get_value();} +}; + +class config_var_string_i : public config_var_string +{ + string_simple name,value,def; + mutable critical_section sync; + callback_list callbacks; +public: + virtual const char * get_name() const {return name;} + virtual void get_raw_data(config_var::write_config_callback * out) const + { + insync(sync); + out->write(value.get_ptr(),strlen(value)); + } + virtual void set_raw_data(const void * data,int size) + { + insync(sync); + value.set_string_n((const char*)data,size); + callbacks.call(this); + } + virtual void reset() + { + insync(sync); + value = def; + callbacks.call(this); + } + + virtual GUID get_type() const {return get_var_type();} + + virtual void get_value(string_base & out) const + { + insync(sync); + out.set_string(value); + } + + virtual void set_value(const char * val) + { + insync(sync); + if (strcmp(value,val)) + { + value.set_string(val); + callbacks.call(this); + } + } + + virtual void add_callback(config_var_callback * ptr,bool calloninit=false) + { + insync(sync); + callbacks.add(ptr); + if (calloninit) ptr->on_changed(this); + } + virtual void remove_callback(config_var_callback * ptr) + { + insync(sync); + callbacks.remove(ptr); + } + config_var_string_i(const char * p_name,const char * p_value) : name(p_name), value(p_value), def(p_value) {} +}; + +//only static creation! +template +class config_var_callback_autoreg : public config_var_callback +{ + class callback_autoreg_initquit : public initquit_autoreg + { + config_var_callback_autoreg * cb; + public: + callback_autoreg_initquit(config_var_callback_autoreg * p_cb) {cb = p_cb;} + virtual void on_init() {cb->on_init();} + virtual void on_quit() {cb->on_quit();} + }; + + vartype * var; + string_simple varname; + virtual void on_changed(const config_var * ptr) {on_changed(static_cast(ptr));} + callback_autoreg_initquit * p_initquit; + bool calloninit; +protected: + virtual void on_changed(const vartype * ptr)=0; +public: + void on_init() + { + if (!var && !varname.is_empty()) + var = vartype::g_find(varname); + if (var) var->add_callback(this,calloninit); + } + void on_quit() + { + if (var) var->remove_callback(this); + } + config_var_callback_autoreg(vartype * p_var,bool p_calloninit = false) + { + calloninit = p_calloninit; + var = p_var; + p_initquit = new callback_autoreg_initquit(this); + } + config_var_callback_autoreg(const char * name,bool p_calloninit = false) + { + calloninit = p_calloninit; + var = 0; + varname = name; + p_initquit = new callback_autoreg_initquit(this); + } + ~config_var_callback_autoreg() + { + delete p_initquit; + } +}; + +template +class config_var_callback_simple : public config_var_callback_autoreg +{ + void (*func)(const vartype *); + virtual void on_changed(const vartype * ptr) {func(ptr);} +public: + config_var_callback_simple(vartype * p_var,void (*p_func)(const vartype *),bool p_calloninit = false) + : config_var_callback_autoreg(p_var,p_calloninit) {func = p_func;} + + config_var_callback_simple(const char * name,void (*p_func)(const vartype *),bool p_calloninit = false) + : config_var_callback_autoreg(name,p_calloninit) {func = p_func;} +}; + +#define DECLARE_CONFIG_VAR_INT(VARNAME,NAME,VALUE) \ + static service_factory_single_transparent_p2_t VARNAME(NAME,VALUE); + + +#define DECLARE_CONFIG_VAR_STRING(VARNAME,NAME,VALUE) \ + static service_factory_single_transparent_p2_t VARNAME(NAME,VALUE); + +#define DECLARE_CONFIG_VAR_STRUCT(TYPE,VARNAME,NAME,VALUE) \ + static service_factory_single_transparent_p2_t,const char*,TYPE> VARNAME(NAME,VALUE); + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/console.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/console.cpp new file mode 100644 index 000000000..a9b1e3c80 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/console.cpp @@ -0,0 +1,94 @@ +#include "foobar2000.h" + +bool console::present() +{ + bool rv = false; + console * ptr = service_enum_create_t(console,0); + if (ptr) + { + rv = true; + ptr->service_release(); + } + return rv; +} + +void console::popup() +{ + console * ptr = service_enum_create_t(console,0); + if (ptr) + { + ptr->_popup(); + ptr->service_release(); + } +} + +void console::beep() +{ + console * ptr = service_enum_create_t(console,0); + if (ptr) + { + ptr->_beep(); + ptr->service_release(); + } +} + +void console::output(int severity,const char * message,const char * source) +{ + console * ptr = service_enum_create_t(console,0); + if (ptr) + { + ptr->_output(severity,message,source); + ptr->service_release(); + } +} + +void console::output(int severity,const char * message) +{ + output(severity,message,core_api::get_my_file_name()); +} + +void console::info_location(const class playable_location * src) +{ + const char * path = src->get_path(); + int number = src->get_subsong_index(); + info(uStringPrintf("location: \"%s\" (%i)",path,number)); +} + +void console::info_location(class metadb_handle * src) +{ + info_location(src->handle_get_location()); +} + +void console::info_location(const class file_info * src) +{ + info_location(src->get_location()); +} + +void console::info_full(const class file_info * src) +{ + info_location(src); + string8_fastalloc temp; + unsigned n,m; + m = src->meta_get_count(); + info("meta:"); + for(n=0;nmeta_enum_name(n); + temp += "="; + temp += src->meta_enum_value(n); + info(temp); + } + info(temp); + m = src->info_get_count(); + info("info:"); + for(n=0;ninfo_enum_name(n); + temp += "="; + temp += src->info_enum_value(n); + info(temp); + } + info(temp); +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/console.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/console.h new file mode 100644 index 000000000..279c23b6b --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/console.h @@ -0,0 +1,59 @@ +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ + +#include "service.h" + +//for sending text (errors etc) to console component +//strings are all utf-8 + +class NOVTABLE console : public service_base +{ +protected: + virtual void _output(int severity,const char * source,const char * message)=0; + virtual void _popup()=0; + virtual void _beep()=0; +public: + enum { + SEVERITY_INFO = 1, + SEVERITY_WARNING = 2, + SEVERITY_CRITICAL = 3, + }; + + static void output(int severity,const char * message,const char * source); + static void output(int severity,const char * message); + static void info(const char * message) {output(SEVERITY_INFO,message);} + static void warning(const char * message) {output(SEVERITY_WARNING,message);} + static void error(const char * message) {output(SEVERITY_CRITICAL,message);} + static bool present();//returns if console component is present + static void popup(); + static void beep(); + static void info_location(const class playable_location * src); + static void info_location(class metadb_handle * src); + static void info_location(const class file_info * src); + static void info_full(const class file_info * src); + + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + //usage: console::warning("blah warning !"); +}; + +//all console methods are multi-thread safe, you can call them from any context + +#define __crash_to_messagebox(x) __except(uMessageBox(0,string_print_crash(GetExceptionInformation(),x),0,0),1) +#define __crash_to_console __except(console::error(string_print_crash(GetExceptionInformation())),1) +#define __crash_to_console_ex(x) __except(console::error(string_print_crash(GetExceptionInformation(),x)),1) +/* +usage +__try { + blah(); +} __crash_to_console_ex("blah()") +{ + //might want to print additional info about what caused the crash here +} + +*/ + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/contextmenu.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/contextmenu.h new file mode 100644 index 000000000..cfc068aec --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/contextmenu.h @@ -0,0 +1 @@ +#error DEPRECATED diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/core_api.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/core_api.h new file mode 100644 index 000000000..00a485402 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/core_api.h @@ -0,0 +1,18 @@ +#ifndef _CORE_API_H_ +#define _CORE_API_H_ + +#include "../../pfc/pfc.h" + +namespace core_api +{ + HINSTANCE get_my_instance(); + const char * get_my_file_name();// eg. "foo_asdf" for foo_asdf.dll + const char * get_my_full_path();//eg. file://c:\blah\foobar2000\foo_asdf.dll + HWND get_main_window(); + bool are_services_available(); + bool assert_main_thread(); + bool is_main_thread(); + const char * get_profile_path();//eg. "c:\documents_and_settings\username\blah\foobar2000\" +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/coreversion.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/coreversion.h new file mode 100644 index 000000000..e10bbf093 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/coreversion.h @@ -0,0 +1,28 @@ +#ifndef _COREVERSION_H_ +#define _COREVERSION_H_ + +#include "service.h" + +class core_version_info : public service_base +{ +private: + virtual const char * _get_version_string()=0; +public: + static const char * get_version_string() + { + const char * ret = ""; + core_version_info * ptr = service_enum_create_t(core_version_info,0); + if (ptr) + { + ret = ptr->_get_version_string(); + ptr->service_release(); + } + return ret; + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + +}; + +#endif //_COREVERSION_H_ diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/cvt_float_to_linear.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/cvt_float_to_linear.h new file mode 100644 index 000000000..151b7e3de --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/cvt_float_to_linear.h @@ -0,0 +1,37 @@ +#ifndef _CVT_FLOAT_TO_LINEAR_H_ +#define _CVT_FLOAT_TO_LINEAR_H_ + +#include "service.h" +#include "audio_chunk.h" + +//use this for converting floatingpoint -> linear PCM, one implementation in core, do not override +class NOVTABLE cvt_float_to_linear : public service_base +{ +public: + virtual int run(const audio_chunk * chunk,output_chunk * out_chunk,UINT out_bps,UINT use_dither,UINT use_pad=0)=0; + //return 1 on success, 0 on failure (eg. unsupported bps) + //use_pad = bps to pad to, 0 for auto + + //if you want to flush on seek or between tracks or whatever, just service_release() and recreate + + static cvt_float_to_linear * get()//helper + { + return service_enum_create_t(cvt_float_to_linear,0); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + +}; + +/* + +Notes on output data format. + +Following win32 conventions, out_chunk will point to buffer containing signed integers of specified size (physically always aligned to 8bits, actual resolution might be smaller according to passed params). +EXception, if output format is 8bit, values in the buffer are unsigned (just like everywhere in win32). +If out_bps isn't a multiply of 8, it will be used as conversion resolution, but results will be padded to multiply of 8-bit (and out_chunk's bps member will be set to padded bps). +out_chunk pointers are maintained by cvt_float_to_linear object, and become invalid after releasing the object or calling run() again. +*/ + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/diskwriter.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/diskwriter.cpp new file mode 100644 index 000000000..99420b989 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/diskwriter.cpp @@ -0,0 +1,27 @@ +#include "foobar2000.h" + + +diskwriter * diskwriter::instantiate(const GUID & guid) +{ + service_enum_t e; + diskwriter * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_guid() == guid) return ptr; + ptr->service_release(); + } + return 0; +} + +bool diskwriter::instantiate_test(const GUID & guid) +{ + service_enum_t e; + diskwriter * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + bool found = (ptr->get_guid() == guid) ? true : false; + ptr->service_release(); + if (found) return true; + } + return false; +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/diskwriter.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/diskwriter.h new file mode 100644 index 000000000..3ed8d6d24 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/diskwriter.h @@ -0,0 +1,74 @@ +#ifndef _DISKWRITER_H_ +#define _DISKWRITER_H_ + +#include "service.h" +#include "interface_helper.h" +#include "audio_chunk.h" +#include "file_info.h" + +//one instance of object will be called *only* with one output file +class NOVTABLE diskwriter : public service_base +{ +public: + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + virtual void get_name(string_base & out)=0;//name of your diskwriter service. never supposed to change + virtual bool get_extension(string_base & out)=0;//return false if you don't actually write files; result is allowed to depend on preset + + virtual bool open(const char * out_path,unsigned expected_sample_rate,unsigned expected_bps,double expected_length,bool should_dither)=0; + //expected_sample_rate may be null in rare cases, rely on it only as much as you must + //expected_sample_rate/expected_bps are pulled from first file on to-encode list (there may be more), if you actually need them and start getting chunks with different specs, return error + //expected_length is only as reliable as inputs reporting length, may not be strictly accurate + + virtual bool on_source_track(metadb_handle * ptr) {return true;}//return false to abort + + virtual bool process_samples(const audio_chunk * src)=0;//return true on success, false on failure + + virtual void flush()=0; + //close output file etc + + virtual GUID get_guid()=0;//GUID of your diskwriter subclass, for storing config + + virtual void preset_set_data(const void * ptr,unsigned bytes)=0; + virtual void preset_get_data(cfg_var::write_config_callback * out)=0; + virtual bool preset_configurable()=0;//return if you support config dialog or not + virtual bool preset_configure(HWND parent)=0;//return false if user aborted the operation + + virtual unsigned preset_default_get_count()=0; + virtual void preset_default_enumerate(unsigned index,cfg_var::write_config_callback * out)=0; + virtual bool preset_get_description(string_base & out)=0; + + + static diskwriter * instantiate(const GUID & guid); + static bool instantiate_test(const GUID & guid); +}; + +class NOVTABLE diskwriter_presetless : public diskwriter //helper, preset-less +{ +public: + virtual void preset_set_data(const void * ptr,unsigned bytes) {} + virtual void preset_get_data(cfg_var::write_config_callback * out) {} + virtual bool preset_configurable() {return false;} + virtual bool preset_configure(HWND parent) {return false;} + + + virtual unsigned preset_default_get_count() {return 1;} + virtual void preset_default_enumerate(unsigned index,cfg_var::write_config_callback * out) {} + virtual bool preset_get_description(string_base & out) {return false;} + +}; + + +template +class diskwriter_factory : public service_factory_t {}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp.cpp new file mode 100644 index 000000000..937b2e148 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp.cpp @@ -0,0 +1,316 @@ +#include "foobar2000.h" +#include + +#if defined(_MSC_VER) && !defined(_DEBUG) && defined(_M_IX86) +#define DSP_HAVE_ASM +#endif + +GUID dsp::guid_from_name(const char * name) +{ + service_enum_t e; + dsp * ptr; + for(ptr=e.first();ptr;ptr = e.next()) + { + if (!stricmp_utf8(ptr->get_name(),name)) + { + GUID g = ptr->get_guid(); + ptr->service_release(); + return g; + } + ptr->service_release(); + } + return mem_ops::make_null_item(); +} + +const char * dsp::name_from_guid(GUID g) +{ + service_enum_t e; + dsp * ptr; + for(ptr=e.first();ptr;ptr = e.next()) + { + if (ptr->get_guid()==g) + { + const char * name = ptr->get_name(); + ptr->service_release(); + return name; + } + ptr->service_release(); + } + return 0; +} + +dsp * dsp::instance_from_guid(GUID g) +{ + service_enum_t e; + dsp * ptr; + for(ptr=e.first();ptr;ptr = e.next()) + { + if (ptr->get_guid()==g) return ptr; + ptr->service_release(); + } + return 0; +} + +#ifndef DSP_HAVE_ASM +void dsp_util::scale(audio_sample * ptr,double scale,unsigned count) +{ + for(;count;count--) + { + (*ptr) = (audio_sample)((*ptr) * scale); + ptr++; + } +} +#else + +__declspec(naked) void dsp_util::scale(audio_sample * ptr,double scale,unsigned count) +{ + _asm + {//ptr: [esp+4], scale: [esp+8], count: [esp+16] + mov ecx,[esp+16] + mov edx,[esp+4] + fld qword ptr [esp+8] + mov eax,ecx + shr ecx,1 + jz l12 +l1: + fld audio_sample_asm ptr [edx] + fld audio_sample_asm ptr [edx+audio_sample_bytes] + fmul st,st(2) + fxch + dec ecx + fmul st,st(2) + fstp audio_sample_asm ptr [edx] + fstp audio_sample_asm ptr [edx+audio_sample_bytes] + lea edx,[edx+audio_sample_bytes*2] + jnz l1 +l12: + test eax,1 + jz l2 + fld audio_sample_asm ptr [edx] + fmul st,st(1) + fstp audio_sample_asm ptr [edx] +l2: + fstp st + ret + } +} +#endif + +void dsp_util::kill_denormal_32(float * fptr,unsigned count) +{ + DWORD * ptr = reinterpret_cast(fptr); + for(;count;count--) + { + DWORD t = *ptr; + if ((t & 0x007FFFFF) && !(t & 0x7F800000)) *ptr=0; + ptr++; + } +} + +void dsp_util::kill_denormal_64(double * fptr,unsigned count) +{ + unsigned __int64 * ptr = reinterpret_cast(fptr); + for(;count;count--) + { + unsigned __int64 t = *ptr; + if ((t & 0x000FFFFFFFFFFFFF) && !(t & 0x7FF0000000000000)) *ptr=0; + ptr++; + } +} + + +unsigned dsp_chunk_list_i::get_count() const {return data.get_count();} + +audio_chunk * dsp_chunk_list_i::get_item(unsigned n) const {return n>=0 && n<(unsigned)data.get_count() ? data[n] : 0;} + +void dsp_chunk_list_i::remove_by_idx(unsigned idx) +{ + if (idx>=0 && idx<(unsigned)data.get_count()) + recycled.add_item(data.remove_by_idx(idx)); +} + +void dsp_chunk_list_i::remove_mask(const bit_array & mask) +{ + unsigned n, m = data.get_count(); + for(n=0;nmax) idx = max; + audio_chunk_i * ret = 0; + if (recycled.get_count()>0) + { + unsigned best; + if (hint_size>0) + { + best = 0; + unsigned best_found = recycled[0]->get_data_size(), n, total = recycled.get_count(); + for(n=1;nget_data_size(); + int delta_old = abs((int)best_found - (int)hint_size), delta_new = abs((int)size - (int)hint_size); + if (delta_new < delta_old) + { + best_found = size; + best = n; + } + } + } + else best = recycled.get_count()-1; + + ret = recycled.remove_by_idx(best); + ret->set_sample_count(0); + ret->set_channels(0); + ret->set_srate(0); + } + else ret = new audio_chunk_i; + if (idx==max) data.add_item(ret); + else data.insert_item(ret,idx); + return ret; +} + +dsp_chunk_list_i::~dsp_chunk_list_i() {data.delete_all();recycled.delete_all();} + +void dsp_chunk_list::remove_bad_chunks() +{ + bool blah = false; + unsigned idx; + for(idx=0;idxis_valid()) + { + chunk->reset(); + remove_by_idx(idx); + blah = true; + } + else idx++; + } + if (blah) console::error("one or more bad chunks removed from dsp chunk list"); +} + +__int64 dsp_util::duration_samples_from_time(double time,unsigned srate) +{ + return (__int64)floor((double)srate * time + 0.5); +} + + +#ifdef DSP_HAVE_ASM + +__declspec(naked) void __fastcall dsp_util::convert_32_to_64(const float * src,double * dest,unsigned count) +{ + _asm//src: ecx, dest: edx, count: eax + { + mov eax,dword ptr [esp+4] + shr eax,2 + jz l2 +l1: fld dword ptr [ecx] + fld dword ptr [ecx+4] + fstp qword ptr [edx+8] + fstp qword ptr [edx] + dec eax + fld dword ptr [ecx+8] + fld dword ptr [ecx+12] + fstp qword ptr [edx+24] + fstp qword ptr [edx+16] + lea ecx,[ecx+16] + lea edx,[edx+32] + jnz l1 +l2: mov eax,dword ptr [esp+4] + and eax,3 + jz l4 +l3: fld dword ptr [ecx] + dec eax + fstp qword ptr [edx] + lea ecx,[ecx+4] + lea edx,[edx+8] + jnz l3 +l4: ret 4 + } +} + +__declspec(naked) void __fastcall dsp_util::convert_64_to_32(const double * src,float * dest,unsigned count) +{ + _asm//src: ecx, dest: edx, count: eax + { + mov eax,dword ptr [esp+4] + shr eax,2 + jz l2 +l1: fld qword ptr [ecx] + fld qword ptr [ecx+8] + fstp dword ptr [edx+4] + fstp dword ptr [edx] + dec eax + fld qword ptr [ecx+16] + fld qword ptr [ecx+24] + fstp dword ptr [edx+12] + fstp dword ptr [edx+8] + lea ecx,[ecx+32] + lea edx,[edx+16] + jnz l1 +l2: mov eax,dword ptr [esp+4] + and eax,3 + jz l4 +l3: fld qword ptr [ecx] + dec eax + fstp dword ptr [edx] + lea ecx,[ecx+8] + lea edx,[edx+4] + jnz l3 +l4: ret 4 + } +} + +#else + +void __fastcall dsp_util::convert_32_to_64(const float * src,double * dest,unsigned count) +{ + for(;count;count--) + *(dest++) = (double)*(src++); +} + +void __fastcall dsp_util::convert_64_to_32(const double * src,float * dest,unsigned count) +{ + for(;count;count--) + *(dest++) = (float)*(src++); +} + +#endif + + +void dsp::get_config(cfg_var::write_config_callback * out) +{ + dsp_v2 * this_v2 = service_query_t(dsp_v2,this); + if (this_v2) + { + this_v2->get_config(out); + this_v2->service_release(); + } +} +void dsp::set_config(const void * src,unsigned bytes) +{ + dsp_v2 * this_v2 = service_query_t(dsp_v2,this); + if (this_v2) + { + this_v2->set_config(src,bytes); + this_v2->service_release(); + } +} +bool dsp::popup_config(HWND parent) +{ + bool rv = false; + dsp_v2 * this_v2 = service_query_t(dsp_v2,this); + if (this_v2) + { + rv = this_v2->popup_config(parent); + this_v2->service_release(); + } + return rv; +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp.h new file mode 100644 index 000000000..d96cdeca0 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp.h @@ -0,0 +1,196 @@ +#ifndef _DSP_H_ +#define _DSP_H_ + +#include "service.h" +#include "audio_chunk.h" +#include "interface_helper.h" + +namespace dsp_util +{ + __int64 duration_samples_from_time(double time,unsigned srate); + + void kill_denormal_32(float * ptr,unsigned count); + void kill_denormal_64(double * ptr,unsigned count); + void scale(audio_sample * ptr,double scale,unsigned count); + inline void kill_denormal(audio_sample * ptr,unsigned count) + { +#if audio_sample_size == 32 + kill_denormal_32(ptr,count); +#else + kill_denormal_64(ptr,count); +#endif + } + inline void scale_chunk(audio_chunk * ptr,double scale) {dsp_util::scale(ptr->get_data(),scale,ptr->get_data_length());} + + void __fastcall convert_32_to_64(const float * src,double * dest,unsigned count); + void __fastcall convert_64_to_32(const double * src,float * dest,unsigned count); +}; + +class NOVTABLE dsp_chunk_list//interface (cross-dll safe) +{ +public: + virtual unsigned get_count() const = 0; + virtual audio_chunk * get_item(unsigned n) const = 0; + virtual void remove_by_idx(unsigned idx) = 0; + virtual void remove_mask(const bit_array & mask) = 0; + virtual audio_chunk * insert_item(unsigned idx,unsigned hint_size=0) = 0; + + audio_chunk * add_item(unsigned hint_size=0) {return insert_item(get_count(),hint_size);} + + void remove_all() {remove_mask(bit_array_true());} + + double get_duration() + { + double rv = 0; + unsigned n,m = get_count(); + for(n=0;nget_duration(); + return rv; + } + + void add_chunk(const audio_chunk * chunk) + { + audio_chunk * dst = insert_item(get_count(),chunk->get_data_length()); + if (dst) dst->copy_from(chunk); + } + + void remove_bad_chunks(); +}; + +class dsp_chunk_list_i : public dsp_chunk_list//implementation +{ + ptr_list_simple data,recycled; +public: + virtual unsigned get_count() const; + virtual audio_chunk * get_item(unsigned n) const; + virtual void remove_by_idx(unsigned idx); + virtual void remove_mask(const bit_array & mask); + virtual audio_chunk * insert_item(unsigned idx,unsigned hint_size=0); + ~dsp_chunk_list_i(); +}; + +class NOVTABLE dsp : public service_base +{ +public: + enum + { + END_OF_TRACK = 1, //flush whatever you need to when tracks change + FLUSH = 2 //flush everything + }; + + virtual GUID get_guid()=0; + virtual const char * get_name()=0; + virtual void run(dsp_chunk_list * list,class metadb_handle * cur_file,int flags)=0;//int flags <= see flags above + //cur_file is OPTIONAL and may be null + virtual void flush() {}//after seek etc + virtual double get_latency() {return 0;}//amount of data buffered (in seconds) + virtual int need_track_change_mark() {return 0;}//return 1 if you need to know exact track change point (eg. for crossfading, removing silence), will force-flush any DSPs placed before you so when you get END_OF_TRACK, chunks you get contain last samples of the track; will often break regular gapless playback so don't use it unless you have reasons to + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static GUID guid_from_name(const char * name);//may fail if DSP isn't present (eg. dll got removed) + static const char * name_from_guid(GUID g);//may fail if DSP isn't present (eg. dll got removed) + static dsp * instance_from_guid(GUID g);//may fail if DSP isn't present (eg. dll got removed) + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + void get_config(cfg_var::write_config_callback * out); + void set_config(const void * src,unsigned bytes); + bool popup_config(HWND parent); + +}; + +class NOVTABLE dsp_v2 : public dsp +{ +public: + virtual void config_get(cfg_var::write_config_callback * out) {}; + virtual void config_set(const void * src,unsigned bytes) {}; + virtual bool config_popup(HWND parent) {return false;};//return false if you don't support config dialog + virtual bool config_supported()=0; + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return dsp::service_query(guid); + } + +}; + +template +class dsp_i_base_t : public T +{ +private: + dsp_chunk_list * list; + unsigned chunk_ptr; + metadb_handle * cur_file; + virtual void run(dsp_chunk_list * p_list,class metadb_handle * p_cur_file,int flags); +protected: + inline metadb_handle * get_cur_file() {return cur_file;}// call only from on_chunk / on_endoftrack (on_endoftrack will give info on track being finished); may return null !! + dsp_i_base_t() {list = 0;cur_file=0;chunk_ptr=0;} + audio_chunk * insert_chunk(unsigned hint_size = 0) //call only from on_endoftrack / on_endofplayback / on_chunk + {//hint_size - optional, amout of buffer space you want to use + return list ? list->insert_item(chunk_ptr++,hint_size) : 0; + } + //override these + virtual void on_endoftrack()//use insert_chunk() if you have data you want to dump + { + } + virtual void on_endofplayback() + {//use insert_chunk() if you have data you want to dump + + } + virtual bool on_chunk(audio_chunk * chunk) + {//return true if your chunk, possibly modified needs to be put back into chain, false if you want it removed + //use insert_chunk() if you want to insert pending data before current chunk + return true; + } + +public: + virtual GUID get_guid()=0; + virtual const char * get_name()=0; + + virtual void flush() {}//after seek etc + virtual double get_latency() {return 0;}//amount of data buffered (in seconds) + virtual int need_track_change_mark() {return 0;}//return 1 if you need to know exact track change point (eg. for crossfading, removing silence), will force-flush any DSPs placed before you so when you get END_OF_TRACK, chunks you get contain last samples of the track; will often break regular gapless playback so don't use it unless you have reasons to + +}; + +template +void dsp_i_base_t::run(dsp_chunk_list * p_list,class metadb_handle * p_cur_file,int flags) +{ + list = p_list; + cur_file = p_cur_file; + for(chunk_ptr = 0;chunk_ptrget_count();chunk_ptr++) + { + audio_chunk * c = list->get_item(chunk_ptr); + if (c->is_empty() || !on_chunk(c)) + list->remove_by_idx(chunk_ptr--); + } + if (flags & FLUSH) + on_endofplayback(); + else if (flags & END_OF_TRACK) + on_endoftrack(); + + list = 0; + cur_file = 0; +} + + +class dsp_i_base : public dsp_i_base_t {}; + +template +class dsp_factory : public service_factory_t {}; + + +#include "dsp_manager.h" + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp_manager.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp_manager.h new file mode 100644 index 000000000..b85e9b9cf --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/dsp_manager.h @@ -0,0 +1,52 @@ +#ifndef _DSP_MANAGER_H_ +#define _DSP_MANAGER_H_ + +#include "dsp.h" + +//use this to run user-configured DSPs on your data stream +//one implementation in main exe, dont override +class NOVTABLE dsp_manager : public service_base +{ +public: + virtual double run(dsp_chunk_list * list,class metadb_handle * cur_file,int eof)=0; + virtual void flush(); + + virtual void set_chain(int b_use_custom,unsigned int count,const GUID * list)=0; + //user settings from core config will be used when b_use_custom is zero, custom DSP list specified by count/list params will be used when non-zero + //user settings are used by default if you don't call set_chain() + + class NOVTABLE get_default_chain_callback + { + public: + virtual void on_list(unsigned int num,const GUID * ptr)=0; + }; + + class get_default_chain_callback_i : public get_default_chain_callback + { + mem_block_t & data; + public: + virtual void on_list(unsigned int num,const GUID * ptr) + { + data.set_size(num); + data.copy(ptr,num); + } + get_default_chain_callback_i(mem_block_t & param) : data(param) {} + }; + + //use this to get user's DSP config from core preferences + virtual void get_default_chain(get_default_chain_callback * cb)=0; + + void get_default_chain(mem_block_t & dest)//helper + { + get_default_chain(&get_default_chain_callback_i(dest)); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static dsp_manager* create() {return service_enum_create_t(dsp_manager,0);} +}; + + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info.cpp new file mode 100644 index 000000000..d498b1e46 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info.cpp @@ -0,0 +1,221 @@ +#include "foobar2000.h" +#include +#include +#include + +void file_info::copy(const file_info * src) +{ + meta_remove_all(); + info_remove_all(); + set_location(src->get_location()); + set_length(src->get_length()); + int n; + for(n=0;nmeta_get_count();n++) + meta_add(src->meta_enum_name(n),src->meta_enum_value(n)); + for(n=0;ninfo_get_count();n++) + info_set(src->info_enum_name(n),src->info_enum_value(n)); +} + +void file_info::info_set_int(const char * name,__int64 value) +{ + assert(is_valid_utf8(name)); + char temp[32]; + _i64toa(value,temp,10); + info_set(name,temp); +} + +void file_info::info_set_float(const char * name,double value,unsigned precision,bool force_sign,const char * unit) +{ + assert(is_valid_utf8(name)); + assert(unit==0 || strlen(unit) <= 64); + char temp[128]; + pfc_float_to_string(temp,value,precision,force_sign); + if (unit) + { + strcat(temp," "); + strcat(temp,unit); + } + info_set(name,temp); +} + +void file_info::info_set_replaygain_track_gain(double value) +{ + info_set_float("replaygain_track_gain",value,2,true,"dB"); +} + +void file_info::info_set_replaygain_album_gain(double value) +{ + info_set_float("replaygain_album_gain",value,2,true,"dB"); +} + +void file_info::info_set_replaygain_track_peak(double value) +{ + info_set_float("replaygain_track_peak",value,6,false); +} + +void file_info::info_set_replaygain_album_peak(double value) +{ + info_set_float("replaygain_album_peak",value,6,false); +} + + +int file_info::info_get_idx(const char * name) const +{ + assert(is_valid_utf8(name)); + int n,m=info_get_count(); + for(n=0;n0 && len>0) + { + ret = dsp_util::duration_samples_from_time(len,(unsigned)srate); + } + return ret; +} + + + + + +void file_info::meta_add_wide(const WCHAR * name,const WCHAR* value) +{//unicode (UTF-16) version + meta_add(string_utf8_from_wide(name),string_utf8_from_wide(value)); +} + +void file_info::meta_add_ansi(const char * name,const char * value) +{//ANSI version + meta_add(string_utf8_from_ansi(name),string_utf8_from_ansi(value)); +} + +void file_info::meta_set_wide(const WCHAR * name,const WCHAR* value) +{//widechar version + meta_set(string_utf8_from_wide(name),string_utf8_from_wide(value)); +} + +void file_info::meta_set_ansi(const char * name,const char * value) +{//ANSI version + meta_set(string_utf8_from_ansi(name),string_utf8_from_ansi(value)); +} + + +void file_info::meta_add_n(const char * name,int name_len,const char * value,int value_len) +{ + meta_add(string_simple(name,name_len),string_simple(value,value_len)); +} + +void file_info::meta_remove_field(const char * name)//removes ALL fields of given name +{ + assert(is_valid_utf8(name)); + int n; + for(n=meta_get_count()-1;n>=0;n--) + { + if (!stricmp_utf8(meta_enum_name(n),name)) + meta_remove(n); + } + +} + +void file_info::meta_set(const char * name,const char * value) //deletes all fields of given name (if any), then adds new one +{ + assert(is_valid_utf8(name)); + assert(is_valid_utf8(value)); + meta_remove_field(name); + meta_add(name,value); +} + +const char * file_info::meta_get(const char * name,int num) const +{ + assert(is_valid_utf8(name)); + int idx = meta_get_idx(name,num); + if (idx<0) return 0; + else return meta_enum_value(idx); +} + +int file_info::meta_get_count_by_name(const char* name) const +{ + assert(is_valid_utf8(name)); + int n,m=meta_get_count(); + int rv=0; + for(n=0;n=0;n--) + { + if (!stricmp_utf8(name,info_enum_name(n))) + info_remove(n); + } + +} + +static bool is_valid_bps(__int64 val) +{ + return val>0 && val<=256; +} + +unsigned file_info::info_get_decoded_bps() +{ + __int64 val = info_get_int("decoded_bitspersample"); + if (is_valid_bps(val)) return (unsigned)val; + val = info_get_int("bitspersample"); + if (is_valid_bps(val)) return (unsigned)val; + return 0; +} + +double file_info::info_get_float(const char * name) +{ + const char * ptr = info_get(name); + if (ptr) return pfc_string_to_float(ptr); + else return 0; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info.h new file mode 100644 index 000000000..212cac816 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info.h @@ -0,0 +1,96 @@ +#ifndef _FILE_INFO_H_ +#define _FILE_INFO_H_ + +#include "playable_location.h" +#include "playlist_entry.h"//for compatibility with old code + +//file_info == playable_location + length + metadata + tech infos +//also see: metadb.h + +//all char* strings are UTF-8, including filenames, unless comments state otherwise + +class NOVTABLE file_info //interface (cross-dll-safe) +{ +public: + virtual ~file_info() {} + //interface + + virtual void copy(const file_info * src);//can be overridden + + //multiple fields of the same name ARE allowed. + virtual int meta_get_count() const = 0; + virtual const char * meta_enum_name(int n) const = 0; + virtual const char * meta_enum_value(int n) const = 0; + virtual void meta_modify_value(int n,const char * new_value) = 0; + virtual void meta_insert(int index,const char * name,const char * value) = 0; + virtual void meta_add(const char * name,const char * value) = 0; + virtual void meta_remove(int n) = 0; + virtual void meta_remove_all() = 0; + virtual int meta_get_idx(const char * name,int num = 0) const; + //tech infos (bitrate, replaygain, etc), not user-editable + //multiple fields of the same are NOT allowed. + virtual void info_set(const char * name,const char * value) = 0;//replaces existing field if found + virtual int info_get_count() const = 0; + virtual const char * info_enum_name(int n) const = 0; + virtual const char * info_enum_value(int n) const = 0; + virtual void info_remove(int n) = 0; + virtual void info_remove_all() = 0; + virtual int info_get_idx(const char * name) const; + + virtual const playable_location * get_location() const = 0; + virtual void set_location(const playable_location *)=0; + + virtual void set_length(double) = 0;//length in seconds + virtual double get_length() const = 0; + + + inline int get_subsong_index() const {return get_location()->get_number();} + inline const char * get_file_path() const {return get_location()->get_path();} + + + inline void reset() {meta_remove_all();info_remove_all();set_length(0);} + +//helper stuff for setting meta + void meta_add_wide(const WCHAR * name,const WCHAR* value); + void meta_add_ansi(const char * name,const char * value); + void meta_set_wide(const WCHAR * name,const WCHAR* value); + void meta_set_ansi(const char * name,const char * value); + void meta_add_n(const char * name,int name_len,const char * value,int value_len); + void meta_remove_field(const char * name);//removes ALL fields of given name + void meta_set(const char * name,const char * value); //deletes all fields of given name (if any), then adds new one + const char * meta_get(const char * name,int num = 0) const; + int meta_get_count_by_name(const char* name) const; + const char * info_get(const char * name) const; + void info_remove_field(const char * name); + + __int64 info_get_int(const char * name) const; + __int64 info_get_length_samples() const; + double info_get_float(const char * name); + void info_set_int(const char * name,__int64 value); + void info_set_float(const char * name,double value,unsigned precision,bool force_sign = false,const char * unit = 0); + void info_set_replaygain_track_gain(double value); + void info_set_replaygain_album_gain(double value); + void info_set_replaygain_track_peak(double value); + void info_set_replaygain_album_peak(double value); + + inline __int64 info_get_bitrate_vbr() {return info_get_int("bitrate_dynamic");} + inline void info_set_bitrate_vbr(__int64 val) {info_set_int("bitrate_dynamic",val);} + inline __int64 info_get_bitrate() {return info_get_int("bitrate");} + inline void info_set_bitrate(__int64 val) {info_set_int("bitrate",val);} + + unsigned info_get_decoded_bps();//what bps the stream originally was (before converting to audio_sample), 0 if unknown +}; + +/* +recommended meta types: +TITLE +ARTIST +ALBUM +TRACKNUMBER (not TRACK) +DATE (not YEAR) +DISC (for disc number in a multidisc album) +GENRE +COMMENT +*/ + +#endif //_FILE_INFO_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info_helper.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info_helper.h new file mode 100644 index 000000000..f14ab53df --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/file_info_helper.h @@ -0,0 +1,93 @@ +#ifndef _FILE_INFO_HELPER_H_ +#define _FILE_INFO_HELPER_H_ + +#include "file_info.h" +#include "metadb_handle.h" + +class file_info_i : public file_info +{ +private: + playable_location_i location; + double length; + + struct entry + { + string_simple name,value; + entry(const char * p_name,const char * p_value) : name(p_name), value(p_value) {} + }; + ptr_list_t meta,info; +public: + file_info_i(const playable_location & src) : location(src), length(0) {} + file_info_i(const playable_location * src) : location(*src), length(0) {} + + file_info_i(const char * fn,int num) : location(fn,num), length(0) {} + + file_info_i() : length(0) {} + + file_info_i(metadb_handle * src) + : location(*src->handle_get_location()), length(0) + { + src->handle_query(this); + } + + file_info_i(const file_info & src) : length(0) {copy(&src);} + + + ~file_info_i() {meta.delete_all();info.delete_all();} + + //multiple fields of the same name ARE allowed. + virtual int meta_get_count() const {return meta.get_count();} + virtual const char * meta_enum_name(int n) const {return meta[n]->name;} + virtual const char * meta_enum_value(int n) const {return meta[n]->value;} + + virtual void meta_modify_value(int n,const char * new_value) + { + assert(is_valid_utf8(new_value)); + meta[n]->value=new_value; + } + + virtual void meta_insert(int index,const char * name,const char * value) + { + assert(is_valid_utf8(name)); + assert(is_valid_utf8(value)); + meta.insert_item(new entry(name,value),index); + } + + virtual void meta_add(const char * name,const char * value) + { + assert(is_valid_utf8(name)); + assert(is_valid_utf8(value)); + meta.add_item(new entry(name,value)); + } + + virtual void meta_remove(int n) {meta.delete_by_idx(n);} + virtual void meta_remove_all() {meta.delete_all();} + + //tech infos (bitrate, replaygain, etc), not user-editable + //multiple fields of the same are NOT allowed. + virtual void info_set(const char * name,const char * value) + { + assert(is_valid_utf8(name)); + assert(is_valid_utf8(value)); + info_remove_field(name); + info.add_item(new entry(name,value)); + } + + virtual int info_get_count() const {return info.get_count();} + virtual const char * info_enum_value(int n) const {return info[n]->value;} + virtual const char * info_enum_name(int n) const {return info[n]->name;} + virtual void info_remove(int n) {info.delete_by_idx(n);} + virtual void info_remove_all() {info.delete_all();} + + + virtual const playable_location * get_location() const {return &location;} + virtual void set_location(const playable_location * z) {location.copy(z);} + + virtual void set_length(double v) {length = v;} + virtual double get_length() const {return length;} + +}; + +#define file_info_i_full file_info_i + +#endif //_FILE_INFO_HELPER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/foobar2000.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/foobar2000.h new file mode 100644 index 000000000..69d9028bd --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/foobar2000.h @@ -0,0 +1,49 @@ +#ifndef _FOOBAR2000_H_ +#define _FOOBAR2000_H_ + +#include "../../pfc/pfc.h" + +#include "utf8api.h" + +#include "service.h" + +#include "audio_chunk.h" +#include "componentversion.h" +#include "config.h" +#include "config_var.h" +#include "console.h" +#include "coreversion.h" +#include "cvt_float_to_linear.h" +#include "diskwriter.h" +#include "dsp.h" +#include "dsp_manager.h" +#include "file_info.h" +#include "file_info_helper.h" +#include "initquit.h" +#include "input.h" +#include "input_helpers.h" +#include "menu_item.h" +#include "menu_manager.h" +#include "modeless_dialog.h" +#include "output.h" +#include "output_manager.h" +#include "play_callback.h" +#include "play_control.h" +#include "playable_location.h" +#include "playback_core.h" +#include "playlist.h" +#include "playlist_loader.h" +#include "reader.h" +#include "replaygain.h" +#include "resampler.h" +#include "service_helper.h" +#include "tagread.h" +#include "titleformat.h" +#include "ui.h" +#include "unpack.h" +#include "vis.h" +#include "playlist_switcher.h" +#include "packet_decoder.h" +#include "commandline.h" + +#endif //_FOOBAR2000_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/foobar2000_SDK.dsp b/tools/vio2sf/src/foobar8/foobar2000/SDK/foobar2000_SDK.dsp new file mode 100644 index 000000000..d62b04b36 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/foobar2000_SDK.dsp @@ -0,0 +1,399 @@ +# Microsoft Developer Studio Project File - Name="foobar2000_SDK" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=foobar2000_SDK - 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 "foobar2000_SDK.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 "foobar2000_SDK.mak" CFG="foobar2000_SDK - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "foobar2000_SDK - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "foobar2000_SDK - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "foobar2000_SDK - 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 Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O1 /Oy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "UNICODE" /D "_UNICODE" /Yu"foobar2000.h" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "foobar2000_SDK - 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 Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "UNICODE" /D "_UNICODE" /Yu"foobar2000.h" /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "foobar2000_SDK - Win32 Release" +# Name "foobar2000_SDK - Win32 Debug" +# Begin Source File + +SOURCE=.\audio_chunk.cpp +# End Source File +# Begin Source File + +SOURCE=.\audio_chunk.h +# End Source File +# Begin Source File + +SOURCE=.\commandline.cpp +# End Source File +# Begin Source File + +SOURCE=.\commandline.h +# End Source File +# Begin Source File + +SOURCE=.\component.h +# End Source File +# Begin Source File + +SOURCE=.\componentversion.h +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\config_var.h +# End Source File +# Begin Source File + +SOURCE=.\console.cpp +# End Source File +# Begin Source File + +SOURCE=.\console.h +# End Source File +# Begin Source File + +SOURCE=.\core_api.h +# End Source File +# Begin Source File + +SOURCE=.\coreversion.h +# End Source File +# Begin Source File + +SOURCE=.\cvt_float_to_linear.h +# End Source File +# Begin Source File + +SOURCE=.\diskwriter.cpp +# End Source File +# Begin Source File + +SOURCE=.\diskwriter.h +# End Source File +# Begin Source File + +SOURCE=.\dsp.cpp +# End Source File +# Begin Source File + +SOURCE=.\dsp.h +# End Source File +# Begin Source File + +SOURCE=.\dsp_manager.h +# End Source File +# Begin Source File + +SOURCE=.\file_info.cpp +# End Source File +# Begin Source File + +SOURCE=.\file_info.h +# End Source File +# Begin Source File + +SOURCE=.\file_info_helper.h +# End Source File +# Begin Source File + +SOURCE=.\foobar2000.h +# End Source File +# Begin Source File + +SOURCE=.\guids.cpp +# End Source File +# Begin Source File + +SOURCE=.\initquit.h +# End Source File +# Begin Source File + +SOURCE=.\input.cpp +# End Source File +# Begin Source File + +SOURCE=.\input.h +# End Source File +# Begin Source File + +SOURCE=.\input_helpers.cpp +# End Source File +# Begin Source File + +SOURCE=.\input_helpers.h +# End Source File +# Begin Source File + +SOURCE=.\menu_item.h +# End Source File +# Begin Source File + +SOURCE=.\menu_manager.cpp +# End Source File +# Begin Source File + +SOURCE=.\menu_manager.h +# End Source File +# Begin Source File + +SOURCE=.\metadb.cpp +# End Source File +# Begin Source File + +SOURCE=.\metadb.h +# End Source File +# Begin Source File + +SOURCE=.\metadb_handle.cpp +# End Source File +# Begin Source File + +SOURCE=.\metadb_handle.h +# End Source File +# Begin Source File + +SOURCE=.\modeless_dialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\modeless_dialog.h +# End Source File +# Begin Source File + +SOURCE=.\output.cpp +# End Source File +# Begin Source File + +SOURCE=.\output.h +# End Source File +# Begin Source File + +SOURCE=.\output_manager.h +# End Source File +# Begin Source File + +SOURCE=.\packet_decoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\packet_decoder.h +# End Source File +# Begin Source File + +SOURCE=.\play_callback.h +# End Source File +# Begin Source File + +SOURCE=.\play_control.cpp +# End Source File +# Begin Source File + +SOURCE=.\play_control.h +# End Source File +# Begin Source File + +SOURCE=.\playable_location.cpp +# End Source File +# Begin Source File + +SOURCE=.\playable_location.h +# End Source File +# Begin Source File + +SOURCE=.\playback_core.h +# End Source File +# Begin Source File + +SOURCE=.\playlist.cpp +# End Source File +# Begin Source File + +SOURCE=.\playlist.h +# End Source File +# Begin Source File + +SOURCE=.\playlist_entry.h +# End Source File +# Begin Source File + +SOURCE=.\playlist_loader.cpp +# End Source File +# Begin Source File + +SOURCE=.\playlist_loader.h +# End Source File +# Begin Source File + +SOURCE=.\playlist_switcher.h +# End Source File +# Begin Source File + +SOURCE=.\reader.cpp +# End Source File +# Begin Source File + +SOURCE=.\reader.h +# End Source File +# Begin Source File + +SOURCE=.\reader_helper.h +# End Source File +# Begin Source File + +SOURCE=.\reader_helper_mem.h +# End Source File +# Begin Source File + +SOURCE=.\replaygain.h +# End Source File +# Begin Source File + +SOURCE=.\resampler.h +# End Source File +# Begin Source File + +SOURCE=.\service.cpp +# End Source File +# Begin Source File + +SOURCE=.\service.h +# End Source File +# Begin Source File + +SOURCE=.\service_helper.h +# End Source File +# Begin Source File + +SOURCE=.\service_impl.h +# End Source File +# Begin Source File + +SOURCE=.\stdafx.cpp + +!IF "$(CFG)" == "foobar2000_SDK - Win32 Release" + +# ADD CPP /Yc + +!ELSEIF "$(CFG)" == "foobar2000_SDK - Win32 Debug" + +# ADD CPP /Yc"foobar2000.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\tagread.cpp +# End Source File +# Begin Source File + +SOURCE=.\tagread.h +# End Source File +# Begin Source File + +SOURCE=.\titleformat.cpp +# End Source File +# Begin Source File + +SOURCE=.\titleformat.h +# End Source File +# Begin Source File + +SOURCE=.\ui.cpp +# End Source File +# Begin Source File + +SOURCE=.\ui.h +# End Source File +# Begin Source File + +SOURCE=.\unpack.h +# End Source File +# Begin Source File + +SOURCE=.\utf8api.cpp +# End Source File +# Begin Source File + +SOURCE=.\utf8api.h +# End Source File +# Begin Source File + +SOURCE=.\vis.h +# End Source File +# End Target +# End Project diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/guids.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/guids.cpp new file mode 100644 index 000000000..5bce2a4c7 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/guids.cpp @@ -0,0 +1,583 @@ +#include "foobar2000.h" + +#ifdef _MSC_VER +#define FOOGUIDDECL __declspec(selectany) //hack against msvc linker stupidity +#else +#define FOOGUIDDECL +#endif + +// {10BB3EBD-DDF7-4975-A3CC-23084829453E} +FOOGUIDDECL const GUID componentversion::class_guid = +{ 0x10bb3ebd, 0xddf7, 0x4975, { 0xa3, 0xcc, 0x23, 0x8, 0x48, 0x29, 0x45, 0x3e } }; + +// {7255E8D0-3FCF-4781-B93B-D06CB88DFAFA} +FOOGUIDDECL const GUID config::class_guid = +{ 0x7255e8d0, 0x3fcf, 0x4781, { 0xb9, 0x3b, 0xd0, 0x6c, 0xb8, 0x8d, 0xfa, 0xfa } }; + +// {056B51C7-E78C-4a4e-B84E-6BFF3F8AB8F2} +FOOGUIDDECL const GUID console::class_guid = +{ 0x56b51c7, 0xe78c, 0x4a4e, { 0xb8, 0x4e, 0x6b, 0xff, 0x3f, 0x8a, 0xb8, 0xf2 } }; + +// {0C36A649-9EA0-4f48-B229-0CB2AA9AB6F4} +FOOGUIDDECL const GUID core_version_info::class_guid = +{ 0xc36a649, 0x9ea0, 0x4f48, { 0xb2, 0x29, 0xc, 0xb2, 0xaa, 0x9a, 0xb6, 0xf4 } }; + +// {545F99D1-602D-4175-867F-F7C6AD680A81} +FOOGUIDDECL const GUID cvt_float_to_linear::class_guid = +{ 0x545f99d1, 0x602d, 0x4175, { 0x86, 0x7f, 0xf7, 0xc6, 0xad, 0x68, 0xa, 0x81 } }; + +// {D9239DB0-210B-4680-82AF-C37DBDD6A43D} +FOOGUIDDECL const GUID dsp_v2::class_guid = +{ 0xd9239db0, 0x210b, 0x4680, { 0x82, 0xaf, 0xc3, 0x7d, 0xbd, 0xd6, 0xa4, 0x3d } }; + +// {2A42AFEA-940B-455b-AEFF-CFDACAF52AFF} +FOOGUIDDECL const GUID dsp::class_guid = +{ 0x2a42afea, 0x940b, 0x455b, { 0xae, 0xff, 0xcf, 0xda, 0xca, 0xf5, 0x2a, 0xff } }; + +// {D63655B2-B0CE-4069-BDF9-E364E43FF23C} +FOOGUIDDECL const GUID input::class_guid = +{ 0xd63655b2, 0xb0ce, 0x4069, { 0xbd, 0xf9, 0xe3, 0x64, 0xe4, 0x3f, 0xf2, 0x3c } }; + +// {113773C4-B387-4b48-8BDF-AB58BC6CE538} +FOOGUIDDECL const GUID initquit::class_guid = +{ 0x113773c4, 0xb387, 0x4b48, { 0x8b, 0xdf, 0xab, 0x58, 0xbc, 0x6c, 0xe5, 0x38 } }; + +// {609D48C8-C6A6-4784-8BBD-FDD32BF0740E} +FOOGUIDDECL const GUID metadb::class_guid = +{ 0x609d48c8, 0xc6a6, 0x4784, { 0x8b, 0xbd, 0xfd, 0xd3, 0x2b, 0xf0, 0x74, 0xe } }; + +// {D5286BB4-FDED-47ef-A623-4C3FF056DEC1} +FOOGUIDDECL const GUID metadb_callback::class_guid = +{ 0xd5286bb4, 0xfded, 0x47ef, { 0xa6, 0x23, 0x4c, 0x3f, 0xf0, 0x56, 0xde, 0xc1 } }; + +// {065190FC-9C8A-4b2b-A5EC-E21EBE288234} +FOOGUIDDECL const GUID metadb_callback_simple::class_guid = +{ 0x65190fc, 0x9c8a, 0x4b2b, { 0xa5, 0xec, 0xe2, 0x1e, 0xbe, 0x28, 0x82, 0x34 } }; + +// {1C0802F7-CF24-49ef-B914-8B9866F19779} +FOOGUIDDECL const GUID menu_item::class_guid = +{ 0x1c0802f7, 0xcf24, 0x49ef, { 0xb9, 0x14, 0x8b, 0x98, 0x66, 0xf1, 0x97, 0x79 } }; + +// {C1CAF378-BCAF-4271-AE4D-45A49B9C3B79} +FOOGUIDDECL const GUID output::class_guid = +{ 0xc1caf378, 0xbcaf, 0x4271, { 0xae, 0x4d, 0x45, 0xa4, 0x9b, 0x9c, 0x3b, 0x79 } }; + +// {D9CF88FF-AC2B-4a8a-8A50-DA0933A03792} +FOOGUIDDECL const GUID visualisation::class_guid = +{ 0xd9cf88ff, 0xac2b, 0x4a8a, { 0x8a, 0x50, 0xda, 0x9, 0x33, 0xa0, 0x37, 0x92 } }; + +// {A7E799BC-9774-41cf-8785-0D91634F937B} +FOOGUIDDECL const GUID packet_decoder::class_guid = +{ 0xa7e799bc, 0x9774, 0x41cf, { 0x87, 0x85, 0xd, 0x91, 0x63, 0x4f, 0x93, 0x7b } }; + +// {D3BD5F53-A6D6-4346-991F-CF14DFAD2B3A} +FOOGUIDDECL const GUID menu_manager::class_guid = +{ 0xd3bd5f53, 0xa6d6, 0x4346, { 0x99, 0x1f, 0xcf, 0x14, 0xdf, 0xad, 0x2b, 0x3a } }; + +// {61CF61E5-7C8E-469b-88E7-CE9B217DD38E} +FOOGUIDDECL const GUID menu_manager_defaults::class_guid = +{ 0x61cf61e5, 0x7c8e, 0x469b, { 0x88, 0xe7, 0xce, 0x9b, 0x21, 0x7d, 0xd3, 0x8e } }; + +// {640E006E-2934-4d6c-8327-4FA9F341ECF2} +FOOGUIDDECL const GUID input_file_type::class_guid = +{ 0x640e006e, 0x2934, 0x4d6c, { 0x83, 0x27, 0x4f, 0xa9, 0xf3, 0x41, 0xec, 0xf2 } }; + +// {B2518A41-A251-4941-9E28-BC51F7B840C3} +FOOGUIDDECL const GUID input_v2::class_guid = +{ 0xb2518a41, 0xa251, 0x4941, { 0x9e, 0x28, 0xbc, 0x51, 0xf7, 0xb8, 0x40, 0xc3 } }; + +// {2DEB68AB-49ED-460a-BFC0-4936AD39BA4F} +FOOGUIDDECL const GUID diskwriter::class_guid = +{ 0x2deb68ab, 0x49ed, 0x460a, { 0xbf, 0xc0, 0x49, 0x36, 0xad, 0x39, 0xba, 0x4f } }; + +// {8C6775A2-56FC-4a64-89F4-2609595C86A2} +FOOGUIDDECL const GUID ui_control::class_guid = +{ 0x8c6775a2, 0x56fc, 0x4a64, { 0x89, 0xf4, 0x26, 0x9, 0x59, 0x5c, 0x86, 0xa2 } }; + +// {52BD7A17-540C-4a97-B812-72BC84EC4FF5} +FOOGUIDDECL const GUID ui_drop_item_callback::class_guid = +{ 0x52bd7a17, 0x540c, 0x4a97, { 0xb8, 0x12, 0x72, 0xbc, 0x84, 0xec, 0x4f, 0xf5 } }; + +// {85605A78-101A-47cb-9541-4101EEBAC724} +FOOGUIDDECL const GUID track_indexer_v2::class_guid = +{ 0x85605a78, 0x101a, 0x47cb, { 0x95, 0x41, 0x41, 0x1, 0xee, 0xba, 0xc7, 0x24 } }; + +// {550B3A19-42A4-4c0f-91F2-90550189CBFF} +FOOGUIDDECL const GUID commandline_handler::class_guid = +{ 0x550b3a19, 0x42a4, 0x4c0f, { 0x91, 0xf2, 0x90, 0x55, 0x1, 0x89, 0xcb, 0xff } }; + +// {B92230CE-12A1-49f4-AFC7-3B5C57AD3760} +FOOGUIDDECL const GUID playback_flow_control::class_guid = +{ 0xb92230ce, 0x12a1, 0x49f4, { 0xaf, 0xc7, 0x3b, 0x5c, 0x57, 0xad, 0x37, 0x60 } }; + +// {7E82BE03-5956-412b-A9C4-6D1A3E2D7123} +FOOGUIDDECL const GUID playback_flow_control_v2::class_guid = +{ 0x7e82be03, 0x5956, 0x412b, { 0xa9, 0xc4, 0x6d, 0x1a, 0x3e, 0x2d, 0x71, 0x23 } }; + +// {8A17F5C7-0EA0-409c-93F6-3A2BF9CE65BF} +FOOGUIDDECL const GUID dsp_manager::class_guid = +{ 0x8a17f5c7, 0xea0, 0x409c, { 0x93, 0xf6, 0x3a, 0x2b, 0xf9, 0xce, 0x65, 0xbf } }; + +// {C71B99BD-12C5-48fe-A9C0-469F6FEA88BF} +FOOGUIDDECL const GUID modeless_dialog_manager::class_guid = +{ 0xc71b99bd, 0x12c5, 0x48fe, { 0xa9, 0xc0, 0x46, 0x9f, 0x6f, 0xea, 0x88, 0xbf } }; + +// {05C42951-1373-43ed-8F0C-F7B55D867868} +FOOGUIDDECL const GUID output_manager::class_guid = +{ 0x5c42951, 0x1373, 0x43ed, { 0x8f, 0xc, 0xf7, 0xb5, 0x5d, 0x86, 0x78, 0x68 } }; + +// {CF91D5CB-743B-401a-A8CC-E149F8944CCB} +FOOGUIDDECL const GUID play_callback::class_guid = +{ 0xcf91d5cb, 0x743b, 0x401a, { 0xa8, 0xcc, 0xe1, 0x49, 0xf8, 0x94, 0x4c, 0xcb } }; + +// {66E4FD37-5839-4233-A2D3-787E86A69011} +FOOGUIDDECL const GUID play_control::class_guid = +{ 0x66e4fd37, 0x5839, 0x4233, { 0xa2, 0xd3, 0x78, 0x7e, 0x86, 0xa6, 0x90, 0x11 } }; + +// {04AEC60C-BF22-46a6-B69E-BB8B4BE31AC2} +FOOGUIDDECL const GUID playback_core::class_guid = +{ 0x4aec60c, 0xbf22, 0x46a6, { 0xb6, 0x9e, 0xbb, 0x8b, 0x4b, 0xe3, 0x1a, 0xc2 } }; + +// {1673784D-E82E-4a70-8FFE-3D5613BD7C3C} +FOOGUIDDECL const GUID play_sound::class_guid = +{ 0x1673784d, 0xe82e, 0x4a70, { 0x8f, 0xfe, 0x3d, 0x56, 0x13, 0xbd, 0x7c, 0x3c } }; + +// {F384709D-7B49-472f-8D41-9D622877BA4E} +FOOGUIDDECL const GUID playlist_callback::class_guid = +{ 0xf384709d, 0x7b49, 0x472f, { 0x8d, 0x41, 0x9d, 0x62, 0x28, 0x77, 0xba, 0x4e } }; + +// {D2E5F92B-3424-4822-AE60-8663E6D26EAB} +FOOGUIDDECL const GUID playlist_loader::class_guid = +{ 0xd2e5f92b, 0x3424, 0x4822, { 0xae, 0x60, 0x86, 0x63, 0xe6, 0xd2, 0x6e, 0xab } }; + +// {95510C89-9968-4ebe-9968-5290CAAB39D2} +FOOGUIDDECL const GUID track_indexer::class_guid = +{ 0x95510c89, 0x9968, 0x4ebe, { 0x99, 0x68, 0x52, 0x90, 0xca, 0xab, 0x39, 0xd2 } }; + +// {2FBCE1E5-902E-49e0-B9CF-CE0FBA765348} +FOOGUIDDECL const GUID file::class_guid = +{ 0x2fbce1e5, 0x902e, 0x49e0, { 0xb9, 0xcf, 0xce, 0xf, 0xba, 0x76, 0x53, 0x48 } }; + +// {E84E9847-ADBB-447b-92F8-E9446EF2F427} +FOOGUIDDECL const GUID directory::class_guid = +{ 0xe84e9847, 0xadbb, 0x447b, { 0x92, 0xf8, 0xe9, 0x44, 0x6e, 0xf2, 0xf4, 0x27 } }; + +// {9098AF12-61A3-4caa-8AA9-BB95C2EF8346} +FOOGUIDDECL const GUID unpacker::class_guid = +{ 0x9098af12, 0x61a3, 0x4caa, { 0x8a, 0xa9, 0xbb, 0x95, 0xc2, 0xef, 0x83, 0x46 } }; + +// {EC707440-FA3E-4d12-9876-FC369F04D4A4} +FOOGUIDDECL const GUID archive::class_guid = +{ 0xec707440, 0xfa3e, 0x4d12, { 0x98, 0x76, 0xfc, 0x36, 0x9f, 0x4, 0xd4, 0xa4 } }; + +// {B2F9FC40-3E55-4b23-A2C9-22BAAD8795B1} +FOOGUIDDECL const GUID reader::class_guid = +{ 0xb2f9fc40, 0x3e55, 0x4b23, { 0xa2, 0xc9, 0x22, 0xba, 0xad, 0x87, 0x95, 0xb1 } }; + +// {C40598AA-089B-4c9f-AFCA-5FEE1CA1973D} +FOOGUIDDECL const GUID reader_dynamicinfo::class_guid = +{ 0xc40598aa, 0x89b, 0x4c9f, { 0xaf, 0xca, 0x5f, 0xee, 0x1c, 0xa1, 0x97, 0x3d } }; + +// {376B8EA5-DA53-4a83-881B-E92CF73D8D60} +FOOGUIDDECL const GUID reader_filetime::class_guid = +{ 0x376b8ea5, 0xda53, 0x4a83, { 0x88, 0x1b, 0xe9, 0x2c, 0xf7, 0x3d, 0x8d, 0x60 } }; + +// {A00CB77D-ED72-4031-806B-4E45AF995241} +FOOGUIDDECL const GUID replaygain::class_guid = +{ 0xa00cb77d, 0xed72, 0x4031, { 0x80, 0x6b, 0x4e, 0x45, 0xaf, 0x99, 0x52, 0x41 } }; + +// {3FEED4FC-A400-4a30-8E73-F0ECD114D7E8} +FOOGUIDDECL const GUID resampler::class_guid = +{ 0x3feed4fc, 0xa400, 0x4a30, { 0x8e, 0x73, 0xf0, 0xec, 0xd1, 0x14, 0xd7, 0xe8 } }; + +// {BB360EDA-1E11-4604-87FC-56CE6C249DD7} +FOOGUIDDECL const GUID tag_reader::class_guid = +{ 0xbb360eda, 0x1e11, 0x4604, { 0x87, 0xfc, 0x56, 0xce, 0x6c, 0x24, 0x9d, 0xd7 } }; + +// {2BE790FB-070F-4b96-BF68-DA579EACE69A} +FOOGUIDDECL const GUID tag_writer::class_guid = +{ 0x2be790fb, 0x70f, 0x4b96, { 0xbf, 0x68, 0xda, 0x57, 0x9e, 0xac, 0xe6, 0x9a } }; + +// {E434F1CA-92DA-482c-A76A-2129EE1CD2E3} +FOOGUIDDECL const GUID tag_remover::class_guid = +{ 0xe434f1ca, 0x92da, 0x482c, { 0xa7, 0x6a, 0x21, 0x29, 0xee, 0x1c, 0xd2, 0xe3 } }; + +// {3F7674AB-044C-4796-8801-6C443C244D88} +FOOGUIDDECL const GUID titleformat::class_guid = +{ 0x3f7674ab, 0x44c, 0x4796, { 0x88, 0x1, 0x6c, 0x44, 0x3c, 0x24, 0x4d, 0x88 } }; + +// {A2AC631F-38D0-46ee-B9B1-F1599DF02BB6} +FOOGUIDDECL const GUID user_interface::class_guid = +{ 0xa2ac631f, 0x38d0, 0x46ee, { 0xb9, 0xb1, 0xf1, 0x59, 0x9d, 0xf0, 0x2b, 0xb6 } }; + +// {8634CA5E-7CE1-419c-97C9-B47B5B6C538F} +FOOGUIDDECL const GUID playlist_switcher::class_guid = +{ 0x8634ca5e, 0x7ce1, 0x419c, { 0x97, 0xc9, 0xb4, 0x7b, 0x5b, 0x6c, 0x53, 0x8f } }; + +// {7F0FB76C-6BB7-4435-8337-8E7598F44BDA} +FOOGUIDDECL const GUID playlist_switcher_callback::class_guid = +{ 0x7f0fb76c, 0x6bb7, 0x4435, { 0x83, 0x37, 0x8e, 0x75, 0x98, 0xf4, 0x4b, 0xda } }; + +// {8CC36FD2-9BC6-46b9-A748-1568DE4CD602} +FOOGUIDDECL const GUID playlist_oper::class_guid = +{ 0x8cc36fd2, 0x9bc6, 0x46b9, { 0xa7, 0x48, 0x15, 0x68, 0xde, 0x4c, 0xd6, 0x2 } }; + +// {994C0D0E-319E-45f3-92FC-518616E73ADC} +FOOGUIDDECL const GUID menu_item::caller_now_playing = +{ 0x994c0d0e, 0x319e, 0x45f3, { 0x92, 0xfc, 0x51, 0x86, 0x16, 0xe7, 0x3a, 0xdc } }; + +// {47502BA1-816D-4a3e-ADE5-A7A9860A67DB} +FOOGUIDDECL const GUID menu_item::caller_playlist = +{ 0x47502ba1, 0x816d, 0x4a3e, { 0xad, 0xe5, 0xa7, 0xa9, 0x86, 0xa, 0x67, 0xdb } }; + +// {00000000-0000-0000-0000-000000000000} +FOOGUIDDECL const GUID menu_item::caller_undefined = +{ 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; + +// {79D28AA9-4E71-4b9b-98BA-36DB16593FDF} +FOOGUIDDECL const GUID menu_item_v2::class_guid = +{ 0x79d28aa9, 0x4e71, 0x4b9b, { 0x98, 0xba, 0x36, 0xdb, 0x16, 0x59, 0x3f, 0xdf } }; + +// {95DE5842-30F5-4f72-B40C-191663782F80} +FOOGUIDDECL const GUID keyboard_shortcut_manager::class_guid = +{ 0x95de5842, 0x30f5, 0x4f72, { 0xb4, 0xc, 0x19, 0x16, 0x63, 0x78, 0x2f, 0x80 } }; + +// {FF77A2C6-7ACD-483d-841C-A052E5CA5E03} +FOOGUIDDECL const GUID config_var::class_guid = +{ 0xff77a2c6, 0x7acd, 0x483d, { 0x84, 0x1c, 0xa0, 0x52, 0xe5, 0xca, 0x5e, 0x3 } }; + +// {30F95BEB-FDF4-4a75-B597-60CAF93B39C4} +FOOGUIDDECL const GUID packet_decoder::owner_MP4 = +{ 0x30f95beb, 0xfdf4, 0x4a75, { 0xb5, 0x97, 0x60, 0xca, 0xf9, 0x3b, 0x39, 0xc4 } }; + +// {5C2DE804-EAEE-4b8e-8C14-9207A2549BBE} +FOOGUIDDECL const GUID packet_decoder::owner_matroska = +{ 0x5c2de804, 0xeaee, 0x4b8e, { 0x8c, 0x14, 0x92, 0x7, 0xa2, 0x54, 0x9b, 0xbe } }; + +// {7B741A69-1AC7-440d-A01D-88536DD4DE1C} +FOOGUIDDECL const GUID packet_decoder::owner_MP3 = +{ 0x7b741a69, 0x1ac7, 0x440d, { 0xa0, 0x1d, 0x88, 0x53, 0x6d, 0xd4, 0xde, 0x1c } }; + +// {BC73F9FC-0107-480e-BF0E-BE58AF7AF328} +FOOGUIDDECL const GUID packet_decoder::property_samplerate = +{ 0xbc73f9fc, 0x107, 0x480e, { 0xbf, 0xe, 0xbe, 0x58, 0xaf, 0x7a, 0xf3, 0x28 } }; + +// {E5D19AAD-931B-48ac-AA6E-95E2C23BEC37} +FOOGUIDDECL const GUID packet_decoder::property_bitspersample = +{ 0xe5d19aad, 0x931b, 0x48ac, { 0xaa, 0x6e, 0x95, 0xe2, 0xc2, 0x3b, 0xec, 0x37 } }; + +// {1AFA1145-E774-4c26-91D6-3F5DD61E260E} +FOOGUIDDECL const GUID packet_decoder::property_channels = +{ 0x1afa1145, 0xe774, 0x4c26, { 0x91, 0xd6, 0x3f, 0x5d, 0xd6, 0x1e, 0x26, 0xe } }; + +// {29C556DA-065A-4d24-8A11-0F9DBC05A817} +FOOGUIDDECL const GUID packet_decoder::property_byteorder = +{ 0x29c556da, 0x65a, 0x4d24, { 0x8a, 0x11, 0xf, 0x9d, 0xbc, 0x5, 0xa8, 0x17 } }; + +// {0759C32F-E78E-4479-B0C0-B653DFA014D8} +FOOGUIDDECL const GUID packet_decoder::property_signed = +{ 0x759c32f, 0xe78e, 0x4479, { 0xb0, 0xc0, 0xb6, 0x53, 0xdf, 0xa0, 0x14, 0xd8 } }; + +// {646930F3-30AC-40e7-B7E4-EB7DFD2C0A47} +FOOGUIDDECL const GUID config_var_int::var_type = +{ 0x646930f3, 0x30ac, 0x40e7, { 0xb7, 0xe4, 0xeb, 0x7d, 0xfd, 0x2c, 0xa, 0x47 } }; + +// {335B8AA3-D05F-459a-A15C-115A3AEB2507} +FOOGUIDDECL const GUID config_var_struct_var_type = +{ 0x335b8aa3, 0xd05f, 0x459a, { 0xa1, 0x5c, 0x11, 0x5a, 0x3a, 0xeb, 0x25, 0x7 } }; + +// {FA9DA2B0-1F5E-42ab-866B-A567E1CE861B} +FOOGUIDDECL const GUID config_var_string::var_type = +{ 0xfa9da2b0, 0x1f5e, 0x42ab, { 0x86, 0x6b, 0xa5, 0x67, 0xe1, 0xce, 0x86, 0x1b } }; + +// {6F441057-1D18-4a58-9AC4-8F409CDA7DFD} +FOOGUIDDECL const GUID standard_commands::guid_context_file_properties = +{ 0x6f441057, 0x1d18, 0x4a58, { 0x9a, 0xc4, 0x8f, 0x40, 0x9c, 0xda, 0x7d, 0xfd } }; + +// {6F441057-1D18-4a58-9AC4-8F409CDA7DFD} +FOOGUIDDECL const GUID standard_commands::guid_context_file_open_directory = +{ 0x6f441057, 0x1d18, 0x4a58, { 0x9a, 0xc4, 0x8f, 0x40, 0x9c, 0xda, 0x7d, 0xfd } }; + +// {FFE18008-BCA2-4b29-AB88-8816B492C434} +FOOGUIDDECL const GUID standard_commands::guid_context_copy_names = +{ 0xffe18008, 0xbca2, 0x4b29, { 0xab, 0x88, 0x88, 0x16, 0xb4, 0x92, 0xc4, 0x34 } }; + +// {44B8F02B-5408-4361-8240-18DEC881B95E} +FOOGUIDDECL const GUID standard_commands::guid_context_send_to_playlist = +{ 0x44b8f02b, 0x5408, 0x4361, { 0x82, 0x40, 0x18, 0xde, 0xc8, 0x81, 0xb9, 0x5e } }; + +// {8C3BA2CB-BC4D-4752-8282-C6F9AED75A78} +FOOGUIDDECL const GUID standard_commands::guid_context_reload_info = +{ 0x8c3ba2cb, 0xbc4d, 0x4752, { 0x82, 0x82, 0xc6, 0xf9, 0xae, 0xd7, 0x5a, 0x78 } }; + +// {BD045EA4-E5E9-4206-8FF9-12AD9F5DCDE1} +FOOGUIDDECL const GUID standard_commands::guid_context_reload_info_if_changed = +{ 0xbd045ea4, 0xe5e9, 0x4206, { 0x8f, 0xf9, 0x12, 0xad, 0x9f, 0x5d, 0xcd, 0xe1 } }; + +// {684D9FBB-4383-44a2-9789-7EE1376209C6} +FOOGUIDDECL const GUID standard_commands::guid_context_rewrite_info = +{ 0x684d9fbb, 0x4383, 0x44a2, { 0x97, 0x89, 0x7e, 0xe1, 0x37, 0x62, 0x9, 0xc6 } }; + +// {860179B7-962F-4340-ACAD-0DDAF060A6B8} +FOOGUIDDECL const GUID standard_commands::guid_context_remove_tags = +{ 0x860179b7, 0x962f, 0x4340, { 0xac, 0xad, 0xd, 0xda, 0xf0, 0x60, 0xa6, 0xb8 } }; + +// {4DD1E1AD-F481-480c-BC3E-DD9C878EAFC3} +FOOGUIDDECL const GUID standard_commands::guid_context_remove_from_database = +{ 0x4dd1e1ad, 0xf481, 0x480c, { 0xbc, 0x3e, 0xdd, 0x9c, 0x87, 0x8e, 0xaf, 0xc3 } }; + +// {A7E7ECB7-1943-4907-83B3-60E92353C7FA} +FOOGUIDDECL const GUID standard_commands::guid_context_convert_run = +{ 0xa7e7ecb7, 0x1943, 0x4907, { 0x83, 0xb3, 0x60, 0xe9, 0x23, 0x53, 0xc7, 0xfa } }; + +// {A58AE6EA-A34F-4879-B25C-F31F2CBC4DA9} +FOOGUIDDECL const GUID standard_commands::guid_context_convert_run_singlefile = +{ 0xa58ae6ea, 0xa34f, 0x4879, { 0xb2, 0x5c, 0xf3, 0x1f, 0x2c, 0xbc, 0x4d, 0xa9 } }; + +// {A8EFA42D-76CB-42bc-8803-70516567B13D} +FOOGUIDDECL const GUID standard_commands::guid_context_write_cd = +{ 0xa8efa42d, 0x76cb, 0x42bc, { 0x88, 0x3, 0x70, 0x51, 0x65, 0x67, 0xb1, 0x3d } }; + +// {487DAED1-02FB-4336-A813-5E90317AB041} +FOOGUIDDECL const GUID standard_commands::guid_context_rg_scan_track = +{ 0x487daed1, 0x2fb, 0x4336, { 0xa8, 0x13, 0x5e, 0x90, 0x31, 0x7a, 0xb0, 0x41 } }; + +// {3850F34C-F619-4296-B8A0-26C617B1D16C} +FOOGUIDDECL const GUID standard_commands::guid_context_rg_scan_album = +{ 0x3850f34c, 0xf619, 0x4296, { 0xb8, 0xa0, 0x26, 0xc6, 0x17, 0xb1, 0xd1, 0x6c } }; + +// {6A2DBA02-260C-436f-8F41-0190A4298266} +FOOGUIDDECL const GUID standard_commands::guid_context_rg_scan_album_multi = +{ 0x6a2dba02, 0x260c, 0x436f, { 0x8f, 0x41, 0x1, 0x90, 0xa4, 0x29, 0x82, 0x66 } }; + +// {54C82A92-5824-4381-8D1B-79FBB1E2ABB8} +FOOGUIDDECL const GUID standard_commands::guid_context_rg_remove = +{ 0x54c82a92, 0x5824, 0x4381, { 0x8d, 0x1b, 0x79, 0xfb, 0xb1, 0xe2, 0xab, 0xb8 } }; + +// {69EAA594-13D9-4237-9BD7-11A39FDD1454} +FOOGUIDDECL const GUID standard_commands::guid_context_save_playlist = +{ 0x69eaa594, 0x13d9, 0x4237, { 0x9b, 0xd7, 0x11, 0xa3, 0x9f, 0xdd, 0x14, 0x54 } }; + +// {2BEB6836-C657-40ef-BB6E-D5B222AB89CE} +FOOGUIDDECL const GUID standard_commands::guid_context_masstag_edit = +{ 0x2beb6836, 0xc657, 0x40ef, { 0xbb, 0x6e, 0xd5, 0xb2, 0x22, 0xab, 0x89, 0xce } }; + +// {A579FF07-5D0B-48ed-A071-B6FCE4385AA9} +FOOGUIDDECL const GUID standard_commands::guid_context_masstag_rename = +{ 0xa579ff07, 0x5d0b, 0x48ed, { 0xa0, 0x71, 0xb6, 0xfc, 0xe4, 0x38, 0x5a, 0xa9 } }; + +// {77CFBCD0-98DC-4015-B327-D7142C664806} +FOOGUIDDECL const GUID standard_commands::guid_main_always_on_top = +{ 0x77cfbcd0, 0x98dc, 0x4015, { 0xb3, 0x27, 0xd7, 0x14, 0x2c, 0x66, 0x48, 0x6 } }; + +// {11213A01-9F36-4e69-A1BB-7A72F418DE3A} +FOOGUIDDECL const GUID standard_commands::guid_main_preferences = +{ 0x11213a01, 0x9f36, 0x4e69, { 0xa1, 0xbb, 0x7a, 0x72, 0xf4, 0x18, 0xde, 0x3a } }; + +// {EDA23441-5D38-4499-A22C-FE0CE0A987D9} +FOOGUIDDECL const GUID standard_commands::guid_main_about = +{ 0xeda23441, 0x5d38, 0x4499, { 0xa2, 0x2c, 0xfe, 0xc, 0xe0, 0xa9, 0x87, 0xd9 } }; + +// {6D38C73A-15D8-472c-8E68-6F946B82ECB4} +FOOGUIDDECL const GUID standard_commands::guid_main_exit = +{ 0x6d38c73a, 0x15d8, 0x472c, { 0x8e, 0x68, 0x6f, 0x94, 0x6b, 0x82, 0xec, 0xb4 } }; + +// {EF9B60FE-CB03-4c40-A8FD-3F1821020B37} +FOOGUIDDECL const GUID standard_commands::guid_main_restart = +{ 0xef9b60fe, 0xcb03, 0x4c40, { 0xa8, 0xfd, 0x3f, 0x18, 0x21, 0x2, 0xb, 0x37 } }; + +// {90500F09-F16F-415e-A047-AC5045C95FFE} +FOOGUIDDECL const GUID standard_commands::guid_main_activate = +{ 0x90500f09, 0xf16f, 0x415e, { 0xa0, 0x47, 0xac, 0x50, 0x45, 0xc9, 0x5f, 0xfe } }; + +// {13C17E8D-0D6F-41a4-B24A-59371043E925} +FOOGUIDDECL const GUID standard_commands::guid_main_hide = +{ 0x13c17e8d, 0xd6f, 0x41a4, { 0xb2, 0x4a, 0x59, 0x37, 0x10, 0x43, 0xe9, 0x25 } }; + +// {D9473FB2-BF11-4be0-972F-0E43F166A118} +FOOGUIDDECL const GUID standard_commands::guid_main_activate_or_hide = +{ 0xd9473fb2, 0xbf11, 0x4be0, { 0x97, 0x2f, 0xe, 0x43, 0xf1, 0x66, 0xa1, 0x18 } }; + +// {91E349DA-8800-42e5-BC8C-F3A92577AE84} +FOOGUIDDECL const GUID standard_commands::guid_main_titleformat_help = +{ 0x91e349da, 0x8800, 0x42e5, { 0xbc, 0x8c, 0xf3, 0xa9, 0x25, 0x77, 0xae, 0x84 } }; + +// {FBCFE01C-6C57-4e6a-A9F1-62334640DC91} +FOOGUIDDECL const GUID standard_commands::guid_main_follow_cursor = +{ 0xfbcfe01c, 0x6c57, 0x4e6a, { 0xa9, 0xf1, 0x62, 0x33, 0x46, 0x40, 0xdc, 0x91 } }; + +// {E58895A0-A2F0-45b6-8799-1440E4DB7284} +FOOGUIDDECL const GUID standard_commands::guid_main_next = +{ 0xe58895a0, 0xa2f0, 0x45b6, { 0x87, 0x99, 0x14, 0x40, 0xe4, 0xdb, 0x72, 0x84 } }; + +// {059C4566-4708-4ebf-8139-6A8EA5A9DFC8} +FOOGUIDDECL const GUID standard_commands::guid_main_previous = +{ 0x59c4566, 0x4708, 0x4ebf, { 0x81, 0x39, 0x6a, 0x8e, 0xa5, 0xa9, 0xdf, 0xc8 } }; + +// {18B1278A-F1BB-4b48-BC3D-6EC9EF80AD19} +FOOGUIDDECL const GUID standard_commands::guid_main_next_or_random = +{ 0x18b1278a, 0xf1bb, 0x4b48, { 0xbc, 0x3d, 0x6e, 0xc9, 0xef, 0x80, 0xad, 0x19 } }; + +// {42BDA765-30A8-40fa-BFA4-6A4E2F2B2CE9} +FOOGUIDDECL const GUID standard_commands::guid_main_random = +{ 0x42bda765, 0x30a8, 0x40fa, { 0xbf, 0xa4, 0x6a, 0x4e, 0x2f, 0x2b, 0x2c, 0xe9 } }; + +// {FCEF5262-7FA5-452e-A527-C14E0CB582DE} +FOOGUIDDECL const GUID standard_commands::guid_main_pause = +{ 0xfcef5262, 0x7fa5, 0x452e, { 0xa5, 0x27, 0xc1, 0x4e, 0xc, 0xb5, 0x82, 0xde } }; + +// {D3F83B15-D4AF-4586-8BD0-4EA415E31FE1} +FOOGUIDDECL const GUID standard_commands::guid_main_play = +{ 0xd3f83b15, 0xd4af, 0x4586, { 0x8b, 0xd0, 0x4e, 0xa4, 0x15, 0xe3, 0x1f, 0xe1 } }; + +// {8DEBC44E-EDA2-48d4-8696-31FC29D1F383} +FOOGUIDDECL const GUID standard_commands::guid_main_play_or_pause = +{ 0x8debc44e, 0xeda2, 0x48d4, { 0x86, 0x96, 0x31, 0xfc, 0x29, 0xd1, 0xf3, 0x83 } }; + +// {2DF17F25-80B9-4a43-B21D-620458FDDE1E} +FOOGUIDDECL const GUID standard_commands::guid_main_rg_set_album = +{ 0x2df17f25, 0x80b9, 0x4a43, { 0xb2, 0x1d, 0x62, 0x4, 0x58, 0xfd, 0xde, 0x1e } }; + +// {C26F1955-5753-4836-887F-84A563DD6DD9} +FOOGUIDDECL const GUID standard_commands::guid_main_rg_set_track = +{ 0xc26f1955, 0x5753, 0x4836, { 0x88, 0x7f, 0x84, 0xa5, 0x63, 0xdd, 0x6d, 0xd9 } }; + +// {8D2D808E-6AA2-455b-A2F1-CDB019328140} +FOOGUIDDECL const GUID standard_commands::guid_main_rg_disable = +{ 0x8d2d808e, 0x6aa2, 0x455b, { 0xa2, 0xf1, 0xcd, 0xb0, 0x19, 0x32, 0x81, 0x40 } }; + +// {C3378028-165F-4374-966C-2FA2E0FCD3A8} +FOOGUIDDECL const GUID standard_commands::guid_main_stop = +{ 0xc3378028, 0x165f, 0x4374, { 0x96, 0x6c, 0x2f, 0xa2, 0xe0, 0xfc, 0xd3, 0xa8 } }; + +// {EE057982-22F9-4862-A986-859E463316FB} +FOOGUIDDECL const GUID standard_commands::guid_main_stop_after_current = +{ 0xee057982, 0x22f9, 0x4862, { 0xa9, 0x86, 0x85, 0x9e, 0x46, 0x33, 0x16, 0xfb } }; + +// {11DC6526-73C4-44f0-91B1-DE5C2D26B0C7} +FOOGUIDDECL const GUID standard_commands::guid_main_volume_down = +{ 0x11dc6526, 0x73c4, 0x44f0, { 0x91, 0xb1, 0xde, 0x5c, 0x2d, 0x26, 0xb0, 0xc7 } }; + +// {A313E630-A04A-4ae8-B5B4-0A944AC964FF} +FOOGUIDDECL const GUID standard_commands::guid_main_volume_up = +{ 0xa313e630, 0xa04a, 0x4ae8, { 0xb5, 0xb4, 0xa, 0x94, 0x4a, 0xc9, 0x64, 0xff } }; + +// {4A36285B-B4AF-46ed-A1AA-6333057F485B} +FOOGUIDDECL const GUID standard_commands::guid_main_volume_mute = +{ 0x4a36285b, 0xb4af, 0x46ed, { 0xa1, 0xaa, 0x63, 0x33, 0x5, 0x7f, 0x48, 0x5b } }; + +// {2DC43C22-CA09-4ef9-A61E-7A0C1DAAE21E} +FOOGUIDDECL const GUID standard_commands::guid_main_add_directory = +{ 0x2dc43c22, 0xca09, 0x4ef9, { 0xa6, 0x1e, 0x7a, 0xc, 0x1d, 0xaa, 0xe2, 0x1e } }; + +// {FC89C278-4475-4853-96C9-F7F05E8CC837} +FOOGUIDDECL const GUID standard_commands::guid_main_add_files = +{ 0xfc89c278, 0x4475, 0x4853, { 0x96, 0xc9, 0xf7, 0xf0, 0x5e, 0x8c, 0xc8, 0x37 } }; + +// {9CA39D38-AC9B-4cca-B0CE-C0F62D188114} +FOOGUIDDECL const GUID standard_commands::guid_main_add_location = +{ 0x9ca39d38, 0xac9b, 0x4cca, { 0xb0, 0xce, 0xc0, 0xf6, 0x2d, 0x18, 0x81, 0x14 } }; + +// {73D6E69D-0DC9-4d5c-A7EE-FF4BE3896B08} +FOOGUIDDECL const GUID standard_commands::guid_main_add_playlist = +{ 0x73d6e69d, 0xdc9, 0x4d5c, { 0xa7, 0xee, 0xff, 0x4b, 0xe3, 0x89, 0x6b, 0x8 } }; + +// {55559142-7AEA-4c20-9B72-1D48E970A274} +FOOGUIDDECL const GUID standard_commands::guid_main_clear_playlist = +{ 0x55559142, 0x7aea, 0x4c20, { 0x9b, 0x72, 0x1d, 0x48, 0xe9, 0x70, 0xa2, 0x74 } }; + +// {BF72488F-36AC-46b3-A36D-193E60C79BC5} +FOOGUIDDECL const GUID standard_commands::guid_main_create_playlist = +{ 0xbf72488f, 0x36ac, 0x46b3, { 0xa3, 0x6d, 0x19, 0x3e, 0x60, 0xc7, 0x9b, 0xc5 } }; + +// {59E99BEE-42A3-4526-B06D-56C0C49F0BC1} +FOOGUIDDECL const GUID standard_commands::guid_main_highlight_playing = +{ 0x59e99bee, 0x42a3, 0x4526, { 0xb0, 0x6d, 0x56, 0xc0, 0xc4, 0x9f, 0xb, 0xc1 } }; + +// {D94393D4-9DBB-4e5c-BE8C-BE9CA80E214D} +FOOGUIDDECL const GUID standard_commands::guid_main_load_playlist = +{ 0xd94393d4, 0x9dbb, 0x4e5c, { 0xbe, 0x8c, 0xbe, 0x9c, 0xa8, 0xe, 0x21, 0x4d } }; + +// {EE1308C5-EBD2-48f1-959D-2627069C2E0F} +FOOGUIDDECL const GUID standard_commands::guid_main_next_playlist = +{ 0xee1308c5, 0xebd2, 0x48f1, { 0x95, 0x9d, 0x26, 0x27, 0x6, 0x9c, 0x2e, 0xf } }; + +// {486ECDA3-7BA2-49e9-BB44-4DB9DF9320C7} +FOOGUIDDECL const GUID standard_commands::guid_main_previous_playlist = +{ 0x486ecda3, 0x7ba2, 0x49e9, { 0xbb, 0x44, 0x4d, 0xb9, 0xdf, 0x93, 0x20, 0xc7 } }; + +// {69C778AA-B836-40a0-89CD-7A2E50C102CB} +FOOGUIDDECL const GUID standard_commands::guid_main_open = +{ 0x69c778aa, 0xb836, 0x40a0, { 0x89, 0xcd, 0x7a, 0x2e, 0x50, 0xc1, 0x2, 0xcb } }; + +// {EB7FB5A4-5904-4d2c-B66C-D882A3B15277} +FOOGUIDDECL const GUID standard_commands::guid_main_remove_playlist = +{ 0xeb7fb5a4, 0x5904, 0x4d2c, { 0xb6, 0x6c, 0xd8, 0x82, 0xa3, 0xb1, 0x52, 0x77 } }; + +// {C297BADB-8098-45a9-A5E8-B53A0D780CE3} +FOOGUIDDECL const GUID standard_commands::guid_main_remove_dead_entries = +{ 0xc297badb, 0x8098, 0x45a9, { 0xa5, 0xe8, 0xb5, 0x3a, 0xd, 0x78, 0xc, 0xe3 } }; + +// {D08C2921-7750-4979-98F9-3A513A31FF96} +FOOGUIDDECL const GUID standard_commands::guid_main_remove_duplicates = +{ 0xd08c2921, 0x7750, 0x4979, { 0x98, 0xf9, 0x3a, 0x51, 0x3a, 0x31, 0xff, 0x96 } }; + +// {D3A25E47-BA98-4e6b-95AD-A7502919EB75} +FOOGUIDDECL const GUID standard_commands::guid_main_rename_playlist = +{ 0xd3a25e47, 0xba98, 0x4e6b, { 0x95, 0xad, 0xa7, 0x50, 0x29, 0x19, 0xeb, 0x75 } }; + +// {0FDCFC65-9B39-445a-AA88-4D245F217480} +FOOGUIDDECL const GUID standard_commands::guid_main_save_all_playlists = +{ 0xfdcfc65, 0x9b39, 0x445a, { 0xaa, 0x88, 0x4d, 0x24, 0x5f, 0x21, 0x74, 0x80 } }; + +// {370B720B-4CF7-465b-908C-2D2ADD027900} +FOOGUIDDECL const GUID standard_commands::guid_main_save_playlist = +{ 0x370b720b, 0x4cf7, 0x465b, { 0x90, 0x8c, 0x2d, 0x2a, 0xdd, 0x2, 0x79, 0x0 } }; + +// {A6CFC2A8-56B3-4d12-88E7-0237961AC47E} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_search = +{ 0xa6cfc2a8, 0x56b3, 0x4d12, { 0x88, 0xe7, 0x2, 0x37, 0x96, 0x1a, 0xc4, 0x7e } }; + +// {383D4E8D-7E30-4fb8-B5DD-8C975D89E58E} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_sel_crop = +{ 0x383d4e8d, 0x7e30, 0x4fb8, { 0xb5, 0xdd, 0x8c, 0x97, 0x5d, 0x89, 0xe5, 0x8e } }; + +// {E0EEA319-E282-4e6c-8B82-4DFD42A1D4ED} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_sel_remove = +{ 0xe0eea319, 0xe282, 0x4e6c, { 0x8b, 0x82, 0x4d, 0xfd, 0x42, 0xa1, 0xd4, 0xed } }; + +// {F0845920-7F6D-40ac-B2EB-3D00C2C8260B} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_sel_invert = +{ 0xf0845920, 0x7f6d, 0x40ac, { 0xb2, 0xeb, 0x3d, 0x0, 0xc2, 0xc8, 0x26, 0xb } }; + +// {29910B33-79E9-40da-992B-5A4AA4281F78} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_undo = +{ 0x29910b33, 0x79e9, 0x40da, { 0x99, 0x2b, 0x5a, 0x4a, 0xa4, 0x28, 0x1f, 0x78 } }; + +// {02D89A8A-5F7D-41c3-A215-6731D8621036} +FOOGUIDDECL const GUID standard_commands::guid_main_show_console = +{ 0x2d89a8a, 0x5f7d, 0x41c3, { 0xa2, 0x15, 0x67, 0x31, 0xd8, 0x62, 0x10, 0x36 } }; + +// {E6970E91-33BE-4288-AC01-4B02F07B5D38} +FOOGUIDDECL const GUID standard_commands::guid_main_play_cd = +{ 0xe6970e91, 0x33be, 0x4288, { 0xac, 0x1, 0x4b, 0x2, 0xf0, 0x7b, 0x5d, 0x38 } }; + +// {1073AB1D-38ED-4957-8B06-38BC878C1F40} +FOOGUIDDECL const GUID standard_commands::guid_main_restart_resetconfig = +{ 0x1073ab1d, 0x38ed, 0x4957, { 0x8b, 0x6, 0x38, 0xbc, 0x87, 0x8c, 0x1f, 0x40 } }; + +// {FDC8A1C2-93EF-4415-8C20-60B6517F0B5F} +FOOGUIDDECL const GUID standard_commands::guid_main_record = +{ 0xfdc8a1c2, 0x93ef, 0x4415, { 0x8c, 0x20, 0x60, 0xb6, 0x51, 0x7f, 0xb, 0x5f } }; + +// {45EB37D2-3CD9-4f0a-9B20-8EAE649D7A9F} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_moveback = +{ 0x45eb37d2, 0x3cd9, 0x4f0a, { 0x9b, 0x20, 0x8e, 0xae, 0x64, 0x9d, 0x7a, 0x9f } }; + +// {02298938-596A-41f7-A398-19766A06E6EB} +FOOGUIDDECL const GUID standard_commands::guid_main_playlist_moveforward = +{ 0x2298938, 0x596a, 0x41f7, { 0xa3, 0x98, 0x19, 0x76, 0x6a, 0x6, 0xe6, 0xeb } }; + +// {DE5A47E0-28BE-4c49-BEEA-F0DE65C489A4} +FOOGUIDDECL const GUID playlist_loader_v2::class_guid= +{ 0xde5a47e0, 0x28be, 0x4c49, { 0xbe, 0xea, 0xf0, 0xde, 0x65, 0xc4, 0x89, 0xa4 } }; diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/initquit.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/initquit.h new file mode 100644 index 000000000..4e7fc3672 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/initquit.h @@ -0,0 +1,39 @@ +#ifndef _INITQUIT_H_ +#define _INITQUIT_H_ + +#include "service.h" + +//init/quit callback, on_init is called after main window has been created, on_quit is called before main window is destroyed +class NOVTABLE initquit : public service_base +{ +public: + virtual void on_init() {} + virtual void on_quit() {} + virtual void on_system_shutdown() {}//called instead of on_quit() when system is shutting down + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +template +class initquit_factory : public service_factory_single_t {}; + +class initquit_autoreg : public service_impl_single_t +{ +private: + service_factory_single_ref_t * p_factory; +public: + initquit_autoreg() {p_factory = new service_factory_single_ref_t(*this);} + ~initquit_autoreg() {delete p_factory;} +}; + +class initquit_simple : public initquit_autoreg +{ + void (*func)(bool is_init); + virtual void on_init() {func(true);} + virtual void on_quit() {func(false);} +public: + initquit_simple(void (*p_func)(bool is_init)) {func=p_func;} +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/input.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/input.cpp new file mode 100644 index 000000000..1f9b72c8b --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/input.cpp @@ -0,0 +1,497 @@ +#include "foobar2000.h" +#include + +input* input::g_open(reader * r,file_info * info,unsigned flags,__int64 * modtime,__int64 * filesize,bool * new_info) +{ + TRACK_CALL_TEXT("input::g_open"); + + service_enum_t e; + input * i; + const char * filename = info->get_file_path(); + + if (r)//check mime types first + { + string8 content_type; + if (r->get_content_type(content_type)) + { + for(i=e.first();i;i = e.next()) + { + if (i->needs_reader() && i->is_our_content_type(filename,content_type)) + { + if (i->open_ex(r,info,flags,modtime,filesize,new_info)) return i; + if (!r->seek(0)) {i->service_release(); return 0;} + } + i->service_release(); + } + } + } + + string_extension_8 extension(filename); + for(i=e.first();i;i = e.next()) + { + if (!!r == !!i->needs_reader()) + { + if (i->test_filename(filename,extension)) + { + if (i->open_ex(r,info,flags,modtime,filesize,new_info)) return i; + if (r) + { + if (!r->seek(0)) {i->service_release();return 0;} + } + } + } + i->service_release(); + } + return 0; +} + +static bool g_get_info_internal(unsigned flags,file_info * info,reader * r,__int64 * modtime,__int64 * filesize,bool * b_new_info) +{ + //return 0 on failure, 1 on success + bool my_reader = false; + const char * filename = info->get_file_path(); + string_extension_8 extension(filename); + bool rv = false; + + if (r==0) //try readerless inputs first + { + service_enum_t e; + input * i; + for(i=e.first();i;i = e.next()) + { + rv = false; + if (!i->needs_reader()) + { + if (i->test_filename(filename,extension)) + rv = i->open_ex(0,info,flags,modtime,filesize,b_new_info); + } + i->service_release(); + if (rv) return true; + } + + r = file::g_open(info->get_file_path(),reader::MODE_READ); + if (r==0) + { + return false; + } + my_reader = true; + } + + service_enum_t e; + input * i; + + {//check content type + string8 content_type; + if (r->get_content_type(content_type)) + { + for(i=e.first();i;i = e.next()) + { + rv = false; + if (i->needs_reader() && i->is_our_content_type(info->get_file_path(),content_type)) + { + if (!r->seek(0)) + { + i->service_release(); + if (my_reader) r->reader_release(); + return false; + } + rv = i->open_ex(r,info,flags,modtime,filesize,b_new_info); + } + i->service_release(); + if (rv) break; + } + } + } + + + if (!rv)//if no luck with content type, proceed with classic open method + { + for(i=e.first();i;i = e.next()) + { + rv = false; + if (i->needs_reader()) + { + if (!r->seek(0)) + { + i->service_release(); + if (my_reader) r->reader_release(); + return false; + } + if (i->test_filename(filename,extension)) + rv= i->open_ex(r,info,flags,modtime,filesize,b_new_info); + } + i->service_release(); + if (rv) break; + } + } + + if (my_reader) r->reader_release(); + + return rv; +} + +bool input::g_check_info(file_info * info,reader * r,__int64 * modtime,__int64 * filesize) +{ + if (modtime==0) return false; + __int64 time = *modtime; + __int64 size = -1; + bool new_info = false; + if (!g_get_info_internal(0,info,r,&time,&size,&new_info)) return false; + if (new_info) + { + *modtime = time; + *filesize = size; + return true; + } + return false; +} + +bool input::g_get_info(file_info * info,reader * r,__int64 * modtime,__int64 * filesize) +{ + return g_get_info_internal(OPEN_FLAG_GET_INFO,info,r,modtime,filesize,0); +} + +bool input::g_test_filename(const char * filename) +{ + service_enum_t e; + input * i; + string_extension_8 extension(filename); + for(i=e.first();i;i = e.next()) + { + bool rv = false; + rv = i->test_filename(filename,extension); + i->service_release(); + if (rv) return true; + } + return false; +} + +int input_pcm::run(audio_chunk * chunk) +{ + int bps,srate,nch; + void * source; + int size; + int rv = get_samples_pcm(&source,&size,&srate,&bps,&nch); + if (rv>0) chunk->set_data_fixedpoint(source,size,srate,nch,bps); + return rv; +} + +input::set_info_t input::g_set_info_readerless(const file_info * info,__int64 * modtime,__int64 * filesize) +{ + set_info_t rv = SET_INFO_FAILURE; + const char * filename = info->get_file_path(); + string_extension_8 extension(filename); + service_enum_t e; + input * i; + for(i=e.first();i;i = e.next()) + { + rv = SET_INFO_FAILURE; + if (!i->needs_reader()) + { + if (i->test_filename(filename,extension)) + rv = i->set_info_ex(0,info,modtime,filesize); + } + i->service_release(); + if (rv != SET_INFO_FAILURE) return rv; + } + return SET_INFO_FAILURE; +} + +input::set_info_t input::g_set_info_reader(const file_info * info,reader * r,__int64 * modtime,__int64 * filesize) +{ + const char * filename = info->get_file_path(); + string_extension_8 extension(filename); + set_info_t rv = SET_INFO_FAILURE; + + service_enum_t e; + input * i; + bool got_busy = false; + for(i=e.first();i;i = e.next()) + { + rv = SET_INFO_FAILURE; + if (i->needs_reader()) + { + r->seek(0); + if (i->test_filename(filename,extension)) + rv = i->set_info_ex(r,info,modtime,filesize); + } + i->service_release(); + if (rv==SET_INFO_SUCCESS) break; + else if (rv==SET_INFO_BUSY) got_busy = true; + } + + return rv == SET_INFO_SUCCESS ? SET_INFO_SUCCESS : got_busy ? SET_INFO_BUSY : SET_INFO_FAILURE; +} + + +input::set_info_t input::g_set_info(const file_info * info,reader * r,__int64 * modtime,__int64 * filesize) +{ + bool my_reader = false; + set_info_t rv = SET_INFO_FAILURE; + + if (r==0) + { + rv = g_set_info_readerless(info,modtime,filesize); + if (rv != SET_INFO_FAILURE) return rv; + + r = file::g_open(info->get_file_path(),reader::MODE_WRITE_EXISTING); + if (r==0) + { + int flags = file::g_exists(info->get_file_path()); + if (flags & file::FILE_EXISTS_WRITEABLE) return SET_INFO_BUSY; + else return SET_INFO_FAILURE; + } + my_reader = true; + } + + + rv = g_set_info_reader(info,r,modtime,filesize); + + if (my_reader) r->reader_release(); + + return rv; +} + + +bool input::is_entry_dead(const playable_location * entry) +{ + const char * path = entry->get_path(); + if (file::g_dont_read_infos(path)) return false; + int exists = file::g_exists(path); + if (exists) + { + return !g_test_filename(path); + } + else + { + //special fix to keep bloody flac tag updating hack from breaking things + //allow non-existent files ONLY when some readerless input accepts them and no reader-based inputs accept them + string_extension_8 extension(path); + service_enum_t e; + input * i; + bool found_reader = false, found_readerless = false; + for(i=e.first();i;i = e.next()) + { + if (i->test_filename(path,extension)) + { + if (i->needs_reader()) + found_reader = true; + else + found_readerless = true; + } + i->service_release(); + } + + return ! ( found_readerless && !found_reader ); + } +} + +bool input_test_filename_helper::test_filename(const char * filename) +{ + if (!inited) + { + service_enum_t e; + input * i; + for(i=e.first();i;i = e.next()) + inputs.add_item(i); + inited=true; + } + + string_extension_8 extension(filename); + + int n,m=inputs.get_count(); + for(n=0;ntest_filename(filename,extension)) return true; + } + return false; +} + +input_test_filename_helper::~input_test_filename_helper() +{ + unsigned n; + for(n=0;nservice_release(); + inputs.remove_all(); +} + +void input_file_type::build_openfile_mask(string_base & out, bool b_include_playlists) +{ + string8_fastalloc name,mask,mask_alltypes,out_temp; + + if (b_include_playlists) + { + playlist_loader * ptr; + service_enum_t e; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (!mask.is_empty()) mask += ";"; + mask += "*."; + mask += ptr->get_extension(); + } + out_temp += "Playlists"; + out_temp += "|"; + out_temp += mask; + out_temp += "|"; + + if (!mask_alltypes.is_empty()) + { + if (mask_alltypes[mask_alltypes.length()-1]!=';') + mask_alltypes += ";"; + } + mask_alltypes += mask; + } + + { + input_file_type * ptr; + service_enum_t e; + for(ptr=e.first();ptr;ptr=e.next()) + { + unsigned n,m = ptr->get_count(); + for(n=0;nget_name(n,name) && ptr->get_mask(n,mask)) + { + if (!strchr(name,'|') && !strchr(mask,'|')) + { + out_temp += name; + out_temp += "|"; + out_temp += mask; + out_temp += "|"; + if (!mask_alltypes.is_empty()) + { + if (mask_alltypes[mask_alltypes.length()-1]!=';') + mask_alltypes += ";"; + } + mask_alltypes += mask; + } + } + } + ptr->service_release(); + } + } + out.reset(); + out += "All files|*.*|"; + if (!mask_alltypes.is_empty()) + { + out += "All supported types|"; + out += mask_alltypes; + out += "|"; + } + out += out_temp; +} + +static bool open_ex_internal(input * i,reader * r,file_info * info,unsigned flags,__int64 * modtime,__int64 * filesize,bool * b_new_info) +{ + if (!!r != !!i->needs_reader()) return false; + if (r) + { + __int64 newmodtime; + __int64 newfilesize; + if (modtime) + { + newmodtime = r->get_modification_time(); + if (newmodtime != *modtime) flags |= input::OPEN_FLAG_GET_INFO; + } + if (filesize) + { + newfilesize = r->get_length(); + if (newfilesize != *filesize) flags |= input::OPEN_FLAG_GET_INFO; + } + + if (!(flags&(input::OPEN_FLAG_GET_INFO|input::OPEN_FLAG_DECODE))) return true; + + if (!i->open(r,info,flags)) return false; + + if (b_new_info && (flags & input::OPEN_FLAG_GET_INFO)) *b_new_info = true; + + if (filesize) *filesize = r->get_length(); + if (modtime) *modtime = newmodtime; + + return true; + } + else + { + + if (!i->open(0,info,flags)) return false; + + if (b_new_info && (flags & input::OPEN_FLAG_GET_INFO)) *b_new_info = true; + + if (filesize) *filesize = -1; + if (modtime) *modtime = 0; + + + + return true; + } +} + +bool input::open_ex(reader * r,file_info * info,unsigned flags,__int64 * modtime,__int64 * filesize,bool * b_new_info) +{ + { + input_v2 * this_v2 = service_query_t(input_v2,this); + if (this_v2) + { + bool rv = this_v2->open_ex(r,info,flags,modtime,filesize,b_new_info); + this_v2->service_release(); + return rv; + } + } + + return open_ex_internal(this,r,info,flags,modtime,filesize,b_new_info); +} + +bool input_v2::open_ex(reader * r,file_info * info,unsigned flags,__int64 * modtime,__int64 * filesize,bool * b_new_info) +{//to be overridden if needed (possibly needed for weird readerless inputs), this implementation is the default behavior + return open_ex_internal(this,r,info,flags,modtime,filesize,b_new_info); +} + +static input::set_info_t set_info_ex_internal(input * i,reader *r,const file_info * info,__int64 * modtime,__int64 * filesize) +{ + input::set_info_t rv = i->set_info(r,info); + if (r) + { + if (modtime) *modtime = r->get_modification_time(); + if (filesize) *filesize = r->get_length(); + } + else + { + if (modtime) *modtime = 0; + if (filesize) *filesize = -1; + } + return rv; +} + +input::set_info_t input::set_info_ex(reader *r,const file_info * info,__int64 * modtime,__int64 * filesize) +{ + { + input_v2 * this_v2 = service_query_t(input_v2,this); + if (this_v2) + { + set_info_t rv = this_v2->set_info_ex(r,info,modtime,filesize); + this_v2->service_release(); + return rv; + } + } + + return set_info_ex_internal(this,r,info,modtime,filesize); +} + +input::set_info_t input_v2::set_info_ex(reader *r,const file_info * info,__int64 * modtime,__int64 * filesize) +{ + return set_info_ex_internal(this,r,info,modtime,filesize); +} + +bool input::is_reopen_safe() +{ + bool rv = false; + input_v2 * this_v2 = service_query_t(input_v2,this); + if (this_v2) + { + rv = this_v2->is_reopen_safe(); + this_v2->service_release(); + } + return rv; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/input.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/input.h new file mode 100644 index 000000000..f166dd897 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/input.h @@ -0,0 +1,186 @@ +#ifndef _INPUT_H_ +#define _INPUT_H_ + +#include "service.h" + +#include "reader.h" +#include "file_info.h" + +#include "audio_chunk.h" + +/*************************** +how input class is used + + case 0: checking filename + create => test_filename() => destroy + + case 1: info reading + create => test_filename() => open(r,info,OPEN_FLAG_GET_INFO) => destroy + + case 2: playback + create => testfilename() => open(r,info,OPEN_FLAG_DECODE | [blah blah blah]) => run() .... => destroy + note: you must fill file_info stuff too if you get OPEN_FLAG_GET_INFO + + case 3: info writing + create => testfilename() => set_info(r,info) => destroy + + + there's no possibility of opening different files from the same input instance. + + when you get set_info() call, you have exclusive write access to the file; if user attempts to update currently played file, fb2k will wait until the file is free + + NOTE: when trying to decode unseekable source (reader->can_seek() returns 0), you should expect the reader you get to be able to seek back up to 64k + + + REMINDER: ALL strings are UTF-8 + + +***************************/ + +class NOVTABLE input : public service_base +{ +public: + enum + { + OPEN_FLAG_GET_INFO = 1,//if specified, you must pass all metadata/etc to file_info, otherwise you dont need to pass any data to file_info (but it wont blow up if you do, it will be just ignored) + OPEN_FLAG_DECODE = 2,//open for decoding + OPEN_FLAG_NO_SEEKING = 4,//when combined with OPEN_FLAG_DECODE, informs you that you don't need to be able to seek (still need to extract track length though) + OPEN_FLAG_NO_LOOPING = 8,//when combined with OPEN_FLAG_DECODE, you're being replaygainscanned or something, if your input can decode indefinitely, disable that + }; + + //you should expect either OPEN_FLAG_GET_INFO alone, or OPEN_FLAG_DECODE (possibly with modifiers), or both OPEN_FLAG_GET_INFO and OPEN_FLAG_DECODE (extract info and start decoding) + + enum set_info_t + { + SET_INFO_SUCCESS, + SET_INFO_FAILURE, + SET_INFO_BUSY, + }; + + virtual bool open(reader * r,file_info * info,unsigned flags)=0; + //caller is responsible for deleting the reader; reader pointer is valid until you get deleted; pass all your metadata/etc to info + //flags => see OPEN_FLAG_* above + //lazy solution: ignore flags, fill info and set up decoder + //somewhat more efficient solution: avoid either setting up decoder or filling info depending on flags + + virtual bool is_our_content_type(const char * url,const char * type) {return 0;}//for mime type checks, before test_filename + virtual bool test_filename(const char * full_path,const char * extension)=0; //perform extension/filename tests, return 1 if the file might be one of our types; do ONLY file extension checks etc, no opening; doesn't hurt if you return 1 for a file that doesn't actually belong to you + + + virtual set_info_t set_info(reader *r,const file_info * info)=0;//reader with exclusive write access + + virtual bool needs_reader() {return true;}//return if you read files or not (if you return 0, reader pointer in open/set_info will be null + virtual int run(audio_chunk * chunk)=0; + // return 1 on success, -1 on failure, 0 on EOF + + virtual bool seek(double seconds)=0;//return 1 on success, 0 on failure; if EOF, return 1 and return 0 in next run() pass + + virtual bool can_seek() {return true;}//return 0 if the file you're playing can't be seeked + + virtual void abort() {} //async call, abort current seek()/run(), ensure multithread safety on your side + + virtual bool get_dynamic_info(file_info * out, double * timestamp_delta,bool * b_track_change) {return false;} + //for dynamic song titles / VBR bitrate / etc + //out initially contains currently displayed info (either last get_dynamic_info result or current database info) + //timestamp_delta - you can use it to tell the core when this info should be displayed (in seconds, relative to first sample of last decoded chunk), initially set to 0 + //get_dynamic_info is called after each run() (or not called at all if caller doesn't care about dynamic info) + //return false to keep old info, or true to modify it + //set b_track_change to true if you want to indicate new song + //please keep in mind that updating dynamic info (returning true from this func) generates some overhead (mallocing to pass new info around, play_callback calls, GUI updates and titleformatting), ; if you implement useless features like realtime vbr bitrate display, make sure that they are optional and disabled by default + + static input* g_open(reader * r,file_info * info,unsigned flags,__int64 * modtime = 0,__int64 * filesize=0,bool * new_info=0); + static bool g_test_filename(const char * fn); + static bool g_get_info(file_info * info,reader * r = 0,__int64 * modtime = 0,__int64 * filesize=0); + static bool g_check_info(file_info * info,reader * r = 0,__int64 * modtime = 0,__int64 * filesize=0);//loads info if newer + static set_info_t g_set_info_readerless(const file_info * info,__int64 * modtime = 0,__int64 * filesize=0); + static set_info_t g_set_info_reader(const file_info * info,reader * r, __int64 * modtime = 0,__int64 * filesize=0); + static set_info_t g_set_info(const file_info * info,reader * r = 0,__int64 * modtime = 0,__int64 * filesize=0); + static bool is_entry_dead(const playable_location * entry);//tests if playlist_entry appears to be alive or not + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + bool open_ex(reader * r,file_info * info,unsigned flags,__int64 * modification_time,__int64 * file_size,bool * new_info); + set_info_t set_info_ex(reader *r,const file_info * info,__int64 * modtime,__int64 * filesize);//reader with exclusive write access + bool is_reopen_safe(); +}; + +class input_v2 : public input//extension for readerless operations in 0.8, to allow modification_time processing +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return input::service_query(guid); + } + + + //time is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601; 0 for invalid/unknown time + virtual bool open_ex(reader * r,file_info * info,unsigned flags,__int64 * modification_time,__int64 * file_size,bool * new_info); + //if modification_time pointer is null, open as usual + //otherwise, if file time is different than *modification_time, set *modification_time to modification time and proceed as if flags had OPEN_FLAG_GET_INFO + //if new_info pointer isnt null, set *new_info to true/false depending if you used OPEN_FLAG_GET_INFO + + virtual set_info_t set_info_ex(reader *r,const file_info * info,__int64 * modtime,__int64 * filesize);//reader with exclusive write access + + virtual bool get_album_art(const playable_location * src,reader * in,reader * out) {return false;};//reserved + + virtual bool is_reopen_safe() {return false;} + +}; + +template +class input_factory : public service_factory_t {}; + + +class input_file_type : public service_base +{ +public: + virtual unsigned get_count()=0; + virtual bool get_name(unsigned idx,string_base & out)=0;//e.g. "MPEG file" + virtual bool get_mask(unsigned idx,string_base & out)=0;//e.g. "*.MP3;*.MP2"; separate with semicolons + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + static void build_openfile_mask(string_base & out,bool b_include_playlists=true); +}; + +class input_file_type_i : public service_impl_single_t +{ + const char * name, * mask; +public: + virtual unsigned get_count() {return 1;} + input_file_type_i(const char * p_name, const char * p_mask) : name(p_name), mask(p_mask) {} + virtual bool get_name(unsigned idx,string_base & out) {if (idx==0) {out = name; return true;} else return false;} + virtual bool get_mask(unsigned idx,string_base & out) {if (idx==0) {out = mask; return true;} else return false;} +}; + +template +class input_file_type_factory : public service_factory_t {}; + +#define DECLARE_FILE_TYPE(NAME,MASK) \ + namespace { static input_file_type_i g_filetype_instance(NAME,MASK); \ + static service_factory_single_ref_t g_filetype_service(g_filetype_instance); } + + +//USAGE: DECLARE_FILE_TYPE("Blah file","*.blah;*.bleh"); + +#include "input_helpers.h" + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/input_helpers.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/input_helpers.cpp new file mode 100644 index 000000000..2d1b2efad --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/input_helpers.cpp @@ -0,0 +1,348 @@ +#include "foobar2000.h" + +input_helper::input_helper() +{ + seek_to = -1; + full_buffer_limit = 0; + p_input=0; + p_reader=0; + reader_overridden = false; + b_no_seek = false; + b_no_loop = false; + b_want_info = true; + b_aborting = false; +} + +input_helper::~input_helper() +{ + close(); +} + +bool input_helper::open_internal(file_info * info,reader * p_reader_override,__int64 *modification_time,__int64 * file_size,bool * new_info) +{ + TRACK_CALL_TEXT("input_helper::open_internal"); + + info->meta_remove_all(); + info->info_remove_all(); + + + if (attempt_reopen_internal(info,p_reader_override,modification_time,file_size,new_info)) + { + return true; + } + + const char * path = info->get_file_path();//file_info always has canonic path + + sync.enter(); + + close_input_internal(); + + sync.leave(); + + + if (p_reader_override) + { + sync.enter(); + close_reader_internal(); + override_reader(p_reader_override); + sync.leave(); + } + else if (p_reader && !stricmp_utf8(my_location.get_path(),path) && p_reader->can_seek()) + { + p_reader->seek(0); + } + else + { + sync.enter(); + close_reader_internal(); + sync.leave(); + } + + if (p_reader == 0) + { + input * p_input_temp = input::g_open(0,info,get_open_flags(),modification_time,file_size,new_info); + if (p_input_temp) + { + sync.enter(); + p_input = p_input_temp; + sync.leave(); + return true; + } + + sync.enter(); + + p_reader = file::g_get_reader(path); + + sync.leave(); + + if (p_reader==0) return false; + + if (p_reader->open(path,reader::MODE_READ)==0) {close();return false;} + + setup_fullbuffer(); + } + + + + { + input * temp = input::g_open(p_reader,info,get_open_flags(),modification_time,file_size,new_info); + if (temp) + { + sync.enter(); + p_input = temp; + sync.leave(); + } + else {close();return false;} + } + + my_location.copy(info->get_location()); + + seek_to = -1; + + return true; +} + +bool input_helper::open(file_info * info,reader * p_reader_override) +{ + b_want_info = true; + return open_internal(info,p_reader_override,0,0,0); +} + +bool input_helper::open_noinfo(file_info * info, reader * p_reader_override) +{ + b_want_info = false; + return open_internal(info,p_reader_override,0,0,0); +} + +bool input_helper::open(const playable_location * src,reader * p_reader_override) +{ + b_want_info = false; + file_info_i_full info(src); + return open_internal(&info,p_reader_override,0,0,0); +} + +bool input_helper::open(metadb_handle * p_handle, reader * p_reader_override) +{ + bool l_want_info = !p_handle->handle_query(0,true); + + __int64 time = p_handle->handle_get_modification_time(); + __int64 newtime = time; + __int64 file_size = p_handle->handle_get_file_size(); + bool b_new_info = false; + + b_want_info = l_want_info; + file_info_i_full info(p_handle->handle_get_location()); + bool rv = open_internal(&info,p_reader_override,&newtime,&file_size,&b_new_info); + if (rv) + { + if (b_new_info) p_handle->handle_hint_ex(&info,newtime,file_size,true); + } + else + { + if (input::is_entry_dead(p_handle->handle_get_location())) + p_handle->handle_entry_dead(); + } + return rv; +} + +void input_helper::close_input_internal() +{ + if (p_input) + { + p_input->service_release(); + p_input = 0; + } +} + +void input_helper::close_reader_internal() +{ + if (p_reader) + { + if (!reader_overridden) p_reader->service_release(); + p_reader=0; + reader_overridden = false; + } +} + + +void input_helper::close() +{ + TRACK_CALL_TEXT("input_helper::close"); + insync(sync); + close_input_internal(); + close_reader_internal(); +} + +bool input_helper::is_open() {return !!p_input;} + +int input_helper::run(audio_chunk * chunk)//fucko: syncing this will break abort +{ + chunk->reset(); + + if (p_input==0) return -1; + + if (seek_to>=0) + { + double target = seek_to; + seek_to = -1; + + { + TRACK_CALL_TEXT("input::seek"); + if (!p_input->seek(target)) return -1; + } + } + + int rv; + + { + TRACK_CALL_TEXT("input::seek::run"); + rv = p_input->run(chunk); + } + + if (rv>0 && !chunk->is_valid()) + { + console::error("input::run() produced invalid chunk:"); + console::info_location(&my_location); + chunk->reset(); + rv = -1; + } + + return rv; +} + +bool input_helper::seek(double seconds) +{ + insync(sync); + if (!p_input || b_no_seek) return false; + seek_to = seconds; + return true; +} + +bool input_helper::can_seek() +{ + insync(sync); + return p_input ? p_input->can_seek() : 0; +} + +void input_helper::abort() +{ + TRACK_CALL_TEXT("input_helper::abort"); + insync(sync); + b_aborting = true; + if (p_reader) p_reader->abort(); + if (p_input) p_input->abort(); +} + +void input_helper::on_idle() +{ + insync(sync); + if (p_reader) p_reader->on_idle(); +} + +bool input_helper::get_dynamic_info(file_info * out,double * timestamp_delta, bool * b_track_change) +{ + TRACK_CALL_TEXT("input_helper::get_dynamic_info"); + insync(sync); + return p_input ? p_input->get_dynamic_info(out,timestamp_delta,b_track_change) : false; +} + +bool input_helper::attempt_reopen_internal(file_info * info,reader * p_reader_override,__int64 * modification_time,__int64* file_size,bool * new_info) +{ + TRACK_CALL_TEXT("input_helper::attempt_reopen_internal"); + assert(sync.get_lock_count_check()==0); + const char * path = info->get_file_path(); + + bool b_reopen_available,b_same_file; + sync.enter(); + b_same_file = p_input && !p_reader_override && my_location.compare(info->get_location())==0 && p_input->can_seek(); + if (!b_same_file) + b_reopen_available = !(!p_input || (p_reader_override && !p_reader) || !p_input->is_reopen_safe() || !p_input->test_filename(path,string_extension(path))); + sync.leave(); + if (b_same_file && !b_want_info) + { + return p_input->seek(0); + } + else if (!b_reopen_available) return false; + + if (p_reader_override) + {//caller wants us to get their reader + sync.enter(); + close_reader_internal(); + override_reader(p_reader_override); + sync.leave(); + } + else if (p_reader && !stricmp_utf8(my_location.get_path(),path) && p_reader->can_seek()) + {//same file + p_reader->seek(0); + } + else if (p_reader) + {//different file + sync.enter(); + close_reader_internal(); + p_reader = file::g_get_reader(path); + sync.leave(); + if (p_reader==0) return false; + if (p_reader->open(path,reader::MODE_READ) == 0) + { + sync.enter(); + close_reader_internal(); + sync.leave(); + return false; + } + setup_fullbuffer(); + } + //else must be readerless input + + if (p_input->open_ex(p_reader,info,get_open_flags(),modification_time,file_size,new_info)) + { + my_location.copy(info->get_location()); + return true; + } + else return false; +} + +void input_helper::override_reader(reader* p_reader_override) +{ + assert(sync.get_lock_count_check()>0); + assert(p_reader == 0); + p_reader = p_reader_override; + reader_overridden = !!p_reader_override; +} + +void input_helper::setup_fullbuffer() +{ + assert(p_reader); + assert(sync.get_lock_count_check()==0); + if (full_buffer_limit>0) + { + __int64 size = p_reader->get_length(); + if (size>0 && size<=full_buffer_limit) + { + reader * temp = reader_membuffer::create(p_reader,p_reader->get_modification_time()); + if (temp) + { + sync.enter(); + p_reader->service_release(); + p_reader = temp; + sync.leave(); + } + } + } +} + + +unsigned input_helper::get_open_flags() +{ + return input::OPEN_FLAG_DECODE | (b_want_info ? input::OPEN_FLAG_GET_INFO : 0) | (b_no_seek ? input::OPEN_FLAG_NO_SEEKING : 0) | (b_no_loop ? input::OPEN_FLAG_NO_LOOPING : 0); +} + +void input_helper::override(const playable_location * new_location,input * new_input,reader * new_reader) +{ + insync(sync); + close(); + if (new_location) my_location.copy(new_location); + else my_location.copy(make_playable_location("UNKNOWN",0)); + p_input = new_input; + p_reader = new_reader; + seek_to = -1; +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/input_helpers.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/input_helpers.h new file mode 100644 index 000000000..b76e3e0ba --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/input_helpers.h @@ -0,0 +1,82 @@ +#ifndef _INPUT_HELPERS_H_ +#define _INPUT_HELPERS_H_ + +#include "input.h" + +class NOVTABLE input_pcm : public input +{ +public: + virtual int run(audio_chunk * chunk); +protected: + virtual int get_samples_pcm(void ** buffer,int * size,int * srate,int * bps,int * nch)=0;//same return value as input::run() +}; + +class input_helper//takes care of opening inputs etc +{ +private: + critical_section sync; + playable_location_i my_location; + input * p_input; + reader * p_reader; + __int64 full_buffer_limit; + bool b_aborting; + bool reader_overridden; + bool b_no_seek,b_no_loop,b_want_info; + double seek_to; + + bool open_file_internal(const char * path,reader * p_reader_override); + bool attempt_reopen_internal(file_info * info,reader * p_reader_override,__int64 * modtime,__int64* filesize,bool * new_info); + bool open_internal(file_info * info,reader * p_reader_override,__int64 * modtime,__int64* filesize,bool * new_info); + void close_input_internal(); + void close_reader_internal(); + void override_reader(reader*); + void setup_fullbuffer(); + unsigned get_open_flags(); +public: + input_helper(); + ~input_helper(); + bool open(file_info * info,reader * p_reader_override = 0); + bool open_noinfo(file_info * info, reader * p_reader_override=0); + bool open(const playable_location * src,reader * p_reader_override = 0);//helper + inline bool open(const char * path,reader * p_reader_override = 0) + {return open(make_playable_location(path,0),p_reader_override);} + + bool open(class metadb_handle * p_handle, reader * p_reader_override=0); + + + + + void override(const playable_location * new_location,input * new_input,reader * new_reader); + + void close(); + bool is_open(); + int run(audio_chunk * chunk); + bool seek(double seconds); + bool can_seek(); + void abort(); + void set_full_buffer(__int64 val) {full_buffer_limit = val;}//default 0 to disable, any positive value to set upper file size limit for full file buffering + void on_idle(); + bool get_dynamic_info(file_info * out,double *timestamp_delta,bool *b_track_change); + + //call these before opening + inline void hint_no_seeking(bool state) {b_no_seek = state;} + inline void hint_no_looping(bool state) {b_no_loop = state;} + + bool open_errorhandled(class metadb_handle * p_handle, reader * p_reader_override=0); + int run_errorhandled(audio_chunk * chunk); + bool seek_errorhandled(double seconds); + void close_errorhandled(); +}; + +class input_test_filename_helper//avoids bloody bottleneck with creating inputs when mass-testing filenames +{ + ptr_list_t inputs; + bool inited; +public: + inline input_test_filename_helper() {inited=false;} + + bool test_filename(const char * filename); + ~input_test_filename_helper(); +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/interface_helper.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/interface_helper.h new file mode 100644 index 000000000..9bc3c8a36 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/interface_helper.h @@ -0,0 +1,12 @@ +#ifndef _PTR_LIST_INTERFACE_H_ +#define _PTR_LIST_INTERFACE_H_ + +#include "../../pfc/pfc.h" + + +//DEPRECATED (wheee) + +#define make_string_interface(blah) blah; + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_item.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_item.h new file mode 100644 index 000000000..6e7dd7f67 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_item.h @@ -0,0 +1,178 @@ +#ifndef _FOOBAR2000_MENU_ITEM_H_ +#define _FOOBAR2000_MENU_ITEM_H_ + +#include "service.h" +#include "interface_helper.h" +#include "metadb_handle.h" + +class NOVTABLE menu_item : public service_base +{ +public: + enum type + { + TYPE_MAIN, + TYPE_CONTEXT, + }; + + enum enabled_state + { + DEFAULT_OFF, + DEFAULT_ON, + FORCE_ON, + FORCE_OFF, + }; + + enum + { + FLAG_CHECKED = 1, + FLAG_DISABLED = 2, + FLAG_GRAYED = 4, + FLAG_DISABLED_GRAYED = FLAG_DISABLED|FLAG_GRAYED, + }; + + virtual enabled_state get_enabled_state(unsigned idx) {return DEFAULT_ON;}//return if menu item should be enabled by default or not + + virtual type get_type()=0; + virtual unsigned get_num_items()=0; + virtual void enum_item(unsigned n,string_base & out)=0;//return full formal name, like "playback/play", 0<=n & data,string_base & out,unsigned & displayflags)=0;//displayflags - see FLAG_* above; displayflags are set to 0 before calling + virtual void perform_command(unsigned n,const ptr_list_base & data)=0; + + virtual bool get_description(unsigned n,string_base & out) {return false;} + + virtual void * get_glyph(unsigned n) {return 0;}//RESERVED, do not override + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + static const GUID caller_now_playing; + static const GUID caller_playlist; + static const GUID caller_undefined; + + bool get_display_data(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags,const GUID & caller); + void perform_command(unsigned n,const ptr_list_base & data,const GUID & caller); + bool enum_item_guid(unsigned n,GUID & out); +}; + +class NOVTABLE menu_item_v2 : public menu_item +{ + virtual bool get_display_data(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags) + {return get_display_data(n,data,out,displayflags,caller_undefined);} + virtual void perform_command(unsigned n,const ptr_list_base & data) + {perform_command(n,data,caller_undefined);} +public: + virtual bool get_display_data(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags,const GUID & caller)=0; + virtual void perform_command(unsigned n,const ptr_list_base & data,const GUID & caller)=0; + virtual bool enum_item_guid(unsigned n,GUID & out) {return false;}//returns false if item doesnt have a GUID + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return menu_item::service_query(guid); + } +}; + +class NOVTABLE menu_item_main : public menu_item_v2 +{ + virtual type get_type() {return TYPE_MAIN;} + + virtual bool get_display_data(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags,const GUID & caller) + { + assert(n>=0 && n & data,const GUID & caller) {perform_command(n);} +protected: + //override these + virtual unsigned get_num_items()=0; + virtual void enum_item(unsigned n,string_base & out)=0; + virtual void perform_command(unsigned n)=0; + virtual bool is_checked(unsigned n) {return false;} + virtual bool is_disabled(unsigned n) {return false;} + virtual bool is_available(unsigned n) {return true;} + virtual bool get_description(unsigned n,string_base & out) {return false;} +}; + +class NOVTABLE menu_item_main_single : public menu_item_main //helper +{ + virtual unsigned get_num_items() {return 1;} + virtual void enum_item(unsigned n,string_base & out) + { + if (n==0) get_name(out); + } + virtual void perform_command(unsigned n) + { + if (n==0) run(); + } + virtual bool is_checked(unsigned n) {assert(n==0); return is_checked();}; + virtual bool is_disabled(unsigned n) {assert(n==0); return is_disabled();} + virtual bool get_description(unsigned n,string_base & out) {assert(n==0); return get_description(out);} +protected://override these + virtual void get_name(string_base & out)=0; + virtual void run()=0; + virtual bool is_checked() {return false;} + virtual bool is_disabled() {return false;} + virtual bool get_description(string_base & out) {return false;} +}; + +class NOVTABLE menu_item_context : public menu_item_v2 +{ + virtual type get_type() {return TYPE_CONTEXT;} + virtual bool get_display_data(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags,const GUID & caller) + { + bool rv = false; + assert(n>=0 && n0) + { + rv = context_get_display(n,data,out,displayflags,caller); + } + return rv; + } + virtual void perform_command(unsigned n,const ptr_list_base & data,const GUID & caller) + { + if (data.get_count()>0) context_command(n,data,caller); + } + virtual bool is_checked(unsigned n,const ptr_list_base & data) {return false;} +protected: + //override these + virtual unsigned get_num_items()=0; + virtual void enum_item(unsigned n,string_base & out)=0; + virtual void context_command(unsigned n,const ptr_list_base & data,const GUID& caller)=0; + virtual bool context_get_display(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags,const GUID &) + { + assert(n>=0 && n +class menu_item_factory : public service_factory_single_t {}; + + +#endif //_FOOBAR2000_MENU_ITEM_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_manager.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_manager.cpp new file mode 100644 index 000000000..101bd1d8d --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_manager.cpp @@ -0,0 +1,632 @@ +#include "foobar2000.h" + +#ifdef WIN32 + +static void fix_ampersand(const char * src,string_base & out) +{ + unsigned ptr = 0; + while(src[ptr]) + { + if (src[ptr]=='&') + { + out.add_string("&&"); + ptr++; + while(src[ptr]=='&') + { + out.add_string("&&"); + ptr++; + } + } + else out.add_byte(src[ptr++]); + } +} + +static unsigned flags_to_win32(unsigned flags) +{ + unsigned ret = 0; + if (flags & menu_item::FLAG_CHECKED) ret |= MF_CHECKED; + if (flags & menu_item::FLAG_DISABLED) ret |= MF_DISABLED; + if (flags & menu_item::FLAG_GRAYED) ret |= MF_GRAYED; + return ret; +} + +void menu_manager::win32_build_menu(HMENU menu,menu_node * parent,int base_id,int max_id)//menu item identifiers are base_id<=Nget_type()==menu_node::TYPE_POPUP) + { + string8_fastalloc temp; + int child_idx,child_num = parent->get_num_children(); + for(child_idx=0;child_idxget_child(child_idx); + if (child) + { + const char * name = child->get_name(); + if (strchr(name,'&')) {fix_ampersand(name,temp);name=temp;} + menu_node::type type = child->get_type(); + if (type==menu_node::TYPE_POPUP) + { + HMENU new_menu = CreatePopupMenu(); + uAppendMenu(menu,MF_STRING|MF_POPUP | flags_to_win32(child->get_display_flags()),(UINT)new_menu,name); + win32_build_menu(new_menu,child,base_id,max_id); + } + else if (type==menu_node::TYPE_SEPARATOR) + { + uAppendMenu(menu,MF_SEPARATOR,0,0); + } + else if (type==menu_node::TYPE_COMMAND) + { + int id = child->get_id(); + if (id>=0 && (max_id<0 || idget_display_flags()),base_id+id,name); + } + } + } + } + } +} + +#endif + +static bool run_command_internal(menu_item::type type,const char * name,const ptr_list_base & data,const GUID & caller) +{ + service_enum_t e; + menu_item * ptr; + bool done = false; + string8_fastalloc action_name; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==type) + { + unsigned action,num_actions = ptr->get_num_items(); + for(action=0;actionenum_item(action,action_name); + if (!stricmp_utf8(name,action_name)) + { + TRACK_CALL_TEXT(uStringPrintf("menu_manager::run_command()/\"%s\"",action_name.get_ptr())); + ptr->perform_command(action,data,caller); + done = true; + break; + } + } + } + ptr->service_release(); + if (done) break; + } + return done; +} + +static bool run_command_internal(menu_item::type type,const GUID & guid,const ptr_list_base & data,const GUID & caller) +{ + service_enum_t e; + menu_item * ptr; + bool done = false; + GUID action_guid; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==type) + { + unsigned action,num_actions = ptr->get_num_items(); + for(action=0;actionenum_item_guid(action,action_guid)) + { + if (action_guid == guid) + { + TRACK_CALL_TEXT("menu_manager::run_command(), by GUID"); + ptr->perform_command(action,data,caller); + done = true; + break; + } + } + } + } + ptr->service_release(); + if (done) break; + } + return done; +} + +bool menu_manager::run_command(const GUID & guid) +{ + return run_command_internal(menu_item::TYPE_MAIN,guid,ptr_list_t(),menu_item::caller_undefined); +} + +bool menu_manager::run_command_context(const GUID & guid,const ptr_list_base & data) +{ + return run_command_internal(menu_item::TYPE_CONTEXT,guid,data,menu_item::caller_undefined); +} + +bool menu_manager::run_command_context_ex(const GUID & guid,const ptr_list_base & data,const GUID & caller) +{ + return run_command_internal(menu_item::TYPE_CONTEXT,guid,data,caller); +} + + +bool menu_manager::run_command(const char * name) +{ + return run_command_internal(menu_item::TYPE_MAIN,name,ptr_list_t(),menu_item::caller_undefined); +} + +bool menu_manager::run_command_context_ex(const char * name,const ptr_list_base & data,const GUID & caller) +{ + return run_command_internal(menu_item::TYPE_CONTEXT,name,data,caller); +} + +bool menu_manager::run_command_context(const char * name,const ptr_list_base &data) +{ + return run_command_internal(menu_item::TYPE_CONTEXT,name,data,menu_item::caller_undefined); +} + +bool menu_manager::run_command_context_playlist(const char * name) +{ + metadb_handle_list temp; + playlist_oper::get()->get_sel_items(temp); + bool rv = run_command_context_ex(name,temp,menu_item::caller_playlist); + temp.delete_all(); + return rv; +} + + +static bool g_test_command(const char * name,menu_item::type m_type) +{ + service_enum_t e; + menu_item * ptr; + bool done = false; + string8_fastalloc action_name; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==m_type) + { + unsigned action,num_actions = ptr->get_num_items(); + for(action=0;actionenum_item(action,action_name); + if (!stricmp_utf8(name,action_name)) + { + done = true; + break; + } + } + } + ptr->service_release(); + if (done) break; + } + return done; +} + +bool menu_manager::test_command(const char * name) +{ + return g_test_command(name,menu_item::TYPE_MAIN); +} + +bool menu_manager::test_command_context(const char * name) +{ + return g_test_command(name,menu_item::TYPE_CONTEXT); +} + +static bool g_is_checked(const char * name,menu_item::type type, const ptr_list_base & data,const GUID & caller) +{ + service_enum_t e; + menu_item * ptr; + bool done = false, rv = false; + string8_fastalloc dummystring,action_name; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==type) + { + unsigned action,num_actions = ptr->get_num_items(); + for(action=0;actionenum_item(action,action_name); + if (!stricmp_utf8(name,action_name)) + { + unsigned displayflags = 0; + if (ptr->get_display_data(action,data,dummystring,displayflags,caller)) + { + rv = !!(displayflags & menu_item::FLAG_CHECKED); + done = true; + break; + } + } + } + } + ptr->service_release(); + if (done) break; + } + return rv; +} + +static bool g_is_checked(const GUID & guid,menu_item::type type, const ptr_list_base & data,const GUID & caller) +{ + service_enum_t e; + menu_item * ptr; + bool done = false, rv = false; + string8_fastalloc dummystring; + GUID action_guid; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==type) + { + unsigned action,num_actions = ptr->get_num_items(); + for(action=0;actionenum_item_guid(action,action_guid)) + { + if (action_guid == guid) + { + unsigned displayflags = 0; + if (ptr->get_display_data(action,data,dummystring,displayflags,caller)) + { + rv = !!(displayflags & menu_item::FLAG_CHECKED); + done = true; + break; + } + } + } + } + } + ptr->service_release(); + if (done) break; + } + return rv; +} + +bool menu_manager::is_command_checked(const GUID & guid) +{ + return g_is_checked(guid,menu_item::TYPE_MAIN,ptr_list_t(),menu_item::caller_undefined); +} + +bool menu_manager::is_command_checked(const char * name) +{ + return g_is_checked(name,menu_item::TYPE_MAIN,ptr_list_t(),menu_item::caller_undefined); +} + +bool menu_manager::is_command_checked_context(const GUID & guid,metadb_handle_list & data) +{ + return g_is_checked(guid,menu_item::TYPE_MAIN,data,menu_item::caller_undefined); +} + +bool menu_manager::is_command_checked_context(const char * name,metadb_handle_list & data) +{ + return g_is_checked(name,menu_item::TYPE_MAIN,data,menu_item::caller_undefined); +} + +bool menu_manager::is_command_checked_context_playlist(const GUID & guid) +{ + bool rv; + metadb_handle_list temp; + playlist_oper::get()->get_data(temp); + rv = g_is_checked(guid,menu_item::TYPE_MAIN,temp,menu_item::caller_playlist); + temp.delete_all(); + return rv; +} + +bool menu_manager::is_command_checked_context_playlist(const char * name) +{ + bool rv; + metadb_handle_list temp; + playlist_oper::get()->get_data(temp); + rv = g_is_checked(name,menu_item::TYPE_MAIN,temp,menu_item::caller_playlist); + temp.delete_all(); + return rv; +} + +bool menu_manager::execute_by_id(unsigned id) +{ + bool rv = false; + menu_node * ptr = find_by_id(id); + if (ptr) {rv=true;ptr->execute();} + return rv; +} + +#ifdef WIN32 + +void menu_manager::win32_run_menu_popup(HWND parent,const POINT * pt) +{ + enum {ID_CUSTOM_BASE = 1}; + + int cmd; + + { + POINT p; + if (pt) p = *pt; + else GetCursorPos(&p); + HMENU hmenu = CreatePopupMenu(); + + v_win32_build_menu(hmenu,ID_CUSTOM_BASE,-1); + v_win32_auto_mnemonics(hmenu); + + cmd = TrackPopupMenu(hmenu,TPM_RIGHTBUTTON|TPM_NONOTIFY|TPM_RETURNCMD,p.x,p.y,0,parent,0); + + DestroyMenu(hmenu); + } + + if (cmd>0) + { + if (cmd>=ID_CUSTOM_BASE) + { + execute_by_id(cmd - ID_CUSTOM_BASE); + } + } +} + +void menu_manager::win32_run_menu_context(HWND parent,const metadb_handle_list & data,const POINT * pt,unsigned flags) +{ + menu_manager * p_manager = menu_manager::create(); + p_manager->init_context(data,flags); + p_manager->win32_run_menu_popup(parent,pt); + p_manager->service_release(); +} + +void menu_manager::win32_run_menu_context_playlist(HWND parent,const POINT * pt,unsigned flags) +{ + menu_manager * p_manager = menu_manager::create(); + p_manager->init_context_playlist(flags); + p_manager->win32_run_menu_popup(parent,pt); + p_manager->service_release(); +} + +void menu_manager::win32_run_menu_main(HWND parent,const char * path,const POINT * pt,unsigned flags) +{ + menu_manager * p_manager = menu_manager::create(); + p_manager->init_main(path,flags); + p_manager->win32_run_menu_popup(parent,pt); + p_manager->service_release(); +} + +namespace { + class mnemonic_manager + { + string8_fastalloc used; + bool is_used(unsigned c) + { + char temp[8]; + temp[utf8_encode_char(char_lower(c),temp)]=0; + return !!strstr(used,temp); + } + + static bool is_alphanumeric(char c) + { + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'); + } + + + + + void insert(const char * src,unsigned idx,string_base & out) + { + out.reset(); + out.add_string(src,idx); + out.add_string("&"); + out.add_string(src+idx); + used.add_char(char_lower(src[idx])); + } + public: + bool check_string(const char * src) + {//check for existing mnemonics + const char * ptr = src; + while(ptr = strchr(ptr,'&')) + { + if (ptr[1]=='&') ptr+=2; + else + { + unsigned c = 0; + if (utf8_decode_char(ptr+1,&c)>0) + { + if (!is_used(c)) used.add_char(char_lower(c)); + } + return true; + } + } + return false; + } + bool process_string(const char * src,string_base & out)//returns if changed + { + if (check_string(src)) {out=src;return false;} + unsigned idx=0; + while(src[idx]==' ') idx++; + while(src[idx]) + { + if (is_alphanumeric(src[idx]) && !is_used(src[idx])) + { + insert(src,idx,out); + return true; + } + + while(src[idx] && src[idx]!=' ' && src[idx]!='\t') idx++; + if (src[idx]=='\t') break; + while(src[idx]==' ') idx++; + } + + //no success picking first letter of one of words + idx=0; + while(src[idx]) + { + if (src[idx]=='\t') break; + if (is_alphanumeric(src[idx]) && !is_used(src[idx])) + { + insert(src,idx,out); + return true; + } + idx++; + } + + //giving up + out = src; + return false; + } + }; +} + +void menu_manager::win32_auto_mnemonics(HMENU menu) +{ + mnemonic_manager mgr; + unsigned n, m = GetMenuItemCount(menu); + string8_fastalloc temp,temp2; + for(n=0;n e; + menu_item * ptr; + string8_fastalloc action_name; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_type()==type) + { + unsigned action,num_actions = ptr->get_num_items(); + for(action=0;actionenum_item(action,action_name); + if (!stricmp_utf8(name,action_name)) + { + bool rv = ptr->get_description(action,out); + ptr->service_release(); + if (!rv) out.reset(); + return rv; + } + } + } + ptr->service_release(); + } + return false; +} + +static bool test_key(unsigned k) +{ + return (GetKeyState(k) & 0x8000) ? true : false; +} + +#define F_SHIFT (HOTKEYF_SHIFT<<8) +#define F_CTRL (HOTKEYF_CONTROL<<8) +#define F_ALT (HOTKEYF_ALT<<8) +#define F_WIN (HOTKEYF_EXT<<8) + +static unsigned get_key_code(WPARAM wp) +{ + unsigned code = wp & 0xFF; + if (test_key(VK_CONTROL)) code|=F_CTRL; + if (test_key(VK_SHIFT)) code|=F_SHIFT; + if (test_key(VK_MENU)) code|=F_ALT; + if (test_key(VK_LWIN) || test_key(VK_RWIN)) code|=F_WIN; + return code; +} + +bool keyboard_shortcut_manager::on_keydown(shortcut_type type,WPARAM wp) +{ + if (type==TYPE_CONTEXT) return false; + metadb_handle_list dummy; + return process_keydown(type,dummy,get_key_code(wp)); +} + +bool keyboard_shortcut_manager::on_keydown_context(const ptr_list_base & data,WPARAM wp,const GUID & caller) +{ + if (data.get_count()==0) return false; + return process_keydown_ex(TYPE_CONTEXT,data,get_key_code(wp),caller); +} + +bool keyboard_shortcut_manager::on_keydown_auto(WPARAM wp) +{ + if (on_keydown(TYPE_MAIN,wp)) return true; + if (on_keydown(TYPE_CONTEXT_PLAYLIST,wp)) return true; + if (on_keydown(TYPE_CONTEXT_NOW_PLAYING,wp)) return true; + return false; +} + +bool keyboard_shortcut_manager::on_keydown_auto_playlist(WPARAM wp) +{ + metadb_handle_list data; + bool rv = false; + playlist_oper::get()->get_sel_items(data); + rv = on_keydown_auto_context(data,wp,menu_item::caller_playlist); + data.delete_all(); + return rv; +} + +bool keyboard_shortcut_manager::on_keydown_auto_context(const ptr_list_base & data,WPARAM wp,const GUID & caller) +{ + if (on_keydown_context(data,wp,caller)) return true; + else return on_keydown_auto(wp); +} + + +bool menu_item::get_display_data(unsigned n,const ptr_list_base & data,string_base & out,unsigned & displayflags,const GUID & caller) +{ + bool rv; + menu_item_v2 * this_v2 = service_query_t(menu_item_v2,this); + if (this_v2) + { + rv = this_v2->get_display_data(n,data,out,displayflags,caller); + this_v2->service_release(); + } + else + { + rv = get_display_data(n,data,out,displayflags); + } + return rv; +} + +void menu_item::perform_command(unsigned n,const ptr_list_base & data,const GUID & caller) +{ + menu_item_v2 * this_v2 = service_query_t(menu_item_v2,this); + if (this_v2) + { + this_v2->perform_command(n,data,caller); + this_v2->service_release(); + } + else + { + perform_command(n,data); + } +} + +bool menu_item::enum_item_guid(unsigned n,GUID & out) +{ + bool rv = false; + menu_item_v2 * this_v2 = service_query_t(menu_item_v2,this); + if (this_v2) + { + rv = this_v2->enum_item_guid(n,out); + this_v2->service_release(); + } + return rv; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_manager.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_manager.h new file mode 100644 index 000000000..bd09aa1bb --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/menu_manager.h @@ -0,0 +1,286 @@ +#ifndef _FOOBAR2000_MENU_MANAGER_H_ +#define _FOOBAR2000_MENU_MANAGER_H_ + +#include "menu_item.h" +#include "metadb_handle.h" + + + +class NOVTABLE keyboard_shortcut_manager : public service_base +{ +public: + static keyboard_shortcut_manager * get() {return service_enum_create_t(keyboard_shortcut_manager,0);} + + enum shortcut_type + { + TYPE_MAIN, + TYPE_CONTEXT, + TYPE_CONTEXT_PLAYLIST, + TYPE_CONTEXT_NOW_PLAYING, + }; + + + virtual bool process_keydown(shortcut_type type,const ptr_list_base & data,unsigned keycode)=0; + virtual bool process_keydown_ex(shortcut_type type,const ptr_list_base & data,unsigned keycode,const GUID & caller)=0; +//caller guid - see menu_item_v2, menu_item::caller_* + bool on_keydown(shortcut_type type,WPARAM wp); + bool on_keydown_context(const ptr_list_base & data,WPARAM wp,const GUID & caller); + bool on_keydown_auto(WPARAM wp); + bool on_keydown_auto_playlist(WPARAM wp); + bool on_keydown_auto_context(const ptr_list_base & data,WPARAM wp,const GUID & caller); + + virtual bool get_key_description_for_action(const char * action_name, string_base & out, shortcut_type type, bool is_global)=0; + + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + +/* +usage: + + in a windowproc: + + case WM_KEYDOWN: + keyboard_shortcut_manager::get()->on_keydown(wparam); + break; + case WM_SYSKEYDOWN: + keyboard_shortcut_manager::get()->on_keydown(wparam); + break; + + return value is true if key got translated to one of user-configured actions, false if not + */ +}; + + + + +class NOVTABLE menu_node +{ +public: + enum type + { + TYPE_POPUP,TYPE_COMMAND,TYPE_SEPARATOR + }; + virtual type get_type()=0; + virtual const char * get_name()=0; + virtual unsigned get_num_children()=0;//TYPE_POPUP only + virtual menu_node * get_child(unsigned n)=0;//TYPE_POPUP only + virtual unsigned get_display_flags()=0;//TYPE_COMMAND/TYPE_POPUP only, see menu_item::FLAG_* + virtual unsigned get_id()=0;//TYPE_COMMAND only, returns zero-based index (helpful for win32 menu command ids) + virtual void execute()=0;//TYPE_COMMAND only + virtual bool get_description(string_base & out)=0;//TYPE_COMMAND only + virtual bool get_full_name(string_base & out)=0;//TYPE_COMMAND only + virtual void * get_glyph()=0;//RESERVED, do not use +}; + + + +class NOVTABLE menu_manager : public service_base +{ +public: + enum + { + FLAG_SHOW_SHORTCUTS = 1, + FLAG_SHOW_SHORTCUTS_GLOBAL = 2, + }; + virtual void init_context(const ptr_list_base & data,unsigned flags)=0;//flags - see FLAG_* above + virtual void init_context_playlist(unsigned flags)=0; + virtual void init_main(const char * path,unsigned flags)=0; + virtual menu_node * get_root()=0;//releasing menu_manager service releaases nodes; root may be null in case of error or something + virtual menu_node * find_by_id(unsigned id)=0; + virtual void set_shortcut_preference(const keyboard_shortcut_manager::shortcut_type * data,unsigned count)=0; + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static menu_manager * create() {return service_enum_create_t(menu_manager,0);}//you must service_release pointers you obtained + +#ifdef WIN32 + static void win32_build_menu(HMENU menu,menu_node * parent,int base_id,int max_id);//menu item identifiers are base_id<=N & list) {run_command_context(name,list);} + virtual void v_run_command_context_playlist(const char * name) {run_command_context_playlist(name);} + + virtual void v_win32_auto_mnemonics(HMENU menu) {win32_auto_mnemonics(menu);} +#endif + + //new (0.8 beta3) + virtual void init_context_ex(const ptr_list_base & data,unsigned flags,const GUID & caller)=0; + virtual bool init_context_now_playing(unsigned flags)=0;//returns false if not playing + virtual void init_main_ex(const char * path,unsigned flags,const GUID & caller)=0; + + bool execute_by_id(unsigned id); + + static bool run_command(const GUID & guid); + static bool run_command_context(const GUID & guid,const ptr_list_base & data); + static bool run_command_context_ex(const GUID & guid,const ptr_list_base & data,const GUID & caller); + + static bool run_command(const char * name);//returns false if not found + static bool run_command_context(const char * name,const ptr_list_base & data); + static bool run_command_context_playlist(const char * name); + static bool run_command_context_ex(const char * name,const ptr_list_base & data,const GUID & caller); + + static bool test_command(const char * name);//checks if a command of this name exists + static bool test_command_context(const char * name); + + static bool is_command_checked(const char * name); + static bool is_command_checked(const GUID & guid); + static bool is_command_checked_context(const char * name,metadb_handle_list & data); + static bool is_command_checked_context(const GUID & guid,metadb_handle_list & data); + static bool is_command_checked_context_playlist(const char * name); + static bool is_command_checked_context_playlist(const GUID & guid); + + static bool get_description(menu_item::type type,const char * path,string_base & out); + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + + + +}; + +class NOVTABLE menu_manager_defaults_callback +{ +public: + virtual void set_path(const char * path)=0; + virtual void add_command(const char * name)=0;//full name/path of a command, according to menu_item::enum_item, case-sensitive! + virtual void add_separator()=0; + virtual bool is_command_present(const char * name)=0; +}; + +class NOVTABLE menu_manager_defaults : public service_base +{ +public: + virtual GUID get_guid()=0; + virtual menu_item::type get_type()=0; + virtual void run(menu_manager_defaults_callback * callback)=0; + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + + + +class standard_commands +{ +public: + static const GUID + guid_context_file_properties, guid_context_file_open_directory, guid_context_copy_names, + guid_context_send_to_playlist, guid_context_reload_info, guid_context_reload_info_if_changed, + guid_context_rewrite_info, guid_context_remove_tags, guid_context_remove_from_database, + guid_context_convert_run, guid_context_convert_run_singlefile,guid_context_write_cd, + guid_context_rg_scan_track, guid_context_rg_scan_album, guid_context_rg_scan_album_multi, + guid_context_rg_remove, guid_context_save_playlist, guid_context_masstag_edit, + guid_context_masstag_rename, + guid_main_always_on_top, guid_main_preferences, guid_main_about, + guid_main_exit, guid_main_restart, guid_main_activate, + guid_main_hide, guid_main_activate_or_hide, guid_main_titleformat_help, + guid_main_follow_cursor, guid_main_next, guid_main_previous, + guid_main_next_or_random, guid_main_random, guid_main_pause, + guid_main_play, guid_main_play_or_pause, guid_main_rg_set_album, + guid_main_rg_set_track, guid_main_rg_disable, guid_main_stop, + guid_main_stop_after_current, guid_main_volume_down, guid_main_volume_up, + guid_main_volume_mute, guid_main_add_directory, guid_main_add_files, + guid_main_add_location, guid_main_add_playlist, guid_main_clear_playlist, + guid_main_create_playlist, guid_main_highlight_playing, guid_main_load_playlist, + guid_main_next_playlist, guid_main_previous_playlist, guid_main_open, + guid_main_remove_playlist, guid_main_remove_dead_entries, guid_main_remove_duplicates, + guid_main_rename_playlist, guid_main_save_all_playlists, guid_main_save_playlist, + guid_main_playlist_search, guid_main_playlist_sel_crop, guid_main_playlist_sel_remove, + guid_main_playlist_sel_invert, guid_main_playlist_undo, guid_main_show_console, + guid_main_play_cd, guid_main_restart_resetconfig, guid_main_record, + guid_main_playlist_moveback, guid_main_playlist_moveforward + ; + + static inline bool run_main(const GUID & guid) {return menu_manager::run_command(guid);} + static inline bool run_context(const GUID & guid,const ptr_list_base &data) {return menu_manager::run_command_context(guid,data);} + static inline bool run_context(const GUID & guid,const ptr_list_base &data,const GUID& caller) {return menu_manager::run_command_context_ex(guid,data,caller);} + + static inline bool context_file_properties(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_file_properties,data,caller);} + static inline bool context_file_open_directory(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_file_open_directory,data,caller);} + static inline bool context_copy_names(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_copy_names,data,caller);} + static inline bool context_send_to_playlist(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_send_to_playlist,data,caller);} + static inline bool context_reload_info(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_reload_info,data,caller);} + static inline bool context_reload_info_if_changed(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_reload_info_if_changed,data,caller);} + static inline bool context_rewrite_info(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_rewrite_info,data,caller);} + static inline bool context_remove_tags(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_remove_tags,data,caller);} + static inline bool context_remove_from_database(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_remove_from_database,data,caller);} + static inline bool context_convert_run(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_convert_run,data,caller);} + static inline bool context_convert_run_singlefile(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_convert_run_singlefile,data,caller);} + static inline bool context_write_cd(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_write_cd,data,caller);} + static inline bool context_rg_scan_track(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_rg_scan_track,data,caller);} + static inline bool context_rg_scan_album(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_rg_scan_album,data,caller);} + static inline bool context_rg_scan_album_multi(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_rg_scan_album_multi,data,caller);} + static inline bool context_rg_remove(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_rg_remove,data,caller);} + static inline bool context_save_playlist(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_save_playlist,data,caller);} + static inline bool context_masstag_edit(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_masstag_edit,data,caller);} + static inline bool context_masstag_rename(const ptr_list_base &data,const GUID& caller = menu_item::caller_undefined) {return run_context(guid_context_masstag_rename,data,caller);} + static inline bool main_always_on_top() {return run_main(guid_main_always_on_top);} + static inline bool main_preferences() {return run_main(guid_main_preferences);} + static inline bool main_about() {return run_main(guid_main_about);} + static inline bool main_exit() {return run_main(guid_main_exit);} + static inline bool main_restart() {return run_main(guid_main_restart);} + static inline bool main_activate() {return run_main(guid_main_activate);} + static inline bool main_hide() {return run_main(guid_main_hide);} + static inline bool main_activate_or_hide() {return run_main(guid_main_activate_or_hide);} + static inline bool main_titleformat_help() {return run_main(guid_main_titleformat_help);} + static inline bool main_follow_cursor() {return run_main(guid_main_follow_cursor);} + static inline bool main_next() {return run_main(guid_main_next);} + static inline bool main_previous() {return run_main(guid_main_previous);} + static inline bool main_next_or_random() {return run_main(guid_main_next_or_random);} + static inline bool main_random() {return run_main(guid_main_random);} + static inline bool main_pause() {return run_main(guid_main_pause);} + static inline bool main_play() {return run_main(guid_main_play);} + static inline bool main_play_or_pause() {return run_main(guid_main_play_or_pause);} + static inline bool main_rg_set_album() {return run_main(guid_main_rg_set_album);} + static inline bool main_rg_set_track() {return run_main(guid_main_rg_set_track);} + static inline bool main_rg_disable() {return run_main(guid_main_rg_disable);} + static inline bool main_stop() {return run_main(guid_main_stop);} + static inline bool main_stop_after_current() {return run_main(guid_main_stop_after_current);} + static inline bool main_volume_down() {return run_main(guid_main_volume_down);} + static inline bool main_volume_up() {return run_main(guid_main_volume_up);} + static inline bool main_volume_mute() {return run_main(guid_main_volume_mute);} + static inline bool main_add_directory() {return run_main(guid_main_add_directory);} + static inline bool main_add_files() {return run_main(guid_main_add_files);} + static inline bool main_add_location() {return run_main(guid_main_add_location);} + static inline bool main_add_playlist() {return run_main(guid_main_add_playlist);} + static inline bool main_clear_playlist() {return run_main(guid_main_clear_playlist);} + static inline bool main_create_playlist() {return run_main(guid_main_create_playlist);} + static inline bool main_highlight_playing() {return run_main(guid_main_highlight_playing);} + static inline bool main_load_playlist() {return run_main(guid_main_load_playlist);} + static inline bool main_next_playlist() {return run_main(guid_main_next_playlist);} + static inline bool main_previous_playlist() {return run_main(guid_main_previous_playlist);} + static inline bool main_open() {return run_main(guid_main_open);} + static inline bool main_remove_playlist() {return run_main(guid_main_remove_playlist);} + static inline bool main_remove_dead_entries() {return run_main(guid_main_remove_dead_entries);} + static inline bool main_remove_duplicates() {return run_main(guid_main_remove_duplicates);} + static inline bool main_rename_playlist() {return run_main(guid_main_rename_playlist);} + static inline bool main_save_all_playlists() {return run_main(guid_main_save_all_playlists);} + static inline bool main_save_playlist() {return run_main(guid_main_save_playlist);} + static inline bool main_playlist_search() {return run_main(guid_main_playlist_search);} + static inline bool main_playlist_sel_crop() {return run_main(guid_main_playlist_sel_crop);} + static inline bool main_playlist_sel_remove() {return run_main(guid_main_playlist_sel_remove);} + static inline bool main_playlist_sel_invert() {return run_main(guid_main_playlist_sel_invert);} + static inline bool main_playlist_undo() {return run_main(guid_main_playlist_undo);} + static inline bool main_show_console() {return run_main(guid_main_show_console);} + static inline bool main_play_cd() {return run_main(guid_main_play_cd);} + static inline bool main_restart_resetconfig() {return run_main(guid_main_restart_resetconfig);} + static inline bool main_playlist_moveback() {return run_main(guid_main_playlist_moveback);} + static inline bool main_playlist_moveforward() {return run_main(guid_main_playlist_moveforward);} +}; + +#endif //_FOOBAR2000_MENU_MANAGER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb.cpp new file mode 100644 index 000000000..95f504007 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb.cpp @@ -0,0 +1,147 @@ +#include "foobar2000.h" + +int metadb::query(file_info * out) +{ + playable_location_i temp(*out->get_location()); + return query(&temp,out); +} + +int metadb::query_flush(file_info * out) +{ + playable_location_i temp(*out->get_location()); + return query_flush(&temp,out); +} + +int metadb::query_dbonly(file_info * out) +{ + playable_location_i temp(*out->get_location()); + return query_dbonly(&temp,out); +} + +int metadb::query_meta_field(const playable_location * src,const char * name,int num,string8 & out) +{ + int rv = 0; + metadb_handle * ptr = handle_create(src); + if (ptr) + { + rv = ptr->handle_query_meta_field(name,num,out); + ptr->handle_release(); + } + return rv; +} + +int metadb::update_info(const file_info * info,bool dbonly)//using playable_location from file_info, return -1 on failure, 0 if pending, 1 on immediate success; may take a few good seconds to execute +{ + int rv; + metadb_handle * handle = handle_create(info->get_location()); + rv = handle->handle_update_info(info,dbonly); + handle->handle_release(); + return rv; +} + +void metadb::user_requested_remove(const playable_location * entry)//use this when user requests files to be removed from database (but not deleted physically) +{ + metadb_handle * ptr = handle_create(entry); + ptr->handle_user_requested_remove(); + ptr->handle_release(); +} + +int metadb::query(const playable_location * entry,file_info * out) +{ + int rv; + metadb_handle * handle = handle_create(entry); + rv = handle->handle_query(out,false); + handle->handle_release(); + return rv; +} + +int metadb::query_flush(const playable_location * entry,file_info * out) +{ + int rv; + metadb_handle * handle = handle_create(entry); + handle->handle_flush_info(); + rv = handle->handle_query(out,false); + handle->handle_release(); + return rv; +} + +int metadb::query_dbonly(const playable_location * entry,file_info * out) +{ + int rv; + metadb_handle * handle = handle_create(entry); + rv = handle->handle_query(out,true); + handle->handle_release(); + return rv; +} + +int metadb::precache(const playable_location * entry,reader * r) +{ + int rv; + metadb_handle * handle = handle_create(entry); + rv = handle->handle_precache(r); + handle->handle_release(); + return rv; +} + +void metadb::precache(const char * filename,reader * r) +{ + if (r) + { + metadb_handle_list temp; + track_indexer::g_get_tracks_ex(filename,temp,r); + unsigned n,m=temp.get_count(); + for(n=0;nhandle_get_path())) + { + r->seek(0); + ptr->handle_precache(r); + } + } + temp.delete_all(); + } +} + + +void metadb::hint(const file_info * src) +{ + metadb_handle * handle = handle_create_hint(src); + handle->handle_release(); +} + + +int metadb::format_title(const playable_location * source,string_base & out,const char * spec,const char * extra_items) +{ + int rv; + metadb_handle * handle = handle_create(source); + rv = handle->handle_format_title(out,spec,extra_items); + handle->handle_release(); + return rv; +} + + +metadb * metadb::get()//safe not to release it; don't call from DLL startup / static object constructor +{ + static metadb * ptr; + if (ptr==0) ptr = service_enum_create_t(metadb,0); + return ptr; +} +#ifdef _DEBUG +int metadb::database_lock_count() +{ + int val = database_try_lock(); + if (val) + val = database_unlock(); + return val; +} + +void metadb::database_delockify(int wanted_count) +{ + assert(wanted_count >= 0); + if (wanted_count<0) wanted_count = 0; + int count = database_lock_count(); + while(count < wanted_count) count = database_lock(); + while(count > wanted_count) count = database_unlock(); +} +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb.h new file mode 100644 index 000000000..711cdcd84 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb.h @@ -0,0 +1,122 @@ +#ifndef _METADB_H_ +#define _METADB_H_ + +#include "service.h" +#include "interface_helper.h" +#include "file_info.h" + +class input; +class reader; + + +#include "metadb_handle.h" + +//only one implementation in main exe, DO NOT DERIVE FROM THIS +class NOVTABLE metadb : public service_base +{ +public: + virtual int update_info_flush()=0;//tries to perform any pending tag update operations, may take a few good seconds to execute + + virtual void file_moved(const char * src,const char * dst)=0;//will transfer existing database data to new path (and notify callbacks about file being moved) + virtual void file_copied(const char * src,const char * dst)=0; + virtual void file_removed(const char * src)=0;//use this to tell database that url [src] is dead + virtual void entry_dead(const playable_location * entry)=0;//same as file_removed but taking playable_location + + virtual int database_lock()=0;//enters database's internal critical section, prevents other threads from accessing database as long as it's locked + virtual int database_try_lock()=0;//returns immediately without waiting, may fail, returns 0 on failure + virtual int database_unlock()=0; + + + virtual metadb_handle * handle_create(const playable_location * src)=0;//should never fail + virtual metadb_handle * handle_create_hint(const file_info * src)=0;//should never fail + + virtual void get_all_entries(ptr_list_base & out)=0;//you get duplicate handles of all database items, you are responsible for releasing them + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static metadb * get();//safe not to release it; don't call from DLL startup / static object constructor + + //helper + static int g_format_title(const playable_location * source,string_base & out,const char * spec,const char * extra_items=0) + { + return get()->format_title(source,out,spec,extra_items); + } + + int query(file_info * out); + int query_flush(file_info * out); + int query_dbonly(file_info * out); + int query_meta_field(const playable_location * src,const char * name,int num,string8 & out); + int update_info(const file_info * info,bool dbonly=false);//using playable_location from file_info, return -1 on failure, 0 if pending, 1 on immediate success; may take a few good seconds to execute + void user_requested_remove(const playable_location * entry);//use this when user requests files to be removed from database (but not deleted physically) + int query(const playable_location * entry,file_info * out); + int query_flush(const playable_location * entry,file_info * out); + int query_dbonly(const playable_location * entry,file_info * out); + int precache(const playable_location * entry,reader * r); + void precache(const char * filename,reader * r); + void hint(const file_info * src); + + int format_title(const playable_location * source,string_base & out,const char * spec,const char * extra_items); + //reminder: see titleformat.h for descriptions of titleformatting parameters + //return 1 on success, 0 on failure (cant get info, used empty fields and filename) + + inline void update_info_dbonly(const file_info * info) {update_info(info,true);} //updates database, doesnt modify files + +#ifdef _DEBUG + int database_lock_count(); + void database_delockify(int wanted_count); + inline void assert_not_locked() + { + assert(database_lock_count()==0); + } + inline void assert_locked() + { + assert(database_lock_count()>0); + } +#endif + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + virtual void handle_release_multi(metadb_handle * const * list,unsigned count)=0; + virtual void handle_add_ref_multi(metadb_handle * const * list,unsigned count)=0; +}; + +class NOVTABLE metadb_callback : public service_base//use service_factory_single_t to instantiate, you will get called with database notifications +{//IMPORTANT: metadb_callback calls may happen from different threads ! watch out for deadlocks / calling things that work only from main thread / etc +public: + virtual void on_info_edited(metadb_handle * handle) {} + virtual void on_info_reloaded(metadb_handle * handle) {} + virtual void on_file_removed(metadb_handle * handle) {} + virtual void on_file_moved(metadb_handle * src,metadb_handle * dst) {} + virtual void on_file_new(metadb_handle * handle) {}//reserved for future use + virtual void on_file_removed_user(metadb_handle * handle) {}//user requested file to be removed from db, file didn't get physically removed +//warning: all callback methods are called inside database_lock section ! watch out for deadlock conditions if you use SendMessage() or critical sections + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE metadb_callback_simple : public service_base +{//this is always properly sync'd to main thread, unlike metadb_callback above +public: + virtual void on_info_change(metadb_handle * handle)=0; + virtual void on_file_moved(metadb_handle * src,metadb_handle * dst)=0; + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + + +class in_metadb_sync +{ +public: + in_metadb_sync() {metadb::get()->database_lock();} + ~in_metadb_sync() {metadb::get()->database_unlock();} +}; + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb_handle.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb_handle.cpp new file mode 100644 index 000000000..8b438bfcb --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb_handle.cpp @@ -0,0 +1,224 @@ +#include "foobar2000.h" + +namespace { + struct custom_sort_data + { + HANDLE text; + int index; + custom_sort_data(const char * p_text,int p_idx) + : text(uSortStringCreate(p_text)), index(p_idx) + {} + ~custom_sort_data() {uSortStringFree(text);} + }; +} +static int __cdecl custom_sort_compare(const custom_sort_data * &elem1, const custom_sort_data *&elem2 ) +{//depends on unicode/ansi shit, nonportable (win32 lstrcmpi) + return uSortStringCompare(elem1->text,elem2->text);//uStringCompare +} + + +void metadb_handle_list::sort_by_format_get_order(int * order,const char * spec,const char * extra_items) const +{ + ptr_list_simple data; + unsigned n; + string8 temp; + string8 temp2; + temp.set_mem_logic(mem_block::ALLOC_FAST_DONTGODOWN); + temp.prealloc(512); + temp2.set_mem_logic(mem_block::ALLOC_FAST_DONTGODOWN); + for(n=0;nhandle_format_title(temp,spec,extra_items); + const char * ptr = temp.get_ptr(); + if (strchr(ptr,3)) + { + titleformat::remove_color_marks(ptr,temp2); + ptr = temp2; + } + data.add_item(new custom_sort_data(ptr,n)); + } + + data.sort(custom_sort_compare); + + for(n=0;nindex; + } + + data.delete_all(); +} + +void metadb_handle_list::sort_by_format(const char * spec,const char * extra_items) +{ + unsigned count = get_count(); + mem_block_t order(count); + sort_by_format_get_order(order,spec,extra_items); + apply_order(order,count); +} + +bool metadb_handle::handle_query_meta_field(const char * name,int num,string_base & out) +{ + bool rv = false; + handle_lock(); + const file_info * info = handle_query_locked(); + if (info) + { + const char * val = info->meta_get(name,num); + if (val) + { + out = val; + rv = true; + } + } + handle_unlock(); + return rv; +} + +int metadb_handle::handle_query_meta_field_int(const char * name,int num)//returns 0 if not found +{ + int rv = 0; + handle_lock(); + const file_info * info = handle_query_locked(); + if (info) + { + const char * val = info->meta_get(name,num); + if (val) + { + rv = atoi(val); + } + } + handle_unlock(); + return rv; +} + +double metadb_handle::handle_get_length() +{ + double rv = 0; + handle_lock(); + const file_info * info = handle_query_locked(); + if (info) + rv = info->get_length(); + handle_unlock(); + return rv; +} + +__int64 metadb_handle::handle_get_length_samples() +{ + __int64 rv = 0; + handle_lock(); + const file_info * info = handle_query_locked(); + if (info) + rv = info->info_get_length_samples(); + handle_unlock(); + return rv; +} + + +void metadb_handle_list::delete_item(metadb_handle * ptr) +{ + remove_item(ptr); + ptr->handle_release(); +} + +void metadb_handle_list::delete_by_idx(int idx) +{ + metadb_handle * ptr = remove_by_idx(idx); + if (ptr) ptr->handle_release(); +} + +void metadb_handle_list::delete_all() +{ + if (get_count()>0) + { + metadb::get()->handle_release_multi(get_ptr(),get_count()); + remove_all(); + } +} + +void metadb_handle_list::add_ref_all() +{ + if (get_count()>0) metadb::get()->handle_add_ref_multi(get_ptr(),get_count()); +} + +void metadb_handle_list::delete_mask(const bit_array & mask) +{ + unsigned n,m=get_count(); + for_each_bit_array(n,mask,true,0,m) + get_item(n)->handle_release(); + remove_mask(mask); +} + +void metadb_handle_list::filter_mask_del(const bit_array & mask) +{ + unsigned n,m=get_count(); + for_each_bit_array(n,mask,false,0,m) + get_item(n)->handle_release(); + filter_mask(mask); +} + +void metadb_handle_list::remove_duplicates(bool b_release) +{ + unsigned count = get_count(); + if (count>0) + { + bit_array_bittable mask(count); + mem_block_t order(count); + + sort_by_format_get_order(order,"%_path_raw%|$num(%_subsong%,9)",0); + + unsigned n; + for(n=0;nval2) return 1; + else return 0; +} + +void metadb_handle_list::remove_duplicates_quick(bool b_release) +{ + unsigned count = get_count(); + if (count>0) + { + sort(remove_duplicates_quick_compare); + bit_array_bittable mask(count); + unsigned n; + bool b_found = false; + for(n=0;n & source) +{ + unsigned n,m = source.get_count(); + for(n=0;nhandle_duplicate()); +} + +void metadb_handle_list::sort_by_path_quick() +{ + sort_by_format("%_path_raw%",0); +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb_handle.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb_handle.h new file mode 100644 index 000000000..9cd3f20fa --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/metadb_handle.h @@ -0,0 +1,121 @@ +#ifndef _FOOBAR2000_METADB_HANDLE_H_ +#define _FOOBAR2000_METADB_HANDLE_H_ + +#include "file_info.h" + +class reader; + +//metadb_handle is a reference to file_info stored in database (see: file_info.h) +//as long as handle is active, info about particular is kept in database and immediately available (unless file i/o error occurs or the file gets removed) +//metadb_handle is the most efficient way of passing around playable resource locations and info about them, since all you have to do is to copy a pointer (and possibly call handle_add_ref) +//metadb_handle also lets you efficiently store locations of playable resources without having to waste memory on file path strings allocated by playable_location etc +//metadb_handle lets you pull file_info immediately without searching database, unlike metadb::query and other metadb api calls +//metadb_handle objects keep their reference counts, eg. you need to make a matching handle_release() call for every handle_add_ref() + +/* +common n00b FAQ: + +getting file location from metadb_handle -> use handle_get_location(), it never fails, returned pointer valid until you release the handle +handle_query_locked MAY fail and return null when file io error occurs or something, so CHECK the result BEFORE using it +make sure you call handle_lock/handle_unlock when you use handle_query_locked, otherwise some other thread might modify database data while you are working with result and thing will be fucked + +unless commented otherwise, functions taking metadb_handle as parameter don't release the handle and add a reference if they store it; when function returns a metadb_handle, calling code is responsible for releasing it +EXCEPTION: all ptr_list-style objects dont touch reference counts when they receive/return metadb_handle; that includes ptr_list_interface, ptr_list_t and metadb_handle_list + +*/ + + +class NOVTABLE metadb_handle +{ +public: + virtual void handle_add_ref()=0; + virtual void handle_release()=0; + virtual int handle_query(file_info * dest,bool dbonly = false)=0;//dest can be null if you're only checking if info is available + virtual const file_info * handle_query_locked(bool dbonly = false)=0;//must be inside database_lock()-protected section, may return 0 if info is not available for some reason + virtual const playable_location * handle_get_location() const = 0;//never fails, returned pointer valid till you call release + virtual void handle_hint(const file_info * src)=0; + virtual int handle_format_title(string_base & out,const char * spec,const char * extra_items)=0;//reminder: see titleformat.h for descriptions of titleformatting parameters + virtual int handle_flush_info()=0;//tries to reload info from file + virtual int handle_update_info(const file_info * src,bool dbonly=false)=0;//return value - see metadb::update_info(); src may be null if you want to update file with info which is currently in database + virtual void handle_entry_dead()=0;//for reporting dead files; need to call handle_release() separately + virtual int handle_precache(reader * r=0)=0;//makes sure that info is in database; reader is optional + virtual void handle_user_requested_remove()=0;//user requests this object to be removed from database (but file isn't being physically removed) + virtual int handle_lock()=0;//same as metadb::database_lock() + virtual int handle_try_lock()=0; + virtual int handle_unlock()=0;//same as metadb::database_unlock() + virtual int handle_update_and_unlock(const file_info * info)=0;//new in 0.7.1; will unlock even if update fails + + //new in 0.8 + //time is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601; 0 for invalid/unknown time + virtual __int64 handle_get_modification_time() const = 0; + virtual void handle_set_modification_time(__int64)=0; + virtual __int64 handle_get_file_size() const = 0; + virtual void handle_set_file_size(__int64)=0; + virtual void handle_hint_ex(const file_info * src,__int64 time,__int64 size,bool b_fresh)=0; + virtual int handle_check_if_changed()=0;//compares known modification time with file system and reloads info if needed + virtual int handle_is_permcached() const = 0;//returns if this object is in "database" or not + virtual int handle_get_relative_path(string_base & out) const = 0; + + + inline int handle_query_dbonly(file_info * dest) {return handle_query(dest,true);} + inline const file_info * handle_query_locked_dbonly() {return handle_query_locked(true);} + + + inline metadb_handle * handle_duplicate() {handle_add_ref();return this;} + + bool handle_query_meta_field(const char * name,int num,string_base & out); + int handle_query_meta_field_int(const char * name,int num);//returns 0 if not found + double handle_get_length(); + __int64 handle_get_length_samples(); + + inline const char * handle_get_path() const//never fails + { + return handle_get_location()->get_path(); + } + inline int handle_get_subsong_index() const + { + return handle_get_location()->get_subsong_index(); + } + + + +protected: + metadb_handle() {} + ~metadb_handle() {}//verboten, avoid ptr_list_t stupidity +}; + +//important: standard conventions with addref'ing before returning / functions addref'ing their params DO NOT apply to pointer lists !!! + +class metadb_handle_list : public ptr_list_t +{ +public: + void delete_item(metadb_handle * ptr); + void delete_by_idx(int idx); + void delete_all(); + void add_ref_all(); + void delete_mask(const bit_array & mask); + void filter_mask_del(const bit_array & mask); + void duplicate_list(const ptr_list_base & source); + + void sort_by_format_get_order(int * order,const char * spec,const char * extra_items) const; //only outputs order, doesnt modify list + void sort_by_format(const char * spec,const char * extra_items); + void remove_duplicates(bool b_release = true); + void remove_duplicates_quick(bool b_release = true);//sorts by pointer values internally + void sort_by_path_quick(); + +}; + +class metadb_handle_lock +{ + metadb_handle * ptr; +public: + inline metadb_handle_lock(metadb_handle * param) + { + ptr = param->handle_duplicate(); + ptr->handle_lock(); + } + inline ~metadb_handle_lock() {ptr->handle_unlock();ptr->handle_release();} +}; + + +#endif //_FOOBAR2000_METADB_HANDLE_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/modeless_dialog.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/modeless_dialog.cpp new file mode 100644 index 000000000..9d212a977 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/modeless_dialog.cpp @@ -0,0 +1,23 @@ +#include "foobar2000.h" + +void modeless_dialog_manager::add(HWND wnd) +{ + service_enum_t e; + modeless_dialog_manager * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + ptr->_add(wnd); + ptr->service_release(); + } +} + +void modeless_dialog_manager::remove(HWND wnd) +{ + service_enum_t e; + modeless_dialog_manager * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + ptr->_remove(wnd); + ptr->service_release(); + } +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/modeless_dialog.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/modeless_dialog.h new file mode 100644 index 000000000..7d05e558f --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/modeless_dialog.h @@ -0,0 +1,22 @@ +#ifndef _MODELESS_DIALOG_H_ +#define _MODELESS_DIALOG_H_ + +#include "service.h" + +//use this to hook your modeless dialogs to main message loop and get IsDialogMessage() stuff +//not needed for config pages + +class modeless_dialog_manager : public service_base +{ +private: + virtual void _add(HWND wnd)=0; + virtual void _remove(HWND wnd)=0; +public: + static void add(HWND wnd); + static void remove(HWND wnd); + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +#endif //_MODELESS_DIALOG_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/output.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/output.cpp new file mode 100644 index 000000000..2354286b8 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/output.cpp @@ -0,0 +1,19 @@ +#include "foobar2000.h" + +output * output::create(GUID g) +{ + output * ptr; + service_enum_t e; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->get_guid()==g) return ptr; + ptr->service_release(); + } + return 0; +} + + +void output_i_base::set_error(const char * msg) +{ + console::error(msg); +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/output.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/output.h new file mode 100644 index 000000000..70c2be0d0 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/output.h @@ -0,0 +1,166 @@ +#ifndef _OUTPUT_H_ +#define _OUTPUT_H_ + +#include "service.h" +#include "audio_chunk.h" +#include "interface_helper.h" + + +class NOVTABLE output : public service_base +{ +public: + virtual double get_latency()=0;//in seconds + virtual int process_samples(const output_chunk * chunk,int format_code)=0;//1 on success, 0 on error, no sleeping, copies data to its own buffer immediately; format_code - see enums below + virtual int update()=0;//return 1 if ready for next write, 0 if still working with last process_samples(), -1 on error + virtual void pause(int state)=0; + virtual void flush()=0; + virtual void force_play()=0; + virtual GUID get_guid()=0;//for storing config + virtual const char * get_name()=0;//for preferences + virtual const char * get_config_page_name() {return 0;}//for "go to settings" button, return 0 if you dont have a config page + + enum + { + DATA_FORMAT_LINEAR_PCM, + DATA_FORMAT_IEEE_FLOAT,//32bit float + }; + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static output * create(GUID g); + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + +}; + +//implementation helper, you can derive from this instead of deriving directly from output +class NOVTABLE output_i_base : public output +{ + mem_block_t chunk; + int chunk_size,chunk_ptr; + int new_bps,new_srate,new_nch; + int cur_bps,cur_srate,cur_nch; + int is_open; + int cur_format_code,new_format_code; + + +protected: + output_i_base() + { + is_open = 0; + chunk_size = chunk_ptr = 0; + } + + void set_error(const char * msg); + + //override me + virtual int open_ex(int srate,int bps,int nch,int format_code)//return 1 on success, 0 on failure, might get called when you are open already (eg. new PCM format) + { + if (format_code==DATA_FORMAT_LINEAR_PCM) + { + return open(srate,bps,nch);//call old version if not overridden + } + else + { + set_error("Unsupported output data format."); + return 0; + } + } + virtual int open(int srate,int bps,int nch) {return 0;}//old version + virtual int can_write()=0;//in bytes + virtual int write(const char * data,int bytes)=0;//return 1 on success, 0 on error, bytes always <= last can_write() return value + virtual int get_latency_bytes()=0;//amount of data buffered (write_offset-playback_offset), in bytes + virtual void pause(int state)=0; + virtual void force_play()=0; + virtual int do_flush() {return 1;} //return 1 if you need reopen, 0 if successfully flushed + virtual int is_playing() {return get_latency_bytes()>0;} + virtual GUID get_guid()=0; + virtual const char * get_name()=0; + +public: + virtual double get_latency() + { + double rv = 0; + if (is_open) + { + int delta = get_latency_bytes(); + if (delta<0) delta=0; + rv += (double) (delta / (cur_nch * cur_bps/8)) / (double) cur_srate; + } + if (chunk_size>0 && chunk_ptrdata,p_chunk->size); + chunk_size = p_chunk->size; + chunk_ptr = 0; + new_bps = p_chunk->bps; + new_srate = p_chunk->srate; + new_nch = p_chunk->nch; + new_format_code = format_code; + return 1; + } + virtual int update() + { + if (chunk_size<=0 || chunk_ptr>=chunk_size) return 1; + if (is_open && (cur_bps!=new_bps || cur_srate!=new_srate || cur_nch!=new_nch || cur_format_code!=new_format_code)) + { + force_play(); + if (is_playing()) return 0; + is_open = 0; + } + if (!is_open) + { + if (!open_ex(new_srate,new_bps,new_nch,new_format_code)) + return -1;//error + cur_srate = new_srate; + cur_nch = new_nch; + cur_bps = new_bps; + cur_format_code = new_format_code; + is_open = 1; + } + + int cw; + while((cw = can_write())>0 && chunk_ptrcw) d=cw; + if (!write(chunk+chunk_ptr,d)) return -1; + chunk_ptr+=d; + } + if (chunk_ptr +class output_factory : public service_factory_t {}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/output_manager.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/output_manager.h new file mode 100644 index 000000000..6ba758af2 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/output_manager.h @@ -0,0 +1,54 @@ +#ifndef _OUTPUT_MANAGER_H_ +#define _OUTPUT_MANAGER_H_ + +#include "output.h" + +struct output_config +{ + GUID output;//null guid for default user-configured device + + int b_override_format; + + struct format_t + { + int bps,bps_pad; + int b_float; + int b_dither; + + }; + + format_t format;//format valid only if b_override_format is set to non-zero, otherwise user settings from core preferences are used + + output_config() + { + memset(&output,0,sizeof(output)); + b_override_format = 0; + + format.bps = 16; + format.bps_pad = 16; + format.b_float = 0; + format.b_dither = 1; + } +}; + +class NOVTABLE output_manager : public service_base +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static output_manager * create() {return service_enum_create_t(output_manager,0);}//may fail on pre-0.63 + + virtual void get_default_config(output_config * out)=0;//retrieves current user settings from core preferences; do not pass returned data to set_config (same effect as not calling set_config at all or passing uninitialized struct) + + virtual void set_config(const output_config * param)=0;//optionally call before first use + + virtual double get_latency()=0;//in seconds + virtual int process_samples(const audio_chunk* chunk)=0;//1 on success, 0 on error, no sleeping, copies data to its own buffer immediately; format_code - see enums below + virtual int update()=0;//return 1 if ready for next write, 0 if still working with last process_samples(), -1 on error + virtual void pause(int state)=0; + virtual void flush()=0; + virtual void force_play()=0; +}; + +#endif //_OUTPUT_MANAGER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/packet_decoder.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/packet_decoder.cpp new file mode 100644 index 000000000..692a9f21e --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/packet_decoder.cpp @@ -0,0 +1,13 @@ +#include "foobar2000.h" + +packet_decoder * packet_decoder::g_open(const GUID & owner,unsigned param1,const void * param2,unsigned param2size,file_info * info) +{ + service_enum_t e; + packet_decoder * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->open_stream(owner,param1,param2,param2size,info)) return ptr; + ptr->service_release(); + } + return 0; +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/packet_decoder.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/packet_decoder.h new file mode 100644 index 000000000..79691e881 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/packet_decoder.h @@ -0,0 +1,54 @@ +#ifndef _FOOBAR2000_PACKET_DECODER_H_ +#define _FOOBAR2000_PACKET_DECODER_H_ + +#include "service.h" +#include "audio_chunk.h" + +class packet_decoder : public service_base +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual bool open_stream(const GUID & owner,unsigned param1,const void * param2,unsigned param2size,file_info * info)=0;//owner - container GUID, param1/2 - contents depend on owner + virtual unsigned set_stream_property(const GUID & type,unsigned param1,const void * param2,unsigned param2size,file_info * info) {return 0;}//optional, return values depend on guid, return 0 by default + + virtual unsigned get_max_frame_dependency()=0; + virtual double get_max_frame_dependency_time()=0; + + virtual void reset_after_seek()=0; + virtual bool decode(const void * buffer,unsigned bytes,audio_chunk * out)=0;//may return empty chunk (decoder delay etc), caller must check for it (and not crash on samplerate==0 etc) + virtual const char * get_name()=0;//for diagnostic purposes, codec list, etc + + static packet_decoder * g_open(const GUID & owner,unsigned param1,const void * param2,unsigned param2size,file_info * info); + + static const GUID owner_MP4,owner_matroska,owner_MP3; + + struct matroska_setup + { + const char * codec_id; + unsigned sample_rate,sample_rate_output; + unsigned channels; + unsigned codec_private_size; + const void * codec_private; + }; + //owner_MP4: param1 - codec ID (MP4 audio type), param2 - MP4 codec initialization data + //owner_MP3: raw MP3/MP2 file, parameters ignored + //owner_matroska: param2 = matroska_setup struct, param2size size must be equal to sizeof(matroska_setup) + + + //these are used to initialize PCM decoder + static const GUID property_samplerate,property_bitspersample,property_channels,property_byteorder,property_signed; + //property_samplerate : param1 == sample rate in hz + //property_bitspersample : param1 == bits per sample + //property_channels : param1 == channel count + //property_byteorder : if (param1) little_endian; else big_endian; + //property_signed : if (param1) signed; else unsigned; +}; + + +template +class packet_decoder_factory : public service_factory_t {}; + + +#endif //_FOOBAR2000_PACKET_DECODER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/play_callback.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/play_callback.h new file mode 100644 index 000000000..ce346a857 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/play_callback.h @@ -0,0 +1,44 @@ +#ifndef _PLAY_CALLBACK_H_ +#define _PLAY_CALLBACK_H_ + +#include "service.h" + +#include "metadb_handle.h" +//callbacks for getting notified about playback status +//multithread safety: all play_callback api calls come from main thread. + +#include "play_control.h" + +class NOVTABLE play_callback : public service_base +{ +public: + + enum { + MASK_on_playback_starting = 1<<0, MASK_on_playback_new_track = 1<<1, MASK_on_playback_stop = 1<<2, + MASK_on_playback_seek = 1<<3, MASK_on_playback_pause = 1<<4, MASK_on_playback_edited = 1<<5, + MASK_on_playback_dynamic_info = 1<<6, MASK_on_playback_time = 1<<7, MASK_on_volume_change = 1<<8, + }; + + virtual unsigned get_callback_mask() {return (unsigned)(-1);} + //returns combination of MASK_* above, return value must be constant, called only once + //system uses it as a hint to avoid calling you when not needed, to reduce working code size (and "memory usage") + + virtual void on_playback_starting()=0; + virtual void on_playback_new_track(metadb_handle * track)=0; + virtual void on_playback_stop(play_control::stop_reason reason)=0; + virtual void on_playback_seek(double time)=0; + virtual void on_playback_pause(int state)=0; + virtual void on_playback_edited(metadb_handle * track)=0;//currently played file got edited + virtual void on_playback_dynamic_info(const file_info * info,bool b_track_change)=0; + virtual void on_playback_time(metadb_handle * track,double val) {}//called every second + virtual void on_volume_change(int new_val) {};//may also happen when not playing + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +template +class play_callback_factory : public service_factory_single_t {}; + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/play_control.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/play_control.cpp new file mode 100644 index 000000000..d708e992a --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/play_control.cpp @@ -0,0 +1,9 @@ +#include "foobar2000.h" + + +play_control * play_control::get() +{ + static play_control * ptr; + if (!ptr) ptr = service_enum_create_t(play_control,0); + return ptr; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/play_control.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/play_control.h new file mode 100644 index 000000000..73a95b554 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/play_control.h @@ -0,0 +1,94 @@ +#ifndef _PLAY_CONTROL_H_ +#define _PLAY_CONTROL_H_ + +#include "service.h" +#include "interface_helper.h" +#include "metadb_handle.h" +//important: you should call api commands declared in this header ONLY from main thread !! +//do not call them from a database_lock section, some commands (eg. those stopping playback) will deadlock if you do ! + + +//note: +//all methods returning metadb_handle return add_ref'd handles, you have to handle_release them +//all methods taking metadb_handle will add_ref them if they store them, so it's your responsibility to later release handles you pass + +class NOVTABLE play_control : public service_base +{ +public: + + enum stop_reason { + STOP_REASON_USER = 0, + STOP_REASON_EOF, + STOP_REASON_STARTING_ANOTHER, + }; + + + enum track_command { + TRACK_COMMAND_ABORT = -1, + TRACK_COMMAND_DEFAULT = 0, + TRACK_COMMAND_PLAY, + TRACK_COMMAND_NEXT, + TRACK_COMMAND_PREV, + TRACK_COMMAND_SETTRACK, + TRACK_COMMAND_RAND, + }; + + virtual metadb_handle * get_now_playing()=0;//will return 0 if not playing + virtual void play_item(metadb_handle * handle)=0; + virtual void play_start(track_command cmd = TRACK_COMMAND_PLAY)=0; + virtual void play_stop(stop_reason reason = STOP_REASON_USER)=0; + virtual bool is_playing()=0; + virtual bool is_paused()=0; + virtual double get_playback_time()=0; + virtual void pause()=0; + + virtual void show_config(const char * page_name)=0; + + virtual bool get_stop_after_current()=0; + virtual void set_stop_after_current(bool state)=0; + virtual void set_volume(int)=0; + virtual int get_volume()=0;//volume is in 0.01 dB + virtual void volume_up()=0; + virtual void volume_down()=0; + virtual void volume_mute_toggle()=0; + + virtual void playback_seek(double param)=0; + virtual void playback_seek_delta(double param)=0; + virtual bool playback_can_seek()=0; + virtual double playback_get_position()=0; + + //reminder: see titleformat.h for descriptions of titleformatting parameters + virtual void playback_format_title(string_base & out,const char * spec,const char * extra_items=0)=0; + + virtual bool playback_format_title_ex(metadb_handle * handle,string_base & out,const char * spec,const char * extra_items,bool b_include_time,bool b_include_dynamicinfo)=0;//0.7.1 and above + + double playback_get_length() + { + double rv = 0; + metadb_handle * ptr = get_now_playing(); + if (ptr) + { + rv = ptr->handle_get_length(); + ptr->handle_release(); + } + return rv; + } + + inline void toggle_stop_after_current() {set_stop_after_current(!get_stop_after_current());} + + static play_control * get(); + + static void g_show_config(const char * page_name) + { + get()->show_config(page_name); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + + +//playlist_oper moved to playlist.h + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playable_location.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/playable_location.cpp new file mode 100644 index 000000000..9dac871e4 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playable_location.cpp @@ -0,0 +1,14 @@ +#include "foobar2000.h" + +int playable_location::compare(const playable_location * src) const +{ + int ret = uStringCompare(get_path(),src->get_path()); + if (ret!=0) return ret; + else + { + int n1 = get_number(), n2 = src->get_number(); + if (n1n2) return 1; + else return 0; + } +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playable_location.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/playable_location.h new file mode 100644 index 000000000..98d508e92 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playable_location.h @@ -0,0 +1,93 @@ +#ifndef _FOOBAR2000_PLAYABLE_LOCATION_H_ +#define _FOOBAR2000_PLAYABLE_LOCATION_H_ + +#include "service.h" + +#include "interface_helper.h" + +//playable_location stores location of a playable resource, currently implemented as file path and integer for indicating multiple playable "subsongs" per file +//also see: file_info.h +//for getting more info about resource referenced by a playable_location, see metadb.h + +//char* strings are all UTF-8 + +class playable_location//interface (for passing around between DLLs) +{ +public: + virtual const char * get_path() const =0; + virtual void set_path(const char*)=0; + virtual int get_number() const =0; + virtual void set_number(int)=0; + virtual ~playable_location() {}; + + void copy(const playable_location * src) + { + set_path(src->get_path()); + set_number(src->get_number()); + } +#if 0 + int compare_sort(const playable_location * src) const + { + int ret = stricmp_utf8_full(file_path_display(get_path()),file_path_display(src->get_path())); + if (ret!=0) return ret; + else return compare(src); + }; +#endif + + int compare(const playable_location * src) const; + + const playable_location & operator=(const playable_location & src) + { + copy(&src); + return *this; + } + + inline bool is_empty() {return get_path()[0]==0 && get_number()==0;} + inline void reset() {set_path("");set_number(0);} + inline int get_subsong_index() const {return get_number();} + inline void set_subsong_index(int v) {set_number(v);} +}; + +class playable_location_i : public playable_location//implementation +{ + string_simple path; + int number; +public: + + virtual const char * get_path() const {return path;} + virtual void set_path(const char* z) {path=z;} + virtual int get_number() const {return number;} + virtual void set_number(int z) {number=z;} + + playable_location_i() {number=0;} + + const playable_location_i & operator=(const playable_location & src) + { + copy(&src); + return *this; + } + + playable_location_i(const char * p_path,int p_number) : path(p_path), number(p_number) {} + + playable_location_i(const playable_location & src) {copy(&src);} +}; + + +// usage: something( make_playable_location("file://c:\blah.ogg",0) ); +// only for use as a parameter to a function taking const playable_location* +class make_playable_location : private playable_location +{ + const char * path; + int num; + virtual const char * get_path() const {return path;} + virtual void set_path(const char*) {} + virtual int get_number() const {return num;} + virtual void set_number(int) {} + +public: + make_playable_location(const char * p_path,int p_num) : path(p_path), num(p_num) {} + operator const playable_location * () {return this;} +}; + + +#endif //_FOOBAR2000_PLAYABLE_LOCATION_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playback_core.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/playback_core.h new file mode 100644 index 000000000..8021eccd0 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playback_core.h @@ -0,0 +1,177 @@ +#ifndef _PLAYBACK_CORE_H_ +#define _PLAYBACK_CORE_H_ + +#include "service.h" +#include "metadb_handle.h" +#include "replaygain.h" +#include "output_manager.h" + +struct playback_config +{ + enum dsp_mode_t + { + DSP_DEFAULT,//DSP enabled, use core settings + DSP_DISABLED, + DSP_CUSTOM,//DSP enabled, use custom settings + }; + + replaygain::mode_t replaygain_mode; + dsp_mode_t dsp_mode; + int process_total_time_counter;//boolean + int low_priority;//boolean + int process_dynamic_info;//boolean + + + + struct + { + unsigned int count; + const GUID * guids; + } dsp_custom;//valid only if dsp_mode = DSP_CUSTOM + + output_config output; + + playback_config() + { + replaygain_mode = replaygain::MODE_DEFAULT; + dsp_mode = DSP_DEFAULT; + dsp_custom.count = 0; + dsp_custom.guids = 0; + process_total_time_counter = 0; + low_priority = 0; + process_dynamic_info = 0; + } +}; + + +class NOVTABLE playback_core : public service_base +{ +public: + + struct track//reminder: if you pass this around, functions you call will not free the metadb_handle; if you return this, make sure you handle_add_ref(), because the code calling you will be responsible for freeing + { + metadb_handle * handle; + int user; + }; + + + class NOVTABLE callback + { + public: + enum file_error_handler + { + file_error_abort, + file_error_continue, + file_error_replace + }; + virtual bool get_next_track(track * out)=0;//return false if end-of-playlist, true if out struct is filled with data + virtual void on_file_open(const track * src) {}//called before attempting file open; use only for logging etc + virtual void on_file_open_success(const track * ptr) {} + virtual file_error_handler on_file_error(const track * src,track * replace) {return file_error_abort;} + virtual void on_track_change(const track * ptr) {};//called when currently played track has changed, some time after get_next_track + virtual void on_dynamic_info(const file_info * info,bool b_track_change) {} + virtual void on_exiting(bool error) {};//called when terminating (either end-of-last-track or some kind of error or stop()) + + //DO NOT call any playback_core methods from inside callback methods ! + //all callback methods are called from playback thread, you are responsible for taking proper anti-deadlock measures (eg. dont call SendMessage() directly) + //safest way to handle end-of-playback: create a window from main thread, PostMessage to it when you get callbacks, execute callback handlers (and safely call playback_core api) from message handlers + }; + + class NOVTABLE vis_callback + { + public: + virtual void on_data(class audio_chunk * chunk,double timestamp)=0;//timestamp == timestamp of first sample in the chunk, according to get_cur_time_fromstart() timing + virtual void on_flush()=0; + }; + + struct stats + { + double decoding_position,playback_position,dsp_latency,output_latency; + }; + + + //MUST be called first, immediately after creation (hint: create() does this for you) + virtual void set_callback(callback * ptr)=0; + + virtual void set_vis_callback(vis_callback * ptr)=0;//optional + + virtual void set_config(const playback_config * data)=0;//call before starting playback + + virtual void start()=0; + virtual void stop()=0; + virtual bool is_playing()=0; + virtual bool is_finished()=0; + virtual bool is_paused()=0; + virtual void pause(int paused)=0; + + virtual bool can_seek()=0; + virtual void seek(double time)=0; + virtual void seek_delta(double time_delta)=0; + + virtual double get_cur_time()=0; + virtual double get_cur_time_fromstart()=0; + virtual bool get_cur_track(track * out)=0; + virtual bool get_stats(stats * out)=0; + + + metadb_handle * get_cur_track_handle() + { + track t; + if (get_cur_track(&t)) return t.handle; + else return 0; + } + + double get_total_time() + { + double rv = 0; + metadb_handle * ptr = get_cur_track_handle(); + if (ptr) + { + rv = ptr->handle_get_length(); + ptr->handle_release(); + } + return rv; + } + + static playback_core * create(callback * cb) + { + playback_core * ptr = service_enum_create_t(playback_core,0); + if (ptr) ptr->set_callback(cb); + return ptr; + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE play_sound : public service_base +{ +public: + enum + { + USE_REPLAYGAIN = 1, + USE_DSP = 2, + }; + + virtual void play(metadb_handle * file,const playback_config * settings=0)=0;//settings are optional; if non-zero, they will be passed to playback_core being used + virtual void stop_all()=0; + + static play_sound * get() {return service_enum_create_t(play_sound,0);}//safe not to release + + static void g_play(metadb_handle * file,const playback_config * settings) + { + play_sound * ptr = get(); + if (ptr) ptr->play(file,settings); + } + + static void g_stop_all() + { + play_sound * ptr = get(); + if (ptr) ptr->stop_all(); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist.cpp new file mode 100644 index 000000000..5eac144c9 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist.cpp @@ -0,0 +1,145 @@ +#include "foobar2000.h" + +void playlist_oper::move_items(int delta) +{ + if (delta==0) return; + + int count = get_count(); + int n; + + mem_block_t order(count); + mem_block_t selection(count); + + for(n=0;n0;delta--) + { + int idx; + for(idx=count-2;idx>=0;idx--) + { + if (selection[idx] && !selection[idx+1]) + { + order.swap(idx,idx+1); + selection.swap(idx,idx+1); + } + } + } + } + + apply_order(order,count); +} +/* +void playlist_callback::on_order(const int * order,int count) +{ + int n; + for(n=0;nget_focus(); + if (focus>=0 && order[focus]!=focus) on_focus_change(order[focus],focus); +} +*/ +playlist_oper * playlist_oper::get() +{//since this is called really often, lets cache a pointer instead of flooding service core + static playlist_oper * g_ptr; + if (g_ptr==0) g_ptr = service_enum_create_t(playlist_oper,0); + return g_ptr; +} + +void playlist_oper::remove_sel(bool crop) +{ + bit_array_bittable mask(get_count()); + get_sel_mask(mask); + if (crop) remove_mask(bit_array_not(mask)); + else remove_mask(mask); +} + +unsigned playlist_switcher::find_playlist(const char * name) +{ + unsigned n,max = get_num_playlists(); + string8_fastalloc temp; + for(n=0;n=num || num<=1) return false; + if (idx==active) + { + if (idx+1>=num) active = idx-1; + else active = idx+1; + set_active_playlist(active); + } + return delete_playlist(idx); +} + +bool playlist_switcher::find_or_create_playlist_activate(const char * name) +{ + bool rv = false; + unsigned idx = find_or_create_playlist(name); + if (idx != (unsigned)(-1)) + rv = set_active_playlist(idx); + return rv; +} + +int playback_flow_control::get_next(int previous_index,int focus_item,int total,int advance,bool follow_focus,bool user_advance,unsigned playlist) +{ + int rv = -1; + playback_flow_control_v2 * this_v2 = service_query_t(playback_flow_control_v2,this); + if (this_v2) + { + rv = this_v2->get_next(previous_index,focus_item,total,advance,follow_focus,user_advance,playlist); + this_v2->service_release(); + } + else + { + console::error(uStringPrintf("\"%s\" needs to be updated to 0.8 SDK or newer in order to function.",get_name())); + } + return rv; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist.h new file mode 100644 index 000000000..888a9407e --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist.h @@ -0,0 +1,173 @@ +#ifndef _PLAYLIST_H_ +#define _PLAYLIST_H_ + +#include "service.h" +#include "metadb_handle.h" +#include "play_control.h" +#include "interface_helper.h" + +//important: playlist engine is SINGLE-THREADED. call any APIs not from main thread and things will either blow up or refuse to work. all callbacks can be assumed to come from main thread. + + +//notes: +//all methods returning metadb_handle return add_ref'd handles, you have to handle_release them +//all methods taking metadb_handle will add_ref them if they store them, so it's your responsibility to later release handles you pass + +class NOVTABLE playlist_oper : public service_base +{ +public: + //retrieving info + virtual int get_count()=0; + virtual bool get_sel(int idx)=0;//returns reference to a static object that holds state of playlist selection + virtual bool get_sel_mask(bool * out,unsigned count)=0; + virtual void get_sel_mask(bit_array_var & out); + virtual metadb_handle * get_item(int index)=0; + virtual int get_now_playing()=0;//will return -1 when not playing or currently played track isn't on playlist + virtual int get_focus()=0; + virtual int get_playback_cursor()=0; + virtual void format_title(int idx,string_base & out,const char * spec,const char * extra_items)=0;//spec may be null, will use core settings; extra items are optional + virtual void get_format_spec(string_base & out)=0; + + //modifying playlist + virtual void set_sel_mask(const bit_array & sel,const bit_array & mask)=0; + virtual void remove_mask(const bit_array & items)=0; + virtual void replace_item(int idx,metadb_handle * handle)=0; + virtual void set_focus(int idx)=0; + virtual void add_items(const ptr_list_base & data,bool replace = false,int insert_idx = -1,bool select = false,bool filter = true)=0; + //data - entries to insert, replace = replace-current-playlist flag, insert_idx - where to insert (-1 will append them), select - should new items be selected or not + virtual void add_locations(const ptr_list_base & urls,bool replace = false,int insert_idx = -1,bool select = false,bool filter = true)=0; + + virtual void apply_order(const int * order,int count)=0; + virtual void sort_by_format(const char * spec,int sel_only)=0;//spec==0 => randomizes + virtual void set_playback_cursor(int idx)=0; + virtual metadb_handle * playback_advance(play_control::track_command cmd)=0;//deprecated in 0.8 + virtual void undo_restore()=0; + virtual void undo_reset()=0; + virtual void ensure_visible(int idx)=0; + + //other + virtual void play_item(int idx)=0; + + + //new (0.8) + virtual bool process_locations(const ptr_list_base & urls,ptr_list_base & out,bool filter = true,const char * mask = 0)=0; + virtual bool process_dropped_files(interface IDataObject * pDataObject,ptr_list_base & out,bool filter = true)=0; + virtual bool process_dropped_files_check(interface IDataObject * pDataObject)=0; + virtual interface IDataObject * create_dataobject(const ptr_list_base & data)=0; + virtual void get_sel_items(ptr_list_base & out)=0; + virtual int get_sel_count()=0; + virtual void get_items_mask(ptr_list_base & out, const bit_array & mask)=0; + + //helper + + inline void add_location(const char * url,bool replace = false,int insert_idx = -1,bool select = false,bool filter = true) + { + ptr_list_t temp; + temp.add_item(url); + add_locations(temp,replace,insert_idx,select,filter); + } + + inline void set_sel_mask(const bit_array & sel) {set_sel_mask(sel,bit_array_true());} + inline void set_sel(int idx,bool state) {set_sel_mask(bit_array_val(state),bit_array_one(idx));} + inline void remove_item(int idx) {remove_mask(bit_array_one(idx));} + inline void set_focus_sel(int idx) {set_focus(idx);set_sel_mask(bit_array_one(idx));} + inline void reset() {remove_mask(bit_array_true());} + inline void remove_all() {remove_mask(bit_array_true());} + inline void set_sel_one(int idx) {set_sel_mask(bit_array_one(idx));} + + inline bool is_sel_count_greater(int v) + { + return get_sel_count()>v; + } + + + + void remove_sel(bool crop); + + void move_items(int delta); + + static playlist_oper * get(); + + inline metadb_handle * get_focus_item() + { + return get_item(get_focus());//may return null + } + + void get_data(ptr_list_interface & out) + { + get_items_mask(out,bit_array_true()); + } + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + + +//note: certain methods may get called outside initquit ! +//playlist_callback methods are called by playlist engine. +class NOVTABLE playlist_callback : public service_base +{ +public: + virtual void on_items_added(int start, int count)=0;//inside any of these methods, you can call playlist_oper APIs to get exact info about what happened (but only methods that read playlist state, not those that modify it) + virtual void on_order(const int * order,int count)=0;//changes selection too; doesnt actually change set of items that are selected or item having focus, just changes their order + virtual void on_items_removing(const bit_array & mask)=0;//called before actually removing them + virtual void on_items_removed(const bit_array & mask)=0;//note: items being removed are de-selected first always + virtual void on_sel_change(int idx,bool state)=0; + virtual void on_sel_change_multi(const bit_array & before,const bit_array & after,int count)=0; + virtual void on_focus_change(int from,int to)=0;//focus may be -1 when no item has focus; reminder: focus may also change on other callbacks + virtual void on_modified(int idx)=0; + virtual void on_replaced(int idx) {on_modified(idx);} + virtual void on_ensure_visible(int idx) {} + virtual void on_default_format_changed() {} + //note: if you cache strings or whatever, make sure to flush cache when total item count changes, because stuff like %_playlist_total% may change as well (not to mention %_playlist_number% everywhere) + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE playback_flow_control : public service_base +{ +public: + virtual const char * get_name()=0; + + virtual int get_next(int previous_index,int focus_item,int total,int advance,bool follow_focus,bool user_advance) {return -1;}//deprecated + + int get_next(int previous_index,int focus_item,int total,int advance,bool follow_focus,bool user_advance,unsigned playlist); + + //int advance : -1 for prev, 0 for play, 1 for next + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } +}; + +class NOVTABLE playback_flow_control_v2 : public playback_flow_control +{ +public: + virtual int get_next(int previous_index,int focus_item,int total,int advance,bool follow_focus,bool user_advance,unsigned playlist)=0; + //previous_index and focus_item may be -1; return -1 to stop + //IMPORTANT (changed in 0.8): you are in playlist indicated by , use playlist_switcher methods to access data + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return playback_flow_control::service_query(guid); + } + +}; + +template +class playback_flow_control_factory : public service_factory_single_t {}; + +//helper code for manipulating configuration of playback flow control (repeat/shuffle/whatever) => see ../helpers/playback_order_helper.h + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_entry.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_entry.h new file mode 100644 index 000000000..197bd0063 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_entry.h @@ -0,0 +1,15 @@ +#ifndef _PLAYLIST_ENTRY_H_ +#define _PLAYLIST_ENTRY_H_ + +//DEPRECATED (or rather, renamed to playable_location to prevent further confusion with playlist-related operations) + +#include "playable_location.h" + +//backwards-compatibility defines + +#define playlist_entry playable_location +#define playlist_entry_i playable_location_i +#define make_playlist_entry make_playable_location + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_loader.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_loader.cpp new file mode 100644 index 000000000..3c5a96df9 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_loader.cpp @@ -0,0 +1,220 @@ +#include "foobar2000.h" + +int playlist_loader::load_playlist(const char * p_filename,playlist_loader_callback * callback) +{ + TRACK_CALL_TEXT("playlist_loader::load_playlist"); + string8 filename = file_path_canonical(p_filename); + service_enum_t e; + playlist_loader * l; + + string_extension_8 extension(filename); + + bool found = 0; + reader * r = 0; + + for(l=e.first();l && !found;l = e.next()) + { + if (!stricmp_utf8(l->get_extension(),extension)) + { + found = 1; + if (r==0) + r = file::g_open(filename,reader::MODE_READ); + if (r) + { + r->seek(0); + int rv=l->open(filename,r,callback); + if (!rv) found=0; + } + } + l->service_release(); + } + if (r) r->reader_release(); + return found ? 1 : 0; +} + +void playlist_loader::process_path(const char * p_filename,playlist_loader_callback * callback,playlist_loader_callback::entry_type type) +{ + TRACK_CALL_TEXT("playlist_loader::process_path"); + file_path_canonical filename(p_filename); + if (!callback->on_progress(0)) return; + + { + directory_callback_i dir_list; + if (directory::g_list(filename,&dir_list,callback)) + { + unsigned n; + for(n=0;non_progress(0)) break; + } + return; + } + + bool found = false; + + + service_enum_t e; + archive * d; + for(d=e.first();d;d=e.next()) + { + int rv; + rv = d->list(filename,&dir_list,callback); + + if (rv) + { + unsigned n; + for(n=0;non_progress(0)) break; + } + + if (!callback->on_progress(0)) break; + d->precache(filename,callback); + + found = true; + } + d->service_release(); + if (found) break; + + if (!callback->on_progress(0)) break; + } + + if (found || !callback->on_progress(0)) return; + + } + +// if (input::g_test_filename(filename)) + { + track_indexer::g_get_tracks_wrap(filename,callback,type,0); + } +} + +int playlist_loader::save_playlist(const char * p_filename,const ptr_list_base & data) +{ + TRACK_CALL_TEXT("playlist_loader::save_playlist"); + string8 filename = file_path_canonical(p_filename); + reader * r = file::g_open(filename,reader::MODE_WRITE_NEW); + if (!r) return 0; + int rv = 0; + + string_extension ext(filename); + + service_enum_t e; + playlist_loader * l; + for(l=e.first();l;l = e.next()) + { + if (l->can_write() && !stricmp_utf8(ext,l->get_extension()) && l->write(filename,r,data)) + { + rv=1; + break; + } + l->service_release(); + } + + r->reader_release(); + + if (!rv) file::g_remove(filename); + + return rv; +} + +int track_indexer::g_get_tracks_callback(const char * filename,callback * out,reader * r) +{ + TRACK_CALL_TEXT("track_indexer::g_get_tracks_callback"); + service_enum_t e; + track_indexer * t; + + for(t=e.first();t;t = e.next()) + { + int rv; + rv = t->get_tracks(filename,out,r); + t->service_release(); + if (rv>0) return rv; + } + out->on_entry(make_playable_location(filename,0));//assume single track if noone reports + return 0; +} + + +int track_indexer::get_tracks_ex(const char * filename,ptr_list_base & out,reader * r) +{ + { + track_indexer_v2 * this_v2 = service_query_t(track_indexer_v2,this); + if (this_v2) + { + int rv = this_v2->get_tracks_ex(filename,out,r); + this_v2->service_release(); + return rv; + } + } + + return get_tracks(filename,&callback_i_metadb(out),r); +} + +int track_indexer::g_get_tracks_ex(const char * filename,ptr_list_base & out,reader * r) +{ + TRACK_CALL_TEXT("track_indexer::g_get_tracks_ex"); + service_enum_t e; + track_indexer * t; + + for(t=e.first();t;t = e.next()) + { + int rv; + rv = t->get_tracks_ex(filename,out,r); + t->service_release(); + if (rv>0) return rv; + } + out.add_item(metadb::get()->handle_create(make_playable_location(filename,0)));//assume single track if noone reports + return 0; +} + + +int track_indexer::g_get_tracks_wrap(const char * filename,playlist_loader_callback * out,playlist_loader_callback::entry_type type,reader * r) +{ + service_enum_t e; + track_indexer * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + int rv = 0; + track_indexer_v2 * ptr_v2 = service_query_t(track_indexer_v2,ptr); + if (ptr_v2) + { + metadb_handle_list temp; + rv = ptr_v2->get_tracks_ex(filename,temp,r); + ptr_v2->service_release(); + if (rv>0) + { + unsigned n, m = temp.get_count(); + for(n=0;non_entry_dbhandle(temp[n],type); + } + temp.delete_all(); + } + else + { + rv = ptr->get_tracks(filename,&callback_i_wrap(out,type),r); + } + ptr->service_release(); + if (rv>0) return rv; + } + + out->on_entry(make_playable_location(filename,0),type); + return 0; + +} + + +bool playlist_loader::is_our_content_type(const char * param) +{ + bool rv = false; + playlist_loader_v2 * this_v2 = service_query_t(playlist_loader_v2,this); + if (this_v2) + { + rv = this_v2->is_our_content_type(param); + this_v2->service_release(); + } + return rv; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_loader.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_loader.h new file mode 100644 index 000000000..93402e3ce --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_loader.h @@ -0,0 +1,188 @@ +#ifndef _PLAYLIST_LOADER_H_ +#define _PLAYLIST_LOADER_H_ + +#include "service.h" + +#include "reader.h" + +#include "metadb.h" + +class NOVTABLE playlist_loader_callback //receives new playlist entries from playlists/filesystem/whatever +{ +public: + enum entry_type + { + USER_REQUESTED, + DIRECTORY_ENUMERATED, + FROM_PLAYLIST, + }; + virtual int on_progress(const char * path) {return 1;} + //for monitoring progress only, return 1 to continue, 0 to abort; note that you will most likely get called a few times after first 0 return + //path might be null if playlist loader is just checking if you are aborting or not + + virtual void on_entry(const playable_location * src,entry_type type)=0; + virtual void on_entry_have_info(const file_info * src,entry_type type) {on_entry(src->get_location(),type);} + virtual void on_entry_dbhandle(metadb_handle * ptr,entry_type type) {on_entry(ptr->handle_get_location(),type);} +}; + +class playlist_loader_callback_i : public playlist_loader_callback +{ + metadb_handle_list data; +public: + + ~playlist_loader_callback_i() {data.delete_all();} + + metadb_handle * get_item(unsigned idx) {return data[idx];} + metadb_handle * operator[](unsigned idx) {return data[idx];} + unsigned get_count() {return data.get_count();} + + const metadb_handle_list & get_data() {return data;} + + virtual int on_progress(const char * path) {return 1;} + virtual void on_entry(const playable_location * src,entry_type type) + {data.add_item(metadb::get()->handle_create(src));} + virtual void on_entry_have_info(const file_info * src,entry_type type) + {data.add_item(metadb::get()->handle_create_hint(src));} + virtual void on_entry_dbhandle(metadb_handle * ptr,entry_type type) + {data.add_item(ptr->handle_duplicate());} +}; + +class NOVTABLE playlist_loader : public service_base +{ +public: + virtual int open(const char * filename, reader * r,playlist_loader_callback * callback)=0; //send new entries to callback + virtual int write(const char * filename, reader * r,const ptr_list_base & data)=0; + virtual const char * get_extension()=0; + virtual bool can_write()=0; + bool is_our_content_type(const char*); + + static int load_playlist(const char * filename,playlist_loader_callback * callback); + //attempts to load file as a playlist, return 0 on failure + + static int save_playlist(const char * filename,const ptr_list_base & data); + //saves playlist into file + + static void process_path(const char * filename,playlist_loader_callback * callback,playlist_loader_callback::entry_type type = playlist_loader_callback::USER_REQUESTED); + //adds contents of filename (can be directory) to playlist, doesnt load playlists + + //this helper also loads playlists + //return 1 if loaded as playlist, 0 if loaded as files + static int process_path_ex(const char * filename,playlist_loader_callback * callback,playlist_loader_callback::entry_type type = playlist_loader_callback::USER_REQUESTED) + { + if (!load_playlist(filename,callback)) + { + process_path(filename,callback,type); + return 0; + } + else return 1; + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE playlist_loader_v2 : public playlist_loader +{ +public: + virtual bool is_our_content_type(const char * param) = 0; + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE track_indexer : public service_base +{ +public: + + class NOVTABLE callback + { + public: + virtual void on_entry(const playable_location * src)=0; + }; + + class callback_i : public callback + { + public: + ptr_list_t data; + virtual void on_entry(const playable_location * src) {data.add_item(new playable_location_i(*src));} + ~callback_i() {data.delete_all();} + }; + + class callback_i_ref : public callback + { + ptr_list_t &data; + public: + virtual void on_entry(const playable_location * src) {data.add_item(new playable_location_i(*src));} + callback_i_ref(ptr_list_t &p_data) : data(p_data) {} + }; + + class callback_i_wrap : public callback + { + playlist_loader_callback * out; + playlist_loader_callback::entry_type type; + public: + virtual void on_entry(const playable_location * src) {out->on_entry(src,type);} + callback_i_wrap(playlist_loader_callback * p_out,playlist_loader_callback::entry_type p_type) : out(p_out), type(p_type) {} + }; + + class callback_i_metadb : public callback + { + ptr_list_base & out; + metadb * p_metadb; + public: + virtual void on_entry(const playable_location * src) {out.add_item(p_metadb->handle_create(src));} + callback_i_metadb(ptr_list_base & p_out) : out(p_out), p_metadb(metadb::get()) {} + }; + +public: + virtual int get_tracks(const char * filename,callback* out,reader * r)=0;//return 0 on failure / not our file, 1 on success; send your subsongs to out; reader CAN BE NULL, if so, create/destroy your own one + //return either playlist entries with same filename, or playlist entries belonging to a readerless input (eg. cdda://) + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static int g_get_tracks_callback(const char * filename,callback * out,reader * r=0); + static int g_get_tracks(const char * filename,ptr_list_t & out,reader * r=0) + { + return g_get_tracks_callback(filename,&callback_i_ref(out),r); + } + + static int g_get_tracks_wrap(const char * filename,playlist_loader_callback * out,playlist_loader_callback::entry_type type,reader * r=0); + int get_tracks_ex(const char * filename,ptr_list_base & out,reader * r = 0); + static int g_get_tracks_ex(const char * filename,ptr_list_base & out,reader * r = 0); + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return service_base::service_query(guid); + } +}; + +class NOVTABLE track_indexer_v2 : public track_indexer +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + //since you usually have to parse the damn file anyway, here's a method that lets you precache info to database already to avoid redundant file operations later + virtual int get_tracks_ex(const char * filename,ptr_list_base & out,reader * r = 0)=0;//return 0 on failure / not our file, 1 on success; send your subsongs to out; reader CAN BE NULL, if so, create/destroy your own one + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return track_indexer::service_query(guid); + } + +}; + +template +class track_indexer_factory : public service_factory_t {}; + + +#endif //_PLAYLIST_LOADER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_switcher.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_switcher.h new file mode 100644 index 000000000..06da2d690 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/playlist_switcher.h @@ -0,0 +1,66 @@ +#ifndef _FOOBAR2000_PLAYLIST_SWITCHER_ +#define _FOOBAR2000_PLAYLIST_SWITCHER_ + + +//all calls from main app thread only ! + +class NOVTABLE playlist_switcher : public service_base +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual unsigned get_num_playlists()=0; + virtual bool get_playlist_name(unsigned idx,string_base & out)=0; + virtual bool get_playlist_data(unsigned idx,ptr_list_interface & out)=0; + virtual unsigned get_playlist_size(unsigned idx)=0;//returns number of entries + virtual bool get_playlist_selection_mask(unsigned idx,bit_array_var & out)=0; + virtual unsigned get_active_playlist()=0; + + virtual bool set_active_playlist(unsigned idx)=0; + virtual unsigned create_playlist(const char * name,const ptr_list_interface & data)=0;//returns index (or 0 on failure; index is always >0 because there is always at least one playlist present) + virtual unsigned create_playlist_fixname(string_base & name,const ptr_list_interface & data)=0;//name may change when playlist of this name is already present or passed name contains invalid chars; returns index (or 0 on failure; index is always >0 because there is always at least one playlist present) + virtual bool delete_playlist(unsigned idx)=0;//will fail if you are trying to delete only playlist, or currently active playlist + virtual bool reorder(const int * order,unsigned count)=0; + virtual bool rename_playlist(unsigned idx,const char * new_name)=0;//will fail if name exists or contains invalid chars + virtual bool rename_playlist_fixname(unsigned idx,string_base & name)=0;//will attempt to correct the name before failing + + virtual metadb_handle * get_item(unsigned playlist,unsigned idx)=0; + virtual bool format_title(unsigned playlist,unsigned idx,string_base & out,const char * spec,const char * extra_items)=0;//spec may be null, will use core settings; extra items are optional + + //new (0.8) + virtual unsigned get_playing_playlist()=0; + virtual metadb_handle * playback_advance(play_control::track_command cmd,unsigned * p_playlist,unsigned * p_item,bool * b_is_active_playlist)=0;//deprecated in 0.8 + virtual void reset_playing_playlist()=0; + virtual void highlight_playing_item()=0; + + static playlist_switcher * get(); + + unsigned find_playlist(const char * name);//returns ((unsigned)-1) when not found + unsigned find_or_create_playlist(const char * name); + bool find_or_create_playlist_activate(const char * name); + bool delete_playlist_autoswitch(unsigned idx); +}; + +class playlist_switcher_callback : public service_base +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual void on_playlist_switch_before(unsigned from,unsigned to)=0;//called before switching + virtual void on_playlist_switch_after(unsigned from,unsigned to)=0;//called after switching + + virtual void on_reorder(const int * order,unsigned count)=0; + virtual void on_new_playlist(const char * name,unsigned idx,const ptr_list_interface & data)=0; + virtual void on_delete_playlist(unsigned idx)=0; + virtual void on_rename_playlist(unsigned idx,const char * new_name)=0; + + virtual void on_item_replaced(unsigned pls,unsigned item,metadb_handle * from,metadb_handle * to)=0;//workaround for inactive-playlist-needs-modification-when-using-masstagger-autorename; does not work for active playlist ! +}; + +template +class playlist_switcher_callback_factory : public service_factory_single_t {}; + + +#endif//_FOOBAR2000_PLAYLIST_SWITCHER_ diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/reader.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader.cpp new file mode 100644 index 000000000..49169a762 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader.cpp @@ -0,0 +1,709 @@ +#include "foobar2000.h" + + +reader * unpacker::g_open(reader * p) +{ + service_enum_t e; + unpacker * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + p->seek(0); + reader * r = ptr->open(p); + ptr->service_release(); + if (r) return r; + } + return 0; + +} + +bool reader::seek2(__int64 position,int mode) +{ + switch(mode) + { + case SEEK_CUR: + { + __int64 delta = get_position(); + if (delta<0) return false; + position+=delta; + } + break; + case SEEK_END: + { + __int64 delta = get_length(); + if (delta<0) return false; + position+=delta; + } + break; + } + return seek(position); +} + +__int64 reader::transfer(reader * src,reader * dst,__int64 bytes) +{ + enum{BUFSIZE = 1024*1024}; + mem_block temp; + void* ptr = temp.set_size((int)(BUFSIZEBUFSIZE) delta = BUFSIZE; + delta = src->read(ptr,(int)delta); + if (delta<=0) break; + delta = dst->write(ptr,(int)delta); + if (delta<=0) break; + done += delta; + + } + return done; +} + + +void file::g_get_canonical_path(const char * path,string_base & out) +{ + service_enum_t e; + file * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + int rv = ptr->get_canonical_path(path,out); + ptr->service_release(); + if (rv) return; + } + //fucko: noone wants to process this, lets copy over + out.set_string(path); +} + +void file::g_get_display_path(const char * path,string_base & out) +{ + file * ptr = g_get_interface(path); + if (ptr==0) + { + //fucko: noone wants to process this, lets copy over + out.set_string(path); + } + else + { + if (!ptr->get_display_path(path,out)) + out.set_string(path); + ptr->service_release(); + } +} + +file * file::g_get_interface(const char * path) +{ + service_enum_t e; + file * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->is_our_path(path)) + return ptr; + ptr->service_release(); + } + return 0; +} + +reader * file::g_get_reader(const char * path) +{ + file * ptr = g_get_interface(path); + if (ptr==0) return 0; + reader * r = ptr->get_reader(path); + ptr->service_release(); + if (r==0) return 0; + return r; +} + +reader * file::g_open(const char * path,reader::MODE mode) +{ + string8 path_c; + g_get_canonical_path(path,path_c); + file * ptr = g_get_interface(path_c); + if (ptr==0) return 0; + reader * r = ptr->get_reader(path_c); + ptr->service_release(); + if (r!=0) + { + if (r->open(path_c,mode)==0) + { + r->reader_release(); + r=0; + } + } + return r; +} + +int file::g_exists(const char * path) +{ + string8 path_c; + g_get_canonical_path(path,path_c); + file * ptr = g_get_interface(path_c); + if (ptr==0) return 0; + int rv = ptr->exists(path_c); + ptr->service_release(); + return rv; +} + +int file::g_remove(const char * path) +{ + string8 path_c; + g_get_canonical_path(path,path_c); + file * ptr = g_get_interface(path_c); + if (ptr==0) return 0; + int rv = ptr->remove(path_c); + ptr->service_release(); + return rv; +} + +int file::g_create_directory(const char * path) +{ + string8 path_c; + g_get_canonical_path(path,path_c); + file * ptr = g_get_interface(path_c); + if (ptr==0) return 0; + int rv = ptr->create_directory(path_c); + ptr->service_release(); + return rv; +} + +int file::g_move(const char * src,const char * dst) +{ + service_enum_t e; + file * ptr; + int rv = 0; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->is_our_path(src) && ptr->is_our_path(dst)) + { + rv = ptr->move(src,dst); + } + ptr->service_release(); + if (rv) break; + } + return rv; +} + +int file::g_move_ex(const char * _src,const char * _dst) +{ + string8 src,dst; + g_get_canonical_path(_src,src); + g_get_canonical_path(_dst,dst); + + service_enum_t e; + file * ptr; + int rv = 0; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (ptr->is_our_path(src) && ptr->is_our_path(dst)) + { + rv = ptr->move(src,dst); + } + ptr->service_release(); + if (rv) break; + } + return rv; +} + +int directory::g_list(const char * path,directory_callback * out,playlist_loader_callback * callback,bool b_recur) +{ + service_enum_t e; + directory * d; + for(d=e.first();d;d=e.next()) + { + int rv; + rv = d->list(path,out,callback,b_recur); + d->service_release(); + if (rv) return 1; + if (callback && !callback->on_progress(0)) break; + } + return 0; +} + + +static void path_pack_string(string8 & out,const char * src) +{ + out.add_char('|'); + out.add_int(strlen(src)); + out.add_char('|'); + out.add_string(src); + out.add_char('|'); +} + +static int path_unpack_string(string8 & out,const char * src) +{ + int ptr=0; + if (src[ptr++]!='|') return -1; + int len = atoi(src+ptr); + if (len<=0) return -1; + while(src[ptr]!=0 && src[ptr]!='|') ptr++; + if (src[ptr]!='|') return -1; + ptr++; + int start = ptr; + while(ptr-startdont_read_infos(path)) + { + ptr->service_release(); + return 0; + } + reader * r = ptr->get_reader(path_c); + ptr->service_release(); + if (r!=0) + { + if (r->open(path_c,reader::MODE_READ)==0) + { + r->reader_release(); + r=0; + } + } + return r; +} + +int file::g_dont_read_infos(const char * path) +{ + int rv = -1; + file * ptr = g_get_interface(path); + if (ptr) + { + rv = ptr->dont_read_infos(path); + ptr->service_release(); + } + return rv; +} + + + +bool reader_backbuffer_wrap::seek(__int64 position) +{ + if (aborting) return false; + if (position>reader_pos) + { + if (position > reader_pos + buffer.get_size()) + { + reader_pos = position - buffer.get_size(); + m_reader->seek(reader_pos); + buffered = 0; + } + + read_pos = reader_pos; + __int64 skip = (position-reader_pos); + char temp[256]; + while(skip>0) + { + __int64 delta = sizeof(temp); + if (delta>skip) delta=skip; + if (read(temp,(int)delta)!=delta) return false; + skip-=delta; + } + return true; + } + else if (reader_pos-position>(__int64)buffered) + { + read_pos = reader_pos = position; + m_reader->seek(reader_pos); + buffered = 0; + return true; + } + else + { + read_pos = position; + return true; + } +} + +int file::g_relative_path_create(const char * file_path,const char * playlist_path,string_base & out) +{ + file * ptr = g_get_interface(file_path); + int rv = 0; + if (ptr) + { + rv = ptr->relative_path_create(file_path,playlist_path,out); + ptr->service_release(); + } + return rv; +} + +int file::g_relative_path_parse(const char * relative_path,const char * playlist_path,string_base & out) +{ + service_enum_t e; + file * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + int rv = ptr->relative_path_parse(relative_path,playlist_path,out); + ptr->service_release(); + if (rv) return rv; + } + return 0; +} + + + +int archive_i::get_canonical_path(const char * path,string_base & out) +{ + if (is_our_path(path)) + { + out.set_string(path); + return 1; + } + else return 0; +} + +int archive_i::is_our_path(const char * path) +{ + if (strncmp(path,"unpack://",9)) return 0; + const char * type = get_archive_type(); + path += 9; + while(*type) + { + if (*type!=*path) return 0; + type++; + path++; + } + if (*path!='|') return 0; + return 1; +} + +int archive_i::get_display_path(const char * path,string_base & out) +{ + string8 archive,file; + if (parse_unpack_path(path,archive,file)) + { + g_get_display_path(archive,out); + out.add_string("|"); + out.add_string(file); + return 1; + } + else return 0; +} + +int archive_i::exists(const char * path) +{ + string8 archive,file; + if (parse_unpack_path(path,archive,file)) + { + if (g_exists(archive)) + { + if (g_dont_read_infos(archive)) return 1; + else return exists_in_archive(archive,file); + } + } + return 0; +} + +int archive_i::remove(const char * path) +{ + return 0; +} + +int archive_i::move(const char * src,const char * dst) +{ + return 0; +} + +int archive_i::dont_read_infos(const char * src) +{ + string8 archive,file; + if (parse_unpack_path(src,archive,file)) + { + return g_dont_read_infos(archive); + } + else return 1; +} + +int archive_i::relative_path_create(const char * file_path,const char * playlist_path,string_base & out) +{ + string8 archive,file; + if (parse_unpack_path(file_path,archive,file)) + { + string8 archive_rel; + if (g_relative_path_create(archive,playlist_path,archive_rel)) + { + string8 out_path; + make_unpack_path(out_path,archive_rel,file); + out.set_string(out_path); + return 1; + } + } + return 0; +} + +int archive_i::relative_path_parse(const char * relative_path,const char * playlist_path,string_base & out) +{ + if (!is_our_path(relative_path)) return 0; + string8 archive_rel,file; + if (parse_unpack_path(relative_path,archive_rel,file)) + { + string8 archive; + if (g_relative_path_parse(archive_rel,playlist_path,archive)) + { + string8 out_path; + make_unpack_path(out_path,archive,file); + out.set_string(out_path); + return 1; + } + } + return 0; +} + +// "unpack://zip|17|file://c:\unf.rar|meh.mp3" + +bool archive_i::parse_unpack_path(const char * path,string8 & archive,string8 & file) +{ + path = strchr(path,'|'); + if (!path) return false; + int delta = path_unpack_string(archive,path); + if (delta<0) return false; + path += delta; + file = path; + return true; +} + +void archive_i::make_unpack_path(string8 & path,const char * archive,const char * file,const char * name) +{ + path = "unpack://"; + path += name; + path_pack_string(path,archive); + path += file; +} + +void archive_i::make_unpack_path(string8 & path,const char * archive,const char * file) {make_unpack_path(path,archive,file,get_archive_type());} + + +FILE * file::streamio_open(const char * path,const char * flags) +{ + FILE * ret = 0; + string8 temp; + g_get_canonical_path(path,temp); + if (!strncmp(temp,"file://",7)) + { + ret = _wfopen(string_wide_from_utf8(path+7),string_wide_from_utf8(flags)); + } + return ret; +} + +void reader::reader_release_safe() +{ + reader_release(); +/* try { + if (this) reader_release(); + } catch(...) {}*/ +} +#if 0 + +bool reader::read_byte(BYTE & val) +{ + return read(&val,sizeof(val))==sizeof(val); +} + +bool reader::read_word(WORD & val) +{ + return read(&val,sizeof(val))==sizeof(val); +} + +bool reader::read_dword(DWORD & val) +{ + return read(&val,sizeof(val))==sizeof(val); +} + +bool reader::read_qword(QWORD & val) +{ + return read(&val,sizeof(val))==sizeof(val); +} + +bool reader::write_byte(BYTE val) +{ + return write(&val,sizeof(val))==sizeof(val); +} + +bool reader::write_word(WORD val) +{ + return write(&val,sizeof(val))==sizeof(val); +} + +bool reader::write_dword(DWORD val) +{ + return write(&val,sizeof(val))==sizeof(val); +} + +bool reader::write_qword(QWORD val) +{ + return write(&val,sizeof(val))==sizeof(val); +} + +//endian helpers +bool reader::read_word_be(WORD &val) +{ + WORD temp; + if (!read_word(temp)) return false; + val = byte_order_helper::word_be_to_native(temp); + return true; +} + +bool reader::read_word_le(WORD &val) +{ + WORD temp; + if (!read_word(temp)) return false; + val = byte_order_helper::word_le_to_native(temp); + return true; +} + +bool reader::read_dword_be(DWORD &val) +{ + DWORD temp; + if (!read_dword(temp)) return false; + val = byte_order_helper::dword_be_to_native(temp); + return true; +} +bool reader::read_dword_le(DWORD &val) +{ + DWORD temp; + if (!read_dword(temp)) return false; + val = byte_order_helper::dword_le_to_native(temp); + return true; + +} +bool reader::read_qword_be(QWORD &val) +{ + QWORD temp; + if (!read_qword(temp)) return false; + val = byte_order_helper::qword_be_to_native(temp); + return true; +} + +bool reader::read_qword_le(QWORD &val) +{ + QWORD temp; + if (!read_qword(temp)) return false; + val = byte_order_helper::qword_le_to_native(temp); + return true; +} + +bool reader::write_word_be(WORD val) +{ + return write_word(byte_order_helper::word_native_to_be(val)); +} +bool reader::write_word_le(WORD val) +{ + return write_word(byte_order_helper::word_native_to_le(val)); +} +bool reader::write_dword_be(DWORD val) +{ + return write_dword(byte_order_helper::dword_native_to_be(val)); +} +bool reader::write_dword_le(DWORD val) +{ + return write_dword(byte_order_helper::dword_native_to_le(val)); +} +bool reader::write_qword_be(QWORD val) +{ + return write_qword(byte_order_helper::qword_native_to_be(val)); +} +bool reader::write_qword_le(QWORD val) +{ + return write_qword(byte_order_helper::qword_native_to_le(val)); +} + +#endif + +bool reader::read_guid_le(GUID & g) +{ + if (read(&g,sizeof(g))!=sizeof(g)) return false; + byte_order_helper::guid_le_to_native(g); + return true; +} + +bool reader::read_guid_be(GUID & g) +{ + if (read(&g,sizeof(g))!=sizeof(g)) return false; + byte_order_helper::guid_be_to_native(g); + return true; +} + +bool reader::write_guid_le(const GUID & g) +{ + GUID temp = g; + byte_order_helper::guid_native_to_le(temp); + return write(&temp,sizeof(temp))==sizeof(temp); +} + +bool reader::write_guid_be(const GUID & g) +{ + GUID temp = g; + byte_order_helper::guid_native_to_be(temp); + return write(&temp,sizeof(temp))==sizeof(temp); +} + +__int64 reader::get_modification_time() +{ + __int64 rv = 0; + reader_filetime * ptr = service_query_t(reader_filetime,this); + if (ptr) + { + rv = ptr->get_modification_time(); + ptr->service_release(); + } + return rv; +} + +namespace { + + class directory_callback_isempty : public directory_callback + { + bool m_isempty; + public: + directory_callback_isempty() : m_isempty(true) {} + void on_file(const char * url) {m_isempty = false;}//api fixme: should signal enumeration abort + bool isempty() {return m_isempty;} + }; + + class directory_callback_dummy : public directory_callback + { + public: + void on_file(const char * url) {} + }; + +} + +bool directory::g_is_empty(const char * path) +{ + service_enum_t e; + directory * d; + for(d=e.first();d;d=e.next()) + { + int rv; + directory_callback_isempty callback; + rv = d->list(path,&callback,0,true);//blargh @ old API not reporting directories inside, need to run in recur mode, fixme + d->service_release(); + if (rv) return callback.isempty(); + } + return true; +} + +bool directory::g_is_valid_dir(const char * path) +{ + service_enum_t e; + directory * d; + for(d=e.first();d;d=e.next()) + { + int rv; + directory_callback_isempty callback; + rv = d->list(path,&directory_callback_dummy(),0,false);//another API fixme + d->service_release(); + if (rv) return true; + } + return false; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/reader.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader.h new file mode 100644 index 000000000..64d9da16d --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader.h @@ -0,0 +1,319 @@ +#ifndef _READER_H_ +#define _READER_H_ + +#include "service.h" +#include "interface_helper.h" + +class playlist_loader_callback; + +//file paths are all UTF-8 + +class NOVTABLE reader : public service_base +{ +protected: + virtual ~reader() {}; + reader() {}; +public: + enum MODE { + MODE_READ = 1,//open with READ access and READ-only sharing + MODE_WRITE_EXISTING,//open existing file with full R/W access and NO sharing + MODE_WRITE_NEW,//create new file with full R/W access and NO sharing + }; + + virtual bool open(const char *path,MODE mode)=0; + //open should be called ONLY ONCE on a reader instance, with the same path as passed to file::get_reader + //you MAY get deleted before open() + + virtual unsigned read(void *buffer, unsigned length)=0; //0 on error/eof, number of bytes read otherwise ( + bool read_x_le(T & val) + { + if (read(&val,sizeof(val))!=sizeof(val)) return false; + byte_order_helper::order_le_to_native(&val,sizeof(val)); + return true; + } + + template + bool read_x_be(T & val) + { + if (read(&val,sizeof(val))!=sizeof(val)) return false; + byte_order_helper::order_be_to_native(&val,sizeof(val)); + return true; + } + + template + bool write_x_le(T val) + { + byte_order_helper::order_native_to_le(&val,sizeof(val)); + return write(&val,sizeof(val))==sizeof(val); + } + + template + bool write_x_be(T val) + { + byte_order_helper::order_native_to_be(&val,sizeof(val)); + return write(&val,sizeof(val))==sizeof(val); + } + + //endian helpers + inline bool read_word_be(WORD & val) {return read_x_be(val);} + inline bool read_word_le(WORD & val) {return read_x_le(val);} + inline bool read_dword_be(DWORD & val) {return read_x_be(val);} + inline bool read_dword_le(DWORD & val) {return read_x_le(val);} + inline bool read_qword_be(QWORD & val) {return read_x_be(val);} + inline bool read_qword_le(QWORD & val) {return read_x_le(val);} + inline bool read_float_be(float & val) {return read_x_be(val);} + inline bool read_float_le(float & val) {return read_x_le(val);} + inline bool read_double_be(double & val) {return read_x_be(val);} + inline bool read_double_le(double & val) {return read_x_le(val);} + inline bool write_word_be(WORD val) {return write_x_be(val);} + inline bool write_word_le(WORD val) {return write_x_le(val);} + inline bool write_dword_be(DWORD val) {return write_x_be(val);} + inline bool write_dword_le(DWORD val) {return write_x_le(val);} + inline bool write_qword_be(QWORD val) {return write_x_be(val);} + inline bool write_qword_le(QWORD val) {return write_x_le(val);} + inline bool write_float_be(float val) {return write_x_be(val);} + inline bool write_float_le(float val) {return write_x_le(val);} + inline bool write_double_be(double val) {return write_x_be(val);} + inline bool write_double_le(double val) {return write_x_le(val);} + bool read_guid_le(GUID & g); + bool read_guid_be(GUID & g); + bool write_guid_le(const GUID & g); + bool write_guid_be(const GUID & g); +}; + +class reader_filetime : public reader +{ +public: + //time is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601; 0 for invalid/unknown time + virtual __int64 get_modification_time()=0; + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return reader::service_query(guid); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;}//only for service_query + +}; + +class reader_dynamicinfo : public reader//for shoutcast metadata BS +{ +public: + + virtual bool is_dynamic_info_enabled()=0;//checks if currently open stream gets dynamic metadata + + virtual bool get_dynamic_info(class file_info * out, bool * b_track_change)=0;//see input::get_dynamic_info + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return reader::service_query(guid); + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;}//only for service_query +}; + +class NOVTABLE file : public service_base +{ +public: + virtual int get_canonical_path(const char * path,string_base & out)=0;//return 1 on success, 0 on failure / not our file + virtual int is_our_path(const char * path)=0; + + virtual int get_display_path(const char * path,string_base & out)=0; + //converts canonical path to "human-readable" path (eg. removes file:// ) + //return 1 on success, 0 on failure + //generally OK to leave it returning 0 + + //in in all subsequent calls other than get_canonical_path, you should expect file path that has been accepted by your is_our_path + + //everything else than get_canonical_path() should expect strings that have already been processed by get_canonical_path() + //get_canonical_path() is called WITHOUT calling is_our_file first + virtual reader * get_reader(const char * path)=0;//note: reader will usually stay alive after you are service_release'd; do not open the file at this point, just create a reader capable of opening this file and return it + virtual int exists(const char * path)=0;//for return values, see FILE_EXISTS* below + virtual int remove(const char * path)=0;//return 1 on success and 0 on failure; also removes directories + virtual int move(const char * src,const char * dst)=0; + virtual int dont_read_infos(const char * src) {return 0;}//return 1 if infos shouldn't be precached from you (eg. HTTP) + + virtual int relative_path_create(const char * file_path,const char * playlist_path,string_base & out) {return 0;} + //eg. file_path : "file://z:\dir\subdir\blah.mpc", playlist_path: "file://z:\dir\playlist.fpl", out: "file://subdir\blah.mpc" + //file_path == canonical path accepted by your class, playlist_path == canonical path possibly belonging to some other file class, set out to a string your relative_path_parse will recognize (use url-style notation to prevent confusion) + //dont worry about output string being possibly passed to anything else than relative_path_parse + //return 1 on success, 0 if relative path can't be created (will store as full path) + virtual int relative_path_parse(const char * relative_path,const char * playlist_path,string_base & out) {return 0;} + //eg. relative_path: "file://subdir\blah.mpc", playlist_path: "file://z:\dir\playlist.fpl", out: "file://z:\dir\subdir\blah.mpc" + //relative_path == relative path produced by some file class (possibly you), check it before processing) + //output canonical path to the file on success + //return: 1 on success, 0 on failure / not-our-file + + virtual int create_directory(const char * path) {return 0;} + + //helpers + static void g_get_canonical_path(const char * path,string_base & out); + static void g_get_display_path(const char * path,string_base & out); + + static file * g_get_interface(const char * path);//path is AFTER get_canonical_path + static reader * g_get_reader(const char * path);//path is AFTER get_canonical_path (you're gonna need canonical version for reader::open() anyway) + static int g_dont_read_infos(const char * path);//path is AFTER get_canonical_path + //these below do get_canonical_path internally + static reader * g_open(const char * path,reader::MODE mode);//get_canonical_path + get_reader + reader->open; slow with http etc (you cant abort it) + static reader * g_open_read(const char * path) {return g_open(path,reader::MODE_READ);} + static reader * g_open_precache(const char * path);//open only for precaching data (eg. will fail on http etc) + static int g_exists(const char * path); + static int g_remove(const char * path); + static int g_move(const char * src,const char * dst);//needs canonical path + static int g_move_ex(const char * src,const char * dst);//converts to canonical path first + static int g_relative_path_create(const char * file_path,const char * playlist_path,string_base & out); + static int g_relative_path_parse(const char * relative_path,const char * playlist_path,string_base & out); + + static int g_create_directory(const char * path); + + static FILE * streamio_open(const char * path,const char * flags); // if for some bloody reason you ever need stream io compatibility, use this, INSTEAD of calling fopen() on the path string you've got; will only work with file:// (and not with http://, unpack:// or whatever) + + inline static reader * g_open_temp() {return g_open("tempfile://",reader::MODE_WRITE_NEW);} + inline static reader * g_open_tempmem() + { + reader * r = g_open("tempmem://",reader::MODE_WRITE_NEW); + if (r==0) r = g_open_temp(); + return r; + } + + enum { + FILE_EXISTS = 1,//use as flags, FILE_EXISTS_WRITEABLE implies FILE_EXISTS + FILE_EXISTS_WRITEABLE = 2 + }; + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE directory_callback +{ +public: + virtual void on_file(const char * url)=0; +}; + +class directory_callback_i : public directory_callback +{ + ptr_list_t data; + static int sortfunc(const char * & p1, const char * & p2) {return stricmp_utf8(p1,p2);} +public: + virtual void on_file(const char * url) {data.add_item(strdup(url));} + ~directory_callback_i() {data.free_all();} + unsigned get_count() {return data.get_count();} + const char * operator[](unsigned n) {return data[n];} + const char * get_item(unsigned n) {return data[n];} + void sort() {data.sort(sortfunc);} +}; + +class NOVTABLE directory : public service_base +{ +public: + virtual int list(const char * path,directory_callback * out,playlist_loader_callback * callback,bool b_recur = true)=0; + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + //helper + static int g_list(const char * path,directory_callback * out,playlist_loader_callback * callback,bool b_recur = true); + //playlist_loader_callback pointer is optional and used only for querying if enumeration should be aborted + + static bool g_is_valid_dir(const char * path); + static bool g_is_empty(const char * path); +}; + +class NOVTABLE archive : public file//dont derive from this, use archive_i class below +{ +public: + virtual int list(const char * path,directory_callback * out,playlist_loader_callback * callback)=0; + virtual int precache(const char * path,playlist_loader_callback * callback) {return 0;} //optional - if you are slow (eg. rar), metadb::precache() your files in optimal way using supplied reader pointer + //playlist_loader_callback ONLY for on_progress calls + + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE archive_i : public archive // derive from this +{ +private: + //do not override these + virtual int get_canonical_path(const char * path,string_base & out); + virtual int is_our_path(const char * path); + virtual int get_display_path(const char * path,string_base & out); + virtual int exists(const char * path); + virtual int remove(const char * path); + virtual int move(const char * src,const char * dst); + virtual int dont_read_infos(const char * src); + virtual int relative_path_create(const char * file_path,const char * playlist_path,string_base & out); + virtual int relative_path_parse(const char * relative_path,const char * playlist_path,string_base & out); +protected: + //override these + virtual const char * get_archive_type()=0;//eg. "zip", must be lowercase + virtual int exists_in_archive(const char * archive,const char * file) {return 1;} + +public: + //override these + virtual reader * get_reader(const char * path)=0; + virtual int list(const char * path,directory_callback * out,playlist_loader_callback * callback)=0; + virtual int precache(const char * path,playlist_loader_callback * callback) {return 0;}//optional - if you are slow (eg. rar), metadb::precache() your files in optimal way using supplied reader pointer + //playlist_loader_callback ONLY for on_progress calls + + + static bool parse_unpack_path(const char * path,string8 & archive,string8 & file); + static void make_unpack_path(string8 & path,const char * archive,const char * file,const char * name); + void make_unpack_path(string8 & path,const char * archive,const char * file); + +}; + +template +class archive_factory +{ + service_factory_single_t factory1; + service_factory_single_t factory2; +public: + archive_factory() {} + T& get_static_instance() {return factory1.get_static_instance();} +}; + +//register as: +// static archive_factory foo; + + +#include "reader_helper.h" + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/reader_helper.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader_helper.h new file mode 100644 index 000000000..7bd26eba5 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader_helper.h @@ -0,0 +1,263 @@ +#ifndef _READER_HELPER_H_ +#define _READER_HELPER_H_ + +//helper +class file_path_canonical : public string8 +{ +public: + file_path_canonical(const char * src) + { + file::g_get_canonical_path(src,*this); + } + operator const char * () {return get_ptr();} +}; + +class file_path_display : public string8 +{ +public: + file_path_display(const char * src) + { + file::g_get_display_path(src,*this); + } + operator const char * () {return get_ptr();} +}; + + +//HELPER, allows short seek back on unseekable reader, readonly +template +class reader_seekback_t : public T +{ +protected: + bool aborting; + mem_block_t buffer; + virtual ~reader_seekback_t() {} + virtual int seekback_read(void * buffer,int size)=0; + __int64 read_pos,reader_pos; + int buffer_pos,buffered; +public: + enum + { + DEFAULT_SEEKBACK_SIZE = 0x10000 + }; + reader_seekback_t(int size = DEFAULT_SEEKBACK_SIZE) : buffer(size) {aborting=0;read_pos=0;reader_pos=0;buffered=0;buffer_pos=0;} + virtual unsigned read(void *buffer, unsigned length); + virtual unsigned write(const void *buffer, unsigned length) {return 0;} +// virtual __int64 get_length() {return m_reader->get_length();} + virtual __int64 get_position() {return read_pos;} + virtual bool set_eof() {return false;} + virtual bool seek(__int64 position); + virtual bool can_seek() {return 0;} + virtual void abort() {aborting=1;} +}; + +typedef reader_seekback_t< reader > reader_seekback; + +class reader_seekback_wrap : public reader_seekback +{ +protected: + reader * m_reader; + virtual int seekback_read(void * buffer,int size) + { + return m_reader->read(buffer,size); + } +public: + reader_seekback_wrap(reader * p_reader,int size) + : reader_seekback(size), m_reader(p_reader) {} + virtual bool open(const char *path,MODE mode) {return false;}//dummy + virtual __int64 get_length() {return m_reader->get_length();} + virtual void abort() {m_reader->abort();reader_seekback::abort();} +}; + + +class reader_backbuffer_wrap : public reader_seekback_wrap +{ +public: + reader_backbuffer_wrap(reader * p_reader,int size) + : reader_seekback_wrap(p_reader,size) {} + virtual bool seek(__int64 position); +}; + + +class reader_membuffer : public reader_filetime +{ +public: + mem_block_t buffer; + int buffer_pos; + reader_membuffer(__int64 modtime) : m_modtime(modtime) {} + virtual unsigned write(const void*, unsigned) {return 0;} + __int64 m_modtime; +protected: + bool init(reader * src) + { + if (src->is_in_memory()) return false;//already buffered + __int64 size64 = src->get_length(); + if (size64<=0 || size64>0x7FFFFFFF) return false; + unsigned size = (unsigned)size64; + if (!buffer.set_size(size)) + { + return false; + } + src->seek(0); + buffer_pos=0; + if (src->read(buffer.get_ptr(),size)!=size) + { + return false; + } + return true; + } +public: + static reader * create(reader * src,__int64 modtime = 0) + { + reader_membuffer * ptr = new service_impl_p1_t(modtime); + if (ptr) + { + if (!ptr->init(src)) {delete ptr; ptr = 0;} + } + return ptr; + } + + virtual bool open(const char *path,MODE mode) {return false;}//dummy + + virtual unsigned read(void *out, unsigned length) + { + unsigned max = buffer.get_size() - buffer_pos; + if (length>max) length = max; + memcpy(out,buffer.get_ptr()+buffer_pos,length); + buffer_pos += length; + return length; + } + + virtual int write(const void *buffer, int length) {return 0;} + virtual __int64 get_length() {return buffer.get_size();} + virtual __int64 get_position() {return buffer_pos;} + virtual bool set_eof() {return 0;} + virtual bool seek(__int64 position) + { + if (position>(__int64)buffer.get_size()) + position = (__int64)buffer.get_size(); + else if (position<0) position=0; + + buffer_pos = (int)position; + + return true; + } + virtual bool can_seek() {return true;} + virtual bool is_in_memory() {return true;} + virtual __int64 get_modification_time() {return m_modtime;} +}; + +class reader_limited : public reader +{ + virtual bool open(const char * filename,MODE mode) {return false;}//dummy + reader * r; + __int64 begin; + __int64 end; + virtual unsigned write(const void * , unsigned) {return 0;} +public: + reader_limited() {r=0;begin=0;end=0;} + reader_limited(reader * p_r,__int64 p_begin,__int64 p_end) + { + r = p_r; + begin = p_begin; + end = p_end; + r->seek(begin); + } + + void init(reader * p_r,__int64 p_begin,__int64 p_end) + { + r = p_r; + begin = p_begin; + end = p_end; + r->seek(begin); + } + + virtual unsigned read(void *buffer, unsigned length) + { + __int64 pos = r->get_position(); + if ((__int64)length > end - pos) length = (unsigned)(end - pos); + return r->read(buffer,length); + } + + virtual __int64 get_length() + { + return end-begin; + } + virtual __int64 get_position() + { + return r->get_position()-begin; + } + + virtual bool seek(__int64 position) + { + return r->seek(position+begin); + } + virtual bool can_seek() {return r->can_seek();} +}; + + +template +bool reader_seekback_t::seek(__int64 position) +{ + if (aborting) return false; + if (position>reader_pos) + { + read_pos = reader_pos; + __int64 skip = (int)(position-reader_pos); + char temp[256]; + while(skip>0) + { + __int64 delta = sizeof(temp); + if (delta>skip) delta=skip; + if (read(temp,(int)delta)!=delta) return 0; + skip-=delta; + } + return true; + } + else if (reader_pos-position>(__int64)buffered) + { + return false; + } + else + { + read_pos = position; + return true; + } +} +template +unsigned reader_seekback_t::read(void *p_out, unsigned length) +{ + if (aborting) return 0; + //buffer can be null + int done = 0; + char * out = (char*)p_out; + if (read_pos(__int64)buffered) return 0; + unsigned delta = (unsigned)(reader_pos-read_pos); + if (delta>length) delta = length; + buffer.read_circular(buffer_pos - (unsigned)(reader_pos-read_pos),out,delta); + read_pos+=delta; + length-=delta; + out+=delta; + done += delta; + } + if (length>0) + { + unsigned delta = seekback_read(out,length); + buffer_pos = buffer.write_circular(buffer_pos,out,delta); + read_pos+=delta; + reader_pos+=delta; + length-=delta; + out+=delta; + done+=delta; + + buffered+=delta; + if (buffered>(int)buffer.get_size()) buffered=buffer.get_size(); + } + + return done; +} + + + +#endif//_READER_HELPER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/reader_helper_mem.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader_helper_mem.h new file mode 100644 index 000000000..9487a3189 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/reader_helper_mem.h @@ -0,0 +1,79 @@ +#ifndef _READER_HELPER_MEM_ +#define _READER_HELPER_MEM_ + +template +class reader_mem_base_t : public T +{ +private: + char * data; + unsigned size,pos; +protected: + bool free_on_exit; + void mem_init(void * p_data,int p_size) + { + if (data && free_on_exit) free(data); + data = (char*)p_data; + size = p_size; + pos=0; + } +public: + reader_mem_base_t() {data=0;size=0;pos=0;free_on_exit=true;} + ~reader_mem_base_t() {if (free_on_exit && data) free(data);} + + virtual unsigned write(const void*, unsigned) {return 0;} + + virtual unsigned read(void *buffer, unsigned length) + { + if (pos + length > size) length = size - pos; + memcpy(buffer,data+pos,length); + pos+=length; + return length; + } + + virtual __int64 get_length() + { + return (__int64)size; + } + virtual __int64 get_position() + { + return (__int64)pos; + } + + virtual bool seek(__int64 position) + { + if (position < 0) position=0; + else if (position>(__int64)size) position=size; + pos = (int)position; + return true; + } + virtual bool is_in_memory() {return 1;} +}; + +#define reader_mem_base reader_mem_base_t< service_impl_t > + +class reader_mem_temp : public reader_mem_base_t< service_impl_t > +{ + __int64 m_time; + virtual bool open(const char * filename,MODE mode) {return 0;}//dummy + virtual __int64 get_modification_time() {return m_time;} +public: + reader_mem_temp(void * p_data,int p_size,__int64 p_time = 0) : m_time(p_time) + { + free_on_exit = false; + mem_init(p_data,p_size); + } +}; + + +class reader_mem : public reader_mem_base +{ + virtual bool open(const char * filename,MODE mode) {return 0;}//dummy +public: + reader_mem(void * p_data,int p_size) + { + free_on_exit = true; + mem_init(p_data,p_size); + } +}; + +#endif //_READER_HELPER_MEM_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/replaygain.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/replaygain.h new file mode 100644 index 000000000..080aaa465 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/replaygain.h @@ -0,0 +1,85 @@ +#ifndef _FOOBAR2000_SDK_REPLAYGAIN_H_ +#define _FOOBAR2000_SDK_REPLAYGAIN_H_ + +#include "service.h" + +#include "file_info.h" +#include "metadb_handle.h" +#include "metadb.h" + + +class NOVTABLE replaygain : public service_base +{ +public: + enum mode_t + { + MODE_DEFAULT,//uses settings from core config + MODE_DISABLED, + MODE_TRACK, + MODE_ALBUM, + }; + + virtual double query_scale(const file_info * info,mode_t mode = MODE_DEFAULT)=0; + virtual mode_t get_user_settings()=0; + + static replaygain * get()//helper + { + return service_enum_create_t(replaygain,0); + } + + static mode_t g_get_user_settings()//returns whatever MODE_DEFAULT currently corresponds to + { + mode_t rv = MODE_DISABLED; + replaygain * ptr = get(); + if (ptr) + { + rv = ptr->get_user_settings(); + ptr->service_release(); + } + return rv; + } + + static double g_query_scale(const file_info* info,mode_t mode = MODE_DEFAULT) + { + double rv = 1; + replaygain * ptr = get(); + if (ptr) + { + rv = ptr->query_scale(info,mode); + ptr->service_release(); + } + return rv; + } + + static double g_query_scale(const playable_location* entry,mode_t mode = MODE_DEFAULT) + { + double rv = 1; + metadb * p_metadb = metadb::get(); + if (p_metadb) + { + metadb_handle * handle = p_metadb->handle_create(entry); + if (handle) + { + rv = g_query_scale(handle,mode); + handle->handle_release(); + } + } + return rv; + } + + static double g_query_scale(metadb_handle * handle,mode_t mode = MODE_DEFAULT) + { + double rv = 1; + handle->handle_lock(); + const file_info * info = handle->handle_query_locked(); + if (info) + rv = g_query_scale(info,mode); + handle->handle_unlock(); + return rv; + } + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +#endif //_FOOBAR2000_SDK_REPLAYGAIN_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/resampler.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/resampler.h new file mode 100644 index 000000000..34b89be97 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/resampler.h @@ -0,0 +1,164 @@ +#ifndef _RESAMPLER_H_ +#define _RESAMPLER_H_ + +#include "dsp.h" + +//hint: use resampler_helper class declared below to resample + +class NOVTABLE resampler : public dsp +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual void set_dest_sample_rate(unsigned srate)=0; + virtual void set_config(unsigned flags)=0;//flags - see below + virtual bool is_conversion_supported(unsigned src_srate,unsigned dst_srate)=0; + + virtual service_base * service_query(const GUID & guid) + { + if (guid == get_class_guid()) {service_add_ref();return this;} + else return dsp::service_query(guid); + } + + enum + { + FLAG_FAST = 0x0, + FLAG_SLOW = 0x1, + }; + + //helper + static bool get_interface(resampler ** out_resampler,dsp ** out_dsp)//may fail if no resampler DSP is installed + {//you need to release both returned pointers + service_enum_t e; + dsp * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + resampler * ptr2 = service_query_t(resampler,ptr); + if (ptr2) + { + *out_resampler = ptr2; + *out_dsp = ptr; + return true; + } + ptr->service_release(); + } + return false; + } + + static bool get_interface_ex(resampler ** out_resampler,dsp ** out_dsp,unsigned src_srate,unsigned dst_srate)//may fail if no resampler DSP is installed or installed ones cant handle this conversion + {//you need to release both returned pointers + service_enum_t e; + dsp * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + resampler * ptr2 = service_query_t(resampler,ptr); + if (ptr2) + { + if (ptr2->is_conversion_supported(src_srate,dst_srate)) + { + *out_resampler = ptr2; + *out_dsp = ptr; + return true; + } + else + { + ptr2->service_release(); + } + } + ptr->service_release(); + } + return false; + } + + static dsp * create(unsigned srate,unsigned flags) + { + dsp * p_resampler_dsp; + resampler * p_resampler; + if (resampler::get_interface(&p_resampler,&p_resampler_dsp)) + { + p_resampler->set_config(flags); + p_resampler->set_dest_sample_rate(srate); + p_resampler->service_release(); + } + else + { + p_resampler_dsp = 0; + } + return p_resampler_dsp; + } + + static dsp * create_ex(unsigned src_srate,unsigned dst_srate,unsigned flags) + { + dsp * p_resampler_dsp; + resampler * p_resampler; + if (resampler::get_interface_ex(&p_resampler,&p_resampler_dsp,src_srate,dst_srate)) + { + p_resampler->set_config(flags); + p_resampler->set_dest_sample_rate(dst_srate); + p_resampler->service_release(); + } + else + { + p_resampler_dsp = 0; + } + return p_resampler_dsp; + } + +}; + +class resampler_helper +{ + dsp * p_dsp; + unsigned expected_dst_srate; +public: + explicit resampler_helper() + { + p_dsp = 0; + expected_dst_srate = 0; + } + + void setup_ex(unsigned src_srate,unsigned dst_srate,unsigned flags) + { + if (!p_dsp) p_dsp = resampler::create_ex(src_srate,dst_srate,flags); + expected_dst_srate = dst_srate; + } + + void setup(unsigned flags,unsigned dst_srate) + { + if (!p_dsp) p_dsp = resampler::create(dst_srate,flags); + expected_dst_srate = dst_srate; + } + + bool run(dsp_chunk_list * list,unsigned flags)//returns false on failure; flags - see dsp.h + { + if (!p_dsp || expected_dst_srate<=0) return false; + else + { + p_dsp->run(list,0,flags); + bool rv = true; + unsigned n,m=list->get_count(); + for(n=0;nget_item(n)->get_srate() != expected_dst_srate) {rv = false;break;} + } + return rv; + } + } + + void flush() {if (p_dsp) p_dsp->flush();} + + double get_latency() + { + return p_dsp ? p_dsp->get_latency() : 0;; + } + + + ~resampler_helper() + { + if (p_dsp) p_dsp->service_release(); + } +}; + + +#endif//_RESAMPLER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/service.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/service.cpp new file mode 100644 index 000000000..4c98f36f5 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/service.cpp @@ -0,0 +1,66 @@ +#include "foobar2000.h" +#include "component.h" + +foobar2000_client g_client; +foobar2000_api * g_api; + +service_base * service_factory_base::enum_create(const GUID &g,int n) +{ + assert(core_api::are_services_available()); + return g_api->service_enum_create(g,n); +} + +int service_factory_base::enum_get_count(const GUID &g) +{ + assert(core_api::are_services_available()); + return g_api->service_enum_get_count(g); +} + +service_factory_base * service_factory_base::list=0; + +service_enum::service_enum(const GUID &g) +{ + guid = g; + reset(); +} + +void service_enum::reset() +{ + service_ptr=0; +} + +service_base * service_enum::next() +{ + return service_factory_base::enum_create(guid,service_ptr++); +} + +/* +void service_base::service_release_safe() +{ + try { + if (this) service_release(); + } + catch(...) + { + } +} +*/ +#ifdef WIN32 + +long interlocked_increment(long * var) +{ + assert(!((unsigned)var&3)); + return InterlockedIncrement(var); +} + +long interlocked_decrement(long * var) +{ + assert(!((unsigned)var&3)); + return InterlockedDecrement(var); +} + +#else + +#error portme + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/service.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/service.h new file mode 100644 index 000000000..3c6d05beb --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/service.h @@ -0,0 +1,246 @@ +#ifndef _SERVICE_H_ +#define _SERVICE_H_ + +#include "../../pfc/pfc.h" + +#include "utf8api.h" + +#include "core_api.h" + +long interlocked_increment(long * var);//note: win32 sucks, return values arent reliable, they can be used only to determine if new value is <0, 0 or >0 +long interlocked_decrement(long * var); + +class NOVTABLE service_base //ALL service classes MUST inherit from this +{ +public: + virtual int service_release() = 0; + virtual int service_add_ref() = 0; + virtual service_base * service_query(const GUID & guid) {return 0;} +}; + +#include "service_impl.h" +/* +//msvc6 sucks + +template + static T* service_query_t(service_base * ptr) {return static_cast(ptr->service_query(T::get_class_guid()));} + +*/ +#define service_query_t(T,ptr) (static_cast(ptr->service_query(T::get_class_guid()))) +//user service_release on returned object when youre done + +class NOVTABLE service_factory_base +{ +private: + static service_factory_base *list; + service_factory_base * next; + GUID guid; +protected: + service_factory_base(const GUID & p_guid) {assert(!core_api::are_services_available());guid=p_guid;next=list;list=this;} +public: + + inline const GUID & get_class_guid() const {return guid;} + + inline static service_factory_base * list_get_pointer() {return list;} + inline service_factory_base * list_get_next() {return next;} + + static service_base * enum_create(const GUID &g,int n); + static int enum_get_count(const GUID &g); + inline static bool is_service_present(const GUID & g) {return enum_get_count(g)>0;} + +#ifdef FOOBAR2000_EXE + static void process_components_directory(const char * path,service_factory_base ** & blah); + static void on_app_init(const char * exe_path); + static void on_app_shutdown(); + static void config_reset(const char * name = 0); + static void on_app_post_init(); + static void on_saveconfig(bool b_reset=false); +#endif + + //obsolete, use core_api + inline static HINSTANCE get_my_instance() {return core_api::get_my_instance();} + inline static const char * get_my_file_name() {return core_api::get_my_file_name();} + inline static const char * get_my_full_path() {return core_api::get_my_full_path();} + inline static HWND get_main_window() {return core_api::get_main_window();} + + virtual service_base * instance_create() = 0; + +}; + + +/* + +//msvc6 sucks + +template + static T * service_enum_create_t(int n) {return (T*)service_factory_base::enum_create(T::get_class_guid(),n);} +template + static int service_enum_get_count_t() {return service_factory_base::enum_get_count(T::get_class_guid());} +*/ + +#define service_enum_create_t(T,n) (static_cast(service_factory_base::enum_create(T::get_class_guid(),n))) +#define service_enum_get_count_t(T) (service_factory_base::enum_get_count(T::get_class_guid())) +#define service_enum_is_present(g) (service_factory_base::is_service_present(g)) +#define service_enum_is_present_t(T) (service_factory_base::is_service_present(T::get_class_guid())) + + +class service_enum +{ +private: + int service_ptr; + GUID guid; +public: + service_enum(const GUID &); + void reset(); + service_base * first() {reset();return next();} + service_base * next(); +}; + +template +class service_enum_t : private service_enum +{ +public: + service_enum_t() : service_enum(B::get_class_guid()) {} + void reset() {service_enum::reset();} + B * first() {return (B*)(service_enum::first());} + B * next() {return (B*)(service_enum::next());} +}; + + +template +class service_factory_t : public service_factory_base +{ +public: + service_factory_t() : service_factory_base(B::get_class_guid()) + { + } + + ~service_factory_t() + { + } + + virtual service_base * instance_create() + { + return (service_base*)(B*)(T*)new service_impl_t; + } +}; + +template +class service_factory_single_t : public service_factory_base +{ + service_impl_single_t g_instance; +public: + service_factory_single_t() : service_factory_base(B::get_class_guid()) {} + + ~service_factory_single_t() {} + + virtual service_base * instance_create() + { + g_instance.service_add_ref(); + return (service_base*)(B*)(T*)&g_instance; + } + + inline T& get_static_instance() const {return (T&)g_instance;} +}; + +template +class service_factory_single_ref_t : public service_factory_base +{ +private: + T & instance; +public: + service_factory_single_ref_t(T& param) : instance(param), service_factory_base(B::get_class_guid()) {} + + virtual service_base * instance_create() + { + service_base * ret = dynamic_cast(&instance); + ret->service_add_ref(); + return ret; + } + + inline T& get_static_instance() {return instance;} + + virtual void instance_release(service_base * ptr) {assert(0);} +}; + + +template +class service_factory_single_transparent_t : public service_factory_base, public service_impl_single_t +{ +public: + service_factory_single_transparent_t() : service_factory_base(B::get_class_guid()) {} + + virtual service_base * instance_create() + { + service_add_ref(); + return (service_base*)(B*)(T*)this; + } + + inline T& get_static_instance() const {return *(T*)this;} +}; + +template +class service_factory_single_transparent_p1_t : public service_factory_base, public service_impl_single_p1_t +{ +public: + service_factory_single_transparent_p1_t(P1 p1) : service_factory_base(B::get_class_guid()), service_impl_single_p1_t(p1) {} + + + virtual service_base * instance_create() + { + service_add_ref(); + return (service_base*)(B*)(T*)this; + } + + inline T& get_static_instance() const {return *(T*)this;} +}; + +template +class service_factory_single_transparent_p2_t : public service_factory_base, public service_impl_single_p2_t +{ +public: + service_factory_single_transparent_p2_t(P1 p1,P2 p2) : service_factory_base(B::get_class_guid()), service_impl_single_p2_t(p1,p2) {} + + + virtual service_base * instance_create() + { + service_add_ref(); + return (service_base*)(B*)(T*)this; + } + + inline T& get_static_instance() const {return *(T*)this;} +}; + +template +class service_factory_single_transparent_p3_t : public service_factory_base, public service_impl_single_p3_t +{ +public: + service_factory_single_transparent_p3_t(P1 p1,P2 p2,P3 p3) : service_factory_base(B::get_class_guid()), service_impl_single_p3_t(p1,p2,p3) {} + + + virtual service_base * instance_create() + { + service_add_ref(); + return (service_base*)(B*)(T*)this; + } + + inline T& get_static_instance() const {return *(T*)this;} +}; + +template +class service_factory_single_transparent_p4_t : public service_factory_base, public service_impl_single_p4_t +{ +public: + service_factory_single_transparent_p4_t(P1 p1,P2 p2,P3 p3,P4 p4) : service_factory_base(B::get_class_guid()), service_impl_single_p4_t(p1,p2,p3,p4) {} + + + virtual service_base * instance_create() + { + service_add_ref(); + return (service_base*)(B*)(T*)this; + } + + inline T& get_static_instance() const {return *(T*)this;} +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/service_helper.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/service_helper.h new file mode 100644 index 000000000..409e27381 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/service_helper.h @@ -0,0 +1,68 @@ +#ifndef _FOOBAR2000_SERVICE_HELPER_H_ +#define _FOOBAR2000_SERVICE_HELPER_H_ + +#include "service.h" + +template +class service_list_t : public ptr_list_t +{ +public: + void delete_item(T * ptr) + { + remove_item(ptr); + ptr->service_release(); + } + + void delete_by_idx(int idx) + { + T * ptr = remove_by_idx(idx); + if (ptr) ptr->service_release(); + } + + void delete_all() + { + int n,max=get_count(); + for(n=0;nservice_release(); + } + remove_all(); + } + + void delete_mask(const bit_array & mask) + { + int n,m=get_count(); + for(n=0;nservice_release(); + remove_mask(mask); + } +}; + +template +class service_list_autodel_t : public service_list_t +{ +public: + inline ~service_list_autodel_t() {delete_all();} +}; + +template +class service_ptr_autodel_t +{ + T * ptr; +public: + inline T* operator=(T* param) {return ptr = param;} + inline T* operator->() {return ptr;} + inline ~service_ptr_autodel_t() {if (ptr) ptr->service_release();} + inline service_ptr_autodel_t(T * param=0) {ptr=param;} + inline operator T* () {return ptr;} + inline void release() + { + T* temp = ptr; + ptr = 0; + if (temp) temp->service_release_safe(); + } + inline bool is_empty() {return ptr==0;} +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/service_impl.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/service_impl.h new file mode 100644 index 000000000..5c73582e6 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/service_impl.h @@ -0,0 +1,104 @@ +//only meant to be included from service.h + +class service_reference_counter +{ +private: + long refcount; +public: + inline service_reference_counter() : refcount(1) {} + inline long increment() {return interlocked_increment(&refcount);} + inline long decrement() {return interlocked_decrement(&refcount);} +}; + +#define __implement_service_base \ + private: \ + service_reference_counter m_reference_counter; \ + public: \ + virtual int service_release() {long ret = m_reference_counter.decrement(); if (ret == 0) delete this; return ret;} \ + virtual int service_add_ref() {return m_reference_counter.increment();} + +#define __implement_service_base_single \ + public: \ + virtual int service_release() {return 1;} \ + virtual int service_add_ref() {return 1;} + +template +class service_impl_t : public T +{ + __implement_service_base; +}; + +template +class service_impl_p1_t : public T +{ + __implement_service_base; +public: + service_impl_p1_t(P1 p1) : T(p1) {} +}; + +template +class service_impl_p2_t : public T +{ + __implement_service_base; +public: + service_impl_p2_t(P1 p1,P2 p2) : T(p1,p2) {} +}; + +template +class service_impl_p3_t : public T +{ + __implement_service_base; +public: + service_impl_p3_t(P1 p1,P2 p2,P3 p3) : T(p1,p2,p3) {} +}; + +template +class service_impl_p4_t : public T +{ + __implement_service_base; +public: + service_impl_p4_t(P1 p1,P2 p2,P3 p3,P4 p4) : T(p1,p2,p3,p4) {} +}; + + +template +class service_impl_single_t : public T +{ + __implement_service_base_single; +}; + +template +class service_impl_single_p1_t : public T +{ + __implement_service_base_single; +public: + service_impl_single_p1_t(P1 p1) : T(p1) {} +}; + +template +class service_impl_single_p2_t : public T +{ + __implement_service_base_single; +public: + service_impl_single_p2_t(P1 p1,P2 p2) : T(p1,p2) {} +}; + +template +class service_impl_single_p3_t : public T +{ + __implement_service_base_single; +public: + service_impl_single_p3_t(P1 p1,P2 p2,P3 p3) : T(p1,p2,p3) {} +}; + +template +class service_impl_single_p4_t : public T +{ + __implement_service_base_single; +public: + service_impl_single_p4_t(P1 p1,P2 p2,P3 p3,P4 p4) : T(p1,p2,p3,p4) {} +}; + + +#undef __implement_service_base +#undef __implement_service_base_single diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/shortcut_actions.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/shortcut_actions.h new file mode 100644 index 000000000..cfc068aec --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/shortcut_actions.h @@ -0,0 +1 @@ +#error DEPRECATED diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/stdafx.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/stdafx.cpp new file mode 100644 index 000000000..ea4f0bdf1 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/stdafx.cpp @@ -0,0 +1,2 @@ +//cpp used to generate precompiled header +#include "foobar2000.h" \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/tagread.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/tagread.cpp new file mode 100644 index 000000000..0347be79f --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/tagread.cpp @@ -0,0 +1,98 @@ +#include "foobar2000.h" + +int tag_reader::g_run(reader * r,file_info * info,const char * name) +{ + if (!r->can_seek()) return 0;//dont bother + __int64 offset = r->get_position(); + int rv=0; + service_enum_t e; + tag_reader * ptr; + for(ptr=e.first();ptr && !rv;ptr = e.next()) + { + const char * s_name = ptr->get_name(); + if (!stricmp_utf8(name,s_name)) + { + r->seek(0); + rv = ptr->run(r,info); + } + ptr->service_release(); + } + r->seek(offset); +// if (rv) info->info_set("tagtype",name); + return rv; +} + +int tag_reader::g_run_multi(reader * r,file_info * info,const char * list) +{ + for(;;) + { + const char * sep = strchr(list,'|'); + if (sep==0) return *list ? g_run(r,info,list) : 0; + if (sep>list && g_run(r,info,string8(list,sep-list))) return 1; + list = sep + 1; + } +} + +int tag_writer::g_run(reader * r,const file_info * info,const char * name) +{ + if (!r->can_seek()) return 0;//dont bother + __int64 offset = r->get_position(); + int rv=0; + service_enum_t e; + tag_writer * ptr; + for(ptr=e.first();ptr && !rv;ptr = e.next()) + { + const char * s_name = ptr->get_name(); + + if (!stricmp_utf8(name,s_name)) + { + r->seek(0); + rv = ptr->run(r,info); + } + + ptr->service_release(); + } + r->seek(offset); + return rv; + +} + +void tag_remover::g_run(reader * r) +{ + service_enum_t e; + tag_remover * ptr; + for(ptr=e.first();ptr;ptr = e.next()) + { + r->seek(0); + ptr->run(r); + ptr->service_release(); + } +} + +bool tag_reader::g_have_type(const char * name) +{ + service_enum_t e; + tag_reader * ptr; + bool found = false; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (!stricmp_utf8(name,ptr->get_name())) found = true; + ptr->service_release(); + if (found) break; + } + return found; +} + +bool tag_writer::g_have_type(const char * name) +{ + service_enum_t e; + tag_writer * ptr; + bool found = false; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (!stricmp_utf8(name,ptr->get_name())) found = true; + ptr->service_release(); + if (found) break; + } + return found; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/tagread.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/tagread.h new file mode 100644 index 000000000..783098110 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/tagread.h @@ -0,0 +1,48 @@ +#ifndef _TAGREAD_H_ +#define _TAGREAD_H_ + +#include "service.h" +#include "reader.h" +#include "file_info.h" + +//helper class to let others use "standard" tag readers/writers in foo_input_std, do not reimplement + +class NOVTABLE tag_reader : public service_base +{ +public: + virtual const char * get_name()=0; + virtual int run(reader * r,file_info * info)=0;//return 1 on success, 0 on failure / unknown format + + static int g_run(reader * r,file_info * info,const char * name);//will seek back to original file offset + static int g_run_multi(reader * r,file_info * info,const char * list);//will seek back to original file offset + static bool g_have_type(const char * name); + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE tag_writer : public service_base +{ +public: + virtual const char * get_name()=0; + virtual int run(reader * r,const file_info * info)=0;//return 1 on success, 0 on failure / unknown format + + static int g_run(reader * r,const file_info * info,const char * name);//will seek back to original file offset + static bool g_have_type(const char * name); + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +class NOVTABLE tag_remover : public service_base +{ +public: + virtual void run(reader * r)=0; + + static void g_run(reader * r); + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/titleformat.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/titleformat.cpp new file mode 100644 index 000000000..32be5d6b4 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/titleformat.cpp @@ -0,0 +1,26 @@ +#include "foobar2000.h" + +void titleformat::g_run(const file_info * source,string_base & out,const char * spec,const char * extra_items) +{ + titleformat * ptr = service_enum_create_t(titleformat,0); + if (ptr) + { + ptr->run(source,out,spec,extra_items); + ptr->service_release();//actually safe not to release it + } +} + +void titleformat::remove_color_marks(const char * src,string8 & out)//helper +{ + out.reset(); + while(*src) + { + if (*src==3) + { + src++; + while(*src && *src!=3) src++; + if (*src==3) src++; + } + else out.add_byte(*src++); + } +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/titleformat.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/titleformat.h new file mode 100644 index 000000000..4f87634a5 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/titleformat.h @@ -0,0 +1,32 @@ +#ifndef _FOOBAR2000_TITLEFORMAT_H_ +#define _FOOBAR2000_TITLEFORMAT_H_ + +#include "service.h" + +#include "file_info.h" +#include "config_var.h" + +//use this to call titleformatting directly (bypassing database) +//implemented in the core, dont override + +class titleformat : public service_base +{ +public: + virtual void run(const file_info * source,string_base & out,const char * spec,const char * extra_items)=0; + //source - file info to use + //out - string receiving results + //spec - formatting specification string to use, e.g. "%ARTIST% - %TITLE%" + //extra_items - %_name% variables, name=value pairs, null-separated, terminated with two nulls, e.g. "name=value\0name=value\0" + //extra_items can be null + + //helpers + static void g_run(const file_info * source,string_base & out,const char * spec,const char * extra_items); + + static void remove_color_marks(const char * src,string8 & out);//helper + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} +}; + + +#endif //_FOOBAR2000_TITLEFORMAT_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/ui.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/ui.cpp new file mode 100644 index 000000000..1d4b0be06 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/ui.cpp @@ -0,0 +1,27 @@ +#include "foobar2000.h" + +bool ui_drop_item_callback::g_on_drop(interface IDataObject * pDataObject) +{ + service_enum_t e; + ui_drop_item_callback * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + bool status = ptr->on_drop(pDataObject); + ptr->service_release(); + if (status) return true; + } + return false; +} + +bool ui_drop_item_callback::g_is_accepted_type(interface IDataObject * pDataObject) +{ + service_enum_t e; + ui_drop_item_callback * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + bool status = ptr->is_accepted_type(pDataObject); + ptr->service_release(); + if (status) return true; + } + return false; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/ui.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/ui.h new file mode 100644 index 000000000..2d4890b99 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/ui.h @@ -0,0 +1,75 @@ +#ifndef _FOOBAR2000_UI_H_ +#define _FOOBAR2000_UI_H_ + +#include "service.h" + +#ifndef WIN32 +#error PORTME +#endif + +class NOVTABLE user_interface : public service_base +{ +public: + typedef BOOL (WINAPI * HookProc_t)(HWND wnd,UINT msg,WPARAM wp,LPARAM lp,LRESULT * ret); + //HookProc usage: + //in your windowproc, call HookProc first, and if it returns true, return LRESULT value it passed to you + + virtual const char * get_name()=0; + virtual HWND init(HookProc_t hook)=0;//create your window here + virtual void shutdown(bool endsession)=0;//you need to destroy your window here + virtual void activate()=0; + virtual void hide()=0; + virtual bool is_visible()=0;//for activate/hide command + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static user_interface * g_find(const char * name) + { + service_enum_t e; + user_interface * ptr; + for(ptr=e.first();ptr;ptr=e.next()) + { + if (!stricmp_utf8(ptr->get_name(),name)) return ptr; + ptr->service_release(); + } + return 0; + } +}; + +template +class user_interface_factory : public service_factory_single_t {}; + +//new (0.8) +class NOVTABLE ui_control : public service_base//implemented in the core, do not override +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual bool is_visible()=0; + virtual void activate()=0; + virtual void hide()=0; + virtual HICON get_main_icon()=0;//no need to free returned handle + virtual HICON load_main_icon(unsigned width,unsigned height)=0;//use DestroyIcon() to free it + + static ui_control * get() {return service_enum_create_t(ui_control,0);}//no need to service_release +}; + +class NOVTABLE ui_drop_item_callback : public service_base //called from UI when some object (ie. files from explorer) is dropped +{ +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + virtual bool on_drop(interface IDataObject * pDataObject)=0;//return true if you processed the data, false if not + virtual bool is_accepted_type(interface IDataObject * pDataObject)=0; + + static bool g_on_drop(interface IDataObject * pDataObject); + static bool g_is_accepted_type(interface IDataObject * pDataObject); +}; + +template +class ui_drop_item_callback_factory : public service_factory_single_t {}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/unpack.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/unpack.h new file mode 100644 index 000000000..8a797e5e7 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/unpack.h @@ -0,0 +1,25 @@ +#ifndef _UNPACK_H_ +#define _UNPACK_H_ + +#include "reader.h" + +class NOVTABLE unpacker : public service_base +{ +private: + //override this + virtual reader * open(reader * src)=0; +public: + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static reader * g_open(reader * r); +}; + +/* +usage: +you have a reader to an zip/rar/gzip/whatever archive containing just a single file you want to read, eg. a module +do unpacker::g_open() on that reader +returns 0 on failure (not a known archive or cant read it) or pointer to a new reader reading contents of that archive on success +*/ + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/utf8api.cpp b/tools/vio2sf/src/foobar8/foobar2000/SDK/utf8api.cpp new file mode 100644 index 000000000..ac58e927d --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/utf8api.cpp @@ -0,0 +1,11 @@ +#include "foobar2000.h" + +HWND uCreateDialog(UINT id,HWND parent,DLGPROC proc,long param) +{ + return uCreateDialog(core_api::get_my_instance(),id,parent,proc,param); +} + +int uDialogBox(UINT id,HWND parent,DLGPROC proc,long param) +{ + return uDialogBox(core_api::get_my_instance(),id,parent,proc,param); +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/utf8api.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/utf8api.h new file mode 100644 index 000000000..cde1bffd7 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/utf8api.h @@ -0,0 +1,9 @@ +#ifndef _FOOBAR2000_UTF8API_H_ +#define _FOOBAR2000_UTF8API_H_ + +#include "../utf8api/utf8api.h" + +HWND uCreateDialog(UINT id,HWND parent,DLGPROC proc,long param=0); +int uDialogBox(UINT id,HWND parent,DLGPROC proc,long param=0); + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/SDK/vis.h b/tools/vio2sf/src/foobar8/foobar2000/SDK/vis.h new file mode 100644 index 000000000..54f1d41cd --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/SDK/vis.h @@ -0,0 +1,57 @@ +#ifndef _FOOBAR2000_VIS_H_ +#define _FOOBAR2000_VIS_H_ + +#include "service.h" +#include "audio_chunk.h" + +typedef float vis_sample; + +struct vis_chunk +{ + enum + { + FLAG_LAGGED = 1, //unless you need to process all samples in the stream for some reason (eg. scanning for peak), you should ignore chunks marked as "lagged" + }; + + vis_sample * data; + unsigned samples;// sizeof(data) == sizeof(vis_sample) * samples * nch; + unsigned srate,nch; + vis_sample * spectrum; + unsigned spectrum_size;// sizeof(spectrum) == sizeof(vis_sample) * spectrum_size * nch; + unsigned flags;//see FLAG_* above + + inline double get_duration() const {return srate>0 ? (double)samples / (double)srate : 0;} + +};//both data and spectrum are channel-interleaved + +#define visualisation visualization +#define visualisation_factory visualization_factory + +class visualization : public service_base +{ +public://all calls are from main thread + virtual void on_data(const vis_chunk * data)=0; + virtual void on_flush()=0; + virtual double get_expected_latency() {return 0;}//return time in seconds; allowed to change when running + + //allowed to change in runtime + virtual bool is_active()=0; + virtual bool need_spectrum()=0; + + static const GUID class_guid; + static inline const GUID & get_class_guid() {return class_guid;} + + static bool is_vis_manager_present() + { + static const GUID guid = + { 0x5ca94fe1, 0x7593, 0x47de, { 0x8a, 0xdf, 0x8e, 0x36, 0xb4, 0x93, 0xa6, 0xd0 } }; + return service_enum_is_present(guid); + } +}; + +template +class visualization_factory : public service_factory_single_t {}; + +//usage: static visualisation_factory blah; + +#endif //_FOOBAR2000_VIS_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/foobar2000.dsw b/tools/vio2sf/src/foobar8/foobar2000/foobar2000.dsw new file mode 100644 index 000000000..1e2faf867 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/foobar2000.dsw @@ -0,0 +1,1346 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "7z_static"=.\foo_unpack\7zip\7zip\Bundles\Format7z\7z_static\7z_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "MACLib"=..\MAC_SDK_398a1\Source\MACLib\MACLib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "foo_abx"=.\foo_abx\foo_abx.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_albumlist"=.\foo_albumlist\foo_albumlist.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_ape"=.\foo_ape\foo_ape.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name MACLib + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_bitcompare"=.\foo_bitcompare\foo_bitcompare.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_burn"=.\foo_burn\foo_burn.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_cdda"=.\foo_cdda\foo_cdda.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_clienc"=.\foo_clienc\foo_clienc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_console"=.\foo_console\foo_console.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_diskwriter"=.\foo_diskwriter\foo_diskwriter.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_dsp_declick"=.\foo_dsp_declick\foo_dsp_declick.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency +}}} + +############################################################################### + +Project: "foo_dsp_extra"=.\foo_dsp_extra\foo_dsp_extra.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_dsp_pitch"=.\foo_dsp_pitch\foo_dsp_pitch.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_dsp_stereo3x"=.\foo_dsp_stereo3x\foo_dsp_stereo3x.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_flac"=.\foo_flac\foo_flac.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name libFLAC_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name libOggFLAC_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_infobox_simple"=.\foo_infobox_simple\foo_infobox_simple.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_input_std"=.\foo_input_std\foo_input_std.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name ogg_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name vorbis_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name vorbisfile_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name pfc + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name mpcdec + End Project Dependency + Begin Project Dependency + Project_Dep_Name mpglib + End Project Dependency + Begin Project Dependency + Project_Dep_Name libfaad + End Project Dependency + Begin Project Dependency + Project_Dep_Name mp4ff + End Project Dependency +}}} + +############################################################################### + +Project: "foo_masstag"=.\foo_masstag\foo_masstag.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_matroska"=.\foo_matroska\foo_matroska.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency + Begin Project Dependency + Project_Dep_Name libebml + End Project Dependency + Begin Project Dependency + Project_Dep_Name libmatroska + End Project Dependency +}}} + +############################################################################### + +Project: "foo_mod"=.\foo_mod\foo_mod.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_mpeg4u"=.\foo_mpeg4u\foo_mpeg4u.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libmp4av_st + End Project Dependency + Begin Project Dependency + Project_Dep_Name libmp4v2_st + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency + Begin Project Dependency + Project_Dep_Name libmp4v2_cb + End Project Dependency +}}} + +############################################################################### + +Project: "foo_oggpreview"=.\foo_oggpreview\foo_oggpreview.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency + Begin Project Dependency + Project_Dep_Name libOggFLAC_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name vorbis_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name vorbisfile_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name vorbisenc_static + End Project Dependency +}}} + +############################################################################### + +Project: "foo_out_dsound_ex"=.\foo_out_dsound_ex\foo_out_dsound_ex.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_out_ks"=.\foo_out_ks\foo_out_ks.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_output_std"=.\foo_output_std\foo_output_std.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_playlist_switcher"=.\foo_playlist_switcher\foo_playlist_switcher.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_playlistgen"=.\foo_playlistgen\foo_playlistgen.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_read_http"=.\foo_read_http\foo_read_http.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name jnetlib + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_rgscan"=.\foo_rgscan\foo_rgscan.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_search_ex"=.\foo_search_ex\foo_search_ex.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_spc"=.\foo_spc\foo_spc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name openspc + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_tagstress"=.\foo_tagstress\foo_tagstress.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_tfmx"=.\foo_tfmx\foo_tfmx.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_ui_std"=.\foo_ui_std\foo_ui_std.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_ui_std_ex"=.\foo_ui_std\foo_ui_std_ex.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency +}}} + +############################################################################### + +Project: "foo_ui_test"=.\foo_ui_test\foo_ui_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_unpack"=.\foo_unpack\foo_unpack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name unrar + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name 7z_static + End Project Dependency +}}} + +############################################################################### + +Project: "foo_vis_manager"=.\foo_vis_manager\foo_vis_manager.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency +}}} + +############################################################################### + +Project: "foo_vis_test"=.\foo_vis_test\foo_vis_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_vorbisenc"=.\foo_vorbisenc\foo_vorbisenc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name vorbis_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name vorbisenc_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name ogg_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foo_wavpack"=.\foo_wavpack\foo_wavpack.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foobar2000"=.\exe\foobar2000.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foo_abx + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_albumlist + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_ape + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_bitcompare + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_cdda + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_console + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_diskwriter + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_dsp_extra + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_dsp_pitch + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_infobox_simple + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_input_std + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_masstag + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_mod + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_out_ks + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_output_std + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_read_http + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_rgscan + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_spc + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_tfmx + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_ui_std + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_ui_test + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_unpack + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_vis_manager + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_vis_test + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_vorbisenc + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_wavpack + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_search_ex + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_ui_std_ex + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_playlist_switcher + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_out_dsound_ex + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_dsp_declick + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_flac + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_cltag + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_tagstress + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_mp4 + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_mpeg4u + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_matroska + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_playlistgen + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_clienc + End Project Dependency + Begin Project Dependency + Project_Dep_Name foo_mad + End Project Dependency +}}} + +############################################################################### + +Project: "foobar2000_SDK"=.\SDK\foobar2000_SDK.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pfc + End Project Dependency + Begin Project Dependency + Project_Dep_Name utf8api + End Project Dependency +}}} + +############################################################################### + +Project: "foobar2000_component_client"=.\foobar2000_component_client\foobar2000_component_client.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "foobar2000_sdk_helpers"=.\helpers\foobar2000_sdk_helpers.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "jnetlib"=.\foo_read_http\jnetlib\jnetlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libFLAC_static"=..\flac\src\libFLAC\libFLAC_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libOggFLAC_static"=..\flac\src\libOggFLAC\libOggFLAC_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ogg_static + End Project Dependency +}}} + +############################################################################### + +Project: "libebml"=..\libebml\make\vc6\lib\static\libebml.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libfaad"=..\faad2\libfaad\libfaad.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libmad"="..\libmad-0.15.1b\msvc++\libmad.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libmatroska"=..\libmatroska\make\vc6\lib\static\libmatroska.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libmp4av_st"=..\faad2\common\mp4av\libmp4av_st.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libmp4v2_cb"=..\faad2\common\mp4v2\libmp4v2_cb.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libspeex"=..\speex\win32\libspeex\libspeex.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mp4ff"=..\faad2\common\mp4ff\mp4ff.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mpcdec"=.\foo_input_std\mpc\mpcdec.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mpglib"=.\foo_input_std\mpglib\mpglib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ogg_static"=..\ogg\win32\ogg_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "openspc"=..\libopenspc\openspc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pfc"=..\pfc\pfc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "unrar"=..\UnrarSrc\unrar.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "utf8api"=.\utf8api\utf8api.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pfc + End Project Dependency +}}} + +############################################################################### + +Project: "vorbis_static"=..\vorbis\win32\vorbis_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "vorbisenc_static"=..\vorbis\win32\vorbisenc_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "vorbisfile_static"=..\vorbis\win32\vorbisfile_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zlib"=..\zlib\zlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/tools/vio2sf/src/foobar8/foobar2000/foobar2000_component_client/component_client.cpp b/tools/vio2sf/src/foobar8/foobar2000/foobar2000_component_client/component_client.cpp new file mode 100644 index 000000000..c93549bb1 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/foobar2000_component_client/component_client.cpp @@ -0,0 +1,93 @@ +#include "../SDK/foobar2000.h" +#include "../SDK/component.h" + +static HINSTANCE g_hIns; + +static string_simple g_name,g_full_path; + +static bool g_services_available = false; + +#ifdef _DEBUG +static void selftest() +{ + assert(sizeof(bool)==1); + assert(sizeof(int)==4); + assert(sizeof(__int64)==8); +} +#endif + +extern "C" +{ + __declspec(dllexport) foobar2000_client * _cdecl foobar2000_get_interface(foobar2000_api * p_api,HINSTANCE hIns) + { +#ifdef _DEBUG + selftest(); +#endif + cfg_var::config_on_app_init(); + g_hIns = hIns; + g_api = p_api; + + return &g_client; + } +} + + +namespace core_api +{ + + HINSTANCE get_my_instance() + { + return g_hIns; + } + + HWND get_main_window() + { + return g_api->get_main_window(); + } + const char * get_my_file_name() + { + return g_name; + } + + const char * get_my_full_path() + { + return g_full_path; + } + + bool are_services_available() + { + return g_services_available; + } + bool assert_main_thread() + { + return (g_services_available && g_api) ? g_api->assert_main_thread() : true; + } + + bool is_main_thread() + { + return (g_services_available && g_api) ? g_api->is_main_thread() : true; + } + const char * get_profile_path() + { + return (g_services_available && g_api) ? g_api->get_profile_path() : 0; + } +} + +void foobar2000_client::set_library_path(const char * path,const char * name) +{ + g_full_path = path; + g_name = name; +} + +void foobar2000_client::services_init(bool val) +{ + g_services_available = val; +} + +#ifndef _DEBUG +#ifdef _MSC_VER +#if _MSC_VER==1200 +#pragma comment(linker,"/opt:nowin98") +#endif +#endif +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/StdAfx.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/StdAfx.cpp new file mode 100644 index 000000000..9dc5b543a --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/StdAfx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// foobar2000_sdk_helpers.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/StdAfx.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/StdAfx.h new file mode 100644 index 000000000..50a4e7bf8 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/StdAfx.h @@ -0,0 +1,22 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__6356EC2B_6DD1_4BE8_935C_87ECBA8697E4__INCLUDED_) +#define AFX_STDAFX_H__6356EC2B_6DD1_4BE8_935C_87ECBA8697E4__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#include "../SDK/foobar2000.h" +#include "helpers.h" + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__6356EC2B_6DD1_4BE8_935C_87ECBA8697E4__INCLUDED_) diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/create_directory_helper.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/create_directory_helper.cpp new file mode 100644 index 000000000..aa785337f --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/create_directory_helper.cpp @@ -0,0 +1,109 @@ +#include "stdafx.h" +#include "create_directory_helper.h" + +namespace create_directory_helper +{ + void create_directory_structure(const char * path) + { + mem_block_t temp(strlen(path)+1); + strcpy(temp,path); + char * ptr = strstr(temp,":\\"); + if (ptr) + { + ptr+=2; + while(*ptr) + { + if (*ptr == '\\') + { + *ptr = 0; + file::g_create_directory(temp); + *ptr = '\\'; + } + ptr++; + } + } + } + + static bool is_bad_dirchar(char c) + { + return c==' ' || c=='.'; + } + + void make_path(const char * parent,const char * filename,const char * extension,bool allow_new_dirs,string8 & out) + { + out.reset(); + if (parent && *parent) + { + out = parent; + out.fix_dir_separator('\\'); + } + bool last_char_is_dir_sep = true; + while(*filename) + { +#ifdef WIN32 + if (allow_new_dirs && is_bad_dirchar(*filename)) + { + const char * ptr = filename+1; + while(is_bad_dirchar(*ptr)) ptr++; + if (*ptr!='\\' && *ptr!='/') out.add_string_n(filename,ptr-filename); + filename = ptr; + if (*filename==0) break; + } +#endif + if (is_path_bad_char(*filename)) + { + if (allow_new_dirs && (*filename=='\\' || *filename=='/')) + { + if (!last_char_is_dir_sep) + { + out.add_char('\\'); + last_char_is_dir_sep = true; + } + } + else + out.add_char('_'); + } + else + { + out.add_byte(*filename); + last_char_is_dir_sep = false; + } + filename++; + } + if (out.length()>0 && out[out.length()-1]=='\\') + { + out.add_string("noname"); + } + if (extension && *extension) + { + out.add_char('.'); + out.add_string(extension); + } + } +} + +void create_directory_helper::format_filename(metadb_handle * handle,const char * spec,string8 & out,const char * extra) +{ + out = ""; + string8 temp; + for(;;) + { + const char * ptr1 = strchr(spec,'\\'), *ptr2 = strchr(spec,'/'); + if ((!ptr1 && ptr2) || (ptr1 && ptr2 && ptr2handle_format_title(temp,string_simple(spec,ptr1-spec),extra); + temp.fix_filename_chars(); + spec = ptr1+1; + out += temp; + out += "\\"; + } + else + { + handle->handle_format_title(temp,spec,extra); + temp.fix_filename_chars(); + out += temp; + break; + } + } +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/create_directory_helper.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/create_directory_helper.h new file mode 100644 index 000000000..08fd44d32 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/create_directory_helper.h @@ -0,0 +1,10 @@ +#ifndef _CREATE_DIRECTORY_HELPER_H_ +#define _CREATE_DIRECTORY_HELPER_H_ + +namespace create_directory_helper { + void create_directory_structure(const char * path); + void make_path(const char * parent,const char * filename,const char * extension,bool allow_new_dirs,string8 & out); + void format_filename(class metadb_handle * handle,const char * spec,string8 & out,const char * extra=0); +}; + +#endif//_CREATE_DIRECTORY_HELPER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/dialog_resize_helper.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/dialog_resize_helper.cpp new file mode 100644 index 000000000..ecf2fe50d --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/dialog_resize_helper.cpp @@ -0,0 +1,201 @@ +#include "stdafx.h" +#include "dialog_resize_helper.h" + +void resize::calc_xy(HWND wnd,UINT id,RECT &r,RECT & o) +{ + RECT c; + GetClientRect(wnd,&c); + SetWindowPos(GetDlgItem(wnd,id),0,0,0, + r.right-r.left+c.right-o.right, + r.bottom-r.top+c.bottom-o.bottom, + SWP_NOMOVE|SWP_NOZORDER); +} + +void resize::calc_move_xy(HWND wnd,UINT id,RECT &r,RECT & o) +{ + RECT c; + GetClientRect(wnd,&c); + SetWindowPos(GetDlgItem(wnd,id),0, + c.right-o.right+r.left, + c.bottom-o.bottom+r.top, + 0,0,SWP_NOSIZE|SWP_NOZORDER); +} + +void resize::calc_move_x(HWND wnd,UINT id,RECT &r,RECT & o) +{ + RECT c; + GetClientRect(wnd,&c); + SetWindowPos(GetDlgItem(wnd,id),0, + c.right-o.right+r.left, + r.top, + 0,0,SWP_NOSIZE|SWP_NOZORDER); +} + +void resize::calc_move_x_size_y(HWND wnd,UINT id,RECT &r,RECT & o) +{ + RECT c; + GetClientRect(wnd,&c); + SetWindowPos(GetDlgItem(wnd,id),0, + c.right-o.right+r.left, + r.top, + r.right-r.left, + r.bottom-r.top+c.bottom-o.bottom, + SWP_NOZORDER); +} + +void resize::calc_move_y(HWND wnd,UINT id,RECT &r,RECT & o) +{ + RECT c; + GetClientRect(wnd,&c); + SetWindowPos(GetDlgItem(wnd,id),0, + r.left, + c.bottom-o.bottom+r.top, + 0,0,SWP_NOSIZE|SWP_NOZORDER); +} + +void resize::calc_x(HWND wnd,UINT id,RECT &r,RECT & o) +{ + RECT c; + GetClientRect(wnd,&c); + SetWindowPos(GetDlgItem(wnd,id),0,0,0, + r.right-r.left+c.right-o.right, + r.bottom-r.top, + SWP_NOMOVE|SWP_NOZORDER); +} + +void GetChildRect(HWND wnd,UINT id,RECT* child) +{ + RECT temp; + GetWindowRect(GetDlgItem(wnd,id),&temp); + MapWindowPoints(0,wnd,(POINT*)&temp,2); + *child = temp; +} + +/* +class dialog_resize_helper +{ + struct entry { RECT orig; UINT id; UINT flags }; + mem_block_list data; + RECT orig_client; + HWND parent; +public: + enum { + X_MOVE = 1, X_SIZE = 2, Y_MOVE = 4, Y_SIZE = 8 + }; + void set_parent(HWND wnd); + void add_item(UINT id,UINT flags); + void reset(); +}; +*/ + +void dialog_resize_helper::set_parent(HWND wnd) +{ + reset(); + parent = wnd; + GetClientRect(parent,&orig_client); +} + +void dialog_resize_helper::reset() +{ + parent = 0; +} + +void dialog_resize_helper::on_wm_size() +{ + if (parent) + { + unsigned n; + for(n=0;nptMaxTrackSize.x = r.right; + info->ptMaxTrackSize.y = r.bottom; + } + if (min_x && min_y) + { + r.left = 0; r.right = min_x; + r.top = 0; r.bottom = min_y; + MapDialogRect(wnd,&r); + info->ptMinTrackSize.x = r.right; + info->ptMinTrackSize.y = r.bottom; + } + } + return true; + case WM_INITDIALOG: + set_parent(wnd); + { + unsigned n; + for(n=0;n & out) +{ + const char * src = data; + while(*src) + { + int ptr = 0; + while(src[ptr] && src[ptr]!=separator) ptr++; + if (ptr>0) + { + out.add_item(strdup_n(src,ptr)); + src += ptr; + } + while(*src==separator) src++; + } +} + +void cfg_dropdown_history::parse_list(const ptr_list_simple & src) +{ + unsigned n; + string8 temp; + temp.set_mem_logic(mem_block::ALLOC_FAST); + for(n=0;n list; + build_list(list); + unsigned n; + for(n=0;n list; + build_list(list); + unsigned n; + bool found = false; + for(n=0;n max) list.delete_by_idx(list.get_count()-1); + list.insert_item(strdup(item),0); + } + parse_list(list); + list.free_all(); +} + +bool cfg_dropdown_history::is_empty() +{ + const char * src = data; + while(*src) + { + if (*src!=separator) return false; + src++; + } + return true; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/dropdown_helper.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/dropdown_helper.h new file mode 100644 index 000000000..abe027600 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/dropdown_helper.h @@ -0,0 +1,21 @@ +#ifndef _DROPDOWN_HELPER_H_ +#define _DROPDOWN_HELPER_H_ + + +class cfg_dropdown_history +{ + enum {separator = '\n'}; + cfg_string data; + unsigned max; + void build_list(ptr_list_simple & out); + void parse_list(const ptr_list_simple & src); +public: + cfg_dropdown_history(const char * name,unsigned p_max = 10,const char * init_vals = "") : data(name,init_vals) {max = p_max;} + void setup_dropdown(HWND wnd); + void setup_dropdown(HWND wnd,UINT id) {setup_dropdown(GetDlgItem(wnd,id));} + void add_item(const char * item); + bool is_empty(); +}; + + +#endif //_DROPDOWN_HELPER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/foobar2000_sdk_helpers.dsp b/tools/vio2sf/src/foobar8/foobar2000/helpers/foobar2000_sdk_helpers.dsp new file mode 100644 index 000000000..4f482c293 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/foobar2000_sdk_helpers.dsp @@ -0,0 +1,165 @@ +# Microsoft Developer Studio Project File - Name="foobar2000_sdk_helpers" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=foobar2000_sdk_helpers - 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 "foobar2000_sdk_helpers.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 "foobar2000_sdk_helpers.mak" CFG="foobar2000_sdk_helpers - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "foobar2000_sdk_helpers - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "foobar2000_sdk_helpers - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "foobar2000_sdk_helpers - 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 Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"stdafx.h" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "foobar2000_sdk_helpers - 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 Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "foobar2000_sdk_helpers - Win32 Release" +# Name "foobar2000_sdk_helpers - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\create_directory_helper.cpp +# End Source File +# Begin Source File + +SOURCE=.\dialog_resize_helper.cpp +# End Source File +# Begin Source File + +SOURCE=.\dropdown_helper.cpp +# End Source File +# Begin Source File + +SOURCE=.\playback_order_helper.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\wildcard.cpp +# End Source File +# Begin Source File + +SOURCE=.\win32_dialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\window_placement_helper.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\create_directory_helper.h +# End Source File +# Begin Source File + +SOURCE=.\dialog_resize_helper.h +# End Source File +# Begin Source File + +SOURCE=.\dropdown_helper.h +# End Source File +# Begin Source File + +SOURCE=.\helpers.h +# End Source File +# Begin Source File + +SOURCE=.\playback_order_helper.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\wildcard.h +# End Source File +# Begin Source File + +SOURCE=.\win32_dialog.h +# End Source File +# Begin Source File + +SOURCE=.\window_placement_helper.h +# End Source File +# End Group +# End Target +# End Project diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/helpers.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/helpers.h new file mode 100644 index 000000000..64a59e5f5 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/helpers.h @@ -0,0 +1,12 @@ +#ifndef _FOOBAR2000_SDK_HELPERS_H_ +#define _FOOBAR2000_SDK_HELPERS_H_ + +#include "create_directory_helper.h" +#include "dialog_resize_helper.h" +#include "dropdown_helper.h" +#include "window_placement_helper.h" +#include "win32_dialog.h" +#include "playback_order_helper.h" +#include "wildcard.h" + +#endif //_FOOBAR2000_SDK_HELPERS_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/playback_order_helper.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/playback_order_helper.cpp new file mode 100644 index 000000000..38c250a24 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/playback_order_helper.cpp @@ -0,0 +1,82 @@ +#include "stdafx.h" + + +namespace playback_order_helper +{ + static const char variable_name[] = "CORE/Playback flow control"; + + unsigned get_count() + { + return service_enum_get_count_t(playback_flow_control); + } + + const char * get_name_from_index(unsigned idx) + { + const char * ret = 0; + assert(idx>=0); + assert(idxget_name(); + ptr->service_release(); + return ret; + } + + unsigned get_index_from_name(const char * name) + { + unsigned idx, max = get_count(); + for(idx=0;idx(variable_name,calloninit), func(p_func) {} + + void modify_callback::on_changed(const config_var_string * ptr) + { + string8 name; + ptr->get_value(name); + func(name,get_index_from_name(name)); + } + +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/playback_order_helper.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/playback_order_helper.h new file mode 100644 index 000000000..a591e3811 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/playback_order_helper.h @@ -0,0 +1,28 @@ +#ifndef _FOOBAR2000_PLAYBACK_ORDER_HELPER_H_ +#define _FOOBAR2000_PLAYBACK_ORDER_HELPER_H_ + +namespace playback_order_helper { + enum { order_invalid = (unsigned)(-1) }; + unsigned get_count(); + const char * get_name_from_index(unsigned idx); //index is 0 ... get_count()-1 + unsigned get_index_from_name(const char * name);//returns order_invalid if not found + unsigned get_config_by_index();//order_invalid on error + const char * get_config_by_name();//reverts to "default" on error + void get_config_by_name(string_base & out);//may return name of order that doesn't exist anymore (e.g. user removing dlls) + void set_config_by_name(const char * name); + void set_config_by_index(unsigned idx); + + class modify_callback : public config_var_callback_autoreg + { + void (*func)(const char * newval,unsigned newidx); + virtual void on_changed(const config_var_string * ptr); + public: + modify_callback(void (*p_func)(const char * newval,unsigned newidx), bool calloninit = false); + }; + + + inline order_exists(const char * name) {return get_index_from_name(name)!=order_invalid;} +}; + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/wildcard.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/wildcard.cpp new file mode 100644 index 000000000..1c3901bf9 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/wildcard.cpp @@ -0,0 +1,44 @@ +#include "stdafx.h" + +static bool test_recur(const char * fn,const char * rm,bool b_sep) +{ + for(;;) + { + if ((b_sep && *rm==';') || *rm==0) return *fn==0; + else if (*rm=='*') + { + rm++; + do + { + if (test_recur(fn,rm,b_sep)) return true; + } while(utf8_advance(fn)); + return false; + } + else if (*fn==0) return false; + else if (*rm!='?' && char_lower(utf8_get_char(fn))!=char_lower(utf8_get_char(rm))) return false; + + fn = utf8_char_next(fn); rm = utf8_char_next(rm); + } +} + +bool wildcard_helper::test_path(const char * path,const char * pattern,bool b_sep) {return test(path + string8::g_scan_filename(path),pattern,b_sep);} + +bool wildcard_helper::test(const char * fn,const char * pattern,bool b_sep) +{ + if (!b_sep) return test_recur(fn,pattern,false); + const char * rm=pattern; + while(*rm) + { + if (test_recur(fn,rm,true)) return true; + while(*rm && *rm!=';') rm++; + if (*rm==';') + { + while(*rm==';') rm++; + while(*rm==' ') rm++; + } + }; + + return false; +} + +bool wildcard_helper::has_wildcards(const char * str) {return strchr(str,'*') || strchr(str,'?');} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/wildcard.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/wildcard.h new file mode 100644 index 000000000..4282094f1 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/wildcard.h @@ -0,0 +1,11 @@ +#ifndef __FOOBAR2000_HELPER_WILDCARD_H__ +#define __FOOBAR2000_HELPER_WILDCARD_H__ + +namespace wildcard_helper +{ + bool test_path(const char * path,const char * pattern,bool b_separate_by_semicolon = false);//will extract filename from path first + bool test(const char * str,const char * pattern,bool b_separate_by_semicolon = false);//tests if str matches pattern + bool has_wildcards(const char * str); +}; + +#endif //__FOOBAR2000_HELPER_WILDCARD_H__ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/win32_dialog.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/win32_dialog.cpp new file mode 100644 index 000000000..e49fc26c0 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/win32_dialog.cpp @@ -0,0 +1,41 @@ +#include "stdafx.h" + + +namespace dialog_helper { + + + BOOL CALLBACK dialog::DlgProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) + { + dialog * p_this; + BOOL rv; + if (msg==WM_INITDIALOG) + { + p_this = reinterpret_cast(lp); + p_this->wnd = wnd; + uSetWindowLong(wnd,DWL_USER,lp); + } + else p_this = reinterpret_cast(uGetWindowLong(wnd,DWL_USER)); + + rv = p_this ? p_this->on_message(msg,wp,lp) : FALSE; + + if (msg==WM_DESTROY && p_this) + { + uSetWindowLong(wnd,DWL_USER,0); + wnd = 0; + } + + return rv; + } + + void set_item_text_multi(HWND wnd,const set_item_text_multi_param * param,unsigned count) + { + unsigned n; + for(n=0;n(this));} + + inline HWND run_modeless(unsigned id,HWND parent) {return uCreateDialog(id,parent,DlgProc,reinterpret_cast(this));} + }; + + struct set_item_text_multi_param + { + unsigned id; + const char * text; + }; + + void set_item_text_multi(HWND wnd,const set_item_text_multi_param * param,unsigned count); + +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/window_placement_helper.cpp b/tools/vio2sf/src/foobar8/foobar2000/helpers/window_placement_helper.cpp new file mode 100644 index 000000000..006e8d545 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/window_placement_helper.cpp @@ -0,0 +1,51 @@ +#include "stdafx.h" +#include "window_placement_helper.h" + +//introduced in win98/win2k +typedef HANDLE (WINAPI * t_MonitorFromRect)(const RECT*, DWORD); + +#ifndef MONITOR_DEFAULTTONULL +#define MONITOR_DEFAULTTONULL 0x00000000 +#endif + +static bool test_rect(const RECT * rc) +{ + t_MonitorFromRect p_MonitorFromRect = (t_MonitorFromRect)GetProcAddress(GetModuleHandle("user32"),"MonitorFromRect"); + if (!p_MonitorFromRect) + { + //if (!SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0)) return true; + int max_x = GetSystemMetrics(SM_CXSCREEN), max_y = GetSystemMetrics(SM_CYSCREEN); + return rc->left < max_x && rc->right > 0 && rc->top < max_y && rc->bottom > 0; + } + return !!p_MonitorFromRect(rc,MONITOR_DEFAULTTONULL); +} + + +bool apply_window_placement(const cfg_struct_t & src,HWND wnd) +{ + bool rv = false; + if (config_var_int::g_get_value("CORE/remember window positions")) + { + WINDOWPLACEMENT wp = src; + if (wp.length==sizeof(wp) && test_rect(&wp.rcNormalPosition)) + { + if (SetWindowPlacement(wnd,&wp)) + rv = true; + } + } + return rv; +} + +void read_window_placement(cfg_struct_t & dst,HWND wnd) +{ + WINDOWPLACEMENT wp; + memset(&wp,0,sizeof(wp)); + if (config_var_int::g_get_value("CORE/remember window positions")) + { + wp.length = sizeof(wp); + if (!GetWindowPlacement(wnd,&wp)) + memset(&wp,0,sizeof(wp)); + } + dst = wp; +} + diff --git a/tools/vio2sf/src/foobar8/foobar2000/helpers/window_placement_helper.h b/tools/vio2sf/src/foobar8/foobar2000/helpers/window_placement_helper.h new file mode 100644 index 000000000..1e3a020e5 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/helpers/window_placement_helper.h @@ -0,0 +1,7 @@ +#ifndef _WINDOW_PLACEMENT_HELPER_H_ +#define _WINDOW_PLACEMENT_HELPER_H_ + +void read_window_placement(cfg_struct_t & dst,HWND wnd); +bool apply_window_placement(const cfg_struct_t & src,HWND wnd); + +#endif //_WINDOW_PLACEMENT_HELPER_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/crash_info.cpp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/crash_info.cpp new file mode 100644 index 000000000..8983982d7 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/crash_info.cpp @@ -0,0 +1,569 @@ +#include "utf8api.h" +#include + +typedef BOOL (__stdcall * t_SymInitialize)(IN HANDLE hProcess,IN LPSTR UserSearchPath,IN BOOL fInvadeProcess); +typedef BOOL (__stdcall * t_SymCleanup)(IN HANDLE hProcess); +typedef BOOL (__stdcall * t_SymGetModuleInfo)(IN HANDLE hProcess,IN DWORD dwAddr,OUT PIMAGEHLP_MODULE ModuleInfo); +typedef BOOL (__stdcall * t_SymGetSymFromAddr)(IN HANDLE hProcess,IN DWORD dwAddr,OUT PDWORD pdwDisplacement,OUT PIMAGEHLP_SYMBOL Symbol); +typedef BOOL (__stdcall * t_SymEnumerateModules)(IN HANDLE hProcess,IN PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,IN PVOID UserContext); + +static t_SymInitialize p_SymInitialize; +static t_SymCleanup p_SymCleanup; +static t_SymGetModuleInfo p_SymGetModuleInfo; +static t_SymGetSymFromAddr p_SymGetSymFromAddr; +static t_SymEnumerateModules p_SymEnumerateModules; + +static HMODULE hImageHlp; + +static critical_section g_imagehelp_sync; + +static string_simple version_string; + +static long crash_no; + +static __declspec(thread) char g_thread_call_stack[1024]; +static __declspec(thread) unsigned g_thread_call_stack_length; + +static bool load_imagehelp() +{ + static bool error; + if (hImageHlp) return true; + if (error) return false; + hImageHlp = LoadLibraryA("imagehlp.dll"); + if (hImageHlp==0) {error = true; return false; } + p_SymInitialize = (t_SymInitialize)GetProcAddress(hImageHlp,"SymInitialize"); + p_SymCleanup = (t_SymCleanup)GetProcAddress(hImageHlp,"SymCleanup"); + p_SymGetModuleInfo = (t_SymGetModuleInfo)GetProcAddress(hImageHlp,"SymGetModuleInfo"); + p_SymGetSymFromAddr = (t_SymGetSymFromAddr)GetProcAddress(hImageHlp,"SymGetSymFromAddr"); + p_SymEnumerateModules = (t_SymEnumerateModules)GetProcAddress(hImageHlp,"SymEnumerateModules"); + + if (!p_SymInitialize || !p_SymCleanup || !p_SymGetModuleInfo || !p_SymGetSymFromAddr || !p_SymEnumerateModules) + { + FreeLibrary(hImageHlp); + hImageHlp = 0; + error = true; + return false; + } + + return true; +} + +#define LOG_PATH_LEN (MAX_PATH + 32) + +static HANDLE create_failure_log(char * filename_used,TCHAR * fullpath_used) +{ + bool rv = false; + TCHAR path[LOG_PATH_LEN]; + path[0]=0; + GetModuleFileName(0,path,MAX_PATH); + path[MAX_PATH-1]=0; + { + TCHAR * ptr = path + _tcslen(path); + while(ptr>path && *ptr!='\\') ptr--; + ptr[1]=0; + } + TCHAR * fn_out = path + _tcslen(path); + HANDLE hFile = INVALID_HANDLE_VALUE; + unsigned attempts = 0; + for(;;) + { + if (*fn_out==0) + { + _tcscpy(fn_out,TEXT("failure.txt")); + if (filename_used) strcpy(filename_used,"failure.txt"); + } + else + { + attempts++; + wsprintf(fn_out,TEXT("failure_%08u.txt"),attempts); + if (filename_used) wsprintfA(filename_used,"failure_%08u.txt",attempts); + } + hFile = CreateFile(path,GENERIC_WRITE,0,0,CREATE_NEW,0,0); + if (hFile!=INVALID_HANDLE_VALUE) break; + if (attempts > 1000) break; + } + if (hFile!=INVALID_HANDLE_VALUE && fullpath_used) + { + _tcscpy(fullpath_used,path); + } + return hFile; +} + +static void WriteFileString_internal(HANDLE hFile,const char * ptr,unsigned len) +{ + DWORD bah; + WriteFile(hFile,ptr,len,&bah,0); +} + +static void WriteFileString(HANDLE hFile,const char * str) +{ + const char * ptr = str; + for(;;) + { + const char * start = ptr; + ptr = strchr(ptr,'\n'); + if (ptr) + { + if (ptr>start) WriteFileString_internal(hFile,start,ptr-start); + WriteFileString_internal(hFile,"\x0d\x0a",2); + ptr++; + } + else + { + WriteFileString_internal(hFile,start,strlen(start)); + break; + } + } +} + +static char * hexdump8(char * out,unsigned address,const char * msg,int from,int to) +{ + unsigned max = (to-from)*16; + if (!IsBadReadPtr((const void*)(address+(from*16)),max)) + { + out += sprintf(out,"%s (%08Xh):",msg,address); + unsigned n; + const unsigned char * src = (const unsigned char*)(address)+(from*16); + + for(n=0;nExceptionRecord->ExceptionAddress; + sprintf(temp,"Illegal operation:\nCode: %08Xh, flags: %08Xh, address: %08Xh\n",param->ExceptionRecord->ExceptionCode,param->ExceptionRecord->ExceptionFlags,address); + WriteFileString(hFile,temp); + + if (param->ExceptionRecord->ExceptionCode==EXCEPTION_ACCESS_VIOLATION && param->ExceptionRecord->NumberParameters>=2) + { + sprintf(temp,"Access violation, operation: %s, address: %08Xh\n",param->ExceptionRecord->ExceptionInformation[0] ? "write" : "read",param->ExceptionRecord->ExceptionInformation[1]); + WriteFileString(hFile,temp); + } + + WriteFileString(hFile,"Call path:\n"); + WriteFileString(hFile,g_thread_call_stack); + WriteFileString(hFile,"\n"); + if (number==1) + { + WriteFileString(hFile,"This is the first crash logged by this instance.\n"); + } + else + { + const char * meh; + switch(number%10) + { + case 1: + meh = "st"; + break; + case 2: + meh = "nd"; + break; + case 3: + meh = "rd"; + break; + default: + meh = "th"; + break; + } + sprintf(temp,"This is your %u-%s crash. When reporting the problem to a developer, please try to post info about the first crash instead.\n",number,meh); + WriteFileString(hFile,temp); + } + + hexdump8(temp,address,"Code bytes",-4,+4); + WriteFileString(hFile,temp); + hexdump32(temp,param->ContextRecord->Esp,"Stack",-2,+18); + WriteFileString(hFile,temp); + sprintf(temp,"Registers:\nEAX: %08X, EBX: %08X, ECX: %08X, EDX: %08X\nESI: %08X, EDI: %08X, EBP: %08X, ESP: %08X\n",param->ContextRecord->Eax,param->ContextRecord->Ebx,param->ContextRecord->Ecx,param->ContextRecord->Edx,param->ContextRecord->Esi,param->ContextRecord->Edi,param->ContextRecord->Ebp,param->ContextRecord->Esp); + WriteFileString(hFile,temp); + + { + bool imagehelp_succeeded = false; + insync(g_imagehelp_sync); + if (load_imagehelp()) + { + HANDLE hProcess = GetCurrentProcess(); + char exepath[MAX_PATH]; + exepath[0]=0; + GetModuleFileNameA(0,exepath,tabsize(exepath)); + exepath[tabsize(exepath)-1]=0; + { + char * ptr = exepath + strlen(exepath); + while(ptr>exepath && *ptr!='\\') ptr--; + *ptr=0; + } + if (p_SymInitialize(hProcess,exepath,TRUE)) + { + { + IMAGEHLP_MODULE mod; + memset(&mod,0,sizeof(mod)); + mod.SizeOfStruct = sizeof(mod); + if (p_SymGetModuleInfo(hProcess,address,&mod)) + { + sprintf(temp,"Crash location: \"%s\", loaded at %08Xh - %08Xh\n",mod.ModuleName,mod.BaseOfImage,mod.BaseOfImage+mod.ImageSize); + WriteFileString(hFile,temp); + } + else + { + sprintf(temp,"Unable to identify crash location\n"); + WriteFileString(hFile,temp); + } + } + + { + union + { + char buffer[128]; + IMAGEHLP_SYMBOL symbol; + }; + memset(buffer,0,sizeof(buffer)); + symbol.SizeOfStruct = sizeof(symbol); + symbol.MaxNameLength = buffer + sizeof(buffer) - symbol.Name; + DWORD offset = 0; + if (p_SymGetSymFromAddr(hProcess,address,&offset,&symbol)) + { + buffer[tabsize(buffer)-1]=0; + if (symbol.Name[0]) + { + sprintf(temp,"Symbol: \"%s\" (+%08Xh)\n",symbol.Name,offset); + WriteFileString(hFile,temp); + } + } + } + + WriteFileString(hFile,"\nLoaded modules:\n"); + p_SymEnumerateModules(hProcess,EnumModulesCallback,hFile); + + + call_stack_parse(param->ContextRecord->Esp,hFile,temp,hProcess); + + p_SymCleanup(hProcess); + imagehelp_succeeded = true; + } + } + if (!imagehelp_succeeded) + { + WriteFileString(hFile,"Failed to get module/symbol info.\n"); + } + + WriteFileString(hFile,"\nVersion info: \n"); + WriteFileString(hFile,version_string); + WriteFileString(hFile,"\n"); + WriteFileString(hFile, + #ifdef UNICODE + "UNICODE" + #else + "ANSI" + #endif + ); + + CloseHandle(hFile); + ShellExecute(0,0,log_path,0,0,SW_SHOW); + } + } +} + +//not really being utf8 here, all chars should be in 128 ascii range +UTF8API_EXPORT UINT uPrintCrashInfo(LPEXCEPTION_POINTERS param,const char * extra_info,char * outbase) +{ + uDumpCrashInfo(param); + if (extra_info==0) extra_info = g_thread_call_stack; + char * out = outbase; + long number = InterlockedIncrement(&crash_no); + + unsigned address = (unsigned)param->ExceptionRecord->ExceptionAddress; + out += sprintf(out,"Illegal operation:\nCode: %08Xh, flags: %08Xh, address: %08Xh",param->ExceptionRecord->ExceptionCode,param->ExceptionRecord->ExceptionFlags,address); + + if (param->ExceptionRecord->ExceptionCode==EXCEPTION_ACCESS_VIOLATION && param->ExceptionRecord->NumberParameters>=2) + { + out += sprintf(out,"\nAccess violation, operation: %s, address: %08Xh",param->ExceptionRecord->ExceptionInformation[0] ? "write" : "read",param->ExceptionRecord->ExceptionInformation[1]); + } + + { + bool imagehelp_succeeded = false; + insync(g_imagehelp_sync); + if (load_imagehelp()) + { + HANDLE hProcess = GetCurrentProcess(); + char exepath[MAX_PATH]; + exepath[0]=0; + GetModuleFileNameA(0,exepath,tabsize(exepath)); + exepath[tabsize(exepath)-1]=0; + { + char * ptr = exepath + strlen(exepath); + while(ptr>exepath && *ptr!='\\') ptr--; + *ptr=0; + } + if (p_SymInitialize(hProcess,exepath,TRUE)) + { + { + IMAGEHLP_MODULE mod; + memset(&mod,0,sizeof(mod)); + mod.SizeOfStruct = sizeof(mod); + if (p_SymGetModuleInfo(hProcess,address,&mod)) + { + out += sprintf(out,"\nCrash location: \"%s\", loaded at %08Xh - %08Xh",mod.ModuleName,mod.BaseOfImage,mod.BaseOfImage+mod.ImageSize); + } + else + { + out += sprintf(out,"\nUnable to identify crash location"); + } + } + + { + union + { + char buffer[128]; + IMAGEHLP_SYMBOL symbol; + }; + memset(buffer,0,sizeof(buffer)); + symbol.SizeOfStruct = sizeof(symbol); + symbol.MaxNameLength = buffer + sizeof(buffer) - symbol.Name; + DWORD offset = 0; + if (p_SymGetSymFromAddr(hProcess,address,&offset,&symbol)) + { + buffer[tabsize(buffer)-1]=0; + if (symbol.Name[0]) + { + out += sprintf(out,"\nSymbol: \"%s\" (+%08Xh)",symbol.Name,offset); + } + } + } + + p_SymCleanup(hProcess); + imagehelp_succeeded = true; + } + } + if (!imagehelp_succeeded) + { + out += sprintf(out,"\n(failed to get module/symbol info)"); + } + if (extra_info && *extra_info) + { + unsigned len = strlen_max(extra_info,256); + out += sprintf(out,"\nAdditional info: "); + memcpy(out,extra_info,len); + out+=len; + *out=0; + } + if (number==1) + { + out += sprintf(out,"\nThis is the first crash logged by this instance."); + } + else + { + const char * meh; + switch(number%10) + { + case 1: + meh = "st"; + break; + case 2: + meh = "nd"; + break; + case 3: + meh = "rd"; + break; + default: + meh = "th"; + break; + } + out += sprintf(out,"\nThis is your %u-%s crash. When reporting the problem to a developer, please try to post info about the first crash instead.",number,meh); + } + } + + out += sprintf(out,"\n"); + out = hexdump8(out,address,"Code bytes",-2,+2); + + return strlen(outbase); +} + +static LPTOP_LEVEL_EXCEPTION_FILTER filterproc; + +static LONG WINAPI exceptfilter(LPEXCEPTION_POINTERS param) +{ + uDumpCrashInfo(param); + ExitProcess(0); + return filterproc(param);//never called +} + +UTF8API_EXPORT void uPrintCrashInfo_Init(const char * name)//called only by exe on startup +{ + version_string = name; + filterproc = SetUnhandledExceptionFilter(exceptfilter); +} + +static void callstack_add(const char * param) +{ + enum { MAX = tabsize(g_thread_call_stack) - 1} ; + unsigned len = strlen(param); + if (g_thread_call_stack_length + len > MAX) len = MAX - g_thread_call_stack_length; + if (len>0) + { + memcpy(g_thread_call_stack+g_thread_call_stack_length,param,len); + g_thread_call_stack_length += len; + g_thread_call_stack[g_thread_call_stack_length]=0; + } +} + +uCallStackTracker::uCallStackTracker(const char * name) +{ + param = g_thread_call_stack_length; + if (g_thread_call_stack_length>0) callstack_add("=>"); + callstack_add(name); +} + +uCallStackTracker::~uCallStackTracker() +{ + g_thread_call_stack_length = param; + g_thread_call_stack[param]=0; + +} + +extern "C" {UTF8API_EXPORT const char * uGetCallStackPath() {return g_thread_call_stack;} } \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/stdafx.cpp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/stdafx.cpp new file mode 100644 index 000000000..65ef0eea8 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/stdafx.cpp @@ -0,0 +1 @@ +#include "utf8api.h" \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/systray.cpp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/systray.cpp new file mode 100644 index 000000000..d21fa7065 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/systray.cpp @@ -0,0 +1,212 @@ +#include "utf8api.h" + +#include + +#ifdef UNICODE + +//mega-fucko: i dont have latest definitions in my platform sdk that came with msvc6 + +#define NIF_MESSAGE 0x00000001 +#define NIF_ICON 0x00000002 +#define NIF_TIP 0x00000004 +#define NIF_STATE 0x00000008 +#define NIF_INFO 0x00000010 +#define NIF_GUID 0x00000020 + +#define NIIF_INFO 0x00000001 +#define NIIF_WARNING 0x00000002 +#define NIIF_ERROR 0x00000003 +#define NIIF_ICON_MASK 0x0000000F +#define NIIF_NOSOUND 0x00000010 + +#pragma pack(push,4) + +typedef struct { + DWORD cbSize; + HWND hWnd; + UINT uID; + UINT uFlags; + UINT uCallbackMessage; + HICON hIcon; + WCHAR szTip[128]; + DWORD dwState; + DWORD dwStateMask; + WCHAR szInfo[256]; + union { + UINT uTimeout; + UINT uVersion; + } DUMMYUNIONNAME; + WCHAR szInfoTitle[64]; + DWORD dwInfoFlags; +} NOTIFYICONDATA_NEW; + + +#pragma pack(pop) + +static bool is_win2k_or_newer() +{ + OSVERSIONINFO ov; + ov.dwOSVersionInfoSize = sizeof(ov); + GetVersionEx(&ov); + switch(ov.dwPlatformId) + { + default: + case VER_PLATFORM_WIN32_WINDOWS: + case VER_PLATFORM_WIN32s: + return false; + case VER_PLATFORM_WIN32_NT: + return ov.dwMajorVersion>4; + } +} + + +#endif + +UTF8API_EXPORT void uFixAmpersandChars(const char * src,string_base & out) +{ + out.reset(); + while(*src) + { + if (*src=='&') + { + out.add_string("&&&"); + src++; + while(*src=='&') + { + out.add_string("&&"); + src++; + } + } + else out.add_byte(*(src++)); + } +} + +UTF8API_EXPORT void uFixAmpersandChars_v2(const char * src,string_base & out) +{ + out.reset(); + while(*src) + { + if (*src=='&') + { + out.add_string("&&"); + src++; + } + else out.add_byte(*(src++)); + } +} + +static BOOL do_action(DWORD action,NOTIFYICONDATA * data) +{ + if (Shell_NotifyIcon(action,data)) return TRUE; + if (action==NIM_MODIFY) + { + if (Shell_NotifyIcon(NIM_ADD,data)) return TRUE; + } + return FALSE; +} + +extern "C" +{ + + UTF8API_EXPORT BOOL uShellNotifyIcon(DWORD action,HWND wnd,UINT id,UINT callbackmsg,HICON icon,const char * tip) + { + NOTIFYICONDATA nid; + NOTIFYICONDATA * p_nid = &nid; +#ifdef UNICODE + NOTIFYICONDATA_NEW nid_new; + if (is_win2k_or_newer()) + { + memset(&nid_new,0,sizeof(nid_new)); + nid_new.cbSize = sizeof(nid_new); + nid_new.hWnd = wnd; + nid_new.uID = id; + nid_new.uFlags = 0; + if (callbackmsg) + { + nid_new.uFlags |= NIF_MESSAGE; + nid_new.uCallbackMessage = callbackmsg; + } + if (icon) + { + nid_new.uFlags |= NIF_ICON; + nid_new.hIcon = icon; + } + if (tip) + { + nid_new.uFlags |= NIF_TIP; + _tcsncpy(nid_new.szTip,string_os_from_utf8(tip),tabsize(nid_new.szTip)-1); + } + + p_nid = reinterpret_cast(&nid_new); + } + else +#endif + { + memset(&nid,0,sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = wnd; + nid.uID = id; + nid.uFlags = 0; + if (callbackmsg) + { + nid.uFlags |= NIF_MESSAGE; + nid.uCallbackMessage = callbackmsg; + } + if (icon) + { + nid.uFlags |= NIF_ICON; + nid.hIcon = icon; + } + if (tip) + { + nid.uFlags |= NIF_TIP; + _tcsncpy(nid.szTip,string_os_from_utf8(tip),tabsize(nid.szTip)-1); + } + } + + return do_action(action,p_nid); + } + + UTF8API_EXPORT BOOL uShellNotifyIconEx(DWORD action,HWND wnd,UINT id,UINT callbackmsg,HICON icon,const char * tip,const char * balloon_title,const char * balloon_msg) + { + //if (!balloon_title && !balloon_msg) return uShellNotifyIcon(action,wnd,id,callbackmsg,icon,tip); +#ifdef UNICODE + if (!is_win2k_or_newer()) return FALSE; + + NOTIFYICONDATA_NEW nid; + memset(&nid,0,sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = wnd; + nid.uID = id; + if (callbackmsg) + { + nid.uFlags |= NIF_MESSAGE; + nid.uCallbackMessage = callbackmsg; + } + if (icon) + { + nid.uFlags |= NIF_ICON; + nid.hIcon = icon; + } + if (tip) + { + nid.uFlags |= NIF_TIP; + _tcsncpy(nid.szTip,string_os_from_utf8(tip),tabsize(nid.szTip)-1); + } + + nid.dwInfoFlags = NIIF_INFO | NIIF_NOSOUND; + //if (balloon_title || balloon_msg) + { + nid.uFlags |= NIF_INFO; + if (balloon_title) _tcsncpy(nid.szInfoTitle,string_os_from_utf8(balloon_title),tabsize(nid.szInfoTitle)-1); + if (balloon_msg) _tcsncpy(nid.szInfo,string_os_from_utf8(balloon_msg),tabsize(nid.szInfo)-1); + } + return do_action(action,reinterpret_cast(&nid)); + +#else + return FALSE; +#endif + + } + +}//extern "C" \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/text_drawing.cpp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/text_drawing.cpp new file mode 100644 index 000000000..da24d687f --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/text_drawing.cpp @@ -0,0 +1,233 @@ +#include "utf8api.h" + +static bool is_rect_null(const RECT * r) +{ + return r->right <= r->left || r->bottom <= r->top; +} + +UTF8API_EXPORT UINT uGetTextHeight(HDC dc) +{ + TEXTMETRIC tm; + POINT poo; + GetTextMetrics(dc,&tm); + poo.x = 0; + poo.y = tm.tmHeight; + LPtoDP(dc,&poo,1); + return poo.y>1 ? poo.y : 1; +} + +static int get_text_width(HDC dc,const TCHAR * src,int len) +{ + if (len<=0) return 0; + else + { + SIZE s; + GetTextExtentPoint32(dc,src,len,&s); + return s.cx; + } +} + +//GetTextExtentPoint32 wrapper, removes color marks +int get_text_width_color(HDC dc,const TCHAR * src,int len) +{ + int ptr = 0; + int start = 0; + int rv = 0; + if (len<0) len = _tcslen(src); + while(ptrright<=pos_x || clip->bottom<=pos_y) return TRUE; + } + SetTextAlign(dc,TA_LEFT); + SetBkMode(dc,TRANSPARENT); + SetTextColor(dc,selected ? 0xFFFFFF - default_color : default_color); + + int height = uGetTextHeight(dc); + + int title_ptr = 0; + int textout_start = 0; + int position = pos_x;//item.left+BORDER; + + for(;;) + { + if (title_ptr>=len || src[title_ptr]==3) + { + if (title_ptr>textout_start) + { + int width = get_text_width(dc,src+textout_start,title_ptr-textout_start); + ExtTextOut(dc,position,pos_y,clip ? ETO_CLIPPED : 0,clip,src+textout_start,title_ptr-textout_start,0); + position += width; + textout_start = title_ptr; + } + if (title_ptr>=len) break; + } + if (src[title_ptr]==3) + { + DWORD new_color; + DWORD new_inverted; + bool have_inverted = false; + + if (src[title_ptr+1]==3) {new_color=default_color;title_ptr+=2;} + else + { + title_ptr++; + new_color = _tcstoul(src+title_ptr,0,16); + while(title_ptrtop + (item->bottom-item->top - uGetTextHeight(dc)) / 2; + + int n_tabs = 0; + int total_width = 0; + { + int start = 0; + int n; + for(n=0;nright - item->left; + if (!columns) tab_total -= total_width; + int ptr = display_len; + int tab_ptr = 0; + int written = 0; + int clip_x = item->right; + do + { + int ptr_end = ptr; + while(ptr>0 && display[ptr-1]!='\t') ptr--; + const TCHAR * t_string = display + ptr; + int t_length = ptr_end - ptr; + if (t_length>0) + { + int t_width = get_text_width_color(dc,t_string,t_length) + border*2; + + int pos_x; + int pos_x_right; + + if (!columns) + { + pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) - written; + } + else + { + if (tab_ptr==0) pos_x_right = item->right; + else pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) + t_width; + } + + if (ptr==0) + { + pos_x = 0; + } + else + { + pos_x = pos_x_right - t_width ; + if (pos_x<0) pos_x = 0; + } + + RECT t_clip = clip; + + if (t_clip.right > clip_x) t_clip.right = clip_x; + + text_out_colors(dc,t_string,t_length,pos_x+border,pos_y,&t_clip,selected,default_color); + + if (clip_x>pos_x) clip_x = pos_x; + + written += t_width; + } + + if (ptr>0) + { + ptr--;//tab char + tab_ptr++; + } + } + while(ptr>0); + + return TRUE; +} + +extern "C" { + +UTF8API_EXPORT BOOL uTextOutColors(HDC dc,const char * text,UINT len,int x,int y,const RECT * clip,BOOL is_selected,DWORD default_color) +{ + unsigned temp_len = estimate_utf8_to_os(text,len); + mem_block_t temp_block; + TCHAR * temp = (temp_len * sizeof(TCHAR) <= PFC_ALLOCA_LIMIT) ? (TCHAR*)alloca(temp_len * sizeof(TCHAR)) : temp_block.set_size(temp_len); + assert(temp); + convert_utf8_to_os(text,temp,len); + + return text_out_colors(dc,temp,_tcslen(temp),x,y,clip,!!is_selected,default_color); +} + +UTF8API_EXPORT BOOL uTextOutColorsTabbed(HDC dc,const char * text,UINT len,const RECT * item,int border,const RECT * clip,BOOL selected,DWORD default_color,BOOL use_columns) +{ + unsigned temp_len = estimate_utf8_to_os(text,len); + mem_block_t temp_block; + TCHAR * temp = (temp_len * sizeof(TCHAR) <= PFC_ALLOCA_LIMIT) ? (TCHAR*)alloca(temp_len * sizeof(TCHAR)) : temp_block.set_size(temp_len); + assert(temp); + convert_utf8_to_os(text,temp,len); + + return text_out_colors_tab(dc,temp,_tcslen(temp),item,border,clip,!!selected,default_color,!!use_columns); +} + +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8.cpp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8.cpp new file mode 100644 index 000000000..b9a34f003 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8.cpp @@ -0,0 +1,280 @@ +#include "utf8api.h" +#include + +extern "C" { + +static unsigned q_tolower(unsigned c) +{ + if (c>='A' && c<='Z') c += 'a' - 'A'; + return c; +} + + +#ifdef WIN32 +static UINT char_convert_win9x(UINT param,bool b_upper) +{ + assert(param && param<0x10000); + char temp[16]; + WCHAR temp_w[16]; + temp_w[0] = (WCHAR)param; + temp_w[1] = 0; + if (WideCharToMultiByte(CP_ACP,0,temp_w,-1,temp,16,0,0)==0) return param; + temp[15] = 0; + if (b_upper) CharUpperA(temp); else CharLowerA(temp); + if (MultiByteToWideChar(CP_ACP,0,temp,-1,temp_w,16)==0) return param; + if (temp_w[0]==0 || temp_w[1]!=0) return param; + return temp_w[0]; +} + +#endif + +UTF8API_EXPORT UINT uCharLower(UINT param) +{ + if (param<128) + { + if (param>='A' && param<='Z') param += 'a' - 'A'; + return param; + } +#ifdef WIN32 + else if (param<0x10000) + { + unsigned ret; +#ifdef UNICODE + ret = (unsigned)CharLowerW((WCHAR*)param); +#else + ret = char_convert_win9x(param,false); +#endif + return ret; + } + else return param; +#else + else + { + setlocale(LC_CTYPE,""); + return towlower(param); + } +#endif +} + +UTF8API_EXPORT UINT uCharUpper(UINT param) +{ + if (param<128) + { + if (param>='a' && param<='z') param += 'A' - 'a'; + return param; + } +#ifdef WIN32 + else if (param<0x10000) + { + unsigned ret; +#ifdef UNICODE + ret = (unsigned)CharUpperW((WCHAR*)param); +#else + ret = char_convert_win9x(param,true); +#endif + return ret; + } + else return param; +#else + else + { + setlocale(LC_CTYPE,""); + return towupper(param); + } +#endif +} + +static inline int compare_wchar(unsigned c1,unsigned c2) +{ + if (c1==c2) return 0; + c1 = char_lower(c1); + c2 = char_lower(c2); + if (c1c2) return 1; + else return 0; +} + + +UTF8API_EXPORT int stricmp_utf8(const char * p1,const char * p2) +{ + for(;;) + { + if (*p1==0 && *p2==0) return 0; + else if (*p1>0 && *p2>0)//signed char + { + unsigned c1 = q_tolower(*p1), c2 = q_tolower(*p2); + if (c1c2) return 1; + else + { + p1++; + p2++; + } + } + else + { + unsigned int w1,w2,d1,d2; + d1 = utf8_decode_char(p1,&w1); + d2 = utf8_decode_char(p2,&w2); + if (w1==0 && w2==0) return 0; + int rv = compare_wchar(w1,w2); + if (rv) return rv; + p1 += d1; + p2 += d2; + } + } +} + +UTF8API_EXPORT int stricmp_utf8_stringtoblock(const char * p1,const char * p2,unsigned p2_bytes) +{ + return stricmp_utf8_ex(p1,-1,p2,p2_bytes); +} + +UTF8API_EXPORT int stricmp_utf8_partial(const char * p1,const char * p2,unsigned num) +{ + for(;num;) + { + unsigned int w1,w2,d1,d2; + d1 = utf8_decode_char(p1,&w1); + d2 = utf8_decode_char(p2,&w2); + if (w2==0 || d2==0) return 0; + int rv = compare_wchar(w1,w2); + if (rv) return rv; + p1 += d1; + p2 += d2; + num--; + } + return 0; +} + +UTF8API_EXPORT int stricmp_utf8_max(const char * p1,const char * p2,unsigned p1_bytes) +{ + return stricmp_utf8_ex(p1,p1_bytes,p2,-1); +} + +namespace { + typedef bool (*t_replace_test)(const char * src,const char * test,unsigned len); + + static bool replace_test_i(const char * src,const char * test,unsigned len) + { + return stricmp_utf8_max(src,test,len)==0; + } + + static bool replace_test(const char * src,const char * test,unsigned len) + { + unsigned ptr; + bool rv = true; + for(ptr=0;ptr0) + { + unsigned ptr = 0; + while(ptr+len1<=len) + { + if (testfunc(src+ptr,s1,len1)) + { + count++; + out.add_string(s2,len2); + ptr += len1; + } + else out.add_byte(src[ptr++]); + } + if (ptr0); + assert(c2>0); + char s1[8],s2[8]; + unsigned len1,len2; + len1 = utf8_encode_char(c1,s1); + len2 = utf8_encode_char(c2,s2); + return uReplaceString(out,src,src_len,s1,len1,s2,len2,casesens); +} + + +UTF8API_EXPORT void uAddStringLower(string_base & out,const char * src,unsigned len) +{ + while(*src && len) + { + unsigned int c,d; + d = utf8_decode_char(src,&c); + if (d==0 || d>len) break; + out.add_char(char_lower(c)); + src+=d; + len-=d; + } +} + +UTF8API_EXPORT void uAddStringUpper(string_base & out,const char * src,unsigned len) +{ + while(*src && len) + { + unsigned int c,d; + d = utf8_decode_char(src,&c); + if (d==0 || d>len) break; + out.add_char(char_upper(c)); + src+=d; + len-=d; + } +} + +UTF8API_EXPORT int stricmp_utf8_ex(const char * p1,unsigned p1_bytes,const char * p2,unsigned p2_bytes) +{ + p1_bytes = strlen_max(p1,p1_bytes); + p2_bytes = strlen_max(p2,p2_bytes); + for(;;) + { + if (p1_bytes == 0 && p2_bytes == 0) return 0; + else if (p1_bytes == 0) return 1; + else if (p2_bytes == 0) return -1; + else if (*p1>0 && *p2>0)//signed char + { + unsigned c1 = q_tolower(*p1), c2 = q_tolower(*p2); + if (c1c2) return 1; + else + { + p1++; + p2++; + p1_bytes--; + p2_bytes--; + } + } + else + { + unsigned w1,w2,d1,d2; + d1 = utf8_decode_char(p1,&w1,p1_bytes); + d2 = utf8_decode_char(p2,&w2,p2_bytes); + if (d1==0) return -1; + if (d2==0) return 1; + int rv = compare_wchar(w1,w2); + if (rv) return rv; + p1 += d1; + p2 += d2; + p1_bytes -= d1; + p2_bytes -= d2; + } + } +} + +} diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.cpp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.cpp new file mode 100644 index 000000000..462970675 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.cpp @@ -0,0 +1,1471 @@ +#include "utf8api.h" + + +#include +#include + + + +UTF8API_EXPORT UINT UTF8API_GetVersion() +{ + return UTF8API_VERSION; +} + + +class param_os_from_utf8 : public string_os_from_utf8 +{ + bool is_null; + WORD low_word; +public: + param_os_from_utf8(const char * p) : + is_null(p==0), + low_word( HIWORD((DWORD)p)==0 ? LOWORD((DWORD)p) : 0), + string_os_from_utf8( p && HIWORD((DWORD)p)!=0 ?p:"") + {} + inline operator const TCHAR *() + { + return get_ptr(); + } + const TCHAR * get_ptr() + { + return low_word ? (const TCHAR*)(DWORD)low_word : is_null ? 0 : string_os_from_utf8::get_ptr(); + } + +}; + + +static void strncpy_addnull(char * dest,const char * src,int max) +{ + int n; + for(n=0;nFree(li); + rv = 1; + } + + pMalloc->Release(); + return rv; +} + +extern "C" { + +UTF8API_EXPORT BOOL IsUnicode() +{ +#ifdef UNICODE + return TRUE; +#else + return FALSE; +#endif +} + +UTF8API_EXPORT LRESULT uSendMessage(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + return SendMessage(wnd,msg,wp,lp); +} + +UTF8API_EXPORT LRESULT uSendMessageText(HWND wnd,UINT msg,WPARAM wp,const char * text) +{//this is called somewhat often (playlist search listbox...), so lets avoid mallocing + if (text==0) return SendMessage(wnd,msg,wp,0); + else + { + unsigned temp_len = estimate_utf8_to_os(text); + mem_block_t temp_block; + TCHAR * temp = (temp_len * sizeof(TCHAR) <= PFC_ALLOCA_LIMIT) ? (TCHAR*)alloca(temp_len * sizeof(TCHAR)) : temp_block.set_size(temp_len); + assert(temp); + convert_utf8_to_os(text,temp); + + return SendMessage(wnd,msg,wp,(long)(const TCHAR*)temp); + } + //return SendMessage(wnd,msg,wp,(long)(const TCHAR*)param_os_from_utf8(text)); +} + +UTF8API_EXPORT LRESULT uSendDlgItemMessage(HWND wnd,UINT id,UINT msg,WPARAM wp,LPARAM lp) +{ + return SendDlgItemMessage(wnd,id,msg,wp,lp); +} + +UTF8API_EXPORT LRESULT uSendDlgItemMessageText(HWND wnd,UINT id,UINT msg,WPARAM wp,const char * text) +{ + return uSendMessageText(uGetDlgItem(wnd,id),msg,wp,text);//SendDlgItemMessage(wnd,id,msg,wp,(long)(const TCHAR*)string_os_from_utf8(text)); +} + +UTF8API_EXPORT BOOL uPostMessage(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + return PostMessage(wnd,msg,wp,lp); +} + +UTF8API_EXPORT BOOL uPostThreadMessage(DWORD id,UINT msg,WPARAM wp,LPARAM lp) +{ + return PostThreadMessage(id,msg,wp,lp); +} + +UTF8API_EXPORT BOOL uGetWindowText(HWND wnd,string_base & out) +{ + int len = GetWindowTextLength(wnd); + if (len>0) + { + len++; + mem_block_t temp(len); + temp[0]=0; + if (GetWindowText(wnd,temp,len)>0) + { + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; + } + } + return FALSE; +} + +UTF8API_EXPORT BOOL uSetWindowText(HWND wnd,const char * text) +{ + unsigned temp_len = estimate_utf8_to_os(text); + mem_block_t temp_block; + TCHAR * temp = (temp_len * sizeof(TCHAR) <= PFC_ALLOCA_LIMIT) ? (TCHAR*)alloca(temp_len * sizeof(TCHAR)) : temp_block.set_size(temp_len); + assert(temp); + + convert_utf8_to_os(text,temp); + return SetWindowText(wnd,temp); +} + + +UTF8API_EXPORT BOOL uGetDlgItemText(HWND wnd,UINT id,string_base & out) +{ + return uGetWindowText(GetDlgItem(wnd,id),out); +} + +UTF8API_EXPORT BOOL uSetDlgItemText(HWND wnd,UINT id,const char * text) +{ + unsigned temp_len = estimate_utf8_to_os(text); + mem_block_t temp_block; + TCHAR * temp = (temp_len * sizeof(TCHAR) <= PFC_ALLOCA_LIMIT) ? (TCHAR*)alloca(temp_len * sizeof(TCHAR)) : temp_block.set_size(temp_len); + assert(temp); + + convert_utf8_to_os(text,temp); + return SetDlgItemText(wnd,id,temp); +} + +UTF8API_EXPORT HWND uCreateDialog(HINSTANCE hIns,UINT id,HWND parent,DLGPROC proc,long param) +{ + return CreateDialogParam(hIns,MAKEINTRESOURCE(id),parent,proc,param); +} + +UTF8API_EXPORT int uDialogBox(HINSTANCE hIns,UINT id,HWND parent,DLGPROC proc,long param) +{ + return DialogBoxParam(hIns,MAKEINTRESOURCE(id),parent,proc,param); +} + +UTF8API_EXPORT BOOL uBrowseForFolder(HWND parent,const char * title,string_base & out) +{ + TCHAR temp[MAX_PATH]; + tcsncpy_addnull(temp,string_os_from_utf8(out),tabsize(temp)); + BOOL rv = browse_for_dir(parent,string_os_from_utf8(title),temp); + if (rv) + { + temp[tabsize(temp)-1]=0; + out.set_string(string_utf8_from_os(temp)); + } + return rv; +} + +UTF8API_EXPORT long uGetWindowLong(HWND wnd,int idx) +{ + return GetWindowLong(wnd,idx); +} + +UTF8API_EXPORT long uSetWindowLong(HWND wnd,int idx,long val) +{ + return SetWindowLong(wnd,idx,val); +} + +UTF8API_EXPORT int uMessageBox(HWND wnd,const char * text,const char * caption,UINT type) +{ + return MessageBox(wnd,param_os_from_utf8(text),param_os_from_utf8(caption),type); +} + +UTF8API_EXPORT void uOutputDebugString(const char * msg) {OutputDebugString(string_os_from_utf8(msg));} + +static void font_os_from_utf8(LOGFONT * dst,const uLOGFONT * src) +{ + memcpy(dst,src,sizeof(*src)-sizeof(src->lfFaceName)); + tcsncpy_addnull(dst->lfFaceName,string_os_from_utf8(src->lfFaceName),tabsize(dst->lfFaceName)); +} + +static void font_utf8_from_os(uLOGFONT * dst,const LOGFONT * src) +{ + memcpy(dst,src,sizeof(*src)-sizeof(src->lfFaceName)); + strncpy_addnull(dst->lfFaceName,string_utf8_from_os(src->lfFaceName),tabsize(dst->lfFaceName)); +} + +UTF8API_EXPORT HFONT uCreateFontIndirect(const uLOGFONT * p_font) +{ + LOGFONT font_os; + font_os_from_utf8(&font_os,p_font); + return CreateFontIndirect(&font_os); +} + +UTF8API_EXPORT void uGetDefaultFont(uLOGFONT * p_font) +{ + LOGFONT font_os; + GetObject(GetStockObject(DEFAULT_GUI_FONT),sizeof(font_os),&font_os); + font_utf8_from_os(p_font,&font_os); +} + +UTF8API_EXPORT BOOL uChooseFont(uLOGFONT * p_font,HWND parent) +{ + LOGFONT font_os; + font_os_from_utf8(&font_os,p_font); + + CHOOSEFONT cf; + memset(&cf,0,sizeof(cf)); + cf.lStructSize = sizeof(cf); + cf.hwndOwner=parent; + cf.lpLogFont=&font_os; + cf.Flags=CF_SCREENFONTS|CF_FORCEFONTEXIST|CF_INITTOLOGFONTSTRUCT; + cf.nFontType=SCREEN_FONTTYPE; + BOOL rv = ChooseFont(&cf); + if (rv) font_utf8_from_os(p_font,&font_os); + return rv; +} + +UTF8API_EXPORT LRESULT uCallWindowProc(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) +{ + return CallWindowProc(lpPrevWndFunc,hWnd,Msg,wParam,lParam); +} + +UTF8API_EXPORT BOOL uAppendMenu(HMENU menu,UINT flags,UINT id,const char * content) +{ + return AppendMenu(menu,flags,id,param_os_from_utf8(content)); +} + +UTF8API_EXPORT BOOL uInsertMenu(HMENU menu,UINT position,UINT flags,UINT id,const char * content) +{ + return InsertMenu(menu,position,flags,id,param_os_from_utf8(content)); +} + +UTF8API_EXPORT int uStringCompare(const char * elem1, const char * elem2) +{ +#ifdef UNICODE + WCHAR temp1[4],temp2[4]; + for(;;) + { + UINT c1,c2,l1,l2; + l1 = utf8_decode_char(elem1,&c1); + l2 = utf8_decode_char(elem2,&c2); + if (l1==0 && l2==0) return 0; + if (c1!=c2) + { + temp1[utf16_encode_char(c1,temp1)]=0; + temp2[utf16_encode_char(c2,temp2)]=0; + int test = lstrcmpiW(temp1,temp2); + if (test) return test; + } + elem1 += l1; + elem2 += l2; + } +#else + WCHAR temp1[4],temp2[4]; + char ctemp1[20],ctemp2[20]; + for(;;) + { + UINT c1,c2,l1,l2; + l1 = utf8_decode_char(elem1,&c1); + l2 = utf8_decode_char(elem2,&c2); + if (l1==0 && l2==0) return 0; + if (c1!=c2) + { + temp1[utf16_encode_char(c1,temp1)]=0; + temp2[utf16_encode_char(c2,temp2)]=0; + WideCharToMultiByte(CP_ACP,0,temp1,-1,ctemp1,tabsize(ctemp1),0,0); + WideCharToMultiByte(CP_ACP,0,temp2,-1,ctemp2,tabsize(ctemp2),0,0); + int test = lstrcmpiA(ctemp1,ctemp2); + if (test) return test; + } + elem1 += l1; + elem2 += l2; + } +#endif +} + +UTF8API_EXPORT HINSTANCE uLoadLibrary(const char * name) +{ + return LoadLibrary(param_os_from_utf8(name)); +} + +UTF8API_EXPORT HANDLE uCreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState, const char * lpName) +{ + return CreateEvent(lpEventAttributes,bManualReset,bInitialState, param_os_from_utf8(lpName)); +} + + +UTF8API_EXPORT DWORD uGetModuleFileName(HMODULE hMod,string_base & out) +{ + TCHAR temp[MAX_PATH]; + temp[0] = 0; + DWORD ret = GetModuleFileName(hMod,temp,tabsize(temp)); + if (ret) + { + temp[tabsize(temp)-1] = 0; + out.set_string_os(temp); + } + return ret; +} + +UTF8API_EXPORT BOOL uSetClipboardString(const char * ptr) +{ + if (OpenClipboard(0)) + { + EmptyClipboard(); + + string_os_from_utf8 temp(ptr); + + HANDLE h_global = GlobalAlloc(GMEM_DDESHARE, (_tcslen(temp) + 1) * sizeof(TCHAR)); + if (h_global!=0) + { + TCHAR * ptr = (TCHAR*)GlobalLock(h_global); + _tcscpy(ptr,temp); + GlobalUnlock(h_global); + SetClipboardData( +#ifdef UNICODE + CF_UNICODETEXT +#else + CF_TEXT +#endif + ,h_global); + } + CloseClipboard(); + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT LRESULT uDefWindowProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + return DefWindowProc(wnd,msg,wp,lp); +} + +UTF8API_EXPORT BOOL uIsDialogMessage(HWND dlg,LPMSG msg) +{ + return IsDialogMessage(dlg,msg); +} + +UTF8API_EXPORT BOOL uGetMessage(LPMSG msg,HWND wnd,UINT min,UINT max) +{ + return GetMessage(msg,wnd,min,max); +} + +UTF8API_EXPORT BOOL uGetClassName(HWND wnd,string_base & out) +{ + TCHAR temp[512]; + temp[0]=0; + if (GetClassName(wnd,temp,tabsize(temp))>0) + { + temp[tabsize(temp)-1]=0; + out.set_string_os(temp); + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT UINT uCharLength(const char * src) {return utf8_char_len(src);} + +UTF8API_EXPORT BOOL uDragQueryFile(HDROP hDrop,UINT idx,string_base & out) +{ + UINT len = DragQueryFile(hDrop,idx,0,0); + if (len>0 && len!=(UINT)(-1)) + { + len++; + mem_block_t temp(len); + if (DragQueryFile(hDrop,idx,temp,len)>0) + { + out.set_string_os(temp); + return TRUE; + } + } + return FALSE; +} + +UTF8API_EXPORT UINT uDragQueryFileCount(HDROP hDrop) +{ + return DragQueryFile(hDrop,-1,0,0); +} + + +UTF8API_EXPORT LRESULT uSendMessageTimeout(HWND wnd,UINT msg,WPARAM wp,LPARAM lp,UINT flags,UINT timeout,LPDWORD result) +{ + return SendMessageTimeout(wnd,msg,wp,lp,flags,timeout,result); +} + +UTF8API_EXPORT BOOL uGetTextExtentPoint32(HDC dc,const char * text,UINT cb,LPSIZE size) +{ + string_os_from_utf8 temp(text,cb); + return GetTextExtentPoint32(dc,temp,_tcslen(temp),size); +} + +UTF8API_EXPORT BOOL uExtTextOut(HDC dc,int x,int y,UINT flags,const RECT * rect,const char * text,UINT cb,const int * lpdx) +{ + string_os_from_utf8 temp(text,cb); + return ExtTextOut(dc,x,y,flags,rect,temp,_tcslen(temp),lpdx); +} + +UTF8API_EXPORT BOOL uChooseColor(DWORD * p_color,HWND parent,DWORD * p_custom_colors) +{ + CHOOSECOLOR cc; + memset(&cc,0,sizeof(cc)); + cc.lStructSize = sizeof(cc); + cc.hwndOwner = parent; + cc.rgbResult = *p_color; + cc.lpCustColors = p_custom_colors; + cc.Flags = CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT; + BOOL rv = ChooseColor(&cc); + if (rv) + { + *p_color = cc.rgbResult; + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT BOOL uPeekMessage(LPMSG msg,HWND wnd,UINT min,UINT max,UINT flag) +{ + return PeekMessage(msg,wnd,min,max,flag); +} + +UTF8API_EXPORT LONG uDispatchMessage(const MSG * msg) +{ + return DispatchMessage(msg); +} + +UTF8API_EXPORT HCURSOR uLoadCursor(HINSTANCE hIns,const char * name) +{ + return LoadCursor(hIns,param_os_from_utf8(name)); +} + +UTF8API_EXPORT HICON uLoadIcon(HINSTANCE hIns,const char * name) +{ + return LoadIcon(hIns,param_os_from_utf8(name)); +} + +UTF8API_EXPORT HMENU uLoadMenu(HINSTANCE hIns,const char * name) +{ + return LoadMenu(hIns,param_os_from_utf8(name)); +} + + + +UTF8API_EXPORT BOOL uGetEnvironmentVariable(const char * name,string_base & out) +{ + string_os_from_utf8 name_t(name); + DWORD size = GetEnvironmentVariable(name_t,0,0); + if (size>0) + { + size++; + mem_block_t temp(size); + temp[0]=0; + if (GetEnvironmentVariable(name_t,temp,size)>0) + { + temp[size-1]=0; + out.set_string_os(temp); + return TRUE; + } + } + return FALSE; +} + +UTF8API_EXPORT HMODULE uGetModuleHandle(const char * name) +{ + return GetModuleHandle(param_os_from_utf8(name)); +} + +UTF8API_EXPORT UINT uRegisterWindowMessage(const char * name) +{ + return RegisterWindowMessage(string_os_from_utf8(name)); +} + +UTF8API_EXPORT BOOL uMoveFile(const char * src,const char * dst) +{ + return MoveFile(string_os_from_utf8(src),string_os_from_utf8(dst)); +} + +UTF8API_EXPORT BOOL uDeleteFile(const char * fn) +{ + return DeleteFile(string_os_from_utf8(fn)); +} + +UTF8API_EXPORT DWORD uGetFileAttributes(const char * fn) +{ + return GetFileAttributes(string_os_from_utf8(fn)); +} + +UTF8API_EXPORT BOOL uRemoveDirectory(const char * fn) +{ + return RemoveDirectory(string_os_from_utf8(fn)); +} + +UTF8API_EXPORT HANDLE uCreateFile(const char * fn,DWORD access,DWORD share,LPSECURITY_ATTRIBUTES blah,DWORD creat,DWORD flags,HANDLE tmpl) +{ + return CreateFile(string_os_from_utf8(fn),access,share,blah,creat,flags,tmpl); +} + +UTF8API_EXPORT BOOL uCreateDirectory(const char * fn,LPSECURITY_ATTRIBUTES blah) +{ + return CreateDirectory(string_os_from_utf8(fn),blah); +} + +UTF8API_EXPORT HANDLE uCreateMutex(LPSECURITY_ATTRIBUTES blah,BOOL bInitialOwner,const char * name) +{ + return name ? CreateMutex(blah,bInitialOwner,string_os_from_utf8(name)) : CreateMutex(blah,bInitialOwner,0); +} + +UTF8API_EXPORT BOOL uGetFullPathName(const char * name,string_base & out) +{ + string_os_from_utf8 name_os(name); + unsigned len = GetFullPathName(name_os,0,0,0); + if (len==0) return FALSE; + mem_block_t temp; + if (!temp.set_size(len+1)) return FALSE; + TCHAR * blah; + if (GetFullPathName(name_os,len+1,temp,&blah)==0) return FALSE; + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; +} + +UTF8API_EXPORT BOOL uGetLongPathName(const char * name,string_base & out) +{ + static bool inited; + typedef DWORD (_stdcall * PGETLONGPATHNAME)(LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer); + static PGETLONGPATHNAME pGetLongPathName; + if (!inited) + { + pGetLongPathName = (PGETLONGPATHNAME)GetProcAddress(uGetModuleHandle("kernel32.dll"), +#ifdef UNICODE + "GetLongPathNameW" +#else + "GetLongPathNameA" +#endif + ); + inited = true; + } + if (pGetLongPathName) + { + TCHAR temp[4096]; + temp[0]=0; + if (pGetLongPathName(string_os_from_utf8(name),temp,tabsize(temp))) + { + temp[tabsize(temp)-1]=0; + out.set_string_os(temp); + return TRUE; + } + } + return FALSE; +} + +UTF8API_EXPORT void uGetCommandLine(string_base & out) +{ + out.set_string_os(GetCommandLine()); +} + +UTF8API_EXPORT BOOL uGetTempPath(string_base & out) +{ + TCHAR temp[MAX_PATH+1]; + temp[0]=0; + if (GetTempPath(tabsize(temp),temp)) + { + temp[tabsize(temp)-1]=0; + out.set_string_os(temp); + return TRUE; + } + return FALSE; + +} +UTF8API_EXPORT BOOL uGetTempFileName(const char * path_name,const char * prefix,UINT unique,string_base & out) +{ + if (path_name==0 || prefix==0) return FALSE; + TCHAR temp[MAX_PATH+1]; + temp[0]=0; + if (GetTempFileName(string_os_from_utf8(path_name),string_os_from_utf8(prefix),unique,temp)) + { + temp[tabsize(temp)-1]=0; + out.set_string_os(temp); + return TRUE; + } + return FALSE; +} + +class uFindFile_i : public uFindFile +{ + string8 fn; + WIN32_FIND_DATA fd; + HANDLE hFF; +public: + uFindFile_i() {hFF = INVALID_HANDLE_VALUE;} + bool FindFirst(const char * path) + { + hFF = FindFirstFile(string_os_from_utf8(path),&fd); + if (hFF==INVALID_HANDLE_VALUE) return false; + fn.set_string_os(fd.cFileName); + return true; + } + virtual BOOL FindNext() + { + if (hFF==INVALID_HANDLE_VALUE) return FALSE; + BOOL rv = FindNextFile(hFF,&fd); + if (rv) fn.set_string_os(fd.cFileName); + return rv; + } + + virtual const char * GetFileName() + { + return fn; + } + + virtual __int64 GetFileSize() + { + union + { + __int64 val64; + struct + { + DWORD lo,hi; + }; + } ret; + + ret.hi = fd.nFileSizeHigh; + ret.lo = fd.nFileSizeLow; + return ret.val64; + + } + virtual DWORD GetAttributes() + { + return fd.dwFileAttributes; + } + + virtual FILETIME GetCreationTime() + { + return fd.ftCreationTime; + } + virtual FILETIME GetLastAccessTime() + { + return fd.ftLastAccessTime; + } + virtual FILETIME GetLastWriteTime() + { + return fd.ftLastWriteTime; + } + virtual ~uFindFile_i() + { + if (hFF!=INVALID_HANDLE_VALUE) FindClose(hFF); + } +}; + +UTF8API_EXPORT uFindFile * uFindFirstFile(const char * path) +{ + uFindFile_i * ptr = new uFindFile_i; + if (!ptr->FindFirst(path)) + { + delete ptr; + ptr = 0; + } + return ptr; +} + +UTF8API_EXPORT BOOL uGetOpenFileName(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,string_base & p_filename,BOOL b_save) +{ + string_os_from_utf8 ext_mask_t(p_ext_mask); + mem_block_t ext_mask(_tcslen(ext_mask_t)+2); + ext_mask.zeromemory(); + _tcscpy(ext_mask,ext_mask_t); + + { + UINT n; + for(n=0;n0 && buffer[ptr-1]==' ') buffer[--ptr] = 0; + } + + p_filename.set_string_os(buffer); + return TRUE; + } + else return FALSE; +} + +class uGetOpenFileNameMultiResult_i : public uGetOpenFileNameMultiResult +{ + ptr_list_simple items; +public: + void AddItem(const char * param) {items.add_item(strdup(param));} + virtual UINT GetCount() {return items.get_count();} + virtual const char * GetFileName(UINT index) {return index>=0 && index<(UINT)items.get_count() ? items[index] : 0;} + virtual ~uGetOpenFileNameMultiResult_i() {items.free_all();} +}; + +UTF8API_EXPORT uGetOpenFileNameMultiResult * uGetOpenFileNameMulti(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory) +{ + string_os_from_utf8 ext_mask_t(p_ext_mask); + mem_block_t ext_mask(_tcslen(ext_mask_t)+2); + ext_mask.zeromemory(); + _tcscpy(ext_mask,ext_mask_t); + + { + UINT n; + for(n=0;n0 && buffer[ptr-1]==' ') buffer[--ptr] = 0; + } + + result->AddItem(string_utf8_from_os(buffer)); + } + else + { + string8 s; + s.set_string_os(buffer); + int ofs=s.length(); + if (s[ofs-1]!='\\') {s.add_char('\\');ofs++;} + while(*p) + { + s.truncate(ofs); + s.add_string_os(p); + s.skip_trailing_char(' '); + result->AddItem(s); + while(*p) p++; + p++; + } + } + return result; + } + else return 0; +} + +UTF8API_EXPORT HINSTANCE uShellExecute(HWND wnd,const char * oper,const char * file,const char * params,const char * dir,int cmd) +{ + return ShellExecute(wnd,param_os_from_utf8(oper),param_os_from_utf8(file),param_os_from_utf8(params),param_os_from_utf8(dir),cmd); +} + +UTF8API_EXPORT HWND uCreateStatusWindow(LONG style,const char * text,HWND parent,UINT id) +{ + return CreateStatusWindow(style,param_os_from_utf8(text),parent,id); +} + +UTF8API_EXPORT ATOM uRegisterClass(const uWNDCLASS * ptr) +{ + param_os_from_utf8 str_menu(ptr->lpszMenuName),str_class(ptr->lpszClassName); + WNDCLASS cl; + cl.style = ptr->style; + cl.lpfnWndProc = ptr->lpfnWndProc; + cl.cbClsExtra = ptr->cbClsExtra; + cl.cbWndExtra = ptr->cbWndExtra; + cl.hInstance = ptr->hInstance; + cl.hIcon = ptr->hIcon; + cl.hCursor = ptr->hCursor; + cl.hbrBackground = ptr->hbrBackground; + cl.lpszMenuName = str_menu; + cl.lpszClassName = str_class; + + return RegisterClass(&cl); +} + +UTF8API_EXPORT HWND uCreateWindowEx(DWORD dwExStyle,const char * lpClassName,const char * lpWindowName,DWORD dwStyle,int x,int y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam) +{ + return CreateWindowEx(dwExStyle,param_os_from_utf8(lpClassName),param_os_from_utf8(lpWindowName),dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam); +} + +UTF8API_EXPORT HANDLE uLoadImage(HINSTANCE hIns,const char * name,UINT type,int x,int y,UINT flags) +{ + return LoadImage(hIns,param_os_from_utf8(name),type,x,y,flags); +} + +UTF8API_EXPORT BOOL uGetSystemDirectory(string_base & out) +{ + UINT len = GetSystemDirectory(0,0); + if (len==0) len = MAX_PATH; + len++; + mem_block_t temp; + if (!temp.set_size(len)) return FALSE; + if (GetSystemDirectory(temp,len)==0) return FALSE; + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; +} + +UTF8API_EXPORT BOOL uGetWindowsDirectory(string_base & out) +{ + UINT len = GetWindowsDirectory(0,0); + if (len==0) len = MAX_PATH; + len++; + mem_block_t temp; + if (!temp.set_size(len)) return FALSE; + if (GetWindowsDirectory(temp,len)==0) return FALSE; + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; +} + +UTF8API_EXPORT BOOL uSetCurrentDirectory(const char * path) +{ + return SetCurrentDirectory(string_os_from_utf8(path)); +} + +UTF8API_EXPORT BOOL uGetCurrentDirectory(string_base & out) +{ + UINT len = GetCurrentDirectory(0,0); + if (len==0) len = MAX_PATH; + len++; + mem_block_t temp; + if (!temp.set_size(len)) return FALSE; + if (GetCurrentDirectory(len,temp)==0) return FALSE; + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; +} + +UTF8API_EXPORT BOOL uExpandEnvironmentStrings(const char * src,string_base & out) +{ + string_os_from_utf8 src_os(src); + UINT len = ExpandEnvironmentStrings(src_os,0,0); + if (len==0) len = 256; + len++; + mem_block_t temp; + if (!temp.set_size(len)) return FALSE; + if (ExpandEnvironmentStrings(src_os,temp,len)==0) return FALSE; + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; +} + +UTF8API_EXPORT BOOL uGetUserName(string_base & out) +{ + TCHAR temp[UNLEN+1]; + DWORD len = tabsize(temp); + if (GetUserName(temp,&len)) + { + temp[tabsize(temp)-1]=0; + out.set_string_os(temp); + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT BOOL uGetShortPathName(const char * src,string_base & out) +{ + string_os_from_utf8 src_os(src); + UINT len = GetShortPathName(src_os,0,0); + if (len==0) len = MAX_PATH; + len++; + mem_block_t temp(len); + if (GetShortPathName(src_os,temp,len)) + { + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT BOOL uUnregisterClass(const char * name,HINSTANCE ins) +{ + return UnregisterClass(param_os_from_utf8(name),ins); +} + +#ifdef UNICODE +#define DDE_CODEPAGE CP_WINUNICODE +#else +#define DDE_CODEPAGE CP_WINANSI +#endif + + +UTF8API_EXPORT HSZ uDdeCreateStringHandle(DWORD ins,const char * src) +{ + return DdeCreateStringHandle(ins,string_os_from_utf8(src),DDE_CODEPAGE); +} + +UTF8API_EXPORT BOOL uDdeQueryString(DWORD ins,HSZ hsz,string_base & out) +{ + mem_block_t temp; + UINT len = DdeQueryString(ins,hsz,0,0,DDE_CODEPAGE); + if (len==0) len = MAX_PATH; + len++; + if (temp.set_size(len)==0) return FALSE; + if (DdeQueryString(ins,hsz,temp,len,DDE_CODEPAGE)) + { + temp[len-1]=0; + out.set_string_os(temp); + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT UINT uDdeInitialize(LPDWORD pidInst,PFNCALLBACK pfnCallback,DWORD afCmd,DWORD ulRes) +{ + return DdeInitialize(pidInst,pfnCallback,afCmd,ulRes); +} + +UTF8API_EXPORT BOOL uDdeAccessData_Text(HDDEDATA data,string_base & out) +{ + const TCHAR * ptr = (const TCHAR*) DdeAccessData(data,0); + if (ptr) + { + out.set_string_os(ptr); + return TRUE; + } + else return FALSE; +} + +UTF8API_EXPORT HANDLE uSortStringCreate(const char * src) +{ + TCHAR * ret = mem_ops::alloc(estimate_utf8_to_os(src)); + if (ret) + { + convert_utf8_to_os(src,ret); + ret = mem_ops::realloc(ret,_tcslen(ret)+1); + } + return (HANDLE)ret; +} + +UTF8API_EXPORT int uSortStringCompareEx(HANDLE string1,HANDLE string2,DWORD flags) +{ + return CompareString(LOCALE_USER_DEFAULT,flags,reinterpret_cast(string1),-1,reinterpret_cast(string2),-1); +} + +UTF8API_EXPORT int uSortStringCompare(HANDLE string1,HANDLE string2) +{ + return lstrcmpi(reinterpret_cast(string1),reinterpret_cast(string2)); +} + +UTF8API_EXPORT void uSortStringFree(HANDLE string) +{ + mem_ops::free(reinterpret_cast(string)); +} + +static void stringlist_os_from_utf8(const char * src,mem_block_t & out) +{ + unsigned p_out = 0; + if (src) + { + while(*src) + { + unsigned src_len = strlen(src); + out.check_size(p_out + estimate_utf8_to_os(src,src_len)); + p_out += 1 + convert_utf8_to_os(src,out.get_ptr() + p_out,src_len); + src += src_len + 1; + } + } + out.copy(TEXT("\0"),2,p_out); +} + +UTF8API_EXPORT int uSHFileOperation(uSHFILEOPSTRUCT * p_op) +{ + mem_block_t temp1,temp2; + stringlist_os_from_utf8(p_op->pFrom,temp1); + stringlist_os_from_utf8(p_op->pTo,temp2); + + param_os_from_utf8 progress_title(p_op->lpszProgressTitle); + + SHFILEOPSTRUCT op; + op.hwnd = p_op->hwnd; + op.wFunc = p_op->wFunc; + op.pFrom = temp1; + op.pTo = temp2; + op.fFlags = p_op->fFlags; + op.fAnyOperationsAborted = p_op->fAnyOperationsAborted; + op.hNameMappings = p_op->hNameMappings; + op.lpszProgressTitle = progress_title; + + int ret = SHFileOperation(&op); + p_op->fAnyOperationsAborted = op.fAnyOperationsAborted; + return ret; +} + +UTF8API_EXPORT BOOL uCreateProcess( + const char * lpApplicationName, + const char * lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + const char * lpEnvironment, + const char * lpCurrentDirectory, + const uSTARTUPINFO * lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +) +{ + if (lpStartupInfo->cb!=sizeof(uSTARTUPINFO)) return FALSE; + STARTUPINFO si; + param_os_from_utf8 si_lpDesktop(lpStartupInfo->lpDesktop); + param_os_from_utf8 si_lpTitle(lpStartupInfo->lpTitle); + si.cb = sizeof(si); + si.lpReserved = 0; + si.lpDesktop = const_cast(si_lpDesktop.get_ptr()); + si.lpTitle = const_cast(si_lpTitle.get_ptr()); + si.dwX = lpStartupInfo->dwX; + si.dwY = lpStartupInfo->dwY; + si.dwXSize = lpStartupInfo->dwXSize; + si.dwYSize = lpStartupInfo->dwYSize; + si.dwXCountChars = lpStartupInfo->dwXCountChars; + si.dwYCountChars = lpStartupInfo->dwYCountChars; + si.dwFillAttribute = lpStartupInfo->dwFillAttribute; + si.dwFlags = lpStartupInfo->dwFlags; + si.wShowWindow = lpStartupInfo->wShowWindow; + si.cbReserved2 = 0; + si.lpReserved2 = 0; + si.hStdInput = lpStartupInfo->hStdInput; + si.hStdOutput = lpStartupInfo->hStdOutput; + si.hStdError = lpStartupInfo->hStdError; + + mem_block_fastalloc env; + if (lpEnvironment) + { + unsigned env_out = 0; + const char * p_env = lpEnvironment; + do { + env.check_size(env_out + estimate_utf8_to_os(p_env)); + env_out += convert_utf8_to_os(p_env,env+env_out) + 1; + p_env += strlen(p_env) + 1; + } while(*p_env); + env.check_size(env_out+1); + env[env_out]=0; + } + + mem_block_t gay; + gay.set_size(estimate_utf8_to_os(lpCommandLine)+MAX_PATH); + convert_utf8_to_os(lpCommandLine,gay); + + return CreateProcess(param_os_from_utf8(lpApplicationName), + gay, + lpProcessAttributes,lpThreadAttributes, + bInheritHandles, +#ifdef UNICODE + dwCreationFlags|CREATE_UNICODE_ENVIRONMENT, +#else + dwCreationFlags&~CREATE_UNICODE_ENVIRONMENT, +#endif + lpEnvironment ? env.get_ptr() : 0, + param_os_from_utf8(lpCurrentDirectory), + &si, + lpProcessInformation + ); +} + +UTF8API_EXPORT HTREEITEM uTreeView_InsertItem(HWND wnd,const uTVINSERTSTRUCT * param) +{ + mem_block_t temp; + unsigned needed_length = estimate_utf8_to_os(param->item.pszText); + TCHAR * pszText = (needed_length * sizeof(TCHAR) <= PFC_ALLOCA_LIMIT) ? (TCHAR*)alloca(needed_length * sizeof(TCHAR)) : temp.set_size(PFC_ALLOCA_LIMIT); + convert_utf8_to_os(param->item.pszText,pszText); + + + TVINSERTSTRUCT l_param; + memset(&l_param,0,sizeof(l_param)); + l_param.hParent = param->hParent; + l_param.hInsertAfter = param->hInsertAfter; + l_param.item.mask = param->item.mask; + l_param.item.hItem = param->item.hItem; + l_param.item.state = param->item.state; + l_param.item.stateMask = param->item.stateMask; + l_param.item.pszText = pszText; + l_param.item.cchTextMax = 0; + l_param.item.iImage = param->item.iImage; + l_param.item.iSelectedImage = param->item.iImage; + l_param.item.cChildren = param->item.cChildren; + l_param.item.lParam = param->item.lParam; + if (param->item.mask & TVIF_INTEGRAL) + { + l_param.itemex.iIntegral = param->itemex.iIntegral; + } + + return (HTREEITEM) uSendMessage(wnd,TVM_INSERTITEM,0,(LPARAM)&l_param); +} + +UTF8API_EXPORT UINT uGetFontHeight(HFONT font) +{ + UINT ret; + HDC dc = CreateCompatibleDC(0); + SelectObject(dc,font); + ret = uGetTextHeight(dc); + DeleteDC(dc); + return ret; +} + +UTF8API_EXPORT HHOOK uSetWindowsHookEx(int idhook,HOOKPROC fn,HINSTANCE hMod,DWORD threadid) +{ + return SetWindowsHookEx(idhook,fn,hMod,threadid); +} + +UTF8API_EXPORT HIMAGELIST uImageList_LoadImage(HINSTANCE hi, const char * lpbmp, int cx, int cGrow, COLORREF crMask, UINT uType, UINT uFlags) +{ + return ImageList_LoadImage(hi,param_os_from_utf8(lpbmp),cx,cGrow,crMask,uType,uFlags); +} + +UTF8API_EXPORT BOOL uSendNotifyMessage(HWND wnd,UINT msg,WPARAM wp,LPARAM lp) +{ + return SendNotifyMessage(wnd,msg,wp,lp); +} + +UTF8API_EXPORT BOOL uSendMessageCallback(HWND wnd,UINT msg,WPARAM wp,LPARAM lp,SENDASYNCPROC cb,DWORD data) +{ + return SendMessageCallback(wnd,msg,wp,lp,cb,data); +} + +UTF8API_EXPORT unsigned uOSStringEstimateSize(const char * src,unsigned len) +{ + return estimate_utf8_to_os(src,len) * sizeof(TCHAR); +} + +UTF8API_EXPORT unsigned uOSStringConvert(const char * src,void * dst,unsigned len) +{ + return convert_utf8_to_os(src,(TCHAR*)dst,len); +} + +UTF8API_EXPORT int uTabCtrl_InsertItem(HWND wnd,int idx,const uTCITEM * item) +{ + param_os_from_utf8 text((item->mask & TCIF_TEXT) ? item->pszText : 0); + TCITEM l_item; + assert(sizeof(l_item)==sizeof(*item));//meh lazy + memcpy(&l_item,item,sizeof(l_item)); + l_item.pszText = const_cast(text.get_ptr()); + l_item.cchTextMax = 0; + return TabCtrl_InsertItem(wnd,idx,&l_item); +} + +UTF8API_EXPORT int uTabCtrl_SetItem(HWND wnd,int idx,const uTCITEM * item) +{ + param_os_from_utf8 text((item->mask & TCIF_TEXT) ? item->pszText : 0); + TCITEM l_item; + assert(sizeof(l_item)==sizeof(*item));//meh lazy + memcpy(&l_item,item,sizeof(l_item)); + l_item.pszText = const_cast(text.get_ptr()); + l_item.cchTextMax = 0; + return TabCtrl_SetItem(wnd,idx,&l_item); +} + +UTF8API_EXPORT int uGetKeyNameText(LONG lparam,string_base & out) +{ + TCHAR temp[256]; + temp[0]=0; + if (!GetKeyNameText(lparam,temp,tabsize(temp))) return 0; + temp[tabsize(temp)-1]=0; + out.set_string(string_utf8_from_os(temp)); + return 1; +} + +UTF8API_EXPORT HANDLE uCreateFileMapping(HANDLE hFile,LPSECURITY_ATTRIBUTES lpFileMappingAttributes,DWORD flProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,const char * lpName) +{ + return CreateFileMapping(hFile,lpFileMappingAttributes,flProtect,dwMaximumSizeHigh,dwMaximumSizeLow,param_os_from_utf8(lpName)); +} + +UTF8API_EXPORT BOOL uListBox_GetText(HWND listbox,UINT index,string_base & out) +{ + unsigned len = uSendMessage(listbox,LB_GETTEXTLEN,index,0); + if (len==LB_ERR || len>16*1024*1024) return FALSE; + if (len==0) {out.reset();return TRUE;} + + mem_block_t temp(len+1); + if (temp.get_ptr()==0) return FALSE; + temp.zeromemory(); + len = uSendMessage(listbox,LB_GETTEXT,index,(LPARAM)temp.get_ptr()); + if (len==LB_ERR) return false; + out.set_string(string_utf8_from_os(temp)); + return TRUE; +} + +UTF8API_EXPORT void uPrintf(string_base & out,const char * fmt,...) +{ + va_list list; + va_start(list,fmt); + uPrintfV(out,fmt,list); + va_end(list); +} + +UTF8API_EXPORT void uPrintfV(string_base & out,const char * fmt,va_list arglist) +{ + string_printf::g_run(out,fmt,arglist); +} + +UTF8API_EXPORT int uCompareString(DWORD flags,const char * str1,unsigned len1,const char * str2,unsigned len2) +{ + return CompareString(LOCALE_USER_DEFAULT,flags,string_os_from_utf8(str1,len1),-1,string_os_from_utf8(str2,len2),-1); +} + +class uResource_i : public uResource +{ + unsigned size; + const void * ptr; +public: + inline uResource_i(const void * p_ptr,unsigned p_size) : ptr(p_ptr), size(p_size) + { + } + virtual const void * GetPointer() + { + return ptr; + } + virtual unsigned GetSize() + { + return size; + } + virtual ~uResource_i() + { + } +}; + +UTF8API_EXPORT uResource * uLoadResource(HMODULE hMod,const char * name,const char * type,WORD wLang) +{ + HRSRC res = uFindResource(hMod,name,type,wLang); + if (res==0) return 0; + HGLOBAL hglob = LoadResource(hMod,res); + if (hglob) + { + void * ptr = LockResource(hglob); + if (ptr) + { + return new uResource_i(ptr,SizeofResource(hMod,res)); + } + else return 0; + } + else return 0; + +} + +UTF8API_EXPORT HRSRC uFindResource(HMODULE hMod,const char * name,const char * type,WORD wLang) +{ + return wLang ? FindResourceEx(hMod,param_os_from_utf8(name),param_os_from_utf8(type),wLang) : FindResource(hMod,param_os_from_utf8(name),param_os_from_utf8(type)); +} + +UTF8API_EXPORT BOOL uLoadString(HINSTANCE ins,UINT id,string_base & out) +{ + BOOL rv = FALSE; + uResource * res = uLoadResource(ins,uMAKEINTRESOURCE(id),(const char*)(RT_STRING)); + if (res) + { + unsigned size = res->GetSize(); + const WCHAR * ptr = (const WCHAR*)res->GetPointer(); + if (size>=4) + { + unsigned len = *(const WORD*)(ptr+1); + if (len * 2 + 4 <= size) + { + out = string_utf8_from_wide(ptr+2,len); + } + } + + delete res; + rv = TRUE; + } + return rv; +} + +UTF8API_EXPORT BOOL uGetMenuString(HMENU menu,UINT id,string_base & out,UINT flag) +{ + unsigned len = GetMenuString(menu,id,0,0,flag); + if (len==0) + { + out.reset(); + return FALSE; + } + TCHAR * temp = (TCHAR*)malloc((len+1)*sizeof(TCHAR)); + if (temp==0) + { + out.reset(); + return FALSE; + } + if (GetMenuString(menu,id,temp,len+1,flag)==0) + { + free(temp); + out.reset(); + return FALSE; + } + out = string_utf8_from_os(temp); + free(temp); + return TRUE; +} + +UTF8API_EXPORT BOOL uModifyMenu(HMENU menu,UINT id,UINT flags,UINT newitem,const char * data) +{ + return ModifyMenu(menu,id,flags,newitem,param_os_from_utf8(data)); +} + +UTF8API_EXPORT UINT uGetMenuItemType(HMENU menu,UINT position) +{ + MENUITEMINFO info; + memset(&info,0,sizeof(info)); + info.cbSize = sizeof(info); + info.fMask = MIIM_TYPE; + if (!GetMenuItemInfo(menu,position,TRUE,&info)) + return 0; + return info.fType; +} + +static inline bool i_is_path_separator(unsigned c) +{ + return c=='\\' || c=='/' || c=='|' || c==':'; +} + +UTF8API_EXPORT int uSortPathCompare(HANDLE string1,HANDLE string2) +{ + const TCHAR * s1 = reinterpret_cast(string1); + const TCHAR * s2 = reinterpret_cast(string2); + const TCHAR * p1, * p2; + + while (*s1 || *s2) + { + if (*s1 == *s2) + { + s1++; + s2++; + continue; + } + + p1 = s1; while (*p1 && !i_is_path_separator(*p1)) p1++; + p2 = s2; while (*p2 && !i_is_path_separator(*p2)) p2++; + + if ((!*p1 && !*p2) || (*p1 && *p2)) + { + int test = CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH, s1, p1 - s1, s2, p2 - s2); + if (test && test != 2) return test - 2; + if (!*p1) return 0; + } + else + { + if (*p1) return -1; + else return 1; + } + + s1 = p1 + 1; + s2 = p2 + 1; + } + + return 0; +} + +UTF8API_EXPORT UINT uRegisterClipboardFormat(const char * name) +{ + return RegisterClipboardFormat(string_os_from_utf8(name)); +} + +UTF8API_EXPORT BOOL uGetClipboardFormatName(UINT format,string_base & out) +{ + TCHAR temp[1024]; + if (!GetClipboardFormatName(format,temp,tabsize(temp))) return FALSE; + temp[tabsize(temp)-1] = 0; + out.set_string_os(temp); + return TRUE; +} + +}//extern "C" +#ifdef _MSC_VER +#if _MSC_VER==1200 +#pragma comment(linker,"/opt:nowin98") +#endif +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.dsp b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.dsp new file mode 100644 index 000000000..e9ced9dd3 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.dsp @@ -0,0 +1,159 @@ +# Microsoft Developer Studio Project File - Name="utf8api" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=utf8api - 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 "utf8api.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 "utf8api.mak" CFG="utf8api - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "utf8api - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "utf8api - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "utf8api - Win32 Release ANSI" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "utf8api - 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 "UTF8API_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UTF8API_EXPORTS" /D "UNICODE" /D "_UNICODE" /Yu"utf8api.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib imagehlp.lib /nologo /dll /machine:I386 +# SUBTRACT LINK32 /debug + +!ELSEIF "$(CFG)" == "utf8api - 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 "UTF8API_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UTF8API_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib imagehlp.lib /nologo /dll /debug /machine:I386 /pdbtype:sept + +!ELSEIF "$(CFG)" == "utf8api - Win32 Release ANSI" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release ANSI" +# PROP BASE Intermediate_Dir "Release ANSI" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../Release_ANSI" +# PROP Intermediate_Dir "Release ANSI" +# 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 "UTF8API_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "UTF8API_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib imagehlp.lib /nologo /dll /machine:I386 + +!ENDIF + +# Begin Target + +# Name "utf8api - Win32 Release" +# Name "utf8api - Win32 Debug" +# Name "utf8api - Win32 Release ANSI" +# Begin Source File + +SOURCE=.\crash_info.cpp +# End Source File +# Begin Source File + +SOURCE=.\stdafx.cpp + +!IF "$(CFG)" == "utf8api - Win32 Release" + +# ADD CPP /Yc + +!ELSEIF "$(CFG)" == "utf8api - Win32 Debug" + +!ELSEIF "$(CFG)" == "utf8api - Win32 Release ANSI" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\systray.cpp +# End Source File +# Begin Source File + +SOURCE=.\text_drawing.cpp +# End Source File +# Begin Source File + +SOURCE=.\utf8.cpp +# End Source File +# Begin Source File + +SOURCE=.\utf8api.cpp +# End Source File +# Begin Source File + +SOURCE=.\utf8api.h +# End Source File +# End Target +# End Project diff --git a/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.h b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.h new file mode 100644 index 000000000..78014c989 --- /dev/null +++ b/tools/vio2sf/src/foobar8/foobar2000/utf8api/utf8api.h @@ -0,0 +1,462 @@ +#ifndef _UTF8API_DLL__UTF8API_H_ +#define _UTF8API_DLL__UTF8API_H_ + +#include "../../pfc/pfc.h" + +#ifndef WIN32 +#error N/A +#endif + +#ifndef STRICT +#define STRICT +#endif + +#include +#include +#include + +#ifndef UTF8API_EXPORTS +#define UTF8API_EXPORT _declspec(dllimport) +#else +#define UTF8API_EXPORT _declspec(dllexport) +#endif + +#define UTF8API_VERSION 3 + +extern "C" { + +UTF8API_EXPORT BOOL IsUnicode(); +UTF8API_EXPORT UINT UTF8API_GetVersion(); +UTF8API_EXPORT LRESULT uSendMessage(HWND wnd,UINT msg,WPARAM wp,LPARAM lp); +UTF8API_EXPORT LRESULT uSendMessageText(HWND wnd,UINT msg,WPARAM wp,const char * text); +UTF8API_EXPORT LRESULT uSendDlgItemMessage(HWND wnd,UINT id,UINT msg,WPARAM wp,LPARAM lp); +UTF8API_EXPORT LRESULT uSendDlgItemMessageText(HWND wnd,UINT id,UINT msg,WPARAM wp,const char * text); +UTF8API_EXPORT LRESULT uSendMessageTimeout(HWND wnd,UINT msg,WPARAM wp,LPARAM lp,UINT flags,UINT timeout,LPDWORD result); +UTF8API_EXPORT BOOL uSendNotifyMessage(HWND wnd,UINT msg,WPARAM wp,LPARAM lp); +UTF8API_EXPORT BOOL uSendMessageCallback(HWND wnd,UINT msg,WPARAM wp,LPARAM lp,SENDASYNCPROC cb,DWORD data); +UTF8API_EXPORT BOOL uPostMessage(HWND wnd,UINT msg,WPARAM wp,LPARAM lp); +UTF8API_EXPORT BOOL uPostThreadMessage(DWORD id,UINT msg,WPARAM wp,LPARAM lp); +UTF8API_EXPORT BOOL uGetWindowText(HWND wnd,string_base & out); +UTF8API_EXPORT BOOL uSetWindowText(HWND wnd,const char * text); +UTF8API_EXPORT BOOL uGetDlgItemText(HWND wnd,UINT id,string_base & out); +UTF8API_EXPORT BOOL uSetDlgItemText(HWND wnd,UINT id,const char * text); +UTF8API_EXPORT HWND uCreateDialog(HINSTANCE hIns,UINT id,HWND parent,DLGPROC proc,long param=0); +UTF8API_EXPORT int uDialogBox(HINSTANCE hIns,UINT id,HWND parent,DLGPROC proc,long param=0); +UTF8API_EXPORT BOOL uBrowseForFolder(HWND parent,const char * title,string_base & out); +UTF8API_EXPORT long uGetWindowLong(HWND wnd,int idx); +UTF8API_EXPORT long uSetWindowLong(HWND wnd,int idx,long val); +UTF8API_EXPORT int uMessageBox(HWND wnd,const char * text,const char * caption,UINT type); +UTF8API_EXPORT void uOutputDebugString(const char * msg); +typedef LOGFONTA uLOGFONT; +UTF8API_EXPORT HFONT uCreateFontIndirect(const uLOGFONT * p_font); +UTF8API_EXPORT void uGetDefaultFont(uLOGFONT * p_font); +UTF8API_EXPORT BOOL uChooseFont(uLOGFONT * p_font,HWND parent); +UTF8API_EXPORT LRESULT uCallWindowProc(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam); +UTF8API_EXPORT BOOL uAppendMenu(HMENU menu,UINT flags,UINT id,const char * content); +UTF8API_EXPORT BOOL uInsertMenu(HMENU menu,UINT position,UINT flags,UINT id,const char * content); +UTF8API_EXPORT int uStringCompare(const char * elem1, const char * elem2); +UTF8API_EXPORT HINSTANCE uLoadLibrary(const char * name); +UTF8API_EXPORT HANDLE uCreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState, const char * lpName); +UTF8API_EXPORT DWORD uGetModuleFileName(HMODULE hMod,string_base & out); +UTF8API_EXPORT BOOL uSetClipboardString(const char * ptr); +UTF8API_EXPORT LRESULT uDefWindowProc(HWND wnd,UINT msg,WPARAM wp,LPARAM lp); +UTF8API_EXPORT BOOL uIsDialogMessage(HWND dlg,LPMSG msg); +UTF8API_EXPORT BOOL uGetMessage(LPMSG msg,HWND wnd,UINT min,UINT max); +UTF8API_EXPORT BOOL uGetClassName(HWND wnd,string_base & out); +UTF8API_EXPORT UINT uCharLength(const char * src); +UTF8API_EXPORT BOOL uDragQueryFile(HDROP hDrop,UINT idx,string_base & out); +UTF8API_EXPORT UINT uDragQueryFileCount(HDROP hDrop); +UTF8API_EXPORT BOOL uGetTextExtentPoint32(HDC dc,const char * text,UINT cb,LPSIZE size);//note, cb is number of bytes, not actual unicode characters in the string (read: plain strlen() will do) +UTF8API_EXPORT BOOL uExtTextOut(HDC dc,int x,int y,UINT flags,const RECT * rect,const char * text,UINT cb,const int * lpdx); +UTF8API_EXPORT BOOL uTextOutColors(HDC dc,const char * src,UINT len,int x,int y,const RECT * clip,BOOL is_selected,DWORD default_color); +UTF8API_EXPORT BOOL uTextOutColorsTabbed(HDC dc,const char * src,UINT src_len,const RECT * item,int border,const RECT * clip,BOOL selected,DWORD default_color,BOOL use_columns); +UTF8API_EXPORT UINT uGetTextHeight(HDC dc); +UTF8API_EXPORT UINT uGetFontHeight(HFONT font); +UTF8API_EXPORT BOOL uChooseColor(DWORD * p_color,HWND parent,DWORD * p_custom_colors); +UTF8API_EXPORT BOOL uPeekMessage(LPMSG msg,HWND wnd,UINT min,UINT max,UINT flag); +UTF8API_EXPORT LONG uDispatchMessage(const MSG * msg); +UTF8API_EXPORT HCURSOR uLoadCursor(HINSTANCE hIns,const char * name); +UTF8API_EXPORT HICON uLoadIcon(HINSTANCE hIns,const char * name); +UTF8API_EXPORT HMENU uLoadMenu(HINSTANCE hIns,const char * name); +UTF8API_EXPORT BOOL uGetEnvironmentVariable(const char * name,string_base & out); +UTF8API_EXPORT HMODULE uGetModuleHandle(const char * name); +UTF8API_EXPORT UINT uRegisterWindowMessage(const char * name); +UTF8API_EXPORT BOOL uMoveFile(const char * src,const char * dst); +UTF8API_EXPORT BOOL uDeleteFile(const char * fn); +UTF8API_EXPORT DWORD uGetFileAttributes(const char * fn); +UTF8API_EXPORT BOOL uRemoveDirectory(const char * fn); +UTF8API_EXPORT HANDLE uCreateFile(const char * fn,DWORD access,DWORD share,LPSECURITY_ATTRIBUTES blah,DWORD creat,DWORD flags,HANDLE tmpl); +UTF8API_EXPORT HANDLE uCreateFileMapping(HANDLE hFile,LPSECURITY_ATTRIBUTES lpFileMappingAttributes,DWORD flProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,const char * lpName); +UTF8API_EXPORT BOOL uCreateDirectory(const char * fn,LPSECURITY_ATTRIBUTES blah); +UTF8API_EXPORT HANDLE uCreateMutex(LPSECURITY_ATTRIBUTES blah,BOOL bInitialOwner,const char * name); +UTF8API_EXPORT BOOL uGetLongPathName(const char * name,string_base & out);//may just fail to work on old windows versions, present on win98/win2k+ +UTF8API_EXPORT BOOL uGetFullPathName(const char * name,string_base & out); +UTF8API_EXPORT void uGetCommandLine(string_base & out); +UTF8API_EXPORT BOOL uGetTempPath(string_base & out); +UTF8API_EXPORT BOOL uGetTempFileName(const char * path_name,const char * prefix,UINT unique,string_base & out); +UTF8API_EXPORT BOOL uGetOpenFileName(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,string_base & p_filename,BOOL b_save); +//note: uGetOpenFileName extension mask uses | as separator, not null +UTF8API_EXPORT HANDLE uLoadImage(HINSTANCE hIns,const char * name,UINT type,int x,int y,UINT flags); +UTF8API_EXPORT UINT uRegisterClipboardFormat(const char * name); +UTF8API_EXPORT BOOL uGetClipboardFormatName(UINT format,string_base & out); + +UTF8API_EXPORT HANDLE uSortStringCreate(const char * src); +UTF8API_EXPORT int uSortStringCompare(HANDLE string1,HANDLE string2); +UTF8API_EXPORT int uSortStringCompareEx(HANDLE string1,HANDLE string2,DWORD flags);//flags - see win32 CompareString +UTF8API_EXPORT int uSortPathCompare(HANDLE string1,HANDLE string2); +UTF8API_EXPORT void uSortStringFree(HANDLE string); + + +UTF8API_EXPORT int uCompareString(DWORD flags,const char * str1,unsigned len1,const char * str2,unsigned len2); + +class NOVTABLE uGetOpenFileNameMultiResult +{ +public: + virtual UINT GetCount()=0; + virtual const char * GetFileName(UINT index)=0; + virtual ~uGetOpenFileNameMultiResult() {} +}; + +UTF8API_EXPORT uGetOpenFileNameMultiResult * uGetOpenFileNameMulti(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory); + +class NOVTABLE uFindFile +{ +protected: + uFindFile() {} +public: + virtual BOOL FindNext()=0; + virtual const char * GetFileName()=0; + virtual __int64 GetFileSize()=0; + virtual DWORD GetAttributes()=0; + virtual FILETIME GetCreationTime()=0; + virtual FILETIME GetLastAccessTime()=0; + virtual FILETIME GetLastWriteTime()=0; + virtual ~uFindFile() {}; + inline bool IsDirectory() {return (GetAttributes() & FILE_ATTRIBUTE_DIRECTORY) ? true : false;} +}; + +UTF8API_EXPORT uFindFile * uFindFirstFile(const char * path); + +UTF8API_EXPORT HINSTANCE uShellExecute(HWND wnd,const char * oper,const char * file,const char * params,const char * dir,int cmd); +UTF8API_EXPORT HWND uCreateStatusWindow(LONG style,const char * text,HWND parent,UINT id); + +typedef WNDCLASSA uWNDCLASS; +UTF8API_EXPORT ATOM uRegisterClass(const uWNDCLASS * ptr); +UTF8API_EXPORT BOOL uUnregisterClass(const char * name,HINSTANCE ins); + +UTF8API_EXPORT BOOL uShellNotifyIcon(DWORD dwMessage,HWND wnd,UINT id,UINT callbackmsg,HICON icon,const char * tip); +UTF8API_EXPORT BOOL uShellNotifyIconEx(DWORD dwMessage,HWND wnd,UINT id,UINT callbackmsg,HICON icon,const char * tip,const char * balloon_title,const char * balloon_msg); + +UTF8API_EXPORT HWND uCreateWindowEx(DWORD dwExStyle,const char * lpClassName,const char * lpWindowName,DWORD dwStyle,int x,int y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam); + +UTF8API_EXPORT BOOL uGetSystemDirectory(string_base & out); +UTF8API_EXPORT BOOL uGetWindowsDirectory(string_base & out); +UTF8API_EXPORT BOOL uSetCurrentDirectory(const char * path); +UTF8API_EXPORT BOOL uGetCurrentDirectory(string_base & out); +UTF8API_EXPORT BOOL uExpandEnvironmentStrings(const char * src,string_base & out); +UTF8API_EXPORT BOOL uGetUserName(string_base & out); +UTF8API_EXPORT BOOL uGetShortPathName(const char * src,string_base & out); + +UTF8API_EXPORT HSZ uDdeCreateStringHandle(DWORD ins,const char * src); +UTF8API_EXPORT BOOL uDdeQueryString(DWORD ins,HSZ hsz,string_base & out); +UTF8API_EXPORT UINT uDdeInitialize(LPDWORD pidInst,PFNCALLBACK pfnCallback,DWORD afCmd,DWORD ulRes); +UTF8API_EXPORT BOOL uDdeAccessData_Text(HDDEDATA data,string_base & out); + +UTF8API_EXPORT HIMAGELIST uImageList_LoadImage(HINSTANCE hi, const char * lpbmp, int cx, int cGrow, COLORREF crMask, UINT uType, UINT uFlags); + +#define uDdeFreeStringHandle DdeFreeStringHandle +#define uDdeCmpStringHandles DdeCmpStringHandles +#define uDdeKeepStringHandle DdeKeepStringHandle +#define uDdeUninitialize DdeUninitialize +#define uDdeNameService DdeNameService +#define uDdeFreeDataHandle DdeFreeDataHandle + + +typedef TVINSERTSTRUCTA uTVINSERTSTRUCT; + +UTF8API_EXPORT HTREEITEM uTreeView_InsertItem(HWND wnd,const uTVINSERTSTRUCT * param); + +UTF8API_EXPORT HHOOK uSetWindowsHookEx(int idhook,HOOKPROC fn,HINSTANCE hMod,DWORD threadid); +#define uUnhookWindowsHookEx UnhookWindowsHookEx +#define uCallNextHookEx CallNextHookEx + + +typedef SHFILEOPSTRUCTA uSHFILEOPSTRUCT; +UTF8API_EXPORT int uSHFileOperation(uSHFILEOPSTRUCT * lpFileOp); + +typedef STARTUPINFOA uSTARTUPINFO; + +UTF8API_EXPORT BOOL uCreateProcess( + const char * lpApplicationName, + const char * lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + const char * lpEnvironment, + const char * lpCurrentDirectory, + const uSTARTUPINFO * lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +); + +UTF8API_EXPORT unsigned uOSStringEstimateSize(const char * src,unsigned len = -1);//return value in bytes +UTF8API_EXPORT unsigned uOSStringConvert(const char * src,void * dst,unsigned len = -1);//length of src (will cut if found null earlier) +/* usage: + + const char * src = "something"; + + void * temp = malloc(uOSStringEstimateSize(src)); + uOSStringConvert(src,temp); + //now temp contains OS-friendly (TCHAR) version of src +*/ + +typedef TCITEMA uTCITEM; +UTF8API_EXPORT int uTabCtrl_InsertItem(HWND wnd,int idx,const uTCITEM * item); +UTF8API_EXPORT int uTabCtrl_SetItem(HWND wnd,int idx,const uTCITEM * item); + +UTF8API_EXPORT int uGetKeyNameText(LONG lparam,string_base & out); + +UTF8API_EXPORT void uFixAmpersandChars(const char * src,string_base & out);//for systray +UTF8API_EXPORT void uFixAmpersandChars_v2(const char * src,string_base & out);//for other controls +//gotta hate MS for shoving ampersand=>underline conversion into random things AND making each of them use different rules for inserting ampersand char instead of underline + + +//deprecated +UTF8API_EXPORT UINT uPrintCrashInfo(LPEXCEPTION_POINTERS param,const char * extrainfo,char * out); +#define uPrintCrashInfo_max_length 1024 + +UTF8API_EXPORT void uPrintCrashInfo_Init(const char * name);//called only by exe on startup + +UTF8API_EXPORT void uDumpCrashInfo(LPEXCEPTION_POINTERS param); + +UTF8API_EXPORT BOOL uListBox_GetText(HWND listbox,UINT index,string_base & out); + +UTF8API_EXPORT void uPrintf(string_base & out,const char * fmt,...); +UTF8API_EXPORT void uPrintfV(string_base & out,const char * fmt,va_list arglist); + +class NOVTABLE uResource +{ +public: + virtual const void * GetPointer() = 0; + virtual unsigned GetSize() = 0; + virtual ~uResource() {} +}; + +UTF8API_EXPORT uResource * uLoadResource(HMODULE hMod,const char * name,const char * type,WORD wLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) ); +UTF8API_EXPORT HRSRC uFindResource(HMODULE hMod,const char * name,const char * type,WORD wLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) ); + +UTF8API_EXPORT BOOL uLoadString(HINSTANCE ins,UINT id,string_base & out); + +UTF8API_EXPORT UINT uCharLower(UINT c); +UTF8API_EXPORT UINT uCharUpper(UINT c); + +UTF8API_EXPORT BOOL uGetMenuString(HMENU menu,UINT id,string_base & out,UINT flag); +UTF8API_EXPORT BOOL uModifyMenu(HMENU menu,UINT id,UINT flags,UINT newitem,const char * data); +UTF8API_EXPORT UINT uGetMenuItemType(HMENU menu,UINT position); + + +}//extern "C" + +inline char * uCharNext(char * src) {return src+uCharLength(src);} +inline const char * uCharNext(const char * src) {return src+uCharLength(src);} + + +class string_utf8_from_window : public string8 +{ +public: + string_utf8_from_window(HWND wnd) + { + uGetWindowText(wnd,*this); + } + string_utf8_from_window(HWND wnd,UINT id) + { + uGetDlgItemText(wnd,id,*this); + } +}; + +#define uMAKEINTRESOURCE(x) ((const char*)LOWORD(x)) + +class critical_section +{ +private: + CRITICAL_SECTION sec; + int count; +public: + int enter() {EnterCriticalSection(&sec);return ++count;} + int leave() {int rv = --count;LeaveCriticalSection(&sec);return rv;} + int get_lock_count() {return count;} + int get_lock_count_check() {enter();return leave();} + inline void assert_locked() {assert(get_lock_count_check()>0);} + inline void assert_not_locked() {assert(get_lock_count_check()==0);} + critical_section() {InitializeCriticalSection(&sec);count=0;} + ~critical_section() {DeleteCriticalSection(&sec);} +#ifdef CRITICAL_SECTION_HAVE_TRYENTER + bool try_enter() {return !!TryEnterCriticalSection(&sec);} +#endif +}; + +class c_insync +{ +private: + critical_section * ptr; +public: + c_insync(critical_section * p) {ptr=p;ptr->enter();} + c_insync(critical_section & p) {ptr=&p;ptr->enter();} + ~c_insync() {ptr->leave();} +}; + +#define insync(X) c_insync blah____sync(X) + + +class critical_section2 //smarter version, has try_enter() +{ +private: + HANDLE hMutex; + int count; +public: + int enter() {return enter_timeout(INFINITE);} + int leave() {int rv = --count;ReleaseMutex(hMutex);return rv;} + int get_lock_count() {return count;} + int get_lock_count_check() + { + int val = try_enter(); + if (val>0) val = leave(); + return val; + } + int enter_timeout(DWORD t) {return WaitForSingleObject(hMutex,t)==WAIT_OBJECT_0 ? ++count : 0;} + int try_enter() {return enter_timeout(0);} + int check_count() {enter();return leave();} + critical_section2() + { + hMutex = uCreateMutex(0,0,0); + count=0; + } + ~critical_section2() {CloseHandle(hMutex);} + + inline void assert_locked() {assert(get_lock_count_check()>0);} + inline void assert_not_locked() {assert(get_lock_count_check()==0);} + +}; + +class c_insync2 +{ +private: + critical_section2 * ptr; +public: + c_insync2(critical_section2 * p) {ptr=p;ptr->enter();} + c_insync2(critical_section2 & p) {ptr=&p;ptr->enter();} + ~c_insync2() {ptr->leave();} +}; + +#define insync2(X) c_insync2 blah____sync2(X) + + +//other +#define uEndDialog EndDialog +#define uDestroyWindow DestroyWindow +#define uGetDlgItem GetDlgItem +#define uEnableWindow EnableWindow +#define uGetDlgItemInt GetDlgItemInt +#define uSetDlgItemInt SetDlgItemInt +#define uHookWindowProc(WND,PROC) ((WNDPROC)uSetWindowLong(WND,GWL_WNDPROC,(long)(PROC))) +#define uCreateToolbarEx CreateToolbarEx +#define uIsBadStringPtr IsBadStringPtrA + + +class string_print_crash +{ + char block[uPrintCrashInfo_max_length]; +public: + inline operator const char * () const {return block;} + inline const char * get_ptr() const {return block;} + inline unsigned length() {return strlen(block);} + inline string_print_crash(LPEXCEPTION_POINTERS param,const char * extrainfo = 0) {uPrintCrashInfo(param,extrainfo,block);} +}; + +class uStringPrintf : private string8_fastalloc +{ +public: + inline explicit uStringPrintf(const char * fmt,...) + { + va_list list; + va_start(list,fmt); + uPrintfV(*this,fmt,list); + va_end(list); + } + operator const char * () {return get_ptr();} +}; + +inline LRESULT uButton_SetCheck(HWND wnd,UINT id,bool state) {return uSendDlgItemMessage(wnd,id,BM_SETCHECK,state ? BST_CHECKED : BST_UNCHECKED,0); } +inline bool uButton_GetCheck(HWND wnd,UINT id) {return uSendDlgItemMessage(wnd,id,BM_GETCHECK,0,0) == BST_CHECKED;} + +class UTF8API_EXPORT uCallStackTracker +{ + unsigned param; +public: + explicit uCallStackTracker(const char * name); + ~uCallStackTracker(); +}; + +extern "C" +{ + UTF8API_EXPORT const char * uGetCallStackPath(); +} + +#define TRACK_CALL(X) uCallStackTracker TRACKER__##X(#X) +#define TRACK_CALL_TEXT(X) uCallStackTracker TRACKER__BLAH(X) + + +extern "C" { +UTF8API_EXPORT int stricmp_utf8(const char * p1,const char * p2); +UTF8API_EXPORT int stricmp_utf8_ex(const char * p1,unsigned len1,const char * p2,unsigned len2); +UTF8API_EXPORT int stricmp_utf8_stringtoblock(const char * p1,const char * p2,unsigned p2_bytes); +UTF8API_EXPORT int stricmp_utf8_partial(const char * p1,const char * p2,unsigned num = (unsigned)(-1)); +UTF8API_EXPORT int stricmp_utf8_max(const char * p1,const char * p2,unsigned p1_bytes); +UTF8API_EXPORT unsigned uReplaceStringAdd(string_base & out,const char * src,unsigned src_len,const char * s1,unsigned len1,const char * s2,unsigned len2,bool casesens); +UTF8API_EXPORT unsigned uReplaceCharAdd(string_base & out,const char * src,unsigned src_len,unsigned c1,unsigned c2,bool casesens); +//all lengths in uReplaceString functions are optional, set to -1 if parameters is a simple null-terminated string +UTF8API_EXPORT void uAddStringLower(string_base & out,const char * src,unsigned len = (unsigned)(-1)); +UTF8API_EXPORT void uAddStringUpper(string_base & out,const char * src,unsigned len = (unsigned)(-1)); + +inline void uStringLower(string_base & out,const char * src,unsigned len = (unsigned)(-1)) {out.reset();uAddStringLower(out,src,len);} +inline void uStringUpper(string_base & out,const char * src,unsigned len = (unsigned)(-1)) {out.reset();uAddStringUpper(out,src,len);} + +inline unsigned uReplaceString(string_base & out,const char * src,unsigned src_len,const char * s1,unsigned len1,const char * s2,unsigned len2,bool casesens) +{ + out.reset(); + return uReplaceStringAdd(out,src,src_len,s1,len1,s2,len2,casesens); +} + +inline unsigned uReplaceChar(string_base & out,const char * src,unsigned src_len,unsigned c1,unsigned c2,bool casesens) +{ + out.reset(); + return uReplaceCharAdd(out,src,src_len,c1,c2,casesens); +} + +class string_lower : private string8 +{ +public: + explicit string_lower(const char * ptr,unsigned num=-1) {uAddStringLower(*this,ptr,num);} + operator const char * () {return string8::get_ptr();} +}; + +class string_upper : private string8 +{ +public: + explicit string_upper(const char * ptr,unsigned num=-1) {uAddStringUpper(*this,ptr,num);} + operator const char * () {return string8::get_ptr();} +}; + + +} + +#define char_lower uCharLower +#define char_upper uCharUpper + +inline BOOL uGetLongPathNameEx(const char * name,string_base & out) +{ + if (uGetLongPathName(name,out)) return TRUE; + return uGetFullPathName(name,out); +} + +#endif //_UTF8API_DLL__UTF8API_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/license.txt b/tools/vio2sf/src/foobar8/license.txt new file mode 100644 index 000000000..d62a0729e --- /dev/null +++ b/tools/vio2sf/src/foobar8/license.txt @@ -0,0 +1,10 @@ +Copyright (c) 2001-2004, Peter Pawlowski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tools/vio2sf/src/foobar8/pfc/array.h b/tools/vio2sf/src/foobar8/pfc/array.h new file mode 100644 index 000000000..2ce8dfe00 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/array.h @@ -0,0 +1,73 @@ +#ifndef _PFC_ARRAY_H_ +#define _PFC_ARRAY_H_ + +template +class array_t +{ +public: + explicit array_t(unsigned size = 0) + { + m_data = 0; + m_size = 0; + resize(size); + } + + inline const T& operator[](unsigned n) const + { + assert(n m_size ? m_size : new_size; + for(n=0;n0 && get(ptr)!=val) {ptr+=d;todo--;} + return ptr; + } + inline bool operator[](int n) const {return get(n);} + + unsigned calc_count(bool val,int start,unsigned count) const//counts number of vals for start<=n class mem_block_t; //blah + +template +class bit_array_table_t : public bit_array +{ + const T * data; + int count; + bool before,after; +public: + inline bit_array_table_t(const T * p_data,int p_count,bool p_before = false,bool p_after = false) + : data(p_data), count(p_count), before(p_before), after(p_after) + { + } + + inline bit_array_table_t(const mem_block_t & p_data,bool p_before = false,bool p_after = false) + : data(p_data.get_ptr()), count(p_data.get_size()), before(p_before), after(p_after) + { + } + + virtual bool get(int n) const + { + if (n<0) return before; + else if (n bit_array_table; + +class bit_array_range : public bit_array +{ + int begin,end; + bool state; +public: + bit_array_range(int first,int count,bool p_state = true) : begin(first), end(first+count), state(p_state) {} + + virtual bool get(int n) const + { + bool rv = n>=begin && n0) + return (val>=start && valstart+count) ? val : start+count; + } + else + { + if (start == val) return count>0 ? start+1 : start-1; + else return start; + } + } +}; + +class bit_array_bittable : public bit_array_var +{ + unsigned char * data; + unsigned count; +public: + //helpers + inline static bool g_get(const unsigned char * ptr,unsigned idx) + { + return !! (ptr[idx>>3] & (1<<(idx&7))); + } + + inline static void g_set(unsigned char * ptr,unsigned idx,bool val) + { + unsigned char & dst = ptr[idx>>3]; + unsigned char mask = 1<<(idx&7); + dst = val ? dst|mask : dst&~mask; + } + + inline static unsigned g_estimate_size(unsigned count) {return (count+7)>>3;} + + void resize(unsigned p_count) + { + count = p_count; + unsigned bytes = g_estimate_size(count); + if (bytes==0) + { + if (data) {free(data);data=0;} + } + else + { + data = data ? (unsigned char*)realloc(data,bytes) : (unsigned char*)malloc(bytes); + memset(data,0,bytes); + } + } + + inline bit_array_bittable(unsigned p_count) {count=0;data=0;resize(p_count);} + inline ~bit_array_bittable() {free(data);} + + virtual void set(int n,bool val) + { + if ((unsigned)n>1;n++) + { + t = ptr[n]; + ptr[n] = ptr[bytes-n-1]; + ptr[bytes-n-1] = t; + } +} + +#if 0 +typedef struct _GUID { // size is 16 + DWORD Data1; + WORD Data2; + WORD Data3; + BYTE Data4[8]; +} GUID; +#endif + +void swap_guid(GUID & g) +{ + swap_order(&g.Data1,sizeof(g.Data1)); + swap_order(&g.Data2,sizeof(g.Data2)); + swap_order(&g.Data3,sizeof(g.Data3)); +} + + +void guid_native_to_le(GUID ¶m) +{ + if (machine_is_big_endian()) swap_guid(param); +} + +void guid_native_to_be(GUID ¶m) +{ + if (!machine_is_big_endian()) swap_guid(param); +} + +void guid_le_to_native(GUID ¶m) +{ + if (machine_is_big_endian()) swap_guid(param); +} + +void guid_be_to_native(GUID ¶m) +{ + if (!machine_is_big_endian()) swap_guid(param); +} + + +WORD swap_word(WORD p) +{ + return ((p&0x00FF)<<8)|((p&0xFF00)>>8); +} + +DWORD swap_dword(DWORD p) +{ + return ((p&0xFF000000)>>24) | ((p&0x00FF0000)>>8) | ((p&0x0000FF00)<<8) | ((p&0x000000FF)<<24); +} + + +#ifndef PFC_BYTE_ORDER_IS_BIG_ENDIAN +void swap_order_if_le(void * ptr,unsigned bytes) +{ + if (machine_is_little_endian()) swap_order(ptr,bytes); +} +void swap_order_if_be(void * ptr,unsigned bytes) +{ + if (machine_is_big_endian()) swap_order(ptr,bytes); +} +WORD swap_word_if_le(WORD p) +{ + return machine_is_little_endian() ? swap_word(p) : p; +} +WORD swap_word_if_be(WORD p) +{ + return machine_is_big_endian() ? swap_word(p) : p; +} +DWORD swap_dword_if_le(DWORD p) +{ + return machine_is_little_endian() ? swap_dword(p) : p; +} +DWORD swap_dword_if_be(DWORD p) +{ + return machine_is_big_endian() ? swap_dword(p) : p; +} +#endif + +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/byte_order_helper.h b/tools/vio2sf/src/foobar8/pfc/byte_order_helper.h new file mode 100644 index 000000000..f35a0869b --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/byte_order_helper.h @@ -0,0 +1,82 @@ +#ifndef _PFC_BYTE_ORDER_HELPER_ +#define _PFC_BYTE_ORDER_HELPER_ + +namespace byte_order_helper { + +#ifdef _M_IX86 +#define PFC_BYTE_ORDER_IS_BIG_ENDIAN 0 +#endif + +#ifdef PFC_BYTE_ORDER_IS_BIG_ENDIAN +#define PFC_BYTE_ORDER_IS_LITTLE_ENDIAN (!(PFC_BYTE_ORDER_IS_BIG_ENDIAN)) +#endif + //if not defined, use machine_is_big_endian() to detect in runtime + +#ifndef PFC_BYTE_ORDER_IS_BIG_ENDIAN + bool machine_is_big_endian(); +#else + inline bool machine_is_big_endian() {return PFC_BYTE_ORDER_IS_BIG_ENDIAN;} +#endif + + inline bool machine_is_little_endian() {return !machine_is_big_endian();} + + + void swap_order(void * ptr,unsigned bytes); + void swap_guid(GUID & g); + WORD swap_word(WORD); + DWORD swap_dword(DWORD); + +#ifdef PFC_BYTE_ORDER_IS_BIG_ENDIAN +#if PFC_BYTE_ORDER_IS_BIG_ENDIAN + inline void swap_order_if_le(void * ptr,unsigned bytes) {} + inline void swap_order_if_be(void * ptr,unsigned bytes) {swap_order(ptr,bytes);} + inline WORD swap_word_if_le(WORD p) {return p;} + inline WORD swap_word_if_be(WORD p) {return swap_word(p);} + inline DWORD swap_dword_if_le(DWORD p) {return p;} + inline DWORD swap_dword_if_be(DWORD p) {return swap_dword(p);} +#else + inline void swap_order_if_le(void * ptr,unsigned bytes) {swap_order(ptr,bytes);} + inline void swap_order_if_be(void * ptr,unsigned bytes) {} + inline WORD swap_word_if_le(WORD p) {return swap_word(p);} + inline WORD swap_word_if_be(WORD p) {return p;} + inline DWORD swap_dword_if_le(DWORD p) {return swap_dword(p);} + inline DWORD swap_dword_if_be(DWORD p) {return p;} +#endif +#else + void swap_order_if_le(void * ptr,unsigned bytes); + void swap_order_if_be(void * ptr,unsigned bytes); + WORD swap_word_if_le(WORD p); + WORD swap_word_if_be(WORD p); + DWORD swap_dword_if_le(DWORD p); + DWORD swap_dword_if_be(DWORD p); +#endif + + inline void order_be_to_native(void * ptr,unsigned bytes) {swap_order_if_le(ptr,bytes);} + inline void order_le_to_native(void * ptr,unsigned bytes) {swap_order_if_be(ptr,bytes);} + inline void order_native_to_be(void * ptr,unsigned bytes) {swap_order_if_le(ptr,bytes);} + inline void order_native_to_le(void * ptr,unsigned bytes) {swap_order_if_be(ptr,bytes);} + + inline QWORD swap_qword(QWORD param) {swap_order(¶m,sizeof(param));return param;} + + inline QWORD qword_be_to_native(QWORD param) {swap_order_if_le(¶m,sizeof(param));return param;} + inline QWORD qword_le_to_native(QWORD param) {swap_order_if_be(¶m,sizeof(param));return param;} + inline QWORD qword_native_to_be(QWORD param) {swap_order_if_le(¶m,sizeof(param));return param;} + inline QWORD qword_native_to_le(QWORD param) {swap_order_if_be(¶m,sizeof(param));return param;} + + inline DWORD dword_be_to_native(DWORD param) {return swap_dword_if_le(param);} + inline DWORD dword_le_to_native(DWORD param) {return swap_dword_if_be(param);} + inline DWORD dword_native_to_be(DWORD param) {return swap_dword_if_le(param);} + inline DWORD dword_native_to_le(DWORD param) {return swap_dword_if_be(param);} + + inline WORD word_be_to_native(WORD param) {return swap_word_if_le(param);} + inline WORD word_le_to_native(WORD param) {return swap_word_if_be(param);} + inline WORD word_native_to_be(WORD param) {return swap_word_if_le(param);} + inline WORD word_native_to_le(WORD param) {return swap_word_if_be(param);} + + void guid_native_to_le(GUID ¶m);//big F-U to whoever wrote original GUID declaration, writing it to files depends on byte order + void guid_native_to_be(GUID ¶m); + void guid_le_to_native(GUID ¶m); + void guid_be_to_native(GUID ¶m); +}; + +#endif diff --git a/tools/vio2sf/src/foobar8/pfc/cfg_memblock.h b/tools/vio2sf/src/foobar8/pfc/cfg_memblock.h new file mode 100644 index 000000000..285ee3f9c --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/cfg_memblock.h @@ -0,0 +1,59 @@ +#ifndef _PFC_CFG_VAR_MEMBLOCK_H_ +#define _PFC_CFG_VAR_MEMBLOCK_H_ + +#if 0 //deprecated + +template +class cfg_memblock : public cfg_var, public mem_block_list +{ +private: + const T* init_val; + unsigned init_size; +protected: + virtual void reset() + { + remove_all(); + if (init_val) + { + unsigned n; + for(n=0;nwrite(get_ptr(),get_count()*sizeof(T)); + } + + virtual void set_raw_data(const void * data,int size) + { + remove_all(); + const T * ptr = reinterpret_cast(data); + unsigned count = size/sizeof(T); + unsigned n; + for(n=0;nnext) ptr->reset(); +} +#endif + + + +void cfg_var::config_read_file(const void * p_src,unsigned p_size) +{ + read_config_helper r(p_src,p_size); + string8_fastalloc name; + DWORD size; + while(r.get_remaining()>4) + { + if (!r.read_string(name)) break; + if (!r.read_dword_le(size)) break; + if (size > r.get_remaining()) break; + + cfg_var * ptr; + for(ptr = list; ptr; ptr=ptr->next) + { + if (!strcmp(ptr->var_name,name)) + { + ptr->set_raw_data(r.get_ptr(),size); + break; + } + } + r.advance(size); + } +} + +void cfg_var::config_write_file(write_config_callback * out) +{ + cfg_var * ptr; + write_config_callback_i temp; + for(ptr = list; ptr; ptr=ptr->next) + { + temp.data.set_size(0); + if (ptr->get_raw_data(&temp)) + { + out->write_string(ptr->var_name); + unsigned size = temp.data.get_size(); + out->write_dword_le(size); + if (size>0) out->write(temp.data.get_ptr(),size); + } + } +} + +void cfg_var::config_on_app_init() +{ + cfg_var_notify::on_app_init(); +} + +void cfg_var_notify::on_app_init() +{ + cfg_var_notify * ptr = list; + while(ptr) + { + if (ptr->my_var) + ptr->my_var->add_notify(ptr); + ptr=ptr->next; + } +} + +void cfg_var::on_change() +{ + cfg_var_notify * ptr = notify_list; + while(ptr) + { + ptr->on_var_change(var_get_name(),this); + ptr = ptr->var_next; + } + +} + +cfg_var_notify * cfg_var_notify::list=0; + +void cfg_var::add_notify(cfg_var_notify * ptr) +{ + ptr->var_next = notify_list; + notify_list = ptr; +} + + +void cfg_var::write_config_callback::write_dword_le(DWORD param) +{ + DWORD temp = byte_order_helper::dword_native_to_le(param); + write(&temp,sizeof(temp)); +} + +void cfg_var::write_config_callback::write_dword_be(DWORD param) +{ + DWORD temp = byte_order_helper::dword_native_to_be(param); + write(&temp,sizeof(temp)); +} + +void cfg_var::write_config_callback::write_string(const char * param) +{ + unsigned len = strlen(param); + write_dword_le(len); + write(param,len); +} + +bool cfg_int::get_raw_data(write_config_callback * out) +{ + out->write_dword_le(val); + return true; +} + +void cfg_int::set_raw_data(const void * data,int size) +{ + if (size==sizeof(long)) + { + val = (long)read_dword_le_fromptr(data); + on_change(); + } +} + + +bool cfg_var::read_config_helper::read(void * out,unsigned bytes) +{ + if (bytes>remaining) return false; + memcpy(out,ptr,bytes); + advance(bytes); + return true; +} + +bool cfg_var::read_config_helper::read_dword_le(DWORD & val) +{ + DWORD temp; + if (!read(&temp,sizeof(temp))) return false; + val = byte_order_helper::dword_le_to_native(temp); + return true; +} +bool cfg_var::read_config_helper::read_dword_be(DWORD & val) +{ + DWORD temp; + if (!read(&temp,sizeof(temp))) return false; + val = byte_order_helper::dword_be_to_native(temp); + return true; +} + +bool cfg_var::read_config_helper::read_string(string_base & out) +{ + DWORD len; + if (!read_dword_le(len)) return false; + if (remainingwrite((const char*)val,strlen(val) * sizeof(char)); + return true; + } + + virtual void set_raw_data(const void * data,int size) + { + val.set_string_n((const char*)data,size/sizeof(char)); + on_change(); + } + +public: + explicit inline cfg_string(const char * name,const char * v) : cfg_var(name), val(v) {} + void operator=(const cfg_string & v) {val=v.get_val();on_change();} + inline operator const char * () const {return val;} + inline const char * operator=(const char* v) {val=v;on_change();return val;} + inline const char * get_val() const {return val;} + inline bool is_empty() {return !val[0];} +}; + +class cfg_guid : public cfg_var +{ + GUID val; + + virtual bool get_raw_data(write_config_callback * out) + { + out->write_guid_le(val); + return true; + } + + virtual void set_raw_data(const void * data,int size) + { + read_config_helper r(data,size); + r.read_guid_le(val); + } +public: + explicit inline cfg_guid(const char * name,GUID v) : cfg_var(name) {val=v;} + explicit inline cfg_guid(const char * name) : cfg_var(name) {memset(&val,0,sizeof(val));} + inline GUID operator=(GUID v) {val = v; on_change(); return v;} + inline GUID get_val() const {return val;} + inline operator GUID() const {return val;} +}; + +template +class cfg_struct_t : public cfg_var +{ +private: + T val; + + + virtual bool get_raw_data(write_config_callback * out) + { + out->write(&val,sizeof(val)); + return true; + } + + virtual void set_raw_data(const void * data,int size) + { + if (size==sizeof(T)) + { + memcpy(&val,data,sizeof(T)); + on_change(); + } + } +public: + explicit inline cfg_struct_t(const char * name,T v) : cfg_var(name) {val=v;} + explicit inline cfg_struct_t(const char * name,int filler) : cfg_var(name) {memset(&val,filler,sizeof(T));} + inline const T& operator=(const cfg_struct_t & v) {val = v.get_val();on_change();return val;} + inline T& get_val() {return val;} + inline const T& get_val() const {return val;} + inline operator T() const {return val;} + inline const T& operator=(const T& v) {val=v;on_change();return val;} +}; + +class cfg_var_notify +{ + friend cfg_var; +private: + cfg_var * my_var; + cfg_var_notify * next; + cfg_var_notify * var_next; + static cfg_var_notify * list; +public: + cfg_var_notify(cfg_var * var) {my_var=var;next=list;list=this;var_next=0;} + //override me + virtual void on_var_change(const char * name,cfg_var * var) {} + + static void on_app_init();//called by cfg_var::config_on_app_init() +}; + +class cfg_var_notify_func : public cfg_var_notify +{ +private: + void (*func)(); +public: + cfg_var_notify_func(cfg_var * var,void (*p_func)() ) : cfg_var_notify(var), func(p_func) {} + virtual void on_var_change(const char * name,cfg_var * var) {func();} +}; + + +#endif diff --git a/tools/vio2sf/src/foobar8/pfc/chainlist.h b/tools/vio2sf/src/foobar8/pfc/chainlist.h new file mode 100644 index 000000000..006ee5521 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/chainlist.h @@ -0,0 +1,160 @@ +#ifndef _PFC_CHAINLIST_H_ +#define _PFC_CHAINLIST_H_ + + +template +class chain_list +{ + class elem + { + public: + T item; + elem * prev, * next; + elem(const T& param,int blah) : item(param) {} + elem(T param) : item(param) {} + elem(int, int, int) {} + }; + + elem * first, * last; + +public: + class enumerator; + +private: + static inline elem * parse_enum(const enumerator & en) {assert(en.ptr);return reinterpret_cast(en.ptr);} + static inline void modify_enum(enumerator & en, elem * ptr) {en.ptr = reinterpret_cast(ptr);} + + void remove(elem * ptr) + { + assert(ptr); + (ptr->prev ? ptr->prev->next : first) = ptr->next; + (ptr->next ? ptr->next->prev : last) = ptr->prev; + delete ptr; + } + + void init_last(elem * ptr) + { + ptr->prev = last; + ptr->next = 0; + last = ptr; + (ptr->prev ? ptr->prev->next : first) = ptr; + } + void init_first(elem * ptr) + { + ptr->next = first; + ptr->prev = 0; + first = ptr; + (ptr->next ? ptr->next->prev : last) = ptr; + } + +public: + inline ~chain_list() {remove_all();} + inline explicit chain_list() {first = 0; last = 0;} + + inline void advance(enumerator & en) const + { + modify_enum(en,parse_enum(en)->next); + } + + inline void reset(enumerator & en) const + { + modify_enum(en,first); + } + + inline T get_item(const enumerator & en) const + { + return parse_enum(en)->item; + } + + inline const T& get_item_ref(const enumerator & en) const + { + return parse_enum(en)->item; + } + + inline T& get_item_var(const enumerator & en) + { + return parse_enum(en)->item; + } + + void remove_all() + { + while(first) {remove(first);} + } + + unsigned get_count() const + { + unsigned val = 0; + elem * ptr = first; + while(ptr) {val++; ptr = ptr->next;} + return val; + } + + inline void add_item_first(T item) + { + init_first(new elem(item)); + } + + inline void add_item_first_ref(const T & item) + { + init_first(new elem(item,0)); + } + + inline void add_item(T item) + { + init_last(new elem(item)); + } + + inline void add_item_ref(const T & item) + { + init_last(new elem(item,0)); + } + + void remove_item(enumerator & en) + { + elem * freeme = parse_enum(en); + advance(en); + remove(freeme); + } + + inline T& add_item_noinit() + { + elem * ptr = new elem(0,0,0); + init_last(ptr); + return ptr->item; + } + + inline T& add_item_first_noinit() + { + elem * ptr = new elem(0,0,0); + init_first(ptr); + return ptr->item; + } + + class enumerator + { + const chain_list & list; + void * ptr; + friend class chain_list; + public: + explicit enumerator(const chain_list & p_list) : list(p_list), ptr(0) {reset();} + + inline void reset() {list.reset(*this);} + inline void advance() {list.advance(*this);} + + inline T get_item() const {return list.get_item(*this);} + inline const T& get_item_ref() const {return list.get_item(*this);} + + inline T first() {reset();return get_item();} + inline const T& first_ref() {reset();return get_item_ref();} + + inline T next() {advance();return get_item();} + inline const T& next_ref() {advance();return get_item_ref();} + + inline operator bool() const {return !!ptr;} + + }; + +}; + + +#endif _PFC_CHAINLIST_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/critsec.h b/tools/vio2sf/src/foobar8/pfc/critsec.h new file mode 100644 index 000000000..f3ebb91f6 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/critsec.h @@ -0,0 +1,6 @@ +#ifndef _PFC_CRITSEC_H_ +#define _PFC_CRITSEC_H_ + +#error MOVED TO UTF8API.H + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/foobar2000.h b/tools/vio2sf/src/foobar8/pfc/foobar2000.h new file mode 100644 index 000000000..f19f43488 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/foobar2000.h @@ -0,0 +1,2 @@ +#include "../pfc/pfc.h" + diff --git a/tools/vio2sf/src/foobar8/pfc/guid.cpp b/tools/vio2sf/src/foobar8/pfc/guid.cpp new file mode 100644 index 000000000..58527b711 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/guid.cpp @@ -0,0 +1,86 @@ +#include "pfc.h" + + +/* +6B29FC40-CA47-1067-B31D-00DD010662DA +. +typedef struct _GUID { // size is 16 + DWORD Data1; + WORD Data2; + WORD Data3; + BYTE Data4[8]; +} GUID; + +// {B296CF59-4D51-466f-8E0B-E57D3F91D908} +static const GUID <> = +{ 0xb296cf59, 0x4d51, 0x466f, { 0x8e, 0xb, 0xe5, 0x7d, 0x3f, 0x91, 0xd9, 0x8 } }; + +*/ + +unsigned GUID_from_text::read_hex(char c) +{ + if (c>='0' && c<='9') return (unsigned)c - '0'; + else if (c>='a' && c<='f') return 0xa + (unsigned)c - 'a'; + else if (c>='A' && c<='F') return 0xa + (unsigned)c - 'A'; + else return 0; +} + +unsigned GUID_from_text::read_byte(const char * ptr) +{ + return (read_hex(ptr[0])<<4) | read_hex(ptr[1]); +} +unsigned GUID_from_text::read_word(const char * ptr) +{ + return (read_byte(ptr)<<8) | read_byte(ptr+2); +} + +unsigned GUID_from_text::read_dword(const char * ptr) +{ + return (read_word(ptr)<<16) | read_word(ptr+4); +} + +void GUID_from_text::read_bytes(BYTE * out,unsigned num,const char * ptr) +{ + for(;num;num--) + { + *out = read_byte(ptr); + out++;ptr+=2; + } +} + + +GUID_from_text::GUID_from_text(const char * text) +{ + if (*text=='{') text++; + const char * max; + + { + const char * t = strchr(text,'}'); + if (t) max = t; + else max = text + strlen(text); + } + + (GUID)*this = mem_ops::make_null_item(); + + + do { + if (text+8>max) break; + Data1 = read_dword(text); + text += 8; + while(*text=='-') text++; + if (text+4>max) break; + Data2 = read_word(text); + text += 4; + while(*text=='-') text++; + if (text+4>max) break; + Data3 = read_word(text); + text += 4; + while(*text=='-') text++; + if (text+4>max) break; + read_bytes(Data4,2,text); + text += 4; + while(*text=='-') text++; + if (text+12>max) break; + read_bytes(Data4+2,6,text); + } while(false); +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/guid.h b/tools/vio2sf/src/foobar8/pfc/guid.h new file mode 100644 index 000000000..6b176902a --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/guid.h @@ -0,0 +1,17 @@ +#ifndef _PFC_GUID_H_ +#define _PFC_GUID_H_ + + +class GUID_from_text : public GUID +{ + unsigned read_hex(char c); + unsigned read_byte(const char * ptr); + unsigned read_word(const char * ptr); + unsigned read_dword(const char * ptr); + void read_bytes(unsigned char * out,unsigned num,const char * ptr); + +public: + GUID_from_text(const char * text); +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/list.h b/tools/vio2sf/src/foobar8/pfc/list.h new file mode 100644 index 000000000..c6005ba5d --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/list.h @@ -0,0 +1,306 @@ +#ifndef _PFC_LIST_H_ +#define _PFC_LIST_H_ + +template +class mem_block_list_t +{ +private: + mem_block_t buffer; +public: + mem_block_list_t() {buffer.set_mem_logic(mem_block::ALLOC_FAST);} + inline void set_mem_logic(mem_block::mem_logic_t v) {buffer.set_mem_logic(v);} + + unsigned add_items_repeat(T item,unsigned count)//returns first index + { + int idx = buffer.get_size(); + buffer.set_size(idx+count); + unsigned n; + for(n=0;nidx;n--) + buffer[n]=buffer[n-1]; + buffer[idx]=item; + } + + void insert_item_ref(const T & item,unsigned idx) + { + unsigned max = buffer.get_size() + 1; + buffer.set_size(max); + unsigned n; + for(n=max-1;n>idx;n--) + buffer[n]=buffer[n-1]; + buffer[idx]=item; + } + + T remove_by_idx(unsigned idx) + { + T ret = buffer[idx]; + int n; + int max = buffer.get_size(); + for(n=idx+1;n=0); + assert(n=0); + assert(n=0); + assert(n=count) add_items_fromptr(source,num); + else + { + buffer.set_size(count+num); + int n; + for(n=count-1;n>=idx;n--) + { + buffer[n+num]=buffer[n]; + } + for(n=0;n & source) + { + add_items_fromptr(source.buffer,source.get_count()); + } + + void add_items_fromptr(const T* source,unsigned num) + { + unsigned count = get_count(); + buffer.set_size(count+num); + unsigned n; + for(n=0;n & out,const bit_array & mask) + { + unsigned n,count = get_count(); + for_each_bit_array(n,mask,true,0,count) + out.add_item(buffer[n]); + } + + void filter_mask(const bit_array & mask) + { + unsigned n,count = get_count(), total = 0; + + n = total = mask.find(false,0,count); + + if (n=0); + assert(idx0) max = ptr; + else + { + if (index) *index = ptr; + return 1; + } + } + if (index) *index = min; + return 0; + } + + bool bsearch_ref(int (__cdecl *compare )(T const& elem1, T const& elem2 ),T const& item,int * index) const + { + int max = get_count(); + int min = 0; + int ptr; + while(min0) max = ptr; + else + { + if (index) *index = ptr; + return 1; + } + } + if (index) *index = min; + return 0; + } + + + bool bsearch_range(int (__cdecl *compare )(T elem1, T elem2 ),T item,int * index,int * count) const + { + int max = get_count(); + int min = 0; + int ptr; + while(min0) max = ptr; + else + { + int num = 1; + while(ptr>0 && !compare(buffer[ptr-1],item)) {ptr--;num++;} + while(ptr+num0) max = ptr; + else + { + if (index) *index = ptr; + return 1; + } + } + if (index) *index = min; + return 0; + } + + + + + inline void apply_order(const int * order,unsigned count) + { + assert(count==get_count()); + buffer.apply_order(order,count); + } + + void remove_mask(const bit_array & mask) {filter_mask(bit_array_not(mask));} + + void remove_mask(const bool * mask) {remove_mask(bit_array_table(mask,get_count()));} + void filter_mask(const bool * mask) {filter_mask(bit_array_table(mask,get_count()));} + + unsigned add_item_ref(const T& item) + { + unsigned idx = get_count(); + insert_item_ref(item,idx); + return idx; + } + + unsigned add_item(T item)//returns index + { + unsigned idx = get_count(); + insert_item(item,idx); + return idx; + } + + void remove_all() {remove_mask(bit_array_true());} + + void remove_item(T item) + { + unsigned n,max = get_count(); + mem_block_t mask(max); + for(n=0;n=0;} + + inline void swap(unsigned idx1,unsigned idx2) + { + replace_item(idx1,replace_item(idx2,get_item(idx1))); + } + +}; + +#define mem_block_list mem_block_list_t //for compatibility + +#endif //_PFC_LIST_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/mem_block.cpp b/tools/vio2sf/src/foobar8/pfc/mem_block.cpp new file mode 100644 index 000000000..d9d203888 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/mem_block.cpp @@ -0,0 +1,116 @@ +#include "pfc.h" + +#define HAVE_ALLOC_FAST + + +void * mem_block::set_size(UINT new_used) +{ + if (new_used==0) + { +#ifdef HAVE_ALLOC_FAST + if (mem_logic != ALLOC_FAST_DONTGODOWN) +#endif + { + if (data!=0) {free(data);data=0;} + size = 0; + } + } + else + { + UINT new_size; +#ifdef HAVE_ALLOC_FAST + if (mem_logic == ALLOC_FAST || mem_logic == ALLOC_FAST_DONTGODOWN) + { + new_size = size; + if (new_size < 1) new_size = 1; + while(new_size < new_used) new_size <<= 1; + if (mem_logic!=ALLOC_FAST_DONTGODOWN) while(new_size>>1 > new_used) new_size >>= 1; + } + else +#endif + { + new_size = new_used; + } + + if (new_size!=size) + { + if (data==0) + { + data = malloc(new_size); + } + else + { + void * new_data; + new_data = realloc(data,new_size); + if (new_data==0) free(data); + data = new_data; + + } + size = new_size; + } + } + used = new_used; + return data; +} + +void mem_block::prealloc(UINT num) +{ +#ifdef HAVE_ALLOC_FAST + if (size done_block; + unsigned char * done = done_size > PFC_ALLOCA_LIMIT ? done_block.set_size(done_size) : (unsigned char*)alloca(done_size); + memset(done,0,done_size); + unsigned n; + for(n=0;nn); + assert(n +class mem_ops +{ +public: + static void copy(T* dst,const T* src,unsigned count) {memcpy(dst,src,count*sizeof(T));} + static void move(T* dst,const T* src,unsigned count) {memmove(dst,src,count*sizeof(T));} + static void set(T* dst,int val,unsigned count) {memset(dst,val,count*sizeof(T));} + static void setval(T* dst,T val,unsigned count) {for(;count;count--) *(dst++)=val;} + static T* alloc(unsigned count) {return reinterpret_cast(malloc(count * sizeof(T)));} + static T* alloc_zeromem(unsigned count) + { + T* ptr = alloc(count); + if (ptr) set(ptr,0,count); + return ptr; + } + static T* realloc(T* ptr,unsigned count) + {return ptr ? reinterpret_cast(::realloc(reinterpret_cast(ptr),count * sizeof(T))) : alloc(count);} + + static void free(T* ptr) {::free(reinterpret_cast(ptr)); } + inline static T make_null_item() + { + char item[sizeof(T)]; + memset(&item,0,sizeof(T)); + return * reinterpret_cast(&item); + } + inline static void swap(T& item1,T& item2) {T temp; temp=item1; item1=item2; item2=temp;} +}; + +class mem_block +{ +public: + enum mem_logic_t {ALLOC_DEFAULT,ALLOC_FAST,ALLOC_FAST_DONTGODOWN}; +private: + void * data; + unsigned size,used; + mem_logic_t mem_logic; +public: + inline void set_mem_logic(mem_logic_t v) {mem_logic=v;} + inline mem_logic_t get_mem_logic() const {return mem_logic;} + + void prealloc(unsigned size); + + inline mem_block() {data=0;size=0;used=0;mem_logic=ALLOC_DEFAULT;} + inline ~mem_block() {if (data) free(data);} + + inline unsigned get_size() const {return used;} + + inline const void * get_ptr() const {return data;} + inline void * get_ptr() {return data;} + + void * set_size(unsigned new_used); + + inline void * check_size(unsigned new_size) + { + if (used +class mem_block_t //: public mem_block +{ + mem_block theBlock;//msvc7 sucks +public: + mem_block_t() {} + mem_block_t(unsigned s) {theBlock.set_size(s*sizeof(T));} + + inline void set_mem_logic(mem_block::mem_logic_t v) {theBlock.set_mem_logic(v);} + inline mem_block::mem_logic_t get_mem_logic() const {return theBlock.get_mem_logic();} + + inline unsigned get_size() const {return theBlock.get_size()/sizeof(T);} + + inline const T* get_ptr() const {return reinterpret_cast(theBlock.get_ptr());} + inline T* get_ptr() {return reinterpret_cast(theBlock.get_ptr());} + + inline T* set_size(unsigned new_size) {return reinterpret_cast(theBlock.set_size(new_size*sizeof(T)));} + + inline T* check_size(unsigned new_size) {return reinterpret_cast(theBlock.check_size(new_size*sizeof(T)));} + + inline operator const T * () const {return get_ptr();} + inline operator T * () {return get_ptr();} + + inline T* copy(const T* ptr,unsigned size,unsigned start=0) {return reinterpret_cast(theBlock.copy(reinterpret_cast(ptr),size*sizeof(T),start*sizeof(T)));} + inline T* append(const T* ptr,unsigned size) {return reinterpret_cast(theBlock.append(reinterpret_cast(ptr),size*sizeof(T)));} + inline void append(T item) {theBlock.append(reinterpret_cast(&item),sizeof(item));} + + inline void swap(unsigned idx1,unsigned idx2) + { + T * ptr = get_ptr(); + mem_ops::swap(ptr[idx1],ptr[idx2]); + } + + T* set_data(const T* src,unsigned count) + { + return reinterpret_cast(theBlock.set_data(reinterpret_cast(src),count*sizeof(T))); + } + + void operator=(const mem_block_t & src) {set_data(src.get_ptr(),src.get_size());} + + unsigned write_circular(unsigned offset,const T* src,unsigned count) + {//returns new offset + unsigned total = get_size(); + if ((int)offset<0) + { + offset = total - ( (-(int)offset)%total ); + } + else offset%=total; + + if (count>total) + { + src += count - total; + count = total; + } + + while(count>0) + { + unsigned delta = count; + if (delta > total - offset) delta = total - offset; + unsigned n; + for(n=0;n0) + { + unsigned delta = count; + if (delta > total - offset) delta = total - offset; + unsigned n; + for(n=0;n +class mem_block_fastalloc : public mem_block_t +{ +public: + mem_block_fastalloc(unsigned initsize=0) {set_mem_logic(mem_block::ALLOC_FAST_DONTGODOWN);if (initsize) prealloc(initsize);} +}; + +#if 0 + +#define mem_block_aligned_t mem_block_t + +#else + +template +class mem_block_aligned_t +{ + mem_block data; + T * ptr_aligned; +public: + mem_block_aligned_t() {ptr_aligned = 0;} + mem_block_aligned_t(unsigned size) {ptr_aligned = 0;set_size(size);} + + unsigned get_size() const {return data.get_size()/sizeof(T);} + + inline void set_mem_logic(mem_block::mem_logic_t v) {data.set_mem_logic(v);} + inline mem_block::mem_logic_t get_mem_logic() const {return data.get_mem_logic();} + + T * set_size(unsigned size) + { + unsigned size_old = get_size(); + int delta_old = (unsigned)ptr_aligned - (unsigned)data.get_ptr(); + unsigned ptr = (unsigned)data.set_size( (size+1) * sizeof(T) - 1), old_ptr = ptr; + ptr += sizeof(T) - 1; + ptr -= ptr % sizeof(T); + int delta_new = ptr - old_ptr; + if (delta_new != delta_old) + { + unsigned to_move = size_old > size ? size : size_old; + memmove((char*)ptr,(char*)ptr - (delta_new-delta_old),to_move * sizeof(T)); + } + ptr_aligned = (T*)ptr; + return ptr_aligned; + } + + T* check_size(unsigned size) + { + return size > get_size() ? set_size(size) : get_ptr(); + } + + void fill(T val) + { + unsigned n = get_size(); + T * dst = get_ptr(); + for(;n;n--) *(dst++) = val; + } + + inline void zeromemory() {data.zeromemory();} + inline const T * get_ptr() const {return ptr_aligned;} + inline T * get_ptr() {return ptr_aligned;} + inline operator const T * () const {return get_ptr();} + inline operator T * () {return get_ptr();} +}; +#endif + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/mem_block_mgr.h b/tools/vio2sf/src/foobar8/pfc/mem_block_mgr.h new file mode 100644 index 000000000..daaead013 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/mem_block_mgr.h @@ -0,0 +1,71 @@ +#ifndef _MEM_BLOCK_MGR_H_ +#define _MEM_BLOCK_MGR_H_ + +#error DEPRECATED + + +template +class mem_block_manager +{ + struct entry + { + mem_block_t block; + bool used; + }; + ptr_list_t list; +public: + T * copy(const T* ptr,int size) + { + int n; + int found_size = -1,found_index = -1; + for(n=0;nused) + { + int block_size = list[n]->block.get_size(); + if (found_size<0) + { + found_index=n; found_size = block_size; + } + else if (found_sizefound_size) + { + found_index=n; found_size = block_size; + } + } + else if (found_size>size) + { + if (block_size>=size && block_size=0) + { + list[found_index]->used = true; + return list[found_index]->block.copy(ptr,size); + } + entry * new_entry = new entry; + new_entry->used = true; + list.add_item(new_entry); + return new_entry->block.copy(ptr,size); + } + + void mark_as_free() + { + int n; + for(n=0;nused = false; + } + } + + ~mem_block_manager() {list.delete_all();} +}; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/other.cpp b/tools/vio2sf/src/foobar8/pfc/other.cpp new file mode 100644 index 000000000..76f94cd53 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/other.cpp @@ -0,0 +1,30 @@ +#include "pfc.h" + +void order_helper::g_swap(int * data,unsigned ptr1,unsigned ptr2) +{ + int temp = data[ptr1]; + data[ptr1] = data[ptr2]; + data[ptr2] = temp; +} + + +int order_helper::g_find_reverse(const int * order,int val) +{ + int prev = val, next = order[val]; + while(next != val) + { + prev = next; + next = order[next]; + } + return prev; +} + + +void order_helper::g_reverse(int * order,unsigned base,unsigned count) +{ + unsigned max = count>>1; + unsigned n; + unsigned base2 = base+count-1; + for(n=0;n +class vartoggle_t +{ + T oldval; + T & var; +public: + vartoggle_t(T & p_var,T val) : var(p_var) + { + oldval = var; + var = val; + } + ~vartoggle_t() {var = oldval;} +}; + +typedef vartoggle_t booltoggle; + +class order_helper +{ + mem_block_t data; +public: + explicit order_helper(unsigned size) : data(size) + { + unsigned n; + for(n=0;n +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=pfc - 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 "pfc.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 "pfc.mak" CFG="pfc - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pfc - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "pfc - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "pfc - Win32 Release ANSI" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pfc - 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_unicode" +# PROP Intermediate_Dir "Release_unicode" +# PROP Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "pfc" /D "UNICODE" /D "_UNICODE" /Yu"pfc.h" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "pfc - 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_unicode" +# PROP Intermediate_Dir "Debug_unicode" +# PROP Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "pfc" /D "UNICODE" /D "_UNICODE" /Yu"pfc.h" /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "pfc - Win32 Release ANSI" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "pfc___Win32_Release_ANSI0" +# PROP BASE Intermediate_Dir "pfc___Win32_Release_ANSI0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_ANSI" +# PROP Intermediate_Dir "Release_ANSI" +# PROP Target_Dir "" +F90=df.exe +MTL=midl.exe +# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "pfc" /D "UNICODE" /D "_UNICODE" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "pfc" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "pfc - Win32 Release" +# Name "pfc - Win32 Debug" +# Name "pfc - Win32 Release ANSI" +# Begin Source File + +SOURCE=.\array.h +# End Source File +# Begin Source File + +SOURCE=.\bit_array.h +# End Source File +# Begin Source File + +SOURCE=.\byte_order_helper.cpp +# End Source File +# Begin Source File + +SOURCE=.\byte_order_helper.h +# End Source File +# Begin Source File + +SOURCE=.\cfg_memblock.h +# End Source File +# Begin Source File + +SOURCE=.\cfg_var.cpp +# End Source File +# Begin Source File + +SOURCE=.\cfg_var.h +# End Source File +# Begin Source File + +SOURCE=.\chainlist.h +# End Source File +# Begin Source File + +SOURCE=.\critsec.h +# End Source File +# Begin Source File + +SOURCE=.\guid.cpp +# End Source File +# Begin Source File + +SOURCE=.\guid.h +# End Source File +# Begin Source File + +SOURCE=.\list.h +# End Source File +# Begin Source File + +SOURCE=.\mem_block.cpp +# End Source File +# Begin Source File + +SOURCE=.\mem_block.h +# End Source File +# Begin Source File + +SOURCE=.\other.cpp +# End Source File +# Begin Source File + +SOURCE=.\other.h +# End Source File +# Begin Source File + +SOURCE=.\pfc.h +# End Source File +# Begin Source File + +SOURCE=.\profiler.cpp +# End Source File +# Begin Source File + +SOURCE=.\profiler.h +# End Source File +# Begin Source File + +SOURCE=.\ptr_list.h +# End Source File +# Begin Source File + +SOURCE=.\stdafx.cpp + +!IF "$(CFG)" == "pfc - Win32 Release" + +# ADD CPP /Yc"pfc.h" + +!ELSEIF "$(CFG)" == "pfc - Win32 Debug" + +# ADD CPP /Yc + +!ELSEIF "$(CFG)" == "pfc - Win32 Release ANSI" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\string.cpp +# End Source File +# Begin Source File + +SOURCE=.\string.h +# End Source File +# Begin Source File + +SOURCE=.\utf8.cpp +# End Source File +# End Target +# End Project diff --git a/tools/vio2sf/src/foobar8/pfc/pfc.h b/tools/vio2sf/src/foobar8/pfc/pfc.h new file mode 100644 index 000000000..ece76cb95 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/pfc.h @@ -0,0 +1,80 @@ +#ifndef ___PFC_H___ +#define ___PFC_H___ + +#ifdef WIN32 +#ifndef STRICT +#define STRICT +#endif +#include +#endif + +#ifndef _MSC_VER +typedef long long __int64; +#endif + +#ifndef QWORD +typedef unsigned __int64 QWORD; +#endif + +#ifndef DWORD +typedef unsigned long DWORD; +#endif + +#ifndef WORD +typedef unsigned short WORD; +#endif + +#ifndef BYTE +typedef unsigned char BYTE; +#endif + +#define PFC_ALLOCA_LIMIT (4096) + +#define INDEX_INVALID ((unsigned)(-1)) + +#include + +#include +#include + +#include + +#include +#include + +#ifdef _MSC_VER + +#define NOVTABLE _declspec(novtable) + +#ifdef _DEBUG +#define ASSUME(X) assert(X) +#else +#define ASSUME(X) __assume(X) +#endif + +#else + +#define NOVTABLE + +#define ASSUME(X) assert(X) + +#endif + + +#define tabsize(x) (sizeof(x)/sizeof(*x)) + +#include "bit_array.h" +//#include "critsec.h" +#include "mem_block.h" +#include "list.h" +#include "ptr_list.h" +#include "string.h" +#include "profiler.h" +#include "cfg_var.h" +#include "cfg_memblock.h" +#include "guid.h" +#include "byte_order_helper.h" +#include "other.h" +#include "chainlist.h" +#include "array.h" +#endif //___PFC_H___ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/pfc.vcproj b/tools/vio2sf/src/foobar8/pfc/pfc.vcproj new file mode 100644 index 000000000..9df78ff5f --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/pfc.vcproj @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vio2sf/src/foobar8/pfc/profiler.cpp b/tools/vio2sf/src/foobar8/pfc/profiler.cpp new file mode 100644 index 000000000..ba9effce3 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/profiler.cpp @@ -0,0 +1,11 @@ +#include "pfc.h" + + +__declspec(naked) __int64 profiler_local::get_timestamp() +{ + __asm + { + rdtsc + ret + } +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/profiler.h b/tools/vio2sf/src/foobar8/pfc/profiler.h new file mode 100644 index 000000000..ab4414147 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/profiler.h @@ -0,0 +1,57 @@ +#ifndef _PFC_PROFILER_H_ +#define _PFC_PROFILER_H_ + +class profiler_static +{ +private: + const char * name; + __int64 total_time,num_called; + +public: + profiler_static(const char * p_name) + { + name = p_name; + total_time = 0; + num_called = 0; + } + ~profiler_static() + { + char blah[256]; + char total_time_text[128]; + char num_text[128]; + _i64toa(total_time,total_time_text,10); + _i64toa(num_called,num_text,10); + sprintf(blah,"profiler: %s - %s cycles (executed %s times)\n",name,total_time_text,num_text); + OutputDebugStringA(blah); + } + void add_time(__int64 delta) {total_time+=delta;num_called++;} +}; + +class profiler_local +{ +private: + static __int64 get_timestamp(); + __int64 start; + profiler_static * owner; +public: + profiler_local(profiler_static * p_owner) + { + owner = p_owner; + start = get_timestamp(); + } + ~profiler_local() + { + __int64 end = get_timestamp(); + owner->add_time(end-start); + } + +}; + +#define profiler(name) \ + static profiler_static profiler_static_##name(#name); \ + profiler_local profiler_local_##name(&profiler_static_##name); + + + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/ptr_list.cpp b/tools/vio2sf/src/foobar8/pfc/ptr_list.cpp new file mode 100644 index 000000000..c91ec989a --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/ptr_list.cpp @@ -0,0 +1,3 @@ +#include "pfc.h" + +#error verboten diff --git a/tools/vio2sf/src/foobar8/pfc/stdafx.cpp b/tools/vio2sf/src/foobar8/pfc/stdafx.cpp new file mode 100644 index 000000000..72044fc8b --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/stdafx.cpp @@ -0,0 +1,2 @@ +//cpp used to generate precompiled header +#include "pfc.h" \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/string.cpp b/tools/vio2sf/src/foobar8/pfc/string.cpp new file mode 100644 index 000000000..b2f905866 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/string.cpp @@ -0,0 +1,615 @@ +#include "pfc.h" + +#ifdef WIN32 +#define STRICT +#include +#include +#endif + + +void string_base::add_char(unsigned c) +{ + char temp[8]; + unsigned len = utf8_encode_char(c,temp); + if (len>0) add_string(temp,len); +} + +void string_base::skip_trailing_char(unsigned skip) +{ + const char * str = get_ptr(); + unsigned ptr,trunc; + bool need_trunc = false; + for(ptr=0;str[ptr];) + { + unsigned c; + unsigned delta = utf8_decode_char(str+ptr,&c); + if (delta==0) break; + if (c==skip) + { + need_trunc = true; + trunc = ptr; + } + else + { + need_trunc = false; + } + ptr += delta; + } + if (need_trunc) truncate(trunc); +} + +string_print_time::string_print_time(__int64 length) +{ + if (length<0) length=0; + char * out = buffer; + int weeks,days,hours,minutes,seconds; + + weeks = (int)( ( length / (60*60*24*7) ) ); + days = (int)( ( length / (60*60*24) ) % 7 ); + hours = (int) ( ( length / (60 * 60) ) % 24); + minutes = (int) ( ( length / (60 ) ) % 60 ); + seconds = (int) ( ( length ) % 60 ); + + if (weeks) + { + out += sprintf(out,"%uwk ",weeks); + } + if (days || weeks) + { + out += sprintf(out,"%ud ",days); + } + if (hours || days || weeks) + { + out += sprintf(out,"%u:%02u:%02u",hours,minutes,seconds); + } + else out += sprintf(out,"%u:%02u",minutes,seconds); +} + +int strcmp_partial(const char * s1,const char * s2) +{ + while(*s2) + { + if (*s1<*s2) return -1; + else if (*s1>*s2) return 1; + s1++; + s2++; + } + return 0; +} + +void string_base::add_float(double val,unsigned digits) +{ + char temp[64]; + _gcvt(val,digits,temp); + add_string(temp); +} + +void string_base::add_int(signed __int64 val,unsigned base) +{ + char temp[64]; + _i64toa(val,temp,base); + add_string(temp); +} + +void string_base::add_uint(unsigned __int64 val,unsigned base) +{ + char temp[64]; + _ui64toa(val,temp,base); + add_string(temp); +} + +bool is_path_separator(unsigned c) +{ + return c=='\\' || c=='/' || c=='|' || c==':'; +} + +bool is_path_bad_char(unsigned c) +{ +#ifdef WIN32 + return c=='\\' || c=='/' || c=='|' || c==':' || c=='*' || c=='?' || c=='\"' || c=='>' || c=='<'; +#else +#error portme +#endif +} + + +void string_printf::g_run(string_base & out,const char * fmt,va_list list) +{ + out.reset(); + while(*fmt) + { + if (*fmt=='%') + { + fmt++; + if (*fmt=='%') + { + out.add_char('%'); + fmt++; + } + else + { + bool force_sign = false; + if (*fmt=='+') + { + force_sign = true; + fmt++; + } + char padchar = (*fmt == '0') ? '0' : ' '; + int pad = 0; + while(*fmt>='0' && *fmt<='9') + { + pad = pad * 10 + (*fmt - '0'); + fmt++; + } + + if (*fmt=='s' || *fmt=='S') + { + const char * ptr = va_arg(list,const char*); + int len = strlen(ptr); + if (pad>len) out.add_chars(padchar,pad-len); + out.add_string(ptr); + fmt++; + + } + else if (*fmt=='i' || *fmt=='I' || *fmt=='d' || *fmt=='D') + { + char temp[8*sizeof(int)]; + int val = va_arg(list,int); + if (force_sign && val>0) out.add_char('+'); + itoa(val,temp,10); + int len = strlen(temp); + if (pad>len) out.add_chars(padchar,pad-len); + out.add_string(temp); + fmt++; + } + else if (*fmt=='u' || *fmt=='U') + { + char temp[8*sizeof(int)]; + int val = va_arg(list,int); + if (force_sign && val>0) out.add_char('+'); + _ultoa(val,temp,10); + int len = strlen(temp); + if (pad>len) out.add_chars(padchar,pad-len); + out.add_string(temp); + fmt++; + } + else if (*fmt=='x' || *fmt=='X') + { + char temp[8*sizeof(int)]; + int val = va_arg(list,int); + if (force_sign && val>0) out.add_char('+'); + _ultoa(val,temp,16); + if (*fmt=='X') + { + char * t = temp; + while(*t) + { + if (*t>='a' && *t<='z') + *t += 'A' - 'a'; + t++; + } + } + int len = strlen(temp); + if (pad>len) out.add_chars(padchar,pad-len); + out.add_string(temp); + fmt++; + } + else if (*fmt=='c' || *fmt=='C') + { + out.add_char(va_arg(list,char)); + fmt++; + } + } + } + else + { + out.add_char(*(fmt++)); + } + } +} + +string_printf::string_printf(const char * fmt,...) +{ + va_list list; + va_start(list,fmt); + run(fmt,list); + va_end(list); +} + + + +unsigned strlen_max(const char * ptr,unsigned max) +{ + if (ptr==0) return 0; + unsigned int n = 0; + while(ptr[n] && n=0;n--) + { + if (data[n]==c) return n; + } + return -1; +} + +int string8::find_first(const char * str,int start) +{ + unsigned n; + if (start<0) start=0; + for(n=start;n=0;n--) + { + if (!strcmp_partial(data.get_ptr()+n,str)) return n; + } + return -1; +} + +unsigned string8::g_scan_filename(const char * ptr) +{ + int n; + int _used = strlen(ptr); + for(n=_used-1;n>=0;n--) + { + if (is_path_separator(ptr[n])) return n+1; + } + return 0; +} + +unsigned string8::scan_filename() +{ + int n; + for(n=used-1;n>=0;n--) + { + if (is_path_separator(data[n])) return n+1; + } + return 0; +} + +void string8::fix_filename_chars(char def,char leave)//replace "bad" characters, leave can be used to keep eg. path separators +{ + unsigned n; + for(n=0;nused) first = used; + if (first+count>used) count = used-first; + if (count>0) + { + unsigned n; + for(n=first+count;n<=used;n++) + data[n-count]=data[n]; + used -= count; + makespace(used+1); + } +} + +//slow +void string8::insert_chars(unsigned first,const char * src, unsigned count) +{ + if (first > used) first = used; + + makespace(used+count+1); + unsigned n; + for(n=used;(int)n>=(int)first;n--) + data[n+count] = data[n]; + for(n=0;nfn) set_string_n(fn,dot-fn); + else set_string(fn); +} + +string_filename_ext::string_filename_ext(const char * fn) +{ + fn += string8::g_scan_filename(fn); + const char * ptr = fn; + while(*ptr && *ptr!='?') ptr++; + set_string_n(fn,ptr-fn); +} + +string_extension::string_extension(const char * src) +{ + buffer[0]=0; + const char * start = src + string8::g_scan_filename(src); + const char * end = start + strlen(start); + const char * ptr = end-1; + while(ptr>start && *ptr!='.') + { + if (*ptr=='?') end=ptr; + ptr--; + } + + if (ptr>=start && *ptr=='.') + { + ptr++; + unsigned len = end-ptr; + if (len='0' && *src<='9') + { + int d = *src - '0'; + val = val * 10 + d; + if (got_dot) div--; + src++; + } + else if (*src=='.' || *src==',') + { + if (got_dot) break; + got_dot = true; + src++; + } + else if (*src=='E' || *src=='e') + { + src++; + div += atoi(src); + break; + } + else break; + } + if (neg) val = -val; + return (double) val * pow(10.0,(double)div); +} + +bool string8::limit_length(unsigned length_in_chars,const char * append) +{ + bool rv = false; + const char * base = get_ptr(), * ptr = base; + while(length_in_chars && utf8_advance(ptr)) length_in_chars--; + if (length_in_chars==0) + { + truncate(ptr-base); + add_string(append); + rv = true; + } + return rv; +} + +void string_base::convert_to_lower_ascii(const char * src,char replace) +{ + reset(); + assert(replace>0); + while(*src) + { + unsigned c; + unsigned delta = utf8_decode_char(src,&c); + if (delta==0) {c = replace; delta = 1;} + else if (c>=0x80) c = replace; + add_byte((char)c); + src += delta; + } +} + +void convert_to_lower_ascii(const char * src,unsigned max,char * out,char replace) +{ + unsigned ptr = 0; + assert(replace>0); + while(src[ptr] && ptr=0x80) c = replace; + *(out++) = (char)c; + ptr += delta; + } + *out = 0; +} + +string_list_nulldelimited::string_list_nulldelimited() +{ + reset(); +} + +void string_list_nulldelimited::add_string(const char * src) +{ + unsigned src_len = strlen(src) + 1; + data.copy(src,src_len,len); + len += src_len; + data.copy("",1,len); +} + +void string_list_nulldelimited::add_string_multi(const char * src) +{ + unsigned src_len = 0; + while(src[src_len]) + { + src_len += strlen(src+src_len) + 1; + } + data.copy(src,src_len,len); + len += src_len; + data.copy("",1,len); +} + + +void string_list_nulldelimited::reset() +{ + len = 0; + data.copy("\0",2,len); +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/string.h b/tools/vio2sf/src/foobar8/pfc/string.h new file mode 100644 index 000000000..c3a1f3131 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/string.h @@ -0,0 +1,595 @@ +#ifndef _PFC_STRING_H_ +#define _PFC_STRING_H_ + +#ifndef WCHAR +typedef unsigned short WCHAR; +#endif + +bool is_path_separator(unsigned c); +bool is_path_bad_char(unsigned c); +bool is_valid_utf8(const char * param); +bool is_lower_ascii(const char * param); +bool has_path_bad_chars(const char * param); +void recover_invalid_utf8(const char * src,char * out,unsigned replace);//out must be enough to hold strlen(char) + 1, or appropiately bigger if replace needs multiple chars +void convert_to_lower_ascii(const char * src,unsigned max,char * out,char replace = '?');//out should be at least strlen(src)+1 long + +class NOVTABLE string_base //cross-dll safe string for returing strings from api functions etc +{//all char* are UTF-8 unless local comments state otherwise +protected: + string_base() {} + ~string_base() {} +public: + virtual const char * get_ptr() const = 0; + virtual void add_string(const char * ptr,unsigned len=-1)=0;//stops adding new chars if encounters null before len + virtual void set_string(const char * ptr,unsigned len=-1) {reset();add_string(ptr,len);} + virtual void truncate(unsigned len)=0; + virtual unsigned length() const {return strlen(get_ptr());} + + inline operator const char * () const {return get_ptr();} + + + inline void reset() {truncate(0);} + + //for compatibility + inline void add_string_n(const char * ptr,unsigned len) {add_string(ptr,len);} + inline void set_string_n(const char * ptr,unsigned len) {set_string(ptr,len);} + + inline void add_byte(char c) {add_string_n(&c,1);} + inline bool is_empty() const {return *get_ptr()==0;} + + void add_char(unsigned c);//adds unicode char to the string + void skip_trailing_char(unsigned c = ' '); + + inline void add_chars(unsigned c,unsigned count) {for(;count;count--) add_char(c);} + + + void add_int(signed __int64 val,unsigned base = 10); + void add_uint(unsigned __int64 val,unsigned base = 10); + void add_float(double val,unsigned digits); + +/* void add_string_lower(const char * src,unsigned len = -1); + void add_string_upper(const char * src,unsigned len = -1); + inline void set_string_lower(const char * src,unsigned len = -1) {reset();add_string_lower(src,len);} + inline void set_string_upper(const char * src,unsigned len = -1) {reset();add_string_upper(src,len);} + + void to_lower(); + void to_upper(); +*/ + void add_string_ansi(const char * src,unsigned len = -1); //converts from ansi to utf8 + void set_string_ansi(const char * src,unsigned len = -1) {reset();add_string_ansi(src,len);} + void add_string_utf16(const WCHAR * src,unsigned len = -1);//converts from utf16 (widechar) to utf8 + void set_string_utf16(const WCHAR * src,unsigned len = -1) {reset();add_string_utf16(src,len);} + + bool is_valid_utf8() {return ::is_valid_utf8(get_ptr());} + + void convert_to_lower_ascii(const char * src,char replace = '?'); + + + + inline const char * operator = (const char * src) {set_string(src);return get_ptr();} + inline const char * operator += (const char * src) {add_string(src);return get_ptr();} + inline const char * operator = (const string_base & src) {set_string(src);return get_ptr();} +}; + +class string8 : public string_base +{ +protected: + mem_block_t data; + unsigned used; + + inline void makespace(unsigned s) + { + unsigned old_size = data.get_size(); + if (old_size < s) + data.set_size(s+16); + else if (old_size > s + 32) + data.set_size(s); + } + +public: + inline const char * operator = (const char * src) {set_string(src);return get_ptr();} + inline const char * operator += (const char * src) {add_string(src);return get_ptr();} + inline operator const char * () const {return get_ptr();} + inline const char * operator = (const string8 & src) {set_string(src);return get_ptr();} + + string8() {used=0;} + string8(const char * src) {used=0;set_string(src);} + string8(const char * src,unsigned num) {used=0;set_string_n(src,num);} + string8(const string8 & src) {used=0;set_string(src);} + + void set_mem_logic(mem_block::mem_logic_t v) {data.set_mem_logic(v);} + int get_mem_logic() const {return data.get_mem_logic();} + void prealloc(unsigned s) {s++;if (s>used) makespace(s);} + + const char * get_ptr() const + { + return used > 0 ? data.get_ptr() : ""; + } + + virtual void add_string(const char * ptr,unsigned len = -1); + virtual void set_string(const char * ptr,unsigned len = -1); + + virtual void truncate(unsigned len) + { + if (used>len) {used=len;data[len]=0;makespace(used+1);} + } + + virtual unsigned length() const {return used;} + +// ~string8() {} + + void set_char(unsigned offset,char c); + int find_first(char c,int start=0); //return -1 if not found + int find_last(char c,int start = -1); + int find_first(const char * str,int start = 0); + int find_last(const char * str,int start = -1); +// unsigned replace_string(const char * s1,unsigned len1,const char * s2,unsigned len2,bool casesens = true,unsigned start = 0);//len1/len2 can be -1 +// unsigned replace_byte(char c1,char c2,unsigned start = 0); + unsigned replace_char(unsigned c1,unsigned c2,unsigned start = 0); +// inline unsigned replace_byte_from(unsigned start,char c1,char c2) {return replace_byte(c1,c2,start);} +// inline unsigned replace_char_from(unsigned start,unsigned c1,unsigned c2) {return replace_char(c1,c2,start);} + static unsigned g_scan_filename(const char * ptr); + unsigned scan_filename(); + void fix_filename_chars(char def = '_',char leave=0);//replace "bad" characters, leave can be used to keep eg. path separators + void fix_dir_separator(char c); + void _xor(char x);//renamed from "xor" to keep weird compilers happy + void remove_chars(unsigned first,unsigned count); //slow + void insert_chars(unsigned first,const char * src, unsigned count);//slow + void insert_chars(unsigned first,const char * src); + bool truncate_eol(unsigned start = 0); + bool fix_eol(const char * append = " (...)",unsigned start = 0); + bool limit_length(unsigned length_in_chars,const char * append = " (...)"); + + //for string_buffer class + inline char * buffer_get(unsigned n) + { + makespace(n+1); + data.zeromemory(); + return data; + } + + inline void buffer_done() + { + used=strlen(data); + makespace(used+1); + } + + inline void force_reset() {used=0;data.force_reset();} + +}; + +class string8_fastalloc : public string8 +{ +public: + explicit string8_fastalloc(unsigned p_prealloc = 0) {set_mem_logic(mem_block::ALLOC_FAST_DONTGODOWN);if (p_prealloc) prealloc(p_prealloc);} + inline const char * operator=(const char * src) {set_string(src);return get_ptr();} + inline const char * operator+=(const char * src) {add_string(src);return get_ptr();} +}; + +class string_buffer +{ +private: + string8 * owner; + char * data; +public: + explicit string_buffer(string8 & s,unsigned siz) {owner=&s;data=s.buffer_get(siz);} + ~string_buffer() {owner->buffer_done();} + operator char* () {return data;} +}; + +class string_printf : public string8_fastalloc +{ +public: + static void g_run(string_base & out,const char * fmt,va_list list); + inline void run(const char * fmt,va_list list) {g_run(*this,fmt,list);} + + explicit string_printf(const char * fmt,...); +}; + +class string_printf_va : public string8_fastalloc +{ +public: + explicit string_printf_va(const char * fmt,va_list list) {string_printf::g_run(*this,fmt,list);} +}; + + +class string_print_time +{ +protected: + char buffer[128]; +public: + string_print_time(__int64 s); + operator const char * () const {return buffer;} +}; + + +class string_print_time_ex : private string_print_time +{ +public: + string_print_time_ex(double s,unsigned extra = 3) : string_print_time((__int64)s) + { + if (extra>0) + { + unsigned mul = 1, n; + for(n=0;n +class string_convert_base +{ +protected: + T * ptr; + inline void alloc(unsigned size) {ptr = mem_ops::alloc(size);} + inline ~string_convert_base() {mem_ops::free(ptr);} +public: + inline operator const T * () const {return ptr;} + inline const T * get_ptr() const {return ptr;} + + inline unsigned length() + { + unsigned ret = 0; + const T* p = ptr; + while(*p) {ret++;p++;} + return ret; + } +}; + +class string_utf8_from_utf16 : public string_convert_base +{ +public: + explicit string_utf8_from_utf16(const WCHAR * src,unsigned len = -1) + { + len = wcslen_max(src,len); + alloc(estimate_utf16_to_utf8(src,len)); + convert_utf16_to_utf8(src,ptr,len); + } +}; + +class string_utf16_from_utf8 : public string_convert_base +{ +public: + explicit string_utf16_from_utf8(const char * src,unsigned len = -1) + { + len = strlen_max(src,len); + alloc(estimate_utf8_to_utf16(src,len)); + convert_utf8_to_utf16(src,ptr,len); + } +}; + +class string_ansi_from_utf16 : public string_convert_base +{ +public: + explicit string_ansi_from_utf16(const WCHAR * src,unsigned len = -1) + { + len = wcslen_max(src,len); + alloc(estimate_utf16_to_ansi(src,len)); + convert_utf16_to_ansi(src,ptr,len); + } +}; + +class string_utf16_from_ansi : public string_convert_base +{ +public: + explicit string_utf16_from_ansi(const char * src,unsigned len = -1) + { + len = strlen_max(src,len); + alloc(estimate_ansi_to_utf16(src,len)); + convert_ansi_to_utf16(src,ptr,len); + } +}; + +class string_utf8_from_ansi : public string_convert_base +{ +public: + explicit string_utf8_from_ansi(const char * src,unsigned len = -1) + { + len = strlen_max(src,len); + alloc(estimate_ansi_to_utf8(src,len)); + convert_ansi_to_utf8(src,ptr,len); + } +}; + +class string_ansi_from_utf8 : public string_convert_base +{ +public: + explicit string_ansi_from_utf8(const char * src,unsigned len = -1) + { + len = strlen_max(src,len); + alloc(estimate_utf8_to_ansi(src,len)); + convert_utf8_to_ansi(src,ptr,len); + } +}; + +class string_ascii_from_utf8 : public string_convert_base +{ +public: + explicit string_ascii_from_utf8(const char * src,unsigned len = -1) + { + len = strlen_max(src,len); + alloc(len+1); + convert_to_lower_ascii(src,len,ptr,'?'); + } +}; + +#define string_wide_from_utf8 string_utf16_from_utf8 +#define string_utf8_from_wide string_utf8_from_utf16 +#define string_wide_from_ansi string_utf16_from_ansi +#define string_ansi_from_wide string_ansi_from_utf16 + +#ifdef UNICODE +#define string_os_from_utf8 string_wide_from_utf8 +#define string_utf8_from_os string_utf8_from_wide +#define _TX(X) L##X +#define estimate_utf8_to_os estimate_utf8_to_utf16 +#define estimate_os_to_utf8 estimate_utf16_to_utf8 +#define convert_utf8_to_os convert_utf8_to_utf16 +#define convert_os_to_utf8 convert_utf16_to_utf8 +#define add_string_os add_string_utf16 +#define set_string_os set_string_utf16 +#else +#define string_os_from_utf8 string_ansi_from_utf8 +#define string_utf8_from_os string_utf8_from_ansi +#define _TX(X) X +#define estimate_utf8_to_os estimate_utf8_to_ansi +#define estimate_os_to_utf8 estimate_ansi_to_utf8 +#define convert_utf8_to_os convert_utf8_to_ansi +#define convert_os_to_utf8 convert_ansi_to_utf8 +#define add_string_os add_string_ansi +#define set_string_os set_string_ansi +#endif + + +int strcmp_partial(const char * s1,const char * s2); +int skip_utf8_chars(const char * ptr,int count); +char * strdup_n(const char * src,unsigned len); + +unsigned utf8_get_char(const char * src); + +inline bool utf8_advance(const char * & var) +{ + UINT delta = utf8_char_len(var); + var += delta; + return delta>0; +} + +inline bool utf8_advance(char * & var) +{ + UINT delta = utf8_char_len(var); + var += delta; + return delta>0; +} + +inline const char * utf8_char_next(const char * src) {return src + utf8_char_len(src);} +inline char * utf8_char_next(char * src) {return src + utf8_char_len(src);} + + +#define filename_cmp(s1,s2) stricmp_utf8(s1,s2) //deprecated + +template +class string_simple_t//simplified string class, less efficient but smaller; could make it derive from string_base but it wouldn't be so light anymore (vtable) +{ +private: + T * ptr; + + void do_realloc(unsigned size) + { + ptr = mem_ops::realloc(ptr,size); + } + + static unsigned t_strlen(const T* src,unsigned max = -1) + { + unsigned ret; + for(ret=0;src[ret] && ret::alloc(t_strlen(src,max)+1); + if (ret) t_strcpy(ret,src,max); + return ret; + } + + inline static void t_memcpy(T* dst,const T* src,unsigned len) {mem_ops::copy(dst,src,len);} + +public: + inline const T * get_ptr() const {return ptr ? ptr : reinterpret_cast("\0\0\0\0");} + inline operator const T * () const {return get_ptr();} + inline string_simple_t(const T * param) {ptr = t_strdup(param);} + inline string_simple_t(const T * param,unsigned len) {ptr = t_strdup(param,len);} + inline string_simple_t() {ptr=0;} + inline string_simple_t(__int64 val) + { + T temp[64]; + if (sizeof(T)==1) + { + _i64toa(val,reinterpret_cast(&temp),10); + } + else if (sizeof(T)==2) + { + _i64tow(val,reinterpret_cast(&temp),10); + } + else + { + ASSUME(0); + } + ptr = t_strdup(temp); + } + inline ~string_simple_t() {if (ptr) mem_ops::free(ptr);} + inline const T * operator = (const T * param) {set_string(param);return get_ptr();} + inline const T * operator = (const string_simple_t & param) {set_string(param);return get_ptr();} + inline const T * operator += (const T * src) {add_string(src);return get_ptr();} + + inline string_simple(const string_simple_t & param) {ptr = t_strdup(param);} + inline void reset() {if (ptr) {mem_ops::free(ptr);ptr=0;}} + inline bool is_empty() {return !ptr || !*ptr;} + inline unsigned length() {return t_strlen(get_ptr());} + + void add_string(const T * param,unsigned len = -1) + { + len = t_strlen(param,len); + if (len>0) + { + unsigned old_len = length(); + do_realloc(old_len + len + 1); + t_memcpy(ptr+old_len,param,len); + ptr[old_len+len]=0; + } + } + + void set_string(const T * param,unsigned len = -1) + { + len = t_strlen(param,len); + if (len>0) + { + do_realloc(len + 1);//will malloc if old ptr was null + t_memcpy(ptr,param,len); + ptr[len]=0; + } + else reset(); + } + + //for compatibility + inline void set_string_n(const T * param,unsigned len) {set_string(param,len);} + inline void add_string_n(const T * param,unsigned len) {add_string(param,len);} + + void truncate(unsigned len) + { + if (len +#define w_string_simple string_simple_t +#define t_string_simple string_simple_t + +class string_filename : public string_simple +{ +public: + explicit string_filename(const char * fn); +}; + +class string_filename_ext : public string_simple +{ +public: + explicit string_filename_ext(const char * fn); +}; + +class string_extension +{ + char buffer[32]; +public: + inline const char * get_ptr() const {return buffer;} + inline unsigned length() const {return strlen(buffer);} + inline operator const char * () const {return buffer;} + explicit string_extension(const char * src); +}; + +#define string_extension_8 string_extension + +template +class string_buffer_t +{ +private: + string_simple_t & owner; + mem_block_t data; + unsigned size; +public: + string_buffer_t(string_simple_t & p_owner,unsigned p_size) : owner(p_owner), data(p_size+1), size(size) {data.zeromemory();} + operator T* () {return data.get_ptr();} + ~string_buffer_t() {owner.set_string(data,size);} +}; + +#define a_string_buffer string_buffer_t +#define t_string_buffer string_buffer_t +#define w_string_buffer string_buffer_t + +class make_string_n //trick for passing truncated char* to api that takes null-terminated strings, needs to temporarily modify string data +{ + char * ptr, *ptr0, old; +public: + inline explicit make_string_n(char * src,unsigned len) + { + ptr = src; ptr0 = src+len; + old = *ptr0; + *ptr0 = 0; + } + inline ~make_string_n() {*ptr0 = old;} + inline const char * get_ptr() const {return ptr;} + inline operator const char * () const {return ptr;} +}; + +void pfc_float_to_string(char * out,double val,unsigned precision,bool force_sign = false);//doesnt add E+X etc, has internal range limits, useful for storing float numbers as strings without having to bother with international coma/dot settings BS +double pfc_string_to_float(const char * src); + +class string_list_nulldelimited +{ + mem_block_fastalloc data; + unsigned len; +public: + string_list_nulldelimited(); + inline const char * get_ptr() const {return data;} + inline operator const char * () const {return data;} + void add_string(const char *); + void add_string_multi(const char *); + void reset(); +}; + +#endif //_PFC_STRING_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/pfc/utf8.cpp b/tools/vio2sf/src/foobar8/pfc/utf8.cpp new file mode 100644 index 000000000..6ffa429f5 --- /dev/null +++ b/tools/vio2sf/src/foobar8/pfc/utf8.cpp @@ -0,0 +1,432 @@ +#include "pfc.h" + +#include + +//utf8 stuff + +#ifndef BYTE +typedef unsigned char BYTE; +#endif + +#ifndef UINT +typedef unsigned int UINT; +#endif + +static const BYTE mask_tab[6]={0x80,0xE0,0xF0,0xF8,0xFC,0xFE}; + +static const BYTE val_tab[6]={0,0xC0,0xE0,0xF0,0xF8,0xFC}; + +unsigned utf8_decode_char(const char *p_utf8,unsigned * wide,unsigned max) +{ + const BYTE * utf8 = (const BYTE*)p_utf8; + + if (wide) *wide = 0; + + if (max==0) + return 0; + else if (max>6) max = 6; + + if (utf8[0]<0x80) + { + if (wide) *wide = utf8[0]; + return utf8[0]>0 ? 1 : 0; + } + + unsigned res=0; + unsigned n; + unsigned cnt=0; + while(1) + { + if ((*utf8&mask_tab[cnt])==val_tab[cnt]) break; + if (++cnt>=max) return 0; + } + cnt++; + + for(n=0;n>(cnt+1))&*utf8; + + for (n=1;n> (7 - cnt))) + return 0; + + res=(res<<6)|(utf8[n]&0x3F); + } + + if (wide) + *wide=res; + + return cnt; +} + + +unsigned utf8_encode_char(unsigned wide,char * target) +{ + unsigned int count; + + if (wide < 0x80) + count = 1; + else if (wide < 0x800) + count = 2; + else if (wide < 0x10000) + count = 3; + else if (wide < 0x200000) + count = 4; + else if (wide < 0x4000000) + count = 5; + else if (wide <= 0x7FFFFFFF) + count = 6; + else + return 0; + //if (count>max) return 0; + + if (target == 0) + return count; + + switch (count) + { + case 6: + target[5] = 0x80 | (wide & 0x3F); + wide = wide >> 6; + wide |= 0x4000000; + case 5: + target[4] = 0x80 | (wide & 0x3F); + wide = wide >> 6; + wide |= 0x200000; + case 4: + target[3] = 0x80 | (wide & 0x3F); + wide = wide >> 6; + wide |= 0x10000; + case 3: + target[2] = 0x80 | (wide & 0x3F); + wide = wide >> 6; + wide |= 0x800; + case 2: + target[1] = 0x80 | (wide & 0x3F); + wide = wide >> 6; + wide |= 0xC0; + case 1: + target[0] = wide; + } + + return count; +} + +unsigned utf16_encode_char(unsigned cur_wchar,WCHAR * out) +{ + if (cur_wchar>0 && cur_wchar<(1<<20)) + { + if (cur_wchar>=0x10000) + { + unsigned c = cur_wchar - 0x10000; + //MSDN: + //The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0. + out[0] = (WCHAR)(0xD800 | (0x3FF & (c>>10)) ); + out[1] = (WCHAR)(0xDC00 | (0x3FF & c) ) ; + return 2; + } + else + { + *out = (WCHAR)cur_wchar; + return 1; + } + } + return 0; +} + +unsigned utf16_decode_char(const WCHAR * src,unsigned * out) +{ + unsigned rv = 0; + unsigned int cur_wchar = *(src++); + if (cur_wchar) + { + rv = 1; + if ((cur_wchar & 0xFC00) == 0xD800) + { + unsigned int low = *src; + if ((low & 0xFC00) == 0xDC00) + { + src++; + cur_wchar = 0x10000 + ( ((cur_wchar & 0x3FF) << 10) | (low & 0x3FF) ); + rv = 2; + } + } + } + *out = cur_wchar; + return rv; +} + + +UINT utf8_get_char(const char * src) +{ + UINT rv = 0; + utf8_decode_char(src,&rv); + return rv; +} + + +unsigned utf8_char_len(const char * s) +{ + return utf8_decode_char(s,0); +} + +int skip_utf8_chars(const char * ptr,int count) +{ + int num = 0; + for(;count && ptr[num];count--) + { + int d = utf8_char_len(ptr+num); + if (d<=0) break; + num+=d; + } + return num; +} + +unsigned convert_utf8_to_utf16(const char * src,WCHAR * dst,unsigned len) +{ + unsigned rv = 0; + while(*src && len) + { + unsigned c,d; + d = utf8_decode_char(src,&c,len); + if (d==0 || d>len) break; + src += d; + len -= d; + d = utf16_encode_char(c,dst); + if (d==0) break; + dst += d; + rv += d; + } + *dst = 0; + return rv; +} + +unsigned convert_utf16_to_utf8(const WCHAR * src,char * dst,unsigned len) +{ + unsigned rv = 0; + while(*src && len) + { + unsigned c,d; + d = utf16_decode_char(src,&c); + if (d==0 || d>len) break; + src += d; + len -= d; + d = utf8_encode_char(c,dst); + if (d==0) break; + dst += d; + rv += d; + } + *dst = 0; + return rv; +} + +unsigned convert_ansi_to_utf16(const char * src,WCHAR * dst,unsigned len) +{ + len = strlen_max(src,len); + unsigned rv; +#ifdef WIN32 + rv = MultiByteToWideChar(CP_ACP,0,src,len,dst,estimate_ansi_to_utf16(src)); +#else + setlocale(LC_CTYPE,""); + rv = mbstowcs(dst,src,len); +#endif + if ((signed)rv<0) rv = 0; + dst[rv]=0; + return rv; +} + +unsigned convert_utf16_to_ansi(const WCHAR * src,char * dst,unsigned len) +{ + len = wcslen_max(src,len); + unsigned rv; +#ifdef WIN32 + rv = WideCharToMultiByte(CP_ACP,0,src,len,dst,estimate_utf16_to_ansi(src),0,0); +#else + setlocale(LC_CTYPE,""); + rv = wcstombs(dst,src,len); +#endif + if ((signed)rv<0) rv = 0; + dst[rv]=0; + return rv; +} + +unsigned convert_utf8_to_ansi(const char * src,char * dst,unsigned len) +{//meh + len = strlen_max(src,len); + + unsigned temp_len = estimate_utf8_to_utf16(src,len); + mem_block_t temp_block; + WCHAR * temp = (temp_len * sizeof(WCHAR) <= PFC_ALLOCA_LIMIT) ? (WCHAR*)alloca(temp_len * sizeof(WCHAR)) : temp_block.set_size(temp_len); + assert(temp); + + len = convert_utf8_to_utf16(src,temp,len); + return convert_utf16_to_ansi(temp,dst,len); +} + +unsigned convert_ansi_to_utf8(const char * src,char * dst,unsigned len) +{//meh + len = strlen_max(src,len); + + unsigned temp_len = estimate_ansi_to_utf16(src,len); + mem_block_t temp_block; + WCHAR * temp = (temp_len * sizeof(WCHAR) <= PFC_ALLOCA_LIMIT) ? (WCHAR*)alloca(temp_len * sizeof(WCHAR)) : temp_block.set_size(temp_len); + assert(temp); + + len = convert_ansi_to_utf16(src,temp,len); + return convert_utf16_to_utf8(temp,dst,len); +} + +void string_base::add_string_ansi(const char * src,unsigned len) +{ + len = strlen_max(src,len); + + unsigned temp_len = estimate_ansi_to_utf8(src,len); + mem_block_t temp_block; + char * temp = (temp_len * sizeof(char) <= PFC_ALLOCA_LIMIT) ? (char*)alloca(temp_len * sizeof(char)) : temp_block.set_size(temp_len); + assert(temp); + + len = convert_ansi_to_utf8(src,temp,len); + add_string_n(temp,len); +} + +void string_base::add_string_utf16(const WCHAR * src,unsigned len) +{ + len = wcslen_max(src,len); + + unsigned temp_len = estimate_utf16_to_utf8(src,len); + mem_block_t temp_block; + char * temp = (temp_len * sizeof(char) <= PFC_ALLOCA_LIMIT) ? (char*)alloca(temp_len * sizeof(char)) : temp_block.set_size(temp_len); + assert(temp); + + len = convert_utf16_to_utf8(src,temp,len); + add_string_n(temp,len); +} + +bool is_valid_utf8(const char * param) +{ + __try { + while(*param) + { + unsigned d; + d = utf8_decode_char(param,0); + if (d==0) return false; + param += d; + } + return true; + } + __except(1) + { + return false; + } +} + +bool is_lower_ascii(const char * param) +{ + while(*param) + { + if (*param<0) return false; + param++; + } + return true; +} + +static bool check_end_of_string(const char * ptr) +{ + __try { + return !*ptr; + } + __except(1) {return true;} +} + +unsigned strcpy_utf8_truncate(const char * src,char * out,unsigned maxbytes) +{ + unsigned rv = 0 , ptr = 0; + if (maxbytes>0) + { + maxbytes--;//for null + while(!check_end_of_string(src) && maxbytes>0) + { + __try { + unsigned delta = utf8_char_len(src); + if (delta>maxbytes || delta==0) break; + do + { + out[ptr++] = *(src++); + } while(--delta); + } __except(1) { break; } + rv = ptr; + } + out[rv]=0; + } + return rv; +} + +void recover_invalid_utf8(const char * src,char * out,unsigned replace) +{ + while(!check_end_of_string(src)) + { + unsigned c,d; + __try { + d = utf8_decode_char(src,&c); + } __except(1) {d = 0;} + if (d==0) c = replace; + out += utf8_encode_char(c,out); + } + *out = 0; +} + +unsigned string8::replace_char(unsigned c1,unsigned c2,unsigned start) +{ + string8 temp(get_ptr()+start); + truncate(start); + const char * ptr = temp; + unsigned rv = 0; + while(*ptr) + { + unsigned test; + unsigned delta = utf8_decode_char(ptr,&test); + if (delta==0 || test==0) break; + if (test == c1) {test = c2;rv++;} + add_char(test); + ptr += delta; + } + return rv; +} + +unsigned strlen_utf8(const char * p,unsigned num) +{ + unsigned w,d; + unsigned ret = 0; + for(;num;) + { + d = utf8_decode_char(p,&w); + if (w==0 || d<=0) break; + ret++; + p+=d; + num-=d; + } + return ret; +} + +unsigned utf8_chars_to_bytes(const char * string,unsigned count) +{ + unsigned bytes = 0; + while(count) + { + unsigned delta = utf8_decode_char(string+bytes,0); + if (delta==0) break; + bytes += delta; + count--; + } + return bytes; +} \ No newline at end of file diff --git a/tools/vio2sf/src/foobar8/readme.txt b/tools/vio2sf/src/foobar8/readme.txt new file mode 100644 index 000000000..61a81729a --- /dev/null +++ b/tools/vio2sf/src/foobar8/readme.txt @@ -0,0 +1,24 @@ +foobar2000 0.8 SDK readme + +All components need to be linked to pfc, foobar2000_SDK, utf8api and to component_client - hint: use dependencies in msvc, *do*not* include all .cpp files in your project - that will drastically increase time needed to compile and cause weird errors to occur. +Included workspace has all project dependencies set up, have a look at it if you can't figure how to make things compile correctly. + +This SDK is intended to work with 0.8 versions of foobar2000. It will not work with any earlier versions. You may need to recompile your components with newer version of this SDK in order to get them to work with post-0.8 versions of foobar2000. + +latest version of this SDK is available at http://www.foobar2000.org/ + +copyright stuff: + +SSRC SuperEQ libraries (c) Naoki Shibata, http://shibatch.sourceforge.net/ + +mpglib library (c) 1995-99 Michael Hipp + +mpc decoding library - (C) 1999-2002 Buschmann/Klemm/Piecha/Wolf + +tagread.cpp tag manipulating routines by Case + +SPC player sourcecode available at http://www.foobar2000.org/foo_spc_src.zip + +akrip.dll source Copyright (C) 1999 Jay A. Key + +JNetLib copyright (C) 2000-2001 Nullsoft, Inc. diff --git a/tools/vio2sf/vio2sf.dsp b/tools/vio2sf/vio2sf.dsp index 6218c7bdb..dac8808f6 100644 --- a/tools/vio2sf/vio2sf.dsp +++ b/tools/vio2sf/vio2sf.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # 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 "AOSSFDRV_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /O2 /I "src/vio2sf/desmume" /I "src/vio2sf/zlib" /D "LSB_FIRST" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AOSSFDRV_EXPORTS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "src/vio2sf/desmume" /I "src/vio2sf/zlib" /I "." /D "LSB_FIRST" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AOSSFDRV_EXPORTS" /D "XSFDRIVER_EXTENDPARAM1NAME" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 @@ -54,7 +54,7 @@ BSC32=bscmake.exe # 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 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 /pdb:none /machine:I386 /out:"C:\Program Files\winamp\Plugins\vio2sf.bin" +# ADD 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 /pdb:none /machine:I386 /out:"vio2sf.bin" !ELSEIF "$(CFG)" == "vio2sf - Win32 Debug" @@ -70,7 +70,7 @@ LINK32=link.exe # 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 "AOSSFDRV_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "src/vio2sf/desmume" /I "src/vio2sf/zlib" /D "LSB_FIRST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AOSSFDRV_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "src/vio2sf/desmume" /I "src/vio2sf/zlib" /I "." /D "LSB_FIRST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "AOSSFDRV_EXPORTS" /D "XSFDRIVER_EXTENDPARAM1NAME" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x411 /d "_DEBUG" @@ -80,7 +80,7 @@ BSC32=bscmake.exe # 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 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 /out:"C:\Program Files\winamp\Plugins\vio2sf.bin" /pdbtype:sept +# ADD 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 /out:"vio2sf.bin" /pdbtype:sept !ENDIF diff --git a/tools/vio2sf/vio2sf.dsw b/tools/vio2sf/vio2sf.dsw index 2172ed9d1..fb45c9d94 100644 --- a/tools/vio2sf/vio2sf.dsw +++ b/tools/vio2sf/vio2sf.dsw @@ -1,5 +1,5 @@ Microsoft Developer Studio Workspace File, Format Version 6.00 -# 警告: このワークスペース ファイル を編集または削除しないでください! +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### @@ -9,6 +9,57 @@ Package=<5> {{{ }}} +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name foobar2000_SDK + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_sdk_helpers + End Project Dependency + Begin Project Dependency + Project_Dep_Name pfc + End Project Dependency + Begin Project Dependency + Project_Dep_Name foobar2000_component_client + End Project Dependency +}}} + +############################################################################### + +Project: "foobar2000_SDK"=.\src\foobar8\foobar2000\SDK\foobar2000_SDK.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name utf8api + End Project Dependency +}}} + +############################################################################### + +Project: "foobar2000_component_client"=.\src\foobar8\foobar2000\foobar2000_component_client\foobar2000_component_client.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "foobar2000_sdk_helpers"=.\src\foobar8\foobar2000\helpers\foobar2000_sdk_helpers.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + Package=<4> {{{ }}} @@ -51,6 +102,33 @@ Package=<4> ############################################################################### +Project: "pfc"=.\src\foobar8\pfc\pfc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "utf8api"=.\src\foobar8\foobar2000\utf8api\utf8api.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pfc + End Project Dependency +}}} + +############################################################################### + Project: "vio2sf"=.\vio2sf.dsp - Package Owner=<4> Package=<5>