From 315073f9a7b29c7ca2ca384da33074a5dfc57748 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Thu, 1 Jun 2023 19:31:19 +0200 Subject: [PATCH] Add EngineDevice class --- src/CMakeLists.txt | 1 + src/engine/alsadevicefinder.cpp | 16 ++++----- src/engine/alsadevicefinder.h | 3 +- src/engine/alsapcmdevicefinder.cpp | 10 +++--- src/engine/alsapcmdevicefinder.h | 3 +- src/engine/devicefinder.cpp | 30 ---------------- src/engine/devicefinder.h | 19 ++-------- src/engine/directsounddevicefinder.cpp | 13 +++---- src/engine/directsounddevicefinder.h | 5 +-- src/engine/enginedevice.cpp | 50 ++++++++++++++++++++++++++ src/engine/enginedevice.h | 39 ++++++++++++++++++++ src/engine/macosdevicefinder.cpp | 23 ++++++------ src/engine/macosdevicefinder.h | 3 +- src/engine/mmdevicefinder.cpp | 13 +++---- src/engine/mmdevicefinder.h | 3 +- src/engine/pulsedevicefinder.cpp | 16 ++++----- src/engine/pulsedevicefinder.h | 5 +-- src/engine/uwpdevicefinder.cpp | 23 ++++++------ src/engine/uwpdevicefinder.h | 1 + src/settings/backendsettingspage.cpp | 5 +-- 20 files changed, 170 insertions(+), 111 deletions(-) create mode 100644 src/engine/enginedevice.cpp create mode 100644 src/engine/enginedevice.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 38a057e9e..2d4a28da4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,7 @@ set(SOURCES utilities/screenutils.cpp engine/enginebase.cpp + engine/enginedevice.cpp engine/devicefinders.cpp engine/devicefinder.cpp engine/enginemetadata.cpp diff --git a/src/engine/alsadevicefinder.cpp b/src/engine/alsadevicefinder.cpp index 7211f6b71..5d39d3286 100644 --- a/src/engine/alsadevicefinder.cpp +++ b/src/engine/alsadevicefinder.cpp @@ -28,14 +28,14 @@ #include -#include "devicefinder.h" #include "alsadevicefinder.h" +#include "enginedevice.h" AlsaDeviceFinder::AlsaDeviceFinder() : DeviceFinder("alsa", { "alsa", "alsasink" }) {} -DeviceFinder::DeviceList AlsaDeviceFinder::ListDevices() { +EngineDeviceList AlsaDeviceFinder::ListDevices() { - DeviceList ret; + EngineDeviceList devices; snd_pcm_stream_name(SND_PCM_STREAM_PLAYBACK); @@ -91,21 +91,21 @@ DeviceFinder::DeviceList AlsaDeviceFinder::ListDevices() { continue; } - Device device; + EngineDevice device; device.description = QString("%1 %2").arg(snd_ctl_card_info_get_name(cardinfo), snd_pcm_info_get_name(pcminfo)); - device.iconname = GuessIconName(device.description); + device.iconname = device.GuessIconName(); device.card = card; device.device = dev; device.value = QString("hw:%1,%2").arg(card).arg(dev); - ret.append(device); + devices.append(device); device.value = QString("plughw:%1,%2").arg(card).arg(dev); - ret.append(device); + devices.append(device); } } snd_config_update_free_global(); - return ret; + return devices; } diff --git a/src/engine/alsadevicefinder.h b/src/engine/alsadevicefinder.h index 31a0fc60f..4e831351e 100644 --- a/src/engine/alsadevicefinder.h +++ b/src/engine/alsadevicefinder.h @@ -23,13 +23,14 @@ #include "config.h" #include "devicefinder.h" +#include "enginedevice.h" class AlsaDeviceFinder : public DeviceFinder { public: explicit AlsaDeviceFinder(); bool Initialize() override { return true; } - DeviceList ListDevices() override; + EngineDeviceList ListDevices() override; private: Q_DISABLE_COPY(AlsaDeviceFinder) diff --git a/src/engine/alsapcmdevicefinder.cpp b/src/engine/alsapcmdevicefinder.cpp index 9f6a5501c..2f24fd073 100644 --- a/src/engine/alsapcmdevicefinder.cpp +++ b/src/engine/alsapcmdevicefinder.cpp @@ -25,14 +25,14 @@ #include -#include "devicefinder.h" #include "alsapcmdevicefinder.h" +#include "enginedevice.h" AlsaPCMDeviceFinder::AlsaPCMDeviceFinder() : DeviceFinder("alsa", { "alsa", "alsasink" }) {} -DeviceFinder::DeviceList AlsaPCMDeviceFinder::ListDevices() { +EngineDeviceList AlsaPCMDeviceFinder::ListDevices() { - DeviceList ret; + EngineDeviceList ret; void **hints = nullptr; if (snd_device_name_hint(-1, "pcm", &hints) < 0) { @@ -63,10 +63,10 @@ DeviceFinder::DeviceList AlsaPCMDeviceFinder::ListDevices() { description.append(desc_last); } - Device device; + EngineDevice device; device.value = name; device.description = description; - device.iconname = GuessIconName(device.description); + device.iconname = device.GuessIconName(); ret << device; // clazy:exclude=reserve-candidates } if (hint_io) free(hint_io); diff --git a/src/engine/alsapcmdevicefinder.h b/src/engine/alsapcmdevicefinder.h index b288ee71f..2f58b3e25 100644 --- a/src/engine/alsapcmdevicefinder.h +++ b/src/engine/alsapcmdevicefinder.h @@ -23,13 +23,14 @@ #include "config.h" #include "devicefinder.h" +#include "enginedevice.h" class AlsaPCMDeviceFinder : public DeviceFinder { public: explicit AlsaPCMDeviceFinder(); bool Initialize() override { return true; } - DeviceList ListDevices() override; + EngineDeviceList ListDevices() override; private: Q_DISABLE_COPY(AlsaPCMDeviceFinder) diff --git a/src/engine/devicefinder.cpp b/src/engine/devicefinder.cpp index 002604c08..903a89f90 100644 --- a/src/engine/devicefinder.cpp +++ b/src/engine/devicefinder.cpp @@ -24,33 +24,3 @@ #include "devicefinder.h" DeviceFinder::DeviceFinder(const QString &name, const QStringList &outputs) : name_(name), outputs_(outputs) {} - -QString DeviceFinder::GuessIconName(const QString &description) { - - QString description_lower = description.toLower(); - - if (description_lower.contains("mcintosh")) { - return "mcintosh"; - } - if (description_lower.contains("electrocompaniet")) { - return "electrocompaniet"; - } - if (description_lower.contains("intel")) { - return "intel"; - } - if (description_lower.contains("realtek")) { - return "realtek"; - } - if (description_lower.contains("nvidia")) { - return "nvidia"; - } - if (description_lower.contains("headset")) { - return "headset"; - } - if (description_lower.contains("pulseaudio")) { - return "pulseaudio"; - } - - return "soundcard"; - -} diff --git a/src/engine/devicefinder.h b/src/engine/devicefinder.h index f3d2515d8..16b10b067 100644 --- a/src/engine/devicefinder.h +++ b/src/engine/devicefinder.h @@ -24,24 +24,13 @@ #include "config.h" -#include -#include #include +#include "enginedevice.h" + // Finds audio output devices class DeviceFinder { - public: - struct Device { - Device() : card(0), device(0) {} - QString description; - QVariant value; - QString iconname; - int card; - int device; - }; - using DeviceList = QList; - virtual ~DeviceFinder() {} QString name() const { return name_; } @@ -52,13 +41,11 @@ class DeviceFinder { virtual bool Initialize() = 0; // Returns a list of available devices. - virtual DeviceList ListDevices() = 0; + virtual EngineDeviceList ListDevices() = 0; protected: explicit DeviceFinder(const QString &name, const QStringList &outputs); - static QString GuessIconName(const QString &description); - private: QString name_; QStringList outputs_; diff --git a/src/engine/directsounddevicefinder.cpp b/src/engine/directsounddevicefinder.cpp index 091e1020c..64ec12857 100644 --- a/src/engine/directsounddevicefinder.cpp +++ b/src/engine/directsounddevicefinder.cpp @@ -32,11 +32,12 @@ #include #include "directsounddevicefinder.h" +#include "enginedevice.h" #include "core/logging.h" DirectSoundDeviceFinder::DirectSoundDeviceFinder() : DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink", "directx", "directx2" }) {} -DeviceFinder::DeviceList DirectSoundDeviceFinder::ListDevices() { +EngineDeviceList DirectSoundDeviceFinder::ListDevices() { State state; DirectSoundEnumerateA(&DirectSoundDeviceFinder::EnumerateCallback, &state); return state.devices; @@ -48,11 +49,11 @@ BOOL CALLBACK DirectSoundDeviceFinder::EnumerateCallback(LPGUID guid, LPCSTR des State *state = reinterpret_cast(state_voidptr); - Device dev; - dev.description = QString::fromLatin1(description); - if (guid) dev.value = QUuid(*guid).toString(); - dev.iconname = GuessIconName(dev.description); - state->devices.append(dev); + EngineDevice device; + device.description = QString::fromLatin1(description); + if (guid) device.value = QUuid(*guid).toString(); + device.iconname = device.GuessIconName(); + state->devices.append(device); return 1; diff --git a/src/engine/directsounddevicefinder.h b/src/engine/directsounddevicefinder.h index 2d775a031..6c58a8a40 100644 --- a/src/engine/directsounddevicefinder.h +++ b/src/engine/directsounddevicefinder.h @@ -27,17 +27,18 @@ #include #include "devicefinder.h" +#include "enginedevice.h" class DirectSoundDeviceFinder : public DeviceFinder { public: explicit DirectSoundDeviceFinder(); virtual bool Initialize() { return true; } - virtual DeviceList ListDevices(); + virtual EngineDeviceList ListDevices(); private: struct State { - DeviceList devices; + EngineDeviceList devices; }; static BOOL CALLBACK EnumerateCallback(LPGUID guid, LPCSTR description, LPCSTR module, LPVOID state_voidptr); diff --git a/src/engine/enginedevice.cpp b/src/engine/enginedevice.cpp new file mode 100644 index 000000000..5e1b1ad57 --- /dev/null +++ b/src/engine/enginedevice.cpp @@ -0,0 +1,50 @@ +/* +* Strawberry Music Player +* Copyright 2021-2023, Jonas Kvinge +* +* 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 . +* +*/ + +#include "enginedevice.h" + +EngineDevice::EngineDevice() : card(0), device(0) {} + +QString EngineDevice::GuessIconName() const { + + if (description.contains("mcintosh", Qt::CaseInsensitive)) { + return "mcintosh"; + } + if (description.contains("electrocompaniet", Qt::CaseInsensitive)) { + return "electrocompaniet"; + } + if (description.contains("intel", Qt::CaseInsensitive)) { + return "intel"; + } + if (description.contains("realtek", Qt::CaseInsensitive)) { + return "realtek"; + } + if (description.contains("nvidia", Qt::CaseInsensitive)) { + return "nvidia"; + } + if (description.contains("headset", Qt::CaseInsensitive)) { + return "headset"; + } + if (description.contains("pulseaudio", Qt::CaseInsensitive)) { + return "pulseaudio"; + } + + return "soundcard"; + +} diff --git a/src/engine/enginedevice.h b/src/engine/enginedevice.h new file mode 100644 index 000000000..bd0b0c4b6 --- /dev/null +++ b/src/engine/enginedevice.h @@ -0,0 +1,39 @@ +/* +* Strawberry Music Player +* Copyright 2021-2023, Jonas Kvinge +* +* 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 . +* +*/ + +#ifndef ENGINEDEVICE_H +#define ENGINEDEVICE_H + +#include +#include +#include + +class EngineDevice { + public: + explicit EngineDevice(); + QString GuessIconName() const; + QString description; + QVariant value; + QString iconname; + int card; + int device; +}; +using EngineDeviceList = QList; + +#endif // ENGINEDEVICE_H diff --git a/src/engine/macosdevicefinder.cpp b/src/engine/macosdevicefinder.cpp index 799ab01a3..80ede9f4a 100644 --- a/src/engine/macosdevicefinder.cpp +++ b/src/engine/macosdevicefinder.cpp @@ -30,6 +30,7 @@ #include "core/scoped_cftyperef.h" #include "macosdevicefinder.h" +#include "enginedevice.h" namespace { @@ -63,9 +64,7 @@ std::unique_ptr GetProperty(const AudioDeviceID &device_id, const AudioObject MacOsDeviceFinder::MacOsDeviceFinder() : DeviceFinder("osxaudio", { "osxaudio", "osx", "osxaudiosink" }) {} -DeviceFinder::DeviceList MacOsDeviceFinder::ListDevices() { - - DeviceList ret; +EngineDeviceList MacOsDeviceFinder::ListDevices() { AudioObjectPropertyAddress address = { kAudioHardwarePropertyDevices, @@ -76,11 +75,12 @@ DeviceFinder::DeviceList MacOsDeviceFinder::ListDevices() { UInt32 device_size_bytes = 0; std::unique_ptr devices = GetProperty(kAudioObjectSystemObject, address, &device_size_bytes); if (!devices) { - return ret; + return EngineDeviceList(); } const UInt32 device_count = device_size_bytes / sizeof(AudioDeviceID); address.mScope = kAudioDevicePropertyScopeOutput; + EngineDeviceList device_list; for (UInt32 i = 0; i < device_count; ++i) { const AudioDeviceID id = devices.get()[i]; @@ -99,14 +99,15 @@ DeviceFinder::DeviceList MacOsDeviceFinder::ListDevices() { continue; } - Device dev; - dev.value = id; - dev.description = QString::fromUtf8(CFStringGetCStringPtr(*device_name, CFStringGetSystemEncoding())); - if (dev.description.isEmpty()) dev.description = QString("Unknown device " + dev.value.toString()); - dev.iconname = GuessIconName(dev.description); - ret.append(dev); + EngineDevice device; + device.value = id; + device.description = QString::fromUtf8(CFStringGetCStringPtr(*device_name, CFStringGetSystemEncoding())); + if (device.description.isEmpty()) device.description = QString("Unknown device " + device.value.toString()); + device.iconname = device.GuessIconName(); + device_list.append(device); } - return ret; + + return device_list; } diff --git a/src/engine/macosdevicefinder.h b/src/engine/macosdevicefinder.h index 69fc2f394..563c8e3e4 100644 --- a/src/engine/macosdevicefinder.h +++ b/src/engine/macosdevicefinder.h @@ -24,13 +24,14 @@ #include "config.h" #include "devicefinder.h" +#include "enginedevice.h" class MacOsDeviceFinder : public DeviceFinder { public: explicit MacOsDeviceFinder(); virtual bool Initialize() { return true; } - virtual DeviceList ListDevices(); + virtual EngineDeviceList ListDevices(); }; #endif // MACOSDEVICEFINDER_H diff --git a/src/engine/mmdevicefinder.cpp b/src/engine/mmdevicefinder.cpp index 115a28b29..e0bc2a5d5 100644 --- a/src/engine/mmdevicefinder.cpp +++ b/src/engine/mmdevicefinder.cpp @@ -33,6 +33,7 @@ #include #include "mmdevicefinder.h" +#include "enginedevice.h" #include "core/logging.h" #ifdef _MSC_VER @@ -42,14 +43,14 @@ MMDeviceFinder::MMDeviceFinder() : DeviceFinder("mmdevice", { "wasapisink" }) {} -DeviceFinder::DeviceList MMDeviceFinder::ListDevices() { +EngineDeviceList MMDeviceFinder::ListDevices() { HRESULT hr_coinit = CoInitializeEx(NULL, COINIT_MULTITHREADED); - DeviceList devices; - Device default_device; + EngineDeviceList devices; + EngineDevice default_device; default_device.description = "Default device"; - default_device.iconname = GuessIconName(default_device.description); + default_device.iconname = default_device.GuessIconName(); devices.append(default_device); IMMDeviceEnumerator *enumerator = nullptr; @@ -75,9 +76,9 @@ DeviceFinder::DeviceList MMDeviceFinder::ListDevices() { PropVariantInit(&var_name); hr = props->GetValue(PKEY_Device_FriendlyName, &var_name); if (hr == S_OK) { - Device device; + EngineDevice device; device.description = QString::fromWCharArray(var_name.pwszVal); - device.iconname = GuessIconName(device.description); + device.iconname = device.GuessIconName(); device.value = QString::fromStdWString(pwszid); devices.append(device); PropVariantClear(&var_name); diff --git a/src/engine/mmdevicefinder.h b/src/engine/mmdevicefinder.h index 038bd62dc..13a51a0ed 100644 --- a/src/engine/mmdevicefinder.h +++ b/src/engine/mmdevicefinder.h @@ -23,13 +23,14 @@ #include "config.h" #include "devicefinder.h" +#include "enginedevice.h" class MMDeviceFinder : public DeviceFinder { public: explicit MMDeviceFinder(); virtual bool Initialize() { return true; } - virtual DeviceList ListDevices(); + virtual EngineDeviceList ListDevices(); }; #endif // MMDEVICEFINDER_H diff --git a/src/engine/pulsedevicefinder.cpp b/src/engine/pulsedevicefinder.cpp index c6f128b4b..72ba86bae 100644 --- a/src/engine/pulsedevicefinder.cpp +++ b/src/engine/pulsedevicefinder.cpp @@ -30,8 +30,8 @@ #include #include "core/logging.h" -#include "devicefinder.h" #include "pulsedevicefinder.h" +#include "enginedevice.h" PulseDeviceFinder::PulseDeviceFinder() : DeviceFinder("pulseaudio", { "pulseaudio", "pulse", "pulsesink" }), mainloop_(nullptr), context_(nullptr) {} @@ -80,10 +80,10 @@ bool PulseDeviceFinder::Reconnect() { } } -DeviceFinder::DeviceList PulseDeviceFinder::ListDevices() { +EngineDeviceList PulseDeviceFinder::ListDevices() { if (!context_ || pa_context_get_state(context_) != PA_CONTEXT_READY) { - return DeviceList(); + return EngineDeviceList(); } retry: @@ -121,12 +121,12 @@ void PulseDeviceFinder::GetSinkInfoCallback(pa_context *c, const pa_sink_info *i if (!state) return; if (info) { - Device dev; - dev.description = QString::fromUtf8(info->description); - dev.value = QString::fromUtf8(info->name); - dev.iconname = GuessIconName(dev.description); + EngineDevice device; + device.description = QString::fromUtf8(info->description); + device.value = QString::fromUtf8(info->name); + device.iconname = device.GuessIconName(); - state->devices.append(dev); + state->devices.append(device); } if (eol > 0) { diff --git a/src/engine/pulsedevicefinder.h b/src/engine/pulsedevicefinder.h index 9e28313cd..2f5fb7ea2 100644 --- a/src/engine/pulsedevicefinder.h +++ b/src/engine/pulsedevicefinder.h @@ -28,6 +28,7 @@ #include #include "devicefinder.h" +#include "enginedevice.h" class PulseDeviceFinder : public DeviceFinder { public: @@ -35,14 +36,14 @@ class PulseDeviceFinder : public DeviceFinder { ~PulseDeviceFinder() override; bool Initialize() override; - DeviceList ListDevices() override; + EngineDeviceList ListDevices() override; private: struct ListDevicesState { ListDevicesState() : finished(false) {} bool finished; - DeviceList devices; + EngineDeviceList devices; }; bool Reconnect(); diff --git a/src/engine/uwpdevicefinder.cpp b/src/engine/uwpdevicefinder.cpp index 0b689dcd1..d3ee04cde 100644 --- a/src/engine/uwpdevicefinder.cpp +++ b/src/engine/uwpdevicefinder.cpp @@ -32,6 +32,7 @@ #include "AsyncOperations.h" #include "uwpdevicefinder.h" +#include "enginedevice.h" #include "core/logging.h" using namespace Microsoft::WRL; @@ -69,45 +70,45 @@ static std::string hstring_to_stdstring(HString *hstr) { } // namespace -DeviceFinder::DeviceList UWPDeviceFinder::ListDevices() { +EngineDeviceList UWPDeviceFinder::ListDevices() { ComPtr device_info_statics; HRESULT hr = ABI::Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &device_info_statics); if (FAILED(hr)) { - return DeviceList(); + return EngineDeviceList(); } ComPtr> async_op; hr = device_info_statics->FindAllAsyncDeviceClass(DeviceClass::DeviceClass_AudioRender, &async_op); device_info_statics.Reset(); if (FAILED(hr)) { - return DeviceList(); + return EngineDeviceList(); } hr = SyncWait(async_op.Get()); if (FAILED(hr)) { - return DeviceList(); + return EngineDeviceList(); } ComPtr> device_list; hr = async_op->GetResults(&device_list); async_op.Reset(); if (FAILED(hr)) { - return DeviceList(); + return EngineDeviceList(); } unsigned int count = 0; hr = device_list->get_Size(&count); if (FAILED(hr)) { - return DeviceList(); + return EngineDeviceList(); } - DeviceList devices; + EngineDeviceList devices; { - Device default_device; + EngineDevice default_device; default_device.description = "Default device"; - default_device.iconname = GuessIconName(default_device.description); + default_device.iconname = default_device.GuessIconName(); devices.append(default_device); } @@ -137,10 +138,10 @@ DeviceFinder::DeviceList UWPDeviceFinder::ListDevices() { continue; } - Device device; + EngineDevice device; device.value = QString::fromStdString(hstring_to_stdstring(&id)); device.description = QString::fromStdString(hstring_to_stdstring(&name)); - device.iconname = GuessIconName(device.description); + device.iconname = device.GuessIconName(); devices.append(device); } diff --git a/src/engine/uwpdevicefinder.h b/src/engine/uwpdevicefinder.h index d7fdf5d6d..af2e643c9 100644 --- a/src/engine/uwpdevicefinder.h +++ b/src/engine/uwpdevicefinder.h @@ -23,6 +23,7 @@ #include "config.h" #include "devicefinder.h" +#include "enginedevice.h" class UWPDeviceFinder : public DeviceFinder { public: diff --git a/src/settings/backendsettingspage.cpp b/src/settings/backendsettingspage.cpp index 13b8169d6..3d7382c02 100644 --- a/src/settings/backendsettingspage.cpp +++ b/src/settings/backendsettingspage.cpp @@ -44,6 +44,7 @@ #include "core/player.h" #include "core/logging.h" #include "engine/enginebase.h" +#include "engine/enginedevice.h" #include "engine/devicefinders.h" #include "engine/devicefinder.h" #include "widgets/lineedit.h" @@ -320,7 +321,7 @@ void BackendSettingsPage::Load_Device(const QString &output, const QVariant &dev if (!EngineInitialized()) return; int devices = 0; - DeviceFinder::Device df_device; + EngineDevice df_device; ui_->combobox_device->clear(); ui_->lineedit_device->clear(); @@ -332,7 +333,7 @@ void BackendSettingsPage::Load_Device(const QString &output, const QVariant &dev for (DeviceFinder *f : dialog()->app()->device_finders()->ListFinders()) { if (!f->outputs().contains(output)) continue; - for (const DeviceFinder::Device &d : f->ListDevices()) { + for (const EngineDevice &d : f->ListDevices()) { devices++; ui_->combobox_device->addItem(IconLoader::Load(d.iconname), d.description, d.value); if (d.value == device) { df_device = d; }