Skip to content

Commit 75f2cbc

Browse files
committed
Implement auto preset loader in audio drivers
1 parent c334fff commit 75f2cbc

File tree

12 files changed

+213
-54
lines changed

12 files changed

+213
-54
lines changed

src/MainWindow.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,9 @@ void MainWindow::onBs2bPresetUpdated()
945945
break;
946946
}
947947

948+
// FIXME remove this vvv
949+
ui->info->setAnimatedText("'" + ui->crossfeed_mode->currentText() + "' has been selected", true);
950+
948951
ui->bs2b_custom_box->setEnabled(index == 99);
949952
_blockApply = false;
950953

@@ -1094,7 +1097,7 @@ void MainWindow::updateTooltipLabelUnit(QObject *sender,
10941097

10951098
if (viasignal)
10961099
{
1097-
ui->info->setText(text);
1100+
ui->info->setAnimatedText(text, false);
10981101
}
10991102
}
11001103

src/MainWindow.ui

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,9 +2232,18 @@
22322232
</widget>
22332233
</item>
22342234
<item>
2235-
<widget class="QLabel" name="info">
2235+
<widget class="FadingLabel" name="info">
2236+
<property name="sizePolicy">
2237+
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
2238+
<horstretch>0</horstretch>
2239+
<verstretch>0</verstretch>
2240+
</sizepolicy>
2241+
</property>
22362242
<property name="text">
2237-
<string/>
2243+
<string>'Galaxy Buds Pro' connected - Preset loaded automatically</string>
2244+
</property>
2245+
<property name="wordWrap">
2246+
<bool>true</bool>
22382247
</property>
22392248
</widget>
22402249
</item>
@@ -2254,19 +2263,6 @@
22542263
</property>
22552264
</spacer>
22562265
</item>
2257-
<item>
2258-
<spacer name="horizontalSpacer">
2259-
<property name="orientation">
2260-
<enum>Qt::Horizontal</enum>
2261-
</property>
2262-
<property name="sizeHint" stdset="0">
2263-
<size>
2264-
<width>40</width>
2265-
<height>20</height>
2266-
</size>
2267-
</property>
2268-
</spacer>
2269-
</item>
22702266
<item>
22712267
<widget class="QPushButton" name="disableFX">
22722268
<property name="minimumSize">
@@ -2335,6 +2331,11 @@
23352331
<header>interface/LiveprogSelectionWidget.h</header>
23362332
<container>1</container>
23372333
</customwidget>
2334+
<customwidget>
2335+
<class>FadingLabel</class>
2336+
<extends>QLabel</extends>
2337+
<header>interface/FadingLabel.h</header>
2338+
</customwidget>
23382339
</customwidgets>
23392340
<tabstops>
23402341
<tabstop>cpreset</tabstop>

src/audio/base/IAudioService.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public slots:
3939
void eelOutputReceived(const QString& output);
4040
void eelVariablesEnumerated(const std::list<EelVariable>& vars);
4141
void convolverInfoChanged(const ConvolverInfoEventArgs& args);
42+
void outputDeviceChanged(const QString& deviceName, const QString& deviceId);
4243

4344
};
4445

src/audio/pipewire/PipewireAudioService.cpp

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include "DspHost.h"
88
#include "PwDevice.h"
99
#include "Utils.h"
10-
#include "config/AppConfig.h"
1110

1211
#include <QDebug>
1312

@@ -37,19 +36,84 @@ PipewireAudioService::PipewireAudioService()
3736
});
3837

3938
mgr.get()->device_output_route_changed.connect([&](DeviceInfo device) {
40-
if (device.output_route_available == SPA_PARAM_AVAILABILITY_no) {
39+
if (device.output_route_available == SPA_PARAM_AVAILABILITY_no)
40+
{
4141
return;
4242
}
4343

44-
util::debug(log_tag + "device " + device.name + " has changed its output route to: " + device.output_route_name);
44+
NodeInfo target_node;
45+
for (const auto& [ts, node] : mgr.get()->node_map)
46+
{
47+
target_node = node;
48+
49+
if (node.device_id == device.id && node.media_class == "Audio/Sink")
50+
{
51+
target_node = node;
52+
break;
53+
}
54+
}
55+
56+
if (target_node.id != SPA_ID_INVALID)
57+
{
58+
emit outputDeviceChanged(QString::fromStdString(target_node.name), QString::fromStdString(device.output_route_name));
59+
}
60+
else
61+
{
62+
util::debug(log_tag + "device_output_route_changed: could not find target node");
63+
}
4564
});
65+
66+
connect(&AppConfig::instance(), &AppConfig::updated, this, &PipewireAudioService::onAppConfigUpdated);
4667
}
4768

4869
PipewireAudioService::~PipewireAudioService()
4970
{
5071
delete plugin;
5172
}
5273

74+
void PipewireAudioService::onAppConfigUpdated(const AppConfig::Key &key, const QVariant &value)
75+
{
76+
switch (key) {
77+
case AppConfig::AudioOutputDevice: {
78+
const auto name = value.toString();
79+
80+
if (name.isEmpty())
81+
{
82+
return;
83+
}
84+
85+
uint device_id = SPA_ID_INVALID;
86+
for (const auto& [ts, node2] : mgr.get()->node_map)
87+
{
88+
if (node2.name == name.toStdString())
89+
{
90+
device_id = node2.device_id;
91+
break;
92+
}
93+
}
94+
95+
if (device_id != SPA_ID_INVALID)
96+
{
97+
for (const auto& device : mgr.get()->list_devices)
98+
{
99+
if (device.id == device_id)
100+
{
101+
emit outputDeviceChanged(name, QString::fromStdString(device.output_route_name));
102+
break;
103+
}
104+
}
105+
}
106+
else
107+
{
108+
util::debug(log_tag + "AudioOutputDevice changed: could not find target node");
109+
}
110+
break;
111+
}
112+
default:
113+
break;
114+
}
115+
}
116+
53117
void PipewireAudioService::update(DspConfig *config)
54118
{
55119
auto* ptr = plugin->host();
@@ -105,6 +169,8 @@ DspStatus PipewireAudioService::status()
105169
}
106170

107171
#include <iostream>
172+
173+
#include <config/AppConfig.h>
108174
void PipewireAudioService::enumerateLiveprogVariables()
109175
{
110176

src/audio/pipewire/PipewireAudioService.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ class PipewireAudioService : public IAudioService
2323
~PipewireAudioService();
2424

2525
public slots:
26+
void onAppConfigUpdated(const AppConfig::Key& key, const QVariant& value);
27+
2628
void update(DspConfig* config) override;
2729
void reloadLiveprog() override;
2830
void reloadService() override;

src/audio/pipewire/PwPipelineManager.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,14 +583,18 @@ void on_device_event_param(void* object,
583583
device.input_route_name = name;
584584
device.input_route_available = available;
585585

586-
Glib::signal_idle().connect_once([pm, device] { pm->device_input_route_changed.emit(device); });
586+
Glib::signal_idle().connect_once([pm, device] {
587+
pm->device_input_route_changed.emit(device);
588+
});
587589
}
588590
} else if (direction == SPA_DIRECTION_OUTPUT) {
589591
if (name != device.output_route_name || available != device.output_route_available) {
590592
device.output_route_name = name;
591593
device.output_route_available = available;
592594

593-
Glib::signal_idle().connect_once([pm, device] { pm->device_output_route_changed.emit(device); });
595+
Glib::signal_idle().connect_once([pm, device] {
596+
pm->device_output_route_changed.emit(device);
597+
});
594598
}
595599
}
596600

src/audio/pulseaudio/PulseAudioProcessingThread.cpp

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,6 @@ PulseAudioProcessingThread::~PulseAudioProcessingThread()
1616

1717
void PulseAudioProcessingThread::run()
1818
{
19-
/* Register sink change handler */
20-
std::string last_sink_dev_name;
21-
22-
mgr.get()->getPulseManager()->sink_changed.connect([&](const std::shared_ptr<mySinkInfo>& info) {
23-
if (info->name == mgr.get()->getPulseManager()->server_info.default_sink_name) {
24-
Glib::signal_timeout().connect_seconds_once(
25-
[=,&last_sink_dev_name]() {
26-
// checking if after 3 seconds this sink still is the default sink
27-
if (info->name == mgr.get()->getPulseManager()->server_info.default_sink_name) {
28-
auto current_info = mgr.get()->getPulseManager()->get_sink_info(info->name);
29-
30-
if (current_info != nullptr) {
31-
auto port = current_info->active_port;
32-
std::string dev_name;
33-
34-
if (port != "null") {
35-
dev_name = current_info->name + ":" + port;
36-
} else {
37-
dev_name = current_info->name;
38-
}
39-
40-
if (dev_name != last_sink_dev_name) {
41-
last_sink_dev_name = dev_name;
42-
43-
//presets_manager->autoload(PresetType::output, dev_name);
44-
}
45-
}
46-
}
47-
},
48-
3);
49-
}
50-
});
51-
5219
/* Update output sink if na headset change was detected */
5320
mgr.get()->getPulseManager()->new_default_sink.connect([&](auto name) {
5421
util::debug("new default sink: " + name);

src/audio/pulseaudio/PulseAudioService.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,36 @@ PulseAudioService::PulseAudioService()
4040

4141
mgr.get()->getDsp()->setMessageHandler(std::bind(&IAudioService::handleMessage, this, std::placeholders::_1, std::placeholders::_2));
4242

43+
/* Register sink change handler */
44+
mgr.get()->getPulseManager()->sink_changed.connect([&](const std::shared_ptr<mySinkInfo>& info) {
45+
if (info->name == mgr.get()->getPulseManager()->server_info.default_sink_name) {
46+
Glib::signal_timeout().connect_seconds_once(
47+
[=]() {
48+
// checking if after 3 seconds this sink still is the default sink
49+
if (info->name == mgr.get()->getPulseManager()->server_info.default_sink_name) {
50+
auto current_info = mgr.get()->getPulseManager()->get_sink_info(info->name);
51+
52+
if (current_info != nullptr) {
53+
auto port = current_info->active_port;
54+
std::string dev_name;
55+
56+
if (port != "null") {
57+
dev_name = current_info->name + ":" + port;
58+
} else {
59+
dev_name = current_info->name;
60+
}
61+
62+
if (dev_name != last_sink_dev_name) {
63+
last_sink_dev_name = dev_name;
64+
emit outputDeviceChanged(QString::fromStdString(dev_name), QString::fromStdString(dev_name));
65+
}
66+
}
67+
}
68+
},
69+
3);
70+
}
71+
});
72+
4373
/* Launch audio processing thread */
4474
apt = new PulseAudioProcessingThread(mgr);
4575
apt->start();

src/audio/pulseaudio/PulseAudioService.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public slots:
3636
PulseAppManager* appMgr;
3737
PulseAudioProcessingThread* apt;
3838

39+
std::string last_sink_dev_name;
40+
3941
};
4042

4143
#endif // PULSEAUDIOSERVICE_H

src/interface/FadingLabel.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "FadingLabel.h"
2+
3+
#include <QGraphicsOpacityEffect>
4+
#include <QPropertyAnimation>
5+
#include <QSequentialAnimationGroup>
6+
7+
FadingLabel::FadingLabel(QWidget* parent) : QLabel(parent)
8+
{
9+
effect = new QGraphicsOpacityEffect(this);
10+
effect->setOpacity(0.0);
11+
this->setGraphicsEffect(effect);
12+
13+
fadeInOut = new QSequentialAnimationGroup(this);
14+
fadeIn = new QPropertyAnimation(effect, "opacity");
15+
fadeIn->setDuration(150);
16+
fadeIn->setEasingCurve(QEasingCurve::Type::OutCurve);
17+
fadeIn->setStartValue(0);
18+
fadeIn->setEndValue(1.0);
19+
fadeOut = new QPropertyAnimation(effect, "opacity");
20+
fadeOut->setDuration(150);
21+
fadeOut->setEasingCurve(QEasingCurve::Type::OutCurve);
22+
fadeOut->setStartValue(1.0);
23+
fadeOut->setEndValue(0.0);
24+
25+
fadeInOut->addAnimation(fadeIn);
26+
fadeInOut->addPause(3000);
27+
fadeInOut->addAnimation(fadeOut);
28+
}
29+
30+
void FadingLabel::setAnimatedText(const QString &msg, bool highPriority)
31+
{
32+
if(fadeInOut->state() == QAbstractAnimation::Running)
33+
{
34+
if(lastAnimationHighPriority && !highPriority)
35+
{
36+
return;
37+
}
38+
39+
fadeInOut->stop();
40+
effect->setOpacity(1);
41+
42+
fadeIn->setStartValue(1.0);
43+
fadeIn->setDuration(0);
44+
}
45+
else
46+
{
47+
fadeIn->setStartValue(0.0);
48+
fadeIn->setDuration(150);
49+
}
50+
51+
this->setText(msg);
52+
fadeInOut->setCurrentTime(0);
53+
fadeInOut->start();
54+
55+
lastAnimationHighPriority = highPriority;
56+
}

0 commit comments

Comments
 (0)