From 7a48df7f0571e2216e14e079c762260e7b7eb7fd Mon Sep 17 00:00:00 2001 From: stonegate Date: Sat, 1 Aug 2020 15:31:18 +0800 Subject: [PATCH] Skip silence feature. --- lib/home/audioplayer.dart | 52 +++++++++++--- lib/local_storage/key_value_storage.dart | 26 +++++-- lib/state/audio_state.dart | 91 ++++++++++++++++-------- 3 files changed, 128 insertions(+), 41 deletions(-) diff --git a/lib/home/audioplayer.dart b/lib/home/audioplayer.dart index 7f957b3..234d3cb 100644 --- a/lib/home/audioplayer.dart +++ b/lib/home/audioplayer.dart @@ -262,6 +262,30 @@ class LastPosition extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + Selector( + selector: (_, audio) => audio.skipSilence, + builder: (_, data, __) => FlatButton( + child: Row( + children: [ + Icon(Icons.flash_on, size: 18), + SizedBox(width: 5), + Text(s.skipSilence), + ], + ), + color: data ? context.accentColor : Colors.transparent, + padding: EdgeInsets.symmetric(horizontal: 10), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100.0), + side: BorderSide( + color: data + ? context.accentColor + : Theme.of(context) + .colorScheme + .onSurface + .withOpacity(0.12))), + textColor: data ? Colors.white : null, + onPressed: () => audio.setSkipSilence(skipSilence: !data))), + SizedBox(width: 10), FutureBuilder( future: getPosition(episode), builder: (context, snapshot) { @@ -287,15 +311,24 @@ class LastPosition extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(100.0), - side: - BorderSide(color: Colors.green[700])), + side: BorderSide( + color: context.accentColor)), highlightedBorderColor: Colors.green[700], onPressed: () => audio.seekTo( (snapshot.data.seconds * 1000).toInt()), child: Row( children: [ - Text(s.timeLastPlayed( - snapshot.data.seconds.toTime)), + SizedBox( + width: 20, + height: 20, + child: CustomPaint( + painter: ListenedPainter( + context.textColor, + stroke: 2.0), + ), + ), + SizedBox(width: 5), + Text(snapshot.data.seconds.toTime), ], ), ) @@ -309,7 +342,8 @@ class LastPosition extends StatelessWidget { width: 40, child: Transform.rotate( angle: math.pi * 0.7, - child: Icon(Icons.brightness_2, size: 18))) + child: Icon(Icons.brightness_2, + size: 18, color: context.accentColor))) : Center(), ) ], @@ -1181,11 +1215,10 @@ class _ControlPanelState extends State }, ), ), - Container( + SizedBox( height: 80.0, - padding: EdgeInsets.only(left: 60, right: 60), - alignment: Alignment.center, child: Column( + crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Expanded( @@ -1193,6 +1226,7 @@ class _ControlPanelState extends State selector: (_, audio) => audio.episode.title, builder: (_, title, __) { return Container( + padding: EdgeInsets.only(left: 60, right: 60), child: LayoutBuilder( builder: (context, size) { var span = TextSpan( @@ -1312,7 +1346,7 @@ class _ControlPanelState extends State width: 100, child: Text( data.item1.feedTitle, - maxLines: 1, + maxLines: 2, overflow: TextOverflow.fade, ), ), diff --git a/lib/local_storage/key_value_storage.dart b/lib/local_storage/key_value_storage.dart index 648a26b..af4a690 100644 --- a/lib/local_storage/key_value_storage.dart +++ b/lib/local_storage/key_value_storage.dart @@ -34,6 +34,8 @@ const String tapToOpenPopupMenuKey = 'tapToOpenPopupMenuKey'; const String fastForwardSecondsKey = 'fastForwardSecondsKey'; const String rewindSecondsKey = 'rewindSecondsKey'; const String playerHeightKey = 'playerHeightKey'; +const String speedKey = 'speedKey'; +const String skipSilenceKey = 'skipSilenceKey'; class KeyValueStorage { final String key; @@ -101,9 +103,10 @@ class KeyValueStorage { return prefs.getString(key); } - saveMenu(List list) async { + Future saveMenu(List list) async { var prefs = await SharedPreferences.getInstance(); - await prefs.setStringList(key, list.map((e) => e.toString()).toList()); + return await prefs.setStringList( + key, list.map((e) => e.toString()).toList()); } Future> getMenu() async { @@ -129,8 +132,23 @@ class KeyValueStorage { } /// Rreverse is used for compatite bool value save before which set true = 0, false = 1 - saveBool(boo, {reverse = false}) async { + Future saveBool(boo, {reverse = false}) async { var prefs = await SharedPreferences.getInstance(); - reverse ? prefs.setInt(key, boo ? 0 : 1) : prefs.setInt(key, boo ? 1 : 0); + return reverse + ? prefs.setInt(key, boo ? 0 : 1) + : prefs.setInt(key, boo ? 1 : 0); + } + + Future saveDouble(double data) async { + var prefs = await SharedPreferences.getInstance(); + return prefs.setDouble(key, data); + } + + Future getDoubel({double defaultValue = 0.0}) async { + var prefs = await SharedPreferences.getInstance(); + if (prefs.getDouble(key) == null) { + await prefs.setDouble(key, defaultValue); + } + return prefs.getDouble(key); } } diff --git a/lib/state/audio_state.dart b/lib/state/audio_state.dart index 9d8ee40..b633122 100644 --- a/lib/state/audio_state.dart +++ b/lib/state/audio_state.dart @@ -64,6 +64,8 @@ class AudioPlayerNotifier extends ChangeNotifier { var fastForwardSecondsStorage = KeyValueStorage(fastForwardSecondsKey); var rewindSecondsStorage = KeyValueStorage(rewindSecondsKey); var playerHeightStorage = KeyValueStorage(playerHeightKey); + var speedStorage = KeyValueStorage(speedKey); + var skipSilenceStorage = KeyValueStorage(skipSilenceKey); /// Current playing episdoe. EpisodeBrief _episode; @@ -137,18 +139,24 @@ class AudioPlayerNotifier extends ChangeNotifier { /// Current speed. double _currentSpeed = 1; - //Update episode card when setting changed + ///Update episode card when setting changed bool _episodeState = false; /// Player height. PlayerHeight _playerHeight; + /// Player skip silence. + bool _skipSilence; + + // ignore: prefer_final_fields + bool _playerRunning = false; + AudioProcessingState get audioState => _audioState; int get backgroundAudioDuration => _backgroundAudioDuration; int get backgroundAudioPosition => _backgroundAudioPosition; double get seekSliderValue => _seekSliderValue; String get remoteErrorMessage => _remoteErrorMessage; - bool get playerRunning => _audioState != AudioProcessingState.none; + bool get playerRunning => _playerRunning; bool get buffering => _audioState != AudioProcessingState.ready; int get lastPositin => _lastPostion; Playlist get queue => _queue; @@ -166,6 +174,7 @@ class AudioPlayerNotifier extends ChangeNotifier { int get fastForwardSeconds => _fastForwardSeconds; int get rewindSeconds => _rewindSeconds; PlayerHeight get playerHeight => _playerHeight; + bool get skipSilence => _skipSilence; set setSwitchValue(double value) { _switchValue = value; @@ -183,9 +192,11 @@ class AudioPlayerNotifier extends ChangeNotifier { _savePlayerHeight(); } - Future _getPlayerHeight() async { + Future _initAudioData() async { var index = await playerHeightStorage.getInt(defaultValue: 0); _playerHeight = PlayerHeight.values[index]; + _currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0); + _skipSilence = await skipSilenceStorage.getBool(defaultValue: false); } Future _savePlayerHeight() async { @@ -210,9 +221,9 @@ class AudioPlayerNotifier extends ChangeNotifier { @override void addListener(VoidCallback listener) { super.addListener(listener); - _getPlayerHeight(); - _queueUpdate = false; - _getAutoSleepTimer(); + _initAudioData(); + // _queueUpdate = false; + // _getAutoSleepTimer(); AudioService.connect(); var running = AudioService.running; if (running) {} @@ -257,7 +268,7 @@ class AudioPlayerNotifier extends ChangeNotifier { _backgroundAudioPosition = 0; _seekSliderValue = 0; _episode = episodeNew; - _audioState = AudioProcessingState.connecting; + _playerRunning = true; notifyListeners(); //await _queue.savePlaylist(); _startAudioService(startPosition, episodeNew.enclosureUrl); @@ -270,6 +281,7 @@ class AudioPlayerNotifier extends ChangeNotifier { _startAudioService(int position, String url) async { _stopOnComplete = false; _sleepTimerMode = SleepTimerMode.undefined; + _switchValue = 0; /// Connect to audio service. if (!AudioService.connected) { @@ -319,7 +331,12 @@ class AudioPlayerNotifier extends ChangeNotifier { sleepTimer(defaultTimer); } } - + if (_currentSpeed != 1.0) { + await AudioService.customAction('setSpeed', _currentSpeed); + } + if (_skipSilence) { + await AudioService.customAction('setSkipSilence', skipSilence); + } await AudioService.play(); AudioService.currentMediaItemStream @@ -343,24 +360,6 @@ class AudioPlayerNotifier extends ChangeNotifier { AudioService.skipToNext(); } }); - - // queueSubject = BehaviorSubject>(); - // queueSubject.addStream( - // AudioService.queueStream.distinct().where((event) => event != null)); -//queueSubject.stream. - AudioService.customEventStream.distinct().listen((event) async { - if (event is String && _episode.title == event) { - print(event); - _queue.delFromPlaylist(_episode); - _lastPostion = 0; - notifyListeners(); - await positionStorage.saveInt(_lastPostion); - final history = PlayHistory(_episode.title, _episode.enclosureUrl, - backgroundAudioPosition ~/ 1000, seekSliderValue); - dbHelper.saveHistory(history); - } - }); - AudioService.playbackStateStream .distinct() .where((event) => event != null) @@ -387,6 +386,23 @@ class AudioPlayerNotifier extends ChangeNotifier { notifyListeners(); }); + AudioService.customEventStream.distinct().listen((event) async { + if (event is String && _episode.title == event) { + print(event); + _queue.delFromPlaylist(_episode); + _lastPostion = 0; + notifyListeners(); + await positionStorage.saveInt(_lastPostion); + final history = PlayHistory(_episode.title, _episode.enclosureUrl, + backgroundAudioPosition ~/ 1000, seekSliderValue); + dbHelper.saveHistory(history); + } + if (event is Map && event['playerRunning'] == false) { + _playerRunning = false; + notifyListeners(); + } + }); + //double s = _currentSpeed ?? 1.0; var getPosition = 0; Timer.periodic(Duration(milliseconds: 500), (timer) { @@ -431,7 +447,8 @@ class AudioPlayerNotifier extends ChangeNotifier { _seekSliderValue = 0; _episode = _queue.playlist.first; _queueUpdate = !_queueUpdate; - _audioState = AudioProcessingState.connecting; + _audioState = AudioProcessingState.none; + _playerRunning = true; notifyListeners(); _startAudioService(_lastPostion ?? 0, _queue.playlist.first.enclosureUrl); } @@ -554,9 +571,18 @@ class AudioPlayerNotifier extends ChangeNotifier { } } + /// Set player speed. setSpeed(double speed) async { await AudioService.customAction('setSpeed', speed); _currentSpeed = speed; + await speedStorage.saveDouble(_currentSpeed); + notifyListeners(); + } + + setSkipSilence({@required bool skipSilence}) async { + await AudioService.customAction('setSkipSilence', skipSilence); + _skipSilence = skipSilence; + await skipSilenceStorage.saveBool(_skipSilence); notifyListeners(); } @@ -819,6 +845,7 @@ class AudioPlayerTask extends BackgroundAudioTask { _playerStateSubscription.cancel(); _eventSubscription.cancel(); await _setState(processingState: AudioProcessingState.none); + AudioServiceBackground.sendCustomEvent({'playerRunning': false}); await super.onStop(); } @@ -857,7 +884,6 @@ class AudioPlayerTask extends BackgroundAudioTask { @override void onFastForward() async { await _seekRelative(fastForwardInterval); - print('test'); } @override @@ -919,9 +945,18 @@ class AudioPlayerTask extends BackgroundAudioTask { case 'setSpeed': await _audioPlayer.setSpeed(argument); break; + case 'setSkipSilence': + await _setSkipSilence(argument); + break; } } + Future _setSkipSilence(bool boo) async { + await _audioPlayer.setSkipSilence(boo); + var duration = await _audioPlayer.durationFuture ?? Duration.zero; + AudioServiceBackground.setMediaItem(mediaItem.copyWith(duration: duration)); + } + Future _setState({ AudioProcessingState processingState, Duration position,