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

linux(pi): implement unity_video_player_flutter #194

Merged
merged 4 commits into from
Jan 2, 2024
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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"))
}
3 changes: 0 additions & 3 deletions packages/unity_video_player/unity_video_player/CHANGELOG.md

This file was deleted.

1 change: 0 additions & 1 deletion packages/unity_video_player/unity_video_player/LICENSE

This file was deleted.

6 changes: 5 additions & 1 deletion packages/unity_video_player/unity_video_player/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
29 changes: 29 additions & 0 deletions packages/unity_video_player/unity_video_player_flutter/.gitignore
Original file line number Diff line number Diff line change
@@ -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/
10 changes: 10 additions & 0 deletions packages/unity_video_player/unity_video_player_flutter/.metadata
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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<void> 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<VideoPlayerValue>.broadcast();

UnityVideoPlayerFlutter({
super.width,
super.height,
bool enableCache = false,
RTSPProtocol? rtspProtocol,
String? title,
});

@override
String? get dataSource => player?.dataSource;

@override
Stream<String> get onError => _videoStream.stream
.where((v) => v.errorDescription != null)
.map((e) => e.errorDescription!);

@override
Duration get duration => player?.value.duration ?? Duration.zero;

@override
Stream<Duration> get onDurationUpdate =>
_videoStream.stream.map((_) => duration);

@override
Duration get currentPos => player?.value.position ?? Duration.zero;

@override
Stream<Duration> 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<Duration> get onBufferUpdate =>
_videoStream.stream.map((_) => currentBuffer);

@override
bool get isSeekable => duration > Duration.zero;

@override
Stream<bool> get onBufferStateUpdate =>
_videoStream.stream.map((_) => isBuffering);

@override
bool get isPlaying => player?.value.isPlaying ?? false;

@override
Stream<bool> get onPlayingStateUpdate =>
_videoStream.stream.map((_) => isPlaying);

@override
Future<void> 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<void> setMultipleDataSource(List<String> url, {bool autoPlay = true}) {
throw UnsupportedError(
'setMultipleDataSource is not supported on this platform',
);
}

// Volume in media kit goes from 0 to 100
@override
Future<void> setVolume(double volume) async =>
await player?.setVolume(volume);

@override
double get volume => (player?.value.volume ?? 0.0);

@override
Stream<double> get volumeStream => _videoStream.stream.map((_) => volume);

@override
double get fps => 0.0;
@override
Stream<double> get fpsStream =>
throw UnsupportedError('Fps is not implemented on this platform');

@override
double get aspectRatio => player?.value.aspectRatio ?? 1.0;

@override
Future<void> setSpeed(double speed) async =>
await player?.setPlaybackSpeed(speed);
@override
Future<void> seekTo(Duration position) async =>
await player?.seekTo(position);

@override
Future<void> setSize(Size size) => Future.value();

@override
Future<void> start() async => await player?.play();

@override
Future<void> pause() async => await player?.pause();

@override
Future<void> release() async {
if (!kIsWeb && Platform.isLinux) {
await pause();
await Future.delayed(const Duration(milliseconds: 150));
}
}

@override
Future<void> reset() async {
await pause();
await seekTo(Duration.zero);
}

@override
Future<void> resetCrop() => crop(-1, -1, -1);

/// Crops the current video into a box at the given row and column
@override
Future<void> 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<void> dispose() async {
await release();
await super.dispose();
await _videoStream.close();
UnityVideoPlayerInterface.unregisterPlayer(this);
}
}
Original file line number Diff line number Diff line change
@@ -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:

This file was deleted.

Loading