Changeset View
Changeset View
Standalone View
Standalone View
src/sink.cpp
Show All 16 Lines | 1 | /* | |||
---|---|---|---|---|---|
17 | You should have received a copy of the GNU Lesser General Public | 17 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | 18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "sink.h" | 21 | #include "sink.h" | ||
22 | 22 | | |||
23 | #include "context.h" | 23 | #include "context.h" | ||
24 | #include "server.h" | 24 | #include "server.h" | ||
25 | #include "canberracontext.h" | ||||
26 | #include <pulse/channelmap.h> | ||||
25 | 27 | | |||
26 | namespace QPulseAudio | 28 | namespace QPulseAudio | ||
27 | { | 29 | { | ||
28 | 30 | | |||
29 | Sink::Sink(QObject *parent) | 31 | Sink::Sink(QObject *parent) | ||
30 | : Device(parent) | 32 | : Device(parent) | ||
31 | { | 33 | { | ||
32 | connect(context()->server(), &Server::defaultSinkChanged, this, &Sink::defaultChanged); | 34 | connect(context()->server(), &Server::defaultSinkChanged, this, &Sink::defaultChanged); | ||
35 | CanberraContext::instance()->ref(); | ||||
36 | } | ||||
37 | | ||||
38 | Sink::~Sink() | ||||
39 | { | ||||
40 | CanberraContext::instance()->unref(); | ||||
33 | } | 41 | } | ||
34 | 42 | | |||
35 | void Sink::update(const pa_sink_info *info) | 43 | void Sink::update(const pa_sink_info *info) | ||
36 | { | 44 | { | ||
37 | updateDevice(info); | 45 | updateDevice(info); | ||
38 | } | 46 | } | ||
39 | 47 | | |||
40 | void Sink::setVolume(qint64 volume) | 48 | void Sink::setVolume(qint64 volume) | ||
Show All 28 Lines | |||||
69 | 77 | | |||
70 | void Sink::setDefault(bool enable) | 78 | void Sink::setDefault(bool enable) | ||
71 | { | 79 | { | ||
72 | if (!isDefault() && enable) { | 80 | if (!isDefault() && enable) { | ||
73 | context()->server()->setDefaultSink(this); | 81 | context()->server()->setDefaultSink(this); | ||
74 | } | 82 | } | ||
75 | } | 83 | } | ||
76 | 84 | | |||
85 | pa_channel_position_t Sink::channelNameToPosition(const QString &name) | ||||
86 | { | ||||
87 | if (name == QLatin1String("Front Left")) { | ||||
droscaUnsubmitted Done drosca: ```
if (name == QLatin1String("Front Left")) {
// ...
} else if (...) {
//
} | |||||
drosca: Braces and "else if" still missing. | |||||
88 | return PA_CHANNEL_POSITION_FRONT_LEFT; | ||||
89 | } else if (name == QLatin1String("Front Center")) { | ||||
90 | return PA_CHANNEL_POSITION_FRONT_CENTER; | ||||
91 | } else if (name == QLatin1String("Front Right")) { | ||||
92 | return PA_CHANNEL_POSITION_FRONT_RIGHT; | ||||
93 | } else if (name == QLatin1String("Side Left")) { | ||||
94 | return PA_CHANNEL_POSITION_SIDE_LEFT; | ||||
95 | } else if (name == QLatin1String("Side Right")) { | ||||
96 | return PA_CHANNEL_POSITION_SIDE_RIGHT; | ||||
97 | } else if (name == QLatin1String("Rear Left")) { | ||||
98 | return PA_CHANNEL_POSITION_REAR_LEFT; | ||||
99 | } else if (name == QLatin1String("Rear Right")) { | ||||
100 | return PA_CHANNEL_POSITION_REAR_RIGHT; | ||||
101 | } else if (name == QLatin1String("Subwoofer")) { | ||||
102 | return PA_CHANNEL_POSITION_SUBWOOFER; | ||||
103 | } | ||||
104 | | ||||
105 | return PA_CHANNEL_POSITION_MONO; | ||||
106 | } | ||||
107 | | ||||
108 | QString Sink::positionToChannelName(pa_channel_position_t position) | ||||
109 | { | ||||
110 | switch (position) { | ||||
111 | case PA_CHANNEL_POSITION_FRONT_LEFT: | ||||
112 | return QStringLiteral("Front Left"); | ||||
113 | case PA_CHANNEL_POSITION_FRONT_RIGHT: | ||||
114 | return QStringLiteral("Front Right"); | ||||
115 | case PA_CHANNEL_POSITION_FRONT_CENTER: | ||||
116 | return QStringLiteral("Front Center"); | ||||
drosca: ```
switch (position) {
case ...:
case ...:
} | |||||
117 | case PA_CHANNEL_POSITION_SIDE_LEFT: | ||||
118 | return QStringLiteral("Side Left"); | ||||
119 | case PA_CHANNEL_POSITION_SIDE_RIGHT: | ||||
120 | return QStringLiteral("Side Right"); | ||||
121 | case PA_CHANNEL_POSITION_REAR_LEFT: | ||||
122 | return QStringLiteral("Rear Left"); | ||||
123 | case PA_CHANNEL_POSITION_REAR_RIGHT: | ||||
124 | return QStringLiteral("Rear Right"); | ||||
125 | case PA_CHANNEL_POSITION_SUBWOOFER: | ||||
126 | return QStringLiteral("Subwoofer"); | ||||
127 | default: | ||||
128 | return QStringLiteral("Mono"); | ||||
129 | } | ||||
130 | } | ||||
131 | | ||||
132 | void Sink::testChannel(const QString &name) | ||||
133 | { | ||||
134 | auto context = CanberraContext::instance()->canberra(); | ||||
135 | if (!context) | ||||
136 | return; | ||||
137 | | ||||
138 | char dev[64]; | ||||
139 | snprintf(dev, sizeof(dev), "%lu", (unsigned long) m_index); | ||||
140 | ca_context_change_device(context, dev); | ||||
141 | | ||||
142 | QString sound_name = QStringLiteral("audio-channel-") + positionAsString(channelNameToPosition(name)); | ||||
143 | ca_proplist *proplist; | ||||
144 | ca_proplist_create(&proplist); | ||||
145 | | ||||
146 | ca_proplist_sets(proplist, CA_PROP_MEDIA_ROLE, "test"); | ||||
147 | ca_proplist_sets(proplist, CA_PROP_MEDIA_NAME, name.toLatin1().constData()); | ||||
148 | ca_proplist_sets(proplist, CA_PROP_CANBERRA_FORCE_CHANNEL, positionAsString(channelNameToPosition(name)).toLatin1().data()); | ||||
149 | ca_proplist_sets(proplist, CA_PROP_CANBERRA_ENABLE, "1"); | ||||
150 | | ||||
151 | ca_proplist_sets(proplist, CA_PROP_EVENT_ID, sound_name.toLatin1().data()); | ||||
152 | if (ca_context_play_full(context, 0, proplist, nullptr, NULL) < 0) { | ||||
153 | // Try a different sound name. | ||||
154 | ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "audio-test-signal"); | ||||
155 | if (ca_context_play_full(context, 0, proplist, nullptr, NULL) < 0) { | ||||
156 | // Finaly try this... if this doesn't work, then stuff it. | ||||
157 | ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system"); | ||||
158 | ca_context_play_full(context, 0, proplist, nullptr, NULL); | ||||
159 | } | ||||
160 | } | ||||
161 | | ||||
162 | ca_context_change_device(context, nullptr); | ||||
163 | ca_proplist_destroy(proplist); | ||||
164 | } | ||||
165 | | ||||
166 | QString Sink::positionAsString(pa_channel_position_t pos) | ||||
167 | { | ||||
168 | switch (pos) { | ||||
169 | case PA_CHANNEL_POSITION_FRONT_LEFT: | ||||
170 | return QStringLiteral("front-left"); | ||||
171 | case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: | ||||
172 | return QStringLiteral("front-left-of-center"); | ||||
173 | case PA_CHANNEL_POSITION_FRONT_CENTER: | ||||
174 | return QStringLiteral("front-center"); | ||||
175 | case PA_CHANNEL_POSITION_MONO: | ||||
176 | return QStringLiteral("mono"); | ||||
177 | case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: | ||||
178 | return QStringLiteral("front-right-of-center"); | ||||
179 | case PA_CHANNEL_POSITION_FRONT_RIGHT: | ||||
180 | return QStringLiteral("front-right"); | ||||
181 | case PA_CHANNEL_POSITION_SIDE_LEFT: | ||||
182 | return QStringLiteral("side-left"); | ||||
183 | case PA_CHANNEL_POSITION_SIDE_RIGHT: | ||||
184 | return QStringLiteral("side-right"); | ||||
185 | case PA_CHANNEL_POSITION_REAR_LEFT: | ||||
186 | return QStringLiteral("rear-left"); | ||||
187 | case PA_CHANNEL_POSITION_REAR_CENTER: | ||||
188 | return QStringLiteral("rear-center"); | ||||
189 | case PA_CHANNEL_POSITION_REAR_RIGHT: | ||||
190 | return QStringLiteral("rear-right"); | ||||
191 | case PA_CHANNEL_POSITION_SUBWOOFER: | ||||
192 | return QStringLiteral("subwoofer"); | ||||
193 | default: | ||||
194 | break; | ||||
195 | } | ||||
196 | return QStringLiteral("invalid"); | ||||
197 | } | ||||
77 | } // QPulseAudio | 198 | } // QPulseAudio |