diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index a760c89..2f7b9d4 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary { "all" : MessageLookupByLibrary.simpleMessage("All"), "autoDownload" : MessageLookupByLibrary.simpleMessage("Auto download"), "back" : MessageLookupByLibrary.simpleMessage("Back"), + "boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"), "buffering" : MessageLookupByLibrary.simpleMessage("Buffering"), "cancel" : MessageLookupByLibrary.simpleMessage("CANCEL"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Cellular data warning"), diff --git a/lib/generated/intl/messages_es.dart b/lib/generated/intl/messages_es.dart index a9e7941..b97daf7 100644 --- a/lib/generated/intl/messages_es.dart +++ b/lib/generated/intl/messages_es.dart @@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary { "all" : MessageLookupByLibrary.simpleMessage("Todos"), "autoDownload" : MessageLookupByLibrary.simpleMessage("Auto-descargar"), "back" : MessageLookupByLibrary.simpleMessage("Atras"), + "boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"), "buffering" : MessageLookupByLibrary.simpleMessage("Cargando "), "cancel" : MessageLookupByLibrary.simpleMessage("CANCELAR"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Alerta de datos móviles "), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 027e111..1cc68b8 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary { "all" : MessageLookupByLibrary.simpleMessage("Tout"), "autoDownload" : MessageLookupByLibrary.simpleMessage("Téléchargements auto"), "back" : MessageLookupByLibrary.simpleMessage("Retour"), + "boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"), "buffering" : MessageLookupByLibrary.simpleMessage("Buffering"), "cancel" : MessageLookupByLibrary.simpleMessage("ANNULER"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Avertissement utilisation des données mobiles"), diff --git a/lib/generated/intl/messages_zh-Hans.dart b/lib/generated/intl/messages_zh-Hans.dart index 4bac15e..708bc01 100644 --- a/lib/generated/intl/messages_zh-Hans.dart +++ b/lib/generated/intl/messages_zh-Hans.dart @@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary { "all" : MessageLookupByLibrary.simpleMessage("全部"), "autoDownload" : MessageLookupByLibrary.simpleMessage("自动下载"), "back" : MessageLookupByLibrary.simpleMessage("返回"), + "boostVolume" : MessageLookupByLibrary.simpleMessage("增强声音"), "buffering" : MessageLookupByLibrary.simpleMessage("缓冲中"), "cancel" : MessageLookupByLibrary.simpleMessage("取消"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("流量确认"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 19d7701..42464e3 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -119,6 +119,16 @@ class S { ); } + /// `Boost volume` + String get boostVolume { + return Intl.message( + 'Boost volume', + name: 'boostVolume', + desc: 'Boost volume in player widget.', + args: [], + ); + } + /// `Buffering` String get buffering { return Intl.message( diff --git a/lib/home/audioplayer.dart b/lib/home/audioplayer.dart index 287bd3d..ba5f92f 100644 --- a/lib/home/audioplayer.dart +++ b/lib/home/audioplayer.dart @@ -261,118 +261,124 @@ class LastPosition extends StatelessWidget { return Selector( selector: (_, audio) => audio.episode, builder: (context, episode, child) { - 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), - Selector( - selector: (_, audio) => audio.boostVolume, - builder: (_, data, __) => FlatButton( - child: Row( - children: [ - Icon(Icons.flash_on, size: 18), - SizedBox(width: 5), - Text('Boost Volume'), - ], - ), - 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.setBoostVolume(boostVolume: !data))), - SizedBox(width: 10), - FutureBuilder( - future: getPosition(episode), - builder: (context, snapshot) { - if (snapshot.hasError) print(snapshot.error); - return snapshot.hasData - ? snapshot.data.seekValue > 0.90 - ? Container( - height: 20, - padding: EdgeInsets.symmetric(horizontal: 10), - child: SizedBox( - width: 20, + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + 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), + Selector( + selector: (_, audio) => audio.boostVolume, + builder: (_, data, __) => FlatButton( + child: Row( + children: [ + Icon(Icons.volume_up, size: 18), + SizedBox(width: 5), + Text(s.boostVolume), + ], + ), + 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.setBoostVolume(boostVolume: !data))), + SizedBox(width: 10), + FutureBuilder( + future: getPosition(episode), + builder: (context, snapshot) { + if (snapshot.hasError) print(snapshot.error); + return snapshot.hasData + ? snapshot.data.seekValue > 0.90 + ? Container( height: 20, - child: CustomPaint( - painter: ListenedAllPainter( - context.accentColor, - stroke: 2.0), - ), - ), - ) - : snapshot.data.seconds < 10 - ? Center() - : OutlineButton( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(100.0), - side: BorderSide( - color: context.accentColor)), - highlightedBorderColor: Colors.green[700], - onPressed: () => audio.seekTo( - (snapshot.data.seconds * 1000).toInt()), - child: Row( - children: [ - SizedBox( - width: 20, - height: 20, - child: CustomPaint( - painter: ListenedPainter( - context.textColor, - stroke: 2.0), - ), - ), - SizedBox(width: 5), - Text(snapshot.data.seconds.toTime), - ], + padding: EdgeInsets.symmetric(horizontal: 10), + child: SizedBox( + width: 20, + height: 20, + child: CustomPaint( + painter: ListenedAllPainter( + context.accentColor, + stroke: 2.0), ), - ) - : Center(); - }), - Selector( - selector: (_, audio) => audio.switchValue, - builder: (_, data, __) => data == 1 - ? Container( - height: 20, - width: 40, - child: Transform.rotate( - angle: math.pi * 0.7, - child: Icon(Icons.brightness_2, - size: 18, color: context.accentColor))) - : Center(), - ) - ], + ), + ) + : snapshot.data.seconds < 10 + ? Center() + : OutlineButton( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(100.0), + side: BorderSide( + color: context.accentColor)), + highlightedBorderColor: Colors.green[700], + onPressed: () => audio.seekTo( + (snapshot.data.seconds * 1000).toInt()), + child: Row( + children: [ + SizedBox( + width: 20, + height: 20, + child: CustomPaint( + painter: ListenedPainter( + context.textColor, + stroke: 2.0), + ), + ), + SizedBox(width: 5), + Text(snapshot.data.seconds.toTime), + ], + ), + ) + : Center(); + }), + Selector( + selector: (_, audio) => audio.switchValue, + builder: (_, data, __) => data == 1 + ? Container( + height: 20, + width: 40, + child: Transform.rotate( + angle: math.pi * 0.7, + child: Icon(Icons.brightness_2, + size: 18, color: context.accentColor))) + : Center(), + ) + ], + ), ); }, ); diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 3375167..65421de 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -24,6 +24,10 @@ "@autoDownload": {}, "back": "Back", "@back": {}, + "boostVolume": "Boost volume", + "@boostVolume": { + "description": "Boost volume in player widget." + }, "buffering": "Buffering", "@buffering": {}, "cancel": "CANCEL", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 5bdc000..e7933ef 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -24,6 +24,10 @@ "@autoDownload": {}, "back": "Atras", "@back": {}, + "boostVolume": "Boost volume", + "@boostVolume": { + "description": "Boost volume in player widget." + }, "buffering": "Cargando ", "@buffering": {}, "cancel": "CANCELAR", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 348e79e..4ad1828 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -24,6 +24,10 @@ "@autoDownload": {}, "back": "Retour", "@back": {}, + "boostVolume": "Boost volume", + "@boostVolume": { + "description": "Boost volume in player widget." + }, "buffering": "Buffering", "@buffering": {}, "cancel": "ANNULER", diff --git a/lib/l10n/intl_zh_Hans.arb b/lib/l10n/intl_zh_Hans.arb index 1225596..26bb655 100644 --- a/lib/l10n/intl_zh_Hans.arb +++ b/lib/l10n/intl_zh_Hans.arb @@ -24,6 +24,10 @@ "@autoDownload": {}, "back": "返回", "@back": {}, + "boostVolume": "增强声音", + "@boostVolume": { + "description": "Boost volume in player widget." + }, "buffering": "缓冲中", "@buffering": {}, "cancel": "取消", diff --git a/lib/state/audio_state.dart b/lib/state/audio_state.dart index da7fd84..1ccb804 100644 --- a/lib/state/audio_state.dart +++ b/lib/state/audio_state.dart @@ -66,6 +66,8 @@ class AudioPlayerNotifier extends ChangeNotifier { var playerHeightStorage = KeyValueStorage(playerHeightKey); var speedStorage = KeyValueStorage(speedKey); var skipSilenceStorage = KeyValueStorage(skipSilenceKey); + var boostVolumeStorage = KeyValueStorage(boostVolumeKey); + var volumeGainStorage = KeyValueStorage(volumeGainKey); /// Current playing episdoe. EpisodeBrief _episode; @@ -148,6 +150,12 @@ class AudioPlayerNotifier extends ChangeNotifier { /// Player skip silence. bool _skipSilence; + /// Boost volumn + bool _boostVolume; + + /// Boost volume gain. + int _volumeGain; + // ignore: prefer_final_fields bool _playerRunning = false; @@ -175,6 +183,8 @@ class AudioPlayerNotifier extends ChangeNotifier { int get rewindSeconds => _rewindSeconds; PlayerHeight get playerHeight => _playerHeight; bool get skipSilence => _skipSilence; + bool get boostVolume => _boostVolume; + int get volumeGain => _volumeGain; set setSwitchValue(double value) { _switchValue = value; @@ -197,6 +207,8 @@ class AudioPlayerNotifier extends ChangeNotifier { _playerHeight = PlayerHeight.values[index]; _currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0); _skipSilence = await skipSilenceStorage.getBool(defaultValue: false); + _boostVolume = await boostVolumeStorage.getBool(defaultValue: false); + _volumeGain = await volumeGainStorage.getInt(defaultValue: 3000); } Future _savePlayerHeight() async { @@ -345,12 +357,23 @@ class AudioPlayerNotifier extends ChangeNotifier { sleepTimer(defaultTimer); } } + + /// Set player speed. if (_currentSpeed != 1.0) { await AudioService.customAction('setSpeed', _currentSpeed); } + + /// Set slipsilence. if (_skipSilence) { await AudioService.customAction('setSkipSilence', skipSilence); } + + /// Set boostValome. + if (_boostVolume) { + await AudioService.customAction( + 'setBoostVolume', [_boostVolume, _volumeGain]); + } + await AudioService.play(); AudioService.currentMediaItemStream @@ -456,6 +479,8 @@ class AudioPlayerNotifier extends ChangeNotifier { playNext() async { await AudioService.skipToNext(); + _queueUpdate = !_queueUpdate; + notifyListeners(); } addToPlaylist(EpisodeBrief episode) async { @@ -520,6 +545,19 @@ class AudioPlayerNotifier extends ChangeNotifier { return index; } + Future reorderPlaylist(int oldIndex, int newIndex) async { + var episode = _queue.playlist[oldIndex]; + if (playerRunning) { + await AudioService.removeQueueItem(episode.toMediaItem()); + await AudioService.addQueueItemAt(episode.toMediaItem(), newIndex); + } + await _queue.addToPlayListAt(episode, newIndex); + if (newIndex == 0) { + _lastPostion = 0; + await positionStorage.saveInt(0); + } + } + Future moveToTop(EpisodeBrief episode) async { await delFromPlaylist(episode); if (playerRunning) { @@ -535,11 +573,11 @@ class AudioPlayerNotifier extends ChangeNotifier { return true; } - pauseAduio() async { - AudioService.pause(); + Future pauseAduio() async { + await AudioService.pause(); } - resumeAudio() async { + Future resumeAudio() async { if (_audioState != AudioProcessingState.connecting && _audioState != AudioProcessingState.none) AudioService.play(); } @@ -591,6 +629,14 @@ class AudioPlayerNotifier extends ChangeNotifier { notifyListeners(); } + setBoostVolume({@required bool boostVolume, int gain}) async { + await AudioService.customAction( + 'setBoostVolume', [boostVolume, _volumeGain]); + _boostVolume = boostVolume; + notifyListeners(); + await boostVolumeStorage.saveBool(boostVolume); + } + //Set sleep timer sleepTimer(int mins) { if (_sleepTimerMode == SleepTimerMode.timer) { @@ -953,6 +999,9 @@ class AudioPlayerTask extends BackgroundAudioTask { case 'setSkipSilence': await _setSkipSilence(argument); break; + case 'setBoostVolume': + await _setBoostVolume(argument[0], argument[1]); + break; } } @@ -962,6 +1011,10 @@ class AudioPlayerTask extends BackgroundAudioTask { AudioServiceBackground.setMediaItem(mediaItem.copyWith(duration: duration)); } + Future _setBoostVolume(bool boo, int gain) async { + await _audioPlayer.setBoostVolume(boo, gain: gain); + } + Future _setState({ AudioProcessingState processingState, Duration position,