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"