Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit ee6714e

Browse files
authored
Merge pull request #405 from DolbyIO/release/3.10.0-beta.1
Release/3.10.0 beta.1
2 parents edb7de2 + 81e1099 commit ee6714e

File tree

69 files changed

+2820
-149
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2820
-149
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
## 3.10.0-beta.1
2+
3+
### Features
4+
5+
- Introduced the ability to change the [capture mode](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/LocalAudio/setCaptureMode.html) in non-Dolby Voice conferences and use either the [Standard](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureMode.html#standard) or [Unprocessed](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureMode.html#unprocessed) mode.
6+
7+
- Introduced a new [voiceFont](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureOptions/voicefont.html) property to [AudioCaptureOptions](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureOptions-class.html) that is supported in the [Standard](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureMode.html#standard) audio capture mode. [Voice fonts](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureOptions/voicefont.html) allow participants to modify their voices in real time to improve social interaction in entertainment scenarios. For more information about this feature, see the [Using Voice Fonts](https://docs.dolby.io/interactivity/docs/guides-using-voice-fonts) guide.
8+
9+
- Introduced a new [preview](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/LocalAudio/preview.html) service that allows the local participant to test different capture modes and voice fonts before a conference. The service records the participant's audio and plays it back. Before playing the recorded audio, set the [captureMode](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/LocalAudio/setCaptureMode.html) to a preferred setting that you wish to try.
10+
11+
- Introduced a new [updateParticipantInfo](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/SessionService/updateParticipantInfo.html) method that lets participants modify their names and avatars while they are in a conference.
12+
13+
- The SDK now supports receiving two shared screens in one conference.
14+
15+
### Changes
16+
17+
Changed the default value of the audio capture mode in non-Dolby Voice conferences to [Standard](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureMode.html#standard) with [high](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/NoiseReduction.html#high) noise reduction. This setting optimizes captured audio for speech by aggressively removing non-speech content. If you want to transmit non-stationary background sounds to a conference and create a more natural audio experience, you can set noise reduction to [low](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/NoiseReduction.html#low), which offers a similar experience as the default setting in previous releases. If you wish to transmit non-voice audio to a conference as well and use input device setting without any processing, use the [Unprocessed](https://api-references.dolby.io/comms-sdk-flutter/dolbyio_comms_sdk_flutter/AudioCaptureMode.html#unprocessed) mode.
18+
119
## 3.8.3
220

321
### Bug Fixes

android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version '1.0-SNAPSHOT'
33

44
buildscript {
55
ext.kotlin_version = '1.7.10'
6-
ext.voxeet_sdk_version = "3.8.+"
6+
ext.voxeet_sdk_version = "3.10.0"
77
ext.dagger_version = "2.40.5"
88
repositories {
99
google()
@@ -78,7 +78,7 @@ android {
7878
dependencies {
7979
// uncomment this to gradle sync for android plugin in android studio, comment again before build
8080
// implementation files("$flutterRoot/bin/cache/artifacts/engine/android-arm64-release/flutter.jar")
81-
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
81+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
8282
def useMockSDK = project.properties.containsKey("useMockSDK") ? project.properties.get("useMockSDK") : false
8383
if (useMockSDK) {
8484
implementation project(":dolbyMock")

android/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
COMMS_SDK_VERSION="3.8.3"
1+
COMMS_SDK_VERSION="3.10.0-beta.1"
22
COMPONENT_NAME="flutter-sdk"

android/src/main/kotlin/io/dolby/comms/sdk/flutter/DolbyioCommsSdkFlutterPlugin.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import io.dolby.comms.sdk.flutter.module.NotificationServiceNativeModule
1414
import io.dolby.comms.sdk.flutter.module.RecordingServiceNativeModule
1515
import io.dolby.comms.sdk.flutter.module.SessionServiceNativeModule
1616
import io.dolby.comms.sdk.flutter.module.VideoPresentationServiceModule
17+
import io.dolby.comms.sdk.flutter.module.audio.AudioPreviewNativeModule
1718
import io.dolby.comms.sdk.flutter.module.audio.LocalAudioNativeModule
1819
import io.dolby.comms.sdk.flutter.module.audio.RemoteAudioNativeModule
1920
import io.dolby.comms.sdk.flutter.module.video.LocalVideoNativeModule
@@ -28,6 +29,7 @@ import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter
2829
import kotlinx.coroutines.CoroutineScope
2930
import kotlinx.coroutines.SupervisorJob
3031
import kotlinx.coroutines.cancelChildren
32+
import org.webrtc.CodecDescriptorFactory
3133

3234
class DolbyioCommsSdkFlutterPlugin : FlutterPlugin, ActivityAware {
3335

@@ -49,7 +51,8 @@ class DolbyioCommsSdkFlutterPlugin : FlutterPlugin, ActivityAware {
4951
NotificationEventEmitter(EventChannelHandler(NOTIFICATION)),
5052
RecordingEventEmitter(EventChannelHandler(RECORDING)),
5153
VideoPresentationEventEmitter(EventChannelHandler(VIDEO_PRESENTATION), videoPresentationHolder),
52-
filePresentationEventEmitter
54+
filePresentationEventEmitter,
55+
AudioPreviewEventEmitter(EventChannelHandler(AUDIO_PREVIEW))
5356
)
5457

5558
nativeModules = listOf(
@@ -70,7 +73,8 @@ class DolbyioCommsSdkFlutterPlugin : FlutterPlugin, ActivityAware {
7073
filePresentationEventEmitter,
7174
filePresentationHolder
7275
),
73-
MediaDeviceServiceNativeModule(scope)
76+
MediaDeviceServiceNativeModule(scope),
77+
AudioPreviewNativeModule(scope)
7478
)
7579

7680
VoxeetSDK.registerComponentVersion(BuildConfig.COMPONENT_NAME, BuildConfig.SDK_VERSION)
@@ -97,6 +101,7 @@ class DolbyioCommsSdkFlutterPlugin : FlutterPlugin, ActivityAware {
97101
const val RECORDING = "dolbyio_recording_service_event_channel"
98102
const val VIDEO_PRESENTATION = "dolbyio_video_presentation_service_event_channel"
99103
const val FILE_PRESENTATION = "dolbyio_file_presentation_service_event_channel"
104+
const val AUDIO_PREVIEW = "dolbyio_audio_preview_event_channel"
100105
}
101106

102107
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.dolby.comms.sdk.flutter.events
2+
3+
import com.voxeet.VoxeetSDK
4+
import com.voxeet.android.media.capture.audio.preview.RecorderStatus
5+
6+
class AudioPreviewEventEmitter(eventChannelHandler: EventChannelHandler) : NativeEventEmitter(eventChannelHandler) {
7+
8+
/**
9+
* Emitted when the application user received an audio preview status changed.
10+
*/
11+
private val previewCallback: (RecorderStatus) -> Unit = { status ->
12+
android.util.Log.d("[KB]", "status changed: $status")
13+
emit(OnStatusChanged, status.name)
14+
}
15+
16+
override fun registerEventEmitter() {
17+
VoxeetSDK.audio().local.preview().callback = previewCallback
18+
}
19+
20+
override fun unregisterEventEmitter() {
21+
VoxeetSDK.audio().local.preview().callback = null
22+
}
23+
24+
companion object {
25+
const val OnStatusChanged = "EVENT_AUDIO_PREVIEW_STATUS_CHANGED"
26+
}
27+
}

android/src/main/kotlin/io/dolby/comms/sdk/flutter/events/EventChannelHandler.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class EventChannelHandler(private val channelName: String) : EventChannel.Stream
2222
}
2323

2424
override fun onListen(arguments: Any?, callback: EventChannel.EventSink?) {
25+
android.util.Log.d("[KB]", "arguments: ${arguments}")
2526
eventCallback = callback
2627
}
2728

android/src/main/kotlin/io/dolby/comms/sdk/flutter/events/NativeEventEmitter.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,24 @@ abstract class NativeEventEmitter(private val eventChannel: EventChannelHandler)
1111

1212
fun onAttached(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
1313
eventChannel.onAttached(flutterPluginBinding)
14-
VoxeetSDK.instance().register(this)
14+
registerEventEmitter()
1515
}
1616

1717
fun onDetached() {
18-
VoxeetSDK.instance().unregister(this)
18+
unregisterEventEmitter()
1919
eventChannel.onDetached()
2020
}
2121

2222
// Event needs to be emitted on main thread
2323
fun emit(key: String, data: Any?) = mainHandler.post {
2424
eventChannel.emitEvent(key, data)
2525
}
26+
27+
protected open fun registerEventEmitter() {
28+
VoxeetSDK.instance().register(this)
29+
}
30+
31+
protected open fun unregisterEventEmitter() {
32+
VoxeetSDK.instance().unregister(this)
33+
}
2634
}

android/src/main/kotlin/io/dolby/comms/sdk/flutter/mapper/AudioCaptureModeMapper.kt

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package io.dolby.comms.sdk.flutter.mapper
22

33
import com.voxeet.android.media.capture.audio.AudioCaptureMode
44
import com.voxeet.android.media.capture.audio.Mode
5+
import com.voxeet.android.media.capture.audio.VoiceFont
56
import com.voxeet.android.media.capture.audio.noise.NoiseReduction
67
import com.voxeet.android.media.capture.audio.noise.StandardNoiseReduction
78

@@ -10,6 +11,7 @@ class AudioCaptureModeMapper(private val audioCaptureMode: AudioCaptureMode) : M
1011
override fun convertToMap() = mapOf(
1112
"mode" to audioCaptureMode.mode.convertToString(),
1213
"noiseReduction" to audioCaptureMode.noiseReduction?.convertToString(),
14+
"voiceFont" to audioCaptureMode.voiceFont?.convertToString(),
1315
)
1416

1517
private fun Mode.convertToString(): String = when (this) {
@@ -22,10 +24,27 @@ class AudioCaptureModeMapper(private val audioCaptureMode: AudioCaptureMode) : M
2224
else -> "low"
2325
}
2426

27+
private fun VoiceFont.convertToString(): String = when (this) {
28+
VoiceFont.MASCULINE -> "masculine"
29+
VoiceFont.FEMININE -> "feminine"
30+
VoiceFont.HELIUM -> "helium"
31+
VoiceFont.DARK_MODULATION -> "dark_modulation"
32+
VoiceFont.BROKEN_ROBOT -> "broken_robot"
33+
VoiceFont.INTERFERENCE -> "interference"
34+
VoiceFont.ABYSS -> "abyss"
35+
VoiceFont.WOBBLE -> "wobble"
36+
VoiceFont.STARSHIP_CAPTAIN -> "starship_captain"
37+
VoiceFont.NERVOUS_ROBOT -> "nervous_robot"
38+
VoiceFont.SWARM -> "swarm"
39+
VoiceFont.AM_RADIO -> "am_radio"
40+
else -> "none"
41+
}
42+
2543
companion object {
2644
fun fromMap(map: Map<String, Any?>): AudioCaptureMode {
45+
val voiceFont = toVoiceFont(map["voiceFont"] as String?)
2746
return when (toMode(map["mode"] as String?)) {
28-
Mode.STANDARD -> AudioCaptureMode.standard(toNoiseReduction(map["noiseReduction"] as String?))
47+
Mode.STANDARD -> AudioCaptureMode.standard(toNoiseReduction(map["noiseReduction"] as String?), voiceFont)
2948
Mode.UNPROCESSED -> AudioCaptureMode.unprocessed()
3049
}
3150
}
@@ -35,6 +54,22 @@ class AudioCaptureModeMapper(private val audioCaptureMode: AudioCaptureMode) : M
3554
else -> Mode.STANDARD
3655
}
3756

57+
private fun toVoiceFont(font: String?): VoiceFont = when (font) {
58+
"masculine" -> VoiceFont.MASCULINE
59+
"feminine" -> VoiceFont.FEMININE
60+
"helium" -> VoiceFont.HELIUM
61+
"dark_modulation" -> VoiceFont.DARK_MODULATION
62+
"broken_robot" -> VoiceFont.BROKEN_ROBOT
63+
"interference" -> VoiceFont.INTERFERENCE
64+
"abyss" -> VoiceFont.ABYSS
65+
"wobble" -> VoiceFont.WOBBLE
66+
"starship_captain" -> VoiceFont.STARSHIP_CAPTAIN
67+
"nervous_robot" -> VoiceFont.NERVOUS_ROBOT
68+
"swarm" -> VoiceFont.SWARM
69+
"am_radio" -> VoiceFont.AM_RADIO
70+
else -> VoiceFont.NONE
71+
}
72+
3873
private fun toNoiseReduction(noiseReduction: String?) = when (noiseReduction) {
3974
"high" -> StandardNoiseReduction.HIGH
4075
else -> StandardNoiseReduction.LOW

android/src/main/kotlin/io/dolby/comms/sdk/flutter/module/SessionServiceNativeModule.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class SessionServiceNativeModule(private val scope: CoroutineScope) : NativeModu
1818
override fun onMethodCall(call: MethodCall, result: Result) {
1919
when (call.method) {
2020
::open.name -> open(call, result)
21+
::updateParticipantInfo.name -> updateParticipantInfo(call, result)
2122
::close.name -> close(result)
2223
::isOpen.name -> isOpen(result)
2324
::getParticipant.name -> getParticipant(result)
@@ -45,6 +46,16 @@ class SessionServiceNativeModule(private val scope: CoroutineScope) : NativeModu
4546
}
4647
)
4748

49+
private fun updateParticipantInfo(call: MethodCall, result: Result) = scope.launch(
50+
onError = result::onError,
51+
onSuccess = {
52+
VoxeetSDK.session().update(
53+
call.argumentOrThrow<String>("name"),
54+
call.argument<String>("avatarUrl")
55+
).await().let { result.success(it) }
56+
}
57+
)
58+
4859
private fun close(result: Result) = scope.launch(
4960
onError = result::onError,
5061
onSuccess = {
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package io.dolby.comms.sdk.flutter.module.audio
2+
3+
import com.voxeet.VoxeetSDK
4+
import io.dolby.comms.sdk.flutter.extension.argumentOrThrow
5+
import io.dolby.comms.sdk.flutter.extension.await
6+
import io.dolby.comms.sdk.flutter.extension.launch
7+
import io.dolby.comms.sdk.flutter.extension.onError
8+
import io.dolby.comms.sdk.flutter.mapper.AudioCaptureModeMapper
9+
import io.dolby.comms.sdk.flutter.module.NativeModule
10+
import io.flutter.embedding.engine.plugins.FlutterPlugin
11+
import io.flutter.plugin.common.MethodCall
12+
import io.flutter.plugin.common.MethodChannel
13+
import kotlinx.coroutines.CoroutineScope
14+
import java.lang.reflect.Proxy
15+
16+
class AudioPreviewNativeModule(private val scope: CoroutineScope) : NativeModule {
17+
private lateinit var channel: MethodChannel
18+
19+
override fun onAttached(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
20+
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "dolbyio_audio_preview_channel")
21+
channel.setMethodCallHandler(this)
22+
}
23+
24+
override fun onDetached() {
25+
channel.setMethodCallHandler(null)
26+
}
27+
28+
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
29+
when (call.method) {
30+
::status.name -> status(result)
31+
::getCaptureMode.name -> getCaptureMode(result)
32+
::setCaptureMode.name -> setCaptureMode(call, result)
33+
::record.name -> record(call, result)
34+
::play.name -> play(call, result)
35+
::cancel.name -> cancel(result)
36+
::release.name -> release(result)
37+
}
38+
}
39+
40+
private fun status(result: MethodChannel.Result) = scope.launch(
41+
onError = result::onError,
42+
onSuccess = {
43+
VoxeetSDK.audio().local.preview().status.let {
44+
result.success(it.name)
45+
}
46+
}
47+
)
48+
49+
private fun getCaptureMode(result: MethodChannel.Result) = scope.launch(
50+
onError = result::onError,
51+
onSuccess = {
52+
VoxeetSDK.audio().local.preview().captureMode.let {
53+
result.success(AudioCaptureModeMapper(it).convertToMap())
54+
}
55+
}
56+
)
57+
58+
private fun setCaptureMode(call: MethodCall, result: MethodChannel.Result) = scope.launch(
59+
onError = result::onError,
60+
onSuccess = {
61+
VoxeetSDK.audio().local.preview().captureMode = AudioCaptureModeMapper.fromMap(call.arguments as Map<String, Any?>)
62+
result.success(null)
63+
}
64+
)
65+
66+
private fun record(call: MethodCall, result: MethodChannel.Result) = scope.launch(
67+
onError = result::onError,
68+
onSuccess = {
69+
call.argumentOrThrow<Int>("duration").let { duration ->
70+
VoxeetSDK.audio().local.preview().record(duration).await()
71+
result.success(null)
72+
}
73+
}
74+
)
75+
76+
private fun play(call: MethodCall, result: MethodChannel.Result) = scope.launch(
77+
onError = result::onError,
78+
onSuccess = {
79+
call.argumentOrThrow<Boolean>("loop").let { loop ->
80+
VoxeetSDK.audio().local.preview().play(loop).await()
81+
result.success(null)
82+
}
83+
}
84+
)
85+
86+
private fun cancel(result: MethodChannel.Result) = scope.launch(
87+
onError = result::onError,
88+
onSuccess = {
89+
result.success(VoxeetSDK.audio().local.preview().cancel())
90+
}
91+
)
92+
93+
private fun release(result: MethodChannel.Result) = scope.launch(
94+
onError = result::onError,
95+
onSuccess = {
96+
result.success(VoxeetSDK.audio().local.preview().release())
97+
}
98+
)
99+
}

0 commit comments

Comments
 (0)