Initial flame_lua_runtime package
This commit is contained in:
124
lib/runtime/audio/runtime_audio_loading.dart
Normal file
124
lib/runtime/audio/runtime_audio_loading.dart
Normal file
@@ -0,0 +1,124 @@
|
||||
part of 'runtime_audio_manager.dart';
|
||||
|
||||
extension _RuntimeAudioManagerLoading on RuntimeAudioManager {
|
||||
Future<Uint8List?> _loadAudio(
|
||||
String? keyOrPath, {
|
||||
required bool failOnError,
|
||||
}) {
|
||||
if (keyOrPath == null || keyOrPath.isEmpty) {
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
final requestToken = _asyncGate.token;
|
||||
final requestGeneration = requestToken.generation;
|
||||
final path = _tryResolve(keyOrPath);
|
||||
if (path == null) {
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
final existing = _audios[path];
|
||||
if (existing != null) {
|
||||
final bytes = existing.bytes;
|
||||
if (existing.generation == requestGeneration &&
|
||||
existing.state == GameResourceState.ready &&
|
||||
bytes != null) {
|
||||
_touch(existing);
|
||||
return Future.value(bytes);
|
||||
}
|
||||
final inflight = existing.inflight;
|
||||
if (existing.generation == requestGeneration && inflight != null) {
|
||||
return failOnError
|
||||
? _throwIfNull(inflight, keyOrPath)
|
||||
: inflight.catchError((_) => null);
|
||||
}
|
||||
}
|
||||
|
||||
final record = _AudioResourceRecord(generation: requestGeneration)
|
||||
..state = GameResourceState.loading;
|
||||
_audios[path] = record;
|
||||
|
||||
final future = _readAudio(path, record, requestToken);
|
||||
record.inflight = future;
|
||||
return failOnError ? _throwIfNull(future, keyOrPath) : future;
|
||||
}
|
||||
|
||||
Future<Uint8List?> _throwIfNull(
|
||||
Future<Uint8List?> future,
|
||||
String keyOrPath,
|
||||
) async {
|
||||
final bytes = await future;
|
||||
if (bytes == null) {
|
||||
throw ResourceLoadException('Required audio resource failed: $keyOrPath');
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
Future<Uint8List?> _readAudio(
|
||||
String path,
|
||||
_AudioResourceRecord record,
|
||||
RuntimeAsyncToken requestToken,
|
||||
) async {
|
||||
try {
|
||||
final activePackage = _package;
|
||||
if (activePackage == null) {
|
||||
throw StateError('RuntimeAudioManager has no active package');
|
||||
}
|
||||
|
||||
final ownedBytes = await _loadLimiter.run(() async {
|
||||
final data = await activePackage.readBytes(path);
|
||||
final bytes = data.buffer.asUint8List(
|
||||
data.offsetInBytes,
|
||||
data.lengthInBytes,
|
||||
);
|
||||
return Uint8List.fromList(bytes);
|
||||
});
|
||||
record.inflight = null;
|
||||
|
||||
if (_disposed ||
|
||||
!_asyncGate.accepts(requestToken) ||
|
||||
_audios[path] != record) {
|
||||
record.state = GameResourceState.disposed;
|
||||
return null;
|
||||
}
|
||||
|
||||
record
|
||||
..bytes = ownedBytes
|
||||
..state = GameResourceState.ready
|
||||
..lastError = null;
|
||||
_cacheBytes += ownedBytes.length;
|
||||
_touch(record);
|
||||
_enforceAudioBudget();
|
||||
return ownedBytes;
|
||||
} catch (error) {
|
||||
record.inflight = null;
|
||||
if (_disposed ||
|
||||
!_asyncGate.accepts(requestToken) ||
|
||||
_audios[path] != record) {
|
||||
record.state = GameResourceState.disposed;
|
||||
return null;
|
||||
}
|
||||
record
|
||||
..state = GameResourceState.failed
|
||||
..lastError = error;
|
||||
_diagnostics?.record(
|
||||
type: RuntimeDiagnosticType.resourceLoadError,
|
||||
message: 'Audio resource failed to load',
|
||||
error: error,
|
||||
context: {'path': path, 'generation': requestToken.generation},
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String? _tryResolve(String keyOrPath) {
|
||||
try {
|
||||
final activePackage = _package;
|
||||
if (activePackage == null) {
|
||||
return null;
|
||||
}
|
||||
return activePackage.resolveResourcePath(keyOrPath);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user