diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2017-09-05 17:53:43 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2017-09-05 17:53:43 +0000 |
| commit | 4abfc3230c456053eaf03bd47897612be9066e8e (patch) | |
| tree | a32552ac229c1d61e8b4e9830db2e19e75163eb5 | |
| parent | 89162c2e2e6141ac5df7494e576f623b20830ce0 (diff) | |
| download | qmmp-4abfc3230c456053eaf03bd47897612be9066e8e.tar.gz qmmp-4abfc3230c456053eaf03bd47897612be9066e8e.tar.bz2 qmmp-4abfc3230c456053eaf03bd47897612be9066e8e.zip | |
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
| -rw-r--r-- | src/plugins/Output/oss4/settingsdialog.ui | 15 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/outputwasapi.cpp | 43 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/outputwasapi.h | 1 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/outputwasapifactory.cpp | 8 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/settingsdialog.cpp | 165 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/settingsdialog.h | 42 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/settingsdialog.ui | 93 | ||||
| -rw-r--r-- | src/plugins/Output/wasapi/wasapi.pro | 37 |
8 files changed, 370 insertions, 34 deletions
diff --git a/src/plugins/Output/oss4/settingsdialog.ui b/src/plugins/Output/oss4/settingsdialog.ui index e96f1706c..d50c592b1 100644 --- a/src/plugins/Output/oss4/settingsdialog.ui +++ b/src/plugins/Output/oss4/settingsdialog.ui @@ -7,16 +7,25 @@ <x>0</x> <y>0</y> <width>276</width> - <height>68</height> + <height>64</height> </rect> </property> <property name="windowTitle"> - <string>OSS4 Plugin Settings</string> + <string>WASAPI Plugin Settings</string> </property> <layout class="QGridLayout"> - <property name="margin"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> <number>9</number> </property> + <property name="rightMargin"> + <number>6</number> + </property> + <property name="bottomMargin"> + <number>6</number> + </property> <property name="spacing"> <number>6</number> </property> 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 <string.h>
#include <iostream>
#include <unistd.h>
-#include <qmmp/buffer.h>
+#include <initguid.h>
+#include <audioclient.h>
+#include <endpointvolume.h>
+#include <mmdeviceapi.h>
+#include <mmreg.h>
+#include <functiondiscoverykeys_devpkey.h>
#include <math.h>
+#include <qmmp/buffer.h>
#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 <QMessageBox>
#include <QTranslator>
#include <QtPlugin>
+#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 <QSettings>
+#include <initguid.h>
+#include <audioclient.h>
+#include <endpointvolume.h>
+#include <mmdeviceapi.h>
+#include <mmreg.h>
+#include <functiondiscoverykeys_devpkey.h>
+#include <qmmp/qmmp.h>
+#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 <QDialog>
+#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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SettingsDialog</class> + <widget class="QDialog" name="SettingsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>276</width> + <height>68</height> + </rect> + </property> + <property name="windowTitle"> + <string>OSS4 Plugin Settings</string> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>9</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="0" column="1" colspan="2"> + <widget class="QComboBox" name="deviceComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Device:</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>SettingsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>179</x> + <y>51</y> + </hint> + <hint type="destinationlabel"> + <x>274</x> + <y>2</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>SettingsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>231</x> + <y>46</y> + </hint> + <hint type="destinationlabel"> + <x>271</x> + <y>44</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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
|
