diff options
Diffstat (limited to 'Src/Plugins/Output/out_ds/ds2.h')
-rw-r--r-- | Src/Plugins/Output/out_ds/ds2.h | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/Src/Plugins/Output/out_ds/ds2.h b/Src/Plugins/Output/out_ds/ds2.h new file mode 100644 index 00000000..ae8593b3 --- /dev/null +++ b/Src/Plugins/Output/out_ds/ds2.h @@ -0,0 +1,237 @@ +#ifndef _DS2_H +#define _DS2_H + +#ifndef STRICT +#define STRICT +#endif +#include <windows.h> +#include <mmsystem.h> +#include <dsound.h> + +#include "ds_main.h" +#include "Config.h" +#include "SoundBlockList.h" +#include "DevEnum.h" +#include "VolCtrl.h" + +class CriticalSection : public CRITICAL_SECTION +{ +public: + inline void Enter() {EnterCriticalSection(this);} + inline void Leave() {LeaveCriticalSection(this);} + CriticalSection() {InitializeCriticalSection(this);} + ~CriticalSection() {DeleteCriticalSection(this);} + //BOOL TryEnter() {return TryEnterCriticalSection(this);} +}; + +typedef struct +{ + UINT sr,bps,nch; + UINT buf_size_bytes,buf_size_ms; + UINT pos_play,pos_write,latency,latency_ms; + UINT lock_count; + UINT underruns; + size_t bytes_async; + __int64 bytes_written,bytes_played; + double vol_left,vol_right; + GUID current_device; + bool have_primary_buffer; + bool paused; + DWORD dscaps_flags; + DWORD dscaps_flags_primary; +} DS2_REALTIME_STAT; + + +class DS2 +{ +private: + + DS2(DS2config * cfg); + + SoundBlockList BlockList; + UINT LockCount; + UINT Underruns; + + bool DoLock(); + +public: + ~DS2(); + int WriteData(void * data,UINT size,bool *killswitch);//returns 1 on success and 0 on failure + int WriteDataNow(void * data,UINT size);//sleep-less version, writes CanWrite() of bytes immediately, returns amount of data written + int ForceWriteData(void * data,UINT size);//sleep-less force-write all the data w/o sleep/canwrite (async buffer has no size limit), use with caution + + /* + how to use writedata shit + + a) just WriteData(), will sleep until its done + b) WriteDataNow() until we're done (writes as much data as possible at the moment, without sleep) + c) ForceWriteData() (evil!), then sleep while CanWrite()<0 + + */ + + void StartNewStream(); + + UINT GetLatency(); + void _inline Release() {delete this;}//obsolete + void Pause(int new_state); + void SetVolume(double); + inline void SetVolume_Int(int i) {SetVolume((double)i/255.0);} + void SetPan(double); + inline void SetPan_Int(int i) {SetPan((double)i/128.0);} + void Flush();//causes problems with some um.. drivers + int CanWrite();//can be negative !!!!!!! (eg. after ForceWriteData) + inline UINT BufferStatusPercent() {return MulDiv(data_buffered+(UINT)BlockList.DataSize(),buf_size,100);} + void ForcePlay(); + void KillEndGap(); + +#ifdef DS2_HAVE_FADES + void FadePause(UINT time); + void FadeAndForget(UINT time); + void Fade(UINT time,double destvol); + inline void Fade_Int(UINT time,int destvol) {Fade(time,(double)destvol/255.0);} + void FadeX(UINT time,double destvol);//actual fade time depends on volume difference + inline void FadeX_Int(UINT time,int destvol) {FadeX(time,(double)destvol/255.0);} + +#endif + + void WaitFor(DS2 * prev,UINT fadeout=0); + + //gapless mode stuff + void SetCloseOnStop(bool b); + bool IsClosed(); + +private: +#ifdef _DEBUG + DWORD serial; + UINT sync_n; +#endif + + int Open(DS2config * cfg); + DS2 * next; + DS2 * wait; + UINT prebuf; + DWORD flags; + enum + { + FLAG_UPDATED=1, + FLAG_WAITED=1<<1, + FLAG_NEED_PLAY_NOW=1<<2, + FLAG_DIE_ON_STOP=1<<3, + FLAG_CLOSE_ON_STOP=1<<4, + FLAG_PAUSED=1<<5, + FLAG_PLAYING=1<<6, +// FLAG_UNDERRUNNING=1<<7, + FLAG_USE_CPU_MNGMNT=1<<8, + FLAG_FADEPAUSE=1<<9, + FLAG_FADEPAUSING=1<<10, + FLAG_STARTSIL=1<<11, + FLAG_SWMIXED=1<<12, + }; + IDirectSoundBuffer * pDSB; + IDirectSound * myDS; + UINT fmt_nch,fmt_bps,fmt_sr,fmt_mul; + UINT buf_size,clear_size; + __int64 last_nonsil,pos_delta,pos_delta2; + inline __int64 GetCurPos() {return data_written-data_buffered;} + __int64 GetSafeWrite(); + __int64 data_written; + UINT data_buffered; + UINT silence_buffered; + + UINT bytes2ms(UINT bytes); + UINT ms2bytes(UINT ms); + + +#ifdef DS2_HAVE_FADES + DsVolCtrl VolCtrl; + double fadepause_orgvol; + UINT fadepause_time; + UINT waitfade; + +#else + class DsVolCtrl + { + private: + double CurVol,CurPan; + public: + DsVolCtrl() {CurVol=1;CurPan=0;} + inline void SetTime(__int64) {} + inline void SetFade(__int64,double) {} + inline void SetFadeVol(__int64,double,double) {} + inline void SetFadePan(__int64,double,double) {} + inline void SetVolume(double v) {CurVol=v;} + inline void SetPan(double p) {CurPan=p;} +// inline __int64 RelFade(__int64 max,double destvol) {return 0;} + void Apply(IDirectSoundBuffer * pDSB); + inline bool Fading() {return 0;} +// inline double GetCurVol() {return CurVol;} +// inline double GetDestVol() {return CurVol;} + inline void Reset() {} + }; + DsVolCtrl VolCtrl; +#endif + + void SetVolumeI(double); + void SetPanI(int _pan); + void _setvol(); + void _setpan(); + void update_pos(); + void ds_stop(); + void ds_kill(); + bool Update(); + + void reset_vars(); + void do_reset_vars(); + + int silence_delta; + void test_silence(char * buf,int len,int * first,int* last); + + static DWORD WINAPI ThreadFunc(void*); + UINT _inline _align() {return (fmt_bps>>3)*fmt_nch;} + UINT _inline _align_var(UINT var) {return var-(var%_align());} + + + static void SYNC_IN(); + static void SYNC_OUT(); + + typedef HRESULT (WINAPI *tDirectSoundCreate)( const GUID * lpGuid, LPDIRECTSOUND * ppDS, IUnknown FAR * pUnkOuter ); + static tDirectSoundCreate pDirectSoundCreate; + + static IDirectSound * pDS; + +public: + + static void Init();//init is OBSOLETE + static void Quit(bool wait=0);//must be called on exit, NOT from DllMain, its ok to call it if init never happened + + static DS2 * Create(DS2config * cfg); + + static bool InitDLL();//used internally + + static HRESULT myDirectSoundCreate(const GUID * g,IDirectSound ** out); + + static void SetTotalTime(__int64); + static __int64 GetTotalTime(); + static UINT InstanceCount(); + + void GetRealtimeStat(DS2_REALTIME_STAT * stat); + static bool GetRealtimeStatStatic(DS2_REALTIME_STAT * stat); + __int64 GetOutputTime(); + +#ifdef DS2_HAVE_DEVICES + static bool TryGetDevCaps(const GUID *g,LPDSCAPS pCaps,DWORD * speakercfg=0);//for current device + + typedef HRESULT (WINAPI *tDirectSoundEnumerate)(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext); + static tDirectSoundEnumerate pDirectSoundEnumerate; + + static GUID GetCurDev(); +#endif + + +#ifdef DS2_HAVE_PITCH + void SetPitch(double p); +#endif + +}; + +#endif
\ No newline at end of file |