Search code examples
just-audio

How to dynamically populate AudioSource with multiple audio data from firestore in just_audio?


I have been trying to dynamically populate AudioSource.uri() with data from firestore.

I uploaded some songs into firestore database and I wanted to use the data for a just_audio playlist in my app. I have done everything possible, and I really am not sure why its not working.

I don't want to add the song urls and other data statically as shown in the plugin example.

Here are my attempts:

First I fetched the song data using a StreamBuilder and passed it as a DocumentSnapshot List to the JustAudioPlaylist() page;

List<DocumentSnapshot> _list;
_list = snapshot.data.docs;

Flexible(
              child: ListView.builder(
                  itemCount: 1,
                  itemBuilder: (BuildContext context, int index) {
                    return InkWell(
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => JustAudioPlaylist(
                                songs: [_list[index]],
                                
                              ),
                            ));
                      },
                      child:
                          Container(child: Center(child: Text('My Playlists'))),
                    );
                  }),
            )


Then, here's the JustAudioPlaylist page where I expected to retrieve and populate the AudioSource.uri().

class JustAudioPlaylist extends StatefulWidget {
  final List songs;

  JustAudioPlaylist({this.songs});
  @override
  _JustAudioPlaylistState createState() => _JustAudioPlaylistState();
}

class _JustAudioPlaylistState extends State<JustAudioPlaylist> {
  AudioPlayer _player;
  int _addedCount = 0;
  var _playlist;
  @override
  void initState() {
    _playlist
        .addAll(widget.songs.map((song) => ConcatenatingAudioSource(children: [
              AudioSource.uri(
                Uri.parse(song['song']),
                tag: AudioMetadata(
                  album: "Science Friday",
                  title: song['songTitle'],
                  artwork: song['songImage'],
                ),
              ),
            ]))); 

I am not sure why its not working, but it produces an error "addAll was called on null". Please can anyone help?


Solution

  • Your relevant code is:

    _playlist.addAll(...);
    

    The error means _playlist is null. That is, _playlist is an uninitialised variable and doesn't actually contain any playlist object. I can see you declare the variable so it starts off empty:

    var _playlist;
    

    But you never actually store anything into this variable, like _playlist = ...something.... So your _playlist variable starts off null and continues to remain null.

    You could do this instead:

    _playlist = ConcatenatingAudioSource(children: []);
    
    // and then later...
    _playlist.addAll(widget.songs.map(...etc...));
    

    Although addAll is intended for dynamically modifying the playlist after it's already created. But in your case, you know which songs you want to play at initialisation time, so you may as well just initialise the playlist right at the beginning and you won't have to add to it later:

    _playlist = ConcatenatingAudioSource(
      children: widget.songs.map(...etc...)
    );