From c65bdd07002bb154ae2d75588ad3fbfd7c800e2f Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Thu, 7 May 2020 22:52:09 -0700 Subject: [PATCH] [video_player] upgraded video_player to use pigeon (#2544) --- .../video_player/video_player/CHANGELOG.md | 4 + .../flutter/plugins/videoplayer/Messages.java | 446 ++++++++++++++++++ .../plugins/videoplayer/VideoPlayer.java | 10 +- .../videoplayer/VideoPlayerPlugin.java | 206 ++++---- .../ios/Classes/FLTVideoPlayerPlugin.m | 172 +++---- .../video_player/ios/Classes/messages.h | 59 +++ .../video_player/ios/Classes/messages.m | 292 ++++++++++++ .../video_player/pigeons/messages.dart | 50 ++ .../video_player/video_player/pubspec.yaml | 7 +- .../video_player_initialization_test.dart | 2 +- .../video_player/test/video_player_test.dart | 139 +++--- 11 files changed, 1112 insertions(+), 275 deletions(-) create mode 100644 packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java create mode 100644 packages/video_player/video_player/ios/Classes/messages.h create mode 100644 packages/video_player/video_player/ios/Classes/messages.m create mode 100644 packages/video_player/video_player/pigeons/messages.dart diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index 075f8f4745c1..128d05b065d6 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.10 + +* Migrated to [pigeon](https://pub.dev/packages/pigeon). + ## 0.10.9+2 * Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). 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 new file mode 100644 index 000000000000..894fb0bde71a --- /dev/null +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/Messages.java @@ -0,0 +1,446 @@ +// Autogenerated from Pigeon (v0.1.0-experimental.10), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package io.flutter.plugins.videoplayer; + +import io.flutter.plugin.common.BasicMessageChannel; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.StandardMessageCodec; +import java.util.HashMap; + +/** Generated class from Pigeon. */ +public class Messages { + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class TextureMessage { + private Long textureId; + + public Long getTextureId() { + return textureId; + } + + public void setTextureId(Long setterArg) { + this.textureId = setterArg; + } + + HashMap toMap() { + HashMap toMapResult = new HashMap(); + toMapResult.put("textureId", textureId); + return toMapResult; + } + + static TextureMessage fromMap(HashMap map) { + TextureMessage fromMapResult = new TextureMessage(); + fromMapResult.textureId = + (map.get("textureId") instanceof Integer) + ? (Integer) map.get("textureId") + : (Long) map.get("textureId"); + return fromMapResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class CreateMessage { + private String asset; + + public String getAsset() { + return asset; + } + + public void setAsset(String setterArg) { + this.asset = setterArg; + } + + private String uri; + + public String getUri() { + return uri; + } + + public void setUri(String setterArg) { + this.uri = setterArg; + } + + private String packageName; + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String setterArg) { + this.packageName = setterArg; + } + + private String formatHint; + + public String getFormatHint() { + return formatHint; + } + + public void setFormatHint(String setterArg) { + this.formatHint = setterArg; + } + + HashMap toMap() { + HashMap toMapResult = new HashMap(); + toMapResult.put("asset", asset); + toMapResult.put("uri", uri); + toMapResult.put("packageName", packageName); + toMapResult.put("formatHint", formatHint); + return toMapResult; + } + + static CreateMessage fromMap(HashMap map) { + CreateMessage fromMapResult = new CreateMessage(); + fromMapResult.asset = (String) map.get("asset"); + fromMapResult.uri = (String) map.get("uri"); + fromMapResult.packageName = (String) map.get("packageName"); + fromMapResult.formatHint = (String) map.get("formatHint"); + return fromMapResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class LoopingMessage { + private Long textureId; + + public Long getTextureId() { + return textureId; + } + + public void setTextureId(Long setterArg) { + this.textureId = setterArg; + } + + private Boolean isLooping; + + public Boolean getIsLooping() { + return isLooping; + } + + public void setIsLooping(Boolean setterArg) { + this.isLooping = setterArg; + } + + HashMap toMap() { + HashMap toMapResult = new HashMap(); + toMapResult.put("textureId", textureId); + toMapResult.put("isLooping", isLooping); + return toMapResult; + } + + static LoopingMessage fromMap(HashMap map) { + LoopingMessage fromMapResult = new LoopingMessage(); + fromMapResult.textureId = + (map.get("textureId") instanceof Integer) + ? (Integer) map.get("textureId") + : (Long) map.get("textureId"); + fromMapResult.isLooping = (Boolean) map.get("isLooping"); + return fromMapResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class VolumeMessage { + private Long textureId; + + public Long getTextureId() { + return textureId; + } + + public void setTextureId(Long setterArg) { + this.textureId = setterArg; + } + + private Double volume; + + public Double getVolume() { + return volume; + } + + public void setVolume(Double setterArg) { + this.volume = setterArg; + } + + HashMap toMap() { + HashMap toMapResult = new HashMap(); + toMapResult.put("textureId", textureId); + toMapResult.put("volume", volume); + return toMapResult; + } + + static VolumeMessage fromMap(HashMap map) { + VolumeMessage fromMapResult = new VolumeMessage(); + fromMapResult.textureId = + (map.get("textureId") instanceof Integer) + ? (Integer) map.get("textureId") + : (Long) map.get("textureId"); + fromMapResult.volume = (Double) map.get("volume"); + return fromMapResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class PositionMessage { + private Long textureId; + + public Long getTextureId() { + return textureId; + } + + public void setTextureId(Long setterArg) { + this.textureId = setterArg; + } + + private Long position; + + public Long getPosition() { + return position; + } + + public void setPosition(Long setterArg) { + this.position = setterArg; + } + + HashMap toMap() { + HashMap toMapResult = new HashMap(); + toMapResult.put("textureId", textureId); + toMapResult.put("position", position); + return toMapResult; + } + + static PositionMessage fromMap(HashMap map) { + PositionMessage fromMapResult = new PositionMessage(); + fromMapResult.textureId = + (map.get("textureId") instanceof Integer) + ? (Integer) map.get("textureId") + : (Long) map.get("textureId"); + fromMapResult.position = + (map.get("position") instanceof Integer) + ? (Integer) map.get("position") + : (Long) map.get("position"); + return fromMapResult; + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface VideoPlayerApi { + void initialize(); + + TextureMessage create(CreateMessage arg); + + void dispose(TextureMessage arg); + + void setLooping(LoopingMessage arg); + + void setVolume(VolumeMessage arg); + + void play(TextureMessage arg); + + PositionMessage position(TextureMessage arg); + + void seekTo(PositionMessage arg); + + void pause(TextureMessage arg); + + /** Sets up an instance of `VideoPlayerApi` to handle messages through the `binaryMessenger` */ + public static void setup(BinaryMessenger binaryMessenger, VideoPlayerApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.initialize", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + HashMap wrapped = new HashMap(); + try { + api.initialize(); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.create", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + CreateMessage input = CreateMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + TextureMessage output = api.create(input); + wrapped.put("result", output.toMap()); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.dispose", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + TextureMessage input = TextureMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.dispose(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.setLooping", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + LoopingMessage input = LoopingMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.setLooping(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.setVolume", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + VolumeMessage input = VolumeMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.setVolume(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.play", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + TextureMessage input = TextureMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.play(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.position", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + TextureMessage input = TextureMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + PositionMessage output = api.position(input); + wrapped.put("result", output.toMap()); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.seekTo", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + PositionMessage input = PositionMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.seekTo(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + { + BasicMessageChannel channel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.VideoPlayerApi.pause", + new StandardMessageCodec()); + channel.setMessageHandler( + new BasicMessageChannel.MessageHandler() { + public void onMessage(Object message, BasicMessageChannel.Reply reply) { + TextureMessage input = TextureMessage.fromMap((HashMap) message); + HashMap wrapped = new HashMap(); + try { + api.pause(input); + wrapped.put("result", null); + } catch (Exception exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + } + }); + } + } + } + + private static HashMap wrapError(Exception exception) { + HashMap errorMap = new HashMap(); + errorMap.put("message", exception.toString()); + errorMap.put("code", null); + errorMap.put("details", null); + return errorMap; + } +} 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 43123ef09238..9db281d38b86 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 @@ -31,7 +31,6 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; import com.google.android.exoplayer2.util.Util; import io.flutter.plugin.common.EventChannel; -import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.view.TextureRegistry; import java.util.Arrays; import java.util.Collections; @@ -62,7 +61,6 @@ final class VideoPlayer { EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry, String dataSource, - Result result, String formatHint) { this.eventChannel = eventChannel; this.textureEntry = textureEntry; @@ -88,7 +86,7 @@ final class VideoPlayer { MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint, context); exoPlayer.prepare(mediaSource); - setupVideoPlayer(eventChannel, textureEntry, result); + setupVideoPlayer(eventChannel, textureEntry); } private static boolean isHTTP(Uri uri) { @@ -148,7 +146,7 @@ private MediaSource buildMediaSource( } private void setupVideoPlayer( - EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry, Result result) { + EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry) { eventChannel.setStreamHandler( new EventChannel.StreamHandler() { @@ -193,10 +191,6 @@ public void onPlayerError(final ExoPlaybackException error) { } } }); - - Map reply = new HashMap<>(); - reply.put("textureId", textureEntry.id()); - result.success(reply); } void sendBufferingUpdate() { 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 57707029f1f2..3ec40e5fa2c4 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 @@ -10,16 +10,18 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; 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.PositionMessage; +import io.flutter.plugins.videoplayer.Messages.TextureMessage; +import io.flutter.plugins.videoplayer.Messages.VideoPlayerApi; +import io.flutter.plugins.videoplayer.Messages.VolumeMessage; import io.flutter.view.FlutterMain; import io.flutter.view.TextureRegistry; /** Android platform implementation of the VideoPlayerPlugin. */ -public class VideoPlayerPlugin implements MethodCallHandler, FlutterPlugin { +public class VideoPlayerPlugin implements FlutterPlugin, VideoPlayerApi { private static final String TAG = "VideoPlayerPlugin"; private final LongSparseArray videoPlayers = new LongSparseArray<>(); private FlutterState flutterState; @@ -35,7 +37,7 @@ private VideoPlayerPlugin(Registrar registrar) { registrar::lookupKeyForAsset, registrar::lookupKeyForAsset, registrar.textures()); - flutterState.startListening(this); + flutterState.startListening(this, registrar.messenger()); } /** Registers this with the stable v1 embedding. Will not respond to lifecycle events. */ @@ -57,7 +59,7 @@ public void onAttachedToEngine(FlutterPluginBinding binding) { FlutterMain::getLookupKeyForAsset, FlutterMain::getLookupKeyForAsset, binding.getFlutterEngine().getRenderer()); - flutterState.startListening(this); + flutterState.startListening(this, binding.getBinaryMessenger()); } @Override @@ -65,7 +67,7 @@ public void onDetachedFromEngine(FlutterPluginBinding binding) { if (flutterState == null) { Log.wtf(TAG, "Detached from the engine before registering to it."); } - flutterState.stopListening(); + flutterState.stopListening(binding.getBinaryMessenger()); flutterState = null; } @@ -85,109 +87,87 @@ private void onDestroy() { disposeAllPlayers(); } - @Override - public void onMethodCall(MethodCall call, Result result) { - if (flutterState == null || flutterState.textureRegistry == null) { - result.error("no_activity", "video_player plugin requires a foreground activity", null); - return; - } - switch (call.method) { - case "init": - disposeAllPlayers(); - break; - case "create": - { - TextureRegistry.SurfaceTextureEntry handle = - flutterState.textureRegistry.createSurfaceTexture(); - EventChannel eventChannel = - new EventChannel( - flutterState.binaryMessenger, "flutter.io/videoPlayer/videoEvents" + handle.id()); - - VideoPlayer player; - if (call.argument("asset") != null) { - String assetLookupKey; - if (call.argument("package") != null) { - assetLookupKey = - flutterState.keyForAssetAndPackageName.get( - call.argument("asset"), call.argument("package")); - } else { - assetLookupKey = flutterState.keyForAsset.get(call.argument("asset")); - } - player = - new VideoPlayer( - flutterState.applicationContext, - eventChannel, - handle, - "asset:///" + assetLookupKey, - result, - null); - videoPlayers.put(handle.id(), player); - } else { - player = - new VideoPlayer( - flutterState.applicationContext, - eventChannel, - handle, - call.argument("uri"), - result, - call.argument("formatHint")); - videoPlayers.put(handle.id(), player); - } - break; - } - default: - { - long textureId = ((Number) call.argument("textureId")).longValue(); - VideoPlayer player = videoPlayers.get(textureId); - if (player == null) { - result.error( - "Unknown textureId", - "No video player associated with texture id " + textureId, - null); - return; - } - onMethodCall(call, result, textureId, player); - break; - } - } + public void initialize() { + disposeAllPlayers(); } - private void onMethodCall(MethodCall call, Result result, long textureId, VideoPlayer player) { - switch (call.method) { - case "setLooping": - player.setLooping(call.argument("looping")); - result.success(null); - break; - case "setVolume": - player.setVolume(call.argument("volume")); - result.success(null); - break; - case "play": - player.play(); - result.success(null); - break; - case "pause": - player.pause(); - result.success(null); - break; - case "seekTo": - int location = ((Number) call.argument("location")).intValue(); - player.seekTo(location); - result.success(null); - break; - case "position": - result.success(player.getPosition()); - player.sendBufferingUpdate(); - break; - case "dispose": - player.dispose(); - videoPlayers.remove(textureId); - result.success(null); - break; - default: - result.notImplemented(); - break; + public TextureMessage create(CreateMessage arg) { + TextureRegistry.SurfaceTextureEntry handle = + flutterState.textureRegistry.createSurfaceTexture(); + EventChannel eventChannel = + new EventChannel( + flutterState.binaryMessenger, "flutter.io/videoPlayer/videoEvents" + handle.id()); + + VideoPlayer player; + if (arg.getAsset() != null) { + String assetLookupKey; + if (arg.getPackageName() != null) { + assetLookupKey = + flutterState.keyForAssetAndPackageName.get(arg.getAsset(), arg.getPackageName()); + } else { + assetLookupKey = flutterState.keyForAsset.get(arg.getAsset()); + } + player = + new VideoPlayer( + flutterState.applicationContext, + eventChannel, + handle, + "asset:///" + assetLookupKey, + null); + videoPlayers.put(handle.id(), player); + } else { + player = + new VideoPlayer( + flutterState.applicationContext, + eventChannel, + handle, + arg.getUri(), + arg.getFormatHint()); + videoPlayers.put(handle.id(), player); } + + TextureMessage result = new TextureMessage(); + result.setTextureId(handle.id()); + return result; + } + + public void dispose(TextureMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + player.dispose(); + videoPlayers.remove(arg.getTextureId()); + } + + public void setLooping(LoopingMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + player.setLooping(arg.getIsLooping()); + } + + public void setVolume(VolumeMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + player.setVolume(arg.getVolume()); + } + + public void play(TextureMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + player.play(); + } + + public PositionMessage position(TextureMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + PositionMessage result = new PositionMessage(); + result.setPosition(player.getPosition()); + player.sendBufferingUpdate(); + return result; + } + + public void seekTo(PositionMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + player.seekTo(arg.getPosition().intValue()); + } + + public void pause(TextureMessage arg) { + VideoPlayer player = videoPlayers.get(arg.getTextureId()); + player.pause(); } private interface KeyForAssetFn { @@ -204,7 +184,6 @@ private static final class FlutterState { private final KeyForAssetFn keyForAsset; private final KeyForAssetAndPackageName keyForAssetAndPackageName; private final TextureRegistry textureRegistry; - private final MethodChannel methodChannel; FlutterState( Context applicationContext, @@ -217,15 +196,14 @@ private static final class FlutterState { this.keyForAsset = keyForAsset; this.keyForAssetAndPackageName = keyForAssetAndPackageName; this.textureRegistry = textureRegistry; - methodChannel = new MethodChannel(messenger, "flutter.io/videoPlayer"); } - void startListening(VideoPlayerPlugin methodCallHandler) { - methodChannel.setMethodCallHandler(methodCallHandler); + void startListening(VideoPlayerPlugin methodCallHandler, BinaryMessenger messenger) { + VideoPlayerApi.setup(messenger, methodCallHandler); } - void stopListening() { - methodChannel.setMethodCallHandler(null); + void stopListening(BinaryMessenger messenger) { + VideoPlayerApi.setup(messenger, null); } } } diff --git a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m index 39313fa18496..0917e8ef303b 100644 --- a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m @@ -5,6 +5,7 @@ #import "FLTVideoPlayerPlugin.h" #import #import +#import "messages.h" #if !__has_feature(objc_arc) #error Code Requires ARC. @@ -420,7 +421,7 @@ - (void)dispose { @end -@interface FLTVideoPlayerPlugin () +@interface FLTVideoPlayerPlugin () @property(readonly, weak, nonatomic) NSObject* registry; @property(readonly, weak, nonatomic) NSObject* messenger; @property(readonly, strong, nonatomic) NSMutableDictionary* players; @@ -429,12 +430,9 @@ @interface FLTVideoPlayerPlugin () @implementation FLTVideoPlayerPlugin + (void)registerWithRegistrar:(NSObject*)registrar { - FlutterMethodChannel* channel = - [FlutterMethodChannel methodChannelWithName:@"flutter.io/videoPlayer" - binaryMessenger:[registrar messenger]]; FLTVideoPlayerPlugin* instance = [[FLTVideoPlayerPlugin alloc] initWithRegistrar:registrar]; - [registrar addMethodCallDelegate:instance channel:channel]; [registrar publish:instance]; + FLTVideoPlayerApiSetup(registrar.messenger, instance); } - (instancetype)initWithRegistrar:(NSObject*)registrar { @@ -453,11 +451,11 @@ - (void)detachFromEngineForRegistrar:(NSObject*)registra [player disposeSansEventChannel]; } [_players removeAllObjects]; + FLTVideoPlayerApiSetup(registrar.messenger, nil); } -- (void)onPlayerSetup:(FLTVideoPlayer*)player - frameUpdater:(FLTFrameUpdater*)frameUpdater - result:(FlutterResult)result { +- (FLTTextureMessage*)onPlayerSetup:(FLTVideoPlayer*)player + frameUpdater:(FLTFrameUpdater*)frameUpdater { int64_t textureId = [_registry registerTexture:player]; frameUpdater.textureId = textureId; FlutterEventChannel* eventChannel = [FlutterEventChannel @@ -467,88 +465,96 @@ - (void)onPlayerSetup:(FLTVideoPlayer*)player [eventChannel setStreamHandler:player]; player.eventChannel = eventChannel; _players[@(textureId)] = player; - result(@{@"textureId" : @(textureId)}); + FLTTextureMessage* result = [[FLTTextureMessage alloc] init]; + result.textureId = @(textureId); + return result; } -- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([@"init" isEqualToString:call.method]) { - // Allow audio playback when the Ring/Silent switch is set to silent - [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; +- (void)initialize:(FlutterError* __autoreleasing*)error { + // Allow audio playback when the Ring/Silent switch is set to silent + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; - for (NSNumber* textureId in _players) { - [_registry unregisterTexture:[textureId unsignedIntegerValue]]; - [_players[textureId] dispose]; - } - [_players removeAllObjects]; - result(nil); - } else if ([@"create" isEqualToString:call.method]) { - NSDictionary* argsMap = call.arguments; - FLTFrameUpdater* frameUpdater = [[FLTFrameUpdater alloc] initWithRegistry:_registry]; - NSString* assetArg = argsMap[@"asset"]; - NSString* uriArg = argsMap[@"uri"]; - FLTVideoPlayer* player; - if (assetArg) { - NSString* assetPath; - NSString* package = argsMap[@"package"]; - if (![package isEqual:[NSNull null]]) { - assetPath = [_registrar lookupKeyForAsset:assetArg fromPackage:package]; - } else { - assetPath = [_registrar lookupKeyForAsset:assetArg]; - } - player = [[FLTVideoPlayer alloc] initWithAsset:assetPath frameUpdater:frameUpdater]; - [self onPlayerSetup:player frameUpdater:frameUpdater result:result]; - } else if (uriArg) { - player = [[FLTVideoPlayer alloc] initWithURL:[NSURL URLWithString:uriArg] - frameUpdater:frameUpdater]; - [self onPlayerSetup:player frameUpdater:frameUpdater result:result]; + for (NSNumber* textureId in _players) { + [_registry unregisterTexture:[textureId unsignedIntegerValue]]; + [_players[textureId] dispose]; + } + [_players removeAllObjects]; +} + +- (FLTTextureMessage*)create:(FLTCreateMessage*)input error:(FlutterError**)error { + FLTFrameUpdater* frameUpdater = [[FLTFrameUpdater alloc] initWithRegistry:_registry]; + FLTVideoPlayer* player; + if (input.asset) { + NSString* assetPath; + if (input.packageName) { + assetPath = [_registrar lookupKeyForAsset:input.asset fromPackage:input.packageName]; } else { - result(FlutterMethodNotImplemented); + assetPath = [_registrar lookupKeyForAsset:input.asset]; } + player = [[FLTVideoPlayer alloc] initWithAsset:assetPath frameUpdater:frameUpdater]; + return [self onPlayerSetup:player frameUpdater:frameUpdater]; + } else if (input.uri) { + player = [[FLTVideoPlayer alloc] initWithURL:[NSURL URLWithString:input.uri] + frameUpdater:frameUpdater]; + return [self onPlayerSetup:player frameUpdater:frameUpdater]; } else { - NSDictionary* argsMap = call.arguments; - int64_t textureId = ((NSNumber*)argsMap[@"textureId"]).unsignedIntegerValue; - FLTVideoPlayer* player = _players[@(textureId)]; - if ([@"dispose" isEqualToString:call.method]) { - [_registry unregisterTexture:textureId]; - [_players removeObjectForKey:@(textureId)]; - // If the Flutter contains https://github.com/flutter/engine/pull/12695, - // the `player` is disposed via `onTextureUnregistered` at the right time. - // Without https://github.com/flutter/engine/pull/12695, there is no guarantee that the - // texture has completed the un-reregistration. It may leads a crash if we dispose the - // `player` before the texture is unregistered. We add a dispatch_after hack to make sure the - // texture is unregistered before we dispose the `player`. - // - // TODO(cyanglaz): Remove this dispatch block when - // https://github.com/flutter/flutter/commit/8159a9906095efc9af8b223f5e232cb63542ad0b is in - // stable And update the min flutter version of the plugin to the stable version. - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), - dispatch_get_main_queue(), ^{ - if (!player.disposed) { - [player dispose]; - } - }); - result(nil); - } else if ([@"setLooping" isEqualToString:call.method]) { - [player setIsLooping:[argsMap[@"looping"] boolValue]]; - result(nil); - } else if ([@"setVolume" isEqualToString:call.method]) { - [player setVolume:[argsMap[@"volume"] doubleValue]]; - result(nil); - } else if ([@"play" isEqualToString:call.method]) { - [player play]; - result(nil); - } else if ([@"position" isEqualToString:call.method]) { - result(@([player position])); - } else if ([@"seekTo" isEqualToString:call.method]) { - [player seekTo:[argsMap[@"location"] intValue]]; - result(nil); - } else if ([@"pause" isEqualToString:call.method]) { - [player pause]; - result(nil); - } else { - result(FlutterMethodNotImplemented); - } + *error = [FlutterError errorWithCode:@"video_player" message:@"not implemented" details:nil]; + return nil; } } +- (void)dispose:(FLTTextureMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + [_registry unregisterTexture:input.textureId.intValue]; + [_players removeObjectForKey:input.textureId]; + // If the Flutter contains https://github.com/flutter/engine/pull/12695, + // the `player` is disposed via `onTextureUnregistered` at the right time. + // Without https://github.com/flutter/engine/pull/12695, there is no guarantee that the + // texture has completed the un-reregistration. It may leads a crash if we dispose the + // `player` before the texture is unregistered. We add a dispatch_after hack to make sure the + // texture is unregistered before we dispose the `player`. + // + // TODO(cyanglaz): Remove this dispatch block when + // https://github.com/flutter/flutter/commit/8159a9906095efc9af8b223f5e232cb63542ad0b is in + // stable And update the min flutter version of the plugin to the stable version. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + if (!player.disposed) { + [player dispose]; + } + }); +} + +- (void)setLooping:(FLTLoopingMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + [player setIsLooping:[input.isLooping boolValue]]; +} + +- (void)setVolume:(FLTVolumeMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + [player setVolume:[input.volume doubleValue]]; +} + +- (void)play:(FLTTextureMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + [player play]; +} + +- (FLTPositionMessage*)position:(FLTTextureMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + FLTPositionMessage* result = [[FLTPositionMessage alloc] init]; + result.position = @([player position]); + return result; +} + +- (void)seekTo:(FLTPositionMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + [player seekTo:[input.position intValue]]; +} + +- (void)pause:(FLTTextureMessage*)input error:(FlutterError**)error { + FLTVideoPlayer* player = _players[input.textureId]; + [player pause]; +} + @end diff --git a/packages/video_player/video_player/ios/Classes/messages.h b/packages/video_player/video_player/ios/Classes/messages.h new file mode 100644 index 000000000000..d9b7081bb640 --- /dev/null +++ b/packages/video_player/video_player/ios/Classes/messages.h @@ -0,0 +1,59 @@ +// Autogenerated from Pigeon (v0.1.0-experimental.10), do not edit directly. +// See also: https://pub.dev/packages/pigeon +#import +@protocol FlutterBinaryMessenger; +@class FlutterError; +@class FlutterStandardTypedData; + +NS_ASSUME_NONNULL_BEGIN + +@class FLTTextureMessage; +@class FLTCreateMessage; +@class FLTLoopingMessage; +@class FLTVolumeMessage; +@class FLTPositionMessage; + +@interface FLTTextureMessage : NSObject +@property(nonatomic, strong, nullable) NSNumber *textureId; +@end + +@interface FLTCreateMessage : NSObject +@property(nonatomic, copy, nullable) NSString *asset; +@property(nonatomic, copy, nullable) NSString *uri; +@property(nonatomic, copy, nullable) NSString *packageName; +@property(nonatomic, copy, nullable) NSString *formatHint; +@end + +@interface FLTLoopingMessage : NSObject +@property(nonatomic, strong, nullable) NSNumber *textureId; +@property(nonatomic, strong, nullable) NSNumber *isLooping; +@end + +@interface FLTVolumeMessage : NSObject +@property(nonatomic, strong, nullable) NSNumber *textureId; +@property(nonatomic, strong, nullable) NSNumber *volume; +@end + +@interface FLTPositionMessage : NSObject +@property(nonatomic, strong, nullable) NSNumber *textureId; +@property(nonatomic, strong, nullable) NSNumber *position; +@end + +@protocol FLTVideoPlayerApi +- (void)initialize:(FlutterError *_Nullable *_Nonnull)error; +- (nullable FLTTextureMessage *)create:(FLTCreateMessage *)input + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)dispose:(FLTTextureMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setLooping:(FLTLoopingMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setVolume:(FLTVolumeMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +- (void)play:(FLTTextureMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +- (nullable FLTPositionMessage *)position:(FLTTextureMessage *)input + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)seekTo:(FLTPositionMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +- (void)pause:(FLTTextureMessage *)input error:(FlutterError *_Nullable *_Nonnull)error; +@end + +extern void FLTVideoPlayerApiSetup(id binaryMessenger, + id _Nullable api); + +NS_ASSUME_NONNULL_END diff --git a/packages/video_player/video_player/ios/Classes/messages.m b/packages/video_player/video_player/ios/Classes/messages.m new file mode 100644 index 000000000000..3c51a8381591 --- /dev/null +++ b/packages/video_player/video_player/ios/Classes/messages.m @@ -0,0 +1,292 @@ +// Autogenerated from Pigeon (v0.1.0-experimental.10), do not edit directly. +// See also: https://pub.dev/packages/pigeon +#import "messages.h" +#import + +#if !__has_feature(objc_arc) +#error File requires ARC to be enabled. +#endif + +static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) { + NSDictionary *errorDict = (NSDictionary *)[NSNull null]; + if (error) { + errorDict = [NSDictionary + dictionaryWithObjectsAndKeys:(error.code ? error.code : [NSNull null]), @"code", + (error.message ? error.message : [NSNull null]), @"message", + (error.details ? error.details : [NSNull null]), @"details", + nil]; + } + return [NSDictionary dictionaryWithObjectsAndKeys:(result ? result : [NSNull null]), @"result", + errorDict, @"error", nil]; +} + +@interface FLTTextureMessage () ++ (FLTTextureMessage *)fromMap:(NSDictionary *)dict; +- (NSDictionary *)toMap; +@end +@interface FLTCreateMessage () ++ (FLTCreateMessage *)fromMap:(NSDictionary *)dict; +- (NSDictionary *)toMap; +@end +@interface FLTLoopingMessage () ++ (FLTLoopingMessage *)fromMap:(NSDictionary *)dict; +- (NSDictionary *)toMap; +@end +@interface FLTVolumeMessage () ++ (FLTVolumeMessage *)fromMap:(NSDictionary *)dict; +- (NSDictionary *)toMap; +@end +@interface FLTPositionMessage () ++ (FLTPositionMessage *)fromMap:(NSDictionary *)dict; +- (NSDictionary *)toMap; +@end + +@implementation FLTTextureMessage ++ (FLTTextureMessage *)fromMap:(NSDictionary *)dict { + FLTTextureMessage *result = [[FLTTextureMessage alloc] init]; + result.textureId = dict[@"textureId"]; + if ((NSNull *)result.textureId == [NSNull null]) { + result.textureId = nil; + } + return result; +} +- (NSDictionary *)toMap { + return [NSDictionary + dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]), + @"textureId", nil]; +} +@end + +@implementation FLTCreateMessage ++ (FLTCreateMessage *)fromMap:(NSDictionary *)dict { + FLTCreateMessage *result = [[FLTCreateMessage alloc] init]; + result.asset = dict[@"asset"]; + if ((NSNull *)result.asset == [NSNull null]) { + result.asset = nil; + } + result.uri = dict[@"uri"]; + if ((NSNull *)result.uri == [NSNull null]) { + result.uri = nil; + } + result.packageName = dict[@"packageName"]; + if ((NSNull *)result.packageName == [NSNull null]) { + result.packageName = nil; + } + result.formatHint = dict[@"formatHint"]; + if ((NSNull *)result.formatHint == [NSNull null]) { + result.formatHint = nil; + } + return result; +} +- (NSDictionary *)toMap { + return [NSDictionary + dictionaryWithObjectsAndKeys:(self.asset ? self.asset : [NSNull null]), @"asset", + (self.uri ? self.uri : [NSNull null]), @"uri", + (self.packageName != nil ? self.packageName : [NSNull null]), + @"packageName", + (self.formatHint != nil ? self.formatHint : [NSNull null]), + @"formatHint", nil]; +} +@end + +@implementation FLTLoopingMessage ++ (FLTLoopingMessage *)fromMap:(NSDictionary *)dict { + FLTLoopingMessage *result = [[FLTLoopingMessage alloc] init]; + result.textureId = dict[@"textureId"]; + if ((NSNull *)result.textureId == [NSNull null]) { + result.textureId = nil; + } + result.isLooping = dict[@"isLooping"]; + if ((NSNull *)result.isLooping == [NSNull null]) { + result.isLooping = nil; + } + return result; +} +- (NSDictionary *)toMap { + return [NSDictionary + dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]), + @"textureId", + (self.isLooping != nil ? self.isLooping : [NSNull null]), + @"isLooping", nil]; +} +@end + +@implementation FLTVolumeMessage ++ (FLTVolumeMessage *)fromMap:(NSDictionary *)dict { + FLTVolumeMessage *result = [[FLTVolumeMessage alloc] init]; + result.textureId = dict[@"textureId"]; + if ((NSNull *)result.textureId == [NSNull null]) { + result.textureId = nil; + } + result.volume = dict[@"volume"]; + if ((NSNull *)result.volume == [NSNull null]) { + result.volume = nil; + } + return result; +} +- (NSDictionary *)toMap { + return [NSDictionary + dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]), + @"textureId", (self.volume != nil ? self.volume : [NSNull null]), + @"volume", nil]; +} +@end + +@implementation FLTPositionMessage ++ (FLTPositionMessage *)fromMap:(NSDictionary *)dict { + FLTPositionMessage *result = [[FLTPositionMessage alloc] init]; + result.textureId = dict[@"textureId"]; + if ((NSNull *)result.textureId == [NSNull null]) { + result.textureId = nil; + } + result.position = dict[@"position"]; + if ((NSNull *)result.position == [NSNull null]) { + result.position = nil; + } + return result; +} +- (NSDictionary *)toMap { + return [NSDictionary + dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]), + @"textureId", + (self.position != nil ? self.position : [NSNull null]), + @"position", nil]; +} +@end + +void FLTVideoPlayerApiSetup(id binaryMessenger, id api) { + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.initialize" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + [api initialize:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.create" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTCreateMessage *input = [FLTCreateMessage fromMap:message]; + FLTTextureMessage *output = [api create:input error:&error]; + callback(wrapResult([output toMap], error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.dispose" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTTextureMessage *input = [FLTTextureMessage fromMap:message]; + [api dispose:input error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.setLooping" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTLoopingMessage *input = [FLTLoopingMessage fromMap:message]; + [api setLooping:input error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.setVolume" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTVolumeMessage *input = [FLTVolumeMessage fromMap:message]; + [api setVolume:input error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = + [FlutterBasicMessageChannel messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.play" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTTextureMessage *input = [FLTTextureMessage fromMap:message]; + [api play:input error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.position" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTTextureMessage *input = [FLTTextureMessage fromMap:message]; + FLTPositionMessage *output = [api position:input error:&error]; + callback(wrapResult([output toMap], error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.seekTo" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTPositionMessage *input = [FLTPositionMessage fromMap:message]; + [api seekTo:input error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.VideoPlayerApi.pause" + binaryMessenger:binaryMessenger]; + if (api) { + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + FLTTextureMessage *input = [FLTTextureMessage fromMap:message]; + [api pause:input error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } +} diff --git a/packages/video_player/video_player/pigeons/messages.dart b/packages/video_player/video_player/pigeons/messages.dart new file mode 100644 index 000000000000..2df5b78f13f8 --- /dev/null +++ b/packages/video_player/video_player/pigeons/messages.dart @@ -0,0 +1,50 @@ +import 'package:pigeon/pigeon_lib.dart'; + +class TextureMessage { + int textureId; +} + +class LoopingMessage { + int textureId; + bool isLooping; +} + +class VolumeMessage { + int textureId; + double volume; +} + +class PositionMessage { + int textureId; + int position; +} + +class CreateMessage { + String asset; + String uri; + String packageName; + String formatHint; +} + +@HostApi() +abstract class VideoPlayerApi { + void initialize(); + TextureMessage create(CreateMessage msg); + void dispose(TextureMessage msg); + void setLooping(LoopingMessage msg); + void setVolume(VolumeMessage msg); + void play(TextureMessage msg); + PositionMessage position(TextureMessage msg); + void seekTo(PositionMessage msg); + void pause(TextureMessage msg); +} + +void configurePigeon(PigeonOptions opts) { + opts.dartOut = '../video_player_platform_interface/lib/messages.dart'; + opts.objcHeaderOut = 'ios/Classes/messages.h'; + opts.objcSourceOut = 'ios/Classes/messages.m'; + opts.objcOptions.prefix = 'FLT'; + opts.javaOut = + 'android/src/main/java/io/flutter/plugins/videoplayer/Messages.java'; + opts.javaOptions.package = 'io.flutter.plugins.videoplayer'; +} diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index ad5cd452756d..d99e6380cb5f 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.9+2 +version: 0.10.10 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player flutter: @@ -20,7 +20,7 @@ flutter: dependencies: meta: "^1.0.5" - video_player_platform_interface: ^1.0.1 + video_player_platform_interface: ^2.0.0 # 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. @@ -35,7 +35,8 @@ dev_dependencies: flutter_test: sdk: flutter pedantic: ^1.8.0 + pigeon: 0.1.0-experimental.10 environment: - sdk: ">=2.0.0-dev.28.0 <3.0.0" + sdk: ">=2.1.0 <3.0.0" flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/packages/video_player/video_player/test/video_player_initialization_test.dart b/packages/video_player/video_player/test/video_player_initialization_test.dart index 61d28070e948..1a09ed9f718c 100644 --- a/packages/video_player/video_player/test/video_player_initialization_test.dart +++ b/packages/video_player/video_player/test/video_player_initialization_test.dart @@ -19,6 +19,6 @@ void main() { 'https://127.0.0.1', ); await controller.initialize(); - expect(fakeVideoPlayerPlatform.calls.first.method, 'init'); + expect(fakeVideoPlayerPlatform.calls.first, 'init'); }); } 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 20413b5564c5..ac8459d0c9e9 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -11,6 +11,7 @@ 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'; class FakeController extends ValueNotifier implements VideoPlayerController { @@ -169,11 +170,9 @@ void main() { await controller.initialize(); expect( - fakeVideoPlayerPlatform.dataSourceDescriptions[0], - { - 'asset': 'a.avi', - 'package': null, - }); + fakeVideoPlayerPlatform.dataSourceDescriptions[0].asset, 'a.avi'); + expect(fakeVideoPlayerPlatform.dataSourceDescriptions[0].packageName, + null); }); test('network', () async { @@ -182,12 +181,10 @@ void main() { ); await controller.initialize(); + expect(fakeVideoPlayerPlatform.dataSourceDescriptions[0].uri, + 'https://127.0.0.1'); expect( - fakeVideoPlayerPlatform.dataSourceDescriptions[0], - { - 'uri': 'https://127.0.0.1', - 'formatHint': null, - }); + fakeVideoPlayerPlatform.dataSourceDescriptions[0].formatHint, null); }); test('network with hint', () async { @@ -196,12 +193,10 @@ void main() { formatHint: VideoFormat.dash); await controller.initialize(); - expect( - fakeVideoPlayerPlatform.dataSourceDescriptions[0], - { - 'uri': 'https://127.0.0.1', - 'formatHint': 'dash', - }); + expect(fakeVideoPlayerPlatform.dataSourceDescriptions[0].uri, + 'https://127.0.0.1'); + expect(fakeVideoPlayerPlatform.dataSourceDescriptions[0].formatHint, + 'dash'); }); test('init errors', () async { @@ -224,11 +219,8 @@ void main() { VideoPlayerController.file(File('a.avi')); await controller.initialize(); - expect( - fakeVideoPlayerPlatform.dataSourceDescriptions[0], - { - 'uri': 'file://a.avi', - }); + expect(fakeVideoPlayerPlatform.dataSourceDescriptions[0].uri, + 'file://a.avi'); }); }); @@ -255,7 +247,7 @@ void main() { await controller.play(); expect(controller.value.isPlaying, isTrue); - expect(fakeVideoPlayerPlatform.calls.last.method, 'play'); + expect(fakeVideoPlayerPlatform.calls.last, 'play'); }); test('setLooping', () async { @@ -280,7 +272,7 @@ void main() { await controller.pause(); expect(controller.value.isPlaying, isFalse); - expect(fakeVideoPlayerPlatform.calls.last.method, 'pause'); + expect(fakeVideoPlayerPlatform.calls.last, 'pause'); }); group('seekTo', () { @@ -543,58 +535,73 @@ void main() { }); } -class FakeVideoPlayerPlatform { +class FakeVideoPlayerPlatform extends VideoPlayerApiTest { FakeVideoPlayerPlatform() { - _channel.setMockMethodCallHandler(onMethodCall); + VideoPlayerApiTestSetup(this); } - final MethodChannel _channel = const MethodChannel('flutter.io/videoPlayer'); - Completer initialized = Completer(); - List calls = []; - List> dataSourceDescriptions = >[]; + List calls = []; + List dataSourceDescriptions = []; final Map streams = {}; bool forceInitError = false; int nextTextureId = 0; final Map _positions = {}; - Future onMethodCall(MethodCall call) { - calls.add(call); - switch (call.method) { - case 'init': - initialized.complete(true); - break; - case 'create': - streams[nextTextureId] = FakeVideoEventStream(nextTextureId, 100, 100, - const Duration(seconds: 1), forceInitError); - final Map dataSource = call.arguments; - dataSourceDescriptions.add(dataSource.cast()); - return Future>.sync(() { - return { - 'textureId': nextTextureId++, - }; - }); - break; - case 'position': - final Duration position = _positions[call.arguments['textureId']] ?? - const Duration(seconds: 0); - return Future.value(position.inMilliseconds); - break; - case 'seekTo': - _positions[call.arguments['textureId']] = - Duration(milliseconds: call.arguments['location']); - break; - case 'dispose': - case 'pause': - case 'play': - case 'setLooping': - case 'setVolume': - break; - default: - throw UnimplementedError( - '${call.method} is not implemented by the FakeVideoPlayerPlatform'); - } - return Future.sync(() {}); + @override + TextureMessage create(CreateMessage arg) { + calls.add('create'); + streams[nextTextureId] = FakeVideoEventStream( + nextTextureId, 100, 100, const Duration(seconds: 1), forceInitError); + TextureMessage result = TextureMessage(); + result.textureId = nextTextureId++; + dataSourceDescriptions.add(arg); + return result; + } + + @override + void dispose(TextureMessage arg) { + calls.add('dispose'); + } + + @override + void initialize() { + calls.add('init'); + initialized.complete(true); + } + + @override + void pause(TextureMessage arg) { + calls.add('pause'); + } + + @override + void play(TextureMessage arg) { + calls.add('play'); + } + + @override + PositionMessage position(TextureMessage arg) { + calls.add('position'); + final Duration position = + _positions[arg.textureId] ?? const Duration(seconds: 0); + return PositionMessage()..position = position.inMilliseconds; + } + + @override + void seekTo(PositionMessage arg) { + calls.add('seekTo'); + _positions[arg.textureId] = Duration(milliseconds: arg.position); + } + + @override + void setLooping(LoopingMessage arg) { + calls.add('setLooping'); + } + + @override + void setVolume(VolumeMessage arg) { + calls.add('setVolume'); } }