This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
melo-app/lib/services/audio_handler.dart
T
Dustin f23dc685cb v2.39 — Issue #8: Persistente Notification (nicht wegwischbar)
- MediaControl.stop aus compact-Controls entfernt (nur play/pause, prev, next)
- Notification bleibt auch bei Pause bestehen
Build: ✓ flutter analyze
2026-08-02 15:56:25 +02:00

92 lines
2.5 KiB
Dart

import 'dart:async';
import 'package:audio_service/audio_service.dart';
import 'package:just_audio/just_audio.dart';
import '../models/song.dart';
import 'player_service.dart';
/// Hintergrund-Audio-Handler für Sperrbildschirm & Benachrichtigung
class MeloAudioHandler extends BaseAudioHandler {
final PlayerService _player = PlayerService();
MeloAudioHandler() {
// Zustand vom Player an audio_service weiterleiten
_player.stateStream.listen(_updateState);
_player.positionStream.listen((pos) {
if (_playing) {
playbackState.add(playbackState.value.copyWith(
updatePosition: pos,
));
}
});
_player.onSongWechsel.listen((song) {
if (song != null) {
mediaItem.add(_toMediaItem(song));
}
});
}
bool _playing = false;
void _updateState(PlayerState state) {
_playing = state.playing;
playbackState.add(PlaybackState(
controls: _playing
? [MediaControl.pause, MediaControl.skipToPrevious, MediaControl.skipToNext]
: [MediaControl.play, MediaControl.skipToPrevious, MediaControl.skipToNext],
systemActions: const {MediaAction.seek},
androidCompactActionIndices: const [0, 1, 2],
processingState: _playing ? AudioProcessingState.ready : AudioProcessingState.idle,
playing: _playing,
speed: 1.0,
));
}
MediaItem _toMediaItem(Song song) => MediaItem(
id: song.id?.toString() ?? '0',
album: song.album.isEmpty ? 'Melo' : song.album,
title: song.titel,
artist: song.kuenstler,
duration: Duration(seconds: song.dauerSekunden),
artUri: song.coverPfad != null ? Uri.file(song.coverPfad!) : null,
);
@override
Future<void> play() async {
if (_player.aktuellerSong != null) {
_playing = true;
await _player.playPause();
}
}
@override
Future<void> pause() async {
_playing = false;
await _player.playPause();
}
@override
Future<void> stop() async {
_playing = false;
await _player.playPause();
playbackState.add(playbackState.value.copyWith(
controls: [MediaControl.play],
playing: false,
processingState: AudioProcessingState.idle,
));
}
@override
Future<void> seek(Duration position) async {
_player.spiele(_player.aktuellerSong!, position: position.inSeconds);
}
@override
Future<void> skipToNext() => _player.naechstes();
@override
Future<void> skipToPrevious() => _player.vorheriges();
// Exposed for the ViewModel
PlayerService get player => _player;
}