mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 21:48:14 -08:00
167 lines
5 KiB
Dart
167 lines
5 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:fladder/models/items/media_streams_model.dart';
|
|
import 'package:fladder/models/playback/playback_model.dart';
|
|
import 'package:fladder/models/settings/video_player_settings.dart';
|
|
import 'package:fladder/src/video_player_helper.g.dart';
|
|
import 'package:fladder/wrappers/players/base_player.dart';
|
|
import 'package:fladder/wrappers/players/player_states.dart';
|
|
|
|
class NativePlayer extends BasePlayer implements VideoPlayerListenerCallback {
|
|
final player = VideoPlayerApi();
|
|
|
|
@override
|
|
Future<void> dispose() async {
|
|
return NativeVideoActivity().disposeActivity();
|
|
}
|
|
|
|
@override
|
|
Future<void> init(VideoPlayerSettingsModel settings) async => VideoPlayerListenerCallback.setUp(this);
|
|
|
|
@override
|
|
Future<void> loop(bool loop) {
|
|
return player.setLooping(loop);
|
|
}
|
|
|
|
@override
|
|
Future<void> loadVideo(String url, bool play) async => player.open(url, play);
|
|
|
|
@override
|
|
Future<void> open(BuildContext newContext) async => NativeVideoActivity().launchActivity();
|
|
|
|
@override
|
|
Future<void> pause() {
|
|
return player.pause();
|
|
}
|
|
|
|
@override
|
|
Future<void> play() => player.play();
|
|
|
|
@override
|
|
Future<void> playOrPause() async {
|
|
return;
|
|
}
|
|
|
|
@override
|
|
Future<void> seek(Duration position) {
|
|
return player.seekTo(position.inMilliseconds);
|
|
}
|
|
|
|
@override
|
|
Future<int> setAudioTrack(AudioStreamModel? model, PlaybackModel playbackModel) async {
|
|
return 0;
|
|
}
|
|
|
|
@override
|
|
Future<void> setSpeed(double speed) async {}
|
|
|
|
@override
|
|
Future<int> setSubtitleTrack(SubStreamModel? model, PlaybackModel playbackModel) async {
|
|
return 0;
|
|
}
|
|
|
|
@override
|
|
Future<void> setVolume(double volume) async {
|
|
return player.setVolume(volume);
|
|
}
|
|
|
|
@override
|
|
Future<void> stop() async {
|
|
return player.stop();
|
|
}
|
|
|
|
@override
|
|
Widget? subtitles(bool showOverlay, {GlobalKey<State<StatefulWidget>>? controlsKey}) => null;
|
|
|
|
@override
|
|
Widget? videoWidget(Key key, BoxFit fit) => null;
|
|
|
|
@override
|
|
void onPlaybackStateChanged(PlaybackState state) {
|
|
lastState = lastState.update(
|
|
playing: state.playing,
|
|
position: Duration(milliseconds: state.position),
|
|
buffer: Duration(milliseconds: state.buffered),
|
|
buffering: state.buffering,
|
|
);
|
|
_stateController.add(lastState);
|
|
}
|
|
|
|
final StreamController<PlayerState> _stateController = StreamController.broadcast();
|
|
|
|
@override
|
|
Stream<PlayerState> get stateStream => _stateController.stream;
|
|
|
|
Future<void> sendPlaybackDataToNative(
|
|
BuildContext? context,
|
|
PlaybackModel model,
|
|
Duration startPosition,
|
|
) async {
|
|
final playableData = PlayableData(
|
|
id: model.item.id,
|
|
title: model.item.title,
|
|
subTitle: context != null ? model.item.label(context) : "",
|
|
logoUrl: model.item.getPosters?.logo?.path,
|
|
startPosition: startPosition.inMilliseconds,
|
|
description: model.item.overview.summary,
|
|
defaultAudioTrack: model.mediaStreams?.defaultAudioStreamIndex ?? 1,
|
|
nextVideo: model.nextVideo?.name,
|
|
previousVideo: model.previousVideo?.name,
|
|
audioTracks: model.audioStreams
|
|
?.map(
|
|
(audio) => AudioTrack(
|
|
name: audio.displayTitle,
|
|
languageCode: audio.language,
|
|
codec: audio.codec,
|
|
index: audio.index,
|
|
external: false,
|
|
),
|
|
)
|
|
.toList() ??
|
|
[],
|
|
defaultSubtrack: model.mediaStreams?.defaultSubStreamIndex ?? 1,
|
|
subtitleTracks: model.subStreams
|
|
?.map(
|
|
(sub) => SubtitleTrack(
|
|
name: sub.displayTitle,
|
|
languageCode: sub.language,
|
|
codec: sub.codec,
|
|
index: sub.index,
|
|
external: sub.isExternal,
|
|
url: sub.url,
|
|
),
|
|
)
|
|
.toList() ??
|
|
[],
|
|
segments: model.mediaSegments?.segments
|
|
.map(
|
|
(e) => MediaSegment(
|
|
type: MediaSegmentType.values.firstWhere((element) => element.name == e.type.name),
|
|
name: context != null ? e.type.label(context) : e.type.name,
|
|
start: e.start.inMilliseconds,
|
|
end: e.end.inMilliseconds,
|
|
),
|
|
)
|
|
.toList() ??
|
|
[],
|
|
trickPlayModel: model.trickPlay != null
|
|
? TrickPlayModel(
|
|
width: model.trickPlay!.width,
|
|
height: model.trickPlay!.height,
|
|
tileWidth: model.trickPlay!.tileWidth,
|
|
tileHeight: model.trickPlay!.tileHeight,
|
|
thumbnailCount: model.trickPlay!.thumbnailCount,
|
|
interval: model.trickPlay!.interval.inMilliseconds,
|
|
images: model.trickPlay?.images ?? [])
|
|
: null,
|
|
chapters: model.chapters
|
|
?.map((e) => Chapter(name: e.name, url: e.imageUrl, time: e.startPosition.inMilliseconds))
|
|
.toList() ??
|
|
[],
|
|
url: model.media?.url ?? "",
|
|
);
|
|
player.sendPlayableModel(playableData);
|
|
}
|
|
}
|