From 1719b1599c74fdc7e1b5e82db5be07e2526b8a09 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sat, 29 Mar 2014 23:47:48 +1100 Subject: [PATCH] Get audio device names on Windows too. --- src/CMakeLists.txt | 2 + src/engines/devicefinder.cpp | 2 +- src/engines/devicefinder.h | 2 +- src/engines/directsounddevicefinder.cpp | 53 +++++++++++++++++++++++++ src/engines/directsounddevicefinder.h | 43 ++++++++++++++++++++ src/engines/gstengine.cpp | 28 +++++++++---- src/engines/gstenginepipeline.cpp | 12 ++++++ 7 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 src/engines/directsounddevicefinder.cpp create mode 100644 src/engines/directsounddevicefinder.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 15e85cdb6..b9aea5a00 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -876,6 +876,7 @@ optional_source(APPLE # Platform specific - Windows optional_source(WIN32 SOURCES + engines/directsounddevicefinder.cpp networkremote/tinysvcmdns.cpp widgets/osd_win.cpp INCLUDE_DIRECTORIES @@ -1326,6 +1327,7 @@ if (WIN32) ${QTSPARKLE_LIBRARIES} tinysvcmdns qtwin + dsound ) endif (WIN32) diff --git a/src/engines/devicefinder.cpp b/src/engines/devicefinder.cpp index ed4a3cb4d..4dda6abea 100644 --- a/src/engines/devicefinder.cpp +++ b/src/engines/devicefinder.cpp @@ -21,7 +21,7 @@ DeviceFinder::DeviceFinder(const QString& gstreamer_sink) : gstreamer_sink_(gstreamer_sink) { } -QString DeviceFinder::GuessIconName(const QString& description) const { +QString DeviceFinder::GuessIconName(const QString& description) { QString description_lower = description.toLower(); if (description_lower.contains("headset")) { return "audio-headset"; diff --git a/src/engines/devicefinder.h b/src/engines/devicefinder.h index bc293ab03..fe2ff671f 100644 --- a/src/engines/devicefinder.h +++ b/src/engines/devicefinder.h @@ -51,7 +51,7 @@ class DeviceFinder { protected: explicit DeviceFinder(const QString& gstreamer_sink); - QString GuessIconName(const QString& description) const; + static QString GuessIconName(const QString& description); private: QString gstreamer_sink_; diff --git a/src/engines/directsounddevicefinder.cpp b/src/engines/directsounddevicefinder.cpp new file mode 100644 index 000000000..9a1d62e25 --- /dev/null +++ b/src/engines/directsounddevicefinder.cpp @@ -0,0 +1,53 @@ +/* This file is part of Clementine. + Copyright 2014, David Sansome + + Clementine 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 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#ifdef INTERFACE +#undef INTERFACE +#endif + +#include + +#include + +#include "directsounddevicefinder.h" + +DirectSoundDeviceFinder::DirectSoundDeviceFinder() + : DeviceFinder("directsoundsink") { +} + +QList DirectSoundDeviceFinder::ListDevices() { + State state; + DirectSoundEnumerateA(&DirectSoundDeviceFinder::EnumerateCallback, &state); + return state.devices; +} + +BOOL DirectSoundDeviceFinder::EnumerateCallback(LPGUID guid, + LPCSTR description, + LPCSTR module, + LPVOID state_voidptr) { + State* state = reinterpret_cast(state_voidptr); + + if (guid) { + Device dev; + dev.description = QString::fromUtf8(description); + dev.device_property_value = QUuid(*guid).toByteArray(); + dev.icon_name = GuessIconName(dev.description); + state->devices.append(dev); + } + + return 1; +} diff --git a/src/engines/directsounddevicefinder.h b/src/engines/directsounddevicefinder.h new file mode 100644 index 000000000..1f46c414a --- /dev/null +++ b/src/engines/directsounddevicefinder.h @@ -0,0 +1,43 @@ +/* This file is part of Clementine. + Copyright 2014, David Sansome + + Clementine 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 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#ifndef DIRECTSOUNDDEVICEFINDER_H +#define DIRECTSOUNDDEVICEFINDER_H + +#include + +#include "engines/devicefinder.h" + +class DirectSoundDeviceFinder : public DeviceFinder { + public: + DirectSoundDeviceFinder(); + + virtual bool Initialise() { return true; } + virtual QList ListDevices(); + + private: + struct State { + QList devices; + }; + + static BOOL EnumerateCallback(LPGUID guid, + LPCSTR description, + LPCSTR module, + LPVOID state_voidptr) __attribute__((stdcall)); +}; + +#endif // DIRECTSOUNDDEVICEFINDER_H diff --git a/src/engines/gstengine.cpp b/src/engines/gstengine.cpp index 6d5f3b84d..d47c80f14 100644 --- a/src/engines/gstengine.cpp +++ b/src/engines/gstengine.cpp @@ -58,6 +58,10 @@ #include "engines/osxdevicefinder.h" #endif +#ifdef Q_OS_WIN32 +#include "engines/directsounddevicefinder.h" +#endif + using std::shared_ptr; using std::vector; @@ -134,6 +138,9 @@ void GstEngine::InitialiseGstreamer() { #ifdef Q_OS_DARWIN device_finders.append(new OsxDeviceFinder); #endif +#ifdef Q_OS_WIN32 + device_finders.append(new DirectSoundDeviceFinder); +#endif for (DeviceFinder* finder : device_finders) { if (!plugin_names.contains(finder->gstreamer_sink())) { @@ -843,15 +850,20 @@ GstEngine::OutputDetailsList GstEngine::GetOutputsList() const { } } - for (const PluginDetails& plugin : GetPluginList("Sink/Audio")) { - if (plugin.name == kAutoSink) { - continue; - } + PluginDetailsList plugins = GetPluginList("Sink/Audio"); + // If there are only 2 plugins (autoaudiosink and the OS' default), don't add + // any, since the OS' default would be redundant. + if (plugins.count() > 2) { + for (const PluginDetails& plugin : plugins) { + if (plugin.name == kAutoSink) { + continue; + } - OutputDetails output; - output.description = tr("Default device on %1").arg(plugin.description); - output.gstreamer_plugin_name = plugin.name; - ret.append(output); + OutputDetails output; + output.description = tr("Default device on %1").arg(plugin.description); + output.gstreamer_plugin_name = plugin.name; + ret.append(output); + } } return ret; diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index b01d3031d..9d897f5ea 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "bufferconsumer.h" #include "config.h" @@ -234,6 +235,17 @@ bool GstEnginePipeline::Init() { "device", device_.toString().toUtf8().constData(), nullptr); break; + + #ifdef Q_OS_WIN32 + case QVariant::ByteArray: { + GUID guid = QUuid(device_.toByteArray()); + g_object_set(G_OBJECT(audiosink_), + "device", &guid, + nullptr); + break; + } + #endif // Q_OS_WIN32 + default: qLog(Warning) << "Unknown device type" << device_; break;