winamp 의 plugin 을 이용한 프로그래밍 ---- winamp 의 경우 다양한 plugin 를 지원한다. input plugin은 해당 화일을 읽어드리고 output plugin 으로의 출력을 소스를 제공한다. output plugin 은 출력 소스를 사운드카드나 하드 디스크로의 출력을 관장한다. 이 중간에 DSP 와 Visual plugin 이 callback 으로 결과물을 받은뒤 변수들을 이용한다. 이들을 잘 이용하면 복잡한 ACM 관련 처리 없이 훌륭한 확장성의 플레이어를 만들 수 있을 것이다. === Simple Code === 컴파일하려면 in2.h 와 Out.h 가 필요하다. 이는 http://www.winamp.com/nsdn/ 에서 Winamp SDK를 다운받는다. http://download.nullsoft.com/winamp/client/wa502_sdk.zip {{{~cpp #include #include #include "in2.h" // define procedures, that'll be found in a .DLL typedef In_Module* (*INHDRPROC)(void); typedef Out_Module* (*OUTHDRPROC)(void); // dsp-functions int dsp_donothing(short int *, int cnt, int, int, int) { return cnt; } int dsp_isactive() { return 0; } // other functions, needed to get it to work void SAVSAInit(int maxlatency_in_ms, int srate){ } void SAVSADeInit(){ } void SAAddPCMData(void *PCMData, int nch, int bps, int timestamp){ // printf ("%d,%d,%d\n", nch,bps,timestamp); } int SAGetMode(){ return 0; } void SAAdd(void *data, int timestamp, int csa){ } void VSAAddPCMData(void *PCMData, int nch, int bps, int timestamp){ // printf ("%d,%d,%d\n", nch,bps,timestamp); } int VSAGetMode(int *specNch, int *waveNch) { *specNch = *waveNch = 0; return 0; } void VSAAdd(void *data, int timestamp){ } void VSASetInfo(int nch, int srate){ } void SetInfo(int bitrate, int srate, int stereo, int synched){ } void playFile() { // 플러그인인 DLL들을 load 하는 부분. HINSTANCE hout = LoadLibrary("out_wave.dll"); HINSTANCE hin = LoadLibrary("in_vorbis.dll"); // 모듈 관련 포인터 얻어오는 부분 INHDRPROC ihp = (INHDRPROC)GetProcAddress(hin,"winampGetInModule2"); OUTHDRPROC ohp = (OUTHDRPROC)GetProcAddress(hout,"winampGetOutModule"); // Mapping. In_Module* in = ihp(); Out_Module* out = ohp(); // 버전이 다른 경우에 대한 처리. if (in->version != IN_VER || out->version != OUT_VER) { FreeLibrary(hout); FreeLibrary(hin); return; } // 이 프로그램은 console mode 기반이다. 그러므로 window 관련 셋팅은 NULL. out->hMainWindow = NULL; out->hDllInstance = hout; in->hMainWindow = NULL; in->hDllInstance = hin; if (in->UsesOutputPlug) { in->outMod = out; } // 아직 파악 안된 부분. input plugin 과 Visual plugin 연결부분이라 생각. // 함수포인터들을 적절하게 매핑해준다. // 여기서는 화면 출력 부분이 없으므로 비어있는 callback 함수를 만들어서 연결해준다. // 추후에 Visualization 부분을 만들때는 실제 함수부분을 이용하게 될 것이다. in->SAVSAInit = SAVSAInit; in->SAVSADeInit = SAVSADeInit; in->SAAdd = SAAdd; in->SAGetMode = SAGetMode; in->SAAddPCMData = SAAddPCMData; in->VSAAddPCMData = VSAAddPCMData; in->VSAGetMode = VSAGetMode; in->VSAAdd = VSAAdd; in->VSASetInfo = VSASetInfo; // DSP Plugin 부분. 역시 위와 비슷한 맥락일듯. in->dsp_dosamples = dsp_donothing; in->dsp_isactive = dsp_isactive; in->SetInfo = SetInfo; // 플러그인 초기화. out->Init(); in->Init(); char playFile[256] = "garden.ogg"; printf ("%d \n", in->version); // 플러그인 버전이 출력 printf ("%s \n", in->description); // 플러그인 설명이 출력 printf ("%s \n", in->FileExtensions); // 해당 플러그인이 지원하는 확장자가 나옴. // if playing starts correctly if (!in->Play(playFile)) { // 볼륨 & panning (좌 우 balance) 조정. in->SetVolume(255); in->SetPan(0); //int x = 1,len = in->GetLength(); //for (;x=1 && in->GetOutputTime()GetLength()); // 전체 play time (ms) printf("current : %d ms\n", in->GetOutputTime()); // 진행중 play time (ms) Sleep(1000); // 각 plugin 에서의 작업은 멀티스레드로 비동기적으로 일어난다. } // when playing stops, terminate in->Stop(); } // un-init plugins in->Quit(); out->Quit(); // dll 들 이용 완료. FreeLibrary(hin); FreeLibrary(hout); } void main() { playFile(); } }}}