From 4abfc3230c456053eaf03bd47897612be9066e8e Mon Sep 17 00:00:00 2001 From: trialuser02 Date: Tue, 5 Sep 2017 17:53:43 +0000 Subject: wasapi: added feature to change device git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@7450 90c681e8-e032-0410-971d-27865f9a5e38 --- src/plugins/Output/wasapi/outputwasapi.cpp | 43 ++++-- src/plugins/Output/wasapi/outputwasapi.h | 1 + src/plugins/Output/wasapi/outputwasapifactory.cpp | 8 +- src/plugins/Output/wasapi/settingsdialog.cpp | 165 ++++++++++++++++++++++ src/plugins/Output/wasapi/settingsdialog.h | 42 ++++++ src/plugins/Output/wasapi/settingsdialog.ui | 93 ++++++++++++ src/plugins/Output/wasapi/wasapi.pro | 37 ++--- 7 files changed, 358 insertions(+), 31 deletions(-) create mode 100644 src/plugins/Output/wasapi/settingsdialog.cpp create mode 100644 src/plugins/Output/wasapi/settingsdialog.h create mode 100644 src/plugins/Output/wasapi/settingsdialog.ui (limited to 'src/plugins/Output/wasapi') diff --git a/src/plugins/Output/wasapi/outputwasapi.cpp b/src/plugins/Output/wasapi/outputwasapi.cpp index cc8f9b0ee..5faeb0c04 100644 --- a/src/plugins/Output/wasapi/outputwasapi.cpp +++ b/src/plugins/Output/wasapi/outputwasapi.cpp @@ -23,17 +23,16 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include #include "outputwasapi.h" -const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); -const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); -const IID IID_IAudioClient = __uuidof(IAudioClient); -const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); -const IID IID_IChannelAudioVolume = __uuidof(IChannelAudioVolume); -const IID IID_ISimpleAudioVolume = __uuidof(ISimpleAudioVolume); - #define WASAPI_BUFSIZE 10000000LL //1s #ifndef AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM @@ -63,6 +62,8 @@ OutputWASAPI::OutputWASAPI() : Output() m_pRenderClient = 0; m_pSimpleAudioVolume = 0; instance = this; + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + m_id = settings.value("WASAPI/device", "default").toString(); } OutputWASAPI::~OutputWASAPI() @@ -81,11 +82,29 @@ bool OutputWASAPI::initialize(quint32 freq, ChannelMap map, Qmmp::AudioFormat fo return false; } - if((result = m_pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice)) != S_OK) + if(m_id != "default" && !m_id.isEmpty()) { - qWarning("OutputWASAPI: IMMDeviceEnumerator::GetDefaultAudioEndpoint failed, error code = 0x%lx", result); - m_pDevice = 0; - return false; + WCHAR id[m_id.length() + 1]; + m_id.toWCharArray(id); + id[m_id.length()] = 0; + + if((result = m_pEnumerator->GetDevice(id, &m_pDevice)) != S_OK) + { + qWarning("OutputWASAPI: IMMDeviceEnumerator::GetDevice failed, error code = 0x%lx", result); + m_pDevice = 0; + } + else + qDebug("OutputWASAPI: using device id: %s", qPrintable(m_id)); + } + + if(!m_pDevice) + { + if((result = m_pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice)) != S_OK) + { + qWarning("OutputWASAPI: IMMDeviceEnumerator::GetDefaultAudioEndpoint failed, error code = 0x%lx", result); + m_pDevice = 0; + return false; + } } if((result = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient)) != S_OK) diff --git a/src/plugins/Output/wasapi/outputwasapi.h b/src/plugins/Output/wasapi/outputwasapi.h index 421c01010..c17465ea9 100644 --- a/src/plugins/Output/wasapi/outputwasapi.h +++ b/src/plugins/Output/wasapi/outputwasapi.h @@ -68,6 +68,7 @@ private: UINT32 m_bufferFrames; int m_frameSize; + QString m_id; typedef struct { diff --git a/src/plugins/Output/wasapi/outputwasapifactory.cpp b/src/plugins/Output/wasapi/outputwasapifactory.cpp index 73dda8ac3..954326a21 100644 --- a/src/plugins/Output/wasapi/outputwasapifactory.cpp +++ b/src/plugins/Output/wasapi/outputwasapifactory.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2016 by Ilya Kotov * + * Copyright (C) 2016-2017 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -21,6 +21,7 @@ #include #include #include +#include "settingsdialog.h" #include "outputwasapi.h" #include "outputwasapifactory.h" @@ -29,7 +30,7 @@ const OutputProperties OutputWASAPIFactory::properties() const OutputProperties properties; properties.name = tr("WASAPI Plugin"); properties.hasAbout = true; - properties.hasSettings = false; + properties.hasSettings = true; properties.shortName = "wasapi"; return properties; } @@ -46,7 +47,8 @@ Volume *OutputWASAPIFactory::createVolume() void OutputWASAPIFactory::showSettings(QWidget* parent) { - Q_UNUSED(parent); + SettingsDialog *s = new SettingsDialog(parent); + s->show(); } void OutputWASAPIFactory::showAbout(QWidget *parent) diff --git a/src/plugins/Output/wasapi/settingsdialog.cpp b/src/plugins/Output/wasapi/settingsdialog.cpp new file mode 100644 index 000000000..f0e26afec --- /dev/null +++ b/src/plugins/Output/wasapi/settingsdialog.cpp @@ -0,0 +1,165 @@ +/*************************************************************************** + * Copyright (C) 2017 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) : + QDialog(parent) +{ + m_ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + enumDevices(); + + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + QString id = settings.value("WASAPI/device", "default").toString(); + int index = m_ui.deviceComboBox->findData(id); + m_ui.deviceComboBox->setCurrentIndex(qMax(index, 0)); +} + +void SettingsDialog::accept() +{ + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + int index = m_ui.deviceComboBox->currentIndex(); + settings.setValue("WASAPI/device", m_ui.deviceComboBox->itemData(index).toString()); + QDialog::accept(); +} + +void SettingsDialog::enumDevices() +{ + m_ui.deviceComboBox->clear(); + m_ui.deviceComboBox->addItem(tr("Default"), "default"); + + IMMDeviceEnumerator *pEnumerator = 0; + HRESULT result = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); + if(result != S_OK) + { + qWarning("SettingsDialog: CoCreateInstance failed, error code = 0x%lx", result); + pEnumerator = 0; + } + + IMMDeviceCollection *pEndpoints = 0; + IMMDevice *pEndpoint = 0; + LPWSTR pwszID = 0; + IPropertyStore *pProps = 0; + UINT count = 0; + + result = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEndpoints); + if(result != S_OK) + { + qWarning("SettingsDialog: IMMDeviceEnumerator::EnumAudioEndpoints failed, error code = 0x%lx", result); + pEndpoints = 0; + } + + if(pEndpoints) + { + pEndpoints->GetCount(&count); + if(result != S_OK) + { + qWarning("SettingsDialog: IMMDeviceCollection::GetCount failed, error code = 0x%lx", result); + count = 0; + } + + for(UINT i = 0; i < count; ++i) + { + result = pEndpoints->Item(i, &pEndpoint); + if(result != S_OK) + { + qWarning("SettingsDialog: IMMDeviceCollection::Item failed, error code = 0x%lx", result); + pEndpoint = 0; + break; + } + + result = pEndpoint->GetId(&pwszID); + if(result != S_OK) + { + qWarning("SettingsDialog: IMMDevice::GetId failed, error code = 0x%lx", result); + pwszID = 0; + break; + } + + result = pEndpoint->OpenPropertyStore(STGM_READ, &pProps); + if(result != S_OK) + { + qWarning("SettingsDialog: IMMDevice::GetId failed, error code = 0x%lx", result); + pProps = 0; + break; + } + + PROPVARIANT varName; + PropVariantInit(&varName); // Initialize container for property value. + result = pProps->GetValue(PKEY_Device_FriendlyName, &varName); // Get the endpoint's friendly-name property. + if(result != S_OK) + { + qWarning("SettingsDialog: IMMDevice::GetId failed, error code = 0x%lx", result); + PropVariantClear(&varName); + break; + } + + m_ui.deviceComboBox->addItem(QString::fromWCharArray(varName.pwszVal), QString::fromWCharArray(pwszID)); + + CoTaskMemFree(pwszID); + pwszID = 0; + PropVariantClear(&varName); + pProps->Release(); + pProps = 0; + pEndpoint->Release(); + pEndpoint = 0; + } + } + + if(pProps) + { + pProps->Release(); + pProps = 0; + } + + if(pwszID) + { + CoTaskMemFree(pwszID); + pwszID = 0; + } + + if(pEndpoint) + { + pEndpoint->Release(); + pEndpoint = 0; + } + + if(pEndpoints) + { + pEndpoints->Release(); + pEndpoints = 0; + } + + if(pEnumerator) + { + pEnumerator->Release(); + pEnumerator = 0; + } +} diff --git a/src/plugins/Output/wasapi/settingsdialog.h b/src/plugins/Output/wasapi/settingsdialog.h new file mode 100644 index 000000000..017dbb343 --- /dev/null +++ b/src/plugins/Output/wasapi/settingsdialog.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2017 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include +#include "ui_settingsdialog.h" + +class SettingsDialog : public QDialog +{ + Q_OBJECT +public: + explicit SettingsDialog(QWidget *parent = 0); + +public slots: + void accept(); + +private: + void enumDevices(); + Ui::SettingsDialog m_ui; + +}; + +#endif // SETTINGSDIALOG_H diff --git a/src/plugins/Output/wasapi/settingsdialog.ui b/src/plugins/Output/wasapi/settingsdialog.ui new file mode 100644 index 000000000..e96f1706c --- /dev/null +++ b/src/plugins/Output/wasapi/settingsdialog.ui @@ -0,0 +1,93 @@ + + + SettingsDialog + + + + 0 + 0 + 276 + 68 + + + + OSS4 Plugin Settings + + + + 9 + + + 6 + + + + + + 0 + 0 + + + + true + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + 0 + 0 + + + + Device: + + + + + + + + + buttonBox + accepted() + SettingsDialog + accept() + + + 179 + 51 + + + 274 + 2 + + + + + buttonBox + rejected() + SettingsDialog + reject() + + + 231 + 46 + + + 271 + 44 + + + + + diff --git a/src/plugins/Output/wasapi/wasapi.pro b/src/plugins/Output/wasapi/wasapi.pro index 014bb4851..d66c9f8c0 100644 --- a/src/plugins/Output/wasapi/wasapi.pro +++ b/src/plugins/Output/wasapi/wasapi.pro @@ -1,16 +1,21 @@ -include(../../plugins.pri) - -TARGET = $$PLUGINS_PREFIX/Output/wasapi - -HEADERS += outputwasapifactory.h \ - outputwasapi.h - -SOURCES += outputwasapifactory.cpp \ - outputwasapi.cpp - -RESOURCES = translations/translations.qrc - -LIBS += -lstrmiids -ldmoguids -lmsdmo -lole32 -loleaut32 -luuid -lgdi32 -lksuser - -target.path = $$LIB_DIR/qmmp/Output -INSTALLS += target +include(../../plugins.pri) + +TARGET = $$PLUGINS_PREFIX/Output/wasapi + +HEADERS += outputwasapifactory.h \ + outputwasapi.h \ + settingsdialog.h + +SOURCES += outputwasapifactory.cpp \ + outputwasapi.cpp \ + settingsdialog.cpp + +RESOURCES = translations/translations.qrc + +LIBS += -lstrmiids -ldmoguids -lmsdmo -lole32 -loleaut32 -luuid -lgdi32 -lksuser + +target.path = $$LIB_DIR/qmmp/Output +INSTALLS += target + +FORMS += \ + settingsdialog.ui -- cgit v1.2.3-13-gbd6f