Browse Source

refactor symuid.Track: use new classes in symuid/tag_interface.py

Fabian Peter Hammerle 6 years ago
parent
commit
1a2fa233b1
2 changed files with 82 additions and 68 deletions
  1. 18 68
      symuid/__init__.py
  2. 64 0
      symuid/tag_interface.py

+ 18 - 68
symuid/__init__.py

@@ -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]
-        # "a signed big-endian integer with length one of { 1,2,3,4,8 } bytes"
-        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(
-            # "a signed big-endian integer with length one of { 1,2,3,4,8 } bytes"
-            dataformat=mutagen.mp4.AtomDataType.INTEGER,
-            # TODO set byte length properly
-            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:
-                # mutagen.id3._specs.EncodedTextSpec.write encodes
-                # 'desc' and 'text'
-                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)

+ 64 - 0
symuid/tag_interface.py

@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+
+import mutagen.id3
+import mutagen.mp4
+
+
+class _mutagen:
+
+    @property
+    def track_path(self):
+        return self._mutagen_file.filename
+
+    def save(self):
+        self._mutagen_file.save()
+
+
+class ID3(_mutagen):
+
+    def __init__(self, mutagen_file):
+        assert mutagen_file.tags, mutagen_file
+        assert isinstance(mutagen_file.tags, mutagen.id3.ID3), \
+            mutagen_file.tags
+        self._mutagen_file = mutagen_file
+
+    def get_free_int(self, tag_label):
+        values = self._mutagen_file.tags['TXXX:' + tag_label].text
+        assert len(values) == 1, values
+        return int(values[0])
+
+    def set_free_int(self, tag_label, data):
+        # mutagen.id3._specs.EncodedTextSpec.write encodes 'desc' and 'text'
+        tag = mutagen.id3.TXXX(
+            encoding=mutagen.id3.Encoding.LATIN1,
+            desc=tag_label,
+            text=[str(data)],
+        )
+        self._mutagen_file.tags.add(tag)
+        return tag
+
+
+class MP4(_mutagen):
+
+    def __init__(self, mutagen_file):
+        assert mutagen_file.tags, mutagen_file
+        assert isinstance(mutagen_file.tags, mutagen.mp4.MP4Tags), \
+            mutagen_file.tags
+        self._mutagen_file = mutagen_file
+
+    def get_free_int(self, tag_label):
+        tag, = self._mutagen_file.tags['----:' + tag_label]
+        # "a signed big-endian integer with length one of { 1,2,3,4,8 } bytes"
+        assert tag.dataformat == mutagen.mp4.AtomDataType.INTEGER, tag.dataformat
+        return int.from_bytes(tag, byteorder='big', signed=True)
+
+    def set_free_int(self, tag_label, data):
+        assert isinstance(data, int)
+        tag = mutagen.mp4.MP4FreeForm(
+            # "a signed big-endian integer with length one of { 1,2,3,4,8 } bytes"
+            dataformat=mutagen.mp4.AtomDataType.INTEGER,
+            # TODO set byte length properly
+            data=data.to_bytes(1, byteorder='big', signed=True),
+        )
+        self._mutagen_file.tags['----:' + tag_label] = tag
+        return tag