mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-05 06:00:33 -04:00
632 lines
No EOL
14 KiB
C++
632 lines
No EOL
14 KiB
C++
// WAInputPlugin.cpp: implementation of the WAInputPlugin class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "WAInputPlugin.h"
|
|
#include <malloc.h>
|
|
#include <direct.h>
|
|
#include "wa_ipc.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#define MAX_PLUGINS_AT_TIME 16
|
|
|
|
#define DECLARE_TEMPLATES(x) \
|
|
x(0)\
|
|
x(1)\
|
|
x(2)\
|
|
x(3)\
|
|
x(4)\
|
|
x(5)\
|
|
x(6)\
|
|
x(7)\
|
|
x(8)\
|
|
x(9)\
|
|
x(10)\
|
|
x(11)\
|
|
x(12)\
|
|
x(13)\
|
|
x(14)\
|
|
x(15)\
|
|
/* x(16)\
|
|
x(17)\
|
|
x(18)\
|
|
x(19)\
|
|
x(20)\
|
|
x(21)\
|
|
x(22)\
|
|
x(23)\
|
|
x(24)\
|
|
x(25)\
|
|
x(26)\
|
|
x(27)\
|
|
x(28)\
|
|
x(29)\
|
|
x(30)\
|
|
x(31)\*/
|
|
|
|
|
|
#define JOIN(x,y) &x##y
|
|
|
|
#define DECLARE_TEMPLATE_ARRAYS(x) \
|
|
static void *p_##x[]={JOIN(x,_0),JOIN(x,_1),JOIN(x,_2),JOIN(x,_3),JOIN(x,_4),JOIN(x,_5),JOIN(x,_6),JOIN(x,_7),\
|
|
JOIN(x,_8),JOIN(x,_9),JOIN(x,_10),JOIN(x,_11),JOIN(x,_12),JOIN(x,_13),JOIN(x,_14),JOIN(x,_15)/*,\
|
|
JOIN(x,_16),JOIN(x,_17),JOIN(x,_18),JOIN(x,_19),JOIN(x,_20),JOIN(x,_21),JOIN(x,_22),JOIN(x,_23),\
|
|
JOIN(x,_24),JOIN(x,_25),JOIN(x,_26),JOIN(x,_27),JOIN(x,_28),JOIN(x,_29),JOIN(x,_30),JOIN(x,_31)*/\
|
|
};
|
|
|
|
|
|
WAInputPlugin::WAInputPlugin()
|
|
{
|
|
_inPlugin=0;
|
|
_mod=0;
|
|
_ioutput=0;
|
|
_finished=false;
|
|
_hNotify=0;
|
|
}
|
|
|
|
WAInputPlugin::~WAInputPlugin()
|
|
{
|
|
UnloadPlugin();
|
|
}
|
|
|
|
typedef In_Module * (*type_winampGetInModule2)();
|
|
|
|
static void empty_SAVSAInit(int maxlatency_in_ms, int srate)
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_SAVSADeInit()
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_SAAddPCMData(void *PCMData, int nch, int bps, int timestamp)
|
|
{
|
|
|
|
}
|
|
|
|
static int empty_SAGetMode()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static void empty_SAAdd(void *data, int timestamp, int csa)
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_VSAAddPCMData(void *PCMData, int nch, int bps, int timestamp)
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_VSAAdd(void *data, int timestamp)
|
|
{
|
|
|
|
}
|
|
|
|
static int empty_VSAGetMode(int *specNch, int *waveNch)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void empty_VSASetInfo(int nch, int srate)
|
|
{
|
|
|
|
}
|
|
|
|
static int empty_dsp_isactive()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int empty_dsp_dosamples(short int *samples, int numsamples, int bps, int nch, int srate)
|
|
{
|
|
return numsamples;
|
|
}
|
|
|
|
static void empty_SetInfo(int bitrate, int srate, int stereo, int synched)
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_About(HWND hWnd)
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_Config(HWND hWnd)
|
|
{
|
|
|
|
}
|
|
|
|
static void empty_Init()
|
|
{
|
|
|
|
}
|
|
static void empty_Quit()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
class RegistredPlugsArray
|
|
{
|
|
WAInputPlugin *_arr[MAX_PLUGINS_AT_TIME];
|
|
public:
|
|
RegistredPlugsArray() {memset(_arr,0,sizeof(_arr));}
|
|
int Register(WAInputPlugin *plug);
|
|
void Unregister(WAInputPlugin *plug);
|
|
WAInputPlugin *operator[] (int index) {return _arr[index];}
|
|
};
|
|
|
|
int RegistredPlugsArray::Register(WAInputPlugin *plug)
|
|
{
|
|
for (int i=0;i<MAX_PLUGINS_AT_TIME;i++) if (_arr[i]==0)
|
|
{
|
|
_arr[i]=plug;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void RegistredPlugsArray::Unregister(WAInputPlugin *plug)
|
|
{
|
|
for (int i=0;i<MAX_PLUGINS_AT_TIME;i++) if (_arr[i]==plug) _arr[i]=0;
|
|
}
|
|
|
|
static RegistredPlugsArray GRegistredPlugsArray;
|
|
|
|
#define m_Open(index)\
|
|
static int output_Open_##index(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms)\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) return o->Open(samplerate, numchannels, bitspersamp, bufferlenms, prebufferms);\
|
|
return -1;\
|
|
}
|
|
|
|
#define m_Close(index)\
|
|
static void output_Close_##index()\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) o->Close();\
|
|
}
|
|
|
|
#define m_Write(index)\
|
|
static int output_Write_##index(char *buff, int len)\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) return o->Write(buff,len);\
|
|
return 1;\
|
|
}
|
|
|
|
#define m_CanWrite(index)\
|
|
static int output_CanWrite_##index()\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) return o->CanWrite();\
|
|
return 0;\
|
|
}
|
|
|
|
#define m_IsPlaying(index)\
|
|
static int output_IsPlaying_##index()\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
int p=o->IsPlaying();\
|
|
return p;\
|
|
}
|
|
|
|
#define m_Pause(index)\
|
|
static int output_Pause_##index(int pause)\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) return o->Pause(pause);\
|
|
return 0;\
|
|
}
|
|
|
|
#define m_SetVolume(index)\
|
|
static void output_SetVolume_##index(int volume)\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) o->SetVolume(volume);\
|
|
}
|
|
|
|
#define m_SetPan(index)\
|
|
static void output_SetPan_##index(int pan)\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) o->SetPan(pan);\
|
|
}
|
|
|
|
#define m_Flush(index)\
|
|
static void output_Flush_##index(int t)\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) o->Flush(t);\
|
|
}
|
|
|
|
#define m_GetOutputTime(index)\
|
|
static int output_GetOutputTime_##index()\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) return o->GetOutputTime();\
|
|
return 0;\
|
|
}
|
|
|
|
#define m_GetWrittenTime(index)\
|
|
static int output_GetWrittenTime_##index()\
|
|
{\
|
|
IWAOutput *o=GRegistredPlugsArray[index]->GetAttachedOutputNoAddRef();\
|
|
if (o) return o->GetWrittenTime();\
|
|
return 0;\
|
|
}
|
|
|
|
DECLARE_TEMPLATES(m_Open);
|
|
DECLARE_TEMPLATES(m_Close);
|
|
DECLARE_TEMPLATES(m_Write);
|
|
DECLARE_TEMPLATES(m_CanWrite);
|
|
DECLARE_TEMPLATES(m_IsPlaying);
|
|
DECLARE_TEMPLATES(m_Pause);
|
|
DECLARE_TEMPLATES(m_SetVolume);
|
|
DECLARE_TEMPLATES(m_SetPan);
|
|
DECLARE_TEMPLATES(m_Flush);
|
|
DECLARE_TEMPLATES(m_GetOutputTime);
|
|
DECLARE_TEMPLATES(m_GetWrittenTime);
|
|
|
|
DECLARE_TEMPLATE_ARRAYS(output_Open);
|
|
DECLARE_TEMPLATE_ARRAYS(output_Close);
|
|
DECLARE_TEMPLATE_ARRAYS(output_Write);
|
|
DECLARE_TEMPLATE_ARRAYS(output_CanWrite);
|
|
DECLARE_TEMPLATE_ARRAYS(output_IsPlaying);
|
|
DECLARE_TEMPLATE_ARRAYS(output_Pause);
|
|
DECLARE_TEMPLATE_ARRAYS(output_SetVolume);
|
|
DECLARE_TEMPLATE_ARRAYS(output_SetPan);
|
|
DECLARE_TEMPLATE_ARRAYS(output_Flush);
|
|
DECLARE_TEMPLATE_ARRAYS(output_GetOutputTime);
|
|
DECLARE_TEMPLATE_ARRAYS(output_GetWrittenTime);
|
|
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::UIConfig(HWND parentHwnd)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->Config(parentHwnd);
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::UIAbout(HWND parentHwnd)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->About(parentHwnd);
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::UnloadPlugin()
|
|
{
|
|
if (_inPlugin!=0)
|
|
{
|
|
__try
|
|
{
|
|
_inPlugin->Quit();
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
_mod=0; //prevent calling FreeLibrary.... plugin cannot be unloaded....
|
|
}
|
|
_inPlugin=0;
|
|
}
|
|
if (_hNotify)
|
|
{
|
|
DestroyWindow(_hNotify);
|
|
_hNotify=0;
|
|
}
|
|
if (_mod)
|
|
{
|
|
FreeLibrary(_mod);
|
|
_mod=0;
|
|
}
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::IsLoaded()
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
return errOk;
|
|
}
|
|
|
|
const char *WAInputPlugin::GetDescription()
|
|
{
|
|
if (_inPlugin==0) return 0;
|
|
return _inPlugin->description;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::GetFileInfo(const char *filename, char *title, int title_size, int *len_in_ms)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
char *buff=new char[4096];
|
|
DWORD r=GetTickCount();
|
|
memcpy(buff+4092,&r,4);
|
|
_inPlugin->GetFileInfo(const_cast<char *>(filename),buff,len_in_ms);
|
|
if (memcmp(buff+4092,&r,4)==0)
|
|
{
|
|
return errPluginBufferOverrun;
|
|
}
|
|
int len=strlen(buff);
|
|
if (len>=title_size)
|
|
{
|
|
strncpy(title,buff,title_size);
|
|
return errBufferTooSmall;
|
|
}
|
|
else
|
|
{
|
|
strcpy(title,buff);
|
|
return errOk;
|
|
}
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::UIFileInfo(const char *filename, HWND parentHwnd)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->InfoBox(const_cast<char *>(filename),parentHwnd);
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::CanPlayFile(const char *filename)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
if (_inPlugin->IsOurFile(const_cast<char *>(filename))) return errOk;
|
|
char *fext=_inPlugin->FileExtensions;
|
|
const char *bslash=strrchr(filename,'\\');
|
|
if (bslash==0) bslash=filename;
|
|
const char *ext=strrchr(bslash,'.');
|
|
if (ext==0) ext=strchr(bslash,0);
|
|
else ext++;
|
|
int extlen=strlen(ext);
|
|
while (*fext)
|
|
{
|
|
if (strnicmp(fext,ext,extlen)==0 && (fext[extlen]==';' || fext[extlen]==0))
|
|
return errOk;
|
|
char *c=strchr(fext,';');
|
|
if (c==0)
|
|
{
|
|
c=strchr(fext,0);
|
|
c++;
|
|
if (*c) c=strchr(c,0)+1;
|
|
fext=c;
|
|
}
|
|
else
|
|
fext=c+1;
|
|
}
|
|
return errUnknownFileFormat;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::AttachOutput(IWAOutput *o)
|
|
{
|
|
if (_ioutput==o) return errOk;
|
|
if ((_ioutput!=0)!=(o!=0))
|
|
{
|
|
if (o==0) GRegistredPlugsArray.Unregister(this);
|
|
else
|
|
{
|
|
int plugid=GRegistredPlugsArray.Register(this);
|
|
if (plugid==-1) return errTooManyPlugins;
|
|
|
|
_output.About=empty_About;
|
|
_output.Config=empty_Config;
|
|
_output.Init=empty_Init;
|
|
_output.Quit=empty_Quit;
|
|
*(void **)&_output.CanWrite=p_output_CanWrite[plugid];
|
|
*(void **)&_output.Close=p_output_Close[plugid];
|
|
*(void **)&_output.Flush=p_output_Flush[plugid];
|
|
*(void **)&_output.GetOutputTime=p_output_GetOutputTime[plugid];
|
|
*(void **)&_output.GetWrittenTime=p_output_GetWrittenTime[plugid];
|
|
*(void **)&_output.IsPlaying=p_output_IsPlaying[plugid];
|
|
*(void **)&_output.Open=p_output_Open[plugid];
|
|
*(void **)&_output.Pause=p_output_Pause[plugid];
|
|
*(void **)&_output.SetPan=p_output_SetPan[plugid];
|
|
*(void **)&_output.SetVolume=p_output_SetVolume[plugid];
|
|
*(void **)&_output.Write=p_output_Write[plugid];
|
|
_output.hDllInstance=GetModuleHandle(0);
|
|
_output.hMainWindow=0;
|
|
_output.description="Emulated output device";
|
|
_output.version=0x100;
|
|
_output.id=999999999;
|
|
}
|
|
}
|
|
if (_ioutput!=0) _ioutput->Release();
|
|
_ioutput=o;
|
|
if (o) o->AddRef();
|
|
return errOk;
|
|
}
|
|
|
|
#define WM_WA_MPEG_EOF WM_USER+2
|
|
#define IPC_GET_API_SERVICE 3025
|
|
|
|
|
|
static LRESULT NotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_WA_MPEG_EOF:
|
|
{
|
|
WAInputPlugin *o=(WAInputPlugin *)GetWindowLong(hWnd,GWL_USERDATA);
|
|
if (o) o->MarkFinished();
|
|
return 0;
|
|
}
|
|
case WM_USER:
|
|
{
|
|
switch (lParam)
|
|
{
|
|
case IPC_GETINIFILE:
|
|
{
|
|
return (LRESULT)("skeldalmusic.ini");
|
|
}
|
|
case IPC_GETINIDIRECTORY:
|
|
{
|
|
return (LRESULT)(".\\");
|
|
}
|
|
case IPC_GET_API_SERVICE: return 0;
|
|
case IPC_GET_RANDFUNC: return (LRESULT)&rand;
|
|
}
|
|
}
|
|
default: return DefWindowProc(hWnd,msg,wParam,lParam);
|
|
}
|
|
}
|
|
|
|
static const char *RegisterWAPluginWnd()
|
|
{
|
|
const char *name="WAPluginWnd";
|
|
WNDCLASS cls;
|
|
if (GetClassInfo(GetModuleHandle(0),name,&cls)==FALSE)
|
|
{
|
|
memset(&cls,0,sizeof(cls));
|
|
cls.lpszClassName=name;
|
|
cls.hInstance=GetModuleHandle(0);
|
|
cls.lpfnWndProc=(WNDPROC)NotifyWndProc;
|
|
RegisterClass(&cls);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::LoadPlugin(const char *name)
|
|
{
|
|
UnloadPlugin();
|
|
char *cwd=_getcwd(0,0);
|
|
char *setcwd=strcpy((char *)alloca(strlen(name)+1),name);
|
|
char *bs=const_cast<char *>(strrchr(setcwd,'\\'));
|
|
if (bs)
|
|
{
|
|
*bs=0;
|
|
bs=const_cast<char *>(strrchr(setcwd,'\\'));
|
|
if (bs) *bs=0;
|
|
}
|
|
_chdir(setcwd);
|
|
SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
_mod=LoadLibrary(name);
|
|
_chdir(cwd);
|
|
free(cwd);
|
|
if (_mod==0) return errNotFound;
|
|
type_winampGetInModule2 winampGetInModule2=(type_winampGetInModule2)GetProcAddress(_mod,"winampGetInModule2");
|
|
if (winampGetInModule2==0) return errNotValidPlugin;
|
|
_inPlugin=winampGetInModule2();
|
|
if (_inPlugin==0) return errCantInit;
|
|
_hNotify=CreateWindow(RegisterWAPluginWnd(),"",0,0,0,0,0,0,0,GetModuleHandle(0),0);
|
|
SetWindowLong(_hNotify,GWL_USERDATA,(LONG)this);
|
|
_inPlugin->hMainWindow=_hNotify;
|
|
_inPlugin->hDllInstance=_mod;
|
|
_inPlugin->SAVSAInit=empty_SAVSAInit;
|
|
_inPlugin->SAVSADeInit=empty_SAVSADeInit;
|
|
_inPlugin->SAAddPCMData=empty_SAAddPCMData;
|
|
_inPlugin->SAGetMode=empty_SAGetMode;
|
|
_inPlugin->SAAdd=empty_SAAdd;
|
|
_inPlugin->VSAAddPCMData=empty_VSAAddPCMData;
|
|
_inPlugin->VSAGetMode=empty_VSAGetMode;
|
|
_inPlugin->VSAAdd=empty_VSAAdd;
|
|
_inPlugin->VSASetInfo=empty_VSASetInfo;
|
|
_inPlugin->dsp_isactive=empty_dsp_isactive;
|
|
_inPlugin->dsp_dosamples=empty_dsp_dosamples;
|
|
_inPlugin->SetInfo=empty_SetInfo;
|
|
_inPlugin->outMod=0;
|
|
__try
|
|
{
|
|
_inPlugin->Init();
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
__try
|
|
{
|
|
_inPlugin->Quit();
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
_mod=0; //Free library cannot be called, because plugin cannot be terminated... memory and resource leak
|
|
}
|
|
_inPlugin=0;
|
|
return errGPF;
|
|
}
|
|
_inPlugin->outMod=&_output;
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::Play(const char *name)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_finished=false;
|
|
int i=_inPlugin->Play(const_cast<char *>(name));
|
|
if (i==0) return errOk;
|
|
if (i==-1) return errFileNotFound;
|
|
return errCantPlay;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::Pause()
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->Pause();
|
|
return errOk;
|
|
}
|
|
WAInputPlugin::PluginError WAInputPlugin::UnPause()
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->UnPause();
|
|
return errOk;
|
|
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::IsPaused()
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
if (_inPlugin->IsPaused()) return errOk;
|
|
return errFalse;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::Stop()
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->Pause();
|
|
_inPlugin->UnPause();
|
|
_inPlugin->Stop();
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::SetOutputTime(int t)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->SetOutputTime(t);
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::SetVolume(int volume)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->SetVolume(volume);
|
|
return errOk;
|
|
|
|
}
|
|
WAInputPlugin::PluginError WAInputPlugin::SetPan(int pan)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->SetPan(pan);
|
|
return errOk;
|
|
}
|
|
|
|
WAInputPlugin::PluginError WAInputPlugin::EQSet(int on, char data[10], int preamp)
|
|
{
|
|
if (_inPlugin==0) return errNotLoaded;
|
|
_inPlugin->EQSet(on,data,preamp);
|
|
return errOk;
|
|
}
|
|
|
|
bool WAInputPlugin::IsFinished()
|
|
{
|
|
MSG msg;
|
|
if (PeekMessage(&msg,_hNotify,WM_WA_MPEG_EOF,WM_WA_MPEG_EOF,PM_REMOVE))
|
|
{
|
|
DispatchMessage(&msg);
|
|
}
|
|
return _finished;
|
|
} |