+21
-3
@@ -6,6 +6,11 @@ import pathlib
|
||||
import re
|
||||
import sqlite3
|
||||
import tempfile
|
||||
import sys
|
||||
if __name__ == '__main__' and __package__ is None:
|
||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
|
||||
|
||||
import generator.performance
|
||||
|
||||
APPLICATION_ID = 0x56414D50
|
||||
SONG_COLUMNS = """
|
||||
@@ -45,9 +50,20 @@ def metadata(path: pathlib.Path, root: pathlib.Path) -> dict:
|
||||
source_path=relative.as_posix(), source_json=text,
|
||||
measure_count=len(staff['measures']), total_pages=len(presentation['pages']), title_image=title_image, part=staff['name'])
|
||||
|
||||
def populate(connection: sqlite3.Connection, root: pathlib.Path) -> None:
|
||||
def populate(connection: sqlite3.Connection, root: pathlib.Path, audio_assets=None) -> None:
|
||||
if not root.is_dir():
|
||||
raise ValueError(f'{root}: score asset directory not found')
|
||||
if audio_assets is None:
|
||||
audio_assets = []
|
||||
for path in sorted(root.glob('sounds/*.wav')):
|
||||
if path.name not in ('beat1.wav', 'beat2.wav'):
|
||||
raise ValueError(f'{path}: unknown metronome sample')
|
||||
audio_assets.append(generator.performance.describe_wav(path, root))
|
||||
for path in sorted(root.glob('backing/*.wav')):
|
||||
match = re.fullmatch(r'([a-z0-9]+(?:_[a-z0-9]+)*)_(60|70|80|90|100|110|120)\.wav', path.name)
|
||||
if not match:
|
||||
raise ValueError(f'{path}: invalid backing filename')
|
||||
audio_assets.append(generator.performance.describe_wav(path, root, song_id=match[1], bpm=int(match[2])))
|
||||
folder = root / 'songs'
|
||||
if (folder.exists() or folder.is_symlink()) and not folder.is_dir():
|
||||
raise ValueError(f'{folder}: score asset directory not found')
|
||||
@@ -56,6 +72,8 @@ def populate(connection: sqlite3.Connection, root: pathlib.Path) -> None:
|
||||
connection.execute(f'PRAGMA application_id = {APPLICATION_ID}')
|
||||
connection.execute(f'CREATE TABLE songs ({SONG_COLUMNS}, part TEXT NOT NULL) STRICT')
|
||||
connection.execute('CREATE INDEX songs_menu ON songs(title, composer, part, id)')
|
||||
connection.execute('CREATE TABLE resources (id TEXT PRIMARY KEY, value TEXT NOT NULL CHECK(json_valid(value))) STRICT')
|
||||
connection.execute('INSERT INTO resources VALUES (?, ?)', ('audio', json.dumps(audio_assets)))
|
||||
for path in sorted(folder.rglob('*.json')):
|
||||
try:
|
||||
if path.parent != folder:
|
||||
@@ -67,7 +85,7 @@ def populate(connection: sqlite3.Connection, root: pathlib.Path) -> None:
|
||||
if connection.execute('PRAGMA integrity_check').fetchall() != [('ok',)]:
|
||||
raise ValueError('catalog integrity check failed')
|
||||
|
||||
def build_catalog(root: pathlib.Path, destination: pathlib.Path | None = None) -> pathlib.Path:
|
||||
def build_catalog(root: pathlib.Path, destination: pathlib.Path | None = None, *, audio_assets=None) -> pathlib.Path:
|
||||
if not root.is_dir():
|
||||
raise ValueError(f'{root}: score asset directory not found')
|
||||
destination = destination or root / 'catalog.db'
|
||||
@@ -76,7 +94,7 @@ def build_catalog(root: pathlib.Path, destination: pathlib.Path | None = None) -
|
||||
staged = pathlib.Path(temporary) / 'catalog.db'
|
||||
connection = sqlite3.connect(staged)
|
||||
try:
|
||||
populate(connection, root)
|
||||
populate(connection, root, audio_assets)
|
||||
finally:
|
||||
connection.close()
|
||||
staged.replace(destination)
|
||||
|
||||
Reference in New Issue
Block a user