Skip to content

Commit

Permalink
Merge pull request souporserious#44 from dobrite/chore-audio-object-v…
Browse files Browse the repository at this point in the history
…endor

chore(HTML5): break AudioObject to its own vendor
  • Loading branch information
souporserious authored Nov 7, 2017
2 parents a51f7cb + bee9ee9 commit 7bf8508
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 87 deletions.
2 changes: 1 addition & 1 deletion src/Player.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class Player extends Component {
defaultMuted,
...extraProps
} = this.props
const { vendor, component } = getVendor(src, _vendor)
const { vendor, component } = getVendor(src, _vendor, !!extraProps.useAudioObject)

return createElement(component, {
ref: this._setPlayer,
Expand Down
8 changes: 6 additions & 2 deletions src/utils/get-vendor.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import HTML5 from '../vendors/HTML5'
import AudioObject from '../vendors/AudioObject'
import Vimeo from '../vendors/Vimeo'
import Youtube from '../vendors/Youtube'

export default function getVendor(src, vendor) {
export default function getVendor(src, vendor, useAudioObject) {
src = src || ''

if (vendor === 'youtube' || /youtube.com|youtu.be/.test(src)) {
Expand All @@ -11,6 +12,9 @@ export default function getVendor(src, vendor) {
return { vendor: 'vimeo', component: Vimeo }
} else {
const isAudio = vendor === 'audio' || /\.(mp3|wav|m4a)($|\?)/i.test(src)
return { vendor: isAudio ? 'audio' : 'video', component: HTML5 }
return {
vendor: isAudio ? 'audio' : 'video',
component: isAudio && useAudioObject ? AudioObject : HTML5
}
}
}
74 changes: 74 additions & 0 deletions src/vendors/AudioObject.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { Component, createElement } from 'react'
import PropTypes from 'prop-types'
import { findDOMNode } from 'react-dom'
import vendorPropTypes from './vendor-prop-types'
import HTML5 from './HTML5'

class AudioObject extends HTML5 {
static propTypes = {
...vendorPropTypes,
useAudioObject: PropTypes.bool,
}

componentWillMount() {
const { src } = this.props

this._createAudioObject(src)
this._bindAudioObjectEvents(this.props)
}

componentWillReceiveProps(nextProps) {
const { src } = nextProps

// destroy and recreate audio object to clean up any browser state
if (this.props.src !== src) {
this._destroyAudioObject()
this._createAudioObject(src)
}
// bind any new props to current audio object
this._bindAudioObjectEvents(nextProps)
}

componentWillUnmount() {
this._destroyAudioObject()
}

get node() { // TODO look
console.warn('findDOMNode for AudioObject')
return findDOMNode(this._player)
}

_createAudioObject(src) {
this._player = new Audio(src)
}

_destroyAudioObject() {
// even when stopped and set to null,
// chrome will continue to buffer files
// set the source to some benign value
// (FF throws on an empty string)
// and load it to truly stop buffering
this.stop()
this._player.src = 'about:blank'
this._player.load()
this._player = null
}

_bindAudioObjectEvents({ extraProps }) {
const playerEvents = this._playerEvents

Object.keys(extraProps).forEach(key => {
this._player[key] = extraProps[key]
})

Object.keys(playerEvents).forEach(key => {
this._player[key.toLowerCase()] = playerEvents[key]
})
}

render() {
return null
}
}

export default AudioObject
92 changes: 8 additions & 84 deletions src/vendors/HTML5.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,7 @@ import { findDOMNode } from 'react-dom'
import vendorPropTypes from './vendor-prop-types'

class HTML5 extends Component {
static propTypes = {
...vendorPropTypes,
useAudioObject: PropTypes.bool,
}

componentWillMount() {
const { src, extraProps: { useAudioObject } } = this.props

if (useAudioObject) {
this._createAudioObject(src)
this._bindAudioObjectEvents(this.props)
}
}

componentWillReceiveProps(nextProps) {
const { src, extraProps: { useAudioObject } } = nextProps

if (useAudioObject) {
// destroy and recreate audio object to clean up any browser state
if (this.props.src !== src) {
this._destroyAudioObject()
this._createAudioObject(src)
}
// bind any new props to current audio object
this._bindAudioObjectEvents(nextProps)
}
}

componentWillUnmount() {
if (this.props.extraProps.useAudioObject) {
this._destroyAudioObject()
}
}
static propTypes = vendorPropTypes

get instance() {
return this._player
Expand Down Expand Up @@ -142,60 +110,16 @@ class HTML5 extends Component {
this.props.onVolumeChange(volume)
}

// Handle Audio Object
_createAudioObject(src) {
this._player = new Audio(src)
}

_destroyAudioObject() {
// even when stopped and set to null,
// chrome will continue to buffer files
// set the source to some benign value
// (FF throws on an empty string)
// and load it to truly stop buffering
this.stop()
this._player.src = 'about:blank'
this._player.load()
this._player = null
}

_setRef = c => {
// if we are using audio object, we've already set
// this._player in componentWillReceiveProps so we
// do not want to wipe it out with the `null` returned
// from render
if (this.props.extraProps.useAudioObject !== true) {
this._player = c
}
}

_bindAudioObjectEvents({ extraProps }) {
const playerEvents = this._playerEvents

Object.keys(extraProps).forEach(key => {
this._player[key] = extraProps[key]
})
render() {
const { vendor, src, extraProps } = this.props

Object.keys(playerEvents).forEach(key => {
this._player[key.toLowerCase()] = playerEvents[key]
return createElement(vendor, {
ref: c => (this._player = c),
src,
...extraProps,
...this._playerEvents,
})
}

render() {
const { vendor, src } = this.props
const { useAudioObject, ...extraProps } = this.props.extraProps

if (!useAudioObject) {
return createElement(vendor, {
ref: this._setRef,
src,
...extraProps,
...this._playerEvents,
})
} else {
return null
}
}
}

export default HTML5

0 comments on commit 7bf8508

Please sign in to comment.