Skip to content

Commit 77fbfcd

Browse files
authored
[video_player] Set audio mix options (flutter#2922)
1 parent 6f6b786 commit 77fbfcd

File tree

13 files changed

+166
-12
lines changed

13 files changed

+166
-12
lines changed

packages/video_player/video_player/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.10.12
2+
3+
* Introduce VideoPlayerOptions to set the audio mix mode.
4+
15
## 0.10.11+2
26

37
* Fix aspectRatio calculation when size.width or size.height are zero.

packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,31 @@ static PositionMessage fromMap(HashMap map) {
223223
}
224224
}
225225

226+
/** Generated class from Pigeon that represents data sent in messages. */
227+
public static class MixWithOthersMessage {
228+
private Boolean mixWithOthers;
229+
230+
public Boolean getMixWithOthers() {
231+
return mixWithOthers;
232+
}
233+
234+
public void setMixWithOthers(Boolean setterArg) {
235+
this.mixWithOthers = setterArg;
236+
}
237+
238+
HashMap toMap() {
239+
HashMap<String, Object> toMapResult = new HashMap<String, Object>();
240+
toMapResult.put("mixWithOthers", mixWithOthers);
241+
return toMapResult;
242+
}
243+
244+
static MixWithOthersMessage fromMap(HashMap map) {
245+
MixWithOthersMessage fromMapResult = new MixWithOthersMessage();
246+
fromMapResult.mixWithOthers = (Boolean) map.get("mixWithOthers");
247+
return fromMapResult;
248+
}
249+
}
250+
226251
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
227252
public interface VideoPlayerApi {
228253
void initialize();
@@ -243,6 +268,8 @@ public interface VideoPlayerApi {
243268

244269
void pause(TextureMessage arg);
245270

271+
void setMixWithOthers(MixWithOthersMessage arg);
272+
246273
/** Sets up an instance of `VideoPlayerApi` to handle messages through the `binaryMessenger` */
247274
public static void setup(BinaryMessenger binaryMessenger, VideoPlayerApi api) {
248275
{
@@ -469,6 +496,31 @@ public void onMessage(Object message, BasicMessageChannel.Reply<Object> reply) {
469496
channel.setMessageHandler(null);
470497
}
471498
}
499+
{
500+
BasicMessageChannel<Object> channel =
501+
new BasicMessageChannel<Object>(
502+
binaryMessenger,
503+
"dev.flutter.pigeon.VideoPlayerApi.setMixWithOthers",
504+
new StandardMessageCodec());
505+
if (api != null) {
506+
channel.setMessageHandler(
507+
new BasicMessageChannel.MessageHandler<Object>() {
508+
public void onMessage(Object message, BasicMessageChannel.Reply<Object> reply) {
509+
MixWithOthersMessage input = MixWithOthersMessage.fromMap((HashMap) message);
510+
HashMap<String, HashMap> wrapped = new HashMap<String, HashMap>();
511+
try {
512+
api.setMixWithOthers(input);
513+
wrapped.put("result", null);
514+
} catch (Exception exception) {
515+
wrapped.put("error", wrapError(exception));
516+
}
517+
reply.reply(wrapped);
518+
}
519+
});
520+
} else {
521+
channel.setMessageHandler(null);
522+
}
523+
}
472524
}
473525
}
474526

packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,18 @@ final class VideoPlayer {
5656

5757
private boolean isInitialized = false;
5858

59+
private final VideoPlayerOptions options;
60+
5961
VideoPlayer(
6062
Context context,
6163
EventChannel eventChannel,
6264
TextureRegistry.SurfaceTextureEntry textureEntry,
6365
String dataSource,
64-
String formatHint) {
66+
String formatHint,
67+
VideoPlayerOptions options) {
6568
this.eventChannel = eventChannel;
6669
this.textureEntry = textureEntry;
70+
this.options = options;
6771

6872
TrackSelector trackSelector = new DefaultTrackSelector();
6973
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
@@ -163,7 +167,7 @@ public void onCancel(Object o) {
163167

164168
surface = new Surface(textureEntry.surfaceTexture());
165169
exoPlayer.setVideoSurface(surface);
166-
setAudioAttributes(exoPlayer);
170+
setAudioAttributes(exoPlayer, options.mixWithOthers);
167171

168172
exoPlayer.addListener(
169173
new EventListener() {
@@ -203,10 +207,10 @@ void sendBufferingUpdate() {
203207
}
204208

205209
@SuppressWarnings("deprecation")
206-
private static void setAudioAttributes(SimpleExoPlayer exoPlayer) {
210+
private static void setAudioAttributes(SimpleExoPlayer exoPlayer, boolean isMixMode) {
207211
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
208212
exoPlayer.setAudioAttributes(
209-
new AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MOVIE).build());
213+
new AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MOVIE).build(), !isMixMode);
210214
} else {
211215
exoPlayer.setAudioStreamType(C.STREAM_TYPE_MUSIC);
212216
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.flutter.plugins.videoplayer;
2+
3+
class VideoPlayerOptions {
4+
public boolean mixWithOthers;
5+
}

packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.flutter.plugin.common.PluginRegistry.Registrar;
1414
import io.flutter.plugins.videoplayer.Messages.CreateMessage;
1515
import io.flutter.plugins.videoplayer.Messages.LoopingMessage;
16+
import io.flutter.plugins.videoplayer.Messages.MixWithOthersMessage;
1617
import io.flutter.plugins.videoplayer.Messages.PositionMessage;
1718
import io.flutter.plugins.videoplayer.Messages.TextureMessage;
1819
import io.flutter.plugins.videoplayer.Messages.VideoPlayerApi;
@@ -25,6 +26,7 @@ public class VideoPlayerPlugin implements FlutterPlugin, VideoPlayerApi {
2526
private static final String TAG = "VideoPlayerPlugin";
2627
private final LongSparseArray<VideoPlayer> videoPlayers = new LongSparseArray<>();
2728
private FlutterState flutterState;
29+
private VideoPlayerOptions options = new VideoPlayerOptions();
2830

2931
/** Register this with the v2 embedding for the plugin to respond to lifecycle callbacks. */
3032
public VideoPlayerPlugin() {}
@@ -113,7 +115,8 @@ public TextureMessage create(CreateMessage arg) {
113115
eventChannel,
114116
handle,
115117
"asset:///" + assetLookupKey,
116-
null);
118+
null,
119+
options);
117120
videoPlayers.put(handle.id(), player);
118121
} else {
119122
player =
@@ -122,7 +125,8 @@ public TextureMessage create(CreateMessage arg) {
122125
eventChannel,
123126
handle,
124127
arg.getUri(),
125-
arg.getFormatHint());
128+
arg.getFormatHint(),
129+
options);
126130
videoPlayers.put(handle.id(), player);
127131
}
128132

@@ -170,6 +174,11 @@ public void pause(TextureMessage arg) {
170174
player.pause();
171175
}
172176

177+
@Override
178+
public void setMixWithOthers(MixWithOthersMessage arg) {
179+
options.mixWithOthers = arg.getMixWithOthers();
180+
}
181+
173182
private interface KeyForAssetFn {
174183
String get(String asset);
175184
}

packages/video_player/video_player/example/lib/main.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
220220
_controller = VideoPlayerController.network(
221221
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
222222
closedCaptionFile: _loadCaptions(),
223+
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
223224
);
224225

225226
_controller.addListener(() {

packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,4 +560,15 @@ - (void)pause:(FLTTextureMessage*)input error:(FlutterError**)error {
560560
[player pause];
561561
}
562562

563+
- (void)setMixWithOthers:(FLTMixWithOthersMessage*)input
564+
error:(FlutterError* _Nullable __autoreleasing*)error {
565+
if ([input.mixWithOthers boolValue]) {
566+
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
567+
withOptions:AVAudioSessionCategoryOptionMixWithOthers
568+
error:nil];
569+
} else {
570+
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
571+
}
572+
}
573+
563574
@end

packages/video_player/video_player/ios/Classes/messages.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
1212
@class FLTLoopingMessage;
1313
@class FLTVolumeMessage;
1414
@class FLTPositionMessage;
15+
@class FLTMixWithOthersMessage;
1516

1617
@interface FLTTextureMessage : NSObject
1718
@property(nonatomic, strong, nullable) NSNumber *textureId;
@@ -39,6 +40,10 @@ NS_ASSUME_NONNULL_BEGIN
3940
@property(nonatomic, strong, nullable) NSNumber *position;
4041
@end
4142

43+
@interface FLTMixWithOthersMessage : NSObject
44+
@property(nonatomic, strong, nullable) NSNumber *mixWithOthers;
45+
@end
46+
4247
@protocol FLTVideoPlayerApi
4348
- (void)initialize:(FlutterError *_Nullable *_Nonnull)error;
4449
- (nullable FLTTextureMessage *)create:(FLTCreateMessage *)input
@@ -51,6 +56,8 @@ NS_ASSUME_NONNULL_BEGIN
5156
error:(FlutterError *_Nullable *_Nonnull)error;
5257
- (void)seekTo:(FLTPositionMessage *)input error:(FlutterError *_Nullable *_Nonnull)error;
5358
- (void)pause:(FLTTextureMessage *)input error:(FlutterError *_Nullable *_Nonnull)error;
59+
- (void)setMixWithOthers:(FLTMixWithOthersMessage *)input
60+
error:(FlutterError *_Nullable *_Nonnull)error;
5461
@end
5562

5663
extern void FLTVideoPlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger,

packages/video_player/video_player/ios/Classes/messages.m

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ @interface FLTPositionMessage ()
4040
+ (FLTPositionMessage *)fromMap:(NSDictionary *)dict;
4141
- (NSDictionary *)toMap;
4242
@end
43+
@interface FLTMixWithOthersMessage ()
44+
+ (FLTMixWithOthersMessage *)fromMap:(NSDictionary *)dict;
45+
- (NSDictionary *)toMap;
46+
@end
4347

4448
@implementation FLTTextureMessage
4549
+ (FLTTextureMessage *)fromMap:(NSDictionary *)dict {
@@ -154,6 +158,22 @@ - (NSDictionary *)toMap {
154158
}
155159
@end
156160

161+
@implementation FLTMixWithOthersMessage
162+
+ (FLTMixWithOthersMessage *)fromMap:(NSDictionary *)dict {
163+
FLTMixWithOthersMessage *result = [[FLTMixWithOthersMessage alloc] init];
164+
result.mixWithOthers = dict[@"mixWithOthers"];
165+
if ((NSNull *)result.mixWithOthers == [NSNull null]) {
166+
result.mixWithOthers = nil;
167+
}
168+
return result;
169+
}
170+
- (NSDictionary *)toMap {
171+
return [NSDictionary
172+
dictionaryWithObjectsAndKeys:(self.mixWithOthers != nil ? self.mixWithOthers : [NSNull null]),
173+
@"mixWithOthers", nil];
174+
}
175+
@end
176+
157177
void FLTVideoPlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, id<FLTVideoPlayerApi> api) {
158178
{
159179
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
@@ -289,4 +309,19 @@ void FLTVideoPlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, id<FLTVi
289309
[channel setMessageHandler:nil];
290310
}
291311
}
312+
{
313+
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
314+
messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.setMixWithOthers"
315+
binaryMessenger:binaryMessenger];
316+
if (api) {
317+
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
318+
FlutterError *error;
319+
FLTMixWithOthersMessage *input = [FLTMixWithOthersMessage fromMap:message];
320+
[api setMixWithOthers:input error:&error];
321+
callback(wrapResult(nil, error));
322+
}];
323+
} else {
324+
[channel setMessageHandler:nil];
325+
}
326+
}
292327
}

packages/video_player/video_player/lib/video_player.dart

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import 'package:meta/meta.dart';
1212

1313
import 'package:video_player_platform_interface/video_player_platform_interface.dart';
1414
export 'package:video_player_platform_interface/video_player_platform_interface.dart'
15-
show DurationRange, DataSourceType, VideoFormat;
15+
show DurationRange, DataSourceType, VideoFormat, VideoPlayerOptions;
1616

1717
import 'src/closed_caption_file.dart';
1818
export 'src/closed_caption_file.dart';
@@ -168,7 +168,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
168168
/// null. The [package] argument must be non-null when the asset comes from a
169169
/// package and null otherwise.
170170
VideoPlayerController.asset(this.dataSource,
171-
{this.package, this.closedCaptionFile})
171+
{this.package, this.closedCaptionFile, this.videoPlayerOptions})
172172
: dataSourceType = DataSourceType.asset,
173173
formatHint = null,
174174
super(VideoPlayerValue(duration: null));
@@ -181,7 +181,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
181181
/// **Android only**: The [formatHint] option allows the caller to override
182182
/// the video format detection code.
183183
VideoPlayerController.network(this.dataSource,
184-
{this.formatHint, this.closedCaptionFile})
184+
{this.formatHint, this.closedCaptionFile, this.videoPlayerOptions})
185185
: dataSourceType = DataSourceType.network,
186186
package = null,
187187
super(VideoPlayerValue(duration: null));
@@ -190,7 +190,8 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
190190
///
191191
/// This will load the file from the file-URI given by:
192192
/// `'file://${file.path}'`.
193-
VideoPlayerController.file(File file, {this.closedCaptionFile})
193+
VideoPlayerController.file(File file,
194+
{this.closedCaptionFile, this.videoPlayerOptions})
194195
: dataSource = 'file://${file.path}',
195196
dataSourceType = DataSourceType.file,
196197
package = null,
@@ -211,6 +212,9 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
211212
/// is constructed with.
212213
final DataSourceType dataSourceType;
213214

215+
/// Provide additional configuration options (optional). Like setting the audio mode to mix
216+
final VideoPlayerOptions videoPlayerOptions;
217+
214218
/// Only set for [asset] videos. The package that the asset was loaded from.
215219
final String package;
216220

@@ -262,6 +266,12 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
262266
);
263267
break;
264268
}
269+
270+
if (videoPlayerOptions?.mixWithOthers != null) {
271+
await _videoPlayerPlatform
272+
.setMixWithOthers(videoPlayerOptions.mixWithOthers);
273+
}
274+
265275
_textureId = await _videoPlayerPlatform.create(dataSourceDescription);
266276
_creatingCompleter.complete(null);
267277
final Completer<void> initializingCompleter = Completer<void>();

packages/video_player/video_player/pigeons/messages.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class CreateMessage {
2626
String formatHint;
2727
}
2828

29+
class MixWithOthersMessage {
30+
bool mixWithOthers;
31+
}
32+
2933
@HostApi()
3034
abstract class VideoPlayerApi {
3135
void initialize();
@@ -37,6 +41,7 @@ abstract class VideoPlayerApi {
3741
PositionMessage position(TextureMessage msg);
3842
void seekTo(PositionMessage msg);
3943
void pause(TextureMessage msg);
44+
void setMixWithOthers(MixWithOthersMessage msg);
4045
}
4146

4247
void configurePigeon(PigeonOptions opts) {

packages/video_player/video_player/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Flutter plugin for displaying inline video with other Flutter
44
# 0.10.y+z is compatible with 1.0.0, if you land a breaking change bump
55
# the version to 2.0.0.
66
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
7-
version: 0.10.11+2
7+
version: 0.10.12
88
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
99

1010
flutter:

0 commit comments

Comments
 (0)