1/*
2 * BluezQt - Asynchronous Bluez wrapper library
3 *
4 * SPDX-FileCopyrightText: 2018 Manuel Weichselbaumer <mincequi@web.de>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9#include "mediaendpoint.h"
10#include "a2dp-codecs.h"
11#include "mediaendpoint_p.h"
12
13namespace BluezQt
14{
15MediaEndpoint::MediaEndpoint(const Configuration &configuration, QObject *parent)
16 : QObject(parent)
17 , d(new MediaEndpointPrivate(configuration))
18{
19}
20
21MediaEndpoint::~MediaEndpoint() = default;
22
23QDBusObjectPath MediaEndpoint::objectPath() const
24{
25 return d->m_objectPath;
26}
27
28const QVariantMap &MediaEndpoint::properties() const
29{
30 return d->m_properties;
31}
32
33void MediaEndpoint::setConfiguration(const QString &transportObjectPath, const QVariantMap &properties)
34{
35 Q_EMIT configurationSet(transportObjectPath, properties);
36}
37
38void MediaEndpoint::selectConfiguration(const QByteArray &capabilities, const Request<QByteArray> &request)
39{
40 switch (d->m_configuration.codec) {
41 case MediaEndpoint::Codec::Sbc: {
42 if (capabilities.size() != sizeof(a2dp_sbc_t)) {
43 Q_EMIT configurationSelected(capabilities, configuration: QByteArray());
44 request.reject();
45 return;
46 }
47
48 a2dp_sbc_t caps = *reinterpret_cast<const a2dp_sbc_t *>(capabilities.constData());
49 if (caps.frequency & SBC_SAMPLING_FREQ_44100) {
50 caps.frequency = SBC_SAMPLING_FREQ_44100;
51 } else if (caps.frequency & SBC_SAMPLING_FREQ_48000) {
52 caps.frequency = SBC_SAMPLING_FREQ_48000;
53 } else {
54 break;
55 }
56
57 if (caps.channel_mode & SBC_CHANNEL_MODE_STEREO) {
58 caps.channel_mode = SBC_CHANNEL_MODE_STEREO;
59 } else if (caps.channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) {
60 caps.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
61 } else {
62 break;
63 }
64
65 if (caps.block_length & SBC_BLOCK_LENGTH_16) {
66 caps.block_length = SBC_BLOCK_LENGTH_16;
67 } else if (caps.block_length & SBC_BLOCK_LENGTH_12) {
68 caps.block_length = SBC_BLOCK_LENGTH_12;
69 } else if (caps.block_length & SBC_BLOCK_LENGTH_8) {
70 caps.block_length = SBC_BLOCK_LENGTH_8;
71 } else if (caps.block_length & SBC_BLOCK_LENGTH_4) {
72 caps.block_length = SBC_BLOCK_LENGTH_4;
73 } else {
74 break;
75 }
76
77 if (caps.subbands & SBC_SUBBANDS_8) {
78 caps.subbands = SBC_SUBBANDS_8;
79 } else if (caps.subbands & SBC_SUBBANDS_4) {
80 caps.subbands = SBC_SUBBANDS_4;
81 } else {
82 break;
83 }
84
85 if (caps.allocation_method & SBC_ALLOCATION_LOUDNESS) {
86 caps.allocation_method = SBC_ALLOCATION_LOUDNESS;
87 } else if (caps.allocation_method & SBC_ALLOCATION_SNR) {
88 caps.allocation_method = SBC_ALLOCATION_SNR;
89 } else {
90 break;
91 }
92
93 caps.min_bitpool = std::max(a: caps.min_bitpool, b: static_cast<uint8_t>(MIN_BITPOOL));
94 caps.max_bitpool = std::min(a: caps.max_bitpool, b: static_cast<uint8_t>(MAX_BITPOOL));
95
96 const QByteArray configuration(reinterpret_cast<const char *>(&caps), sizeof(caps));
97 Q_EMIT configurationSelected(capabilities, configuration);
98 request.accept(returnValue: configuration);
99 return;
100
101 break;
102 }
103 case MediaEndpoint::Codec::Aac:
104 if (capabilities.size() != sizeof(a2dp_aac_t)) {
105 Q_EMIT configurationSelected(capabilities, configuration: QByteArray());
106 request.reject();
107 return;
108 }
109
110 // TODO: implement AAC. However selectConfiguration seems not to be used by iOS nor Android.
111 Q_EMIT configurationSelected(capabilities, configuration: QByteArray());
112 request.reject();
113 return;
114
115 break;
116 }
117
118 Q_EMIT configurationSelected(capabilities, configuration: QByteArray());
119 request.reject();
120}
121
122void MediaEndpoint::clearConfiguration(const QString &transportObjectPath)
123{
124 Q_EMIT configurationCleared(transportObjectPath);
125}
126
127void MediaEndpoint::release()
128{
129}
130
131} // namespace BluezQt
132
133#include "moc_mediaendpoint.cpp"
134

source code of bluez-qt/src/mediaendpoint.cpp