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 | |
13 | namespace BluezQt |
14 | { |
15 | MediaEndpoint::MediaEndpoint(const Configuration &configuration, QObject *parent) |
16 | : QObject(parent) |
17 | , d(new MediaEndpointPrivate(configuration)) |
18 | { |
19 | } |
20 | |
21 | MediaEndpoint::~MediaEndpoint() = default; |
22 | |
23 | QDBusObjectPath MediaEndpoint::objectPath() const |
24 | { |
25 | return d->m_objectPath; |
26 | } |
27 | |
28 | const QVariantMap &MediaEndpoint::properties() const |
29 | { |
30 | return d->m_properties; |
31 | } |
32 | |
33 | void MediaEndpoint::setConfiguration(const QString &transportObjectPath, const QVariantMap &properties) |
34 | { |
35 | Q_EMIT configurationSet(transportObjectPath, properties); |
36 | } |
37 | |
38 | void 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 | |
122 | void MediaEndpoint::clearConfiguration(const QString &transportObjectPath) |
123 | { |
124 | Q_EMIT configurationCleared(transportObjectPath); |
125 | } |
126 | |
127 | void MediaEndpoint::release() |
128 | { |
129 | } |
130 | |
131 | } // namespace BluezQt |
132 | |
133 | #include "moc_mediaendpoint.cpp" |
134 | |