import 'dart:typed_data'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import '../../app_style/colors.dart'; class ASoundPlayer extends StatefulWidget { final String audio; const ASoundPlayer({Key key, this.audio}) : super(key: key); @override _ASoundPlayerState createState() => _ASoundPlayerState(); } class _ASoundPlayerState extends State { //FlutterSoundPlayer _myPlayer = FlutterSoundPlayer(); bool _sliderMoving = false; Duration _audioTime; Duration _audioPosition; String _audio; bool _isLocalFile = false; bool _failedToLoad = false; AudioPlayer _audioPlayer; Widget _getAudioButton(){ switch(_audioPlayer.state){ case PlayerState.playing: return IconButton( icon: const Icon(Icons.pause_rounded), onPressed: () async { _failedToLoad = false; await _audioPlayer.pause(); rebuild(); } ); case PlayerState.paused: return IconButton( icon: const Icon(Icons.play_arrow_rounded), onPressed: () async { _failedToLoad = false; await _audioPlayer.resume(); rebuild(); } ); case PlayerState.completed: return IconButton( icon: const Icon(Icons.replay_rounded), onPressed: () async { _failedToLoad = false; await _audioPlayer.stop(); await _audioPlayer.resume(); rebuild(); } ); case PlayerState.stopped: return IconButton( icon: Icon( _isLocalFile ? Icons.play_circle_fill_outlined : Icons.download_rounded ), onPressed: () async { _failedToLoad = false; try { await _audioPlayer.play( _isLocalFile? DeviceFileSource(_audio):UrlSource(_audio), ); rebuild(); } on Exception catch (e) { _failedToLoad = true; } } ); default: return IconButton( icon: const Icon( Icons.replay_rounded), onPressed: () async { _failedToLoad = false; try { _audioPlayer.seek(const Duration(milliseconds: 0)); _audioPlayer.stop(); await _audioPlayer.play( _isLocalFile? DeviceFileSource(_audio):UrlSource(_audio), ); rebuild(); } on Exception catch (e) { _failedToLoad = true; } } ); } } String format(Duration d) { if(d == null) return "00:00"; return d.toString().substring(2, 7); } rebuild(){ if (!mounted) return; setState(() {}); } bool _isLocalUrl(String url) { if(url?.isEmpty != false) return false; return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); } @override void initState() { super.initState(); _audioPlayer = AudioPlayer(); _audioPlayer.release(); _audio = widget.audio; _isLocalFile = _isLocalUrl(_audio); _audioPlayer.setReleaseMode(ReleaseMode.stop); if(_isLocalFile){ _audioPlayer.setSourceDeviceFile(_audio).then((value) {rebuild();}); } else{ _audioPlayer.setReleaseMode(ReleaseMode.stop); } // set up listeners _audioPlayer.onPositionChanged.listen((Duration duration) { if(!_sliderMoving){ _audioPosition = duration; rebuild(); } //setState(() => position = p); }); _audioPlayer.onPlayerStateChanged.listen((event) { //_audioPosition = _audioTime; rebuild(); }); _audioPlayer.onDurationChanged.listen((Duration duration) { _audioTime = duration; rebuild(); }); _audioPlayer.onSeekComplete.listen((event) { rebuild(); }); } @override void dispose() { super.dispose(); // _myPlayer.closeAudioSession(); _audioPlayer.release(); _audioPlayer.dispose(); } @override Widget build(BuildContext context) { if(_audio != widget.audio){ WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { _audio = widget.audio; if(_isLocalFile){ await _audioPlayer.setSourceDeviceFile(_audio); }else{ await _audioPlayer.setSourceUrl(_audio); } _audioPlayer.seek(const Duration(milliseconds: 0)); _audioPlayer.stop(); rebuild(); }); } return Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Row( children: [ Material( color: Colors.transparent, child: _getAudioButton() ), Expanded( child: Slider( value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, min: 0, max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, onChangeStart: (value){ _sliderMoving = true; }, onChanged: (value){ _audioPosition = Duration(milliseconds: value.round()); rebuild(); }, onChangeEnd: (value){ _sliderMoving = false; _audioPlayer.seek(Duration(milliseconds: value.round())); rebuild(); } ), ), ], ), Row( children: [ Expanded( child: Visibility( visible: _failedToLoad, child: Row( children: [ Text( "Failed to load", style: Theme.of(context).textTheme.overline.copyWith( color: AColors.red ), textScaleFactor: AppStyle.getScaleFactor(context), ), ], ), ), ), Visibility( visible: _audioPlayer.state != PlayerState.stopped, child: Text( "${format(_audioPosition)}/${format(_audioTime)}", style: Theme.of(context).textTheme.overline, textScaleFactor: AppStyle.getScaleFactor(context), ), ), ], ) ], ); } }