123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962 |
- #include "main.h"
- #include <math.h>
- #include "seq.h"
- #include "fakedsound.h"
- #include "resource.h"
- // {B84EB58A-29F5-410b-880A-EB473BF34291}
- static const GUID guid_output =
- { 0xb84eb58a, 0x29f5, 0x410b, { 0x88, 0xa, 0xeb, 0x47, 0x3b, 0xf3, 0x42, 0x91 } };
- // {DF0800B6-D1E1-4b53-9C1E-642AF4CB7136}
- static const GUID dmusic_driver_guid =
- { 0xdf0800b6, 0xd1e1, 0x4b53, { 0x9c, 0x1e, 0x64, 0x2a, 0xf4, 0xcb, 0x71, 0x36 } };
- enum
- {
- MDD_OUT=1,
- };
- extern cfg_int cfg_dls_active,cfg_dm_keep_port;
- extern cfg_string cfg_dls_file;
- class MIDI_device_dmusic : public MIDI_device
- {
- private:
- GUID guid,guid_dmusic;
- DWORD dmFlags;
- bool f_has_output;
- virtual player_base * create();
- virtual bool is_default() {return 0;}
- virtual bool has_freq() {return !!(dmFlags&DMUS_PC_DIRECTSOUND);}
- virtual bool volctrl_happy() {return (dmFlags&DMUS_PC_DIRECTSOUND) || (dmFlags&DMUS_PC_SOFTWARESYNTH);}
- public:
- MIDI_device_dmusic(GUID p_guid,bool p_has_output,DWORD p_dmFlags,const wchar_t * p_name,const wchar_t * p_info)
- {
- guid = p_guid;
- guid_dmusic = p_guid;
- dmFlags = p_dmFlags;
- set_name(p_name);
- set_info(p_info);
- f_has_output = p_has_output;
- if (f_has_output)
- {
- const BYTE * src = (const BYTE*) &guid_output;
- BYTE * dst = (BYTE*) &guid;
- int n;
- for(n=0;n<sizeof(GUID);n++) dst[n]^=src[n];
- }
-
- }
- virtual GUID get_guid() {return guid;}
- GUID get_dm_guid() {return guid_dmusic;}
- virtual bool has_output() {return f_has_output;}
- virtual bool has_dls() {return !!(dmFlags&DMUS_PC_DLS);}
- };
- //bool IsDrumBankOK(BYTE n);
- IDirectMusicLoader* pLoader=0;
- IDirectMusicPerformance* pPerf=0;
- static IDirectMusicCollection *pGM=0;
- static IDirectMusic* pDM;
- static IDirectMusicPort *pPort;
- static IDirectSoundBuffer* pHack;
- IDirectMusicCollection *pCDLS=0;
- static void SendMsg(IDirectMusicPerformance *pPerf,DWORD msg)
- {
- DMUS_MIDI_PMSG *pMSG;
- if(SUCCEEDED(pPerf->AllocPMsg(sizeof(DMUS_MIDI_PMSG),(DMUS_PMSG**)&pMSG)))
- {
- ZeroMemory(pMSG, sizeof(DMUS_MIDI_PMSG));
- pMSG->dwSize = sizeof(DMUS_MIDI_PMSG);
- pMSG->dwPChannel = msg&0xF;
- pMSG->dwVirtualTrackID = 0;
- pMSG->dwType = DMUS_PMSGT_MIDI;
- pMSG->dwVoiceID = 0;
- pMSG->dwGroupID = 0xFFFFFFFF;
- pMSG->mtTime=0;
- pMSG->dwFlags = DMUS_PMSGF_REFTIME|DMUS_PMSGF_TOOL_IMMEDIATE;//pMSG->dwFlags = DMUS_PMSGF_REFTIME|DMUS_PMSGF_TOOL_IMMEDIATE;
- pMSG->bStatus=(BYTE)(msg&0xFF);
- pMSG->bByte1=(BYTE)((msg>>8)&0xFF);
- pMSG->bByte2=(BYTE)((msg>>16)&0xFF);
- if (FAILED(pPerf->SendPMsg((DMUS_PMSG*)pMSG)))
- {
- pPerf->FreePMsg((DMUS_PMSG*)pMSG);
- }
- }
- }
- static void SendSysex(IDirectMusicPerformance *pPerf,BYTE* data,UINT len)
- {
- DMUS_SYSEX_PMSG *pMSG;
- if(SUCCEEDED(pPerf->AllocPMsg(sizeof(DMUS_SYSEX_PMSG) + len,(DMUS_PMSG**)&pMSG)))
- {
- ZeroMemory(pMSG, sizeof(DMUS_SYSEX_PMSG)+len);
- pMSG->dwSize = sizeof(DMUS_SYSEX_PMSG);
- pMSG->dwPChannel = 0;
- pMSG->dwVirtualTrackID = 0;
- pMSG->dwType = DMUS_PMSGT_SYSEX;
- pMSG->dwVoiceID = 0;
- pMSG->dwGroupID = 0xFFFFFFFF;
- pMSG->dwLen = len;
- memcpy(pMSG->abData, (void*)data, len);
- pMSG->mtTime=0;
- pMSG->dwFlags = DMUS_PMSGF_REFTIME|DMUS_PMSGF_TOOL_IMMEDIATE;//pMSG->dwFlags = |DMUS_PMSGF_TOOL_IMMEDIATE;
- if (FAILED(pPerf->SendPMsg((DMUS_PMSG*)pMSG)))
- {
- pPerf->FreePMsg((DMUS_PMSG*)pMSG);
- }
- }
- }
- static void PortKill()
- {
- #ifdef USE_LOG
- log_write("portkill()");
- #endif
- if (pPort)
- {
- pPort->Activate(0);
- if (pPerf) pPerf->RemovePort(pPort);
- pPort->Release();
- pPort=0;
- }
- }
- static int PortInit(MIDI_device_dmusic * dev)
- {
- #ifdef USE_LOG
- log_write("portinit()");
- #endif
- static int _act_freq;
- static int _cfg_reverb,_cfg_chorus;
- static GUID last_port;
- if (!pPort || last_port!=dev->get_guid() || _act_freq!=cfg_freq || _cfg_reverb!=cfg_reverb || _cfg_chorus!=cfg_chorus)
- {
- #ifdef USE_LOG
- log_write("port settings changed");
- #endif
- if (pPort) PortKill();
- DMUS_PORTPARAMS dmpp;
- ZeroMemory(&dmpp,sizeof(dmpp));
- dmpp.dwSize=sizeof(dmpp);
- dmpp.dwValidParams=DMUS_PORTPARAMS_EFFECTS|DMUS_PORTPARAMS_SAMPLERATE|DMUS_PORTPARAMS_CHANNELGROUPS;
- dmpp.dwChannelGroups=1;
- dmpp.dwSampleRate=cfg_freq;
- if (cfg_reverb) dmpp.dwEffectFlags=DMUS_EFFECT_REVERB;
- if (cfg_chorus) dmpp.dwEffectFlags|=DMUS_EFFECT_CHORUS;
- if (FAILED( pDM->CreatePort(dev->get_dm_guid(),&dmpp,&pPort,0) )) return 0;
-
- pPerf->AddPort(pPort);
- pPerf->AssignPChannelBlock(0,pPort,1);
- last_port = dev->get_guid();
- _act_freq=cfg_freq;
- _cfg_reverb=cfg_reverb;
- _cfg_chorus=cfg_chorus;
- }
- if ((dev->has_output()))
- {
- #ifdef USE_LOG
- log_write("initializing output hack");
- #endif
- DWORD buf_s=0,blah=0;
- pPort->GetFormat(0,&blah,&buf_s);
- pHack=dhb_create(buf_s,cfg_freq);
- if (FAILED(pPort->SetDirectSound(get_ds(),pHack)))
- {//BORK
- PortKill();
- return 0;
- }
- }
- return 1;
- }
- /*
- int lastvol1=(vol==0)?0x80000000:((int)(2000.0*log((double)vol/256.0)));
- if (pPerf)
- {
- return SUCCEEDED(pPerf->SetGlobalParam(GUID_PerfMasterVolume,&lastvol1,4));
- }
- */
- static int DM_setvol(int vol)
- {
- int lastvol1=(vol==0)?0x80000000:((int)(2000.0*log10((double)vol/255.0)));
- if (pPerf)
- {
- return SUCCEEDED(pPerf->SetGlobalParam(GUID_PerfMasterVolume,&lastvol1,4));
- }
- return 0;
- }
- class player_dmusic_imm : public seq_base
- {
- private:
- MIDI_device_dmusic * dev;
- UINT n_ins,s_ins;
- IDirectMusicDownloadedInstrument ** ins;
- IDirectMusicCollection *edls;
- protected:
- virtual void seq_shortmsg(DWORD msg) {SendMsg(pPerf,msg);}
- virtual void seq_sysex(BYTE* d,UINT l) {SendSysex(pPerf,d,l);}
- virtual void eof() {MIDI_core::Eof();}
- int setvol(int t) {return DM_setvol(t);}
- public:
- player_dmusic_imm(MIDI_device_dmusic * p_dev)
- {
- dev=p_dev;
- s_ins=n_ins=0;
- ins=0;
- edls=0;
- if (dev->has_dls())
- {
- s_ins=0x100;
- ins=(IDirectMusicDownloadedInstrument**)malloc(s_ins*sizeof(void*));
- }
-
- }
- ~player_dmusic_imm();
- int play();
- };
- int player_dmusic_imm::play()
- {
- if (!PortInit(dev)) return 0;
- MIDI_file * mf=MIDI_core::getFile();
- if (ins)
- {
- if (mf->pDLSdata)
- {
- LoadDLS(mf);
- if (mf->pDLS)
- {
- edls=mf->pDLS;
- }
- }
-
- if (!edls) edls=pCDLS;
- {
- INSTRUMENT_DESC* instr=GetInstruments(mf,1);
- while(instr)
- {
- DWORD i=instr->patch | (instr->bank_lo<<8) | (instr->bank_hi<<16);
- if (instr->drum) i|=0x80000000;
- if (n_ins>=s_ins)
- {
- s_ins<<=1;
- void *t=realloc(ins,s_ins);
- // if (!t) {s_ins>>=1;return ;}
- ins=(IDirectMusicDownloadedInstrument**)t;
- }
- IDirectMusicInstrument * pi=0;
- start:
- if (edls)
- {
- edls->GetInstrument(i,&pi);
- }
- if (!pi && pGM)
- {
- pGM->GetInstrument(i,&pi);
- }
- if (!pi) //cleaner's hacks don't work here
- {
- if (i&0x80000000)
- {
- if (i&0xFFFF00) {i&=0x800000FF;goto start;}
- }
- else
- {
- if (i&0xFF00) {i&=0xFF00FF;goto start;}
- if (i&0xFF0000) {i&=0xFF;goto start;}
- }
- }
- #if 0
- if (!pi)
- {
- char tmp[128] = {0};
- if (i&0x80000000)
- wsprintf(tmp,"missing drum kit: %u",i&0xFF);
- else
- wsprintf(tmp,"missing instrument: bank %x:%x / patch %x",(i>>16)&0xFF,(i>>8)&0xFF,i&0xFF);
- Warning(tmp);
- }
- #endif
- if (pi)
- {
- // DMUS_NOTERANGE nr = {instr->note_min,instr->note_max};
- // pPort->DownloadInstrument(pi,&ins[n_ins++],&nr,1);
- pPort->DownloadInstrument(pi,&ins[n_ins++],0,0);
- pi->Release();
- }
- {
- INSTRUMENT_DESC * d=instr->next;
- delete instr;
- instr=d;
- }
- }
- }
- }
- /* UINT n;
- for(n=0;n<16;n++)
- {
- pPort->SetChannelPriority(0,n,DAUD_CRITICAL_VOICE_PRIORITY);
- }*/
- pPort->Activate(1);
- DM_setvol(MIDI_core::player_getVol());
- return seq_cmd_start(CLEAN_DM);
- }
- player_dmusic_imm::~player_dmusic_imm()
- {
- seq_cmd_stop();
- if (ins)
- {
- if (pPort)
- {
- pPort->Activate(0);
- UINT n;
- for(n=0;n<n_ins;n++)
- {
- if (ins[n])
- {
- pPort->UnloadInstrument(ins[n]);
- ins[n]=0;
- }
- }
- }
- free(ins);
- }
- if (pHack)
- {
- pPort->SetDirectSound(0,0);
- pHack->Release();
- pHack=0;
- }
- if (!cfg_dm_keep_port) PortKill();
- }
- static void CALLBACK TimerProc(HWND,UINT,UINT id,DWORD)
- {
- DMUS_NOTIFICATION_PMSG* pMsg;
- while(pPerf->GetNotificationPMsg(&pMsg)==S_OK)
- {
- if (IsEqualGUID(pMsg->guidNotificationType,GUID_NOTIFICATION_SEGMENT))
- {
- if (MIDI_core::HavePlayer() && pMsg->dwNotificationOption == DMUS_NOTIFICATION_SEGEND)
- {
- MIDI_core::Eof();
- }
- }
- pPerf->FreePMsg((DMUS_PMSG*)pMsg);
- }
- }
- class player_dmusic : public player_base
- {
- public:
- ~player_dmusic();
- int gettime();
- int settime(int);
- int setvol(int vol) {return DM_setvol(vol);}
- void pause();
- void unpause();
- int play();
- player_dmusic(MIDI_device_dmusic * p_dev)
- {
- dev = p_dev;
- pSeg=0;
- pSS=0;
- rtStart=rtOffset=0;
- mtStart=mtOffset=0;
- }
- private:
- MIDI_device_dmusic * dev;
- IDirectMusicSegment* pSeg;
- IDirectMusicSegmentState* pSS;
- REFERENCE_TIME rtStart,rtOffset;
- MUSIC_TIME mtOffset,mtStart;
- bool dloaded,paused;
- UINT timer_id;
- };
- player_base * MIDI_device_dmusic::create()
- {
- #ifdef USE_LOG
- log_write("DM_create");
- #endif
- CoInitialize(0);
- if (!pLoader)
- {
- try {
-
- CoCreateInstance(CLSID_DirectMusicLoader,0,CLSCTX_INPROC,IID_IDirectMusicLoader,(void**)&pLoader);
- if (!pLoader) return 0;
- pLoader->EnableCache(GUID_DirectMusicAllTypes,0);
- } catch(...) {
- return 0;
- }
- }
- if (!pPerf)
- {
- try {
- CoCreateInstance(CLSID_DirectMusicPerformance,0,CLSCTX_INPROC,IID_IDirectMusicPerformance,(void**)&pPerf);
- if (!pPerf) return 0;
- pPerf->Init(&pDM,0,0);
- pPerf->AddNotificationType(GUID_NOTIFICATION_SEGMENT);
- } catch(...) {
- return 0;
- }
- }
- if (!pGM)
- {
- DMUS_OBJECTDESC desc;
- ZeroMemory(&desc,sizeof(desc));
- desc.dwSize=sizeof(desc);
- desc.dwValidData=DMUS_OBJ_OBJECT|DMUS_OBJ_CLASS;
- desc.guidObject=GUID_DefaultGMCollection;
- desc.guidClass=CLSID_DirectMusicCollection;
- try {
- pLoader->GetObject(&desc,IID_IDirectMusicCollection,(void**)&pGM);
- } catch(...) {
- return 0;
- }
- }
-
- if (has_dls())
- {
- static string current_dls;
- if (!cfg_dls_active)
- {
- if (pCDLS) {pCDLS->Release();pCDLS=0;}
- }
- else
- {
- if (pCDLS && _stricmp(current_dls,cfg_dls_file)) {pCDLS->Release();pCDLS=0;}
- if (!pCDLS)
- {
- DMUS_OBJECTDESC desc;
- ZeroMemory(&desc,sizeof(desc));
- desc.dwSize=sizeof(desc);
- desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
- desc.guidClass = CLSID_DirectMusicCollection;
- mbstowcs(desc.wszFileName,cfg_dls_file,DMUS_MAX_FILENAME);
- if (FAILED(pLoader->GetObject(&desc,IID_IDirectMusicCollection,(void**)&pCDLS)))
- {
- // ErrorBox(Can't load DLS file.);
- pCDLS=0;
- cfg_dls_active=0;
- }
- else
- {
- ReleaseObject(pCDLS);
- current_dls = cfg_dls_file;
- }
- }
- }
- }
- if (cfg_playback_mode)
- {
- player_dmusic_imm * p=new player_dmusic_imm(this);
- if (p)
- {
- if (!p->play())
- {
- delete p;
- p=0;
- }
- }
- return p;
- }
- else
- {
- player_dmusic* p=new player_dmusic(this);
- if (p)
- {
- if (!p->play()) {delete p;p=0;}
- }
- return p;
- }
- }
- MUSIC_TIME GetMTforMS(IDirectMusicSegment* pS,DWORD ms)
- {
- MUSIC_TIME mtSeg,mct=0,mnt;
- DMUS_TEMPO_PARAM tp;
- pS->GetLength(&mtSeg);
- double _r=0,r1;
- while(mct<mtSeg)
- {
- if (FAILED(pS->GetParam(GUID_TempoParam,-1,0,mct,&mnt,&tp))) break;
- if (!mnt) mnt=mtSeg-mct;
- r1=_r;
- _r+=(mnt)/tp.dblTempo*78;
- if (_r>ms)
- {
- return (MUSIC_TIME)(mct+mnt*((double)ms-r1)/(_r-r1));
- }
- mct+=mnt;
- }
- return mtSeg;
- }
- DWORD GetSegLen(IDirectMusicSegment* pS)
- {
- MUSIC_TIME mtSeg,mct=0,mnt;
- DMUS_TEMPO_PARAM tp;
- pS->GetLength(&mtSeg);
- double _r=0;
- while(mct<mtSeg)
- {
- pS->GetParam(GUID_TempoParam,-1,0,mct,&mnt,&tp);
- if (!mnt) mnt=mtSeg-mct;
- _r+=(double)mnt/tp.dblTempo*78;
- mct+=mnt;
- }
- return (DWORD)_r;
- }
- void ReleaseObject(IUnknown* o)
- {
- IDirectMusicObject* pObject=0;
- if (pLoader && SUCCEEDED(o->QueryInterface(IID_IDirectMusicObject,(void**)&pObject)))
- {
- pLoader->ReleaseObject(pObject);
- pObject->Release();
- }
- }
- player_dmusic::~player_dmusic()
- {
- pPerf->Stop(0,0,0,0);
- if (pPort) pPort->Activate(0);
- // pPerf->Invalidate(0,0);
- mtOffset=0;
- rtOffset=0;
- mtStart=0;
- rtStart=0;
- if (pSS) {pSS->Release();pSS=0;}
- if (pSeg)
- {
- if (dloaded) pSeg->SetParam(GUID_Unload,0xFFFFFFFF,0,0,(void*)pPerf);
- pSeg->Release();
- pSeg=0;
- }
- if (pHack)
- {
- pPort->SetDirectSound(0,0);
- pHack->Release();
- pHack=0;
- }
- if (!cfg_dm_keep_port) PortKill();
- if (timer_id) KillTimer(0,timer_id);
- }
- void player_dmusic::pause()
- {
- MUSIC_TIME mt;
- REFERENCE_TIME rt;
- pPerf->Stop(0,0,0,0);
- if (pSS)
- {
- pSS->Release();
- pSS=0;
- }
- pPerf->GetTime(&rt,&mt);
- mtOffset+=mt-mtStart;
- rtOffset+=rt-rtStart;
- pSeg->SetStartPoint(mtOffset);
- paused=1;
- }
- void player_dmusic::unpause()
- {
- if (pSS)
- {
- pSS->Release();
- pSS=0;
- }
- if (SUCCEEDED(pPerf->PlaySegment(pSeg,0,0,&pSS)))
- {
- pSS->GetStartTime(&mtStart);
- pPerf->MusicToReferenceTime(mtStart,&rtStart);
- }
- paused=0;
- }
- int player_dmusic::gettime()
- {
- static DWORD tm;
- if (pSS)
- {
- REFERENCE_TIME rt;
- pPerf->GetTime(&rt,0);
- tm=(int)((rt-rtStart+rtOffset)/10000);
- }
- return tm;
- }
- int player_dmusic::play()
- {
- #ifdef USE_LOG
- log_write("player_dmusic::play()");
- #endif
- if (!PortInit(dev)) return 0;
- pSeg=LoadSegment(MIDI_core::getFile());
- if (!pSeg)
- {
- #ifdef USE_LOG
- log_write("LoadSegment() failed");
- #endif
- // Error("Unable to get IDirectMusicSegment.");
- return 0;
- }
- #ifdef USE_LOG
- log_write("player_dmusic::play() : got IDirectMusicSegment");
- #endif
- pSeg->SetRepeats( (cfg_loop_type==2 || (cfg_loop_type==1 && MIDI_core::getFile()->loopstart)) ? (cfg_loop_infinite ? -1 : cfg_loop_count-1) : 0);
-
- dloaded=0;
- if (dev->has_dls())
- if (SUCCEEDED(pSeg->SetParam(GUID_Download,-1,0,0,(void*)pPerf)))
- dloaded=1;
- pSeg->SetStartPoint(0);
- #ifdef USE_LOG
- log_write("Activating port...");
- #endif
- pPort->Activate(1);
- #ifdef USE_LOG
- log_write("IDirectMusicPort::Activate() returned");
- #endif
- sysex_startup((SYSEXFUNC)SendSysex,pPerf);
- #ifdef USE_LOG
- log_write("IDirectMusicPerformance::PlaySegment()");
- #endif
- pSS=0;
-
- DM_setvol(MIDI_core::player_getVol());
- if (FAILED(pPerf->PlaySegment(pSeg,DMUS_SEGF_DEFAULT,0,&pSS)))
- {
- // Error("IDirectMusicPerformance::PlaySegment() failed.");
- return 0;
- }
- #ifdef USE_LOG
- log_write("IDirectMusicPerformance::PlaySegment() returned OK");
- #endif
-
- rtOffset=0;
- if (pSS)
- {
- pSS->GetStartTime(&mtStart);
- }
- else
- {
- #ifdef USE_LOG
- log_write("no segment starte. WTF ?");
- #endif
- mtStart=0;
- }
- pPerf->MusicToReferenceTime(mtStart,&rtStart);
-
- timer_id=SetTimer(0,0,33,(TIMERPROC)TimerProc);
- return 1;
- }
- static struct
- {
- int name;
- UINT flag;
- } DMCAPZ[]=
- {
- /*
- #define DMUS_PC_DLS (0x00000001) // Supports DLS downloading and DLS level 1.
- #define DMUS_PC_EXTERNAL (0x00000002) // External MIDI module.
- #define DMUS_PC_SOFTWARESYNTH (0x00000004) // Software synthesizer.
- #define DMUS_PC_MEMORYSIZEFIXED (0x00000008) // Memory size is fixed.
- #define DMUS_PC_GMINHARDWARE (0x00000010) // GM sound set is built in, no need to download.
- #define DMUS_PC_GSINHARDWARE (0x00000020) // GS sound set is built in.
- #define DMUS_PC_XGINHARDWARE (0x00000040) // XG sound set is built in.
- #define DMUS_PC_DIRECTSOUND (0x00000080) // Connects to DirectSound via a DSound buffer.
- #define DMUS_PC_SHAREABLE (0x00000100) // Synth can be actively shared by multiple apps at once.
- #define DMUS_PC_DLS2 (0x00000200) // Supports DLS2 instruments.
- #define DMUS_PC_AUDIOPATH (0x00000400) // Multiple outputs can be connected to DirectSound for audiopaths.
- #define DMUS_PC_WAVE (0x00000800) // Supports streaming and one shot waves.
- */
- {STRING_DMCAPS_DLS1,DMUS_PC_DLS},
- {STRING_DMCAPS_DLS2,DMUS_PC_DLS2},
- {STRING_DMCAPS_SOFTSYNTH,DMUS_PC_SOFTWARESYNTH},
- {STRING_DMCAPS_GM,DMUS_PC_GMINHARDWARE},
- {STRING_DMCAPS_GS,DMUS_PC_GSINHARDWARE},
- {STRING_DMCAPS_XG,DMUS_PC_XGINHARDWARE},
- // {STRING_DMCAPS_DSOUND,DMUS_PC_DIRECTSOUND},
- {STRING_DMCAPS_SHARE,DMUS_PC_SHAREABLE},
- };
- #define N_DMCAPZ (sizeof(DMCAPZ)/sizeof(DMCAPZ[0]))
- static struct
- {
- int name;
- UINT flag;
- } DMCAPZ1[]= //effects
- {
- {STRING_REVERB,DMUS_EFFECT_REVERB},
- {STRING_CHORUS,DMUS_EFFECT_CHORUS},
- };
- #define N_DMCAPZ1 (sizeof(DMCAPZ1)/sizeof(DMCAPZ1[0]))
- int player_dmusic::settime(int tm)
- {
- int rv;
- #ifdef USE_LOG
- log_write("player_dmusic::settime");
- #endif
- rtOffset=UInt32x32To64(tm,10000);
- #ifdef USE_LOG
- log_write("calling IDirectMusicPerformance::Stop()");
- #endif
- if (!paused)
- {
- #ifdef USE_LOG
- log_write("IDirectMusicPerformance::Stop() returned");
- #endif
- if (pSS) {pSS->Release();pSS=0;}
- }
- // not ideal but a pause, seek and unpause seems to resolve a failed seek issue
- // with the 'Direct Music / Microsoft Synthesizer' and 'streamed' output mode
- pause();
- MUSIC_TIME time=GetMTforMS(pSeg,tm);
- rv = SUCCEEDED( pSeg->SetStartPoint(time) );
- if (rv) mtOffset=time;
- unpause();
- if (!paused)
- {
- #ifdef USE_LOG
- log_write("calling IDirectMusicPerformance::PlaySegment()");
- #endif
- pSS=0;
- pPerf->PlaySegment(pSeg,0,0,&pSS);
- if (pSS) pSS->GetStartTime(&mtStart);
- pPerf->MusicToReferenceTime(mtStart,&rtStart);
- }
- return rv;
- }
- BOOL test_ins_dls(DWORD patch,IDirectMusicCollection* pDLS)
- {
- IDirectMusicInstrument *pi=0;
- BOOL rv=0;
- if (SUCCEEDED(pDLS->GetInstrument(patch,&pi)))
- {
- pi->Release();
- rv=1;
- }
- return rv;
- }
- int test_drum_kit(DWORD no,IDirectMusicCollection* dls)
- {
- DWORD p=no|0x80000000;
- if (pGM)
- if (test_ins_dls(p,pGM)) return 1;
- if (pCDLS)
- if (test_ins_dls(p,pCDLS)) return 1;
- if (dls)
- if (test_ins_dls(p,dls)) return 1;
- return 0;
- }
- void do_dls_check(DWORD * i,IDirectMusicCollection * dls)
- {
- start:
- if (pGM)
- if (test_ins_dls(*i,pGM)) return;
- if (pCDLS)
- if (test_ins_dls(*i,pCDLS)) return;
- if (dls)
- if (test_ins_dls(*i,dls)) return;
- //hack hack hack
- if (*i&0xFF00)
- {
- *i&=0xFF00FF;
- goto start;
- }
- if (*i&0xFF0000)
- {
- *i&=0xFF;
- return;
- }
- }
- static cfg_int cfg_show_all("dmusic_show_all",0);
- class MIDI_driver_dmusic : MIDI_driver
- {
- bool dm_inited;
- virtual void do_init()
- {
- dm_inited=1;
- try {
- #ifdef USE_LOG
- log_write("CoInitialize()");
- #endif
- CoInitialize(0);
- #ifdef USE_LOG
- log_write("CoCreateInstance / IDirectMusic");
- #endif
- IDirectMusic* pDM=0;
- if (SUCCEEDED(CoCreateInstance(CLSID_DirectMusic,0,CLSCTX_INPROC,IID_IDirectMusic,(void**)&pDM)) && pDM)
- {
- #ifdef USE_LOG
- log_write("IDirectMusic created OK");
- #endif
- DMUS_PORTCAPS dmpc;
- memset(&dmpc,0,sizeof(dmpc));
- dmpc.dwSize=sizeof(dmpc);
- UINT np=0;
- GUID def;
- pDM->GetDefaultPort(&def);
- while(1)
- {
- if (pDM->EnumPort(np++,&dmpc)==S_FALSE) break;
- if (dmpc.dwClass==DMUS_PC_OUTPUTCLASS && (cfg_show_all || (dmpc.dwType!=DMUS_PORT_WINMM_DRIVER && dmpc.dwType==DMUS_PORT_KERNEL_MODE) || (dmpc.dwFlags&DMUS_PC_DLS) ))
- {
- wchar_t name_mbs[2*DMUS_MAX_DESCRIPTION] = {0};
- wcsncpy(name_mbs,dmpc.wszDescription,256);
- string_w info;
- {
- if (dmpc.dwType<3)
- {
- int dmport_types[3]={STRING_DMCAPS_WINMM,STRING_DMCAPS_USERMODE,STRING_DMCAPS_WDM};
- info+=WASABI_API_LNGSTRINGW(STRING_DEVICE_TYPE);
- info+=WASABI_API_LNGSTRINGW(dmport_types[dmpc.dwType]);
- info+=L"\x0d\x0a";
- }
- UINT z;
- for(z=0;z<N_DMCAPZ;z++)
- {
- if (dmpc.dwFlags & DMCAPZ[z].flag)
- {
- info+=WASABI_API_LNGSTRINGW(DMCAPZ[z].name);
- info+=L"\x0d\x0a";
- }
- }
- UINT n_effects=0;
- for(z=0;z<N_DMCAPZ1;z++)
- {
- if (dmpc.dwEffectFlags&DMCAPZ1[z].flag)
- {
- info+=n_effects ? L", " : WASABI_API_LNGSTRINGW(STRING_EFFECTS);
- info+=WASABI_API_LNGSTRINGW(DMCAPZ1[z].name);
- n_effects++;
- }
- }
- if (n_effects) info+=L"\x0d\x0a";
- }
- add_device(new MIDI_device_dmusic(dmpc.guidPort,0,dmpc.dwFlags,name_mbs,info));
- if ((dmpc.dwFlags&DMUS_PC_DIRECTSOUND)&&(dmpc.dwFlags&DMUS_PC_SOFTWARESYNTH))
- {
- wcscat(name_mbs,WASABI_API_LNGSTRINGW(IDS_WITH_OUTPUT));
- info+=WASABI_API_LNGSTRINGW(IDS_USES_WINAMPS_OUTPUT_PLUGINS);
- add_device(new MIDI_device_dmusic(dmpc.guidPort,1,dmpc.dwFlags,name_mbs,info));
- }
- }
- }
- pDM->Release();
- }
- } catch(...) {
- // bewm.
- reset_devices();
- }
- }
- virtual const wchar_t * get_name() {return L"DirectMusic";}
- virtual GUID get_guid() {return dmusic_driver_guid;}
- public:
- MIDI_driver_dmusic() {dm_inited=0;}
- protected:
- void do_deinit()
- {
- if (!dm_inited) return;
- if (pGM)
- {
- pGM->Release();
- pGM=0;
- }
- if (pCDLS) {pCDLS->Release();pCDLS=0;}
- if (pLoader) {pLoader->Release();pLoader=0;}
- if (pPort) PortKill();
- if (pDM)
- {
- pDM->Release();
- pDM=0;
- }
- if (pPerf)
- {
- pPerf->CloseDown();
- pPerf->Release();
- pPerf=0;
- }
- CoUninitialize();
- }
- };
- static MIDI_driver_dmusic midi_driver_dmusic;
|