|
@@ -11,30 +11,53 @@ import sys
|
|
|
FILE_PREFIX = b'CTC'
|
|
|
VERSION_LENGTH = 1
|
|
|
SUPPORTED_VERSION = b'\x0c'
|
|
|
-LINE_SEPARATOR = b'\xff' * 56
|
|
|
-COLUMN_SEPARATOR = b'\x00'
|
|
|
# always big endian, see cache_init()
|
|
|
FLAGS_BYTEORDER = 'big'
|
|
|
FLAGS_LENGTH = 4
|
|
|
FLAG_64_BIT = 0x01
|
|
|
|
|
|
+
|
|
|
+class Track:
|
|
|
+
|
|
|
+ def __init__(self, cache_size, cache_bytes):
|
|
|
+ """
|
|
|
+ struct cache_entry {
|
|
|
+ // size of this struct including size itself
|
|
|
+ uint32_t size;
|
|
|
+ int32_t play_count;
|
|
|
+ int64_t mtime;
|
|
|
+ int32_t duration;
|
|
|
+ int32_t bitrate;
|
|
|
+ int32_t bpm;
|
|
|
+ uint8_t _reserved[CACHE_ENTRY_RESERVED_SIZE];
|
|
|
+ // filename, codec, codec_profile and N * (key, val)
|
|
|
+ char strings[];
|
|
|
+ };
|
|
|
+ """
|
|
|
+ assert len(cache_bytes) + 4 == cache_size
|
|
|
+ self._play_count = int.from_bytes(cache_bytes[0:4], byteorder=sys.byteorder)
|
|
|
+ self._path = cache_bytes.split(b'\xff' * 56)[1].split(b'\x00')[0]
|
|
|
+ if self._play_count > 0:
|
|
|
+ print(self._play_count, self._path.decode())
|
|
|
+
|
|
|
+
|
|
|
def symuid_import_cmus(cache_path):
|
|
|
- with open(os.path.expanduser(cache_path), 'rb') as c:
|
|
|
+ with open(os.path.expanduser(cache_path), 'rb') as cache:
|
|
|
# see cache.c cache_init()
|
|
|
- assert c.read(len(FILE_PREFIX)) == FILE_PREFIX
|
|
|
- cache_version = c.read(VERSION_LENGTH)
|
|
|
+ assert cache.read(len(FILE_PREFIX)) == FILE_PREFIX
|
|
|
+ cache_version = cache.read(VERSION_LENGTH)
|
|
|
assert cache_version == SUPPORTED_VERSION, cache_version
|
|
|
- flags = int.from_bytes(c.read(FLAGS_LENGTH), byteorder=FLAGS_BYTEORDER)
|
|
|
+ flags = int.from_bytes(cache.read(FLAGS_LENGTH), byteorder=FLAGS_BYTEORDER)
|
|
|
# only support 64-bit flag
|
|
|
assert flags & ~FLAG_64_BIT == 0, flags
|
|
|
- cache_data = [l.split(COLUMN_SEPARATOR)
|
|
|
- for l in c.read().split(LINE_SEPARATOR)]
|
|
|
- for track_data in cache_data[1:]:
|
|
|
- track_path, codec, codec_profile = track_data[0:3]
|
|
|
- if not os.path.exists(track_path):
|
|
|
- sys.stderr.write('{!r}: not found\n'.format(track_path))
|
|
|
- else:
|
|
|
- print(track_path)
|
|
|
+ # size includes size itself
|
|
|
+ while True:
|
|
|
+ size = int.from_bytes(cache.read(4), byteorder=sys.byteorder)
|
|
|
+ if size == 0:
|
|
|
+ break
|
|
|
+ Track(size, cache.read(size - 4))
|
|
|
+ # see cache.c write_ti ALIGN
|
|
|
+ cache.read((-size) % 8)
|
|
|
|
|
|
|
|
|
def _init_argparser():
|