src/widgets/videojs_plugins/Dailymotion.js
changeset 1076 510fd2a482f4
child 1079 d4f0681c4ff1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/widgets/videojs_plugins/Dailymotion.js	Tue Oct 22 07:03:54 2024 +0200
@@ -0,0 +1,546 @@
+// Adapted from https://github.com/lawchihon/videojs-dailymotion
+/*global define, dailymotion*/
+import videojs from "video.js";
+
+var _isOnMobile = videojs.browser.IS_IOS || videojs.browser.IS_NATIVE_ANDROID;
+var Tech = videojs.getTech("Tech");
+
+
+class Dailymotion extends Tech {
+  constructor(options, ready) {
+    super(options, ready);
+
+    this.setSrc(this.options_.source);
+    console.log(this.options_.source)
+
+    // Set the vjs-dailymotion class to the player
+    // Parent is not set yet so we have to wait a tick
+    setTimeout( () => {
+      if (this.el_) {
+        this.el_.parentNode.className += " vjs-dailymotion";
+
+        if (_isOnMobile) {
+          this.el_.parentNode.className += " vjs-dailymotion-mobile";
+        }
+
+        if (Dailymotion.isSdkReady) {
+            this.initDMPlayer();
+        } else {
+          Dailymotion.sdkReadyQueue.push(this);
+        }
+      }
+    });
+  };
+
+  _getPlayerParams() {
+    var playerParams = {
+      autoplay: false,
+      mute: false,
+      controls: false,
+      "enable-playback-controls": false,
+      "queue-autoplay-next": false,
+      "queue-enable": false,
+    };
+    // Let the user set any Dailymotion parameter
+    // https://developer.dailymotion.com/player/#player-parameters
+    // To use Dailymotion controls, you must use dmControls instead
+
+    var params = [
+      "api",
+      "autoplay",
+      "autoplay-mute",
+      "id",
+      "mute",
+      "origin",
+      "quality",
+      "queue-autoplay-next",
+      "queue-enable",
+      "sharing-enable",
+      "start",
+      "subtitles-default",
+      "syndication",
+      "ui-highlight",
+      "ui-logo",
+      "ui-start-screen-info",
+      "ui-theme",
+      "apimode",
+      "playlist",
+    ];
+    var options = this.options_;
+    params.forEach(function (param) {
+      if (typeof options[param] === "undefined") {
+        return;
+      }
+      playerParams[param] = options[param];
+    });
+
+    if (typeof this.options_.dmControls !== "undefined") {
+      playerParams.controls = this.options_.dmControls;
+    }
+
+    // Overwriting playlist if it is included in url
+    if (this.url && typeof this.url.playlist !== "undefined") {
+      playerParams.playlist = this.url.playlist;
+    }
+
+    // Allow undocumented options to be passed along via customVars
+    if (typeof this.options_.customVars !== "undefined") {
+      var customVars = this.options_.customVars;
+      Object.keys(customVars).forEach(function (key) {
+        playerParams[key] = customVars[key];
+      });
+    }
+
+    return playerParams;
+  }
+
+  _getPlayerConfig() {
+    var playerConfig = {
+      width: "100%",
+      height: "100%",
+      params: this._getPlayerParams(),
+    };
+
+    if (this.url && typeof this.url.video !== "undefined") {
+      playerConfig.video = this.url.video;
+    } else if (typeof this.options_.video !== "undefined") {
+      playerConfig.video = this.options_.video;
+    }
+
+    return playerConfig;
+  }
+
+  async initDMPlayer() {
+    console.log("INIT DM Player", this._getPlayerConfig());
+    if (this.dmPlayer) {
+      return;
+    }
+    const eventMapping = {
+      [dailymotion.events.VIDEO_DURATIONCHANGE]: [ "durationchange" ],
+      [dailymotion.events.PLAYER_END]: [ "ended" ],
+      [dailymotion.events.PLAYER_ERROR]: [ "error" ],
+      [dailymotion.events.PLAYER_VIDEOCHANGE]: [ "loadeddata", "loadedmetadata"],
+      [dailymotion.events.VIDEO_PAUSE]: [ "pause" ],
+      //[dailymotion.events.VIDEO_PLAY]: [ "loadstart", "play", "playing", "waiting" ],
+      [dailymotion.events.VIDEO_PLAY]: [ "loadstart", "play", "playing" ],
+      [dailymotion.events.VIDEO_PLAYING]: [ "playing" ],
+      [dailymotion.events.VIDEO_TIMECHANGE]: [ "timeupdate" ],
+      [dailymotion.events.PLAYER_VOLUMECHANGE]: [ "volumechange", "mute" ],
+    };    
+    this.dmPlayer = await dailymotion.createPlayer(
+      this.options_.techId,
+      this._getPlayerConfig()
+    );
+    this.dmState = await this.getPlayerState();
+    //var vm = this;
+    this.isApiReady = true;
+    this.dmPlayer.enable_playback_controls = false;
+    console.log("AUTONEXT", this.dmPlayer.enable_playback_controls);
+
+    for (const ev in eventMapping) {
+      this.dmPlayer.on(ev, (s) => {
+        this.dmState = s;
+        for (const tev of eventMapping[ev]) {
+          this.trigger(tev)
+        }
+      });
+    }
+    this.dmPlayer.on(dailymotion.events.PLAYER_ERROR, (s) => {
+      vm.trigger("error", s.playerError);
+    });
+    this.triggerReady();
+  }
+
+  autoplay(autoplay) {
+    if (typeof autoplay !== "undefined") {
+      return this.setAutoplay(autoplay);
+    }
+
+    return this.options_.autoplay;
+  }
+
+  setAutoplay(val) {
+    return (this.options_.autoplay = val);
+  }
+
+  buffered() {
+    if (!this.dmPlayer || !this.dmPlayer.bufferedTime) {
+      return videojs.createTimeRange();
+    }
+
+    return videojs.createTimeRange(0, this.dmPlayer.bufferedTime);
+  }
+
+  createEl() {
+    var div = document.createElement("div");
+    div.setAttribute("id", this.options_.techId);
+    div.setAttribute(
+      "style",
+      "width:100%;height:100%;top:0;left:0;position:absolute"
+    );
+    div.setAttribute("class", "vjs-tech");
+
+    var divWrapper = document.createElement("div");
+    divWrapper.appendChild(div);
+
+    if (!_isOnMobile && !this.options_.dmControls) {
+      // var divBlocker = document.createElement('div');
+      // divBlocker.setAttribute('class', 'vjs-iframe-blocker');
+      // divBlocker.setAttribute('style', 'position:absolute;top:0;left:0;width:100%;height:100%');
+      //
+      // // In case the blocker is still there and we want to pause
+      // divBlocker.onclick = function() {
+      //   this.pause();
+      // }.bind(this);
+      //
+      // divWrapper.appendChild(divBlocker);
+    }
+
+    return divWrapper;
+  }
+
+  currentSrc() {
+    return this.source && this.source.src;
+  }
+
+  currentTime() {
+
+    return this.dmPlayer && this.dmState && this.dmState.videoTime;
+  }
+
+  setCurrentTime(seconds) {
+    if (!this.dmPlayer || !this.dmPlayer.seek) {
+      return;
+    }
+
+    return this.dmPlayer.seek(seconds);
+  }
+
+  dispose() {
+    if (this.dmPlayer) {
+      //Destroy the Dailymotion Player
+      this.dmPlayer.destroy(this.options_.techId);
+      Tech.prototype.dispose.call(this);
+    } else {
+      //Dailymotion API hasn't finished loading or the player is already disposed
+      var index = Dailymotion.sdkReadyQueue.indexOf(this);
+      if (index !== -1) {
+        Dailymotion.sdkReadyQueue.splice(index, 1);
+      }
+    }
+    this.dmPlayer = undefined;
+
+    this.el_.parentNode.className = this.el_.parentNode.className
+      .replace(" vjs-dailymotion", "")
+      .replace(" vjs-dailymotion-mobile", "");
+    this.el_.parentNode.removeChild(this.el_);
+
+    // Needs to be called after the Dailymotion player is destroyed,
+    // otherwise there will be a undefined reference exception
+    Tech.prototype.dispose.call(this);
+  }
+
+  duration() {
+    return this.dmState ? this.dmState.videoDuration : 0;
+  }
+
+  setDuration(seconds) {
+  }
+
+  ended() {
+  }
+
+  enterFullWindow() {
+    if (!this.dmPlayer || !this.dmPlayer.setFullscreen) {
+      return;
+    }
+    return this.dmPlayer.setFullscreen(true);
+  }
+
+  error() {
+    return this.dmState && this.dmState.playerError;
+  }
+
+  exitFullscreen() {
+    if (!this.dmPlayer || !this.dmPlayer.setFullscreen) {
+      return;
+    }
+    return this.dmPlayer.setFullscreen(false);
+  }
+
+  isFullscreen() {
+    return this.dmState && this.dmState.playerPresentationMode === "fullscreen";
+  }
+
+  // Not supported by Dailymotion
+  language() {
+  }
+
+  // Not supported by Dailymotion
+  languages() {
+  }
+
+  load() {
+    if (!this.dmPlayer || !this.dmPlayer.loadContent) {
+      return;
+    }
+    return this.dmPlayer.loadContent(this._getPlayerConfig());
+  }
+
+  // Not supported by Dailymotion
+  loop() {
+  }
+
+  async muted() {
+    
+    if(!this.dmState) {
+      return false;
+    }
+    return this.dmState.playerIsMuted;
+  }
+
+  async setMuted(mute) {
+    if (typeof mute === "undefined") {
+      const state = await this.getPlayerState();
+      mute = state.playerIsMuted ? false : true;
+    }
+
+    await this.dmPlayer.setMute(mute);
+  }
+
+  networkState() {
+  }
+
+  async pause() {
+    if (!this.dmPlayer || !this.dmPlayer.pause) {
+      return;
+    }
+
+    return await this.dmPlayer.pause();
+  }
+
+  paused() {
+    return this.dmState && this.dmState.playerIsPlaying === false;
+  }
+
+  play() {
+    if (!this.isApiReady || !this.dmPlayer || !this.dmPlayer.play) {
+      return;
+    }
+
+    return this.dmPlayer.play();
+  }
+
+  // Playback rate is not support by Dailymotion
+  playbackRate() {
+    return 1;
+  }
+
+  // Not supported by Dailymotion
+  poster() {
+    return undefined;
+  }
+
+  // Not supported by Dailymotion
+  preload() {
+    return undefined;
+  }
+
+  // TODO: Confirm if it can be more detail
+  readyState() {
+    if (!this.dmState || this.dmState.playerError) {
+      return 0; //NETWORK_EMPTY
+    }
+
+    return 4; //HAVE_ENOUGH_DATA
+  }
+
+  remainingTime() {
+    return this.dmState && this.dmState.videoDuration - this.dmState.videoTime;
+  }
+
+  requestFullscreen() {
+    return this.enterFullWindow();
+  }
+
+  enterFullScreen() {
+    return this.enterFullWindow();
+  }
+
+  reset() {
+    this.load();
+  }
+
+  seekable() {
+  }
+
+  seeking() {
+  }
+
+  src(source) {
+    if (typeof source !== "undefined") {
+      return this.setSrc(source);
+    }
+
+    return this.source;
+  }
+
+  setSrc(source) {
+    if (typeof source === "undefined") {
+      return;
+    }
+
+    this.source = source;
+    this.url = Dailymotion.parseUrl(source.src || source);
+
+    // Load the video if sdk is ready
+    if (Dailymotion.isSdkReady) {
+      this.load();
+    }
+    return this.source;
+  }
+
+  supportsFullScreen() {
+    return true;
+  }
+
+  async volume() {
+    if(!this.dmPlayer ) {
+      return 1
+    }
+    const state = await this.dmPlayer.getState();
+    return state.playerVolume;
+  }
+
+  setVolume(percentAsDecimal) {
+    if (!this.dmPlayer || !this.dmPlayer.setMute || !this.dmPlayer.setVolume) {
+      return;
+    }
+
+    if (percentAsDecimal > 0) {
+      this.dmPlayer.setMute(false);
+    } else {
+      this.dmPlayer.setMute(true);
+    }
+    this.dmPlayer.setVolume(percentAsDecimal);
+  }
+
+  async getPlayerState() {
+    if (!this.dmPlayer) {
+      return {};
+    }
+    return await this.dmPlayer.getState();
+  }
+};
+
+Dailymotion.isSupported = function () {
+  return true;
+};
+
+Dailymotion.canPlaySource = function (e) {
+  return Dailymotion.canPlayType(e.type);
+};
+
+Dailymotion.canPlayType = function (e) {
+  return e === "video/dailymotion";
+};
+
+Dailymotion.parseUrl = function (url) {
+  var result = {};
+
+  var regex = /video\/[^?|^\/]*/;
+  var match = url.match(regex);
+
+  if (match && match[0]) {
+    result.video = match[0].replace("video/", "");
+  }
+
+  var regPlaylist = /playlist(=|\/)[^&]*/;
+  match = url.match(regPlaylist);
+
+  if (match && match[0]) {
+    result.playlist = match[0].replace(/playlist(=|\/)/, "");
+  }
+
+  return result;
+};
+
+async function apiLoaded() {
+    Dailymotion.isSdkReady = true;
+
+    for (var i = 0; i < Dailymotion.sdkReadyQueue.length; ++i) {
+      await Dailymotion.sdkReadyQueue[i].initDMPlayer();
+    }
+}
+
+function loadScript(src, callback) {
+  var loaded = false;
+  var tag = document.createElement("script");
+  var firstScriptTag = document.getElementsByTagName("script")[0];
+  if (!firstScriptTag) {
+    // when loaded in jest without jsdom setup it doesn't get any element.
+    // In jest it doesn't really make sense to do anything, because no one is watching dailymotion in jest
+    return;
+  }
+  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
+  tag.onload = function () {
+    if (!loaded) {
+      loaded = true;
+      callback();
+    }
+  };
+  tag.onreadystatechange = function () {
+    if (
+      !loaded &&
+      (this.readyState === "complete" || this.readyState === "loaded")
+    ) {
+      loaded = true;
+      callback();
+    }
+  };
+  tag.src = src;
+}
+
+function injectCss() {
+  var css = // iframe blocker to catch mouse events
+    ".vjs-dailymotion .vjs-iframe-blocker { display: none; }" +
+    ".vjs-dailymotion.vjs-user-inactive .vjs-iframe-blocker { display: block; }" +
+    ".vjs-dailymotion .vjs-poster { background-size: cover; }" +
+    ".vjs-dailymotion-mobile .vjs-big-play-button { display: none; }";
+
+  var head = document.head || document.getElementsByTagName("head")[0];
+
+  var style = document.createElement("style");
+  style.setAttribute("type", "text/css");
+
+  if (style.styleSheet) {
+    style.styleSheet.cssText = css;
+  } else {
+    style.appendChild(document.createTextNode(css));
+  }
+
+  head.appendChild(style);
+}
+
+Dailymotion.sdkReadyQueue = [];
+
+// x10ckq
+Dailymotion.loadLibrary = function(playerId) {
+
+  if (typeof document !== "undefined") {
+    loadScript(`https://geo.dailymotion.com/libs/player/${playerId}.js`, () => {
+      if (window.dailymotion === undefined) {
+        window.dailymotion = { 
+          onScriptLoaded: apiLoaded
+        }
+      } else {
+        apiLoaded();
+      }  
+    });
+    injectCss();
+  }  
+}
+
+videojs.registerTech("Dailymotion", Dailymotion);
+
+export default Dailymotion;