1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// SPDX-License-Identifier: Apache-2.0
#include "audiomixer-service.hpp"
#include <iostream>
#include <algorithm>
AudiomixerService::AudiomixerService(const VisConfig &config, net::io_context& ioc, ssl::context& ctx) :
VisSession(config, ioc, ctx)
{
m_audiomixer = audiomixer_new();
if (m_audiomixer) {
// Set up callbacks for WirePlumber events
m_audiomixer_events.controls_changed = audiomixer_control_change_cb;
m_audiomixer_events.value_changed = audiomixer_value_change_cb;
audiomixer_add_event_listener(m_audiomixer, &m_audiomixer_events, this);
// Drive connecting to PipeWire core and refreshing controls list
audiomixer_lock(m_audiomixer);
audiomixer_ensure_controls(m_audiomixer, 3);
audiomixer_unlock(m_audiomixer);
} else {
std::cerr << "Could not create WirePlumber connection" << std::endl;
}
}
AudiomixerService::~AudiomixerService()
{
audiomixer_free(m_audiomixer);
}
void AudiomixerService::handle_authorized_response(void)
{
subscribe("Vehicle.Cabin.Infotainment.Media.Volume");
subscribe("Vehicle.Cabin.SteeringWheel.Switches.VolumeUp");
subscribe("Vehicle.Cabin.SteeringWheel.Switches.VolumeDown");
subscribe("Vehicle.Cabin.SteeringWheel.Switches.VolumeMute");
// Set initial volume in VSS
// For now a value of 50 matches the default in the homescreen app.
// Ideally there would be some form of persistence scheme to restore
// the last value on restart.
set("Vehicle.Cabin.Infotainment.Media.Volume", "50");
}
void AudiomixerService::handle_get_response(std::string &path, std::string &value, std::string ×tamp)
{
// Placeholder since no gets are performed ATM
}
void AudiomixerService::handle_notification(std::string &path, std::string &value, std::string ×tamp)
{
if (!m_audiomixer) {
return;
}
audiomixer_lock(m_audiomixer);
const struct mixer_control *ctl = audiomixer_find_control(m_audiomixer, "Master Playback");
if (!ctl) {
audiomixer_unlock(m_audiomixer);
return;
}
if (path == "Vehicle.Cabin.Infotainment.Media.Volume") {
try {
int volume = std::stoi(value);
if (volume >= 0 && volume <= 100) {
double v = (double) volume / 100.0;
if (m_config.verbose() > 1)
std::cout << "Setting volume to " << v << std::endl;
audiomixer_change_volume(m_audiomixer, ctl, v);
}
}
catch (std::exception ex) {
// ignore bad value
}
} else if (path == "Vehicle.Cabin.SteeringWheel.Switches.VolumeUp" && value == "true") {
double volume = ctl->volume;
volume += 0.05; // up 5%
if (volume > 1.0)
volume = 1.0; // clamp to 100%
if (m_config.verbose() > 1)
std::cout << "Increasing volume to " << volume << std::endl;
audiomixer_change_volume(m_audiomixer, ctl, volume);
} else if (path == "Vehicle.Cabin.SteeringWheel.Switches.VolumeDown" && value == "true") {
double volume = ctl->volume;
volume -= 0.05; // down 5%
if (volume < 0.0)
volume = 0.0; // clamp to 0%
if (m_config.verbose() > 1)
std::cout << "Decreasing volume to " << volume << std::endl;
audiomixer_change_volume(m_audiomixer, ctl, volume);
} else if (path == "Vehicle.Cabin.SteeringWheel.Switches.VolumeMute" && value == "true") {
if (m_config.verbose() > 1) {
if (ctl->mute)
std::cout << "Unmuting" << std::endl;
else
std::cout << "Muting" << std::endl;
}
audiomixer_change_mute(m_audiomixer, ctl, !ctl->mute);
}
// else ignore
audiomixer_unlock(m_audiomixer);
}
void AudiomixerService::handle_control_change(void)
{
// Ignore for now
}
void AudiomixerService::handle_value_change(unsigned int change_mask, const struct mixer_control *control)
{
if (!control)
return;
if (change_mask & MIXER_CONTROL_CHANGE_FLAG_VOLUME) {
if (std::string(control->name) == "Master Playback") {
// Push change into VIS
std::string value = std::to_string((int) (control->volume * 100.0));
set("Vehicle.Cabin.Infotainment.Media.Volume", value);
}
} else if (change_mask & MIXER_CONTROL_CHANGE_FLAG_MUTE) {
// For now, do nothing, new state is in control->mute
}
}
|