diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f15eff80..c76640334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,7 +61,7 @@ All user visible changes to this project will be documented in this file. This p - `FormatException`; - `MediaStateTransitionException`; - `MediaSettingsUpdateException`. - - `MediaManagerHandle.set_output_audio_id()` function switching output audio device on Dart platform ([#29]); + - `MediaManagerHandle.set_output_audio_id()` method switching output audio device on Dart platform ([#29]); - `MediaManagerHandle.on_device_change()` callback firing whenever `MediaManagerHandle.enumerate_devices()` list changes ([#30]); - `ConnectionHandle` methods ([#43]): - `enable_remote_video`; @@ -69,6 +69,10 @@ All user visible changes to this project will be documented in this file. This p - `enable_remote_audio`; - `disable_remote_audio`. - `MediaDirection` type ([#46]). + - `MediaManagerHandle` methods for microphone volume on Dart platform ([#49]): + - `microphone_volume_is_available`; + - `microphone_volume`; + - `set_microphone_volume`. ### Updated @@ -81,6 +85,7 @@ All user visible changes to this project will be documented in this file. This p [#30]: /../../pull/30 [#43]: /../../pull/43 [#46]: /../../pull/46 +[#49]: /../../pull/49 diff --git a/Cargo.lock b/Cargo.lock index 6a692a54e..67a090f2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -319,9 +319,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "arc-swap" @@ -391,9 +391,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47594e438a243791dba58124b6669561f5baa14cb12046641d8008bf035e5a25" +checksum = "f4af7447fc1214c1f3a1ace861d0216a6c8bb13965b64bbad9650f375b67689a" dependencies = [ "async-trait", "axum-core", @@ -420,9 +420,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a671c9ae99531afdd5d3ee8340b8da547779430689947144c140fc74a740244" +checksum = "3bdc19781b16e32f8a7200368a336fa4509d4b72ef15dd4e41df5290855ee1e6" dependencies = [ "async-trait", "bytes 1.1.0", @@ -558,16 +558,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.8" +version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db" dependencies = [ "atty", "bitflags", "clap_derive", + "clap_lex", "indexmap", "lazy_static", - "os_str_bytes", "strsim", "termcolor", "textwrap 0.15.0", @@ -586,6 +586,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_lex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cmake" version = "0.1.48" @@ -1163,9 +1172,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +checksum = "76c813ffb63e8fd3df6f1ac3cc1ea392c7612ac2de4d0b44dcbfe03e5c4bf94a" dependencies = [ "proc-macro2", "quote", @@ -1275,9 +1284,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6330e8a36bd8c859f3fa6d9382911fbb7147ec39807f63b923933a247240b9ba" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -1415,9 +1424,9 @@ dependencies = [ [[package]] name = "inventory" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6b5d8c669bfbad811d95ddd7a1c6cf9cfdbf2777e59928b6f3fa8ff54f72a0" +checksum = "84344c6e0b90a9e2b6f3f9abe5cc74402684e348df7b32adca28747e0cef091a" dependencies = [ "ctor", "ghost", @@ -1425,9 +1434,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itertools" @@ -1476,9 +1485,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.123" +version = "0.2.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd" +checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" [[package]] name = "linked-hash-map" @@ -1886,9 +1895,6 @@ name = "os_str_bytes" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] [[package]] name = "parking_lot" @@ -1984,9 +1990,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -2038,9 +2044,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b83ec2d0af5c5c556257ff52c9f98934e243b9fd39604bfb2a9b75ec2e97f18" +checksum = "d9e07e3a46d0771a8a06b5f4441527802830b43e679ba12f44960f48dd4c6803" dependencies = [ "proc-macro2", "syn", @@ -2081,9 +2087,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd5316aa8f5c82add416dfbc25116b84b748a21153f512917e8143640a71bbd" +checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890" dependencies = [ "bytes 1.1.0", "prost-derive", @@ -2091,9 +2097,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328f9f29b82409216decb172d81e936415d21245befa79cd34c3f29d87d1c50b" +checksum = "120fbe7988713f39d780a58cf1a7ef0d7ef66c6d87e5aa3438940c05357929f4" dependencies = [ "bytes 1.1.0", "cfg-if 1.0.0", @@ -2113,9 +2119,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df35198f0777b75e9ff669737c6da5136b59dba33cf5a010a6d1cc4d56defc6f" +checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" dependencies = [ "anyhow", "itertools", @@ -2126,9 +2132,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926681c118ae6e512a3ccefd4abbe5521a14f4cc1e207356d4d00c0b7f2006fd" +checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes 1.1.0", "prost", @@ -2405,9 +2411,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "946fa04a8ac43ff78a1f4b811990afb9ddbdf5890b46d6dda0ba1998230138b7" +checksum = "b827f2113224f3f19a665136f006709194bdfdcb1fdc1e4b2b5cbac8e0cced54" dependencies = [ "rustversion", "serde", @@ -2758,9 +2764,9 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -2773,9 +2779,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "0f48b6d60512a392e34dbf7fd456249fd2de3c83669ab642e021903f4015185b" dependencies = [ "bytes 1.1.0", "libc", @@ -2881,9 +2887,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d17087af5c80e5d5fc8ba9878e60258065a0a757e35efe7a05b7904bece1943" +checksum = "c03447cdc9eaf8feffb6412dcb27baf2db11669a6c4789f29da799aabfb99547" dependencies = [ "prettyplease", "proc-macro2", @@ -2914,9 +2920,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.2.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +checksum = "f7755f984aa46a9d50829dc84b6a674b2f3b8b4de47c0708923953b090d48acc" dependencies = [ "bitflags", "bytes 1.1.0", @@ -2955,9 +2961,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b9fa4360528139bc96100c160b7ae879f5567f49f1782b0b02035b0358ebf3" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if 1.0.0", "log", @@ -2968,9 +2974,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", "quote", @@ -2979,9 +2985,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dfce9f3241b150f36e8e54bb561a742d5daa1a47b5dd9a5ce369fd4a4db2210" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", ] @@ -3021,9 +3027,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-normalization" diff --git a/flutter/android/src/main/jniLibs/arm64-v8a/libmedea_jason.so b/flutter/android/src/main/jniLibs/arm64-v8a/libmedea_jason.so index e5eba53c3..caf722bbf 100755 Binary files a/flutter/android/src/main/jniLibs/arm64-v8a/libmedea_jason.so and b/flutter/android/src/main/jniLibs/arm64-v8a/libmedea_jason.so differ diff --git a/flutter/android/src/main/jniLibs/armeabi-v7a/libmedea_jason.so b/flutter/android/src/main/jniLibs/armeabi-v7a/libmedea_jason.so index 25d7c2ba2..4475de47d 100755 Binary files a/flutter/android/src/main/jniLibs/armeabi-v7a/libmedea_jason.so and b/flutter/android/src/main/jniLibs/armeabi-v7a/libmedea_jason.so differ diff --git a/flutter/android/src/main/jniLibs/x86/libmedea_jason.so b/flutter/android/src/main/jniLibs/x86/libmedea_jason.so index 2b73b92cc..1952f9514 100755 Binary files a/flutter/android/src/main/jniLibs/x86/libmedea_jason.so and b/flutter/android/src/main/jniLibs/x86/libmedea_jason.so differ diff --git a/flutter/android/src/main/jniLibs/x86_64/libmedea_jason.so b/flutter/android/src/main/jniLibs/x86_64/libmedea_jason.so index cc2e0ff34..6359e3af7 100755 Binary files a/flutter/android/src/main/jniLibs/x86_64/libmedea_jason.so and b/flutter/android/src/main/jniLibs/x86_64/libmedea_jason.so differ diff --git a/flutter/example/integration_test/jason.dart b/flutter/example/integration_test/jason.dart index 9dd36f683..f8f98a4d8 100644 --- a/flutter/example/integration_test/jason.dart +++ b/flutter/example/integration_test/jason.dart @@ -665,6 +665,15 @@ void main() { } throw Exception('Exception not fired on panic'); }); + + testWidgets('Volume settings', (WidgetTester widgetTester) async { + var jason = Jason(); + var media = jason.mediaManager(); + + expect(await media.microphoneVolumeIsAvailable(), true); + expect(await media.microphoneVolume(), 50); + expect(() async => await media.setMicrophoneVolume(100), returnsNormally); + }); } class TestObj { diff --git a/flutter/example/linux/flutter/generated_plugins.cmake b/flutter/example/linux/flutter/generated_plugins.cmake index 18c97d06b..c8ebd7c52 100644 --- a/flutter/example/linux/flutter/generated_plugins.cmake +++ b/flutter/example/linux/flutter/generated_plugins.cmake @@ -7,9 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST medea_jason ) -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - set(PLUGIN_BUNDLED_LIBRARIES) foreach(plugin ${FLUTTER_PLUGIN_LIST}) @@ -18,8 +15,3 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/flutter/example/pubspec.lock b/flutter/example/pubspec.lock index ef934630e..a7920521a 100644 --- a/flutter/example/pubspec.lock +++ b/flutter/example/pubspec.lock @@ -1,34 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - url: "https://pub.dartlang.org" - source: hosted - version: "38.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - url: "https://pub.dartlang.org" - source: hosted - version: "3.4.1" archive: dependency: transitive description: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.1.11" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.0" + version: "3.1.6" async: dependency: transitive description: @@ -43,20 +22,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" - build: - dependency: transitive - description: - name: build - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.0" - build_config: - dependency: transitive - description: - name: build_config - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" characters: dependency: transitive description: @@ -71,13 +36,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" clock: dependency: transitive description: @@ -91,14 +49,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.16.0" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" + version: "1.15.0" crypto: dependency: transitive description: @@ -113,20 +64,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" - dart_style: - dependency: transitive - description: - name: dart_style - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.3" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.2.0" ffi: dependency: transitive description: @@ -168,17 +112,10 @@ packages: description: path: "." ref: HEAD - resolved-ref: "0be9d6c46d989071091cfcf120ec1e758f3708ca" + resolved-ref: "9b48b5939cb864e70179045532d7cd38d94ec3c9" url: "https://github.com/instrumentisto/flutter-webrtc.git" source: git version: "0.8.0-dev" - freezed: - dependency: transitive - description: - name: freezed - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" freezed_annotation: dependency: transitive description: @@ -191,13 +128,6 @@ packages: description: flutter source: sdk version: "0.0.0" - glob: - dependency: transitive - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" integration_test: dependency: "direct dev" description: flutter @@ -216,14 +146,7 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" - logging: - dependency: transitive - description: - name: logging - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" + version: "4.5.0" matcher: dependency: transitive description: @@ -237,7 +160,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.3" medea_jason: dependency: "direct main" description: @@ -252,20 +175,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" - package_config: - dependency: transitive - description: - name: package_config - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" pedantic: dependency: "direct dev" description: @@ -287,39 +203,18 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" - pub_semver: - dependency: transitive - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.2" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -361,7 +256,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.8" typed_data: dependency: transitive description: @@ -375,21 +270,14 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.1" vm_service: dependency: transitive description: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "8.2.2" - watcher: - dependency: transitive - description: - name: watcher - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" + version: "7.5.0" webdriver: dependency: transitive description: @@ -397,13 +285,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.0" - yaml: - dependency: transitive - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.16.0 <3.0.0" flutter: ">=2.0.0" diff --git a/flutter/example/windows/flutter/generated_plugins.cmake b/flutter/example/windows/flutter/generated_plugins.cmake index dec867099..811c9040e 100644 --- a/flutter/example/windows/flutter/generated_plugins.cmake +++ b/flutter/example/windows/flutter/generated_plugins.cmake @@ -7,9 +7,6 @@ list(APPEND FLUTTER_PLUGIN_LIST medea_jason ) -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - set(PLUGIN_BUNDLED_LIBRARIES) foreach(plugin ${FLUTTER_PLUGIN_LIST}) @@ -18,8 +15,3 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/flutter/lib/src/interface/exceptions.dart b/flutter/lib/src/interface/exceptions.dart index 40fac3e84..43fb66de4 100644 --- a/flutter/lib/src/interface/exceptions.dart +++ b/flutter/lib/src/interface/exceptions.dart @@ -61,6 +61,15 @@ abstract class InvalidOutputAudioDeviceIdException { String trace(); } +/// Exception thrown when cannot interact with microphone volume. +abstract class MicVolumeException { + /// Returns error that caused this [MicVolumeException]. + dynamic cause(); + + /// Returns stacktrace of this [MicVolumeException]. + String trace(); +} + /// Jason's internal exception. /// /// This is either a programmatic error or some unexpected platform component diff --git a/flutter/lib/src/interface/media_manager.dart b/flutter/lib/src/interface/media_manager.dart index d2875c5cd..1ac4adff2 100644 --- a/flutter/lib/src/interface/media_manager.dart +++ b/flutter/lib/src/interface/media_manager.dart @@ -37,6 +37,15 @@ abstract class MediaManagerHandle implements PlatformHandle { /// Switches output audio device to the device with the provided [deviceId]. Future setOutputAudioId(String deviceId); + /// Indicates whether it's possible to access microphone volume settings. + Future microphoneVolumeIsAvailable(); + + /// Sets the microphone volume level in percents. + Future setMicrophoneVolume(int level); + + /// Returns the current microphone volume level in percents. + Future microphoneVolume(); + /// Subscribes onto the [MediaManagerHandle]'s `devicechange` event. void onDeviceChange(void Function() cb); } diff --git a/flutter/lib/src/native/ffi/exception.dart b/flutter/lib/src/native/ffi/exception.dart index dacd2066e..6dd1a9796 100644 --- a/flutter/lib/src/native/ffi/exception.dart +++ b/flutter/lib/src/native/ffi/exception.dart @@ -26,7 +26,8 @@ void registerFunctions(DynamicLibrary dl) { Pointer.fromFunction(_newMediaSettingsUpdateException), newInvalidOutputAudioDeviceIdException: Pointer.fromFunction(_newInvalidOutputAudioDeviceIdException), - throwPanicException: Pointer.fromFunction(_throwPanicException)); + throwPanicException: Pointer.fromFunction(_throwPanicException), + newMicVolumeException: Pointer.fromFunction(_newMicVolumeException)); } /// Creates a new [ArgumentError] from the provided invalid [value], its [name] @@ -58,8 +59,8 @@ Object _newLocalMediaInitException(int kind, Pointer message, stacktrace.nativeStringToDartString()); } -/// Creates a new [NativeEnumerateDevicesException] with the provided error [cause] -/// and [stacktrace]. +/// Creates a new [NativeEnumerateDevicesException] with the provided error +/// [cause] and [stacktrace]. Object _newEnumerateDevicesException( Pointer cause, Pointer stacktrace) { return NativeEnumerateDevicesException( @@ -73,6 +74,13 @@ Object _newInvalidOutputAudioDeviceIdException(Pointer trace) { trace.nativeStringToDartString()); } +/// Creates a new [MicVolumeException] with the provided error [cause] and +/// [trace]. +Object _newMicVolumeException(Pointer cause, Pointer trace) { + return NativeMicVolumeException( + unboxDartHandle(cause), trace.nativeStringToDartString()); +} + /// Creates a new [NativeRpcClientException] with the provided error [kind], /// [message], [cause] and [stacktrace]. Object _newRpcClientException(int kind, Pointer message, @@ -206,6 +214,28 @@ class NativeInvalidOutputAudioDeviceIdException } } +/// Exception thrown when cannot interact with microphone volume. +class NativeMicVolumeException extends MicVolumeException { + /// Dart [Exception] or [Error] that caused this [NativeMicVolumeException]. + late final Object _cause; + + /// Native stacktrace. + late final String _nativeStackTrace; + + /// Instantiates a new [NativeMicVolumeException]. + NativeMicVolumeException(this._cause, this._nativeStackTrace); + + @override + dynamic cause() { + return _cause; + } + + @override + String trace() { + return _nativeStackTrace; + } +} + /// Exceptions thrown from `Jason`'s `RpcClient` which implements messaging with /// media server. class NativeRpcClientException extends RpcClientException implements Exception { diff --git a/flutter/lib/src/native/ffi/exception.g.dart b/flutter/lib/src/native/ffi/exception.g.dart index a61cecd9d..f2f2196c3 100644 --- a/flutter/lib/src/native/ffi/exception.g.dart +++ b/flutter/lib/src/native/ffi/exception.g.dart @@ -37,13 +37,27 @@ void registerFunction( newMediaSettingsUpdateException, required Pointer)>> newInvalidOutputAudioDeviceIdException, + required Pointer< + NativeFunction, Pointer)>> + newMicVolumeException, required Pointer> throwPanicException, }) { dl.lookupFunction< Void Function(Pointer, Pointer, Pointer, Pointer, Pointer, Pointer, - Pointer, Pointer, Pointer, Pointer, Pointer), - void Function(Pointer, Pointer, Pointer, Pointer, Pointer, Pointer, - Pointer, Pointer, Pointer, Pointer, Pointer)>('register_exception')( + Pointer, Pointer, Pointer, Pointer, Pointer, Pointer), + void Function( + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer, + Pointer)>('register_exception')( newArgumentError, newStateError, newFormatException, @@ -54,6 +68,7 @@ void registerFunction( newInternalException, newMediaSettingsUpdateException, newInvalidOutputAudioDeviceIdException, + newMicVolumeException, throwPanicException, ); } diff --git a/flutter/lib/src/native/media_manager.dart b/flutter/lib/src/native/media_manager.dart index 26b7d4f49..f2b2eccbd 100644 --- a/flutter/lib/src/native/media_manager.dart +++ b/flutter/lib/src/native/media_manager.dart @@ -25,6 +25,15 @@ typedef _enumerateDevices_Dart = Object Function(Pointer); typedef _setOutputAudioId_C = Handle Function(Pointer, Pointer); typedef _setOutputAudioId_Dart = Object Function(Pointer, Pointer); +typedef _setMicrophoneVolume_C = Handle Function(Pointer, Int64); +typedef _setMicrophoneVolume_Dart = Object Function(Pointer, int); + +typedef _microphoneVolumeIsAvailable_C = Handle Function(Pointer); +typedef _microphoneVolumeIsAvailable_Dart = Object Function(Pointer); + +typedef _microphoneVolume_C = Handle Function(Pointer); +typedef _microphoneVolume_Dart = Object Function(Pointer); + typedef _onDeviceChange_C = Result Function(Pointer, Handle); typedef _onDeviceChange_Dart = Result Function(Pointer, Object); @@ -43,6 +52,18 @@ final _setOutputAudioId = dl.lookupFunction<_setOutputAudioId_C, _setOutputAudioId_Dart>( 'MediaManagerHandle__set_output_audio_id'); +final _setMicrophoneVolume = + dl.lookupFunction<_setMicrophoneVolume_C, _setMicrophoneVolume_Dart>( + 'MediaManagerHandle__set_microphone_volume'); + +final _microphoneVolumeIsAvailable = dl.lookupFunction< + _microphoneVolumeIsAvailable_C, _microphoneVolumeIsAvailable_Dart>( + 'MediaManagerHandle__microphone_volume_is_available'); + +final _microphoneVolume = + dl.lookupFunction<_microphoneVolume_C, _microphoneVolume_Dart>( + 'MediaManagerHandle__microphone_volume'); + final _onDeviceChange = dl.lookupFunction<_onDeviceChange_C, _onDeviceChange_Dart>( 'MediaManagerHandle__on_device_change'); @@ -89,6 +110,24 @@ class NativeMediaManagerHandle extends MediaManagerHandle { as Future); } + @override + Future setMicrophoneVolume(int level) async { + await (_setMicrophoneVolume(ptr.getInnerPtr(), level) as Future); + } + + @override + Future microphoneVolume() async { + return await (_microphoneVolume(ptr.getInnerPtr()) as Future); + } + + @override + Future microphoneVolumeIsAvailable() async { + var available = + await (_microphoneVolumeIsAvailable(ptr.getInnerPtr()) as Future); + + return available != 0; + } + @override void onDeviceChange(void Function() cb) { _onDeviceChange(ptr.getInnerPtr(), cb).unwrap(); diff --git a/flutter/lib/src/native/platform/media_devices.dart b/flutter/lib/src/native/platform/media_devices.dart index 7a5ef3aad..45ee8ad10 100644 --- a/flutter/lib/src/native/platform/media_devices.dart +++ b/flutter/lib/src/native/platform/media_devices.dart @@ -14,6 +14,10 @@ void registerFunctions(DynamicLibrary dl) { getUserMedia: Pointer.fromFunction(_getUserMedia), getDisplayMedia: Pointer.fromFunction(_getDisplayMedia), setOutputAudioId: Pointer.fromFunction(_setOutputAudioId), + setMicrophoneVolume: Pointer.fromFunction(_setMicrophoneVolume), + microphoneVolumeIsAvailable: + Pointer.fromFunction(_microphoneVolumeIsAvailable), + microphoneVolume: Pointer.fromFunction(_microphoneVolume), onDeviceChange: Pointer.fromFunction(_onDeviceChange), ); } @@ -39,6 +43,23 @@ Object _setOutputAudioId(Pointer deviceId) { return () => webrtc.setOutputAudioId(deviceId.toDartString()); } +/// Sets the microphone volume level in percents. +Object _setMicrophoneVolume(int level) { + return () => webrtc.setMicrophoneVolume(level); +} + +/// Indicates whether it's possible to access microphone volume settings. +Object _microphoneVolumeIsAvailable() { + return () async { + return await webrtc.microphoneVolumeIsAvailable() ? 1 : 0; + }; +} + +/// Gets the current microphone volume level in percents. +Object _microphoneVolume() { + return () => webrtc.microphoneVolume(); +} + /// Subscribes onto the `MediaDevices`'s `devicechange` event. void _onDeviceChange(Function cb) { webrtc.onDeviceChange(() => cb(null)); diff --git a/flutter/lib/src/native/platform/media_devices.g.dart b/flutter/lib/src/native/platform/media_devices.g.dart index 2f6627b55..c39b08d44 100644 --- a/flutter/lib/src/native/platform/media_devices.g.dart +++ b/flutter/lib/src/native/platform/media_devices.g.dart @@ -9,16 +9,24 @@ void registerFunction( required Pointer> getDisplayMedia, required Pointer)>> setOutputAudioId, + required Pointer> + microphoneVolumeIsAvailable, + required Pointer> microphoneVolume, + required Pointer> setMicrophoneVolume, required Pointer> onDeviceChange, }) { dl.lookupFunction< - Void Function(Pointer, Pointer, Pointer, Pointer, Pointer), - void Function(Pointer, Pointer, Pointer, Pointer, - Pointer)>('register_media_devices')( + Void Function(Pointer, Pointer, Pointer, Pointer, Pointer, Pointer, + Pointer, Pointer), + void Function(Pointer, Pointer, Pointer, Pointer, Pointer, Pointer, + Pointer, Pointer)>('register_media_devices')( enumerateDevices, getUserMedia, getDisplayMedia, setOutputAudioId, + microphoneVolumeIsAvailable, + microphoneVolume, + setMicrophoneVolume, onDeviceChange, ); } diff --git a/flutter/lib/src/web/media_manager.dart b/flutter/lib/src/web/media_manager.dart index cc79876d5..a4c18a46d 100644 --- a/flutter/lib/src/web/media_manager.dart +++ b/flutter/lib/src/web/media_manager.dart @@ -47,4 +47,21 @@ class WebMediaManagerHandle extends MediaManagerHandle { void onDeviceChange(Function cb) { obj.on_device_change(allowInterop(cb)); } + + @override + Future microphoneVolumeIsAvailable() async { + return false; + } + + @override + Future microphoneVolume() { + // TODO(logist322): implement microphoneVolume + throw UnimplementedError(); + } + + @override + Future setMicrophoneVolume(int level) { + // TODO(logist322): implement setMicrophoneVolume + throw UnimplementedError(); + } } diff --git a/flutter/linux/lib/x86_64-unknown-linux-gnu/libmedea_jason.so b/flutter/linux/lib/x86_64-unknown-linux-gnu/libmedea_jason.so index 074e751f3..60a43165f 100755 Binary files a/flutter/linux/lib/x86_64-unknown-linux-gnu/libmedea_jason.so and b/flutter/linux/lib/x86_64-unknown-linux-gnu/libmedea_jason.so differ diff --git a/flutter/windows/lib/x86_64-pc-windows-msvc/medea_jason.dll b/flutter/windows/lib/x86_64-pc-windows-msvc/medea_jason.dll index 458f8a12f..888dee7ff 100644 Binary files a/flutter/windows/lib/x86_64-pc-windows-msvc/medea_jason.dll and b/flutter/windows/lib/x86_64-pc-windows-msvc/medea_jason.dll differ diff --git a/src/api/dart/media_manager_handle.rs b/src/api/dart/media_manager_handle.rs index c6edb0a70..41d7cedeb 100644 --- a/src/api/dart/media_manager_handle.rs +++ b/src/api/dart/media_manager_handle.rs @@ -9,8 +9,8 @@ use crate::{ utils::{DartError, DartResult}, }, media::{ - EnumerateDevicesError, InitLocalTracksError, - InvalidOutputAudioDeviceIdError, + EnumerateDevicesError, HandleDetachedError, InitLocalTracksError, + InvalidOutputAudioDeviceIdError, MicVolumeError, }, platform, }; @@ -88,6 +88,55 @@ pub unsafe extern "C" fn MediaManagerHandle__set_output_audio_id( }) } +/// Sets the microphone volume level in percents. +#[no_mangle] +pub unsafe extern "C" fn MediaManagerHandle__set_microphone_volume( + this: ptr::NonNull, + level: i64, +) -> DartFuture>> { + propagate_panic(move || { + let this = this.as_ref().clone(); + + async move { + this.set_microphone_volume(level) + .await + .map_err(tracerr::map_from_and_wrap!())?; + Ok(()) + } + .into_dart_future() + }) +} + +/// Indicates whether it's possible to access microphone volume settings. +#[no_mangle] +pub unsafe extern "C" fn MediaManagerHandle__microphone_volume_is_available( + this: ptr::NonNull, +) -> DartFuture>> { + propagate_panic(move || { + let this = this.as_ref().clone(); + + async move { this.microphone_volume_is_available().await } + .into_dart_future() + }) +} + +/// Returns the current microphone volume level in percents. +#[no_mangle] +pub unsafe extern "C" fn MediaManagerHandle__microphone_volume( + this: ptr::NonNull, +) -> DartFuture>> { + propagate_panic(move || { + let this = this.as_ref().clone(); + + async move { + this.microphone_volume() + .await + .map_err(tracerr::map_from_and_wrap!()) + } + .into_dart_future() + }) +} + /// Subscribes onto the [`MediaManagerHandle`]'s `devicechange` event. #[no_mangle] pub unsafe extern "C" fn MediaManagerHandle__on_device_change( @@ -139,7 +188,7 @@ mod mock { }, media::{ EnumerateDevicesError, HandleDetachedError, InitLocalTracksError, - InvalidOutputAudioDeviceIdError, + InvalidOutputAudioDeviceIdError, MicVolumeError, }, platform, }; @@ -179,6 +228,25 @@ mod mock { Ok(()) } + pub async fn set_microphone_volume( + &self, + _: i64, + ) -> Result<(), Traced> { + Ok(()) + } + + pub async fn microphone_volume_is_available( + &self, + ) -> Result> { + Ok(true) + } + + pub async fn microphone_volume( + &self, + ) -> Result> { + Ok(50) + } + pub fn on_device_change( &self, cb: platform::Function<()>, diff --git a/src/api/dart/mod.rs b/src/api/dart/mod.rs index 24ee3394e..fd473b836 100644 --- a/src/api/dart/mod.rs +++ b/src/api/dart/mod.rs @@ -40,14 +40,16 @@ use crate::{ utils::new_panic_error, }, media::{FacingMode, MediaDeviceKind, MediaKind, MediaSourceKind}, - platform, - platform::utils::{ - dart_api::{ - Dart_DeletePersistentHandle_DL_Trampolined, - Dart_NewPersistentHandle_DL_Trampolined, - Dart_PropagateError_DL_Trampolined, + platform::{ + self, + utils::{ + dart_api::{ + Dart_DeletePersistentHandle_DL_Trampolined, + Dart_NewPersistentHandle_DL_Trampolined, + Dart_PropagateError_DL_Trampolined, + }, + handle::DartHandle, }, - handle::DartHandle, }, }; diff --git a/src/api/dart/utils/err.rs b/src/api/dart/utils/err.rs index 267d3b7f4..ef428029f 100644 --- a/src/api/dart/utils/err.rs +++ b/src/api/dart/utils/err.rs @@ -14,7 +14,7 @@ use crate::{ EnumerateDevicesException, FormatException, InternalException, InvalidOutputAudioDeviceIdException, LocalMediaInitException, MediaSettingsUpdateException, MediaStateTransitionException, - RpcClientException, StateError, + MicVolumeException, RpcClientException, StateError, }, }, platform, @@ -111,6 +111,13 @@ mod exception { trace: ptr::NonNull, ) -> Dart_Handle; + /// Returns a new Dart [`MicVolumeException`] with the provided `cause` + /// and `trace` properties. + pub fn new_mic_volume_exception( + cause: DartError, + trace: ptr::NonNull, + ) -> Dart_Handle; + /// Returns a new Dart `NativePanicException`. /// /// Returned [`Dart_Handle`] will be recognized by Dart runtime as an @@ -236,6 +243,17 @@ impl From for DartError { } } +impl From for DartError { + fn from(err: MicVolumeException) -> Self { + unsafe { + Self::new(exception::new_mic_volume_exception( + err.cause().into(), + string_into_c_str(err.trace()), + )) + } + } +} + impl From for DartError { fn from(err: FormatException) -> Self { unsafe { diff --git a/src/api/err.rs b/src/api/err.rs index f5391b234..087b313e8 100644 --- a/src/api/err.rs +++ b/src/api/err.rs @@ -15,7 +15,7 @@ use crate::{ connection, media::{ self, EnumerateDevicesError, GetDisplayMediaError, GetUserMediaError, - InitLocalTracksError, InvalidOutputAudioDeviceIdError, + InitLocalTracksError, InvalidOutputAudioDeviceIdError, MicVolumeError, }, peer::{ sender::CreateError, InsertLocalTracksError, LocalMediaError, @@ -215,6 +215,41 @@ impl InvalidOutputAudioDeviceIdException { } } +/// Exception thrown when cannot interact with microphone volume. +#[cfg_attr(target_family = "wasm", wasm_bindgen)] +#[derive(Debug)] +pub struct MicVolumeException { + /// [`platform::Error`] causing this [`MicVolumeException`]. + cause: platform::Error, + + /// Stacktrace of this [`MicVolumeException`]. + trace: Trace, +} + +impl MicVolumeException { + /// Creates a new [`MicVolumeException`] from the provided error [`Trace`]. + #[must_use] + pub fn new(cause: platform::Error, trace: Trace) -> Self { + Self { cause, trace } + } +} + +#[cfg_attr(target_family = "wasm", allow(clippy::unused_unit))] +#[cfg_attr(target_family = "wasm", wasm_bindgen)] +impl MicVolumeException { + /// Returns the [`platform::Error`] causing this [`MicVolumeException`]. + #[must_use] + pub fn cause(&self) -> platform::Error { + self.cause.clone() + } + + /// Returns stacktrace of this [`MicVolumeException`]. + #[must_use] + pub fn trace(&self) -> String { + self.trace.to_string() + } +} + /// Possible error kinds of a [`RpcClientException`]. #[cfg_attr(target_family = "wasm", wasm_bindgen)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -553,6 +588,20 @@ impl From> for Error { } } +impl From> for Error { + fn from(err: Traced) -> Self { + let (err, stacktrace) = err.split(); + match err { + MicVolumeError::MicVolumeError(err) => { + MicVolumeException::new(err, stacktrace).into() + } + MicVolumeError::Detached => { + StateError::new(err.to_string(), stacktrace).into() + } + } + } +} + impl From> for Error { fn from(err: Traced) -> Self { use GetDisplayMediaError as Gdm; diff --git a/src/api/wasm/err.rs b/src/api/wasm/err.rs index dc86778d2..b7c38c90c 100644 --- a/src/api/wasm/err.rs +++ b/src/api/wasm/err.rs @@ -12,7 +12,7 @@ use crate::api::err::{ EnumerateDevicesException, FormatException, InternalException, InvalidOutputAudioDeviceIdException, LocalMediaInitException, MediaSettingsUpdateException, MediaStateTransitionException, - RpcClientException, StateError, + MicVolumeException, RpcClientException, StateError, }; /// Wrapper around [`JsValue`] which represents a JS error. @@ -65,3 +65,4 @@ impl_from_into_jsval_for_error!(FormatException); impl_from_into_jsval_for_error!(MediaStateTransitionException); impl_from_into_jsval_for_error!(MediaSettingsUpdateException); impl_from_into_jsval_for_error!(InvalidOutputAudioDeviceIdException); +impl_from_into_jsval_for_error!(MicVolumeException); diff --git a/src/media/manager.rs b/src/media/manager.rs index e05dc23f4..81272c614 100644 --- a/src/media/manager.rs +++ b/src/media/manager.rs @@ -62,6 +62,20 @@ pub enum InitLocalTracksError { #[display(fmt = "Invalid audio device ID provided")] pub struct InvalidOutputAudioDeviceIdError; +/// Error returned from the [`MediaManagerHandle::microphone_volume()`] or +/// [`MediaManagerHandle::set_microphone_volume()`] methods. +#[derive(Caused, Clone, Debug, Display, From)] +#[cause(error = "platform::Error")] +pub enum MicVolumeError { + /// Error accessing microphone volume settings. + #[display(fmt = "Error accessing microphone volume settings: {}", _0)] + MicVolumeError(platform::Error), + + /// [`MediaManagerHandle`]'s inner [`Weak`] pointer cannot be upgraded. + #[display(fmt = "`MediaManagerHandle` is in detached state")] + Detached, +} + /// Error indicating about a [`MediaManagerHandle`] in detached state. #[derive(Clone, Copy, Debug, Display)] #[display(fmt = "MediaManagerHandle is in detached state")] @@ -395,6 +409,38 @@ impl InnerMediaManager { .await .map_err(|_| tracerr::new!(InvalidOutputAudioDeviceIdError)) } + + /// Indicates whether it's possible to access microphone volume settings. + async fn microphone_volume_is_available(&self) -> bool { + self.media_devices.microphone_volume_is_available().await + } + + /// Sets the microphone volume level in percents. + /// + /// # Errors + /// + /// With [`MicVolumeError`] if platform call errors. + async fn set_microphone_volume( + &self, + level: i64, + ) -> Result<(), Traced> { + self.media_devices + .set_microphone_volume(level) + .await + .map_err(tracerr::map_from_and_wrap!()) + } + + /// Gets the current microphone volume level in percents. + /// + /// # Errors + /// + /// With [`MicVolumeError`] if platform call errors. + async fn microphone_volume(&self) -> Result> { + self.media_devices + .microphone_volume() + .await + .map_err(tracerr::map_from_and_wrap!()) + } } impl MediaManager { @@ -514,6 +560,57 @@ impl MediaManagerHandle { .map_err(tracerr::map_from_and_wrap!()) } + /// Sets the microphone volume level in percents. + /// + /// # Errors + /// + /// See [`MicVolumeError`] for details. + pub async fn set_microphone_volume( + &self, + level: i64, + ) -> Result<(), Traced> { + let this = self + .0 + .upgrade() + .ok_or_else(|| tracerr::new!(MicVolumeError::Detached))?; + + this.set_microphone_volume(level) + .await + .map_err(tracerr::map_from_and_wrap!()) + } + + /// Indicates whether it's possible to access microphone volume settings. + /// + /// # Errors + /// + /// If the underlying [`MediaManagerHandle`] is dropped. + pub async fn microphone_volume_is_available( + &self, + ) -> Result> { + let this = self + .0 + .upgrade() + .ok_or_else(|| tracerr::new!(HandleDetachedError))?; + Ok(this.microphone_volume_is_available().await) + } + + /// Returns the current microphone volume level in percents. + /// + /// # Errors + /// + /// See [`MicVolumeError`] for details. + pub async fn microphone_volume( + &self, + ) -> Result> { + let this = self + .0 + .upgrade() + .ok_or_else(|| tracerr::new!(MicVolumeError::Detached))?; + this.microphone_volume() + .await + .map_err(tracerr::map_from_and_wrap!()) + } + /// Subscribes onto the `devicechange` event of this [`MediaManagerHandle`]. /// /// # Errors diff --git a/src/media/mod.rs b/src/media/mod.rs index cf69d4d50..4d7fa96d4 100644 --- a/src/media/mod.rs +++ b/src/media/mod.rs @@ -21,6 +21,7 @@ pub use self::{ EnumerateDevicesError, GetDisplayMediaError, GetUserMediaError, HandleDetachedError, InitLocalTracksError, InvalidOutputAudioDeviceIdError, MediaManager, MediaManagerHandle, + MicVolumeError, }, track::{remote::MediaDirection, MediaSourceKind}, }; diff --git a/src/platform/dart/media_devices.rs b/src/platform/dart/media_devices.rs index be746d3f6..adeaca391 100644 --- a/src/platform/dart/media_devices.rs +++ b/src/platform/dart/media_devices.rs @@ -54,6 +54,16 @@ mod media_devices { device_id: ptr::NonNull, ) -> Dart_Handle; + /// Indicates whether it's possible to access microphone volume + /// settings. + pub fn microphone_volume_is_available() -> Dart_Handle; + + /// Returns the current microphone volume level in percents. + pub fn microphone_volume() -> Dart_Handle; + + /// Sets the microphone volume level in percents. + pub fn set_microphone_volume(level: i64) -> Dart_Handle; + /// Subscribes onto the `MediaDevices`'s `devicechange` event. pub fn on_device_change(cb: Dart_Handle); } @@ -186,6 +196,52 @@ impl MediaDevices { .map_err(tracerr::wrap!()) } + /// Indicates whether it's possible to access microphone volume settings. + pub async fn microphone_volume_is_available(&self) -> bool { + let result = unsafe { + FutureFromDart::execute::( + media_devices::microphone_volume_is_available(), + ) + .await + } + .unwrap(); + + result == 1 + } + + /// Returns the current microphone volume level in percents. + /// + /// # Errors + /// + /// If it the "Audio Device Module" is not initialized or there is no + /// connected audio input devices. + pub async fn microphone_volume(&self) -> Result> { + unsafe { + FutureFromDart::execute::(media_devices::microphone_volume()) + .await + } + .map_err(tracerr::wrap!()) + } + + /// Sets the microphone volume level in percents. + /// + /// # Errors + /// + /// If it the "Audio Device Module" is not initialized or there is no + /// connected audio input devices. + pub async fn set_microphone_volume( + &self, + level: i64, + ) -> Result<(), Traced> { + unsafe { + FutureFromDart::execute::<()>(media_devices::set_microphone_volume( + level, + )) + .await + } + .map_err(tracerr::wrap!()) + } + /// Subscribes onto the [`MediaDevices`]'s `devicechange` event. pub fn on_device_change(&self, handler: Option) where diff --git a/src/platform/wasm/media_devices.rs b/src/platform/wasm/media_devices.rs index f552c614e..8a034e1df 100644 --- a/src/platform/wasm/media_devices.rs +++ b/src/platform/wasm/media_devices.rs @@ -9,7 +9,7 @@ use tracerr::Traced; use web_sys::{Event, MediaDevices as SysMediaDevices}; use crate::{ - media::{InvalidOutputAudioDeviceIdError, MediaSourceKind}, + media::{InvalidOutputAudioDeviceIdError, MediaSourceKind, MicVolumeError}, platform::{ utils::EventListener, DisplayMediaStreamConstraints, Error, MediaDeviceInfo, MediaStreamConstraints, MediaStreamTrack, @@ -234,4 +234,50 @@ impl MediaDevices { ); } } + + /// Always returns `false` since accessing microphone cannot be implemented + /// on web platform. + #[allow(clippy::unused_async)] + pub async fn microphone_volume_is_available(&self) -> bool { + false + } + + /// This method should be unreachable, because cannot be implemented on web + /// platform. + /// + /// # Errors + /// + /// Never. + /// + /// # Panics + /// + /// Always. + #[allow(clippy::unused_async)] + pub async fn microphone_volume( + &self, + ) -> Result> { + unreachable!( + "`microphone_volume()` cannot be implemented on web platform", + ) + } + + /// This method should be unreachable, because cannot be implemented on web + /// platform. + /// + /// # Errors + /// + /// Never. + /// + /// # Panics + /// + /// Always. + #[allow(clippy::unused_async)] + pub async fn set_microphone_volume( + &self, + _: i64, + ) -> Result<(), Traced> { + unreachable!( + "`set_microphone_volume()` cannot be implemented on web platform", + ) + } }