Syncing Up Play/Pause: Avoiding an Infinite Loop
As mentioned in our last Couch Potato installment, one of the toughest features we implemented in our extension that lets friends watch shows together on Hulu was synching up play/pause across users. And one of the trickiest things to avoid while working on that was accidentally triggering the play/pause button to click infinitely.
Our solution to this problem largely rests on the fact that event.target did not match event.currentTarget when an actual person clicked on the play/pause button, but they did match if it was a simulated click (see this blog post for more details about the difference between target and currentTarget). By adding an if/else statement to our event listener on the play/pause button, we were able to stop our extension from talking to the Couch Potato backend if a simulated click triggered by another user pressing play/pause occurred.
But one if/else statement that terminates with a computer-generated click isn’t enough. With only this check in place, it’s still possible for a user to click the play/pause button, and then have a simulated click take place before stopping the play/pause loop.
For instance, Grace could hit play on her computer, which then hits play on everyone’s computer on her couch (our term for chat room), but her computer receives the same command to hit the play/pause button that everyone else received, even though she’s the one who hit play and started the synchronized play/pause loop. With no check in place, the play/pause button is hit on her computer again, pausing her video while everyone else’s plays. That’s not the behavior we want to happen!
To avoid this, we decided to take further advantage of localStorage by storing a huluID that identifies each individual user on the couch. Because we don’t anticipate too many users on a couch at once, we felt it was sufficient to randomly generate a four-digit number. We did so in a function that runs when the extension is launched and stores that number as a string on localStorage.
We then added a check to the event listener on the window that listened for a message telling it to click the play/pause button. If the huluID sent along with the cross-domain fetch request through the sockets and back up to the window doesn’t match the user’s huluID, the computer generates a click on the play/pause button. But if it does match the user’s huluID, it doesn’t do anything.
As a result, Grace can hit play, trigger everyone else’s computers to play, and not worry about accidentally pausing her own screen again. Voila!
While I wish I could say this was the last tricky element of getting the play/pause loop to work, it definitely was not. Because of the way our code was written at this point, it would successfully click the play/pause button once on everyone’s screen, but it didn’t distinguish between whether the show was playing or paused.
As such, if Caitlin joined the couch when her video was paused, but June was already watching a show and paused it to say hi to Caitlin, it would successfully pause June’s video, but accidentally play Caitlin’s, preventing the two of them from ever successfully watching a show together!
Stay tuned for our next post, where I’ll cover how we resolved this issue.
Interested in learning more about Couch Potato? Start this blog series from the beginning! And don’t forget to download Couch Potato from the Chrome store so you can start watching shows with friends now!