[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/ -> medialib.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   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.
   8  //
   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.
  13  //
  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/>.
  16  
  17  /**
  18   * Classes for handling embedded media (mainly audio and video).
  19   *
  20   * These are used only from within the core media renderer.
  21   *
  22   * To embed media from Moodle code, do something like the following:
  23   *
  24   * $mediarenderer = $PAGE->get_renderer('core', 'media');
  25   * echo $mediarenderer->embed_url(new moodle_url('http://example.org/a.mp3'));
  26   *
  27   * You do not need to require this library file manually. Getting the renderer
  28   * (the first line above) requires this library file automatically.
  29   *
  30   * @package core_media
  31   * @copyright 2012 The Open University
  32   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  
  35  defined('MOODLE_INTERNAL') || die();
  36  
  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);
  42  }
  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);
  46  }
  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);
  51  }
  52  
  53  
  54  /**
  55   * Constants and static utility functions for use with core_media_renderer.
  56   *
  57   * @copyright 2011 The Open University
  58   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  59   */
  60  abstract class core_media {
  61      /**
  62       * Option: Disable text link fallback.
  63       *
  64       * Use this option if you are going to print a visible link anyway so it is
  65       * pointless to have one as fallback.
  66       *
  67       * To enable, set value to true.
  68       */
  69      const OPTION_NO_LINK = 'nolink';
  70  
  71      /**
  72       * Option: When embedding, if there is no matching embed, do not use the
  73       * default link fallback player; instead return blank.
  74       *
  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.
  78       *
  79       * To enable, set value to true.
  80       */
  81      const OPTION_FALLBACK_TO_BLANK = 'embedorblank';
  82  
  83      /**
  84       * Option: Enable players which are only suitable for use when we trust the
  85       * user who embedded the content.
  86       *
  87       * At present, this option enables the SWF player.
  88       *
  89       * To enable, set value to true.
  90       */
  91      const OPTION_TRUSTED = 'trusted';
  92  
  93      /**
  94       * Option: Put a div around the output (if not blank) so that it displays
  95       * as a block using the 'resourcecontent' CSS class.
  96       *
  97       * To enable, set value to true.
  98       */
  99      const OPTION_BLOCK = 'block';
 100  
 101      /**
 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.
 105       *
 106       * Note that the input string should NOT be html-escaped (i.e. if it comes
 107       * from html, call html_entity_decode first).
 108       *
 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
 113       */
 114      public static function split_alternatives($combinedurl, &$width, &$height) {
 115          $urls = explode('#', $combinedurl);
 116          $width = 0;
 117          $height = 0;
 118          $returnurls = array();
 119  
 120          foreach ($urls as $url) {
 121              $matches = null;
 122  
 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];
 128                  continue;
 129              }
 130  
 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];
 136  
 137                  // Trim from URL.
 138                  $url = str_replace($matches[0], '', $url);
 139              }
 140  
 141              // Clean up url.
 142              $url = clean_param($url, PARAM_URL);
 143              if (empty($url)) {
 144                  continue;
 145              }
 146  
 147              // Turn it into moodle_url object.
 148              $returnurls[] = new moodle_url($url);
 149          }
 150  
 151          return $returnurls;
 152      }
 153  
 154      /**
 155       * Returns the file extension for a URL.
 156       * @param moodle_url $url URL
 157       */
 158      public static function get_extension(moodle_url $url) {
 159          // Note: Does not use core_text (. is UTF8-safe).
 160          $filename = self::get_filename($url);
 161          $dot = strrpos($filename, '.');
 162          if ($dot === false) {
 163              return '';
 164          } else {
 165              return strtolower(substr($filename, $dot + 1));
 166          }
 167      }
 168  
 169      /**
 170       * Obtains the filename from the moodle_url.
 171       * @param moodle_url $url URL
 172       * @return string Filename only (not escaped)
 173       */
 174      public static function get_filename(moodle_url $url) {
 175          global $CFG;
 176  
 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');
 180          if (!$path) {
 181              $path = $url->get_path();
 182          }
 183  
 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);
 188          }
 189          return $path;
 190      }
 191  
 192      /**
 193       * Guesses MIME type for a moodle_url based on file extension.
 194       * @param moodle_url $url URL
 195       * @return string MIME type
 196       */
 197      public static function get_mimetype(moodle_url $url) {
 198          return mimeinfo('type', self::get_filename($url));
 199      }
 200  }
 201  
 202  
 203  /**
 204   * Base class for media players.
 205   *
 206   * Media players return embed HTML for a particular way of playing back audio
 207   * or video (or another file type).
 208   *
 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.
 214   *
 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.
 219   *
 220   * @copyright 2011 The Open University
 221   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 222   */
 223  abstract class core_media_player {
 224      /**
 225       * Placeholder text used to indicate where the fallback content is placed
 226       * within a result.
 227       */
 228      const PLACEHOLDER = '<!--FALLBACK-->';
 229  
 230      /**
 231       * Generates code required to embed the player.
 232       *
 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.
 237       *
 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).
 241       *
 242       * The $options array contains key-value pairs. See OPTION_xx constants
 243       * for documentation of standard option(s).
 244       *
 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
 251       */
 252      public abstract function embed($urls, $name, $width, $height, $options);
 253  
 254      /**
 255       * Gets the list of file extensions supported by this media player.
 256       *
 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
 260       * is not necessary.
 261       *
 262       * @return array Array of strings (extension not including dot e.g. 'mp3')
 263       */
 264      public function get_supported_extensions() {
 265          return array();
 266      }
 267  
 268      /**
 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.
 271       *
 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.)
 274       *
 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.
 278       *
 279       * This is used to improve performance when matching links in the media filter.
 280       *
 281       * @return array Array of keywords to add to the embeddable markers list
 282       */
 283      public function get_embeddable_markers() {
 284          $markers = array();
 285          foreach ($this->get_supported_extensions() as $extension) {
 286              $markers[] = '.' . $extension;
 287          }
 288          return $markers;
 289      }
 290  
 291      /**
 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).
 295       *
 296       * Rank must be unique (no two players should have the same rank).
 297       *
 298       * Rank zero has a special meaning, indicating that this 'player' does not
 299       * really embed the video.
 300       *
 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.
 307       *
 308       * Note: Within medialib.php, players are listed in rank order (highest
 309       * rank first).
 310       *
 311       * @return int Rank (higher is better)
 312       */
 313      public abstract function get_rank();
 314  
 315      /**
 316       * @return bool True if player is enabled
 317       */
 318      public function is_enabled() {
 319          global $CFG;
 320  
 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});
 325      }
 326  
 327      /**
 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
 333       */
 334      public function list_supported_urls(array $urls, array $options = array()) {
 335          $extensions = $this->get_supported_extensions();
 336          $result = array();
 337          foreach ($urls as $url) {
 338              if (in_array(core_media::get_extension($url), $extensions)) {
 339                  $result[] = $url;
 340              }
 341          }
 342          return $result;
 343      }
 344  
 345      /**
 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
 351       */
 352      protected function get_name($name, $urls) {
 353          // If there is a specified name, use that.
 354          if ($name) {
 355              return $name;
 356          }
 357  
 358          // Get filename of first URL.
 359          $url = reset($urls);
 360          $name = core_media::get_filename($url);
 361  
 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);
 366          }
 367  
 368          return $name;
 369      }
 370  
 371      /**
 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
 376       */
 377      public static function compare_by_rank(core_media_player $a, core_media_player $b) {
 378          return $b->get_rank() - $a->get_rank();
 379      }
 380  
 381      /**
 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)
 387       */
 388      protected static function pick_video_size(&$width, &$height) {
 389          if (!$width) {
 390              $width = CORE_MEDIA_VIDEO_WIDTH;
 391              $height = CORE_MEDIA_VIDEO_HEIGHT;
 392          }
 393      }
 394  }
 395  
 396  
 397  /**
 398   * Base class for players which handle external links (YouTube etc).
 399   *
 400   * As opposed to media files.
 401   *
 402   * @copyright 2011 The Open University
 403   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 404   */
 405  abstract class core_media_player_external extends core_media_player {
 406      /**
 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
 409       * the regex.
 410       * @var array
 411       */
 412      protected $matches;
 413  
 414      /**
 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,
 420       * up to </a>.
 421       * @var string
 422       */
 423      const END_LINK_REGEX_PART = '[^#]*(#d=([\d]{1,4})x([\d]{1,4}))?~si';
 424  
 425      public function embed($urls, $name, $width, $height, $options) {
 426          return $this->embed_external(reset($urls), $name, $width, $height, $options);
 427      }
 428  
 429      /**
 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
 437       */
 438      protected abstract function embed_external(moodle_url $url, $name, $width, $height, $options);
 439  
 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) {
 443              return array();
 444          }
 445          $url = reset($urls);
 446  
 447          // Check against regex.
 448          if (preg_match($this->get_regex(), $url->out(false), $this->matches)) {
 449              return array($url);
 450          }
 451  
 452          return array();
 453      }
 454  
 455      /**
 456       * Returns regular expression used to match URLs that this player handles
 457       * @return string PHP regular expression e.g. '~^https?://example.org/~'
 458       */
 459      protected function get_regex() {
 460          return '~^unsupported~';
 461      }
 462  
 463      /**
 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)
 469       */
 470      protected static function fix_match_count(&$matches, $count) {
 471          for ($i = count($matches); $i <= $count; $i++) {
 472              $matches[$i] = false;
 473          }
 474      }
 475  }
 476  
 477  
 478  /**
 479   * Player that embeds Vimeo links.
 480   *
 481   * @copyright 2011 The Open University
 482   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 483   */
 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];
 487          $info = s($name);
 488  
 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);
 493  
 494          $output = <<<OET
 495  <span class="mediaplugin mediaplugin_vimeo">
 496  <iframe title="$info" src="https://player.vimeo.com/video/$videoid"
 497    width="$width" height="$height" frameborder="0"
 498    webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
 499  </span>
 500  OET;
 501  
 502          return $output;
 503      }
 504  
 505      protected function get_regex() {
 506          // Initial part of link.
 507          $start = '~^https?://vimeo\.com/';
 508          // Middle bit: either watch?v= or v/.
 509          $middle = '([0-9]+)';
 510          return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
 511      }
 512  
 513      public function get_rank() {
 514          return 1010;
 515      }
 516  
 517      public function get_embeddable_markers() {
 518          return array('vimeo.com/');
 519      }
 520  }
 521  
 522  /**
 523   * Player that creates YouTube embedding.
 524   *
 525   * @copyright 2011 The Open University
 526   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 527   */
 528  class core_media_player_youtube extends core_media_player_external {
 529      protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
 530          $videoid = end($this->matches);
 531  
 532          $info = trim($name);
 533          if (empty($info) or strpos($info, 'http') === 0) {
 534              $info = get_string('siteyoutube', 'core_media');
 535          }
 536          $info = s($info);
 537  
 538          self::pick_video_size($width, $height);
 539  
 540          $params = '';
 541          $start = self::get_start_time($url);
 542          if ($start > 0) {
 543              $params .= "start=$start&";
 544          }
 545  
 546          $listid = $url->param('list');
 547          // Check for non-empty but valid playlist ID.
 548          if (!empty($listid) && !preg_match('/[^a-zA-Z0-9\-_]/', $listid)) {
 549              // This video is part of a playlist, and we want to embed it as such.
 550              $params .= "list=$listid&";
 551          }
 552  
 553          return <<<OET
 554  <span class="mediaplugin mediaplugin_youtube">
 555  <iframe title="$info" width="$width" height="$height"
 556    src="https://www.youtube.com/embed/$videoid?{$params}rel=0&wmode=transparent" frameborder="0" allowfullscreen="1"></iframe>
 557  </span>
 558  OET;
 559  
 560      }
 561  
 562      /**
 563       * Check for start time parameter.  Note that it's in hours/mins/secs in the URL,
 564       * but the embedded player takes only a number of seconds as the "start" parameter.
 565       * @param moodle_url $url URL of video to be embedded.
 566       * @return int Number of seconds video should start at.
 567       */
 568      protected static function get_start_time($url) {
 569          $matches = array();
 570          $seconds = 0;
 571  
 572          $rawtime = $url->param('t');
 573          if (empty($rawtime)) {
 574              $rawtime = $url->param('start');
 575          }
 576  
 577          if (is_numeric($rawtime)) {
 578              // Start time already specified as a number of seconds; ensure it's an integer.
 579              $seconds = $rawtime;
 580          } else if (preg_match('/(\d+?h)?(\d+?m)?(\d+?s)?/i', $rawtime, $matches)) {
 581              // Convert into a raw number of seconds, as that's all embedded players accept.
 582              for ($i = 1; $i < count($matches); $i++) {
 583                  if (empty($matches[$i])) {
 584                      continue;
 585                  }
 586                  $part = str_split($matches[$i], strlen($matches[$i]) - 1);
 587                  switch ($part[1]) {
 588                      case 'h':
 589                          $seconds += 3600 * $part[0];
 590                          break;
 591                      case 'm':
 592                          $seconds += 60 * $part[0];
 593                          break;
 594                      default:
 595                          $seconds += $part[0];
 596                  }
 597              }
 598          }
 599  
 600          return intval($seconds);
 601      }
 602  
 603      protected function get_regex() {
 604          // Regex for standard youtube link
 605           $link = '(youtube(-nocookie)?\.com/(?:watch\?v=|v/))';
 606          // Regex for shortened youtube link
 607          $shortlink = '((youtu|y2u)\.be/)';
 608  
 609          // Initial part of link.
 610           $start = '~^https?://(www\.)?(' . $link . '|' . $shortlink . ')';
 611          // Middle bit: Video key value
 612          $middle = '([a-z0-9\-_]+)';
 613          return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
 614      }
 615  
 616      public function get_rank() {
 617          // I decided to make the link-embedding ones (that don't handle file
 618          // formats) have ranking in the 1000 range.
 619          return 1001;
 620      }
 621  
 622      public function get_embeddable_markers() {
 623          return array('youtube.com', 'youtube-nocookie.com', 'youtu.be', 'y2u.be');
 624      }
 625  }
 626  
 627  
 628  /**
 629   * Player that creates YouTube playlist embedding.
 630   *
 631   * @copyright 2011 The Open University
 632   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 633   */
 634  class core_media_player_youtube_playlist extends core_media_player_external {
 635      public function is_enabled() {
 636          global $CFG;
 637          // Use the youtube on/off flag.
 638          return $CFG->core_media_enable_youtube;
 639      }
 640  
 641      protected function embed_external(moodle_url $url, $name, $width, $height, $options) {
 642          $site = $this->matches[1];
 643          $playlist = $this->matches[3];
 644  
 645          $info = trim($name);
 646          if (empty($info) or strpos($info, 'http') === 0) {
 647              $info = get_string('siteyoutube', 'core_media');
 648          }
 649          $info = s($info);
 650  
 651          self::pick_video_size($width, $height);
 652  
 653          return <<<OET
 654  <span class="mediaplugin mediaplugin_youtube">
 655  <iframe width="$width" height="$height" src="https://$site/embed/videoseries?list=$playlist" frameborder="0" allowfullscreen="1"></iframe>
 656  </span>
 657  OET;
 658      }
 659  
 660      protected function get_regex() {
 661          // Initial part of link.
 662          $start = '~^https?://(www\.youtube(-nocookie)?\.com)/';
 663          // Middle bit: either view_play_list?p= or p/ (doesn't work on youtube) or playlist?list=.
 664          $middle = '(?:view_play_list\?p=|p/|playlist\?list=)([a-z0-9\-_]+)';
 665          return $start . $middle . core_media_player_external::END_LINK_REGEX_PART;
 666      }
 667  
 668      public function get_rank() {
 669          // I decided to make the link-embedding ones (that don't handle file
 670          // formats) have ranking in the 1000 range.
 671          return 1000;
 672      }
 673  
 674      public function get_embeddable_markers() {
 675          return array('youtube');
 676      }
 677  }
 678  
 679  
 680  /**
 681   * MP3 player inserted using JavaScript.
 682   *
 683   * @copyright 2011 The Open University
 684   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 685   */
 686  class core_media_player_mp3 extends core_media_player {
 687      public function embed($urls, $name, $width, $height, $options) {
 688          // Use first url (there can actually be only one unless some idiot
 689          // enters two mp3 files as alternatives).
 690          $url = reset($urls);
 691  
 692          // Unique id even across different http requests made at the same time
 693          // (for AJAX, iframes).
 694          $id = 'core_media_mp3_' . md5(time() . '_' . rand());
 695  
 696          // When Flash or JavaScript are not available only the fallback is displayed,
 697          // using span not div because players are inline elements.
 698          $spanparams = array('id' => $id, 'class' => 'mediaplugin mediaplugin_mp3');
 699          if ($width) {
 700              $spanparams['style'] = 'width: ' . $width . 'px';
 701          }
 702          $output = html_writer::tag('span', core_media_player::PLACEHOLDER, $spanparams);
 703          // We can not use standard JS init because this may be cached
 704          // note: use 'small' size unless embedding in block mode.
 705          $output .= html_writer::script(js_writer::function_call(
 706                  'M.util.add_audio_player', array($id, $url->out(false),
 707                  empty($options[core_media::OPTION_BLOCK]))));
 708  
 709          return $output;
 710      }
 711  
 712      public function get_supported_extensions() {
 713          return array('mp3');
 714      }
 715  
 716      public function get_rank() {
 717          return 80;
 718      }
 719  }
 720  
 721  
 722  /**
 723   * Flash video player inserted using JavaScript.
 724   *
 725   * @copyright 2011 The Open University
 726   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 727   */
 728  class core_media_player_flv extends core_media_player {
 729      public function embed($urls, $name, $width, $height, $options) {
 730          // Use first url (there can actually be only one unless some idiot
 731          // enters two mp3 files as alternatives).
 732          $url = reset($urls);
 733  
 734          // Unique id even across different http requests made at the same time
 735          // (for AJAX, iframes).
 736          $id = 'core_media_flv_' . md5(time() . '_' . rand());
 737  
 738          // Compute width and height.
 739          $autosize = false;
 740          if (!$width && !$height) {
 741              $width = CORE_MEDIA_VIDEO_WIDTH;
 742              $height = CORE_MEDIA_VIDEO_HEIGHT;
 743              $autosize = true;
 744          }
 745  
 746          // Fallback span (will normally contain link).
 747          $output = html_writer::tag('span', core_media_player::PLACEHOLDER,
 748                  array('id'=>$id, 'class'=>'mediaplugin mediaplugin_flv'));
 749          // We can not use standard JS init because this may be cached.
 750          $output .= html_writer::script(js_writer::function_call(
 751                  'M.util.add_video_player', array($id, addslashes_js($url->out(false)),
 752                  $width, $height, $autosize)));
 753          return $output;
 754      }
 755  
 756      public function get_supported_extensions() {
 757          return array('flv', 'f4v');
 758      }
 759  
 760      public function get_rank() {
 761          return 70;
 762      }
 763  }
 764  
 765  
 766  /**
 767   * Embeds Windows Media Player using object tag.
 768   *
 769   * @copyright 2011 The Open University
 770   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 771   */
 772  class core_media_player_wmp extends core_media_player {
 773      public function embed($urls, $name, $width, $height, $options) {
 774          // Get URL (we just use first, probably there is only one).
 775          $firsturl = reset($urls);
 776          $url = $firsturl->out(false);
 777  
 778          // Work out width.
 779          if (!$width || !$height) {
 780              // Object tag has default size.
 781              $mpsize = '';
 782              $size = 'width="' . CORE_MEDIA_VIDEO_WIDTH .
 783                      '" height="' . (CORE_MEDIA_VIDEO_HEIGHT+64) . '"';
 784              $autosize = 'true';
 785          } else {
 786              $size = 'width="' . $width . '" height="' . ($height + 15) . '"';
 787              $mpsize = 'width="' . $width . '" height="' . ($height + 64) . '"';
 788              $autosize = 'false';
 789          }
 790  
 791          // MIME type for object tag.
 792          $mimetype = core_media::get_mimetype($firsturl);
 793  
 794          $fallback = core_media_player::PLACEHOLDER;
 795  
 796          // Embed code.
 797          return <<<OET
 798  <span class="mediaplugin mediaplugin_wmp">
 799      <object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" $mpsize
 800              standby="Loading Microsoft(R) Windows(R) Media Player components..."
 801              type="application/x-oleobject">
 802          <param name="Filename" value="$url" />
 803          <param name="src" value="$url" />
 804          <param name="url" value="$url" />
 805          <param name="ShowControls" value="true" />
 806          <param name="AutoRewind" value="true" />
 807          <param name="AutoStart" value="false" />
 808          <param name="Autosize" value="$autosize" />
 809          <param name="EnableContextMenu" value="true" />
 810          <param name="TransparentAtStart" value="false" />
 811          <param name="AnimationAtStart" value="false" />
 812          <param name="ShowGotoBar" value="false" />
 813          <param name="EnableFullScreenControls" value="true" />
 814          <param name="uimode" value="full" />
 815          <!--[if !IE]><!-->
 816          <object data="$url" type="$mimetype" $size>
 817              <param name="src" value="$url" />
 818              <param name="controller" value="true" />
 819              <param name="autoplay" value="false" />
 820              <param name="autostart" value="false" />
 821              <param name="resize" value="scale" />
 822          <!--<![endif]-->
 823              $fallback
 824          <!--[if !IE]><!-->
 825          </object>
 826          <!--<![endif]-->
 827      </object>
 828  </span>
 829  OET;
 830      }
 831  
 832      public function get_supported_extensions() {
 833          return array('wmv', 'avi');
 834      }
 835  
 836      public function get_rank() {
 837          return 60;
 838      }
 839  }
 840  
 841  
 842  /**
 843   * Media player using object tag and QuickTime player.
 844   *
 845   * @copyright 2011 The Open University
 846   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 847   */
 848  class core_media_player_qt extends core_media_player {
 849      public function embed($urls, $name, $width, $height, $options) {
 850          // Show first URL.
 851          $firsturl = reset($urls);
 852          $url = $firsturl->out(true);
 853  
 854          // Work out size.
 855          if (!$width || !$height) {
 856              $size = 'width="' . CORE_MEDIA_VIDEO_WIDTH .
 857                      '" height="' . (CORE_MEDIA_VIDEO_HEIGHT + 15) . '"';
 858          } else {
 859              $size = 'width="' . $width . '" height="' . ($height + 15) . '"';
 860          }
 861  
 862          // MIME type for object tag.
 863          $mimetype = core_media::get_mimetype($firsturl);
 864  
 865          $fallback = core_media_player::PLACEHOLDER;
 866  
 867          // Embed code.
 868          return <<<OET
 869  <span class="mediaplugin mediaplugin_qt">
 870      <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
 871              codebase="http://www.apple.com/qtactivex/qtplugin.cab" $size>
 872          <param name="pluginspage" value="http://www.apple.com/quicktime/download/" />
 873          <param name="src" value="$url" />
 874          <param name="controller" value="true" />
 875          <param name="loop" value="false" />
 876          <param name="autoplay" value="false" />
 877          <param name="autostart" value="false" />
 878          <param name="scale" value="aspect" />
 879          <!--[if !IE]><!-->
 880          <object data="$url" type="$mimetype" $size>
 881              <param name="src" value="$url" />
 882              <param name="pluginurl" value="http://www.apple.com/quicktime/download/" />
 883              <param name="controller" value="true" />
 884              <param name="loop" value="false" />
 885              <param name="autoplay" value="false" />
 886              <param name="autostart" value="false" />
 887              <param name="scale" value="aspect" />
 888          <!--<![endif]-->
 889              $fallback
 890          <!--[if !IE]><!-->
 891          </object>
 892          <!--<![endif]-->
 893      </object>
 894  </span>
 895  OET;
 896      }
 897  
 898      public function get_supported_extensions() {
 899          return array('mpg', 'mpeg', 'mov', 'mp4', 'm4v', 'm4a');
 900      }
 901  
 902      public function get_rank() {
 903          return 10;
 904      }
 905  }
 906  
 907  
 908  /**
 909   * Media player using object tag and RealPlayer.
 910   *
 911   * Hopefully nobody is using this obsolete format any more!
 912   *
 913   * @copyright 2011 The Open University
 914   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 915   */
 916  class core_media_player_rm extends core_media_player {
 917      public function embed($urls, $name, $width, $height, $options) {
 918          // Show first URL.
 919          $firsturl = reset($urls);
 920          $url = $firsturl->out(true);
 921  
 922          // Get name to use as title.
 923          $info = s($this->get_name($name, $urls));
 924  
 925          // The previous version of this code has the following comment, which
 926          // I don't understand, but trust it is correct:
 927          // Note: the size is hardcoded intentionally because this does not work anyway!
 928          $width = CORE_MEDIA_VIDEO_WIDTH;
 929          $height = CORE_MEDIA_VIDEO_HEIGHT;
 930  
 931          $fallback = core_media_player::PLACEHOLDER;
 932          return <<<OET
 933  <span class="mediaplugin mediaplugin_real">
 934      <object title="$info" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"
 935              data="$url" width="$width" height="$height"">
 936          <param name="src" value="$url" />
 937          <param name="controls" value="All" />
 938          <!--[if !IE]><!-->
 939          <object title="$info" type="audio/x-pn-realaudio-plugin"
 940                  data="$url" width="$width" height="$height">
 941              <param name="src" value="$url" />
 942              <param name="controls" value="All" />
 943          <!--<![endif]-->
 944              $fallback
 945          <!--[if !IE]><!-->
 946          </object>
 947          <!--<![endif]-->
 948    </object>
 949  </span>
 950  OET;
 951      }
 952  
 953      public function get_supported_extensions() {
 954          return array('ra', 'ram', 'rm', 'rv');
 955      }
 956  
 957      public function get_rank() {
 958          return 40;
 959      }
 960  }
 961  
 962  
 963  /**
 964   * Media player for Flash SWF files.
 965   *
 966   * This player contains additional security restriction: it will only be used
 967   * if you add option core_media_player_swf::ALLOW = true.
 968   *
 969   * Code should only set this option if it has verified that the data was
 970   * embedded by a trusted user (e.g. in trust text).
 971   *
 972   * @copyright 2011 The Open University
 973   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 974   */
 975  class core_media_player_swf extends core_media_player {
 976      public function embed($urls, $name, $width, $height, $options) {
 977          self::pick_video_size($width, $height);
 978  
 979          $firsturl = reset($urls);
 980          $url = $firsturl->out(true);
 981  
 982          $fallback = core_media_player::PLACEHOLDER;
 983          $output = <<<OET
 984  <span class="mediaplugin mediaplugin_swf">
 985    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="$width" height="$height">
 986      <param name="movie" value="$url" />
 987      <param name="autoplay" value="true" />
 988      <param name="loop" value="false" />
 989      <param name="controller" value="true" />
 990      <param name="scale" value="aspect" />
 991      <param name="base" value="." />
 992      <param name="allowscriptaccess" value="never" />
 993      <param name="allowfullscreen" value="true" />
 994  <!--[if !IE]><!-->
 995      <object type="application/x-shockwave-flash" data="$url" width="$width" height="$height">
 996        <param name="controller" value="true" />
 997        <param name="autoplay" value="true" />
 998        <param name="loop" value="false" />
 999        <param name="scale" value="aspect" />
1000        <param name="base" value="." />
1001        <param name="allowscriptaccess" value="never" />
1002        <param name="allowfullscreen" value="true" />
1003  <!--<![endif]-->
1004  $fallback
1005  <!--[if !IE]><!-->
1006      </object>
1007  <!--<![endif]-->
1008    </object>
1009  </span>
1010  OET;
1011  
1012          return $output;
1013      }
1014  
1015      public function get_supported_extensions() {
1016          return array('swf');
1017      }
1018  
1019      public function list_supported_urls(array $urls, array $options = array()) {
1020          // Not supported unless the creator is trusted.
1021          if (empty($options[core_media::OPTION_TRUSTED])) {
1022              return array();
1023          }
1024          return parent::list_supported_urls($urls, $options);
1025      }
1026  
1027      public function get_rank() {
1028          return 30;
1029      }
1030  }
1031  
1032  
1033  /**
1034   * Player that creates HTML5 <video> tag.
1035   *
1036   * @copyright 2011 The Open University
1037   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1038   */
1039  class core_media_player_html5video extends core_media_player {
1040      public function embed($urls, $name, $width, $height, $options) {
1041          // Special handling to make videos play on Android devices pre 2.3.
1042          // Note: I tested and 2.3.3 (in emulator) works without, is 533.1 webkit.
1043          $oldandroid = core_useragent::is_webkit_android() &&
1044                  !core_useragent::check_webkit_android_version('533.1');
1045  
1046          // Build array of source tags.
1047          $sources = array();
1048          foreach ($urls as $url) {
1049              $mimetype = core_media::get_mimetype($url);
1050              $source = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
1051              if ($mimetype === 'video/mp4') {
1052                  if ($oldandroid) {
1053                      // Old Android fails if you specify the type param.
1054                      $source = html_writer::tag('source', '', array('src' => $url));
1055                  }
1056  
1057                  // Better add m4v as first source, it might be a bit more
1058                  // compatible with problematic browsers.
1059                  array_unshift($sources, $source);
1060              } else {
1061                  $sources[] = $source;
1062              }
1063          }
1064  
1065          $sources = implode("\n", $sources);
1066          $title = s($this->get_name($name, $urls));
1067  
1068          if (!$width) {
1069              // No width specified, use system default.
1070              $width = CORE_MEDIA_VIDEO_WIDTH;
1071          }
1072  
1073          if (!$height) {
1074              // Let browser choose height automatically.
1075              $size = "width=\"$width\"";
1076          } else {
1077              $size = "width=\"$width\" height=\"$height\"";
1078          }
1079  
1080          $sillyscript = '';
1081          $idtag = '';
1082          if ($oldandroid) {
1083              // Old Android does not support 'controls' option.
1084              $id = 'core_media_html5v_' . md5(time() . '_' . rand());
1085              $idtag = 'id="' . $id . '"';
1086              $sillyscript = <<<OET
1087  <script type="text/javascript">
1088  document.getElementById('$id').addEventListener('click', function() {
1089      this.play();
1090  }, false);
1091  </script>
1092  OET;
1093          }
1094  
1095          $fallback = core_media_player::PLACEHOLDER;
1096          return <<<OET
1097  <span class="mediaplugin mediaplugin_html5video">
1098  <video $idtag controls="true" $size preload="metadata" title="$title">
1099      $sources
1100      $fallback
1101  </video>
1102  $sillyscript
1103  </span>
1104  OET;
1105      }
1106  
1107      public function get_supported_extensions() {
1108          return array('m4v', 'webm', 'ogv', 'mp4');
1109      }
1110  
1111      public function list_supported_urls(array $urls, array $options = array()) {
1112          $extensions = $this->get_supported_extensions();
1113          $result = array();
1114          foreach ($urls as $url) {
1115              $ext = core_media::get_extension($url);
1116              if (in_array($ext, $extensions)) {
1117                  // Unfortunately html5 video does not handle fallback properly.
1118                  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=10975
1119                  // That means we need to do browser detect and not use html5 on
1120                  // browsers which do not support the given type, otherwise users
1121                  // will not even see the fallback link.
1122                  // Based on http://en.wikipedia.org/wiki/HTML5_video#Table - this
1123                  // is a simplified version, does not take into account old browser
1124                  // versions or manual plugins.
1125                  if ($ext === 'ogv' || $ext === 'webm') {
1126                      // Formats .ogv and .webm are not supported in IE, Edge or Safari.
1127                      if (core_useragent::is_ie() || core_useragent::is_edge() || core_useragent::is_safari()) {
1128                          continue;
1129                      }
1130                  } else {
1131                      // Formats .m4v and .mp4 are not supported in Opera, or in Firefox before 27.
1132                      // https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
1133                      // has the details.
1134                      if (core_useragent::is_opera() || (core_useragent::is_firefox() &&
1135                              !core_useragent::check_firefox_version(27))) {
1136                          continue;
1137                      }
1138                  }
1139  
1140                  $result[] = $url;
1141              }
1142          }
1143          return $result;
1144      }
1145  
1146      public function get_rank() {
1147          return 50;
1148      }
1149  }
1150  
1151  
1152  /**
1153   * Player that creates HTML5 <audio> tag.
1154   *
1155   * @copyright 2011 The Open University
1156   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1157   */
1158  class core_media_player_html5audio extends core_media_player {
1159      public function embed($urls, $name, $width, $height, $options) {
1160  
1161          // Build array of source tags.
1162          $sources = array();
1163          foreach ($urls as $url) {
1164              $mimetype = core_media::get_mimetype($url);
1165              $sources[] = html_writer::tag('source', '', array('src' => $url, 'type' => $mimetype));
1166          }
1167  
1168          $sources = implode("\n", $sources);
1169          $title = s($this->get_name($name, $urls));
1170  
1171          // Default to not specify size (so it can be changed in css).
1172          $size = '';
1173          if ($width) {
1174              $size = 'width="' . $width . '"';
1175          }
1176  
1177          $fallback = core_media_player::PLACEHOLDER;
1178  
1179          return <<<OET
1180  <audio controls="true" $size class="mediaplugin mediaplugin_html5audio" preload="none" title="$title">
1181  $sources
1182  $fallback
1183  </audio>
1184  OET;
1185      }
1186  
1187      public function get_supported_extensions() {
1188          return array('ogg', 'oga', 'aac', 'm4a', 'mp3');
1189      }
1190  
1191      public function list_supported_urls(array $urls, array $options = array()) {
1192          $extensions = $this->get_supported_extensions();
1193          $result = array();
1194          foreach ($urls as $url) {
1195              $ext = core_media::get_extension($url);
1196              if (in_array($ext, $extensions)) {
1197                  if ($ext === 'ogg' || $ext === 'oga') {
1198                      // Formats .ogg and .oga are not supported in IE, Edge, or Safari.
1199                      if (core_useragent::is_ie() || core_useragent::is_edge() || core_useragent::is_safari()) {
1200                          continue;
1201                      }
1202                  } else {
1203                      // Formats .aac, .mp3, and .m4a are not supported in Opera.
1204                      if (core_useragent::is_opera()) {
1205                          continue;
1206                      }
1207                      // Formats .mp3 and .m4a were not reliably supported in Firefox before 27.
1208                      // https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
1209                      // has the details. .aac is still not supported.
1210                      if (core_useragent::is_firefox() && ($ext === 'aac' ||
1211                              !core_useragent::check_firefox_version(27))) {
1212                          continue;
1213                      }
1214                  }
1215                  // Old Android versions (pre 2.3.3) 'support' audio tag but no codecs.
1216                  if (core_useragent::is_webkit_android() &&
1217                          !core_useragent::is_webkit_android('533.1')) {
1218                      continue;
1219                  }
1220  
1221                  $result[] = $url;
1222              }
1223          }
1224          return $result;
1225      }
1226  
1227      public function get_rank() {
1228          return 20;
1229      }
1230  }
1231  
1232  
1233  /**
1234   * Special media player class that just puts a link.
1235   *
1236   * Always enabled, used as the last fallback.
1237   *
1238   * @copyright 2011 The Open University
1239   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1240   */
1241  class core_media_player_link extends core_media_player {
1242      public function embed($urls, $name, $width, $height, $options) {
1243          // If link is turned off, return empty.
1244          if (!empty($options[core_media::OPTION_NO_LINK])) {
1245              return '';
1246          }
1247  
1248          // Build up link content.
1249          $output = '';
1250          foreach ($urls as $url) {
1251              $title = core_media::get_filename($url);
1252              $printlink = html_writer::link($url, $title, array('class' => 'mediafallbacklink'));
1253              if ($output) {
1254                  // Where there are multiple available formats, there are fallback links
1255                  // for all formats, separated by /.
1256                  $output .= ' / ';
1257              }
1258              $output .= $printlink;
1259          }
1260          return $output;
1261      }
1262  
1263      public function list_supported_urls(array $urls, array $options = array()) {
1264          // Supports all URLs.
1265          return $urls;
1266      }
1267  
1268      public function is_enabled() {
1269          // Cannot be disabled.
1270          return true;
1271      }
1272  
1273      public function get_rank() {
1274          return 0;
1275      }
1276  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1