open-story-teller/story-player/lib/libstory/indexfile.dart
2024-05-17 09:28:59 +02:00

176 lines
4.5 KiB
Dart

library libstory;
import 'dart:io';
import 'dart:typed_data';
import 'package:logger/logger.dart';
var logger = Logger(printer: PrettyPrinter(methodCount: 0));
class IndexFile {
static const int tlvArrayType = 0xAB;
static const int tlvObjectType = 0xE7;
static const int tlvIntegerType = 0x77;
static const int tlvStringType = 0x3D;
static const int tlvRealType = 0xB8;
// Index File stuff
Uint8List indexFileBuffer = Uint8List(0);
ByteData indexFileStream = ByteData(0);
int readPtr = 0;
int indexFileVersion = 0;
bool indexFileIsValid = false;
// Variables de gestion de l'index des histoires
int storiesCount = 0;
String libraryPath = '';
int currentStoryIndex = 0;
List<
({
String uuid,
String titleImage,
String titleSound,
String title,
String description,
int version
})> stories = [];
String getCurrentTitleImage() {
String fileName = '';
if (currentStoryIndex < storiesCount) {
fileName =
'$libraryPath/${stories[currentStoryIndex].uuid}/assets/${stories[currentStoryIndex].titleImage}';
}
return fileName;
}
String getCurrentSoundImage() {
String fileName = '';
if (currentStoryIndex < storiesCount) {
fileName =
'$libraryPath/${stories[currentStoryIndex].uuid}/assets/${stories[currentStoryIndex].titleSound}';
}
return fileName;
}
String getCurrentStoryPath() {
String path = '';
if (currentStoryIndex < storiesCount) {
path =
'$libraryPath/${stories[currentStoryIndex].uuid}';
}
return path;
}
void next() {
currentStoryIndex++;
if (currentStoryIndex >= storiesCount) {
currentStoryIndex = 0;
}
}
void previous() {
currentStoryIndex--;
if (currentStoryIndex < 0) {
currentStoryIndex = storiesCount - 1;
}
}
// Returns the size, 0 if error
int getTl(int expectedType) {
int size = 0;
if (indexFileStream.getUint8(readPtr) == expectedType) {
readPtr++;
size = indexFileStream.getUint16(readPtr, Endian.little);
readPtr += 2;
} else {
throw Exception("Expected type: $expectedType");
}
return size;
}
int getIntegerValue() {
int size = getTl(tlvIntegerType);
if (size == 4) {
int value = indexFileStream.getUint32(readPtr, Endian.little);
readPtr += 4;
return value;
} else {
throw Exception("Expected an integer of size 4 bytes");
}
}
String getStringValue() {
int size = getTl(tlvStringType);
if (size > 0) {
String value = String.fromCharCodes(
indexFileStream.buffer.asUint8List(), readPtr, readPtr + size);
readPtr += size;
return value;
} else {
return "";
}
}
Future<bool> loadIndexFile(String libraryRoot) async {
libraryPath = libraryRoot;
indexFileIsValid = false;
final file = File('$libraryRoot/index.ost');
if (!await file.exists()) {
logger.d('Le fichier n\'existe pas.');
return false;
}
// Ouvrir le fichier en mode lecture binaire
indexFileBuffer = file.readAsBytesSync();
readPtr = 0;
indexFileStream =
ByteData.sublistView(indexFileBuffer, readPtr); // start at zero
stories.clear();
if (indexFileBuffer.lengthInBytes > 3) {
// Root must be an object containing 2 elements
try {
if (getTl(tlvObjectType) == 2) {
indexFileVersion = getIntegerValue();
storiesCount = getTl(tlvArrayType);
for (int i = 0; i < storiesCount; i++) {
if (getTl(tlvObjectType) == 6) {
var record = (
uuid: getStringValue(),
titleImage: getStringValue(),
titleSound: getStringValue(),
title: getStringValue(),
description: getStringValue(),
version: getIntegerValue()
);
logger.d('Found story: ${record.title.toString()}');
stories.add(record);
} else {
throw Exception("Expected object of 6 elements at root");
}
}
// If get through here, no exception raised so the file shoould be ok
indexFileIsValid = true;
currentStoryIndex = 0;
return true;
} else {
throw Exception("Expected object of 2 elements at root");
}
} catch (e) {
logger.e('Exception reading index file: $e');
} finally {}
}
return false;
}
}