|
6 | 6 | from mutagen.id3 import (ID3, CHAP, CTOC, APIC, TIT2, TLEN, TENC,
|
7 | 7 | PictureType, CTOCFlags)
|
8 | 8 |
|
| 9 | +# Monkey patch to ensure chapter order |
| 10 | +# https://github.com/quodlibet/mutagen/pull/539 |
| 11 | +from mutagen.id3._tags import ID3Tags, save_frame |
| 12 | + |
| 13 | + |
| 14 | +def _write(self, config): |
| 15 | + # Sort frames by 'importance', then reverse frame size and then frame |
| 16 | + # hash to get a stable result |
| 17 | + order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"] |
| 18 | + |
| 19 | + framedata = [ |
| 20 | + (f, save_frame(f, config=config)) for f in self.values()] |
| 21 | + |
| 22 | + def get_prio(frame): |
| 23 | + try: |
| 24 | + return order.index(frame.FrameID) |
| 25 | + except ValueError: |
| 26 | + return len(order) |
| 27 | + |
| 28 | + def sort_key(items): |
| 29 | + frame, data = items |
| 30 | + frame_key = frame.HashKey |
| 31 | + frame_size = len(data) |
| 32 | + |
| 33 | + # Let's ensure chapters are always sorted by their 'start_time' |
| 34 | + # and not by size/element_id pair. |
| 35 | + if frame.FrameID == "CHAP": |
| 36 | + frame_key = frame.FrameID |
| 37 | + frame_size = frame.start_time |
| 38 | + |
| 39 | + return (get_prio(frame), frame_size, frame_key) |
| 40 | + |
| 41 | + framedata = [d for (f, d) in sorted(framedata, key=sort_key)] |
| 42 | + |
| 43 | + # only write unknown frames if they were loaded from the version |
| 44 | + # we are saving with. Theoretically we could upgrade frames |
| 45 | + # but some frames can be nested like CHAP, so there is a chance |
| 46 | + # we create a mixed frame mess. |
| 47 | + if self._unknown_v2_version == config.v2_version: |
| 48 | + framedata.extend(data for data in self.unknown_frames |
| 49 | + if len(data) > 10) |
| 50 | + |
| 51 | + return bytearray().join(framedata) |
| 52 | + |
| 53 | + |
| 54 | +ID3Tags._write = _write |
| 55 | + |
9 | 56 |
|
10 | 57 | def _get_frames(f_id: str):
|
11 | 58 | paths = glob(f'{f_id}/*.jpg')
|
|
0 commit comments