Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/video_player/video_player/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ Anton Borries <[email protected]>
Alex Li <[email protected]>
Rahul Raj <[email protected]>
Koen Van Looveren <[email protected]>
Márton Matuz <[email protected]>
3 changes: 2 additions & 1 deletion packages/video_player/video_player/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 2.5.2

* Synchronizes `VideoPlayerValue.isPlaying` with underlying video player.
* Updates minimum Flutter version to 3.0.

## 2.5.1
Expand Down
5 changes: 5 additions & 0 deletions packages/video_player/video_player/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ flutter:
- assets/bumble_bee_captions.srt
- assets/bumble_bee_captions.vtt
- assets/Audio.mp3

# FOR TESTING ONLY. DO NOT MERGE.
dependency_overrides:
video_player_platform_interface:
path: ../../video_player_platform_interface
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// 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' show objectRuntimeType;
import 'package:flutter/foundation.dart' show immutable, objectRuntimeType;

import 'sub_rip.dart';
import 'web_vtt.dart';
Expand Down Expand Up @@ -32,6 +32,7 @@ abstract class ClosedCaptionFile {
///
/// A typical closed captioning file will include several [Caption]s, each
/// linked to a start and end time.
@immutable
class Caption {
/// Creates a new [Caption] object.
///
Expand Down Expand Up @@ -74,4 +75,22 @@ class Caption {
'end: $end, '
'text: $text)';
}

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Caption &&
runtimeType == other.runtimeType &&
number == other.number &&
start == other.start &&
end == other.end &&
text == other.text;

@override
int get hashCode => Object.hash(
number,
start,
end,
text,
);
}
56 changes: 49 additions & 7 deletions packages/video_player/video_player/lib/video_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ VideoPlayerPlatform get _videoPlayerPlatform {

/// The duration, current position, buffering state, error state and settings
/// of a [VideoPlayerController].
@immutable
class VideoPlayerValue {
/// Constructs a video with the given values. Only [duration] is required. The
/// rest will initialize with default values when unset.
VideoPlayerValue({
const VideoPlayerValue({
required this.duration,
this.size = Size.zero,
this.position = Duration.zero,
Expand All @@ -54,11 +55,11 @@ class VideoPlayerValue {
});

/// Returns an instance for a video that hasn't been loaded.
VideoPlayerValue.uninitialized()
const VideoPlayerValue.uninitialized()
: this(duration: Duration.zero, isInitialized: false);

/// Returns an instance with the given [errorDescription].
VideoPlayerValue.erroneous(String errorDescription)
const VideoPlayerValue.erroneous(String errorDescription)
: this(
duration: Duration.zero,
isInitialized: false,
Expand Down Expand Up @@ -195,6 +196,44 @@ class VideoPlayerValue {
'playbackSpeed: $playbackSpeed, '
'errorDescription: $errorDescription)';
}

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is VideoPlayerValue &&
runtimeType == other.runtimeType &&
duration == other.duration &&
position == other.position &&
caption == other.caption &&
captionOffset == other.captionOffset &&
listEquals(buffered, other.buffered) &&
isPlaying == other.isPlaying &&
isLooping == other.isLooping &&
isBuffering == other.isBuffering &&
volume == other.volume &&
playbackSpeed == other.playbackSpeed &&
errorDescription == other.errorDescription &&
size == other.size &&
rotationCorrection == other.rotationCorrection &&
isInitialized == other.isInitialized;

@override
int get hashCode => Object.hash(
duration,
position,
caption,
captionOffset,
buffered,
isPlaying,
isLooping,
isBuffering,
volume,
playbackSpeed,
errorDescription,
size,
rotationCorrection,
isInitialized,
);
}

/// Controls a platform video player, and provides updates when the state is
Expand All @@ -221,7 +260,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
dataSourceType = DataSourceType.asset,
formatHint = null,
httpHeaders = const <String, String>{},
super(VideoPlayerValue(duration: Duration.zero));
super(const VideoPlayerValue(duration: Duration.zero));

/// Constructs a [VideoPlayerController] playing a video from obtained from
/// the network.
Expand All @@ -241,7 +280,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
}) : _closedCaptionFileFuture = closedCaptionFile,
dataSourceType = DataSourceType.network,
package = null,
super(VideoPlayerValue(duration: Duration.zero));
super(const VideoPlayerValue(duration: Duration.zero));

/// Constructs a [VideoPlayerController] playing a video from a file.
///
Expand All @@ -254,7 +293,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
package = null,
formatHint = null,
httpHeaders = const <String, String>{},
super(VideoPlayerValue(duration: Duration.zero));
super(const VideoPlayerValue(duration: Duration.zero));

/// Constructs a [VideoPlayerController] playing a video from a contentUri.
///
Expand All @@ -270,7 +309,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
package = null,
formatHint = null,
httpHeaders = const <String, String>{},
super(VideoPlayerValue(duration: Duration.zero));
super(const VideoPlayerValue(duration: Duration.zero));

/// The URI to the video file. This will be in different formats depending on
/// the [DataSourceType] of the original video.
Expand Down Expand Up @@ -399,6 +438,9 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
case VideoEventType.bufferingEnd:
value = value.copyWith(isBuffering: false);
break;
case VideoEventType.isPlayingStateUpdate:
value = value.copyWith(isPlaying: event.isPlaying);
break;
case VideoEventType.unknown:
break;
}
Expand Down
13 changes: 12 additions & 1 deletion packages/video_player/video_player/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for displaying inline video with other Flutter
widgets on Android, iOS, and web.
repository: https://github.com/flutter/plugins/tree/main/packages/video_player/video_player
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
version: 2.5.1
version: 2.5.2

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down Expand Up @@ -31,3 +31,14 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter

# FOR TESTING ONLY. DO NOT MERGE.
dependency_overrides:
video_player_android:
path: ../video_player_android
video_player_avfoundation:
path: ../video_player_avfoundation
video_player_platform_interface:
path: ../video_player_platform_interface
video_player_web:
path: ../video_player_web
47 changes: 24 additions & 23 deletions packages/video_player/video_player/test/video_player_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import 'package:video_player_platform_interface/video_player_platform_interface.

class FakeController extends ValueNotifier<VideoPlayerValue>
implements VideoPlayerController {
FakeController() : super(VideoPlayerValue(duration: Duration.zero));
FakeController() : super(const VideoPlayerValue(duration: Duration.zero));

FakeController.value(VideoPlayerValue value) : super(value);

Expand Down Expand Up @@ -164,7 +164,8 @@ void main() {
testWidgets('non-zero rotationCorrection value is used',
(WidgetTester tester) async {
final FakeController controller = FakeController.value(
VideoPlayerValue(duration: Duration.zero, rotationCorrection: 180));
const VideoPlayerValue(
duration: Duration.zero, rotationCorrection: 180));
controller.textureId = 1;
await tester.pumpWidget(VideoPlayer(controller));
final Transform actualRotationCorrection =
Expand All @@ -184,7 +185,7 @@ void main() {
testWidgets('no transform when rotationCorrection is zero',
(WidgetTester tester) async {
final FakeController controller =
FakeController.value(VideoPlayerValue(duration: Duration.zero));
FakeController.value(const VideoPlayerValue(duration: Duration.zero));
controller.textureId = 1;
await tester.pumpWidget(VideoPlayer(controller));
expect(find.byType(Transform), findsNothing);
Expand Down Expand Up @@ -849,7 +850,7 @@ void main() {

group('VideoPlayerValue', () {
test('uninitialized()', () {
final VideoPlayerValue uninitialized = VideoPlayerValue.uninitialized();
const VideoPlayerValue uninitialized = VideoPlayerValue.uninitialized();

expect(uninitialized.duration, equals(Duration.zero));
expect(uninitialized.position, equals(Duration.zero));
Expand All @@ -870,7 +871,7 @@ void main() {

test('erroneous()', () {
const String errorMessage = 'foo';
final VideoPlayerValue error = VideoPlayerValue.erroneous(errorMessage);
const VideoPlayerValue error = VideoPlayerValue.erroneous(errorMessage);

expect(error.duration, equals(Duration.zero));
expect(error.position, equals(Duration.zero));
Expand Down Expand Up @@ -940,26 +941,26 @@ void main() {

group('copyWith()', () {
test('exact copy', () {
final VideoPlayerValue original = VideoPlayerValue.uninitialized();
const VideoPlayerValue original = VideoPlayerValue.uninitialized();
final VideoPlayerValue exactCopy = original.copyWith();

expect(exactCopy.toString(), original.toString());
});
test('errorDescription is not persisted when copy with null', () {
final VideoPlayerValue original = VideoPlayerValue.erroneous('error');
const VideoPlayerValue original = VideoPlayerValue.erroneous('error');
final VideoPlayerValue copy = original.copyWith(errorDescription: null);

expect(copy.errorDescription, null);
});
test('errorDescription is changed when copy with another error', () {
final VideoPlayerValue original = VideoPlayerValue.erroneous('error');
const VideoPlayerValue original = VideoPlayerValue.erroneous('error');
final VideoPlayerValue copy =
original.copyWith(errorDescription: 'new error');

expect(copy.errorDescription, 'new error');
});
test('errorDescription is changed when copy with error', () {
final VideoPlayerValue original = VideoPlayerValue.uninitialized();
const VideoPlayerValue original = VideoPlayerValue.uninitialized();
final VideoPlayerValue copy =
original.copyWith(errorDescription: 'new error');

Expand All @@ -969,45 +970,45 @@ void main() {

group('aspectRatio', () {
test('640x480 -> 4:3', () {
final VideoPlayerValue value = VideoPlayerValue(
const VideoPlayerValue value = VideoPlayerValue(
isInitialized: true,
size: const Size(640, 480),
duration: const Duration(seconds: 1),
size: Size(640, 480),
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 4 / 3);
});

test('no size -> 1.0', () {
final VideoPlayerValue value = VideoPlayerValue(
const VideoPlayerValue value = VideoPlayerValue(
isInitialized: true,
duration: const Duration(seconds: 1),
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 1.0);
});

test('height = 0 -> 1.0', () {
final VideoPlayerValue value = VideoPlayerValue(
const VideoPlayerValue value = VideoPlayerValue(
isInitialized: true,
size: const Size(640, 0),
duration: const Duration(seconds: 1),
size: Size(640, 0),
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 1.0);
});

test('width = 0 -> 1.0', () {
final VideoPlayerValue value = VideoPlayerValue(
const VideoPlayerValue value = VideoPlayerValue(
isInitialized: true,
size: const Size(0, 480),
duration: const Duration(seconds: 1),
size: Size(0, 480),
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 1.0);
});

test('negative aspect ratio -> 1.0', () {
final VideoPlayerValue value = VideoPlayerValue(
const VideoPlayerValue value = VideoPlayerValue(
isInitialized: true,
size: const Size(640, -480),
duration: const Duration(seconds: 1),
size: Size(640, -480),
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 1.0);
});
Expand Down
1 change: 1 addition & 0 deletions packages/video_player/video_player_android/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,4 @@ Aleksandr Yurkovskiy <[email protected]>
Anton Borries <[email protected]>
Alex Li <[email protected]>
Rahul Raj <[email protected]>
Márton Matuz <[email protected]>
3 changes: 2 additions & 1 deletion packages/video_player/video_player_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 2.3.11

* Synchronizes `VideoPlayerValue.isPlaying` with `ExoPlayer`.
* Updates minimum Flutter version to 3.0.

## 2.3.10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,16 @@ public void onPlayerError(final PlaybackException error) {
eventSink.error("VideoError", "Video player had error " + error, null);
}
}

@Override
public void onIsPlayingChanged(boolean isPlaying) {
if (eventSink != null) {
Map<String, Object> event = new HashMap<>();
event.put("event", "isPlayingStateUpdate");
event.put("isPlaying", isPlaying);
eventSink.success(event);
}
}
});
}

Expand Down
Loading