Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[video_player] #60048 ios picture in picture #3500

Open
wants to merge 68 commits into
base: main
Choose a base branch
from

Conversation

vanlooverenkoen
Copy link
Contributor

@vanlooverenkoen vanlooverenkoen commented Mar 20, 2023

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

demo_pip_iphone

List which issues are fixed by this PR. You must list at least one issue.

This feature is only available on iOS because android has a different implementation. simple_pip_mode can be used for Android

Fixes flutter/flutter#60048

Migration from flutter/plugin to flutter/packages is done with this pr

old pr: flutter/plugins#6284

No migration needed this is an addon

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages repo does use dart format.)
  • I signed the CLA.
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I listed at least one issue that this PR fixes in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.
  • I updated CHANGELOG.md to add a description of the change, following repository CHANGELOG style.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@vanlooverenkoen
Copy link
Contributor Author

@hellohuanlin & @stuartmorgan I did the migration from flutter/plugins#6284 to here

Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

carrying over the stamp from previous PR

@camsim99 camsim99 removed their request for review March 27, 2023 15:33
@vanlooverenkoen
Copy link
Contributor Author

@tarrinneal can I assist you with the review?

Copy link
Contributor

@tarrinneal tarrinneal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial pass. A few changes to be made. Good work on this!

# Conflicts:
#	packages/video_player/video_player/CHANGELOG.md
#	packages/video_player/video_player/lib/video_player.dart
#	packages/video_player/video_player/pubspec.yaml
#	packages/video_player/video_player_android/example/lib/mini_controller.dart
#	packages/video_player/video_player_avfoundation/CHANGELOG.md
#	packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart
#	packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart
#	packages/video_player/video_player_avfoundation/pubspec.yaml
@vanlooverenkoen
Copy link
Contributor Author

@tarrinneal I updated my pull request fully retested it to make sure it does what I expect.

@@ -106,6 107,9 @@ class VideoPlayerValue {
/// The current speed of the playback.
final double playbackSpeed;

/// True if picture-in-picture is currently active.
final bool isPictureInPictureActive;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanlooverenkoen
Nice job, I'm in need of this feature.

I'm testing this pr in a project and I found a bug when updating this value. This property is not used in the bool operator ==(Object other) function, so it is not updated in the ValueNotifier. Can you fix this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn! Good catch!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like you added a Dart unit test to cover that change (i.e., one which would have caught this bug).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like you added a Dart unit test to cover that change (i.e., one which would have caught this bug).

This doesn't appear to have been resolved.

@tarrinneal
Copy link
Contributor

@tarrinneal I updated my pull request fully retested it to make sure it does what I expect.

Seems like you still have a few broken tests. I should be able to get this re-reviewed this week, if you can git them sorted out.

@vanlooverenkoen
Copy link
Contributor Author

@tarrinneal the tests are failing on camera because of the dependency overrides. How should I handle this? Because the dependency override script doesn't update it in the camera package.

I will fix the merge conflicts today

@vanlooverenkoen
Copy link
Contributor Author

@stuartmorgan Linux repo_checks will always fail on 50. federated safety check right? As long as I have not yet split the PR up. So this fail is allowed for now?

Dart changes are not allowed to other packages in video_player in the same PR as changes to public Dart code in video_player_platform_interface, as this can cause accidental breaking changes to be missed by automated checks. Please split the changes to these two packages into separate PRs.

@vanlooverenkoen
Copy link
Contributor Author

@stuartmorgan what is the best way to fix check_podspecs & macos_platform_tests master?

Just wrap everything related to pip with this?

  if (@available(macOS 10.15, *)) {
// pip code
  }

@stuartmorgan
Copy link
Contributor

@stuartmorgan Linux repo_checks will always fail on 50. federated safety check right? As long as I have not yet split the PR up. So this fail is allowed for now?

That's correct. The format failure in repo_checks is not expected though.

@stuartmorgan what is the best way to fix check_podspecs & macos_platform_tests master?

Just wrap everything related to pip with this?

It depends on what you mean by "just wrap"; you'll need reasonable else behavior (e.g., returning an error) for the unsupported OS case.

@@ -71,8 71,10 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id<FlutterPluginRegistrar>)registr

#pragma mark -

@interface FVPVideoPlayer ()
API_AVAILABLE(macos(10.15))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stuartmorgan is this how I should mark the FVPVideoPlayer? Or how else should I fix AVPictureInPicutreControllerDelegate to only be available on macOS?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is marking everything in the private interface as 10.15 ; you'll need to declare this in an extension:

API_AVAILABLE(macos(10.15))
@interface FVPVideoPlayer (AVPIPDelegate) <AVPictureInPictureControllerDelegate>
@end

@interface FVPVideoPlayer ()
...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This will, correctly, cause you to need to adjust other guards later in the code, such as the pictureInPictureController property and calls to it.)

@vanlooverenkoen
Copy link
Contributor Author

@stuartmorgan I have fixed all bugs and failing CI checks

@@ -30,3 30,14 @@ dev_dependencies:

flutter:
uses-material-design: true

# FOR TESTING ONLY. DO NOT MERGE.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the camera* package overrides can be removed, since this won't affect the camera usages.

If you want to enable picture-in-picture make sure to enable the `audio` capability (in Xcode's UI it will say **Audio, AirPlay, and Picture in Picture**).
Not setting this capability but calling `setPictureInPictureOverlayRectMessage` and `setPictureInPicture` will not start the picture-in-picture.

```xml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There needs to be something in the text just before this that says exactly what file(s) this is showing.

VideoProgressIndicator(_controller, allowScrubbing: true),
if (_controller.value.isPictureInPictureActive) ...<Widget>[
Container(color: Colors.white),
// TODO(goderbauer): Make this const when this package requires Flutter 3.8 or later.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already the case.

@@ -106,6 107,9 @@ class VideoPlayerValue {
/// The current speed of the playback.
final double playbackSpeed;

/// True if picture-in-picture is currently active.
final bool isPictureInPictureActive;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like you added a Dart unit test to cover that change (i.e., one which would have caught this bug).

This doesn't appear to have been resolved.

@@ -71,8 71,10 @@ - (FVPDisplayLink *)displayLinkWithRegistrar:(id<FlutterPluginRegistrar>)registr

#pragma mark -

@interface FVPVideoPlayer ()
API_AVAILABLE(macos(10.15))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is marking everything in the private interface as 10.15 ; you'll need to declare this in an extension:

API_AVAILABLE(macos(10.15))
@interface FVPVideoPlayer (AVPIPDelegate) <AVPictureInPictureControllerDelegate>
@end

@interface FVPVideoPlayer ()
...

@@ -84,6 86,7 @@ @interface FVPVideoPlayer ()
@property(nonatomic, readonly) BOOL isPlaying;
@property(nonatomic) BOOL isLooping;
@property(nonatomic, readonly) BOOL isInitialized;
@property(nonatomic) BOOL isPictureInPictureStarted;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}

- (void)startOrStopPictureInPicture:(BOOL)shouldPictureInPictureStart {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems very confusing from an API standpoint that both

[self startOrStopPictureInPicture:foo];

(which is already hard to parse, since the bool argument isn't named by the signature in violation of standard Obj-C naming conventions)

and

self.isPictureInPictureStarted = foo;

exist, and do different things.

Why not just override the setter of the property to do what this method does, and eliminate this duplicate-sounding method?

@@ -664,6 664,30 @@ - (void)testSeekToleranceWhenSeekingToEnd {
XCTAssertNil(error);
XCTAssertEqual(avPlayer.volume, 0.1f);

// Set picture-in-picture
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My earlier comment about this testing was never resolved.

@@ -31,6 32,34 @@ - (void)testPlayVideo {
XCTAssertTrue([playButton waitForExistenceWithTimeout:30.0]);
[playButton tap];

if ([AVPictureInPictureController isPictureInPictureSupported]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a separate test.

bool isPictureInPictureSupported();
@ObjCSelector('setPictureInPictureOverlaySettings:')
void setPictureInPictureOverlaySettings(
SetPictureInPictureOverlaySettingsMessage msg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New code should not use the message object pattern (and in fact the existing code has since been updated not to use it).

@stuartmorgan stuartmorgan added the triage-ios Should be looked at in iOS triage label Jun 3, 2024
@jmagman jmagman removed the triage-ios Should be looked at in iOS triage label Jun 5, 2024
@stuartmorgan
Copy link
Contributor

@vanlooverenkoen Are you still planning on updating this PR?

@vanlooverenkoen
Copy link
Contributor Author

@stuartmorgan Yes, for some reason I missed these comments again. Can we maybe plan a timeframe where I fix these comments and get a review right after, in order to prevent endless merge conflict fixes?

Because everytime I come back to this PR it often takes more time to figure out what changed on main and if it affected my PR?

Let me know if that is feasible, than I can add this PR again to my planning

@stuartmorgan
Copy link
Contributor

@vanlooverenkoen I should generally be able to turn around an incremental review for this PR within about a week going forward. In cases where there's a month or more between when I do a review and when the PR is updated again though, I need to re-review the entire large PR almost from scratch because I no longer have enough context to do an incremental review, and finding a large block of time to re-review everything can take longer.

@vanlooverenkoen
Copy link
Contributor Author

@stuartmorgan alright that is clear! Let me try to fit this in. Keep you posted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants