aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Peter2017-12-12 14:07:49 +0100
committerGitHub2017-12-12 14:07:49 +0100
commit3229c9e8af148575d87b4dfbd878ffb300a2ddd2 (patch)
tree52a824f118f99f14d7079d2c05e9f3035350e1ee
parent65397e5734b1439df4d68be40ffe994f26e551ec (diff)
parent0b73843d5e0d0ac22a46db28090e707566668ae4 (diff)
Merge pull request #56 from voc/feature/multitranslations
Feature/multitranslations
-rw-r--r--.editorconfig12
-rw-r--r--README.md8
-rw-r--r--assets/js/lustiges-script.js8
-rw-r--r--configs/conferences/33c3/config.php19
-rw-r--r--configs/conferences/nixcon15/config.php19
-rw-r--r--index.php10
-rw-r--r--model/Conferences.php29
-rw-r--r--model/Room.php63
-rw-r--r--model/RoomSelection.php16
-rw-r--r--model/Stream.php14
-rw-r--r--template/assemblies/embed-form.phtml2
-rw-r--r--template/assemblies/switcher/audio.phtml20
-rw-r--r--template/assemblies/switcher/slides.phtml12
-rw-r--r--template/assemblies/switcher/video.phtml28
-rw-r--r--view/embed.php17
-rw-r--r--view/room.php10
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
+
diff --git a/README.md b/README.md
index 7aa9378..8bcbe12 100644
--- a/README.md
+++ b/README.md
@@ -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,
diff --git a/index.php b/index.php
index 3c814f9..a526b06 100644
--- a/index.php
+++ b/index.php
@@ -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',