From 8fca45acc3ac3c103ed47d91b6a875ae22716b0a Mon Sep 17 00:00:00 2001
From: Alexander Lantsev <aunsane@gmail.com>
Date: Tue, 8 Sep 2015 20:04:50 +0000
Subject: Tox: moving on MMDeviceAPI. pt 1. Multimedia options

git-svn-id: http://svn.miranda-ng.org/main/trunk@15312 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 protocols/Tox/src/stdafx.h        |   5 ++
 protocols/Tox/src/tox_core.cpp    |  21 +++---
 protocols/Tox/src/tox_options.cpp | 143 ++++++++++++++++++++++++++------------
 protocols/Tox/src/tox_options.h   |   5 +-
 4 files changed, 119 insertions(+), 55 deletions(-)

(limited to 'protocols')

diff --git a/protocols/Tox/src/stdafx.h b/protocols/Tox/src/stdafx.h
index 93c73cdf65..3374130495 100644
--- a/protocols/Tox/src/stdafx.h
+++ b/protocols/Tox/src/stdafx.h
@@ -7,6 +7,11 @@
 #include <commctrl.h>
 
 #include <mmreg.h>
+#include <MMDeviceAPI.h>
+
+#define EXIT_ON_ERROR(hres) if (FAILED(hres)) { goto Exit; }
+#define SAFE_RELEASE(punk) if ((punk) != NULL) { (punk)->Release(); (punk) = NULL; }
+DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
 
 #include <string>
 #include <vector>
diff --git a/protocols/Tox/src/tox_core.cpp b/protocols/Tox/src/tox_core.cpp
index 57281ad340..e2c683d751 100644
--- a/protocols/Tox/src/tox_core.cpp
+++ b/protocols/Tox/src/tox_core.cpp
@@ -68,15 +68,18 @@ bool CToxProto::InitToxCore()
 		// group chats
 		//tox_callback_group_invite(tox, OnGroupChatInvite, this);
 		// a/v
-		/*toxAv = toxav_new(tox, TOX_MAX_CALLS);
-		toxav_register_audio_callback(toxAv, OnFriendAudio, this);
-		toxav_register_callstate_callback(toxAv, OnAvInvite, av_OnInvite, this);
-		toxav_register_callstate_callback(toxAv, OnAvStart, av_OnStart, this);
-		toxav_register_callstate_callback(toxAv, OnAvCancel, av_OnCancel, this);
-		toxav_register_callstate_callback(toxAv, OnAvReject, av_OnReject, this);
-		toxav_register_callstate_callback(toxAv, OnAvEnd, av_OnEnd, this);
-		toxav_register_callstate_callback(toxAv, OnAvCallTimeout, av_OnRequestTimeout, this);
-		toxav_register_callstate_callback(toxAv, OnAvPeerTimeout, av_OnPeerTimeout, this);*/
+		if (IsWinVerVistaPlus())
+		{
+			/*toxAv = toxav_new(tox, TOX_MAX_CALLS);
+			toxav_register_audio_callback(toxAv, OnFriendAudio, this);
+			toxav_register_callstate_callback(toxAv, OnAvInvite, av_OnInvite, this);
+			toxav_register_callstate_callback(toxAv, OnAvStart, av_OnStart, this);
+			toxav_register_callstate_callback(toxAv, OnAvCancel, av_OnCancel, this);
+			toxav_register_callstate_callback(toxAv, OnAvReject, av_OnReject, this);
+			toxav_register_callstate_callback(toxAv, OnAvEnd, av_OnEnd, this);
+			toxav_register_callstate_callback(toxAv, OnAvCallTimeout, av_OnRequestTimeout, this);
+			toxav_register_callstate_callback(toxAv, OnAvPeerTimeout, av_OnPeerTimeout, this);*/
+		}
 
 		uint8_t data[TOX_ADDRESS_SIZE];
 		tox_self_get_address(tox, data);
diff --git a/protocols/Tox/src/tox_options.cpp b/protocols/Tox/src/tox_options.cpp
index b559cc1f4d..87b9df8ce3 100644
--- a/protocols/Tox/src/tox_options.cpp
+++ b/protocols/Tox/src/tox_options.cpp
@@ -152,8 +152,8 @@ void CToxOptionsMain::ProfileExport_OnClick(CCtrlButton*)
 	ofn.lpstrFilter = filter;
 	ofn.nFilterIndex = 0;
 	ofn.lpstrFile = profilePath;
-	ofn.lpstrTitle = TranslateT("Save Tox profile");\
-	ofn.nMaxFile = MAX_PATH;
+	ofn.lpstrTitle = TranslateT("Save Tox profile"); \
+		ofn.nMaxFile = MAX_PATH;
 	ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_EXPLORER;
 	ofn.lpstrInitialDir = _T("%HOMEPATH%");
 
@@ -192,69 +192,124 @@ CToxOptionsMultimedia::CToxOptionsMultimedia(CToxProto *proto)
 {
 }
 
-bool CToxOptionsMultimedia::GetDeviceFullName(GUID guid, TCHAR *deviceName, DWORD deviceNameLength)
+void CToxOptionsMultimedia::EnumDevices(CCtrlCombo &combo, IMMDeviceEnumerator *pEnumerator, EDataFlow dataFlow, const char* setting)
 {
-	TCHAR registryKey[MAX_PATH];
-	mir_sntprintf(registryKey, _T("System\\CurrentControlSet\\Control\\MediaCategories\\{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
-		guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+	HRESULT hr;
+	UINT count;
+	DBVARIANT dbv;
+	LPWSTR pwszID = NULL,
+		pwszDefID = NULL;
+	IMMDevice *pDevice = NULL;
+	IMMDeviceCollection *pDevices = NULL;
+	PROPVARIANT varName;
+	IPropertyStore *pProperties = NULL;
+
+	if (!m_proto->getWString(setting, &dbv))
+	{
+		int len = mir_wstrlen(dbv.pwszVal) * 2;
+		pwszDefID = (LPWSTR)CoTaskMemAlloc(len + 1);
+		mir_wstrncpy(pwszDefID, dbv.pwszVal, len);
+		db_free(&dbv);
+	}
+	else
+	{
+		hr = pEnumerator->GetDefaultAudioEndpoint(dataFlow, eConsole, &pDevice);
+		EXIT_ON_ERROR(hr);
+		hr = pDevice->GetId(&pwszDefID);
+		EXIT_ON_ERROR(hr);
+	}
 
-	HKEY hKey;
-	LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registryKey, 0, KEY_READ, &hKey);
-	if (error != ERROR_SUCCESS)
-		return false;
+	hr = pEnumerator->EnumAudioEndpoints(dataFlow, DEVICE_STATE_ACTIVE, &pDevices);
+	EXIT_ON_ERROR(hr);
+	hr = pDevices->GetCount(&count);
+	EXIT_ON_ERROR(hr);
 
-	error = RegQueryValueEx(hKey, _T("Name"), 0, NULL, (LPBYTE)deviceName, &deviceNameLength);
-	if (error != ERROR_SUCCESS)
+	for (UINT i = 0; i < count; i++)
 	{
-		RegCloseKey(hKey);
-		return false;
+		hr = pDevices->Item(i, &pDevice);
+		EXIT_ON_ERROR(hr);
+		hr = pDevice->OpenPropertyStore(STGM_READ, &pProperties);
+		EXIT_ON_ERROR(hr);
+		PropVariantInit(&varName);
+		hr = pProperties->GetValue(PKEY_Device_FriendlyName, &varName);
+		EXIT_ON_ERROR(hr);
+		hr = pDevice->GetId(&pwszID);
+		EXIT_ON_ERROR(hr);
+		combo.InsertString(varName.pwszVal, i, (LPARAM)mir_wstrdup(pwszID));
+		if (mir_wstrcmpi(pwszID, pwszDefID) == 0)
+			combo.SetCurSel(i);
+		CoTaskMemFree(pwszID);
+		CoTaskMemFree(pwszDefID);
+		PropVariantClear(&varName);
+		SAFE_RELEASE(pDevice);
+		SAFE_RELEASE(pProperties);
 	}
 
-	RegCloseKey(hKey);
-	return true;
+	SAFE_RELEASE(pDevices);
+	return;
+
+Exit:
+	CoTaskMemFree(pwszID);
+	CoTaskMemFree(pwszDefID);
+	SAFE_RELEASE(pDevices);
+	SAFE_RELEASE(pDevice);
+	SAFE_RELEASE(pProperties);
 }
 
 void CToxOptionsMultimedia::OnInitDialog()
 {
 	CToxDlgBase::OnInitDialog();
 
-	DWORD count = 0;
-	TCHAR deviceName[MAX_PATH];
-	DWORD deviceNameLength = _countof(deviceName);
+	IMMDeviceEnumerator *pEnumerator = NULL;
+	HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
+	EXIT_ON_ERROR(hr);
 
-	WAVEINCAPS2 wic2;
-	count = waveInGetNumDevs();
-	for (DWORD i = 0; i < count; i++)
-	{
-		if (!waveInGetDevCaps(i, (LPWAVEINCAPS)&wic2, sizeof(WAVEINCAPS2)))
-		{
-			if (!GetDeviceFullName(wic2.NameGuid, deviceName, deviceNameLength))
-				mir_tstrncpy(deviceName, wic2.szPname, deviceNameLength);
+	EnumDevices(m_audioInput, pEnumerator, eCapture, "AudioInputDeviceID");
+	EnumDevices(m_audioOutput, pEnumerator, eRender, "AudioOutputDeviceID");
+	return;
 
-			m_audioInput.InsertString(deviceName, i);
-		}
-	}
-	m_audioInput.SetCurSel(m_proto->getDword("AudioInputDeviceID", 0));
+Exit:
+	SAFE_RELEASE(pEnumerator);
+}
 
-	WAVEOUTCAPS2 woc2;
-	count = waveOutGetNumDevs();
-	for (DWORD i = 0; i < count; i++)
+void CToxOptionsMultimedia::OnApply()
+{
+	int i = m_audioInput.GetCurSel();
+	if (i == -1)
+		m_proto->delSetting("AudioInputDeviceID");
+	else
 	{
-		if (!waveOutGetDevCaps(i, (LPWAVEOUTCAPS)&woc2, sizeof(WAVEOUTCAPS2)))
-		{
-			if (!GetDeviceFullName(woc2.NameGuid, deviceName, deviceNameLength))
-				mir_tstrncpy(deviceName, woc2.szPname, deviceNameLength);
+		wchar_t* data = (wchar_t*)m_audioInput.GetItemData(i);
+		m_proto->setWString("AudioInputDeviceID", data);
+	}
 
-			m_audioOutput.InsertString(deviceName, i);
-		}
+	i = m_audioOutput.GetCurSel();
+	if (i == -1)
+		m_proto->delSetting("AudioOutputDeviceID");
+	else
+	{
+		wchar_t* data = (wchar_t*)m_audioOutput.GetItemData(i);
+		m_proto->setWString("AudioOutputDeviceID", data);
 	}
-	m_audioOutput.SetCurSel(m_proto->getDword("AudioOutputDeviceID", 0));
 }
 
-void CToxOptionsMultimedia::OnApply()
+void CToxOptionsMultimedia::OnDestroy()
 {
-	m_proto->setDword("AudioInputDeviceID", m_audioInput.GetCurSel());
-	m_proto->setDword("AudioOutputDeviceID", m_audioOutput.GetCurSel());
+	int count = m_audioInput.GetCount();
+	for (int i = 0; i < count; i++)
+	{
+		wchar_t* data = (wchar_t*)m_audioInput.GetItemData(i);
+		mir_free(data);
+
+	}
+
+	count = m_audioOutput.GetCount();
+	for (int i = 0; i < count; i++)
+	{
+		wchar_t* data = (wchar_t*)m_audioOutput.GetItemData(i);
+		mir_free(data);
+
+	}
 }
 
 /////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/Tox/src/tox_options.h b/protocols/Tox/src/tox_options.h
index 902bc49254..a3550bf454 100644
--- a/protocols/Tox/src/tox_options.h
+++ b/protocols/Tox/src/tox_options.h
@@ -53,11 +53,12 @@ private:
 	CCtrlCombo m_audioInput;
 	CCtrlCombo m_audioOutput;
 
-	static bool GetDeviceFullName(GUID guid, TCHAR *deviceName, DWORD deviceNameLength);
-
 protected:
+	void EnumDevices(CCtrlCombo &combo, IMMDeviceEnumerator *pEnumerator, EDataFlow dataFlow, const char* setting);
+
 	void OnInitDialog();
 	void OnApply();
+	void OnDestroy();
 
 public:
 	CToxOptionsMultimedia(CToxProto *proto);
-- 
cgit v1.2.3