mirror of
https://github.com/beetbox/beets.git
synced 2025-12-15 21:14:19 +01:00
Remove sound check packing from mediafile
Instead implement it as a mixin
This commit is contained in:
parent
c325e1645f
commit
680009021c
1 changed files with 50 additions and 91 deletions
|
|
@ -251,14 +251,6 @@ def _sc_encode(gain, peak):
|
|||
|
||||
|
||||
|
||||
# Flags for encoding field behavior.
|
||||
|
||||
# Determine style of packing, if any.
|
||||
packing = enum('SC', # Sound Check gain/peak encoding
|
||||
name='packing')
|
||||
|
||||
|
||||
|
||||
# StorageStyle classes describe strategies for accessing values in
|
||||
# Mutagen file objects.
|
||||
|
||||
|
|
@ -268,11 +260,6 @@ class StorageStyle(object):
|
|||
- key: The Mutagen key used to access the field's data.
|
||||
- as_type: Which type the value is stored as (unicode, int,
|
||||
bool, or str).
|
||||
- packing: If this value is packed in a multiple-value storage
|
||||
unit, which type of packing (in the packing enum). Otherwise,
|
||||
None. (Makes as_type irrelevant).
|
||||
- pack_pos: If the value is packed, in which position it is
|
||||
stored.
|
||||
- suffix: When `as_type` is a string type, append this before
|
||||
storing the value.
|
||||
- float_places: When the value is a floating-point number and
|
||||
|
|
@ -283,12 +270,10 @@ class StorageStyle(object):
|
|||
# TODO Use mutagen file types instead of MediaFile formats
|
||||
formats = ['flac', 'opus', 'ogg', 'ape', 'wv', 'mpc']
|
||||
|
||||
def __init__(self, key, as_type=unicode, packing=None, pack_pos=0,
|
||||
suffix=None, float_places=2, formats=None):
|
||||
def __init__(self, key, as_type=unicode, suffix=None,
|
||||
float_places=2, formats=None):
|
||||
self.key = key
|
||||
self.as_type = as_type
|
||||
self.packing = packing
|
||||
self.pack_pos = pack_pos
|
||||
self.suffix = suffix
|
||||
self.float_places = float_places
|
||||
if formats:
|
||||
|
|
@ -306,62 +291,20 @@ class StorageStyle(object):
|
|||
return None
|
||||
|
||||
def get(self, mutagen_file):
|
||||
"""Retrieve the unpacked value of this field from the mediafile."""
|
||||
data = self.fetch(mutagen_file)
|
||||
if self.packing:
|
||||
try:
|
||||
data = self.unpack(data)[self.pack_pos]
|
||||
except IndexError:
|
||||
data = None
|
||||
|
||||
data = self._strip_possible_suffix(data)
|
||||
return data
|
||||
|
||||
def unpack(self, data):
|
||||
"""Splits raw data from a tag into a list of values."""
|
||||
packing_length = 2
|
||||
|
||||
if data is None:
|
||||
return [None] * packing_length
|
||||
|
||||
if self.packing == packing.SC:
|
||||
items = _sc_decode(data)
|
||||
|
||||
return list(items) + [None] * (packing_length - len(items))
|
||||
|
||||
def store(self, mutagen_file, value):
|
||||
"""Stores a serialized value in the mediafile."""
|
||||
mutagen_file[self.key] = [value]
|
||||
|
||||
def set(self, mutagen_file, value):
|
||||
"""Packs, serializes and stores the value in the mediafile."""
|
||||
if value is None:
|
||||
value = self._none_value()
|
||||
|
||||
if self.packing:
|
||||
data = self.fetch(mutagen_file)
|
||||
value = self.pack(data, value)
|
||||
|
||||
value = self.serialize(value)
|
||||
self.store(mutagen_file, value)
|
||||
|
||||
def pack(self, data, value):
|
||||
"""Pack value into data.
|
||||
|
||||
It unpacks ``data`` into a list, updates the value at ``self.pack_pos``
|
||||
and returns the updated list.
|
||||
"""
|
||||
items = list(self.unpack(data))
|
||||
for i in range(len(items)):
|
||||
if not items[i]:
|
||||
items[i] = self._none_value()
|
||||
|
||||
items[self.pack_pos] = value
|
||||
if self.packing == packing.SC:
|
||||
data = _sc_encode(*items)
|
||||
|
||||
return data
|
||||
|
||||
def serialize(self, value):
|
||||
"""Convert value to a type that is suitable for storing in a tag."""
|
||||
if value is None:
|
||||
|
|
@ -387,7 +330,6 @@ class StorageStyle(object):
|
|||
return value
|
||||
|
||||
def _none_value(self):
|
||||
"""The value that ``None`` atains when serializing and packing."""
|
||||
if self.out_type == int:
|
||||
return 0
|
||||
elif self.out_type == float:
|
||||
|
|
@ -411,9 +353,6 @@ class ListStorageStyle(StorageStyle):
|
|||
Subclasses may overwrite ``fetch`` and ``store``. ``fetch`` must
|
||||
return a (possibly empty) list and ``store`` receives a serialized
|
||||
list of values as the second argument.
|
||||
|
||||
This class does not support packing. A call to the packing methods
|
||||
raises an error.
|
||||
"""
|
||||
|
||||
def get(self, mutagen_file):
|
||||
|
|
@ -441,11 +380,25 @@ class ListStorageStyle(StorageStyle):
|
|||
def store(self, mutagen_file, values):
|
||||
mutagen_file[self.key] = values
|
||||
|
||||
def pack(self, data, value):
|
||||
raise NotImplementedError('packing is not implemented for lists')
|
||||
|
||||
def unpack(self, data):
|
||||
raise NotImplementedError('packing is not implemented for lists')
|
||||
class SoundCheckStorageStyleMixin(object):
|
||||
|
||||
def get(self, mutagen_file):
|
||||
data = self.fetch(mutagen_file)
|
||||
if data is None:
|
||||
return 0
|
||||
else:
|
||||
return _sc_decode(data)[self.index]
|
||||
|
||||
def set(self, mutagen_file, value):
|
||||
data = self.fetch(mutagen_file)
|
||||
if data is None:
|
||||
gain_peak = [0, 0]
|
||||
else:
|
||||
gain_peak = list(_sc_decode(data))
|
||||
gain_peak[self.index] = value or 0
|
||||
data = self.serialize(_sc_encode(*gain_peak))
|
||||
self.store(mutagen_file, data)
|
||||
|
||||
|
||||
class ASFStorageStyle(StorageStyle):
|
||||
|
|
@ -458,7 +411,6 @@ class ASFStorageStyle(StorageStyle):
|
|||
return data
|
||||
|
||||
|
||||
|
||||
class MP4StorageStyle(StorageStyle):
|
||||
|
||||
formats = ['aac', 'alac']
|
||||
|
|
@ -475,12 +427,6 @@ class MP4StorageStyle(StorageStyle):
|
|||
value = value.encode('utf8')
|
||||
return value
|
||||
|
||||
def pack(self, data, value):
|
||||
value = super(MP4StorageStyle, self).pack(data, value)
|
||||
if self.key.startswith('----:') and isinstance(value, unicode):
|
||||
value = value.encode('utf8')
|
||||
return value
|
||||
|
||||
|
||||
class MP4TupleStorageStyle(MP4StorageStyle):
|
||||
"""Store values as part of a numeric pair.
|
||||
|
|
@ -511,6 +457,12 @@ class MP4ListStorageStyle(ListStorageStyle, MP4StorageStyle):
|
|||
pass
|
||||
|
||||
|
||||
class MP4SoundCheckStorageStyle(SoundCheckStorageStyleMixin, MP4StorageStyle):
|
||||
|
||||
def __init__(self, index=0, **kwargs):
|
||||
super(MP4SoundCheckStorageStyle, self).__init__(**kwargs)
|
||||
self.index = index
|
||||
|
||||
class MP4BoolStorageStyle(MP4StorageStyle):
|
||||
|
||||
def get(self, mutagen_file):
|
||||
|
|
@ -703,6 +655,13 @@ class MP3ImageStorageStyle(ListStorageStyle, MP3StorageStyle):
|
|||
mutagen_file.tags.setall(self.key, [frame])
|
||||
|
||||
|
||||
class MP3SoundCheckStorageStyle(SoundCheckStorageStyleMixin, MP3DescStorageStyle):
|
||||
|
||||
def __init__(self, index=0, **kwargs):
|
||||
super(MP3SoundCheckStorageStyle, self).__init__(**kwargs)
|
||||
self.index = index
|
||||
|
||||
|
||||
class ASFImageStorageStyle(ListStorageStyle):
|
||||
|
||||
formats = ['asf']
|
||||
|
|
@ -1398,16 +1357,16 @@ class MediaFile(object):
|
|||
float_places=2, suffix=u' dB'),
|
||||
MP3DescStorageStyle(u'replaygain_track_gain',
|
||||
float_places=2, suffix=u' dB'),
|
||||
MP3DescStorageStyle(key='COMM', desc=u'iTunNORM', id3_lang='eng',
|
||||
packing=packing.SC, pack_pos=0),
|
||||
MP4StorageStyle('----:com.apple.iTunes:replaygain_track_gain',
|
||||
MP3SoundCheckStorageStyle(key='COMM', index=0, desc=u'iTunNORM',
|
||||
id3_lang='eng'),
|
||||
MP4StorageStyle(key='----:com.apple.iTunes:replaygain_track_gain',
|
||||
float_places=2, suffix=b' dB'),
|
||||
MP4StorageStyle('----:com.apple.iTunes:iTunNORM',
|
||||
packing=packing.SC, pack_pos=0),
|
||||
MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM',
|
||||
index=0),
|
||||
StorageStyle(u'REPLAYGAIN_TRACK_GAIN',
|
||||
float_places=2, suffix=u' dB'),
|
||||
float_places=2, suffix=u' dB'),
|
||||
ASFStorageStyle(u'replaygain_track_gain',
|
||||
float_places=2, suffix=u' dB'),
|
||||
float_places=2, suffix=u' dB'),
|
||||
out_type=float
|
||||
)
|
||||
rg_album_gain = MediaField(
|
||||
|
|
@ -1415,12 +1374,12 @@ class MediaFile(object):
|
|||
float_places=2, suffix=u' dB'),
|
||||
MP3DescStorageStyle(u'replaygain_album_gain',
|
||||
float_places=2, suffix=u' dB'),
|
||||
MP4StorageStyle('----:com.apple.iTunes:replaygain_album_gain',
|
||||
float_places=2, suffix=b' dB'),
|
||||
MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM',
|
||||
index=1),
|
||||
StorageStyle(u'REPLAYGAIN_ALBUM_GAIN',
|
||||
float_places=2, suffix=u' dB'),
|
||||
float_places=2, suffix=u' dB'),
|
||||
ASFStorageStyle(u'replaygain_album_gain',
|
||||
float_places=2, suffix=u' dB'),
|
||||
float_places=2, suffix=u' dB'),
|
||||
out_type=float
|
||||
)
|
||||
rg_track_peak = MediaField(
|
||||
|
|
@ -1428,16 +1387,16 @@ class MediaFile(object):
|
|||
float_places=6),
|
||||
MP3DescStorageStyle(u'replaygain_track_peak',
|
||||
float_places=6),
|
||||
MP3DescStorageStyle(key='COMM', desc=u'iTunNORM', id3_lang='eng',
|
||||
packing=packing.SC, pack_pos=1),
|
||||
MP3SoundCheckStorageStyle(key='COMM', index=1, desc=u'iTunNORM',
|
||||
id3_lang='eng'),
|
||||
MP4StorageStyle('----:com.apple.iTunes:replaygain_track_peak',
|
||||
float_places=6),
|
||||
MP4StorageStyle('----:com.apple.iTunes:iTunNORM',
|
||||
packing=packing.SC, pack_pos=1),
|
||||
MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM',
|
||||
index=1),
|
||||
StorageStyle(u'REPLAYGAIN_TRACK_PEAK',
|
||||
float_places=6),
|
||||
float_places=6),
|
||||
ASFStorageStyle(u'replaygain_track_peak',
|
||||
float_places=6),
|
||||
float_places=6),
|
||||
out_type=float,
|
||||
)
|
||||
rg_album_peak = MediaField(
|
||||
|
|
|
|||
Loading…
Reference in a new issue