import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_text_style.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 audioPlayerButton(IconData icon, VoidCallback onpress) { return Container( width: 48, height: 48, decoration: ShapeDecoration( color: Colors.white, shape: RoundedRectangleBorder( side: const BorderSide(width: 1, color: Color(0xFFEAF1F4)), borderRadius: BorderRadius.circular(32), ), ), child: Icon( icon, color: const Color(0xff163A51).withOpacity(0.5), ), ).onPress(onpress); } Widget _getAudioButton() { switch (_audioPlayer.state) { case PlayerState.playing: return audioPlayerButton(Icons.pause_rounded, () async { _failedToLoad = false; await _audioPlayer.pause(); rebuild(); }); case PlayerState.paused: return audioPlayerButton(Icons.play_arrow_rounded, () async { _failedToLoad = false; await _audioPlayer.resume(); rebuild(); }); case PlayerState.completed: return audioPlayerButton(Icons.replay_rounded, () async { _failedToLoad = false; await _audioPlayer.stop(); await _audioPlayer.resume(); rebuild(); }); case PlayerState.stopped: return audioPlayerButton(_isLocalFile ? Icons.play_circle_fill_outlined : Icons.download_rounded, () async { _failedToLoad = false; try { await _audioPlayer.play( _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), ); rebuild(); } on Exception catch (e) { _failedToLoad = true; } }); default: return audioPlayerButton(Icons.replay_rounded, () 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: [ _getAudioButton(), SliderTheme( data: SliderTheme.of(context).copyWith(trackHeight: 2.0, thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 6.0), overlayShape: SliderComponentShape.noOverlay), child: Slider( value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, min: 0, max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, activeColor: AppColor.primary70, inactiveColor: AppColor.neutral30, onChangeStart: (value) { _sliderMoving = true; }, onChanged: (value) { _audioPosition = Duration(milliseconds: value.round()); rebuild(); }, onChangeEnd: (value) { _sliderMoving = false; _audioPlayer.seek(Duration(milliseconds: value.round())); rebuild(); }), ).paddingOnly(start: 8, end: 8).expanded, _failedToLoad ? Text("Failed to load", style: AppTextStyle.tiny.copyWith(color: AppColor.red60)) : Text("${format(_audioPosition)}/${format(_audioTime)}", style: AppTextStyle.tiny.copyWith(color: AppColor.neutral50)), ], ), ], ); } }