0

I'm using Flutter's Just-Audio plugin to play an mp3 file fetched from a streambuilder in my app. The streambuilder returns the duration of the file which I need for the setClip function;

player.setClip(start: Duration(milliseconds: 0), end: Duration(milliseconds: 10);

Instead of "10", the "end" point should be the file's duration minus 500ms. So I've got this stream listener in my initState;

@override
  void initState() {
    super.initState();
    _init();
  }
    Future<void> _init() async {
    await player.setUrl('https://bucket.s3.amazonaws.com/example.mp3');

     player.durationStream.listen((event) {
       int newevent = event.inMilliseconds;
          });
        await player.setClip(start: Duration(milliseconds: 0), end: newevent);
     }

But I need to convert the fetched duration to an integer in order to take off 500ms. Unfortunately the int newevent = event.inMilliseconds; throws the following error;

A value of type 'int' can't be assigned to a variable of type 'Duration?'.  Try changing the type of the variable, or casting the right-hand type to 'Duration?'.

I've tried this;

 int? newevent = event?.inMilliseconds;

and then;

 await player.setClip(start: Duration(milliseconds: 0), end: Duration(milliseconds: newevent));

But then I just get this redline error under milliseconds: newevent ;

 The argument type 'Duration?' can't be assigned to the parameter type 'int'.

So how can I get my duration from my streamlistener as an integer so I can use it as the end point in player.setClip?

Meggy
  • 1,491
  • 3
  • 28
  • 63

1 Answers1

1

The problem appears because durationStream returns a nullable duration, and it has to be non-nullable to be able to convert it to an integer. You can promote the duration to a non-nullable type with a null check.

Furthermore, to only run setClip after the first event, use first instead of listen and move setClip inside the function:

player.durationStream.first.then((event) {
  if(event != null){
    int newevent = event.inMilliseconds - 500;
    await player.setClip(start: Duration(milliseconds: 0), end: Duration(milliseconds: newevent);
  }
});
Hannes Hultergård
  • 1,157
  • 1
  • 11
  • 33
  • Unfortunately though there was no error, when I did a hot restart it went into a loop where it endlessly tried to load. The only way to stop the loop was to remove- player.setClip(start: Duration(milliseconds: 0), end: Duration(milliseconds: newevent)); – Meggy May 18 '21 at 14:36
  • Here's another error when I tried adding async and await ; Error: Non-nullable variable 'newevent' must be assigned before it can be used. await player.setClip(start: Duration(milliseconds: 0), end: Duration(milliseconds: newevent - 500)); – Meggy May 18 '21 at 14:42
  • Finally able to remove errors and loop by setting int newevent=0; int clippedevent =0; outside the initState. But although it seems work at first, both variables eventually get set back to zero somehow. – Meggy May 18 '21 at 15:08
  • Try moving `setClip` inside the listener to make sure that newevent has a value when using it. If you only want to run `setClip` once you can use [`first`](https://api.dart.dev/stable/2.12.4/dart-async/Stream/first.html) instead of `listen`. – Hannes Hultergård May 18 '21 at 15:15
  • First doesn't seem to work as a drop in replacement. player.durationStream.first((event) - The error I get is - The expression doesn't evaluate to a function, so it can't be invoked. – Meggy May 18 '21 at 16:25
  • 1
    This is what worked. If you want to put it as answer, I'll choose it. player.durationStream.first.then((event) { if(event != null){ int newevent; newevent = event.inMilliseconds - 500; player.setClip(start: Duration(milliseconds: 0), end: Duration(milliseconds: newevent)); } } – Meggy May 18 '21 at 17:34
  • Sorry that it took a while to answer, glad you sorted it out. I have updated the answer – Hannes Hultergård May 18 '21 at 21:19