Skip to content

Instantly share code, notes, and snippets.

@aradnom
Created January 27, 2014 19:48
Show Gist options
  • Save aradnom/8655947 to your computer and use it in GitHub Desktop.
Save aradnom/8655947 to your computer and use it in GitHub Desktop.
Chunk of JS from a larger project illustrating how to use the SoundCloud API to construct a basic player with playlist, seek and basic control functionality.
// Initialize the Soundcloud API and set up player functionality
Soundcloud: {
// Start the API up
Init: function () {
SC.initialize({
client_id: app.Config.soundcloudClient
});
// For each audio player, bind soundcloud functionality
$('.audio-player').each( function () {
var player = $(this);
// Retrieve the soundcloud URL from the content
if ( $(this).find('.audio-url').length ) {
var url = $(this).find('.audio-url').text();
// If the URL is valid, get the correct API resource
if ( url ) {
// Resolve the passed URL into an API-usable URL and play the resulting ID
app.Component.Soundcloud.Resolve( url, function ( track_info ) {
// If that went well, set up player (handled differently for sets/tracks)
// 'user' is also a potential type that could be played but isn't handled
// currently
if ( track_info ) {
if ( track_info.kind == 'playlist' ) {
// Build the playlist
var playlist = _.template( app.Templates.soundcloud_playlist, {
tracks: track_info.tracks
});
// Append the playlist to the player
if ( playlist ) {
player.find('.playlist').append( playlist );
// Refresh the layout because the height will have changed
app.Component.Stackery.Init();
// Set up individual track controls
player.find('.playlist li').click( function () {
app.Component.Soundcloud.PlayTrack( $(this), player );
});
}
} else if ( track_info.kind == 'track' ) {
// Placeholder for single-track functionality (may need later)
}
// Bind generic audio controls
player.find('.progress-bar').click( function ( event ) {
var track = App.Config.currentTrack;
if ( track ) {
var offset = event.offsetX;
if ( offset ) {
var new_position = Math.floor( ( offset / $(this).width() ) * track.duration );
if ( new_position && new_position <= track.duration ) {
track.setPosition( new_position );
}
}
}
});
player.find('.controls .play-pause').click( function () {
var track = App.Config.currentTrack;
// Usual play/oause functionality if there's a track loaded
if ( track ) {
$(this).toggleClass( 'play' );
if ( $(this).hasClass( 'play' ) ) {
track.pause();
} else {
track.play();
}
// Otherwise load the first track if not
} else {
app.Component.Soundcloud.PlayTrack( player.find('.soundcloud-playlist li').first(), player );
}
});
player.find('.controls .previous').click( function () {
// Find and play previous track only if it exists
var playing = player.find('.playlist .playing');
if ( playing.length && playing.prev('li').length ) {
var previous = playing.prev('li');
// And away we go
app.Component.Soundcloud.PlayTrack( previous, player );
}
});
player.find('.controls .next').click( function () {
// Find and play next track only if it exists
var playing = player.find('.playlist .playing');
if ( playing.length && playing.next('li').length ) {
var next = playing.next('li');
// And away we go
app.Component.Soundcloud.PlayTrack( next, player );
}
});
player.find('.volume-bar').click( function ( event ) {
var track = App.Config.currentTrack;
if ( track ) {
var offset = event.offsetX;
if ( offset ) {
var new_position = Math.floor( ( offset / $(this).width() ) * 100 );
if ( new_position ) {
// Gate the new value to valid values
if ( new_position < 0 ) new_position = 0;
if ( new_position > 100 ) new_position = 100;
track.setVolume( new_position );
$(this).find('.inner').css( 'width', new_position.toString() + '%' );
}
}
}
});
player.find('.volume-icon').click( function () {
var track = App.Config.currentTrack;
if ( track ) {
$(this).toggleClass( 'muted' );
if ( $(this).hasClass('muted') ) {
track.mute();
} else {
track.unmute();
}
}
});
}
});
}
}
});
},
// Retrieve track/user/set information for a specified soundcloud URL
Resolve: function ( url, callback ) {
$.getJSON( 'http://api.soundcloud.com/resolve.json?callback=?', {
url: url,
client_id: app.Config.soundcloudClient
}, function ( response ) {
if ( callback ) callback( response );
});
},
// Play an audio track utilizing Soundcloud functions below
PlayTrack: function ( track_element, player ) {
var stream_url = track_element.find('.stream-url').text();
if ( stream_url ) {
// Update the track duration
player.find('.total-time').text( app.__.MillisecondsToMinutes( track_element.find('.duration').text() ) );
// Play the track and update progress while playing
app.Component.Soundcloud.StreamTrack( stream_url, function ( sound ) {
// Set volume to default level on load
sound.setVolume( 75 );
// Update playing icon
player.find('.controls .play-pause').removeClass( 'play' );
},
// While playing, update progress
function ( sound ) {
// Progress bar
var progress = player.find('.progress-bar'),
inner = progress.children('.inner'),
position = Math.ceil( progress.width() * ( sound.position / sound.duration ) );
inner.width( position );
// Current play time
var current_time = player.find('.current-time'),
converted = app.__.MillisecondsToMinutes( sound.position );
current_time.text( converted );
},
// On finish, jump to next track if it exists
function ( sound ) {
// Find and play next track only if it exists
var playing = player.find('.playlist .playing');
if ( playing.length && playing.next('li').length ) {
var next = playing.next('li');
// And away we go
app.Component.Soundcloud.PlayTrack( next, player );
}
});
// Update track's playing status
track_element.addClass( 'playing' ).siblings().removeClass( 'playing' );
}
},
// Play a single track over the Soundcloud API with the specified stream_url.
// Will provide the created SoundManager object in App.Config.CurrentTrack
StreamTrack: function ( stream_url, loaded, playing, finished ) {
if ( SC ) {
SC.stream( stream_url, function ( sound ) {
// If an existing track exists, null it out before switching
if ( app.Config.currentTrack ) app.Config.currentTrack.destruct();
// Save a reference to the current track and play the track
app.Config.currentTrack = sound;
sound.play({
whileplaying: function () {
if ( playing ) playing( this );
},
onload: function () {
if ( loaded ) loaded( this );
},
onfinish: function () {
if ( finished ) finished( this );
}
});
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment