aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2017-09-05 17:53:43 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2017-09-05 17:53:43 +0000
commit4abfc3230c456053eaf03bd47897612be9066e8e (patch)
treea32552ac229c1d61e8b4e9830db2e19e75163eb5 /src
parent89162c2e2e6141ac5df7494e576f623b20830ce0 (diff)
downloadqmmp-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
Diffstat (limited to 'src')
-rw-r--r--src/plugins/Output/oss4/settingsdialog.ui15
-rw-r--r--src/plugins/Output/wasapi/outputwasapi.cpp43
-rw-r--r--src/plugins/Output/wasapi/outputwasapi.h1
-rw-r--r--src/plugins/Output/wasapi/outputwasapifactory.cpp8
-rw-r--r--src/plugins/Output/wasapi/settingsdialog.cpp165
-rw-r--r--src/plugins/Output/wasapi/settingsdialog.h42
-rw-r--r--src/plugins/Output/wasapi/settingsdialog.ui93
-rw-r--r--src/plugins/Output/wasapi/wasapi.pro37
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