add sound item in diffusions; move programs.Sound's attribute 'remove' into the type + update its public attribute based on diffusion publication
This commit is contained in:
parent
502af1dba0
commit
801a89e503
|
@ -418,6 +418,11 @@ class DiffusionPage(Publication):
|
|||
'initial__isnull': True,
|
||||
},
|
||||
)
|
||||
publish_archive = models.BooleanField(
|
||||
_('publish archive'),
|
||||
default = False,
|
||||
help_text = _('publish the podcast of the complete diffusion'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Diffusion')
|
||||
|
@ -425,11 +430,11 @@ class DiffusionPage(Publication):
|
|||
|
||||
content_panels = [
|
||||
FieldPanel('diffusion'),
|
||||
FieldPanel('publish_archive'),
|
||||
] + Publication.content_panels + [
|
||||
InlinePanel('tracks', label=_('Tracks')),
|
||||
]
|
||||
|
||||
|
||||
@classmethod
|
||||
def from_diffusion(cl, diff, model = None, **kwargs):
|
||||
model = model or cl
|
||||
|
@ -470,9 +475,50 @@ class DiffusionPage(Publication):
|
|||
item.css_class = 'diffusion'
|
||||
return item
|
||||
|
||||
def get_archive(self):
|
||||
if not self.publish_archive:
|
||||
return
|
||||
|
||||
sound = self.diffusion.get_archives() \
|
||||
.filter(public = True).first()
|
||||
if sound:
|
||||
sound.detail_url = self.detail_url
|
||||
return sound
|
||||
|
||||
def get_podcasts(self):
|
||||
"""
|
||||
Return a list of podcasts, with archive as the first item of the
|
||||
list when available.
|
||||
"""
|
||||
podcasts = []
|
||||
archive = self.get_archive()
|
||||
if archive:
|
||||
podcasts.append(archive)
|
||||
|
||||
qs = self.diffusion.get_excerpts().filter(public = True)
|
||||
podcasts.extend(qs[:])
|
||||
for podcast in podcasts:
|
||||
podcast.detail_url = self.url
|
||||
return podcasts
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# TODO: update public attribute of the archive + podcasts check if live
|
||||
if self.diffusion:
|
||||
self.date = self.diffusion.start
|
||||
|
||||
# update podcasts' attributes
|
||||
for podcast in self.diffusion.sound_set \
|
||||
.exclude(type = programs.Sound.Type.removed):
|
||||
publish = self.live and self.publish_archive \
|
||||
if podcast.type == podcast.Type.archive else self.live
|
||||
|
||||
if podcast.public != publish:
|
||||
podcast.public = publish
|
||||
podcast.save()
|
||||
|
||||
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
|
|
|
@ -51,8 +51,8 @@ PlayerPlaylist.prototype = {
|
|||
items: undefined,
|
||||
|
||||
find: function(stream) {
|
||||
return this.items.find(function(v) {
|
||||
return v.stream == item;
|
||||
return this.items.find(function(stream_) {
|
||||
return stream_ == stream;
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -30,6 +30,17 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
{% with podcasts=self.get_podcasts %}
|
||||
{% if podcasts %}
|
||||
<div class="podcasts list">
|
||||
<h2>{% trans "Podcasts" %}</h2>
|
||||
{% for item in podcasts %}
|
||||
{% include 'cms/snippets/sound_list_item.html' %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{# TODO: podcasts #}
|
||||
{% endblock %}
|
||||
|
||||
|
|
13
cms/templates/cms/snippets/sound_list_item.html
Normal file
13
cms/templates/cms/snippets/sound_list_item.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% load static %}
|
||||
|
||||
{# TODO: complete archive podcast -> info #}
|
||||
<a class="list_item sound" onclick="player.playlist.add(new Sound(
|
||||
title='{{ item.name|escape }}',
|
||||
detail='{{ item.detail_url }}',
|
||||
stream='{% static item.path %}'));">
|
||||
<h3>{{ item.name }}</h3>
|
||||
<span class="info">
|
||||
{{ duration.date|date:'H:i:s' }}
|
||||
</span>
|
||||
</a>
|
||||
|
|
@ -66,7 +66,7 @@ class DiffusionsMenu(GenericMenu):
|
|||
def register_programs_menu_item():
|
||||
return SubmenuMenuItem(
|
||||
_('Today\'s Diffusions'), DiffusionsMenu(),
|
||||
classnames='icon icon-folder-open-inverse', order=10
|
||||
classnames='icon icon-folder-open-inverse', order=101
|
||||
)
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ class ProgramsMenu(GenericMenu):
|
|||
def register_programs_menu_item():
|
||||
return SubmenuMenuItem(
|
||||
_('Programs'), ProgramsMenu(),
|
||||
classnames='icon icon-folder-open-inverse', order=10
|
||||
classnames='icon icon-folder-open-inverse', order=102
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class StreamInline(admin.TabularInline):
|
|||
extra = 1
|
||||
|
||||
class SoundInline(admin.TabularInline):
|
||||
fields = ['type', 'path', 'duration']
|
||||
fields = ['type', 'path', 'duration','public']
|
||||
# readonly_fields = fields
|
||||
model = Sound
|
||||
extra = 0
|
||||
|
@ -66,11 +66,11 @@ class TrackInline(GenericTabularInline):
|
|||
class SoundAdmin(NameableAdmin):
|
||||
fields = None
|
||||
list_display = ['id', 'name', 'duration', 'type', 'mtime',
|
||||
'public', 'good_quality', 'removed']
|
||||
'public', 'good_quality']
|
||||
fieldsets = [
|
||||
(None, { 'fields': NameableAdmin.fields + ['path', 'type', 'diffusion'] } ),
|
||||
(None, { 'fields': ['embed', 'duration', 'public', 'mtime'] }),
|
||||
(None, { 'fields': ['removed', 'good_quality' ] } )
|
||||
(None, { 'fields': ['good_quality' ] } )
|
||||
]
|
||||
readonly_fields = ('path', 'duration',)
|
||||
inlines = [TrackInline]
|
||||
|
|
|
@ -79,7 +79,7 @@ class Importer:
|
|||
position = position,
|
||||
)
|
||||
|
||||
track.in_seconds = pos_in_secs
|
||||
track.in_seconds = in_seconds
|
||||
track.info = self.__get(line, 'info')
|
||||
tags = self.__get(line, 'tags')
|
||||
if tags:
|
||||
|
|
|
@ -157,7 +157,7 @@ class SoundInfo:
|
|||
diffusion = diffusion[0]
|
||||
|
||||
logger.info('diffusion %s mathes to sound -> %s', str(diffusion),
|
||||
sound.path)
|
||||
self.sound.path)
|
||||
self.sound.diffusion = diffusion
|
||||
if save:
|
||||
self.sound.save()
|
||||
|
@ -201,7 +201,7 @@ class MonitorHandler(PatternMatchingEventHandler):
|
|||
sound = Sound.objects.filter(path = event.src_path)
|
||||
if sound:
|
||||
sound = sound[0]
|
||||
sound.removed = True
|
||||
sound.type = sound.Type.removed
|
||||
sound.save()
|
||||
|
||||
def on_moved(self, event):
|
||||
|
@ -296,7 +296,6 @@ class Command(BaseCommand):
|
|||
|
||||
# sounds in directory
|
||||
for path in os.listdir(subdir):
|
||||
print(path)
|
||||
path = os.path.join(subdir, path)
|
||||
if not path.endswith(settings.AIRCOX_SOUND_FILE_EXT):
|
||||
continue
|
||||
|
@ -319,21 +318,23 @@ class Command(BaseCommand):
|
|||
import aircox.programs.management.commands.sounds_quality_check \
|
||||
as quality_check
|
||||
|
||||
sounds = Sound.objects.filter(good_quality = False)
|
||||
# get available sound files
|
||||
sounds = Sound.objects.filter(good_quality = False) \
|
||||
.exclude(type = Sound.Type.removed)
|
||||
if check:
|
||||
self.check_sounds(sounds)
|
||||
files = [ sound.path for sound in sounds
|
||||
if not sound.removed and os.path.exists(sound.path) ]
|
||||
else:
|
||||
files = [ sound.path for sound in sounds.filter(removed = False)
|
||||
if os.path.exists(sound.path) ]
|
||||
|
||||
files = [ sound.path for sound in sounds
|
||||
if os.path.exists(sound.path) ]
|
||||
|
||||
# check quality
|
||||
logger.info('quality check...',)
|
||||
cmd = quality_check.Command()
|
||||
cmd.handle( files = files,
|
||||
**settings.AIRCOX_SOUND_QUALITY )
|
||||
|
||||
logger.info('update database')
|
||||
# update stats
|
||||
logger.info('update stats in database')
|
||||
def update_stats(sound_info, sound):
|
||||
stats = sound_info.get_file_stats()
|
||||
if stats:
|
||||
|
|
|
@ -121,6 +121,7 @@ class Sound(Nameable):
|
|||
other = 0x00,
|
||||
archive = 0x01,
|
||||
excerpt = 0x02,
|
||||
removed = 0x03,
|
||||
|
||||
diffusion = models.ForeignKey(
|
||||
'Diffusion',
|
||||
|
@ -157,11 +158,6 @@ class Sound(Nameable):
|
|||
blank = True, null = True,
|
||||
help_text = _('last modification date and time'),
|
||||
)
|
||||
removed = models.BooleanField(
|
||||
_('removed'),
|
||||
default = False,
|
||||
help_text = _('this sound has been removed from filesystem'),
|
||||
)
|
||||
good_quality = models.BooleanField(
|
||||
_('good quality'),
|
||||
default = False,
|
||||
|
@ -204,15 +200,21 @@ class Sound(Nameable):
|
|||
needed (do not save). Return True if there was changes.
|
||||
"""
|
||||
if not self.file_exists():
|
||||
if self.removed:
|
||||
if self.type == self.Type.removed:
|
||||
return
|
||||
logger.info('sound %s: has been removed', self.path)
|
||||
self.removed = True
|
||||
self.type = self.Type.removed
|
||||
return True
|
||||
|
||||
old_removed = self.removed
|
||||
self.removed = False
|
||||
# not anymore removed
|
||||
changed = False
|
||||
if self.type == self.Type.removed and self.program:
|
||||
changed = True
|
||||
self.type = self.Type.archive \
|
||||
if self.path.startswith(self.program.archives_path) else \
|
||||
self.Type.excerpt
|
||||
|
||||
# check mtime -> reset quality if changed (assume file changed)
|
||||
mtime = self.get_mtime()
|
||||
if self.mtime != mtime:
|
||||
self.mtime = mtime
|
||||
|
@ -220,7 +222,7 @@ class Sound(Nameable):
|
|||
logger.info('sound %s: m_time has changed. Reset quality info',
|
||||
self.path)
|
||||
return True
|
||||
return old_removed != self.removed
|
||||
return changed
|
||||
|
||||
def check_perms(self):
|
||||
"""
|
||||
|
@ -529,6 +531,18 @@ class Program(Nameable):
|
|||
os.makedirs(path, exist_ok = True)
|
||||
return os.path.exists(path)
|
||||
|
||||
@property
|
||||
def archives_path(self):
|
||||
return os.path.join(
|
||||
self.path, settings.AIRCOX_SOUND_ARCHIVES_SUBDIR
|
||||
)
|
||||
|
||||
@property
|
||||
def excerpts_path(self):
|
||||
return os.path.join(
|
||||
self.path, settings.AIRCOX_SOUND_ARCHIVES_SUBDIR
|
||||
)
|
||||
|
||||
def find_schedule(self, date):
|
||||
"""
|
||||
Return the first schedule that matches a given date.
|
||||
|
@ -684,8 +698,15 @@ class Diffusion(models.Model):
|
|||
ordered by path.
|
||||
"""
|
||||
sounds = self.initial.sound_set if self.initial else self.sound_set
|
||||
return sounds.filter(type = Sound.Type.archive, removed = False). \
|
||||
order_by('path')
|
||||
return sounds.filter(type = Sound.Type.archive).order_by('path')
|
||||
|
||||
def get_excerpts(self):
|
||||
"""
|
||||
Return a list of available archives sounds for the given episode,
|
||||
ordered by path.
|
||||
"""
|
||||
sounds = self.initial.sound_set if self.initial else self.sound_set
|
||||
return sounds.filter(type = Sound.Type.excerpt).order_by('path')
|
||||
|
||||
def is_date_in_range(self, date = None):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user