streamer sound uri/path

This commit is contained in:
bkfox 2022-03-26 16:23:46 +01:00
parent 66f02bdb05
commit fb665aff5d
7 changed files with 32 additions and 9 deletions

View File

@ -84,6 +84,7 @@ class SoundFile:
# FIXME: sound.program as not null # FIXME: sound.program as not null
if not program: if not program:
program = Program.get_from_path(self.path) program = Program.get_from_path(self.path)
logger.info('program from path "%s" -> %s', self.path, program)
kwargs['program_id'] = program.pk kwargs['program_id'] = program.pk
sound, created = Sound.objects.get_or_create(file=self.sound_path, defaults=kwargs) \ sound, created = Sound.objects.get_or_create(file=self.sound_path, defaults=kwargs) \

View File

@ -46,7 +46,13 @@ class SoundQuerySet(models.QuerySet):
""" Return sounds that are archives """ """ Return sounds that are archives """
return self.filter(type=Sound.TYPE_ARCHIVE) return self.filter(type=Sound.TYPE_ARCHIVE)
def paths(self, archive=True, order_by=True): def path(self, paths):
if isinstance(paths, str):
return self.filter(file=paths.replace(conf.MEDIA_ROOT + '/', ''))
return self.filter(file__in=(p.replace(conf.MEDIA_ROOT + '/', '')
for p in paths))
def playlist(self, archive=True, order_by=True):
""" """
Return files absolute paths as a flat list (exclude sound without path). Return files absolute paths as a flat list (exclude sound without path).
If `order_by` is True, order by path. If `order_by` is True, order by path.
@ -104,6 +110,7 @@ class Sound(models.Model):
file = models.FileField( file = models.FileField(
_('file'), upload_to=_upload_to, max_length=256, _('file'), upload_to=_upload_to, max_length=256,
db_index=True,
) )
duration = models.TimeField( duration = models.TimeField(
_('duration'), _('duration'),

View File

@ -245,7 +245,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\**********************/ \**********************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./app */ \"./src/app.js\");\n/* harmony import */ var _appBuilder__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./appBuilder */ \"./src/appBuilder.js\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sound */ \"./src/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./src/model.js\");\n/* harmony import */ var _assets_styles_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./assets/styles.scss */ \"./src/assets/styles.scss\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n //-- aircox\n\n\n\n\n\n\nwindow.aircox = {\n // main application\n builder: new _appBuilder__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_app__WEBPACK_IMPORTED_MODULE_2__[\"default\"]),\n\n get app() {\n return this.builder.app;\n },\n\n // player application\n playerBuilder: new _appBuilder__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_app__WEBPACK_IMPORTED_MODULE_2__.PlayerApp),\n\n get playerApp() {\n return this.playerBuilder && this.playerBuilder.app;\n },\n\n get player() {\n return this.playerBuilder.vm && this.playerBuilder.vm.$refs.player;\n },\n\n Set: _model__WEBPACK_IMPORTED_MODULE_5__.Set,\n Sound: _sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n\n /**\n * Initialize main application and player.\n */\n init(props = null, {\n config = null,\n builder = null,\n initBuilder = true,\n initPlayer = true,\n hotReload = false\n } = {}) {\n if (initPlayer) {\n let playerBuilder = this.playerBuilder;\n playerBuilder.mount();\n }\n\n if (initBuilder) {\n builder = builder || this.builder;\n this.builder = builder;\n if (config || window.App) builder.config = config || window.App;\n builder.title = document.title;\n builder.mount({\n props\n });\n if (hotReload) builder.enableHotReload(hotReload);\n }\n }\n\n};\n\n//# sourceURL=webpack://aircox-assets/./src/index.js?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./app */ \"./src/app.js\");\n/* harmony import */ var _appBuilder__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./appBuilder */ \"./src/appBuilder.js\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sound */ \"./src/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./src/model.js\");\n/* harmony import */ var _assets_styles_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./assets/styles.scss */ \"./src/assets/styles.scss\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n //-- aircox\n\n\n\n\n\n\nwindow.aircox = {\n // main application\n builder: new _appBuilder__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_app__WEBPACK_IMPORTED_MODULE_2__[\"default\"]),\n\n get app() {\n return this.builder.app;\n },\n\n // player application\n playerBuilder: new _appBuilder__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_app__WEBPACK_IMPORTED_MODULE_2__.PlayerApp),\n\n get playerApp() {\n return this.playerBuilder && this.playerBuilder.app;\n },\n\n get player() {\n return this.playerBuilder.vm && this.playerBuilder.vm.$refs.player;\n },\n\n Set: _model__WEBPACK_IMPORTED_MODULE_5__.Set,\n Sound: _sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n\n /**\n * Initialize main application and player.\n */\n init(props = null, {\n config = null,\n builder = null,\n initBuilder = true,\n initPlayer = true,\n hotReload = false\n } = {}) {\n if (initPlayer) {\n let playerBuilder = this.playerBuilder;\n playerBuilder.mount();\n }\n\n if (initBuilder) {\n builder = builder || this.builder;\n this.builder = builder;\n if (config || window.App) builder.config = config || window.App;\n builder.title = document.title;\n builder.mount({\n props\n });\n if (hotReload) builder.enableHotReload(hotReload);\n }\n },\n\n /**\n * Filter navbar dropdown menu items\n */\n filter_menu(event) {\n var filter = new RegExp(event.target.value, 'gi');\n var container = event.target.closest('.navbar-dropdown');\n if (event.target.value) for (let item of container.querySelectorAll('a.navbar-item')) item.style.display = item.innerHTML.search(filter) == -1 ? 'none' : null;else for (let item of container.querySelectorAll('a.navbar-item')) item.style.display = null;\n }\n\n};\n\n//# sourceURL=webpack://aircox-assets/./src/index.js?");
/***/ }), /***/ }),

View File

@ -77,7 +77,7 @@
<div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="{% url "admin:aircox_program_changelist" %}">{% trans "Programs" %}</a> <a class="navbar-link" href="{% url "admin:aircox_program_changelist" %}">{% trans "Programs" %}</a>
<div class="navbar-dropdown is-boxed"> <div class="navbar-dropdown is-boxed">
<input type="text" onkeyup="aircox_admin.filter_menu(event)" <input type="text" onkeyup="aircox.filter_menu(event)"
placeholder="{% trans "Search" %}" class="navbar-item input" /> placeholder="{% trans "Search" %}" class="navbar-item input" />
<hr class="navbar-divider"/> <hr class="navbar-divider"/>
{% for program in programs %} {% for program in programs %}
@ -91,7 +91,7 @@
<div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="{% url "admin:aircox_article_changelist" %}">{% trans "Articles" %}</a> <a class="navbar-link" href="{% url "admin:aircox_article_changelist" %}">{% trans "Articles" %}</a>
<div class="navbar-dropdown is-boxed"> <div class="navbar-dropdown is-boxed">
<input type="text" onkeyup="aircox_admin.filter_menu(event)" <input type="text" onkeyup="aircox.filter_menu(event)"
placeholder="{% trans "Search" %}" class="navbar-item input" /> placeholder="{% trans "Search" %}" class="navbar-item input" />
<hr class="navbar-divider"/> <hr class="navbar-divider"/>
{% for program in programs %} {% for program in programs %}
@ -105,7 +105,7 @@
<div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="{% url "admin:aircox_episode_changelist" %}">{% trans "Episodes" %}</a> <a class="navbar-link" href="{% url "admin:aircox_episode_changelist" %}">{% trans "Episodes" %}</a>
<div class="navbar-dropdown is-boxed"> <div class="navbar-dropdown is-boxed">
<input type="text" onkeyup="aircox_admin.filter_menu(event)" <input type="text" onkeyup="aircox.filter_menu(event)"
placeholder="{% trans "Search" %}" class="navbar-item input" /> placeholder="{% trans "Search" %}" class="navbar-item input" />
<hr class="navbar-divider"/> <hr class="navbar-divider"/>
{% for program in programs %} {% for program in programs %}

View File

@ -327,7 +327,7 @@ class PlaylistSource(Source):
def get_playlist(self): def get_playlist(self):
""" Get playlist from db """ """ Get playlist from db """
return self.get_sound_queryset().paths() return self.get_sound_queryset().playlist()
def write_playlist(self, playlist=[]): def write_playlist(self, playlist=[]):
""" Write playlist to file. """ """ Write playlist to file. """

View File

@ -136,7 +136,7 @@ class Monitor:
# check if there is yet a log for this sound on the source # check if there is yet a log for this sound on the source
log = self.logs.on_air().filter( log = self.logs.on_air().filter(
Q(sound__path=air_uri) | Q(sound__file=air_uri) |
# sound can be null when arbitrary sound file is played # sound can be null when arbitrary sound file is played
Q(sound__isnull=True, track__isnull=True, comment=air_uri), Q(sound__isnull=True, track__isnull=True, comment=air_uri),
source=source.id, source=source.id,
@ -147,7 +147,7 @@ class Monitor:
# get sound # get sound
diff = None diff = None
sound = Sound.objects.filter(path=air_uri).first() sound = Sound.objects.path(air_uri).first()
if sound and sound.episode_id is not None: if sound and sound.episode_id is not None:
diff = Diffusion.objects.episode(id=sound.episode_id).on_air() \ diff = Diffusion.objects.episode(id=sound.episode_id).on_air() \
.now(air_time).first() .now(air_time).first()
@ -227,7 +227,7 @@ class Monitor:
self.cancel_diff(dealer, diff) self.cancel_diff(dealer, diff)
def start_diff(self, source, diff): def start_diff(self, source, diff):
playlist = Sound.objects.episode(id=diff.episode_id).paths() playlist = Sound.objects.episode(id=diff.episode_id).playlist()
source.push(*playlist) source.push(*playlist)
self.log(type=Log.TYPE_START, source=source.id, diffusion=diff, self.log(type=Log.TYPE_START, source=source.id, diffusion=diff,
comment=str(diff)) comment=str(diff))

View File

@ -52,5 +52,20 @@ window.aircox = {
builder.enableHotReload(hotReload) builder.enableHotReload(hotReload)
} }
}, },
/**
* Filter navbar dropdown menu items
*/
filter_menu(event) {
var filter = new RegExp(event.target.value, 'gi');
var container = event.target.closest('.navbar-dropdown');
if(event.target.value)
for(let item of container.querySelectorAll('a.navbar-item'))
item.style.display = item.innerHTML.search(filter) == -1 ? 'none' : null;
else
for(let item of container.querySelectorAll('a.navbar-item'))
item.style.display = null;
}
} }