]> git.0d.be Git - django-panik-nonstop.git/commitdiff
use streamed diffusion objects for persistence of soundfile diffusions
authorFrédéric Péters <fpeters@0d.be>
Sat, 16 May 2020 08:46:23 +0000 (10:46 +0200)
committerFrédéric Péters <fpeters@0d.be>
Sat, 16 May 2020 08:47:29 +0000 (10:47 +0200)
nonstop/forms.py
nonstop/migrations/0019_auto_20200516_1034.py [new file with mode: 0644]
nonstop/models.py
nonstop/templates/nonstop/soma_palinsesti.xml
nonstop/templates/nonstop/streamed-diffusion.html
nonstop/urls.py
nonstop/utils.py
nonstop/views.py

index 4b5eaab3a53ab859e5e9baa610f21550c7fa8a76..b0dce522a61bc8e4c49e52bfb55d9dc1275319ba 100644 (file)
@@ -40,12 +40,3 @@ class TrackSearchForm(forms.Form):
 
 class CleanupForm(forms.Form):
     zone = forms.ChoiceField(label=_('Nonstop Zone'), choices=get_optional_nonstop_zones)
-
-
-
-def get_optional_jingle():
-    return [('', '')] + [(x.id, x.label) for x in Jingle.objects.all()]
-
-
-class AddDiffusionForm(forms.Form):
-    jingle = forms.ChoiceField(label=_('Jingle'), choices=get_optional_jingle, required=False)
diff --git a/nonstop/migrations/0019_auto_20200516_1034.py b/nonstop/migrations/0019_auto_20200516_1034.py
new file mode 100644 (file)
index 0000000..a8a8bd8
--- /dev/null
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2020-05-16 10:34
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('nonstop', '0018_auto_20200106_1927'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='streameddiffusion',
+            name='added_to_nonstop_timestamp',
+            field=models.DateTimeField(null=True),
+        ),
+        migrations.AddField(
+            model_name='streameddiffusion',
+            name='creation_timestamp',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='streameddiffusion',
+            name='diffusion',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='emissions.Diffusion'),
+        ),
+        migrations.AlterField(
+            model_name='streameddiffusion',
+            name='stream',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='nonstop.Stream'),
+        ),
+    ]
index 1ab0daf232ac5c27e0afa34505a67d99fcca2e4f..9280a1784973a146c7b08c77435b4af7fb8e1823 100644 (file)
@@ -5,6 +5,8 @@ import mutagen
 from django.conf import settings
 from django.core.urlresolvers import reverse
 from django.db import models
+from django.db.models.signals import post_delete
+from django.dispatch import receiver
 from django.utils.timezone import now
 from django.utils.translation import ugettext_lazy as _
 
@@ -192,6 +194,41 @@ class StreamedDiffusion(models.Model):
         verbose_name = _('Streamed diffusion')
         verbose_name_plural = _('Streamed diffusions')
 
-    diffusion = models.ForeignKey('emissions.Diffusion')
+    diffusion = models.ForeignKey('emissions.Diffusion', null=True, blank=True, on_delete=models.SET_NULL)
     jingle = models.ForeignKey(Jingle, null=True, blank=True)
-    stream = models.ForeignKey(Stream)
+    stream = models.ForeignKey(Stream, null=True, blank=True)
+    creation_timestamp = models.DateTimeField(auto_now_add=True, null=True)
+    added_to_nonstop_timestamp = models.DateTimeField(null=True)
+
+    @property
+    def datetime(self):
+        return self.diffusion.datetime
+
+    @property
+    def end_datetime(self):
+        return self.diffusion.end_datetime
+
+    @property
+    def episode(self):
+        return self.diffusion.episode
+
+    @property
+    def soma_id(self):
+        if self.is_stream():
+            return '[stream:%s]' % self.id
+        else:
+            return '[sound:%s]' % self.id
+
+    def is_stream(self):
+        return bool(self.stream_id)
+
+
+@receiver(post_delete)
+def remove_soundfile(sender, instance=None, **kwargs):
+    from emissions.models import SoundFile
+    if not issubclass(sender, SoundFile):
+        return
+    StreamedDiffusion.objects.filter(
+            diffusion__episode_id=instance.episode_id,
+            stream_id=None).update(
+            diffusion=None)
index 2a697862324163f99e4aae6ad27246bb339fff54..ceea5f866fcf05d369e027eb0987885ff0e811d1 100644 (file)
@@ -1,7 +1,7 @@
 {% load l10n nonstop %}
 {% localize off %}
 <Palinsesto>
-  <Description color="#FF0000">{% if streamed_diffusion %}[stream:{{streamed_diffusion.id}}] {% endif %}{{ episode.emission.title|somafix }} - {{ episode.title|somafix }}</Description>
+  <Description color="#FF0000">{{ diffusion.soma_id }} {{ episode.emission.title|somafix }} - {{ episode.title|somafix }}</Description>
 
   <Priority>1</Priority>
   <Start>{{ start|date:"Y-m-d x H:i" }}</Start>
@@ -9,9 +9,9 @@
   <TimeContinued>1</TimeContinued>
   <SpotController>0</SpotController>
 
-  {% if streamed_diffusion %}
+  {% if diffusion.is_stream %}
   <Type>stream</Type>
-  <Stream>{{streamed_diffusion.stream.url}}</Stream>
+  <Stream>{{diffusion.stream.url}}</Stream>
   {% else %}
   <Type>files</Type>
   <Stream></Stream>
@@ -27,7 +27,7 @@
   <ModuleData></ModuleData>
 
   <Random>0</Random>
-  {% if streamed_diffusion %}
+  {% if diffusion.is_stream %}
   <SoftStop>0</SoftStop>
   {% else %}
   <SoftStop>1</SoftStop>
index c8eed3a2036926bbe4ec8d2ae443fd84cd5eeabb..0bd9304ed36ab4dc6495851860a72f9e616fd365 100644 (file)
@@ -2,7 +2,7 @@
 {% load i18n %}
 
 {% block appbar %}
-<h2>{% trans "New Streamed Diffusion" %}</h2>
+<h2>{% trans "Diffusion Details" %}</h2>
 {% endblock %}
 
 {% block content %}
index 4439c7d1bef1d2878b594e7614e5ac82a06a4820..fdb7ba128a8478668179bd62bda443113c00b477 100644 (file)
@@ -3,8 +3,7 @@ from django.conf.urls import url
 from .views import (SomaDayArchiveView, SomaDayArchiveCsvView, RedirectTodayView,
         TrackDetailView, ArtistDetailView, ArtistListView, StatisticsView,
         UploadTracksView, RecentTracksView, QuickLinksView, SearchView, CleanupView,
-        SearchCsvView, AddDiffusionView, AddStreamedDiffusionView,
-        DelStreamedDiffusionView,
+        SearchCsvView, AddSomaDiffusionView, DelSomaDiffusionView,
         jingle_audio_view)
 
 urlpatterns = [
@@ -29,8 +28,7 @@ urlpatterns = [
     url(r'^cleanup/$', CleanupView.as_view(), name='nonstop-cleanup'),
 
     # soma management for episodes
-    url(r'^diffusion/(?P<pk>\d+)/add/$', AddDiffusionView.as_view(), name='nonstop-add-diffusion'),
-    url(r'^diffusion/(?P<pk>\d+)/add-stream/$', AddStreamedDiffusionView.as_view(), name='nonstop-add-streamed-diffusion'),
-    url(r'^diffusion/(?P<pk>\d+)/del-stream/$', DelStreamedDiffusionView.as_view(), name='nonstop-del-streamed-diffusion'),
+    url(r'^diffusion/(?P<pk>\d+)/add/$', AddSomaDiffusionView.as_view(), name='nonstop-add-diffusion'),
+    url(r'^diffusion/(?P<pk>\d+)/del/$', DelSomaDiffusionView.as_view(), name='nonstop-del-diffusion'),
     url(r'^api/jingle/(?P<pk>\d+)/$', jingle_audio_view),
 ]
index 3ab9c68b7d52cb2aadf49b1d096cb9fa0bafa9a5..c4cb24540bbb4f229d73dae74c126a16241f5f77 100644 (file)
@@ -47,13 +47,9 @@ def get_diffusion_file_path(diffusion):
             diffusion.datetime.strftime('%Y%m%d-%H%M'),
             diffusion.episode.emission.slug)
 
-def is_already_in_soma(diffusion):
-    if StreamedDiffusion.objects.filter(diffusion=diffusion).count():
-        return True
-    return os.path.exists(os.path.join(LOCAL_BASE_PATH, get_diffusion_file_path(diffusion)))
 
-class DuplicateDiffusionSlot(Exception):
-    pass
+def is_already_in_soma(diffusion):
+    return StreamedDiffusion.objects.filter(diffusion=diffusion).exists()
 
 
 def soma_connection():
@@ -70,13 +66,13 @@ def soma_connection():
 
 def add_diffusion(diffusion, **kwargs):
     context = {}
-    streamed_diffusion = StreamedDiffusion.objects.filter(diffusion=diffusion).first()
-    if streamed_diffusion:
-        # program a stream
-        context['streamed_diffusion'] = streamed_diffusion
-        context['end'] = diffusion.end_datetime
-        context['jingle'] = streamed_diffusion.jingle
-    else:
+    context['diffusion'] = diffusion
+    context['jingle'] = diffusion.jingle
+    context['episode'] = diffusion.episode
+    context['start'] = diffusion.datetime
+    context['end'] = diffusion.end_datetime
+
+    if not diffusion.is_stream():
         # program a soundfile
         soundfile = diffusion.episode.soundfile_set.filter(fragment=False)[0]
         diffusion_path = get_diffusion_file_path(diffusion)
@@ -84,9 +80,12 @@ def add_diffusion(diffusion, **kwargs):
         # copy file
         if not os.path.exists(LOCAL_BASE_PATH):
             raise SomaException('soma directory is not available')
-        if os.path.exists(os.path.join(LOCAL_BASE_PATH, diffusion_path)):
-            raise DuplicateDiffusionSlot()
-        os.mkdir(os.path.join(LOCAL_BASE_PATH, diffusion_path))
+        local_diffusion_path = os.path.join(LOCAL_BASE_PATH, diffusion_path)
+        if os.path.exists(local_diffusion_path):
+            for filename in os.listdir(local_diffusion_path):
+                os.unlink(os.path.join(local_diffusion_path, filename))
+        else:
+            os.mkdir(os.path.join(LOCAL_BASE_PATH, diffusion_path))
         try:
             shutil.copyfile(soundfile.file.path,
                 os.path.join(LOCAL_BASE_PATH, diffusion_path, os.path.basename(soundfile.file.path)))
@@ -104,15 +103,12 @@ def add_diffusion(diffusion, **kwargs):
         context['end'] = diffusion.datetime + datetime.timedelta(seconds=
                 max(((soundfile.duration or 480) - 180), 60))
 
-        if kwargs.get('jingle_id'):
-            context['jingle'] = Jingle.objects.get(id=kwargs['jingle_id'])
-
     # create palinsesti
     palinsesti_template = loader.get_template('nonstop/soma_palinsesti.xml')
-    context['episode'] = diffusion.episode
-    context['start'] = diffusion.datetime
 
     palinsesti = palinsesti_template.render(context)
+    open('/tmp/soma.xml', 'w').write(palinsesti)
+    return
     palinsesti_xml = ET.fromstring(palinsesti.encode('utf-8'))
 
     palinsesto_xml = get_palinsesto_xml()
@@ -120,11 +116,10 @@ def add_diffusion(diffusion, **kwargs):
     send_palinsesto_xml(palinsesto_xml)
 
 
-def remove_streamed_diffusion(streamed_diffusion):
+def remove_soma_diffusion(diffusion):
     palinsesto_xml = get_palinsesto_xml()
-    stream_marker = '[stream:%s]' % streamed_diffusion.id
     for palinsesto in palinsesto_xml.findall('Palinsesto'):
-        if palinsesto.findall('Description')[0].text.startswith(stream_marker):
+        if palinsesto.findall('Description')[0].text.startswith(diffusion.soma_id):
             palinsesto_xml.remove(palinsesto)
     send_palinsesto_xml(palinsesto_xml)
 
index 14a8af34219eea57906838c2db077673ae77380c..2e6e6054ea7d5770786b3e424f73f937ab4ac51f 100644 (file)
@@ -20,8 +20,9 @@ from django.views.generic.detail import DetailView
 from django.views.generic.edit import CreateView, FormView
 from django.views.generic.list import ListView
 
-from .forms import UploadTracksForm, TrackMetaForm, TrackSearchForm, CleanupForm, AddDiffusionForm
-from .models import SomaLogLine, Track, Artist, NonstopFile, StreamedDiffusion, Jingle, Stream, LOCAL_BASE_PATH
+from .forms import UploadTracksForm, TrackMetaForm, TrackSearchForm, CleanupForm
+from .models import (SomaLogLine, Track, Artist, NonstopFile, StreamedDiffusion, Jingle,
+        Stream, LOCAL_BASE_PATH)
 from emissions.models import Nonstop, Diffusion
 
 from . import utils
@@ -349,57 +350,36 @@ class CleanupView(TemplateView):
         return HttpResponseRedirect('.')
 
 
-class AddDiffusionView(FormView):
-    template_name = 'nonstop/add-diffusion.html'
-    form_class = AddDiffusionForm
-
-    def get_initial(self):
-        initial = super(AddDiffusionView, self).get_initial()
-        jingle = Jingle.objects.filter(default_for_initial_diffusions=True).first()
-        if jingle:
-            initial['jingle'] = jingle.id
-        return initial
-
-    def form_valid(self, form):
-        diffusion = Diffusion.objects.get(id=self.kwargs['pk'])
-        episode = diffusion.episode
-        try:
-            utils.add_diffusion(diffusion, jingle_id=form.cleaned_data.get('jingle'))
-        except utils.DuplicateDiffusionSlot:
-            messages.error(self.request, _('soma slot already in use, the diffusion could not be added.'))
-        except utils.SomaException as e:
-            messages.error(self.request, _('technical soma error (%s)') % e)
-        else:
-            messages.info(self.request, _('%s added to soma') % episode.emission.title)
-
-        return super(AddDiffusionView, self).form_valid(form)
-
-    def get_success_url(self):
-        diffusion = Diffusion.objects.get(id=self.kwargs['pk'])
-        episode = diffusion.episode
-        return reverse('episode-view', kwargs={
-            'emission_slug': episode.emission.slug,
-            'slug': episode.slug})
-
-
-
-class AddStreamedDiffusionView(CreateView):
+class AddSomaDiffusionView(CreateView):
     model = StreamedDiffusion
     fields = ['jingle', 'stream']
     template_name = 'nonstop/streamed-diffusion.html'
 
+    @property
+    def fields(self):
+        diffusion = Diffusion.objects.get(id=self.kwargs['pk'])
+        fields = ['jingle']
+        if not diffusion.episode.soundfile_set.filter(fragment=False).exists():
+            fields.append('stream')
+        return fields
+
     def get_initial(self):
-        initial = super(AddStreamedDiffusionView, self).get_initial()
+        initial = super(AddSomaDiffusionView, self).get_initial()
         initial['jingle'] = Jingle.objects.filter(default_for_streams=True).first()
         initial['stream'] = Stream.objects.all().first()
         return initial
 
     def form_valid(self, form):
         form.instance.diffusion_id = self.kwargs['pk']
-        response = super(AddStreamedDiffusionView, self).form_valid(form)
         episode = form.instance.diffusion.episode
+        if 'stream' in self.fields and form.instance.stream_id is None:
+            messages.error(self.request, _('missing stream'))
+            return HttpResponseRedirect(reverse('episode-view', kwargs={
+                'emission_slug': episode.emission.slug,
+                'slug': episode.slug}))
+        response = super(AddSomaDiffusionView, self).form_valid(form)
         try:
-            utils.add_diffusion(form.instance.diffusion)
+            utils.add_diffusion(form.instance)
         except utils.SomaException as e:
             messages.error(self.request, _('technical soma error (%s)') % e)
         else:
@@ -414,13 +394,11 @@ class AddStreamedDiffusionView(CreateView):
             'slug': episode.slug})
 
 
-class DelStreamedDiffusionView(RedirectView):
+class DelSomaDiffusionView(RedirectView):
     def get_redirect_url(self, pk):
-        diffusion = Diffusion.objects.get(id=pk)
-        streamed_diffusion = diffusion.streameddiffusion_set.first()
-        utils.remove_streamed_diffusion(streamed_diffusion)
-        streamed_diffusion.delete()
-        episode = diffusion.episode
+        soma_diffusion = StreamedDiffusion.objects.filter(diffusion_id=pk).first()
+        episode = soma_diffusion.episode
+        StreamedDiffusion.objects.filter(diffusion_id=pk).delete()
         return reverse('episode-view', kwargs={
             'emission_slug': episode.emission.slug,
             'slug': episode.slug})