Add _ensure_schema() to create SQLite tables if missing
- Creates all required tables (item, artist, album, avformat_info, store_info, item_to_container, track_size_calc) in Library.itdb - Creates location table in Locations.itdb - Called from Nano7Database.__init__(), so empty DB is always valid - Fixes 'no such table: item' error on iPod with wiped DB
This commit is contained in:
parent
8c9e146a6c
commit
cc429eed31
@ -31,6 +31,76 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
MASTER_CONTAINER_PID = 203092939621887772 # "iPod" master playlist
|
||||
|
||||
LIBRARY_SCHEMA_SQL = """
|
||||
CREATE TABLE IF NOT EXISTS item (
|
||||
pid INTEGER PRIMARY KEY, media_kind INTEGER, is_song INTEGER,
|
||||
date_modified INTEGER, year INTEGER, is_compilation INTEGER,
|
||||
is_user_disabled INTEGER, remember_bookmark INTEGER,
|
||||
exclude_from_shuffle INTEGER, part_of_gapless_album INTEGER,
|
||||
chosen_by_auto_fill INTEGER, artwork_status INTEGER,
|
||||
artwork_cache_id INTEGER, total_time_ms INTEGER,
|
||||
track_number INTEGER, track_count INTEGER, disc_number INTEGER,
|
||||
disc_count INTEGER, album_pid INTEGER, artist_pid INTEGER,
|
||||
title TEXT, artist TEXT, album TEXT, album_artist TEXT,
|
||||
sort_title TEXT, sort_artist TEXT, sort_album TEXT,
|
||||
sort_album_artist TEXT, title_order INTEGER, artist_order INTEGER,
|
||||
album_order INTEGER, physical_order INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS artist (
|
||||
pid INTEGER PRIMARY KEY, kind INTEGER, artwork_status INTEGER,
|
||||
artwork_album_pid INTEGER, name TEXT, name_order INTEGER,
|
||||
sort_name TEXT, is_unknown INTEGER, has_songs INTEGER,
|
||||
has_music_videos INTEGER, has_non_compilation_tracks INTEGER,
|
||||
album_count INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS album (
|
||||
pid INTEGER PRIMARY KEY, kind INTEGER, artwork_status INTEGER,
|
||||
artwork_item_pid INTEGER, artist_pid INTEGER, user_rating INTEGER,
|
||||
name TEXT, name_order INTEGER, all_compilations INTEGER,
|
||||
feed_url TEXT, season_number INTEGER, is_unknown INTEGER,
|
||||
has_songs INTEGER, has_music_videos INTEGER, sort_order INTEGER,
|
||||
artist_order INTEGER, has_any_compilations INTEGER, sort_name TEXT,
|
||||
artist_count_calc INTEGER, has_movies INTEGER, item_count INTEGER,
|
||||
min_volume_normalization_energy INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS avformat_info (
|
||||
item_pid INTEGER, sub_id INTEGER, audio_format INTEGER,
|
||||
bit_rate INTEGER, channels INTEGER, sample_rate INTEGER,
|
||||
duration INTEGER, gapless_heuristic_info INTEGER,
|
||||
gapless_encoding_delay INTEGER, gapless_encoding_drain INTEGER,
|
||||
gapless_last_frame_resynch INTEGER, analysis_inhibit_flags INTEGER,
|
||||
audio_fingerprint INTEGER, volume_normalization_energy INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS store_info (
|
||||
item_pid INTEGER PRIMARY KEY
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS item_to_container (
|
||||
item_pid INTEGER, container_pid INTEGER, physical_order INTEGER,
|
||||
shuffle_order INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS track_size_calc (
|
||||
kind TEXT PRIMARY KEY, size INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO track_size_calc (kind, size) VALUES ('audio', 0);
|
||||
"""
|
||||
|
||||
LOCATIONS_SCHEMA_SQL = """
|
||||
CREATE TABLE IF NOT EXISTS location (
|
||||
item_pid INTEGER, sub_id INTEGER, base_location_id INTEGER,
|
||||
location_type INTEGER, location TEXT, extension INTEGER,
|
||||
kind_id INTEGER, date_created INTEGER, file_size INTEGER,
|
||||
file_creator INTEGER, file_type INTEGER,
|
||||
num_dir_levels_file INTEGER, num_dir_levels_lib INTEGER
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
class Nano7Database:
|
||||
"""Manages iPod Nano 7 SQLite database and iTunesCDB"""
|
||||
@ -62,6 +132,25 @@ class Nano7Database:
|
||||
".mp4": struct.unpack(">I", b"MP4 ")[0],
|
||||
}
|
||||
|
||||
self._ensure_schema()
|
||||
|
||||
def _ensure_schema(self) -> None:
|
||||
"""Create required tables in Library.itdb and Locations.itdb if missing."""
|
||||
sqlite_path = self.sqlite_path
|
||||
locations_path = self.locations_path
|
||||
|
||||
for db_path, schema in [(sqlite_path, LIBRARY_SCHEMA_SQL),
|
||||
(locations_path, LOCATIONS_SCHEMA_SQL)]:
|
||||
try:
|
||||
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.executescript(schema)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
logger.info(f"Schema ensured in {os.path.basename(db_path)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to ensure schema in {db_path}: {e}")
|
||||
|
||||
def _detect_firewire_id(self) -> bytes:
|
||||
"""Parse FirewireGuid from SysInfo file on the iPod."""
|
||||
sysinfo_path = os.path.join(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user