Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[video_player] Add option to set video audio to mix mode in iOS #1174

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/video_player/video_player/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.10.6

* Introduce VideoPlayerOptions to set the audio mix mode.

## 0.10.5

* Support `web` by default.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,19 @@ final class VideoPlayer {

private boolean isInitialized = false;

private final VideoPlayerOptions options;

VideoPlayer(
Context context,
EventChannel eventChannel,
TextureRegistry.SurfaceTextureEntry textureEntry,
String dataSource,
Result result,
String formatHint) {
String formatHint,
VideoPlayerOptions options) {
this.eventChannel = eventChannel;
this.textureEntry = textureEntry;
this.options = options;

TrackSelector trackSelector = new DefaultTrackSelector();
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
Expand Down Expand Up @@ -165,7 +169,7 @@ public void onCancel(Object o) {

surface = new Surface(textureEntry.surfaceTexture());
exoPlayer.setVideoSurface(surface);
setAudioAttributes(exoPlayer);
setAudioAttributes(exoPlayer, options.mixWithOthers);

exoPlayer.addListener(
new EventListener() {
Expand Down Expand Up @@ -209,10 +213,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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.flutter.plugins.videoplayer;

public class VideoPlayerOptions {
public boolean mixWithOthers;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class VideoPlayerPlugin implements MethodCallHandler, FlutterPlugin {
private static final String TAG = "VideoPlayerPlugin";
private final LongSparseArray<VideoPlayer> 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() {}
Expand Down Expand Up @@ -95,6 +96,10 @@ public void onMethodCall(MethodCall call, Result result) {
case "init":
disposeAllPlayers();
break;
case "setMixWithOthers":
options.mixWithOthers = (boolean) call.arguments;
result.success(null);
break;
case "create":
{
TextureRegistry.SurfaceTextureEntry handle =
Expand All @@ -120,7 +125,8 @@ public void onMethodCall(MethodCall call, Result result) {
handle,
"asset:///" + assetLookupKey,
result,
null);
null,
options);
videoPlayers.put(handle.id(), player);
} else {
player =
Expand All @@ -130,7 +136,8 @@ public void onMethodCall(MethodCall call, Result result) {
handle,
call.argument("uri"),
result,
call.argument("formatHint"));
call.argument("formatHint"),
options);
videoPlayers.put(handle.id(), player);
}
break;
Expand Down
3 changes: 2 additions & 1 deletion packages/video_player/video_player/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ abstract class _PlayerLifeCycleState extends State<PlayerLifeCycle> {
class _NetworkPlayerLifeCycleState extends _PlayerLifeCycleState {
@override
VideoPlayerController createVideoPlayerController() {
return VideoPlayerController.network(widget.dataSource);
return VideoPlayerController.network(widget.dataSource,
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,16 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
}
[_players removeAllObjects];
result(nil);
} else if ([@"setMixWithOthers" isEqualToString:call.method]) {
BOOL mixWithOthers = [call.arguments boolValue];
if (mixWithOthers) {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:nil];
} else {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
}
result(nil);
} else if ([@"create" isEqualToString:call.method]) {
NSDictionary* argsMap = call.arguments;
FLTFrameUpdater* frameUpdater = [[FLTFrameUpdater alloc] initWithRegistry:_registry];
Expand Down
18 changes: 14 additions & 4 deletions packages/video_player/video_player/lib/video_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'package:meta/meta.dart';

import 'package:video_player_platform_interface/video_player_platform_interface.dart';
export 'package:video_player_platform_interface/video_player_platform_interface.dart'
show DurationRange, DataSourceType, VideoFormat;
show DurationRange, DataSourceType, VideoFormat, VideoPlayerOptions;

// This will clear all open videos on the platform when a full restart is
// performed.
Expand Down Expand Up @@ -145,7 +145,8 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
/// The name of the asset is given by the [dataSource] argument and must not be
/// null. The [package] argument must be non-null when the asset comes from a
/// package and null otherwise.
VideoPlayerController.asset(this.dataSource, {this.package})
VideoPlayerController.asset(this.dataSource,
{this.package, this.videoPlayerOptions})
: dataSourceType = DataSourceType.asset,
formatHint = null,
super(VideoPlayerValue(duration: null));
Expand All @@ -157,7 +158,8 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
/// null.
/// **Android only**: The [formatHint] option allows the caller to override
/// the video format detection code.
VideoPlayerController.network(this.dataSource, {this.formatHint})
VideoPlayerController.network(this.dataSource,
{this.formatHint, this.videoPlayerOptions})
: dataSourceType = DataSourceType.network,
package = null,
super(VideoPlayerValue(duration: null));
Expand All @@ -166,7 +168,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
///
/// This will load the file from the file-URI given by:
/// `'file://${file.path}'`.
VideoPlayerController.file(File file)
VideoPlayerController.file(File file, {this.videoPlayerOptions})
: dataSource = 'file://${file.path}',
dataSourceType = DataSourceType.file,
package = null,
Expand All @@ -187,6 +189,9 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
/// 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;
Timer _timer;
Expand Down Expand Up @@ -229,6 +234,11 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
);
break;
}
if (videoPlayerOptions?.mixWithOthers != null) {
await VideoPlayerPlatform.instance
.setMixWithOthers(videoPlayerOptions.mixWithOthers);
}

_textureId =
await VideoPlayerPlatform.instance.create(dataSourceDescription);
_creatingCompleter.complete(null);
Expand Down
4 changes: 2 additions & 2 deletions packages/video_player/video_player/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: video_player
description: Flutter plugin for displaying inline video with other Flutter
widgets on Android and iOS.
version: 0.10.5
version: 0.10.6
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player

flutter:
Expand All @@ -17,7 +17,7 @@ flutter:

dependencies:
meta: "^1.0.5"
video_player_platform_interface: ^1.0.1
video_player_platform_interface: ^1.0.5
# The design on https://flutter.dev/go/federated-plugins was to leave
# this constraint as "any". We cannot do it right now as it fails pub publish
# validation, so we set a ^ constraint.
Expand Down
24 changes: 24 additions & 0 deletions packages/video_player/video_player/test/video_player_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class FakeController extends ValueNotifier<VideoPlayerValue>

@override
VideoFormat get formatHint => null;

@override
VideoPlayerOptions get videoPlayerOptions => null;
}

void main() {
Expand Down Expand Up @@ -424,6 +427,27 @@ void main() {
expect(colors.bufferedColor, bufferedColor);
expect(colors.backgroundColor, backgroundColor);
});

test('setMixWithOthers', () {
bool mixWithOthers = false;
const MethodChannel('flutter.io/videoPlayer')
.setMockMethodCallHandler((MethodCall methodCall) async {
switch (methodCall.method) {
case 'setMixWithOthers':
return mixWithOthers = methodCall.arguments;
case 'create':
return <String, dynamic>{'textureId': 100};
default:
return null;
}
});

final VideoPlayerController controller = VideoPlayerController.file(
File(''),
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true));
controller.initialize();
expect(mixWithOthers, true);
});
}

class FakeVideoPlayerPlatform {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.5

* Add VideoPlayerOptions with audo mix mode

## 1.0.4

* Remove the deprecated `author:` field from pubspec.yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ class MethodChannelVideoPlayer extends VideoPlayerPlatform {
return Texture(textureId: textureId);
}

@override
Future<void> setMixWithOthers(bool mixWithOthers) {
return _channel.invokeMethod('setMixWithOthers', mixWithOthers);
}

EventChannel _eventChannelFor(int textureId) {
return EventChannel('flutter.io/videoPlayer/videoEvents$textureId');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ abstract class VideoPlayerPlatform {
throw UnimplementedError('buildView() has not been implemented.');
}

/// Sets the audio mode to mix with other sources
Future<void> setMixWithOthers(bool mixWithOthers) {
throw UnimplementedError('setMixWithOthers() has not been implemented.');
}

// This method makes sure that VideoPlayer isn't implemented with `implements`.
//
// See class doc for more details on why implementing this class is forbidden.
Expand Down Expand Up @@ -331,3 +336,13 @@ class DurationRange {
@override
int get hashCode => start.hashCode ^ end.hashCode;
}

/// [VideoPlayerOptions] can be optionally used to set additional player settings
class VideoPlayerOptions {
/// Set this to true to mix the video players audio with other audio sources.
/// The default value is false
final bool mixWithOthers;

/// set additional optional player settings
VideoPlayerOptions({this.mixWithOthers = false});
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: A common platform interface for the video_player plugin.
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player_platform_interface
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 1.0.4
version: 1.0.5

dependencies:
flutter:
Expand Down