From 813531be26b2ccc62e1795463e5b43959087baa1 Mon Sep 17 00:00:00 2001 From: RecursiveGreen Date: Wed, 3 Jul 2019 11:57:46 -0400 Subject: [PATCH] Add replaygain support. --- contrib/djcontrol/djcontrol.py | 13 +++++++++-- savepointradio/api/serializers/radio.py | 5 ++-- savepointradio/radio/admin.py | 10 ++++++-- .../management/commands/importoldradio.py | 15 +++++++++++- .../radio/migrations/0005_replaygain_data.py | 23 +++++++++++++++++++ savepointradio/radio/models.py | 21 +++++++++++++++++ 6 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 savepointradio/radio/migrations/0005_replaygain_data.py diff --git a/contrib/djcontrol/djcontrol.py b/contrib/djcontrol/djcontrol.py index b4c9ab8..70d32b8 100644 --- a/contrib/djcontrol/djcontrol.py +++ b/contrib/djcontrol/djcontrol.py @@ -26,7 +26,14 @@ HEADERS = { 'Authorization': 'Token {}'.format(DJ_TOKEN) } -ANNOTATE = 'annotate:req_id="{}",type="{}",artist="{}",title="{}",game="{}":{}' +ANNOTATE = ( + 'annotate:req_id="{}",' + 'type="{}",' + 'artist="{}",' + 'title="{}",' + 'game="{}",' + 'replay_gain="{}":{}' +) logging.basicConfig( handlers=[ @@ -93,11 +100,12 @@ def next_request(): title = clean_quotes(song['title']) game = clean_quotes(song['game']) LOGGER.info( - 'Req_ID: %s, Artist[s]: %s, Title: %s, Game: %s, Path: %s', + 'ID: %s, Artist[s]: %s, Title: %s, Game: %s, Gain: %s, Path: %s', song_request['id'], artist, title, game, + song['replaygain'], song['path'] ) annotate_string = ANNOTATE.format( @@ -106,6 +114,7 @@ def next_request(): artist, title, game, + song['replaygain'], song['path'] ) LOGGER.debug(annotate_string) diff --git a/savepointradio/api/serializers/radio.py b/savepointradio/api/serializers/radio.py index a0fdaf4..cf216b8 100644 --- a/savepointradio/api/serializers/radio.py +++ b/savepointradio/api/serializers/radio.py @@ -1,4 +1,4 @@ -from rest_framework.serializers import (BooleanField, DecimalField, +from rest_framework.serializers import (BooleanField, CharField, DecimalField, IntegerField, ListField, ModelSerializer, Serializer, SerializerMethodField, @@ -120,12 +120,13 @@ class RadioSongSerializer(ModelSerializer): decimal_places=2, source='active_store.length' ) + replaygain = CharField(source='active_store.replaygain') path = SerializerMethodField() class Meta: model = Song fields = ('album', 'artists', 'game', 'song_type', 'title', 'length', - 'path') + 'replaygain', 'path') def get_path(self, obj): '''Converts the IRI into a filesystem path.''' diff --git a/savepointradio/radio/admin.py b/savepointradio/radio/admin.py index 6c5b006..d05e06d 100644 --- a/savepointradio/radio/admin.py +++ b/savepointradio/radio/admin.py @@ -114,14 +114,20 @@ class StoreAdmin(admin.ModelAdmin): list_display = ('iri', 'mime_type', 'file_size', - 'length') + 'length', + '_replaygain') search_fields = ['iri'] # Edit Form display readonly_fields = ('created_date', 'modified_date') fieldsets = ( ('Main', { - 'fields': ('iri', 'mime_type', 'file_size', 'length') + 'fields': ('iri', + 'mime_type', + 'file_size', + 'length', + 'track_gain', + 'track_peak') }), ('Stats', { 'classes': ('collapse',), diff --git a/savepointradio/radio/management/commands/importoldradio.py b/savepointradio/radio/management/commands/importoldradio.py index 3e62e46..2c643ce 100644 --- a/savepointradio/radio/management/commands/importoldradio.py +++ b/savepointradio/radio/management/commands/importoldradio.py @@ -101,11 +101,24 @@ class Command(BaseCommand): else: iri = song['store']['path'] + if song['store']['track_gain']: + gain_str = re.sub(r'[dB\+ ]', '', song['store']['track_gain']) + gain = decimal.Decimal(gain_str) + else: + gain = None + + if song['store']['track_peak']: + peak = decimal.Decimal(song['store']['track_peak']) + else: + peak = None + new_store = Store.objects.create( iri=iri, mime_type=song['store']['mime'], file_size=song['store']['filesize'], - length=song['store']['length'] + length=song['store']['length'], + track_gain=gain, + track_peak=peak ) new_song.stores.add(new_store) new_song.active_store = new_store diff --git a/savepointradio/radio/migrations/0005_replaygain_data.py b/savepointradio/radio/migrations/0005_replaygain_data.py new file mode 100644 index 0000000..8481d49 --- /dev/null +++ b/savepointradio/radio/migrations/0005_replaygain_data.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.2 on 2019-07-03 13:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('radio', '0004_new_song_path_structure'), + ] + + operations = [ + migrations.AddField( + model_name='store', + name='track_gain', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True, verbose_name='recommended replaygain adjustment'), + ), + migrations.AddField( + model_name='store', + name='track_peak', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=10, null=True, verbose_name='highest volume level in the track'), + ), + ] diff --git a/savepointradio/radio/models.py b/savepointradio/radio/models.py index e0cd628..d9dd320 100644 --- a/savepointradio/radio/models.py +++ b/savepointradio/radio/models.py @@ -117,6 +117,27 @@ class Store(Timestampable, models.Model): decimal_places=2, null=True, blank=True) + track_gain = models.DecimalField(_('recommended replaygain adjustment'), + max_digits=6, + decimal_places=2, + null=True, + blank=True) + track_peak = models.DecimalField(_('highest volume level in the track'), + max_digits=10, + decimal_places=6, + null=True, + blank=True) + + def _replaygain(self): + ''' + String representation of the recommended amplitude adjustment. + ''' + if self.track_gain is None: + return '+0.00 dB' + if self.track_gain > 0: + return '+{} dB'.format(str(self.track_gain)) + return '{} dB'.format(str(self.track_gain)) + replaygain = property(_replaygain) def __str__(self): return self.iri