var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('safari') > -1 && ua.indexOf('chrome') < 0) { // safari OSX doesn't handle CORS with audio streaming :/ this.setAttribute('streaming', 'false') } // Deal with JSON.stringify() issues by converting to a regular array var copy = Array.apply([], fft); // bus.send('fft', copy); //if (key.keyCode == 32) this.setAttribute('paused', ! this.paused); minutes = Math.floor(time / 60) seconds = Math.floor(time) - minutes * 60 seconds = '0' + seconds if (seconds < 10) return minutes + ':' + seconds var x = dr.mouse.x - this.getAbsolute().x; var perc = x / this.width; trackEvent('player', 'seek', player.productid, perc) audio.seek(perc * audio.duration); if (audio.playing) { trackEvent('player', 'pause', player.productid, ! audio.paused) audio.setAttribute('paused', ! audio.paused); } else { trackEvent('player', 'play', player.productid) audio.setAttribute('playing', true); } if (audio.loaded) { this.txt.setAttribute('class', 'fa fa-play') if (audio.playing && ! audio.paused) { this.txt.setAttribute('class', 'fa fa-pause') } else { this.txt.setAttribute('class', 'fa fa-play') } } else { this.txt.setAttribute('class', 'fa fa-spin fa-spinner') } trackEvent('player', 'stop', player.productid) audio.setAttribute('playing', false); trackEvent('player', 'next', player.productid) player.next(); / if (search.keywords[this.text]) this.setAttribute('color', 'white') if (this.color === 'black') { trackEvent('search', 'keywordon', this.text) this.setAttribute('color', 'white'); search.keywords[this.text] = true; //} else if (this.color === 'green') { // this.setAttribute('color', 'red'); } else { trackEvent('search', 'keywordoff', this.text) this.setAttribute('color', 'black'); search.keywords[this.text] = null; } search.setAttribute('keywords', search.keywords); var text = this.text.toLowerCase(); trackEvent('search', 'label', this.text) searchinput.setAttributes({text: text, value: text}) var coverurl = '//s3.amazonaws.com/assets.musicwindow.com/public/album_images_' + (login.loggedin ? 500 : 200) + '/' + data.imageurl this.cover.setAttribute('src', coverurl) this.labels.title.setAttribute('text', data.title) var release = data.release; var tracks = 0; if (data.tracks) tracks = data.tracks.length // console.log('data.tracks', data.tracks, tracks, data.release) var track = data.tracks[player.trackoffset] if (tracks > 1) { // this is an album if (track && player.productid != track.id) { // we are playing the album, show the track offset and count in the title var offset = ' (' + (player.trackoffset + 1) + '/' + tracks + ')'; this.labels.title.setAttribute('text', track.title + offset) this.labels.artist.setAttribute('text', track.artist) } else { // append track count to release release += ' (' + tracks + ' tracks)'; this.labels.title.setAttribute('text', data.title) this.labels.artist.setAttribute('text', data.artist) } } else { this.labels.title.setAttribute('text', data.title) this.labels.artist.setAttribute('text', data.artist) } this.setAttribute('owned', player.isOwned(data)); this.labels.release.setAttribute('text', release) this.labels.label.setAttribute('text', data.label) this.labels.released.setAttribute('text', data.released) this.labels.keywords.setAttribute('text', data.keywords.join(',').toLowerCase()) if (purchased) this.setAttribute('owned', player.isOwned(this.data)); if (loggedin) this.cover.setAttribute('src', '//s3.amazonaws.com/assets.musicwindow.com/public/album_images_500/' + this.data.imageurl) this.labels.actions.buyordownload.setAttribute('class', owned ? 'fa fa-download' : 'fa fa-cart-plus') var product = this.parent.parent.parent.data; trackEvent('product', 'play', product.id) player.play(product); var product = this.parent.parent.parent.data; trackEvent('product', 'add', product.id) // TODO: use classroot in dreem2! player.add(product); // TODO: use classroot in dreem2! var parent = this.parent.parent.parent; if (parent.owned) { trackEvent('product', 'download', parent.data.id) player.download(parent.data); } else { trackEvent('product', 'buy', parent.data.id) player.buy(parent.data); } var _this = this; var readHash = function() { var hash = decodeURI(window.location.hash).substring(1) if (hash.indexOf('/search/') === 0) { if (hash != _this.searchresult.url) { _this.searchresult.setAttribute('url', hash); if (hash.indexOf('keywords')) { var keywords = hash.split('=')[1] if (keywords) { var wordlist = keywords.split(',') search.keywords = {}; for (var i = 0; i < wordlist.length; i++) { search.keywords[wordlist[i]] = true; } taglist.reset() } } } } else if (hash.indexOf('/playlist/') === 0) { var playlisturl = hash.substring(10, hash.length); playlist.setAttribute('url', playlisturl) } } $(window).on('hashchange',readHash); readHash(); if ((! this.term) && (Object.keys(this.keywords).length) == 0) return; var url = '/search/' + this.term; var keywords = []; for (var key in this.keywords) { if (this.keywords[key]) { keywords.push(key.toLowerCase().split(' ')[0]) } } if (keywords.length) { url = '/search/*?keywords=' + keywords.join(','); } if (url !== this.searchresult.url) { this.searchresult.setAttribute('url', url) } if (! data.totalHits) { return; } var out = data.hits.map(function(hit) { var doc = hit.document; if (! doc.tracks) { doc.tracks = [JSON.parse(JSON.stringify(doc))] } return doc; }) if (out.length > 100) { out.length = 100 } return out; if (! data) return window.location.hash = encodeURI(this.searchresult.url); if (!(audio.playing && audio.url)) { // play first track of first result, but don't interrupt current audio playback player.play(data[0]) } taglist.reset() if (text) this.suggestionds.setAttribute('url', '/suggest/' + text) this.suggestionds.setAttribute('data', []) trackEvent('search', 'suggestion', this.text) suggestions.clear(); searchinput.setAttributes({text: this.text, value: this.text}) out = data.map(function(suggestion) { return suggestion[0]; }) return out; // console.log('data', data) this.repl.setAttribute('data', data) this.data = data; search if (this._tid !== null) { clearTimeout(this._tid); } // enter or tab key, set the value immediately and bail var keyCode = key.keyCode if (keyCode === 13 || keyCode === 32) { if (suggestions.data.length) { this.setAttribute('text', suggestionds.data[0]) this.setAttribute('value', suggestionds.data[0]) suggestions.clear() } return; } this._tid = setTimeout(this._update, this.delay); var hash = decodeURI(window.location.hash).substring(1) if (hash.indexOf('/search/') === 0) { var terms = hash.substring(8); if (terms.indexOf('*?') != 0) this.setAttributes({text: terms, value: terms}) } else { if (! hash) window.location.hash = '/playlist/charts/monthly/releases/albums' this._update(); } this.parent.measure.setAttribute('text', this.text) this.setAttribute('width', (this.parent.measure.width || 100) + 50) ; this.setAttribute('height', (this.parent.measure.height || 30)) ; this.parent.measure.setAttribute('text', '') if (text !== suggestions.text) suggestions.clear() suggestions.clear() this.setAttribute('value', this.text) if (this.text) { suggestions.setAttribute('text', this.text) } else { suggestions.clear() } if (! value) return this.parent.setAttribute('keywords', {}) taglist.reset(); if (value != this.parent.term) this.parent.setAttribute('term', value) this.repl.setAttribute('datapath', this.repl.datapath) {"tags": [ {"name":"ambient"}, {"name":"breakbeat"}, {"name":"dark"}, {"name":"dope"}, {"name":"downtempo"}, {"name":"drum & bass"}, {"name":"dubstep/grime"}, {"name":"electro"}, {"name":"experimental"}, {"name":"funky"}, {"name":"glitch hop"}, {"name":"glitchy"}, {"name":"heavy"}, {"name":"hip hop"}, {"name":"house"}, {"name":"idm"}, {"name":"midtempo"}, {"name":"organic"}, {"name":"progressive"}, {"name":"ragga"}, {"name":"techfunk"}, {"name":"techno"}, {"name":"vocal"} ] } if (data.length) { this.results.repl.setAttribute('data', data); } if (! this.playlist.data) return; var tracks = this.playlist.data.tracks; if (! tracks) return; if (playlistoffset >= tracks.length) { // we reached the end, reset to zero to keep playing playlistoffset = 0; } var track = tracks[playlistoffset]; // console.log('onplaylistoffset', playlistoffset, track) // localStorage.playlistoffset = playlistoffset; if (track && track.id !== this.productid) { this.play(track); } data.tracks = data.tracks.splice(0, 50) data.tracks.map(function(track) { if (! track.tracks) { track.tracks = [JSON.parse(JSON.stringify(track))] } }); return data; // if (localStorage.playlist) this.playlist.setAttribute('data', JSON.parse(localStorage.playlist)); // if (localStorage.trackoffset) this.setAttribute('trackoffset', localStorage.trackoffset + 0) // if (localStorage.playlistoffset) this.setAttribute('playlistoffset', localStorage.playlistoffset + 0) // console.log('localStorage', localStorage) // if (data) localStorage.playlist = JSON.stringify(data); if (!(audio.playing && audio.url && this.productid)) { // play first track of first result, but don't interrupt current audio playback player.play(data.tracks[0]) } // console.log('play', product) var productid = product.id; this.setAttribute('productid', productid) if (this.playlist.data) { var tracks = this.playlist.data.tracks; // look through playlist for matching productid for (var i = 0, l = tracks.length; i < l; i++) { var track = tracks[i]; if (track.id == productid && this.playlistoffset != i) { // console.log('set playlistoffset to match', track.id, i); this.setAttribute('playlistoffset', i); } } } // Not found in playlist, load album instead this.album.setAttribute('data', product) tracks = [] if (this.album.data) { tracks = this.album.data.tracks; } if (tracks.length > 1 && this.trackoffset + 1 < tracks.length) { // play next track in album this.setAttribute('trackoffset', this.trackoffset + 1) } else if (this.playlist.data && (this.trackoffset + 1 < this.playlist.data.tracks.length)) { // play next in playlist this.setAttribute('playlistoffset', this.playlistoffset + 1) } else { // look in search var tracks = search.searchresult.data; for (var i = 0; i < tracks.length; i++) { var track = tracks[i]; if (track.id == this.productid) { this.play(tracks[i + 1]) return; } } if (tracks[0]) this.play(tracks[0]) } // don't add the track that's playing to the list // if (product.id == this.productid) return; var tracks = this.playlist.data && this.playlist.data.tracks; if (! tracks) { this.playlist.data = {tracks: []}; tracks = this.playlist.data.tracks; } // console.log('add', tracks, this.playlist) for (var i = 0, l = tracks.length; i < l; i++) { var track = tracks[i]; if (product.id == track.id) { // don't add the same track more than once return; } } // add to the end of the playlist tracks.push(product); this.playlist.setAttribute('data', this.playlist.data); if (! this.productid) { this.setAttribute('playlistoffset', 0); } var id = product.id; buywindow.setAttributes({src: '/checkouts/new/' + id, visible: true}) var url = '/download/' + product.tracks[0].audio + '?pid=' + product.id; //console.log('download', url, product) window.open(url, '_new'); //this.downloadwindow.setAttribute('src', url) // console.log('got album data', data) if (data.tracks && data.tracks.length > 0) { // reset track offset var trackoffset = 0// || (Math.min(localStorage.trackoffset + 0, data.tracks.length - 1)); this.setAttribute('trackoffset', trackoffset) // console.log('offset', JSON.stringify(trackoffset)) } if (! this.album.data) return; var tracks = this.album.data.tracks; if (trackoffset < tracks.length) { // localStorage.trackoffset = trackoffset; var track = tracks[trackoffset]; // console.log('loading track', track) // get signed streaming URL var pid = track.id songredirect.getURL(track.audio, track.id, function(url) { if (url !== audio.url) { trackEvent('player', 'playing', pid) audio.setAttributes({url: url, playing: true, paused: false}); } }); var nexttrack = tracks[trackoffset + 1]; if (nexttrack) { // prefetch URL for next track setTimeout(function() { songredirect.getURL(nexttrack.audio, nexttrack.id, function() { }) },4000) } var sv = this.artwork.subviews if (tracks.length > 1 && sv && sv[0]) { // force update of playing album sv[0].setAttribute('data', sv[0].data) } } var key = id; if (this.cache && this.cache[key]) { // console.log('cache hit', key, this.cache.expires, Date.now()) if (callback) return callback(this.cache[key]); } if (this.callbacks[id]) return; this.callbacks[id] = callback; this.songredirectds.setAttribute('url', '/stream/' + file + '?pid=' + id); // console.log('songredirect', data); var key = data.pid; var callback = this.callbacks[key]; if (data.url) { if (! this.cache || (Date.now() >= this.cache.expires)) { this.cache = {}; this.cache.expires = data.expires // console.log('new cache', data) } this.cache[key] = data.url; if (callback) { callback(data.url); this.callbacks[key] = null; } } if (! (product && this.purchased)) return false; if (product.tracks.length > 1) { var ownall = true; for (var i = 0; i < product.tracks.length; i++) { //console.log('checking for ownership', data.tracks[i]) if (! this.purchased[product.tracks[i].id]) { ownall = false break } } return ownall } else { return this.purchased[product.id] } trackEvent('player', 'loadplaylist', this.url) window.location.hash = this.url; charts features purchased var loggedin = data.loggedIn; if (loggedin != this.loggedin) this.setAttribute('loggedin', loggedin) if (loggedin) { trackEvent('user', 'loggedin') this.loginwindow.setAttribute('visible', false) buywindow.setAttribute('visible', false) songredirect.cache = null this.but.setAttribute('visible', true) this.but.setAttribute('class', 'fa fa-sign-out') } else { this.but.setAttribute('class', 'fa fa-sign-in') } if (this.parent.loggedin) { trackEvent('user', 'logout') window.location = '/logout' } else { trackEvent('user', 'login') this.setAttribute('visible', false) this.parent.loginwindow.setAttributes({visible: true, src: '/login'}) } if (loggedin) { // load purchases this.purchased_ds.setAttribute('url', '/purchased') } // process purchases into a hash for quick lookups var ids = {}; for (var i = 0; i < purchased.length; i++) { var tid = purchased[i] ids[tid] = true; } this.parent.setAttribute('purchased', ids) this.repl.setAttribute('data', [data])