diff options
Diffstat (limited to '')
-rw-r--r-- | .editorconfig | 12 | ||||
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | assets/js/lustiges-script.js | 8 | ||||
-rw-r--r-- | configs/conferences/33c3/config.php | 19 | ||||
-rw-r--r-- | configs/conferences/nixcon15/config.php | 19 | ||||
-rw-r--r-- | index.php | 10 | ||||
-rw-r--r-- | model/Conferences.php | 29 | ||||
-rw-r--r-- | model/Room.php | 63 | ||||
-rw-r--r-- | model/RoomSelection.php | 16 | ||||
-rw-r--r-- | model/Stream.php | 14 | ||||
-rw-r--r-- | template/assemblies/embed-form.phtml | 2 | ||||
-rw-r--r-- | template/assemblies/switcher/audio.phtml | 20 | ||||
-rw-r--r-- | template/assemblies/switcher/slides.phtml | 12 | ||||
-rw-r--r-- | template/assemblies/switcher/video.phtml | 28 | ||||
-rw-r--r-- | view/embed.php | 17 | ||||
-rw-r--r-- | view/room.php | 10 |
16 files changed, 233 insertions, 54 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..94148b4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +end_of_line = lf + +[*.{html,phtml,sh}] +indent_style = tab + +[*.{php,js}] +indent_style = tab +trim_trailing_whitespace = true + @@ -72,7 +72,7 @@ see [deploy.sh](deploy.sh) ## JSON-API -Unter der URL http://streaming.media.ccc.de/streams/v2.json bietet die +Unter der URL [http://streaming.media.ccc.de/streams/v2.json](http://streaming.media.ccc.de/streams/v2.json) bietet die Steaming-Webseite eine Übersicht über alle konfigurierten Räume und Streams in einem maschinenlesbaren Format an. Dieses kann z.B. genutzt werden, um in den diversen Anwendungen, die sich rund um das Konferenzgeschehen entwickelt haben, @@ -83,3 +83,9 @@ der `v2.json` keine Felder *entfernt werden* oder ihre *Bedeutung ändern* – e können aber durchaus *neue Felder* hinzukommen. Eine formalere Spezifikation des JSON-Formats ist tbd. Ein Beispiel kann [hier betrachtet](https://gist.github.com/MaZderMind/a91f242efb2f446a2237d4596896efd6) werden. + +### Bekannte Nutzer der API + + - [Kodi media.ccc.de Plugin](https://github.com/cccc/plugin.video.media-ccc-de) + - v2 + - [API Kompatiblitätstest](https://github.com/cccc/plugin.video.media-ccc-de/blob/master/resources/lib/test_stream.py)
\ No newline at end of file diff --git a/assets/js/lustiges-script.js b/assets/js/lustiges-script.js index c14de15..22c4e04 100644 --- a/assets/js/lustiges-script.js +++ b/assets/js/lustiges-script.js @@ -374,7 +374,13 @@ $(function() { if(!originalsrc) originalsrc = $iframe.attr('src'); - var src = originalsrc + (autoplay ? '' : 'no-autoplay/'); + var src = originalsrc; + if (! autoplay) { + if (src.slice(-1) !== '/') { + src += '/'; + } + src += 'no-autoplay' + } $iframe.attr({width: selected[0], height: selected[1]}); $iframe.attr({src: src}); diff --git a/configs/conferences/33c3/config.php b/configs/conferences/33c3/config.php index f60df38..eb4d18b 100644 --- a/configs/conferences/33c3/config.php +++ b/configs/conferences/33c3/config.php @@ -173,6 +173,25 @@ $CONFIG['ROOMS'] = array( * Wenn diese Zeile auskommentiert oder auf false gesetzt ist werden nur * die native-Streams verwendet, andernfalls wird native und translated * angeboten und auch für beide Tonspuren eine Player-Seite angezeigt. + * + * Betrifft video sd / hd, slides, audio + * + * Ein Label für die Übersetzung oder mehrere Übersetzungsspuren können + * wie folgt konfiguriert werden: + * + * 'TRANSLATION' => [ + * ['endpoint' => 'translated', 'label' => 'Translated1'], + * ['endpoint' => 'translated-2', 'label' => 'Translated2'] + * ], + * + * Ein einfaches true entspricht dabei folgendem: + * + * 'TRANSLATION' => [ + * ['endpoint' => 'translated', 'label' => 'Translated'] + * ], + * + * Sollte die Sprache während der Veranstaltung Konstant sein, kann ein + * Label auch spezifisch konfiguriert werden z.B. 'label' => 'English'. */ 'TRANSLATION' => true, diff --git a/configs/conferences/nixcon15/config.php b/configs/conferences/nixcon15/config.php index abf67f7..69545f6 100644 --- a/configs/conferences/nixcon15/config.php +++ b/configs/conferences/nixcon15/config.php @@ -164,6 +164,25 @@ $CONFIG['ROOMS'] = array( * Wenn diese Zeile auskommentiert oder auf false gesetzt ist werden nur * die native-Streams verwendet, andernfalls wird native und translated * angeboten und auch für beide Tonspuren eine Player-Seite angezeigt. + * + * Betrifft video sd / hd, slides, audio + * + * Ein Label für die Übersetzung oder mehrere Übersetzungsspuren können + * wie folgt konfiguriert werden: + * + * 'TRANSLATION' => [ + * ['endpoint' => 'translated', 'label' => 'Translated1'], + * ['endpoint' => 'translated-2', 'label' => 'Translated2'] + * ], + * + * Ein einfaches true entspricht dabei folgendem: + * + * 'TRANSLATION' => [ + * ['endpoint' => 'translated', 'label' => 'Translated'] + * ], + * + * Sollte die Sprache während der Veranstaltung Konstant sein, kann ein + * Label auch spezifisch konfiguriert werden z.B. 'label' => 'English'. */ 'TRANSLATION' => false, @@ -285,12 +285,12 @@ try { require('view/room.php'); } - else if(preg_match('@^([^/]+)/translated$@', $route, $m)) + else if(preg_match('@^([^/]+)/i18n/([^/]+)$@', $route, $m)) { $_GET = array( 'room' => $m[1], 'selection' => '', - 'language' => 'translated', + 'language' => $m[2], ); require('view/room.php'); } @@ -305,17 +305,17 @@ try { require('view/room.php'); } - else if(preg_match('@^([^/]+)/(sd|audio|slides|dash)/translated$@', $route, $m)) + else if(preg_match('@^([^/]+)/(sd|audio|slides|dash)/i18n/([^/]+)$@', $route, $m)) { $_GET = array( 'room' => $m[1], 'selection' => $m[2], - 'language' => 'translated', + 'language' => $m[3], ); require('view/room.php'); } - else if(preg_match('@^embed/([^/]+)/(hd|sd|audio|slides)/(native|translated|stereo)(/no-autoplay)?$@', $route, $m)) + else if(preg_match('@^embed/([^/]+)/(hd|sd|audio|slides)/(native|stereo|[^/]+)(/no-autoplay)?$@', $route, $m)) { $_GET = array( 'room' => $m[1], diff --git a/model/Conferences.php b/model/Conferences.php index f7276ac..575759e 100644 --- a/model/Conferences.php +++ b/model/Conferences.php @@ -72,6 +72,33 @@ class Conferences return in_array($mandator, Conferences::listConferences()); } + private static function migrateTranslationConfiguration($config) { + // Allow setting TRANSLATION simply to true and fill in default values for uniformity + $rooms = $config['ROOMS']; + foreach ($rooms as $slug => $room) { + // Translation is commented out, equaivalent of false + if (!isset($room['TRANSLATION'])) { + $config['ROOMS'][$slug]['TRANSLATION'] = []; + } + // Translation is present but not an array + elseif (! is_array($room['TRANSLATION'])) { + // Translation is true, set default values + if ($room['TRANSLATION'] === true) { + $config['ROOMS'][$slug]['TRANSLATION'] = [[ + 'endpoint' => 'translated', + 'label' => 'Translated' + ]]; + } + // Translation is false or garbage + else { + $config['ROOMS'][$slug]['TRANSLATION'] = []; + } + } + } + + return $config; + } + public static function loadConferenceConfig($mandator) { $configfile = forceslash(Conferences::MANDATOR_DIR).forceslash($mandator).'config.php'; $config = include($configfile); @@ -80,6 +107,8 @@ class Conferences throw new ConfigException("Loading $configfile did not return an array. Maybe it's missing a return-statement?"); } + $config = Conferences::migrateTranslationConfiguration($config); + return $config; } diff --git a/model/Room.php b/model/Room.php index 4b251cd..24d87cb 100644 --- a/model/Room.php +++ b/model/Room.php @@ -175,10 +175,40 @@ class Room return 'Adaptive multi-format-multi-bitrate-Stream to rule the World!!1elf'; } - public function hasTranslation() { + public function getTranslations() { return $this->getConference()->get('ROOMS.'.$this->getSlug().'.TRANSLATION'); } + private function getTranslationEndpoints() { + return array_map( + function ($translation) { + return $translation['endpoint']; + }, + $this->getTranslations() + ); + } + + private function isTranslationEndpoint($endpoint) { + return in_array($endpoint, $this->getTranslationEndpoints()); + } + + private function findTranslationLabel($language) { + foreach($this->getTranslations() as $translation) { + if ($translation['endpoint'] === $language) { + return $translation['label']; + } + } + return null; + } + + public function hasTranslation() { + return count($this->getTranslations()) > 0; + } + + public function isValidLanguage($language) { + return ($language === 'native' || $this->isTranslationEndpoint($language)); + } + public function getSelectionNames() { $selections = array(); @@ -203,6 +233,11 @@ class Room return $selections; } + public function isSelectionTranslated($selection) { + # dash is special, has langs included + return $selection !== 'dash' && $selection !== 'music'; + } + public function getTabNames() { $tabs = array(); @@ -284,8 +319,11 @@ class Room foreach ($selections as $selection) { $streams[] = $this->createStreamObject($selection, 'native'); - if($this->hasTranslation()) - $streams[] = $this->createStreamObject($selection, 'translated'); + if ($this->isSelectionTranslated($selection)) { + foreach ($this->getTranslations() as $translation) { + $streams[] = $this->createStreamObject($selection, $translation['endpoint'], $translation['label']); + } + } } return $streams; @@ -305,17 +343,26 @@ class Room if(!in_array($selection, $selections)) throw new NotFoundException('Selection '.$selection.' in Room '.$this->getSlug()); - if($language == 'translated' && !$this->hasTranslation()) - throw new NotFoundException('Translated Streams of Room '.$this->getSlug()); + $translation_label = null; + if ($language !== 'native' && $language !== 'stereo') { + if (! $this->hasTranslation()) { + throw new NotFoundException('Translated Streams of Room '. $this->getSlug()); + } + if (! $this->isValidLanguage($language)) { + throw new NotFoundException('Selected translation'); + } + + $translation_label = $this->findTranslationLabel($language); + } - return $this->createStreamObject($selection, $language); + return $this->createStreamObject($selection, $language, $translation_label); } - public function createStreamObject($selection, $language = 'native') + public function createStreamObject($selection, $language = 'native', $languageLabel = null) { if($language == 'native' && $this->hasStereo()) $language = 'stereo'; - return new Stream($this, $selection, $language); + return new Stream($this, $selection, $language, $languageLabel); } } diff --git a/model/RoomSelection.php b/model/RoomSelection.php index 9211c31..c21ea7e 100644 --- a/model/RoomSelection.php +++ b/model/RoomSelection.php @@ -18,20 +18,24 @@ class RoomSelection return $this->selection; } - public function getLink() - { + private function getSelectionPath() { $path = [$this->getRoom()->getConference()->getSlug(), $this->getRoom()->getSlug()]; $selection = $this->getRoom()->getSelectionNames(); - if($selection[0] != $this->getSelection()) + if ($selection[0] != $this->getSelection()) $path[] = $this->getSelection(); - return joinpath($path).url_params(); + return joinpath($path); + } + + public function getLink() + { + return $this->getSelectionPath() . url_params(); } - public function getTranslatedLink() + public function getTranslatedLink($translation_endpoint) { - return joinpath([$this->getLink(), 'translated']); + return joinpath([$this->getSelectionPath(), 'i18n', $translation_endpoint]) . url_params(); } public function getDisplay() diff --git a/model/Stream.php b/model/Stream.php index daed17f..99abaf1 100644 --- a/model/Stream.php +++ b/model/Stream.php @@ -2,11 +2,12 @@ class Stream { - public function __construct(Room $room, $selection, $language) + public function __construct(Room $room, $selection, $language, $translation_label = null) { $this->room = $room; $this->selection = $selection; $this->language = $language; + $this->translation_label = (empty($translation_label)) ? $language : $translation_label; } public function getRoom() @@ -24,9 +25,16 @@ class Stream return $this->language; } + public function getTranslationLabel() + { + return $this->translation_label; + } + public function isTranslated() { - return $this->getLanguage() == 'translated'; + return !empty($this->getLanguage()) && + $this->getLanguage() !== 'native' && + $this->getLanguage() !== 'stereo'; } public function getVideoSize() @@ -98,7 +106,7 @@ class Stream } if($this->isTranslated()) - $display .= ' (Translation)'; + $display .= ' ('. $this->getTranslationLabel() .')'; return $display; } diff --git a/template/assemblies/embed-form.phtml b/template/assemblies/embed-form.phtml index 721d886..020a22f 100644 --- a/template/assemblies/embed-form.phtml +++ b/template/assemblies/embed-form.phtml @@ -20,7 +20,7 @@ <div class="checkbox"> <label> - <input checked="checked" type="checkbox" id="autoplay"> Autoplay + <input checked="checked" type="checkbox" id="autoplay">Autoplay </label> </div> </div> diff --git a/template/assemblies/switcher/audio.phtml b/template/assemblies/switcher/audio.phtml index 182572e..eab77fb 100644 --- a/template/assemblies/switcher/audio.phtml +++ b/template/assemblies/switcher/audio.phtml @@ -10,12 +10,14 @@ <a href="<?=h($selection->getLink())?>" class="btn btn-primary"> <span class="fa fa-flag-o"></span> - native + Native </a> - <a href="<?=h($selection->getTranslatedLink())?>" class="btn btn-primary"> + <? foreach($room->getTranslations() as $translation): ?> + <a href="<?=h($selection->getTranslatedLink($translation['endpoint']))?>" class="btn btn-primary"> <span class="fa fa-flag"></span> - translated + <?=h(ucfirst($translation['label']))?> </a> + <? endforeach ?> </div> </div> @@ -39,12 +41,14 @@ <a href="<?=h($room->createStreamObject('audio', 'native')->getAudioUrl($proto))?>" class="btn btn-default"> <span class="fa fa-flag-o"></span> - native - </a> - <a href="<?=h($room->createStreamObject('audio', 'translated')->getAudioUrl($proto))?>" class="btn btn-default"> - <span class="fa fa-flag"></span> - translated + Native </a> + <? foreach($room->getTranslations() as $translation): ?> + <a href="<?=h($room->createStreamObject('audio', $translation['endpoint'])->getAudioUrl($proto))?>" class="btn btn-default"> + <span class="fa fa-flag"></span> + <?=h(ucfirst($translation['label']))?> + </a> + <? endforeach ?> <? else: ?> diff --git a/template/assemblies/switcher/slides.phtml b/template/assemblies/switcher/slides.phtml index dfbc26d..ba70c5f 100644 --- a/template/assemblies/switcher/slides.phtml +++ b/template/assemblies/switcher/slides.phtml @@ -10,12 +10,14 @@ <a href="<?=h($selection->getLink())?>" class="btn btn-primary"> <span class="fa fa-flag-o"></span> - native - </a> - <a href="<?=h($selection->getTranslatedLink())?>" class="btn btn-primary"> - <span class="fa fa-flag"></span> - translated + Native </a> + <? foreach($room->getTranslations() as $translation): ?> + <a href="<?=h($selection->getTranslatedLink($translation['endpoint']))?>" class="btn btn-primary"> + <span class="fa fa-flag"></span> + <?=h(ucfirst($translation['label']))?> + </a> + <? endforeach ?> </div> </div> diff --git a/template/assemblies/switcher/video.phtml b/template/assemblies/switcher/video.phtml index 3877128..ae2815f 100644 --- a/template/assemblies/switcher/video.phtml +++ b/template/assemblies/switcher/video.phtml @@ -12,18 +12,20 @@ <a href="<?=h($selection->getLink())?>" class="btn btn-primary"> <span class="fa fa-flag-o"></span> - native - </a> - <a href="<?=h($selection->getTranslatedLink())?>" class="btn btn-primary"> - <span class="fa fa-flag"></span> - translated + Native </a> + <? foreach($room->getTranslations() as $translation): ?> + <a href="<?=h($selection->getTranslatedLink($translation['endpoint']))?>" class="btn btn-primary"> + <span class="fa fa-flag"></span> + <?=h(ucfirst($translation['label']))?> + </a> + <? endforeach ?> <? else: ?> <a href="<?=h($selection->getLink())?>" class="btn btn-primary"> <span class="fa fa-video-camera"></span> - video + Video </a> <? endif ?> @@ -51,18 +53,20 @@ <a href="<?=h($room->createStreamObject($res, 'native')->getVideoUrl($proto))?>" class="btn btn-default"> <span class="fa fa-flag-o"></span> - native - </a> - <a href="<?=h($room->createStreamObject($res, 'translated')->getVideoUrl($proto))?>" class="btn btn-default"> - <span class="fa fa-flag"></span> - translated + Native </a> + <? foreach($room->getTranslations() as $translation): ?> + <a href="<?=h($room->createStreamObject($res, $translation['endpoint'])->getVideoUrl($proto))?>" class="btn btn-default"> + <span class="fa fa-flag"></span> + <?=h(ucfirst($translation['label']))?> + </a> + <? endforeach ?> <? else: ?> <a href="<?=h($switcherstream->getVideoUrl($proto))?>" class="btn btn-default"> <span class="fa fa-video-camera"></span> - video + Video </a> <? endif ?> diff --git a/view/embed.php b/view/embed.php index eb7caee..97df148 100644 --- a/view/embed.php +++ b/view/embed.php @@ -1,11 +1,24 @@ <?php $room = $conference->getRoom($_GET['room']); + if(!$room->hasEmbed()) throw new NotFoundException('Embedding is not enabled in this room'); -$stream = $room->selectStream( - $_GET['selection'], $_GET['language']); +$selection = $_GET['selection']; +$language = $_GET['language']; + +if ($language !== 'native' && $language !== 'stereo') { + if (! $room->hasTranslation()) { + throw new NotFoundException('Not translated'); + } + + if (! $room->isValidLanguage($language)) { + throw new NotFoundException('Language not found'); + } +} + +$stream = $room->selectStream($selection, $language); echo $tpl->render(array( 'page' => 'embed', diff --git a/view/room.php b/view/room.php index d586248..d035219 100644 --- a/view/room.php +++ b/view/room.php @@ -1,8 +1,14 @@ <?php $room = $conference->getRoom($_GET['room']); -$stream = $room->selectStream( - $_GET['selection'], $_GET['language']); +$selection = $_GET['selection']; +$language = $_GET['language']; + +if (! $room->isValidLanguage($language)) { + throw new NotFoundException('Language not found'); +} + +$stream = $room->selectStream($selection, $language); echo $tpl->render(array( 'page' => 'room', |