From 14b1f480899762dff022ddf50f9a32ab41a8d0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 4 Feb 2025 15:13:40 +0100 Subject: [PATCH 1/7] Add macOS platform view support --- .../video_player_avfoundation/README.md | 4 - .../darwin/RunnerTests/VideoPlayerTests.m | 7 +- .../FVPVideoPlayerPlugin.m | 9 +- .../FVPNativeVideoView.h | 2 - .../FVPNativeVideoViewFactory.h | 2 - .../FVPNativeVideoView.m | 83 +++++++++++++++++++ .../FVPNativeVideoViewFactory.m | 39 +++++++++ .../example/lib/main.dart | 37 ++++----- .../lib/src/avfoundation_video_player.dart | 6 +- 9 files changed, 139 insertions(+), 50 deletions(-) create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m create mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m diff --git a/packages/video_player/video_player_avfoundation/README.md b/packages/video_player/video_player_avfoundation/README.md index f46470ee2f5..1325daf0acf 100644 --- a/packages/video_player/video_player_avfoundation/README.md +++ b/packages/video_player/video_player_avfoundation/README.md @@ -13,7 +13,3 @@ should add it to your `pubspec.yaml` as usual. [1]: https://pub.dev/packages/video_player [2]: https://flutter.dev/to/endorsed-federated-plugin - -## Platform limitations - -On macOS, the plugin does not currently support platform views. Instead, a texture view is always used to display the video player, even if `VideoViewType.platformView` is specified as a parameter. \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m index a67a9003693..6c65ee7dd4e 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -8,14 +8,11 @@ #import #import +#import #import #import #import -#if TARGET_OS_IOS -#import -#endif - #if TARGET_OS_IOS @interface FakeAVAssetTrack : AVAssetTrack @property(readonly, nonatomic) CGAffineTransform preferredTransform; @@ -871,7 +868,6 @@ - (void)testHotReloadDoesNotCrash { handler:nil]; // No assertions needed. Lack of crash is a success. } -#if TARGET_OS_IOS - (void)testNativeVideoViewFactoryRegistration { NSObject *registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); @@ -881,7 +877,6 @@ - (void)testNativeVideoViewFactoryRegistration { OCMVerifyAll(registrar); } -#endif - (void)testPublishesInRegistration { NSObject *registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m index 0d76e6d24c5..68afd9fde93 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayerPlugin.m @@ -10,17 +10,13 @@ #import "./include/video_player_avfoundation/FVPAVFactory.h" #import "./include/video_player_avfoundation/FVPDisplayLink.h" #import "./include/video_player_avfoundation/FVPFrameUpdater.h" +#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" #import "./include/video_player_avfoundation/FVPTextureBasedVideoPlayer.h" #import "./include/video_player_avfoundation/FVPVideoPlayer.h" // Relative path is needed for messages.g.h. See // https://github.com/flutter/packages/pull/6675/#discussion_r1591210702 #import "./include/video_player_avfoundation/messages.g.h" -#if TARGET_OS_IOS -// Platform views are only supported on iOS as of now. -#import "./include/video_player_avfoundation/FVPNativeVideoViewFactory.h" -#endif - #if !__has_feature(objc_arc) #error Code Requires ARC. #endif @@ -61,15 +57,12 @@ @implementation FVPVideoPlayerPlugin + (void)registerWithRegistrar:(NSObject *)registrar { FVPVideoPlayerPlugin *instance = [[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; [registrar publish:instance]; -#if TARGET_OS_IOS - // Platform views are only supported on iOS as of now. FVPNativeVideoViewFactory *factory = [[FVPNativeVideoViewFactory alloc] initWithMessenger:registrar.messenger playerByIdentifierProvider:^FVPVideoPlayer *(NSNumber *playerIdentifier) { return instance->_playersByIdentifier[playerIdentifier]; }]; [registrar registerViewFactory:factory withId:@"plugins.flutter.dev/video_player_ios"]; -#endif SetUpFVPAVFoundationVideoPlayerApi(registrar.messenger, instance); } diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h index f05ebccf991..b974f10af03 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Platform views are only supported on iOS as of now. Ifdefs are used to avoid compilation errors. - #import #if TARGET_OS_OSX diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h index 2872bebdfcf..df9c403b434 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Platform views are only supported on iOS as of now. Ifdef is used to avoid compilation errors. - #import #import "FVPVideoPlayer.h" diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m new file mode 100644 index 00000000000..88e5354caf5 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m @@ -0,0 +1,83 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" + +#import + +@interface FVPPlayerView : NSView +@property(nonatomic, strong) AVPlayerLayer *playerLayer; +@end + +@implementation FVPPlayerView + ++ (Class)layerClass { + return [AVPlayerLayer class]; +} + +- (instancetype)initWithFrame:(NSRect)frameRect { + self = [super initWithFrame:frameRect]; + if (self) { + self.wantsLayer = YES; + self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:nil]; + [self.layer addSublayer:self.playerLayer]; + } + return self; +} + +- (void)setPlayer:(AVPlayer *)player { + self.playerLayer.player = player; + self.playerLayer.frame = self.bounds; +} + +- (void)layout { + [super layout]; + + // Disable implicit player animations to size the player layer to the view bounds without a delay. + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + self.playerLayer.frame = self.bounds; + + [CATransaction commit]; + + [self.playerLayer displayIfNeeded]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + +@interface FVPNativeVideoView () +@property(nonatomic, strong) FVPPlayerView *playerView; +@end + +@implementation FVPNativeVideoView + +- (instancetype)initWithPlayer:(AVPlayer *)player { + self = [super init]; + if (self) { + _playerView = [[FVPPlayerView alloc] initWithFrame:NSMakeRect(0, 0, 640, 480)]; + [_playerView setPlayer:player]; + [self addSubview:_playerView]; + + // Add constraints to ensure the playerView resizes with its parent. + _playerView.translatesAutoresizingMaskIntoConstraints = NO; + [NSLayoutConstraint activateConstraints:@[ + [_playerView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], + [_playerView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], + [_playerView.topAnchor constraintEqualToAnchor:self.topAnchor], + [_playerView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], + ]]; + } + return self; +} + +- (FVPPlayerView *)view { + return self.playerView; +} + +@end \ No newline at end of file diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m new file mode 100644 index 00000000000..eefa86b9145 --- /dev/null +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h" + +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" +#import "../video_player_avfoundation/include/video_player_avfoundation/messages.g.h" + +@interface FVPNativeVideoViewFactory () +@property(nonatomic, strong) NSObject *messenger; +@property(nonatomic, copy) FVPVideoPlayer * (^playerByIdProvider)(NSNumber *); +@end + +@implementation FVPNativeVideoViewFactory + +- (instancetype)initWithMessenger:(NSObject *)messenger + playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider { + self = [super init]; + if (self) { + _messenger = messenger; + _playerByIdProvider = [playerByIdProvider copy]; + } + return self; +} + +- (NSView *)createWithViewIdentifier:(int64_t)viewId + arguments:(FVPPlatformVideoViewCreationParams *)args { + NSNumber *playerId = @(args.playerId); + FVPVideoPlayer *player = self.playerByIdProvider(playerId); + return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; +} + +- (NSObject *)createArgsCodec { + return FVPGetMessagesCodec(); +} + +@end diff --git a/packages/video_player/video_player_avfoundation/example/lib/main.dart b/packages/video_player/video_player_avfoundation/example/lib/main.dart index 0067b639c96..e043e05b882 100644 --- a/packages/video_player/video_player_avfoundation/example/lib/main.dart +++ b/packages/video_player/video_player_avfoundation/example/lib/main.dart @@ -4,8 +4,6 @@ // ignore_for_file: public_member_api_docs -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; @@ -44,27 +42,20 @@ class _App extends StatelessWidget { ), ), body: TabBarView( - children: Platform.isIOS - ? [ - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _BumbleBeeRemoteVideo(viewType), - ), - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _BumbleBeeEncryptedLiveStream(viewType), - ), - _ViewTypeTabBar( - builder: (VideoViewType viewType) => - _ButterFlyAssetVideo(viewType), - ), - ] - // Platform views are only supported on iOS as of now. - : const [ - _BumbleBeeRemoteVideo(VideoViewType.textureView), - _BumbleBeeEncryptedLiveStream(VideoViewType.textureView), - _ButterFlyAssetVideo(VideoViewType.textureView), - ], + children: [ + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeRemoteVideo(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _BumbleBeeEncryptedLiveStream(viewType), + ), + _ViewTypeTabBar( + builder: (VideoViewType viewType) => + _ButterFlyAssetVideo(viewType), + ), + ], ), ), ); diff --git a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart index ec790187abf..bc368befb42 100644 --- a/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart +++ b/packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; @@ -53,10 +52,7 @@ class AVFoundationVideoPlayer extends VideoPlayerPlatform { @override Future createWithOptions(VideoCreationOptions options) async { final DataSource dataSource = options.dataSource; - // Platform views are not supported on macOS yet. Use texture view instead. - final VideoViewType viewType = defaultTargetPlatform == TargetPlatform.macOS - ? VideoViewType.textureView - : options.viewType; + final VideoViewType viewType = options.viewType; String? asset; String? packageName; From dacb776552b7489c4d7c9580b1d13376f36a3b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jakubowski?= Date: Tue, 4 Feb 2025 15:54:40 +0100 Subject: [PATCH 2/7] Update unit tests according to new logic --- .../test/avfoundation_video_player_test.dart | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart index 3d02cef3cbe..9fc26cea98e 100644 --- a/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart +++ b/packages/video_player/video_player_avfoundation/test/avfoundation_video_player_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:video_player_avfoundation/src/messages.g.dart'; @@ -270,8 +269,7 @@ void main() { const VideoPlayerTextureViewState(textureId: 3)); }); - test('createWithOptions with platform view on iOS', () async { - debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + test('createWithOptions with platform view', () async { final int? playerId = await player.createWithOptions( VideoCreationOptions( dataSource: DataSource( @@ -287,25 +285,6 @@ void main() { expect(player.playerViewStates[3], const VideoPlayerPlatformViewState()); }); - test('createWithOptions with platform view uses texture view on MacOS', - () async { - debugDefaultTargetPlatformOverride = TargetPlatform.macOS; - final int? playerId = await player.createWithOptions( - VideoCreationOptions( - dataSource: DataSource( - sourceType: DataSourceType.file, - uri: 'someUri', - ), - viewType: VideoViewType.platformView, - ), - ); - expect(log.log.last, 'create'); - expect(log.creationOptions?.viewType, PlatformVideoViewType.textureView); - expect(playerId, 3); - expect(player.playerViewStates[3], - const VideoPlayerTextureViewState(textureId: 3)); - }); - test('setLooping', () async { await player.setLooping(1, true); expect(log.log.last, 'setLooping'); From b99e45ea4696b3ec1c8019cf5cce475ffd84ad46 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 7 Jul 2025 14:04:54 -0400 Subject: [PATCH 3/7] Combine factories, slight adjustments --- .../FVPNativeVideoViewFactory.m | 7 ++++ .../FVPNativeVideoView.m | 8 +--- .../FVPNativeVideoViewFactory.m | 39 ------------------- 3 files changed, 9 insertions(+), 45 deletions(-) rename packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/{video_player_avfoundation_ios => video_player_avfoundation}/FVPNativeVideoViewFactory.m (88%) delete mode 100644 packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m similarity index 88% rename from packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m rename to packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m index 94ece09e11e..9314dda9d06 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_ios/FVPNativeVideoViewFactory.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPNativeVideoViewFactory.m @@ -25,9 +25,16 @@ - (instancetype)initWithMessenger:(NSObject *)messenger return self; } +#pragma mark - FlutterPlatformViewFactory + +#if TARGET_OS_OSX +- (NSView *)createWithViewIdentifier:(int64_t)viewIdentifier + arguments:(FVPPlatformVideoViewCreationParams *)args { +#else - (NSObject *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewIdentifier arguments:(FVPPlatformVideoViewCreationParams *)args { +#endif NSNumber *playerIdentifier = @(args.playerId); FVPVideoPlayer *player = self.playerByIdProvider(playerIdentifier); return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m index 88e5354caf5..7f8690b6581 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m @@ -45,10 +45,6 @@ - (void)layout { [self.playerLayer displayIfNeeded]; } -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - @end @interface FVPNativeVideoView () @@ -60,7 +56,7 @@ @implementation FVPNativeVideoView - (instancetype)initWithPlayer:(AVPlayer *)player { self = [super init]; if (self) { - _playerView = [[FVPPlayerView alloc] initWithFrame:NSMakeRect(0, 0, 640, 480)]; + _playerView = [[FVPPlayerView alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; [_playerView setPlayer:player]; [self addSubview:_playerView]; @@ -80,4 +76,4 @@ - (FVPPlayerView *)view { return self.playerView; } -@end \ No newline at end of file +@end diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m deleted file mode 100644 index eefa86b9145..00000000000 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoViewFactory.m +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoViewFactory.h" - -#import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" -#import "../video_player_avfoundation/include/video_player_avfoundation/FVPVideoPlayer.h" -#import "../video_player_avfoundation/include/video_player_avfoundation/messages.g.h" - -@interface FVPNativeVideoViewFactory () -@property(nonatomic, strong) NSObject *messenger; -@property(nonatomic, copy) FVPVideoPlayer * (^playerByIdProvider)(NSNumber *); -@end - -@implementation FVPNativeVideoViewFactory - -- (instancetype)initWithMessenger:(NSObject *)messenger - playerByIdProvider:(FVPVideoPlayer * (^)(NSNumber *))playerByIdProvider { - self = [super init]; - if (self) { - _messenger = messenger; - _playerByIdProvider = [playerByIdProvider copy]; - } - return self; -} - -- (NSView *)createWithViewIdentifier:(int64_t)viewId - arguments:(FVPPlatformVideoViewCreationParams *)args { - NSNumber *playerId = @(args.playerId); - FVPVideoPlayer *player = self.playerByIdProvider(playerId); - return [[FVPNativeVideoView alloc] initWithPlayer:player.player]; -} - -- (NSObject *)createArgsCodec { - return FVPGetMessagesCodec(); -} - -@end From a5b8ae2fa297be34805add3d556245dafc2721a8 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Mon, 7 Jul 2025 14:05:24 -0400 Subject: [PATCH 4/7] Version bump --- packages/video_player/video_player_avfoundation/CHANGELOG.md | 4 ++++ packages/video_player/video_player_avfoundation/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 26299c26dbc..3cf06ee1a8c 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.8.0 + +* Adds platform view support for macOS. + ## 2.7.2 * Uses `CADisplayLink` on macOS 14.0+. diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index ded01c7a74d..cf9f99f636e 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_avfoundation description: iOS and macOS implementation of the video_player plugin. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.7.2 +version: 2.8.0 environment: sdk: ^3.6.0 From 5514390c167d527daf4456980f507aa7dfb61ca8 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 8 Jul 2025 14:56:24 -0400 Subject: [PATCH 5/7] Allow AppKit to manage the layer --- .../FVPNativeVideoView.m | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m index 7f8690b6581..8f2fe60f33f 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m @@ -12,37 +12,18 @@ @interface FVPPlayerView : NSView @implementation FVPPlayerView -+ (Class)layerClass { - return [AVPlayerLayer class]; +- (CALayer *)makeBackingLayer { + return [AVPlayerLayer playerLayerWithPlayer:nil]; } - (instancetype)initWithFrame:(NSRect)frameRect { self = [super initWithFrame:frameRect]; - if (self) { - self.wantsLayer = YES; - self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:nil]; - [self.layer addSublayer:self.playerLayer]; - } + self.wantsLayer = YES; return self; } - (void)setPlayer:(AVPlayer *)player { - self.playerLayer.player = player; - self.playerLayer.frame = self.bounds; -} - -- (void)layout { - [super layout]; - - // Disable implicit player animations to size the player layer to the view bounds without a delay. - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - - self.playerLayer.frame = self.bounds; - - [CATransaction commit]; - - [self.playerLayer displayIfNeeded]; + ((AVPlayerLayer *)self.layer).player = player; } @end From d60140c2c1579e4d08e51fa3545f1bfab275f117 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 8 Jul 2025 15:05:11 -0400 Subject: [PATCH 6/7] Simplify significantly --- .../FVPNativeVideoView.m | 45 +++---------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m index 8f2fe60f33f..742ff4e146b 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m @@ -5,56 +5,21 @@ #import "../video_player_avfoundation/include/video_player_avfoundation/FVPNativeVideoView.h" #import - -@interface FVPPlayerView : NSView -@property(nonatomic, strong) AVPlayerLayer *playerLayer; -@end - -@implementation FVPPlayerView - -- (CALayer *)makeBackingLayer { - return [AVPlayerLayer playerLayerWithPlayer:nil]; -} - -- (instancetype)initWithFrame:(NSRect)frameRect { - self = [super initWithFrame:frameRect]; - self.wantsLayer = YES; - return self; -} - -- (void)setPlayer:(AVPlayer *)player { - ((AVPlayerLayer *)self.layer).player = player; -} - -@end - -@interface FVPNativeVideoView () -@property(nonatomic, strong) FVPPlayerView *playerView; -@end +#import @implementation FVPNativeVideoView - (instancetype)initWithPlayer:(AVPlayer *)player { self = [super init]; if (self) { - _playerView = [[FVPPlayerView alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; - [_playerView setPlayer:player]; - [self addSubview:_playerView]; - - // Add constraints to ensure the playerView resizes with its parent. - _playerView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [_playerView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], - [_playerView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], - [_playerView.topAnchor constraintEqualToAnchor:self.topAnchor], - [_playerView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], - ]]; + self.wantsLayer = YES; + ((AVPlayerLayer *)self.layer).player = player; } return self; } -- (FVPPlayerView *)view { - return self.playerView; +- (CALayer *)makeBackingLayer { + return [AVPlayerLayer playerLayerWithPlayer:nil]; } @end From 36411fa27cee95e8f75d8c0af08a45939dc2e315 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 8 Jul 2025 15:08:25 -0400 Subject: [PATCH 7/7] Just use init since there's no player --- .../video_player_avfoundation_macos/FVPNativeVideoView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m index 742ff4e146b..466ef06f549 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_macos/FVPNativeVideoView.m @@ -19,7 +19,7 @@ - (instancetype)initWithPlayer:(AVPlayer *)player { } - (CALayer *)makeBackingLayer { - return [AVPlayerLayer playerLayerWithPlayer:nil]; + return [[AVPlayerLayer alloc] init]; } @end