diff --git a/assets/audio/internet_error.mp3 b/assets/audio/internet_error.mp3 new file mode 100644 index 0000000..f884413 Binary files /dev/null and b/assets/audio/internet_error.mp3 differ diff --git a/lib/Globals.dart b/lib/Globals.dart index 86a0cc8..843604b 100644 --- a/lib/Globals.dart +++ b/lib/Globals.dart @@ -3,27 +3,33 @@ import 'dart:io' show Platform; import 'package:audio_service/audio_service.dart'; import 'package:audio_session/audio_session.dart'; import 'package:audioplayers/audioplayers.dart'; -import 'package:http/http.dart' as http; import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:http/http.dart' as http; import 'ListenHandler.dart'; late final ListenHandler _listenHandler; late final AudioSession _session; -const String _fallback = - "https://generic.ything.app/music/separation-185196.mp3"; +final _fallbackSource = + Uri.parse("https://generic.ything.app/music/fallback.url"); final _urlSource = Uri.parse("https://generic.ything.app/music/player.url"); -late final String _radioUrl; -Future loadCurrentUrl() async { - final resp = await http.get(_urlSource); - if (resp.statusCode == 200) { - _radioUrl = resp.body.trim(); - print('Loaded remote url'); - } else { - _radioUrl = _fallback; - print('Request for current streaming url failed, using fallback url'); +Future loadStringFromUrl(Uri remote) async { + try { + final resp = await http.get(remote); + if (resp.statusCode == 200) { + var ret = resp.body.trim(); + print('Loaded remote url: $remote - $ret'); + return ret; + } else { + print( + 'Request to load remote url: $remote - failed - Status Code: ${resp.statusCode} - Body: ${resp.body}'); + return null; + } + } catch (e) { + print("Exception - unable to load remote url: $remote - $e"); + return null; } } @@ -35,21 +41,21 @@ final _urlAbout = final _urlAboutIOS = Uri.parse("https://generic.ything.app/ything_radio/about_ios.txt"); -late final String _remoteAbout; +late final String _displayAbout; Future loadAboutUrl() async { - final resp = await http.get(kIsWeb || !Platform.isIOS ? _urlAbout : _urlAboutIOS); + final reqUrl = kIsWeb || !Platform.isIOS ? _urlAbout : _urlAboutIOS; - if (resp.statusCode == 200) { - _remoteAbout = resp.body; - print('Loaded remote about'); + var about = await loadStringFromUrl(reqUrl); + + if (about != null) { + _displayAbout = about; } else { - _remoteAbout = _fallbackAbout; - print('Request for remote about failed, using fallback about'); + _displayAbout = _fallbackAbout; } } -String getAboutText() => _remoteAbout; +String getAboutText() => _displayAbout; Future setupListenHandler() async { _listenHandler = await AudioService.init( @@ -96,10 +102,20 @@ Future setupListenHandler() async { ListenHandler getListenHandlder() => _listenHandler; -UrlSource getUrlSource() { - return UrlSource(_radioUrl, mimeType: "audio/mpeg"); +Future getSource({bool fallback = false}) async { + var radioUrl = fallback == false + ? await loadStringFromUrl(_urlSource) + : await loadStringFromUrl(_fallbackSource); + if (radioUrl != null) { + return UrlSource(radioUrl, mimeType: "audio/mpeg"); + } else { + return getInternetError(); + } } +Source getInternetError() => + AssetSource("audio/internet_error.mp3", mimeType: "audio/mpeg"); + Future startAudioSession() async { return await _session.setActive(true); } diff --git a/lib/ListenHandler.dart b/lib/ListenHandler.dart index 5d72fe1..7987833 100644 --- a/lib/ListenHandler.dart +++ b/lib/ListenHandler.dart @@ -5,8 +5,6 @@ import 'package:ything_radio/Globals.dart'; class ListenHandler extends BaseAudioHandler { final _player = AudioPlayer(); - final UrlSource _radioSource = getUrlSource(); - setup_player() { _player.setReleaseMode(ReleaseMode.release); _player.onPlayerStateChanged.listen((event) { @@ -64,10 +62,22 @@ class ListenHandler extends BaseAudioHandler { @override Future play() async { + print('Starting playback'); if (await startAudioSession()) { - //setSource followed by resume does not work on Android or web - //play works everywhere though - _player.play(_radioSource, mode: PlayerMode.mediaPlayer); + try { + //setSource followed by resume does not work on Android or web + //play works everywhere though + await _player.play(await getSource(), mode: PlayerMode.mediaPlayer); + } catch (e) { + print("Exception $e - loading fallback"); + try { + await _player.play(await getSource(fallback: true), + mode: PlayerMode.mediaPlayer); + } catch (e) { + print("Exception $e - playing internet connectivity problem"); + await _player.play(getInternetError()); + } + } } } diff --git a/lib/main.dart b/lib/main.dart index 8274aef..5fe379b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,10 +1,11 @@ +import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'Globals.dart'; import 'YthingRadio.dart'; Future main() async { - await loadCurrentUrl(); + AudioLogger.logLevel = AudioLogLevel.info; await loadAboutUrl(); await setupListenHandler(); runApp(const YthingRadio()); diff --git a/pubspec.yaml b/pubspec.yaml index f4fe0c6..3a82fbd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -73,6 +73,8 @@ flutter: - assets/images/app-background.jpg - assets/images/app-background2.jpg - assets/images/app-background3.jpg + - assets/images/app-background4.jpg + - assets/audio/internet_error.mp3 # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images