Support boost volume.

This commit is contained in:
stonegate 2020-08-09 23:10:32 +08:00
parent 058e97a8f2
commit 28c7222d06
11 changed files with 202 additions and 113 deletions

View File

@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary {
"all" : MessageLookupByLibrary.simpleMessage("All"), "all" : MessageLookupByLibrary.simpleMessage("All"),
"autoDownload" : MessageLookupByLibrary.simpleMessage("Auto download"), "autoDownload" : MessageLookupByLibrary.simpleMessage("Auto download"),
"back" : MessageLookupByLibrary.simpleMessage("Back"), "back" : MessageLookupByLibrary.simpleMessage("Back"),
"boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"),
"buffering" : MessageLookupByLibrary.simpleMessage("Buffering"), "buffering" : MessageLookupByLibrary.simpleMessage("Buffering"),
"cancel" : MessageLookupByLibrary.simpleMessage("CANCEL"), "cancel" : MessageLookupByLibrary.simpleMessage("CANCEL"),
"cellularConfirm" : MessageLookupByLibrary.simpleMessage("Cellular data warning"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Cellular data warning"),

View File

@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary {
"all" : MessageLookupByLibrary.simpleMessage("Todos"), "all" : MessageLookupByLibrary.simpleMessage("Todos"),
"autoDownload" : MessageLookupByLibrary.simpleMessage("Auto-descargar"), "autoDownload" : MessageLookupByLibrary.simpleMessage("Auto-descargar"),
"back" : MessageLookupByLibrary.simpleMessage("Atras"), "back" : MessageLookupByLibrary.simpleMessage("Atras"),
"boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"),
"buffering" : MessageLookupByLibrary.simpleMessage("Cargando "), "buffering" : MessageLookupByLibrary.simpleMessage("Cargando "),
"cancel" : MessageLookupByLibrary.simpleMessage("CANCELAR"), "cancel" : MessageLookupByLibrary.simpleMessage("CANCELAR"),
"cellularConfirm" : MessageLookupByLibrary.simpleMessage("Alerta de datos móviles "), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Alerta de datos móviles "),

View File

@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary {
"all" : MessageLookupByLibrary.simpleMessage("Tout"), "all" : MessageLookupByLibrary.simpleMessage("Tout"),
"autoDownload" : MessageLookupByLibrary.simpleMessage("Téléchargements auto"), "autoDownload" : MessageLookupByLibrary.simpleMessage("Téléchargements auto"),
"back" : MessageLookupByLibrary.simpleMessage("Retour"), "back" : MessageLookupByLibrary.simpleMessage("Retour"),
"boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"),
"buffering" : MessageLookupByLibrary.simpleMessage("Buffering"), "buffering" : MessageLookupByLibrary.simpleMessage("Buffering"),
"cancel" : MessageLookupByLibrary.simpleMessage("ANNULER"), "cancel" : MessageLookupByLibrary.simpleMessage("ANNULER"),
"cellularConfirm" : MessageLookupByLibrary.simpleMessage("Avertissement utilisation des données mobiles"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Avertissement utilisation des données mobiles"),

View File

@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary {
"all" : MessageLookupByLibrary.simpleMessage("全部"), "all" : MessageLookupByLibrary.simpleMessage("全部"),
"autoDownload" : MessageLookupByLibrary.simpleMessage("自动下载"), "autoDownload" : MessageLookupByLibrary.simpleMessage("自动下载"),
"back" : MessageLookupByLibrary.simpleMessage("返回"), "back" : MessageLookupByLibrary.simpleMessage("返回"),
"boostVolume" : MessageLookupByLibrary.simpleMessage("增强声音"),
"buffering" : MessageLookupByLibrary.simpleMessage("缓冲中"), "buffering" : MessageLookupByLibrary.simpleMessage("缓冲中"),
"cancel" : MessageLookupByLibrary.simpleMessage("取消"), "cancel" : MessageLookupByLibrary.simpleMessage("取消"),
"cellularConfirm" : MessageLookupByLibrary.simpleMessage("流量确认"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("流量确认"),

View File

@ -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` /// `Buffering`
String get buffering { String get buffering {
return Intl.message( return Intl.message(

View File

@ -261,118 +261,124 @@ class LastPosition extends StatelessWidget {
return Selector<AudioPlayerNotifier, EpisodeBrief>( return Selector<AudioPlayerNotifier, EpisodeBrief>(
selector: (_, audio) => audio.episode, selector: (_, audio) => audio.episode,
builder: (context, episode, child) { builder: (context, episode, child) {
return Row( return SingleChildScrollView(
mainAxisAlignment: MainAxisAlignment.center, scrollDirection: Axis.horizontal,
children: [ child: Row(
Selector<AudioPlayerNotifier, bool>( mainAxisAlignment: MainAxisAlignment.center,
selector: (_, audio) => audio.skipSilence, mainAxisSize: MainAxisSize.min,
builder: (_, data, __) => FlatButton( children: [
child: Row( Selector<AudioPlayerNotifier, bool>(
children: [ selector: (_, audio) => audio.skipSilence,
Icon(Icons.flash_on, size: 18), builder: (_, data, __) => FlatButton(
SizedBox(width: 5), child: Row(
Text(s.skipSilence), children: [
], Icon(Icons.flash_on, size: 18),
), SizedBox(width: 5),
color: data ? context.accentColor : Colors.transparent, Text(s.skipSilence),
padding: EdgeInsets.symmetric(horizontal: 10), ],
shape: RoundedRectangleBorder( ),
borderRadius: BorderRadius.circular(100.0), color: data ? context.accentColor : Colors.transparent,
side: BorderSide( padding: EdgeInsets.symmetric(horizontal: 10),
color: data shape: RoundedRectangleBorder(
? context.accentColor borderRadius: BorderRadius.circular(100.0),
: Theme.of(context) side: BorderSide(
.colorScheme color: data
.onSurface ? context.accentColor
.withOpacity(0.12))), : Theme.of(context)
textColor: data ? Colors.white : null, .colorScheme
onPressed: () => audio.setSkipSilence(skipSilence: !data))), .onSurface
SizedBox(width: 10), .withOpacity(0.12))),
Selector<AudioPlayerNotifier, bool>( textColor: data ? Colors.white : null,
selector: (_, audio) => audio.boostVolume, onPressed: () =>
builder: (_, data, __) => FlatButton( audio.setSkipSilence(skipSilence: !data))),
child: Row( SizedBox(width: 10),
children: [ Selector<AudioPlayerNotifier, bool>(
Icon(Icons.flash_on, size: 18), selector: (_, audio) => audio.boostVolume,
SizedBox(width: 5), builder: (_, data, __) => FlatButton(
Text('Boost Volume'), child: Row(
], children: [
), Icon(Icons.volume_up, size: 18),
color: data ? context.accentColor : Colors.transparent, SizedBox(width: 5),
padding: EdgeInsets.symmetric(horizontal: 10), Text(s.boostVolume),
shape: RoundedRectangleBorder( ],
borderRadius: BorderRadius.circular(100.0), ),
side: BorderSide( color: data ? context.accentColor : Colors.transparent,
color: data padding: EdgeInsets.symmetric(horizontal: 10),
? context.accentColor shape: RoundedRectangleBorder(
: Theme.of(context) borderRadius: BorderRadius.circular(100.0),
.colorScheme side: BorderSide(
.onSurface color: data
.withOpacity(0.12))), ? context.accentColor
textColor: data ? Colors.white : null, : Theme.of(context)
onPressed: () => audio.setBoostVolume(boostVolume: !data))), .colorScheme
SizedBox(width: 10), .onSurface
FutureBuilder<PlayHistory>( .withOpacity(0.12))),
future: getPosition(episode), textColor: data ? Colors.white : null,
builder: (context, snapshot) { onPressed: () =>
if (snapshot.hasError) print(snapshot.error); audio.setBoostVolume(boostVolume: !data))),
return snapshot.hasData SizedBox(width: 10),
? snapshot.data.seekValue > 0.90 FutureBuilder<PlayHistory>(
? Container( future: getPosition(episode),
height: 20, builder: (context, snapshot) {
padding: EdgeInsets.symmetric(horizontal: 10), if (snapshot.hasError) print(snapshot.error);
child: SizedBox( return snapshot.hasData
width: 20, ? snapshot.data.seekValue > 0.90
? Container(
height: 20, height: 20,
child: CustomPaint( padding: EdgeInsets.symmetric(horizontal: 10),
painter: ListenedAllPainter( child: SizedBox(
context.accentColor, width: 20,
stroke: 2.0), height: 20,
), child: CustomPaint(
), painter: ListenedAllPainter(
) context.accentColor,
: snapshot.data.seconds < 10 stroke: 2.0),
? 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(); )
}), : snapshot.data.seconds < 10
Selector<AudioPlayerNotifier, double>( ? Center()
selector: (_, audio) => audio.switchValue, : OutlineButton(
builder: (_, data, __) => data == 1 shape: RoundedRectangleBorder(
? Container( borderRadius:
height: 20, BorderRadius.circular(100.0),
width: 40, side: BorderSide(
child: Transform.rotate( color: context.accentColor)),
angle: math.pi * 0.7, highlightedBorderColor: Colors.green[700],
child: Icon(Icons.brightness_2, onPressed: () => audio.seekTo(
size: 18, color: context.accentColor))) (snapshot.data.seconds * 1000).toInt()),
: Center(), 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<AudioPlayerNotifier, double>(
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(),
)
],
),
); );
}, },
); );

View File

@ -24,6 +24,10 @@
"@autoDownload": {}, "@autoDownload": {},
"back": "Back", "back": "Back",
"@back": {}, "@back": {},
"boostVolume": "Boost volume",
"@boostVolume": {
"description": "Boost volume in player widget."
},
"buffering": "Buffering", "buffering": "Buffering",
"@buffering": {}, "@buffering": {},
"cancel": "CANCEL", "cancel": "CANCEL",

View File

@ -24,6 +24,10 @@
"@autoDownload": {}, "@autoDownload": {},
"back": "Atras", "back": "Atras",
"@back": {}, "@back": {},
"boostVolume": "Boost volume",
"@boostVolume": {
"description": "Boost volume in player widget."
},
"buffering": "Cargando ", "buffering": "Cargando ",
"@buffering": {}, "@buffering": {},
"cancel": "CANCELAR", "cancel": "CANCELAR",

View File

@ -24,6 +24,10 @@
"@autoDownload": {}, "@autoDownload": {},
"back": "Retour", "back": "Retour",
"@back": {}, "@back": {},
"boostVolume": "Boost volume",
"@boostVolume": {
"description": "Boost volume in player widget."
},
"buffering": "Buffering", "buffering": "Buffering",
"@buffering": {}, "@buffering": {},
"cancel": "ANNULER", "cancel": "ANNULER",

View File

@ -24,6 +24,10 @@
"@autoDownload": {}, "@autoDownload": {},
"back": "返回", "back": "返回",
"@back": {}, "@back": {},
"boostVolume": "增强声音",
"@boostVolume": {
"description": "Boost volume in player widget."
},
"buffering": "缓冲中", "buffering": "缓冲中",
"@buffering": {}, "@buffering": {},
"cancel": "取消", "cancel": "取消",

View File

@ -66,6 +66,8 @@ class AudioPlayerNotifier extends ChangeNotifier {
var playerHeightStorage = KeyValueStorage(playerHeightKey); var playerHeightStorage = KeyValueStorage(playerHeightKey);
var speedStorage = KeyValueStorage(speedKey); var speedStorage = KeyValueStorage(speedKey);
var skipSilenceStorage = KeyValueStorage(skipSilenceKey); var skipSilenceStorage = KeyValueStorage(skipSilenceKey);
var boostVolumeStorage = KeyValueStorage(boostVolumeKey);
var volumeGainStorage = KeyValueStorage(volumeGainKey);
/// Current playing episdoe. /// Current playing episdoe.
EpisodeBrief _episode; EpisodeBrief _episode;
@ -148,6 +150,12 @@ class AudioPlayerNotifier extends ChangeNotifier {
/// Player skip silence. /// Player skip silence.
bool _skipSilence; bool _skipSilence;
/// Boost volumn
bool _boostVolume;
/// Boost volume gain.
int _volumeGain;
// ignore: prefer_final_fields // ignore: prefer_final_fields
bool _playerRunning = false; bool _playerRunning = false;
@ -175,6 +183,8 @@ class AudioPlayerNotifier extends ChangeNotifier {
int get rewindSeconds => _rewindSeconds; int get rewindSeconds => _rewindSeconds;
PlayerHeight get playerHeight => _playerHeight; PlayerHeight get playerHeight => _playerHeight;
bool get skipSilence => _skipSilence; bool get skipSilence => _skipSilence;
bool get boostVolume => _boostVolume;
int get volumeGain => _volumeGain;
set setSwitchValue(double value) { set setSwitchValue(double value) {
_switchValue = value; _switchValue = value;
@ -197,6 +207,8 @@ class AudioPlayerNotifier extends ChangeNotifier {
_playerHeight = PlayerHeight.values[index]; _playerHeight = PlayerHeight.values[index];
_currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0); _currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0);
_skipSilence = await skipSilenceStorage.getBool(defaultValue: false); _skipSilence = await skipSilenceStorage.getBool(defaultValue: false);
_boostVolume = await boostVolumeStorage.getBool(defaultValue: false);
_volumeGain = await volumeGainStorage.getInt(defaultValue: 3000);
} }
Future _savePlayerHeight() async { Future _savePlayerHeight() async {
@ -345,12 +357,23 @@ class AudioPlayerNotifier extends ChangeNotifier {
sleepTimer(defaultTimer); sleepTimer(defaultTimer);
} }
} }
/// Set player speed.
if (_currentSpeed != 1.0) { if (_currentSpeed != 1.0) {
await AudioService.customAction('setSpeed', _currentSpeed); await AudioService.customAction('setSpeed', _currentSpeed);
} }
/// Set slipsilence.
if (_skipSilence) { if (_skipSilence) {
await AudioService.customAction('setSkipSilence', skipSilence); await AudioService.customAction('setSkipSilence', skipSilence);
} }
/// Set boostValome.
if (_boostVolume) {
await AudioService.customAction(
'setBoostVolume', [_boostVolume, _volumeGain]);
}
await AudioService.play(); await AudioService.play();
AudioService.currentMediaItemStream AudioService.currentMediaItemStream
@ -456,6 +479,8 @@ class AudioPlayerNotifier extends ChangeNotifier {
playNext() async { playNext() async {
await AudioService.skipToNext(); await AudioService.skipToNext();
_queueUpdate = !_queueUpdate;
notifyListeners();
} }
addToPlaylist(EpisodeBrief episode) async { addToPlaylist(EpisodeBrief episode) async {
@ -520,6 +545,19 @@ class AudioPlayerNotifier extends ChangeNotifier {
return index; 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<bool> moveToTop(EpisodeBrief episode) async { Future<bool> moveToTop(EpisodeBrief episode) async {
await delFromPlaylist(episode); await delFromPlaylist(episode);
if (playerRunning) { if (playerRunning) {
@ -535,11 +573,11 @@ class AudioPlayerNotifier extends ChangeNotifier {
return true; return true;
} }
pauseAduio() async { Future<void> pauseAduio() async {
AudioService.pause(); await AudioService.pause();
} }
resumeAudio() async { Future<void> resumeAudio() async {
if (_audioState != AudioProcessingState.connecting && if (_audioState != AudioProcessingState.connecting &&
_audioState != AudioProcessingState.none) AudioService.play(); _audioState != AudioProcessingState.none) AudioService.play();
} }
@ -591,6 +629,14 @@ class AudioPlayerNotifier extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
setBoostVolume({@required bool boostVolume, int gain}) async {
await AudioService.customAction(
'setBoostVolume', [boostVolume, _volumeGain]);
_boostVolume = boostVolume;
notifyListeners();
await boostVolumeStorage.saveBool(boostVolume);
}
//Set sleep timer //Set sleep timer
sleepTimer(int mins) { sleepTimer(int mins) {
if (_sleepTimerMode == SleepTimerMode.timer) { if (_sleepTimerMode == SleepTimerMode.timer) {
@ -953,6 +999,9 @@ class AudioPlayerTask extends BackgroundAudioTask {
case 'setSkipSilence': case 'setSkipSilence':
await _setSkipSilence(argument); await _setSkipSilence(argument);
break; break;
case 'setBoostVolume':
await _setBoostVolume(argument[0], argument[1]);
break;
} }
} }
@ -962,6 +1011,10 @@ class AudioPlayerTask extends BackgroundAudioTask {
AudioServiceBackground.setMediaItem(mediaItem.copyWith(duration: duration)); AudioServiceBackground.setMediaItem(mediaItem.copyWith(duration: duration));
} }
Future _setBoostVolume(bool boo, int gain) async {
await _audioPlayer.setBoostVolume(boo, gain: gain);
}
Future<void> _setState({ Future<void> _setState({
AudioProcessingState processingState, AudioProcessingState processingState,
Duration position, Duration position,