From e8f44103511f63d37163e2683598feabe56c3b11 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 17 Aug 2020 19:34:49 -0700 Subject: [PATCH] Revert "Revert "[video_player] Set audio mix options (#2922)" (#2938)" This reverts commit d4750ea86657bf8b35f96c8f3d9bcd5a025d189b. --- .../video_player/video_player/CHANGELOG.md | 4 ++ .../flutter/plugins/videoplayer/Messages.java | 52 +++++++++++++++++++ .../plugins/videoplayer/VideoPlayer.java | 12 +++-- .../videoplayer/VideoPlayerOptions.java | 5 ++ .../videoplayer/VideoPlayerPlugin.java | 13 ++++- .../video_player/example/lib/main.dart | 1 + .../ios/Classes/FLTVideoPlayerPlugin.m | 11 ++++ .../video_player/ios/Classes/messages.h | 7 +++ .../video_player/ios/Classes/messages.m | 35 +++++++++++++ .../video_player/lib/video_player.dart | 18 +++++-- .../video_player/pigeons/messages.dart | 5 ++ .../video_player/video_player/pubspec.yaml | 2 +- .../video_player/test/video_player_test.dart | 13 ++++- 13 files changed, 166 insertions(+), 12 deletions(-) create mode 100644 packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index e3f49e736411..1fdfad6256f4 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.12 + +* Introduce VideoPlayerOptions to set the audio mix mode. + ## 0.10.11+2 * Fix aspectRatio calculation when size.width or size.height are zero. diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java index 7bba51b21f98..003ca18f23cb 100644 --- a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java @@ -223,6 +223,31 @@ static PositionMessage fromMap(HashMap map) { } } + /** Generated class from Pigeon that represents data sent in messages. */ + public static class MixWithOthersMessage { + private Boolean mixWithOthers; + + public Boolean getMixWithOthers() { + return mixWithOthers; + } + + public void setMixWithOthers(Boolean setterArg) { + this.mixWithOthers = setterArg; + } + + HashMap toMap() { + HashMap toMapResult = new HashMap(); + toMapResult.put("mixWithOthers", mixWithOthers); + return toMapResult; + } + + static MixWithOthersMessage fromMap(HashMap map) { + MixWithOthersMessage fromMapResult = new MixWithOthersMessage(); + fromMapResult.mixWithOthers = (Boolean) map.get("mixWithOthers"); + return fromMapResult; + } + } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface VideoPlayerApi { void initialize(); @@ -243,6 +268,8 @@ public interface VideoPlayerApi { void pause(TextureMessage arg); + void setMixWithOthers(MixWithOthersMessage arg); + /** Sets up an instance of `VideoPlayerApi` to handle messages through the `binaryMessenger` */ public static void setup(BinaryMessenger binaryMessenger, VideoPlayerApi api) { { @@ -469,6 +496,31 @@ public void onMessage(Object message, BasicMessageChannel.Reply reply) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.setMixWithOthers", + new StandardMessageCodec()); + if (api != null) { + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + MixWithOthersMessage input = MixWithOthersMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.setMixWithOthers(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } else { + channel.setMessageHandler(null); + } + } } } diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 9db281d38b86..801c2ca3bff2 100644 --- a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -56,14 +56,18 @@ final class VideoPlayer { private boolean isInitialized = false; + private final VideoPlayerOptions options; + VideoPlayer( Context context, EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry, String dataSource, - String formatHint) { + String formatHint, + VideoPlayerOptions options) { this.eventChannel = eventChannel; this.textureEntry = textureEntry; + this.options = options; TrackSelector trackSelector = new DefaultTrackSelector(); exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector); @@ -163,7 +167,7 @@ public void onCancel(Object o) { surface = new Surface(textureEntry.surfaceTexture()); exoPlayer.setVideoSurface(surface); - setAudioAttributes(exoPlayer); + setAudioAttributes(exoPlayer, options.mixWithOthers); exoPlayer.addListener( new EventListener() { @@ -203,10 +207,10 @@ void sendBufferingUpdate() { } @SuppressWarnings("deprecation") - private static void setAudioAttributes(SimpleExoPlayer exoPlayer) { + private static void setAudioAttributes(SimpleExoPlayer exoPlayer, boolean isMixMode) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { exoPlayer.setAudioAttributes( - new AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MOVIE).build()); + new AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MOVIE).build(), !isMixMode); } else { exoPlayer.setAudioStreamType(C.STREAM_TYPE_MUSIC); } diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java new file mode 100644 index 000000000000..7381f4a941a5 --- /dev/null +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java @@ -0,0 +1,5 @@ +package io.flutter.plugins.videoplayer; + +class VideoPlayerOptions { + public boolean mixWithOthers; +} diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index 3ec40e5fa2c4..a22a4f2d7ae4 100644 --- a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -13,6 +13,7 @@ import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugins.videoplayer.Messages.CreateMessage; import io.flutter.plugins.videoplayer.Messages.LoopingMessage; +import io.flutter.plugins.videoplayer.Messages.MixWithOthersMessage; import io.flutter.plugins.videoplayer.Messages.PositionMessage; import io.flutter.plugins.videoplayer.Messages.TextureMessage; import io.flutter.plugins.videoplayer.Messages.VideoPlayerApi; @@ -25,6 +26,7 @@ public class VideoPlayerPlugin implements FlutterPlugin, VideoPlayerApi { private static final String TAG = "VideoPlayerPlugin"; private final LongSparseArray videoPlayers = new LongSparseArray<>(); private FlutterState flutterState; + private VideoPlayerOptions options = new VideoPlayerOptions(); /** Register this with the v2 embedding for the plugin to respond to lifecycle callbacks. */ public VideoPlayerPlugin() {} @@ -113,7 +115,8 @@ public TextureMessage create(CreateMessage arg) { eventChannel, handle, "asset:///" + assetLookupKey, - null); + null, + options); videoPlayers.put(handle.id(), player); } else { player = @@ -122,7 +125,8 @@ public TextureMessage create(CreateMessage arg) { eventChannel, handle, arg.getUri(), - arg.getFormatHint()); + arg.getFormatHint(), + options); videoPlayers.put(handle.id(), player); } @@ -170,6 +174,11 @@ public void pause(TextureMessage arg) { player.pause(); } + @Override + public void setMixWithOthers(MixWithOthersMessage arg) { + options.mixWithOthers = arg.getMixWithOthers(); + } + private interface KeyForAssetFn { String get(String asset); } diff --git a/packages/video_player/video_player/example/lib/main.dart b/packages/video_player/video_player/example/lib/main.dart index bfe81b9056fb..ee2fcbdc9632 100644 --- a/packages/video_player/video_player/example/lib/main.dart +++ b/packages/video_player/video_player/example/lib/main.dart @@ -220,6 +220,7 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> { _controller = VideoPlayerController.network( 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', closedCaptionFile: _loadCaptions(), + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), ); _controller.addListener(() { diff --git a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m index 7dbc1b0bfd11..a834fe32b87b 100644 --- a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m @@ -560,4 +560,15 @@ - (void)pause:(FLTTextureMessage*)input error:(FlutterError**)error { [player pause]; } +- (void)setMixWithOthers:(FLTMixWithOthersMessage*)input + error:(FlutterError* _Nullable __autoreleasing*)error { + if ([input.mixWithOthers boolValue]) { + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback + withOptions:AVAudioSessionCategoryOptionMixWithOthers + error:nil]; + } else { + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; + } +} + @end diff --git a/packages/video_player/video_player/ios/Classes/messages.h b/packages/video_player/video_player/ios/Classes/messages.h index 3c89b1f203d1..27025ef27413 100644 --- a/packages/video_player/video_player/ios/Classes/messages.h +++ b/packages/video_player/video_player/ios/Classes/messages.h @@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @class FLTLoopingMessage; @class FLTVolumeMessage; @class FLTPositionMessage; +@class FLTMixWithOthersMessage; @interface FLTTextureMessage : NSObject @property(nonatomic, strong, nullable) NSNumber *textureId; @@ -39,6 +40,10 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong, nullable) NSNumber *position; @end +@interface FLTMixWithOthersMessage : NSObject +@property(nonatomic, strong, nullable) NSNumber *mixWithOthers; +@end + @protocol FLTVideoPlayerApi - (void)initialize:(FlutterError *_Nullable *_Nonnull)error; - (nullable FLTTextureMessage *)create:(FLTCreateMessage *)input @@ -51,6 +56,8 @@ NS_ASSUME_NONNULL_BEGIN error:(FlutterError *_Nullable *_Nonnull)error; - (void)seekTo:(FLTPositionMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; - (void)pause:(FLTTextureMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setMixWithOthers:(FLTMixWithOthersMessage *)input + error:(FlutterError *_Nullable *_Nonnull)error; @end extern void FLTVideoPlayerApiSetup(id binaryMessenger, diff --git a/packages/video_player/video_player/ios/Classes/messages.m b/packages/video_player/video_player/ios/Classes/messages.m index 3694a11622dc..64fcd75cc6bf 100644 --- a/packages/video_player/video_player/ios/Classes/messages.m +++ b/packages/video_player/video_player/ios/Classes/messages.m @@ -40,6 +40,10 @@ @interface FLTPositionMessage () + (FLTPositionMessage *)fromMap:(NSDictionary *)dict; - (NSDictionary *)toMap; @end +@interface FLTMixWithOthersMessage () ++ (FLTMixWithOthersMessage *)fromMap:(NSDictionary *)dict; +- (NSDictionary *)toMap; +@end @implementation FLTTextureMessage + (FLTTextureMessage *)fromMap:(NSDictionary *)dict { @@ -154,6 +158,22 @@ - (NSDictionary *)toMap { } @end +@implementation FLTMixWithOthersMessage ++ (FLTMixWithOthersMessage *)fromMap:(NSDictionary *)dict { + FLTMixWithOthersMessage *result = [[FLTMixWithOthersMessage alloc] init]; + result.mixWithOthers = dict[@"mixWithOthers"]; + if ((NSNull *)result.mixWithOthers == [NSNull null]) { + result.mixWithOthers = nil; + } + return result; +} +- (NSDictionary *)toMap { + return [NSDictionary + dictionaryWithObjectsAndKeys:(self.mixWithOthers != nil ? self.mixWithOthers : [NSNull null]), + @"mixWithOthers", nil]; +} +@end + void FLTVideoPlayerApiSetup(id binaryMessenger, id api) { { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel @@ -289,4 +309,19 @@ void FLTVideoPlayerApiSetup(id binaryMessenger, id { /// null. The [package] argument must be non-null when the asset comes from a /// package and null otherwise. VideoPlayerController.asset(this.dataSource, - {this.package, this.closedCaptionFile}) + {this.package, this.closedCaptionFile, this.videoPlayerOptions}) : dataSourceType = DataSourceType.asset, formatHint = null, super(VideoPlayerValue(duration: null)); @@ -181,7 +181,7 @@ class VideoPlayerController extends ValueNotifier { /// **Android only**: The [formatHint] option allows the caller to override /// the video format detection code. VideoPlayerController.network(this.dataSource, - {this.formatHint, this.closedCaptionFile}) + {this.formatHint, this.closedCaptionFile, this.videoPlayerOptions}) : dataSourceType = DataSourceType.network, package = null, super(VideoPlayerValue(duration: null)); @@ -190,7 +190,8 @@ class VideoPlayerController extends ValueNotifier { /// /// This will load the file from the file-URI given by: /// `'file://${file.path}'`. - VideoPlayerController.file(File file, {this.closedCaptionFile}) + VideoPlayerController.file(File file, + {this.closedCaptionFile, this.videoPlayerOptions}) : dataSource = 'file://${file.path}', dataSourceType = DataSourceType.file, package = null, @@ -211,6 +212,9 @@ class VideoPlayerController extends ValueNotifier { /// is constructed with. final DataSourceType dataSourceType; + /// Provide additional configuration options (optional). Like setting the audio mode to mix + final VideoPlayerOptions videoPlayerOptions; + /// Only set for [asset] videos. The package that the asset was loaded from. final String package; @@ -262,6 +266,12 @@ class VideoPlayerController extends ValueNotifier { ); break; } + + if (videoPlayerOptions?.mixWithOthers != null) { + await _videoPlayerPlatform + .setMixWithOthers(videoPlayerOptions.mixWithOthers); + } + _textureId = await _videoPlayerPlatform.create(dataSourceDescription); _creatingCompleter.complete(null); final Completer initializingCompleter = Completer(); diff --git a/packages/video_player/video_player/pigeons/messages.dart b/packages/video_player/video_player/pigeons/messages.dart index 2df5b78f13f8..074eef023b94 100644 --- a/packages/video_player/video_player/pigeons/messages.dart +++ b/packages/video_player/video_player/pigeons/messages.dart @@ -26,6 +26,10 @@ class CreateMessage { String formatHint; } +class MixWithOthersMessage { + bool mixWithOthers; +} + @HostApi() abstract class VideoPlayerApi { void initialize(); @@ -37,6 +41,7 @@ abstract class VideoPlayerApi { PositionMessage position(TextureMessage msg); void seekTo(PositionMessage msg); void pause(TextureMessage msg); + void setMixWithOthers(MixWithOthersMessage msg); } void configurePigeon(PigeonOptions opts) { diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index 03f71bf4f412..a62f6f09a202 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for displaying inline video with other Flutter # 0.10.y+z is compatible with 1.0.0, if you land a breaking change bump # the version to 2.0.0. # See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0 -version: 0.10.11+2 +version: 0.10.12 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player flutter: diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index ae236def4e57..67722594989c 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -10,8 +10,8 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:video_player/video_player.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:video_player_platform_interface/video_player_platform_interface.dart'; import 'package:video_player_platform_interface/messages.dart'; +import 'package:video_player_platform_interface/video_player_platform_interface.dart'; class FakeController extends ValueNotifier implements VideoPlayerController { @@ -52,6 +52,9 @@ class FakeController extends ValueNotifier @override Future get closedCaptionFile => _loadClosedCaption(); + + @override + VideoPlayerOptions get videoPlayerOptions => null; } Future _loadClosedCaption() async => @@ -575,6 +578,14 @@ void main() { expect(colors.bufferedColor, bufferedColor); expect(colors.backgroundColor, backgroundColor); }); + + test('setMixWithOthers', () { + final VideoPlayerController controller = VideoPlayerController.file( + File(''), + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true)); + controller.initialize(); + expect(controller.videoPlayerOptions.mixWithOthers, true); + }); } class FakeVideoPlayerPlatform extends VideoPlayerApiTest {