mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-17 11:16:33 -07:00
feature: Added LibMDK video player backend (#162)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
6e32018183
commit
da354437e3
53 changed files with 1499 additions and 1006 deletions
183
lib/wrappers/players/lib_mdk.dart
Normal file
183
lib/wrappers/players/lib_mdk.dart
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:fvp/fvp.dart' as fvp;
|
||||
import 'package:fvp/mdk.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import 'package:fladder/models/items/media_streams_model.dart';
|
||||
import 'package:fladder/models/playback/playback_model.dart';
|
||||
import 'package:fladder/wrappers/players/base_player.dart';
|
||||
import 'package:fladder/wrappers/players/player_states.dart';
|
||||
|
||||
class LibMDK extends BasePlayer {
|
||||
VideoPlayerController? _controller;
|
||||
late final player = Player();
|
||||
|
||||
bool externalSubEnabled = false;
|
||||
|
||||
final StreamController<PlayerState> _stateController = StreamController.broadcast();
|
||||
|
||||
@override
|
||||
Stream<PlayerState> get stateStream => _stateController.stream;
|
||||
|
||||
@override
|
||||
Future<void> init(Ref ref) async {
|
||||
dispose();
|
||||
fvp.registerWith(options: {
|
||||
'global': {'log': 'off'},
|
||||
'subtitleFontFile': libassFallbackFont,
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
_controller?.dispose();
|
||||
_controller = null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> open(String url, bool play) async {
|
||||
final validUrl = isValidUrl(url);
|
||||
if (validUrl != null) {
|
||||
_controller = VideoPlayerController.networkUrl(validUrl);
|
||||
} else {
|
||||
_controller = VideoPlayerController.file(File(url));
|
||||
}
|
||||
await _controller?.initialize();
|
||||
|
||||
_controller?.addListener(() => updateState());
|
||||
|
||||
if (play) {
|
||||
await _controller?.play();
|
||||
}
|
||||
return setState(lastState.update(
|
||||
buffering: true,
|
||||
));
|
||||
}
|
||||
|
||||
void setState(PlayerState state) {
|
||||
lastState = state;
|
||||
_stateController.add(state);
|
||||
}
|
||||
|
||||
void updateState() {
|
||||
setState(lastState.update(
|
||||
playing: _controller?.value.isPlaying ?? false,
|
||||
completed: _controller?.value.isCompleted ?? false,
|
||||
position: _controller?.value.position ?? Duration.zero,
|
||||
duration: _controller?.value.duration ?? Duration.zero,
|
||||
volume: (_controller?.value.volume ?? 1.0) * 100,
|
||||
rate: _controller?.value.playbackSpeed ?? 1.0,
|
||||
buffering: _controller?.value.isBuffering ?? true,
|
||||
buffer: _controller?.value.buffered.last.end ?? Duration.zero,
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> pause() async => _controller?.pause();
|
||||
@override
|
||||
Future<void> play() async => _controller?.play();
|
||||
@override
|
||||
Future<void> playOrPause() async => lastState.playing ? _controller?.pause() : _controller?.play();
|
||||
|
||||
@override
|
||||
Future<void> seek(Duration position) async => _controller?.seekTo(position);
|
||||
|
||||
@override
|
||||
Future<int> setAudioTrack(AudioStreamModel? model, PlaybackModel playbackModel) async {
|
||||
final wantedAudioStream = model ?? playbackModel.defaultAudioStream;
|
||||
if (wantedAudioStream == AudioStreamModel.no() || wantedAudioStream == null) {
|
||||
_controller?.setAudioTracks([-1]);
|
||||
return -1;
|
||||
} else {
|
||||
final indexOf = playbackModel.audioStreams?.indexOf(wantedAudioStream);
|
||||
if (indexOf != null) {
|
||||
_controller?.setAudioTracks([indexOf - 1]);
|
||||
}
|
||||
return wantedAudioStream.index;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setSpeed(double speed) async => _controller?.setPlaybackSpeed(speed);
|
||||
|
||||
@override
|
||||
Future<int> setSubtitleTrack(SubStreamModel? model, PlaybackModel playbackModel) async {
|
||||
final wantedSubtitle = model ?? playbackModel.defaultSubStream;
|
||||
if (wantedSubtitle == SubStreamModel.no()) {
|
||||
externalSubEnabled = false;
|
||||
_controller?.setSubtitleTracks([-1]);
|
||||
return -1;
|
||||
}
|
||||
if (wantedSubtitle != null) {
|
||||
if (wantedSubtitle.isExternal && wantedSubtitle.url != null) {
|
||||
externalSubEnabled = true;
|
||||
_controller?.setExternalSubtitle(wantedSubtitle.url!);
|
||||
return wantedSubtitle.index;
|
||||
} else {
|
||||
if (externalSubEnabled) {
|
||||
externalSubEnabled = false;
|
||||
_controller?.setExternalSubtitle("");
|
||||
}
|
||||
final indexOf = playbackModel.subStreams?.indexOf(wantedSubtitle);
|
||||
if (indexOf != null) {
|
||||
_controller?.setSubtitleTracks([indexOf - 1]);
|
||||
}
|
||||
return wantedSubtitle.index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async => _controller?.dispose();
|
||||
|
||||
@override
|
||||
Widget? videoWidget(
|
||||
Key key,
|
||||
BoxFit fit,
|
||||
) =>
|
||||
_controller == null
|
||||
? null
|
||||
: Container(
|
||||
key: key,
|
||||
color: Colors.transparent,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
FittedBox(
|
||||
fit: fit,
|
||||
alignment: Alignment.center,
|
||||
child: ValueListenableBuilder<VideoPlayerValue>(
|
||||
valueListenable: _controller!,
|
||||
builder: (context, value, child) {
|
||||
final aspectRatio = value.isInitialized ? value.aspectRatio : 1.77;
|
||||
return SizedBox(
|
||||
width: constraints.maxWidth,
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatio,
|
||||
child: VideoPlayer(_controller!),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget? subtitles(bool showOverlay) => null;
|
||||
|
||||
@override
|
||||
Future<void> setVolume(double volume) async => _controller?.setVolume(volume / 100);
|
||||
|
||||
@override
|
||||
Future<void> loop(bool loop) async => _controller?.setLooping(loop);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue