Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/webtorrent/webtorrent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFeross Aboukhadijeh <feross@feross.org>2015-12-28 16:13:45 +0300
committerFeross Aboukhadijeh <feross@feross.org>2015-12-28 16:13:45 +0300
commit0210d5592652407d135e8b01c9d8ca1d87976c68 (patch)
treef07321b54e0e2b76cbab6ac4213fa2e937d36aea /lib
parent8a551101fc69f8f3859e15379e6dd68f56a54b75 (diff)
parent41dc75b8e7420297043d2fb294ce334a498498df (diff)
Merge pull request #425 from valeriangalliat/feature/render-to
[Feature proposition] Allow to render a torrent into an existing element
Diffstat (limited to 'lib')
-rw-r--r--lib/append-to.js169
-rw-r--r--lib/file.js12
-rw-r--r--lib/render-to.js17
-rw-r--r--lib/render.js150
4 files changed, 197 insertions, 151 deletions
diff --git a/lib/append-to.js b/lib/append-to.js
index c68e3f9..672d711 100644
--- a/lib/append-to.js
+++ b/lib/append-to.js
@@ -1,26 +1,6 @@
-var debug = require('debug')('webtorrent:append-to')
-var MediaSourceStream = require('mediasource')
-var path = require('path')
-var videostream = require('videostream')
-
-var VIDEOSTREAM_EXTS = [ '.mp4', '.m4v', '.m4a' ]
-
-var MEDIASOURCE_VIDEO_EXTS = [ '.mp4', '.m4v', '.webm' ]
-var MEDIASOURCE_AUDIO_EXTS = [ '.m4a', '.mp3' ]
-var MEDIASOURCE_EXTS = MEDIASOURCE_VIDEO_EXTS.concat(MEDIASOURCE_AUDIO_EXTS)
-
-var AUDIO_EXTS = [ '.wav', '.aac', '.ogg', '.oga' ]
-var IMAGE_EXTS = [ '.jpg', '.jpeg', '.png', '.gif', '.bmp' ]
-var IFRAME_EXTS = [ '.css', '.html', '.js', '.md', '.pdf', '.txt' ]
-
-var MediaSource = typeof window !== 'undefined' && window.MediaSource
+var render = require('./render')
module.exports = function appendTo (file, rootElem, cb) {
- if (!cb) cb = noop
- var elem
- var extname = path.extname(file.name).toLowerCase()
- var currentTime = 0
-
if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) {
throw new Error(
'Invalid video/audio node argument. Argument must be root element that ' +
@@ -28,141 +8,28 @@ module.exports = function appendTo (file, rootElem, cb) {
)
}
- if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) appendToMediaSource()
- else if (AUDIO_EXTS.indexOf(extname) >= 0) appendToAudio()
- else if (IMAGE_EXTS.indexOf(extname) >= 0) appendToImage()
- else if (IFRAME_EXTS.indexOf(extname) >= 0) appendToIframe()
- else nextTick(cb, new Error('Unsupported file type "' + extname + '": Cannot append to DOM'))
-
- function appendToMediaSource () {
- if (!MediaSource) {
- return nextTick(cb, new Error(
- 'Video/audio streaming is not supported in your browser. You can still share ' +
- 'or download ' + file.name + ' (once it\'s fully downloaded). Use Chrome for ' +
- 'MediaSource support.'
- ))
- }
-
- var tagName = MEDIASOURCE_VIDEO_EXTS.indexOf(extname) >= 0 ? 'video' : 'audio'
-
- if (VIDEOSTREAM_EXTS.indexOf(extname) >= 0) useVideostream()
- else useMediaSource()
-
- function useVideostream () {
- debug('Use `videostream` package for ' + file.name)
- createElem()
- elem.addEventListener('error', fallbackToMediaSource)
- elem.addEventListener('playing', onPlaying)
- videostream(file, elem)
- }
-
- function useMediaSource () {
- debug('Use MediaSource API for ' + file.name)
- createElem()
- elem.addEventListener('error', fallbackToBlobURL)
- elem.addEventListener('playing', onPlaying)
-
- file.createReadStream().pipe(new MediaSourceStream(elem, { extname: extname }))
- if (currentTime) elem.currentTime = currentTime
- }
-
- function useBlobURL () {
- debug('Use Blob URL for ' + file.name)
- createElem()
- elem.addEventListener('error', fatalError)
- elem.addEventListener('playing', onPlaying)
- file.getBlobURL(function (err, url) {
- if (err) return fatalError(err)
- elem.src = url
- if (currentTime) elem.currentTime = currentTime
- })
- }
-
- function fallbackToMediaSource (err) {
- debug('videostream error: fallback to MediaSource API: %o', err.message || err)
- elem.removeEventListener('error', fallbackToMediaSource)
- elem.removeEventListener('playing', onPlaying)
-
- useMediaSource()
- }
-
- function fallbackToBlobURL (err) {
- debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)
- elem.removeEventListener('error', fallbackToBlobURL)
- elem.removeEventListener('playing', onPlaying)
-
- useBlobURL()
- }
-
- function createElem (time) {
- if (!elem) {
- elem = document.createElement(tagName)
- elem.controls = true
- elem.autoplay = true // for chrome
- elem.play() // for firefox
-
- elem.addEventListener('progress', function () {
- currentTime = elem.currentTime
- })
-
- rootElem.appendChild(elem)
- }
+ render(file, function (tagName) {
+ if (tagName === 'video' || tagName === 'audio') return createMedia(tagName)
+ else return createElem(tagName)
+ }, function (err, elem) {
+ if (err && elem) {
+ elem.remove()
}
- }
- function onPlaying () {
- elem.removeEventListener('playing', onPlaying)
- cb(null, elem)
- }
+ cb(err, elem)
+ })
- function appendToAudio () {
- elem = document.createElement('audio')
+ function createMedia (tagName) {
+ var elem = createElem(tagName)
elem.controls = true
- elem.autoplay = true
- rootElem.appendChild(elem)
- file.getBlobURL(function (err, url) {
- if (err) return fatalError(err)
- elem.addEventListener('error', fatalError)
- elem.addEventListener('playing', onPlaying)
- elem.src = url
- elem.play()
- })
+ elem.autoplay = true // for chrome
+ elem.play() // for firefox
+ return elem
}
- function appendToImage () {
- file.getBlobURL(function (err, url) {
- if (err) return fatalError(err)
- elem = document.createElement('img')
- elem.src = url
- elem.alt = file.name
- rootElem.appendChild(elem)
- cb(null, elem)
- })
- }
-
- function appendToIframe () {
- file.getBlobURL(function (err, url) {
- if (err) return fatalError(err)
- elem = document.createElement('iframe')
- elem.src = url
- if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts'
- rootElem.appendChild(elem)
- cb(null, elem)
- })
- }
-
- function fatalError (err) {
- if (elem) elem.remove()
- err.message = 'Error appending file "' + file.name + '" to DOM: ' + err.message
- debug(err.message)
- if (cb) cb(err)
+ function createElem (tagName) {
+ var elem = document.createElement(tagName)
+ rootElem.appendChild(elem)
+ return elem
}
}
-
-function noop () {}
-
-function nextTick (cb, err, val) {
- process.nextTick(function () {
- if (cb) cb(err, val)
- })
-}
diff --git a/lib/file.js b/lib/file.js
index 340ff37..09d3af8 100644
--- a/lib/file.js
+++ b/lib/file.js
@@ -1,6 +1,7 @@
module.exports = File
var appendTo = require('./append-to')
+var renderTo = require('./render-to')
var eos = require('end-of-stream')
var EventEmitter = require('events').EventEmitter
var FileStream = require('./file-stream')
@@ -130,3 +131,14 @@ File.prototype.appendTo = function (elem, cb) {
if (typeof elem === 'string') elem = document.querySelector(elem)
appendTo(this, elem, cb)
}
+
+/**
+ * Render the file in an existing DOM element.
+ * @param {Element|string} elem
+ * @param {function} cb
+ */
+File.prototype.renderTo = function (elem, cb) {
+ if (typeof window === 'undefined') throw new Error('browser-only method')
+ if (typeof elem === 'string') elem = document.querySelector(elem)
+ renderTo(this, elem, cb)
+}
diff --git a/lib/render-to.js b/lib/render-to.js
new file mode 100644
index 0000000..d2b47cc
--- /dev/null
+++ b/lib/render-to.js
@@ -0,0 +1,17 @@
+var path = require('path')
+var render = require('./render')
+
+module.exports = function renderTo (file, elem, cb) {
+ render(file, function (tagName) {
+ if (elem.nodeName !== tagName.toUpperCase()) {
+ var extname = path.extname(file.name).toLowerCase()
+
+ throw new Error(
+ 'Cannot render "' + extname + '" inside a "' +
+ elem.nodeName.toLowerCase() + '" element, expected "' + tagName + '"'
+ )
+ }
+
+ return elem
+ }, cb)
+}
diff --git a/lib/render.js b/lib/render.js
new file mode 100644
index 0000000..84c3a29
--- /dev/null
+++ b/lib/render.js
@@ -0,0 +1,150 @@
+var debug = require('debug')('webtorrent:render')
+var MediaSourceStream = require('mediasource')
+var path = require('path')
+var videostream = require('videostream')
+
+var VIDEOSTREAM_EXTS = [ '.mp4', '.m4v', '.m4a' ]
+
+var MEDIASOURCE_VIDEO_EXTS = [ '.mp4', '.m4v', '.webm' ]
+var MEDIASOURCE_AUDIO_EXTS = [ '.m4a', '.mp3' ]
+var MEDIASOURCE_EXTS = MEDIASOURCE_VIDEO_EXTS.concat(MEDIASOURCE_AUDIO_EXTS)
+
+var AUDIO_EXTS = [ '.wav', '.aac', '.ogg', '.oga' ]
+var IMAGE_EXTS = [ '.jpg', '.jpeg', '.png', '.gif', '.bmp' ]
+var IFRAME_EXTS = [ '.css', '.html', '.js', '.md', '.pdf', '.txt' ]
+
+var MediaSource = typeof window !== 'undefined' && window.MediaSource
+
+module.exports = function render (file, getElem, cb) {
+ if (!cb) cb = noop
+ var elem
+ var extname = path.extname(file.name).toLowerCase()
+ var currentTime = 0
+
+ if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) renderMediaSource()
+ else if (AUDIO_EXTS.indexOf(extname) >= 0) renderAudio()
+ else if (IMAGE_EXTS.indexOf(extname) >= 0) renderImage()
+ else if (IFRAME_EXTS.indexOf(extname) >= 0) renderIframe()
+ else nextTick(cb, new Error('Unsupported file type "' + extname + '": Cannot append to DOM'))
+
+ function renderMediaSource () {
+ if (!MediaSource) {
+ return nextTick(cb, new Error(
+ 'Video/audio streaming is not supported in your browser. You can still share ' +
+ 'or download ' + file.name + ' (once it\'s fully downloaded). Use Chrome for ' +
+ 'MediaSource support.'
+ ))
+ }
+
+ var tagName = MEDIASOURCE_VIDEO_EXTS.indexOf(extname) >= 0 ? 'video' : 'audio'
+
+ if (VIDEOSTREAM_EXTS.indexOf(extname) >= 0) useVideostream()
+ else useMediaSource()
+
+ function useVideostream () {
+ debug('Use `videostream` package for ' + file.name)
+ prepareElem()
+ elem.addEventListener('error', fallbackToMediaSource)
+ elem.addEventListener('playing', onPlaying)
+ videostream(file, elem)
+ }
+
+ function useMediaSource () {
+ debug('Use MediaSource API for ' + file.name)
+ prepareElem()
+ elem.addEventListener('error', fallbackToBlobURL)
+ elem.addEventListener('playing', onPlaying)
+
+ file.createReadStream().pipe(new MediaSourceStream(elem, { extname: extname }))
+ if (currentTime) elem.currentTime = currentTime
+ }
+
+ function useBlobURL () {
+ debug('Use Blob URL for ' + file.name)
+ prepareElem()
+ elem.addEventListener('error', fatalError)
+ elem.addEventListener('playing', onPlaying)
+ file.getBlobURL(function (err, url) {
+ if (err) return fatalError(err)
+ elem.src = url
+ if (currentTime) elem.currentTime = currentTime
+ })
+ }
+
+ function fallbackToMediaSource (err) {
+ debug('videostream error: fallback to MediaSource API: %o', err.message || err)
+ elem.removeEventListener('error', fallbackToMediaSource)
+ elem.removeEventListener('playing', onPlaying)
+
+ useMediaSource()
+ }
+
+ function fallbackToBlobURL (err) {
+ debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)
+ elem.removeEventListener('error', fallbackToBlobURL)
+ elem.removeEventListener('playing', onPlaying)
+
+ useBlobURL()
+ }
+
+ function prepareElem () {
+ if (!elem) {
+ elem = getElem(tagName)
+
+ elem.addEventListener('progress', function () {
+ currentTime = elem.currentTime
+ })
+ }
+ }
+ }
+
+ function onPlaying () {
+ elem.removeEventListener('playing', onPlaying)
+ cb(null, elem)
+ }
+
+ function renderAudio () {
+ elem = getElem('audio')
+ file.getBlobURL(function (err, url) {
+ if (err) return fatalError(err)
+ elem.addEventListener('error', fatalError)
+ elem.addEventListener('playing', onPlaying)
+ elem.src = url
+ })
+ }
+
+ function renderImage () {
+ elem = getElem('img')
+ file.getBlobURL(function (err, url) {
+ if (err) return fatalError(err)
+ elem.src = url
+ elem.alt = file.name
+ cb(null)
+ })
+ }
+
+ function renderIframe () {
+ elem = getElem('iframe')
+
+ file.getBlobURL(function (err, url) {
+ if (err) return fatalError(err)
+ elem.src = url
+ if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts'
+ cb(null, elem)
+ })
+ }
+
+ function fatalError (err) {
+ err.message = 'Error rendering file "' + file.name + '": ' + err.message
+ debug(err.message)
+ if (cb) cb(err)
+ }
+}
+
+function noop () {}
+
+function nextTick (cb, err, val) {
+ process.nextTick(function () {
+ if (cb) cb(err, val)
+ })
+}