File indexing completed on 2024-12-01 12:29:49

0001 /*
0002  * BluezQt - Asynchronous Bluez wrapper library
0003  *
0004  * SPDX-FileCopyrightText: 2018 Manuel Weichselbaumer <mincequi@web.de>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #include "mediaendpoint.h"
0010 #include "a2dp-codecs.h"
0011 #include "mediaendpoint_p.h"
0012 
0013 namespace BluezQt
0014 {
0015 MediaEndpoint::MediaEndpoint(const Configuration &configuration, QObject *parent)
0016     : QObject(parent)
0017     , d(new MediaEndpointPrivate(configuration))
0018 {
0019 }
0020 
0021 MediaEndpoint::~MediaEndpoint()
0022 {
0023     delete d;
0024 }
0025 
0026 QDBusObjectPath MediaEndpoint::objectPath() const
0027 {
0028     return d->m_objectPath;
0029 }
0030 
0031 const QVariantMap &MediaEndpoint::properties() const
0032 {
0033     return d->m_properties;
0034 }
0035 
0036 void MediaEndpoint::setConfiguration(const QString &transportObjectPath, const QVariantMap &properties)
0037 {
0038     Q_EMIT configurationSet(transportObjectPath, properties);
0039 }
0040 
0041 void MediaEndpoint::selectConfiguration(const QByteArray &capabilities, const Request<QByteArray> &request)
0042 {
0043     switch (d->m_configuration.codec) {
0044     case MediaEndpoint::Codec::Sbc: {
0045         if (capabilities.size() != sizeof(a2dp_sbc_t)) {
0046             Q_EMIT configurationSelected(capabilities, QByteArray());
0047             request.reject();
0048             return;
0049         }
0050 
0051         a2dp_sbc_t caps = *reinterpret_cast<const a2dp_sbc_t *>(capabilities.constData());
0052         if (caps.frequency & SBC_SAMPLING_FREQ_44100) {
0053             caps.frequency = SBC_SAMPLING_FREQ_44100;
0054         } else if (caps.frequency & SBC_SAMPLING_FREQ_48000) {
0055             caps.frequency = SBC_SAMPLING_FREQ_48000;
0056         } else {
0057             break;
0058         }
0059 
0060         if (caps.channel_mode & SBC_CHANNEL_MODE_STEREO) {
0061             caps.channel_mode = SBC_CHANNEL_MODE_STEREO;
0062         } else if (caps.channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) {
0063             caps.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
0064         } else {
0065             break;
0066         }
0067 
0068         if (caps.block_length & SBC_BLOCK_LENGTH_16) {
0069             caps.block_length = SBC_BLOCK_LENGTH_16;
0070         } else if (caps.block_length & SBC_BLOCK_LENGTH_12) {
0071             caps.block_length = SBC_BLOCK_LENGTH_12;
0072         } else if (caps.block_length & SBC_BLOCK_LENGTH_8) {
0073             caps.block_length = SBC_BLOCK_LENGTH_8;
0074         } else if (caps.block_length & SBC_BLOCK_LENGTH_4) {
0075             caps.block_length = SBC_BLOCK_LENGTH_4;
0076         } else {
0077             break;
0078         }
0079 
0080         if (caps.subbands & SBC_SUBBANDS_8) {
0081             caps.subbands = SBC_SUBBANDS_8;
0082         } else if (caps.subbands & SBC_SUBBANDS_4) {
0083             caps.subbands = SBC_SUBBANDS_4;
0084         } else {
0085             break;
0086         }
0087 
0088         if (caps.allocation_method & SBC_ALLOCATION_LOUDNESS) {
0089             caps.allocation_method = SBC_ALLOCATION_LOUDNESS;
0090         } else if (caps.allocation_method & SBC_ALLOCATION_SNR) {
0091             caps.allocation_method = SBC_ALLOCATION_SNR;
0092         } else {
0093             break;
0094         }
0095 
0096         caps.min_bitpool = 2;
0097         caps.max_bitpool = 53;
0098 
0099         const QByteArray configuration(reinterpret_cast<const char *>(&caps), sizeof(caps));
0100         Q_EMIT configurationSelected(capabilities, configuration);
0101         request.accept(configuration);
0102         return;
0103 
0104         break;
0105     }
0106     case MediaEndpoint::Codec::Aac:
0107         if (capabilities.size() != sizeof(a2dp_aac_t)) {
0108             Q_EMIT configurationSelected(capabilities, QByteArray());
0109             request.reject();
0110             return;
0111         }
0112 
0113         // TODO: implement AAC. However selectConfiguration seems not to be used by iOS nor Android.
0114         Q_EMIT configurationSelected(capabilities, QByteArray());
0115         request.reject();
0116         return;
0117 
0118         break;
0119     }
0120 
0121     Q_EMIT configurationSelected(capabilities, QByteArray());
0122     request.reject();
0123 }
0124 
0125 void MediaEndpoint::clearConfiguration(const QString &transportObjectPath)
0126 {
0127     Q_EMIT configurationCleared(transportObjectPath);
0128 }
0129 
0130 void MediaEndpoint::release()
0131 {
0132 }
0133 
0134 } // namespace BluezQt
0135 
0136 #include "moc_mediaendpoint.cpp"