summaryrefslogtreecommitdiffstats
path: root/Src/Plugins/Input/in_vorbis/wa2.cpp
diff options
context:
space:
mode:
authorwinampgit <github@winamp.com>2024-09-27 08:32:58 +0200
committerGitHub <noreply@github.com>2024-09-27 08:32:58 +0200
commit5b91e3f697cb6a484b6a63d4fe529e4e15f6dd19 (patch)
tree1f14e8e1d4a93c9379e2731ef0d967add426546f /Src/Plugins/Input/in_vorbis/wa2.cpp
parentUpdate README.md (diff)
downloadwinamp-community.tar
winamp-community.tar.gz
winamp-community.tar.bz2
winamp-community.tar.lz
winamp-community.tar.xz
winamp-community.tar.zst
winamp-community.zip
Diffstat (limited to 'Src/Plugins/Input/in_vorbis/wa2.cpp')
-rw-r--r--Src/Plugins/Input/in_vorbis/wa2.cpp1097
1 files changed, 0 insertions, 1097 deletions
diff --git a/Src/Plugins/Input/in_vorbis/wa2.cpp b/Src/Plugins/Input/in_vorbis/wa2.cpp
deleted file mode 100644
index 3920a0eed..000000000
--- a/Src/Plugins/Input/in_vorbis/wa2.cpp
+++ /dev/null
@@ -1,1097 +0,0 @@
-#include "main.h"
-#include "genres.h"
-#include "decoder.h"
-#include "api__in_vorbis.h"
-#include "../Winamp/wa_ipc.h"
-#include "../nu/Singleton.h"
-#include "mkv_vorbis_decoder.h"
-#include <shlwapi.h>
-#include "../nu/AutoWide.h"
-#include "../nu/AutoChar.h"
-#include <strsafe.h>
-#include <api/service/waservicefactory.h>
-
-template <class api_T>
-void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
-{
- if (mod.service)
- {
- waServiceFactory *factory = mod.service->service_getServiceByGuid(factoryGUID_t);
- if (factory)
- api_t = reinterpret_cast<api_T *>( factory->getInterface() );
- }
-}
-
-template <class api_T>
-void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
-{
- if (mod.service && api_t)
- {
- waServiceFactory *factory = mod.service->service_getServiceByGuid(factoryGUID_t);
- if (factory)
- factory->releaseInterface(api_t);
- }
- api_t = NULL;
-}
-
-VorbisFile * theFile = 0;
-
-extern CfgInt cfg_abr,cfg_httpseek2;
-
-OSVERSIONINFO os_ver = {0};
-
-static int pos_ms;
-static int seek_to=-1;
-static int length;
-static bool kill;
-
-StringW stat_disp;
-
-void show_stat(const wchar_t* txt)
-{
- if (txt)
- {
- stat_disp=txt;
- PostMessage(mod.hMainWindow,WM_USER,0,243);
- }
- else
- stat_disp=L"";
-}
-
-static int is_out_open;
-static int paused;
-static int volume=255;
-static int pan=0;
-StringW cur_file;
-
-CRITICAL_SECTION sync;
-
-HANDLE hThread=0;
-
-void Config(HWND);
-void About(HWND p);
-void do_cfg(int s);
-void GetFileInfo(const in_char *file, wchar_t *title, int *len);
-
-const char *INI_FILE=0;
-const wchar_t *INI_DIRECTORY=0;
-int (*warand)()=0;
-float (*warandf)()=0;
-
-api_application *WASABI_API_APP = 0;
-// wasabi based services for localisation support
-api_language *WASABI_API_LNG = 0;
-HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
-api_memmgr* WASABI_API_MEMMGR = 0;
-api_config *AGAVE_API_CONFIG=0;
-
-static MKVDecoderCreator mkvCreator;
-static SingletonServiceFactory<svc_mkvdecoder, MKVDecoderCreator> mkvFactory;
-
-void SetFileExtensions(void)
-{
- static char fileExtensionsString[1200] = {0}; // "OGG\0Ogg files (*.OGG)\0"
- char* end = 0;
- StringCchCopyExA(fileExtensionsString, 1200, "OGG;OGA", &end, 0, 0);
- StringCchCopyExA(end+1, 1200, WASABI_API_LNGSTRING(IDS_OGG_FILES), 0, 0, 0);
- mod.FileExtensions = fileExtensionsString;
-}
-
-int Init()
-{
- if (!IsWindow(mod.hMainWindow))
- return IN_INIT_FAILURE;
-
- mod.UsesOutputPlug|=8;
-
- warand = (int (*)())SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GET_RANDFUNC);
- warandf = (float (*)())SendMessage(mod.hMainWindow, WM_WA_IPC, 1, IPC_GET_RANDFUNC);
-
- ServiceBuild(WASABI_API_MEMMGR, memMgrApiServiceGuid);
- ServiceBuild(AGAVE_API_CONFIG, AgaveConfigGUID);
- // loader so that we can get the localisation service api for use
- ServiceBuild(WASABI_API_LNG, languageApiGUID);
- ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
-
- mkvFactory.Register(mod.service, &mkvCreator);
-
- // need to have this initialised before we try to do anything with localisation features
- WASABI_API_START_LANG(mod.hDllInstance,InVorbisLangGUID);
-
- static wchar_t szDescription[256];
- StringCchPrintfW(szDescription,256,WASABI_API_LNGSTRINGW(IDS_NULLSOFT_VORBIS_DECODER),VER);
- mod.description = (char*)szDescription;
-
- SetFileExtensions();
-
- INI_FILE = (const char *)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GETINIFILE);
- INI_DIRECTORY = (const wchar_t *)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORYW);
-
- os_ver.dwOSVersionInfoSize=sizeof(os_ver);
- GetVersionEx(&os_ver);
-
- InitializeCriticalSection(&sync);
- do_cfg(0);
- return IN_INIT_SUCCESS;
-}
-
-void Quit()
-{
- winampGetExtendedFileInfoW_Cleanup();
- DeleteCriticalSection(&sync);
- mkvFactory.Deregister(mod.service);
- ServiceRelease(WASABI_API_MEMMGR, memMgrApiServiceGuid);
- ServiceRelease(AGAVE_API_CONFIG, AgaveConfigGUID);
- ServiceRelease(WASABI_API_LNG, languageApiGUID);
- ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
-}
-
-int GetLength()
-{
- return length;
-}
-
-int IsOurFile(const in_char *fn)
-{
- if (PathIsURLW(fn))
- {
- const wchar_t *foo=wcsrchr(fn,L'.');
- return foo ? !_wcsicmp(foo,L".ogg") : 0;
- }
- else return 0;
-}
-
-static UINT kbps_disp;
-
-static void out_close()
-{
- if (is_out_open)
- {
- mod.outMod->Close();
- mod.SAVSADeInit();
- is_out_open=0;
- }
-}
-
-static bool need_full_setinfo;
-
-static int out_open(const Decoder &dec)
-{
- int max_l=mod.outMod->Open(dec.sr,dec.nch,dec.bps,-1,-1);
- if (max_l<0) return 0;
- mod.outMod->SetVolume(-666);
- mod.outMod->SetPan(pan);
- mod.SAVSAInit(max_l,dec.sr);
- mod.VSASetInfo(dec.sr,dec.nch);
-
- is_out_open=1;
- need_full_setinfo=1;
- return 1;
-}
-
-void Decoder::wa2_setinfo(UINT cur)
-{
- UINT disp=file->get_avg_bitrate();
- if (!cfg_abr)
- {
- disp=cur;
- }
- if ((disp && disp!=kbps_disp) || need_full_setinfo)
- {
- kbps_disp=disp;
- if (need_full_setinfo)
- {
- mod.SetInfo(disp,sr/1000,nch,1);
- need_full_setinfo=0;
- }
- else mod.SetInfo(disp,-1,-1,1);
- }
-}
-
-static bool need_movefile;
-static void process_movefile();
-
-void alloc_buffers(Decoder & dec,short ** visbuf,char ** sample_buf,int * s_size)
-{
- *s_size=576 * (dec.bps>>3) * dec.nch;
-
- if (*sample_buf) *sample_buf=(char*)realloc(*sample_buf,*s_size*2);
- else *sample_buf=(char*)malloc(*s_size*2);
-
- if (dec.bps>16)
- {
- int vs=576*2*dec.nch;
- if (*visbuf) *visbuf=(short*)realloc(*visbuf,vs);
- else *visbuf=(short*)malloc(vs);
- }
- else if (*visbuf) {free(*visbuf);*visbuf=0;}
-}
-
-static DWORD WINAPI PlayThread(Decoder &dec)
-{
- int pos_base=0;
- int samp_wr=0;
- int done=0;
- int upd=0;
- __int64 brate;
- int br_div,br_t;
- short* visbuf=0;
- char *sample_buf=0;
- int retries=0;
- int s_size=0;
-
- pos_ms=0;
-
- {
- int r;
- r=dec.play_init();
- if (r)
- {
- if (!kill) Sleep(50);
- if (!kill) Sleep(50);
- if (!kill) Sleep(50);
- if (!kill) Sleep(50);
- if (!kill)
- {
- if (r==2) PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0);
- else PostMessage(mod.hMainWindow,WM_COMMAND,40047,0);
- }
- delete &dec;
- return 0;
- }
- theFile->do_prebuf();
- }
-
- brate=0;
- br_div=0;
- upd=0;
-
- alloc_buffers(dec,&visbuf,&sample_buf,&s_size);
-
- //int f_type=theFile->GetType();
- bool is_live=theFile->IsLive();
-
- while(!kill)
- {
- if (!theFile) break;//ugh
- if (seek_to!= -1)
- {
- UINT _st=seek_to;
- int r=1;
- seek_to=-1;
- if (theFile)
- {
- theFile->use_prebuf=0;
- int link=theFile->vf.current_link;
- r=dec.Seek((double)_st*0.001);
- if (link!=theFile->vf.current_link) PostMessage(mod.hMainWindow,WM_USER,0,243);
- }
- else r=1;
- if (!r)
- {
- pos_base=pos_ms=_st;
- mod.outMod->Flush(pos_ms);
- samp_wr=0;
- done=0;
- theFile->do_prebuf();
- }
- }
-
- if (need_movefile && paused)//HACK, prevent stupid lockup
- {
- process_movefile();
- if (!theFile) break;//#@!
- dec.file=theFile;
- dec.Flush();
- }
-
- if (done)
- {
- // mod.outMod->CanWrite();
- if (!mod.outMod->IsPlaying())
- {
- PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0);
- break;
- }
- Sleep(10);
- }
- else if (mod.outMod->CanWrite() >= (s_size<<(mod.dsp_isactive()?1:0)))
- {
- int l=0;
- while(1)
- {
- if (!dec.need_reopen)
- {
- l+=dec.Read(s_size-l,sample_buf+l);
- if (l>=s_size) break;
-
- int link=theFile->vf.current_link;
- if (need_movefile)//safe not to flush here
- {
- process_movefile();
- if (!theFile) break;//#@!
- dec.file=theFile;
- }
- if (!dec.DoFrame()) break;
- if (kill) break;
-
- if (link!=theFile->vf.current_link)
- {
- PostMessage(mod.hMainWindow,WM_USER,0,243);
- }
- br_t=ov_bitrate_instant(&theFile->vf);
- if (br_t>0)
- {
- int i = dec.DataAvailable()/((dec.bps/8)*dec.nch);
- br_div+=i;
- brate+=(__int64)(br_t*i);
- }
- if (need_full_setinfo || (!((++upd)%200) && br_div))
- {
- if (!br_div) {br_div=1;brate=theFile->get_avg_bitrate();}
- dec.wa2_setinfo((int)((__int64)brate/(__int64)br_div/(__int64)1000));
- brate=0;
- br_div=0;
- }
- }
- if (dec.need_reopen)
- {//blargh, new PCM format
- if (l>0) break;//got samples to play, we'll deal with this later
- //l=0;
- while(!kill && mod.outMod->IsPlaying()) Sleep(1);
- if (kill) break;
- out_close();
- if (!out_open(dec))//boo
- {
- PostMessage(mod.hMainWindow,WM_COMMAND,40047,0);
- kill=1;
- break;
- }
- alloc_buffers(dec,&visbuf,&sample_buf,&s_size);
- dec.need_reopen=0;
- }
- }
-
- if (kill || !theFile) break;
-
- if (l<=0 && (!is_live || (--retries)<0))
- {
- mod.outMod->Write(sample_buf,0);
- done=1;
- }
- else if (l<=0)
- {
- int r;
- out_close();
- EnterCriticalSection(&sync);
- delete theFile;
- theFile=0;
- LeaveCriticalSection(&sync);
- if (sample_buf)
- {
- free(sample_buf);
- sample_buf=0;
- }
-
- r=dec.play_init();
-
- if (r)
- {
- mod.outMod->Write(sample_buf,0);
- done=1;
- }
- else
- {
- theFile->do_prebuf();
- }
- }
- else
- {
- if (l<s_size) memset(sample_buf+l,dec.bps==8 ? 0x80 : 0,s_size-l);
- char * vis=sample_buf;
- UINT vis_bps=dec.bps;
- if (dec.bps>16)
- {
- UINT n;
- UINT d=dec.bps>>3;
- char * foo=sample_buf+d-2;
- for(n=0;n<576*dec.nch;n++)
- {
- visbuf[n]=*(short*)foo;
- foo+=d;
- }
- vis=(char*)visbuf;
- vis_bps=16;
- }
- mod.SAAddPCMData(vis,dec.nch,vis_bps,pos_ms);
- mod.VSAAddPCMData(vis,dec.nch,vis_bps,pos_ms);
-
- if (mod.dsp_isactive())
- {
- l=(l<<3)/(dec.bps*dec.nch);
- l=mod.dsp_dosamples((short*)sample_buf,l,dec.bps,dec.nch,dec.sr);
- l*=(dec.nch*dec.bps)>>3;
- }
- if (kill) break;
- mod.outMod->Write((char*)sample_buf,l);
-
- samp_wr+=(8*l)/(dec.bps*dec.nch);
- pos_ms=pos_base+MulDiv(1000,samp_wr,dec.sr);
- }
- }
- else
- {
- theFile->Idle();
- }
- }
-
- // out_close();
- // gay gapless plugins puke, need to call this from stop
- // ok, hetero (out_wave v2.x / out_ds v1.4+) gapless plugins wouldn't puke anymore
-
- if (theFile)
- {
- VorbisFile * t=theFile;
- EnterCriticalSection(&sync);
- theFile=0;
- LeaveCriticalSection(&sync);
- delete t;
- }
-
- if (sample_buf)
- {
- free(sample_buf);
- sample_buf=0;
- }
-
- if (need_movefile) process_movefile();
-
- /* if (!kill)
- {
- CloseHandle(hThread);
- hThread=0;
- }*/
-
- if (visbuf) free(visbuf);
-
- delete &dec;
- return 0;
-}
-
-static StringW move_src,move_dst;
-static bool mf_ret;
-
-static void do_movefile()
-{
- mf_ret=1;
- winampGetExtendedFileInfoW_Cleanup();
- if (!DeleteFileW(move_dst)) mf_ret=0;
- else
- {
- if (!MoveFileW(move_src,move_dst))
- {
- if (!CopyFileW(move_src,move_dst,0)) mf_ret=0;
- DeleteFileW(move_src);
- }
- }
-}
-
-static void process_movefile()
-{
- if (theFile)
- {
- StringW f_path;
- f_path.AddString(theFile->url);
- double pos=theFile->GetPos();
- EnterCriticalSection(&sync);
- delete theFile;
- theFile=0;
-
- do_movefile();
-
- theFile=VorbisFile::Create(f_path,0);
- LeaveCriticalSection(&sync);
- if (theFile)
- {
- theFile->Seek(pos);
- }
- }
- else do_movefile();
- need_movefile=0;
-}
-
-bool sync_movefile(const wchar_t * src,const wchar_t * dst)//called from info_.cpp
-{
- move_src=src;
- move_dst=dst;
- need_movefile=1;
- if (!theFile) process_movefile();
- else
- {
- while(need_movefile && hThread) Sleep(1);
- if (need_movefile) process_movefile();//shouldnt really happen
- move_src=L"";
- move_dst=L"";
- PostMessage(mod.hMainWindow,WM_USER,0,243);
- }
-
- return mf_ret;
-}
-
-
-int Decoder::play_init()//still messy
-{
- if (play_inited) return 0;
-
- kbps_disp=0;
-
- VorbisFile * t=VorbisFile::Create(cur_file,0);
- if (!t)
- {
-#ifdef _DEBUG
- OutputDebugString(L"can't open file\n");
-#endif
- // if (scream) MessageBox(mod.hMainWindow,"error opening file",0,MB_ICONERROR);
- return 2;
- }
- Init(t);
- if (!out_open(*this))
- {
-#ifdef _DEBUG
- OutputDebugString(L"can't open output\n");
-#endif
- delete t;
- return 1;
- }
-
- EnterCriticalSection(&sync);
- theFile=t;
- LeaveCriticalSection(&sync);
-
- wa2_setinfo(theFile->get_avg_bitrate());
-
- {
- double v=theFile->Length();
- if (v==OV_EINVAL || v<=0) length=-1;
- else length=(int)(v*1000.0);
- }
-
- play_inited=1;
-
- return 0;
-}
-
-int Play(const in_char *fn)
-{
- seek_to=-1;
- kill=0;
- length=0;
- paused=0;
-
- show_stat(0);
-
- EnterCriticalSection(&sync);
- cur_file=fn;
- LeaveCriticalSection(&sync);
-
- Decoder * dec=new Decoder;
-
- if (!PathIsURLW(fn))
- {
- mod.is_seekable=1;
-#if 1
- int rv=dec->play_init();
- if (rv)
- {
- delete dec;
- if (rv==2) return -1;
- return 1;
- }
-#endif
- }
- else mod.is_seekable=cfg_httpseek2;
-
- {
- DWORD id;
- hThread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)PlayThread,dec,CREATE_SUSPENDED,&id);
- }
-
- if (hThread)
- {
- SetThreadPriority(hThread, (int)AGAVE_API_CONFIG->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST));
- ResumeThread(hThread);
- return 0;
- }
- else
- {
- out_close();
- delete dec;
- return 1;
- }
-}
-
-void Pause()
-{
- if (!paused)
- {
- mod.outMod->Pause(1);
- paused=1;
- }
-}
-
-void UnPause()
-{
- if (paused)
- {
- mod.outMod->Pause(0);
- paused=0;
- }
-}
-
-int IsPaused()
-{
- return paused;
-}
-
-void Stop()
-{
- if (hThread)
- {
- kill=1;
- EnterCriticalSection(&sync);
- if (theFile) theFile->stopping=1;
- LeaveCriticalSection(&sync);
- if (WaitForSingleObject(hThread,10000)!=WAIT_OBJECT_0)
- {
- TerminateThread(hThread,0);
- //MessageBox(mod.hMainWindow,"error asking thread to die",0,MB_ICONERROR);
- }
- CloseHandle(hThread);
- hThread=0;
- out_close();
- }
- show_stat(0);
- winampGetExtendedFileInfoW_Cleanup();
-}
-
-void EQSet(int on, char data[10], int preamp)
-{
-}
-
-int GetOutputTime()
-{
- return pos_ms+(mod.outMod->GetOutputTime()-mod.outMod->GetWrittenTime());
-}
-
-void SetOutputTime(int t)
-{
- seek_to=t;
- EnterCriticalSection(&sync);
- if (theFile) theFile->abort_prebuf=1;
- LeaveCriticalSection(&sync);
-}
-
-void SetVolume(int v)
-{
- mod.outMod->SetVolume(volume=v);
-}
-
-void SetPan(int p)
-{
- mod.outMod->SetPan(pan=p);
-}
-
-//int InfoBox(char *file, HWND parent); //old
-int RunInfoDlg(const in_char * url,HWND parent);
-
-In_Module mod=
-{
- IN_VER_RET,
- "nullsoft(in_vorbis.dll)",
- 0,0,
- 0,
- 1,
- 1,
-
- Config,
- About,
-
- Init,
- Quit,
-
- GetFileInfo,
- RunInfoDlg,
-
- IsOurFile,
- Play,
- Pause,
- UnPause,
- IsPaused,
- Stop,
-
- GetLength,
- GetOutputTime,
- SetOutputTime,
-
- SetVolume,
- SetPan,
-
- 0,0,0,0,0,0,0,0,0,0,0,
- EQSet,
-
- 0,
- 0,
-};
-
-extern "C" {
- __declspec( dllexport ) In_Module * winampGetInModule2()
- {
- return &mod;
- }
-}
-
-void VorbisFile::Status(const wchar_t * zzz)
-{
- if (primary)
- show_stat(zzz);
-}
-
-bool VorbisFile::Aborting()
-{
- return stopping || (primary && kill);
-}
-
-
-Info::Info(const wchar_t *filename) : filename(filename), vc(0)
-{
- VorbisFile * vf = VorbisFile::Create(filename,true);
- if(!vf)
- return;
-
- numstreams = vf->vf.links;
- if(numstreams)
- {
- // now copy the comment section to our own memory...
- stream = vf->vf.current_link; // this is the stream we're editing...
- vc = (vorbis_comment*)calloc(sizeof(vorbis_comment),numstreams);
-
- for(int i=0; i<numstreams; i++)
- { // one comment section per stream
- vorbis_comment *c = ov_comment(&vf->vf,i);
-
- vc[i].comments = c->comments;
- vc[i].user_comments = (char **)malloc(sizeof(char*)*c->comments);
- vc[i].comment_lengths = (int *)malloc(sizeof(int)*c->comments);
-
- for(int j=0;j<vc[i].comments;j++)
- { // copy the comments over
- vc[i].user_comments[j] = _strdup(c->user_comments[j]);
- vc[i].comment_lengths[j] = c->comment_lengths[j];
- }
- vc[i].vendor=_strdup(c->vendor);
- }
- }
- delete vf;
-}
-
-Info::~Info()
-{
- if(vc) {
- for(int i=0; i < numstreams; i++)
- vorbis_comment_clear(&vc[i]);
- free(vc);
- }
-}
-
-bool Info::Save()
-{
- return !!modify_file(filename,vc,numstreams);
-}
-
-int Info::GetNumMetadataItems()
-{
- return vc[stream].comments;
-}
-
-void Info::EnumMetadata(int n, wchar_t *key, int keylen, wchar_t *val, int vallen)
-{
- if(keylen) key[0]=0;
- if(vallen) val[0]=0;
- if(!vc) return;
- if(!vc[stream].user_comments[n]) return;
- AutoWide comment(vc[stream].user_comments[n],CP_UTF8);
- const wchar_t* eq = wcschr((const wchar_t*)comment,L'=');
- if(eq)
- {
- if(keylen) lstrcpynW(key,comment,(int)min(eq - comment + 1,keylen));
- if(vallen) lstrcpynW(val,eq+1,vallen);
- }
- else
- {
- if(keylen) lstrcpynW(key,L"COMMENT",keylen);
- if(vallen) lstrcpynW(val,comment,vallen);
- }
-}
-
-void Info::RemoveMetadata(wchar_t * key)
-{
- wchar_t k[256] = {0};
- for(int i=0; i<GetNumMetadataItems(); i++)
- {
- EnumMetadata(i,k,256,0,0);
- if(_wcsicmp(k,key)==0)
- RemoveMetadata(i);
- }
-}
-
-void Info::RemoveMetadata(int n)
-{
- if(!vc) return;
- free(vc[stream].user_comments[n]);
-
- for(int i=n+1; i<vc[stream].comments; i++)
- {
- vc[stream].user_comments[i-1] = vc[stream].user_comments[i];
- if(vc[stream].comment_lengths)
- vc[stream].comment_lengths[i-1] = vc[stream].comment_lengths[i];
- }
- vc[stream].comments--;
- vc[stream].user_comments = (char**)realloc(vc[stream].user_comments,sizeof(vc[stream].user_comments[0]) * vc[stream].comments);
- if(vc[stream].comment_lengths)
- vc[stream].comment_lengths = (int*)realloc(vc[stream].comment_lengths,sizeof(vc[stream].comment_lengths[0]) * vc[stream].comments);
-}
-
-void Info::SetMetadata(wchar_t *key, wchar_t *val)
-{
- bool set=false;
- wchar_t k[256] = {0};
- for(int i=0; i<GetNumMetadataItems(); i++)
- {
- EnumMetadata(i,k,256,0,0);
- if(_wcsicmp(k,key)==0)
- {
- SetMetadata(i,key,val);
- set=true;
- }
- }
- if(!set)
- {
- int n = vc[stream].comments++;
- vc[stream].user_comments = (char**)realloc(vc[stream].user_comments,sizeof(vc[stream].user_comments[0]) * vc[stream].comments);
- if(vc[stream].comment_lengths)
- vc[stream].comment_lengths = (int*)realloc(vc[stream].comment_lengths,sizeof(vc[stream].comment_lengths[0]) * vc[stream].comments);
- vc[stream].user_comments[n] = NULL;
- SetMetadata(n,key,val);
- }
-}
-
-void Info::SetMetadata(int n, wchar_t *key, wchar_t *val)
-{
- AutoChar k(key,CP_UTF8);
- AutoChar v(val,CP_UTF8);
-
- int l = (int)(strlen(k)+strlen(v)+2);
- char * c = (char*)malloc(l);
- StringCchPrintfA(c,l,"%s=%s",(char*)k,(char*)v);
-
- if(vc[stream].user_comments[n])
- free(vc[stream].user_comments[n]);
-
- vc[stream].user_comments[n] = c;
- if(vc[stream].comment_lengths)
- vc[stream].comment_lengths[n] = l-1;
-}
-
-void Info::SetTag(int n,wchar_t *key) // changes the key name
-{
- wchar_t val[2048] = {0};
- EnumMetadata(n,NULL,0,val,2048);
- SetMetadata(n,key,val);
-}
-
-Info *setMetadata = 0;
-
-extern "C"
-{
- static wchar_t m_lastfn[2048];
-
- #define START_TAG_ALIAS(name, alias) if (KeywordMatch(data, name)) lookup=alias
- #define TAG_ALIAS(name, alias) else if (KeywordMatch(data, name)) lookup=alias
-
- __declspec( dllexport ) int winampSetExtendedFileInfoW(const wchar_t *fn, const char *data, wchar_t *val)
- {
- if (!setMetadata || setMetadata && wcscmp(fn,m_lastfn))
- {
- if (setMetadata)
- {
- delete setMetadata;
- setMetadata = 0;
- }
-
- setMetadata = new Info(fn);
- if(setMetadata->Error())
- {
- delete setMetadata;
- m_lastfn[0] = 0;
- return 0;
- }
- lstrcpynW(m_lastfn,fn, 2048);
- }
-
- wchar_t *lookup=0;
- START_TAG_ALIAS("artist", L"ARTIST");
- TAG_ALIAS("title", L"TITLE");
- TAG_ALIAS("album", L"ALBUM");
- TAG_ALIAS("genre", L"GENRE");
- TAG_ALIAS("comment", L"COMMENT");
- TAG_ALIAS("year", L"DATE");
- TAG_ALIAS("track", L"TRACKNUMBER");
- TAG_ALIAS("albumartist", L"ALBUM ARTIST");
- TAG_ALIAS("composer", L"COMPOSER");
- TAG_ALIAS("disc", L"DISCNUMBER");
- TAG_ALIAS("publisher", L"PUBLISHER");
- TAG_ALIAS("conductor", L"CONDUCTOR");
- TAG_ALIAS("tool", L"ENCODED-BY");
- TAG_ALIAS("replaygain_track_gain", L"REPLAYGAIN_TRACK_GAIN");
- TAG_ALIAS("replaygain_track_peak", L"REPLAYGAIN_TRACK_PEAK");
- TAG_ALIAS("replaygain_album_gain", L"REPLAYGAIN_ALBUM_GAIN");
- TAG_ALIAS("replaygain_album_peak", L"REPLAYGAIN_ALBUM_PEAK");
- TAG_ALIAS("GracenoteFileID", L"GRACENOTEFILEID");
- TAG_ALIAS("GracenoteExtData", L"GRACENOTEEXTDATA");
- TAG_ALIAS("bpm", L"BPM");
- TAG_ALIAS("remixing", L"REMIXING");
- TAG_ALIAS("subtitle", L"VERSION");
- TAG_ALIAS("isrc", L"ISRC");
- TAG_ALIAS("category", L"CATEGORY");
- TAG_ALIAS("rating", L"RATING");
- TAG_ALIAS("producer", L"PRODUCER");
-
- if (!lookup)
- return 0;
-
-#if 0
- if (val && *val)
- {
- if(KeywordMatch("rating",data))
- {
- wchar_t temp[128] = {0};
- StringCchPrintfW(temp, 128, L"%u", _wtoi(val)*20);
- val=temp;
- }
- }
- AutoChar utf8(val, CP_UTF8);
-
- for(int i=0;i<m_vc->comments;i++)
- {
- char *c=m_vc[m_curstream].user_comments[i];
- if(!c) continue;
- char *p=strchr(c,'=');
- if (p && *p)
- {
- if(strlen(data) == (p-c) && !_strnicmp(c,data,p-c))
- {
- //found!
- if (val && val[0])
- {
- int added_buf_len = strlen(utf8)+strlen(lookup)+2;
- m_vc[m_curstream].user_comments[i]=(char *)realloc(m_vc[m_curstream].user_comments[i],added_buf_len);
- StringCchPrintfA(m_vc[m_curstream].user_comments[i],added_buf_len,"%s=%s",lookup,(char *)utf8);
- m_vc[m_curstream].comment_lengths[i]=strlen(m_vc[m_curstream].user_comments[i]);
- }
- else
- {
- free(m_vc[m_curstream].user_comments[i]);
- m_vc[m_curstream].user_comments[i]=0;
- m_vc[m_curstream].comment_lengths[i]=0;
- }
- return 1;
- }
- }
- }
-
- //not found, so create new field
- if (val && val[0])
- {
- int k=m_vc[m_curstream].comments++;
- m_vc[m_curstream].user_comments=(char **)realloc(m_vc[m_curstream].user_comments,sizeof(char*)*m_vc[m_curstream].comments);
- m_vc[m_curstream].comment_lengths=(int *)realloc(m_vc[m_curstream].comment_lengths,sizeof(int)*m_vc[m_curstream].comments);
- int added_buf_len = strlen(utf8)+strlen(lookup)+2;
- m_vc[m_curstream].user_comments[k]=(char *)malloc(added_buf_len);
- StringCchPrintfA(m_vc[m_curstream].user_comments[k],added_buf_len,"%s=%s",lookup,(char *)utf8);
- m_vc[m_curstream].comment_lengths[k]=strlen(m_vc[m_curstream].user_comments[k]);
- }
-#endif
-
- if (val && *val)
- {
- if(KeywordMatch("rating",data))
- {
- wchar_t temp[128] = {0};
- StringCchPrintfW(temp, 128, L"%u", _wtoi(val)*20);
- setMetadata->SetMetadata(lookup, temp);
- }
- else
- {
- setMetadata->SetMetadata(lookup, val);
- }
- }
- else
- {
- setMetadata->RemoveMetadata(lookup);
- if(KeywordMatch("comment",data))
- {
- // need to remove this one also, or else it's gonna look like delete doesn't work
- // if the file was tagged using this alternate field
- setMetadata->RemoveMetadata(L"DESCRIPTION");
- }
- else if(KeywordMatch("year",data))
- {
- // need to remove this one also, or else it's gonna look like delete doesn't work
- // if the file was tagged using this alternate field
- setMetadata->RemoveMetadata(L"YEAR");
- }
- else if(KeywordMatch("track",data))
- {
- // need to remove this one also, or else it's gonna look like delete doesn't work
- // if the file was tagged using this alternate field
- setMetadata->RemoveMetadata(L"TRACK");
- }
- else if(KeywordMatch("albumartist",data))
- {
- // need to remove these two, also, or else it's gonna look like delete doesn't work
- // if the file was tagged using these alternate fields
- setMetadata->RemoveMetadata(L"ALBUMARTIST");
- setMetadata->RemoveMetadata(L"ENSEMBLE");
- }
- else if(KeywordMatch("publisher",data))
- {
- // need to remove this one also, or else it's gonna look like delete doesn't work
- // if the file was tagged using this alternate field
- setMetadata->RemoveMetadata(L"ORGANIZATION");
- }
- else if(KeywordMatch("category",data))
- {
- // need to remove these two also, or else it's gonna look like delete doesn't work
- // if the file was tagged using these alternate fields
- setMetadata->RemoveMetadata(L"CONTENTGROUP");
- setMetadata->RemoveMetadata(L"GROUPING");
- }
- }
-
- return 1;
- }
-
- __declspec( dllexport ) int winampWriteExtendedFileInfo()
- {
- if(!setMetadata) return 0;
-
- bool ret = setMetadata->Save();
- delete setMetadata;
- setMetadata = 0;
-
- // update last modified so we're not re-queried on our own updates
- UpdateFileTimeChanged(m_lastfn);
-
- return ret;
- }
-} \ No newline at end of file