Como hacer un reproductor usando SoundCloud #2

La segunda parte del tutorial se enfocará en terminar las funciones pendientes del player. También veremos una pequeña sorpresa que nos adelantará el siguiente tutorial.

En el capítulo anterior hicimos un player que se conectaba a una lista de SoundCloud a través de la API Javascript. El resultado fue muy básico y quedó así:

Lo que quedó pendiente fue básicamente:

  • Cambiar de sonido (canción)
  • Pausar el sonido
  • Mostrar un cargador del sonido
Nuevas funciones

Para comenzar agregaré el resultado del archivo player.js que hicimos en el capítulo anterior:

SC.initialize({
  client_id: '27dbbae0099f348ca6dc481b2f9eddd7'
});

var player_tracks, player_sound, player_current_track;
var player_current_track_index = 0;

SC.get("/playlists/624667", { 
}, function(playlist) {
    player_tracks = playlist.tracks;
});

var playSong = function(track) {   
    SC.stream("/tracks/" + track.id, function(sound) {
        player_sound = sound;
        player_sound.play();
        player_sound.setVolume(50);
        player_sound.on
    });
};

$(document).ready(function(){
    $('#player_play').click(function(){
        if (typeof(player_current_track) == 'undefined') {
            player_current_track = player_tracks[player_current_track_index];
        }

        if (typeof(player_sound) == 'undefined') {
            playSong(player_current_track);

            $('#player_track_title a').html(player_current_track.title);
            $('#player_track_artist').html(player_current_track.user.username);
            $('#player_artwork a img').attr('src', player_current_track.artwork_url);
        }
    });
});

Desde esta base vamos a crear la función changeSong que nos permitirá cambiar la canción en cierta dirección, bajo la función playSong.

var changeSong = function(direction) {
    if (direction == 'next') {
        // si es next
        if (player_current_track_index == (player_tracks.length) - 1) {
            // pregunta si está al final y lo envía al comienzo
            player_current_track_index = 0;
        } else {
            // sino, suena el siguiente
            player_current_track_index++;
        }
    } else if (direction == 'prev') {
        // si es prev
        if (player_current_track_index == 0) {
            // pregunta si está al comienzo y lo envía al final
            player_current_track_index = (player_tracks.length) - 1;
        } else {
            // sino, suena la anterior
            player_current_track_index--;
        }
    }

    // detectamos si el player está activo
    if (typeof(player_sound) != 'undefined') {
        player_sound.stop();
    }

    // se define la variable para el track activo
    player_current_track = player_tracks[player_current_track_index];

    // dj play that song
    playSong(player_current_track);
};

Acá creamos la función considerando el parámetro direction. La dirección puede ser next o prev, y en base a eso sumamos valores al índice o enviamos al comienzo y al final según corresponda. Cuando el índice de la canción se cambia, se usa la función playSong.

Con la función creada podremos agregar los eventos a los botones correspondientes:

$(document).ready(function(){
...
    $('#player_next').click(function() {
        changeSong('next');
    });

    $('#player_prev').click(function() {
        changeSong('prev');
    });
});

El siguiente paso es agregar la función de pausa. Esta función agrega una variable global llamada player_sound_paused la que determina si el sonido está pausado o no, y que va cambiando según los eventos del botón play.

var player_sound_paused = false;

La añadimos bajo la variable player_current_track_index y se define como false, porque por defecto el track no viene pausada. El siguiente paso es agregar el función de pausa al mismo botón play, para esto modificaremos la función del botón #player_play dejándolo del siguiente modo.

$('#player_play').click(function(){
        if (typeof(player_current_track) == 'undefined') {
            player_current_track = player_tracks[player_current_track_index];
        }

        if (typeof(player_sound) == 'undefined') {
            playSong(player_current_track);

            $('#player_track_title a').html(player_current_track.title);
            $('#player_track_artist').html(player_current_track.user.username);
            $('#player_artwork a img').attr('src', player_current_track.artwork_url);
        } else {
            if (player_sound_paused) {
                player_sound.resume();
                player_sound_paused = false;
                $this.html('<span class="icon-pause"></span>');
            } else {
                player_sound.pause();
                player_sound_paused = true;
                $this.html('<span class="icon-play"></span>');
            }
        }
    });

Acá agregamos la funcionalidad dentro del else, donde se utiliza el método resume si es que el sonido está pausado y el método pause si no lo está.

Lo siguiente que debemos hacer es cambiar esas 3 líneas que agregan la información del track del botón #player_play y las trasladamos al método playSong, dejándolo de éste modo.

var playSong = function(track) {   
    SC.stream("/tracks/" + track.id, function(sound) {
        player_sound = sound;
        player_sound.play();
        player_sound.setVolume(50);
        player_sound.on

        $('#player_track_title a').html(player_current_track.title);
        $('#player_track_artist').html(player_current_track.user.username);
        $('#player_artwork a img').attr('src', player_current_track.artwork_url);
    });
};

La siguiente función que vamos a agregar es una que detecte cada 0.5 segundos si el track llegó al final para que pase al siguiente. Este método se llamará checkSong y debe hacer un cálculo entre la posición actual del track y la duración, lo agregamos debajo de la función changeSong.

var checkSong = function() {
    if (typeof(player_sound) != 'undefined') {
        if (Math.round((player_sound.position / 1000)) >= Math.round((player_current_track.duration / 1000))) {
            changeSong('next');
        }
    }
};

Esta función como tal no sirve si no tiene un interval que la llame cada cierto tiempo. Para esto agregaremos una variable global llamada player_interval y en la función play le definiremos un setInterval que llame a checkSong cada 0.5 segundos.

var player_tracks, player_sound, player_current_track, player_interval;
...
...
var playSong = function(track) {   
    player_interval = setInterval('checkSong()', 500);
...
...
}

El último paso ahora es agregar el cargador al comienzo usando un icono spin de fontello. Yo prefierí usar el icon-spin3 junto con la clase animate-spin que hace que este cargador gire. Así que modificaremos playSong agregando el html del icon-spin3 y volviéndolo a icon-pause cuando la canción se carga.

var playSong = function(track) {   
    player_interval = setInterval('checkSong()', 500);

    $('#player_play').html('<span class="icon-spin3 animate-spin"></span>')

    SC.stream("/tracks/" + track.id, function(sound) {
        player_sound = sound;
        player_sound.play();
        player_sound.setVolume(50);
        player_sound.on

        $('#player_play').html('<span class="icon-pause"></span>');
        $('#player_track_title a').html(player_current_track.title);
        $('#player_track_artist').html(player_current_track.user.username);
        $('#player_artwork a img').attr('src', player_current_track.artwork_url);
    });
};

Y con eso, finalizamos nuestro player. El resultado lo pueden ver acá abajo y pueden descargar la versión actualizada desde acá

Conclusiones y siguiente paso

Soundcloud es una plataforma tan dinámica y avanzada en términos técnicos que integrarse con ella es tan gratificante como escuchar tu disco favorito. Las herramientas que ponen a disposición nos da la suficiente holgura como para crear aplicaciones mucho más poderosas basadas en el streaming de sonidos e incluso en la grabación de estos.

Sin embargo, esta API no es la única que es así de amigable. Existe otra aplicación dedicada exclusivamente a la música que tiene una API muy interesante y tan simple de implementar como la de SoundCloud, y me refiero a Rdio.

El siguiente tutorial permitirá crear un player con canciones que Rdio ofrece, reutilizaremos la interfaz del player y veremos cómo funciona esta interesante API.

Espero que hayan disfrutado tanto como yo y si tienen comentarios, ¡háganlos acá abajo!

Blog, Tutorial, Tutorial Javascript
6 minutos