diff options
Diffstat (limited to '')
-rw-r--r-- | config.php | 125 | ||||
-rw-r--r-- | index.php | 4 | ||||
-rw-r--r-- | lib/helper.php | 174 | ||||
-rw-r--r-- | lib/program.php | 168 | ||||
-rw-r--r-- | model/Relive.php | 24 | ||||
-rw-r--r-- | model/Room.php | 193 | ||||
-rw-r--r-- | model/RoomSelection.php | 52 | ||||
-rw-r--r-- | model/RoomTab.php | 34 | ||||
-rw-r--r-- | model/Schedule.php | 173 | ||||
-rw-r--r-- | model/Stream.php | 174 | ||||
-rw-r--r-- | model/StreamList.php | 55 | ||||
-rw-r--r-- | template/assemblies/chat.phtml | 13 | ||||
-rw-r--r-- | template/assemblies/player/audio.phtml | 26 | ||||
-rw-r--r-- | template/assemblies/player/music.phtml | 26 | ||||
-rw-r--r-- | template/assemblies/player/slides.phtml | 20 | ||||
-rw-r--r-- | template/assemblies/player/video.phtml | 42 | ||||
-rw-r--r-- | template/assemblies/switcher/audio.phtml | 33 | ||||
-rw-r--r-- | template/assemblies/switcher/music.phtml | 23 | ||||
-rw-r--r-- | template/assemblies/switcher/slides.phtml | 52 | ||||
-rw-r--r-- | template/assemblies/switcher/video.phtml | 36 | ||||
-rw-r--r-- | template/page.phtml | 2 | ||||
-rw-r--r-- | template/room.phtml | 36 | ||||
-rw-r--r-- | view/room.php | 118 |
23 files changed, 833 insertions, 770 deletions
@@ -130,20 +130,6 @@ $GLOBALS['CONFIG']['ROOMS'] = array( 'DISPLAY' => 'Saal 1', /** - * Vefügbare Streaming-Formate - * Die Formate müssen in $GLOBALS['CONFIG']['FORMATS'] benannt sein, es - * können jedoch über die Config keine neuen erfunden werden; dazu sind - * Änderungen am Code erforderlich. - */ - 'FORMATS' => array( - 'rtmp-sd', 'rtmp-hd', - 'hls-sd', 'hls-hd', - 'webm-sd', 'webm-hd', - 'audio-mp3', 'audio-opus', - 'slides', - ), - - /** * ID des Video/Audio-Streams. Die Stream-ID ist davon abhängig, welches * Event-Case in welchem Raum aufgebaut wird und wird üblicherweise von * s1 bis s5 durchnummeriert. @@ -163,14 +149,15 @@ $GLOBALS['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. - * - * Der Spezialwert 'stereo' (oder ein beliebiger anderer String) kann - * verwendet werden, um statt s1_native_sd Streamnamen in der Art von - * s1_<string>_sd, also z.B. s1_stereo_sd zu benutzen. Abgesehen von den - * anderen Streamnamen verhält sich die Seite, als wäre false gesetzt. */ 'TRANSLATION' => true, + //'STEREO' => true, + 'SD_VIDEO' => true, + 'HD_VIDEO' => true, + 'AUDIO' => true, + 'SLIDES' => true, + /** * Fahrplan-Ansicht auf der Raum-Seite aktivieren (boolean) * @@ -271,16 +258,16 @@ $GLOBALS['CONFIG']['ROOMS'] = array( 'saal2' => array( 'DISPLAY' => 'Saal 2', - 'FORMATS' => array( - 'rtmp-sd', 'rtmp-hd', - 'hls-sd', 'hls-hd', - 'webm-sd', 'webm-hd', - 'audio-mp3', 'audio-opus', - 'slides', - ), 'STREAM' => 's2', 'PREVIEW' => true, + 'TRANSLATION' => true, + //'STEREO' => true, + 'SD_VIDEO' => true, + 'HD_VIDEO' => true, + 'AUDIO' => true, + 'SLIDES' => true, + 'SCHEDULE' => true, 'SCHEDULE_NAME' => 'Saal 2', 'FEEDBACK' => true, @@ -299,16 +286,16 @@ $GLOBALS['CONFIG']['ROOMS'] = array( 'saalg' => array( 'DISPLAY' => 'Saal G', - 'FORMATS' => array( - 'rtmp-sd', 'rtmp-hd', - 'hls-sd', 'hls-hd', - 'webm-sd', - 'audio-mp3', 'audio-opus', - 'slides', - ), 'STREAM' => 's3', 'PREVIEW' => true, + 'TRANSLATION' => true, + //'STEREO' => true, + 'SD_VIDEO' => true, + 'HD_VIDEO' => true, + 'AUDIO' => true, + 'SLIDES' => true, + 'SCHEDULE' => true, 'SCHEDULE_NAME' => 'Saal G', 'FEEDBACK' => true, @@ -327,16 +314,16 @@ $GLOBALS['CONFIG']['ROOMS'] = array( 'saal6' => array( 'DISPLAY' => 'Saal 6', - 'FORMATS' => array( - 'rtmp-sd', 'rtmp-hd', - 'hls-sd', 'hls-hd', - 'webm-sd', 'webm-hd', - 'audio-mp3', 'audio-opus', - 'slides', - ), 'STREAM' => 's4', 'PREVIEW' => true, + 'TRANSLATION' => true, + //'STEREO' => true, + 'SD_VIDEO' => true, + 'HD_VIDEO' => true, + 'AUDIO' => true, + 'SLIDES' => true, + 'SCHEDULE' => true, 'SCHEDULE_NAME' => 'Saal 6', 'FEEDBACK' => true, @@ -356,28 +343,23 @@ $GLOBALS['CONFIG']['ROOMS'] = array( 'lounge' => array( 'DISPLAY' => 'Lounge', - 'FORMATS' => array( - 'music-mp3', 'music-opus', - ), + 'MUSIC' => true, ), 'ambient' => array( 'DISPLAY' => 'Ambient', - 'FORMATS' => array( - 'music-mp3', 'music-opus', - ), + 'MUSIC' => true, ), 'sendezentrum' => array( 'DISPLAY' => 'Sendezentrum', - 'FORMATS' => array( - 'rtmp-sd', 'rtmp-hd', - 'hls-sd', 'hls-hd', - 'webm-sd', 'webm-hd', - 'audio-mp3', 'audio-opus', - ), 'STREAM' => 's5', - 'TRANSLATION' => false, + + //'STEREO' => true, + 'SD_VIDEO' => true, + 'HD_VIDEO' => true, + 'AUDIO' => true, + 'SCHEDULE' => true, 'FEEDBACK' => true, 'SUBTITLES' => false, @@ -489,8 +471,11 @@ $GLOBALS['CONFIG']['IRC'] = array( /** * URL für die IRC-Links. + * Hierbei kann sowohl ein irc://-Link als auch ein Link zu einem + * WebIrc-Provider wie z.B. 'https://kiwiirc.com/client/irc.hackint.eu/#31C3-%s' + * verwendet werden. * - * %s wird durch den Raum-Slug ersetzt. + * %s wird durch den urlencodeten Raum-Slug ersetzt. * Eine Anpassung kann ebenfalls in der Raum-Konfiguration vorgenommen werden. */ 'URL' => 'irc://irc.hackint.eu:6667/31C3-%s', @@ -523,35 +508,3 @@ $GLOBALS['CONFIG']['TWITTER'] = array( */ 'TEXT' => '#31C3 #%s', ); - - - - -/** - * Beschreibung der Streaming-Formate - * - * Achtung: Über diese Sektion können keine zusätzlichen Formate erstellt werden -- dazu - * sind Code-Anpassungen erforderlich. - * - * In diesem Abschnitt können ausschließlich die Anzeigetexte für die verschiedenen - * Streaming-Formate bearbeitet werden. Für jedes Streamingformat das in einem Raum - * verwendet wird müssen hier Texte hinterlegt sein. - */ -$GLOBALS['CONFIG']['FORMAT'] = array( - 'rtmp-sd' => '1024x576, h264+AAC im FLV-Container via RTMP, 800 kBit/s', - 'rtmp-hd' => '1920x1080, h264+AAC im FLV-Container via RTMP, 3 MBit/s', - - 'hls-sd' => '1024x576, h264+AAC im MPEG-TS-Container via HTTP, 800 kBit/s', - 'hls-hd' => '1920x1080, h264+AAC im MPEG-TS-Container via HTTP, 3 MBit/s', - - 'webm-sd' => '1024x576, VP8+Vorbis in WebM, 800 kBit/s', - 'webm-hd' => '1920x1080, VP8+Vorbis in WebM, 3 MBit/s', - - 'audio-mp3' => 'MP3-Audio, 96 kBit/s', - 'audio-opus' => 'Opus-Audio, 64 kBit/s', - - 'music-mp3' => 'MP3-Audio, 320 kBit/s', - 'music-opus' => 'Opus-Audio, 128 kBit/s', - - 'slides' => '1024x576, h264+AAC, <500 kBit/s', -); @@ -12,6 +12,9 @@ require_once('model/Feedback.php'); require_once('model/Schedule.php'); require_once('model/Overview.php'); require_once('model/Room.php'); +require_once('model/RoomTab.php'); +require_once('model/RoomSelection.php'); +require_once('model/Stream.php'); $route = @$_GET['route']; $route = rtrim($route, '/'); @@ -20,6 +23,7 @@ $route = rtrim($route, '/'); $tpl = new PhpTemplate('template/page.phtml'); $tpl->set(array( 'baseurl' => baseurl(), + 'route' => $route, 'assemblies' => './template/assemblies/', 'conference' => new Conference(), diff --git a/lib/helper.php b/lib/helper.php index 640651b..7423a9c 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -1,46 +1,5 @@ <?php -require_once('program.php'); - -function link_player($room, $format = 'video', $translated = false) -{ - $defaultformat = room_has_hd($room) ? 'hd' : 'sd'; - - return rawurlencode($room).'/'.(($defaultformat == $format || 'video' == $format) ? '' : rawurlencode($format).'/').($translated ? 'translated/' : ''); -} - -function link_stream($protocol, $room, $format, $translated = false) -{ - $language = $translated ? 'translated' : 'native'; - - switch ($protocol) { - case 'rtmp': - return 'rtmp://cdn.c3voc.de/stream/'.rawurlencode(get("ROOMS.$room.STREAM", $room)).'_'.rawurlencode($language).'_'.rawurlencode($format); - - case 'hls': - return 'http://cdn.c3voc.de/hls/'.rawurlencode(get("ROOMS.$room.STREAM", $room)).'_'.rawurlencode($language).($format == 'auto' ? '' : '_'.rawurlencode($format)).'.m3u8'; - - case 'webm': - return 'http://cdn.c3voc.de/'.rawurlencode(get("ROOMS.$room.STREAM", $room)).'_'.rawurlencode($language).'_'.rawurlencode($format).'.webm'; - - case 'music': - return 'http://cdn.c3voc.de/'.rawurlencode(get("ROOMS.$room.STREAM", $room)).'.'.rawurlencode($format); - - case 'audio': - return 'http://cdn.c3voc.de/'.rawurlencode(get("ROOMS.$room.STREAM", $room)).'_'.rawurlencode($language).'.'.rawurlencode($format); - - case 'slide': - return 'http://cdn.c3voc.de/slides/'.rawurlencode(get("ROOMS.$room.STREAM", $room)).'/current.png'; - } - - return '#'; -} - -function link_vod($id) -{ - return 'relive/'.rawurlencode($id).'/'; -} - function baseurl() { if(isset($GLOBALS['CONFIG']['baseurl'])) @@ -62,12 +21,6 @@ function forceslash($url) return $url; } -function strtoduration($str) -{ - $parts = explode(':', $str); - return ((int)$parts[0] * 60 + (int)$parts[1]) * 60; -} - function has($keychain) { return _has($GLOBALS['CONFIG'], $keychain); @@ -106,134 +59,7 @@ function _get($array, $keychain, $default) return _get($array[$key], array_slice($keychain, 1), $default); } - - -function room_has_hd($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('rtmp-hd', 'hls-hd', 'webm-hd'), $formats)) > 0; -} - -function room_has_sd($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('rtmp-sd', 'hls-sd', 'webm-sd'), $formats)) > 0; -} - -function room_has_video($room) -{ - return room_has_hd($room) || room_has_sd($room); -} - -function room_has_audio($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('audio-mp3', 'audio-opus', 'audio-ogg'), $formats)) > 0; -} - -function room_has_music($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('music-mp3', 'music-opus', 'music-ogg'), $formats)) > 0; -} - -function room_has_slides($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('slides'), $formats)) > 0; -} - -function room_get_possible_selections($room) -{ - $selections = array(); - - if(room_has_hd($room)) $selections[] = 'hd'; - if(room_has_sd($room)) $selections[] = 'sd'; - if(room_has_audio($room)) $selections[] = 'audio'; - if(room_has_music($room)) $selections[] = 'music'; - if(room_has_slides($room)) $selections[] = 'slides'; - - return $selections; -} - -function room_has_rtmp($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('rtmp-hd', 'rtmp-sd'), $formats)) > 0; -} - -function room_has_webm($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('webm-hd', 'webm-sd'), $formats)) > 0; -} - -function room_has_hls($room) -{ - $formats = get("ROOMS.$room.FORMATS"); - return count(array_intersect(array('hls-hd', 'hls-sd'), $formats)) > 0; -} - -function room_has_irc($room) -{ - return get("ROOMS.$room.IRC") && has("IRC"); -} - -function room_has_twitter($room) -{ - return get("ROOMS.$room.TWITTER") && has("TWITTER"); -} - -function room_has_chat($room) -{ - return room_has_irc($room) || room_has_twitter($room); -} - -function room_get_irc_url($room) -{ - $cfg = get("ROOMS.$room.IRC_CONFIG", get("IRC")); - return sprintf($cfg['URL'], rawurlencode($room)); -} - -function room_get_irc_display($room) -{ - $cfg = get("ROOMS.$room.IRC_CONFIG", get("IRC")); - return sprintf($cfg['DISPLAY'], $room); -} - -function room_get_twitter_hashtag($room) -{ - $cfg = get("ROOMS.$room.TWITTER_CONFIG", get("TWITTER")); - return sprintf($cfg['TEXT'], $room); -} - -function room_get_twitter_display($room) -{ - $cfg = get("ROOMS.$room.TWITTER_CONFIG", get("TWITTER")); - return sprintf($cfg['DISPLAY'], $room); -} - function startswith($needle, $haystack) { return substr($haystack, 0, strlen($needle)) == $needle; } - -function relive_talks() -{ - $talks = @file_get_contents(get('OVERVIEW.RELIVE_JSON')); - $talks = utf8_decode($talks); - $talks = (array)json_decode($talks, true); - - usort($talks, function($a, $b) { - $sort = array('live', 'recorded', 'released'); - return array_search($a['status'], $sort) > array_search($b['status'], $sort); - }); - - $talks_by_id = array(); - foreach ($talks as $value) - { - $talks_by_id[$value['id']] = $value; - } - - return $talks_by_id; -} diff --git a/lib/program.php b/lib/program.php deleted file mode 100644 index 79ce91d..0000000 --- a/lib/program.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php - -function program() -{ - if(!has('SCHEDULE')) - return; - - if(has('SCHEDULE.CACHE') && function_exists('apc_fetch')) - { - $program = apc_fetch('SCHEDULE.CACHE'); - if($program) return $program; - } - - - $program = array(); - $opts = array( - 'http' => array( - 'timeout' => 2, - 'user_agent' => 'C3Voc Universal Streaming-Website Backend @ '.$_SERVER['HTTP_HOST'], - ) - ); - $context = stream_context_create($opts); - $schedule = file_get_contents(get('SCHEDULE.URL'), false, $context); - - // failed, give up - if(!$schedule) - return array(); - - $schedule = simplexml_load_string($schedule); - - // re-calculate day-ends - // some schedules have long gaps before the first talk or talks that expand beyond the dayend - // (fiffkon, i look at you) - // so to be on the safer side we calculate our own daystart/end here - foreach($schedule->day as $day) - { - $daystart = PHP_INT_MAX; - $dayend = 0; - - foreach($day->room as $room) - { - foreach($room->event as $event) - { - $start = strtotime((string)$event->date); - $duration = strtoduration((string)$event->duration); - $end = $start + $duration; - - $daystart = min($daystart, $start); - $dayend = max($dayend, $end); - } - } - - $day['start'] = $daystart; - $day['end'] = $dayend; - } - - $dayidx = 0; - foreach($schedule->day as $day) - { - $dayidx++; - $daystart = (int)$day['start']; - $dayend = (int)$day['end']; - - $roomidx = 0; - foreach($day->room as $room) - { - $roomidx++; - $lastend = false; - $name = (string)$room['name']; - if(isset($GLOBALS['CONFIG']['FAHRPLAN_ROOM_MAPPING'][$name])) - $name = $GLOBALS['CONFIG']['FAHRPLAN_ROOM_MAPPING'][$name]; - - foreach($room->event as $event) - { - $start = strtotime((string)$event->date); - $duration = strtoduration((string)$event->duration); - $end = $start + $duration; - - if($lastend && $lastend < $start) - { - // synthesize pause event - $pauseduration = $start - $lastend; - $program[$name][] = array( - 'special' => 'pause', - 'title' => round($pauseduration / 60).' minutes pause', - - 'fstart' => date('c', $lastend), - 'fend' => date('c', $start), - - 'start' => $lastend, - 'end' => $start, - 'duration' => $pauseduration, - ); - } - else if(!$lastend && $daystart < $start) - { - $program[$name][] = array( - 'special' => 'gap', - - 'fstart' => date('c', $daystart), - 'fend' => date('c', $start), - - 'start' => $daystart, - 'end' => $start, - 'duration' => $start - $daystart, - ); - } - - $personnames = array(); - foreach($event->persons->person as $person) - $personnames[] = (string)$person; - - $program[$name][] = array( - 'title' => (string)$event->title, - 'speaker' => implode(', ', $personnames), - - 'fstart' => date('c', $start), - 'fend' => date('c', $end), - - 'start' => $start, - 'end' => $end, - 'duration' => $duration, - ); - - $lastend = $end; - } - - // synthesize daychange event - if(!$lastend) $lastend = $daystart; - if($lastend < $dayend) - { - $program[$name][] = array( - 'special' => 'gap', - - 'fstart' => date('c', $lastend), - 'fend' => date('c', $dayend), - - 'start' => $lastend, - 'end' => $dayend, - 'duration' => $dayend - $lastend, - ); - } - - if($dayidx < count($schedule->day)) - { - $program[$name][] = array( - 'special' => 'daychange', - 'title' => 'Daychange from Day '.$dayidx.' to '.($dayidx+1), - - 'start' => $dayend, - 'end' => (int)$schedule->day[$dayidx]['start'], - 'duration' => 60*60, - ); - } - } - } - - if(has('SCHEDULE.CACHE') && function_exists('apc_store')) - { - apc_store( - 'SCHEDULE.CACHE', - $program, - get('SCHEDULE.CACHE') - ); - } - - return $program; -} diff --git a/model/Relive.php b/model/Relive.php new file mode 100644 index 0000000..3ffdc1b --- /dev/null +++ b/model/Relive.php @@ -0,0 +1,24 @@ +<?php + +class Relive extends ModelBase +{ + function relive_talks() + { + $talks = @file_get_contents(get('OVERVIEW.RELIVE_JSON')); + $talks = utf8_decode($talks); + $talks = (array)json_decode($talks, true); + + usort($talks, function($a, $b) { + $sort = array('live', 'recorded', 'released'); + return array_search($a['status'], $sort) > array_search($b['status'], $sort); + }); + + $talks_by_id = array(); + foreach ($talks as $value) + { + $talks_by_id[$value['id']] = $value; + } + + return $talks_by_id; + } +} diff --git a/model/Room.php b/model/Room.php index c7e51f9..f428d87 100644 --- a/model/Room.php +++ b/model/Room.php @@ -35,11 +35,202 @@ class Room extends ModelBase + public function hasStereo() { + return $this->get('ROOMS.'.$this->getSlug().'.STEREO'); + } + public function hasPreview() { - return get('ROOMS.'.$this->getSlug().'.PREVIEW'); + return $this->get('ROOMS.'.$this->getSlug().'.PREVIEW'); } public function hasSchedule() { return $this->get('ROOMS.'.$this->getSlug().'.SCHEDULE') && $this->has('SCHEDULE'); } + + public function hasFeedback() { + return $this->get('ROOMS.'.$this->getSlug().'.FEEDBACK') && $this->has('FEEDBACK'); + } + + + public function hasTwitter() { + return $this->get('ROOMS.'.$this->getSlug().'.TWITTER') && $this->has('TWITTER'); + } + + public function getTwitterDisplay() { + return sprintf( + $this->get('ROOMS.'.$this->getSlug().'.TWITTER_CONFIG.DISPLAY', $this->get('TWITTER.DISPLAY')), + $this->getSlug() + ); + } + + public function getTwitterUrl() { + return sprintf( + 'https://twitter.com/intent/tweet?text=%s', + rawurlencode($this->getTwitterText()) + ); + } + + public function getTwitterText() { + return sprintf( + $this->get('ROOMS.'.$this->getSlug().'.TWITTER_CONFIG.TEXT', $this->get('TWITTER.TEXT')), + $this->getSlug() + ); + } + + + public function hasIrc() { + return $this->get('ROOMS.'.$this->getSlug().'.IRC') && $this->has('IRC'); + } + + public function getIrcDisplay() { + return sprintf( + $this->get('ROOMS.'.$this->getSlug().'.IRC_CONFIG.DISPLAY', $this->get('IRC.DISPLAY')), + $this->getSlug() + ); + } + + public function getIrcUrl() { + return sprintf( + $this->get('ROOMS.'.$this->getSlug().'.IRC_CONFIG.URL', $this->get('IRC.URL')), + rawurlencode($this->getSlug()) + ); + } + + + public function hasChat() { + return $this->hasTwitter() || $this->hasIrc(); + } + + + public function hasSdVideo() { + return $this->get('ROOMS.'.$this->getSlug().'.SD_VIDEO'); + } + + public function hasHdVideo() { + return $this->get('ROOMS.'.$this->getSlug().'.HD_VIDEO'); + } + + public function hasVideo() { + return $this->hasSdVideo() || $this->hasHdVideo(); + } + + public function hasAudio() { + return $this->get('ROOMS.'.$this->getSlug().'.AUDIO'); + } + + public function hasSlides() { + return $this->get('ROOMS.'.$this->getSlug().'.SLIDES'); + } + + public function hasMusic() { + return $this->get('ROOMS.'.$this->getSlug().'.MUSIC'); + } + + public function hasTranslation() { + return $this->get('ROOMS.'.$this->getSlug().'.TRANSLATION'); + } + + public function getSelectionNames() + { + $selections = array(); + if($this->hasHdVideo()) + $selections[] = 'hd'; + + if($this->hasSdVideo()) + $selections[] = 'sd'; + + if($this->hasSlides()) + $selections[] = 'slides'; + + if($this->hasAudio()) + $selections[] = 'audio'; + + if($this->hasMusic()) + $selections[] = 'music'; + + return $selections; + } + + public function getTabNames() + { + $tabs = array(); + if($this->hasVideo()) + $tabs[] = 'video'; + + if($this->hasSlides()) + $tabs[] = 'slides'; + + if($this->hasAudio()) + $tabs[] = 'audio'; + + if($this->hasMusic()) + $tabs[] = 'music'; + + return $tabs; + } + + public function getSelections() + { + $selections = array(); + foreach($this->getSelectionNames() as $selection) + $selections[$tab] = $this->createSelectionObject($selection); + + return $selections; + } + + public function createSelectionObject($selection) + { + return new RoomSelection($this, $selection); + } + + public function getTabs() + { + $tabs = array(); + foreach($this->getTabNames() as $tab) + $tabs[$tab] = $this->createTabObject($tab); + + return $tabs; + } + + public function createTabObject($tab) + { + return new RoomTab($this, $tab); + } + + public function getVideoResolutions() + { + $res = array(); + if($this->hasHdVideo()) + $res[] = 'hd'; + + if($this->hasSdVideo()) + $res[] = 'sd'; + + return $res; + } + + public function selectStream($selection, $language = 'native') + { + $selections = $this->getSelectionNames(); + + // default page + if(!$selection) + $selection = $selections[0]; + + 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()); + + return $this->createStreamObject($selection, $language); + } + + public function createStreamObject($selection, $language = 'native') + { + if($language == 'native' && $this->hasStereo()) + $language = 'stereo'; + + return new Stream($this, $selection, $language); + } } diff --git a/model/RoomSelection.php b/model/RoomSelection.php new file mode 100644 index 0000000..c163321 --- /dev/null +++ b/model/RoomSelection.php @@ -0,0 +1,52 @@ +<?php + +class RoomSelection +{ + public function __construct(Room $room, $selection) + { + $this->room = $room; + $this->selection = $selection; + } + + public function getRoom() + { + return $this->room; + } + + public function getSelection() + { + return $this->selection; + } + + public function getLink() + { + $selection = $this->getRoom()->getSelectionNames(); + if($selection[0] == $this->getSelection()) + return rawurlencode($this->getRoom()->getSlug()).'/'; + + return rawurlencode($this->getRoom()->getSlug()).'/'.rawurlencode($this->getSelection()).'/'; + } + + public function getTranslatedLink() + { + return $this->getLink().'translated/'; + } + + public function getDisplay() + { + switch($this->getSelection()) + { + case 'sd': + case 'hd': + return strtoupper($this->getSelection()); + + default: + return ucfirst($this->getSelection()); + } + } + + public function getTech() + { + return $this->getSelection().'-tech'; + } +} diff --git a/model/RoomTab.php b/model/RoomTab.php new file mode 100644 index 0000000..d4f781b --- /dev/null +++ b/model/RoomTab.php @@ -0,0 +1,34 @@ +<?php + +class RoomTab +{ + public function __construct(Room $room, $tab) + { + $this->room = $room; + $this->tab = $tab; + } + + public function getRoom() + { + return $this->room; + } + + public function getTab() + { + return $this->tab; + } + + public function getLink() + { + $tabs = $this->getRoom()->getTabNames(); + if($tabs[0] == $this->getTab()) + return rawurlencode($this->getRoom()->getSlug()).'/'; + + return rawurlencode($this->getRoom()->getSlug()).'/'.rawurlencode($this->getTab()).'/'; + } + + public function getDisplay() + { + return ucfirst($this->getTab()); + } +} diff --git a/model/Schedule.php b/model/Schedule.php index db940ce..ca4881d 100644 --- a/model/Schedule.php +++ b/model/Schedule.php @@ -5,4 +5,177 @@ class Schedule extends ModelBase public function getSimulationOffset() { return $this->get('SCHEDULE.SIMULATE_OFFSET', 0); } + + private function strtoduration($str) + { + $parts = explode(':', $str); + return ((int)$parts[0] * 60 + (int)$parts[1]) * 60; + } + + function program() + { + if(!has('SCHEDULE')) + return; + + if(has('SCHEDULE.CACHE') && function_exists('apc_fetch')) + { + $program = apc_fetch('SCHEDULE.CACHE'); + if($program) return $program; + } + + + $program = array(); + $opts = array( + 'http' => array( + 'timeout' => 2, + 'user_agent' => 'C3Voc Universal Streaming-Website Backend @ '.$_SERVER['HTTP_HOST'], + ) + ); + $context = stream_context_create($opts); + $schedule = file_get_contents(get('SCHEDULE.URL'), false, $context); + + // failed, give up + if(!$schedule) + return array(); + + $schedule = simplexml_load_string($schedule); + + // re-calculate day-ends + // some schedules have long gaps before the first talk or talks that expand beyond the dayend + // (fiffkon, i look at you) + // so to be on the safer side we calculate our own daystart/end here + foreach($schedule->day as $day) + { + $daystart = PHP_INT_MAX; + $dayend = 0; + + foreach($day->room as $room) + { + foreach($room->event as $event) + { + $start = strtotime((string)$event->date); + $duration = strtoduration((string)$event->duration); + $end = $start + $duration; + + $daystart = min($daystart, $start); + $dayend = max($dayend, $end); + } + } + + $day['start'] = $daystart; + $day['end'] = $dayend; + } + + $dayidx = 0; + foreach($schedule->day as $day) + { + $dayidx++; + $daystart = (int)$day['start']; + $dayend = (int)$day['end']; + + $roomidx = 0; + foreach($day->room as $room) + { + $roomidx++; + $lastend = false; + $name = (string)$room['name']; + if(isset($GLOBALS['CONFIG']['FAHRPLAN_ROOM_MAPPING'][$name])) + $name = $GLOBALS['CONFIG']['FAHRPLAN_ROOM_MAPPING'][$name]; + + foreach($room->event as $event) + { + $start = strtotime((string)$event->date); + $duration = strtoduration((string)$event->duration); + $end = $start + $duration; + + if($lastend && $lastend < $start) + { + // synthesize pause event + $pauseduration = $start - $lastend; + $program[$name][] = array( + 'special' => 'pause', + 'title' => round($pauseduration / 60).' minutes pause', + + 'fstart' => date('c', $lastend), + 'fend' => date('c', $start), + + 'start' => $lastend, + 'end' => $start, + 'duration' => $pauseduration, + ); + } + else if(!$lastend && $daystart < $start) + { + $program[$name][] = array( + 'special' => 'gap', + + 'fstart' => date('c', $daystart), + 'fend' => date('c', $start), + + 'start' => $daystart, + 'end' => $start, + 'duration' => $start - $daystart, + ); + } + + $personnames = array(); + foreach($event->persons->person as $person) + $personnames[] = (string)$person; + + $program[$name][] = array( + 'title' => (string)$event->title, + 'speaker' => implode(', ', $personnames), + + 'fstart' => date('c', $start), + 'fend' => date('c', $end), + + 'start' => $start, + 'end' => $end, + 'duration' => $duration, + ); + + $lastend = $end; + } + + // synthesize daychange event + if(!$lastend) $lastend = $daystart; + if($lastend < $dayend) + { + $program[$name][] = array( + 'special' => 'gap', + + 'fstart' => date('c', $lastend), + 'fend' => date('c', $dayend), + + 'start' => $lastend, + 'end' => $dayend, + 'duration' => $dayend - $lastend, + ); + } + + if($dayidx < count($schedule->day)) + { + $program[$name][] = array( + 'special' => 'daychange', + 'title' => 'Daychange from Day '.$dayidx.' to '.($dayidx+1), + + 'start' => $dayend, + 'end' => (int)$schedule->day[$dayidx]['start'], + 'duration' => 60*60, + ); + } + } + } + + if(has('SCHEDULE.CACHE') && function_exists('apc_store')) + { + apc_store( + 'SCHEDULE.CACHE', + $program, + get('SCHEDULE.CACHE') + ); + } + + return $program; + } } diff --git a/model/Stream.php b/model/Stream.php index a60284a..402dfff 100644 --- a/model/Stream.php +++ b/model/Stream.php @@ -1,5 +1,177 @@ <?php -class Room { +class Stream +{ + public function __construct(Room $room, $selection, $language) + { + $this->room = $room; + $this->selection = $selection; + $this->language = $language; + } + public function getRoom() + { + return $this->room; + } + + public function getSelection() + { + return $this->selection; + } + + public function getLanguage() + { + return $this->language; + } + + public function isTranslated() + { + return $this->getLanguage() == 'translated'; + } + + public function getVideoSize() + { + switch($this->getSelection()) + { + case 'sd': + case 'slides': + return array(1024, 576); + + case 'hd': + return array(1920, 1080); + + default: + return null; + } + } + + public function getVideoWidth() + { + $sz = $this->getVideoSize(); + return $sz[0]; + } + + public function getVideoHeight() + { + $sz = $this->getVideoSize(); + return $sz[1]; + } + + public function getTab() + { + switch($this->getSelection()) + { + case 'sd': + case 'hd': + return 'video'; + + default: + return $this->getSelection(); + } + } + + public function getPlayerType() + { + return $this->getTab(); + } + + public function getDisplay() + { + $display = $this->getRoom()->getDisplay().' '; + switch($this->getSelection()) + { + case 'hd': + $display .= 'FullHD Video'; + break; + + case 'sd': + $display .= 'SD Video'; + break; + + default: + $display .= ucfirst($this->getSelection()); + break; + } + + if($this->isTranslated()) + $display .= ' (Translation)'; + + return $display; + } + + public function getVideoUrl($proto) + { + switch($proto) + { + case 'webm': + return 'http://cdn.c3voc.de/'.rawurlencode($this->getRoom()->getStream()).'_'.rawurlencode($this->getLanguage()).'_'.rawurlencode($this->getSelection()).'.webm'; + + case 'hls': + return 'http://cdn.c3voc.de/hls/'.rawurlencode($this->getRoom()->getStream()).'_'.rawurlencode($this->getLanguage()).'_'.rawurlencode($this->getSelection()).'.m3u8'; + + default: + return null; + } + } + public static function getVideoProtos() + { + return array( + 'webm' => 'WebM', + 'hls' => 'HLS', + ); + } + + public function getSlidesUrl($proto) + { + return $this->getVideoUrl($proto); + } + public static function getSlidesProtos() + { + return Stream::getVideoProtos(); + } + + + public function getAudioUrl($proto) + { + switch($proto) + { + case 'mp3': + return 'http://cdn.c3voc.de/'.rawurlencode($this->getRoom()->getStream()).'_'.rawurlencode($this->getLanguage()).'.mp3'; + + case 'opus': + return 'http://cdn.c3voc.de/'.rawurlencode($this->getRoom()->getStream()).'_'.rawurlencode($this->getLanguage()).'.opus'; + + default: + return null; + } + } + public static function getAudioProtos() + { + return array( + 'mp3' => 'MP3', + 'opus' => 'Opus', + ); + } + + public function getMusicUrl($proto) + { + switch($proto) + { + case 'mp3': + return 'http://cdn.c3voc.de/'.rawurlencode($this->getRoom()->getStream()).'.mp3'; + + case 'opus': + return 'http://cdn.c3voc.de/'.rawurlencode($this->getRoom()->getStream()).'.opus'; + + default: + return null; + } + } + public static function getMusicProtos() + { + return array( + 'mp3' => 'MP3', + 'opus' => 'Opus', + ); + } } diff --git a/model/StreamList.php b/model/StreamList.php deleted file mode 100644 index d203a52..0000000 --- a/model/StreamList.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -class StreamList extends ModelBase implements IteratorAggregate -{ - private $streams = array(); - - public function __construct($slug) - { - if(! $this->has('ROOMS.'.$slug)) - throw new NotFoundException('Room '.$slug); - - $this->slug = $slug; - $this->streams = array(); - - $streams = $this->get("ROOMS.$slug.STREAMS"); - foreach((array)$streams as $stream) { - $this->streams[$stream] = explode('-', $stream); - } - } - - public function getRoomSlug() { - return $this->slug; - } - - public function getRoom() { - return new Room($this->getRoomSlug()); - } - - public function getStreams() { - return array_keys($this->streams); - } - - public function getIterator() { - return new ArrayIterator($this->streams); - } - - - public function hasTranslation() { - } - - public function hasRTMP() { - } - - public function hasHLS() { - } - - public function hasWebM() { - } - - public function hasHD() { - } - - public function hasSD() { - } -} diff --git a/template/assemblies/chat.phtml b/template/assemblies/chat.phtml index 85245b2..8498c45 100644 --- a/template/assemblies/chat.phtml +++ b/template/assemblies/chat.phtml @@ -1,14 +1,15 @@ -<? if(room_has_irc($room)): ?> +<? if($room->hasIrc()): ?> <div> - <a class="btn btn-primary irclink" href="<?=h(room_get_irc_url($room))?>" target="_blank"> - <span class="fa fa-comment"></span> <?=h(room_get_irc_display($room))?> + <a class="btn btn-primary irclink" href="<?=h($room->getIrcUrl())?>" target="_blank"> + <span class="fa fa-comment"></span> <?=h($room->getIrcDisplay())?> </a> </div> <? endif ?> -<? if(room_has_twitter($room)): ?> + +<? if($room->hasTwitter($room)): ?> <div> - <a class="btn twitterlink" href="https://twitter.com/intent/tweet?text=<?=h(rawurlencode(room_get_twitter_hashtag($room)))?>" target="_blank"> - <span class="fa fa-twitter"></span> <?=h(room_get_twitter_display($room))?> + <a class="btn twitterlink" href="<?=h($room->getTwitterUrl())?>" target="_blank"> + <span class="fa fa-twitter"></span> <?=h($room->getTwitterDisplay())?> </a> </div> <? endif ?> diff --git a/template/assemblies/player/audio.phtml b/template/assemblies/player/audio.phtml index e007ab3..f8ed579 100644 --- a/template/assemblies/player/audio.phtml +++ b/template/assemblies/player/audio.phtml @@ -3,22 +3,12 @@ preload="auto" style="width: 230px;" > - <? if(in_array("audio-mp3", $formats)): ?> - <source - src="<?=h(link_stream('audio', $room, 'mp3', @$translated))?>" - type="audio/mp3" - /> - <? endif ?> - <? if(in_array("audio-opus", $formats)): ?> - <source - src="<?=h(link_stream('audio', $room, 'opus', @$translated))?>" - type="audio/opus" - /> - <? endif ?> - <? if(in_array("audio-ogg", $formats)): ?> - <source - src="<?=h(link_stream('audio', $room, 'ogg', @$translated))?>" - type="audio/ogg" - /> - <? endif ?> + <source + src="<?=h($stream->getAudioUrl('mp3'))?>" + type="audio/mp3" + /> + <source + src="<?=h($stream->getAudioUrl('opus'))?>" + type="audio/opus" + /> </audio> diff --git a/template/assemblies/player/music.phtml b/template/assemblies/player/music.phtml index 587d2d2..b1c804a 100644 --- a/template/assemblies/player/music.phtml +++ b/template/assemblies/player/music.phtml @@ -3,22 +3,12 @@ preload="auto" style="width: 230px;" > - <? if(in_array("music-mp3", $formats)): ?> - <source - src="<?=h(link_stream('music', $room, 'mp3', @$translated))?>" - type="audio/mp3" - /> - <? endif ?> - <? if(in_array("music-opus", $formats)): ?> - <source - src="<?=h(link_stream('music', $room, 'opus', @$translated))?>" - type="audio/opus" - /> - <? endif ?> - <? if(in_array("music-ogg", $formats)): ?> - <source - src="<?=h(link_stream('music', $room, 'ogg', @$translated))?>" - type="audio/ogg" - /> - <? endif ?> + <source + src="<?=h($stream->getMusicUrl('mp3'))?>" + type="audio/mp3" + /> + <source + src="<?=h($stream->getMusicUrl('opus'))?>" + type="audio/opus" + /> </audio> diff --git a/template/assemblies/player/slides.phtml b/template/assemblies/player/slides.phtml index c2720d6..7887aa0 100644 --- a/template/assemblies/player/slides.phtml +++ b/template/assemblies/player/slides.phtml @@ -1,28 +1,22 @@ -<div style="width: 100%; height: 100%; max-width: <?=h($width)?>px; margin: 0 auto;"> +<div style="max-width: <?=h($stream->getVideoWidth())?>px; max-height: <?=h($stream->getVideoHeight())?>px;" class="video-wrap"> <video autoplay="autoplay" preload="auto" - width="<?=h($width)?>" - height="<?=h($height)?>" + width="<?=h($stream->getVideoWidth())?>" + height="<?=h($stream->getVideoHeight())?>" style="width: 100%; height: 100%;" > - <!--source + <source data-plugin-type="native" - src="<?=h(link_stream('webm', $room, 'webm_slides', $translated))?>" + src="<?=h($stream->getSlidesUrl('webm'))?>" title="WebM (Icecast)" type="video/webm" - /--> - <source - data-plugin-type="flash" - src="<?=h(link_stream('rtmp', $room, 'slides', $translated))?>" - title="h.264 (RTMP)" - type="video/rtmp" /> <source data-plugin-type="native" - src="<?=h(link_stream('hls', $room, 'slides', $translated))?>" + src="<?=h($stream->getSlidesUrl('hls'))?>" title="h.264 (HLS)" type="application/vnd.apple.mpegURL" /> </video> -</div>
\ No newline at end of file +</div> diff --git a/template/assemblies/player/video.phtml b/template/assemblies/player/video.phtml index 0861cf8..3ffc333 100644 --- a/template/assemblies/player/video.phtml +++ b/template/assemblies/player/video.phtml @@ -1,34 +1,22 @@ -<div style="max-width: <?=h($width)?>px; max-height: <?=h($height)?>px;" class="video-wrap"> +<div style="max-width: <?=h($stream->getVideoWidth())?>px; max-height: <?=h($stream->getVideoHeight())?>px;" class="video-wrap"> <video autoplay="autoplay" preload="auto" - width="<?=h($width)?>" - height="<?=h($height)?>" + width="<?=h($stream->getVideoWidth())?>" + height="<?=h($stream->getVideoHeight())?>" style="width: 100%; height: 100%;" > - <? if(in_array("webm-$selection", $formats)): ?> - <source - data-plugin-type="native" - src="<?=h(link_stream('webm', $room, $selection, $translated))?>" - title="WebM (Icecast)" - type="video/webm" - /> - <? endif ?> - <? if(in_array("hls-$selection", $formats)): ?> - <source - data-plugin-type="native" - src="<?=h(link_stream('hls', $room, $hlsformat, $translated))?>" - title="h.264 (HLS)" - type="application/vnd.apple.mpegURL" - /> - <? endif ?> - <? if(in_array("rtmp-$selection", $formats)): ?> - <source - data-plugin-type="flash" - src="<?=h(link_stream('rtmp', $room, $selection, $translated))?>" - title="h.264 (RTMP)" - type="video/rtmp" - /> - <? endif ?> + <source + data-plugin-type="native" + src="<?=h($stream->getVideoUrl('webm'))?>" + title="WebM (Icecast)" + type="video/webm" + /> + <source + data-plugin-type="native" + src="<?=h($stream->getVideoUrl('hls'))?>" + title="h.264 (HLS)" + type="application/vnd.apple.mpegURL" + /> </video> </div> diff --git a/template/assemblies/switcher/audio.phtml b/template/assemblies/switcher/audio.phtml index 53131d3..9f3ba76 100644 --- a/template/assemblies/switcher/audio.phtml +++ b/template/assemblies/switcher/audio.phtml @@ -1,5 +1,6 @@ <div class="container-fluid"> - <? if($has_translation): ?> + <? $selection = $room->createSelectionObject('audio') ?> + <? if($room->hasTranslation()): ?> <h3>Audio</h3> <div class="formats row"> @@ -7,11 +8,11 @@ <div class="btn-group" role="group"> <div class="btn btn-primary" disabled>Audio</div> - <a href="<?=h(link_player($room, 'audio'))?>" class="btn btn-default"> + <a href="<?=h($selection->getLink())?>" class="btn btn-default"> <span class="fa fa-flag-o"></span> native </a> - <a href="<?=h(link_player($room, 'audio', true))?>" class="btn btn-default"> + <a href="<?=h($selection->getTranslatedLink())?>" class="btn btn-default"> <span class="fa fa-flag"></span> translated </a> @@ -23,35 +24,35 @@ <? endif ?> - <h3>Directlinks</h3> - <div class="formats row"> - <? foreach(array_intersect($formats, array('audio-mp3', 'audio-opus', 'audio-ogg')) as $format): ?> - <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> - <? $proto = substr($format, 6) ?> - <div class="btn-group" role="group" title="<?=h(get("FORMAT.$format"))?>"> - <div class="btn btn-primary" disabled><?=h(strtoupper($proto))?></div> + <div class="directlinks"> - <? if($has_translation): ?> + <? foreach(Stream::getAudioProtos() as $proto => $display): ?> + <h3>Directlinks (<?=h($display)?>)</h3> + <div class="row"> + <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> + <div class="btn-group" role="group"> + <div class="btn btn-primary" disabled><?=h($selection->getDisplay())?></div> + <? if($room->hasTranslation()): ?> - <a href="<?=h(link_stream('audio', $room, $proto))?>" class="btn btn-default"> + <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(link_stream('audio', $room, $proto, true))?>" class="btn btn-default"> + <a href="<?=h($room->createStreamObject('audio', 'translated')->getAudioUrl($proto))?>" class="btn btn-default"> <span class="fa fa-flag"></span> translated </a> <? else: ?> - <a href="<?=h(link_stream('audio', $room, $proto))?>" class="btn btn-default"> + <a href="<?=h($room->createStreamObject('audio')->getAudioUrl($proto))?>" class="btn btn-default"> <span class="fa fa-volume-up"></span> - audio + video </a> <? endif ?> - + </div> </div> </div> <? endforeach ?> diff --git a/template/assemblies/switcher/music.phtml b/template/assemblies/switcher/music.phtml index df1fbf2..a6b3ffc 100644 --- a/template/assemblies/switcher/music.phtml +++ b/template/assemblies/switcher/music.phtml @@ -1,21 +1,20 @@ <div class="container-fluid"> <h3>Directlinks</h3> - <div class="formats row"> + <div class="directlinks"> + <div class="row"> + <? foreach(Stream::getMusicProtos() as $proto => $display): ?> + <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> + <div class="btn-group" role="group"> + <div class="btn btn-primary" disabled><?=h($display)?></div> - <? foreach(array_intersect($formats, array('music-mp3', 'music-opus', 'music-ogg')) as $format): ?> - <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> - <? $proto = substr($format, 6) ?> - <div class="btn-group" role="group" title="<?=h(get("FORMAT.$format"))?>"> - <div class="btn btn-primary" disabled><?=h(strtoupper($proto))?></div> - - <a href="<?=h(link_stream('music', $room, $proto))?>" class="btn btn-default"> + <a href="<?=h($room->createStreamObject('music')->getMusicUrl($proto))?>" class="btn btn-default"> <span class="fa fa-music"></span> - music + live music </a> + </div> </div> - </div> - <? endforeach ?> - + <? endforeach ?> + </div> </div> </div> diff --git a/template/assemblies/switcher/slides.phtml b/template/assemblies/switcher/slides.phtml index 7355da0..a5f5082 100644 --- a/template/assemblies/switcher/slides.phtml +++ b/template/assemblies/switcher/slides.phtml @@ -1,5 +1,6 @@ <div class="container-fluid"> - <? if($has_translation): ?> + <? $selection = $room->createSelectionObject('audio') ?> + <? if($room->hasTranslation()): ?> <h3>Slides</h3> <div class="formats row"> @@ -7,11 +8,11 @@ <div class="btn-group" role="group"> <div class="btn btn-primary" disabled>Slides</div> - <a href="<?=h(link_player($room, 'slides'))?>" class="btn btn-default"> + <a href="<?=h($selection->getLink())?>" class="btn btn-default"> <span class="fa fa-flag-o"></span> native </a> - <a href="<?=h(link_player($room, 'slides', true))?>" class="btn btn-default"> + <a href="<?=h($selection->getTranslatedLink())?>" class="btn btn-default"> <span class="fa fa-flag"></span> translated </a> @@ -22,38 +23,39 @@ </div> <? endif ?> - <h3>Directlinks</h3> - <div class="formats row"> - <? foreach(array_intersect($protos, array('rtmp', 'hls')) as $proto): ?> - <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> - <div class="btn-group" role="group" title="<?=h(get("FORMAT.slides"))?>"> - <div class="btn btn-primary" disabled><?=h(strtoupper($proto))?></div> - <? if($has_translation): ?> + <div class="directlinks"> - <a href="<?=h(link_stream($proto, $room, 'slides'))?>" class="btn btn-default"> - <span class="fa fa-flag-o"></span> - native - </a> - <a href="<?=h(link_stream($proto, $room, 'slides', true))?>" class="btn btn-default"> - <span class="fa fa-flag"></span> - translated - </a> + <? foreach(Stream::getSlidesProtos() as $proto => $display): ?> + <h3>Directlinks (<?=h($display)?>)</h3> + <div class="row"> + <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> + <div class="btn-group" role="group" title="<?=h(get("FORMAT.slides"))?>"> + <div class="btn btn-primary" disabled><?=h($selection->getDisplay())?></div> + <? if($room->hasTranslation()): ?> - <? else: ?> + <a href="<?=h($room->createStreamObject('slides', 'native')->getSlidesUrl($proto))?>" class="btn btn-default"> + <span class="fa fa-flag-o"></span> + native + </a> + <a href="<?=h($room->createStreamObject('slides', 'translated')->getSlidesUrl($proto))?>" class="btn btn-default"> + <span class="fa fa-flag"></span> + translated + </a> - <a href="<?=h(link_stream($proto, $room, 'slides'))?>" class="btn btn-default"> - <span class="fa fa-picture-o"></span> - slides - </a> + <? else: ?> - <? endif ?> + <a href="<?=h($room->createStreamObject('slides')->getSlidesUrl($proto))?>" class="btn btn-default"> + <span class="fa fa-picture-o"></span> + slides + </a> + <? endif ?> + </div> </div> </div> <? endforeach ?> </div> - </div>
\ No newline at end of file diff --git a/template/assemblies/switcher/video.phtml b/template/assemblies/switcher/video.phtml index 5a35657..c0429d3 100644 --- a/template/assemblies/switcher/video.phtml +++ b/template/assemblies/switcher/video.phtml @@ -2,25 +2,26 @@ <h3>Video</h3> <div class="formats row"> - <? foreach($videores as $iter): ?> + <? foreach($room->getVideoResolutions() as $res): ?> + <? $selection = $room->createSelectionObject($res) ?> <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> <div class="btn-group" role="group"> - <div class="btn btn-primary" disabled><?=h(strtoupper($iter))?></div> + <div class="btn btn-primary" disabled><?=h($selection->getDisplay())?></div> - <? if($has_translation): ?> + <? if($room->hasTranslation()): ?> - <a href="<?=h(link_player($room, $iter))?>" class="btn btn-default"> + <a href="<?=h($selection->getLink())?>" class="btn btn-default"> <span class="fa fa-flag-o"></span> native </a> - <a href="<?=h(link_player($room, $iter, true))?>" class="btn btn-default"> + <a href="<?=h($selection->getTranslatedLink())?>" class="btn btn-default"> <span class="fa fa-flag"></span> translated </a> <? else: ?> - <a href="<?=h(link_player($room, $iter))?>" class="btn btn-default"> + <a href="<?=h($selection->getLink())?>" class="btn btn-default"> <span class="fa fa-video-camera"></span> video </a> @@ -37,30 +38,28 @@ </div> <div class="directlinks"> - - <? foreach($protos as $proto): ?> - <h3>Directlinks (<?=h(strtoupper($proto))?>)</h3> + <? foreach(Stream::getVideoProtos() as $proto => $display): ?> + <h3>Directlinks (<?=h($display)?>)</h3> <div class="row"> - <? foreach($formats as $format): ?> - <? if(!startswith($proto, $format)) continue ?> - <? $res = substr($format, -2) ?> + <? foreach($room->getVideoResolutions() as $res): ?> + <? $selection = $room->createSelectionObject($res) ?> <div class="col-lg-3 col-md-4 col-lg-5 col-xs-12"> - <div class="btn-group" role="group" title="<?=h(get("FORMAT.$format"))?>"> - <div class="btn btn-primary" disabled><?=h(strtoupper($res))?></div> - <? if($has_translation): ?> + <div class="btn-group" role="group"> + <div class="btn btn-primary" disabled><?=h($selection->getDisplay())?></div> + <? if($room->hasTranslation()): ?> - <a href="<?=h(link_stream($proto, $room, $res))?>" class="btn btn-default"> + <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(link_stream($proto, $room, $res, true))?>" class="btn btn-default"> + <a href="<?=h($room->createStreamObject($res, 'translated')->getVideoUrl($proto))?>" class="btn btn-default"> <span class="fa fa-flag"></span> translated </a> <? else: ?> - <a href="<?=h(link_stream($proto, $room, $res))?>" class="btn btn-default"> + <a href="<?=h($room->createStreamObject($res)->getVideoUrl($proto))?>" class="btn btn-default"> <span class="fa fa-video-camera"></span> video </a> @@ -71,6 +70,5 @@ <? endforeach ?> </div> <? endforeach ?> - </div> </div> diff --git a/template/page.phtml b/template/page.phtml index 58f502c..cb79c16 100644 --- a/template/page.phtml +++ b/template/page.phtml @@ -27,7 +27,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <base href="<?=h($baseurl)?>" /> - <link href="<?=h($baseurl.forceslash($GLOBALS['ROUTE']))?>" rel="canonical" /> + <link href="<?=h($baseurl.forceslash($route))?>" rel="canonical" /> <link href="assets/img/apple-touch-icon/76x76.png" rel="apple-touch-icon" /> <link href="assets/img/apple-touch-icon/76x76.png" rel="apple-touch-icon" sizes="76x76" /> diff --git a/template/room.phtml b/template/room.phtml index 416629b..25a7255 100644 --- a/template/room.phtml +++ b/template/room.phtml @@ -1,17 +1,17 @@ -<div class="container <?=h($tab)?> <?=h($selection)?> <?=h($language)?>"> +<div class="container <?=h($stream->getTab())?> <?=h($stream->getSelection())?> <?=h($stream->getLanguage())?>"> <div class="row headline"> <div class="col-xs-12"> - <h1 data-room="<?=h(get("ROOMS.$room.DISPLAY"))?>"><?=h($title)?></h1> + <h1 data-room="<?=h($room->getDisplay())?>"><?=h($stream->getDisplay())?></h1> </div> </div> <ul class="nav nav-player nav-tabs nav-justified"> - <? foreach($tabs as $iter): ?> + <? foreach($room->getTabs() as $tab): ?> <li - <? if($tab == $iter):?>class="active"<? endif ?> + <? if($tab->getTab() == $stream->getTab()): ?>class="active"<? endif ?> > - <a href="<?=h(link_player($room, $iter))?>"> - <?=h(ucfirst($iter))?> + <a href="<?=h($tab->getLink())?>"> + <?=h($tab->getDisplay())?> </a> </li> <? endforeach ?> @@ -19,7 +19,7 @@ <div class="player-wrap tab-content"> <div role="tabpanel" class="tab-pane active"> - <? include("$assemblies/player/$tab.phtml") ?> + <? require("$assemblies/player/".$stream->getPlayerType().".phtml") ?> </div> </div> @@ -27,17 +27,17 @@ <li class="active"> <a href="#switcher" role="tab" data-toggle="tab">Formats</a> </li> - <? if(room_has_chat($room)): ?> + <? if($room->hasChat()): ?> <li> <a href="#chat" role="tab" data-toggle="tab">Chat</a> </li> <? endif ?> - <? if(get("ROOMS.$room.SCHEDULE") && has("SCHEDULE")): ?> + <? if($room->hasSchedule()): ?> <li> - <a href="#program" role="tab" data-toggle="tab">Program</a> + <a href="#schedule" role="tab" data-toggle="tab">Schedule</a> </li> <? endif ?> - <? if(get("ROOMS.$room.FEEDBACK") && has("FEEDBACK")): ?> + <? if($room->hasFeedback()): ?> <li> <a href="#feedback" role="tab" data-toggle="tab">Feedback</a> </li> @@ -46,21 +46,21 @@ <div class="functions-wrap tab-content"> <div role="tabpanel" class="tab-pane active" id="switcher"> - <? include("$assemblies/switcher/$tab.phtml") ?> + <? require("$assemblies/switcher/".$stream->getPlayerType().".phtml") ?> </div> - <? if(room_has_chat($room)): ?> + <? if($room->hasChat()): ?> <div role="tabpanel" class="tab-pane" id="chat"> - <? include("$assemblies/chat.phtml") ?> + <? require("$assemblies/chat.phtml") ?> </div> <? endif ?> - <? if(get("ROOMS.$room.SCHEDULE") && has("SCHEDULE")): ?> + <? if($room->hasSchedule()): ?> <div role="tabpanel" class="tab-pane" id="program"> - <? include("$assemblies/program.phtml") ?> + <? require("$assemblies/program.phtml") ?> </div> <? endif ?> - <? if(get("ROOMS.$room.FEEDBACK") && has("FEEDBACK")): ?> + <? if($room->hasFeedback()): ?> <div role="tabpanel" class="tab-pane" id="feedback"> - <? include("$assemblies/feedback.phtml") ?> + <? require("$assemblies/feedback.phtml") ?> </div> <? endif ?> </div> diff --git a/view/room.php b/view/room.php index 4484a14..505be95 100644 --- a/view/room.php +++ b/view/room.php @@ -1,121 +1,15 @@ <?php -$room = $_GET['room']; -$language = $_GET['language']; -$selection = $_GET['selection']; - -if(!has("ROOMS.$room")) - return include('pages/404.php'); - -$formats = get("ROOMS.$room.FORMATS"); -$has_translation = get("ROOMS.$room.TRANSLATION"); - -$protos = array(); -$selections = array(); -$tabs = array(); -$videores = array(); - -if(room_has_hd($room)) - $selections[] = $videores[] = 'hd'; - -if(room_has_sd($room)) - $selections[] = $videores[] = 'sd'; - -if(room_has_video($room)) - $tabs[] = 'video'; - - -if(room_has_audio($room)) - $selections[] = $tabs[] = 'audio'; - -if(room_has_music($room)) - $selections[] = $tabs[] = 'music'; - -if(room_has_slides($room)) - $selections[] = $tabs[] = 'slides'; - - -if(room_has_rtmp($room)) - $protos[] = 'rtmp'; - -if(room_has_webm($room)) - $protos[] = 'webm'; - -if(room_has_hls($room)) - $protos[] = 'hls'; - - - -// default page -if(!$selection) - $selection = $selections[0]; - -if(!in_array($selection, $selections)) - return include('pages/404.php'); - - - -switch($selection) { - case 'audio': - $tab = 'audio'; - $title = 'Audio'; - break; - - case 'music': - $tab = 'music'; - $title = 'Music'; - break; - - case 'slides': - $tab = 'slides'; - $title = 'Slides'; - $width = 1024; - $height = 576; - break; - - case 'hd': - $tab = 'video'; - $title = 'FullHD Video'; - $width = 1920; - $height = 1080; - break; - - case 'sd': - $tab = 'video'; - $title = 'SD Video'; - $width = 1024; - $height = 576; - break; -} - -if($language == 'translated') -{ - if(!$has_translation) - return include('pages/404.php'); - - $title = 'Translated '.$title; -} +$room = new Room($_GET['room']); +$stream = $room->selectStream( + $_GET['selection'], $_GET['language']); echo $tpl->render(array( 'page' => 'room', - 'title' => get("ROOMS.$room.DISPLAY").' – '.$title, + 'title' => $stream->getDisplay(), 'room' => $room, + 'stream' => $stream, - 'program' => program(), - - 'tab' => $tab, - 'tabs' => $tabs, - - 'width' => @$width, - 'height' => @$height, - 'language' => $language, - 'translated' => ($language == 'translated'), - 'selection' => $selection, - 'hlsformat' => ($selection == 'hd' ? 'auto' : $selection), - - 'has_translation' => $has_translation, - 'formats' => $formats, - 'protos' => $protos, - 'videores' => $videores, + 'schedule' => new Schedule(), )); |