116 lines
3.3 KiB
Dart
116 lines
3.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:audio_session/audio_session.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:just_audio_background/just_audio_background.dart';
|
|
import 'package:just_audio/just_audio.dart';
|
|
|
|
enum StreamingPlaybackStatus { stopped, buffering, playing }
|
|
|
|
class StreamingAudioBusinessObject extends ChangeNotifier {
|
|
StreamingAudioBusinessObject({
|
|
this.streamUrl = 'https://kryz.out.airtime.pro/kryz_a',
|
|
}) {
|
|
_playerStateSubscription = _player.playerStateStream.listen((state) {
|
|
_setPlaybackStatus(_mapPlayerStateToStatus(state));
|
|
});
|
|
}
|
|
|
|
final String streamUrl;
|
|
final AudioPlayer _player = AudioPlayer();
|
|
late final StreamSubscription<PlayerState> _playerStateSubscription;
|
|
bool _isSourceLoaded = false;
|
|
StreamingPlaybackStatus _playbackStatus = StreamingPlaybackStatus.stopped;
|
|
bool _isAudioSessionConfigured = false;
|
|
bool _playRequested = false;
|
|
|
|
StreamingPlaybackStatus get playbackStatus => _playbackStatus;
|
|
bool get isPlaying => _playbackStatus == StreamingPlaybackStatus.playing;
|
|
bool get isBuffering => _playbackStatus == StreamingPlaybackStatus.buffering;
|
|
bool get isStopped => _playbackStatus == StreamingPlaybackStatus.stopped;
|
|
|
|
StreamingPlaybackStatus _mapPlayerStateToStatus(PlayerState state) {
|
|
if (state.processingState == ProcessingState.completed) {
|
|
return StreamingPlaybackStatus.stopped;
|
|
}
|
|
|
|
if (state.playing) {
|
|
if (state.processingState == ProcessingState.ready) {
|
|
return StreamingPlaybackStatus.playing;
|
|
}
|
|
|
|
return StreamingPlaybackStatus.buffering;
|
|
}
|
|
|
|
if (_playRequested && state.processingState != ProcessingState.completed) {
|
|
return StreamingPlaybackStatus.buffering;
|
|
}
|
|
|
|
return StreamingPlaybackStatus.stopped;
|
|
}
|
|
|
|
void _setPlaybackStatus(StreamingPlaybackStatus status) {
|
|
if (_playbackStatus == status) {
|
|
return;
|
|
}
|
|
|
|
_playbackStatus = status;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> _configureAudioSessionIfNeeded() async {
|
|
if (_isAudioSessionConfigured) {
|
|
return;
|
|
}
|
|
|
|
final session = await AudioSession.instance;
|
|
await session.configure(const AudioSessionConfiguration.music());
|
|
_isAudioSessionConfigured = true;
|
|
}
|
|
|
|
Future<void> play() async {
|
|
_playRequested = true;
|
|
await _configureAudioSessionIfNeeded();
|
|
_setPlaybackStatus(StreamingPlaybackStatus.buffering);
|
|
|
|
try {
|
|
if (!_isSourceLoaded) {
|
|
await _player.setAudioSource(
|
|
AudioSource.uri(
|
|
Uri.parse(streamUrl),
|
|
tag: const MediaItem(
|
|
id: 'kryz-live-stream',
|
|
title: 'KRYZ Live Stream',
|
|
artist: 'KRYZ Radio',
|
|
album: 'Live',
|
|
),
|
|
),
|
|
);
|
|
_isSourceLoaded = true;
|
|
}
|
|
|
|
final session = await AudioSession.instance;
|
|
await session.setActive(true);
|
|
await _player.play();
|
|
} catch (_) {
|
|
_playRequested = false;
|
|
_setPlaybackStatus(StreamingPlaybackStatus.stopped);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> stop() async {
|
|
_playRequested = false;
|
|
_isSourceLoaded = false;
|
|
_setPlaybackStatus(StreamingPlaybackStatus.stopped);
|
|
await _player.stop();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_playerStateSubscription.cancel();
|
|
_player.dispose();
|
|
super.dispose();
|
|
}
|
|
}
|