Directshow: Added a "buffering" option, now properly sorts data packets, made it so crossbar is available only if the current device shows it, and made some improvements to the audio devices combobox and moved it to the audio group

master
jp9000 2013-04-05 16:54:07 -07:00
parent 6d3153c33d
commit a7a49d2c0c
7 changed files with 480 additions and 316 deletions

View File

@ -198,9 +198,9 @@ STDMETHODIMP CapturePin::Receive(IMediaSample *pSample)
if(pSample)
{
if(expectedMajorType == MEDIATYPE_Video)
source->ReceiveVideo(pSample);
source->ReceiveMediaSample(pSample, false);
else if(expectedMajorType == MEDIATYPE_Audio)
source->ReceiveAudio(pSample);
source->ReceiveMediaSample(pSample, true);
}
return S_OK;
}

View File

@ -161,7 +161,7 @@ IBaseFilter* GetDeviceByValue(const IID &enumType, WSTR lpType, CTSTR lpName, WS
IEnumMoniker *videoDeviceEnum;
HRESULT err;
err = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&deviceEnum);
err = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&deviceEnum);
if(FAILED(err))
{
AppWarning(TEXT("GetDeviceByValue: CoCreateInstance for the device enum failed, result = %08lX"), err);
@ -567,8 +567,6 @@ struct ConfigDialogData
StringList deviceIDList;
StringList audioNameList;
StringList audioIDList;
StringList crossbarList;
StringList crossbarIDList;
bool bGlobalSource;
bool bCreating;
bool bDeviceHasAudio;
@ -678,7 +676,7 @@ bool FillOutListOfDevices(HWND hwndCombo, GUID matchGUID, StringList *deviceList
IEnumMoniker *videoDeviceEnum;
HRESULT err;
err = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&deviceEnum);
err = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&deviceEnum);
if(FAILED(err))
{
AppWarning(TEXT("FillOutListDevices: CoCreateInstance for the device enum failed, result = %08lX"), err);
@ -869,38 +867,75 @@ struct ColorSelectionData
}
};
void OpenPropertyPages(HWND hwnd, String devicename, String deviceid, GUID matchGUID) {
IBaseFilter *filter = GetDeviceByValue(matchGUID,
L"FriendlyName", devicename,
L"DevicePath", deviceid);
if(filter)
{
ISpecifyPropertyPages *propPages;
CAUUID cauuid;
static void OpenPropertyPages(HWND hwnd, IUnknown *propObject)
{
if(!propObject)
return;
if(SUCCEEDED(filter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&propPages)))
ISpecifyPropertyPages *propPages;
CAUUID cauuid;
if(SUCCEEDED(propObject->QueryInterface(IID_ISpecifyPropertyPages, (void**)&propPages)))
{
if(SUCCEEDED(propPages->GetPages(&cauuid)))
{
if(SUCCEEDED(propPages->GetPages(&cauuid)))
if(cauuid.cElems)
{
if(cauuid.cElems)
{
OleCreatePropertyFrame(hwnd, 0, 0, NULL, 1, (LPUNKNOWN*)&filter, cauuid.cElems, cauuid.pElems, 0, 0, NULL);
CoTaskMemFree(cauuid.pElems);
}
OleCreatePropertyFrame(hwnd, 0, 0, NULL, 1, (LPUNKNOWN*)&propObject, cauuid.cElems, cauuid.pElems, 0, 0, NULL);
CoTaskMemFree(cauuid.pElems);
}
propPages->Release();
}
propPages->Release();
}
}
static void OpenPropertyPagesByName(HWND hwnd, String devicename, String deviceid, GUID matchGUID)
{
IBaseFilter *filter = GetDeviceByValue(matchGUID,
L"FriendlyName", devicename,
L"DevicePath", deviceid);
if(filter)
{
OpenPropertyPages(hwnd, filter);
filter->Release();
}
}
return;
static IAMCrossbar *GetFilterCrossbar(IBaseFilter *filter)
{
IAMCrossbar *crossbar = NULL;
IGraphBuilder *graph = NULL;
ICaptureGraphBuilder2 *capture = NULL;
IAMStreamConfig *configVideo = NULL;
if (FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, (REFIID)IID_IFilterGraph, (void**)&graph)))
goto crossbar_exit;
if (FAILED(CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, (REFIID)IID_ICaptureGraphBuilder2, (void**)&capture)))
goto crossbar_exit;
if (FAILED(capture->SetFiltergraph(graph)))
goto crossbar_exit;
if (FAILED(graph->AddFilter(filter, L"Capture device")))
goto crossbar_exit;
capture->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, filter, IID_IAMStreamConfig, (void**)&configVideo);
capture->FindInterface(NULL, NULL, filter, IID_IAMCrossbar, (void**)&crossbar);
graph->RemoveFilter(filter);
crossbar_exit:
SafeRelease(configVideo);
SafeRelease(capture);
SafeRelease(graph);
return crossbar;
}
INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool bSelectingColor = false;
static bool bMouseDown = false, audioInputDevicesPresent = true;
static bool bMouseDown = false, bAudioDevicesPresent = true;
static ColorSelectionData colorData;
switch(message)
@ -913,7 +948,6 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
HWND hwndDeviceList = GetDlgItem(hwnd, IDC_DEVICELIST);
HWND hwndAudioList = GetDlgItem(hwnd, IDC_AUDIOLIST);
HWND hwndCrossbarList = GetDlgItem(hwnd, IDC_CROSSBARLIST);
HWND hwndResolutionList = GetDlgItem(hwnd, IDC_RESOLUTION);
HWND hwndFPS = GetDlgItem(hwnd, IDC_FPS);
HWND hwndFlip = GetDlgItem(hwnd, IDC_FLIPIMAGE);
@ -947,23 +981,10 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
LocalizeWindow(hwnd, pluginLocale);
FillOutListOfDevices(hwndDeviceList, CLSID_VideoInputDeviceCategory, &configData->deviceNameList, &configData->deviceIDList);
audioInputDevicesPresent = FillOutListOfDevices(hwndAudioList, CLSID_AudioInputDeviceCategory, &configData->audioNameList, &configData->audioIDList);
bool bCrossbarAvailable = FillOutListOfDevices(hwndCrossbarList, AM_KSCATEGORY_CROSSBAR, &configData->crossbarList, &configData->crossbarIDList);
if(bCrossbarAvailable)
SendMessage(hwndCrossbarList, CB_SETCURSEL, 0, 0);
EnableWindow(GetDlgItem(hwnd, IDC_CROSSBAR), bCrossbarAvailable);
EnableWindow(hwndCrossbarList, bCrossbarAvailable);
UINT deviceID = CB_ERR;
UINT audioDeviceID = CB_ERR;
if(strDevice.IsValid() && cx > 0 && cy > 0 && frameInterval > 0)
deviceID = (UINT)SendMessage(hwndDeviceList, CB_FINDSTRINGEXACT, -1, (LPARAM)strDevice.Array());
if(strAudioDevice.IsValid())
audioDeviceID = (UINT)SendMessage(hwndAudioList, CB_FINDSTRINGEXACT, -1, (LPARAM)strAudioDevice.Array());
if(deviceID == CB_ERR)
{
@ -987,22 +1008,6 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
}
}
if(audioInputDevicesPresent)
{
if(audioDeviceID == CB_ERR)
{
SendMessage(hwndAudioList, CB_SETCURSEL, 0, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_AUDIOLIST, CBN_SELCHANGE), (LPARAM)hwndAudioList);
}
else
{
SendMessage(hwndAudioList, CB_SETCURSEL, audioDeviceID, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_AUDIOLIST, CBN_SELCHANGE), (LPARAM)hwndAudioList);
}
}
EnableWindow(hwndAudioList, audioInputDevicesPresent);
EnableWindow(GetDlgItem(hwnd, IDC_CONFIGAUDIO), audioInputDevicesPresent);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CUSTOMRESOLUTION, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDC_CUSTOMRESOLUTION));
HWND hwndPreferredList = GetDlgItem(hwnd, IDC_PREFERREDOUTPUT);
@ -1014,12 +1019,33 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
//------------------------------------------
DWORD delayTime = configData->data->GetInt(TEXT("delayTime"));
bool bUseBuffering = configData->data->GetInt(TEXT("useBuffering")) != 0;
EnableWindow(GetDlgItem(hwnd, IDC_DELAY_EDIT), bUseBuffering);
EnableWindow(GetDlgItem(hwnd, IDC_DELAY), bUseBuffering);
SendMessage(GetDlgItem(hwnd, IDC_USEBUFFERING), BM_SETCHECK, bUseBuffering ? BST_CHECKED : BST_UNCHECKED, 0);
DWORD bufferTime = configData->data->GetInt(TEXT("bufferTime"));
SendMessage(GetDlgItem(hwnd, IDC_DELAY), UDM_SETRANGE32, 0, 8000);
SendMessage(GetDlgItem(hwnd, IDC_DELAY), UDM_SETPOS32, 0, delayTime);
SendMessage(GetDlgItem(hwnd, IDC_DELAY), UDM_SETPOS32, 0, bufferTime);
//------------------------------------------
UINT audioDeviceID = CB_ERR;
if(strAudioDevice.IsValid())
audioDeviceID = (UINT)SendMessage(hwndAudioList, CB_FINDSTRINGEXACT, -1, (LPARAM)strAudioDevice.Array());
if(audioDeviceID == CB_ERR)
{
SendMessage(hwndAudioList, CB_SETCURSEL, 0, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_AUDIOLIST, CBN_SELCHANGE), (LPARAM)hwndAudioList);
}
else
{
SendMessage(hwndAudioList, CB_SETCURSEL, audioDeviceID, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_AUDIOLIST, CBN_SELCHANGE), (LPARAM)hwndAudioList);
}
HWND hwndTemp;
int soundOutputType = configData->data->GetInt(TEXT("soundOutputType"));
@ -1030,11 +1056,6 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
case 2: hwndTemp = GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND); break;
}
bool bForceCustomAudioDevice = configData->data->GetInt(TEXT("forceCustomAudioDevice")) != 0;
SendMessage(GetDlgItem(hwnd, IDC_FORCECUSTOMAUDIO), BM_SETCHECK, bForceCustomAudioDevice ? BST_CHECKED : BST_UNCHECKED, 0);
EnableWindow(GetDlgItem(hwnd, IDC_AUDIOLIST), !configData->bDeviceHasAudio || bForceCustomAudioDevice);
SendMessage(hwndTemp, BM_SETCHECK, BST_CHECKED, 0);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET), soundOutputType == 1);
@ -1163,6 +1184,15 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
break;
}
case IDC_USEBUFFERING:
if (HIWORD(wParam) == BN_CLICKED) {
bool bUseBuffering = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
EnableWindow(GetDlgItem(hwnd, IDC_DELAY_EDIT), bUseBuffering);
EnableWindow(GetDlgItem(hwnd, IDC_DELAY), bUseBuffering);
}
break;
case IDC_NOSOUND:
case IDC_PLAYDESKTOPSOUND:
case IDC_OUTPUTSOUND:
@ -1246,27 +1276,6 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
break;
}
case IDC_FORCECUSTOMAUDIO:
{
if(HIWORD(wParam) == BN_CLICKED)
{
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
BOOL bForceCustomAudioChk = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
if(configData->bDeviceHasAudio) {
EnableWindow(GetDlgItem(hwnd, IDC_AUDIOLIST), bForceCustomAudioChk);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_DEVICELIST, CBN_SELCHANGE), (LPARAM)GetDlgItem(hwnd, IDC_DEVICELIST));
if(bForceCustomAudioChk)
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_DEVICELIST, CBN_SELCHANGE), (LPARAM)GetDlgItem(hwnd, IDC_AUDIOLIST));
}
else {
EnableWindow(GetDlgItem(hwnd, IDC_AUDIOLIST), TRUE);
}
}
}
break;
case IDC_FLIPIMAGE:
case IDC_FLIPIMAGEH:
if(HIWORD(wParam) == BN_CLICKED)
@ -1316,7 +1325,7 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
int val = (int)SendMessage(hwndVal, UDM_GETPOS32, 0, 0);
switch(LOWORD(wParam))
{
case IDC_DELAY_EDIT: source->SetInt(TEXT("delayTime"), val); break;
case IDC_DELAY_EDIT: source->SetInt(TEXT("bufferTime"), val); break;
case IDC_TIMEOFFSET_EDIT: source->SetInt(TEXT("timeOffset"), val); break;
case IDC_OPACITY_EDIT: source->SetInt(TEXT("opacity"), val); break;
case IDC_BASETHRESHOLD_EDIT: source->SetInt(TEXT("keySimilarity"), val); break;
@ -1339,33 +1348,23 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
{
HWND hwndDeviceList = GetDlgItem(hwnd, IDC_DEVICELIST);
HWND hwndAudioDeviceList = GetDlgItem(hwnd, IDC_AUDIOLIST);
HWND hwndCrossbarList = GetDlgItem(hwnd, IDC_CROSSBARLIST);
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
FillOutListOfDevices(hwndDeviceList, CLSID_VideoInputDeviceCategory, &configData->deviceNameList, &configData->deviceIDList);
audioInputDevicesPresent = FillOutListOfDevices(hwndAudioDeviceList, CLSID_AudioInputDeviceCategory, &configData->audioNameList, &configData->audioIDList);
bool bCrossbarAvailable = FillOutListOfDevices(hwndCrossbarList, AM_KSCATEGORY_CROSSBAR, &configData->crossbarList, &configData->crossbarIDList);
if(bCrossbarAvailable)
SendMessage(hwndCrossbarList, CB_SETCURSEL, 0, 0);
EnableWindow(GetDlgItem(hwnd, IDC_CROSSBAR), bCrossbarAvailable);
EnableWindow(hwndCrossbarList, bCrossbarAvailable);
bAudioDevicesPresent = FillOutListOfDevices(hwndAudioDeviceList, CLSID_AudioInputDeviceCategory, &configData->audioNameList, &configData->audioIDList);
SendMessage(hwndDeviceList, CB_SETCURSEL, 0, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_DEVICELIST, CBN_SELCHANGE), (LPARAM)hwndDeviceList);
if(audioInputDevicesPresent)
if(bAudioDevicesPresent)
{
SendMessage(hwndAudioDeviceList, CB_SETCURSEL, 0, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_AUDIOLIST, CBN_SELCHANGE), (LPARAM)hwndAudioDeviceList);
}
EnableWindow(hwndAudioDeviceList, audioInputDevicesPresent);
EnableWindow(GetDlgItem(hwnd, IDC_CONFIGAUDIO), audioInputDevicesPresent);
SendMessage(hwndCrossbarList, CB_SETCURSEL, 0, 0);
EnableWindow(hwndAudioDeviceList, bAudioDevicesPresent);
EnableWindow(GetDlgItem(hwnd, IDC_CONFIGAUDIO), bAudioDevicesPresent);
break;
}
@ -1387,18 +1386,21 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
}
else
{
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
HWND hwndAudioList = GetDlgItem(hwnd, IDC_AUDIOLIST);
BOOL bCustomResolution = SendMessage(GetDlgItem(hwnd, IDC_CUSTOMRESOLUTION) , BM_GETCHECK, 0, 0) == BST_CHECKED;
BOOL bForceCustomAudioDevice = SendMessage(GetDlgItem(hwnd, IDC_FORCECUSTOMAUDIO) , BM_GETCHECK, 0, 0) == BST_CHECKED;
EnableWindow(GetDlgItem(hwnd, IDC_RESOLUTION), bCustomResolution);
EnableWindow(GetDlgItem(hwnd, IDC_FPS), bCustomResolution);
EnableWindow(GetDlgItem(hwnd, IDC_CONFIG), TRUE);
EnableWindow(GetDlgItem(hwnd, IDOK), TRUE);
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
IBaseFilter *filter = GetDeviceByValue(CLSID_VideoInputDeviceCategory,
L"FriendlyName", configData->deviceNameList[id],
L"DevicePath", configData->deviceIDList[id]);
if(filter)
{
//--------------------------------
@ -1424,35 +1426,13 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
outputPin = NULL;
}
//--------------------------------
// get audio info
bool bHasAudio = false;
IAMCrossbar *crossbar = GetFilterCrossbar(filter);
EnableWindow(GetDlgItem(hwnd, IDC_CROSSBAR), crossbar != NULL);
SafeRelease(crossbar);
outputPin = GetOutputPin(filter, &MEDIATYPE_Audio);
if(outputPin)
{
bHasAudio = true;
outputPin->Release();
}
configData->bDeviceHasAudio = bHasAudio;
EnableWindow(GetDlgItem(hwnd, IDC_NOSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_OUTPUTSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_VOLUME), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_AUDIOLIST), !bHasAudio || bForceCustomAudioDevice);
if(!bHasAudio)
{
SendMessage(GetDlgItem(hwnd, IDC_NOSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_OUTPUTSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET_EDIT), FALSE);
}
configData->bDeviceHasAudio = (outputPin != NULL);
SafeRelease(outputPin);
filter->Release();
}
@ -1477,6 +1457,41 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
SendMessage(hwndResolutions, CB_SETCURSEL, 0, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_RESOLUTION, CBN_SELCHANGE), (LPARAM)hwndResolutions);
}
//-------------------------------------------------
// get audio devices
bAudioDevicesPresent = FillOutListOfDevices(hwndAudioList, CLSID_AudioInputDeviceCategory, &configData->audioNameList, &configData->audioIDList);
if (configData->bDeviceHasAudio) {
CTSTR lpName = PluginStr("DeviceSelection.UseDeviceAudio");
SendMessage(hwndAudioList, CB_INSERTSTRING, 0, (LPARAM)lpName);
configData->audioNameList.Insert(0, lpName);
configData->audioIDList.Insert(0, NULL);
}
EnableWindow(hwndAudioList, bAudioDevicesPresent);
if (!bAudioDevicesPresent)
EnableWindow(GetDlgItem(hwnd, IDC_CONFIGAUDIO), FALSE);
bool bHasAudio = configData->bDeviceHasAudio || bAudioDevicesPresent;
EnableWindow(GetDlgItem(hwnd, IDC_NOSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_OUTPUTSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET_EDIT), bHasAudio);
if (bHasAudio) {
SendMessage(hwndAudioList, CB_SETCURSEL, 0, 0);
ConfigureDialogProc(hwnd, WM_COMMAND, MAKEWPARAM(IDC_AUDIOLIST, CBN_SELCHANGE), (LPARAM)hwndAudioList);
} else {
SendMessage(GetDlgItem(hwnd, IDC_NOSOUND), BM_SETCHECK, BST_CHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_OUTPUTSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
}
}
}
break;
@ -1489,43 +1504,21 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
IBaseFilter *filter = GetDeviceByValue(CLSID_AudioInputDeviceCategory,
L"FriendlyName", configData->audioNameList[id],
L"DevicePath", configData->audioIDList[id]);
if(filter)
{
//--------------------------------
// get audio info
bool bHasAudio = false;
BOOL bForceCustomAudioDevice = SendMessage(GetDlgItem(hwnd, IDC_FORCECUSTOMAUDIO) , BM_GETCHECK, 0, 0) == BST_CHECKED;
IPin *outputPin = GetOutputPin(filter, &MEDIATYPE_Audio);
if(outputPin)
{
bHasAudio = true;
outputPin->Release();
}
EnableWindow(GetDlgItem(hwnd, IDC_NOSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_OUTPUTSOUND), bHasAudio);
EnableWindow(GetDlgItem(hwnd, IDC_VOLUME), bHasAudio);
if(!configData->bDeviceHasAudio || bForceCustomAudioDevice) EnableWindow(GetDlgItem(hwnd, IDC_AUDIOLIST), bHasAudio);
if(!bHasAudio)
{
SendMessage(GetDlgItem(hwnd, IDC_NOSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_OUTPUTSOUND), BM_SETCHECK, BST_UNCHECKED, 0);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET_EDIT), FALSE);
}
L"FriendlyName", configData->audioNameList[id],
L"DevicePath", configData->audioIDList[id]);
if (filter) {
EnableWindow(GetDlgItem(hwnd, IDC_CONFIGAUDIO), TRUE);
filter->Release();
} else {
EnableWindow(GetDlgItem(hwnd, IDC_CONFIGAUDIO), FALSE);
}
EnableWindow(GetDlgItem(hwnd, IDC_NOSOUND), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_OUTPUTSOUND), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_TIMEOFFSET_EDIT), TRUE);
}
break;
@ -1669,25 +1662,44 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
}
break;
case IDC_CONFIG:
case IDC_CONFIGAUDIO:
case IDC_CROSSBAR:
case IDC_CONFIG:
case IDC_CONFIGAUDIO:
case IDC_CROSSBAR:
{
UINT id;
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
IBaseFilter *filter;
switch(LOWORD(wParam))
{
case IDC_CONFIG:
id = (UINT)SendMessage(GetDlgItem(hwnd, IDC_DEVICELIST), CB_GETCURSEL, 0, 0);
if(id != CB_ERR) OpenPropertyPages(hwnd, configData->deviceNameList[id], configData->deviceIDList[id], CLSID_VideoInputDeviceCategory);
if(id != CB_ERR) OpenPropertyPagesByName(hwnd, configData->deviceNameList[id], configData->deviceIDList[id], CLSID_VideoInputDeviceCategory);
break;
case IDC_CONFIGAUDIO:
id = (UINT)SendMessage(GetDlgItem(hwnd, IDC_AUDIOLIST), CB_GETCURSEL, 0, 0);
if(id != CB_ERR) OpenPropertyPages(hwnd, configData->audioNameList[id], configData->audioIDList[id], CLSID_AudioInputDeviceCategory);
if(id != CB_ERR) OpenPropertyPagesByName(hwnd, configData->audioNameList[id], configData->audioIDList[id], CLSID_AudioInputDeviceCategory);
break;
case IDC_CROSSBAR:
id = (UINT)SendMessage(GetDlgItem(hwnd, IDC_CROSSBARLIST), CB_GETCURSEL, 0, 0);
if(id != CB_ERR) OpenPropertyPages(hwnd, configData->crossbarList[id], configData->crossbarIDList[id], AM_KSCATEGORY_CROSSBAR);
id = (UINT)SendMessage(GetDlgItem(hwnd, IDC_DEVICELIST), CB_GETCURSEL, 0, 0);
if (id == CB_ERR)
break;
filter = GetDeviceByValue(CLSID_VideoInputDeviceCategory,
L"FriendlyName", configData->deviceNameList[id],
L"DevicePath", configData->deviceIDList[id]);
if (filter) {
IAMCrossbar *crossbar = GetFilterCrossbar(filter);
if (crossbar) {
OpenPropertyPages(hwnd, crossbar);
crossbar->Release();
}
filter->Release();
}
break;
}
break;
@ -1762,20 +1774,6 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
configData->data->SetString(TEXT("deviceName"), configData->deviceNameList[deviceID]);
configData->data->SetString(TEXT("deviceID"), configData->deviceIDList[deviceID]);
bool bForceCustomAudioDevice = SendMessage(GetDlgItem(hwnd, IDC_FORCECUSTOMAUDIO), BM_GETCHECK, 0, 0) == BST_CHECKED;
configData->data->SetInt(TEXT("forceCustomAudioDevice"), bForceCustomAudioDevice);
if(audioInputDevicesPresent)
{
UINT audioDeviceID = (UINT)SendMessage(GetDlgItem(hwnd, IDC_AUDIOLIST), CB_GETCURSEL, 0, 0);
if(audioDeviceID == CB_ERR)
break;
String strAudioDevice = GetCBText(GetDlgItem(hwnd, IDC_AUDIOLIST), audioDeviceID);
configData->data->SetString(TEXT("audioDevice"), strAudioDevice);
configData->data->SetString(TEXT("audioDeviceName"), configData->audioNameList[audioDeviceID]);
configData->data->SetString(TEXT("audioDeviceID"), configData->audioIDList[audioDeviceID]);
}
configData->data->SetInt(TEXT("customResolution"), bCustomResolution);
configData->data->SetInt(TEXT("resolutionWidth"), resolution.cx);
configData->data->SetInt(TEXT("resolutionHeight"), resolution.cy);
@ -1786,11 +1784,6 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
//------------------------------------------
BOOL bForceCustomAudioChk = SendMessage(GetDlgItem(hwnd, IDC_FORCECUSTOMAUDIO), BM_GETCHECK, 0, 0) == BST_CHECKED;
configData->data->SetInt(TEXT("forceCustomAudioDevice"), bForceCustomAudioChk);
//------------------------------------------
BOOL bUDMError;
UINT opacity = (UINT)SendMessage(GetDlgItem(hwnd, IDC_OPACITY), UDM_GETPOS32, 0, (LPARAM)&bUDMError);
if(bUDMError) opacity = 100;
@ -1808,16 +1801,32 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
configData->data->SetInt(TEXT("usePreferredType"), bUsePreferredType);
configData->data->SetInt(TEXT("preferredType"), preferredType);
DWORD delayTime = (DWORD)SendMessage(GetDlgItem(hwnd, IDC_DELAY), UDM_GETPOS32, 0, 0);
configData->data->SetInt(TEXT("delayTime"), delayTime);
bool bUseBuffering = SendMessage(GetDlgItem(hwnd, IDC_USEBUFFERING), BM_GETCHECK, 0, 0) == BST_CHECKED;
configData->data->SetInt(TEXT("useBuffering"), bUseBuffering);
DWORD bufferTime = (DWORD)SendMessage(GetDlgItem(hwnd, IDC_DELAY), UDM_GETPOS32, 0, 0);
configData->data->SetInt(TEXT("bufferTime"), bufferTime);
//------------------------------------------
int soundOutputType = 0;
if(SendMessage(GetDlgItem(hwnd, IDC_OUTPUTSOUND), BM_GETCHECK, 0, 0) == BST_CHECKED)
soundOutputType = 1;
else if(SendMessage(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), BM_GETCHECK, 0, 0) == BST_CHECKED)
soundOutputType = 2;
UINT audioDeviceID = (UINT)SendMessage(GetDlgItem(hwnd, IDC_AUDIOLIST), CB_GETCURSEL, 0, 0);
if (audioDeviceID != CB_ERR) {
if (bAudioDevicesPresent) {
String strAudioDevice = GetCBText(GetDlgItem(hwnd, IDC_AUDIOLIST), audioDeviceID);
configData->data->SetString(TEXT("audioDevice"), strAudioDevice);
configData->data->SetString(TEXT("audioDeviceName"), configData->audioNameList[audioDeviceID]);
configData->data->SetString(TEXT("audioDeviceID"), configData->audioIDList[audioDeviceID]);
}
configData->data->SetInt(TEXT("forceCustomAudioDevice"), (!configData->bDeviceHasAudio || audioDeviceID != 0));
if(SendMessage(GetDlgItem(hwnd, IDC_OUTPUTSOUND), BM_GETCHECK, 0, 0) == BST_CHECKED)
soundOutputType = 1;
else if(SendMessage(GetDlgItem(hwnd, IDC_PLAYDESKTOPSOUND), BM_GETCHECK, 0, 0) == BST_CHECKED)
soundOutputType = 2;
}
configData->data->SetInt(TEXT("soundOutputType"), soundOutputType);
@ -1856,7 +1865,7 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
if(source)
{
source->SetInt(TEXT("delayTime"), configData->data->GetInt(TEXT("delayTime"), 0));
source->SetInt(TEXT("bufferTime"), configData->data->GetInt(TEXT("bufferTime"), 0));
source->SetInt(TEXT("timeOffset"), configData->data->GetInt(TEXT("soundTimeOffset"), 0));
source->SetFloat(TEXT("volume"), configData->data->GetFloat(TEXT("volume"), 1.0f));

View File

@ -50,7 +50,7 @@ END
// Dialog
//
IDD_CONFIG DIALOGEX 0, 0, 467, 282
IDD_CONFIG DIALOGEX 0, 0, 428, 270
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "DeviceSelection"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
@ -58,61 +58,57 @@ BEGIN
RTEXT "DeviceSelection.Device",IDC_STATIC,4,9,117,8
COMBOBOX IDC_DEVICELIST,125,7,133,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "DeviceSelection.Config",IDC_CONFIG,264,7,78,13
PUSHBUTTON "DeviceSelection.Refresh",IDC_REFRESH,345,7,78,13
RTEXT "DeviceSelection.AudioDevice",IDC_STATIC,4,24,117,8
COMBOBOX IDC_AUDIOLIST,125,22,133,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "DeviceSelection.Config",IDC_CONFIGAUDIO,264,22,78,13
CONTROL "DeviceSelection.ForceCustomAudio",IDC_FORCECUSTOMAUDIO,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,345,24,115,10
CONTROL "DeviceSelection.FlipImage",IDC_FLIPIMAGE,"Button",BS_AUTOCHECKBOX | BS_RIGHT | WS_TABSTOP,14,38,119,10,WS_EX_RIGHT
PUSHBUTTON "DeviceSelection.Refresh",IDC_REFRESH,343,7,78,13
PUSHBUTTON "CrossbarSelection.Open",IDC_CROSSBAR,343,22,78,13
CONTROL "DeviceSelection.FlipImage",IDC_FLIPIMAGE,"Button",BS_AUTOCHECKBOX | BS_RIGHT | WS_TABSTOP,14,24,119,10,WS_EX_RIGHT
CONTROL "DeviceSelection.FlipImageHorizontal",IDC_FLIPIMAGEH,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,2,52,131,10,WS_EX_RIGHT
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,2,38,131,10,WS_EX_RIGHT
CONTROL "DeviceSelection.PointFiltering",IDC_POINTFILTERING,
"Button",BS_AUTOCHECKBOX | BS_RIGHT | WS_TABSTOP,154,38,119,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Opacity",IDC_STATIC,144,52,117,8
EDITTEXT IDC_OPACITY_EDIT,264,49,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_OPACITY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,304,49,11,14
GROUPBOX "DeviceSelection.Video",IDC_STATIC,7,69,216,101
"Button",BS_AUTOCHECKBOX | BS_RIGHT | WS_TABSTOP,154,24,119,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Opacity",IDC_STATIC,144,38,117,8
EDITTEXT IDC_OPACITY_EDIT,264,35,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_OPACITY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,304,35,11,14
GROUPBOX "DeviceSelection.Video",IDC_STATIC,7,56,216,101
CONTROL "DeviceSelection.CustomResolution",IDC_CUSTOMRESOLUTION,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,81,130,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Resolution",IDC_STATIC,18,98,117,8
COMBOBOX IDC_RESOLUTION,138,95,76,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
RTEXT "DeviceSelection.FPS",IDC_STATIC,18,115,117,8
COMBOBOX IDC_FPS,138,113,76,56,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,68,130,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Resolution",IDC_STATIC,18,85,117,8
COMBOBOX IDC_RESOLUTION,138,82,76,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
RTEXT "DeviceSelection.FPS",IDC_STATIC,18,102,117,8
COMBOBOX IDC_FPS,138,100,76,56,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "DeviceSelection.PreferredType",IDC_USEPREFERREDOUTPUT,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,134,117,10,WS_EX_RIGHT
COMBOBOX IDC_PREFERREDOUTPUT,138,132,76,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "DeviceSelection.Delay",IDC_STATIC,18,153,117,8,NOT WS_GROUP,WS_EX_RIGHT
EDITTEXT IDC_DELAY_EDIT,138,150,40,14,ES_AUTOHSCROLL | WS_DISABLED
CONTROL "",IDC_DELAY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | WS_DISABLED,178,150,10,14
GROUPBOX "DeviceSelection.Sound",IDC_STATIC,230,69,180,101,WS_GROUP
CONTROL "ƒJƒXƒ^ƒ€1",IDC_VOLUME,"OBSVolumeControl",WS_TABSTOP,238,80,118,19
CONTROL "DeviceSelection.NoSound",IDC_NOSOUND,"Button",BS_AUTORADIOBUTTON,238,109,163,10
CONTROL "DeviceSelection.OutputSound",IDC_OUTPUTSOUND,"Button",BS_AUTORADIOBUTTON,238,120,163,10
LTEXT "DeviceSelection.SoundOffset",IDC_STATIC,234,136,117,8,NOT WS_GROUP,WS_EX_RIGHT
EDITTEXT IDC_TIMEOFFSET_EDIT,356,133,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_TIMEOFFSET,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,396,133,10,14
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,121,117,10,WS_EX_RIGHT
COMBOBOX IDC_PREFERREDOUTPUT,138,119,76,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "DeviceSelection.UseBuffering",IDC_USEBUFFERING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,140,117,10,WS_EX_RIGHT
EDITTEXT IDC_DELAY_EDIT,138,137,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_DELAY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,178,137,10,14
GROUPBOX "DeviceSelection.Sound",IDC_STATIC,234,56,187,146,WS_GROUP
LTEXT "DeviceSelection.AudioDevice",IDC_STATIC,243,73,117,8
COMBOBOX IDC_AUDIOLIST,243,85,169,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "DeviceSelection.Config",IDC_CONFIGAUDIO,335,101,78,13
CONTROL "ƒJƒXƒ^ƒ€1",IDC_VOLUME,"OBSVolumeControl",WS_TABSTOP,243,120,118,19
CONTROL "DeviceSelection.NoSound",IDC_NOSOUND,"Button",BS_AUTORADIOBUTTON,243,145,163,10
CONTROL "DeviceSelection.OutputSound",IDC_OUTPUTSOUND,"Button",BS_AUTORADIOBUTTON,243,156,163,10
LTEXT "DeviceSelection.SoundOffset",IDC_STATIC,239,171,117,8,NOT WS_GROUP,WS_EX_RIGHT
EDITTEXT IDC_TIMEOFFSET_EDIT,361,168,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_TIMEOFFSET,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,401,168,11,14
CONTROL "DeviceSelection.PlayToDesktop",IDC_PLAYDESKTOPSOUND,
"Button",BS_AUTORADIOBUTTON,238,150,163,10
GROUPBOX "DeviceSelection.ChromaKey",IDC_STATIC,7,176,216,99
CONTROL "DeviceSelection.UseChromaKey",IDC_USECHROMAKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,188,130,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Color",IDC_STATIC,14,204,117,8
CONTROL "",IDC_COLOR,"OBSColorControl",WS_TABSTOP,133,201,28,14
PUSHBUTTON "DeviceSelection.Select",IDC_SELECTCOLOR,166,201,50,14
RTEXT "DeviceSelection.Similarity",IDC_STATIC,14,222,117,8
EDITTEXT IDC_BASETHRESHOLD_EDIT,132,220,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_BASETHRESHOLD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,173,220,10,14
RTEXT "DeviceSelection.Blend",IDC_STATIC,12,238,117,8
EDITTEXT IDC_BLEND_EDIT,132,237,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_BLEND,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,237,11,14
RTEXT "DeviceSelection.SpillReduction",IDC_STATIC,12,254,117,8
EDITTEXT IDC_SPILLREDUCTION_EDIT,132,253,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_SPILLREDUCTION,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,253,11,14
GROUPBOX "DeviceSelection.CrossbarSelect",IDC_STATIC,231,176,229,34
COMBOBOX IDC_CROSSBARLIST,238,189,133,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "CrossbarSelection.Open",IDC_CROSSBAR,375,189,78,13
DEFPUSHBUTTON "OK",IDOK,352,261,50,14
PUSHBUTTON "Cancel",IDCANCEL,410,261,50,14
"Button",BS_AUTORADIOBUTTON,243,186,163,10
GROUPBOX "DeviceSelection.ChromaKey",IDC_STATIC,7,163,216,99
CONTROL "DeviceSelection.UseChromaKey",IDC_USECHROMAKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,175,130,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Color",IDC_STATIC,14,191,117,8
CONTROL "",IDC_COLOR,"OBSColorControl",WS_TABSTOP,133,188,28,14
PUSHBUTTON "DeviceSelection.Select",IDC_SELECTCOLOR,166,188,50,14
RTEXT "DeviceSelection.Similarity",IDC_STATIC,14,209,117,8
EDITTEXT IDC_BASETHRESHOLD_EDIT,132,207,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_BASETHRESHOLD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,173,207,10,14
RTEXT "DeviceSelection.Blend",IDC_STATIC,12,225,117,8
EDITTEXT IDC_BLEND_EDIT,132,224,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_BLEND,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,224,11,14
RTEXT "DeviceSelection.SpillReduction",IDC_STATIC,12,241,117,8
EDITTEXT IDC_SPILLREDUCTION_EDIT,132,240,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_SPILLREDUCTION,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,240,11,14
DEFPUSHBUTTON "OK",IDOK,313,249,50,14
PUSHBUTTON "Cancel",IDCANCEL,371,249,50,14
END
@ -127,9 +123,9 @@ BEGIN
IDD_CONFIG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 460
RIGHTMARGIN, 421
TOPMARGIN, 7
BOTTOMMARGIN, 275
BOTTOMMARGIN, 263
END
END
#endif // APSTUDIO_INVOKED

View File

@ -93,7 +93,7 @@ bool DeviceAudioSource::Initialize(DeviceSource *parent)
outputBuffer.SetSize(sampleSegmentSize);
InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, inputBlockSize, inputChannelMask);
InitAudioData(bFloat, inputChannels, inputSamplesPerSec, inputBitsPerSample, inputBlockSize, inputChannelMask, false);
return true;
}
@ -105,17 +105,20 @@ DeviceAudioSource::~DeviceAudioSource()
}
void DeviceAudioSource::ReceiveAudio(IMediaSample *sample)
void DeviceAudioSource::ReceiveAudio(LPBYTE lpData, UINT dataLength)
{
if(sample)
if(lpData)
{
BYTE *pData;
if(SUCCEEDED(sample->GetPointer(&pData)))
{
OSEnterMutex(hAudioMutex);
sampleBuffer.AppendArray(pData, sample->GetActualDataLength());
OSLeaveMutex(hAudioMutex);
}
OSEnterMutex(hAudioMutex);
sampleBuffer.AppendArray(lpData, dataLength);
OSLeaveMutex(hAudioMutex);
}
}
void DeviceAudioSource::FlushSamples()
{
OSEnterMutex(hAudioMutex);
sampleBuffer.Clear();
OSLeaveMutex(hAudioMutex);
}

View File

@ -194,12 +194,13 @@ bool DeviceSource::LoadFilters()
bFlipHorizontal = data->GetInt(TEXT("flipImageHorizontal")) != 0;
bUsePointFiltering = data->GetInt(TEXT("usePointFiltering")) != 0;
delayTime = data->GetInt(TEXT("delayTime"))*10000;
opacity = data->GetInt(TEXT("opacity"), 100);
float volume = data->GetFloat(TEXT("volume"), 1.0f);
bUseBuffering = data->GetInt(TEXT("useBuffering")) != 0;
bufferTime = data->GetInt(TEXT("bufferTime"))*10000;
//------------------------------------------------
// chrom key stuff
@ -626,6 +627,18 @@ bool DeviceSource::LoadFilters()
goto cleanFinish;
}
if (bUseBuffering) {
if (!(hStopSampleEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
AppWarning(TEXT("DShowPlugin: Failed to create stop event"), err);
goto cleanFinish;
}
if (!(hSampleThread = OSCreateThread((XTHREAD)SampleThread, this))) {
AppWarning(TEXT("DShowPlugin: Failed to create sample thread"), err);
goto cleanFinish;
}
}
if(soundOutputType == 1)
{
audioOut = new DeviceAudioSource;
@ -633,7 +646,6 @@ bool DeviceSource::LoadFilters()
API->AddAudioSource(audioOut);
audioOut->SetAudioOffset(soundTimeOffset);
audioOut->SetDelayTime(delayTime/10000);
audioOut->SetVolume(volume);
}
@ -669,6 +681,18 @@ cleanFinish:
SafeRelease(audioFilter);
SafeRelease(control);
if (hSampleThread) {
SetEvent(hStopSampleEvent);
WaitForSingleObject(hSampleThread, INFINITE);
CloseHandle(hSampleThread);
hSampleThread = NULL;
}
if (hStopSampleEvent) {
CloseHandle(hStopSampleEvent);
hStopSampleEvent = NULL;
}
if(colorConvertShader)
{
delete colorConvertShader;
@ -732,6 +756,16 @@ cleanFinish:
void DeviceSource::UnloadFilters()
{
if (hSampleThread) {
SetEvent(hStopSampleEvent);
WaitForSingleObject(hSampleThread, INFINITE);
CloseHandle(hSampleThread);
CloseHandle(hStopSampleEvent);
hSampleThread = NULL;
hStopSampleEvent = NULL;
}
if(texture)
{
delete texture;
@ -839,48 +873,166 @@ void DeviceSource::EndScene()
Stop();
}
void DeviceSource::ReceiveVideo(IMediaSample *sample)
DWORD DeviceSource::SampleThread(DeviceSource *source)
{
if(bCapturing)
{
BYTE *pointer;
if (sample)
{
if (SUCCEEDED(sample->GetPointer(&pointer)))
{
SampleData *data = new SampleData;
HANDLE hSampleMutex = source->hSampleMutex;
LONGLONG lastTime = GetQPCTime100NS(), bufferTime = 0, frameWait = 0, curBufferTime = source->bufferTime;
LONGLONG lastSampleTime = 0;
data->lpData = (LPBYTE)Allocate(sample->GetActualDataLength());
mcpy(data->lpData, pointer, sample->GetActualDataLength());
bool bFirstFrame = true;
bool bFirstDelay = true;
LONGLONG stopTime;
sample->GetTime(&data->startTime, &stopTime);
while (WaitForSingleObject(source->hStopSampleEvent, 4) == WAIT_TIMEOUT) {
LONGLONG t = GetQPCTime100NS();
LONGLONG delta = t-lastTime;
lastTime = t;
OSEnterMutex(hSampleMutex);
if (samples.Num() > 0) {
delete samples[0];
samples.Remove(0);
OSEnterMutex(hSampleMutex);
if (source->samples.Num()) {
if (bFirstFrame) {
bFirstFrame = false;
lastSampleTime = source->samples[0]->timestamp;
}
//wait until the requested delay has been buffered before processing packets
if (bufferTime >= source->bufferTime) {
frameWait += delta;
//if delay time was adjusted downward, remove packets accordingly
bool bBufferTimeChanged = (curBufferTime != source->bufferTime);
if (bBufferTimeChanged) {
if (curBufferTime > source->bufferTime) {
if (source->audioOut)
source->audioOut->FlushSamples();
LONGLONG lostTime = curBufferTime - source->bufferTime;
bufferTime -= lostTime;
if (source->samples.Num()) {
LONGLONG startTime = source->samples[0]->timestamp;
while (source->samples.Num()) {
SampleData *sample = source->samples[0];
if ((sample->timestamp - startTime) >= lostTime)
break;
lastSampleTime = sample->timestamp;
sample->Release();
source->samples.Remove(0);
}
}
}
curBufferTime = source->bufferTime;
}
samples << data;
OSLeaveMutex(hSampleMutex);
while (source->samples.Num()) {
SampleData *sample = source->samples[0];
LONGLONG timestamp = sample->timestamp;
LONGLONG sampleTime = timestamp - lastSampleTime;
//sometimes timestamps can go to shit with horrible garbage devices.
//so, bypass any unusual timestamp offsets.
if (sampleTime < -6000000 || sampleTime > 6000000) {
//OSDebugOut(TEXT("sample time: %lld\r\n"), sampleTime);
sampleTime = 0;
}
if (frameWait < sampleTime)
break;
if (sample->bAudio) {
if (source->audioOut)
source->audioOut->ReceiveAudio(sample->lpData, sample->dataLength);
sample->Release();
} else {
SafeRelease(source->latestVideoSample);
source->latestVideoSample = sample;
}
source->samples.Remove(0);
if (sampleTime > 0)
frameWait -= sampleTime;
lastSampleTime = timestamp;
}
}
}
OSLeaveMutex(hSampleMutex);
if (!bFirstFrame && bufferTime < source->bufferTime)
bufferTime += delta;
}
return 0;
}
void DeviceSource::ReceiveAudio(IMediaSample *sample)
UINT DeviceSource::GetSampleInsertIndex(LONGLONG timestamp)
{
if(bCapturing && audioOut)
{
audioOut->ReceiveAudio(sample);
UINT index;
for (index=0; index<samples.Num(); index++) {
if (samples[index]->timestamp > timestamp)
return index;
}
return index;
}
void DeviceSource::ReceiveMediaSample(IMediaSample *sample, bool bAudio)
{
if (!sample)
return;
if (bCapturing) {
BYTE *pointer;
if (SUCCEEDED(sample->GetPointer(&pointer))) {
SampleData *data = NULL;
if (bUseBuffering || !bAudio) {
data = new SampleData;
data->bAudio = bAudio;
data->dataLength = sample->GetActualDataLength();
data->lpData = (LPBYTE)Allocate(data->dataLength);//pointer; //
/*data->sample = sample;
sample->AddRef();*/
SSECopy(data->lpData, pointer, data->dataLength);
LONGLONG stopTime;
sample->GetTime(&data->timestamp, &stopTime);
}
//Log(TEXT("timestamp: %lld, bAudio - %s"), data->timestamp, bAudio ? TEXT("true") : TEXT("false"));
OSEnterMutex(hSampleMutex);
if (bUseBuffering) {
UINT id = GetSampleInsertIndex(data->timestamp);
samples.Insert(id, data);
} else if (bAudio) {
if (audioOut)
audioOut->ReceiveAudio(pointer, sample->GetActualDataLength());
} else {
SafeRelease(latestVideoSample);
latestVideoSample = data;
}
OSLeaveMutex(hSampleMutex);
}
}
}
static DWORD STDCALL PackPlanarThread(ConvertData *data)
{
do
{
do {
WaitForSingleObject(data->hSignalConvert, INFINITE);
if(data->bKillThread) break;
@ -924,24 +1076,14 @@ void DeviceSource::Preprocess()
SampleData *lastSample = NULL;
OSEnterMutex(hSampleMutex);
if(samples.Num())
{
QWORD sampleTime = samples.Last()->startTime - samples[0]->startTime;
while (sampleTime >= 0) {//delayTime) {
delete lastSample;
lastSample = latestVideoSample;
latestVideoSample = NULL;
lastSample = samples[0];
samples.Remove(0);
if (!samples.Num())
break;
sampleTime = samples.Last()->startTime - samples[0]->startTime;
}
}
OSLeaveMutex(hSampleMutex);
//----------------------------------------
int numThreads = MAX(OSGetTotalCores()-2, 1);
if(lastSample)
@ -1112,8 +1254,12 @@ void DeviceSource::UpdateSettings()
BOOL bNewCustom = data->GetInt(TEXT("customResolution"));
UINT newPreferredType = data->GetInt(TEXT("usePreferredType")) != 0 ? data->GetInt(TEXT("preferredType")) : -1;
UINT newSoundOutputType = data->GetInt(TEXT("soundOutputType"));
bool bNewUseBuffering = data->GetInt(TEXT("useBuffering")) != 0;
if(newSoundOutputType != soundOutputType || renderCX != newCX || renderCY != newCY || frameInterval != newFrameInterval || newPreferredType != preferredOutputType || !strDevice.CompareI(strNewDevice) || !strAudioDevice.CompareI(strNewAudioDevice) || bNewCustom != bUseCustomResolution)
if(newSoundOutputType != soundOutputType || renderCX != newCX || renderCY != newCY ||
frameInterval != newFrameInterval || newPreferredType != preferredOutputType ||
!strDevice.CompareI(strNewDevice) || !strAudioDevice.CompareI(strNewAudioDevice) ||
bNewCustom != bUseCustomResolution || bNewUseBuffering != bUseBuffering)
{
API->EnterSceneMutex();
@ -1200,11 +1346,9 @@ void DeviceSource::SetInt(CTSTR lpName, int iVal)
if(audioOut)
audioOut->SetAudioOffset(iVal);
}
else if(scmpi(lpName, TEXT("delayTime")) == 0)
else if(scmpi(lpName, TEXT("bufferTime")) == 0)
{
delayTime = iVal*10000;
if (audioOut)
audioOut->SetDelayTime(iVal);
bufferTime = iVal*10000;
}
}
}

View File

@ -37,12 +37,16 @@ enum DeviceColorType
};
struct SampleData {
//IMediaSample *sample;
LPBYTE lpData;
LONGLONG startTime;
long dataLength;
bool bAudio;
LONGLONG timestamp;
volatile long refs;
inline SampleData() {refs = 1;}
inline ~SampleData() {Free(lpData);}
inline ~SampleData() {Free(lpData);} //sample->Release();}
inline void AddRef() {++refs;}
inline void Release()
@ -75,7 +79,7 @@ class DeviceAudioSource : public AudioSource
List<BYTE> sampleBuffer;
List<BYTE> outputBuffer;
int delayTime, offset;
int offset;
protected:
virtual bool GetNextBuffer(void **buffer, UINT *numFrames, QWORD *timestamp);
@ -87,10 +91,11 @@ public:
bool Initialize(DeviceSource *parent);
~DeviceAudioSource();
void ReceiveAudio(IMediaSample *sample);
void ReceiveAudio(LPBYTE lpData, UINT dataLength);
inline void SetDelayTime(int delayTime) {this->delayTime = delayTime; SetTimeOffset(delayTime+offset);}
inline void SetAudioOffset(int offset) {this->offset = offset; SetTimeOffset(delayTime+offset);}
void FlushSamples();
inline void SetAudioOffset(int offset) {this->offset = offset; SetTimeOffset(offset);}
};
class DeviceSource : public ImageSource
@ -135,14 +140,19 @@ class DeviceSource : public ImageSource
bool bOutputAudioToDesktop;
Texture *texture;
HANDLE hSampleMutex;
XElement *data;
UINT texturePitch;
bool bCapturing, bFiltersLoaded;
int delayTime;
List<SampleData*> samples;
Shader *colorConvertShader;
bool bUseBuffering;
HANDLE hStopSampleEvent;
HANDLE hSampleMutex;
HANDLE hSampleThread;
UINT bufferTime;
SampleData *latestVideoSample;
List<SampleData*> samples;
UINT opacity;
//---------------------------------
@ -173,13 +183,14 @@ class DeviceSource : public ImageSource
for (UINT i=0; i<samples.Num(); i++)
delete samples[i];
samples.Clear();
SafeRelease(latestVideoSample);
OSLeaveMutex(hSampleMutex);
}
void SetAudioInfo(AM_MEDIA_TYPE *audioMediaType, GUID &expectedAudioType);
void ReceiveVideo(IMediaSample *sample);
void ReceiveAudio(IMediaSample *sample);
UINT GetSampleInsertIndex(LONGLONG timestamp);
void ReceiveMediaSample(IMediaSample *sample, bool bAudio);
bool LoadFilters();
void UnloadFilters();
@ -187,6 +198,8 @@ class DeviceSource : public ImageSource
void Start();
void Stop();
static DWORD WINAPI SampleThread(DeviceSource *source);
public:
bool Init(XElement *data);
~DeviceSource();

View File

@ -7,7 +7,6 @@
#define IDC_CONFIG 1002
#define IDC_AUDIOLIST 1003
#define IDC_CONFIGAUDIO 1004
#define IDC_CROSSBARLIST 1006
#define IDC_CROSSBAR 1007
#define IDC_RESOLUTION 1008
#define IDC_FPS_EDIT 1009
@ -15,6 +14,8 @@
#define IDC_REFRESH 1011
#define IDC_FPS2 1012
#define IDC_USEPREFERREDOUTPUT 1012
#define IDC_USEPREFERREDOUTPUT2 1013
#define IDC_USEBUFFERING 1013
#define IDC_FLIPIMAGE 1014
#define IDC_BUTTON1 1015
#define IDC_CUSTOM 1015
@ -46,8 +47,6 @@
#define IDC_TIMEOFFSET_EDIT 1032
#define IDC_TIMEOFFSET 1033
#define IDC_CHECK1 1034
#define IDC_NOBUFFERING 1034
#define IDC_FORCECUSTOMAUDIO 1034
#define IDC_CUSTOM1 1035
#define IDC_VOLUME 1035
#define IDC_VOLMETER 1036