2
// This file is part of Moodle - http://moodle.org/
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18
* Classes for handling embedded media (mainly audio and video).
20
* These are used only from within the core media renderer.
22
* To embed media from Moodle code, do something like the following:
24
* $mediarenderer = $PAGE->get_renderer('core', 'media');
25
* echo $mediarenderer->embed_url(new moodle_url('http://example.org/a.mp3'));
27
* You do not need to require this library file manually. Getting the renderer
28
* (the first line above) requires this library file automatically.
31
* @copyright 2012 The Open University
32
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
defined('MOODLE_INTERNAL') || die();
37
if (!defined('CORE_MEDIA_VIDEO_WIDTH')) {
38
// Default video width if no width is specified; some players may do something
39
// more intelligent such as use real video width.
40
// May be defined in config.php if required.
41
define('CORE_MEDIA_VIDEO_WIDTH', 400);
43
if (!defined('CORE_MEDIA_VIDEO_HEIGHT')) {
44
// Default video height. May be defined in config.php if required.
45
define('CORE_MEDIA_VIDEO_HEIGHT', 300);
47
if (!defined('CORE_MEDIA_AUDIO_WIDTH')) {
48
// Default audio width if no width is specified.
49
// May be defined in config.php if required.
50
define('CORE_MEDIA_AUDIO_WIDTH', 300);
55
* Constants and static utility functions for use with core_media_renderer.
57
* @copyright 2011 The Open University
58
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
60
abstract class core_media {
62
* Option: Disable text link fallback.
64
* Use this option if you are going to print a visible link anyway so it is
65
* pointless to have one as fallback.
67
* To enable, set value to true.
69
const OPTION_NO_LINK = 'nolink';
72
* Option: When embedding, if there is no matching embed, do not use the
73
* default link fallback player; instead return blank.
75
* This is different from OPTION_NO_LINK because this option still uses the
76
* fallback link if there is some kind of embedding. Use this option if you
77
* are going to check if the return value is blank and handle it specially.
79
* To enable, set value to true.
81
const OPTION_FALLBACK_TO_BLANK = 'embedorblank';
84
* Option: Enable players which are only suitable for use when we trust the
85
* user who embedded the content.
87
* At present, this option enables the SWF player.
89
* To enable, set value to true.
91
const OPTION_TRUSTED = 'trusted';
94
* Option: Put a div around the output (if not blank) so that it displays
95
* as a block using the 'resourcecontent' CSS class.
97
* To enable, set value to true.
99
const OPTION_BLOCK = 'block';
102
* Given a string containing multiple URLs separated by #, this will split
103
* it into an array of moodle_url objects suitable for using when calling
104
* embed_alternatives.
106
* Note that the input string should NOT be html-escaped (i.e. if it comes
107
* from html, call html_entity_decode first).
109
* @param string $combinedurl String of 1 or more alternatives separated by #
110
* @param int $width Output variable: width (will be set to 0 if not specified)
111
* @param int $height Output variable: height (0 if not specified)
112
* @return array Array of 1 or more moodle_url objects
114
public static function split_alternatives($combinedurl, &$width, &$height) {
115
$urls = explode('#', $combinedurl);
118
$returnurls = array();
120
foreach ($urls as $url) {
123
// You can specify the size as a separate part of the array like
124
// #d=640x480 without actually including a url in it.
125
if (preg_match('/^d=([\d]{1,4})x([\d]{1,4})$/i', $url, $matches)) {
126
$width = $matches[1];
127
$height = $matches[2];
131
// Can also include the ?d= as part of one of the URLs (if you use
132
// more than one they will be ignored except the last).
133
if (preg_match('/\?d=([\d]{1,4})x([\d]{1,4})$/i', $url, $matches)) {
134
$width = $matches[1];
135
$height = $matches[2];
138
$url = str_replace($matches[0], '', $url);
142
$url = clean_param($url, PARAM_URL);
147
// Turn it into moodle_url object.
148
$returnurls[] = new moodle_url($url);
155
* Returns the file extension for a URL.
156
* @param moodle_url $url URL
158
public static function get_extension(moodle_url $url) {
159
// Note: Does not use textlib (. is UTF8-safe).
160
$filename = self::get_filename($url);
161
$dot = strrpos($filename, '.');
162
if ($dot === false) {
165
return strtolower(substr($filename, $dot + 1));
170
* Obtains the filename from the moodle_url.
171
* @param moodle_url $url URL
172
* @return string Filename only (not escaped)
174
public static function get_filename(moodle_url $url) {
177
// Use the 'file' parameter if provided (for links created when
178
// slasharguments was off). If not present, just use URL path.
179
$path = $url->get_param('file');
181
$path = $url->get_path();
184
// Remove everything before last / if present. Does not use textlib as / is UTF8-safe.
185
$slash = strrpos($path, '/');
186
if ($slash !== false) {
187
$path = substr($path, $slash + 1);
193
* Guesses MIME type for a moodle_url based on file extension.
194
* @param moodle_url $url URL
195
* @return string MIME type
197
public static function get_mimetype(moodle_url $url) {
198
return mimeinfo('type', self::get_filename($url));
204
* Base class for media players.
206
* Media players return embed HTML for a particular way of playing back audio
207
* or video (or another file type).
209
* In order to make the code more lightweight, this is not a plugin type
210
* (players cannot have their own settings, database tables, capabilities, etc).
211
* These classes are used only by core_media_renderer in outputrenderers.php.
212
* If you add a new class here (in core code) you must modify the
213
* get_players_raw function in that file to include it.
215
* If a Moodle installation wishes to add extra player objects they can do so
216
* by overriding that renderer in theme, and overriding the get_players_raw
217
* function. The new player class should then of course be defined within the
218
* custom theme or other suitable location, not in this file.
220
* @copyright 2011 The Open University
221
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
223
abstract class core_media_player {
225
* Placeholder text used to indicate where the fallback content is placed
228
const PLACEHOLDER = '<!--FALLBACK-->';
231
* Generates code required to embed the player.
233
* The returned code contains a placeholder comment '<!--FALLBACK-->'
234
* (constant core_media_player::PLACEHOLDER) which indicates the location
235
* where fallback content should be placed in the event that this type of
236
* player is not supported by user browser.
238
* The $urls parameter includes one or more alternative media formats that
239
* are supported by this player. It does not include formats that aren't
240
* supported (see list_supported_urls).
242
* The $options array contains key-value pairs. See OPTION_xx constants
243
* for documentation of standard option(s).
245
* @param array $urls URLs of media files
246
* @param string $name Display name; '' to use default
247
* @param int $width Optional width; 0 to use default
248
* @param int $height Optional height; 0 to use default
249
* @param array $options Options array
250
* @return string HTML code for embed
252
public abstract function embed($urls, $name, $width, $height, $options);
255
* Gets the list of file extensions supported by this media player.
257
* Note: This is only required for the default implementation of
258
* list_supported_urls. If you override that function to determine
259
* supported URLs in some way other than by extension, then this function
262
* @return array Array of strings (extension not including dot e.g. 'mp3')
264
public function get_supported_extensions() {
269
* Lists keywords that must be included in a url that can be embedded with
270
* this player. Any such keywords should be added to the array.
272
* For example if this player supports FLV and F4V files then it should add
273
* '.flv' and '.f4v' to the array. (The check is not case-sensitive.)
275
* Default handling calls the get_supported_extensions function and adds
276
* a dot to each of those values, so players only need to override this
277
* if they don't implement get_supported_extensions.
279
* This is used to improve performance when matching links in the media filter.
281
* @return array Array of keywords to add to the embeddable markers list
283
public function get_embeddable_markers() {
285
foreach ($this->get_supported_extensions() as $extension) {
286
$markers[] = '.' . $extension;
292
* Gets the ranking of this player. This is an integer used to decide which
293
* player to use (after applying other considerations such as which ones
294
* the user has disabled).
296
* Rank must be unique (no two players should have the same rank).
298
* Rank zero has a special meaning, indicating that this 'player' does not
299
* really embed the video.
301
* Rank is not a user-configurable value because it needs to be defined
302
* carefully in order to ensure that the embedding fallbacks actually work.
303
* It might be possible to have some user options which affect rank, but
304
* these would be best defined as e.g. checkboxes in settings that have
305
* a particular effect on the rank of a couple of plugins, rather than
306
* letting users generally alter rank.
308
* Note: Within medialib.php, players are listed in rank order (highest
311
* @return int Rank (higher is better)
313
public abstract function get_rank();
316
* @return bool True if player is enabled
318
public function is_enabled() {
321
// With the class core_media_player_html5video it is enabled
322
// based on $CFG->core_media_enable_html5video.
323
$setting = str_replace('_player_', '_enable_', get_class($this));
324
return !empty($CFG->{$setting});
328
* Given a list of URLs, returns a reduced array containing only those URLs
329
* which are supported by this player. (Empty if none.)
330
* @param array $urls Array of moodle_url
331
* @param array $options Options (same as will be passed to embed)
332
* @return array Array of supported moodle_url
334
public function list_supported_urls(array $urls, array $options = array()) {
335
$extensions = $this->get_supported_extensions();
337
foreach ($urls as $url) {
338
if (in_array(core_media::get_extension($url), $extensions)) {
346
* Obtains suitable name for media. Uses specified name if there is one,
347
* otherwise makes one up.
348
* @param string $name User-specified name ('' if none)
349
* @param array $urls Array of moodle_url used to make up name
350
* @return string Name
352
protected function get_name($name, $urls) {
353
// If there is a specified name, use that.
358
// Get filename of first URL.
360
$name = core_media::get_filename($url);
362
// If there is more than one url, strip the extension as we could be
363
// referring to a different one or several at once.
364
if (count($urls) > 1) {
365
$name = preg_replace('~\.[^.]*$~', '', $name);
372
* Compares by rank order, highest first. Used for sort functions.
373
* @param core_media_player $a Player A
374
* @param core_media_player $b Player B
375
* @return int Negative if A should go before B, positive for vice versa
377
public static function compare_by_rank(core_media_player $a, core_media_player $b) {
378
return $b->get_rank() - $a->get_rank();
382
* Utility function that sets width and height to defaults if not specified
383
* as a parameter to the function (will be specified either if, (a) the calling
384
* code passed it, or (b) the URL included it).
385
* @param int $width Width passed to function (updated with final value)
386
* @param int $height Height passed to function (updated with final value)
388
protected static function pick_video_size(&$width, &$height) {
390
$width = CORE_MEDIA_VIDEO_WIDTH;
391
$height = CORE_MEDIA_VIDEO_HEIGHT;
398
* Base class for players which handle external links (YouTube etc).
400
* As opposed to media files.
402
* @copyright 2011 The Open University
403
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
405
abstract class core_media_player_external extends core_media_player {
407
* Array of matches from regular expression - subclass can assume these
408
* will be valid when the embed function is called, to save it rerunning
415
* Part of a regular expression, including ending ~ symbol (note: these
416
* regexes use ~ instead of / because URLs and HTML code typically include
417
* / symbol and makes harder to read if you have to escape it).
418
* Matches the end part of a link after you have read the 'important' data
419
* including optional #d=400x300 at end of url, plus content of <a> tag,
423
const END_LINK_REGEX_PART = '[^#]*(#d=([\d]{1,4})x([\d]{1,4}))?~si';
425
public function embed($urls, $name, $width, $height, $options) {
426
return $this->embed_external(reset($urls), $name, $width, $height, $options);
430
* Obtains HTML code to embed the link.
431
* @param moodle_url $url Single URL to embed
432
* @param string $name Display name; '' to use default
433
* @param int $width Optional width; 0 to use default
434
* @param int $height Optional height; 0 to use default
435
* @param array $options Options array
436
* @return string HTML code for embed
438
protected abstract function embed_external(moodle_url $url, $name, $width, $height, $options);
440
public function list_supported_urls(array $urls, array $options = array()) {
441
// These only work with a SINGLE url (there is no fallback).
442
if (count($urls) != 1) {
447
// Check against regex.
448
if (preg_match($this->get_regex(), $url->out(false), $this->matches)) {
456
* Returns regular expression used to match URLs that this player handles
457
* @return string PHP regular expression e.g. '~^https?://example.org/~'
459
protected function get_regex() {
460
return '~^unsupported~';
464
* Annoyingly, preg_match $matches result does not always have the same
465
* number of parameters - it leaves out optional ones at the end. WHAT.
466
* Anyway, this function can be used to fix it.
467
* @param array $matches Array that should be adjusted
468
* @param int $count Number of capturing groups (=6 to make $matches[6] work)
470
protected static function fix_match_count(&$matches, $count) {
471
for ($i = count($matches); $i <= $count; $i++) {
472
$matches[$i] = false;
479
* Player that embeds Vimeo links.
481
* @copyright 2011 The Open University
482
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
484
class core_media_player_vimeo extends core_media_player_external {
485
protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
486
$videoid = $this->matches[1];
489
// Note: resizing via url is not supported, user can click the fullscreen
490
// button instead. iframe embedding is not xhtml strict but it is the only
491
// option that seems to work on most devices.
492
self::pick_video_size($width, $height);
495
<span class="mediaplugin mediaplugin_vimeo">
496
<iframe title="$info" src="https://player.vimeo.com/video/$videoid"
497
width="$width" height="$height" frameborder="0"></iframe>
504
protected function get_regex() {
505
// Initial part of link.
506
$start = '~^https?://vimeo\.com/';
507
// Middle bit: either watch?v= or v/.
508
$middle = '([0-9]+)';
509
return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
512
public function get_rank() {
516
public function get_embeddable_markers() {
517
return array('vimeo.com/');
522
* Player that creates YouTube embedding.
524
* @copyright 2011 The Open University
525
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
527
class core_media_player_youtube extends core_media_player_external {
528
protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
529
$videoid = end($this->matches);
532
if (empty($info) or strpos($info, 'http') === 0) {
533
$info = get_string('siteyoutube', 'core_media');
537
self::pick_video_size($width, $height);
540
<span class="mediaplugin mediaplugin_youtube">
541
<iframe title="$info" width="$width" height="$height"
542
src="https://www.youtube.com/embed/$videoid?rel=0&wmode=transparent" frameborder="0" allowfullscreen="1"></iframe>
548
protected function get_regex() {
549
// Regex for standard youtube link
550
$link = '(youtube(-nocookie)?\.com/(?:watch\?v=|v/))';
551
// Regex for shortened youtube link
552
$shortlink = '((youtu|y2u)\.be/)';
554
// Initial part of link.
555
$start = '~^https?://(www\.)?(' . $link . '|' . $shortlink . ')';
556
// Middle bit: Video key value
557
$middle = '([a-z0-9\-_]+)';
558
return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
561
public function get_rank() {
562
// I decided to make the link-embedding ones (that don't handle file
563
// formats) have ranking in the 1000 range.
567
public function get_embeddable_markers() {
568
return array('youtube.com', 'youtube-nocookie.com', 'youtu.be', 'y2u.be');
574
* Player that creates YouTube playlist embedding.
576
* @copyright 2011 The Open University
577
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
579
class core_media_player_youtube_playlist extends core_media_player_external {
580
public function is_enabled() {
582
// Use the youtube on/off flag.
583
return $CFG->core_media_enable_youtube;
586
protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
587
$site = $this->matches[1];
588
$playlist = $this->matches[3];
591
if (empty($info) or strpos($info, 'http') === 0) {
592
$info = get_string('siteyoutube', 'core_media');
596
self::pick_video_size($width, $height);
599
<span class="mediaplugin mediaplugin_youtube">
600
<iframe width="$width" height="$height" src="https://$site/embed/videoseries?list=$playlist" frameborder="0" allowfullscreen="1"></iframe>
605
protected function get_regex() {
606
// Initial part of link.
607
$start = '~^https?://(www\.youtube(-nocookie)?\.com)/';
608
// Middle bit: either view_play_list?p= or p/ (doesn't work on youtube) or playlist?list=.
609
$middle = '(?:view_play_list\?p=|p/|playlist\?list=)([a-z0-9\-_]+)';
610
return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
613
public function get_rank() {
614
// I decided to make the link-embedding ones (that don't handle file
615
// formats) have ranking in the 1000 range.
619
public function get_embeddable_markers() {
620
return array('youtube');
626
* MP3 player inserted using JavaScript.
628
* @copyright 2011 The Open University
629
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
631
class core_media_player_mp3 extends core_media_player {
632
public function embed($urls, $name, $width, $height, $options) {
633
// Use first url (there can actually be only one unless some idiot
634
// enters two mp3 files as alternatives).
637
// Unique id even across different http requests made at the same time
638
// (for AJAX, iframes).
639
$id = 'core_media_mp3_' . md5(time() . '_' . rand());
641
// When Flash or JavaScript are not available only the fallback is displayed,
642
// using span not div because players are inline elements.
643
$spanparams = array('id' => $id, 'class' => 'mediaplugin mediaplugin_mp3');
645
$spanparams['style'] = 'width: ' . $width . 'px';
647
$output = html_writer::tag('span', core_media_player::PLACEHOLDER, $spanparams);
648
// We can not use standard JS init because this may be cached
649
// note: use 'small' size unless embedding in block mode.
650
$output .= html_writer::script(js_writer::function_call(
651
'M.util.add_audio_player', array($id, $url->out(false),
652
empty($options[core_media::OPTION_BLOCK]))));
657
public function get_supported_extensions() {
661
public function get_rank() {
668
* Flash video player inserted using JavaScript.
670
* @copyright 2011 The Open University
671
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
673
class core_media_player_flv extends core_media_player {
674
public function embed($urls, $name, $width, $height, $options) {
675
// Use first url (there can actually be only one unless some idiot
676
// enters two mp3 files as alternatives).
679
// Unique id even across different http requests made at the same time
680
// (for AJAX, iframes).
681
$id = 'core_media_flv_' . md5(time() . '_' . rand());
683
// Compute width and height.
685
if (!$width && !$height) {
686
$width = CORE_MEDIA_VIDEO_WIDTH;
687
$height = CORE_MEDIA_VIDEO_HEIGHT;
691
// Fallback span (will normally contain link).
692
$output = html_writer::tag('span', core_media_player::PLACEHOLDER,
693
array('id'=>$id, 'class'=>'mediaplugin mediaplugin_flv'));
694
// We can not use standard JS init because this may be cached.
695
$output .= html_writer::script(js_writer::function_call(
696
'M.util.add_video_player', array($id, addslashes_js($url->out(false)),
697
$width, $height, $autosize)));
701
public function get_supported_extensions() {
702
return array('flv', 'f4v');
705
public function get_rank() {
712
* Embeds Windows Media Player using object tag.
714
* @copyright 2011 The Open University
715
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
717
class core_media_player_wmp extends core_media_player {
718
public function embed($urls, $name, $width, $height, $options) {
719
// Get URL (we just use first, probably there is only one).
720
$firsturl = reset($urls);
721
$url = $firsturl->out(false);
724
if (!$width || !$height) {
725
// Object tag has default size.
727
$size = 'width="' . CORE_MEDIA_VIDEO_WIDTH .
728
'" height="' . (CORE_MEDIA_VIDEO_HEIGHT+64) . '"';
731
$size = 'width="' . $width . '" height="' . ($height + 15) . '"';
732
$mpsize = 'width="' . $width . '" height="' . ($height + 64) . '"';
736
// MIME type for object tag.
737
$mimetype = core_media::get_mimetype($firsturl);
739
$fallback = core_media_player::PLACEHOLDER;
743
<span class="mediaplugin mediaplugin_wmp">
744
<object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" $mpsize
745
standby="Loading Microsoft(R) Windows(R) Media Player components..."
746
type="application/x-oleobject">
747
<param name="Filename" value="$url" />
748
<param name="src" value="$url" />
749
<param name="url" value="$url" />
750
<param name="ShowControls" value="true" />
751
<param name="AutoRewind" value="true" />
752
<param name="AutoStart" value="false" />
753
<param name="Autosize" value="$autosize" />
754
<param name="EnableContextMenu" value="true" />
755
<param name="TransparentAtStart" value="false" />
756
<param name="AnimationAtStart" value="false" />
757
<param name="ShowGotoBar" value="false" />
758
<param name="EnableFullScreenControls" value="true" />
759
<param name="uimode" value="full" />
761
<object data="$url" type="$mimetype" $size>
762
<param name="src" value="$url" />
763
<param name="controller" value="true" />
764
<param name="autoplay" value="false" />
765
<param name="autostart" value="false" />
766
<param name="resize" value="scale" />
777
public function get_supported_extensions() {
778
return array('wmv', 'avi');
781
public function get_rank() {
788
* Media player using object tag and QuickTime player.
790
* @copyright 2011 The Open University
791
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
793
class core_media_player_qt extends core_media_player {
794
public function embed($urls, $name, $width, $height, $options) {
796
$firsturl = reset($urls);
797
$url = $firsturl->out(true);
800
if (!$width || !$height) {
801
$size = 'width="' . CORE_MEDIA_VIDEO_WIDTH .
802
'" height="' . (CORE_MEDIA_VIDEO_HEIGHT + 15) . '"';
804
$size = 'width="' . $width . '" height="' . ($height + 15) . '"';
807
// MIME type for object tag.
808
$mimetype = core_media::get_mimetype($firsturl);
810
$fallback = core_media_player::PLACEHOLDER;
814
<span class="mediaplugin mediaplugin_qt">
815
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
816
codebase="http://www.apple.com/qtactivex/qtplugin.cab" $size>
817
<param name="pluginspage" value="http://www.apple.com/quicktime/download/" />
818
<param name="src" value="$url" />
819
<param name="controller" value="true" />
820
<param name="loop" value="true" />
821
<param name="autoplay" value="false" />
822
<param name="autostart" value="false" />
823
<param name="scale" value="aspect" />
825
<object data="$url" type="$mimetype" $size>
826
<param name="src" value="$url" />
827
<param name="pluginurl" value="http://www.apple.com/quicktime/download/" />
828
<param name="controller" value="true" />
829
<param name="loop" value="true" />
830
<param name="autoplay" value="false" />
831
<param name="autostart" value="false" />
832
<param name="scale" value="aspect" />
843
public function get_supported_extensions() {
844
return array('mpg', 'mpeg', 'mov', 'mp4', 'm4v', 'm4a');
847
public function get_rank() {
854
* Media player using object tag and RealPlayer.
856
* Hopefully nobody is using this obsolete format any more!
858
* @copyright 2011 The Open University
859
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
861
class core_media_player_rm extends core_media_player {
862
public function embed($urls, $name, $width, $height, $options) {
864
$firsturl = reset($urls);
865
$url = $firsturl->out(true);
867
// Get name to use as title.
868
$info = s($this->get_name($name, $urls));
870
// The previous version of this code has the following comment, which
871
// I don't understand, but trust it is correct:
872
// Note: the size is hardcoded intentionally because this does not work anyway!
873
$width = CORE_MEDIA_VIDEO_WIDTH;
874
$height = CORE_MEDIA_VIDEO_HEIGHT;
876
$fallback = core_media_player::PLACEHOLDER;
878
<span class="mediaplugin mediaplugin_real">
879
<object title="$info" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"
880
data="$url" width="$width" height="$height"">
881
<param name="src" value="$url" />
882
<param name="controls" value="All" />
884
<object title="$info" type="audio/x-pn-realaudio-plugin"
885
data="$url" width="$width" height="$height">
886
<param name="src" value="$url" />
887
<param name="controls" value="All" />
898
public function get_supported_extensions() {
899
return array('ra', 'ram', 'rm', 'rv');
902
public function get_rank() {
909
* Media player for Flash SWF files.
911
* This player contains additional security restriction: it will only be used
912
* if you add option core_media_player_swf::ALLOW = true.
914
* Code should only set this option if it has verified that the data was
915
* embedded by a trusted user (e.g. in trust text).
917
* @copyright 2011 The Open University
918
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
920
class core_media_player_swf extends core_media_player {
921
public function embed($urls, $name, $width, $height, $options) {
922
self::pick_video_size($width, $height);
924
$firsturl = reset($urls);
925
$url = $firsturl->out(true);
927
$fallback = core_media_player::PLACEHOLDER;
929
<span class="mediaplugin mediaplugin_swf">
930
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="$width" height="$height">
931
<param name="movie" value="$url" />
932
<param name="autoplay" value="true" />
933
<param name="loop" value="true" />
934
<param name="controller" value="true" />
935
<param name="scale" value="aspect" />
936
<param name="base" value="." />
937
<param name="allowscriptaccess" value="never" />
939
<object type="application/x-shockwave-flash" data="$url" width="$width" height="$height">
940
<param name="controller" value="true" />
941
<param name="autoplay" value="true" />
942
<param name="loop" value="true" />
943
<param name="scale" value="aspect" />
944
<param name="base" value="." />
945
<param name="allowscriptaccess" value="never" />
958
public function get_supported_extensions() {
962
public function list_supported_urls(array $urls, array $options = array()) {
963
// Not supported unless the creator is trusted.
964
if (empty($options[core_media::OPTION_TRUSTED])) {
967
return parent::list_supported_urls($urls, $options);
970
public function get_rank() {
977
* Player that creates HTML5 <video> tag.
979
* @copyright 2011 The Open University
980
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
982
class core_media_player_html5video extends core_media_player {
983
public function embed($urls, $name, $width, $height, $options) {
984
// Special handling to make videos play on Android devices pre 2.3.
985
// Note: I tested and 2.3.3 (in emulator) works without, is 533.1 webkit.
986
$oldandroid = check_browser_version('WebKit Android') &&
987
!check_browser_version('WebKit Android', '533.1');
989
// Build array of source tags.
991
foreach ($urls as $url) {
992
$mimetype = core_media::get_mimetype($url);
993
$source = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
994
if ($mimetype === 'video/mp4') {
996
// Old Android fails if you specify the type param.
997
$source = html_writer::tag('source', '', array('src' => $url));
1000
// Better add m4v as first source, it might be a bit more
1001
// compatible with problematic browsers.
1002
array_unshift($sources, $source);
1004
$sources[] = $source;
1008
$sources = implode("\n", $sources);
1009
$title = s($this->get_name($name, $urls));
1012
// No width specified, use system default.
1013
$width = CORE_MEDIA_VIDEO_WIDTH;
1017
// Let browser choose height automatically.
1018
$size = "width=\"$width\"";
1020
$size = "width=\"$width\" height=\"$height\"";
1026
// Old Android does not support 'controls' option.
1027
$id = 'core_media_html5v_' . md5(time() . '_' . rand());
1028
$idtag = 'id="' . $id . '"';
1029
$sillyscript = <<<OET
1030
<script type="text/javascript">
1031
document.getElementById('$id').addEventListener('click', function() {
1038
$fallback = core_media_player::PLACEHOLDER;
1040
<span class="mediaplugin mediaplugin_html5video">
1041
<video $idtag controls="true" $size preload="metadata" title="$title">
1050
public function get_supported_extensions() {
1051
return array('m4v', 'webm', 'ogv', 'mp4');
1054
public function list_supported_urls(array $urls, array $options = array()) {
1055
$extensions = $this->get_supported_extensions();
1057
foreach ($urls as $url) {
1058
$ext = core_media::get_extension($url);
1059
if (in_array($ext, $extensions)) {
1060
// Unfortunately html5 video does not handle fallback properly.
1061
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=10975
1062
// That means we need to do browser detect and not use html5 on
1063
// browsers which do not support the given type, otherwise users
1064
// will not even see the fallback link.
1065
// Based on http://en.wikipedia.org/wiki/HTML5_video#Table - this
1066
// is a simplified version, does not take into account old browser
1067
// versions or manual plugins.
1068
if ($ext === 'ogv' || $ext === 'webm') {
1069
// Formats .ogv and .webm are not supported in IE or Safari.
1070
if (check_browser_version('MSIE') || check_browser_version('Safari')) {
1074
// Formats .m4v and .mp4 are not supported in Firefox or Opera.
1075
if (check_browser_version('Firefox') || check_browser_version('Opera')) {
1086
public function get_rank() {
1093
* Player that creates HTML5 <audio> tag.
1095
* @copyright 2011 The Open University
1096
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1098
class core_media_player_html5audio extends core_media_player {
1099
public function embed($urls, $name, $width, $height, $options) {
1101
// Build array of source tags.
1103
foreach ($urls as $url) {
1104
$mimetype = core_media::get_mimetype($url);
1105
$sources[] = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
1108
$sources = implode("\n", $sources);
1109
$title = s($this->get_name($name, $urls));
1111
// Default to not specify size (so it can be changed in css).
1114
$size = 'width="' . $width . '"';
1117
$fallback = core_media_player::PLACEHOLDER;
1120
<audio controls="true" $size class="mediaplugin mediaplugin_html5audio" preload="no" title="$title">
1127
public function get_supported_extensions() {
1128
return array('ogg', 'oga', 'aac', 'm4a', 'mp3');
1131
public function list_supported_urls(array $urls, array $options = array()) {
1132
$extensions = $this->get_supported_extensions();
1134
foreach ($urls as $url) {
1135
$ext = core_media::get_extension($url);
1136
if (in_array($ext, $extensions)) {
1137
if ($ext === 'ogg' || $ext === 'oga') {
1138
// Formats .ogg and .oga are not supported in IE or Safari.
1139
if (check_browser_version('MSIE') || check_browser_version('Safari')) {
1143
// Formats .aac, .mp3, and .m4a are not supported in Firefox or Opera.
1144
if (check_browser_version('Firefox') || check_browser_version('Opera')) {
1148
// Old Android versions (pre 2.3.3) 'support' audio tag but no codecs.
1149
if (check_browser_version('WebKit Android') &&
1150
!check_browser_version('WebKit Android', '533.1')) {
1160
public function get_rank() {
1167
* Special media player class that just puts a link.
1169
* Always enabled, used as the last fallback.
1171
* @copyright 2011 The Open University
1172
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1174
class core_media_player_link extends core_media_player {
1175
public function embed($urls, $name, $width, $height, $options) {
1176
// If link is turned off, return empty.
1177
if (!empty($options[core_media::OPTION_NO_LINK])) {
1181
// Build up link content.
1183
foreach ($urls as $url) {
1184
$title = core_media::get_filename($url);
1185
$printlink = html_writer::link($url, $title, array('class' => 'mediafallbacklink'));
1187
// Where there are multiple available formats, there are fallback links
1188
// for all formats, separated by /.
1191
$output .= $printlink;
1196
public function list_supported_urls(array $urls, array $options = array()) {
1197
// Supports all URLs.
1201
public function is_enabled() {
1202
// Cannot be disabled.
1206
public function get_rank() {