From 97598c741de84b48630293928690d8be2be7e6c6 Mon Sep 17 00:00:00 2001 From: Orangerot Date: Mon, 23 Dec 2024 04:18:04 +0100 Subject: feat: ProgressBar shows position in song --- lib/level.dart | 95 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/level.dart b/lib/level.dart index e35325a..1391f8a 100644 --- a/lib/level.dart +++ b/lib/level.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -12,44 +13,98 @@ class Level extends StatefulWidget { } class _LevelState extends State { - final _player = AudioPlayer(); + final player = AudioPlayer(); bool _isPlaying = true; + Duration? _duration; + Duration? _position; + + StreamSubscription? _durationSubscription; + StreamSubscription? _positionSubscription; + + @override + void setState(VoidCallback fn) { + // Subscriptions only can be closed asynchronously, + // therefore events can occur after widget has been disposed. + if (mounted) { + super.setState(fn); + } + } + + @override + void initState() { + super.initState(); + // Use initial values from player + player.getDuration().then( + (value) => setState(() { + _duration = value; + }), + ); + player.getCurrentPosition().then( + (value) => setState(() { + _position = value; + }), + ); + _durationSubscription = player.onDurationChanged.listen((duration) { + setState(() => _duration = duration); + }); + + _positionSubscription = player.onPositionChanged.listen( + (p) => setState(() => _position = p), + ); + } @override Widget build(BuildContext context) { + player.onDurationChanged.listen((Duration d) { + // print('Max duration: $d'); + setState(() => _duration = d); + }); + + player.onPositionChanged.listen((Duration p) { + // print('Current position: $p'); + setState(() => _position = p); + }); + String audioPath = Directory(widget.stepmaniaFolderPath) .listSync() .firstWhere((entity) => entity.path.endsWith('.ogg'), orElse: () => File('')) .path; - _player.play(DeviceFileSource(audioPath)); + player.play(DeviceFileSource(audioPath)); return Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(_isPlaying ? Icons.pause : Icons.play_arrow), - onPressed: () => { - if (_isPlaying) - { - _player.pause(), - setState(() { - _isPlaying = false; - }) - } - else - { - _player.resume(), - setState(() { - _isPlaying = true; - }) - }, + onPressed: () { + if (_isPlaying) { + player.pause(); + setState(() { + _isPlaying = false; + }); + } else { + player.resume(); + setState(() { + _isPlaying = true; + }); + } }, ), - title: Text('Level 1'), + title: Text(widget.stepmaniaFolderPath.split('/').last), actions: [ IconButton( icon: Icon(Icons.close), onPressed: () => Navigator.pop(context)) ], + bottom: PreferredSize( + preferredSize: Size(double.infinity, 1.0), + child: LinearProgressIndicator( + value: (_duration != null && + _position != null && + _position!.inMilliseconds > 0 && + _position!.inMilliseconds < _duration!.inMilliseconds) + ? _position!.inMilliseconds / _duration!.inMilliseconds + : 0.0, + )), ), body: Stack(children: [ Arrow( @@ -91,7 +146,9 @@ class _LevelState extends State { @override void dispose() { - _player.dispose(); + _durationSubscription?.cancel(); + _positionSubscription?.cancel(); + player.dispose(); super.dispose(); } } -- cgit v1.2.3