Initial soundcloud implementation
This commit is contained in:
parent
ce8ac4591e
commit
480497bea4
105
player/soundcloud.coffee
Normal file
105
player/soundcloud.coffee
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
window.SoundCloudPlayer = class SoundCloudPlayer extends Player
|
||||||
|
constructor: (data) ->
|
||||||
|
if not (this instanceof SoundCloudPlayer)
|
||||||
|
return new SoundCloudPlayer(data)
|
||||||
|
|
||||||
|
@setMediaProperties(data)
|
||||||
|
|
||||||
|
waitUntilDefined(window, 'SC', =>
|
||||||
|
removeOld()
|
||||||
|
|
||||||
|
# For tracks that are private, but embeddable, the API returns a
|
||||||
|
# special URL to load into the player.
|
||||||
|
# TODO: rename scuri?
|
||||||
|
if data.meta.scuri
|
||||||
|
soundUrl = data.meta.scuri
|
||||||
|
else
|
||||||
|
soundUrl = data.id
|
||||||
|
|
||||||
|
widget = $('<iframe/>').appendTo($('#ytapiplayer'))
|
||||||
|
widget.attr(
|
||||||
|
id: 'scplayer'
|
||||||
|
src: "https://w.soundcloud.com/player/?url=#{soundUrl}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Soundcloud embed widget doesn't have a volume control.
|
||||||
|
volumeSlider = $('<div/>').attr('id', 'widget-volume')
|
||||||
|
.css('top', '170px')
|
||||||
|
.insertAfter(widget)
|
||||||
|
.slider(
|
||||||
|
range: 'min'
|
||||||
|
value: VOLUME * 100
|
||||||
|
stop: (event, ui) =>
|
||||||
|
@setVolume(ui.value / 100)
|
||||||
|
)
|
||||||
|
|
||||||
|
@soundcloud = SC.Widget(widget[0])
|
||||||
|
@soundcloud.bind(SC.Widget.Events.READY, =>
|
||||||
|
@soundcloud.ready = true
|
||||||
|
@setVolume(VOLUME)
|
||||||
|
@play()
|
||||||
|
|
||||||
|
@soundcloud.bind(SC.Widget.Events.PAUSE, =>
|
||||||
|
@paused = true
|
||||||
|
if CLIENT.leader
|
||||||
|
sendVideoUpdate()
|
||||||
|
)
|
||||||
|
@soundcloud.bind(SC.Widget.Events.PLAY, =>
|
||||||
|
@paused = false
|
||||||
|
if CLIENT.leader
|
||||||
|
sendVideoUpdate()
|
||||||
|
)
|
||||||
|
@soundcloud.bind(SC.Widget.Events.FINISH, =>
|
||||||
|
if CLIENT.leader
|
||||||
|
socket.emit('playNext')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
load: (data) ->
|
||||||
|
@setMediaProperties(data)
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
if data.meta.scuri
|
||||||
|
soundUrl = data.meta.scuri
|
||||||
|
else
|
||||||
|
soundUrl = data.id
|
||||||
|
@soundcloud.load(soundUrl, auto_play: true)
|
||||||
|
else
|
||||||
|
console.error('SoundCloudPlayer::load() called but soundcloud is not ready')
|
||||||
|
|
||||||
|
play: ->
|
||||||
|
@paused = false
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
@soundcloud.play()
|
||||||
|
|
||||||
|
pause: ->
|
||||||
|
@paused = true
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
@soundcloud.pause()
|
||||||
|
|
||||||
|
seekTo: (time) ->
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
# SoundCloud measures time in milliseconds while CyTube uses seconds.
|
||||||
|
@soundcloud.seekTo(time * 1000)
|
||||||
|
|
||||||
|
setVolume: (volume) ->
|
||||||
|
# NOTE: SoundCloud's documentation claims that setVolume() accepts
|
||||||
|
# volumes in the range [0, 100], however it *actually* accepts volumes
|
||||||
|
# in the range [0, 1] (anything larger than 1 is treated as 1). I
|
||||||
|
# emailed them about this 2 years ago and they still haven't fixed
|
||||||
|
# their documentation.
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
@soundcloud.setVolume(volume)
|
||||||
|
|
||||||
|
getTime: (cb) ->
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
# Returned time is in milliseconds; CyTube expects seconds
|
||||||
|
@soundcloud.getPosition((time) -> cb(time / 1000))
|
||||||
|
else
|
||||||
|
cb(0)
|
||||||
|
|
||||||
|
getVolume: (cb) ->
|
||||||
|
if @soundcloud and @soundcloud.ready
|
||||||
|
@soundcloud.getVolume(cb)
|
||||||
|
else
|
||||||
|
cb(VOLUME)
|
|
@ -4,6 +4,7 @@ TYPE_MAP =
|
||||||
dm: DailymotionPlayer
|
dm: DailymotionPlayer
|
||||||
gd: VideoJSPlayer
|
gd: VideoJSPlayer
|
||||||
gp: VideoJSPlayer
|
gp: VideoJSPlayer
|
||||||
|
sc: SoundCloudPlayer
|
||||||
|
|
||||||
window.loadMediaPlayer = (data) ->
|
window.loadMediaPlayer = (data) ->
|
||||||
if data.type of TYPE_MAP
|
if data.type of TYPE_MAP
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(function() {
|
(function() {
|
||||||
var DailymotionPlayer, Player, TYPE_MAP, VideoJSPlayer, VimeoPlayer, YouTubePlayer, sortSources,
|
var DailymotionPlayer, Player, SoundCloudPlayer, TYPE_MAP, VideoJSPlayer, VimeoPlayer, YouTubePlayer, sortSources,
|
||||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
hasProp = {}.hasOwnProperty;
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
@ -593,12 +593,134 @@
|
||||||
|
|
||||||
})(Player);
|
})(Player);
|
||||||
|
|
||||||
|
window.SoundCloudPlayer = SoundCloudPlayer = (function(superClass) {
|
||||||
|
extend(SoundCloudPlayer, superClass);
|
||||||
|
|
||||||
|
function SoundCloudPlayer(data) {
|
||||||
|
if (!(this instanceof SoundCloudPlayer)) {
|
||||||
|
return new SoundCloudPlayer(data);
|
||||||
|
}
|
||||||
|
this.setMediaProperties(data);
|
||||||
|
waitUntilDefined(window, 'SC', (function(_this) {
|
||||||
|
return function() {
|
||||||
|
var soundUrl, volumeSlider, widget;
|
||||||
|
removeOld();
|
||||||
|
if (data.meta.scuri) {
|
||||||
|
soundUrl = data.meta.scuri;
|
||||||
|
} else {
|
||||||
|
soundUrl = data.id;
|
||||||
|
}
|
||||||
|
widget = $('<iframe/>').appendTo($('#ytapiplayer'));
|
||||||
|
widget.attr({
|
||||||
|
id: 'scplayer',
|
||||||
|
src: "https://w.soundcloud.com/player/?url=" + soundUrl
|
||||||
|
});
|
||||||
|
volumeSlider = $('<div/>').attr('id', 'widget-volume').css('top', '170px').insertAfter(widget).slider({
|
||||||
|
range: 'min',
|
||||||
|
value: VOLUME * 100,
|
||||||
|
stop: function(event, ui) {
|
||||||
|
return _this.setVolume(ui.value / 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_this.soundcloud = SC.Widget(widget[0]);
|
||||||
|
return _this.soundcloud.bind(SC.Widget.Events.READY, function() {
|
||||||
|
_this.soundcloud.ready = true;
|
||||||
|
_this.setVolume(VOLUME);
|
||||||
|
_this.play();
|
||||||
|
_this.soundcloud.bind(SC.Widget.Events.PAUSE, function() {
|
||||||
|
_this.paused = true;
|
||||||
|
if (CLIENT.leader) {
|
||||||
|
return sendVideoUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_this.soundcloud.bind(SC.Widget.Events.PLAY, function() {
|
||||||
|
_this.paused = false;
|
||||||
|
if (CLIENT.leader) {
|
||||||
|
return sendVideoUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return _this.soundcloud.bind(SC.Widget.Events.FINISH, function() {
|
||||||
|
if (CLIENT.leader) {
|
||||||
|
return socket.emit('playNext');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
})(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.load = function(data) {
|
||||||
|
var soundUrl;
|
||||||
|
this.setMediaProperties(data);
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
if (data.meta.scuri) {
|
||||||
|
soundUrl = data.meta.scuri;
|
||||||
|
} else {
|
||||||
|
soundUrl = data.id;
|
||||||
|
}
|
||||||
|
return this.soundcloud.load(soundUrl, {
|
||||||
|
auto_play: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return console.error('SoundCloudPlayer::load() called but soundcloud is not ready');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.play = function() {
|
||||||
|
this.paused = false;
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
return this.soundcloud.play();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.pause = function() {
|
||||||
|
this.paused = true;
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
return this.soundcloud.pause();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.seekTo = function(time) {
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
return this.soundcloud.seekTo(time * 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.setVolume = function(volume) {
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
return this.soundcloud.setVolume(volume);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.getTime = function(cb) {
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
return this.soundcloud.getPosition(function(time) {
|
||||||
|
return cb(time / 1000);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return cb(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundCloudPlayer.prototype.getVolume = function(cb) {
|
||||||
|
if (this.soundcloud && this.soundcloud.ready) {
|
||||||
|
return this.soundcloud.getVolume(cb);
|
||||||
|
} else {
|
||||||
|
return cb(VOLUME);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return SoundCloudPlayer;
|
||||||
|
|
||||||
|
})(Player);
|
||||||
|
|
||||||
TYPE_MAP = {
|
TYPE_MAP = {
|
||||||
yt: YouTubePlayer,
|
yt: YouTubePlayer,
|
||||||
vi: VimeoPlayer,
|
vi: VimeoPlayer,
|
||||||
dm: DailymotionPlayer,
|
dm: DailymotionPlayer,
|
||||||
gd: VideoJSPlayer,
|
gd: VideoJSPlayer,
|
||||||
gp: VideoJSPlayer
|
gp: VideoJSPlayer,
|
||||||
|
sc: SoundCloudPlayer
|
||||||
};
|
};
|
||||||
|
|
||||||
window.loadMediaPlayer = function(data) {
|
window.loadMediaPlayer = function(data) {
|
||||||
|
|
331
www/js/sc.js
331
www/js/sc.js
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue