Fix iPod transfer: create Music/F00 dir and iTunesCDB on first run

- copy_track_to_ipod: create target directory via os.makedirs
- sync_itunescdb: create iTunesCDB from scratch if missing
- sync_itunescdb: create iTunesCDB.ext with hash if missing
This commit is contained in:
Maksim Totmin 2026-05-31 18:39:25 +07:00
parent cc429eed31
commit ab912c2e49

View File

@ -206,6 +206,7 @@ class Nano7Database:
target_dir = self.find_free_music_dir() target_dir = self.find_free_music_dir()
target_path = os.path.join(self.music_base, target_dir, new_name) target_path = os.path.join(self.music_base, target_dir, new_name)
os.makedirs(os.path.dirname(target_path), exist_ok=True)
shutil.copy2(filepath, target_path) shutil.copy2(filepath, target_path)
relative_path = f"{target_dir}/{new_name}" relative_path = f"{target_dir}/{new_name}"
@ -1102,37 +1103,48 @@ class Nano7Database:
# Compute new SHA1 hash # Compute new SHA1 hash
new_hash = hashlib.sha1(lib_data).hexdigest() new_hash = hashlib.sha1(lib_data).hexdigest()
# Read existing iTunesCDB to extract the header (first 244 bytes) # Read existing iTunesCDB to extract the header (first bytes before zlib)
with open(self.cdb_path, "rb") as f: if not os.path.exists(self.cdb_path):
cdb_data = f.read() header = b"\x00" * 244
header = b"mhfd" + struct.pack("<I", 244) + header[8:]
# Find zlib header (0x78 0x9c is most common, but also check 0x78 0xda and 0x78 0x01) compressed = zlib.compress(lib_data)
zlib_offset = -1 with open(self.cdb_path, "wb") as f:
for pattern in [b"\x78\x9c", b"\x78\xda", b"\x78\x01", b"\x78\x5e"]: f.write(header + compressed)
zlib_offset = cdb_data.find(pattern) logger.info(f"Created iTunesCDB: compressed={len(compressed)} bytes")
if zlib_offset >= 0: else:
break with open(self.cdb_path, "rb") as f:
if zlib_offset == -1: cdb_data = f.read()
logger.error("Could not find zlib header in iTunesCDB")
return # Find zlib header (0x78 0x9c is most common, but also check 0x78 0xda and 0x78 0x01)
zlib_offset = -1
header = cdb_data[:zlib_offset] for pattern in [b"\x78\x9c", b"\x78\xda", b"\x78\x01", b"\x78\x5e"]:
zlib_offset = cdb_data.find(pattern)
# Compress Library.itdb if zlib_offset >= 0:
compressed = zlib.compress(lib_data) break
if zlib_offset == -1:
# Write new iTunesCDB logger.error("Could not find zlib header in iTunesCDB")
with open(self.cdb_path, "wb") as f: return
f.write(header + compressed)
header = cdb_data[:zlib_offset]
# Compress Library.itdb
compressed = zlib.compress(lib_data)
# Write new iTunesCDB
with open(self.cdb_path, "wb") as f:
f.write(header + compressed)
# Update hash in iTunesCDB.ext # Update hash in iTunesCDB.ext
with open(self.cdb_ext_path, "r") as f: if not os.path.exists(self.cdb_ext_path):
ext_content = f.read() ext_content = f"[iTunesCDB]\nitunesdb_hash={new_hash}\n"
else:
with open(self.cdb_ext_path, "r") as f:
ext_content = f.read()
new_ext_content = re.sub(r"itunesdb_hash=\w+", f"itunesdb_hash={new_hash}", ext_content) new_ext_content = re.sub(r"itunesdb_hash=\w+", f"itunesdb_hash={new_hash}", ext_content)
with open(self.cdb_ext_path, "w") as f: with open(self.cdb_ext_path, "w") as f:
f.write(new_ext_content) f.write(new_ext_content)
logger.info(f"Synced iTunesCDB: hash={new_hash}, compressed={len(compressed)} bytes") logger.info(f"Synced iTunesCDB: hash={new_hash}, compressed={len(compressed)} bytes")
def sync_locations_cbk(self): def sync_locations_cbk(self):