Rename EngineDevice --> DeviceFinders, Add MMDeviceFinder
This commit is contained in:
@@ -26,8 +26,8 @@
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "devicefinders.h"
|
||||
#include "devicefinder.h"
|
||||
#include "enginedevice.h"
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
# include "alsadevicefinder.h"
|
||||
@@ -43,16 +43,16 @@
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
# include "directsounddevicefinder.h"
|
||||
# include "mmdevicefinder.h"
|
||||
#endif
|
||||
|
||||
EngineDevice::EngineDevice(QObject *parent) : QObject(parent) {
|
||||
}
|
||||
DeviceFinders::DeviceFinders(QObject *parent) : QObject(parent) {}
|
||||
|
||||
EngineDevice::~EngineDevice() {
|
||||
DeviceFinders::~DeviceFinders() {
|
||||
qDeleteAll(device_finders_);
|
||||
}
|
||||
|
||||
void EngineDevice::Init() {
|
||||
void DeviceFinders::Init() {
|
||||
|
||||
QList<DeviceFinder*> device_finders;
|
||||
|
||||
@@ -67,6 +67,7 @@ void EngineDevice::Init() {
|
||||
#endif
|
||||
#ifdef Q_OS_WIN32
|
||||
device_finders.append(new DirectSoundDeviceFinder);
|
||||
device_finders.append(new MMDeviceFinder);
|
||||
#endif
|
||||
|
||||
for (DeviceFinder *finder : device_finders) {
|
||||
@@ -17,8 +17,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ENGINEDEVICE_H
|
||||
#define ENGINEDEVICE_H
|
||||
#ifndef DEVICEFINDERS_H
|
||||
#define DEVICEFINDERS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -28,21 +28,19 @@
|
||||
|
||||
class DeviceFinder;
|
||||
|
||||
class EngineDevice : public QObject {
|
||||
class DeviceFinders : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EngineDevice(QObject *parent = nullptr);
|
||||
~EngineDevice();
|
||||
explicit DeviceFinders(QObject *parent = nullptr);
|
||||
~DeviceFinders();
|
||||
|
||||
void Init();
|
||||
|
||||
QList<DeviceFinder*> device_finders_;
|
||||
QList<DeviceFinder*> ListFinders() { return device_finders_; }
|
||||
|
||||
private:
|
||||
QString output_;
|
||||
QList<DeviceFinder*> device_finders_;
|
||||
|
||||
};
|
||||
|
||||
#endif // ENGINEDEVICE_H
|
||||
|
||||
#endif // DEVICEFINDERS_H
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "core/logging.h"
|
||||
|
||||
DirectSoundDeviceFinder::DirectSoundDeviceFinder()
|
||||
: DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink", "directx", "directx2", "wasapisink" }) {
|
||||
: DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink", "directx", "directx2" }) {
|
||||
}
|
||||
|
||||
QList<DeviceFinder::Device> DirectSoundDeviceFinder::ListDevices() {
|
||||
@@ -52,9 +52,7 @@ BOOL DirectSoundDeviceFinder::EnumerateCallback(LPGUID guid, LPCSTR description,
|
||||
|
||||
Device dev;
|
||||
dev.description = QString::fromLatin1(description);
|
||||
//if (guid) dev.value = QUuid(*guid).toByteArray();
|
||||
if (guid) dev.value = QUuid(*guid).toString();
|
||||
else dev.value = QVariant();
|
||||
dev.iconname = GuessIconName(dev.description);
|
||||
state->devices.append(dev);
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
#include "engine_fwd.h"
|
||||
#include "enginetype.h"
|
||||
#include "enginedevice.h"
|
||||
#include "devicefinders.h"
|
||||
#include "core/song.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <QTimeLine>
|
||||
#include <QMetaObject>
|
||||
#include <QtDebug>
|
||||
#include <QUuid>
|
||||
|
||||
#include "core/concurrentrun.h"
|
||||
#include "core/logging.h"
|
||||
@@ -197,11 +198,11 @@ bool GstEnginePipeline::InitAudioBin() {
|
||||
if (device_.isValid() && g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink), "device")) {
|
||||
switch (device_.type()) {
|
||||
case QVariant::String:
|
||||
if (device_.toString().isEmpty()) break;
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toString().toUtf8().constData(), nullptr);
|
||||
if (device_.toString().isEmpty()) break;
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toString().toUtf8().constData(), nullptr);
|
||||
break;
|
||||
case QVariant::ByteArray:
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toByteArray().constData(), nullptr);
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toByteArray().constData(), nullptr);
|
||||
break;
|
||||
case QVariant::LongLong:
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toLongLong(), nullptr);
|
||||
@@ -209,12 +210,20 @@ bool GstEnginePipeline::InitAudioBin() {
|
||||
case QVariant::Int:
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toInt(), nullptr);
|
||||
break;
|
||||
case QVariant::Uuid:
|
||||
g_object_set(G_OBJECT(audiosink), "device", device_.toUuid(), nullptr);
|
||||
break;
|
||||
default:
|
||||
qLog(Warning) << "Unknown device type" << device_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_ == "wasapisink") {
|
||||
g_object_set(G_OBJECT(audiosink), "exclusive", true, nullptr);
|
||||
g_object_set(G_OBJECT(audiosink), "low-latency", true, nullptr);
|
||||
}
|
||||
|
||||
// Create all the other elements
|
||||
|
||||
audioqueue_ = engine_->CreateElement("queue2", audiobin_);
|
||||
@@ -901,6 +910,7 @@ void GstEnginePipeline::SourceSetupCallback(GstPlayBin *bin, GParamSpec *, gpoin
|
||||
if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "device") && !instance->source_device().isEmpty()) {
|
||||
// Gstreamer is not able to handle device in URL (referring to Gstreamer documentation, this might be added in the future).
|
||||
// Despite that, for now we include device inside URL: we decompose it during Init and set device here, when this callback is called.
|
||||
qLog(Info) << instance->source_device().toLocal8Bit().constData();
|
||||
g_object_set(element, "device", instance->source_device().toLocal8Bit().constData(), nullptr);
|
||||
}
|
||||
|
||||
|
||||
115
src/engine/mmdevicefinder.cpp
Normal file
115
src/engine/mmdevicefinder.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry 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.
|
||||
*
|
||||
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <devpkey.h>
|
||||
#include <functiondiscoverykeys_devpkey.h>
|
||||
#include <mmdeviceapi.h>
|
||||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
#include "mmdevicefinder.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
MMDeviceFinder::MMDeviceFinder() : DeviceFinder("mmdevice", { "wasapisink" }) {}
|
||||
|
||||
QList<DeviceFinder::Device> MMDeviceFinder::ListDevices() {
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
IMMDeviceEnumerator *enumerator = nullptr;
|
||||
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enumerator);
|
||||
if (FAILED(hr)) {
|
||||
return QList<Device>();
|
||||
}
|
||||
|
||||
IMMDeviceCollection *collection = nullptr;
|
||||
hr = enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection);
|
||||
if (FAILED(hr)) {
|
||||
enumerator->Release();
|
||||
return QList<Device>();
|
||||
}
|
||||
|
||||
UINT count;
|
||||
hr = collection->GetCount(&count);
|
||||
if (FAILED(hr)) {
|
||||
collection->Release();
|
||||
enumerator->Release();
|
||||
return QList<Device>();
|
||||
}
|
||||
|
||||
QList<Device> devices;
|
||||
Device default_device;
|
||||
default_device.description = "Default device";
|
||||
default_device.iconname = GuessIconName(default_device.description);
|
||||
devices.append(default_device);
|
||||
|
||||
for (ULONG i = 0 ; i < count ; i++) {
|
||||
|
||||
IMMDevice *endpoint = nullptr;
|
||||
hr = collection->Item(i, &endpoint);
|
||||
if (FAILED(hr)) { return devices; }
|
||||
|
||||
LPWSTR pwszid = nullptr;
|
||||
hr = endpoint->GetId(&pwszid);
|
||||
if (FAILED(hr)) {
|
||||
endpoint->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
IPropertyStore *props = nullptr;
|
||||
hr = endpoint->OpenPropertyStore(STGM_READ, &props);
|
||||
if (FAILED(hr)) {
|
||||
CoTaskMemFree(pwszid);
|
||||
endpoint->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
PROPVARIANT var_name;
|
||||
PropVariantInit(&var_name);
|
||||
hr = props->GetValue(PKEY_Device_FriendlyName, &var_name);
|
||||
if (FAILED(hr)) {
|
||||
props->Release();
|
||||
CoTaskMemFree(pwszid);
|
||||
endpoint->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
Device device;
|
||||
device.description = QString::fromWCharArray(var_name.pwszVal);
|
||||
device.iconname = GuessIconName(device.description);
|
||||
device.value = QString::fromStdWString(pwszid);
|
||||
devices.append(device);
|
||||
|
||||
PropVariantClear(&var_name);
|
||||
props->Release();
|
||||
CoTaskMemFree(pwszid);
|
||||
endpoint->Release();
|
||||
|
||||
}
|
||||
collection->Release();
|
||||
enumerator->Release();
|
||||
|
||||
return devices;
|
||||
|
||||
}
|
||||
34
src/engine/mmdevicefinder.h
Normal file
34
src/engine/mmdevicefinder.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry 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.
|
||||
*
|
||||
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MMDEVICEFINDER_H
|
||||
#define MMDEVICEFINDER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "devicefinder.h"
|
||||
|
||||
class MMDeviceFinder : public DeviceFinder {
|
||||
public:
|
||||
MMDeviceFinder();
|
||||
virtual bool Initialise() { return true; }
|
||||
virtual QList<Device> ListDevices();
|
||||
};
|
||||
|
||||
#endif // MMDEVICEFINDER_H
|
||||
Reference in New Issue
Block a user