0

I'm creating a loading screen that will load when a user is connecting to the game that will be constantly playing YouTube videos using the iFrame API that will be fetched from a file named callback.php. Everything seems to work fine for the first song, except that after the first song it gets replayed and the track information above the video shows information for the next song...

I'm not a person who uses JavaScript regularly, and I've been forced to use it this time. I need to make sure that the whole system is getting the right values all of the time otherwise it will be unreliable and will cause problems.

My JavaScript code:

function youtubeDisable() {
    $('.youtube').addClass('youtube-novideo').removeClass('youtube');
    $("#youtube-widget").addClass('info').removeAttr('id');
    $(".youtube-novideo>.youtube-header>div:nth-child(2)>h1").html('Loading screen Playlists...');
    $(".youtube-novideo>.youtube-header>div:nth-child(2)>h2").remove();
    $(".youtube-novideo>.info").append("<p>Visit portal.repeatgaming.com to create Loading screen playlists.</p>");
    $("#youtube-preloader").remove();
    $(".youtube-novideo").show();
}

var song,
    playing,
    player,
    run=false,
    systemglitch=false;

var jqxhr = $.ajax("callback.php?action=doesuserhavemusic&steamid="+params.steamid).done(function(e) {
    if (e.success == true) {
        run = true;
        console.log('[PLAYLISTS] User '+params.steamid+' is subscribed to playlists and has songs within them.');
        var tag = document.createElement('script');
        tag.src = "https://www.youtube.com/iframe_api";
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    } else {
        run = false;
        console.log('[PLAYLISTS] User '+params.steamid+' is not subscribed to any playlists. Not playing any music.');
        youtubeDisable();
    }
}).fail(function() {
    console.log('[PLAYLISTS] Failed to initialise. Assuming error with callback.');
    run = false;
    youtubeDisable();
    systemglitch = 'Failed to connect to Portal to fetch songs.';
});

function getNextSong(last_song) {
    last_song = last_song || false;

    if (last_song == false) {
        var jqxhr = $.ajax("callback.php?action=fetchnextsong&steamid="+params.steamid).done(function(e) {
            if (e.success == true) {
                console.log('[PLAYLISTS] Selecting song: '+e.songid);
                song = e.songid;
                return e.songid;
            } else {
                console.log('[PLAYLISTS] Failed to fetch next song: getNextSong()');
                run = false;
                systemglitch = 'Failed to connect to Portal to fetch songs.';
            }
        }).fail(function() {
            console.log('[PLAYLISTS] Failed to fetch next song: getNextSong()');
            run = false;
            systemglitch = 'Failed to connect to Portal to fetch songs.';
        });
    } else {
        var jqxhr = $.ajax("callback.php?action=fetchnextsong&steamid="+params.steamid+"&lastsong="+last_song).done(function(e) {
            if (e.success == true) {
                console.log('[PLAYLISTS] Selecting song (with last_song defined): '+e.songid);
                song = e.songid;
                return e.songid;
            } else {
                console.log('[PLAYLISTS] Failed to fetch next song (with last_song defined): getNextSong('+last_song+')');
                run = false;
                systemglitch = 'Failed to connect to Portal to fetch songs.';
            }
        }).fail(function() {
            console.log('[PLAYLISTS] Failed to fetch next song (with last_song defined): getNextSong('+last_song+')');
            run = false;
            systemglitch = 'Failed to connect to Portal to fetch songs.';
        });
    }
}

getNextSong();

function youtubeStart() {
    player = new YT.Player('youtube-widget', {
        height: '225',
        width: '400',
        controls: 0,
        events: {
            'onReady': youtubePlayerReady,
            'onStateChange': youtubePlayerStateChange,
            'onError': youtubePlayerError
        },
        playerVars: {
            'controls': 0,
            'showinfo': 0,
            'iv_load_policy': 3
        },
    });

    $(".youtube").show();
    $("#youtube-preloader").show();
}

function getSongInformation(songid, autogen) {
    autogen = autogen || true;

    var jqxhr = $.ajax("callback.php?action=fetchsonginformation&songid="+songid).done(function(e) {
        if (e.success == true) {
            if (autogen) {
                $(".youtube>.youtube-header>div:nth-child(2)>h1").text(e.snippet.title);
                $(".youtube>.youtube-header>div:nth-child(2)>h2").text(e.snippet.channelTitle);
            }

            return e;
        } else {
            console.log('[PLAYLISTS] Failed to fetch song information: getSongInformation('+songid+', '+autogen+')');
            run = false;
            systemglitch = 'Failed to connect to Portal to fetch songs.';
        }
    }).fail(function() {
        console.log('[PLAYLISTS] Failed to fetch song information: getSongInformation('+songid+', '+autogen+')');
        run = false;
        systemglitch = 'Failed to connect to Portal to fetch songs.';
    });
}

function youtubePlayerReady(event) {
    event.target.loadVideoById(song);
    player.setVolume(20);
}

function youtubePlayerStateChange(event) {
    switch (event.data) {
        case -1:
            break;
        case YT.PlayerState.ENDED:
            $("#youtube-preloader").show();
            youtubeLoadNewSong();
            break;
        case YT.PlayerState.PLAYING:
            $("#youtube-preloader").hide();
            getSongInformation(song, true);
            break;
        case YT.PlayerState.PAUSED:
            $("#youtube-preloader").show();
            player.playVideo();
            player.setVolume(20);
            break;
        case YT.PlayerState.BUFFERING:
            $("#youtube-preloader").show();
            break;
        case YT.PlayerState.CUED:
            break;
        default:
            break;
    }
}

function youtubeLoadNewSong() {
    getNextSong(song);
    player.loadVideoById(song);
    getSongInformation(song, true);
}

function youtubePlayerError(error) {
    console.log('[PLAYLISTS] Error: '+error.data);
}

function onYouTubeIframeAPIReady() {
    youtubeStart();
}

if (systemglitch != false) {
    console.log('[PLAYLISTS] System glitch: '+systemglitch);
}

Quick overview of the above file, just for TL;DR's sake:

  1. Player checks if the player is subscribed to any playlists that contain songs.
  2. Then the file gets the next song to play.
  3. Set up the YouTube iFrame.
  4. Start playing the preselected song.
  5. Checks for when the video is finished and then calls the youtubeLoadNewSong() function to change songs
  6. Video doesn't change (on first change) and the song information headers show the next videos information.

I'm using jQuery as you could probably tell. This issue is really making me annoyed, and I don't see why it isn't working. If I had code similar to this in PHP (my favourite language) it would work just fine, this is probably why I'm confused.

I'm sure the answer will be really simple *facepalms*, but I would really appreciate your help.

P.S: Sorry for the massive file...

  • I know that in PHP variables are locked within a function unless they are globalised, but I'm fairly sure this isn't the case within JavaScript as long as you define the variable outside of the function, right? – deansheather Oct 17 '15 at 04:14
  • "JavaScript is giving different values under one variable". Which variable is it? What is its value? What do you expect the value to be instead? – chiliNUT Oct 17 '15 at 04:14
  • a variable in javascript has global scope unless declared with `var ` in which case it has the scope it is being declared in. Variables declared in global scope are always global. – chiliNUT Oct 17 '15 at 04:15
  • Javascript will always give you the same value on a variable, unless you change it's value. – Max Oct 17 '15 at 04:16
  • @chiliNUT, I'm talking about the `song` variable, every time the `getNextSong()` function is called it should be changed. Technically it is being changed, but when I call the function to play the song within the `song` variable it's playing the last song again but when I call the function to update the information shown on screen directly afterwards it's receiving a different value from the `song` variable. – deansheather Oct 17 '15 at 04:19
  • @MaxMastalerz, I changed the first declaration of the `song` variable to not have `var ` in front so it would be truly global, but my problem is still present. That wasn't the issue it seems. – deansheather Oct 17 '15 at 04:22
  • song is already a global, because it is in the global scope. That shouldn't change anything. – Max Oct 17 '15 at 04:26
  • 1
    Ahhh. OK I think this is a the classic situation of making an asynchronous call and not waiting for it to finish. your functions are making ajax calls, but they aren't waiting for each other to finish. in the youtubeLoadNewSong method, leave the first line, but take the last 2 lines, cut them, and paste them into the bottom of each success function block in the getNextSong function – chiliNUT Oct 17 '15 at 04:28
  • see here for more info http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call – chiliNUT Oct 17 '15 at 04:36

0 Answers0