mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 13:19:44 +02:00
65 lines
1.6 KiB
Dart
65 lines
1.6 KiB
Dart
import 'dart:async';
|
|
|
|
class AudioAnalysisCancelled implements Exception {
|
|
const AudioAnalysisCancelled();
|
|
}
|
|
|
|
/// Serializes native analysis sessions and cancels only the owned session.
|
|
/// A replacement waits for native completion before creating its output files.
|
|
class AudioAnalysisJobs<T> {
|
|
final Future<({int id, Future<T> completed})> Function(List<String>) start;
|
|
final Future<void> Function(int) cancel;
|
|
Future<void> _tail = Future<void>.value();
|
|
int _generation = 0;
|
|
int? _activeId;
|
|
bool _disposed = false;
|
|
|
|
AudioAnalysisJobs({required this.start, required this.cancel});
|
|
|
|
void invalidate() {
|
|
_generation++;
|
|
final id = _activeId;
|
|
if (id != null) unawaited(_cancel(id));
|
|
}
|
|
|
|
void dispose() {
|
|
_disposed = true;
|
|
invalidate();
|
|
}
|
|
|
|
Future<void> _cancel(int id) async {
|
|
try {
|
|
await cancel(id);
|
|
} catch (_) {
|
|
// Await the native completion even if the cancellation request fails.
|
|
}
|
|
}
|
|
|
|
Future<T> run(List<String> arguments) {
|
|
final generation = _generation;
|
|
void checkCurrent() {
|
|
if (_disposed || generation != _generation) {
|
|
throw const AudioAnalysisCancelled();
|
|
}
|
|
}
|
|
|
|
final result = _tail.then((_) async {
|
|
checkCurrent();
|
|
final session = await start(arguments);
|
|
_activeId = session.id;
|
|
try {
|
|
if (_disposed || generation != _generation) {
|
|
await _cancel(session.id);
|
|
}
|
|
final value = await session.completed;
|
|
checkCurrent();
|
|
return value;
|
|
} finally {
|
|
_activeId = null;
|
|
}
|
|
});
|
|
_tail = result.then<void>((_) {}, onError: (Object _, StackTrace _) {});
|
|
return result;
|
|
}
|
|
}
|