mirror of
https://github.com/stonega/tsacdop
synced 2025-01-23 04:12:12 +01:00
Skip silence feature.
This commit is contained in:
parent
aa1c4843d3
commit
7a48df7f05
@ -262,6 +262,30 @@ class LastPosition extends StatelessWidget {
|
|||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
Selector<AudioPlayerNotifier, bool>(
|
||||||
|
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<PlayHistory>(
|
FutureBuilder<PlayHistory>(
|
||||||
future: getPosition(episode),
|
future: getPosition(episode),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
@ -287,15 +311,24 @@ class LastPosition extends StatelessWidget {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(100.0),
|
BorderRadius.circular(100.0),
|
||||||
side:
|
side: BorderSide(
|
||||||
BorderSide(color: Colors.green[700])),
|
color: context.accentColor)),
|
||||||
highlightedBorderColor: Colors.green[700],
|
highlightedBorderColor: Colors.green[700],
|
||||||
onPressed: () => audio.seekTo(
|
onPressed: () => audio.seekTo(
|
||||||
(snapshot.data.seconds * 1000).toInt()),
|
(snapshot.data.seconds * 1000).toInt()),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(s.timeLastPlayed(
|
SizedBox(
|
||||||
snapshot.data.seconds.toTime)),
|
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,
|
width: 40,
|
||||||
child: Transform.rotate(
|
child: Transform.rotate(
|
||||||
angle: math.pi * 0.7,
|
angle: math.pi * 0.7,
|
||||||
child: Icon(Icons.brightness_2, size: 18)))
|
child: Icon(Icons.brightness_2,
|
||||||
|
size: 18, color: context.accentColor)))
|
||||||
: Center(),
|
: Center(),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -1181,11 +1215,10 @@ class _ControlPanelState extends State<ControlPanel>
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
SizedBox(
|
||||||
height: 80.0,
|
height: 80.0,
|
||||||
padding: EdgeInsets.only(left: 60, right: 60),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -1193,6 +1226,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||||||
selector: (_, audio) => audio.episode.title,
|
selector: (_, audio) => audio.episode.title,
|
||||||
builder: (_, title, __) {
|
builder: (_, title, __) {
|
||||||
return Container(
|
return Container(
|
||||||
|
padding: EdgeInsets.only(left: 60, right: 60),
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, size) {
|
builder: (context, size) {
|
||||||
var span = TextSpan(
|
var span = TextSpan(
|
||||||
@ -1312,7 +1346,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||||||
width: 100,
|
width: 100,
|
||||||
child: Text(
|
child: Text(
|
||||||
data.item1.feedTitle,
|
data.item1.feedTitle,
|
||||||
maxLines: 1,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -34,6 +34,8 @@ const String tapToOpenPopupMenuKey = 'tapToOpenPopupMenuKey';
|
|||||||
const String fastForwardSecondsKey = 'fastForwardSecondsKey';
|
const String fastForwardSecondsKey = 'fastForwardSecondsKey';
|
||||||
const String rewindSecondsKey = 'rewindSecondsKey';
|
const String rewindSecondsKey = 'rewindSecondsKey';
|
||||||
const String playerHeightKey = 'playerHeightKey';
|
const String playerHeightKey = 'playerHeightKey';
|
||||||
|
const String speedKey = 'speedKey';
|
||||||
|
const String skipSilenceKey = 'skipSilenceKey';
|
||||||
|
|
||||||
class KeyValueStorage {
|
class KeyValueStorage {
|
||||||
final String key;
|
final String key;
|
||||||
@ -101,9 +103,10 @@ class KeyValueStorage {
|
|||||||
return prefs.getString(key);
|
return prefs.getString(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveMenu(List<int> list) async {
|
Future<bool> saveMenu(List<int> list) async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
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<List<int>> getMenu() async {
|
Future<List<int>> getMenu() async {
|
||||||
@ -129,8 +132,23 @@ class KeyValueStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Rreverse is used for compatite bool value save before which set true = 0, false = 1
|
/// Rreverse is used for compatite bool value save before which set true = 0, false = 1
|
||||||
saveBool(boo, {reverse = false}) async {
|
Future<bool> saveBool(boo, {reverse = false}) async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
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<bool> saveDouble(double data) async {
|
||||||
|
var prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.setDouble(key, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<double> 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
var fastForwardSecondsStorage = KeyValueStorage(fastForwardSecondsKey);
|
var fastForwardSecondsStorage = KeyValueStorage(fastForwardSecondsKey);
|
||||||
var rewindSecondsStorage = KeyValueStorage(rewindSecondsKey);
|
var rewindSecondsStorage = KeyValueStorage(rewindSecondsKey);
|
||||||
var playerHeightStorage = KeyValueStorage(playerHeightKey);
|
var playerHeightStorage = KeyValueStorage(playerHeightKey);
|
||||||
|
var speedStorage = KeyValueStorage(speedKey);
|
||||||
|
var skipSilenceStorage = KeyValueStorage(skipSilenceKey);
|
||||||
|
|
||||||
/// Current playing episdoe.
|
/// Current playing episdoe.
|
||||||
EpisodeBrief _episode;
|
EpisodeBrief _episode;
|
||||||
@ -137,18 +139,24 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
/// Current speed.
|
/// Current speed.
|
||||||
double _currentSpeed = 1;
|
double _currentSpeed = 1;
|
||||||
|
|
||||||
//Update episode card when setting changed
|
///Update episode card when setting changed
|
||||||
bool _episodeState = false;
|
bool _episodeState = false;
|
||||||
|
|
||||||
/// Player height.
|
/// Player height.
|
||||||
PlayerHeight _playerHeight;
|
PlayerHeight _playerHeight;
|
||||||
|
|
||||||
|
/// Player skip silence.
|
||||||
|
bool _skipSilence;
|
||||||
|
|
||||||
|
// ignore: prefer_final_fields
|
||||||
|
bool _playerRunning = false;
|
||||||
|
|
||||||
AudioProcessingState get audioState => _audioState;
|
AudioProcessingState get audioState => _audioState;
|
||||||
int get backgroundAudioDuration => _backgroundAudioDuration;
|
int get backgroundAudioDuration => _backgroundAudioDuration;
|
||||||
int get backgroundAudioPosition => _backgroundAudioPosition;
|
int get backgroundAudioPosition => _backgroundAudioPosition;
|
||||||
double get seekSliderValue => _seekSliderValue;
|
double get seekSliderValue => _seekSliderValue;
|
||||||
String get remoteErrorMessage => _remoteErrorMessage;
|
String get remoteErrorMessage => _remoteErrorMessage;
|
||||||
bool get playerRunning => _audioState != AudioProcessingState.none;
|
bool get playerRunning => _playerRunning;
|
||||||
bool get buffering => _audioState != AudioProcessingState.ready;
|
bool get buffering => _audioState != AudioProcessingState.ready;
|
||||||
int get lastPositin => _lastPostion;
|
int get lastPositin => _lastPostion;
|
||||||
Playlist get queue => _queue;
|
Playlist get queue => _queue;
|
||||||
@ -166,6 +174,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
int get fastForwardSeconds => _fastForwardSeconds;
|
int get fastForwardSeconds => _fastForwardSeconds;
|
||||||
int get rewindSeconds => _rewindSeconds;
|
int get rewindSeconds => _rewindSeconds;
|
||||||
PlayerHeight get playerHeight => _playerHeight;
|
PlayerHeight get playerHeight => _playerHeight;
|
||||||
|
bool get skipSilence => _skipSilence;
|
||||||
|
|
||||||
set setSwitchValue(double value) {
|
set setSwitchValue(double value) {
|
||||||
_switchValue = value;
|
_switchValue = value;
|
||||||
@ -183,9 +192,11 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
_savePlayerHeight();
|
_savePlayerHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _getPlayerHeight() async {
|
Future _initAudioData() async {
|
||||||
var index = await playerHeightStorage.getInt(defaultValue: 0);
|
var index = await playerHeightStorage.getInt(defaultValue: 0);
|
||||||
_playerHeight = PlayerHeight.values[index];
|
_playerHeight = PlayerHeight.values[index];
|
||||||
|
_currentSpeed = await speedStorage.getDoubel(defaultValue: 1.0);
|
||||||
|
_skipSilence = await skipSilenceStorage.getBool(defaultValue: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _savePlayerHeight() async {
|
Future _savePlayerHeight() async {
|
||||||
@ -210,9 +221,9 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
@override
|
@override
|
||||||
void addListener(VoidCallback listener) {
|
void addListener(VoidCallback listener) {
|
||||||
super.addListener(listener);
|
super.addListener(listener);
|
||||||
_getPlayerHeight();
|
_initAudioData();
|
||||||
_queueUpdate = false;
|
// _queueUpdate = false;
|
||||||
_getAutoSleepTimer();
|
// _getAutoSleepTimer();
|
||||||
AudioService.connect();
|
AudioService.connect();
|
||||||
var running = AudioService.running;
|
var running = AudioService.running;
|
||||||
if (running) {}
|
if (running) {}
|
||||||
@ -257,7 +268,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
_backgroundAudioPosition = 0;
|
_backgroundAudioPosition = 0;
|
||||||
_seekSliderValue = 0;
|
_seekSliderValue = 0;
|
||||||
_episode = episodeNew;
|
_episode = episodeNew;
|
||||||
_audioState = AudioProcessingState.connecting;
|
_playerRunning = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
//await _queue.savePlaylist();
|
//await _queue.savePlaylist();
|
||||||
_startAudioService(startPosition, episodeNew.enclosureUrl);
|
_startAudioService(startPosition, episodeNew.enclosureUrl);
|
||||||
@ -270,6 +281,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
_startAudioService(int position, String url) async {
|
_startAudioService(int position, String url) async {
|
||||||
_stopOnComplete = false;
|
_stopOnComplete = false;
|
||||||
_sleepTimerMode = SleepTimerMode.undefined;
|
_sleepTimerMode = SleepTimerMode.undefined;
|
||||||
|
_switchValue = 0;
|
||||||
|
|
||||||
/// Connect to audio service.
|
/// Connect to audio service.
|
||||||
if (!AudioService.connected) {
|
if (!AudioService.connected) {
|
||||||
@ -319,7 +331,12 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
sleepTimer(defaultTimer);
|
sleepTimer(defaultTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_currentSpeed != 1.0) {
|
||||||
|
await AudioService.customAction('setSpeed', _currentSpeed);
|
||||||
|
}
|
||||||
|
if (_skipSilence) {
|
||||||
|
await AudioService.customAction('setSkipSilence', skipSilence);
|
||||||
|
}
|
||||||
await AudioService.play();
|
await AudioService.play();
|
||||||
|
|
||||||
AudioService.currentMediaItemStream
|
AudioService.currentMediaItemStream
|
||||||
@ -343,24 +360,6 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
AudioService.skipToNext();
|
AudioService.skipToNext();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// queueSubject = BehaviorSubject<List<MediaItem>>();
|
|
||||||
// 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
|
AudioService.playbackStateStream
|
||||||
.distinct()
|
.distinct()
|
||||||
.where((event) => event != null)
|
.where((event) => event != null)
|
||||||
@ -387,6 +386,23 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
notifyListeners();
|
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;
|
//double s = _currentSpeed ?? 1.0;
|
||||||
var getPosition = 0;
|
var getPosition = 0;
|
||||||
Timer.periodic(Duration(milliseconds: 500), (timer) {
|
Timer.periodic(Duration(milliseconds: 500), (timer) {
|
||||||
@ -431,7 +447,8 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
_seekSliderValue = 0;
|
_seekSliderValue = 0;
|
||||||
_episode = _queue.playlist.first;
|
_episode = _queue.playlist.first;
|
||||||
_queueUpdate = !_queueUpdate;
|
_queueUpdate = !_queueUpdate;
|
||||||
_audioState = AudioProcessingState.connecting;
|
_audioState = AudioProcessingState.none;
|
||||||
|
_playerRunning = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
_startAudioService(_lastPostion ?? 0, _queue.playlist.first.enclosureUrl);
|
_startAudioService(_lastPostion ?? 0, _queue.playlist.first.enclosureUrl);
|
||||||
}
|
}
|
||||||
@ -554,9 +571,18 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set player speed.
|
||||||
setSpeed(double speed) async {
|
setSpeed(double speed) async {
|
||||||
await AudioService.customAction('setSpeed', speed);
|
await AudioService.customAction('setSpeed', speed);
|
||||||
_currentSpeed = 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();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,6 +845,7 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
|||||||
_playerStateSubscription.cancel();
|
_playerStateSubscription.cancel();
|
||||||
_eventSubscription.cancel();
|
_eventSubscription.cancel();
|
||||||
await _setState(processingState: AudioProcessingState.none);
|
await _setState(processingState: AudioProcessingState.none);
|
||||||
|
AudioServiceBackground.sendCustomEvent({'playerRunning': false});
|
||||||
await super.onStop();
|
await super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,7 +884,6 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
|||||||
@override
|
@override
|
||||||
void onFastForward() async {
|
void onFastForward() async {
|
||||||
await _seekRelative(fastForwardInterval);
|
await _seekRelative(fastForwardInterval);
|
||||||
print('test');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -919,9 +945,18 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
|||||||
case 'setSpeed':
|
case 'setSpeed':
|
||||||
await _audioPlayer.setSpeed(argument);
|
await _audioPlayer.setSpeed(argument);
|
||||||
break;
|
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<void> _setState({
|
Future<void> _setState({
|
||||||
AudioProcessingState processingState,
|
AudioProcessingState processingState,
|
||||||
Duration position,
|
Duration position,
|
||||||
|
Loading…
Reference in New Issue
Block a user