diff --git a/README.md b/README.md index fcfb3224..13532601 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Zoff ==== -Zoff (pronounced __søff__) is a shared (free) YouTube based radio service, built upon the YouTube API, with integrated casting with Chromecast. +Zoff (pronounced __søff__) is a shared (free) YouTube and SoundCloud based radio service, built upon the YouTube API, and SoundCloud API, with integrated casting with Chromecast. ## Install diff --git a/gulpfile.js b/gulpfile.js index 2ae8c87b..f2c7b3b6 100755 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,11 +5,11 @@ var gulp = require('gulp'), gulp.task('js', function () { gulp.src(['server/VERSION.js', 'server/config/api_key.js', 'server/public/assets/js/*.js', '!server/public/assets/js/embed*', '!server/public/assets/js/token*', '!server/public/assets/js/remotecontroller.js', '!server/public/assets/js/callback.js']) - .pipe(uglify({ + /*.pipe(uglify({ mangle: true, compress: true, enclose: true - })) + }))*/ .pipe(concat('main.min.js')) .pipe(gulp.dest('server/public/assets/dist')); }); diff --git a/server/REST.md b/server/REST.md index 3309c9af..856ae921 100644 --- a/server/REST.md +++ b/server/REST.md @@ -26,6 +26,8 @@ POST /api/list/:channel_name/:video_id "start_time": START_TIME, "adminpass": PASSWORD, (leave this blank if there is no password/you don't know the password) "userpass": USER_PASSWORD + "source": Either "youtube" or "soundcloud" + ("thumbnail": thumbnail url for soundcloud elements (only used when source == "soundcloud")) } Returns 400 for bad request diff --git a/server/VERSION.js b/server/VERSION.js index aed79609..fa4eedcb 100644 --- a/server/VERSION.js +++ b/server/VERSION.js @@ -1,4 +1,4 @@ -VERSION = 5; +VERSION = 6; try { module.exports = VERSION; diff --git a/server/handlers/frontpage.js b/server/handlers/frontpage.js index 2514aa26..7b8225b9 100644 --- a/server/handlers/frontpage.js +++ b/server/handlers/frontpage.js @@ -17,14 +17,23 @@ function frontpage_lists(msg, socket) { }); } -function update_frontpage(coll, id, title, callback) { +function update_frontpage(coll, id, title, thumbnail, callback) { coll = coll.replace(/ /g,''); - db.collection("frontpage_lists").update({_id: coll}, {$set: { - id: id, - title: title, - accessed: Functions.get_time()} - },{upsert: true}, function(err, returnDocs){ - if(typeof(callback) == "function") callback(); + db.collection("frontpage_lists").find({_id: coll}, function(e, doc) { + var updateObject = { + id: id, + title: title, + accessed: Functions.get_time() + }; + if(doc.length > 0 && (doc[0].thumbnail == "" || doc[0].thumbnail == undefined || doc[0].thumbnail.indexOf("ttps://i1.sndcdn.com") > -1)) { + updateObject.thumbnail = thumbnail; + if(thumbnail == undefined) updateObject.thumbnail = ""; + } + + db.collection("frontpage_lists").update({_id: coll}, {$set: updateObject + },{upsert: true}, function(err, returnDocs){ + if(typeof(callback) == "function") callback(); + }); }); } diff --git a/server/handlers/functions.js b/server/handlers/functions.js index f988cfb0..f99d9171 100644 --- a/server/handlers/functions.js +++ b/server/handlers/functions.js @@ -19,6 +19,24 @@ function remove_name_from_db(guid, name) { }); } +function isUrl(str) { + var pattern = new RegExp("\\b(((ht|f)tp(s?)\\:\\/\\/|~\\/|\\/)|www.)" + + "(\\w+:\\w+@)?(([-\\w]+\\.)+(com|org|net|gov" + + "|mil|biz|info|mobi|name|aero|jobs|museum" + + "|travel|[a-z]{2}))(:[\\d]{1,5})?" + + "(((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?" + + "((\\?([-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" + + "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)" + + "(&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" + + "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*" + + "(#([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?\\b"); + if(!pattern.test(str)) { + return false; + } else { + return true; + } +} + function getSession(socket) { try { /*var cookieParser = require("cookie-parser"); @@ -273,6 +291,7 @@ function removeSessionAdminPass(id, channel, callback) { }); } +module.exports.isUrl = isUrl; module.exports.removeEmojis = removeEmojis; module.exports.getSessionChatPass = getSessionChatPass; module.exports.setSessionChatPass = setSessionChatPass; diff --git a/server/handlers/io.js b/server/handlers/io.js index 5f263073..e0b582ec 100644 --- a/server/handlers/io.js +++ b/server/handlers/io.js @@ -471,6 +471,7 @@ module.exports = function() { socket.on('change_channel', function(obj) { if(obj == undefined && coll != undefined) { + obj = {}; obj.channel = coll; } else if(obj.hasOwnProperty("channel") && obj.channel.indexOf("?") > -1){ var _list = obj.channel.substring(0, obj.channel.indexOf("?")); diff --git a/server/handlers/list.js b/server/handlers/list.js index a360f3cc..8a9c843d 100644 --- a/server/handlers/list.js +++ b/server/handlers/list.js @@ -84,7 +84,8 @@ function list(msg, guid, coll, offline, socket) { db.collection(coll + "_settings").insert(configs, function(err, docs){ socket.join(coll); List.send_list(coll, socket, true, false, true); - db.collection("frontpage_lists").insert({"_id": coll, "count" : 0, "frontpage": true, "accessed": Functions.get_time(), "viewers": 1}); + db.collection("frontpage_lists").insert({"_id": coll, "count" : 0, "frontpage": true, "accessed": Functions.get_time(), "viewers": 1}, function(e,d){ + }); Functions.check_inlist(coll, guid, socket, offline); }); }); @@ -380,7 +381,7 @@ function change_song_post(coll, next_song, callback, socket) { List.send_play(coll, socket, true); callback(); } - Frontpage.update_frontpage(coll, docs[0].id, docs[0].title); + Frontpage.update_frontpage(coll, docs[0].id, docs[0].title, docs[0].thumbnail); }); }); }); @@ -438,7 +439,7 @@ function send_list(coll, socket, send, list_send, configs, shuffled) skips:[] } }, function(err, returnDocs){ - Frontpage.update_frontpage(coll, now_playing_doc[0].id, now_playing_doc[0].title); + Frontpage.update_frontpage(coll, now_playing_doc[0].id, now_playing_doc[0].title, now_playing_doc[0].thumbnail); List.send_list(coll, socket, send, list_send, configs, shuffled); }); }); @@ -680,7 +681,13 @@ function getNextSong(coll, callback) { $limit:1 }], function(err, doc) { if(doc.length == 1) { - io.to(coll).emit("next_song", {videoId: doc[0].id, title: doc[0].title}); + var thumbnail = ""; + var source = "youtube"; + if(doc[0].source && doc[0].source == "soundcloud") { + source = "soundcloud"; + thumbnail = doc[0].thumbnail; + } + io.to(coll).emit("next_song", {videoId: doc[0].id, title: doc[0].title, source: source, thumbnail: thumbnail}); } if(typeof(callback) == "function") callback(); }); diff --git a/server/handlers/list_change.js b/server/handlers/list_change.js index 831ed281..88af15fd 100644 --- a/server/handlers/list_change.js +++ b/server/handlers/list_change.js @@ -88,11 +88,17 @@ function addFromOtherList(arr, guid, offline, socket) { db.collection(channel).find({now_playing: true}, function(e, np_docs) { to_change.id = np_docs[0].id; to_change.title = np_docs[0].title; - db.collection("frontpage_lists").update({_id: channel}, {$set: to_change}, function(e, d) { - List.send_list(channel, undefined, false, true, false); - List.send_play(channel, undefined); - socket.emit("toast", "addedplaylist"); - _db.close(); + db.collection("frontpage_lists").find({_id: coll}, function(e, doc) { + if(doc.length > 0 && doc[0].thumbnail != "" && doc[0].thumbnail != undefined) { + to_change.thumbnail = np_docs[0].thumbnail; + } + + db.collection("frontpage_lists").update({_id: channel}, {$set: to_change}, function(e, d) { + List.send_list(channel, undefined, false, true, false); + List.send_play(channel, undefined); + socket.emit("toast", "addedplaylist"); + _db.close(); + }); }); }); } else { @@ -218,11 +224,17 @@ function addPlaylist(arr, guid, offline, socket) { db.collection(channel).find({now_playing: true}, function(e, np_docs) { to_change.id = np_docs[0].id; to_change.title = np_docs[0].title; - db.collection("frontpage_lists").update({_id: channel}, {$set: to_change}, function(e, d) { - List.send_list(channel, undefined, false, true, false); - List.send_play(channel, undefined); - socket.emit("toast", "addedplaylist"); - _db.close(); + db.collection("frontpage_lists").find({_id: coll}, function(e, doc) { + if(doc.length > 0 && doc[0].thumbnail != "" && doc[0].thumbnail != undefined) { + to_change.thumbnail = np_docs[0].thumbnail; + } + + db.collection("frontpage_lists").update({_id: channel}, {$set: to_change}, function(e, d) { + List.send_list(channel, undefined, false, true, false); + List.send_play(channel, undefined); + socket.emit("toast", "addedplaylist"); + _db.close(); + }); }); }); } else { @@ -298,7 +310,9 @@ function add_function(arr, coll, guid, offline, socket) { if(typeof(arr.id) != "string" || typeof(arr.start) != "number" || typeof(arr.end) != "number" || typeof(arr.title) != "string" || - typeof(arr.list) != "string" || typeof(arr.duration) != "number") { + typeof(arr.list) != "string" || typeof(arr.duration) != "number" || + typeof(arr.source) != "string" || + (arr.source == "soundcloud" && (!arr.hasOwnProperty("thumbnail") || !Functions.isUrl(arr.thumbnail)))) { var result = { start: { expected: "number or string that can be cast to int", @@ -327,6 +341,14 @@ function add_function(arr, coll, guid, offline, socket) { adminpass: { expected: "string", got: arr.hasOwnProperty("adminpass") ? typeof(arr.adminpass) : undefined + }, + source: { + expected: "string (youtube or soundcloud)", + got: arr.hasOwnProperty("source") ? typeof(arr.source) : undefined + }, + thumbnail: { + expected: "url if source == soundcloud", + got: arr.hasOwnProperty("thumbnail") ? typeof(arr.thumbnail) : undefined } }; socket.emit('update_required', result); @@ -350,6 +372,7 @@ function add_function(arr, coll, guid, offline, socket) { var title = arr.title; var hash = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(arr.adminpass), true)); var duration = parseInt(arr.duration); + var source = arr.source; /*db.collection(coll + "_settings").find(function(err, docs) {*/ conf = docs; @@ -366,18 +389,20 @@ function add_function(arr, coll, guid, offline, socket) { } else { np = false; } - var new_song = {"added": added,"guids":guids,"id":id,"now_playing":np,"title":title,"votes":votes, "duration":duration, "start": parseInt(start), "end": parseInt(end), "type": "video"}; + var new_song = {"added": added,"guids":guids,"id":id,"now_playing":np,"title":title,"votes":votes, "duration":duration, "start": parseInt(start), "end": parseInt(end), "type": "video", "source": source}; + if(source == "soundcloud") new_song.thumbnail = arr.thumbnail; db.collection(coll).update({id: id}, new_song, {upsert: true}, function(err, docs){ new_song._id = "asd"; if(np) { List.send_list(coll, undefined, false, true, false); db.collection(coll + "_settings").update({ id: "config" }, {$set:{startTime: Functions.get_time()}}); List.send_play(coll, undefined); - Frontpage.update_frontpage(coll, id, title); - Search.get_correct_info(new_song, coll, false); + var thumbnail = arr.thumbnail != undefined ? arr.thumbnail : undefined; + Frontpage.update_frontpage(coll, id, title, thumbnail); + if(source != "soundcloud") Search.get_correct_info(new_song, coll, false); } else { io.to(coll).emit("channel", {type: "added", value: new_song}); - Search.get_correct_info(new_song, coll, true); + if(source != "soundcloud") Search.get_correct_info(new_song, coll, true); } db.collection("frontpage_lists").update({_id:coll}, {$inc:{count:1}, $set:{accessed: Functions.get_time()}}, {upsert:true}, function(err, docs){}); List.getNextSong(coll); diff --git a/server/handlers/search.js b/server/handlers/search.js index 9671f399..7961a416 100644 --- a/server/handlers/search.js +++ b/server/handlers/search.js @@ -82,6 +82,7 @@ function check_error_video(msg, channel) { }; return; } + if(msg.source == "soundcloud") return; channel = channel.replace(/ /g,''); request({ type: "GET", diff --git a/server/handlers/suggestions.js b/server/handlers/suggestions.js index ba87ef96..1851aaf5 100644 --- a/server/handlers/suggestions.js +++ b/server/handlers/suggestions.js @@ -1,23 +1,7 @@ -function isUrl(str) { - var pattern = new RegExp("\\b(((ht|f)tp(s?)\\:\\/\\/|~\\/|\\/)|www.)" + - "(\\w+:\\w+@)?(([-\\w]+\\.)+(com|org|net|gov" + - "|mil|biz|info|mobi|name|aero|jobs|museum" + - "|travel|[a-z]{2}))(:[\\d]{1,5})?" + - "(((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?" + - "((\\?([-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" + - "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)" + - "(&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" + - "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*" + - "(#([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?\\b"); - if(!pattern.test(str)) { - return false; - } else { - return true; - } -} + function thumbnail(msg, coll, guid, offline, socket) { - if(msg.thumbnail != undefined && msg.channel && msg.channel != undefined && isUrl(msg.thumbnail)){ + if(msg.thumbnail != undefined && msg.channel && msg.channel != undefined && Functions.isUrl(msg.thumbnail)){ if(typeof(msg.channel) != "string" || typeof(msg.thumbnail) != "string") { var result = { diff --git a/server/public/assets/css/embed.css b/server/public/assets/css/embed.css index 63034832..57a87b29 100755 --- a/server/public/assets/css/embed.css +++ b/server/public/assets/css/embed.css @@ -13,6 +13,28 @@ transition: all .3s !important; } +#player_overlay { + position: absolute; + height: calc(100% - 32px); + top: 0px; + left: 0px; + width: 50vw; +} + +.soundcloud_info_container { + position: absolute; + bottom: 20px; + right: 0px; + padding-left: 20px; + display: flex; + align-items: center; + background: rgba(0,0,0,.7); +} + +.soundcloud_info_container a { + margin: 0 10px; +} + .card { cursor:pointer; background-color: rgba(255, 255, 255, 0.04) !important; diff --git a/server/public/assets/css/style.css b/server/public/assets/css/style.css index 267ee457..eff61427 100755 --- a/server/public/assets/css/style.css +++ b/server/public/assets/css/style.css @@ -123,6 +123,34 @@ a { margin: auto; } +.soundcloud_info_container { + position: absolute; + bottom: 20px; + right: 0px; + padding-left: 20px; + display: flex; + align-items: center; + background: rgba(0,0,0,.7); +} + +.soundcloud_info_container a { + margin: 0 10px; +} + +#player_loader_container { + height: 100%; +width: 100%; +background: rgba(0,0,0,.5); +} +#player_loader { + position: absolute; +left: 0; +right: 0; +margin: auto; +} + + + #send-loader { position: absolute; top: 0px; @@ -1480,7 +1508,7 @@ margin:-1px; } #inner-results { - height: calc(100vh - 64px - 76px); + height: calc(100vh - 64px - 76px - 64px); overflow-y: scroll; overflow-x: hidden; } @@ -1602,6 +1630,38 @@ ul #chat-log{ align-items: center; } +.search_results { + + background: black; + position: absolute; + width: 100vw; + top: 64px; + /* height: 100vh; */ + +} + +.results-tabs li { + width: 50%; + text-align: center; +} + +.results-tabs .indicator { + height: 2px; + z-index: 9; + position: absolute; + margin-left: -16px; + margin-top: 64px; + width: 50%; +} + +#results_soundcloud { + padding: 0; +} + +#results_soundcloud #inner-results { + height: calc(100vh - 64px - 64px); +} + #search_loader_inner{ display: flex; } @@ -2011,11 +2071,15 @@ nav ul li:hover, nav ul li.active { position: absolute; width: 100%; top: 64px; - max-height: calc(100vh - 64px); + max-height: calc(100vh - 128px); overflow: overlay; overflow-x: hidden; /* z-index: 99999999; */ } + +#results_soundcloud { + max-height: calc(100vh - 64px - 64px); +} .result:hover, .hoverResults { background-color: rgba(0,0,0,0.4); } diff --git a/server/public/assets/images/btcdonate.png b/server/public/assets/images/btcdonate.png new file mode 100644 index 00000000..e80ad6d1 Binary files /dev/null and b/server/public/assets/images/btcdonate.png differ diff --git a/server/public/assets/js/channel.js b/server/public/assets/js/channel.js index ee29bd47..c701b465 100644 --- a/server/public/assets/js/channel.js +++ b/server/public/assets/js/channel.js @@ -15,6 +15,8 @@ var Channel = { Helper.addClass("#results", "client-results-height"); Helper.addClass(".pagination-results", "client-pagination-height"); Helper.addClass(".control-list", "client-control-list"); + } else { + //Player.soundcloud_player = document.querySelector("#soundcloud_player"); } if(!Admin.logged_in) Admin.display_logged_out(); number_suggested = 0; @@ -77,6 +79,7 @@ var Channel = { } Helper.tabs('.chatTabs'); + Helper.tabs('.results-tabs'); } var sidenavElem = document.getElementsByClassName("sidenav")[0]; M.Sidenav.init(sidenavElem, { @@ -165,6 +168,7 @@ var Channel = { Playercontrols.initSlider(); if(player_ready) { Player.player.setVolume(Crypt.get_volume()); + Player.soundcloud_player.setVolume(embed ? 1 : Crypt.get_volume() / 100); } Helper.removeClass(".video-container", "no-opacity"); var codeURL = "https://remote."+window.location.hostname+"/"+id; diff --git a/server/public/assets/js/embed.js b/server/public/assets/js/embed.js index a201eb5a..c060a567 100755 --- a/server/public/assets/js/embed.js +++ b/server/public/assets/js/embed.js @@ -8,6 +8,11 @@ var startTime = 0; var socket_connected = false; var dynamicListeners = {}; var player_ready = false; +var empty_clear = false; +var fix_too_far = false; +var beginning = false; +var soundcloud_loading = false; +var firstLoad = ""; var list_html = document.getElementById("list-song-html").innerHTML; var w_p = true; var lazy_load = false; @@ -85,6 +90,7 @@ window.addEventListener("DOMContentLoaded", function() { }); color = "#" + hash[1]; add = "https://zoff.me"; + if(window.location.hostname == "localhost") add = "localhost"; //add = "localhost"; socket = io.connect(''+add+':8080', connection_options); @@ -299,6 +305,10 @@ addListener("click", ".prev_page", function(e) { List.dynamicContentPage(-1); }); +addListener("click", "#player_overlay", function(event) { + if(videoSource == "soundcloud") Playercontrols.play_pause(); +}); + addListener("click", ".next_page", function(e) { event.preventDefault(); List.dynamicContentPage(1); diff --git a/server/public/assets/js/frontpage.js b/server/public/assets/js/frontpage.js index a4198532..5ace6f9e 100755 --- a/server/public/assets/js/frontpage.js +++ b/server/public/assets/js/frontpage.js @@ -77,8 +77,9 @@ var Frontpage = { var id = lists[x].id; var viewers = lists[x].viewers; var description = lists[x].description; - var img = "background-image:url('https://img.youtube.com/vi/"+id+"/hqdefault.jpg');"; - if(lists[x].thumbnail) { + var img; + img = "background-image:url('https://img.youtube.com/vi/"+id+"/hqdefault.jpg');"; + if(lists[x].thumbnail && lists[x].thumbnail != "") { img = "background-image:url('" + lists[x].thumbnail + "');"; } @@ -86,7 +87,7 @@ var Frontpage = { var card = document.createElement("div"); card.innerHTML += pre_card; //card.innerHTML = card.children[0]; - if(song_count > 4) { + if(song_count > 3) { if(lists[x].pinned == 1) { card.querySelector(".pin").setAttribute("style", "display:block;"); //card.find(".card").attr("title", "Featured list"); diff --git a/server/public/assets/js/functions.js b/server/public/assets/js/functions.js index 8d155fd3..70c0d535 100644 --- a/server/public/assets/js/functions.js +++ b/server/public/assets/js/functions.js @@ -84,6 +84,7 @@ function hide_native(way) { Helper.setHtml("#chromecast_text", "Playing on
" + castSession.La.friendlyName); } Player.player.setVolume(100); + Player.soundcloud_player.setVolume(1); Helper.toggleClass("#player_overlay_text", "hide"); } else if(way == 0){ @@ -108,6 +109,7 @@ function hide_native(way) { if(!Helper.mobilecheck()){ Player.player.setVolume(Crypt.get_volume()); Playercontrols.visualVolume(Crypt.get_volume()); + Player.soundcloud_player.setVolume(embed ? 1 : Crypt.get_volume() / 100); } Helper.addClass("#player_overlay", "hide"); Helper.toggleClass("#player_overlay_text", "hide"); @@ -199,7 +201,6 @@ function get_list_ajax() { } }, error: function(response) { - console.log(response); response = JSON.parse(response); if(response.status == 403) { start_auth(); @@ -235,6 +236,11 @@ function contextListener(that, event) { } else if(top < 0) { top = 15; } + if(parent.getAttribute("data-video-source") == "soundcloud") { + Helper.addClass(".find-context-menu", "context-menu-disabled"); + } else { + Helper.removeClass(".find-context-menu", "context-menu-disabled"); + } Helper.css(".context-menu-root", "left", left + "px"); Helper.css(".context-menu-root", "top", top + "px"); Helper.removeClass(".context-menu-root","hide"); @@ -318,7 +324,7 @@ function del_ajax(id) { }) } -function add_ajax(id, title, duration, playlist, num, full_num, start, end) { +function add_ajax(id, title, duration, playlist, num, full_num, start, end, source, thumbnail) { /*var a = Crypt.get_pass(chan.toLowerCase()); var u = Crypt.get_userpass(chan.toLowerCase()); if(a == undefined) a = ""; @@ -332,6 +338,8 @@ function add_ajax(id, title, duration, playlist, num, full_num, start, end) { duration: duration, end_time: end, start_time: start, + thumbnail: thumbnail, + source: source, token: zoff_api_token }, headers: {"Content-Type": "application/json;charset=UTF-8"}, @@ -901,9 +909,11 @@ function searchTimeout(event) { } if(code == 13){ Search.search(search_input); + Search.soundcloudSearch(search_input); }else{ timeout_search = setTimeout(function(){ Search.search(search_input); + Search.soundcloudSearch(search_input); }, 1000); } } diff --git a/server/public/assets/js/hostcontroller.js b/server/public/assets/js/hostcontroller.js index c071de08..d7f4d00a 100755 --- a/server/public/assets/js/hostcontroller.js +++ b/server/public/assets/js/hostcontroller.js @@ -38,6 +38,7 @@ var Hostcontroller = { if(arr.type == "volume") { Playercontrols.visualVolume(arr.value); Player.setVolume(arr.value); + Player.soundcloud_player.setVolume(arr.value / 100); localStorage.setItem("volume", arr.value); Playercontrols.choose_button(arr.value, false); } else if(arr.type == "channel") { diff --git a/server/public/assets/js/list.js b/server/public/assets/js/list.js index 73c54151..a94302e5 100755 --- a/server/public/assets/js/list.js +++ b/server/public/assets/js/list.js @@ -245,7 +245,7 @@ var List = { check_error_videos: function(i) { //Helper.log("Empty-checker at " + i); - if(full_playlist.length == 0) return; + if(full_playlist.length == 0 || full_playlist[i].source == "soundcloud") return; Helper.ajax({ method: "get", url: 'https://www.googleapis.com/youtube/v3/videos?id=' + full_playlist[i].id @@ -255,7 +255,7 @@ var List = { //Helper.log("Empty-checker items " + data.items.length); if (data.items.length == 0) { Helper.log(["Emtpy-checker error at " + full_playlist[i].id + " " + full_playlist[i].title]); - socket.emit("error_video", {channel: chan.toLowerCase(), id: full_playlist[i].id, title: full_playlist[i].title}); + socket.emit("error_video", {channel: chan.toLowerCase(), id: full_playlist[i].id, title: full_playlist[i].title, source: full_playlist[i].source}); } if(full_playlist.length > i + 1 && window.location.pathname != "/") { List.check_error_videos(i + 1); @@ -356,7 +356,7 @@ var List = { full_playlist.push(now_playing); } - if(document.querySelectorAll("#suggested-"+added.id).length > 0) { + if(added.source != "soundcloud" && document.querySelectorAll("#suggested-"+added.id).length > 0) { number_suggested = number_suggested - 1; if(number_suggested < 0) number_suggested = 0; @@ -366,9 +366,9 @@ var List = { } document.querySelector(".suggested-link span.badge.new.white").innerText = to_display; + Helper.removeElement("#suggested-"+added.id); } - Helper.removeElement("#suggested-"+added.id); if(List.empty){ List.empty = false; } @@ -798,7 +798,7 @@ var List = { exportToYoutube: function() { ga('send', 'event', "export", "youtube"); - var request_url = "https://www.googleapis.com/youtube/v3/playlists?part=snippet"; + var request_url = "https://www.googleapis.com/youtube/v3/playlists?part=snippet&key=" + api_key; Helper.removeClass(".exported-list-container", "hide"); Helper.removeClass("#playlist_loader_export", "hide"); Helper.ajax({ @@ -818,10 +818,11 @@ var List = { response = JSON.parse(response); var number_added = 0; var playlist_id = response.id; - var request_url = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet"; + var request_url = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key=" + api_key; List.addToYoutubePlaylist(playlist_id, full_playlist, number_added, request_url) }, error: function(response){ + console.log(response); response = response.responseText; Helper.log([ "export to youtube response", @@ -831,13 +832,13 @@ var List = { }); }, - addToYoutubePlaylist: function(playlist_id, full_playlist, num, request_url) { + insertInYouTubePlaylist: function(playlist_id, _videoId, num, request_url) { var _data = JSON.stringify({ 'snippet': { 'playlistId': playlist_id, 'resourceId': { 'kind': 'youtube#video', - 'videoId': full_playlist[num].id + 'videoId': _videoId } } }); @@ -863,14 +864,162 @@ var List = { //setTimeout(function(){ Helper.removeClass(".current_number", "hide"); document.querySelector(".current_number").innerText = (num + 1) + " of " + (full_playlist.length); - List.addToYoutubePlaylist(playlist_id, full_playlist, num + 1, request_url) + List.addToYoutubePlaylist(playlist_id, full_playlist, num + 1, request_url); //}, 50); } + }, error: function(response) { + console.log(response); } }); }, + addToYoutubePlaylist: function(playlist_id, full_playlist, num, request_url) { + console.log(full_playlist[num], num); + if(num == full_playlist.length - 1){ + Helper.log(["All videoes added!"]); + Helper.log(["url: https://www.youtube.com/playlist?list=" + playlist_id]); + document.querySelector(".exported-list").insertAdjacentHTML("beforeend", "" + chan + ""); + Helper.addClass("#playlist_loader_export", "hide"); + Helper.addClass(".current_number", "hide"); + return; + //$(".youtube_export_button").removeClass("hide"); + } + if(full_playlist[num].hasOwnProperty("source") && full_playlist[num].source != "soundcloud") { + List.insertInYouTubePlaylist(playlist_id, full_playlist[num].id, num, request_url) + } else { + var yt_url = "https://www.googleapis.com/youtube/v3/search?key="+api_key+"&videoEmbeddable=true&part=id,snippet&fields=items(id,snippet)&type=video&order=relevance&safeSearch=none&maxResults=10&videoCategoryId=10"; + yt_url+="&q="+full_playlist[num].title; + var title = full_playlist[num].title; + var temptitle = title.split("-"); + temptitle = temptitle.join(" ").split(" "); + var vid_url = "https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key="+api_key+"&id="; + Helper.ajax({ + type: "GET", + url: yt_url, + dataType:"jsonp", + success: function(response){ + response = JSON.parse(response); + //Helper.log(response); + if(response.items.length === 0){ + Helper.log([ + "NO MATCH FOR:", + "Spotify title: " + title, + "Spotify length: " + length + ]); + var not_added_song = document.createElement("div"); + not_added_song.innerHTML = not_export_html; + + not_added_song.querySelector(".extra-add-text").innerText = title; + not_added_song.querySelector(".extra-add-text").setAttribute("title", title); + not_added_song.querySelector(".extra-button-search").setAttribute("data-text", title); + document.querySelector(".not-exported-container").insertAdjacentHTML("beforeend", not_added_song.innerHTML); + Helper.removeClass(".not-exported", "hide"); + if(num == full_playlist.length - 1){ + Helper.log(["All videoes added!"]); + Helper.log(["url: https://www.youtube.com/playlist?list=" + playlist_id]); + document.querySelector(".exported-list").insertAdjacentHTML("beforeend", "" + chan + ""); + Helper.addClass("#playlist_loader_export", "hide"); + Helper.addClass(".current_number", "hide"); + //$(".youtube_export_button").removeClass("hide"); + } else { + //setTimeout(function(){ + Helper.removeClass(".current_number", "hide"); + document.querySelector(".current_number").innerText = (num + 1) + " of " + (full_playlist.length); + List.addToYoutubePlaylist(playlist_id, full_playlist, num + 1, request_url); + //}, 50); + } + } else if(response.items.length > 0) { + for(var i = 0; i < response.items.length; i++) { + var data = response.items[i]; + vid_url += data.id.videoId+","; + } + + Helper.ajax({ + type: "GET", + url: vid_url, + dataType:"jsonp", + success: function(response){ + response = JSON.parse(response); + if(response.items.length > 0) { + var matched = false; + for(var y = 0; y < response.items.length; y++) { + var data = response.items[y]; + //Helper.log(data); + //var title = data.snippet.title; + var duration = Search.durationToSeconds(data.contentDetails.duration); + var not_matched = false; + if(similarity(data.snippet.title,title) > 0.75) { + not_matched = false; + } else { + for(var i = 0; i < temptitle.length; i++) { + var data_title = temptitle[i]; + + if(data.snippet.title.toLowerCase().indexOf(data_title.toLowerCase()) == -1 || !( + data.snippet.title.toLowerCase().indexOf("cover") == -1 && + title.toLowerCase().indexOf("cover") == -1 && + ((data.snippet.title.toLowerCase().indexOf("remix") == -1 && + title.toLowerCase().indexOf("remix") == -1) || + (data.snippet.title.toLowerCase().indexOf("remix") != -1 && + title.toLowerCase().indexOf("remix") != -1) || !(data.snippet.title.toLowerCase().indexOf(artist[0].toLowerCase()) == -1 && + data.snippet.channelTitle.toLowerCase().indexOf("vevo") == -1))) + ) + not_matched = true; + else if(duration > 1800) not_matched = true; + } + } + + if((!not_matched)){ + matched = true; + List.insertInYouTubePlaylist(playlist_id, data.id, num, request_url); + break; + } + } + if(!matched){ + if(num == full_playlist.length - 1){ + Helper.log(["All videoes added!"]); + Helper.log(["url: https://www.youtube.com/playlist?list=" + playlist_id]); + document.querySelector(".exported-list").insertAdjacentHTML("beforeend", "" + chan + ""); + Helper.addClass("#playlist_loader_export", "hide"); + Helper.addClass(".current_number", "hide"); + //$(".youtube_export_button").removeClass("hide"); + } else { + //setTimeout(function(){ + Helper.removeClass(".current_number", "hide"); + document.querySelector(".current_number").innerText = (num + 1) + " of " + (full_playlist.length); + //}, 50); + } + Helper.log([ + "NO MATCH FOR:", + "Spotify title: " + title, + "Spotify length: " + length + ]); + var not_added_song = document.createElement("div"); + not_added_song.innerHTML = not_export_html; + not_added_song.querySelector(".extra-add-text").innerText = title; + not_added_song.querySelector(".extra-add-text").setAttribute("title", title); + not_added_song.querySelector(".extra-button-search").setAttribute("data-text", title); + document.querySelector(".not-exported-container").insertAdjacentHTML("beforeend", not_added_song.innerHTML); + Helper.removeClass(".not-exported", "hide"); + List.addToYoutubePlaylist(playlist_id, full_playlist, num + 1, request_url); + + } + } + }, + error: function(e) { + console.log(e); + } + }); + + } + }, error: function(e) { + console.log(e); + } + }); + + } + }, + sortList: function() { full_playlist.sort(Helper.predicate({ name: 'votes', @@ -899,6 +1048,9 @@ var List = { var video_title = _song_info.title; var video_votes = _song_info.votes; var video_thumb_url = "//img.youtube.com/vi/"+video_id+"/mqdefault.jpg"; + if(_song_info.source == "soundcloud") { + video_thumb_url = _song_info.thumbnail; + } var video_thumb = "background-image:url('" + video_thumb_url + "');"; var song = document.createElement("div"); song.innerHTML = list_html; @@ -924,9 +1076,11 @@ var List = { song.querySelector(".list-image").setAttribute(image_attr,video_thumb); if(list){ + song.querySelector("#list-song") song.querySelector(".list-votes").innerText = video_votes; song.querySelector("#list-song").setAttribute("data-video-id", video_id); song.querySelector("#list-song").setAttribute("data-video-type", "song"); + song.querySelector("#list-song").setAttribute("data-video-source", _song_info.source); song.querySelector("#list-song").setAttribute("id", video_id); song.classList.remove("hide"); song.querySelector(".vote-container").setAttribute("title", video_title); diff --git a/server/public/assets/js/listeners.js b/server/public/assets/js/listeners.js index 1c8e3aab..68c5d12e 100755 --- a/server/public/assets/js/listeners.js +++ b/server/public/assets/js/listeners.js @@ -5,9 +5,14 @@ var client = false; if(domain.length > 0 && domain[0] == "client") { client = true; } +var SC; +var _SC2; +var firstLoad = ""; +var videoSource; var dynamicListeners = {}; var socket_connected = false; var hasadmin = 0; +var soundcloud_loading = false; var list_html = document.querySelectorAll("#list-song-html").length > 0 ? document.querySelector("#list-song-html").innerHTML : undefined; var unseen = false; var searching = false; @@ -183,6 +188,31 @@ window.addEventListener("DOMContentLoaded", function() { else if(!fromChannel && window.location.pathname == "/"){ Frontpage.init(); } + if(window.location.pathname == "/" && !client) { + tag = document.createElement('script'); + tag.src = "https://www.youtube.com/iframe_api"; + firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + + tag.onload = function() { + if(document.querySelectorAll("script[src='https://w.soundcloud.com/player/api.js']").length == 1) { + + } else { + tagSearch = document.createElement('script'); + tagSearch.setAttribute("async", true); + tagSearch.src = "https://connect.soundcloud.com/sdk/sdk-3.3.0.js"; + firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tagSearch, firstScriptTag); + + tagSearch.onload = function() { + SC.initialize({ + client_id: 'ed53fc01f248f15becddf8eb52cc91ef' + }, function() { + }); + } + } + } + } if(Helper.mobilecheck()) { socket.on("guid", function(msg) { @@ -262,8 +292,8 @@ initializeCastApi = function() { } catch(event){ _seekTo = seekTo; } - castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", start: Player.np.start, end: Player.np.end, videoId: video_id, seekTo: _seekTo, channel: chan.toLowerCase()}) - castSession.sendMessage("urn:x-cast:zoff.me", {type: "nextVideo", videoId: full_playlist[0].id, title: full_playlist[0].title}) + castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", start: Player.np.start, end: Player.np.end, videoId: video_id, seekTo: _seekTo, channel: chan.toLowerCase(), source: videoSource}) + castSession.sendMessage("urn:x-cast:zoff.me", {type: "nextVideo", videoId: full_playlist[0].id, title: full_playlist[0].title, source: full_playlist[0].source}) if(Helper.mobilecheck() && !chromecast_specs_sent) { socket.emit("get_id"); @@ -291,8 +321,8 @@ initializeCastApi = function() { } catch(event){ _seekTo = seekTo; } - castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", start: Player.np.start, end: Player.np.end, videoId: video_id, seekTo: _seekTo, channel: chan.toLowerCase()}) - castSession.sendMessage("urn:x-cast:zoff.me", {type: "nextVideo", videoId: full_playlist[0].id, title: full_playlist[0].title}) + castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", start: Player.np.start, end: Player.np.end, videoId: video_id, seekTo: _seekTo, channel: chan.toLowerCase(), source: videoSource}) + castSession.sendMessage("urn:x-cast:zoff.me", {type: "nextVideo", videoId: full_playlist[0].id, title: full_playlist[0].title, source: full_playlist[0].source}) hide_native(1); Helper.css("#channel-load", "display", "none"); Helper.addClass('.castButton', 'castButton-white-active'); @@ -488,6 +518,9 @@ addListener("click", ".copy-context-menu", function(e) { addListener("click", ".find-context-menu", function(e) { this.preventDefault(); var that = e; + if(that.classList.contains("context-menu-disabled")) { + return; + } var parent = that.parentElement; var id = parent.getAttribute("data-id"); Search.search(id, false, true); @@ -541,6 +574,7 @@ addListener("click", "#closePlayer", function(event){ socket.removeEventListener("np"); socket.removeEventListener("id"); socket.removeEventListener(id); + Helper.removeElement("#soundcloud_container"); Helper.removeElement("#alreadychannel"); Player.player = ""; document.title = "Zoff - the shared YouTube based radio"; @@ -580,6 +614,11 @@ document.addEventListener("keydown", function(event) { document.querySelector("#import") != document.activeElement && document.querySelector("#find_input") != document.activeElement && document.querySelector("#import_spotify") != document.activeElement) { + if(videoSource == "soundcloud") { + event.preventDefault(); + Playercontrols.play_pause(); + return false; + } if(Player.player.getPlayerState() == 1) { event.preventDefault(); Player.player.pauseVideo(); @@ -636,6 +675,7 @@ document.addEventListener("keyup", function(event) { } });*/ document.querySelector("#results").innerHTML = ""; + document.querySelector("#results_soundcloud").innerHTML = ""; document.getElementsByTagName("body")[0].setAttribute("style", "overflow-y:auto") document.querySelector("#search-btn i").innerText = "search"; document.querySelector(".search_input").value = ""; @@ -741,6 +781,10 @@ addListener("click", ".modal-close", function(event){ this.preventDefault(); }); +addListener("click", "#player_overlay", function(event) { + if(videoSource == "soundcloud") Playercontrols.play_pause(); +}); + /* addListener("change", ".password_protected", function(event) { this.preventDefault(); @@ -1213,6 +1257,7 @@ addListener("click", "#closeSettings", function(event) Admin.hide_settings(); }); + window.addEventListener("focus", function(event) { document.getElementById("favicon").setAttribute("href", "/assets/images/favicon.png"); unseen = false; @@ -1254,6 +1299,12 @@ addListener("click", ".result-object", function(e){ var original_length = e.getAttribute("data-video-length"); var start = parseInt(e.querySelector(".result-start").value); var end = parseInt(e.querySelector(".result-end").value); + var source = "youtube"; + var thumbnail; + if(e.getAttribute("data-type-source") != undefined) { + source = "soundcloud"; + thumbnail = e.getAttribute("data-type-thumbnail"); + } if(end > original_length) { end = original_length; } @@ -1264,7 +1315,7 @@ addListener("click", ".result-object", function(e){ } else { try { var length = parseInt(end) - parseInt(start); - Search.submitAndClose(id, title, length, start, end); + Search.submitAndClose(id, title, length, start, end, source, thumbnail); } catch(err) { M.toast({html: "Only numbers are accepted as song start and end parameters..", displayLength: 3000, classes: "red lighten"}); } @@ -1349,6 +1400,13 @@ addListener("click", "#add-many", function(e){ if(end > original_length) { end = original_length; } + var source = "youtube"; + var thumbnail; + if(e.getAttribute("data-type-source") != undefined) { + + source = "soundcloud"; + thumbnail = e.getAttribute("data-type-thumbnail"); + } if(start > end) { M.toast({html: "Start can't be before the end..", displayLength: 3000, classes: "red lighten"}); } else if(start < 0) { @@ -1356,8 +1414,9 @@ addListener("click", "#add-many", function(e){ } else { try { var length = parseInt(end) - parseInt(start); + e.parentElement.parentElement.parentElement.remove(); - Search.submit(id, title, length, false, 0, 1, start, end); + Search.submit(id, title, length, false, 0, 1, start, end, source, thumbnail); } catch(event) { M.toast({html: "Only numbers are accepted as song start and end parameters..", displayLength: 3000, classes: "red lighten"}); } @@ -1380,7 +1439,7 @@ addListener("click", ".add-suggested", function(e){ var title = e.getAttribute("data-video-title"); var length = e.getAttribute("data-video-length"); var added_by = e.getAttribute("data-added-by"); - Search.submit(id, title, parseInt(length), false, 0, 1, 0, parseInt(length)); + Search.submit(id, title, parseInt(length), false, 0, 1, 0, parseInt(length), "youtube"); if(added_by == "user") { number_suggested = number_suggested - 1; if(number_suggested < 0) number_suggested = 0; diff --git a/server/public/assets/js/player.js b/server/public/assets/js/player.js index c25008f8..7ccb7da2 100755 --- a/server/public/assets/js/player.js +++ b/server/public/assets/js/player.js @@ -7,23 +7,12 @@ var Player = { stopInterval: false, fireplace: "", np: {}, + soundcloud_player: { + setVolume: function(val) {} + }, youtube_listener: function(obj) { - Helper.log(["object", obj]); - var state; - fix_too_far = false; - if(embed && !autoplay && obj && obj.np.length > 0) { - if(Object.keys(obj).length == 0) { - paused = false; - empty_clear = true; - } else { - empty_clear = false; - } - Player.getTitle(obj.np[0].title, viewers); - //Player.setBGimage(video_id); - if(!Helper.mobilecheck()) { - Player.notifyUser(obj.np[0].id, obj.np[0].title); - } + if(obj.np != undefined) { video_id = obj.np[0].id; Player.np = { id: video_id, @@ -31,227 +20,70 @@ var Player = { end: obj.np[0].end, duration: obj.np[0].duration, }; + if(!obj.np[0].hasOwnProperty("start")) { Player.np.start = 0; } + if(!obj.np[0].hasOwnProperty("end")) { Player.np.end = Player.np.duration; } - - conf = obj.conf[0]; - time = obj.time; - seekTo = (time - conf.startTime) + Player.np.start; - startTime = time - conf.startTime; song_title = obj.np[0].title; duration = obj.np[0].duration; - if(player_ready) { - Player.cueVideoById(video_id, duration); - Player.stopVideo(); + videoSource = obj.np[0].hasOwnProperty("source") ? obj.np[0].source : "youtube"; + } else { + Player.np = { + id: "", + start: 0, + end: 0, + duration: 0, + }; + + document.getElementById('song-title').innerText = "Empty channel. Add some songs!"; + document.title = "Zoff - the shared YouTube based radio"; + Helper.css("#channel-load", "display", "none"); + + if(!window.MSStream && !chromecastAvailable) { + Helper.removeClass("#player_overlay", "hide"); } - return; - } - if(embed && obj.np) { - if(window.parentWindow && window.parentOrigin) { - window.parentWindow.postMessage({type: "np", title: obj.np[0].title}, window.parentOrigin); - if(full_playlist.length > 0) { - Player.sendNext({title: full_playlist[0].title, videoId: full_playlist[0].id}); - } - } - } - try { - state = Player.player.getPlayerState(); - } catch(e) { - state = null; - } - if(!paused) { - gotten_np = true; - } - if((((!offline && (state != null || from_frontpage)) || (offline && (!(state != null) || from_frontpage))|| (!offline && (!(state != null) || from_frontpage)) || (offline && state == -1)) && !(offline && prev_chan_player == chan)) || (offline && video_id == undefined)){ - prev_chan_player = chan; - from_frontpage = false; - Player.loaded = false; - Helper.log([ - "youtube_listener", - "Received: ", - obj, - "paused variable: " + paused, - "mobile_beginning variable: " + mobile_beginning]); try{ - Helper.log(["getVideoUrl(): " + Player.player.getVideoUrl().split('v=')[1]]); - } catch(e){} - Helper.log(["video_id variable: " + video_id]); - if(!obj.np){ - document.getElementById('song-title').innerText = "Empty channel. Add some songs!"; - document.title = "Zoff - the shared YouTube based radio"; - Helper.css("#channel-load", "display", "none"); - - if(!window.MSStream && !chromecastAvailable) { - Helper.removeClass("#player_overlay", "hide"); - } - try{ - if(!chromecastAvailable) { - Player.stopVideo(); - } - }catch(e){ - - } - //List.importOldList(channel.toLowerCase()); - } else if(paused || was_stopped){ - - Player.getTitle(obj.np[0].title, viewers); - //Player.setBGimage(video_id); - if(!Helper.mobilecheck()) { - Player.notifyUser(obj.np[0].id, obj.np[0].title); - } if(!chromecastAvailable) { Player.stopVideo(); } - video_id = obj.np[0].id; - Player.np = { - id: video_id, - start: obj.np[0].start, - end: obj.np[0].end, - duration: obj.np[0].duration, - }; - if(!obj.np[0].hasOwnProperty("start")) { - Player.np.start = 0; - } - if(!obj.np[0].hasOwnProperty("end")) { - Player.np.end = Player.np.duration; - } + }catch(e){ - conf = obj.conf[0]; - time = obj.time; - seekTo = (time - conf.startTime) + Player.np.start; - startTime = time - conf.startTime; - song_title = obj.np[0].title; - duration = obj.np[0].duration; - Player.setThumbnail(conf, video_id); - Player.cueVideoById(video_id, duration); - //Player.setBGimage(video_id); - } else if(!paused){ - //Helper.log("gotten new song"); - if(previous_video_id === undefined) { - previous_video_id = obj.np[0].id; - } else if(previous_video_id != video_id) { - previous_video_id = video_id; - } - - video_id = obj.np[0].id; - Player.np = { - id: video_id, - start: obj.np[0].start, - end: obj.np[0].end, - duration: obj.np[0].duration, - }; - if(!obj.np[0].hasOwnProperty("start")) { - Player.np.start = 0; - } - if(!obj.np[0].hasOwnProperty("end")) { - Player.np.end = Player.np.duration; - } - conf = obj.conf[0]; - time = obj.time; - seekTo = (time - conf.startTime) + Player.np.start; - startTime = time - conf.startTime; - song_title = obj.np[0].title; - duration = obj.np[0].duration; - Player.setThumbnail(conf, video_id); - if(mobile_beginning && Helper.mobilecheck() && seekTo === 0 && !chromecastAvailable) { - seekTo = 1 + Player.np.start; - } - - try{ - if(full_playlist[0].id == video_id && !mobile_beginning){ - List.song_change(full_playlist[0].added); - } - if(!client) Suggestions.fetchYoutubeSuggests(video_id); - }catch(e){} - - Player.getTitle(song_title, viewers); - if(player_ready && !window.MSStream) { - try { - var compared; - var prev_state = state; - try { - compared = Player.player.getVideoUrl().split('v=')[1] != video_id; - } catch(e) { - compared = true; - } - if(prev_state == 2 && !chromecastAvailable) { - Player.stopVideo(); - was_stopped = true; - Player.cueVideoById(video_id, duration); - if(!durationBegun) { - Player.durationSetter(); - } - } else { - if(compared || chromecastAvailable){ - if(paused && !chromecastAvailable){ - Player.cueVideoById(video_id, duration); - } else { - Player.loadVideoById(video_id, duration); - Player.seekTo(seekTo); - } - if(!Helper.mobilecheck()) { - Player.notifyUser(video_id, song_title); - } - } - if(!paused){ - if(((!mobile_beginning || chromecastAvailable) && prev_state != 2) && autoplay) { - Player.playVideo(); - } - if(!durationBegun) { - Player.durationSetter(); - } - } - - if(Player.player.getDuration() > seekTo || Player.player.getDuration() === 0 || chromecastAvailable || Player.player.getCurrentTime() != seekTo) { - Player.seekTo(seekTo); - } - Player.after_load = video_id; - - if(!Player.loaded) { - setTimeout(function(){Player.loaded = true;},500); - } - } - }catch(e) { - if(chromecastAvailable && !paused) { - Player.loadVideoById(video_id, duration); - Player.seekTo(seekTo); - } - if(!durationBegun && !chromecastAvailable) { - Player.durationSetter(); - } - } - } else { - if(!autoplay) { - Player.stopVideo(); - } else if(player_ready){ - Player.seekTo(seekTo); - } - Player.getTitle(song_title, viewers); - } } - } else { - if(!durationBegun) { - Player.durationSetter(); - } - duration = Player.player.getDuration(); } - if(Object.keys(obj).length == 0) { - paused = false; - empty_clear = true; - } else { - empty_clear = false; + if(obj.conf != undefined) { + conf = obj.conf[0]; + } + time = obj.time; + seekTo = (time - conf.startTime) + Player.np.start; + startTime = time - conf.startTime; + + + // Play video/autoplay video + if(obj.np != undefined) { + Player.getTitle(song_title, viewers); + if(((embed && autoplay) || !embed ) && !offline && !was_stopped) { + Helper.log(["loadVideoById \nwas_stopped="+was_stopped+"\noffline="+offline]) + Player.loadVideoById(Player.np.id, duration, Player.np.start, Player.np.end); + } else { + Helper.log(["cueVideoById \nwas_stopped="+was_stopped+"\noffline="+offline]) + Player.cueVideoById(Player.np.id, duration, Player.np.start, Player.np.end); + } } }, setThumbnail: function(conf, video_id) { if(embed) return; if(!conf.hasOwnProperty("thumbnail") || conf.thumbnail == "") { - document.getElementById("thumbnail_image").innerHTML = "thumbnail"; + if(videoSource == "soundcloud") { + document.getElementById("thumbnail_image").innerHTML = "thumbnail"; + } else { + document.getElementById("thumbnail_image").innerHTML = "thumbnail"; + } } }, @@ -271,13 +103,14 @@ var Player = { Helper.log(["getVideoUrl(): " + Player.player.getVideoUrl().split('v=')[1]]); } catch(e){} Helper.log(["video_id variable: " + video_id]); + switch(newState.data) { case YT.PlayerState.UNSTARTED: break; case YT.PlayerState.ENDED: playing = false; paused = false; - + was_stopped = false; if(!offline) { /*var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true); if(u == undefined) u = "";*/ @@ -287,6 +120,11 @@ var Player = { } break; case YT.PlayerState.PLAYING: + if(videoSource == "soundcloud") { + Player.player.stopVideo(); + //was_stopped = false; + return; + } if(embed) { Helper.css("#player", "visibility", "visible"); } @@ -329,6 +167,7 @@ var Player = { end_programmatically = false; } else { if(!chromecastAvailable){ + was_stopped = true; if(beginning && mobile_beginning) { Helper.css("#playpause", "visibility", "visible"); Helper.css("#playpause", "pointer-events", "all"); @@ -366,7 +205,12 @@ var Player = { } //Playercontrols.play_pause(); } else { - Player.player.playVideo(); + if(videoSource == "soundcloud") { + Player.soundcloud_player.play(); + //SC.Widget(document.querySelector("#soundcloud_player")).play(); + } else { + Player.player.playVideo(); + } } }, @@ -380,7 +224,12 @@ var Player = { //Playercontrols.play_pause(); } else { paused = true; - Player.player.pauseVideo(); + if(videoSource == "soundcloud") { + Player.soundcloud_player.pause(); + //SC.Widget(document.querySelector("#soundcloud_player")).pause(); + } else { + Player.player.pauseVideo(); + } } }, @@ -394,7 +243,66 @@ var Player = { } }, + loadSoundCloud: function(id, this_duration, start, end, _autoplay) { + try { + if(SC == null) return; + } catch(e) { + return; + } + Player.stopVideo(); + if(_autoplay) was_stopped = false; + Helper.removeClass(document.getElementById("player_overlay"), "hide"); + Helper.css(document.getElementById("player_overlay"), "background-color", "#2d2d2d"); + if(start == undefined) start = 0; + if(seekTo == undefined) seekTo = 0; + soundcloud_loading = false; + var _autoAdd = "false"; + if(_autoplay) { + _autoAdd = "true"; + Helper.removeClass("#player_loader_container", "hide"); + } + try { + if(SC == null || !SC.stream) return; + } catch(e) { + return; + } + SC.stream("/tracks/" + id).then(function(player){ + Player.soundcloud_player = player; + Player.soundcloud_player.bind("finish", Player.soundcloudFinish); + Player.soundcloud_player.bind("pause", Player.soundcloudPause); + Player.soundcloud_player.bind("play", Player.soundcloudPlay); + window.player = player; + SC.get('/tracks', { + ids: id + }).then(function(tracks) { + var sound = tracks[0]; + Helper.removeClass(".soundcloud_info_container", "hide"); + document.querySelector("#soundcloud_listen_link").href = sound.permalink_url; + document.querySelector(".soundcloud_info_container .green").href = sound.user.permalink_url; + //document.querySelector(".soundcloud_info_container .red").href = sound.user.permalink_url; + }); + if(_autoplay) { + player.play().then(function(){ + Player.soundcloud_player.setVolume(embed ? 1 : Crypt.get_volume() / 100); + Player.soundcloud_player.seek((seekTo) * 1000); + }).catch(function(e){ + }); + } + }); + soundcloud_loading = true; + if(start == undefined) start = 0; + if(seekTo == undefined) seekTo = 0; + + if(_autoplay) was_stopped = false; + Helper.css(document.getElementById("player_overlay"), "background", "url('" + full_playlist[full_playlist.length - 1].thumbnail + "')"); + Helper.css(document.getElementById("player_overlay"), "background-size", "auto"); + Helper.css(document.getElementById("player_overlay"), "background-position", "20%"); + Helper.css(document.getElementById("player_overlay"), "background-color", "#2d2d2d"); + Helper.addClass("#player_overlay_text", "hide"); + }, + loadVideoById: function(id, this_duration, start, end){ + if(id == undefined) return; var s; var e; if(start) s = start; @@ -402,12 +310,40 @@ var Player = { if(end) e = end; else e = Player.np.end; if(chromecastAvailable){ - castSession.sendMessage("urn:x-cast:zoff.me", {start: s, end: e, type: "loadVideo", videoId: id, channel: chan.toLowerCase()}); + castSession.sendMessage("urn:x-cast:zoff.me", {start: s, end: e, type: "loadVideo", videoId: id, channel: chan.toLowerCase(), source: videoSource}); chrome.cast.media.GenericMediaMetadata({metadataType: 0, title:song_title, image: 'https://img.youtube.com/vi/'+id+'/mqdefault.jpg', images: ['https://img.youtube.com/vi/'+id+'/mqdefault.jpg']}); chrome.cast.Image('https://img.youtube.com/vi/'+id+'/mqdefault.jpg'); } else { + if(videoSource == "soundcloud") { + try { + Player.player.stopVideo(); + } catch(e) { + } + + was_stopped = false; + Player.loadSoundCloud(id, this_duration, start, end, true); + //SC.Widget(Player.soundcloud_player).play(); + } else { //window.player = Player.player; - Player.player.loadVideoById({'videoId': id, 'startSeconds': s, 'endSeconds': e}); + try { + Player.soundcloud_player.pause(); + } catch(e) { + } + Helper.addClass(".soundcloud_info_container", "hide"); + Helper.addClass(document.getElementById("player_overlay"), "hide"); + Helper.css(document.getElementById("player_overlay"), "background", "none"); + Helper.addClass("#player_overlay_text", "hide"); + Helper.addClass(document.getElementById("player_overlay"), "hide"); + try { + if(Player.player.getVideoUrl().indexOf(id) > -1) { + Player.player.seekTo(seekTo); + } else { + Player.player.loadVideoById({'videoId': id, 'startSeconds': s, 'endSeconds': e}); + } + } catch(e) { + } + was_stopped = false; + } } if(offline) { getColor(id); @@ -423,8 +359,28 @@ var Player = { if(end) e = end; else e = Player.np.end; - Player.player.cueVideoById({'videoId': id, 'startSeconds': s, 'endSeconds': e}); + if(videoSource == "soundcloud") { + try { + Player.player.stopVideo(); + } catch(e) { + } + Player.loadSoundCloud(id, this_duration, start, end, false); + //SC.Widget(Player.soundcloud_player).play(); + } else { + try { + Player.soundcloud_player.pause(); + } catch(e) { + } + Helper.addClass(document.getElementById("player_overlay"), "hide"); + Helper.css(document.getElementById("player_overlay"), "background", "none"); + Helper.addClass("#player_overlay_text", "hide"); + Helper.addClass(document.getElementById("player_overlay"), "hide"); + try { + Player.player.cueVideoById({'videoId': id, 'startSeconds': s, 'endSeconds': e}); + } catch(e) { + } + } }, stopVideo: function(){ @@ -442,6 +398,7 @@ var Player = { castSession.setVolume(vol/100); } else { Player.player.setVolume(vol); + Player.soundcloud_player.setVolume(vol / 100); } }, @@ -469,7 +426,7 @@ var Player = { Player.getTitle(song_title, viewers); //Player.setBGimage(video_id); if(chromecastAvailable){ - castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", videoId: video_id, channel: chan.toLowerCase(), start: start, end:end}); + castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", videoId: video_id, channel: chan.toLowerCase(), start: start, end:end, source: videoSource}); chrome.cast.media.GenericMediaMetadata({metadataType: 0, title:song_title, image: 'https://img.youtube.com/vi/'+video_id+'/mqdefault.jpg', images: ['https://img.youtube.com/vi/'+video_id+'/mqdefault.jpg']}); chrome.cast.Image('https://img.youtube.com/vi/'+video_id+'/mqdefault.jpg'); } else { @@ -506,7 +463,7 @@ var Player = { //Player.setBGimage(video_id); if(chromecastAvailable){ - castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", videoId: video_id, channel: chan.toLowerCase(), start: start, end: end}); + castSession.sendMessage("urn:x-cast:zoff.me", {type: "loadVideo", videoId: video_id, channel: chan.toLowerCase(), start: start, end: end, source: videoSource}); chrome.cast.media.GenericMediaMetadata({metadataType: 0, title:song_title, image: 'https://img.youtube.com/vi/'+video_id+'/mqdefault.jpg', images: ['https://img.youtube.com/vi/'+video_id+'/mqdefault.jpg']}); chrome.cast.Image('https://img.youtube.com/vi/'+video_id+'/mqdefault.jpg'); } else { @@ -518,7 +475,7 @@ var Player = { sendNext: function(obj){ if(chromecastAvailable){ - castSession.sendMessage("urn:x-cast:zoff.me", {type: "nextVideo", title: obj.title, videoId: obj.videoId}); + castSession.sendMessage("urn:x-cast:zoff.me", {type: "nextVideo", title: obj.title, videoId: obj.videoId, source: obj.source}); } if(embed) { @@ -571,6 +528,97 @@ var Player = { } }, + soundcloudFinish: function() { + playing = false; + paused = false; + end_programmatically = true; + if(!offline) { + /*var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true); + if(u == undefined) u = "";*/ + socket.emit("end", {id: video_id, channel: chan.toLowerCase()}); + } else { + Player.playNext(); + } + }, + + soundcloudPause: function() { + if(end_programmatically) { + paused = false; + playing = false; + end_programmatically = false; + } else { + was_stopped = true; + if(!chromecastAvailable){ + if(Helper.mobilecheck()) { + Helper.css("#playpause", "visibility", "visible"); + Helper.css("#playpause", "pointer-events", "all"); + Helper.css("#channel-load", "display", "none"); + } + if(!empty_clear && !gotten_np) { + paused = true; + } + if(gotten_np) gotten_np = false; + if(window.location.pathname != "/") Playercontrols.play_pause_show(); + mobile_beginning = true; + } + Helper.removeClass("#play", "hide"); + Helper.addClass("#pause", "hide"); + } + }, + + soundcloudPlay: function() { + Helper.addClass("#player_loader_container", "hide"); + if(videoSource == "youtube") { + Player.soundcloud_player.pause(); + } else if(soundcloud_loading){ + Player.soundcloud_player.seek((seekTo) * 1000); + Player.soundcloud_player.setVolume(embed ? 1 : Crypt.get_volume() / 100); + soundcloud_loading = false; + } + if(embed) { + Helper.css("#player", "visibility", "visible"); + } + if(embed && !autoplay) autoplay = true; + if(!window.MSStream) { + Helper.css("#player", "opacity", "1"); + //if(!Helper.mobilecheck()) { + Helper.css("#channel-load", "display", "none"); + + //} + } + Helper.css("#playpause", "visibility", "visible"); + Helper.css("#playpause", "pointer-events", "all"); + playing = true; + if(beginning && Helper.mobilecheck() && !chromecastAvailable){ + //Player.pauseVideo(); + beginning = false; + mobile_beginning = false; + + } + //if(!embed && window.location.pathname != "/" && !chromecastAvailable) Helper.addClass("#player_overlay", "hide"); + if(window.location.pathname != "/"){ + Helper.addClass("#play", "hide"); + Helper.removeClass("#pause", "hide"); + } + if((was_stopped) && !offline) { + /*var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true); + if(u == undefined) u = "";*/ + paused = false; + was_stopped = false; + socket.emit('pos', {channel: chan.toLowerCase()}); + } else { + paused = false; + was_stopped = false; + } + + }, + + soundcloudReady: function() { + beginning = true; + player_ready = true; + if(videoSource == "soundcloud" && videoId != undefined) Player.loadVideoById(videoId, Player.np.duration, Player.np.start, Player.np.end); + }, + onPlayerReady: function(event) { try{ beginning = true; @@ -669,7 +717,9 @@ var Player = { notifyUser: function(id, title) { title = title.replace(/\\\'/g, "'").replace(/"/g,"'").replace(/&/g,"&"); if (Notification.permission === "granted" && document.hidden && !embed) { - var notification = new Notification("Now Playing", {body: title, icon: "https://img.youtube.com/vi/"+id+"/mqdefault.jpg", iconUrl: "http://img.youtube.com/vi/"+id+"/mqdefault.jpg"}); + var icon = "https://img.youtube.com/vi/"+id+"/mqdefault.jpg"; + if(videoSource) icon = full_playlist[full_playlist.length - 1].thumbnail; + var notification = new Notification("Now Playing", {body: title, icon: icon, iconUrl: icon}); notification.onclick = function(x) { window.focus(); this.cancel(); }; setTimeout(function(){ notification.close(); @@ -734,7 +784,12 @@ var Player = { dMinutes = Math.floor(duration / 60); dSeconds = duration - dMinutes * 60; - currDurr = Player.player.getCurrentTime() !== undefined ? Math.floor(Player.player.getCurrentTime()) : seekTo; + if(videoSource == "soundcloud") { + currDurr = Math.floor(Player.soundcloud_player.currentTime()) / 1000; + } else { + currDurr = Player.player.getCurrentTime() !== undefined ? Math.floor(Player.player.getCurrentTime()) : seekTo; + } + if(currDurr - Player.np.start > duration && !offline) { currDurr = duration - Player.np.start; } @@ -761,17 +816,28 @@ var Player = { if(!dragging) { document.getElementById("bar").style.width = per+"%"; } + if(videoSource == "soundcloud") { + if(Math.ceil(currDurr) + 1 > Player.np.end && Player.soundcloud_player.isPlaying()) { + end_programmatically = true; + if(!offline) { + Player.soundcloud_player.pause(); + was_stopped = false; + socket.emit("end", {id: video_id, channel: chan.toLowerCase()}); + } else { + Player.playNext(); + } + } + } else { + if(Player.player.getCurrentTime() > Player.np.end && Player.player.getPlayerState() == YT.PlayerState.PLAYING) { + end_programmatically = true; - if(Player.player.getCurrentTime() > Player.np.end && Player.player.getPlayerState() == YT.PlayerState.PLAYING) { - end_programmatically = true; - - if(!offline) { - Player.player.pauseVideo(); - /*var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true); - if(u == undefined) u = "";*/ - socket.emit("end", {id: video_id, channel: chan.toLowerCase()}); - } else { - Player.playNext(); + if(!offline) { + Player.player.pauseVideo(); + was_stopped = false; + socket.emit("end", {id: video_id, channel: chan.toLowerCase()}); + } else { + Player.playNext(); + } } } } @@ -785,6 +851,8 @@ var Player = { if(document.querySelectorAll("script[src='https://www.youtube.com/iframe_api']").length == 1){ try{ Player.onYouTubeIframeAPIReady(); + //SC.Widget(Player.soundcloud_player).bind("ready", Player.soundcloudReady); + Player.soundcloudReady(); } catch(error){ console.error("Seems YouTube iFrame script isn't correctly loaded. Please reload the page."); } @@ -793,6 +861,27 @@ var Player = { tag.src = "https://www.youtube.com/iframe_api"; firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + + tag.onload = function() { + if(document.querySelectorAll("script[src='https://w.soundcloud.com/player/api.js']").length == 1) { + //SC.Widget(Player.soundcloud_player); + //SC.Widget(Player.soundcloud_player).bind(SC.Widget.Events.READY, Player.soundcloudReady); + } else { + + tagSearch = document.createElement('script'); + tagSearch.setAttribute("async", true); + tagSearch.src = "https://connect.soundcloud.com/sdk/sdk-3.3.0.js"; + firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tagSearch, firstScriptTag); + + tagSearch.onload = function() { + SC.initialize({ + client_id: 'ed53fc01f248f15becddf8eb52cc91ef' + }, function() { + }); + } + } + } } } diff --git a/server/public/assets/js/playercontrols.js b/server/public/assets/js/playercontrols.js index 975c6e99..0aef12e7 100755 --- a/server/public/assets/js/playercontrols.js +++ b/server/public/assets/js/playercontrols.js @@ -190,24 +190,32 @@ var Playercontrols = { play_pause: function() { if(!chromecastAvailable){ - if(Player.player.getPlayerState() == YT.PlayerState.PLAYING) - { - Player.pauseVideo(); - if(Helper.mobilecheck() && !window.MSStream){ - //if(Helper.mobilecheck() && !/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){ - //document.getElementById("player").style.display = "none"; - Helper.css("#player", "display", "none"); - Helper.toggleClass(".video-container", "click-through"); - Helper.toggleClass(".page-footer", "padding-bottom-extra"); + if(videoSource == "soundcloud") { + if(!Player.soundcloud_player.isPlaying()) { + Player.playVideo(); + } else { + Player.pauseVideo(); } - } else if(Player.player.getPlayerState() == YT.PlayerState.PAUSED || Player.player.getPlayerState() === YT.PlayerState.ENDED || (Player.player.getPlayerState() === YT.PlayerState.CUED)){ - Player.playVideo(); - //if(Helper.mobilecheck() && !/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){ - if(Helper.mobilecheck() && !window.MSStream){ - //document.getElementById("player").style.display = "block"; - Helper.css("#player", "display", "block"); - Helper.toggleClass(".video-container", "click-through"); - Helper.toggleClass(".page-footer", "padding-bottom-extra"); + } else { + if(Player.player.getPlayerState() == YT.PlayerState.PLAYING) + { + Player.pauseVideo(); + if(Helper.mobilecheck() && !window.MSStream){ + //if(Helper.mobilecheck() && !/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){ + //document.getElementById("player").style.display = "none"; + Helper.css("#player", "display", "none"); + Helper.toggleClass(".video-container", "click-through"); + Helper.toggleClass(".page-footer", "padding-bottom-extra"); + } + } else if(Player.player.getPlayerState() == YT.PlayerState.PAUSED || Player.player.getPlayerState() === YT.PlayerState.ENDED || (Player.player.getPlayerState() === YT.PlayerState.CUED)){ + Player.playVideo(); + //if(Helper.mobilecheck() && !/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){ + if(Helper.mobilecheck() && !window.MSStream){ + //document.getElementById("player").style.display = "block"; + Helper.css("#player", "display", "block"); + Helper.toggleClass(".video-container", "click-through"); + Helper.toggleClass(".page-footer", "padding-bottom-extra"); + } } } } else { @@ -265,6 +273,7 @@ var Playercontrols = { setVolume: function(vol) { Player.setVolume(vol); + Player.soundcloud_player.setVolume(vol / 1000); Playercontrols.choose_button(vol, false); if(Player.player.isMuted()) Player.player.unMute(); @@ -345,12 +354,24 @@ var Playercontrols = { }, playPause: function() { - state = Player.player.getPlayerState(); - button = document.getElementById("playpause"); - if(state == YT.PlayerState.PLAYING) { - Player.pauseVideo(); - } else if(state == YT.PlayerState.PAUSED) { - Player.playVideo(); + if(videoSource == "soundcloud") { + if(!Player.soundcloud_player.isPlaying()) { + Helper.addClass("#play", "hide"); + Helper.removeClass("#pause", "hide"); + Player.soundcloud_player.play(); + } else { + Helper.removeClass("#play", "hide"); + Helper.addClass("#pause", "hide"); + Player.soundcloud_player.pause(); + } + } else { + state = Player.player.getPlayerState(); + button = document.getElementById("playpause"); + if(state == YT.PlayerState.PLAYING) { + Player.pauseVideo(); + } else if(state == YT.PlayerState.PAUSED) { + Player.playVideo(); + } } }, diff --git a/server/public/assets/js/search.js b/server/public/assets/js/search.js index d6b15e46..3cb0297e 100755 --- a/server/public/assets/js/search.js +++ b/server/public/assets/js/search.js @@ -17,28 +17,30 @@ var Search = { //$("#results").empty(); if(document.querySelector("#search-btn i").innerText == "close") { document.querySelector("body").setAttribute("style", "overflow-y:auto") - /*$("#results").slideUp({ - complete: function() { - $("#results").empty(); - } - });*/ + document.getElementById("results").innerHTML = ""; + document.getElementById("results_soundcloud").innerHTML = ""; + Helper.css(".search_results", "display", "none"); + //Helper.css(".results-tabs", "display", "none"); document.querySelector(".search_input").value = ""; document.querySelector("#search-btn i").innerText = "search"; + //Helper.css(document.querySelector(".search_results .col.s12"), "display", "none"); } else { document.querySelector("#search-btn i").innerText = "close"; + //Helper.css(".search_results", "display", "block"); } document.querySelector("#search").focus(); }, search: function(search_input, retried, related, pagination){ + if(result_html === undefined || empty_results_html === undefined) { result_html = document.getElementById("temp-results-container"); empty_results_html = Helper.html("#empty-results-container"); } if(!pagination && document.querySelectorAll("#inner-results").length == 0) { - Helper.setHtml(".search_results", ''); + Helper.setHtml("#results", ''); } if(search_input !== ""){ searching = true; @@ -55,7 +57,8 @@ var Search = { Helper.addClass(".search_loader_spinner", "active"); - Helper.removeClass("#results", "hide"); + //Helper.removeClass(".search_results", "hide"); + //Helper.css(".results-tabs", "display", "none"); Helper.ajax({ type: "GET", @@ -63,11 +66,14 @@ var Search = { dataType: "jsonp", success: function(response){ response = JSON.parse(response); + var output = ""; var nextPageToken = response.nextPageToken; var prevPageToken = response.prevPageToken; + //Helper.css(document.querySelector(".search_results .col.s12"), "display", "block"); if(response.items.length === 0) { document.getElementById("results").innerHTML = ""; Helper.css("#results", "display", "block"); + //Helper.css(".results-tabs", "display", "block"); //$("").appendTo($("#results")).show("blind", 83.33); document.getElementById("results").insertAdjacentHTML("beforeend", "
"+empty_results_html+"
"); Helper.removeClass(".search_loader_spinner", "active"); @@ -88,18 +94,17 @@ var Search = { pre_result.innerHTML = result_html.outerHTML; //$("#results").append(result_html); - for(var i = 0; i < response.items.length; i++) { var song = response.items[i]; var duration=song.contentDetails.duration; - secs=Search.durationToSeconds(duration); + var secs=Search.durationToSeconds(duration); var _temp_duration = Helper.secondsToOther(secs); - if(!longsongs || secs<720){ - title=song.snippet.title; - enc_title=title;//encodeURIComponent(title).replace(/'/g, "\\\'"); - id=song.id; + if((longsongs != undefined && !longsongs) || secs<720){ + var title=song.snippet.title; + var enc_title=title;//encodeURIComponent(title).replace(/'/g, "\\\'"); + var id=song.id; duration = duration.replace("PT","").replace("H","h ").replace("M","m ").replace("S","s"); - thumb=song.snippet.thumbnails.medium.url; + var thumb=song.snippet.thumbnails.medium.url; //$("#results").append(result_html); var songs = pre_result.cloneNode(true); @@ -127,7 +132,7 @@ var Search = { if(document.querySelectorAll("#inner-results").length == 0) { fresh = true; } - document.getElementsByClassName("search_results")[0].innerHTML = ""; + document.getElementById("results").innerHTML = ""; if(output.length > 0) { //$(window).scrollTop(0); if(!pagination && fresh) { @@ -157,7 +162,10 @@ var Search = { //setTimeout(function(){$(".thumb").lazyload({container: $("#results")});}, 250); Helper.removeClass(".search_loader_spinner", "active"); - Helper.css(".search_results", "display", "block"); + if(document.querySelector("#results_soundcloud").innerHTML.length > 0) { + Helper.css(".search_results", "display", "block"); + } + Helper.css(".results-tabs", "display", "block"); } else if(!retried){ Search.search(search_input, true); @@ -165,6 +173,9 @@ var Search = { //$("").appendTo($("#results")).show("blind", 83.33); document.getElementById("results").insertAdjacentHTML("beforeend", "
"+empty_results_html+"
"); Helper.css("#results", "display", "block"); + if(document.querySelector("#results_soundcloud").innerHTML.length > 0) { + Helper.css(".search_results", "display", "block"); + } Helper.removeClass(".search_loader_spinner", "active"); } } @@ -179,6 +190,111 @@ var Search = { } }, + soundcloudSearch: function(keyword) { + SC.get('/tracks', { + q: keyword + }).then(function(tracks) { + var pre_result = document.createElement("div"); + pre_result.innerHTML = result_html.outerHTML; + + //$("#results").append(result_html); + //Helper.css(document.querySelector(".search_results .col.s12"), "display", "block"); + var output = ""; + for(var i = 0; i < tracks.length; i++) { + var song = tracks[i]; + if(!song.streamable) continue; + var duration=Math.floor(song.duration / 1000); + //var secs=Search.durationToSeconds(duration); + var secs = duration; + var _temp_duration = Helper.secondsToOther(secs); + if((longsongs != undefined && !longsongs) || secs<720){ + var title=song.title; + if(title.indexOf(song.user.username) == -1) { + title = song.user.username + " - " + title; + } + var enc_title=title;//encodeURIComponent(title).replace(/'/g, "\\\'"); + var id=song.id; + //duration = duration.replace("PT","").replace("H","h ").replace("M","m ").replace("S","s"); + var thumb=song.artwork_url; + //var thumb = null; + if(thumb == null) thumb = song.waveform_url; + else thumb = thumb.replace("-large.jpg", "-t500x500.jpg"); + //$("#results").append(result_html); + var songs = pre_result.cloneNode(true); + songs.querySelector(".search-title").innerText = title; + songs.querySelector(".result_info").innerText = Helper.pad(_temp_duration[0]) + ":" + Helper.pad(_temp_duration[1]); + songs.querySelector(".thumb").setAttribute("src", thumb); + //songs.querySelector(".add-many").attr("onclick", "submit('"+id+"','"+enc_title+"',"+secs+");"); + songs.querySelector("#add-many").setAttribute("data-type-source", "soundcloud"); + songs.querySelector("#add-many").setAttribute("data-type-thumbnail", thumb); + songs.querySelector("#add-many").setAttribute("data-video-id", id); + songs.querySelector("#add-many").setAttribute("data-video-title", enc_title); + songs.querySelector("#add-many").setAttribute("data-video-length", secs); + //$($(songs).querySelector("div")[0]).setAttribute("onclick", "submitAndClose('"+id+"','"+enc_title+"',"+secs+");"); + songs.querySelector("#temp-results").setAttribute("data-video-id", id); + songs.querySelector("#temp-results").setAttribute("data-video-title", enc_title); + songs.querySelector("#temp-results").setAttribute("data-video-length", secs); + songs.querySelector(".open-externally").setAttribute("href", song.permalink_url); + songs.querySelector(".result-end").setAttribute("value", secs); + songs.querySelector("#temp-results").setAttribute("data-type-source", "soundcloud"); + songs.querySelector("#temp-results").setAttribute("data-type-thumbnail", thumb); + //$($(songs).querySelector("div")[0]).setAttribute("id", id) + //output += undefined; + if(songs.innerHTML != undefined && songs.innerHTML != "") { + output += songs.innerHTML; + } + } + } + var fresh = false; + if(document.querySelectorAll("#inner-results").length == 0) { + fresh = true; + } + document.getElementById("results_soundcloud").innerHTML = ""; + if(output.length > 0) { + if(document.querySelector("#results").innerHTML.length > 0) { + Helper.css(".search_results", "display", "block"); + } + //$(window).scrollTop(0); + /*if(!pagination && fresh) { + //Helper.css(".search_results", "display", "none"); + }*/ + //document.getElementById("results_soundcloud").insertAdjacentHTML("beforeend", pagination_buttons_html); + //$("
"+output+"
").prependTo($("#results")); + document.getElementById("results_soundcloud").insertAdjacentHTML("afterbegin", "
"+output+"
"); + if(!pagination && fresh) { + //$(".search_results").slideDown(); + } + document.getElementsByTagName("body")[0].setAttribute("style", "overflow-y:hidden !important") + + /*if(nextPageToken) { + document.querySelector(".next-results-button").setAttribute("data-pagination", nextPageToken); + } else { + Helper.addClass(".next-results-button", "disabled"); + } + if(prevPageToken) { + document.querySelector(".prev-results-button").setAttribute("data-pagination", prevPageToken); + } else { + Helper.addClass(".prev-results-button", "disabled"); + } + + document.querySelector(".pagination-results a").setAttribute("data-original-search", search_input); + */ + //setTimeout(function(){$(".thumb").lazyload({container: $("#results")});}, 250); + + /*Helper.removeClass(".search_loader_spinner", "active"); + Helper.css(".search_results", "display", "block");*/ + + } /*else if(!retried){ + Search.search(search_input, true); + } else { + //$("").appendTo($("#results_soundcloud")).show("blind", 83.33); + document.getElementById("results_soundcloud").insertAdjacentHTML("beforeend", "
"+empty_results_html+"
"); + Helper.css("#results_soundcloud", "display", "block"); + Helper.removeClass(".search_loader_spinner", "active"); + }*/ + }); + }, + backgroundSearch: function(title, artist, length, totalNumber, current){ var keyword= encodeURIComponent(title + " " + artist); var yt_url = "https://www.googleapis.com/youtube/v3/search?key="+api_key+"&videoEmbeddable=true&part=id,snippet&fields=items(id,snippet)&type=video&order=relevance&safeSearch=none&maxResults=10&videoCategoryId=10"; @@ -247,8 +363,6 @@ var Search = { )) not_matched = true; else if(duration > 1800) not_matched = true; - - } } @@ -276,13 +390,13 @@ var Search = { } }, error: function(e) { - console.log(e); + console.error(e); } }); } }, error: function(e) { - console.log(e); + console.error(e); } }); }, @@ -299,112 +413,57 @@ var Search = { if((Search.submitArray.length - 1) == Search.submitArrayExpected) { socket.emit("addPlaylist", {channel: chan.toLowerCase(), songs: Search.submitArray}); /*$.each(Search.submitArray, function(i, data){ - Search.submit(data.id, data.title, data.duration, true, i, Search.submitArray.length - 1, 0, data.duration); - });*/ - document.getElementById("import_spotify").disabled = false; - Helper.removeClass("#import_spotify", "hide"); - Helper.addClass("#playlist_loader_spotify", "hide"); - Search.submitArray = []; - Search.submitArrayExpected = null; - } - }, + Search.submit(data.id, data.title, data.duration, true, i, Search.submitArray.length - 1, 0, data.duration); + });*/ + document.getElementById("import_spotify").disabled = false; + Helper.removeClass("#import_spotify", "hide"); + Helper.addClass("#playlist_loader_spotify", "hide"); + Search.submitArray = []; + Search.submitArrayExpected = null; + } +}, - submitAndClose: function(id,title,duration, start, end){ - Search.submit(id,title, duration, false, 0, 1, start, end); - Helper.setHtml("#results", ''); - Search.showSearch(); - document.getElementById("search").value = ""; - document.getElementsByTagName("body")[0].setAttribute("style", "overflow-y:auto") - Helper.setHtml("#results",""); - Helper.removeClass(".main", "blurT"); - Helper.removeClass("#controls", "blurT"); - Helper.removeClass(".main", "clickthrough"); - }, +submitAndClose: function(id,title,duration, start, end, source, thumbnail){ + Search.submit(id,title, duration, false, 0, 1, start, end, source, thumbnail); + Helper.setHtml("#results", ''); + Search.showSearch(); + document.getElementById("search").value = ""; + document.getElementsByTagName("body")[0].setAttribute("style", "overflow-y:auto") + Helper.setHtml("#results",""); + Helper.setHtml("#results-soundcloud", ""); + Helper.removeClass(".main", "blurT"); + Helper.removeClass("#controls", "blurT"); + Helper.removeClass(".main", "clickthrough"); + Helper.css(".search_results", "display", "none"); +}, - importPlaylist: function(pId,pageToken){ - token = ""; - var headers; - var datatype; - if(pageToken !== undefined) - token = "&pageToken="+pageToken; - playlist_url = "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&maxResults=49&key="+api_key+"&playlistId="+pId+token; - if(youtube_authenticated) { - datatype = "html"; - headers = { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + access_token_data_youtube.access_token - }; - } else { - headers = {};//'Content-Type': 'application/json'}; - datatype = "jsonp"; - } - Helper.ajax({ - type: "GET", - url: playlist_url, - dataType: datatype, - //dataType:"jsonp", - headers: headers, - success: function(response) { - response = JSON.parse(response); - if(response.error){ - if(response.error.errors[0].reason == "playlistItemsNotAccessible"){ - var nonce = Helper.randomString(29); - window.callback = function(data) { - access_token_data_youtube = data; - if(access_token_data_youtube.state == nonce){ - youtube_authenticated = true; - setTimeout(function(){ - youtube_authenticated = false; - access_token_data_youtube = {}; - }, access_token_data_youtube.expires_in * 1000); - Search.importPlaylist(pId, pageToken); - } else { - access_token_data_youtube = ""; - console.error("Nonce doesn't match"); - } - youtube_window.close(); - window.callback = ""; - }; - youtube_window = window.open("/o_callback#youtube=true&nonce=" + nonce, "", "width=600, height=600"); - } else { - Helper.log([ - "import list error: ", - response.error - ]); - document.getElementById("import").disabled = false; - Helper.addClass("#playlist_loader", "hide"); - Helper.removeClass("#import", "hide"); - before_toast(); - M.toast({html: "It seems you've entered a invalid url.", displayLength: 4000}); - } - - } else { - var ids=""; - var this_length = 0; - if(typeof(response) == "string") response = JSON.parse(response); - //Search.addVideos(response.items[0].contentDetails.videoId); - //response.items.shift(); - for(var i = 0; i < response.items.length; i++) { - var data = response.items[i]; - ids+=data.contentDetails.videoId+","; - Search.submitYouTubeArrayIds.push(data.contentDetails.videoId); - this_length += 1; - Search.submitYouTubeExpected += 1; - } - - if(response.nextPageToken) { - //Search.addVideos(ids, true, 0, false, this_length); - Search.importPlaylist(pId, response.nextPageToken); - } else { - Search.addVideos(Search.submitYouTubeArrayIds); - //Search.addVideos(ids, true, Search.submitYouTubeExpected, true, this_length); - //Search.submitYouTubeExpected = 0; - } - document.getElementById("import").value = ""; - } - }, - error: function(e) { - if(e.status == 403){ +importPlaylist: function(pId,pageToken){ + token = ""; + var headers; + var datatype; + if(pageToken !== undefined) + token = "&pageToken="+pageToken; + playlist_url = "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&maxResults=49&key="+api_key+"&playlistId="+pId+token; + if(youtube_authenticated) { + datatype = "html"; + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + access_token_data_youtube.access_token + }; + } else { + headers = {};//'Content-Type': 'application/json'}; + datatype = "jsonp"; + } + Helper.ajax({ + type: "GET", + url: playlist_url, + dataType: datatype, + //dataType:"jsonp", + headers: headers, + success: function(response) { + response = JSON.parse(response); + if(response.error){ + if(response.error.errors[0].reason == "playlistItemsNotAccessible"){ var nonce = Helper.randomString(29); window.callback = function(data) { access_token_data_youtube = data; @@ -434,110 +493,167 @@ var Search = { before_toast(); M.toast({html: "It seems you've entered a invalid url.", displayLength: 4000}); } - } - }); - }, - importSpotifyPlaylist: function(url){ - Helper.ajax({ - method: "get", - url: url, - headers: { - 'Authorization': 'Bearer ' + access_token_data.access_token - }, - success: function(response) { - response = JSON.parse(response); + } else { + var ids=""; + var this_length = 0; + if(typeof(response) == "string") response = JSON.parse(response); + //Search.addVideos(response.items[0].contentDetails.videoId); + //response.items.shift(); for(var i = 0; i < response.items.length; i++) { var data = response.items[i]; - //ids+=data.contentDetails.videoId+","; - Search.backgroundSearch(data.track.name, data.track.artists.map(function(elem){return elem.name;}).join(" "), Math.floor(data.track.duration_ms/1000), response.total, i + response.offset); + ids+=data.contentDetails.videoId+","; + Search.submitYouTubeArrayIds.push(data.contentDetails.videoId); + this_length += 1; + Search.submitYouTubeExpected += 1; + } + if(response.nextPageToken) { + //Search.addVideos(ids, true, 0, false, this_length); + Search.importPlaylist(pId, response.nextPageToken); + } else { + Search.addVideos(Search.submitYouTubeArrayIds); + //Search.addVideos(ids, true, Search.submitYouTubeExpected, true, this_length); + //Search.submitYouTubeExpected = 0; } - if(response.next){ - Search.importSpotifyPlaylist(response.next); - } - }, - error: function(e) { - document.getElementById("import_spotify").disabled = false; - Helper.removeClass("#import_spotify", "hide"); - Helper.addClass("#playlist_loader_spotify", "hide"); + document.getElementById("import").value = ""; + } + }, + error: function(e) { + if(e.status == 403){ + var nonce = Helper.randomString(29); + window.callback = function(data) { + access_token_data_youtube = data; + if(access_token_data_youtube.state == nonce){ + youtube_authenticated = true; + setTimeout(function(){ + youtube_authenticated = false; + access_token_data_youtube = {}; + }, access_token_data_youtube.expires_in * 1000); + Search.importPlaylist(pId, pageToken); + } else { + access_token_data_youtube = ""; + console.error("Nonce doesn't match"); + } + youtube_window.close(); + window.callback = ""; + }; + youtube_window = window.open("/o_callback#youtube=true&nonce=" + nonce, "", "width=600, height=600"); + } else { + Helper.log([ + "import list error: ", + response.error + ]); + document.getElementById("import").disabled = false; + Helper.addClass("#playlist_loader", "hide"); + Helper.removeClass("#import", "hide"); before_toast(); M.toast({html: "It seems you've entered a invalid url.", displayLength: 4000}); } - }); - }, - - addVideos: function(ids){ - var more = false; - var next_ids = []; - var request_url="https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key=" + api_key + "&id="; - for(var i = 0; i < ids.length; i++) { - if(i > 48) { - more = true; - next_ids = ids.slice(i, ids.length); - break; - } - request_url += ids[i] + ","; } - Helper.ajax({ - type: "GET", - url: request_url, - success: function(response){ - response = JSON.parse(response); - var x = 0; - if(response.error) { - Search.submitYouTubeError = true; - } - for(var i = 0; i < response.items.length; i++) { - var song = response.items[i]; - var duration=Search.durationToSeconds(song.contentDetails.duration); - if(!longsongs || duration<720){ - enc_title= song.snippet.title;//encodeURIComponent(song.snippet.title); - //Search.submit(song.id, enc_title, duration, playlist, i); - x += 1; - Search.submitYouTubeArray.push({id: song.id, title: enc_title, duration: duration}); - } - } - if(more) Search.addVideos(next_ids); - else { - socket.emit("addPlaylist", {channel: chan.toLowerCase(), songs: Search.submitYouTubeArray}); - Search.submitYouTubeArray = []; - Search.submitYouTubeExpected = 0; - } - }, - error: function(e) { - console.log(e); - } - }); - }, + }); +}, - submit: function(id,title,duration, playlist, num, full_num, start, end){ - if((client || Helper.mobilecheck()) && !socket_connected) { - add_ajax(id, title, duration, playlist, num, full_num, start, end); - return; +importSpotifyPlaylist: function(url){ + Helper.ajax({ + method: "get", + url: url, + headers: { + 'Authorization': 'Bearer ' + access_token_data.access_token + }, + success: function(response) { + response = JSON.parse(response); + for(var i = 0; i < response.items.length; i++) { + var data = response.items[i]; + //ids+=data.contentDetails.videoId+","; + Search.backgroundSearch(data.track.name, data.track.artists.map(function(elem){return elem.name;}).join(" "), Math.floor(data.track.duration_ms/1000), response.total, i + response.offset); + + } + if(response.next){ + Search.importSpotifyPlaylist(response.next); + } + }, + error: function(e) { + document.getElementById("import_spotify").disabled = false; + Helper.removeClass("#import_spotify", "hide"); + Helper.addClass("#playlist_loader_spotify", "hide"); + before_toast(); + M.toast({html: "It seems you've entered a invalid url.", displayLength: 4000}); } - if(offline && document.getElementsByName("addsongs")[0].checked && document.getElementsByName("addsongs")[0].disabled){ - var found_array = []; - for(var i = 0; i < full_playlist.length; i++) { - if(full_playlist[i].id == id) found_array.push(i); - } - if(found_array.length == 0){ - List.channel_function({type: "added", start: start, end: end, value: {added: (new Date).getTime()/1000, guids: [1], id: id, title: title, duration: duration, now_playing: false, votes: 1}}); - } else { - List.vote(id, "pos"); - } - } else { - /*var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true); - if(u == undefined) u = "";*/ - emit("add", {id: id, start: start, end: end, title: title, list: chan.toLowerCase(), duration: duration}); - }//[id, decodeURIComponent(title), adminpass, duration, playlist]); - }, + }); +}, - durationToSeconds: function(duration) { - var matches = duration.match(time_regex); - hours= parseInt(matches[12])||0; - minutes= parseInt(matches[14])||0; - seconds= parseInt(matches[16])||0; - return hours*60*60+minutes*60+seconds; +addVideos: function(ids){ + var more = false; + var next_ids = []; + var request_url="https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key=" + api_key + "&id="; + for(var i = 0; i < ids.length; i++) { + if(i > 48) { + more = true; + next_ids = ids.slice(i, ids.length); + break; + } + request_url += ids[i] + ","; } + Helper.ajax({ + type: "GET", + url: request_url, + success: function(response){ + response = JSON.parse(response); + var x = 0; + if(response.error) { + Search.submitYouTubeError = true; + } + for(var i = 0; i < response.items.length; i++) { + var song = response.items[i]; + var duration=Search.durationToSeconds(song.contentDetails.duration); + if((longsongs != undefined && !longsongs) || duration<720){ + enc_title= song.snippet.title;//encodeURIComponent(song.snippet.title); + //Search.submit(song.id, enc_title, duration, playlist, i); + x += 1; + Search.submitYouTubeArray.push({id: song.id, title: enc_title, duration: duration}); + } + } + if(more) Search.addVideos(next_ids); + else { + socket.emit("addPlaylist", {channel: chan.toLowerCase(), songs: Search.submitYouTubeArray}); + Search.submitYouTubeArray = []; + Search.submitYouTubeExpected = 0; + } + }, + error: function(e) { + console.error(e); + } + }); +}, + +submit: function(id,title,duration, playlist, num, full_num, start, end, source, thumbnail){ + if((client || Helper.mobilecheck()) && !socket_connected) { + add_ajax(id, title, duration, playlist, num, full_num, start, end, source, thumbnail); + return; + } + if(offline && document.getElementsByName("addsongs")[0].checked && document.getElementsByName("addsongs")[0].disabled){ + var found_array = []; + for(var i = 0; i < full_playlist.length; i++) { + if(full_playlist[i].id == id) found_array.push(i); + } + if(found_array.length == 0){ + List.channel_function({type: "added", start: start, end: end, value: {added: (new Date).getTime()/1000, guids: [1], id: id, title: title, duration: duration, now_playing: false, votes: 1}}); + } else { + List.vote(id, "pos"); + } + } else { + /*var u = Crypt.crypt_pass(Crypt.get_userpass(chan.toLowerCase()), true); + if(u == undefined) u = "";*/ + emit("add", {id: id, start: start, end: end, title: title, list: chan.toLowerCase(), duration: duration, source: source, thumbnail: thumbnail}); + }//[id, decodeURIComponent(title), adminpass, duration, playlist]); +}, + +durationToSeconds: function(duration) { + var matches = duration.match(time_regex); + hours= parseInt(matches[12])||0; + minutes= parseInt(matches[14])||0; + seconds= parseInt(matches[16])||0; + return hours*60*60+minutes*60+seconds; +} }; diff --git a/server/public/assets/js/suggestions.js b/server/public/assets/js/suggestions.js index 7141bc8b..84fb22b9 100755 --- a/server/public/assets/js/suggestions.js +++ b/server/public/assets/js/suggestions.js @@ -37,6 +37,7 @@ var Suggestions = { }, fetchYoutubeSuggests: function(id){ + if(videoSource == "soundcloud") return; var get_url = "https://www.googleapis.com/youtube/v3/search?part=snippet&relatedToVideoId="+id+"&type=video&key="+api_key; var video_urls = "https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key="+api_key+"&id="; diff --git a/server/public/layouts/admin/authenticated.handlebars b/server/public/layouts/admin/authenticated.handlebars index d768c203..bd7fefcc 100644 --- a/server/public/layouts/admin/authenticated.handlebars +++ b/server/public/layouts/admin/authenticated.handlebars @@ -191,9 +191,9 @@
Zoff
-

The shared YouTube radio

+

The shared YouTube and SoundCloud radio

- Being built around the YouTube search and video API + Being built around the YouTube and SoundCloud API it enables the creation of collaborative and shared live playlists, with billions of videos and songs to choose from, all for free and without registration.
diff --git a/server/public/layouts/client/embed.handlebars b/server/public/layouts/client/embed.handlebars index 3ae8152b..2c780d92 100644 --- a/server/public/layouts/client/embed.handlebars +++ b/server/public/layouts/client/embed.handlebars @@ -10,6 +10,20 @@

+
+
+ + + + Buy + Artist +
+
+
+ {{> spinner}} +
+
+
diff --git a/server/public/layouts/client/main.handlebars b/server/public/layouts/client/main.handlebars index f05a8438..919da8b3 100644 --- a/server/public/layouts/client/main.handlebars +++ b/server/public/layouts/client/main.handlebars @@ -8,10 +8,10 @@ | Made by: Kasper Rynning-Tønnesen and Nicolas Almagro Tonne | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - Zoff - the shared YouTube based radio + Zoff - the shared YouTube and SoundCloud based radio - + @@ -19,7 +19,7 @@ - + diff --git a/server/public/partials/channel/header.handlebars b/server/public/partials/channel/header.handlebars index ed164b05..9e85b715 100644 --- a/server/public/partials/channel/header.handlebars +++ b/server/public/partials/channel/header.handlebars @@ -13,7 +13,7 @@ Loading...
  • - +
    • diff --git a/server/public/partials/channel/players.handlebars b/server/public/partials/channel/players.handlebars index 0dd00980..77658927 100644 --- a/server/public/partials/channel/players.handlebars +++ b/server/public/partials/channel/players.handlebars @@ -3,6 +3,7 @@
      {{/unless}}
      +
      @@ -11,9 +12,20 @@
      +
      Waiting for Video
      +
      +
      + {{> spinner}} +
      +
      play_arrow diff --git a/server/public/partials/channel/search.handlebars b/server/public/partials/channel/search.handlebars index f4e48a08..2749a555 100644 --- a/server/public/partials/channel/search.handlebars +++ b/server/public/partials/channel/search.handlebars @@ -1,43 +1,52 @@ -
      -
      -
      -
      -
      -
      - Thumb - -
      -
      -
      -
      - Start/End - - / - +