-
-
Notifications
You must be signed in to change notification settings - Fork 694
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
216 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
// This is a minimal example demonstrating live streaming. | ||
// | ||
// To run: | ||
// | ||
// flutter run -t lib/example_radio.dart | ||
|
||
import 'package:audio_session/audio_session.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/services.dart'; | ||
import 'package:just_audio/just_audio.dart'; | ||
|
||
void main() => runApp(MyApp()); | ||
|
||
class MyApp extends StatefulWidget { | ||
@override | ||
_MyAppState createState() => _MyAppState(); | ||
} | ||
|
||
class _MyAppState extends State<MyApp> with WidgetsBindingObserver { | ||
final _player = AudioPlayer(); | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
WidgetsBinding.instance?.addObserver(this); | ||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( | ||
statusBarColor: Colors.black, | ||
)); | ||
_init(); | ||
} | ||
|
||
Future<void> _init() async { | ||
// Inform the operating system of our app's audio attributes etc. | ||
// We pick a reasonable default for an app that plays speech. | ||
final session = await AudioSession.instance; | ||
await session.configure(AudioSessionConfiguration.speech()); | ||
// Listen to errors during playback. | ||
_player.playbackEventStream.listen((event) {}, | ||
onError: (Object e, StackTrace stackTrace) { | ||
print('A stream error occurred: $e'); | ||
}); | ||
// Try to load audio from a source and catch any errors. | ||
try { | ||
await _player.setAudioSource(AudioSource.uri( | ||
Uri.parse("https://stream-uk1.radioparadise.com/aac-320"))); | ||
} catch (e) { | ||
print("Error loading audio source: $e"); | ||
} | ||
} | ||
|
||
@override | ||
void dispose() { | ||
WidgetsBinding.instance?.removeObserver(this); | ||
// Release decoders and buffers back to the operating system making them | ||
// available for other apps to use. | ||
_player.dispose(); | ||
super.dispose(); | ||
} | ||
|
||
@override | ||
void didChangeAppLifecycleState(AppLifecycleState state) { | ||
if (state == AppLifecycleState.paused) { | ||
// Release the player's resources when not in use. We use "stop" so that | ||
// if the app resumes later, it will still remember what position to | ||
// resume from. | ||
_player.stop(); | ||
} | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return MaterialApp( | ||
debugShowCheckedModeBanner: false, | ||
home: Scaffold( | ||
body: SafeArea( | ||
child: Container( | ||
width: double.maxFinite, | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.center, | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: [ | ||
StreamBuilder<IcyMetadata?>( | ||
stream: _player.icyMetadataStream, | ||
builder: (context, snapshot) { | ||
final metadata = snapshot.data; | ||
final title = metadata?.info?.title ?? ''; | ||
final url = metadata?.info?.url; | ||
return Column( | ||
children: [ | ||
if (url != null) Image.network(url), | ||
Padding( | ||
padding: const EdgeInsets.only(top: 8.0), | ||
child: Text(title, | ||
style: Theme.of(context).textTheme.headline6), | ||
), | ||
], | ||
); | ||
}, | ||
), | ||
// Display play/pause button and volume/speed sliders. | ||
ControlButtons(_player), | ||
], | ||
), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
/// Displays the play/pause button and volume/speed sliders. | ||
class ControlButtons extends StatelessWidget { | ||
final AudioPlayer player; | ||
|
||
ControlButtons(this.player); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Row( | ||
mainAxisSize: MainAxisSize.min, | ||
children: [ | ||
/// This StreamBuilder rebuilds whenever the player state changes, which | ||
/// includes the playing/paused state and also the | ||
/// loading/buffering/ready state. Depending on the state we show the | ||
/// appropriate button or loading indicator. | ||
StreamBuilder<PlayerState>( | ||
stream: player.playerStateStream, | ||
builder: (context, snapshot) { | ||
final playerState = snapshot.data; | ||
final processingState = playerState?.processingState; | ||
final playing = playerState?.playing; | ||
if (processingState == ProcessingState.loading || | ||
processingState == ProcessingState.buffering) { | ||
return Container( | ||
margin: EdgeInsets.all(8.0), | ||
width: 64.0, | ||
height: 64.0, | ||
child: CircularProgressIndicator(), | ||
); | ||
} else if (playing != true) { | ||
return IconButton( | ||
icon: Icon(Icons.play_arrow), | ||
iconSize: 64.0, | ||
onPressed: player.play, | ||
); | ||
} else if (processingState != ProcessingState.completed) { | ||
return IconButton( | ||
icon: Icon(Icons.pause), | ||
iconSize: 64.0, | ||
onPressed: player.pause, | ||
); | ||
} else { | ||
return IconButton( | ||
icon: Icon(Icons.replay), | ||
iconSize: 64.0, | ||
onPressed: () => player.seek(Duration.zero), | ||
); | ||
} | ||
}, | ||
), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters