From 1a2438cbc4da567aed9d8d842f748af7fc94ea79 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Mon, 23 Aug 2021 12:04:39 +0200 Subject: [PATCH] Prepare fullscreen support --- lib/dart_vlc.dart | 14 +++++---- lib/src/widgets/controls.dart | 58 ++++++++++++++++++++++++++++++++--- lib/src/widgets/video.dart | 33 +++++++++++--------- 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/lib/dart_vlc.dart b/lib/dart_vlc.dart index 1b260440..c9341c3e 100644 --- a/lib/dart_vlc.dart +++ b/lib/dart_vlc.dart @@ -20,6 +20,7 @@ import 'package:dart_vlc_ffi/src/internal/ffi.dart' as FFI; import 'package:dart_vlc_ffi/dart_vlc_ffi.dart' as FFI; export 'package:dart_vlc_ffi/dart_vlc_ffi.dart' hide DartVLC, Player; export 'package:dart_vlc/src/widgets/video.dart'; +export 'package:dart_vlc/src/widgets/controls.dart'; /// Platform channel for using [Texture] & flutter::TextureRegistrar on Windows. final MethodChannel _channel = MethodChannel('dart_vlc'); @@ -103,15 +104,16 @@ abstract class DartVLC { final libraryPath = path.join( path.dirname(Platform.resolvedExecutable), 'dart_vlc_plugin.dll'); FFI.DartVLC.initialize(libraryPath); - } - else if (Platform.isLinux) { + } else if (Platform.isLinux) { final libraryPath = path.join(path.dirname(Platform.resolvedExecutable), 'lib', 'libdart_vlc_plugin.so'); FFI.DartVLC.initialize(libraryPath); - } - else if(Platform.isMacOS) { - final libraryPath = path.join(path.dirname(path.dirname(Platform.resolvedExecutable)), - 'Frameworks', 'dart_vlc.framework', 'dart_vlc'); + } else if (Platform.isMacOS) { + final libraryPath = path.join( + path.dirname(path.dirname(Platform.resolvedExecutable)), + 'Frameworks', + 'dart_vlc.framework', + 'dart_vlc'); FFI.DartVLC.initialize(libraryPath); } } diff --git a/lib/src/widgets/controls.dart b/lib/src/widgets/controls.dart index b0a5589e..51c6a245 100644 --- a/lib/src/widgets/controls.dart +++ b/lib/src/widgets/controls.dart @@ -6,9 +6,30 @@ import 'package:dart_vlc_ffi/src/device.dart'; import 'package:dart_vlc_ffi/src/player.dart'; import 'package:dart_vlc_ffi/src/playerState/playerState.dart'; +class FullscreenState { + final bool isFullscreen; + final bool isFullscreenAllowed; + const FullscreenState( + {required this.isFullscreen, required this.isFullscreenAllowed}); + + FullscreenState copyWith({bool? isFullscreen, bool? isFullscreenAllowed}) => + FullscreenState( + isFullscreen: isFullscreen ?? this.isFullscreen, + isFullscreenAllowed: isFullscreenAllowed ?? this.isFullscreenAllowed); +} + +abstract class FullscreenController extends ValueNotifier { + FullscreenController() + : super(FullscreenState(isFullscreenAllowed: true, isFullscreen: false)); + + bool get isFullscreen => value.isFullscreen; + void toggleFullscreen(); +} + class Control extends StatefulWidget { final Widget child; final Player player; + final FullscreenController? fullscreenController; final bool? showTimeLeft; final double? progressBarThumbRadius; final double? progressBarThumbGlowRadius; @@ -25,6 +46,7 @@ class Control extends StatefulWidget { Control({ required this.child, required this.player, + this.fullscreenController, required this.showTimeLeft, required this.progressBarThumbRadius, required this.progressBarThumbGlowRadius, @@ -124,6 +146,34 @@ class ControlState extends State with SingleTickerProviderStateMixin { ), ), ), + if (widget.fullscreenController != null) + Positioned( + left: 16, + bottom: 10, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ValueListenableBuilder( + valueListenable: widget.fullscreenController!, + builder: (context, state, _) => IconButton( + color: Colors.white, + disabledColor: Colors.white, + iconSize: 30, + icon: Icon( + state.isFullscreen + ? Icons.fullscreen_exit + : Icons.fullscreen, + ), + onPressed: state.isFullscreenAllowed + ? () { + widget.fullscreenController + ?.toggleFullscreen(); + } + : null, + )), + ], + ), + ), Positioned( left: 0, right: 0, @@ -247,8 +297,8 @@ class ControlState extends State with SingleTickerProviderStateMixin { ), ), Positioned( - right: 15, - bottom: 12.5, + right: 16, + bottom: 10, child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -260,7 +310,7 @@ class ControlState extends State with SingleTickerProviderStateMixin { backgroundColor: widget.volumeBackgroundColor, ), PopupMenuButton( - iconSize: 24, + iconSize: 28, icon: Icon(Icons.speaker, color: Colors.white), onSelected: (Device device) { player.setDevice(device); @@ -361,7 +411,6 @@ class _VolumeControlState extends State { setState(() => _showVolume = false); }, child: Container( - width: 60, height: 250, child: Card( color: widget.backgroundColor, @@ -400,6 +449,7 @@ class _VolumeControlState extends State { }, child: IconButton( color: Colors.white, + iconSize: 28, onPressed: () => muteUnmute(), icon: Icon(getIcon()), ), diff --git a/lib/src/widgets/video.dart b/lib/src/widgets/video.dart index 5edcfffb..0c2001ba 100644 --- a/lib/src/widgets/video.dart +++ b/lib/src/widgets/video.dart @@ -21,7 +21,7 @@ class VideoFrame { final int videoHeight; final Uint8List byteArray; - VideoFrame({ + const VideoFrame({ required this.playerId, required this.videoWidth, required this.videoHeight, @@ -87,43 +87,46 @@ class Video extends StatefulWidget { // Built-In video controls. final bool showControls; - // Radius of the progressbar's thumb + /// Radius of the progressbar's thumb final double? progressBarThumbRadius; - // Radius of the progressbar's glow of the thumb + /// Radius of the progressbar's glow of the thumb final double? progressBarThumbGlowRadius; - // Active color of the progress bar + /// Active color of the progress bar final Color? progressBarActiveColor; - // Inactive color of the progress bar + /// Inactive color of the progress bar final Color? progressBarInactiveColor; - // Thumb color of the progress bar + /// Thumb color of the progress bar final Color? progressBarThumbColor; // Thumb's glow color of the progress bar final Color? progressBarThumbGlowColor; - // TextStyle for the Progress Bar + /// TextStyle for the Progress Bar final TextStyle progressBarTextStyle; - // Active color of the volume slider + /// Active color of the volume slider final Color? volumeActiveColor; - // Inactive color of the volume slider + /// Inactive color of the volume slider final Color? volumeInactiveColor; - // Background color of the volume slider + /// Background color of the volume slider final Color volumeBackgroundColor; - // Thumb color of the volume slider + /// Thumb color of the volume slider final Color? volumeThumbColor; - // if you want the progress bar to display the time left while playing - // instead of the total time, set this to true + /// if you want the progress bar to display the time left while playing + /// instead of the total time, set this to true final bool showTimeLeft; + /// An optional [FullscreenController]. + final FullscreenController? fullscreenController; + Video({ @Deprecated('playerId is deprecated. Use player instead.') int? playerId, Player? player, @@ -146,6 +149,7 @@ class Video extends StatefulWidget { this.showTimeLeft = false, this.progressBarTextStyle = const TextStyle(), this.filterQuality = FilterQuality.low, + this.fullscreenController, Key? key, }) : player = player ?? players[playerId]! as Player, super(key: key); @@ -175,6 +179,7 @@ abstract class _VideoStateBase extends State