| |
| function createPluginReplacement(root, parent, host, attributeNames, attributeValues) |
| { |
| return new Replacement(root, parent, host, attributeNames, attributeValues); |
| }; |
| |
| function Replacement(root, parent, host, attributeNames, attributeValues) |
| { |
| this.root = root; |
| this.parent = parent; |
| this.host = host; |
| this.listeners = {}; |
| this.scriptObject = {}; |
| |
| this.autoExitFullScreen = true; |
| this.postEvents = false; |
| this.height = 0; |
| this.width = 0; |
| this.src = ""; |
| this.autohref = false; |
| this.href = ""; |
| this.qtsrc = ""; |
| this.baseUrl = ""; |
| this.target = ""; |
| |
| this.createVideoElement(attributeNames, attributeValues); |
| this.createScriptInterface(); |
| }; |
| |
| Replacement.prototype = { |
| |
| HandledVideoEvents: { |
| loadstart: 'handleLoadStart', |
| error: 'handleError', |
| loadedmetadata: 'handleLoadedMetaData', |
| canplay: 'qt_canplay', |
| canplaythrough: 'qt_canplaythrough', |
| play: 'qt_play', |
| pause: 'qt_pause', |
| ended: 'handleEnded', |
| webkitfullscreenchange: 'handleFullscreenChange', |
| }, |
| |
| AttributeMap: { |
| autoexitfullscreen: 'autoExitFullScreen', |
| postdomevents: 'postEvents', |
| height: 'height', |
| width: 'width', |
| qtsrc: 'qtsrc', |
| src: 'src', |
| airplay: 'x-webkit-airplay=', |
| href: 'href', |
| target: 'target', |
| }, |
| |
| MethodMap: { |
| SetURL : 'setURL', |
| GetURL : 'url', |
| Play : 'play', |
| Stop : 'pause', |
| GetRate : 'rate', |
| SetRate : 'setRate', |
| IsFullScreen : 'isFullScreen', |
| ExitFullScreen : 'exitFullScreen', |
| GetPluginStatus : 'pluginStatus', |
| GetTime : 'currentTime', |
| SetTime : 'setCurrentTime', |
| SeekToDate : 'seekToDate', |
| GetDate : 'date', |
| GetDuration : 'duration', |
| GetTimeScale : 'timeScale', |
| GetMaxTimeLoaded : 'maxTimeLoaded', |
| GetMaxBytesLoaded : 'maxBytesLoaded', |
| GetMovieSize : 'movieSize', |
| GetTimedMetadataUpdates : 'timedMetadataUpdates', |
| GetAccessLog : 'accessLog', |
| GetErrorLog : 'errorLog', |
| }, |
| |
| TimeScale: 30000, |
| |
| createVideoElement: function(attributeNames, attributeValues) |
| { |
| var video = this.video = document.createElement('video'); |
| |
| for (name in this.HandledVideoEvents) |
| video.addEventListener(name, this, false); |
| |
| for (i = 0; i < attributeNames.length; i++) { |
| var property = this.AttributeMap[attributeNames[i]]; |
| if (this[property] != undefined) |
| this[property] = attributeValues[i]; |
| } |
| |
| video.setAttribute('pseudo', '-webkit-plugin-replacement'); |
| video.setAttribute('controls', 'controls'); |
| this.setStatus('Waiting'); |
| |
| var src = this.resolveRelativeToUrl(this.src, ""); |
| this.baseUrl = src; |
| |
| // The 'qtsrc' attribute is used when a page author wanted to always use the QuickTime plug-in |
| // to load a media type even if another plug-in was registered for that type. It tells the |
| // plug-in to ignore the 'src' url, and to load the 'qtsrc' url instead. |
| if (this.qtsrc) |
| src = this.resolveRelativeToUrl(this.qtsrc, this.src); |
| if (this.href && this.target) { |
| src = this.resolveRelativeToUrl(this.href, this.src); |
| video.poster = this.src; |
| video.setAttribute('preload', 'none'); |
| } |
| |
| if (src.length) { |
| this.setStatus('Validating'); |
| this.video.src = src; |
| } |
| |
| this.root.appendChild(video); |
| }, |
| |
| resolveRelativeToUrl: function(url, baseUrl) |
| { |
| if (url.indexOf('://') != -1) |
| return url; |
| if (baseUrl.indexOf('://') == -1) |
| baseUrl = this.resolveRelativeToUrl(baseUrl, document.baseURI); |
| |
| var base = document.createElement('base'); |
| base.href = baseUrl; |
| document.head.appendChild(base); |
| |
| var resolver = document.createElement('a'); |
| resolver.href = url; |
| url = resolver.href; |
| |
| document.head.removeChild(base); |
| base = null; |
| |
| return url; |
| }, |
| |
| createScriptInterface: function() |
| { |
| for (name in this.MethodMap) { |
| var methodName = this.MethodMap[name]; |
| this.scriptObject[name] = this[methodName].bind(this); |
| } |
| }, |
| |
| handleEvent: function(event) |
| { |
| if (event.target !== this.video) |
| return; |
| |
| try { |
| var eventData = this.HandledVideoEvents[event.type]; |
| if (!eventData) |
| return; |
| |
| if (this[eventData] && typeof this[eventData] === "function") |
| this[eventData].call(this, event); |
| else |
| this.postEvent(eventData); |
| } catch(e) { |
| if (window.console) |
| console.error(e); |
| } |
| }, |
| |
| postEvent: function(eventName) |
| { |
| try { |
| if (this.postEvents) |
| this.host.postEvent(eventName); |
| } catch(e) { } |
| }, |
| |
| setStatus: function(status) |
| { |
| this.status = status; |
| }, |
| |
| handleLoadedMetaData: function(event) |
| { |
| this.setStatus('Playable'); |
| this.postEvent('qt_validated'); |
| this.postEvent('qt_loadedfirstframe'); |
| this.postEvent('qt_loadedmetadata'); |
| }, |
| |
| handleFullscreenChange: function(event) |
| { |
| this.postEvent(this.isFullScreen() ? 'qt_enterfullscreen' : 'qt_exitfullscreen'); |
| }, |
| |
| handleError: function(event) |
| { |
| this.setStatus('Error'); |
| this.postEvent('qt_error'); |
| }, |
| |
| handleLoadStart:function(event) |
| { |
| if (this.video.poster) |
| this.setStatus('Waiting'); |
| else |
| this.setStatus('Loading'); |
| this.postEvent('qt_begin'); |
| }, |
| |
| handleEnded: function(event) |
| { |
| this.postEvent('qt_ended'); |
| if (this.isFullScreen() && this.autoExitFullScreen) |
| document.webkitExitFullscreen(); |
| }, |
| |
| isFullScreen: function() |
| { |
| return document.webkitCurrentFullScreenElement === this.video; |
| }, |
| |
| setURL: function(url) |
| { |
| this.setStatus('Validating'); |
| if (url.length) |
| url = this.resolveRelativeToUrl(url, this.baseUrl); |
| this.video.src = url; |
| }, |
| |
| url: function() |
| { |
| return this.video.currentSrc; |
| }, |
| |
| play: function() |
| { |
| this.video.play(); |
| }, |
| |
| pause: function() |
| { |
| this.video.playbackRate = 0; |
| this.video.pause(); |
| }, |
| |
| rate: function() |
| { |
| return this.video.paused ? 0 : 1; |
| }, |
| |
| setRate: function(rate) |
| { |
| if (rate) |
| this.video.play(); |
| else |
| this.video.pause(); |
| }, |
| |
| exitFullScreen: function() |
| { |
| document.webkitExitFullscreen(); |
| }, |
| |
| pluginStatus: function() |
| { |
| return this.status; |
| }, |
| |
| currentTime: function() |
| { |
| return this.video.currentTime * this.TimeScale; |
| }, |
| |
| setCurrentTime: function(time) |
| { |
| this.video.currentTime = time / this.TimeScale; |
| }, |
| |
| seekToDate: function() |
| { |
| // FIXME: not implemented yet. |
| }, |
| |
| date: function() |
| { |
| return new Date(); |
| }, |
| |
| duration: function() |
| { |
| return this.video.duration * this.TimeScale; |
| }, |
| |
| timeScale: function() |
| { |
| // Note: QuickTime movies and MPEG-4 files have a timescale, but it is not exposed by all media engines. |
| // 30000 works well with common frame rates, eg. 29.97 NTSC can be represented accurately as a time |
| // scale of 30000 and frame duration of 1001. |
| return 30000; |
| }, |
| |
| maxTimeLoaded: function() |
| { |
| return this.video.duration * this.TimeScale; |
| }, |
| |
| maxBytesLoaded: function() |
| { |
| var percentLoaded = this.video.buffered.end(0) / this.video.duration; |
| return percentLoaded * this.movieSize(); |
| }, |
| |
| movieSize: function() |
| { |
| try { |
| return this.host.movieSize; |
| } catch(e) { } |
| |
| return 0; |
| }, |
| |
| timedMetadataUpdates: function() |
| { |
| try { |
| return this.host.timedMetaData; |
| } catch(e) { } |
| |
| return null; |
| }, |
| |
| accessLog: function() |
| { |
| try { |
| return this.host.accessLog; |
| } catch(e) { } |
| |
| return null; |
| }, |
| |
| errorLog: function() |
| { |
| try { |
| return this.host.errorLog; |
| } catch(e) { } |
| |
| return null; |
| }, |
| }; |
| |