From 10f95880f463baba5cfcedff099bdd96f18385d4 Mon Sep 17 00:00:00 2001 From: quentinms Date: Sun, 16 Dec 2012 20:00:14 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 1 + css/index.css | 115 ++++++++++++++++++++++ img/pause.png | Bin 0 -> 5628 bytes img/play.png | Bin 0 -> 7182 bytes index.html | 49 ++++++++++ js/index.js | 253 +++++++++++++++++++++++++++++++++++++++++++++++++ js/waveform.js | 253 +++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 17 ++++ 8 files changed, 688 insertions(+) create mode 100644 .gitignore create mode 100644 css/index.css create mode 100644 img/pause.png create mode 100644 img/play.png create mode 100644 index.html create mode 100644 js/index.js create mode 100644 js/waveform.js create mode 100644 readme.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a03b5f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.sketch/* \ No newline at end of file diff --git a/css/index.css b/css/index.css new file mode 100644 index 0000000..031ca26 --- /dev/null +++ b/css/index.css @@ -0,0 +1,115 @@ +/* +Quentin Mazars-Simon +@quentinms +*/ + +*{ + margin: 0; + padding: 0; +} + +body{ + font-family: "Helvetica Neue", Helvetica, Arial; + font-weight: 100; +} + +#main_panel{ + +} + + +nav { + width: 250px; + float: left; + display: inline; + margin: 10px 10px 10px 100px; + padding: 0; + +} + +nav ul { + list-style: none; + text-align: center; +} + +nav ul li { + border-bottom: 1px solid black; +} + +nav ul li a{ + text-decoration: none; + color: inherit; + font-size: 30px; + +} + +h1{ + font-size: 45px; + font-weight: 100; + text-align: center; + margin: 20px; +} + +#newSongForm{ + float: left; + font-size: 20px; + margin: 5%; + display: none; +} + +#newSongForm input{ + font-size: 20px; + width: 400px; + font-family: "Helvetica Neue"; + font-weight: 100; + +} +#newSongForm button{ + + font-size: 20px; + width: 100px; + font-family: "Helvetica Neue"; + font-weight: 100; + margin: 20px auto 20px auto; + + position: relative; + left: 25%; +} + +#content{ + + +} + +#illustration{ + width: 500px; + height: 500px; + margin: auto; + background: url('http://lorempixel.com/500/500/abstract/'); + + background-repeat: no-repeat; + background-position: center center; + + /* + If do not want to always be squared + background-size: contain; + */ +} + +#playImage{ + margin: 200px; +} + +#time{ + width: 500px; + height: 20px; + margin: auto; + text-align: right; +} + +#waveform { + width: 500px; + height: 75px; + margin: auto; +} + diff --git a/img/pause.png b/img/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..f768ed5a1135d624edb3a514cd2facb56199f3ec GIT binary patch literal 5628 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 + + + + + +SoundCloud Video Clip + + + + + + + + + + + + +

SoundCloud Video Clip

+ + + +
+
+ +
+ +
+ +
+ +
+
+ Play/Pause icon +
+
+
+
+
+
+ + + diff --git a/js/index.js b/js/index.js new file mode 100644 index 0000000..a13d976 --- /dev/null +++ b/js/index.js @@ -0,0 +1,253 @@ +/* + Quentin Mazars-Simon + @quentinms +*/ + + +/*Initialize Tumblr*/ + var initTumblr = function(tag){ + + //We get the list of post with the specified tag + + $.ajax({url: "http://api.tumblr.com/v2/blog/soundcloudvideoclip.tumblr.com/posts/photo?api_key=QXmLiokbFl8PFldxAlznGCKPIQ44oTf18NW2UqZzsjAIDWjp5h&tag="+tag+"&jsonp=?", dataType: "jsonp", success: function(data){ + + var tumblr_api_read = data.response || null; + + //We add those photos to an array + if (tumblr_api_read != null) { + for (var i = 0; i < tumblr_api_read.posts.length; i++) { + //We get the url of the images with a width of 500px + window.tumblrImages[i]=tumblr_api_read.posts[i]["photos"][0]["alt_sizes"][1]["url"]; + + //We preload the images + var image = $('').attr('src', window.tumblrImages[i]); + } + + } + + if(tumblrImages.length!=0){ + //Kinda random ordering; + tumblrImages.sort(function() {return 0.5 - Math.random();}); + } else { + tumblrImages[0]="http://lorempixel.com/500/500/abstract/"; + } + + //We set the illustration to be the first of the images. + $("#illustration").css("background-image", "url("+window.tumblrImages[0]+")"); }}); + + } + + +/*Initialize SoundCloud*/ + +var initSoundCloud = function(trackId){ + +//We get the track and initialize the waveform (see http://waveformjs.org) + SC.get("/tracks/"+trackId, function(track){ + var waveform = new Waveform({ + container: document.getElementById("waveform") + }); + waveform.dataFromSoundCloudTrack(track); + + /* We set the proper options for the stream*/ + var streamOptions = waveform.optionsForSyncedStream(); + streamOptions["ontimedcomments"] = function(comments){ + /* Each time there is a comment, it will show the next image */ + window.ImgCount=(window.ImgCount+1)%window.tumblrImages.length; + $("#illustration").css("background-image", "url("+window.tumblrImages[ImgCount]+")"); + }; + +//We stream the song + SC.stream(track.uri, streamOptions, function(stream){ + window.stream = stream; + + //Hack to display prelaod the song*/ + stream.play(); + stream.pause(); + + // Play/Pause each time the user clicks somewhere in the #content
(image + waveform). + $("#content").bind('click',function(){stream.togglePause(); togglePause();}) + + //Display time indication when the user hovers the waveform + $('#waveform').bind('mouseenter', function() { + this.iid = setInterval(function() { + + secP = '0'+parseInt(stream.position / 1000)%60; + secP = secP.slice(-2); + minP = parseInt(stream.position / 1000 / 60)%60; + + secD = '0'+parseInt(stream.duration / 1000)%60; + secD = secD.slice(-2); + minD = parseInt(stream.duration / 1000 / 60)%60; + + $("#time").text(minP+':'+secP+' / '+minD+':'+secD); + }, 500); + }).bind('mouseleave', function(){ + $("#time").text(""); + this.iid && clearInterval(this.iid); + }); + + + + + }); +}); + +} + + +var selectSong = function(url, tag){ + + //Reset a bunch of stuff + + window.ImgCount = 0; + window.tumblrImages = []; + window.paused = true; + $("#playImage").attr('src','img/play.png'); + $("#newSongForm").hide(); + $("#content").show(); + $('#waveform').empty(); + $('#waveform').unbind('mouseenter').unbind('mouseleave'); + $("#content").unbind('click'); + + if(window.stream != null){ + window.stream.destruct(); + } + + + //We get the new song id, initialize the stream, the waveform and get the images from Tumblr + SC.get('/resolve', { url: url }, function(track){ + initSoundCloud(track.id); + }) + + initTumblr(tag); + +} + +/*Utility functions*/ + +var togglePause = function(){ + + if(window.paused){ + $("#playImage").attr('src','img/pause.png'); + } else { + $("#playImage").attr('src','img/play.png'); + } + window.paused = ! window.paused; +} + +var showForm = function(){ + $("#content").hide(); + $("#newSongForm").show(); +} + +var hideForm = function(){ + $("#newSongForm").hide(); + $("#content").show(); +} + +//Generates the menu based on the list of songs +var generateNav = function(songs){ + + + $('nav').append($("
    ")); + + for(var i = 0; i < songs.length; i++){ + + var item = $("
  • "+songs[i].title+"
  • "); + $('nav ul').append(item); + + } + + var item = $("
  • New Song...
  • "); + $('nav ul').append(item); + +} + +/*Main*/ + +var songs = [ { + "title": "Color Theory", + "artist": "Tea Leigh", + "url": "https://soundcloud.com/tea-leigh/color-theory-1", + "tag": "Color Theory" + }, + + { + "title": "Clouds", + "artist": "Marekhemmann", + "url": "https://soundcloud.com/marekhemmann/clouds", + "tag": "Clouds" + } , + { + "title": "Yonkers", + "artist": "Tyler The Creator", + "url": "https://soundcloud.com/diamondmedia360/tyler-the-creator-yonkers-prod", + "tag": "Yonkers" + } , + { + "title": "L.O.V.E", + "artist": "Onra", + "url": "https://soundcloud.com/onra/l-o-v-e", + "tag": "Love" + } , + { + "title": "Icarus", + "artist": "Madeon", + "url": "https://soundcloud.com/madeon/madeon-icarus", + "tag": "Icarus" + } , + { + "title": "Hours", + "artist": "Tycho", + "url": "https://soundcloud.com/tycho/tycho-hours", + "tag": "Hours" + } , + { + "title": "New Theory", + "artist": "RAC", + "url": "https://soundcloud.com/rac/washed-out-new-theory-rac-mix", + "tag": "New Theory" + } , + { + "title": "Too Insistent", + "artist": "Inertiamusic", + "url": "https://soundcloud.com/inertiamusic/the-do-too-insistent", + "tag": "Too Insistent" + } , + { + "title": "If U Got It", + "artist": "Chris Malinchak", + "url": "https://soundcloud.com/chrismalinchak/if-u-got-it", + "tag": "If U Got It" + } , + { + "title": "Pharao Black Magic", + "artist": "Future Classic", + "url": "https://soundcloud.com/futureclassic/pharao-black-magic-hermes", + "tag": "Pharao Black Magic" + } + + ]; + + +$(document).ready(function() { + + //Authenticate with SoundCloud + SC.initialize({ + client_id: "16be599a525a2df3fc4b5a20da9927c4" + }); + + var ImgCount = 0; + var tumblrImages = []; + var paused = true; + +$("#illustration").mouseenter(function(){$("#playImage").show();}) +$("#illustration").mouseleave(function(){$("#playImage").hide();}) + + +generateNav(songs); + +selectSong(songs[0].url,songs[0].tag); + + }); \ No newline at end of file diff --git a/js/waveform.js b/js/waveform.js new file mode 100644 index 0000000..5a0482d --- /dev/null +++ b/js/waveform.js @@ -0,0 +1,253 @@ +(function() { + var JSONP, Waveform, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + + window.Waveform = Waveform = (function() { + + Waveform.name = 'Waveform'; + + function Waveform(options) { + this.redraw = __bind(this.redraw, this); + this.container = options.container; + this.canvas = options.canvas; + this.data = options.data || []; + this.outerColor = options.outerColor || "transparent"; + this.innerColor = options.innerColor || "#000000"; + this.interpolate = true; + if (options.interpolate === false) { + this.interpolate = false; + } + if (this.canvas == null) { + if (this.container) { + this.canvas = this.createCanvas(this.container, options.width || this.container.clientWidth, options.height || this.container.clientHeight); + } else { + throw "Either canvas or container option must be passed"; + } + } + this.patchCanvasForIE(this.canvas); + this.context = this.canvas.getContext("2d"); + this.width = parseInt(this.context.canvas.width, 10); + this.height = parseInt(this.context.canvas.height, 10); + if (options.data) { + this.update(options); + } + } + + Waveform.prototype.setData = function(data) { + return this.data = data; + }; + + Waveform.prototype.setDataInterpolated = function(data) { + return this.setData(this.interpolateArray(data, this.width)); + }; + + Waveform.prototype.setDataCropped = function(data) { + return this.setData(this.expandArray(data, this.width)); + }; + + Waveform.prototype.update = function(options) { + if (options.interpolate != null) { + this.interpolate = options.interpolate; + } + if (this.interpolate === false) { + this.setDataCropped(options.data); + } else { + this.setDataInterpolated(options.data); + } + return this.redraw(); + }; + + Waveform.prototype.redraw = function() { + var d, i, middle, t, _i, _len, _ref, _results; + this.clear(); + this.context.fillStyle = this.innerColor; + middle = this.height / 2; + i = 0; + _ref = this.data; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + d = _ref[_i]; + t = this.width / this.data.length; + if (typeof this.innerColor === "function") { + this.context.fillStyle = this.innerColor(i / this.width, d); + } + this.context.clearRect(t * i, middle - middle * d, t, middle * d * 2); + this.context.fillRect(t * i, middle - middle * d, t, middle * d * 2); + _results.push(i++); + } + return _results; + }; + + Waveform.prototype.clear = function() { + this.context.fillStyle = this.outerColor; + this.context.clearRect(0, 0, this.width, this.height); + return this.context.fillRect(0, 0, this.width, this.height); + }; + + Waveform.prototype.patchCanvasForIE = function(canvas) { + var oldGetContext; + if (typeof window.G_vmlCanvasManager !== "undefined") { + canvas = window.G_vmlCanvasManager.initElement(canvas); + oldGetContext = canvas.getContext; + return canvas.getContext = function(a) { + var ctx; + ctx = oldGetContext.apply(canvas, arguments); + canvas.getContext = oldGetContext; + return ctx; + }; + } + }; + + Waveform.prototype.createCanvas = function(container, width, height) { + var canvas; + canvas = document.createElement("canvas"); + container.appendChild(canvas); + canvas.width = width; + canvas.height = height; + return canvas; + }; + + Waveform.prototype.expandArray = function(data, limit, defaultValue) { + var i, newData, _i, _ref; + if (defaultValue == null) { + defaultValue = 0.0; + } + newData = []; + if (data.length > limit) { + newData = data.slice(data.length - limit, data.length); + } else { + for (i = _i = 0, _ref = limit - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) { + newData[i] = data[i] || defaultValue; + } + } + return newData; + }; + + Waveform.prototype.linearInterpolate = function(before, after, atPoint) { + return before + (after - before) * atPoint; + }; + + Waveform.prototype.interpolateArray = function(data, fitCount) { + var after, atPoint, before, i, newData, springFactor, tmp; + newData = new Array(); + springFactor = new Number((data.length - 1) / (fitCount - 1)); + newData[0] = data[0]; + i = 1; + while (i < fitCount - 1) { + tmp = i * springFactor; + before = new Number(Math.floor(tmp)).toFixed(); + after = new Number(Math.ceil(tmp)).toFixed(); + atPoint = tmp - before; + newData[i] = this.linearInterpolate(data[before], data[after], atPoint); + i++; + } + newData[fitCount - 1] = data[data.length - 1]; + return newData; + }; + + Waveform.prototype.optionsForSyncedStream = function(options) { + var innerColorWasSet, that; + if (options == null) { + options = {}; + } + innerColorWasSet = false; + that = this; + return { + whileplaying: this.redraw, + whileloading: function() { + var stream; + if (!innerColorWasSet) { + stream = this; + that.innerColor = function(x, y) { + if (x < stream.position / stream.durationEstimate) { + return options.playedColor || "rgba(255, 102, 0, 0.8)"; + } else if (x < stream.bytesLoaded / stream.bytesTotal) { + return options.loadedColor || "rgba(0, 0, 0, 0.8)"; + } else { + return options.defaultColor || "rgba(0, 0, 0, 0.4)"; + } + }; + innerColorWasSet = true; + } + return this.redraw; + } + }; + }; + + Waveform.prototype.dataFromSoundCloudTrack = function(track) { + var _this = this; + return JSONP.get("http://waveformjs.org/w", { + url: track.waveform_url + }, function(data) { + return _this.update({ + data: data + }); + }); + }; + + return Waveform; + + })(); + + JSONP = (function() { + var config, counter, encode, head, jsonp, key, load, query, setDefaults, window; + load = function(url) { + var done, head, script; + script = document.createElement("script"); + done = false; + script.src = url; + script.async = true; + script.onload = script.onreadystatechange = function() { + if (!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) { + done = true; + script.onload = script.onreadystatechange = null; + if (script && script.parentNode) { + return script.parentNode.removeChild(script); + } + } + }; + if (!head) { + head = document.getElementsByTagName("head")[0]; + } + return head.appendChild(script); + }; + encode = function(str) { + return encodeURIComponent(str); + }; + jsonp = function(url, params, callback, callbackName) { + var key, query; + query = ((url || "").indexOf("?") === -1 ? "?" : "&"); + params = params || {}; + for (key in params) { + if (params.hasOwnProperty(key)) { + query += encode(key) + "=" + encode(params[key]) + "&"; + } + } + jsonp = "json" + (++counter); + window[jsonp] = function(data) { + callback(data); + try { + delete window[jsonp]; + } catch (_error) {} + return window[jsonp] = null; + }; + load(url + query + (callbackName || config["callbackName"] || "callback") + "=" + jsonp); + return jsonp; + }; + setDefaults = function(obj) { + var config; + return config = obj; + }; + counter = 0; + head = void 0; + query = void 0; + key = void 0; + window = this; + config = {}; + return { + get: jsonp, + init: setDefaults + }; + })(); + +}).call(this); diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..789e2ef --- /dev/null +++ b/readme.md @@ -0,0 +1,17 @@ +# Soundcloud Video Clip + +## A Soundcloud-Tumblr Mashup + +This project is a collaboration between students from ECAL and EPFL. +The image displayed next to the song changes each time a comment occurs during the song. +The illustration are fetched from [this Tumblr](http://soundcloudvideoclip.tumblr.com) according to the tag of the song. + +### Demo +[http://www.quentin.ms/SoundcloudVideo/index.html](http://www.quentin.ms/SoundcloudVideo/index.html) + +### Used libraries +* [jQuery](jquery.com) +* [Soundcloud API](http://developers.soundcloud.com/docs/api/sdks#javascript) +* [waveform.js](waveformjs.org) + +Made by Quentin Mazars-Simon and Belinda \ No newline at end of file