|
@@ -2,52 +2,24 @@
|
|
|
|
|
|
import datetime as dt
|
|
|
import mutagen
|
|
|
-import mutagen.id3
|
|
|
-import mutagen.mp4
|
|
|
+
|
|
|
+import symuid.tag_interface
|
|
|
|
|
|
|
|
|
class Track:
|
|
|
|
|
|
def __init__(self, path):
|
|
|
- self._mutagen = mutagen.File(filename=path)
|
|
|
+ mutagen_file = mutagen.File(filename=path)
|
|
|
+ if isinstance(mutagen_file.tags, mutagen.id3.ID3):
|
|
|
+ self._iface = symuid.tag_interface.ID3(mutagen_file)
|
|
|
+ elif isinstance(mutagen_file.tags, mutagen.mp4.MP4Tags):
|
|
|
+ self._iface = symuid.tag_interface.MP4(mutagen_file)
|
|
|
+ else:
|
|
|
+ raise NotImplementedError((path, type(mutagen_file)))
|
|
|
|
|
|
@property
|
|
|
def path(self):
|
|
|
- return self._mutagen.filename
|
|
|
-
|
|
|
- @property
|
|
|
- def has_tags(self):
|
|
|
- return self._mutagen and self._mutagen.tags
|
|
|
-
|
|
|
- @property
|
|
|
- def has_id3_tags(self):
|
|
|
- return self.has_tags and isinstance(self._mutagen.tags, mutagen.id3.ID3)
|
|
|
-
|
|
|
- @property
|
|
|
- def has_mp4_tags(self):
|
|
|
- return self.has_tags and isinstance(self._mutagen.tags, mutagen.mp4.MP4Tags)
|
|
|
-
|
|
|
- def _get_id3_textframe_int(self, tag_label):
|
|
|
- values = self._mutagen.tags['TXXX:' + tag_label].text
|
|
|
- assert len(values) == 1, values
|
|
|
- return int(values[0])
|
|
|
-
|
|
|
- def _get_mp4_freeform_int(self, tag_label):
|
|
|
- tag, = self._mutagen.tags['----:' + tag_label]
|
|
|
-
|
|
|
- assert tag.dataformat == mutagen.mp4.AtomDataType.INTEGER, tag.dataformat
|
|
|
- return int.from_bytes(tag, byteorder='big', signed=True)
|
|
|
-
|
|
|
- def _set_mp4_freeform_int(self, tag_label, data):
|
|
|
- assert isinstance(data, int)
|
|
|
- tag = mutagen.mp4.MP4FreeForm(
|
|
|
-
|
|
|
- dataformat=mutagen.mp4.AtomDataType.INTEGER,
|
|
|
-
|
|
|
- data=data.to_bytes(1, byteorder='big', signed=True),
|
|
|
- )
|
|
|
- self._mutagen.tags['----:' + tag_label] = tag
|
|
|
- return tag
|
|
|
+ return self._iface.track_path
|
|
|
|
|
|
def register_play_count(self, player, library_id, register_dt, play_count, tag_set_cb=None):
|
|
|
assert isinstance(register_dt, dt.datetime), register_dt
|
|
@@ -55,33 +27,11 @@ class Track:
|
|
|
tag_label = 'symuid:pcnt:{}:{}:{:.0f}'.format(
|
|
|
player, library_id, register_dt.timestamp(),
|
|
|
)
|
|
|
- if self.has_id3_tags:
|
|
|
- try:
|
|
|
- reg_count = self._get_id3_textframe_int(tag_label)
|
|
|
- assert reg_count == play_count, (reg_count, play_count)
|
|
|
- except KeyError:
|
|
|
-
|
|
|
-
|
|
|
- tag = mutagen.id3.TXXX(
|
|
|
- encoding=mutagen.id3.Encoding.LATIN1,
|
|
|
- desc=tag_label,
|
|
|
- text=[str(play_count)],
|
|
|
- )
|
|
|
- self._mutagen.tags.add(tag)
|
|
|
- self._mutagen.save()
|
|
|
- if tag_set_cb:
|
|
|
- tag_set_cb(self, tag)
|
|
|
- elif self.has_mp4_tags:
|
|
|
- try:
|
|
|
- reg_count = self._get_mp4_freeform_int(tag_label)
|
|
|
- assert reg_count == play_count, (reg_count, play_count)
|
|
|
- except KeyError:
|
|
|
- tag = self._set_mp4_freeform_int(
|
|
|
- tag_label=tag_label,
|
|
|
- data=play_count,
|
|
|
- )
|
|
|
- self._mutagen.save()
|
|
|
- if tag_set_cb:
|
|
|
- tag_set_cb(self, tag)
|
|
|
- else:
|
|
|
- raise NotImplementedError()
|
|
|
+ try:
|
|
|
+ current_count = self._iface.get_free_int(tag_label)
|
|
|
+ assert current_count == play_count, (current_count, play_count)
|
|
|
+ except KeyError:
|
|
|
+ new_tag = self._iface.set_free_int(tag_label, play_count)
|
|
|
+ self._iface.save()
|
|
|
+ if tag_set_cb:
|
|
|
+ tag_set_cb(self, new_tag)
|