Skip to content

Instantly share code, notes, and snippets.

@scysys
Last active June 20, 2022 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scysys/7f700cd49f09ba788021504e8d3477aa to your computer and use it in GitHub Desktop.
Save scysys/7f700cd49f09ba788021504e8d3477aa to your computer and use it in GitHub Desktop.
// 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';
import 'package:just_audio_example/common.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> with WidgetsBindingObserver {
final _player = AudioPlayer(userAgent: 'myradioapp/1.0 (Linux;Android 11) https://myradioapp.com');
@override
void initState() {
super.initState();
ambiguate(WidgetsBinding.instance)!.addObserver(this);
SystemChrome.setSystemUIOverlayStyle(const 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(const 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("http://stream.laut.fm/hitradio1")));
} catch (e) {
print("Error loading audio source: $e");
}
}
@override
void dispose() {
ambiguate(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: SizedBox(
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;
const ControlButtons(this.player, {Key? key}) : super(key: key);
@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: const EdgeInsets.all(8.0),
width: 64.0,
height: 64.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 64.0,
onPressed: player.play,
);
} else if (processingState != ProcessingState.completed) {
return IconButton(
icon: const Icon(Icons.pause),
iconSize: 64.0,
onPressed: player.pause,
);
} else {
return IconButton(
icon: const Icon(Icons.replay),
iconSize: 64.0,
onPressed: () => player.seek(Duration.zero),
);
}
},
),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment