Audio-only mpv core on every platform (dedicated com.plezy/mpv_audio_player channels): parameterized android/windows/ linux mpv plugins and a new apple MpvAudioPlayerCore, all skipping video/window paths (vid=no, audio-display=no, gapless-audio=weak). MusicPlaybackService drives an in-memory queue with shuffle/repeat, file-loaded-event gapless arming (property edges coalesce and the android bridge drops them), per-track progress reporting, OS media controls, audio focus, sleep timer, and error auto-skip. PlaybackCoordinator enforces one live native player: starting video disposes the audio core first.
76 lines
3.2 KiB
Dart
76 lines
3.2 KiB
Dart
import 'dart:async';
|
|
|
|
import '../models.dart';
|
|
import 'player_streams.dart';
|
|
|
|
mixin PlayerStreamControllersMixin {
|
|
final playingController = StreamController<bool>.broadcast();
|
|
final completedController = StreamController<bool>.broadcast();
|
|
final bufferingController = StreamController<bool>.broadcast();
|
|
final positionController = StreamController<Duration>.broadcast();
|
|
final durationController = StreamController<Duration>.broadcast();
|
|
final seekableController = StreamController<bool>.broadcast();
|
|
final bufferController = StreamController<Duration>.broadcast();
|
|
final volumeController = StreamController<double>.broadcast();
|
|
final rateController = StreamController<double>.broadcast();
|
|
final tracksController = StreamController<Tracks>.broadcast();
|
|
final trackController = StreamController<TrackSelection>.broadcast();
|
|
final logController = StreamController<PlayerLog>.broadcast();
|
|
final errorController = StreamController<PlayerError>.broadcast();
|
|
final audioDeviceController = StreamController<AudioDevice>.broadcast();
|
|
final audioDevicesController = StreamController<List<AudioDevice>>.broadcast();
|
|
final bufferRangesController = StreamController<List<BufferRange>>.broadcast();
|
|
final playbackRestartController = StreamController<void>.broadcast();
|
|
final fileLoadedController = StreamController<void>.broadcast();
|
|
final backendSwitchedController = StreamController<void>.broadcast();
|
|
final trackTransitionController = StreamController<String>.broadcast();
|
|
|
|
PlayerStreams createStreams() {
|
|
return PlayerStreams(
|
|
playing: playingController.stream,
|
|
completed: completedController.stream,
|
|
buffering: bufferingController.stream,
|
|
position: positionController.stream,
|
|
duration: durationController.stream,
|
|
seekable: seekableController.stream,
|
|
buffer: bufferController.stream,
|
|
volume: volumeController.stream,
|
|
rate: rateController.stream,
|
|
tracks: tracksController.stream,
|
|
track: trackController.stream,
|
|
log: logController.stream,
|
|
error: errorController.stream,
|
|
audioDevice: audioDeviceController.stream,
|
|
audioDevices: audioDevicesController.stream,
|
|
bufferRanges: bufferRangesController.stream,
|
|
playbackRestart: playbackRestartController.stream,
|
|
fileLoaded: fileLoadedController.stream,
|
|
backendSwitched: backendSwitchedController.stream,
|
|
trackTransition: trackTransitionController.stream,
|
|
);
|
|
}
|
|
|
|
Future<void> closeStreamControllers() async {
|
|
await playingController.close();
|
|
await completedController.close();
|
|
await bufferingController.close();
|
|
await positionController.close();
|
|
await durationController.close();
|
|
await seekableController.close();
|
|
await bufferController.close();
|
|
await volumeController.close();
|
|
await rateController.close();
|
|
await tracksController.close();
|
|
await trackController.close();
|
|
await logController.close();
|
|
await errorController.close();
|
|
await audioDeviceController.close();
|
|
await audioDevicesController.close();
|
|
await bufferRangesController.close();
|
|
await playbackRestartController.close();
|
|
await fileLoadedController.close();
|
|
await backendSwitchedController.close();
|
|
await trackTransitionController.close();
|
|
}
|
|
}
|