File indexing completed on 2024-05-05 03:52:31

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() = default;
0022 
0023 QDBusObjectPath MediaEndpoint::objectPath() const
0024 {
0025     return d->m_objectPath;
0026 }
0027 
0028 const QVariantMap &MediaEndpoint::properties() const
0029 {
0030     return d->m_properties;
0031 }
0032 
0033 void MediaEndpoint::setConfiguration(const QString &transportObjectPath, const QVariantMap &properties)
0034 {
0035     Q_EMIT configurationSet(transportObjectPath, properties);
0036 }
0037 
0038 void MediaEndpoint::selectConfiguration(const QByteArray &capabilities, const Request<QByteArray> &request)
0039 {
0040     switch (d->m_configuration.codec) {
0041     case MediaEndpoint::Codec::Sbc: {
0042         if (capabilities.size() != sizeof(a2dp_sbc_t)) {
0043             Q_EMIT configurationSelected(capabilities, QByteArray());
0044             request.reject();
0045             return;
0046         }
0047 
0048         a2dp_sbc_t caps = *reinterpret_cast<const a2dp_sbc_t *>(capabilities.constData());
0049         if (caps.frequency & SBC_SAMPLING_FREQ_44100) {
0050             caps.frequency = SBC_SAMPLING_FREQ_44100;
0051         } else if (caps.frequency & SBC_SAMPLING_FREQ_48000) {
0052             caps.frequency = SBC_SAMPLING_FREQ_48000;
0053         } else {
0054             break;
0055         }
0056 
0057         if (caps.channel_mode & SBC_CHANNEL_MODE_STEREO) {
0058             caps.channel_mode = SBC_CHANNEL_MODE_STEREO;
0059         } else if (caps.channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) {
0060             caps.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
0061         } else {
0062             break;
0063         }
0064 
0065         if (caps.block_length & SBC_BLOCK_LENGTH_16) {
0066             caps.block_length = SBC_BLOCK_LENGTH_16;
0067         } else if (caps.block_length & SBC_BLOCK_LENGTH_12) {
0068             caps.block_length = SBC_BLOCK_LENGTH_12;
0069         } else if (caps.block_length & SBC_BLOCK_LENGTH_8) {
0070             caps.block_length = SBC_BLOCK_LENGTH_8;
0071         } else if (caps.block_length & SBC_BLOCK_LENGTH_4) {
0072             caps.block_length = SBC_BLOCK_LENGTH_4;
0073         } else {
0074             break;
0075         }
0076 
0077         if (caps.subbands & SBC_SUBBANDS_8) {
0078             caps.subbands = SBC_SUBBANDS_8;
0079         } else if (caps.subbands & SBC_SUBBANDS_4) {
0080             caps.subbands = SBC_SUBBANDS_4;
0081         } else {
0082             break;
0083         }
0084 
0085         if (caps.allocation_method & SBC_ALLOCATION_LOUDNESS) {
0086             caps.allocation_method = SBC_ALLOCATION_LOUDNESS;
0087         } else if (caps.allocation_method & SBC_ALLOCATION_SNR) {
0088             caps.allocation_method = SBC_ALLOCATION_SNR;
0089         } else {
0090             break;
0091         }
0092 
0093         caps.min_bitpool = 2;
0094         caps.max_bitpool = 53;
0095 
0096         const QByteArray configuration(reinterpret_cast<const char *>(&caps), sizeof(caps));
0097         Q_EMIT configurationSelected(capabilities, configuration);
0098         request.accept(configuration);
0099         return;
0100 
0101         break;
0102     }
0103     case MediaEndpoint::Codec::Aac:
0104         if (capabilities.size() != sizeof(a2dp_aac_t)) {
0105             Q_EMIT configurationSelected(capabilities, QByteArray());
0106             request.reject();
0107             return;
0108         }
0109 
0110         // TODO: implement AAC. However selectConfiguration seems not to be used by iOS nor Android.
0111         Q_EMIT configurationSelected(capabilities, QByteArray());
0112         request.reject();
0113         return;
0114 
0115         break;
0116     }
0117 
0118     Q_EMIT configurationSelected(capabilities, QByteArray());
0119     request.reject();
0120 }
0121 
0122 void MediaEndpoint::clearConfiguration(const QString &transportObjectPath)
0123 {
0124     Q_EMIT configurationCleared(transportObjectPath);
0125 }
0126 
0127 void MediaEndpoint::release()
0128 {
0129 }
0130 
0131 } // namespace BluezQt
0132 
0133 #include "moc_mediaendpoint.cpp"