Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting props.playing false during load doesn't prevent autoplay after loading #22

Closed
ascii-husky opened this issue Nov 23, 2016 · 7 comments

Comments

@ascii-husky
Copy link

Not sure if this is a bug. Because of my architecture i add the component always with playing=true in the initial render and set it to true/false in componentWillMount depending on the value of a cookie. This doesn't work if the cookie value is false.

@Stenerson
Copy link
Collaborator

Does it work as expected if you do the opposite? (Not sure if this is possible in your implementation but without looking into it that's my first thought.)

  • Start with playing={false}
  • Update in componentWillMount() depending on cookie

Also, just another side thought - what happens if you move it into componentDidMount()?

@ascii-husky
Copy link
Author

Thanks for your help.

I want audio playing=true as a default, so I have it set as true in my initial redux store. But if the user set it to false in a earlier session a cookie is set. To fix my problem I could read the cookie before mounting the component.

But setting the prop value to false at any time should preventing the audio from playing, imho. As I said I'm not sure if this a bug. I'll close the issue.

Thanks again.

@Stenerson
Copy link
Collaborator

@ascii-husky,
I agree that it should never play if the prop is set to false.

I modified our example AutoPlay component with hopes to reproduce this but it worked as expected for me. I've pasted the entire component below. Could you let me know what you're doing differently?

Thanks!

import React from 'react'
import ReactHowler from 'ReactHowler'

class AutoPlay extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      playing: true // Default to auto play
    }
  }

  componentWillMount() {
    // "Check cookie"... set to false
    this.setState({ playing: false })
  }

  render () {
    return (
      <div>
        <ReactHowler
          src='sound.ogg'
          // Using local state to set playing
          // When local state changes (with setState()) 
          // ReactHowler will be sent new props
          playing={this.state.playing}
        />
      </div>
    )
  }
}

export default AutoPlay

@ascii-husky
Copy link
Author

If you set the state to false in componentDidMount it will fail. Maybe you have to test it with a bigger audio file or throttle your network speed.

@Stenerson
Copy link
Collaborator

Stenerson commented Nov 25, 2016

You're right @ascii-husky, I can reproduce this by throttling my network way down and setting my local playing state to false in componentDidMount(). If I set the state to false in componentWillMount() it does not display the behavior (i.e. it works as expected).

When we set the playing state to false in componentWillMount() autoplay will never be started but if we do it in componentDidMount() we're starting autoplay then trying to stop it right away.

I was able to reproduce this with Howler itself. Here's a jsbin that show it. I picked a pretty big audio file from WikiCommons. It takes about 2.5 seconds for it to load on my unthrottled network connection. When I call pause() while it's loading it will not pause. When I call pause() after the file has loaded (5 seconds in my case) it does pause correctly.

I'll leave it up to you if you want to open a bug in the howler project. I'm not sure if they know about this limitation or not. A quick search through open issues didn't find anything obvious.

Update: I opened an issue in howler.js - goldfire/howler.js#659

@Stenerson
Copy link
Collaborator

I couldn't help myself from looking into this a little further.

If howler receives a call to pause() before the audio is loaded it puts the command into an internal queue to be run after loading has completed. The issue is that they are checking for autoplay after the queue has been unloaded. This means that the audio will be paused (even though it hasn't started yet) then it will be played.

See Howler.js Source

    // Fire the loaded event.
    if (self._state !== 'loaded') {
      self._state = 'loaded';
      self._emit('load');
      self._loadQueue(); // <-- Going to call pause() in here...
    }

    // Begin playback if specified.
    if (self._autoplay) {
      self.play(); // <-- Then autoplay
    }

Maybe we should use the play() function rather than setting autoplay?
Maybe we should open a bug in howler to see what James thinks?

@Stenerson
Copy link
Collaborator

I did verify that we can work around this issue altogether by calling play() rather than setting autoplay when initializing.

Functionally this should be identical, except for this specific issue. I believe this to be a bug, not a feature in Howler, so I'm going to reopen this and fix it with a hotfix release.

@Stenerson Stenerson reopened this Nov 26, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants