diff options
author | Bartlomiej Moskal <bartlomiej.moskal@qt.io> | 2021-08-04 11:35:32 +0200 |
---|---|---|
committer | Bartlomiej Moskal <bartlomiej.moskal@qt.io> | 2021-08-10 12:37:47 +0000 |
commit | 748315bf2777f104e45634f87198acd37bc98762 (patch) | |
tree | 4bf5765deff748d3d59e478110804f402c1c44fc | |
parent | 5c763eb639cd0c8ab3cfdc3ae74f5ea23edd03b3 (diff) |
Android: set audioOutput device
Add implementation for changing audio output device
Change-Id: Ib510979b72319a3e716f190da0df03589d253792
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
10 files changed, 95 insertions, 2 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtAudioDeviceManager.java b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtAudioDeviceManager.java index 7823a72e8..dcc001fc0 100644 --- a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtAudioDeviceManager.java +++ b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtAudioDeviceManager.java @@ -205,4 +205,50 @@ public class QtAudioDeviceManager ret = devices.toArray(ret); return ret; } + + private static boolean setAudioOutput(int id) + { + final AudioDeviceInfo[] audioDevices = + m_audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS); + for (AudioDeviceInfo deviceInfo : audioDevices) { + if (deviceInfo.getId() == id) { + switch (deviceInfo.getType()) + { + case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: + case AudioDeviceInfo.TYPE_BLUETOOTH_SCO: + setAudioOutput(AudioManager.MODE_IN_COMMUNICATION, true, false); + return true; + case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER: + setAudioOutput(AudioManager.MODE_NORMAL, false, true); + return true; + case AudioDeviceInfo.TYPE_WIRED_HEADSET: + case AudioDeviceInfo.TYPE_WIRED_HEADPHONES: + setAudioOutput(AudioManager.MODE_IN_COMMUNICATION, false, false); + return true; + case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE: + // It doesn't work when WIRED HEADPHONES are connected + // Earpiece has the lowest priority and setWiredHeadsetOn(boolean) + // method to force it is deprecated + setAudioOutput(AudioManager.MODE_IN_CALL, false, false); + return true; + default: + return false; + } + } + } + return false; + } + + private static void setAudioOutput(int mode, boolean bluetoothOn, boolean speakerOn) + { + m_audioManager.setMode(mode); + if (bluetoothOn) { + m_audioManager.startBluetoothSco(); + } else { + m_audioManager.stopBluetoothSco(); + } + m_audioManager.setBluetoothScoOn(bluetoothOn); + m_audioManager.setSpeakerphoneOn(speakerOn); + + } } diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt index 058227dfc..d2ac1ab85 100644 --- a/src/multimedia/CMakeLists.txt +++ b/src/multimedia/CMakeLists.txt @@ -112,6 +112,7 @@ if(ANDROID) set_property(TARGET Multimedia APPEND PROPERTY QT_ANDROID_PERMISSIONS android.permission.CAMERA android.permission.RECORD_AUDIO android.permission.BLUETOOTH + android.permission.MODIFY_AUDIO_SETTINGS ) endif() diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp index 83928ca6a..0eb282f1d 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp @@ -41,11 +41,13 @@ #include "androidcamera_p.h" #include "qandroidcamerasession_p.h" +#include "androidmediaplayer_p.h" #include "androidmultimediautils_p.h" #include "qandroidmultimediautils_p.h" #include "qandroidvideooutput_p.h" #include "qandroidglobal_p.h" #include <private/qplatformaudioinput_p.h> +#include <private/qplatformaudiooutput_p.h> #include <private/qmediarecorder_p.h> #include <QtCore/qmimetype.h> @@ -104,6 +106,17 @@ void QAndroidCaptureSession::setAudioInput(QPlatformAudioInput *input) m_audioInput = input; } +void QAndroidCaptureSession::setAudioOutput(QPlatformAudioOutput *output) +{ + if (m_audioOutput == output) + return; + + m_audioOutput = output; + + if (m_audioOutput) + AndroidMediaPlayer::setAudioOutput(m_audioOutput->device.id()); +} + QMediaRecorder::RecorderState QAndroidCaptureSession::state() const { return m_state; diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h b/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h index 1673710a6..ca6209ac5 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h +++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h @@ -77,6 +77,7 @@ public: void setCameraSession(QAndroidCameraSession *cameraSession = 0); void setAudioInput(QPlatformAudioInput *input); + void setAudioOutput(QPlatformAudioOutput *output); QMediaRecorder::RecorderState state() const; @@ -159,6 +160,7 @@ private: QAndroidCameraSession *m_cameraSession; QPlatformAudioInput *m_audioInput = nullptr; + QPlatformAudioOutput *m_audioOutput = nullptr; QMediaStorageLocation m_mediaStorageLocation; diff --git a/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession.cpp b/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession.cpp index ee0fd9f8d..94207c8a9 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession.cpp @@ -139,6 +139,11 @@ void QAndroidMediaCaptureSession::setAudioInput(QPlatformAudioInput *input) m_captureSession->setAudioInput(input); } +void QAndroidMediaCaptureSession::setAudioOutput(QPlatformAudioOutput *output) +{ + m_captureSession->setAudioOutput(output); +} + void QAndroidMediaCaptureSession::setVideoPreview(QVideoSink *sink) { m_cameraSession->setVideoSink(sink); diff --git a/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession_p.h b/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession_p.h index e75527ebe..667fbba7a 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession_p.h +++ b/src/multimedia/platform/android/mediacapture/qandroidmediacapturesession_p.h @@ -84,6 +84,8 @@ public: void setVideoPreview(QVideoSink *sink) override; + void setAudioOutput(QPlatformAudioOutput *output) override; + QAndroidCaptureSession *captureSession() const { return m_captureSession; } QAndroidCameraSession *cameraSession() const { return m_cameraSession; } diff --git a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer.cpp b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer.cpp index 873fd78ef..79cb0fa2b 100644 --- a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer.cpp +++ b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer.cpp @@ -363,12 +363,19 @@ void QAndroidMediaPlayer::setAudioOutput(QPlatformAudioOutput *output) m_audioOutput->q->disconnect(this); m_audioOutput = static_cast<QAndroidAudioOutput *>(output); if (m_audioOutput) { - // #### Implement device changes: connect(m_audioOutput->q, &QAudioOutput::deviceChanged, this, XXXX); + connect(m_audioOutput->q, &QAudioOutput::deviceChanged, this, &QAndroidMediaPlayer::updateAudioDevice); connect(m_audioOutput->q, &QAudioOutput::volumeChanged, this, &QAndroidMediaPlayer::setVolume); connect(m_audioOutput->q, &QAudioOutput::mutedChanged, this, &QAndroidMediaPlayer::setMuted); + updateAudioDevice(); } } +void QAndroidMediaPlayer::updateAudioDevice() +{ + if (m_audioOutput) + mMediaPlayer->setAudioOutput(m_audioOutput->device.id()); +} + void QAndroidMediaPlayer::play() { StateChangeNotifier notifier(this); diff --git a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer_p.h b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer_p.h index 88ad6774f..c134e5b08 100644 --- a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer_p.h +++ b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayer_p.h @@ -87,6 +87,7 @@ public: void setVideoSink(QVideoSink *surface) override; void setAudioOutput(QPlatformAudioOutput *output) override; + void updateAudioDevice(); void setPosition(qint64 position) override; void play() override; diff --git a/src/multimedia/platform/android/wrappers/jni/androidmediaplayer.cpp b/src/multimedia/platform/android/wrappers/jni/androidmediaplayer.cpp index 26da7ed3d..84ec3edbd 100644 --- a/src/multimedia/platform/android/wrappers/jni/androidmediaplayer.cpp +++ b/src/multimedia/platform/android/wrappers/jni/androidmediaplayer.cpp @@ -52,6 +52,8 @@ Q_GLOBAL_STATIC(QReadWriteLock, rwLock) QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcAudio, "qt.multimedia.audio") + static bool exceptionCheckAndClear() { #ifdef QT_DEBUG @@ -241,6 +243,20 @@ void AndroidMediaPlayer::setDisplay(AndroidSurfaceTexture *surfaceTexture) surfaceTexture ? surfaceTexture->surfaceHolder() : 0); } +bool AndroidMediaPlayer::setAudioOutput(const QByteArray &deviceId) +{ + const bool ret = QJniObject::callStaticMethod<jboolean>( + "org/qtproject/qt/android/multimedia/QtAudioDeviceManager", + "setAudioOutput", + "(I)Z", + deviceId.toInt()); + + if (!ret) + qCWarning(lcAudio) << "Output device not set"; + + return ret; +} + #if 0 void AndroidMediaPlayer::setAudioRole(QAudio::Role role) { diff --git a/src/multimedia/platform/android/wrappers/jni/androidmediaplayer_p.h b/src/multimedia/platform/android/wrappers/jni/androidmediaplayer_p.h index 2d1e645c4..96c93223c 100644 --- a/src/multimedia/platform/android/wrappers/jni/androidmediaplayer_p.h +++ b/src/multimedia/platform/android/wrappers/jni/androidmediaplayer_p.h @@ -129,7 +129,7 @@ public: void setVolume(int volume); bool setPlaybackRate(qreal rate); void setDisplay(AndroidSurfaceTexture *surfaceTexture); - + static bool setAudioOutput(const QByteArray &deviceId); static bool registerNativeMethods(); Q_SIGNALS: |