/* * BluezQt - Asynchronous Bluez wrapper library * * SPDX-FileCopyrightText: 2019 Manuel Weichselbaumer * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "mediatransport_p.h" #include "a2dp-codecs.h" #include "macros.h" #include "utils.h" namespace BluezQt { static MediaTransport::State stringToState(const QString &state) { if (state == QLatin1String("pending")) { return MediaTransport::State::Pending; } else if (state == QLatin1String("active")) { return MediaTransport::State::Active; } return MediaTransport::State::Idle; } static AudioCodec intToCodec(int value) { switch (value) { case A2DP_CODEC_SBC: return AudioCodec::Sbc; break; case A2DP_CODEC_MPEG24: return AudioCodec::Aac; break; } return AudioCodec::Invalid; } static AudioSampleRate byteArrayToSampleRate(AudioCodec codec, const QByteArray &buffer) { switch (codec) { case AudioCodec::Sbc: { if (buffer.size() != sizeof(a2dp_sbc_t)) { return AudioSampleRate::Invalid; } a2dp_sbc_t sbcConfig = *reinterpret_cast(buffer.constData()); switch (sbcConfig.frequency) { case SBC_SAMPLING_FREQ_44100: return AudioSampleRate::Rate44100; break; case SBC_SAMPLING_FREQ_48000: return AudioSampleRate::Rate48000; break; } break; } case AudioCodec::Aac: { if (buffer.size() != sizeof(a2dp_aac_t)) { return AudioSampleRate::Invalid; } a2dp_aac_t aacConfig = *reinterpret_cast(buffer.constData()); switch (AAC_GET_FREQUENCY(aacConfig)) { case AAC_SAMPLING_FREQ_44100: return AudioSampleRate::Rate44100; break; case AAC_SAMPLING_FREQ_48000: return AudioSampleRate::Rate48000; break; } break; } default: break; } return AudioSampleRate::Invalid; } MediaTransportPrivate::MediaTransportPrivate(const QString &path, const QVariantMap &properties) : QObject() , m_dbusInterface(Strings::orgBluez(), path, DBusConnection::orgBluez()) , m_dbusProperties(nullptr) , m_path(path) { DBusConnection::orgBluez().connect(Strings::orgBluez(), path, Strings::orgFreedesktopDBusProperties(), QStringLiteral("PropertiesChanged"), this, SLOT(onPropertiesChanged(QString, QVariantMap, QStringList))); init(properties); } void MediaTransportPrivate::init(const QVariantMap &properties) { m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_path, DBusConnection::orgBluez(), this); m_volume = properties.value(QStringLiteral("Volume")).toUInt(); m_state = stringToState(properties.value(QStringLiteral("State")).toString()); m_configuration.codec = intToCodec(properties.value(QStringLiteral("Codec")).toInt()); m_configuration.sampleRate = byteArrayToSampleRate(m_configuration.codec, properties.value(QStringLiteral("Configuration")).toByteArray()); } QDBusPendingReply<> MediaTransportPrivate::setDBusProperty(const QString &name, const QVariant &value) { return m_dbusProperties->Set(Strings::orgBluezMediaTransport1(), name, QDBusVariant(value)); } void MediaTransportPrivate::onPropertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) { if (interface != Strings::orgBluezMediaTransport1()) { return; } for (auto it = changed.constBegin(); it != changed.constEnd(); ++it) { const QString &key = it.key(); const QVariant &value = it.value(); if (key == QLatin1String("Volume")) { m_volume = value.toUInt(); Q_EMIT q.lock()->volumeChanged(m_volume); } else if (key == QLatin1String("State")) { m_state = stringToState(value.toString()); Q_EMIT q.lock()->stateChanged(m_state); } } for (const QString &property : invalidated) { if (property == QLatin1String("Volume")) { m_volume = 0; Q_EMIT q.lock()->volumeChanged(m_volume); } else if (property == QLatin1String("State")) { PROPERTY_INVALIDATED(m_state, MediaTransport::State::Idle, stateChanged); } } } } // namespace BluezQt #include "moc_mediatransport_p.cpp"