Skip to content
Open
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
36 changes: 33 additions & 3 deletions lib/src/controllers/pod_base_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class _PodBaseController extends GetxController {
int doubleTapForwardSeconds = 10;
String? playingVideoUrl;

/// The video view type (textureView or platformView)
VideoViewType _videoViewType = VideoViewType.textureView;

late BuildContext mainContext;
late BuildContext fullScreenContext;

Expand All @@ -44,7 +47,7 @@ class _PodBaseController extends GetxController {
await _videoCtr!.initialize();
}
if (_videoCtr!.value.isInitialized) {
// _listneToVideoState();
_listenToVideoState();
_listneToVideoPosition();
_listneToVolume();
if (kIsWeb && autoPlay && isMute && !_isWebAutoPlayDone) _webAutoPlay();
Expand Down Expand Up @@ -78,6 +81,34 @@ class _PodBaseController extends GetxController {
// : PodVideoState.paused,
// );
// }
void _listenToVideoState() {
// Handle the uninitialized state
if (!_videoCtr!.value.isInitialized) {
podVideoStateChanger(PodVideoState.loading);
return;
}

// Handle the buffering state
if (!_videoCtr!.value.isPlaying && _videoCtr!.value.isBuffering) {
podVideoStateChanger(PodVideoState.loading);
return;
}

// Handle the playing and paused states
if (_videoCtr!.value.isPlaying) {
podVideoStateChanger(PodVideoState.playing);
} else {
// Ensure that the video is really paused
// It was observed that sometimes the "isPlaying" value comes as FALSE then immediately comes as TRUE
// If we update the Pod Video state to paused right away, the player UI enters in a play/pause loop
Future<void>.delayed(const Duration(milliseconds: 200)).then((value) {
// If after a small delay the video is still paused, then we update the Pod Video state
if (!_videoCtr!.value.isPlaying) {
podVideoStateChanger(PodVideoState.paused);
}
});
}
}

///updates state with id `_podVideoState`
void podVideoStateChanger(PodVideoState? val, {bool updateUi = true}) {
Expand All @@ -96,8 +127,7 @@ class _PodBaseController extends GetxController {
update(['video-progress']);
update(['update-all']);
} else {
if (_videoPosition.inSeconds !=
(_videoCtr?.value.position ?? Duration.zero).inSeconds) {
if (_videoPosition.inSeconds != (_videoCtr?.value.position ?? Duration.zero).inSeconds) {
_videoPosition = _videoCtr?.value.position ?? Duration.zero;
update(['video-progress']);
update(['update-all']);
Expand Down
13 changes: 13 additions & 0 deletions lib/src/controllers/pod_getx_video_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class PodGetXVideoController extends _PodGesturesController {
}) {
this.playVideoFrom = playVideoFrom;
_videoPlayerType = playVideoFrom.playerType;
_videoViewType = playVideoFrom.viewType ?? VideoViewType.textureView;
podPlayerConfig = playerConfig;
autoPlay = playerConfig.autoPlay;
isLooping = playerConfig.isLooping;
Expand Down Expand Up @@ -91,6 +92,7 @@ class PodGetXVideoController extends _PodGesturesController {
formatHint: playVideoFrom.formatHint,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
httpHeaders: playVideoFrom.httpHeaders,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);
playingVideoUrl = playVideoFrom.dataSource;
break;
Expand All @@ -107,6 +109,7 @@ class PodGetXVideoController extends _PodGesturesController {
formatHint: playVideoFrom.formatHint,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
httpHeaders: playVideoFrom.httpHeaders,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);
playingVideoUrl = url;

Expand All @@ -128,6 +131,7 @@ class PodGetXVideoController extends _PodGesturesController {
formatHint: playVideoFrom.formatHint,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
httpHeaders: playVideoFrom.httpHeaders,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);
playingVideoUrl = url;

Expand All @@ -148,6 +152,7 @@ class PodGetXVideoController extends _PodGesturesController {
formatHint: playVideoFrom.formatHint,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
httpHeaders: playVideoFrom.httpHeaders,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);
playingVideoUrl = url;

Expand All @@ -160,6 +165,7 @@ class PodGetXVideoController extends _PodGesturesController {
closedCaptionFile: playVideoFrom.closedCaptionFile,
package: playVideoFrom.package,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);
playingVideoUrl = playVideoFrom.dataSource;

Expand All @@ -174,6 +180,7 @@ class PodGetXVideoController extends _PodGesturesController {
playVideoFrom.file!,
closedCaptionFile: playVideoFrom.closedCaptionFile,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);

break;
Expand All @@ -193,6 +200,7 @@ class PodGetXVideoController extends _PodGesturesController {
formatHint: playVideoFrom.formatHint,
videoPlayerOptions: playVideoFrom.videoPlayerOptions,
httpHeaders: playVideoFrom.httpHeaders,
viewType: playVideoFrom.viewType ?? VideoViewType.textureView,
);
playingVideoUrl = url;

Expand All @@ -207,6 +215,11 @@ class PodGetXVideoController extends _PodGesturesController {
required String tag,
}) {
if (kIsWeb) {
// If keyboard shortcuts are disabled, don't handle any keyboard events
if (podPlayerConfig.disableKeyboardShortcuts) {
return;
}

if (event.isKeyPressed(LogicalKeyboardKey.space)) {
togglePlayPauseVideo();
return;
Expand Down
13 changes: 11 additions & 2 deletions lib/src/controllers/pod_player_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,17 @@ class PodPlayerController {
);

//Change double tap duration
void setDoubeTapForwarDuration(int seconds) =>
_ctr.doubleTapForwardSeconds = seconds;
void setDoubeTapForwarDuration(int seconds) => _ctr.doubleTapForwardSeconds = seconds;

// Change the video playback speed
Future<void> setVideoPlayBack(double speed) async {
await _ctr.setVideoPlayBackSpeed(speed);
}

// Change the video looping status
Future<void> setVideoLooping(bool looping) async {
await _ctr.setLooping(looping);
}

///Jumps to specific position of the video
Future<void> videoSeekTo(Duration moment) async {
Expand Down
12 changes: 6 additions & 6 deletions lib/src/controllers/pod_video_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ class _PodVideoController extends _PodUiController {
_videoCtr?.setPlaybackSpeed(pickedSpeed);
}

Future<void> setVideoPlayBackSpeed(double speed) async {
await _videoCtr?.setPlaybackSpeed(speed);
}

Future<void> setLooping(bool isLooped) async {
isLooping = isLooped;
await _videoCtr?.setLooping(isLooping);
Expand Down Expand Up @@ -234,8 +238,7 @@ class _PodVideoController extends _PodUiController {
tag: tag,
),
reverseTransitionDuration: const Duration(milliseconds: 400),
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(
transitionsBuilder: (context, animation, secondaryAnimation, child) => FadeTransition(
opacity: animation,
child: child,
),
Expand All @@ -248,10 +251,7 @@ class _PodVideoController extends _PodUiController {
String calculateVideoDuration(Duration duration) {
final totalHour = duration.inHours == 0 ? '' : '${duration.inHours}:';
final totalMinute = duration.toString().split(':')[1];
final totalSeconds = (duration - Duration(minutes: duration.inMinutes))
.inSeconds
.toString()
.padLeft(2, '0');
final totalSeconds = (duration - Duration(minutes: duration.inMinutes)).inSeconds.toString().padLeft(2, '0');
final String videoLength = '$totalHour$totalMinute:$totalSeconds';
return videoLength;
}
Expand Down
5 changes: 4 additions & 1 deletion lib/src/controllers/pod_video_quality_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ class _PodVideoQualityController extends _PodVideoController {
podVideoStateChanger(PodVideoState.paused);
podVideoStateChanger(PodVideoState.loading);
playingVideoUrl = _videoQualityUrl;
_videoCtr = VideoPlayerController.networkUrl(Uri.parse(_videoQualityUrl));
_videoCtr = VideoPlayerController.networkUrl(
Uri.parse(_videoQualityUrl),
viewType: _videoViewType,
);
await _videoCtr?.initialize();
_videoDuration = _videoCtr?.value.duration ?? Duration.zero;
_videoCtr?.addListener(videoListner);
Expand Down
16 changes: 16 additions & 0 deletions lib/src/models/play_video_from.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class PlayVideoFrom {
final VideoPlayerOptions? videoPlayerOptions;
final Map<String, String> httpHeaders;
final bool live;
final VideoViewType? viewType;

const PlayVideoFrom._({
required this.playerType,
Expand All @@ -27,6 +28,7 @@ class PlayVideoFrom {
this.closedCaptionFile,
this.videoPlayerOptions,
this.httpHeaders = const {},
this.viewType,
});

factory PlayVideoFrom.network(
Expand All @@ -35,6 +37,7 @@ class PlayVideoFrom {
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
Map<String, String> httpHeaders = const {},
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
playerType: PodVideoPlayerType.network,
Expand All @@ -43,6 +46,7 @@ class PlayVideoFrom {
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
httpHeaders: httpHeaders,
viewType: viewType,
);
}

Expand All @@ -51,13 +55,15 @@ class PlayVideoFrom {
String? package,
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
playerType: PodVideoPlayerType.asset,
dataSource: dataSource,
package: package,
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
viewType: viewType,
);
}

Expand All @@ -67,12 +73,14 @@ class PlayVideoFrom {
File file, {
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
file: file,
playerType: PodVideoPlayerType.file,
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
viewType: viewType,
);
}

Expand All @@ -83,6 +91,7 @@ class PlayVideoFrom {
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
Map<String, String> httpHeaders = const {},
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
playerType: PodVideoPlayerType.vimeo,
Expand All @@ -92,6 +101,7 @@ class PlayVideoFrom {
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
httpHeaders: httpHeaders,
viewType: viewType,
);
}

Expand All @@ -101,6 +111,7 @@ class PlayVideoFrom {
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
Map<String, String> httpHeaders = const {},
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
playerType: PodVideoPlayerType.vimeoPrivateVideos,
Expand All @@ -109,6 +120,7 @@ class PlayVideoFrom {
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
httpHeaders: httpHeaders,
viewType: viewType,
);
}
factory PlayVideoFrom.youtube(
Expand All @@ -118,6 +130,7 @@ class PlayVideoFrom {
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
Map<String, String> httpHeaders = const {},
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
live: live,
Expand All @@ -127,6 +140,7 @@ class PlayVideoFrom {
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
httpHeaders: httpHeaders,
viewType: viewType,
);
}
factory PlayVideoFrom.networkQualityUrls({
Expand All @@ -135,6 +149,7 @@ class PlayVideoFrom {
Future<ClosedCaptionFile>? closedCaptionFile,
VideoPlayerOptions? videoPlayerOptions,
Map<String, String> httpHeaders = const {},
VideoViewType? viewType,
}) {
return PlayVideoFrom._(
playerType: PodVideoPlayerType.networkQualityUrls,
Expand All @@ -143,6 +158,7 @@ class PlayVideoFrom {
closedCaptionFile: closedCaptionFile,
videoPlayerOptions: videoPlayerOptions,
httpHeaders: httpHeaders,
viewType: viewType,
);
}
}
8 changes: 8 additions & 0 deletions lib/src/models/pod_player_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ class PodPlayerConfig {
final bool forcedVideoFocus;
final bool wakelockEnabled;

/// Disable keyboard shortcuts on web (Space, M, F, Esc, Arrow keys).
/// When true, keyboard shortcuts are disabled to prevent interference with form inputs.
/// Default value is true (shortcuts disabled).
final bool disableKeyboardShortcuts;

/// Initial video quality priority. The first available option will be used,
/// from start to the end of this list. If all options informed are not
/// available or if nothing is provided, 360p is used.
Expand All @@ -16,6 +21,7 @@ class PodPlayerConfig {
this.isLooping = false,
this.forcedVideoFocus = false,
this.wakelockEnabled = true,
this.disableKeyboardShortcuts = true,
this.videoQualityPriority = const [1080, 720, 360],
});

Expand All @@ -24,13 +30,15 @@ class PodPlayerConfig {
bool? isLooping,
bool? forcedVideoFocus,
bool? wakelockEnabled,
bool? disableKeyboardShortcuts,
List<int>? videoQualityPriority,
}) {
return PodPlayerConfig(
autoPlay: autoPlay ?? this.autoPlay,
isLooping: isLooping ?? this.isLooping,
forcedVideoFocus: forcedVideoFocus ?? this.forcedVideoFocus,
wakelockEnabled: wakelockEnabled ?? this.wakelockEnabled,
disableKeyboardShortcuts: disableKeyboardShortcuts ?? this.disableKeyboardShortcuts,
videoQualityPriority: videoQualityPriority ?? this.videoQualityPriority,
);
}
Expand Down