diff --git a/README.md b/README.md index cb8c9378..94ba7419 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ flutter build [linux|windows|macos|android|ios] The automated build process is done using GitHub Actions. You may find the workflow [here](.github/workflows/main.yml). The workflow builds the app for all supported platforms & uploads the artifacts to the release page. -On Linux, a Flutter executable with different environment variables is used to build the app for different distributions. This tells the app how the system is configured and how it should install updates. To run for Linux, you need to provide the following environment variables based on your system, where `[DISTRO_ENV]` can be `appimage` (AppImage), `deb` (Debian), `rpm` (RedHat) or `tar.gz` (Tarball). +On Linux, a Flutter executable with different environment variables is used to build the app for different distributions. This tells the app how the system is configured and how it should install updates. To run for Linux, you need to provide the following environment variables based on your system, where `[DISTRO_ENV]` can be `appimage` (AppImage), `deb` (Debian), `rpm` (RedHat), `tar.gz` (Tarball) or `pi` (Raspberry Pi). ```bash flutter run --dart-define-from-file=linux/env/[DISTRO_ENV].json diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index fa1aec86..6dbc1bb5 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -19,6 +19,7 @@ import screen_brightness_macos import screen_retriever import system_date_time_format import url_launcher_macos +import video_player_avfoundation import wakelock_plus import window_manager @@ -37,6 +38,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) SystemDateTimeFormatPlugin.register(with: registry.registrar(forPlugin: "SystemDateTimeFormatPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/packages/unity_video_player/unity_video_player/CHANGELOG.md b/packages/unity_video_player/unity_video_player/CHANGELOG.md deleted file mode 100644 index 17139a01..00000000 --- a/packages/unity_video_player/unity_video_player/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 0.0.1 - -* Initial implementation diff --git a/packages/unity_video_player/unity_video_player/LICENSE b/packages/unity_video_player/unity_video_player/LICENSE deleted file mode 100644 index ba75c69f..00000000 --- a/packages/unity_video_player/unity_video_player/LICENSE +++ /dev/null @@ -1 +0,0 @@ -TODO: Add your license here. diff --git a/packages/unity_video_player/unity_video_player/pubspec.yaml b/packages/unity_video_player/unity_video_player/pubspec.yaml index 4b06d331..f8c8ac98 100644 --- a/packages/unity_video_player/unity_video_player/pubspec.yaml +++ b/packages/unity_video_player/unity_video_player/pubspec.yaml @@ -14,6 +14,8 @@ dependencies: sdk: flutter unity_video_player_main: path: ../unity_video_player_main + unity_video_player_flutter: + path: ../unity_video_player_flutter dev_dependencies: flutter_test: @@ -30,6 +32,8 @@ flutter: macos: default_package: unity_video_player_main linux: - default_package: unity_video_player_main + default_package: unity_video_player_flutter windows: default_package: unity_video_player_main + web: + default_package: unity_video_player_main diff --git a/packages/unity_video_player/unity_video_player_flutter/.gitignore b/packages/unity_video_player/unity_video_player_flutter/.gitignore new file mode 100644 index 00000000..ac5aa989 --- /dev/null +++ b/packages/unity_video_player/unity_video_player_flutter/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/packages/unity_video_player/unity_video_player_flutter/.metadata b/packages/unity_video_player/unity_video_player_flutter/.metadata new file mode 100644 index 00000000..5512c947 --- /dev/null +++ b/packages/unity_video_player/unity_video_player_flutter/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "6cf9ab02baecddfa3daf0c1498e62b9dc617970d" + channel: "master" + +project_type: package diff --git a/packages/unity_video_player/unity_video_player_flutter/README.md b/packages/unity_video_player/unity_video_player_flutter/README.md new file mode 100644 index 00000000..6d8f7f72 --- /dev/null +++ b/packages/unity_video_player/unity_video_player_flutter/README.md @@ -0,0 +1,3 @@ +`unity_video_player` imeplementation with `video_player`. + +This was created to be used in the Raspberry Pi, but it should work on any platform. \ No newline at end of file diff --git a/packages/unity_video_player/unity_video_player_flutter/analysis_options.yaml b/packages/unity_video_player/unity_video_player_flutter/analysis_options.yaml new file mode 100644 index 00000000..a5744c1c --- /dev/null +++ b/packages/unity_video_player/unity_video_player_flutter/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart b/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart new file mode 100644 index 00000000..09999a61 --- /dev/null +++ b/packages/unity_video_player/unity_video_player_flutter/lib/unity_video_player_flutter.dart @@ -0,0 +1,241 @@ +library unity_video_player_flutter; + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterpi_gstreamer_video_player/flutterpi_gstreamer_video_player.dart'; +import 'package:unity_video_player_main/unity_video_player_main.dart'; +import 'package:video_player/video_player.dart'; +import 'package:unity_video_player_platform_interface/unity_video_player_platform_interface.dart'; + +class UnityVideoPlayerFlutterInterface extends UnityVideoPlayerInterface { + /// Registers this class as the default instance of [UnityVideoPlayerInterface]. + static void registerWith() { + if ('pi' case const String.fromEnvironment('linux_environment')) { + UnityVideoPlayerInterface.instance = UnityVideoPlayerFlutterInterface(); + return; + } + UnityVideoPlayerInterface.instance = UnityVideoPlayerMediaKitInterface(); + } + + @override + Future initialize() async { + FlutterpiVideoPlayer.registerWith(); + } + + @override + UnityVideoPlayer createPlayer({ + int? width, + int? height, + bool enableCache = false, + RTSPProtocol? rtspProtocol, + VoidCallback? onReload, + String? title, + }) { + final player = UnityVideoPlayerFlutter( + width: width, + height: height, + enableCache: enableCache, + title: title, + ); + UnityVideoPlayerInterface.registerPlayer(player); + return player; + } + + @override + Widget createVideoView({ + Key? key, + required covariant UnityVideoPlayerFlutter player, + UnityVideoFit fit = UnityVideoFit.contain, + UnityVideoPaneBuilder? paneBuilder, + UnityVideoBuilder? videoBuilder, + Color color = const Color(0xFF000000), + }) { + videoBuilder ??= (context, video) => video; + + return Builder(builder: (context) { + return Stack(children: [ + Positioned.fill( + child: videoBuilder!( + context, + ColoredBox( + color: color, + child: player.player == null + ? const SizedBox.expand() + : VideoPlayer(player.player!), + ), + ), + ), + if (paneBuilder != null) + Positioned.fill( + child: Material( + type: MaterialType.transparency, + child: paneBuilder(context, player), + ), + ), + ]); + }); + } +} + +class UnityVideoPlayerFlutter extends UnityVideoPlayer { + VideoPlayerController? player; + + final _videoStream = StreamController.broadcast(); + + UnityVideoPlayerFlutter({ + super.width, + super.height, + bool enableCache = false, + RTSPProtocol? rtspProtocol, + String? title, + }); + + @override + String? get dataSource => player?.dataSource; + + @override + Stream get onError => _videoStream.stream + .where((v) => v.errorDescription != null) + .map((e) => e.errorDescription!); + + @override + Duration get duration => player?.value.duration ?? Duration.zero; + + @override + Stream get onDurationUpdate => + _videoStream.stream.map((_) => duration); + + @override + Duration get currentPos => player?.value.position ?? Duration.zero; + + @override + Stream get onCurrentPosUpdate => + _videoStream.stream.map((_) => currentPos); + + @override + bool get isBuffering => player?.value.isBuffering ?? false; + + @override + Duration get currentBuffer => + player?.value.buffered.last.end ?? Duration.zero; + + @override + Stream get onBufferUpdate => + _videoStream.stream.map((_) => currentBuffer); + + @override + bool get isSeekable => duration > Duration.zero; + + @override + Stream get onBufferStateUpdate => + _videoStream.stream.map((_) => isBuffering); + + @override + bool get isPlaying => player?.value.isPlaying ?? false; + + @override + Stream get onPlayingStateUpdate => + _videoStream.stream.map((_) => isPlaying); + + @override + Future setDataSource(String url, {bool autoPlay = true}) async { + if (url == dataSource) return Future.value(); + debugPrint('Playing $url'); + + if (player != null) { + await player?.dispose(); + } + + player = VideoPlayerController.networkUrl(Uri.parse(url)); + await player!.initialize(); + notifyListeners(); + player!.addListener(() { + _videoStream.add(player!.value); + }); + if (autoPlay) { + await player!.play(); + } + } + + @override + Future setMultipleDataSource(List url, {bool autoPlay = true}) { + throw UnsupportedError( + 'setMultipleDataSource is not supported on this platform', + ); + } + + // Volume in media kit goes from 0 to 100 + @override + Future setVolume(double volume) async => + await player?.setVolume(volume); + + @override + double get volume => (player?.value.volume ?? 0.0); + + @override + Stream get volumeStream => _videoStream.stream.map((_) => volume); + + @override + double get fps => 0.0; + @override + Stream get fpsStream => + throw UnsupportedError('Fps is not implemented on this platform'); + + @override + double get aspectRatio => player?.value.aspectRatio ?? 1.0; + + @override + Future setSpeed(double speed) async => + await player?.setPlaybackSpeed(speed); + @override + Future seekTo(Duration position) async => + await player?.seekTo(position); + + @override + Future setSize(Size size) => Future.value(); + + @override + Future start() async => await player?.play(); + + @override + Future pause() async => await player?.pause(); + + @override + Future release() async { + if (!kIsWeb && Platform.isLinux) { + await pause(); + await Future.delayed(const Duration(milliseconds: 150)); + } + } + + @override + Future reset() async { + await pause(); + await seekTo(Duration.zero); + } + + @override + Future resetCrop() => crop(-1, -1, -1); + + /// Crops the current video into a box at the given row and column + @override + Future crop(int row, int col, int size) async { + throw UnsupportedError('Cropping is not implemented on this platform'); + } + + @override + bool get isCropped { + throw UnsupportedError('Cropping is not implemented on this platform'); + } + + @override + Future dispose() async { + await release(); + await super.dispose(); + await _videoStream.close(); + UnityVideoPlayerInterface.unregisterPlayer(this); + } +} diff --git a/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml b/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml new file mode 100644 index 00000000..fa3f833f --- /dev/null +++ b/packages/unity_video_player/unity_video_player_flutter/pubspec.yaml @@ -0,0 +1,27 @@ +name: unity_video_player_flutter +description: "unity_video_player implementation with video_player" +version: 0.0.1 +homepage: + +publish_to: "none" + +environment: + sdk: '>=3.3.0-149.0.dev <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + unity_video_player_platform_interface: + path: ../unity_video_player_platform_interface/ + unity_video_player_main: + path: ../unity_video_player_main + video_player: ^2.8.1 + flutterpi_gstreamer_video_player: ^0.1.1+1 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^3.0.0 + +flutter: diff --git a/packages/unity_video_player/unity_video_player_main/LICENSE b/packages/unity_video_player/unity_video_player_main/LICENSE deleted file mode 100644 index ba75c69f..00000000 --- a/packages/unity_video_player/unity_video_player_main/LICENSE +++ /dev/null @@ -1 +0,0 @@ -TODO: Add your license here. diff --git a/packages/unity_video_player/unity_video_player_main/README.md b/packages/unity_video_player/unity_video_player_main/README.md index 02fe8eca..b63191bb 100644 --- a/packages/unity_video_player/unity_video_player_main/README.md +++ b/packages/unity_video_player/unity_video_player_main/README.md @@ -1,39 +1 @@ - - -TODO: Put a short description of the package here that helps potential users -know whether this package might be useful for them. - -## Features - -TODO: List what your package can do. Maybe include images, gifs, or videos. - -## Getting started - -TODO: List prerequisites and provide or point to information on how to -start using the package. - -## Usage - -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. - -```dart -const like = 'sample'; -``` - -## Additional information - -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +`unity_video_player` implementation with `media_kit` \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 4c097288..81dd4979 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -161,6 +161,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" dbus: dependency: transitive description: @@ -349,6 +357,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutterpi_gstreamer_video_player: + dependency: transitive + description: + name: flutterpi_gstreamer_video_player + sha256: "1f70015783e8a9c4805ee1590d351131bf83853a53fc6bc7b93c3a325804f061" + url: "https://pub.dev" + source: hosted + version: "0.1.1+1" get_it: dependency: transitive description: @@ -389,6 +405,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" http: dependency: "direct main" description: @@ -958,6 +982,13 @@ packages: relative: true source: path version: "0.0.1" + unity_video_player_flutter: + dependency: transitive + description: + path: "packages/unity_video_player/unity_video_player_flutter" + relative: true + source: path + version: "0.0.1" unity_video_player_main: dependency: transitive description: @@ -1076,6 +1107,46 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + video_player: + dependency: transitive + description: + name: video_player + sha256: e16f0a83601a78d165dabc17e4dac50997604eb9e4cc76e10fa219046b70cef3 + url: "https://pub.dev" + source: hosted + version: "2.8.1" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "3fe89ab07fdbce786e7eb25b58532d6eaf189ceddc091cb66cba712f8d9e8e55" + url: "https://pub.dev" + source: hosted + version: "2.4.10" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: "01a57940e1dabc8769ccd457c4ae9ea50274e7d5a7617f7820dae5fe1d8436ae" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: be72301bf2c0150ab35a8c34d66e5a99de525f6de1e8d27c0672b836fe48f73a + url: "https://pub.dev" + source: hosted + version: "6.2.1" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: ab7a462b07d9ca80bed579e30fb3bce372468f1b78642e0911b10600f2c5cb5b + url: "https://pub.dev" + source: hosted + version: "2.1.2" vm_service: dependency: transitive description: @@ -1173,5 +1244,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.3.0-149.0.dev <4.0.0" + flutter: ">=3.16.0"