mirror of
https://github.com/moodle/moodle.git
synced 2025-08-06 01:16:44 +02:00
MDL-38158 core_media: Convert media players to new plugin type
AMOS BEGIN MOV [siteyoutube,core_media],[pluginname,media_youtube] MOV [siteyoutube_desc,core_media],[pluginname_help,media_youtube] MOV [sitevimeo,core_media],[pluginname,media_vimeo] MOV [sitevimeo_desc,core_media],[pluginname_help,media_vimeo] MOV [html5audio,core_media],[pluginname,media_html5audio] MOV [html5audio_desc,core_media],[pluginname_help,media_html5audio] MOV [html5video,core_media],[pluginname,media_html5video] MOV [html5video_desc,core_media],[pluginname_help,media_html5video] MOV [flashanimation,core_media],[pluginname,media_swf] MOV [flashanimation_desc,core_media],[pluginname_help,media_swf] AMOS END
This commit is contained in:
parent
3c73b26c4b
commit
fab11235d8
76 changed files with 3524 additions and 4406 deletions
219
lib/adminlib.php
219
lib/adminlib.php
|
@ -7158,6 +7158,225 @@ class admin_page_managefilters extends admin_externalpage {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special class for media player plugins management.
|
||||
*
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_setting_managemediaplayers extends admin_setting {
|
||||
/**
|
||||
* Calls parent::__construct with specific arguments
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->nosave = true;
|
||||
parent::__construct('managemediaplayers', get_string('managemediaplayers', 'media'), '', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_setting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_defaultsetting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns '', does not write anything
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return string Always returns ''
|
||||
*/
|
||||
public function write_setting($data) {
|
||||
// Do not write any setting.
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if $query is one of the available enrol plugins
|
||||
*
|
||||
* @param string $query The string to search for
|
||||
* @return bool Returns true if found, false if not
|
||||
*/
|
||||
public function is_related($query) {
|
||||
if (parent::is_related($query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$query = core_text::strtolower($query);
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
foreach ($plugins as $name => $plugin) {
|
||||
$localised = $plugin->displayname;
|
||||
if (strpos(core_text::strtolower($name), $query) !== false) {
|
||||
return true;
|
||||
}
|
||||
if (strpos(core_text::strtolower($localised), $query) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort plugins so enabled plugins are displayed first and all others are displayed in the end sorted by rank.
|
||||
* @return \core\plugininfo\media[]
|
||||
*/
|
||||
protected function get_sorted_plugins() {
|
||||
$pluginmanager = core_plugin_manager::instance();
|
||||
|
||||
$plugins = $pluginmanager->get_plugins_of_type('media');
|
||||
$enabledplugins = $pluginmanager->get_enabled_plugins('media');
|
||||
|
||||
// Sort plugins so enabled plugins are displayed first and all others are displayed in the end sorted by rank.
|
||||
\core_collator::asort_objects_by_method($plugins, 'get_rank', \core_collator::SORT_NUMERIC);
|
||||
|
||||
$order = array_values($enabledplugins);
|
||||
$order = array_merge($order, array_diff(array_reverse(array_keys($plugins)), $order));
|
||||
|
||||
$sortedplugins = array();
|
||||
foreach ($order as $name) {
|
||||
$sortedplugins[$name] = $plugins[$name];
|
||||
}
|
||||
|
||||
return $sortedplugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XHTML to display the control
|
||||
*
|
||||
* @param string $data Unused
|
||||
* @param string $query
|
||||
* @return string
|
||||
*/
|
||||
public function output_html($data, $query='') {
|
||||
global $CFG, $OUTPUT, $DB, $PAGE;
|
||||
|
||||
// Display strings.
|
||||
$strup = get_string('up');
|
||||
$strdown = get_string('down');
|
||||
$strsettings = get_string('settings');
|
||||
$strenable = get_string('enable');
|
||||
$strdisable = get_string('disable');
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
$strversion = get_string('version');
|
||||
$strname = get_string('name');
|
||||
$strsupports = get_string('supports', 'core_media');
|
||||
|
||||
$pluginmanager = core_plugin_manager::instance();
|
||||
|
||||
$plugins = $this->get_sorted_plugins();
|
||||
$enabledplugins = $pluginmanager->get_enabled_plugins('media');
|
||||
|
||||
$return = $OUTPUT->box_start('generalbox mediaplayersui');
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array($strname, $strsupports, $strversion,
|
||||
$strenable, $strup.'/'.$strdown, $strsettings, $struninstall);
|
||||
$table->colclasses = array('leftalign', 'leftalign', 'centeralign',
|
||||
'centeralign', 'centeralign', 'centeralign', 'centeralign');
|
||||
$table->id = 'mediaplayerplugins';
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->data = array();
|
||||
|
||||
// Iterate through media plugins and add to the display table.
|
||||
$updowncount = 1;
|
||||
$url = new moodle_url('/admin/media.php', array('sesskey' => sesskey()));
|
||||
$printed = array();
|
||||
$spacer = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'iconsmall'));
|
||||
|
||||
$usedextensions = [];
|
||||
foreach ($plugins as $name => $plugin) {
|
||||
$url->param('media', $name);
|
||||
$plugininfo = $pluginmanager->get_plugin_info('media_'.$name);
|
||||
$version = $plugininfo->versiondb;
|
||||
$supports = $plugininfo->supports($usedextensions);
|
||||
|
||||
// Hide/show links.
|
||||
$class = '';
|
||||
if (!$plugininfo->is_installed_and_upgraded()) {
|
||||
$hideshow = '';
|
||||
$enabled = false;
|
||||
$displayname = '<span class="notifyproblem">'.$name.'</span>';
|
||||
} else {
|
||||
$enabled = $plugininfo->is_enabled();
|
||||
if ($enabled) {
|
||||
$hideshow = html_writer::link(new moodle_url($url, array('action' => 'disable')),
|
||||
$OUTPUT->pix_icon('t/hide', $strdisable, 'moodle', array('class' => 'iconsmall')));
|
||||
} else {
|
||||
$hideshow = html_writer::link(new moodle_url($url, array('action' => 'enable')),
|
||||
$OUTPUT->pix_icon('t/show', $strenable, 'moodle', array('class' => 'iconsmall')));
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
$displayname = $plugin->displayname;
|
||||
if (get_string_manager()->string_exists('pluginname_help', 'media_' . $name)) {
|
||||
$displayname .= ' ' . $OUTPUT->help_icon('pluginname', 'media_' . $name);
|
||||
}
|
||||
}
|
||||
if ($PAGE->theme->resolve_image_location('icon', 'media_' . $name, false)) {
|
||||
$icon = $OUTPUT->pix_icon('icon', '', 'media_' . $name, array('class' => 'icon pluginicon'));
|
||||
} else {
|
||||
$icon = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'icon pluginicon noicon'));
|
||||
}
|
||||
|
||||
// Up/down link (only if enrol is enabled).
|
||||
$updown = '';
|
||||
if ($enabled) {
|
||||
if ($updowncount > 1) {
|
||||
$updown = html_writer::link(new moodle_url($url, array('action' => 'up')),
|
||||
$OUTPUT->pix_icon('t/up', $strup, 'moodle', array('class' => 'iconsmall')));
|
||||
} else {
|
||||
$updown = $spacer;
|
||||
}
|
||||
if ($updowncount < count($enabledplugins)) {
|
||||
$updown .= html_writer::link(new moodle_url($url, array('action' => 'down')),
|
||||
$OUTPUT->pix_icon('t/down', $strdown, 'moodle', array('class' => 'iconsmall')));
|
||||
} else {
|
||||
$updown .= $spacer;
|
||||
}
|
||||
++$updowncount;
|
||||
}
|
||||
|
||||
$uninstall = '';
|
||||
$status = $plugininfo->get_status();
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
$uninstall = get_string('status_missing', 'core_plugin') . '<br/>';
|
||||
}
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_NEW) {
|
||||
$uninstall = get_string('status_new', 'core_plugin');
|
||||
} else if ($uninstallurl = $pluginmanager->get_uninstall_url('media_'.$name, 'manage')) {
|
||||
$uninstall .= html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
|
||||
$settings = '';
|
||||
if ($plugininfo->get_settings_url()) {
|
||||
$settings = html_writer::link($plugininfo->get_settings_url(), $strsettings);
|
||||
}
|
||||
|
||||
// Add a row to the table.
|
||||
$row = new html_table_row(array($icon.$displayname, $supports, $version, $hideshow, $updown, $settings, $uninstall));
|
||||
if ($class) {
|
||||
$row->attributes['class'] = $class;
|
||||
}
|
||||
$table->data[] = $row;
|
||||
|
||||
$printed[$name] = true;
|
||||
}
|
||||
|
||||
$return .= html_writer::table($table);
|
||||
$return .= $OUTPUT->box_end();
|
||||
return highlight($query, $return);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise admin page - this function does require login and permission
|
||||
|
|
|
@ -454,7 +454,7 @@ $cache = '.var_export($cache, true).';
|
|||
'langconfig' => null,
|
||||
'license' => null,
|
||||
'mathslib' => null,
|
||||
'media' => null,
|
||||
'media' => $CFG->dirroot.'/media',
|
||||
'message' => $CFG->dirroot.'/message',
|
||||
'mimetypes' => null,
|
||||
'mnet' => $CFG->dirroot.'/mnet',
|
||||
|
@ -502,6 +502,7 @@ $cache = '.var_export($cache, true).';
|
|||
'enrol' => $CFG->dirroot.'/enrol',
|
||||
'message' => $CFG->dirroot.'/message/output',
|
||||
'block' => $CFG->dirroot.'/blocks',
|
||||
'media' => $CFG->dirroot.'/media/player',
|
||||
'filter' => $CFG->dirroot.'/filter',
|
||||
'editor' => $CFG->dirroot.'/lib/editor',
|
||||
'format' => $CFG->dirroot.'/course/format',
|
||||
|
|
|
@ -140,7 +140,7 @@ abstract class core_filetypes {
|
|||
'mht' => array('type' => 'message/rfc822', 'icon' => 'archive'),
|
||||
'mhtml' => array('type' => 'message/rfc822', 'icon' => 'archive'),
|
||||
'mov' => array('type' => 'video/quicktime', 'icon' => 'quicktime',
|
||||
'groups' => array('video', 'web_video'), 'string' => 'video'),
|
||||
'groups' => array('video', 'web_video', 'html_video'), 'string' => 'video'),
|
||||
'movie' => array('type' => 'video/x-sgi-movie', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'),
|
||||
'mw' => array('type' => 'application/maple', 'icon' => 'math'),
|
||||
'mws' => array('type' => 'application/maple', 'icon' => 'math'),
|
||||
|
@ -260,7 +260,7 @@ abstract class core_filetypes {
|
|||
'tsv' => array('type' => 'text/tab-separated-values', 'icon' => 'text'),
|
||||
'txt' => array('type' => 'text/plain', 'icon' => 'text', 'defaulticon' => true),
|
||||
'vtt' => array('type' => 'text/vtt', 'icon' => 'text', 'groups' => array('html_track')),
|
||||
'wav' => array('type' => 'audio/wav', 'icon' => 'wav', 'groups' => array('audio'. 'html_audio', 'web_audio'),
|
||||
'wav' => array('type' => 'audio/wav', 'icon' => 'wav', 'groups' => array('audio', 'html_audio', 'web_audio'),
|
||||
'string' => 'audio'),
|
||||
'webm' => array('type' => 'video/webm', 'icon' => 'video', 'groups' => array('html_video', 'video', 'web_video'),
|
||||
'string' => 'video'),
|
||||
|
|
|
@ -1815,6 +1815,10 @@ class core_plugin_manager {
|
|||
'memberships', 'profile', 'toolproxy', 'toolsettings'
|
||||
),
|
||||
|
||||
'media' => array(
|
||||
'html5audio', 'html5video', 'swf', 'videojs', 'vimeo', 'youtube'
|
||||
),
|
||||
|
||||
'message' => array(
|
||||
'airnotifier', 'email', 'jabber', 'popup'
|
||||
),
|
||||
|
|
188
lib/classes/plugininfo/media.php
Normal file
188
lib/classes/plugininfo/media.php
Normal file
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Defines classes used for plugin info.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for media plugins
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media extends base {
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name for the settings section.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_settings_section_name() {
|
||||
return 'mediasetting' . $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the global settings for a particular availability plugin (if there are any)
|
||||
*
|
||||
* @param \part_of_admin_tree $adminroot
|
||||
* @param string $parentnodename
|
||||
* @param bool $hassiteconfig
|
||||
*/
|
||||
public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
|
||||
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them.
|
||||
$ADMIN = $adminroot; // May be used in settings.php.
|
||||
$plugininfo = $this; // Also can be used inside settings.php
|
||||
$availability = $this; // Also to be used inside settings.php.
|
||||
|
||||
if (!$this->is_installed_and_upgraded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$hassiteconfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
$section = $this->get_settings_section_name();
|
||||
|
||||
$settings = null;
|
||||
if (file_exists($this->full_path('settings.php'))) {
|
||||
$settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false);
|
||||
include($this->full_path('settings.php')); // This may also set $settings to null.
|
||||
}
|
||||
if ($settings) {
|
||||
$ADMIN->add($parentnodename, $settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return URL used for management of plugins of this type.
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public static function get_manage_url() {
|
||||
return new \moodle_url('/admin/settings.php', array('section' => 'managemediaplayers'));
|
||||
}
|
||||
|
||||
public static function get_enabled_plugins() {
|
||||
global $CFG;
|
||||
|
||||
$order = (!empty($CFG->media_plugins_sortorder)) ? explode(',', $CFG->media_plugins_sortorder) : [];
|
||||
if ($order) {
|
||||
$plugins = \core_plugin_manager::instance()->get_installed_plugins('media');
|
||||
$order = array_intersect($order, array_keys($plugins));
|
||||
}
|
||||
return array_combine($order, $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current plugin as enabled or disabled
|
||||
* When enabling tries to guess the sortorder based on default rank returned by the plugin.
|
||||
* @param bool $newstate
|
||||
*/
|
||||
public function set_enabled($newstate = true) {
|
||||
$enabled = self::get_enabled_plugins();
|
||||
if (array_key_exists($this->name, $enabled) == $newstate) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
if ($newstate) {
|
||||
// Enable media plugin.
|
||||
$plugins = \core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
if (!array_key_exists($this->name, $plugins)) {
|
||||
// Can not be enabled.
|
||||
return;
|
||||
}
|
||||
$rank = $this->get_rank();
|
||||
$position = 0;
|
||||
// Insert before the first enabled plugin which default rank is smaller than the default rank of this one.
|
||||
foreach ($enabled as $playername) {
|
||||
if (($player = $plugins[$playername]) && ($rank > $player->get_rank())) {
|
||||
break;
|
||||
}
|
||||
$position++;
|
||||
}
|
||||
array_splice($enabled, $position, 0, [$this->name]);
|
||||
self::set_enabled_plugins($enabled);
|
||||
} else {
|
||||
// Disable media plugin.
|
||||
unset($enabled[$this->name]);
|
||||
self::set_enabled_plugins($enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of enabled media players in the specified sort order
|
||||
* To be used when changing settings or in unit tests
|
||||
* @param string|array $list list of plugin names without frankenstyle prefix - comma-separated string or an array
|
||||
*/
|
||||
public static function set_enabled_plugins($list) {
|
||||
if (empty($list)) {
|
||||
$list = [];
|
||||
} else if (!is_array($list)) {
|
||||
$list = explode(',', $list);
|
||||
}
|
||||
if ($list) {
|
||||
$plugins = \core_plugin_manager::instance()->get_installed_plugins('media');
|
||||
$list = array_intersect($list, array_keys($plugins));
|
||||
}
|
||||
set_config('media_plugins_sortorder', join(',', $list));
|
||||
\core_plugin_manager::reset_caches();
|
||||
\core_media_manager::reset_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default rank of this plugin for default sort order
|
||||
* @return int
|
||||
*/
|
||||
public function get_rank() {
|
||||
$classname = '\media_'.$this->name.'_plugin';
|
||||
if (class_exists($classname)) {
|
||||
$object = new $classname();
|
||||
return $object->get_rank();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-readable string of supported file/link types for the "Manage media players" page
|
||||
* @param array $extensions
|
||||
* @return string
|
||||
*/
|
||||
public function supports(&$extensions) {
|
||||
$classname = '\media_'.$this->name.'_plugin';
|
||||
if (class_exists($classname)) {
|
||||
$object = new $classname();
|
||||
$result = $object->supports($extensions);
|
||||
foreach ($object->get_supported_extensions() as $ext) {
|
||||
$extensions[$ext] = $ext;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
|
@ -316,6 +316,10 @@ class core_useragent {
|
|||
// Internet Explorer.
|
||||
return self::check_ie_version($version);
|
||||
|
||||
case 'Edge':
|
||||
// Microsoft Edge.
|
||||
return self::check_edge_version($version);
|
||||
|
||||
case 'Firefox':
|
||||
// Mozilla Firefox browsers.
|
||||
return self::check_firefox_version($version);
|
||||
|
@ -1054,4 +1058,85 @@ class core_useragent {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current browser supports files with give extension as <video> or <audio> source
|
||||
*
|
||||
* Note, the check here is not 100% accurate!
|
||||
*
|
||||
* First, we do not know which codec is used in .mp4 or .webm files. Not all browsers support
|
||||
* all codecs.
|
||||
*
|
||||
* Also we assume that users of Firefox/Chrome/Safari do not use the ancient versions of browsers.
|
||||
*
|
||||
* We check the exact version for IE/Edge though. We know that there are still users of very old
|
||||
* versions that are afraid to upgrade or have slow IT department.
|
||||
*
|
||||
* Resources:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
|
||||
* https://en.wikipedia.org/wiki/HTML5_video
|
||||
* https://en.wikipedia.org/wiki/HTML5_Audio
|
||||
*
|
||||
* @param string $extension extension without leading .
|
||||
* @return bool
|
||||
*/
|
||||
public static function supports_html5($extension) {
|
||||
$extension = strtolower($extension);
|
||||
|
||||
$supportedvideo = array('m4v', 'webm', 'ogv', 'mp4');
|
||||
$supportedaudio = array('ogg', 'oga', 'aac', 'm4a', 'mp3', 'wav', 'mov');
|
||||
// TODO MDL-56549 Flac will be supported in Firefox 51 in January 2017.
|
||||
|
||||
// Basic extension support.
|
||||
if (!in_array($extension, $supportedvideo) && !in_array($extension, $supportedaudio)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MS IE support - version 9.0 or later.
|
||||
if (self::is_ie() && !self::check_ie_version('9.0')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MS Edge support - version 12.0 for desktop and 13.0 for mobile.
|
||||
if (self::is_edge()) {
|
||||
if (!self::check_edge_version('12.0')) {
|
||||
return false;
|
||||
}
|
||||
if (self::instance()->is_useragent_mobile() && !self::check_edge_version('13.0')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Different exceptions.
|
||||
|
||||
// Webm is not supported in IE, Edge and in Safari.
|
||||
if ($extension === 'webm' &&
|
||||
(self::is_ie() || self::is_edge() || self::is_safari() || self::is_safari_ios())) {
|
||||
return false;
|
||||
}
|
||||
// Ogg is not supported in IE, Edge and Safari.
|
||||
$isogg = in_array($extension, ['ogg', 'oga', 'ogv']);
|
||||
if ($isogg && (self::is_ie() || self::is_edge() || self::is_safari() || self::is_safari_ios())) {
|
||||
return false;
|
||||
}
|
||||
// Wave is not supported in IE.
|
||||
if ($extension === 'wav' && self::is_ie()) {
|
||||
return false;
|
||||
}
|
||||
// Aac is not supported in IE below 11.0.
|
||||
if ($extension === 'aac' && (self::is_ie() && !self::check_ie_version('11.0'))) {
|
||||
return false;
|
||||
}
|
||||
// Mpeg is not supported in IE below 10.0.
|
||||
$ismpeg = in_array($extension, ['m4a', 'mp3', 'm4v', 'mp4']);
|
||||
if ($ismpeg && (self::is_ie() && !self::check_ie_version('10.0'))) {
|
||||
return false;
|
||||
}
|
||||
// Mov is not supported in IE.
|
||||
if ($extension === 'mov' && self::is_ie()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,7 @@ function xmldb_main_install() {
|
|||
'filterall' => 0, // setting page, so have to be initialised here.
|
||||
'texteditors' => 'atto,tinymce,textarea',
|
||||
'antiviruses' => '',
|
||||
'media_plugins_sortorder' => 'videojs,youtube,swf',
|
||||
'upgrade_minmaxgradestepignored' => 1, // New installs should not run this upgrade step.
|
||||
'upgrade_extracreditweightsstepignored' => 1, // New installs should not run this upgrade step.
|
||||
'upgrade_calculatedgradeitemsignored' => 1, // New installs should not run this upgrade step.
|
||||
|
|
|
@ -2322,5 +2322,75 @@ function xmldb_main_upgrade($oldversion) {
|
|||
upgrade_main_savepoint(true, 2016110300.00);
|
||||
}
|
||||
|
||||
if ($oldversion < 2016110400.01) {
|
||||
|
||||
$oldplayers = [
|
||||
'vimeo' => null,
|
||||
'mp3' => ['.mp3'],
|
||||
'html5video' => ['.mov', '.mp4', '.m4v', '.mpeg', '.mpe', '.mpg', '.ogv', '.webm'],
|
||||
'flv' => ['.flv', '.f4v'],
|
||||
'html5audio' => ['.aac', '.flac', '.mp3', '.m4a', '.oga', '.ogg', '.wav'],
|
||||
'youtube' => null,
|
||||
'swf' => null,
|
||||
];
|
||||
|
||||
// Convert hardcoded media players to the settings of the new media player plugin type.
|
||||
if (get_config('core', 'media_plugins_sortorder') === false) {
|
||||
$enabledplugins = [];
|
||||
$videoextensions = [];
|
||||
$audioextensions = [];
|
||||
foreach ($oldplayers as $oldplayer => $extensions) {
|
||||
$settingname = 'core_media_enable_'.$oldplayer;
|
||||
if (!empty($CFG->$settingname)) {
|
||||
if ($extensions) {
|
||||
// VideoJS will be used for all media files players that were used previously.
|
||||
$enabledplugins['videojs'] = 'videojs';
|
||||
if ($oldplayer === 'mp3' || $oldplayer === 'html5audio') {
|
||||
$audioextensions += array_combine($extensions, $extensions);
|
||||
} else {
|
||||
$videoextensions += array_combine($extensions, $extensions);
|
||||
}
|
||||
} else {
|
||||
// Enable youtube, vimeo and swf.
|
||||
$enabledplugins[$oldplayer] = $oldplayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_config('media_plugins_sortorder', join(',', $enabledplugins));
|
||||
|
||||
// Configure VideoJS to match the existing players set up.
|
||||
if ($enabledplugins['videojs']) {
|
||||
$enabledplugins[] = 'videojs';
|
||||
set_config('audioextensions', join(',', $audioextensions), 'media_videojs');
|
||||
set_config('videoextensions', join(',', $videoextensions), 'media_videojs');
|
||||
$useflash = !empty($CFG->core_media_enable_flv) || !empty($CFG->core_media_enable_mp3);
|
||||
set_config('useflash', $useflash, 'media_videojs');
|
||||
if (empty($CFG->core_media_enable_youtube)) {
|
||||
// Normally YouTube is enabled in videojs, but if youtube converter was disabled before upgrade
|
||||
// disable it in videojs as well.
|
||||
set_config('youtube', false, 'media_videojs');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unset old settings.
|
||||
foreach ($oldplayers as $oldplayer => $extensions) {
|
||||
unset_config('core_media_enable_' . $oldplayer);
|
||||
}
|
||||
|
||||
// Preset defaults if CORE_MEDIA_VIDEO_WIDTH and CORE_MEDIA_VIDEO_HEIGHT are specified in config.php .
|
||||
// After this upgrade step these constants will not be used any more.
|
||||
if (defined('CORE_MEDIA_VIDEO_WIDTH')) {
|
||||
set_config('media_default_width', CORE_MEDIA_VIDEO_WIDTH);
|
||||
}
|
||||
if (defined('CORE_MEDIA_VIDEO_HEIGHT')) {
|
||||
set_config('media_default_height', CORE_MEDIA_VIDEO_HEIGHT);
|
||||
}
|
||||
|
||||
// Savepoint reached.
|
||||
upgrade_main_savepoint(true, 2016110400.01);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ $PAGE->add_body_class('core_media_preview');
|
|||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$mediarenderer = $PAGE->get_renderer('core', 'media');
|
||||
$mediarenderer = core_media_manager::instance();
|
||||
|
||||
if (isloggedin() and !isguestuser() and $mediarenderer->can_embed_url($url)) {
|
||||
require_sesskey();
|
||||
|
|
|
@ -1,721 +0,0 @@
|
|||
The Flowplayer Free version is released under the
|
||||
GNU GENERAL PUBLIC LICENSE Version 3 (GPL).
|
||||
|
||||
The GPL requires that you not remove the Flowplayer copyright notices
|
||||
from the user interface. See section 5.d below.
|
||||
|
||||
Commercial licenses are available. The commercial player version
|
||||
does not require any Flowplayer notices or texts and also provides
|
||||
some additional features.
|
||||
|
||||
========================================================================
|
||||
|
||||
ADDITIONAL TERM per GPL Section 7
|
||||
If you convey this program (or any modifications of it) and assume
|
||||
contractual liability for the program to recipients of it, you agree
|
||||
to indemnify Flowplayer, Ltd. for any liability that those contractual
|
||||
assumptions impose on Flowplayer, Ltd.
|
||||
|
||||
Except as expressly provided herein, no trademark rights are granted in
|
||||
any trademarks of Flowplayer, Ltd. Licensees are granted a limited,
|
||||
non-exclusive right to use the mark Flowplayer and the Flowplayer logos
|
||||
in connection with unmodified copies of the Program and the copyright
|
||||
notices required by section 5.d of the GPL license. For the purposes
|
||||
of this limited trademark license grant, customizing the Flowplayer
|
||||
by skinning, scripting, or including PlugIns provided by Flowplayer, Ltd.
|
||||
is not considered modifying the Program.
|
||||
|
||||
Licensees that do modify the Program, taking advantage of the open-source
|
||||
license, may not use the Flowplayer mark or Flowplayer logos and must
|
||||
change the fullscreen notice (and the non-fullscreen notice, if that
|
||||
option is enabled), the copyright notice in the dialog box, and the
|
||||
notice on the Canvas as follows:
|
||||
|
||||
the full screen (and non-fullscreen equivalent, if activated) notice
|
||||
should read: "Based on Flowplayer source code"; in the context menu
|
||||
(right-click menu), the link to "About Flowplayer free version #.#.#"
|
||||
can remain. The copyright notice can remain, but must be supplemented with
|
||||
an additional notice, stating that the licensee modified the Flowplayer.
|
||||
A suitable notice might read "Flowplayer Source code modified by ModOrg 2009";
|
||||
for the canvas, the notice should read "Based on Flowplayer source code".
|
||||
In addition, licensees that modify the Program must give the modified
|
||||
Program a new name that is not confusingly similar to Flowplayer and
|
||||
may not distribute it under the name Flowplayer.
|
||||
|
||||
========================================================================
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -1,504 +0,0 @@
|
|||
Version history:
|
||||
|
||||
3.2.17
|
||||
------
|
||||
- #75 set the child display list different when a gradient is set.
|
||||
- The clip property 'bufferLength' now accepts decimal values, for example bufferLength: 0.2
|
||||
- #121 XSS fix: Only load plugins and external config from the same domain as the player swf is loaded from
|
||||
- Made it possible to tab out of the player and into the HTML page using the keyboard alone.
|
||||
- Change links in the context menu and in the logos to point to http://flash.flowplayer.org
|
||||
- Pausing a live stream now leaves the video frame visible #81
|
||||
- Audio plugin is not loaded nor used when the the provider is set excplicitly in the clip to a non-audio value, for
|
||||
example to 'http'
|
||||
- Allow playing another instream clip while already playing one. Issue #131
|
||||
- Fixed memory leaks related to repeatedly starting playback with the play() API method. #163
|
||||
|
||||
3.2.16
|
||||
------
|
||||
- new clip event onMetadataChange, dispatched for example when switching bitrate
|
||||
|
||||
Fixes:
|
||||
|
||||
- Shows logo in accelerated mode #20
|
||||
- mid-rolls freeze if multiple providers are used #42
|
||||
- onFire fired twice on replay #52
|
||||
- rtmp + hw accel + instream clips lose video, or aspect ratio #44
|
||||
- URL name parts containing semi-colons (;) should pass validation through linkUrl usage #53
|
||||
- cuepoints fired multiple times with the bitrateselect plugin #50
|
||||
- fix for dispatching onBegin in certain situations
|
||||
- if onStart has been dispatched already prevent dispatching many onBegin events
|
||||
|
||||
|
||||
3.2.15
|
||||
------
|
||||
- #15 fixes for #627, handle the display init on startup.
|
||||
- #615 dispatch begin if in paused mode too early.
|
||||
- #629 if start has been dispatched already prevent dispatching many begin events.
|
||||
- #20 for the free player swap the logo with the stage video mask to display underneath not on top.
|
||||
- #42 pass in stream clips through and close the stream before returning to the parent clip.
|
||||
- #52 when replaying flag start has dispatched on the current clip.
|
||||
- #44 fixes for #627 check if the stagevideo dimensions and positioning has changed to update the stage video mask with.
|
||||
- unbinding and binding stage video events caused issues with instream playlists therefore has to be kept binded.
|
||||
- unbinded stage video events during seeking to prevent the mask repositioning.
|
||||
- #53 update url filter to accomodate for pretty urls with semi colons.
|
||||
- #50 if we have metadata already set it is being updated during seeks and switching, dispatch metadata change events instead.
|
||||
|
||||
3.2.14
|
||||
------
|
||||
- #614 when the clip ends if the next clip in the provider has a different provider close the provider stream.
|
||||
- #627 only detach / attach the display on start events which causes issues in buffering events after a seek in stagevideo.
|
||||
- #627 re-enable stagevideo state change listeners if stagevideo is available or detach the fullscreen events on first call.
|
||||
- #9 when replaying from stopping, connection does not receive callbacks anymore.
|
||||
|
||||
|
||||
|
||||
|
||||
3.2.13
|
||||
------
|
||||
- Updated to automatically load the latest controls and audio plugins
|
||||
- #612 add some logging for the stagevideo render state to determine what mode the hardware acceleration is in for various systems.
|
||||
- #628 opera browsers do not return filesize correctly for latest flash players so require to use load completion instead which may help with gzipped files also.
|
||||
|
||||
3.2.12
|
||||
------
|
||||
- new flowplayer.js version 3.2.11,
|
||||
fixes removing the player in fullscreen mode leaves Android locked in landscape orientation (#511)
|
||||
- #586 add a bitrate label with a new namespace attribute fp:bitratelabel.
|
||||
- #583 fixes for handling the fullscreenOnly property better
|
||||
- #494 with relative filenames with a root path strip the baseurl of paths first.
|
||||
|
||||
3.2.11
|
||||
------
|
||||
- new flowplayer.js, now requires Flash 10.1 as the minimum flash version
|
||||
- #526 allow click through event for flash installation message when using div containers.
|
||||
- #508 disabling the stagevideo screen mask, canvas is visible without it, this was causing issues with the display list.
|
||||
- #443 adding accessibility option to the playbuttonoverlay.
|
||||
|
||||
|
||||
3.2.10
|
||||
------
|
||||
- Fixed #514, scrubbing was broken
|
||||
- new flowplayer.js version 3.2.9, fixes #510
|
||||
|
||||
3.2.9
|
||||
-----
|
||||
- Fixed #490, controlbar background, buffer bar and progress bar colors were all reset to white
|
||||
- #503 Update viewport when stage is added to obtain the coordnates correctly. Update viewport when in and out of fullscreen.
|
||||
- #508 stage video mask was being added to the top layer and hiding all children.
|
||||
|
||||
3.2.8
|
||||
-----
|
||||
- Added new property clip.backBufferLength, to be used with FMS 3.5
|
||||
- Adds support for StageVideo. To enable it set clip.accelerated to true.
|
||||
- Tries to reload two times if the stream is not initially found. Also does 3 connection attempts if the connection fails with RTMP.
|
||||
- Support for FMS slow motion
|
||||
- Support for thumbnails in RSS files
|
||||
- Added onPlayStatus clip event handler on NetStreamClient.
|
||||
- Added new clip events for stream switching onSwitchFailed and onSwitchComplete
|
||||
- made it possible to replay a clip using play(<current_clip's_index>)
|
||||
|
||||
Fixes:
|
||||
- fixed to dispatch onStart also when replaying the previous clip, now the JS controlbar again works when replaying
|
||||
- cuepoints were fired multiple times when there is a playlist with several clips. Issue #150.
|
||||
- fixed XML parsing error when metadata's keys contains dashes
|
||||
- backgroundImage css property can now be set to "none" to be removed
|
||||
- fixed the facts that clips in a playlist were cut off by a fraction in the end
|
||||
- fullScreenOnly now works in conjunction with displayTime
|
||||
- JS plugins now handles grouped syntax like flowplayer("a.player" /*...*/ )
|
||||
- JS function setClip can now be used to add listeners on the new Clip
|
||||
- different players with the same configuration stored in a variable can now use JS plugins
|
||||
- using linkUrl now works when calling JS function setClip
|
||||
- zIndex for plugins works fine now, issue #302
|
||||
- onLastSecond was fired twice, issue #300
|
||||
- fixed license key verification on subdomains, issue #318
|
||||
- fixed XSS vulnerability with linkUrls. Thank you Szymon Gruszecki for discovering and reporting this to us. Issue #329.
|
||||
- fixed switch stream api support in paused state. #279.
|
||||
- added switching state properties. #339
|
||||
- fixed the stopBuffering() API method to close the NetConnection and to clear the screen
|
||||
- Issue #355 setup targeting for Flash 10.0 and 10.1 to provide support for Flash 10.0 without Stagevideo requirements.
|
||||
- fixed #364, NetConnection unnecessary closed/reconnected when the netConnection does not change from clip to clip
|
||||
- xss fix for flashembed #357
|
||||
- Issue #384 added links support in context menus with configuration { url: "domain.com", target: "_blank"} which will work in embedded players.
|
||||
- #378, javascript method loadPluginWithConfig is unavailable and non existant. Documentation updated required to remove this and updates for loadPlugin like so
|
||||
this.loadPlugin("content","../flowplayer.content.swf", { html: "test", top: 30 }); or
|
||||
this.loadPlugin("content","../flowplayer.content.swf", { html: "test" }, function() {
|
||||
this.css({ top: 30 });
|
||||
});
|
||||
- #191 send the resume event, and no stop event first before reconnecting due to a connection timeout so the player comes out of a paused state correctly.
|
||||
- #363 pause stream after metadata not beforehand or else no metadata is sent for rtmp clips .
|
||||
- #363 silent seek and force to seek to a keyframe or else video frame will not display initially when paused.
|
||||
- #375 clearing the event listeners when adding new video displays prevents new events being added when the playlist is replaced.
|
||||
- #391 add message argument to connection failure callback required by some connection providers.
|
||||
- #363 add overridable pause to frame for different seek functionality between http and rtmp.
|
||||
- #392 possible fix for extensions with no filetypes like rtmp flv clips, require positive index check.
|
||||
- #395 apply buffer animation status to VOD streams only.
|
||||
- #375 possible fix when replacing the playlist in onBeforeFinish, move replay button to onFinish.
|
||||
- #390 correct seek back to a valid time on invalid seeking while seeking in the buffer.
|
||||
- #404 implement netstreamplayoptions for http streams, resets the stream or start loading a new stream.
|
||||
- fixed an issue in parsing JSON config that contains several comments separated by whitespace
|
||||
- new clip property 'stopLiveOnPause'
|
||||
- #415 regression issue with #395, stop the buffering animation correctly.
|
||||
- #414 problem appears again for very short clips with invalid seek times, make it step back 1 second from the invalid seek time to seek the buffer correctly.
|
||||
- #416 enable seekableOnBegin to enable the scrubbar correctly when autobuffering.
|
||||
- #423 add the . to clip type extension checks or else files with known extension postfixes within them will be chosen instead.
|
||||
- #426 when a plugin width is set to a percentage, x/y is required to be floored or else it will affect the animation engine. specifically for the autohide function.
|
||||
- #430 adding event listeners for netconnection to obtain certain events.
|
||||
- #430 clear buffering status on connection failure.
|
||||
- #430 clear buffering status on stream failure.
|
||||
- #412 check for empty baseurl or else player url is appended and affects the url parsing.
|
||||
- #439 check for all rtmp streaming protocols when checking for rtmp urls.
|
||||
- #442 fix for code error in the javascript api.
|
||||
- #461 when we have a clip base url set, we need the complete clip url sent to play2 for http streams.
|
||||
- #470 check for a playlist when replacing the playlist with an rss feed.
|
||||
- #494 regression issued caused by #412, enable base url correctly.
|
||||
- #30 regression caused by character replacements, removing for now and let end user deal with them.
|
||||
|
||||
3.2.7
|
||||
-----
|
||||
- Loads the new controlbar plugin version 3.2.5.
|
||||
Fixes:
|
||||
- Fixed 'orig' scaling in fullscreen: http://flowplayer.org/forum/2/10274#post-52646
|
||||
|
||||
3.2.6
|
||||
-----
|
||||
- linkUrl should now work better with popup blockers: http://code.google.com/p/flowplayer-core/issues/detail?id=31
|
||||
- new linkWindow value "_popup" opens the linked page in a popup browser window
|
||||
- added new onClipResized event
|
||||
- Added new onUnload event, can be only listened in Flash and not triggered to JS
|
||||
- API: Added new url property to plugin objects
|
||||
Fixes:
|
||||
- it was not possible to call play() in an onFinish listener
|
||||
- fix to preserve the infoObject for custom netStream and netConnection clients in cases where the infoObject is a
|
||||
primitive object without properties
|
||||
- does not show the error dialog in the debugger player when showErrors: false
|
||||
- fixed to correctly handle xx.ca subdomains when validating the license key
|
||||
- a custom logo is now sized correctly according to the configured size
|
||||
- does not show the buffer animation any more when the player receives the onBufferEmpty message from the netStream.
|
||||
The animation was unnecessarily shown in some situations.
|
||||
- fixed #155. added new urlEncoding property to Clip for url ncoding ut8 urls
|
||||
|
||||
3.2.5
|
||||
-----
|
||||
- added new scaling option 'crop' that resizes to fill all available space, cropping on top/bottom or left/right
|
||||
- improvements to RSS file parsing
|
||||
- Now displays a hand cursor when a linkUrl is used in clips
|
||||
|
||||
3.2.4
|
||||
-----
|
||||
- new flowplayer.js version, with Apple iDevice fixes
|
||||
|
||||
3.2.3
|
||||
-----
|
||||
- a new 'type' clip property exposed to JS
|
||||
- changed the clip type property to better work as a read-write property. Now accepts 'video', 'audio',
|
||||
'image' and 'api' as configuration values.
|
||||
- moved parallel rtmp connection mechanism from the RTMP plugin to Core so other plugins can use it (ie: securestreaming)
|
||||
Fixes:
|
||||
- fixed #112, wrong URL computation when using clip with relative URL on a page with a / after a # in its url
|
||||
- fixed #111, wrong behavior of pre/post roll images with duration 0
|
||||
- fixed multiple license keys logic
|
||||
Fixes:
|
||||
- correct verification of license keys in *.ca domains
|
||||
- fix to make playback to always reach end of video
|
||||
- fixed resuming of live streams
|
||||
|
||||
3.2.2
|
||||
-----
|
||||
Fixes:
|
||||
- Now recognizes following kind of urls as audio clips: 'mp3:audiostreamname' (ulrs with mp3 prefix and no extension)
|
||||
- Now ignores the duration from metadata if we already got one. Fix required for pseudostreaming
|
||||
- Fix to reuse buffered data when replaying a clip
|
||||
|
||||
3.2.1
|
||||
---------
|
||||
- Support for RTMP redirects (tested with Wowza loadbalancing)
|
||||
- Fixed video size when no size info available in clip metadata
|
||||
|
||||
Fixes:
|
||||
- Fix to correctly detect if the player SWF name contains a version number and if it does also use the version number
|
||||
when it automatically loads the controls plugin.
|
||||
|
||||
3.2.0
|
||||
-----
|
||||
- canvas, controlbar and the content plugin backgound color and border color can be now given with rgb() and rgba() CSS style syntax
|
||||
- Added onMouseOver() and onMouseOut() listener registration methods to the Flowplayer API
|
||||
- enhancements to RSS playlist. Converted parsing to E4X, yahoo media and flowplayer namespace support.
|
||||
- added feature to obtain bitrate and dimension information to a new clip custom property "bitrates" for future support for bitrate choosing.
|
||||
- added getter for playerSwfName config
|
||||
- if clip.url has the string "mp3:" in it, the clip.type will report 'audio'
|
||||
- added setKeyboardShortcutsEnabled(), addKeyListener(), removeKeyListener() to FlowplayerBase
|
||||
Fixes:
|
||||
- onSeek() was not fired when seeking while paused and when using RTMP. An extra onStart was fired too.
|
||||
- fireErrorExternal() was not working properly with an error PlayerEvent
|
||||
- countPlugins() was throwing an error when a plugin was not found
|
||||
- external swf files were not scaled properly
|
||||
- the logo was unnecessary shown when going fullscreen if logo.displayTime was being used
|
||||
- added a loadPluginWithConfig method to FlowplayerBase, accessible from javascript. Fixed double onload callback call.
|
||||
- now handles cuepoint parameters injected using the Adobe Media Encoder
|
||||
- showPlugin was not working when config.play was null
|
||||
- handles 3-part duration values included in FLV metadata, like "500.123.123"
|
||||
- player wasn't always reaching end of video
|
||||
- fixed broken buffering: false
|
||||
- fixed event dispatching when embedding flowplayer without flowplayer.js (=without playlist config field)
|
||||
- fixed safari crashes when unloading player
|
||||
- fixed scrubber behaviour with a playlist containing 2 images (or swf) in a row
|
||||
- fixed errors in logs when using an RSS playlist
|
||||
- fixed OverlayPlayButton that was showing even if it shouldn't on some cases
|
||||
- fixed wrong behavior when onBeforeFinish was returning false within playlists
|
||||
- /!\ Don't use the fadeIn / fadeOut controlbar's API while using autoHide.
|
||||
- fixed play state button with images
|
||||
- fixed splash image flickering
|
||||
|
||||
3.1.5
|
||||
-----
|
||||
Fixes:
|
||||
- The player went to a locked state when resuming playback after a period that was long enought to send the
|
||||
netConnection to an invalid state. Now when resuming playback on an invalid connection the clip starts again from
|
||||
the beginning. This is only when using RTMP connections and does not affect progressive download playback.
|
||||
- Custom netConnect and netStream events did not pass the info object to JS listeners
|
||||
|
||||
3.1.4
|
||||
-----
|
||||
Fixes:
|
||||
- player did not initialize if the controlbar plugin was disabled and if the play button overlay was disabled with play: null
|
||||
- works properly without cachebusting on IE
|
||||
- RSS playlist parsing now respects the isDefault attribute used in mRSS media group items
|
||||
- Fixed passing of connection arguments
|
||||
|
||||
3.1.3
|
||||
-----
|
||||
- enhancements to RSS playlist parsing: Now skips all media:content that have unsupported types. Now the type attribute
|
||||
of the media:content element is mandatory and has to be present in the RSS file
|
||||
- Possibility to pass a RSS file name with playFeed("playlist.rss") and setPlaylist("playlist.rss") calls.
|
||||
- changes to the ConnectionProvider and URLResolver APIs
|
||||
- Now automatically uses a plugin that is called 'rtmp' for all clips that have the rtmp-protocol in their URLs.
|
||||
- Added possibility to specify all clip properties in an RSS playlist
|
||||
|
||||
Fixes:
|
||||
- the result of URL resolvers in now cached, and the resolvers will not be used again when a clip is replayed
|
||||
- some style properties like 'backgroundGradient' had no effect in config
|
||||
- video goes tiny on Firefox: http://flowplayer.org/forum/8/23226
|
||||
- RSS playlists: The 'type' attribute value 'audio/mp3' in the media:content element caused an error.
|
||||
- Dispatches onMetadata() if an URL resolver changes the clip URL (changes to a different file)
|
||||
- error codes and error message were not properly passed to onEvent JS listeners
|
||||
|
||||
3.1.2
|
||||
-----
|
||||
- The domain of the logo url must the same domain from where the player SWF is loaded from.
|
||||
- Fullscreen can be toggled by doublclick on the video area.
|
||||
Fixes:
|
||||
- Player was not initialized correctly when instream playlists were used and the provider used in the instream clips was defined in the common clip.
|
||||
- A separator in the Context Menu made the callbacks in the following menu items out of order. Related forum post: http://flowplayer.org/forum/8/22541
|
||||
- the width and height settings of a logo were ignored if the logo was a sWF file
|
||||
- volume control and mute/unmute were not working after an instream clip had been played
|
||||
- now possible to use RTMP for mp3 files
|
||||
- Issue 12: cuepointMultiplier was undefined in the clip object set to JS event listeners
|
||||
- Issue 14: onBeforeStop was unnecessarily fired when calling setPlaylist() and the player was not playing,
|
||||
additionally onStop was never fired even if onBeforeStop was
|
||||
- fixed screen vertical placement problems that reappeared with 3.1.1
|
||||
- The rotating animation now has the same size and position as it has after initialized
|
||||
|
||||
3.1.1
|
||||
-----
|
||||
- External configuration files
|
||||
- Instream playback
|
||||
- Added toggleFullscreen() the API
|
||||
- Possibility to specify controls configuration in clips
|
||||
- Seek target position is now sent in the onBeforeSeek event
|
||||
Fixes:
|
||||
- The screen size was initially too small on Firefox (Mac)
|
||||
- Did not persist a zero volume value: http://www.flowplayer.org/forum/8/18413
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
New features:
|
||||
- clip's can have urlResolvers and connectionProviders
|
||||
- Added new configuration options 'connectionCallbacks' and 'streamCallbacks'. Both accept an Array of event names as a value.
|
||||
When these events get fired on the connection or stream object, corresponding Clip events will be fired by the player.
|
||||
This can be used for example when firing custom events from RTMP server apps
|
||||
- Added new clip event types: 'onConnectionEvent' and 'onStreamEvent' these get fired when the predefined events happen on the connection and stream objects.
|
||||
- Added Security.allowDomain() to allow loaded plugins to script the player
|
||||
- Added addClip(clip, index) to the API, index is optional
|
||||
- Possibility to view videos without metadata, using clip.metaData: false
|
||||
- Now the player's preloader uses the rotating animation instead of a percent text to indicate the progress
|
||||
of loading the player SWF. You can disable the aninamtion by setting buffering: false
|
||||
- calling close() now does not send the onStop event
|
||||
- Clip's custom properties are now present in the root of the clip argument in all clip events that are sent to JS.
|
||||
|
||||
Bug fixes:
|
||||
- The preloader sometimes failed to initialize the player
|
||||
- Allow seeking while in buffering state: http://flowplayer.org/forum/8/16505
|
||||
- Replay of a RTMP stream was failing after the connection had expired
|
||||
- Security error when clicking on the screen if there is an image in the playlist loaded from a foreign domain
|
||||
- loadPlugin() was not working
|
||||
- now fullscreen works with Flash versions older than 9.0.115, in versions that do not support hardware scaling
|
||||
- replaying a RTMP stream with an image in front of the stream in the playlist was not working (video stayed hidden). Happened
|
||||
because the server does not send metadata if replaying the same stream.
|
||||
- the scrubber is disabled if the clip is not seekable in the first frame: http://flowplayer.org/forum/8/16526
|
||||
By default if the clip has one of following extensions (the typical flash video extensions) it is seekable
|
||||
in the first frame: 'f4b', 'f4p', 'f4v', 'flv'. Added new clip property seekableOnBegin that can be used to override the default.
|
||||
|
||||
3.0.6
|
||||
-----
|
||||
- added possibility to associate a linkUrl and linkWindow to the canvas
|
||||
Fixes:
|
||||
- fix for entering fullscreen for Flash versions that don't support the hardware scaled fullscreen-mode
|
||||
- when showing images the duration tracking starts only after the image has been completely loaded: http://flowplayer.org/forum/2/15301
|
||||
- fix for verifying license keys for domains that have more than 4 labels in them
|
||||
- if plugin loading failis because of a IO error, the plugin will be discarded and the player initialization continues:
|
||||
|
||||
3.0.4
|
||||
-----
|
||||
- The "play" pseudo-plugin now supports fadeIn(), fadeOut(), showPlugin(), hidePlugin() and
|
||||
additionally you can configure it like this:
|
||||
// make only the play button invisible (buffering animation is still used)
|
||||
play: { display: 'none' }
|
||||
// disable the play button and the buffering animation
|
||||
play: null
|
||||
// disable the buffering animation
|
||||
buffering: null
|
||||
- Added possibility to seek when in the buffering state: http://flowplayer.org/forum/3/13896
|
||||
- Added copyright notices and other GPL required entries to the user interface
|
||||
|
||||
Fixes:
|
||||
- clip urls were not resolved correctly if the HTML page URL had a query string starting with a question mark (http://flowplayer.org/forum/8/14016#post-14016)
|
||||
- Fixed context menu for with IE (commercial version)
|
||||
- a cuepoint at time zero was fired several times
|
||||
- screen is now arranged correctly even when only bottom or top is defined for it in the configuration
|
||||
- Fixed context menu for with IE (commercial version)
|
||||
- a cuepoint at time zero was fired several times
|
||||
- screen is now arranged correctly even when only bottom or top is defined for it in the configuration
|
||||
- Now possible to call play() in an onError handler: http://flowplayer.org/forum/8/12939
|
||||
- Does not throw an error if the player cannot persist the volume on the client computer: http://flowplayer.org/forum/8/13286#post-13495
|
||||
- Triggering fullscreen does not pause the player in IE
|
||||
- The play button overlay no longer has a gap between it's pieces when a label is used: http://flowplayer.org/forum/8/14250
|
||||
- clip.update() JS call now resets the duration
|
||||
- a label configured for the play button overlay did not work in the commercial version
|
||||
|
||||
3.0.3
|
||||
-----
|
||||
- fixed cuepoint firing: Does not skip cuepoints any more
|
||||
- Plugins can now be loaded from a different domain to the flowplayer.swf
|
||||
- Specifying a clip to play by just using the 'clip' node in the configuration was not working, a playlist definition was required. This is now fixed.
|
||||
- Fixed: A playlist with different providers caused the onMetadata event to fire events with metadata from the previous clip in the playlist. Occurred when moving in the playlist with next() and prev()
|
||||
- the opacity setting now works with the logo
|
||||
- fadeOut() call to the "screen" plugin was sending the listenerId and pluginName arguments in wrong order
|
||||
- stop(), pause(), resume(), close() no longer return the flowplayer object to JS
|
||||
- changing the size of the screen in a onFullscreen listener now always works, there was a bug that caused this to fail occasionally
|
||||
- fixed using arbitrary SWFs as plugins
|
||||
- the API method setPlaylist() no longer starts playing if autoPlay: true, neither it starts buffering if autoBuffering: true
|
||||
- the API method play() now accepts an array of clip objects as an argument, the playlist is replaced with the specified clips and playback starts from the 1st clip
|
||||
|
||||
3.0.2
|
||||
-----
|
||||
- setting play: null now works again
|
||||
- pressing the play again button overlay does not open a linkUrl associated with a clip
|
||||
- now displays a live feed even when the RTMP server does not send any metadata and the onStart method is not therefore dispatched
|
||||
- added onMetaData clip event
|
||||
- fixed 'orig' scaling: the player went to 'fit' scaling after coming back from fullscreen. This is now fixed and the original dimensions are preserved in non-fullscreen mode.
|
||||
- cuepoint times are now given in milliseconds, the firing precision is 100 ms. All cuepoint times are rounded to the nearest 100 ms value (for example 1120 rounds to 1100)
|
||||
- backgroundGradient was drawn over the background image in the canvas and in the content and controlbar plugins. Now it's drawn below the image.
|
||||
- added cuepointMultiplier property to clips. This can be used to multiply the time values read from cuepoint metadata embedded into video files.
|
||||
- the player's framerate was increased to 24 FPS, makes all animations smoother
|
||||
|
||||
3.0.1
|
||||
-----
|
||||
- Fixed negative cuepoints from common clip. Now these are properly propagated to the clips in playlist.
|
||||
- buffering animation is now the same size as the play button overlay
|
||||
- commercial version now supports license keys that allows the use of subdomains
|
||||
- error messages are now automatically hidden after a 4 second delay. They are also hidden when a new clips
|
||||
starts playing (when onBeforeBegin is fired)
|
||||
- added possibility to disable the buffering animation like so: buffering: false
|
||||
- pressing the play button overlay does not open a linkUrl associated with a clip
|
||||
- license key verification failed if a port number was used in the URL (like in this url: http://mydomain.com:8080/video.html)
|
||||
- added audio support, clip has a new "image" property
|
||||
- workaround for missing "NetStream.Play.Start" notfication that was happending with Red5. Because of this issue the video was not shown.
|
||||
- commercial version has the possibility to change the zIndex of the logo
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
- Removed security errors that happened when loading images from foreign domains (domains other than the domain of the core SWF).
|
||||
Using a backgroundImage on canvas, in the content plugin, and for the controls is also possible to be loaded
|
||||
from a foreign domain - BUT backgroundRepeat cannot be used for foreign images.
|
||||
- Now allows the embedding HTML to script the player even if the player is loaded from another domain.
|
||||
- Added a 'live' property to Clips, used for live streams.
|
||||
- A player embedded to a foreign domain now loads images, css files and other resources from the domain where the palyer SWF was loaded from. This is to generate shorter embed-codes.
|
||||
- Added linkUrl and linkWindow properties to the logo, in commercial version you can set these to point to a linked page. The linked page gets opened
|
||||
when the logo is clicked. Possible values for linkWindow:
|
||||
* "_self" specifies the current frame in the current window.
|
||||
* "_blank" specifies a new window.
|
||||
* "_parent" specifies the parent of the current frame.
|
||||
* "_top" specifies the top-level frame in the current window.
|
||||
- Added linkUrl and linkWindow properties to clips. The linked page is opened when the video are is clicked and the corresponding clip has a linkUrl specified.
|
||||
- Made the play button overlay and the "Play again" button slightly bigger.
|
||||
|
||||
RC4
|
||||
---
|
||||
- Now shows a "Play again" button at the end of the video/playlist
|
||||
- Commercial version shows a Flowplayer logo if invalidKey was supplied, but the otherwise the player works
|
||||
- setting play: null in configuration will disable the play button overlay
|
||||
- setting opacity for "play" also sets it for the buffering animation
|
||||
- Fixed firing of cuepoints too early. Cuepoint firing is now based on stream time and does not rely on timers
|
||||
- added onXMPData event listener
|
||||
- Should not stop playback too early before the clip is really completed
|
||||
- The START event is now delayed so that the metadata is available when the event is fired, METADATA event was removed,
|
||||
new event BEGIN that is dispatched when the playback has been successfully started. Metadata is not normally
|
||||
available when BEGIN is fired.
|
||||
|
||||
RC3
|
||||
---
|
||||
- stopBuffering() now dispatches the onStop event first if the player is playing/paused/buffering at the time of calling it
|
||||
- fixed detection of images based on file extensions
|
||||
- fixed some issues with having images in the playlist
|
||||
- made it possible to autoBuffer next video while showing an image (image without a duration)
|
||||
|
||||
RC2
|
||||
---
|
||||
- fixed: setting the screen height in configuration did not have any effect
|
||||
|
||||
RC1
|
||||
-----
|
||||
- better error message if plugin loading fails, shows the URL used
|
||||
- validates our redesigned multidomain license key correctly
|
||||
- fix to prevent the play button going visible when the onBufferEmpty event occurs
|
||||
- the commercial swf now correctly loads the controls using version information
|
||||
- fixed: the play button overlay became invisible with long fadeOutSpeeds
|
||||
|
||||
beta6
|
||||
-----
|
||||
- removed the onFirstFramePause event
|
||||
- playing a clip for the second time caused a doubled sound
|
||||
- pausing on first frame did not work on some FLV files
|
||||
|
||||
beta5
|
||||
-----
|
||||
- logo only uses percentage scaling if it's a SWF file (there is ".swf" in it's url)
|
||||
- context menu now correctly builds up from string entries in configuration
|
||||
-always closes the previous connection before starting a new clip
|
||||
|
||||
beta4
|
||||
-----
|
||||
- now it's possible to load a plugin into the panel without specifying any position/dimensions
|
||||
information, the plugin is placed to left: "50%", top: "50%" and using the plugin DisplayObject's width & height
|
||||
- The Flowplayer API was not fully initialized when onLoad was invoked on Flash plugins
|
||||
|
||||
beta3
|
||||
-----
|
||||
- tweaking logo placement
|
||||
- "play" did not show up after repeated pause/resume
|
||||
- player now loads the latest controls SWF version, right now the latest SWF is called 'flowplayer.controls-3.0.0-beta2.swf'
|
||||
|
||||
beta2
|
||||
-----
|
||||
- fixed support for RTMP stream groups
|
||||
- changed to loop through available fonts in order to find a suitable font also in IE
|
||||
- Preloader was broken on IE: When the player SWf was in browser's cache it did not initialize properly
|
||||
- Context menu now correctly handles menu items that are configured by their string labels only (not using json objects)
|
||||
- fixed custom logo positioning (was moved to the left edge of screen in fullscreen)
|
||||
- "play" now always follows the position and size of the screen
|
||||
- video was stretched below the controls in fullscreen when autoHide: 'never'
|
||||
- logo now takes 6.5% of the screen height, width is scaled so that the aspect ratio is preserved
|
||||
|
||||
beta1
|
||||
-----
|
||||
- First public beta release
|
|
@ -1,89 +0,0 @@
|
|||
Version history:
|
||||
|
||||
3.2.10
|
||||
------
|
||||
- #575 send the start event after begin
|
||||
- #569 if the playlist has been reset but the audio has been already buffered, set the duration and start event.
|
||||
- #582 fixes for metadata events dispatching in playlists and when replaying same audio item, cleanup duration updating once download has completed,
|
||||
fixes for clearing the previous cover image display.
|
||||
- #611 close the channel and sound on stream not found errors.
|
||||
- #614 fixes for auto buffering issues where a sound channel may not be active yet.
|
||||
|
||||
3.2.9
|
||||
-----
|
||||
- #501 fixes to dispatch start state correctly.
|
||||
- #501 use the sound channel to listen for a complete event to finish correctly.
|
||||
|
||||
3.2.8
|
||||
-----
|
||||
Fixes:
|
||||
- fixed to dispatch onStart only once
|
||||
- the duration is now available in the clip when onStart is dispatched
|
||||
- audio duration was estimated to be too long, issue #323
|
||||
- duration not available in the onMetaData event, issue #278
|
||||
- now dispatches error 200 when the mp3 URL does not respond, issue #334
|
||||
- #428 regression issue calculating the initial duration, was returning too small for the duration tracker.
|
||||
- #428 when fully downloaded ID3 is resent and update the duration.
|
||||
- #475 if we have a clip duration set, dispatch start or else wait until the duration is estimated. Start required for beginning duration tracker.
|
||||
|
||||
3.2.3
|
||||
-----
|
||||
Fixes:
|
||||
- Fixed to dispatch onStart when the mp3 file does not contain a id3 tag
|
||||
- Now uses baseUrl if that is given
|
||||
|
||||
3.2.2
|
||||
-----
|
||||
Fixes:
|
||||
- Now can download cover images from different domains without cross-domain security errors
|
||||
|
||||
3.2.1
|
||||
-----
|
||||
Changes:
|
||||
- Supports cover images via a 'coverImage' configuration option
|
||||
- now works with securestreaming plugin
|
||||
Fixes:
|
||||
- fix to work properly if accessing the ID3 tag fails because Flash security prevents it
|
||||
- works better if the file does not have the ID3 tag
|
||||
|
||||
3.2.0
|
||||
-----
|
||||
- added a new plugin event "onDuration" that is dispatched whenever a new duration value is estimated and the
|
||||
clip.duration value was changed. The new duration value is passed as event argument.
|
||||
|
||||
3.1.3
|
||||
-----
|
||||
- added timeProvider setter as required by the changed StreamProvider interface
|
||||
- now checks the crossdomain.xml file to allow reading of the ID3 tag when this file is present in the domain
|
||||
hosting the audio file
|
||||
|
||||
3.1.2
|
||||
-----
|
||||
- compatible with the new ConnectionProvider and URLResolver API
|
||||
|
||||
3.1.1
|
||||
-----
|
||||
Fixes:
|
||||
- calling closeBuffering() after the audio had finished caused an exception
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
- compatibility with core 3.1 StreamProvider interface
|
||||
|
||||
3.0.4
|
||||
-----
|
||||
- fixed to stop audio when stop() is called
|
||||
|
||||
3.0.3
|
||||
-----
|
||||
- changed to recalculate the duration until the end of the file has been reached,
|
||||
this is needed to correctly estimate the duration of variable bitrate MP3's
|
||||
|
||||
3.0.2
|
||||
-----
|
||||
- dispatches the LOAD event when initialized (needed for flowplayer 3.0.2 compatibility)
|
||||
- fixed crashes of Mac Safari when navigating out of a page that had a playing audio
|
||||
|
||||
3.0.1
|
||||
-----
|
||||
- First public beta release
|
File diff suppressed because it is too large
Load diff
22
lib/flowplayer/flowplayer-3.2.13.min.js
vendored
22
lib/flowplayer/flowplayer-3.2.13.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Flowplayer handling file.
|
||||
*
|
||||
* @package core
|
||||
* @copyright Petr Skoda <petr.skoda@totaralms.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('NO_DEBUG_DISPLAY', true);
|
||||
define('NO_MOODLE_COOKIES', true);
|
||||
define('NO_UPGRADE_CHECK', true);
|
||||
|
||||
require('../../config.php');
|
||||
require('../../lib/flowplayer/lib.php');
|
||||
|
||||
flowplayer_send_flash_content('flowplayer-3.2.18.swf');
|
File diff suppressed because one or more lines are too long
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Flowplayer audio swf handling.
|
||||
*
|
||||
* @package core
|
||||
* @copyright Petr Skoda <petr.skoda@totaralms.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('NO_DEBUG_DISPLAY', true);
|
||||
define('NO_MOODLE_COOKIES', true);
|
||||
define('NO_UPGRADE_CHECK', true);
|
||||
|
||||
require('../../config.php');
|
||||
require('../../lib/flowplayer/lib.php');
|
||||
|
||||
flowplayer_send_flash_content('flowplayer.audio-3.2.11.swf');
|
File diff suppressed because one or more lines are too long
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Flowplayer audio controls handling.
|
||||
*
|
||||
* @package core
|
||||
* @copyright Petr Skoda <petr.skoda@totaralms.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('NO_DEBUG_DISPLAY', true);
|
||||
define('NO_MOODLE_COOKIES', true);
|
||||
define('NO_UPGRADE_CHECK', true);
|
||||
|
||||
require('../../config.php');
|
||||
require('../../lib/flowplayer/lib.php');
|
||||
|
||||
flowplayer_send_flash_content('flowplayer.controls-3.2.16.swf');
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Flowplayer library.
|
||||
*
|
||||
* @package core
|
||||
* @copyright Petr Skoda <petr.skoda@totaralms.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Safer flash serving code.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void does not return, ends with die()
|
||||
*/
|
||||
function flowplayer_send_flash_content($filename) {
|
||||
global $CFG;
|
||||
// Note: Do not use any fancy APIs here, this must work in all supported versions.
|
||||
|
||||
// No url params.
|
||||
if (!empty($_GET) or !empty($_POST)) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
die;
|
||||
}
|
||||
|
||||
// Our referrers only, nobody else should embed these scripts.
|
||||
if (!empty($_SERVER['HTTP_REFERER'])) {
|
||||
$refhost = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
|
||||
$host = parse_url($CFG->wwwroot . '/', PHP_URL_HOST);
|
||||
if ($refhost and $host and strtolower($refhost) !== strtolower($host)) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch and decode the original content.
|
||||
$content = file_get_contents($CFG->dirroot . '/lib/flowplayer/' . $filename . '.bin');
|
||||
if (!$content) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
die;
|
||||
}
|
||||
$content = base64_decode($content);
|
||||
|
||||
// No caching allowed.
|
||||
if (strpos($CFG->wwwroot, 'https://') === 0) {
|
||||
// HTTPS sites - watch out for IE! KB812935 and KB316431.
|
||||
header('Cache-Control: private, max-age=10, no-transform');
|
||||
header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
|
||||
header('Pragma: ');
|
||||
} else {
|
||||
header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0, no-transform');
|
||||
header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
|
||||
header('Pragma: no-cache');
|
||||
}
|
||||
|
||||
// Send the original binary code.
|
||||
header('Content-Type: application/x-shockwave-flash');
|
||||
echo $content;
|
||||
die;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
Description of FlowPlayer import
|
||||
|
||||
Source code available at: https://github.com/flowplayer/flash
|
||||
|
||||
Our changes:
|
||||
* the handling of flash content now it's done by PHP, checking url parameter to avoid security issues.
|
||||
* we do not load the flow player if flash not present - this is much better
|
||||
for accessibility and flash incompatible devices - they may play mp3 or flv directly
|
||||
* no splashscreens
|
||||
|
||||
skodak
|
|
@ -1667,182 +1667,6 @@ M.form.init_smartselect = function(Y, id, options) {
|
|||
});
|
||||
};
|
||||
|
||||
/** List of flv players to be loaded */
|
||||
M.util.video_players = [];
|
||||
/** List of mp3 players to be loaded */
|
||||
M.util.audio_players = [];
|
||||
|
||||
/**
|
||||
* Add video player
|
||||
* @param id element id
|
||||
* @param fileurl media url
|
||||
* @param width
|
||||
* @param height
|
||||
* @param autosize true means detect size from media
|
||||
*/
|
||||
M.util.add_video_player = function (id, fileurl, width, height, autosize) {
|
||||
M.util.video_players.push({id: id, fileurl: fileurl, width: width, height: height, autosize: autosize, resized: false});
|
||||
};
|
||||
|
||||
/**
|
||||
* Add audio player.
|
||||
* @param id
|
||||
* @param fileurl
|
||||
* @param small
|
||||
*/
|
||||
M.util.add_audio_player = function (id, fileurl, small) {
|
||||
M.util.audio_players.push({id: id, fileurl: fileurl, small: small});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise all audio and video player, must be called from page footer.
|
||||
*/
|
||||
M.util.load_flowplayer = function() {
|
||||
if (M.util.video_players.length == 0 && M.util.audio_players.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (typeof(flowplayer) == 'undefined') {
|
||||
var loaded = false;
|
||||
|
||||
var embed_function = function() {
|
||||
if (loaded || typeof(flowplayer) == 'undefined') {
|
||||
return;
|
||||
}
|
||||
loaded = true;
|
||||
|
||||
var controls = {
|
||||
url: M.cfg.wwwroot + '/lib/flowplayer/flowplayer.controls-3.2.16.swf.php',
|
||||
autoHide: true
|
||||
}
|
||||
/* TODO: add CSS color overrides for the flv flow player */
|
||||
|
||||
for(var i=0; i<M.util.video_players.length; i++) {
|
||||
var video = M.util.video_players[i];
|
||||
if (video.width > 0 && video.height > 0) {
|
||||
var src = {src: M.cfg.wwwroot + '/lib/flowplayer/flowplayer-3.2.18.swf.php', width: video.width, height: video.height};
|
||||
} else {
|
||||
var src = M.cfg.wwwroot + '/lib/flowplayer/flowplayer-3.2.18.swf.php';
|
||||
}
|
||||
flowplayer(video.id, src, {
|
||||
plugins: {controls: controls},
|
||||
clip: {
|
||||
url: video.fileurl, autoPlay: false, autoBuffering: true, scaling: 'fit', mvideo: video,
|
||||
onMetaData: function(clip) {
|
||||
if (clip.mvideo.autosize && !clip.mvideo.resized) {
|
||||
clip.mvideo.resized = true;
|
||||
//alert("metadata!!! "+clip.width+' '+clip.height+' '+JSON.stringify(clip.metaData));
|
||||
if (typeof(clip.metaData.width) == 'undefined' || typeof(clip.metaData.height) == 'undefined') {
|
||||
// bad luck, we have to guess - we may not get metadata at all
|
||||
var width = clip.width;
|
||||
var height = clip.height;
|
||||
} else {
|
||||
var width = clip.metaData.width;
|
||||
var height = clip.metaData.height;
|
||||
}
|
||||
var minwidth = 300; // controls are messed up in smaller objects
|
||||
if (width < minwidth) {
|
||||
height = (height * minwidth) / width;
|
||||
width = minwidth;
|
||||
}
|
||||
|
||||
var object = this._api();
|
||||
object.width = width;
|
||||
object.height = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (M.util.audio_players.length == 0) {
|
||||
return;
|
||||
}
|
||||
var controls = {
|
||||
url: M.cfg.wwwroot + '/lib/flowplayer/flowplayer.controls-3.2.16.swf.php',
|
||||
autoHide: false,
|
||||
fullscreen: false,
|
||||
next: false,
|
||||
previous: false,
|
||||
scrubber: true,
|
||||
play: true,
|
||||
pause: true,
|
||||
volume: true,
|
||||
mute: false,
|
||||
backgroundGradient: [0.5,0,0.3]
|
||||
};
|
||||
|
||||
var rule;
|
||||
for (var j=0; j < document.styleSheets.length; j++) {
|
||||
|
||||
// To avoid javascript security violation accessing cross domain stylesheets
|
||||
var allrules = false;
|
||||
try {
|
||||
if (typeof (document.styleSheets[j].rules) != 'undefined') {
|
||||
allrules = document.styleSheets[j].rules;
|
||||
} else if (typeof (document.styleSheets[j].cssRules) != 'undefined') {
|
||||
allrules = document.styleSheets[j].cssRules;
|
||||
} else {
|
||||
// why??
|
||||
continue;
|
||||
}
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// On cross domain style sheets Chrome V8 allows access to rules but returns null
|
||||
if (!allrules) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(var i=0; i<allrules.length; i++) {
|
||||
rule = '';
|
||||
if (/^\.mp3flowplayer_.*Color$/.test(allrules[i].selectorText)) {
|
||||
if (typeof(allrules[i].cssText) != 'undefined') {
|
||||
rule = allrules[i].cssText;
|
||||
} else if (typeof(allrules[i].style.cssText) != 'undefined') {
|
||||
rule = allrules[i].style.cssText;
|
||||
}
|
||||
if (rule != '' && /.*color\s*:\s*([^;]+).*/gi.test(rule)) {
|
||||
rule = rule.replace(/.*color\s*:\s*([^;]+).*/gi, '$1');
|
||||
var colprop = allrules[i].selectorText.replace(/^\.mp3flowplayer_/, '');
|
||||
controls[colprop] = rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
allrules = false;
|
||||
}
|
||||
|
||||
for(i=0; i<M.util.audio_players.length; i++) {
|
||||
var audio = M.util.audio_players[i];
|
||||
if (audio.small) {
|
||||
controls.controlall = false;
|
||||
controls.height = 15;
|
||||
controls.time = false;
|
||||
} else {
|
||||
controls.controlall = true;
|
||||
controls.height = 25;
|
||||
controls.time = true;
|
||||
}
|
||||
flowplayer(audio.id, M.cfg.wwwroot + '/lib/flowplayer/flowplayer-3.2.18.swf.php', {
|
||||
plugins: {controls: controls, audio: {url: M.cfg.wwwroot + '/lib/flowplayer/flowplayer.audio-3.2.11.swf.php'}},
|
||||
clip: {url: audio.fileurl, provider: "audio", autoPlay: false}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (M.cfg.jsrev == -1) {
|
||||
var jsurl = M.cfg.wwwroot + '/lib/flowplayer/flowplayer-3.2.13.js';
|
||||
} else {
|
||||
var jsurl = M.cfg.wwwroot + '/lib/javascript.php?jsfile=/lib/flowplayer/flowplayer-3.2.13.min.js&rev=' + M.cfg.jsrev;
|
||||
}
|
||||
var fileref = document.createElement('script');
|
||||
fileref.setAttribute('type','text/javascript');
|
||||
fileref.setAttribute('src', jsurl);
|
||||
fileref.onload = embed_function;
|
||||
fileref.onreadystatechange = embed_function;
|
||||
document.getElementsByTagName('head')[0].appendChild(fileref);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiates the listeners for skiplink interaction
|
||||
*
|
||||
|
|
1168
lib/medialib.php
1168
lib/medialib.php
File diff suppressed because it is too large
Load diff
|
@ -563,9 +563,6 @@ class core_renderer extends renderer_base {
|
|||
}
|
||||
}
|
||||
|
||||
// flow player embedding support
|
||||
$this->page->requires->js_function_call('M.util.load_flowplayer');
|
||||
|
||||
// Set up help link popups for all links with the helptooltip class
|
||||
$this->page->requires->js_init_call('M.util.help_popups.setup');
|
||||
|
||||
|
@ -4639,6 +4636,7 @@ class core_renderer_ajax extends core_renderer {
|
|||
* Used in file resources, media filter, and any other places that need to
|
||||
* output embedded media.
|
||||
*
|
||||
* @deprecated since Moodle 3.2
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
@ -4649,75 +4647,14 @@ class core_media_renderer extends plugin_renderer_base {
|
|||
private $embeddablemarkers;
|
||||
|
||||
/**
|
||||
* Constructor requires medialib.php.
|
||||
* Constructor
|
||||
*
|
||||
* This is needed in the constructor (not later) so that you can use the
|
||||
* constants and static functions that are defined in core_media class
|
||||
* before you call renderer functions.
|
||||
*/
|
||||
public function __construct() {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/medialib.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the list of core_media_player objects currently in use to render
|
||||
* items.
|
||||
*
|
||||
* The list is in rank order (highest first) and does not include players
|
||||
* which are disabled.
|
||||
*
|
||||
* @return array Array of core_media_player objects in rank order
|
||||
*/
|
||||
protected function get_players() {
|
||||
global $CFG;
|
||||
|
||||
// Save time by only building the list once.
|
||||
if (!$this->players) {
|
||||
// Get raw list of players.
|
||||
$players = $this->get_players_raw();
|
||||
|
||||
// Chuck all the ones that are disabled.
|
||||
foreach ($players as $key => $player) {
|
||||
if (!$player->is_enabled()) {
|
||||
unset($players[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort in rank order (highest first).
|
||||
usort($players, array('core_media_player', 'compare_by_rank'));
|
||||
$this->players = $players;
|
||||
}
|
||||
return $this->players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a raw list of player objects that includes objects regardless
|
||||
* of whether they are disabled or not, and without sorting.
|
||||
*
|
||||
* You can override this in a subclass if you need to add additional
|
||||
* players.
|
||||
*
|
||||
* The return array is be indexed by player name to make it easier to
|
||||
* remove players in a subclass.
|
||||
*
|
||||
* @return array $players Array of core_media_player objects in any order
|
||||
*/
|
||||
protected function get_players_raw() {
|
||||
return array(
|
||||
'vimeo' => new core_media_player_vimeo(),
|
||||
'youtube' => new core_media_player_youtube(),
|
||||
'youtube_playlist' => new core_media_player_youtube_playlist(),
|
||||
'html5video' => new core_media_player_html5video(),
|
||||
'html5audio' => new core_media_player_html5audio(),
|
||||
'mp3' => new core_media_player_mp3(),
|
||||
'flv' => new core_media_player_flv(),
|
||||
'wmp' => new core_media_player_wmp(),
|
||||
'qt' => new core_media_player_qt(),
|
||||
'rm' => new core_media_player_rm(),
|
||||
'swf' => new core_media_player_swf(),
|
||||
'link' => new core_media_player_link(),
|
||||
);
|
||||
debugging('Class core_media_renderer is deprecated, please use core_media_manager::instance()', DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4739,18 +4676,7 @@ class core_media_renderer extends plugin_renderer_base {
|
|||
*/
|
||||
public function embed_url(moodle_url $url, $name = '', $width = 0, $height = 0,
|
||||
$options = array()) {
|
||||
|
||||
// Get width and height from URL if specified (overrides parameters in
|
||||
// function call).
|
||||
$rawurl = $url->out(false);
|
||||
if (preg_match('/[?#]d=([\d]{1,4}%?)x([\d]{1,4}%?)/', $rawurl, $matches)) {
|
||||
$width = $matches[1];
|
||||
$height = $matches[2];
|
||||
$url = new moodle_url(str_replace($matches[0], '', $rawurl));
|
||||
}
|
||||
|
||||
// Defer to array version of function.
|
||||
return $this->embed_alternatives(array($url), $name, $width, $height, $options);
|
||||
return core_media_manager::instance()->embed_url($url, $name, $width, $height, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4785,38 +4711,7 @@ class core_media_renderer extends plugin_renderer_base {
|
|||
*/
|
||||
public function embed_alternatives($alternatives, $name = '', $width = 0, $height = 0,
|
||||
$options = array()) {
|
||||
|
||||
// Get list of player plugins (will also require the library).
|
||||
$players = $this->get_players();
|
||||
|
||||
// Set up initial text which will be replaced by first player that
|
||||
// supports any of the formats.
|
||||
$out = core_media_player::PLACEHOLDER;
|
||||
|
||||
// Loop through all players that support any of these URLs.
|
||||
foreach ($players as $player) {
|
||||
// Option: When no other player matched, don't do the default link player.
|
||||
if (!empty($options[core_media::OPTION_FALLBACK_TO_BLANK]) &&
|
||||
$player->get_rank() === 0 && $out === core_media_player::PLACEHOLDER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$supported = $player->list_supported_urls($alternatives, $options);
|
||||
if ($supported) {
|
||||
// Embed.
|
||||
$text = $player->embed($supported, $name, $width, $height, $options);
|
||||
|
||||
// Put this in place of the 'fallback' slot in the previous text.
|
||||
$out = str_replace(core_media_player::PLACEHOLDER, $text, $out);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove 'fallback' slot from final version and return it.
|
||||
$out = str_replace(core_media_player::PLACEHOLDER, '', $out);
|
||||
if (!empty($options[core_media::OPTION_BLOCK]) && $out !== '') {
|
||||
$out = html_writer::tag('div', $out, array('class' => 'resourcecontent'));
|
||||
}
|
||||
return $out;
|
||||
return core_media_manager::instance()->embed_alternatives($alternatives, $name, $width, $height, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4831,7 +4726,7 @@ class core_media_renderer extends plugin_renderer_base {
|
|||
* @return bool True if file can be embedded
|
||||
*/
|
||||
public function can_embed_url(moodle_url $url, $options = array()) {
|
||||
return $this->can_embed_urls(array($url), $options);
|
||||
return core_media_manager::instance()->can_embed_url($url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4844,18 +4739,7 @@ class core_media_renderer extends plugin_renderer_base {
|
|||
* @return bool True if file can be embedded
|
||||
*/
|
||||
public function can_embed_urls(array $urls, $options = array()) {
|
||||
// Check all players to see if any of them support it.
|
||||
foreach ($this->get_players() as $player) {
|
||||
// Link player (always last on list) doesn't count!
|
||||
if ($player->get_rank() <= 0) {
|
||||
break;
|
||||
}
|
||||
// First player that supports it, return true.
|
||||
if ($player->list_supported_urls($urls, $options)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return core_media_manager::instance()->can_embed_urls($urls, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4870,19 +4754,7 @@ class core_media_renderer extends plugin_renderer_base {
|
|||
* @return string String suitable for use in regex such as '(\.mp4|\.flv)'
|
||||
*/
|
||||
public function get_embeddable_markers() {
|
||||
if (empty($this->embeddablemarkers)) {
|
||||
$markers = '';
|
||||
foreach ($this->get_players() as $player) {
|
||||
foreach ($player->get_embeddable_markers() as $marker) {
|
||||
if ($markers !== '') {
|
||||
$markers .= '|';
|
||||
}
|
||||
$markers .= preg_quote($marker);
|
||||
}
|
||||
}
|
||||
$this->embeddablemarkers = $markers;
|
||||
}
|
||||
return $this->embeddablemarkers;
|
||||
return core_media_manager::instance()->get_embeddable_markers();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,6 +217,9 @@ class phpunit_util extends testing_util {
|
|||
core_filetypes::reset_caches();
|
||||
\core_search\manager::clear_static();
|
||||
core_user::reset_caches();
|
||||
if (class_exists('core_media_manager', false)) {
|
||||
core_media_manager::reset_caches();
|
||||
}
|
||||
|
||||
// Reset static unit test options.
|
||||
if (class_exists('\availability_date\condition', false)) {
|
||||
|
|
|
@ -25,38 +25,25 @@
|
|||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/medialib.php');
|
||||
|
||||
/**
|
||||
* Test script for media embedding.
|
||||
*/
|
||||
class core_medialib_testcase extends advanced_testcase {
|
||||
|
||||
/** @var array Files covered by test */
|
||||
public static $includecoverage = array('lib/medialib.php', 'lib/outputrenderers.php');
|
||||
|
||||
/**
|
||||
* Pre-test setup. Preserves $CFG.
|
||||
*/
|
||||
public function setUp() {
|
||||
global $CFG;
|
||||
parent::setUp();
|
||||
|
||||
// Reset $CFG and $SERVER.
|
||||
$this->resetAfterTest();
|
||||
|
||||
// "Install" a fake plugin for testing.
|
||||
set_config('version', '2016101400', 'media_test');
|
||||
|
||||
// Consistent initial setup: all players disabled.
|
||||
$CFG->core_media_enable_html5video = false;
|
||||
$CFG->core_media_enable_html5audio = false;
|
||||
$CFG->core_media_enable_mp3 = false;
|
||||
$CFG->core_media_enable_flv = false;
|
||||
$CFG->core_media_enable_wmp = false;
|
||||
$CFG->core_media_enable_qt = false;
|
||||
$CFG->core_media_enable_rm = false;
|
||||
$CFG->core_media_enable_youtube = false;
|
||||
$CFG->core_media_enable_vimeo = false;
|
||||
$CFG->core_media_enable_swf = false;
|
||||
\core\plugininfo\media::set_enabled_plugins('');
|
||||
|
||||
$_SERVER = array('HTTP_USER_AGENT' => '');
|
||||
$this->pretend_to_be_safari();
|
||||
|
@ -76,33 +63,20 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
*/
|
||||
private function pretend_to_be_firefox() {
|
||||
// Pretend to be using Firefox browser (must support ogg for tests to work).
|
||||
core_useragent::instance(true, 'Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for the core_media_player is_enabled.
|
||||
*/
|
||||
public function test_is_enabled() {
|
||||
global $CFG;
|
||||
|
||||
// Test enabled: unset, 0, 1.
|
||||
$test = new core_media_player_test;
|
||||
$this->assertFalse($test->is_enabled());
|
||||
$CFG->core_media_enable_test = 0;
|
||||
$this->assertFalse($test->is_enabled());
|
||||
$CFG->core_media_enable_test = 1;
|
||||
$this->assertTrue($test->is_enabled());
|
||||
core_useragent::instance(true, 'Mozilla/5.0 (X11; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0 ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for core_media::get_filename.
|
||||
*/
|
||||
public function test_get_filename() {
|
||||
$this->assertSame('frog.mp4', core_media::get_filename(new moodle_url(
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
$this->assertSame('frog.mp4', $manager->get_filename(new moodle_url(
|
||||
'/pluginfile.php/312/mod_page/content/7/frog.mp4')));
|
||||
// This should work even though slasharguments is true, because we want
|
||||
// it to support 'legacy' links if somebody toggles the option later.
|
||||
$this->assertSame('frog.mp4', core_media::get_filename(new moodle_url(
|
||||
$this->assertSame('frog.mp4', $manager->get_filename(new moodle_url(
|
||||
'/pluginfile.php?file=/312/mod_page/content/7/frog.mp4')));
|
||||
}
|
||||
|
||||
|
@ -110,13 +84,15 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Test for core_media::get_extension.
|
||||
*/
|
||||
public function test_get_extension() {
|
||||
$this->assertSame('mp4', core_media::get_extension(new moodle_url(
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
$this->assertSame('mp4', $manager->get_extension(new moodle_url(
|
||||
'/pluginfile.php/312/mod_page/content/7/frog.mp4')));
|
||||
$this->assertSame('', core_media::get_extension(new moodle_url(
|
||||
$this->assertSame('', $manager->get_extension(new moodle_url(
|
||||
'/pluginfile.php/312/mod_page/content/7/frog')));
|
||||
$this->assertSame('mp4', core_media::get_extension(new moodle_url(
|
||||
$this->assertSame('mp4', $manager->get_extension(new moodle_url(
|
||||
'/pluginfile.php?file=/312/mod_page/content/7/frog.mp4')));
|
||||
$this->assertSame('', core_media::get_extension(new moodle_url(
|
||||
$this->assertSame('', $manager->get_extension(new moodle_url(
|
||||
'/pluginfile.php?file=/312/mod_page/content/7/frog')));
|
||||
}
|
||||
|
||||
|
@ -124,8 +100,7 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Test for the core_media_player list_supported_urls.
|
||||
*/
|
||||
public function test_list_supported_urls() {
|
||||
global $CFG;
|
||||
$test = new core_media_player_test;
|
||||
$test = new media_test_plugin(1, 13, ['tst', 'test']);
|
||||
|
||||
// Some example URLs.
|
||||
$supported1 = new moodle_url('http://example.org/1.test');
|
||||
|
@ -157,57 +132,59 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Test for core_media_renderer get_players
|
||||
*/
|
||||
public function test_get_players() {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// All players are initially disabled (except link, which you can't).
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertSame('link', $renderer->get_players_test());
|
||||
$manager = new core_media_manager_test();
|
||||
$this->assertEmpty($manager->get_players_test());
|
||||
|
||||
// A couple enabled, check the order.
|
||||
$CFG->core_media_enable_html5audio = true;
|
||||
$CFG->core_media_enable_mp3 = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertSame('mp3, html5audio, link', $renderer->get_players_test());
|
||||
\core\plugininfo\media::set_enabled_plugins('youtube,html5audio');
|
||||
$manager = new core_media_manager_test();
|
||||
$this->assertSame('youtube, html5audio', $manager->get_players_test());
|
||||
|
||||
// Test QT and HTML5 media order.
|
||||
$CFG->core_media_enable_mp3 = false;
|
||||
$CFG->core_media_enable_html5video = true;
|
||||
$CFG->core_media_enable_qt = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertSame('html5video, html5audio, qt, link', $renderer->get_players_test());
|
||||
// Test SWF and HTML5 media order.
|
||||
\core\plugininfo\media::set_enabled_plugins('html5video,html5audio,swf');
|
||||
$manager = new core_media_manager_test();
|
||||
$this->assertSame('html5video, html5audio, swf', $manager->get_players_test());
|
||||
|
||||
// Make sure that our test plugin is considered installed.
|
||||
\core\plugininfo\media::set_enabled_plugins('test,html5video');
|
||||
$manager = new core_media_manager_test();
|
||||
$this->assertSame('test, html5video', $manager->get_players_test());
|
||||
|
||||
// Make sure that non-existing plugin is NOT considered installed.
|
||||
\core\plugininfo\media::set_enabled_plugins('nonexistingplugin,html5video');
|
||||
$manager = new core_media_manager_test();
|
||||
$this->assertSame('html5video', $manager->get_players_test());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for core_media_renderer can_embed_url
|
||||
*/
|
||||
public function test_can_embed_url() {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// All players are initially disabled, so mp4 cannot be rendered.
|
||||
$url = new moodle_url('http://example.org/test.mp4');
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertFalse($renderer->can_embed_url($url));
|
||||
$manager = core_media_manager::instance();
|
||||
$this->assertFalse($manager->can_embed_url($url));
|
||||
|
||||
// Enable QT player.
|
||||
$CFG->core_media_enable_qt = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertTrue($renderer->can_embed_url($url));
|
||||
// Enable VideoJS player.
|
||||
\core\plugininfo\media::set_enabled_plugins('videojs');
|
||||
$manager = core_media_manager::instance();
|
||||
$this->assertTrue($manager->can_embed_url($url));
|
||||
|
||||
// QT + html5.
|
||||
$CFG->core_media_enable_html5video = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertTrue($renderer->can_embed_url($url));
|
||||
// VideoJS + html5.
|
||||
\core\plugininfo\media::set_enabled_plugins('videojs,html5video');
|
||||
$manager = core_media_manager::instance();
|
||||
$this->assertTrue($manager->can_embed_url($url));
|
||||
|
||||
// Only html5.
|
||||
$CFG->core_media_enable_qt = false;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertTrue($renderer->can_embed_url($url));
|
||||
\core\plugininfo\media::set_enabled_plugins('html5video');
|
||||
$manager = core_media_manager::instance();
|
||||
$this->assertTrue($manager->can_embed_url($url));
|
||||
|
||||
// Only WMP.
|
||||
$CFG->core_media_enable_html5video = false;
|
||||
$CFG->core_media_enable_wmp = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$this->assertFalse($renderer->can_embed_url($url));
|
||||
// Only SWF.
|
||||
\core\plugininfo\media::set_enabled_plugins('swf');
|
||||
$manager = core_media_manager::instance();
|
||||
$this->assertFalse($manager->can_embed_url($url));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,73 +192,68 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Checks multiple format/fallback support.
|
||||
*/
|
||||
public function test_embed_url_fallbacks() {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Key strings in the embed code that identify with the media formats being tested.
|
||||
$qt = 'qtplugin.cab';
|
||||
$swf = '</object>';
|
||||
$html5video = '</video>';
|
||||
$html5audio = '</audio>';
|
||||
$link = 'mediafallbacklink';
|
||||
$mp3 = 'mediaplugin_mp3';
|
||||
$test = 'mediaplugin_test';
|
||||
|
||||
$url = new moodle_url('http://example.org/test.mp4');
|
||||
|
||||
// All plugins disabled, NOLINK option.
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$t = $renderer->embed_url($url, 0, 0, '',
|
||||
array(core_media::OPTION_NO_LINK => true));
|
||||
\core\plugininfo\media::set_enabled_plugins('');
|
||||
$manager = core_media_manager::instance();
|
||||
$t = $manager->embed_url($url, 0, 0, '',
|
||||
array(core_media_manager::OPTION_NO_LINK => true));
|
||||
// Completely empty.
|
||||
$this->assertSame('', $t);
|
||||
|
||||
// All plugins disabled but not NOLINK.
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$t = $renderer->embed_url($url);
|
||||
\core\plugininfo\media::set_enabled_plugins('');
|
||||
$manager = core_media_manager::instance();
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains($link, $t);
|
||||
|
||||
// Enable media players that can play the same media formats. (ie. qt & html5video for mp4 files, etc.)
|
||||
$CFG->core_media_enable_html5video = true;
|
||||
$CFG->core_media_enable_html5audio = true;
|
||||
$CFG->core_media_enable_mp3 = true;
|
||||
$CFG->core_media_enable_qt = true;
|
||||
// Enable media players that can play the same media formats. (ie. test & html5audio for mp3 files, etc.)
|
||||
\core\plugininfo\media::set_enabled_plugins('html5video,html5audio,test,swf');
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
// Test media formats that can be played by 2 or more players.
|
||||
$mediaformats = array('mp3', 'm4a', 'mp4', 'm4v');
|
||||
$mediaformats = array('mp3', 'mp4');
|
||||
|
||||
foreach ($mediaformats as $format) {
|
||||
$url = new moodle_url('http://example.org/test.' . $format);
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
$textwithlink = $renderer->embed_url($url);
|
||||
$textwithoutlink = $renderer->embed_url($url, 0, 0, '', array(core_media::OPTION_NO_LINK => true));
|
||||
$textwithlink = $manager->embed_url($url);
|
||||
$textwithoutlink = $manager->embed_url($url, 0, 0, '', array(core_media_manager::OPTION_NO_LINK => true));
|
||||
|
||||
switch ($format) {
|
||||
case 'mp3':
|
||||
$this->assertContains($mp3, $textwithlink);
|
||||
$this->assertContains($test, $textwithlink);
|
||||
$this->assertNotContains($html5video, $textwithlink);
|
||||
$this->assertContains($html5audio, $textwithlink);
|
||||
$this->assertNotContains($swf, $textwithlink);
|
||||
$this->assertContains($link, $textwithlink);
|
||||
|
||||
$this->assertContains($mp3, $textwithoutlink);
|
||||
$this->assertContains($html5audio, $textwithoutlink);
|
||||
$this->assertNotContains($link, $textwithoutlink);
|
||||
break;
|
||||
|
||||
case 'm4a':
|
||||
$this->assertContains($qt, $textwithlink);
|
||||
$this->assertContains($html5audio, $textwithlink);
|
||||
$this->assertContains($link, $textwithlink);
|
||||
|
||||
$this->assertContains($qt, $textwithoutlink);
|
||||
$this->assertContains($test, $textwithoutlink);
|
||||
$this->assertNotContains($html5video, $textwithoutlink);
|
||||
$this->assertContains($html5audio, $textwithoutlink);
|
||||
$this->assertNotContains($swf, $textwithoutlink);
|
||||
$this->assertNotContains($link, $textwithoutlink);
|
||||
break;
|
||||
|
||||
case 'mp4':
|
||||
case 'm4v':
|
||||
$this->assertContains($qt, $textwithlink);
|
||||
$this->assertContains($test, $textwithlink);
|
||||
$this->assertContains($html5video, $textwithlink);
|
||||
$this->assertNotContains($html5audio, $textwithlink);
|
||||
$this->assertNotContains($swf, $textwithlink);
|
||||
$this->assertContains($link, $textwithlink);
|
||||
|
||||
$this->assertContains($qt, $textwithoutlink);
|
||||
$this->assertContains($test, $textwithoutlink);
|
||||
$this->assertContains($html5video, $textwithoutlink);
|
||||
$this->assertNotContains($html5audio, $textwithoutlink);
|
||||
$this->assertNotContains($swf, $textwithoutlink);
|
||||
$this->assertNotContains($link, $textwithoutlink);
|
||||
break;
|
||||
|
||||
|
@ -296,140 +268,37 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Check SWF works including the special option required to enable it
|
||||
*/
|
||||
public function test_embed_url_swf() {
|
||||
global $CFG, $PAGE;
|
||||
$CFG->core_media_enable_swf = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
\core\plugininfo\media::set_enabled_plugins('swf');
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
// Without any options...
|
||||
$url = new moodle_url('http://example.org/test.swf');
|
||||
$t = $renderer->embed_url($url);
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertNotContains('</object>', $t);
|
||||
|
||||
// ...and with the 'no it's safe, I checked it' option.
|
||||
$url = new moodle_url('http://example.org/test.swf');
|
||||
$t = $renderer->embed_url($url, '', 0, 0, array(core_media::OPTION_TRUSTED => true));
|
||||
$t = $manager->embed_url($url, '', 0, 0, array(core_media_manager::OPTION_TRUSTED => true));
|
||||
$this->assertContains('</object>', $t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for core_media_renderer embed_url.
|
||||
* Exercises all the basic formats not covered elsewhere.
|
||||
*/
|
||||
public function test_embed_url_other_formats() {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Enable all players and get renderer.
|
||||
$CFG->core_media_enable_html5audio = true;
|
||||
$CFG->core_media_enable_mp3 = true;
|
||||
$CFG->core_media_enable_flv = true;
|
||||
$CFG->core_media_enable_wmp = true;
|
||||
$CFG->core_media_enable_rm = true;
|
||||
$CFG->core_media_enable_youtube = true;
|
||||
$CFG->core_media_enable_vimeo = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
|
||||
// Check each format one at a time. This is a basic check to be sure
|
||||
// the HTML is included for files of the right type, not a test that
|
||||
// the HTML itself is correct.
|
||||
|
||||
// Format: mp3.
|
||||
$url = new moodle_url('http://example.org/test.mp3');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('core_media_mp3_', $t);
|
||||
|
||||
// Format: flv.
|
||||
$url = new moodle_url('http://example.org/test.flv');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('core_media_flv_', $t);
|
||||
|
||||
// Format: wmp.
|
||||
$url = new moodle_url('http://example.org/test.avi');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('6BF52A52-394A-11d3-B153-00C04F79FAA6', $t);
|
||||
|
||||
// Format: rm.
|
||||
$url = new moodle_url('http://example.org/test.rm');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA', $t);
|
||||
|
||||
// Format: youtube.
|
||||
$url = new moodle_url('http://www.youtube.com/watch?v=vyrwMmsufJc');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$url = new moodle_url('http://www.youtube.com/v/vyrwMmsufJc');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
|
||||
// Format: youtube video within playlist.
|
||||
$url = new moodle_url('https://www.youtube.com/watch?v=dv2f_xfmbD8&index=4&list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$this->assertContains('list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0', $t);
|
||||
|
||||
// Format: youtube video with start time.
|
||||
$url = new moodle_url('https://www.youtube.com/watch?v=JNJMF1l3udM&t=1h11s');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$this->assertContains('start=3611', $t);
|
||||
|
||||
// Format: youtube video within playlist with start time.
|
||||
$url = new moodle_url('https://www.youtube.com/watch?v=dv2f_xfmbD8&index=4&list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0&t=1m5s');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$this->assertContains('list=PLxcO_MFWQBDcyn9xpbmx601YSDlDcTcr0', $t);
|
||||
$this->assertContains('start=65', $t);
|
||||
|
||||
// Format: youtube video with invalid parameter values (injection attempts).
|
||||
$url = new moodle_url('https://www.youtube.com/watch?v=dv2f_xfmbD8&index=4&list=PLxcO_">');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$this->assertNotContains('list=PLxcO_', $t); // We shouldn't get a list param as input was invalid.
|
||||
$url = new moodle_url('https://www.youtube.com/watch?v=JNJMF1l3udM&t=">');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$this->assertNotContains('start=', $t); // We shouldn't get a start param as input was invalid.
|
||||
|
||||
// Format: youtube playlist.
|
||||
$url = new moodle_url('http://www.youtube.com/view_play_list?p=PL6E18E2927047B662');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$url = new moodle_url('http://www.youtube.com/playlist?list=PL6E18E2927047B662');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
$url = new moodle_url('http://www.youtube.com/p/PL6E18E2927047B662');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
|
||||
// Format: vimeo.
|
||||
$url = new moodle_url('http://vimeo.com/1176321');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</iframe>', $t);
|
||||
|
||||
// Format: html5audio.
|
||||
$this->pretend_to_be_firefox();
|
||||
$url = new moodle_url('http://example.org/test.ogg');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('</audio>', $t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as test_embed_url MP3 test, but for slash arguments.
|
||||
*/
|
||||
public function test_slash_arguments() {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Again we do not turn slasharguments actually on, because it has to
|
||||
// work regardless of the setting of that variable in case of handling
|
||||
// links created using previous setting.
|
||||
|
||||
// Enable MP3 and get renderer.
|
||||
$CFG->core_media_enable_mp3 = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
// Enable player.
|
||||
\core\plugininfo\media::set_enabled_plugins('html5audio');
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
// Format: mp3.
|
||||
$url = new moodle_url('http://example.org/pluginfile.php?file=x/y/z/test.mp3');
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('core_media_mp3_', $t);
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('</audio>', $t);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -437,23 +306,21 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Checks the EMBED_OR_BLANK option.
|
||||
*/
|
||||
public function test_embed_or_blank() {
|
||||
global $CFG, $PAGE;
|
||||
$CFG->core_media_enable_html5audio = true;
|
||||
\core\plugininfo\media::set_enabled_plugins('html5audio');
|
||||
$manager = core_media_manager::instance();
|
||||
$this->pretend_to_be_firefox();
|
||||
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
|
||||
$options = array(core_media::OPTION_FALLBACK_TO_BLANK => true);
|
||||
$options = array(core_media_manager::OPTION_FALLBACK_TO_BLANK => true);
|
||||
|
||||
// Embed that does match something should still include the link too.
|
||||
$url = new moodle_url('http://example.org/test.ogg');
|
||||
$t = $renderer->embed_url($url, '', 0, 0, $options);
|
||||
$t = $manager->embed_url($url, '', 0, 0, $options);
|
||||
$this->assertContains('</audio>', $t);
|
||||
$this->assertContains('mediafallbacklink', $t);
|
||||
|
||||
// Embed that doesn't match something should be totally blank.
|
||||
$url = new moodle_url('http://example.org/test.mp4');
|
||||
$t = $renderer->embed_url($url, '', 0, 0, $options);
|
||||
$t = $manager->embed_url($url, '', 0, 0, $options);
|
||||
$this->assertSame('', $t);
|
||||
}
|
||||
|
||||
|
@ -463,29 +330,29 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* size support in html5video output.
|
||||
*/
|
||||
public function test_embed_url_size() {
|
||||
global $CFG, $PAGE;
|
||||
global $CFG;
|
||||
|
||||
// Technically this could break in every format and they handle size
|
||||
// in several different ways, but I'm too lazy to test it in every
|
||||
// format, so let's just pick one to check the values get passed
|
||||
// through.
|
||||
$CFG->core_media_enable_html5video = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
\core\plugininfo\media::set_enabled_plugins('html5video');
|
||||
$manager = core_media_manager::instance();
|
||||
$url = new moodle_url('http://example.org/test.mp4');
|
||||
|
||||
// HTML5 default size - specifies core width and does not specify height.
|
||||
$t = $renderer->embed_url($url);
|
||||
$this->assertContains('width="' . CORE_MEDIA_VIDEO_WIDTH . '"', $t);
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('width="' . $CFG->media_default_width . '"', $t);
|
||||
$this->assertNotContains('height', $t);
|
||||
|
||||
// HTML5 specified size - specifies both.
|
||||
$t = $renderer->embed_url($url, '', '666', '101');
|
||||
$t = $manager->embed_url($url, '', '666', '101');
|
||||
$this->assertContains('width="666"', $t);
|
||||
$this->assertContains('height="101"', $t);
|
||||
|
||||
// HTML5 size specified in url, overrides call.
|
||||
$url = new moodle_url('http://example.org/test.mp4?d=123x456');
|
||||
$t = $renderer->embed_url($url, '', '666', '101');
|
||||
$t = $manager->embed_url($url, '', '666', '101');
|
||||
$this->assertContains('width="123"', $t);
|
||||
$this->assertContains('height="456"', $t);
|
||||
}
|
||||
|
@ -496,20 +363,18 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* name support in html5video output.
|
||||
*/
|
||||
public function test_embed_url_name() {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// As for size this could break in every format but I'm only testing
|
||||
// html5video.
|
||||
$CFG->core_media_enable_html5video = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
\core\plugininfo\media::set_enabled_plugins('html5video');
|
||||
$manager = core_media_manager::instance();
|
||||
$url = new moodle_url('http://example.org/test.mp4');
|
||||
|
||||
// HTML5 default name - use filename.
|
||||
$t = $renderer->embed_url($url);
|
||||
$t = $manager->embed_url($url);
|
||||
$this->assertContains('title="test.mp4"', $t);
|
||||
|
||||
// HTML5 specified name - check escaping.
|
||||
$t = $renderer->embed_url($url, 'frog & toad');
|
||||
$t = $manager->embed_url($url, 'frog & toad');
|
||||
$this->assertContains('title="frog & toad"', $t);
|
||||
}
|
||||
|
||||
|
@ -517,9 +382,11 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Test for core_media_renderer split_alternatives.
|
||||
*/
|
||||
public function test_split_alternatives() {
|
||||
$mediamanager = core_media_manager::instance();
|
||||
|
||||
// Single URL - identical moodle_url.
|
||||
$mp4 = 'http://example.org/test.mp4';
|
||||
$result = core_media::split_alternatives($mp4, $w, $h);
|
||||
$result = $mediamanager->split_alternatives($mp4, $w, $h);
|
||||
$this->assertEquals($mp4, $result[0]->out(false));
|
||||
|
||||
// Width and height weren't specified.
|
||||
|
@ -528,20 +395,20 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
|
||||
// Two URLs - identical moodle_urls.
|
||||
$webm = 'http://example.org/test.webm';
|
||||
$result = core_media::split_alternatives("$mp4#$webm", $w, $h);
|
||||
$result = $mediamanager->split_alternatives("$mp4#$webm", $w, $h);
|
||||
$this->assertEquals($mp4, $result[0]->out(false));
|
||||
$this->assertEquals($webm, $result[1]->out(false));
|
||||
|
||||
// Two URLs plus dimensions.
|
||||
$size = 'd=400x280';
|
||||
$result = core_media::split_alternatives("$mp4#$webm#$size", $w, $h);
|
||||
$result = $mediamanager->split_alternatives("$mp4#$webm#$size", $w, $h);
|
||||
$this->assertEquals($mp4, $result[0]->out(false));
|
||||
$this->assertEquals($webm, $result[1]->out(false));
|
||||
$this->assertEquals(400, $w);
|
||||
$this->assertEquals(280, $h);
|
||||
|
||||
// Two URLs plus legacy dimensions (use last one).
|
||||
$result = core_media::split_alternatives("$mp4?d=1x1#$webm?$size", $w, $h);
|
||||
$result = $mediamanager->split_alternatives("$mp4?d=1x1#$webm?$size", $w, $h);
|
||||
$this->assertEquals($mp4, $result[0]->out(false));
|
||||
$this->assertEquals($webm, $result[1]->out(false));
|
||||
$this->assertEquals(400, $w);
|
||||
|
@ -552,83 +419,50 @@ class core_medialib_testcase extends advanced_testcase {
|
|||
* Test for core_media_renderer embed_alternatives (with multiple urls)
|
||||
*/
|
||||
public function test_embed_alternatives() {
|
||||
global $PAGE, $CFG;
|
||||
|
||||
// Most aspects of this are same as single player so let's just try
|
||||
// a single typical / complicated scenario.
|
||||
|
||||
// MP3, WebM and FLV.
|
||||
// MP4, OGV, WebM and FLV.
|
||||
$urls = array(
|
||||
new moodle_url('http://example.org/test.mp4'),
|
||||
new moodle_url('http://example.org/test.ogv'),
|
||||
new moodle_url('http://example.org/test.webm'),
|
||||
new moodle_url('http://example.org/test.flv'),
|
||||
);
|
||||
|
||||
// Enable html5 and flv.
|
||||
$CFG->core_media_enable_html5video = true;
|
||||
$CFG->core_media_enable_flv = true;
|
||||
$renderer = new core_media_renderer_test($PAGE, '');
|
||||
// Enable html5 and "test" ("test" first).
|
||||
\core\plugininfo\media::set_enabled_plugins('test,html5video');
|
||||
$manager = core_media_manager::instance();
|
||||
|
||||
// Result should contain HTML5 with two sources + FLV.
|
||||
$t = $renderer->embed_alternatives($urls);
|
||||
$t = $manager->embed_alternatives($urls);
|
||||
|
||||
// HTML5 sources - mp4, not flv or webm (not supported in Safari).
|
||||
// HTML5 sources - mp4, but not ogv, flv or webm (not supported in Safari).
|
||||
$this->assertContains('<source src="http://example.org/test.mp4"', $t);
|
||||
$this->assertNotContains('<source src="http://example.org/test.ogv"', $t);
|
||||
$this->assertNotContains('<source src="http://example.org/test.webm"', $t);
|
||||
$this->assertNotContains('<source src="http://example.org/test.flv"', $t);
|
||||
|
||||
// FLV is before the video tag (indicating html5 is used as fallback to flv
|
||||
// and not vice versa).
|
||||
$this->assertTrue((bool)preg_match('~core_media_flv_.*<video~s', $t));
|
||||
$this->assertTrue((bool)preg_match('~mediaplugin_test.*<video~s', $t));
|
||||
|
||||
// Do same test with firefox and check we get the webm and not mp4.
|
||||
$this->pretend_to_be_firefox();
|
||||
$t = $renderer->embed_alternatives($urls);
|
||||
$t = $manager->embed_alternatives($urls);
|
||||
|
||||
// HTML5 sources - webm, not not flv or mp4 (not supported in Firefox).
|
||||
$this->assertNotContains('<source src="http://example.org/test.mp4"', $t);
|
||||
// HTML5 sources - mp4, ogv and webm, but not flv.
|
||||
$this->assertContains('<source src="http://example.org/test.mp4"', $t);
|
||||
$this->assertContains('<source src="http://example.org/test.ogv"', $t);
|
||||
$this->assertContains('<source src="http://example.org/test.webm"', $t);
|
||||
$this->assertNotContains('<source src="http://example.org/test.flv"', $t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts moodle_url array into a single comma-separated string for
|
||||
* easier testing.
|
||||
*
|
||||
* @param array $urls Array of moodle_urls
|
||||
* @return string String containing those URLs, comma-separated
|
||||
*/
|
||||
public static function string_urls($urls) {
|
||||
$out = array();
|
||||
foreach ($urls as $url) {
|
||||
$out[] = $url->out(false);
|
||||
}
|
||||
return implode(',', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts associative array into a semicolon-separated string for easier
|
||||
* testing.
|
||||
*
|
||||
* @param array $options Associative array
|
||||
* @return string String of form 'a=b;c=d'
|
||||
*/
|
||||
public static function string_options($options) {
|
||||
$out = '';
|
||||
foreach ($options as $key => $value) {
|
||||
if ($out) {
|
||||
$out .= ';';
|
||||
}
|
||||
$out .= "$key=$value";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Media player stub for testing purposes.
|
||||
*/
|
||||
class core_media_player_test extends core_media_player {
|
||||
class media_test_plugin extends core_media_player {
|
||||
/** @var array Array of supported extensions */
|
||||
public $ext;
|
||||
/** @var int Player rank */
|
||||
|
@ -641,15 +475,17 @@ class core_media_player_test extends core_media_player {
|
|||
* @param int $rank Player rank
|
||||
* @param array $ext Array of supported extensions
|
||||
*/
|
||||
public function __construct($num = 1, $rank = 13, $ext = array('tst', 'test')) {
|
||||
public function __construct($num = 1, $rank = 13, $ext = array('mp3', 'flv', 'f4v', 'mp4')) {
|
||||
$this->ext = $ext;
|
||||
$this->rank = $rank;
|
||||
$this->num = $num;
|
||||
}
|
||||
|
||||
public function embed($urls, $name, $width, $height, $options) {
|
||||
return $this->num . ':' . medialib_test::string_urls($urls) .
|
||||
",$name,$width,$height,<!--FALLBACK-->," . medialib_test::string_options($options);
|
||||
self::pick_video_size($width, $height);
|
||||
$contents = "\ntestsource=". join("\ntestsource=", $urls) .
|
||||
"\ntestname=$name\ntestwidth=$width\ntestheight=$height\n<!--FALLBACK-->\n";
|
||||
return html_writer::span($contents, 'mediaplugin mediaplugin_test');
|
||||
}
|
||||
|
||||
public function get_supported_extensions() {
|
||||
|
@ -657,14 +493,14 @@ class core_media_player_test extends core_media_player {
|
|||
}
|
||||
|
||||
public function get_rank() {
|
||||
return $this->rank;
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Media renderer override for testing purposes.
|
||||
*/
|
||||
class core_media_renderer_test extends core_media_renderer {
|
||||
class core_media_manager_test extends core_media_manager {
|
||||
/**
|
||||
* Access list of players as string, shortening it by getting rid of
|
||||
* repeated text.
|
||||
|
@ -677,7 +513,7 @@ class core_media_renderer_test extends core_media_renderer {
|
|||
if ($out) {
|
||||
$out .= ', ';
|
||||
}
|
||||
$out .= str_replace('core_media_player_', '', get_class($player));
|
||||
$out .= str_replace('core_media_player_', '', preg_replace('/^media_(.*)_plugin$/', '$1', get_class($player)));
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
|
|
@ -70,13 +70,6 @@
|
|||
<version>1.0.8</version>
|
||||
<licenseversion></licenseversion>
|
||||
</library>
|
||||
<library>
|
||||
<location>flowplayer</location>
|
||||
<name>Flowplayer</name>
|
||||
<license>GPL</license>
|
||||
<version>3.2.18</version>
|
||||
<licenseversion>3.0+</licenseversion>
|
||||
</library>
|
||||
<library>
|
||||
<location>pear/Auth/RADIUS.php</location>
|
||||
<name>Pear_Auth_Radius</name>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue