jPlayer is such a pain in the ass

Can someone please tell me why clicking on the "Live" or "DNA Radio" links on the webcast page does not cause it to start playing? You have to go to the bottom and hit the the play triangle to actually get it to go. I'm calling p.jPlayer("play",0); and it's doing fuck-all. How do I do exactly-the-thing-that-hitting-the-triangle-does?

It does the intended thing on the archives page, so whatever's going wrong is... obscure. And probably related to the difference between seekable and non-seekable or finite and infinite streams. And yet, hitting the triangles does the right thing, so I want to just do that.

Code is in dnaplayer.js. Making a copy and uncommenting the return at the front of LOG() may be helpful.


Update: Apparently this fixes it, though I can't really explain why. Before calling "play", do:

    if (secs == 0) secs = NaN;   // You've got to be fucking kidding me.


Previously.

Tags: , , , ,

11 Responses:

  1. nonplus says:

    You fixed it! Or... Macworld problems. Works as intended (no triangle fiddling required) with my IE10, FF17esr, Chrome26.

  2. Line Noise says:

    It works in Firefox 20.0 on Linux. Click the link and music starts playing.

  3. Alan Storm says:

    Per the other comments in this thread, I was able to reproduce your problem on my 10.6.8 Mac running Chrome 25.0.1364.172.

    I was able to get the player running by using the following

    p = $("#jquery_jplayer_1");
    p.jPlayer("play",NaN);

    Or, if you want to give up completely you can just trigger a click on the play button.

    $('.jp-play').trigger('click');

    If you're interested in the why, I downloaded the uncompressed source and traced the play call to

    play: function(time) {
    time = (typeof time === "number") ? time : NaN; // Remove jQuery event from click handler
    if(this.status.srcSet) {
    this.focus();
    if(this.html.active) {
    console.log("html_paly");
    this._html_play(time);
    } else if(this.flash.active) {
    console.log("flash_play");
    this._flash_play(time);
    }
    } else {
    console.log("_urlNotSetError");
    this._urlNotSetError("play");
    }
    },

    which in turn calls _html_play, which is where things go south. The _html_play function has the following

    try {
    // !media.seekable is for old HTML5 browsers, like Firefox 3.6.
    // Checking seekable.length is important for iOS6 to work with setMedia().play(time)
    if(!media.seekable || typeof media.seekable === "object" && media.seekable.length > 0) {
    media.currentTime = time;
    media.play();
    } else {
    throw 1;
    }
    } catch(err) {
    this.internal.htmlDlyCmdId = setTimeout(function() {
    self.play(time);
    }, 250);
    return; // Cancel execution and wait for the delayed command.
    }

    The media variable refers to an html <audio/> element. In my version of chrome media.seekable.length is 0 for the player on the webcast page. This condition throws the exception "1", which is caught, ultimately calling self.play(time); in the setTimeout function ... which is the same play function as above, which makes the same things happen again. Endless recursion, do not pass go, do not collection $200.

    • Alan Storm says:

      Here's a gist with better formatted source code, since I can't make WordPress format things the way I'd like.

      • nonplus says:

        nice sleuthing mr storm.

        seems like `media thinks differently. as the code is simply reading .seekable, media.* must instantiate with values that deviate from almost every other implementation. shades of "<!--[if IE 6]>" LOL.-->

    • jwz says:

      Wow, thanks! Apparently the fix is this, before calling "play":

      if (secs == 0) secs = NaN; // You've got to be fucking kidding me.

      Though from reading the code, I don't understand why, since it seems to only do tests like "time > 0".

  4. nonplus says:

    (oops - forgot about the non-parsing) i was saying, "shades of `if ie6`" -shudder-