12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- import datetime as dt
- import os
- import re
- import symuid
- # import symuid.library.cmus
- import sys
- FILE_PREFIX = b'CTC'
- VERSION_LENGTH = 1
- SUPPORTED_VERSION = b'\x0c'
- # 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 cache:
- # see cache.c cache_init()
- 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(cache.read(FLAGS_LENGTH), byteorder=FLAGS_BYTEORDER)
- # only support 64-bit flag
- assert flags & ~FLAG_64_BIT == 0, flags
- # 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():
- import argparse
- argparser = argparse.ArgumentParser(description=None)
- argparser.add_argument(
- 'cache_path',
- nargs='?',
- default='~/.config/cmus/cache',
- help='(default: %(default)r)',
- )
- return argparser
- def main(argv):
- argparser = _init_argparser()
- args = argparser.parse_args(argv[1:])
- symuid_import_cmus(**vars(args))
- return 0
- if __name__ == "__main__":
- sys.exit(main(sys.argv))
|