Hi, I have been trying to create a custom widget to take a List of records, which contains an attribute of the audioUrl I want to play. Once started, it should play in the background and play each audioUrl sequentially (start the next one once the current one is finished).
This has not been easy, and am wondering if someone has succeeded to do this?
I started with the just_audio package, but it's not coming together easily.
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';
class PlaylistPlayer extends StatefulWidget {
const PlaylistPlayer({
Key? key,
this.width,
this.height,
this.compactionsList,
}) : super(key: key);
final double? width;
final double? height;
final List<CompactionsRecord>? compactionsList;
@override
_PlaylistPlayerState createState() => _PlaylistPlayerState();
}
class _PlaylistPlayerState extends State<PlaylistPlayer> {
late AudioPlayer _player;
late ConcatenatingAudioSource _playlist;
int? _currentIndex;
@override
void initState() {
super.initState();
_player = AudioPlayer();
_currentIndex = 0;
_playlist = ConcatenatingAudioSource(
children: widget.compactionsList
?.map((compaction) =>
AudioSource.uri(Uri.parse(compaction.audioUrl)))
.toList() ??
[],
);
_player
.setAudioSource(_playlist,
initialIndex: 0, initialPosition: Duration.zero)
.then((_) {
_player.play();
});
// Listen to changes in the currently playing item
_player.currentIndexStream.listen((index) {
if (index != null) {
setState(() {
_currentIndex = index;
});
}
});
}
@override
void dispose() {
_player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Player controls
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.skip_previous),
onPressed: () =>
_player.hasPrevious ? _player.seekToPrevious() : null,
),
IconButton(
icon: Icon(_player.playing ? Icons.pause : Icons.play_arrow),
onPressed: () =>
_player.playing ? _player.pause() : _player.play(),
),
IconButton(
icon: Icon(Icons.skip_next),
onPressed: () => _player.hasNext ? _player.seekToNext() : null,
),
],
),
// Playlist display
Expanded(
child: ListView.builder(
itemCount: widget.compactionsList?.length ?? 0,
itemBuilder: (context, index) {
final compaction = widget.compactionsList![index];
return ListTile(
title: Text(compaction.itemTitle),
onTap: () {
_player.seek(Duration.zero, index: index);
},
selected: index == _currentIndex,
selectedTileColor: Colors.grey[300],
);
},
),
),
],
),
);
}
}