4#include <QtMultimedia/private/qandroidaudiodevices_p.h>
6#include <QtMultimedia/private/qandroidaudiodevice_p.h>
7#include <QtMultimedia/private/qandroidaudiojnitypes_p.h>
8#include <QtMultimedia/private/qandroidaudiosink_p.h>
9#include <QtMultimedia/private/qandroidaudiosource_p.h>
11#include <QtMultimedia/private/qplatformmediaintegration_p.h>
13#include <QtCore/qjniobject.h>
17using namespace QtJniTypes;
21QAudioFormat preferredFormatForDevice(
const QtJniTypes::AudioDeviceInfo &deviceInfo)
23 QAudioFormat preferredFormat;
26 QJniArray<jint> channelCounts = deviceInfo.callMethod<QJniArray<jint>>(
"getChannelCounts");
27 if (channelCounts.isEmpty()) {
28 preferredFormat.setChannelConfig(QAudioFormat::ChannelConfigStereo);
30 const auto [minIt, maxIt] = std::minmax_element(channelCounts.begin(), channelCounts.end());
31 const int channelCount = std::clamp(2, *minIt, *maxIt);
32 preferredFormat.setChannelConfig(
33 QAudioFormat::defaultChannelConfigForChannelCount(channelCount));
37 preferredFormat.setSampleRate(
38 QtAudioDeviceManager::callStaticMethod<jint>(
"getDefaultSampleRate"));
42 preferredFormat.setSampleFormat(QAudioFormat::Float);
44 return preferredFormat;
47QList<QAudioDevice> availableDevices(QAudioDevice::Mode mode)
49 if (mode == QAudioDevice::Null)
52 QList<QAudioDevice> devices;
53 const char *getMethod =
54 mode == QAudioDevice::Input ?
"getAudioInputDevices" :
"getAudioOutputDevices";
56 QtAudioDeviceManager::callStaticMethod<QJniArray<AudioDeviceInfo>>(getMethod);
58 if (!deviceInfos.isValid())
61 for (
int i = 0; i < deviceInfos.size(); ++i) {
62 AudioDeviceInfo deviceInfo = deviceInfos.at(i);
63 int id = deviceInfo.callMethod<jint>(
"getId");
64 jint deviceType = deviceInfo.callMethod<jint>(
"getType");
65 auto description = QtAudioDeviceManager::callStaticMethod<QString>(
66 "audioDeviceTypeToString", deviceType);
67 bool isBluetoothDevice =
68 QtAudioDeviceManager::callStaticMethod<jboolean>(
"isBluetoothDevice", deviceInfo);
69 devices << QAudioDevicePrivate::createQAudioDevice(std::make_unique<QAndroidAudioDevice>(
70 QString::number(id).toUtf8(), description, mode,
71 preferredFormatForDevice(deviceInfo), isBluetoothDevice, i == 0));
80QAndroidAudioDevices::QAndroidAudioDevices() : QPlatformAudioDevices()
82 QtAudioDeviceManager::callStaticMethod<
void>(
83 "qAndroidAudioDevicesConstructed",
84 static_cast<jlong>(
reinterpret_cast<size_t>(
this)));
87QAndroidAudioDevices::~QAndroidAudioDevices()
91 QtAudioDeviceManager::callStaticMethod<
void>(
"qAndroidAudioDevicesDestroyed");
95QList<QAudioDevice> QAndroidAudioDevices::findAudioInputs()
const
97 return availableDevices(QAudioDevice::Input);
101QList<QAudioDevice> QAndroidAudioDevices::findAudioOutputs()
const
103 return availableDevices(QAudioDevice::Output);
107QPlatformAudioSource *QAndroidAudioDevices::createAudioSource(
const QAudioDevice &deviceInfo,
108 const QAudioFormat &fmt,
111 return new QtAAudio::QAndroidAudioSource(deviceInfo, fmt, parent);
115QPlatformAudioSink *QAndroidAudioDevices::createAudioSink(
const QAudioDevice &deviceInfo,
116 const QAudioFormat &fmt, QObject *parent)
118 return new QtAAudio::QAndroidAudioSink(deviceInfo, fmt, parent);
127 auto *audioDevices =
reinterpret_cast<QAndroidAudioDevices*>(
static_cast<size_t>(nativePtr));
128 Q_ASSERT(!audioDevices->thread()->isCurrentThread());
129 audioDevices->onAudioInputsChanged();
131Q_DECLARE_JNI_NATIVE_METHOD(onAudioInputDevicesUpdated)
139 auto *audioDevices =
reinterpret_cast<QAndroidAudioDevices*>(
static_cast<size_t>(nativePtr));
140 Q_ASSERT(!audioDevices->thread()->isCurrentThread());
141 audioDevices->onAudioOutputsChanged();
143Q_DECLARE_JNI_NATIVE_METHOD(onAudioOutputDevicesUpdated)
145bool QAndroidAudioDevices::registerNativeMethods()
147 static const bool registered = []{
148 const auto context = QNativeInterface::QAndroidApplication::context();
149 QtAudioDeviceManager::callStaticMethod<
void>(
"setContext", context);
151 return QtJniTypes::QtAudioDeviceManager::registerNativeMethods({
152 Q_JNI_NATIVE_METHOD(onAudioInputDevicesUpdated),
153 Q_JNI_NATIVE_METHOD(onAudioOutputDevicesUpdated),
161extern "C" Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,
void * )
163 static bool initialized =
false;
165 return JNI_VERSION_1_6;
170 JNIEnv *nativeEnvironment;
174 UnionJNIEnvToVoid uenv;
177 if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK)
180 if (!QAndroidAudioDevices::registerNativeMethods())
183 return JNI_VERSION_1_6;
static void onAudioInputDevicesUpdated(JNIEnv *, jobject, jlong nativePtr)
static void onAudioOutputDevicesUpdated(JNIEnv *, jobject, jlong nativePtr)