Merge branch 'develop'

Conflicts:
	README.rst
	mopidy_musicbox_webclient/static/css/webclient.css
	mopidy_musicbox_webclient/static/index.html
This commit is contained in:
woutervanwijk 2014-11-24 22:24:39 +01:00
parent aa867288d8
commit b82a956c52
18 changed files with 1242 additions and 429 deletions

View File

@ -1,7 +1,7 @@
Webclient Webclient
- Wouter van Wijk - Wouter van Wijk
- Flat Interface: Ulrich Lichtenegger - Flat Interface: Ulrich Lichtenegger
- Kingosticks - Kingosticks (Nick Steel)
- Szymon Nowak - Szymon Nowak
Mopidy: Mopidy:
@ -11,4 +11,5 @@ Icons:
https://github.com/hybridgroup/betterfrontend/blob/master/iconic/AUTHORS https://github.com/hybridgroup/betterfrontend/blob/master/iconic/AUTHORS
Background: Background:
Openclipart / Chrisdesign Openclipart / Chrisdesign

View File

@ -39,8 +39,7 @@ Alternatively, clone the repository and run ``sudo python setup.py install`` fro
Usage Usage
===== =====
Point your (modern) browser at Mopidy-MusicBox-Webclient running on your Mopidy server e.g. http://localhost:6680/musicbox. Point your (modern) browser at Mopidy-MusicBox-Webclient running on your Mopidy server e.g. http://localhost:6680/musicbox_webclient.
Project resources Project resources
@ -59,10 +58,19 @@ v1.0.2 Dev
- A friendlier welcome with a home page with buttons to the most used functions - A friendlier welcome with a home page with buttons to the most used functions
- Converted Radio Stations to Streams, so user can add streams for youtube, spotify, soundcloud, podcasts - Converted Radio Stations to Streams, so user can add streams for youtube, spotify, soundcloud, podcasts
<<<<<<< HEAD
- Enhanced radio/streams interface - Enhanced radio/streams interface
- Search: select service to search - Search: select service to search
- Youtube icons added - Youtube icons added
- Fixed single quote bug #39, other bugs - Fixed single quote bug #39, other bugs
=======
- Improved radio/streams interface
- Better handling of coverart
- Search: select service to search
- Youtube icons added
- Fixed single quote bug #39
- Bugfixes (search, popups, etc)
>>>>>>> develop
v1.0.1 (20-9-2014) v1.0.1 (20-9-2014)
------------------- -------------------

View File

@ -5,7 +5,7 @@ import os
from mopidy import config, ext from mopidy import config, ext
__version__ = '1.0.2' __version__ = '1.0.4'
class MusicBoxExtension(ext.Extension): class MusicBoxExtension(ext.Extension):

View File

@ -131,6 +131,11 @@
margin-top: 6px; margin-top: 6px;
} }
#contentHeadline a {
color:white;
margin-left: 20%;
}
#headermenubtn{ #headermenubtn{
width: 50px; width: 50px;
} }
@ -204,10 +209,23 @@
#artistviewimage, #albumviewcover { #artistviewimage, #albumviewcover {
float: right; float: right;
heigth: 90px; heigth: 90px;
max-width: 90%;
} }
/*** home ***/ /*** home ***/
#homerows div {
text-align:center;
background-color: #2C3E50;
padding: 2px;
padding-top: 20px;
border: 2px solid white;
color: white;
}
<<<<<<< HEAD
/*** home ***/
#homerows div { #homerows div {
text-align:center; text-align:center;
background-color: #2C3E50; background-color: #2C3E50;
@ -216,6 +234,8 @@
border: 3px solid white; border: 3px solid white;
} }
=======
>>>>>>> develop
#homerows div i { #homerows div i {
font-size: 28px; font-size: 28px;
} }
@ -332,18 +352,18 @@
/******************* /*******************
* Now Playing area * Now Playing area
*******************/ *******************/
.nowPlayingControls{ .nowPlayingControls {
font-size: 1.2em; font-size: 20px;
line-height: 50px; line-height: 45px;
padding-left: 10px;
} }
.nowPlayingControls .fa{ .nowPlayingControls .fa{
vertical-align: -webkit-baseline-middle; vertical-align: -webkit-baseline-middle;
vertical-align: middle;
} }
.nowPlayingControls #btplayNowPlaying{ .nowPlayingControls #btplayNowPlaying{
font-size: 190%; font-size: 190%;
margin-left: 20px; margin-left: 15px;
margin-right: 20px; margin-right: 15px;
} }
@ -360,7 +380,7 @@
} }
#controlspopup, #artistpopup, #coverpopup { #controlspopup, #artistpopup, #coverpopup {
max-width: 550px; max-width: 90%;
background: white; background: white;
padding: 5px; padding: 5px;
} }
@ -374,7 +394,19 @@
display: block; display: block;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
margin-bottom: 5px; margin-bottom: 10px;
max-width:90%;
max-height:90%;
}
#buttons {
font-size: 24px;
padding-right: 15px;
margin-bottom: 15px;
}
#btplayNowPlaying {
padding-top: 15px;
} }
#popupTracksLv li, #popupQueueLv li { #popupTracksLv li, #popupQueueLv li {
@ -543,7 +575,8 @@ a {
padding: 15px 25px 0px 25px; padding: 15px 25px 0px 25px;
} }
#nowPlayingpane #controlspopupimage{ #nowPlayingpane #controlspopupimage{
max-width: 100%; max-width:90%;
max-height:90%;
} }
.nowPlaying-artistInfo { .nowPlaying-artistInfo {
font-size: 12px; font-size: 12px;
@ -560,6 +593,8 @@ a {
} }
#controlspopupimage{ #controlspopupimage{
max-width:90%;
max-height:90%;
margin-bottom: 3px; margin-bottom: 3px;
} }
#nowPlayingpane #slidercontainer { #nowPlayingpane #slidercontainer {

View File

@ -3,13 +3,16 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<script src="js/jquery-1.10.2.min.js"></script> <script src="js/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/jquery.mobile.flatui.css"/> <link rel="stylesheet" type="text/css" href="css/jquery.mobile.flatui.css"/>
<script type='application/javascript' src='js/fastclick.js'></script> <!-- <script type='application/javascript' src='js/fastclick.js'></script> -->
<script> <script>
//configuration //configuration
// var wsLocation = location.host + ':6680'; //for musicbox configuration and normal operation of mopidy http // var wsLocation = location.host + ':6680'; //for normal operation of mopidy http
var wsLocation = location.host; //for running on port 80 var wsLocation = location.host; //for running on port 80
if (wsLocation == location.hostname) {
wsLocation = location.hostname + ':6680';
}
var isMusicBox = true; //set to true to remove buttons only for musicbox var isMusicBox = true; //set to true to remove buttons only for musicbox
$(document).bind("mobileinit", function () { $(document).bind("mobileinit", function () {
@ -21,9 +24,10 @@
// buttonMarkup.corners: false // buttonMarkup.corners: false
}); });
}); });
window.addEventListener('load', function () { /* window.addEventListener('load', function () {
new FastClick(document.body); new FastClick(document.body);
}, false); }, false);
*/
</script> </script>
<link rel="icon" type="image/gif" href="images/icons/musicbox32.gif" /> <link rel="icon" type="image/gif" href="images/icons/musicbox32.gif" />
<link rel="apple-touch-icon" href="images/icons/musicbox57.png" /> <link rel="apple-touch-icon" href="images/icons/musicbox57.png" />
@ -75,6 +79,13 @@
<li id="navnowPlaying" data-icon="false"> <li id="navnowPlaying" data-icon="false">
<a href="#nowPlaying" onclick="switchContent('nowPlaying' ); return false;"> <a href="#nowPlaying" onclick="switchContent('nowPlaying' ); return false;">
<span class="navtxt"> Now Playing </span><i class="fa fa-music"></i></a> <span class="navtxt"> Now Playing </span><i class="fa fa-music"></i></a>
<<<<<<< HEAD
=======
</li>
<li id="navcurrent" data-icon="false">
<a href="#current" onclick="switchContent('current' ); return false;">
<span class="navtxt">Queue </span><i class="fa fa-bars"></i></a>
>>>>>>> develop
</li> </li>
<li id="navplaylists" data-icon="false"> <li id="navplaylists" data-icon="false">
<a href="#playlists" onclick="switchContent('playlists' ); return false;"> <a href="#playlists" onclick="switchContent('playlists' ); return false;">
@ -84,18 +95,27 @@
<a href="#browse" onclick="switchContent('browse' ); return false;"> <a href="#browse" onclick="switchContent('browse' ); return false;">
<span class="navtxt"> Browse </span><i class="fa fa-folder"></i></a> <span class="navtxt"> Browse </span><i class="fa fa-folder"></i></a>
</li> </li>
<<<<<<< HEAD
<li id="navcurrent" data-icon="false"> <li id="navcurrent" data-icon="false">
<a href="#current" onclick="switchContent('current' ); return false;"> <a href="#current" onclick="switchContent('current' ); return false;">
<span class="navtxt">Queue </span><i class="fa fa-bars"></i></a> <span class="navtxt">Queue </span><i class="fa fa-bars"></i></a>
=======
<li id="navstream" data-icon="false">
<a href="#stream" onclick="switchContent('stream' ); return false;">
<span class="navtxt">Streams </span><i class="fa fa-rss"></i></a>
>>>>>>> develop
</li> </li>
<li id="navsearch" data-icon="false"> <li id="navsearch" data-icon="false">
<a href="#search" onclick="switchContent('search' ); return false;"> <a href="#search" onclick="switchContent('search' ); return false;">
<span class="navtxt">Search </span><i class="fa fa-search"></i></a> <span class="navtxt">Search </span><i class="fa fa-search"></i></a>
</li> </li>
<<<<<<< HEAD
<li id="navstream" data-icon="false"> <li id="navstream" data-icon="false">
<a href="#stream" onclick="switchContent('stream' ); return false;"> <a href="#stream" onclick="switchContent('stream' ); return false;">
<span class="navtxt">Streams </span><i class="fa fa-rss"></i></a> <span class="navtxt">Streams </span><i class="fa fa-rss"></i></a>
</li> </li>
=======
>>>>>>> develop
<li id="navEnterFullscreen" data-icon="false"> <li id="navEnterFullscreen" data-icon="false">
<a href="#"> <a href="#">
<span class="navtxt"> Fullscreen </span><i class="fa fa-desktop"></i></a> <span class="navtxt"> Fullscreen </span><i class="fa fa-desktop"></i></a>
@ -158,7 +178,7 @@
Queue</a> Queue</a>
</li> </li>
<li> <li>
<a href="#" onclick="showAlbumPopup()">Show Album <span class="popupAlbumName"></span></a> <a href="#" onclick="showAlbumPopup('#popupTracks')">Show Album <span class="popupAlbumName"></span></a>
</li> </li>
<li id="popupArtistsLi"> <li id="popupArtistsLi">
<a href="#" onclick="showArtist()" class="popupArtistHref">Show Artist <span <a href="#" onclick="showArtist()" class="popupArtistHref">Show Artist <span
@ -183,7 +203,7 @@
<a href="#" onclick="return removeTrack();">Remove from Queue</a> <a href="#" onclick="return removeTrack();">Remove from Queue</a>
</li> </li>
<li> <li>
<a href="#" onclick="showAlbumPopup()">Show Album <span class="popupAlbumName"></span></a> <a href="#" onclick="showAlbumPopup('#popupQueue')">Show Album <span class="popupAlbumName"></span></a>
</li> </li>
<li id="popupArtistsLi"> <li id="popupArtistsLi">
<a href="#" onclick="showArtist()" class="popupArtistHref">Show Artist <span <a href="#" onclick="showArtist()" class="popupArtistHref">Show Artist <span
@ -202,23 +222,36 @@
<div data-role="header" data-tap-toggle="false" id="header" data-position="fixed" class="ui-grid-b header-breakpoint headerbtn"> <div data-role="header" data-tap-toggle="false" id="header" data-position="fixed" class="ui-grid-b header-breakpoint headerbtn">
<a href="#panel" style="margin-left: -12px; padding-top: 2px;" id="headermenubtn"><i class="fa fa-align-justify"></i></a> <a href="#panel" style="margin-left: -12px; padding-top: 2px;" id="headermenubtn"><i class="fa fa-align-justify"></i></a>
<<<<<<< HEAD
<h1 id="contentHeadline" >Musicbox</h1> <h1 id="contentHeadline" >Musicbox</h1>
=======
<h1 id="contentHeadline">Musicbox</h1>
>>>>>>> develop
<a id="headersearchbtn" href="#" class="ui-btn-icon-right headerbtn" onclick="switchContent('search' ); return false;"> <a id="headersearchbtn" href="#" class="ui-btn-icon-right headerbtn" onclick="switchContent('search' ); return false;">
<i class="fa fa-search"></i></a> <i class="fa fa-search"></i></a>
</div> </div>
<!-- /header --> <!-- /header -->
<div data-role="content" id="homepane" class="pane"> <div data-role="content" id="homepane" class="pane">
<<<<<<< HEAD
<div id="homerows" class="ui-grid-c ui-responsive"> <div id="homerows" class="ui-grid-c ui-responsive">
<a href="#nowPlaying" onclick="switchContent('nowPlaying' ); return false;"> <a href="#nowPlaying" onclick="switchContent('nowPlaying' ); return false;">
<div class="ui-block-a"> <div class="ui-block-a">
<i class="fa fa-music"></i> <i class="fa fa-music"></i>
<h5>Now Playing</h5> <h5>Now Playing</h5>
=======
<div id="homerows" class="ui-grid-a ui-responsive">
<a href="#nowPlaying" onclick="switchContent('nowPlaying' ); return false;">
<div class="ui-block-a">
<i class="fa fa-music"></i>
<h4>Now Playing</h4>
>>>>>>> develop
</div> </div>
</a> </a>
<a href="#current" onclick="switchContent('current' ); return false;"> <a href="#current" onclick="switchContent('current' ); return false;">
<div class="ui-block-b"> <div class="ui-block-b">
<i class="fa fa-bars"></i> <i class="fa fa-bars"></i>
<<<<<<< HEAD
<h5>Queue</h5> <h5>Queue</h5>
</div> </div>
</a> </a>
@ -256,6 +289,45 @@
<div class="ui-block-d"> <div class="ui-block-d">
<i class="fa fa-power-off"></i> <i class="fa fa-power-off"></i>
<h5>System</h5> <h5>System</h5>
=======
<h4>Queue</h4>
</div>
</a>
<a href="#playlists" onclick="switchContent('playlists' ); return false;">
<div class="ui-block-a">
<i class="fa fa-star"></i>
<h4>Playlists</h4>
</div>
</a>
<a href="#browse" onclick="switchContent('browse' ); return false;">
<div class="ui-block-b">
<i class="fa fa-folder"></i>
<h4>Browse</h4>
</div>
</a>
<a href="#stream" onclick="switchContent('stream' ); return false;">
<div class="ui-block-a">
<i class="fa fa-rss"></i>
<h4>Streams</h4>
</div>
</a>
<a href="#search" onclick="switchContent('search' ); return false;">
<div class="ui-block-b">
<i class="fa fa-search"></i>
<h4>Search</h4>
</div>
</a>
<a id="homesettings" href="/settings/">
<div class="ui-block-a">
<i class="fa fa-gear"></i>
<h4>Settings</h4>
</div>
</a>
<a id="homeshutdown" href="system.html">
<div class="ui-block-b">
<i class="fa fa-power-off"></i>
<h4>System</h4>
>>>>>>> develop
</div> </div>
</a> </a>
@ -429,26 +501,13 @@
</div> </div>
</div> </div>
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="nowPlayingFooter"> <div data-role="footer" data-tap-toggle="false" data-position="fixed" id="nowPlayingFooter">
<!-- <p id="buttons">
<select name="flip-random" id="flip-random" data-role="slider" data-mini="true" >
<option value="off">Shuffle</option>
<option value="on">Shuffle</option>
</select>
<select name="flip-repeat" id="flip-repeat" data-role="slider" data-mini="true">
<option value="off">Repeat</option>
<option value="on">Repeat</option>
</select>
</p> -->
<!--&nbsp; <a href="#" onclick="doShuffle(); return false" title="Shuffle"><img src="images/icons/fork_21x24.png"--> <!--&nbsp; <a href="#" onclick="doShuffle(); return false" title="Shuffle"><img src="images/icons/fork_21x24.png"-->
<!--id="shufflebt" alt=""/></a>--> <!--id="shufflebt" alt=""/></a>-->
<p id="buttons"' style="float:right; margin-top: 20px; margin-right: 5px;"> <p id="buttons"' style="float:right; margin-top: 20px; margin-right: 5px;">
<a href="#" onclick="doRandom(); return false"><i class="fa fa-random" id="randombt"></i></a> <a href="#" onclick="doRandom(); return false"><i class="fa fa-random" id="randombt"></i></a>
&nbsp; <a href="#" onclick="doRepeat(); return false"><i class="fa fa-repeat" id="repeatbt"></i></a> &nbsp; <a href="#" onclick="doRepeat(); return false"><i class="fa fa-repeat" id="repeatbt"></i></a>
&nbsp; <a href="#" onclick="doShuffle(); return false" title="Shuffle"><i class="fa fa-code-fork" id="shufflebt"></i></a> &nbsp; <a href="#" onclick="doShuffle(); return false"><i class="fa fa-arrows-v" id="shufflebt"></i></a>
</p> </p>
<div class="nowPlayingControls" style="float:left; margin-left: 5px;"> <div class="nowPlayingControls" style="float:left; margin-left: 5px;">
@ -479,7 +538,7 @@
<script type="text/javascript" src="js/lastfm.api.js"></script> <script type="text/javascript" src="js/lastfm.api.js"></script>
<script type="text/javascript" src="js/lastfm.api.cache.js"></script> <script type="text/javascript" src="js/lastfm.api.cache.js"></script>
<script src="js/lastfm.js"></script> <script src="js/images.js"></script>
<script src="js/gui.js"></script> <script src="js/gui.js"></script>
</body> </body>

View File

@ -2,7 +2,8 @@
* play tracks from a browse list * play tracks from a browse list
*********************************************************/ *********************************************************/
function playBrowsedTracks(addtoqueue, trackid) { function playBrowsedTracks(addtoqueue, trackid) {
//stop directly, for user feedback
//stop directly, for user feedback.
if (!addtoqueue) { if (!addtoqueue) {
mopidy.playback.stop(true); mopidy.playback.stop(true);
mopidy.tracklist.clear(); mopidy.tracklist.clear();
@ -11,41 +12,42 @@ function playBrowsedTracks(addtoqueue, trackid) {
var selected = 0, counter = 0; var selected = 0, counter = 0;
var isRadio = isRadioUri(trackid); var isStream = isStreamUri(trackid);
//only add one station for dirble, otherwise add all tracks //only add one uri for dirble, tunein; otherwise add all tracks
if (isRadio) { if (isStream) {
mopidy.tracklist.add(null, null, trackid); mopidy.tracklist.add(null, null, trackid);
} else { } else {
//add selected item to the playlist //add selected item to the playlist
$('.browsetrack').each(function() { $('.browsetrack').each(function() {
if (this.id == trackid) { if (this.id == trackid) {
selected = counter; selected = counter;
} }
mopidy.tracklist.add(null, null, this.id); mopidy.tracklist.add(null, null, this.id);
counter++; counter++;
} ); });
} }
//play selected item //play selected item
if (!addtoqueue) { if (!addtoqueue) {
for (var i = 0; i <= selected; i++) { mopidy.playback.stop();
mopidy.playback.next(); for (var i = 0; i <= selected; i++) {
} mopidy.playback.next();
}
mopidy.playback.play(); //tracks[selected]); mopidy.playback.play(); //tracks[selected]);
} }
//add all items, but selected to the playlist //add all items, but selected to the playlist
selected = 0; selected = 0;
counter = 0 counter = 0
/* if(!isRadio) { /* if(!isStream) {
$('.browsetrack').each(function() { $('.browsetrack').each(function() {
//do not add selected song again //do not add selected song again
if (this.id == trackid) { if (this.id == trackid) {
selected = counter; selected = counter;
} else { } else {
mopidy.tracklist.add(null, counter, this.id); mopidy.tracklist.add(null, counter, this.id);
} }
counter++; counter++;
} ); } );
} }
*/ */
@ -57,8 +59,17 @@ function playBrowsedTracks(addtoqueue, trackid) {
* play an uri from a tracklist * play an uri from a tracklist
*********************************************************/ *********************************************************/
function playTrack(addtoqueue) { function playTrack(addtoqueue) {
//stop directly, for user feedback var hash = document.location.hash.split('?');
var divid = hash[0].substr(1);
if (!addtoqueue) { if (!addtoqueue) {
addtoqueue = PLAY_NOW;
}
// console.log(addtoqueue, divid);
//stop directly, for user feedback. If searchresults, also clear queue
if (!addtoqueue || ((addtoqueue == PLAY_NOW) && (divid == 'search'))) {
mopidy.playback.stop(true); mopidy.playback.stop(true);
mopidy.tracklist.clear(); mopidy.tracklist.clear();
} }
@ -74,22 +85,28 @@ function playTrack(addtoqueue) {
var track, tracksbefore, tracksafter; var track, tracksbefore, tracksafter;
var tracks = getTracksFromUri(playlisturi); var tracks = getTracksFromUri(playlisturi);
//find track that was selected //find track that was selected
for (var selected = 0; selected < tracks.length; selected++) { for (var selected = 0; selected < tracks.length; selected++) {
if (tracks[selected].uri == uri) { if (tracks[selected].uri == uri) {
break; break;
} }
} }
//find track that is playing //find track that is playing
for (var playing = 0; playing < currentplaylist.length; playing++) { for (var playing = 0; playing < currentplaylist.length; playing++) {
if (currentplaylist[playing].uri == songdata.uri) { if (currentplaylist[playing].uri == songdata.uri) {
break; break;
} }
} }
//switch popup options //switch popup options
switch (addtoqueue) { switch (addtoqueue) {
case PLAY_NOW:
if (divid == 'search') {
mopidy.tracklist.add(tracks.slice(selected, selected + 1));
mopidy.playback.play();
return false;
}
case ADD_THIS_BOTTOM: case ADD_THIS_BOTTOM:
mopidy.tracklist.add(tracks.slice(selected, selected + 1)); mopidy.tracklist.add(tracks.slice(selected, selected + 1));
return false; return false;
@ -100,49 +117,41 @@ function playTrack(addtoqueue) {
mopidy.tracklist.add(tracks); mopidy.tracklist.add(tracks);
return false; return false;
} }
// PLAY_NOW, play the selected track
// mopidy.tracklist.add(null, null, uri); //tracks);
mopidy.tracklist.add(tracks);
//normal if (!addtoqueue) {
// mopidy.tracklist.add(tracks); mopidy.playback.stop();
for (var i = 0; i <= selected; i++) {
//test mopidy.tracklist.add(null, 0, playlisturi); mopidy.playback.next();
}
// first add track to be played, then the other tracks mopidy.playback.play();
mopidy.tracklist.add(tracks.slice(selected, selected + 1) );
// // mopidy.playback.changeTrack(tracks[selected]);
// mopidy.tracklist.add(tracks.slice(selected, selected + 1) );
// //wait 2.5 seconds before adding the rest to give server the time to start playing
// setTimeout(function() {
// mopidy.tracklist.add(tracks.slice(0, selected), 0);
// if (selected < tracks.length) {
// mopidy.tracklist.add(tracks.slice(selected + 1) );
// }
// }, 2500);
if (!addtoqueue) {
for (var i = 0; i <= selected; i++) {
mopidy.playback.next();
}
mopidy.playback.play(); //tracks[selected]);
} }
mopidy.tracklist.add(tracks.slice(0, selected), 0);
if (selected < tracks.length) {
mopidy.tracklist.add(tracks.slice(selected + 1) );
}
//console.log(selected);
return false; return false;
} }
/*** /***
* Plays a Track given by an URI * Plays a Track given by an URI from the given playlist URI.
* @param uri * @param track_uri, playlist_uri
* @returns {boolean} * @returns {boolean}
*/ */
function playTrackByUri(uri, playlisturi){ function playTrackByUri(track_uri, playlist_uri) {
//console.log('playuri'); function findAndPlayTrack(tltracks) {
//stop directly, for user feedback // console.log('fa', tltracks, track_uri);
if (tltracks == []) { return;}
// Find track that was selected
for (var selected = 0; selected < tltracks.length; selected++) {
if (tltracks[selected].track.uri == track_uri) {
mopidy.playback.play(tltracks[selected]);
return;
}
}
console.log('Failed to play selected track ', track_uri);
}
// Stop directly, for user feedback
mopidy.playback.stop(true); mopidy.playback.stop(true);
mopidy.tracklist.clear(); mopidy.tracklist.clear();
@ -153,32 +162,18 @@ function playTrackByUri(uri, playlisturi){
toast('Loading...'); toast('Loading...');
var trackslist = new Array(); var func;
var track, tracksbefore, tracksafter; func = mopidy.tracklist.add(null, null, playlist_uri);
var tracks = getTracksFromUri(playlisturi); func.then(
function(tltracks) {
//find track that was selected //check if tltracks is filled, some backends (gmusic) do not support adding by uri, it seems
for (var selected = 0; selected < tracks.length; selected++) { if (tltracks.length == 0) {
if (tracks[selected].uri == uri) { var tracks = getTracksFromUri(playlist_uri);
break; mopidy.tracklist.add(tracks).then(findAndPlayTrack);
}
findAndPlayTrack(tltracks);
} }
} ).then(getCurrentPlaylist()); // Updates some state
//find track that is playing
for (var playing = 0; playing < currentplaylist.length; playing++) {
if (currentplaylist[playing].uri == songdata.uri) {
break;
}
}
mopidy.tracklist.add(tracks);
for (var i = 0; i <= selected; i++) {
mopidy.playback.next();
}
mopidy.playback.play(); //tracks[selected]);
// console.log(selected);
return false; return false;
} }
@ -192,27 +187,24 @@ function playTrackByUri(uri, playlisturi){
* @param playlisturi * @param playlisturi
* @returns {boolean} * @returns {boolean}
*/ */
function playTrackQueueByUri(uri, playlisturi){ function playTrackQueueByUri(uri, playlisturi) {
//console.log('playqu'); // console.log('playquuri');
//stop directly, for user feedback //stop directly, for user feedback
//console.log('qu');
mopidy.playback.stop(true); mopidy.playback.stop(true);
$('#popupQueue').popup('close'); $('#popupQueue').popup('close');
toast('Loading...'); toast('Loading...');
var track; mopidy.tracklist.filter({
for (var i = 0; i < currentplaylist.length; i++) { 'uri': [uri]
if (currentplaylist[i].uri == uri) { }).then(
track = i + 1; function(tltracks) {
break; if (tltracks.length > 0) {
mopidy.playback.play(tltracks[0]);
return;
}
console.log('Failed to play selected track ', uri);
} }
} );
for (var i = 0; i < track; i++) {
mopidy.playback.next();
}
mopidy.playback.play(); //currentplaylist[track]);
//console.log(track, currentplaylist[track]);
return false; return false;
} }
@ -221,9 +213,10 @@ function playTrackQueueByUri(uri, playlisturi){
* @returns {boolean} * @returns {boolean}
*/ */
function playTrackQueue() { function playTrackQueue() {
// console.log('playqu');
playlisturi = $('#popupQueue').data("list"); playlisturi = $('#popupQueue').data("list");
uri = $('#popupQueue').data("track"); uri = $('#popupQueue').data("track");
return playTrackByUri(uri, playlisturi); return playTrackQueueByUri(uri, playlisturi);
} }
/******************************************************** /********************************************************
@ -242,9 +235,9 @@ function removeTrack() {
} }
} }
var track = {}; var track = {};
track.uri = currentplaylist[i].uri; track.uri = [currentplaylist[i].uri];
mopidy.tracklist.remove(track); mopidy.tracklist.remove(track);
console.log(currentplaylist[i].uri); // console.log(currentplaylist[i].uri);
} }
function clearQueue() { function clearQueue() {
@ -312,9 +305,9 @@ function setRepeat(nwrepeat) {
return return
} }
if (!nwrepeat) { if (!nwrepeat) {
$("#repeatbt").attr('style', 'color:#7cc4e7'); $("#repeatbt").attr('style', 'color:#2489ce');
} else { } else {
$("#repeatbt").attr('style', 'color:#66FF33'); $("#repeatbt").attr('style', 'color:#66DD33');
} }
repeat = nwrepeat; repeat = nwrepeat;
} }
@ -324,26 +317,26 @@ function setRandom(nwrandom) {
return return
} }
if (!nwrandom) { if (!nwrandom) {
$("#randombt").attr('style', 'color:#7cc4e7'); $("#randombt").attr('style', 'color:#2489ce');
} else { } else {
$("#randombt").attr('style', 'color:#66FF33'); $("#randombt").attr('style', 'color:#66DD33');
} }
random = nwrandom; random = nwrandom;
} }
function doRandom() { function doRandom() {
if (random == false) { if (random == false) {
//check for mopidy 0.16.x or higher //check for mopidy 0.16.x or higher
if (mopidy.tracklist.setRandom) { if (mopidy.tracklist.setRandom) {
mopidy.tracklist.setRandom(true).then(); mopidy.tracklist.setRandom(true).then();
} else { } else {
mopidy.playback.setRandom(true).then(); mopidy.playback.setRandom(true).then();
} }
} else { } else {
//check for mopidy 0.16.x or higher //check for mopidy 0.16.x or higher
if (mopidy.tracklist.setRandom) { if (mopidy.tracklist.setRandom) {
mopidy.tracklist.setRandom(false).then(); mopidy.tracklist.setRandom(false).then();
} else { } else {
mopidy.playback.setRandom(false).then(); mopidy.playback.setRandom(false).then();
} }
} }
@ -352,19 +345,19 @@ function doRandom() {
function doRepeat() { function doRepeat() {
if (repeat == false) { if (repeat == false) {
//check for mopidy 0.16.x or higher //check for mopidy 0.16.x or higher
if (mopidy.tracklist.setRepeat) { if (mopidy.tracklist.setRepeat) {
mopidy.tracklist.setRepeat(true).then(); mopidy.tracklist.setRepeat(true).then();
} else { } else {
mopidy.playback.setRepeat(true).then(); mopidy.playback.setRepeat(true).then();
} }
} else { } else {
//check for mopidy 0.16.x or higher //check for mopidy 0.16.x or higher
if (mopidy.tracklist.setRepeat) { if (mopidy.tracklist.setRepeat) {
mopidy.tracklist.setRepeat(false).then(); mopidy.tracklist.setRepeat(false).then();
} else { } else {
mopidy.playback.setRepeat(false).then(); mopidy.playback.setRepeat(false).then();
} }
} }
setRepeat(!repeat); setRepeat(!repeat);
} }
@ -433,10 +426,10 @@ function doSeekPos(value) {
function triggerPos() { function triggerPos() {
if (mopidy) { if (mopidy) {
posChanging = true; posChanging = true;
// mopidy.playback.pause(); // mopidy.playback.pause();
// console.log(newposition); // console.log(newposition);
mopidy.playback.seek(newposition); mopidy.playback.seek(newposition);
// mopidy.playback.resume(); // mopidy.playback.resume();
resumePosTimer(); resumePosTimer();
posChanging = false; posChanging = false;
} }
@ -526,99 +519,117 @@ function pausePosTimer() {
} }
/********************************* /*********************************
* Radio * Stream
*********************************/ *********************************/
function radioPressed(key) { function streamPressed(key) {
if (key == 13) { if (key == 13) {
addRadioUri(); playStreamUri();
return false; return false;
} }
return true; return true;
} }
function addRadioUri(name, uri) { function playStreamUri(uri) {
//value of name is based on the passing of an uri as a parameter or not //value of name is based on the passing of an uri as a parameter or not
var name = ''; var nwuri = uri || $('#streamuriinput').val().trim();
if (!uri) { var service = $('#selectstreamservice').val();
name = $('#radionameinput').val(); if (!uri && service) {
} else { nwuri = service + ':' + nwuri;
$('#radionameinput').val('');
} }
uri = uri || $('#radiouriinput').val(); if (isServiceUri(nwuri) || isStreamUri(nwuri) || validUri(nwuri)) {
if (isRadioUri(uri)) { toast('Playing...');
toast('Selecting radiostation...');
//stop directly, for user feedback //stop directly, for user feedback
mopidy.playback.stop(true); mopidy.playback.stop(true);
//hide ios/android keyboard //hide ios/android keyboard
document.activeElement.blur(); document.activeElement.blur();
$("input").blur(); $("input").blur();
clearQueue(); clearQueue();
mopidy.tracklist.add(null, 0, uri); mopidy.tracklist.add(null, null, nwuri);
mopidy.playback.play(); mopidy.playback.play();
var tmpname = name || '';
var i = 0;
//add station to list and check for doubles and add no more than 25
for (var key in radioStations) {
rs = radioStations[key];
if (i > 25) {
delete radioStations[key];
continue;
}
i++;
if (rs && rs[1] == uri) {
tmpname = name || radioStations[key][0];
delete radioStations[key];
}
}
;
$('#radionameinput').val(tmpname);
$('#radiouriinput').val(uri);
radioStations.unshift([tmpname, uri]);
saveRadioStations();
updateRadioStations();
} else { } else {
toast('No valid url!'); toast('No valid url!');
} }
return false; return false;
} }
function updateRadioStations() { function saveStreamUri() {
var i = 0;
var name = $('#streamnameinput').val().trim();
var uri = $('#streamuriinput').val().trim();
var service = $('#selectstreamservice').val();
if (service) {
uri = service + ':' + uri;
}
//add stream to list and check for doubles and add no more than 100
for (var key in streamUris) {
rs = streamUris[key];
if (i > 100) {
delete streamUris[key];
continue;
}
i++;
}
streamUris.unshift([name, uri]);
$.cookie.json = true;
$.cookie('streamUris', streamUris);
updateStreamUris();
return false;
}
function deleteStreamUri(uri) {
var i = 0;
for (var key in streamUris) {
rs = streamUris[key];
if (rs && rs[1] == uri) {
if (confirm("About to remove " + rs[0] + ". Sure?")) {
delete streamUris[key];
}
}
}
$.cookie.json = true;
$.cookie('streamUris', streamUris);
updateStreamUris();
return false;
}
function updateStreamUris() {
var tmp = ''; var tmp = '';
$('#radiostationstable').empty(); $('#streamuristable').empty();
var child = ''; var child = '';
for (var key in radioStations) { for (var key in streamUris) {
var rs = radioStations[key]; var rs = streamUris[key];
if (rs) { if (rs) {
name = rs[0] || rs[1]; name = rs[0] || rs[1];
child = '<li data-icon="delete"> <a href="#" onclick="return addRadioUri(\'' + rs[0] + '\', \'' + rs[1] + '\');">'; child = '<li><span class="ui-icon ui-icon-delete ui-icon-shadow" style="float:right; margin: .5em; margin-top: .8em;"><a href="#" onclick="return deleteStreamUri(\'' + rs[1] + '\');">&nbsp;</a></span>' +
'<i class="fa fa-rss" style="float: left; padding: .5em; padding-top: 1em;"></i>' +
' <a style="margin-left: 20px" href="#" onclick="return playStreamUri(\'' + rs[1] + '\');">';
child += '<h1>' + name + '</h1></a></li>'; child += '<h1>' + name + '</h1></a></li>';
tmp += child; tmp += child;
} }
} }
; $('#streamuristable').html(tmp);
$('#radiostationstable').html(tmp);
} }
function initRadio() { function initStreams() {
$.cookie.json = true; $.cookie.json = true;
tmpRS = $.cookie('radioStations'); tmpRS = $.cookie('streamUris');
radioStations = tmpRS || radioStations; streamUris = tmpRS || streamUris;
updateRadioStations(); updateStreamUris();
}
function saveRadioStations() {
$.cookie.json = true;
$.cookie('radioStations', radioStations);
} }
function haltSystem() { function haltSystem() {
$.post("/settings/shutdown"); $.post("/settings/shutdown");
toast('Stopping system...', 10000); toast('Stopping system...', 10000);
setTimeout(function(){window.history.back();}, 10000); setTimeout(function() {
window.history.back();
}, 10000);
} }
function rebootSystem() { function rebootSystem() {
$.post("/settings/reboot"); $.post("/settings/reboot");
toast('Rebooting...', 10000); toast('Rebooting...', 10000);
setTimeout(function(){window.history.back();}, 10000); setTimeout(function() {
window.history.back();
}, 10000);
} }

View File

@ -0,0 +1,502 @@
/**
* @author Wouter van Wijk
*
* all kinds functions and vars
*/
var baseurl = '/mopidy';
var host = window.location.hostname;
var port = window.location.port;
var wsurl = host + ':' + port + baseurl
var intv;
var socket;
var mopidy;
//values for controls
var play = false;
var random;
var repeat;
var currentVolume = -1;
var muteVolume = -1;
var volumeChanging = false;
var posChanging = false;
var posTimer;
var volumeTimer;
var seekTimer;
var initgui = true;
var currentpos = 0;
var popupData = {};
var songlength = 0;
var artistshtml = '';
var artiststext = '';
var songname = '';
var songdata = '';
var newposition = 0;
var playlisttracksScroll;
var playlistslistScroll;
//array of cached playlists (not only user-playlists, also search, artist, album-playlists)
var playlists = {};
var currentplaylist;
var customPlaylists = [];
var customTracklists = [];
var browseStack = [];
var ua = navigator.userAgent,
isMobileSafari = /Mac/.test(ua) && /Mobile/.test(ua), isMobileWebkit = /WebKit/.test(ua) && /Mobile/.test(ua), isMobile = /Mobile/.test(ua), isWebkit = /WebKit/.test(ua);
//constants
PROGRAM_NAME = 'MusicBox';
//PROGRAM_NAME = 'Mopidy';
ARTIST_TABLE = '#artiststable';
ALBUM_TABLE = '#albumstable';
PLAYLIST_TABLE = '#playlisttracks';
CURRENT_PLAYLIST_TABLE = '#currenttable';
SEARCH_ALL_TABLE = '#allresulttable';
SEARCH_ALBUM_TABLE = '#albumresulttable';
SEARCH_ARTIST_TABLE = '#artistresulttable';
SEARCH_TRACK_TABLE = '#trackresulttable';
PLAY_NOW = 0;
PLAY_NEXT = 1;
ADD_THIS_BOTTOM = 2;
ADD_ALL_BOTTOM = 3;
MAX_TABLEROWS = 50;
//update track slider timer, milliseconds
TRACK_TIMER = 1000;
//check status timer, every 5 or 10 sec
STATUS_TIMER = 10000;
// the first part of Mopidy extensions which serve radio streams
var radioExtensionsList = ['somafm', 'tunein', 'dirble'];
var uriClassList = [ ['spotify', 'fa-spotify'], ['local', 'fa-file-sound-o'], ['podcast', 'fa-rss-square'], ['dirble', 'fa-microphone'],
['tunein', 'fa-headphones'], ['soundcloud', 'fa-soundcloud'], ['sc', 'fa-soundcloud'], ['gmusic', 'fa-google'], ['internetarchive', 'fa-university'], ['somafm', 'fa-flask'], ['youtube', 'fa-youtube'], ['yt', 'fa-youtube'], ['subsonic', 'fa-folder-open'] ];
var uriHumanList = [ ['spotify', 'Spotify'], ['local', 'Local Files'], ['podcast', 'Podcasts'], ['dirble', 'Dirble'],
['tunein', 'TuneIn'], ['soundcloud', 'SoundCloud'], ['gmusic', 'Google Music'], ['internetarchive', 'Internet Archive'], ['somafm', 'Soma FM'], ['youtube', 'YouTube'], ['subsonic', 'Subsonic'] ];
var uriServiceDetectList = [['youtube.com', 'yt'], ['soundcloud.com', 'sc']];
function scrollToTop() {
var divtop = 0;
$('body,html').animate({
scrollTop : divtop
}, 250);
}
function scrollToTracklist() {
/* if (isMobileWebkit) {
playlistslistScroll.refresh();
}
*/
var divtop = $("#playlisttracksdiv").offset().top - 50;
$('body,html').animate({
scrollTop : divtop
}, 250);
}
//A hack to find the name of the first artist of a playlist. this is not yet returned by mopidy
//does not work wel with multiple artists of course
function getArtist(pl) {
for (var i = 0; i < pl.length; i++) {
for (var j = 0; j < pl[i].artists.length; j++) {
if (pl[i].artists[j].name != '') {
return pl[i].artists[j].name;
}
}
};
}
//A hack to find the first album of a playlist. this is not yet returned by mopidy
function getAlbum(pl) {
for (var i = 0; i < pl.length; i++) {
if (pl[i].album.name != '') {
return pl[i].album.name;
}
};
}
/********************************************************
* break up results and put them in album tables
*********************************************************/
function albumTracksToTable(pl, target, uri) {
var tmp = '<ul class="songsOfAlbum table" >';
var liId = '';
var targetmin = target.substr(1);
$(target).empty();
for (var i = 0; i < pl.length; i++) {
popupData[pl[i].uri] = pl[i];
liID = targetmin + '-' + pl[i].uri;
tmp += renderSongLi(pl[i], liID, uri, 'playTrackByUri');
};
tmp += '</ul>';
$(target).html(tmp);
$(target).attr('data', uri);
}
function renderSongLi(song, liID, uri, playlistType){
var name;
if (!song.name || song.name == '') {
name = uri.split('/');
name = decodeURI(name[name.length - 1]);
} else {
name = song.name;
}
// var iconClass = getMediaClass(liID.split('-')[1]);
songLi = '<li class="song albumli" id="' + liID + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + '\');">' +
'<i class="fa fa-ellipsis-v"></i>' +
'</a>' +'<a href="#" onclick="return ' + playlistType + '(\'' + song.uri + '\',\'' + uri + '\');">' +
// '<h1 class="trackname"><i class="' + iconClass + '"></i> ' + name + '</h1>' +
'<h1 class="trackname">' + name + '</h1>' +
'</a>' +
'</li>';
return songLi;
}
function resultsToTables(results, target, uri) {
if (!results) { return }
if (target == '#currenttable') {
playlistType = 'playTrackQueueByUri';
} else {
playlistType = 'playTrackByUri';
}
var newalbum = [];
//keep a list of albums for retreiving of covers
var coversList = [];
var nextname = '';
var count = 0;
$(target).html('');
//break into albums and put in tables
var html = '';
var tableid, j, artistname, alburi, name, iconClass;
var targetmin = target.substr(1);
$(target).attr('data', uri);
var length = 0 || results.length;
for ( i = 0; i < length; i++) {
//create album if none extists
if (!results[i].album) { results[i].album={}; }
//create album uri if there is none
if (!results[i].album.uri) { results[i].album.uri = 'x'; }
if (!results[i].album.name) { results[i].album.name = ''; }
//create name if there is no one
if (!results[i].name || results[i].name == '') {
name = results[i].uri.split('/');
results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i);
}
//leave out unplayable items
if (results[i].name.substring(0,12) == '[unplayable]') continue;
newalbum.push(results[i]);
nextname = '';
if ((i < length - 1) && results[i+1].album && results[i+1].album.name ) {
nextname = results[i + 1].album.name;
}
if (results[i].length == -1) {
html += '<li class="albumli"><a href="#"><h1><i class="' + iconClass + '"></i> ' + results[i].name + ' [Stream]</h1></a></li>';
newalbum = [];
nextname = '';
} else {
if ( (results[i].album.name != nextname) || (nextname == '') ) {
tableid = 'art' + i;
//render differently if only one track in the album
if ( newalbum.length == 1 ) {
if (i != 0) { html += '<li class="smalldivider"> &nbsp;</li>'; }
iconClass = getMediaClass(newalbum[0].uri);
html += '<li class="song albumli" id="' + targetmin + '-' + newalbum[0].uri + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[0].uri + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return ' + playlistType + '(\'' + newalbum[0].uri + '\',\'' + uri + '\');">' +
'<h1><i class="' + iconClass + '"></i> ' + newalbum[0].name + "</h1><p>";
/* '<span style="float: right;">' + timeFromSeconds(newalbum[0].length / 1000) + '</span>'; */
if (newalbum[0].artists) {
for ( j = 0; j < newalbum[0].artists.length; j++) {
html += newalbum[0].artists[j].name;
html += (j == newalbum[0].artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
html += '...';
break;
}
}
}
if ( newalbum[0].album.name != '') { html += ' / ';}
html += '<em>' + newalbum[0].album.name + '</em></p>';
html += '</a></li>';
popupData[newalbum[0].uri] = newalbum[0];
newalbum = [];
} else { //newalbum length
if ( results[i].album.uri && results[i].album.name ) {
// iconClass = getMediaClass(results[i].album.uri);
iconClass = getMediaClass(newalbum[0].uri);
html += '<li class="albumdivider">';
html += '<a href="#" onclick="return showAlbum(\'' + results[i].album.uri + '\');"><img id="' +
targetmin + '-cover-' + i + '" class="artistcover" width="30" height="30" /><h1><i class="' + iconClass + '"></i> ' + results[i].album.name + '</h1><p>';
}
if (results[i].album.artists) {
for (j = 0; j < results[i].album.artists.length; j++) {
html += results[i].album.artists[j].name;
html += (j == results[i].album.artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
child += '...';
break;
}
}
}
html += '</p></a></li>';
for (j = 0; j < newalbum.length; j++) {
popupData[newalbum[j].uri] = newalbum[j];
// html += '<li class="albumli" id="' + targetmin + '-' + newalbum[j].uri + '"><a href="#" onclick="return ' + popupMenu + '(event, \'' + uri + '\',\'' + newalbum[j].uri + '\');">';
//hERE!
var liID = targetmin + '-' + newalbum[j].uri;
html+= renderSongLi(newalbum[j], liID, uri, playlistType);
//html += '<li class="albumli" id="' + targetmin + '-' + newalbum[j].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[j].uri + '\');">';
//html += '<p class="pright">' + timeFromSeconds(newalbum[j].length / 1000) + '</p><h1>' + newalbum[j].name + '</h1></a></li>';
}
newalbum = [];
if (results[i].album) {
coversList.push([results[i].album, i]);
}
} //newalbum length
if (results[i].album) {
coversList.push([results[i].album, i]);
}
} //albums name
}
}
tableid = "#" + tableid;
$(target).html(html);
$(target).attr('data', uri);
//retreive albumcovers
for (i = 0; i < coversList.length; i++){
// console.log(coversList[i]);
getCover(coversList[i][0], target + '-cover-' + coversList[i][1], 'small');
}
}
//process updated playlist to gui
function playlisttotable(pl, target, uri) {
var tmp = '';
$(target).html('');
var targetmin = target.substr(1);
var child = '';
for (var i = 0; i < pl.length; i++) {
if (pl[i]) {
popupData[pl[i].uri] = pl[i];
child = '<li id="' + targetmin + '-' + pl[i].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + pl[i].uri + '\');">';
child += '<h1>' + pl[i].name + "</h1>";
child += '<p>';
child += '<span style="float: right;">' + timeFromSeconds(pl[i].length / 1000) + '</span>';
// <span class="ui-icon ui-icon-arrow-r ui-icon-shadow">&nbsp;</span>
for (var j = 0; j < pl[i].artists.length; j++) {
if (pl[i].artists[j]) {
child += pl[i].artists[j].name;
child += (j == pl[i].artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
child += '...';
break;
}
}
}
child += ' / <em>' + pl[i].album.name + '</em></p>';
child += '</a></li>';
tmp += child;
}
};
$(target).html(tmp);
$(target).attr('data', uri);
}
function getPlaylistFromUri(uri) {
if (playlists[uri]) {
return playlists[uri];
}
if (customPlaylists[uri]) {
return customPlaylists[uri];
}
}
function getTracksFromUri(uri) {
var pl = getPlaylistFromUri(uri);
if (pl) {
return pl.tracks;
} else if (customTracklists[uri]) {
return customTracklists[uri];
}
return [];
}
//convert time to human readable format
function timeFromSeconds(length) {
var d = Number(length);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
return ((h > 0 ? h + ":" : "") + (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "0:") + (s < 10 ? "0" : "") + s);
}
/******* Toast ***/
function toast (message, delay, textOnly) {
textOnl = textOnly || false;
message = message || "Loading...";
delay = delay || 1000;
$.mobile.loading( 'show', {
text: message,
textVisible: true,
theme: 'a',
textonly: textOnl
});
if(delay > 0) {
setTimeout(function(){
$.mobile.loading('hide');
}, delay);
}
}
/*****************
* Modal dialogs
*****************/
function showLoading(on) {
if (on) {
$("body").css("cursor", "progress");
$.mobile.loading('show', {
text : 'Loading data from ' + PROGRAM_NAME + '. Please wait...',
textVisible : true,
theme : 'a'
});
} else {
$("body").css("cursor", "default");
$.mobile.loading('hide');
}
}
function showOffline(on) {
if (on) {
$.mobile.loading('show', {
text : 'Trying to reach ' + PROGRAM_NAME + '. Please wait...',
textVisible : true,
theme : 'a'
});
} else {
$.mobile.loading('hide');
}
}
// from http://dzone.com/snippets/validate-url-regexp
function validUri(str) {
var regexp = /^(mms|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
// return regexp.test(str) || isServiceUri(str);
return regexp.test(str);
}
function validServiceUri(str) {
return validUri(str) || isServiceUri(str);
}
/*
$.event.special.swipe = $.extend($.event.special.swipe, {
start: function( event ) {
var data = event.originalEvent.touches ?
event.originalEvent.touches[ 0 ] : event;
return {
time: ( new Date() ).getTime(),
coords: [ data.pageX, data.pageY ],
origin: $( event.target ),
offset: $('body').scrollTop()
};
},
stop: function( event ) {
var data = event.originalEvent.touches ?
event.originalEvent.touches[ 0 ] : event;
return {
time: ( new Date() ).getTime(),
coords: [ data.pageX, data.pageY ],
offset: $('body').scrollTop()
};
alert.log('stop');
},
handleSwipe: function( start, stop ) {
var swipe = $.event.special.swipe,
x = Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ),
y = Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ),
offset = Math.abs( start.offset - stop.offset ),
time = stop.time - start.time;
if ( time < swipe.durationThreshold && x > swipe.horizontalDistanceThreshold && ( y + offset )
< swipe.verticalDistanceThreshold ) {
start.origin.trigger( "swipe" ).trigger( ( start.coords[ 0 ] - stop.coords[ 0 ] ) ? "swipeleft" : "swiperight" );
// alert(x + ' ' + y + ' ' + time + ' ' + offset + ' ' + swipe.verticalDistanceThreshold);
}
}
});
*/
function isStreamUri (uri) {
var uriSplit = uri.split(":");
var a = validUri(uri);
var b = radioExtensionsList.indexOf(uriSplit[0].toLowerCase()) >= 0;
return a || b;
}
function getMediaClass(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
for (var i = 0; i < uriClassList.length; i++) {
if (uriSplit == uriClassList[i][0]) {
return "fa " + uriClassList[i][1];
}
}
return '';
}
function getMediaHuman(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
for (var i = 0; i < uriHumanList.length; i++) {
if (uriSplit == uriHumanList[i][0]) {
return uriHumanList[i][1];
}
}
return '';
}
function isServiceUri(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
var retVal = false;
for (var i = 0; i < uriClassList.length; i++) {
if (uriSplit == uriClassList[i][0]) {
retVal = true;
}
}
for (var i = 0; i < radioExtensionsList.length; i++) {
if (uriSplit == radioExtensionsList[i]) {
retVal = true;
}
}
return retVal;
}

View File

@ -47,10 +47,10 @@ var customTracklists = [];
var browseStack = []; var browseStack = [];
var ua = navigator.userAgent, var ua = navigator.userAgent,
isMobileSafari = /Mac/.test(ua) && /Mobile/.test(ua), isMobileWebkit = /WebKit/.test(ua) && /Mobile/.test(ua), isMobile = /Mobile/.test(ua), isWebkit = /WebKit/.test(ua); isMobileSafari = /Mac/.test(ua) && /Mobile/.test(ua),
isMobileWebkit = /WebKit/.test(ua) && /Mobile/.test(ua),
// the first part of Mopidy extensions which serve radiostations (streams) isMobile = /Mobile/.test(ua),
var radioExtensionsUris = ['somafm', 'tunein', 'dirble']; isWebkit = /WebKit/.test(ua);
//constants //constants
PROGRAM_NAME = 'MusicBox'; PROGRAM_NAME = 'MusicBox';
@ -77,30 +77,63 @@ TRACK_TIMER = 1000;
//check status timer, every 5 or 10 sec //check status timer, every 5 or 10 sec
STATUS_TIMER = 10000; STATUS_TIMER = 10000;
//var uriHumanList = [ ['spotify', 'Spotify'], ['local', 'Local Files'], ['podcast', 'Podcasts'], ['dirble', 'Dirble'], // the first part of Mopidy extensions which serve radio streams
// ['tunein', 'TuneIn'], ['soundcloud', 'SoundCloud'], ['sc', 'SoundCloud'], ['gmusic', 'Google Music'], ['internetarchive', 'Internet Archive'], ['somafm', 'Soma FM'], ['yt', 'YouTube'], ['youtube', 'YouTube'], ['subsonic', 'Subsonic'] ]; var radioExtensionsList = ['somafm', 'tunein', 'dirble', 'audioaddict'];
var uriClassList = [ ['spotify', 'fa-spotify'], ['local', 'fa-file-sound-o'], ['podcast', 'fa-rss-square'], ['dirble', 'fa-microphone'], var uriClassList = [
['tunein', 'fa-headphones'], ['soundcloud', 'fa-soundcloud'], ['sc', 'fa-soundcloud'], ['gmusic', 'fa-google'], ['internetarchive', 'fa-university'], ['somafm', 'fa-flask'], ['youtube', 'fa-youtube'], ['yt', 'fa-youtube'], ['subsonic', 'fa-folder-open'] ]; ['spotify', 'fa-spotify'],
['spotifytunigo', 'fa-spotify'],
['local', 'fa-file-sound-o'],
['podcast', 'fa-rss-square'],
['dirble', 'fa-microphone'],
['tunein', 'fa-headphones'],
['soundcloud', 'fa-soundcloud'],
['sc', 'fa-soundcloud'],
['gmusic', 'fa-google'],
['internetarchive', 'fa-university'],
['somafm', 'fa-flask'],
['youtube', 'fa-youtube'],
['yt', 'fa-youtube'],
['audioaddict', 'fa-bullhorn'],
['subsonic', 'fa-folder-open']
];
var uriHumanList = [ ['spotify', 'Spotify'], ['local', 'Local Files'], ['podcast', 'Podcasts'], ['dirble', 'Dirble'], var uriHumanList = [
['tunein', 'TuneIn'], ['soundcloud', 'SoundCloud'], ['gmusic', 'Google Music'], ['internetarchive', 'Internet Archive'], ['somafm', 'Soma FM'], ['youtube', 'YouTube'], ['subsonic', 'Subsonic'] ]; ['spotify', 'Spotify'],
['spotifytunigo', 'Spotify Browse'],
['local', 'Local Files'],
['podcast', 'Podcasts'],
['dirble', 'Dirble'],
['tunein', 'TuneIn'],
['soundcloud', 'SoundCloud'],
['gmusic', 'Google Music'],
['internetarchive', 'Internet Archive'],
['somafm', 'Soma FM'],
['youtube', 'YouTube'],
['audioaddict', 'AudioAddict'],
['subsonic', 'Subsonic']
];
var uriServiceDetectList = [
['youtube.com', 'yt'],
['soundcloud.com', 'sc']
];
function scrollToTop() { function scrollToTop() {
var divtop = 0; var divtop = 0;
$('body,html').animate({ $('body,html').animate({
scrollTop : divtop scrollTop: divtop
}, 250); }, 250);
} }
function scrollToTracklist() { function scrollToTracklist() {
/* if (isMobileWebkit) { /* if (isMobileWebkit) {
playlistslistScroll.refresh(); playlistslistScroll.refresh();
} }
*/ */
var divtop = $("#playlisttracksdiv").offset().top - 50; var divtop = $("#playlisttracksdiv").offset().top - 50;
$('body,html').animate({ $('body,html').animate({
scrollTop : divtop scrollTop: divtop
}, 250); }, 250);
} }
@ -137,46 +170,48 @@ function albumTracksToTable(pl, target, uri) {
popupData[pl[i].uri] = pl[i]; popupData[pl[i].uri] = pl[i];
liID = targetmin + '-' + pl[i].uri; liID = targetmin + '-' + pl[i].uri;
tmp += renderSongLi(pl[i], liID, uri, 'playTrackByUri'); tmp += renderSongLi(pl[i], liID, uri, 'playTrackByUri');
//child = '<li id="' + targetmin + '-' + pl[i].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + pl[i].uri + '\');">';
// child += '<p style="float:right; display: inline;">' + timeFromSeconds(pl[i].length / 1000) + '</p><h1>' + pl[i].name + '</h1></a></li>';
}; };
tmp += '</ul>'; tmp += '</ul>';
$(target).html(tmp); $(target).html(tmp);
$(target).attr('data', uri); $(target).attr('data', uri);
} }
function renderSongLi(song, liID, uri, playlistType){ function renderSongLi(song, liID, uri, playlistType) {
var name; var name;
if (!song.name || song.name == '') { if (!song.name || song.name == '') {
name = uri.split('/'); name = uri.split('/');
name = decodeURI(name[name.length - 1]); name = decodeURI(name[name.length - 1]);
} else { } else {
name = song.name; name = song.name;
} }
// var iconClass = getMediaClass(liID.split('-')[1]); // var iconClass = getMediaClass(liID.split('-')[1]);
songLi = '<li class="song albumli" id="' + liID + '">' + songLi = '<li class="song albumli" id="' + liID + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + '\');">' + '<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + '\');">' +
'<i class="fa fa-ellipsis-v"></i>' + '<i class="fa fa-ellipsis-v"></i>' +
'</a>' +'<a href="#" onclick="return ' + playlistType + '(\'' + song.uri + '\',\'' + uri + '\');">' + '</a>' + '<a href="#" onclick="return ' + playlistType + '(\'' + song.uri + '\',\'' + uri + '\');">' +
// '<h1 class="trackname"><i class="' + iconClass + '"></i> ' + name + '</h1>' + // '<h1 class="trackname"><i class="' + iconClass + '"></i> ' + name + '</h1>' +
'<h1 class="trackname">' + name + '</h1>' + '<h1 class="trackname">' + name + '</h1>' +
'</a>' + '</a>' +
'</li>'; '</li>';
return songLi; return songLi;
} }
function resultsToTables(results, target, uri) { function resultsToTables(results, target, uri) {
if (!results) { return } if (!results) {
return
}
if (target == '#currenttable') { if (target == '#currenttable') {
playlistType = 'playTrackQueueByUri'; playlistType = 'playTrackQueueByUri';
} else if (target == SEARCH_TRACK_TABLE) {
playlistType = 'playTrackByUri';
} else { } else {
playlistType = 'playTrackByUri'; playlistType = 'playTrackByUri';
} }
var newalbum = []; var newalbum = [];
//keep a list of albums for retreiving of covers
var coversList = [];
var nextname = ''; var nextname = '';
var count = 0; var count = 0;
$(target).html(''); $(target).html('');
@ -187,103 +222,120 @@ function resultsToTables(results, target, uri) {
var targetmin = target.substr(1); var targetmin = target.substr(1);
$(target).attr('data', uri); $(target).attr('data', uri);
var length = 0 || results.length; var length = 0 || results.length;
for ( i = 0; i < length; i++) { for (i = 0; i < length; i++) {
//create album if none extists //create album if none extists
if (!results[i].album) { results[i].album={}; } if (!results[i].album) {
//create album uri if there is none results[i].album = {};
if (!results[i].album.uri) { results[i].album.uri = 'x'; } }
if (!results[i].album.name) { results[i].album.name = ''; } //create album uri if there is none
//create name if there is no one if (!results[i].album.uri) {
results[i].album.uri = 'x';
}
if (!results[i].album.name) {
results[i].album.name = '';
}
//create name if there is no one
if (!results[i].name || results[i].name == '') { if (!results[i].name || results[i].name == '') {
name = results[i].uri.split('/'); name = results[i].uri.split('/');
results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i); results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i);
} }
//leave out unplayable items //leave out unplayable items
if (results[i].name.substring(0,12) == '[unplayable]') continue; if (results[i].name.substring(0, 12) == '[unplayable]') continue;
newalbum.push(results[i]); newalbum.push(results[i]);
nextname = ''; nextname = '';
if ((i < length - 1) && results[i+1].album && results[i+1].album.name ) { if ((i < length - 1) && results[i + 1].album && results[i + 1].album.name) {
nextname = results[i + 1].album.name; nextname = results[i + 1].album.name;
} }
if (results[i].length == -1) { if (results[i].length == -1) {
html += '<li class="albumli"><a href="#"><h1><i class="' + iconClass + '"></i> ' + results[i].name + ' [Stream]</h1></a></li>'; html += '<li class="albumli"><a href="#"><h1><i class="' + iconClass + '"></i> ' + results[i].name + ' [Stream]</h1></a></li>';
newalbum = []; newalbum = [];
nextname = ''; nextname = '';
} else { } else {
if ( (results[i].album.name != nextname) || (nextname == '') ) { if ((results[i].album.name != nextname) || (nextname == '')) {
tableid = 'art' + i; tableid = 'art' + i;
//render differently if only one track in the album //render differently if only one track in the album
if ( newalbum.length == 1 ) { if (newalbum.length == 1) {
if (i != 0) { html += '<li class="smalldivider"> &nbsp;</li>'; } if (i != 0) {
iconClass = getMediaClass(newalbum[0].uri); html += '<li class="smalldivider"> &nbsp;</li>';
html += '<li class="song albumli" id="' + targetmin + '-' + newalbum[0].uri + '">' + }
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[0].uri + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return ' + playlistType + '(\'' + newalbum[0].uri + '\',\'' + uri + '\');">' +
'<h1><i class="' + iconClass + '"></i> ' + newalbum[0].name + "</h1><p>";
/* '<span style="float: right;">' + timeFromSeconds(newalbum[0].length / 1000) + '</span>'; */
if (newalbum[0].artists) {
for ( j = 0; j < newalbum[0].artists.length; j++) {
html += newalbum[0].artists[j].name;
html += (j == newalbum[0].artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
html += '...';
break;
}
}
}
if ( newalbum[0].album.name != '') { html += ' / ';}
html += '<em>' + newalbum[0].album.name + '</em></p>';
html += '</a></li>';
popupData[newalbum[0].uri] = newalbum[0];
newalbum = [];
} else { //newalbum length
if ( results[i].album.uri && results[i].album.name ) {
// iconClass = getMediaClass(results[i].album.uri);
iconClass = getMediaClass(newalbum[0].uri); iconClass = getMediaClass(newalbum[0].uri);
html += '<li class="albumdivider">'; html += '<li class="song albumli" id="' + targetmin + '-' + newalbum[0].uri + '">' +
html += '<a href="#" onclick="return showAlbum(\'' + results[i].album.uri + '\');"><img id="' + '<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[0].uri + '\');">' +
targetmin + '-cover-' + i + '" class="artistcover" width="30" height="30" /><h1><i class="' + iconClass + '"></i> ' + results[i].album.name + '</h1><p>'; '<i class="fa fa-ellipsis-v"></i></a>' +
} '<a href="#" onclick="return ' + playlistType + '(\'' + newalbum[0].uri + '\',\'' + uri + '\');">' +
if (results[i].album.artists) { '<h1><i class="' + iconClass + '"></i> ' + newalbum[0].name + "</h1><p>";
for (j = 0; j < results[i].album.artists.length; j++) { /* '<span style="float: right;">' + timeFromSeconds(newalbum[0].length / 1000) + '</span>'; */
html += results[i].album.artists[j].name; if (newalbum[0].artists) {
html += (j == results[i].album.artists.length - 1) ? '' : ' / '; for (j = 0; j < newalbum[0].artists.length; j++) {
//stop after 3 html += newalbum[0].artists[j].name;
if (j > 2) { html += (j == newalbum[0].artists.length - 1) ? '' : ' / ';
child += '...'; //stop after 3
break; if (j > 2) {
html += '...';
break;
}
} }
} }
} if (newalbum[0].album.name != '') {
html += '</p></a></li>'; html += ' / ';
for (j = 0; j < newalbum.length; j++) { }
popupData[newalbum[j].uri] = newalbum[j]; html += '<em>' + newalbum[0].album.name + '</em></p>';
// html += '<li class="albumli" id="' + targetmin + '-' + newalbum[j].uri + '"><a href="#" onclick="return ' + popupMenu + '(event, \'' + uri + '\',\'' + newalbum[j].uri + '\');">'; html += '</a></li>';
//hERE! popupData[newalbum[0].uri] = newalbum[0];
var liID = targetmin + '-' + newalbum[j].uri; newalbum = [];
html+= renderSongLi(newalbum[j], liID, uri, playlistType); } else { //newalbum length
if (results[i].album.uri && results[i].album.name) {
// iconClass = getMediaClass(results[i].album.uri);
iconClass = getMediaClass(newalbum[0].uri);
html += '<li class="albumdivider">';
html += '<a href="#" onclick="return showAlbum(\'' + results[i].album.uri + '\');"><img id="' +
targetmin + '-cover-' + i + '" class="artistcover" width="30" height="30" /><h1><i class="' + iconClass + '"></i> ' + results[i].album.name + '</h1><p>';
}
if (results[i].album.artists) {
for (j = 0; j < results[i].album.artists.length; j++) {
html += results[i].album.artists[j].name;
html += (j == results[i].album.artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
child += '...';
break;
}
}
}
html += '</p></a></li>';
for (j = 0; j < newalbum.length; j++) {
popupData[newalbum[j].uri] = newalbum[j];
// html += '<li class="albumli" id="' + targetmin + '-' + newalbum[j].uri + '"><a href="#" onclick="return ' + popupMenu + '(event, \'' + uri + '\',\'' + newalbum[j].uri + '\');">';
//html += '<li class="albumli" id="' + targetmin + '-' + newalbum[j].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[j].uri + '\');">'; //hERE!
//html += '<p class="pright">' + timeFromSeconds(newalbum[j].length / 1000) + '</p><h1>' + newalbum[j].name + '</h1></a></li>'; var liID = targetmin + '-' + newalbum[j].uri;
html += renderSongLi(newalbum[j], liID, uri, playlistType);
//html += '<li class="albumli" id="' + targetmin + '-' + newalbum[j].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[j].uri + '\');">';
//html += '<p class="pright">' + timeFromSeconds(newalbum[j].length / 1000) + '</p><h1>' + newalbum[j].name + '</h1></a></li>';
}
newalbum = [];
if (results[i].album) {
coversList.push([results[i].album, i]);
}
} //newalbum length
if (results[i].album) {
coversList.push([results[i].album, i]);
} }
; } //albums name
artistname = results[i].artists[0].name;
getCover(artistname, results[i].album.name, target + '-cover-' + i, 'small');
// customTracklists[results[i].album.uri] = newalbum;
newalbum = [];
} //newalbum length
} //albums name
} }
} }
tableid = "#" + tableid; tableid = "#" + tableid;
$(target).html(html); $(target).html(html);
$(target).attr('data', uri); $(target).attr('data', uri);
//retreive albumcovers
for (i = 0; i < coversList.length; i++) {
// console.log(coversList[i]);
getCover(coversList[i][0], target + '-cover-' + coversList[i][1], 'small');
}
} }
//process updated playlist to gui //process updated playlist to gui
@ -293,28 +345,28 @@ function playlisttotable(pl, target, uri) {
var targetmin = target.substr(1); var targetmin = target.substr(1);
var child = ''; var child = '';
for (var i = 0; i < pl.length; i++) { for (var i = 0; i < pl.length; i++) {
if (pl[i]) { if (pl[i]) {
popupData[pl[i].uri] = pl[i]; popupData[pl[i].uri] = pl[i];
child = '<li id="' + targetmin + '-' + pl[i].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + pl[i].uri + '\');">'; child = '<li id="' + targetmin + '-' + pl[i].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + pl[i].uri + '\');">';
child += '<h1>' + pl[i].name + "</h1>"; child += '<h1>' + pl[i].name + "</h1>";
child += '<p>'; child += '<p>';
child += '<span style="float: right;">' + timeFromSeconds(pl[i].length / 1000) + '</span>'; child += '<span style="float: right;">' + timeFromSeconds(pl[i].length / 1000) + '</span>';
// <span class="ui-icon ui-icon-arrow-r ui-icon-shadow">&nbsp;</span> // <span class="ui-icon ui-icon-arrow-r ui-icon-shadow">&nbsp;</span>
for (var j = 0; j < pl[i].artists.length; j++) { for (var j = 0; j < pl[i].artists.length; j++) {
if (pl[i].artists[j]) { if (pl[i].artists[j]) {
child += pl[i].artists[j].name; child += pl[i].artists[j].name;
child += (j == pl[i].artists.length - 1) ? '' : ' / '; child += (j == pl[i].artists.length - 1) ? '' : ' / ';
//stop after 3 //stop after 3
if (j > 2) { if (j > 2) {
child += '...'; child += '...';
break; break;
} }
} }
} }
child += ' / <em>' + pl[i].album.name + '</em></p>'; child += ' / <em>' + pl[i].album.name + '</em></p>';
child += '</a></li>'; child += '</a></li>';
tmp += child; tmp += child;
} }
}; };
$(target).html(tmp); $(target).html(tmp);
@ -351,18 +403,18 @@ function timeFromSeconds(length) {
/******* Toast ***/ /******* Toast ***/
function toast (message, delay, textOnly) { function toast(message, delay, textOnly) {
textOnl = textOnly || false; textOnl = textOnly || false;
message = message || "Loading..."; message = message || "Loading...";
delay = delay || 1000; delay = delay || 1000;
$.mobile.loading( 'show', { $.mobile.loading('show', {
text: message, text: message,
textVisible: true, textVisible: true,
theme: 'a', theme: 'a',
textonly: textOnl textonly: textOnl
}); });
if(delay > 0) { if (delay > 0) {
setTimeout(function(){ setTimeout(function() {
$.mobile.loading('hide'); $.mobile.loading('hide');
}, delay); }, delay);
} }
@ -375,9 +427,9 @@ function showLoading(on) {
if (on) { if (on) {
$("body").css("cursor", "progress"); $("body").css("cursor", "progress");
$.mobile.loading('show', { $.mobile.loading('show', {
text : 'Loading data from ' + PROGRAM_NAME + '. Please wait...', text: 'Loading data from ' + PROGRAM_NAME + '. Please wait...',
textVisible : true, textVisible: true,
theme : 'a' theme: 'a'
}); });
} else { } else {
$("body").css("cursor", "default"); $("body").css("cursor", "default");
@ -388,9 +440,9 @@ function showLoading(on) {
function showOffline(on) { function showOffline(on) {
if (on) { if (on) {
$.mobile.loading('show', { $.mobile.loading('show', {
text : 'Trying to reach ' + PROGRAM_NAME + '. Please wait...', text: 'Trying to reach ' + PROGRAM_NAME + '. Please wait...',
textVisible : true, textVisible: true,
theme : 'a' theme: 'a'
}); });
} else { } else {
$.mobile.loading('hide'); $.mobile.loading('hide');
@ -401,9 +453,14 @@ function showOffline(on) {
// from http://dzone.com/snippets/validate-url-regexp // from http://dzone.com/snippets/validate-url-regexp
function validUri(str) { function validUri(str) {
var regexp = /^(mms|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ var regexp = /^(mms|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
// return regexp.test(str) || isServiceUri(str);
return regexp.test(str); return regexp.test(str);
} }
function validServiceUri(str) {
return validUri(str) || isServiceUri(str);
}
/* /*
$.event.special.swipe = $.extend($.event.special.swipe, { $.event.special.swipe = $.extend($.event.special.swipe, {
start: function( event ) { start: function( event ) {
@ -425,7 +482,7 @@ $.event.special.swipe = $.extend($.event.special.swipe, {
coords: [ data.pageX, data.pageY ], coords: [ data.pageX, data.pageY ],
offset: $('body').scrollTop() offset: $('body').scrollTop()
}; };
alert.log('stop'); alert.log('stop');
}, },
handleSwipe: function( start, stop ) { handleSwipe: function( start, stop ) {
@ -439,16 +496,16 @@ $.event.special.swipe = $.extend($.event.special.swipe, {
start.origin.trigger( "swipe" ).trigger( ( start.coords[ 0 ] - stop.coords[ 0 ] ) ? "swipeleft" : "swiperight" ); start.origin.trigger( "swipe" ).trigger( ( start.coords[ 0 ] - stop.coords[ 0 ] ) ? "swipeleft" : "swiperight" );
// alert(x + ' ' + y + ' ' + time + ' ' + offset + ' ' + swipe.verticalDistanceThreshold); // alert(x + ' ' + y + ' ' + time + ' ' + offset + ' ' + swipe.verticalDistanceThreshold);
} }
} }
}); });
*/ */
function isRadioUri (uri) { function isStreamUri(uri) {
var uriSplit = uri.split(":"); var uriSplit = uri.split(":");
var a = validUri(uri); var a = validUri(uri);
var b = radioExtensionsUris.indexOf(uriSplit[0].toLowerCase()) >= 0; var b = radioExtensionsList.indexOf(uriSplit[0].toLowerCase()) >= 0;
return a || b; return a || b;
} }
@ -472,3 +529,21 @@ function getMediaHuman(uri) {
return ''; return '';
} }
function isServiceUri(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
var retVal = false;
for (var i = 0; i < uriClassList.length; i++) {
if (uriSplit == uriClassList[i][0]) {
retVal = true;
}
}
for (var i = 0; i < radioExtensionsList.length; i++) {
if (uriSplit == radioExtensionsList[i]) {
retVal = true;
}
}
return retVal;
}

View File

@ -24,6 +24,13 @@ function resizeMb() {
$("#infoname").html(songdata.name); $("#infoname").html(songdata.name);
$("#infoartist").html(artiststext); $("#infoartist").html(artiststext);
if ($(window).width() <= 960) {
// $('#playlisttracksdiv').hide();
// $('#playlistslistdiv').show();
} else {
$('#playlisttracksdiv').show();
$('#playlistslistdiv').show();
}
// //set height of playlist scrollers // //set height of playlist scrollers
/* if ($(window).width() > 960) { /* if ($(window).width() > 960) {
$('#playlisttracksdiv').show(); $('#playlisttracksdiv').show();
@ -76,8 +83,8 @@ function setSongInfo(data) {
artiststext = ''; artiststext = '';
if (validUri(data.name)) { if (validUri(data.name)) {
for (var key in radioStations) { for (var key in streamUris) {
rs = radioStations[key]; rs = streamUris[key];
if (rs && rs[1] == data.name) { if (rs && rs[1] == data.name) {
data.name = (rs[0] || rs[1]); data.name = (rs[0] || rs[1]);
} }
@ -93,8 +100,8 @@ function setSongInfo(data) {
$("#songlength").html(''); $("#songlength").html('');
pausePosTimer(); pausePosTimer();
$('#trackslider').slider('disable'); $('#trackslider').slider('disable');
$('#radionameinput').val(data.name); // $('#streamnameinput').val(data.name);
$('#radiouriinput').val(data.uri); // $('#streamuriinput').val(data.uri);
} else { } else {
songlength = data.length; songlength = data.length;
$("#songlength").html(timeFromSeconds(data.length / 1000)); $("#songlength").html(timeFromSeconds(data.length / 1000));
@ -114,10 +121,9 @@ function setSongInfo(data) {
} }
arttmp = artistshtml; arttmp = artistshtml;
} }
if (data.album && data.album.name) { if (data.album && data.album.name) {
$("#modalalbum").html('<a href="#" onclick="return showAlbum(\'' + data.album.uri + '\');">' + data.album.name + '</a>'); $("#modalalbum").html('<a href="#" onclick="return showAlbum(\'' + data.album.uri + '\');">' + data.album.name + '</a>');
getCover(artiststext, data.album.name, '#infocover, #controlspopupimage', 'extralarge'); getCover(data.album, '#infocover, #controlspopupimage', 'extralarge');
} else { } else {
$("#modalalbum").html(''); $("#modalalbum").html('');
$("#infocover").attr('src', 'images/default_cover.png'); $("#infocover").attr('src', 'images/default_cover.png');
@ -190,8 +196,8 @@ function popupTracks(e, listuri, trackuri) {
return false; return false;
} }
function showAlbumPopup() { function showAlbumPopup(popupId) {
uri = $('#popupTracks').data("track"); uri = $(popupId).data("track");
showAlbum(popupData[uri].album.uri); showAlbum(popupData[uri].album.uri);
} }
@ -205,7 +211,8 @@ function initSocketevents() {
getCurrentPlaylist(); getCurrentPlaylist();
updateStatusOfAll(); updateStatusOfAll();
getPlaylists(); getPlaylists();
getBrowseDir(); getBrowseDir();
getSearchSchemes();
showLoading(false); showLoading(false);
$(window).hashchange(); $(window).hashchange();
}); });
@ -284,14 +291,11 @@ function enterFullscreen() {
elem.requestFullscreen(); elem.requestFullscreen();
} }
} }
} }
function exitFullscreen() { function exitFullscreen() {
document.webkitExitFullscreen(); document.webkitExitFullscreen();
document.mozCancelFullscreen(); document.mozCancelFullscreen();
document.exitFullscreen(); document.exitFullscreen();
} }
function onFullScreenEnter() { function onFullScreenEnter() {
@ -323,11 +327,12 @@ function setHeadline(site){
if(str==""){ if(str==""){
str=site; str=site;
} }
$('#contentHeadline').text(str); $('#contentHeadline').html('<a href="#home" onclick="switchContent(\'home\'); return false;">' + str + '</a>');
} }
//update timer //update timer
function updateStatusTimer() { function updateStatusTimer() {
// console.log('statustimer');
mopidy.playback.getCurrentTrack().then(processCurrenttrack, console.error); mopidy.playback.getCurrentTrack().then(processCurrenttrack, console.error);
mopidy.playback.getTimePosition().then(processCurrentposition, console.error); mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
//TODO check offline? //TODO check offline?
@ -370,11 +375,15 @@ function locationHashChanged() {
$('#' + divid + 'pane').show(); $('#' + divid + 'pane').show();
switch(divid) { switch(divid) {
case 'home':
$('#navhome a').addClass('ui-state-active ui-state-persist ui-btn-active');
break;
case 'nowPlaying': case 'nowPlaying':
$('#navnowPlaying a').addClass('ui-state-active ui-state-persist ui-btn-active'); $('#navnowPlaying a').addClass('ui-state-active ui-state-persist ui-btn-active');
break; break;
case 'current': case 'current':
$('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active'); $('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active');
getCurrentPlaylist();
break; break;
case 'playlists': case 'playlists':
$('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active'); $('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active');
@ -389,8 +398,8 @@ function locationHashChanged() {
initSearch($('#searchinput').val()); initSearch($('#searchinput').val());
} }
break; break;
case 'radio': case 'stream':
$('#navradio a').addClass('ui-state-active ui-state-persist ui-btn-active'); $('#navstream a').addClass('ui-state-active ui-state-persist ui-btn-active');
break; break;
case 'artists': case 'artists':
if (uri != '') { if (uri != '') {
@ -452,7 +461,7 @@ $(document).ready(function(event) {
resetSong(); resetSong();
if (location.hash.length < 2) { if (location.hash.length < 2) {
switchContent("playlists"); switchContent("home");
} }
@ -491,6 +500,8 @@ $(document).ready(function(event) {
if (!isMusicBox) { if (!isMusicBox) {
$('#navSettings').hide(); $('#navSettings').hide();
$('#navshutdown').hide(); $('#navshutdown').hide();
$('#homesettings').hide();
$('#homeshutdown').hide();
} }
//navigation stuff //navigation stuff
@ -513,7 +524,7 @@ $(document).ready(function(event) {
return true; return true;
} }
}); });
initRadio(); initStreams();
if ($(window).width() < 980) { if ($(window).width() < 980) {
$("#panel").panel("close"); $("#panel").panel("close");
@ -544,7 +555,6 @@ $(document).ready(function(event) {
$("#panel").panel("close"); $("#panel").panel("close");
event.stopImmediatePropagation(); } event.stopImmediatePropagation(); }
} ); } );
}); });
function updatePlayIcons (uri) { function updatePlayIcons (uri) {

View File

@ -0,0 +1,61 @@
/**
* @author Wouter van Wijk
*/
API_KEY= 'b6d34c3af91d62ab0ae00ab1b6fa8733';
API_SECRET = '2c631802c2285d5d5d1502462fe42a2b';
var fmcache;
var lastfm;
$(window).load(function() {
// create a Cache object
fmcache = new LastFMCache();
// create a LastFM object
lastfm = new LastFM({
apiKey : API_KEY,
apiSecret : API_SECRET,
cache : fmcache
});
});
function getCover(album, images, size) {
var defUrl = 'images/default_cover.png';
$(images).attr('src', defUrl);
if (!album) {
return;
}
var albumname = album.name || '';
var artistname = '';
if ( album.artists && (album.artists.length > 0) ) {
artistname = album.artists[0].name;
}
// console.log(album, images);
if (album.images && (album.images.length > 0) ) {
$(images).attr('src', album.images[0]);
} else {
lastfm.album.getInfo( {artist: artistname, album: albumname},
{ success: function(data){
for (var i = 0; i < data.album.image.length; i++) {
if ( data.album.image[i]['size'] == size) {
$(images).attr('src', data.album.image[i]['#text'] || defUrl);
}
}
}
});
}
}
function getArtistImage(nwartist, image, size) {
var defUrl = 'images/user_24x32.png';
lastfm.artist.getInfo({artist: nwartist}, {success: function(data){
for (var i = 0; i < data.artist.image.length; i++) {
if ( data.artist.image[i]['size'] == size) {
$(image).attr('src', data.artist.image[i]['#text'] || defUrl);
}
}
}});
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -57,6 +57,18 @@ function initSearch() {
/******************************************************** /********************************************************
* process results of a search * process results of a search
*********************************************************/ *********************************************************/
//# speed clone http://jsperf.com/cloning-an-object/2
function clone(obj) {
var target = {};
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
target[i] = obj[i];
}
}
return target;
}
function processSearchResults(resultArr) { function processSearchResults(resultArr) {
$(SEARCH_TRACK_TABLE).empty(); $(SEARCH_TRACK_TABLE).empty();
$(SEARCH_ARTIST_TABLE).empty(); $(SEARCH_ARTIST_TABLE).empty();
@ -65,10 +77,9 @@ function processSearchResults(resultArr) {
// Merge results from different backends. // Merge results from different backends.
// TODO should of coures have multiple tables // TODO should of coures have multiple tables
var results = {'tracks': [], 'artists': [], 'albums': []}; var results = {'tracks': [], 'artists': [], 'albums': []};
var emptyResult = true; var j, emptyResult = true;
/* for (var i = 0; i < resultArr.length; ++i) {
for (var i = 0; i < resultArr.length; ++i) {
for (var prop in results) { for (var prop in results) {
if (resultArr[i][prop] && resultArr[i][prop].length) { if (resultArr[i][prop] && resultArr[i][prop].length) {
results[prop] = results[prop].concat(resultArr[i][prop]); results[prop] = results[prop].concat(resultArr[i][prop]);
@ -76,6 +87,31 @@ function processSearchResults(resultArr) {
} }
} }
} }
*/
for (var i = 0; i < resultArr.length; i++) {
if (resultArr[i].tracks) {
for (j = 0; j < resultArr[i].tracks.length; j++) {
results.tracks.push(resultArr[i].tracks[j]);
emptyResult = false;
}
}
if (resultArr[i].artists) {
for (j = 0; j < resultArr[i].artists.length; j++) {
results.artists.push(resultArr[i].artists[j]);
emptyResult = false;
}
}
if (resultArr[i].albums) {
for (j = 0; j < resultArr[i].albums.length; j++) {
results.albums.push(resultArr[i].albums[j]);
emptyResult = false;
}
}
}
// console.log(resultArr, results);
customTracklists['trackresultscache'] = results.tracks; customTracklists['trackresultscache'] = results.tracks;
@ -203,7 +239,11 @@ function getCurrentPlaylist() {
function togglePlaylists() { function togglePlaylists() {
if ($(window).width() <= 960) { if ($(window).width() <= 960) {
$('#playlisttracksdiv').toggle(); $('#playlisttracksdiv').toggle();
$('#playlistslistdiv').toggle(); //Hide other div
($('#playlisttracksdiv').is(":visible")) ? $('#playlistslistdiv').hide() : $('#playlistslistdiv').show();
} else {
$('#playlisttracksdiv').show();
$('#playlistslistdiv').show();
} }
return true; return true;
} }
@ -218,7 +258,7 @@ function showTracklist(uri) {
} else { } else {
showLoading(true); showLoading(true);
} }
updatePlayIcons(uri);
$('#playlistslist li a').each(function() { $('#playlistslist li a').each(function() {
$(this).removeClass("playlistactive"); $(this).removeClass("playlistactive");
if (this.id == uri) { if (this.id == uri) {
@ -227,6 +267,7 @@ function showTracklist(uri) {
}); });
// scrollToTracklist(); // scrollToTracklist();
//lookup recent tracklist //lookup recent tracklist
mopidy.playlists.lookup(uri).then(processGetTracklist, console.error); mopidy.playlists.lookup(uri).then(processGetTracklist, console.error);
return false; return false;
} }
@ -236,6 +277,7 @@ function showTracklist(uri) {
*/ */
function showArtist(nwuri) { function showArtist(nwuri) {
$('#popupQueue').popup('close');
$('#popupTracks').popup('close'); $('#popupTracks').popup('close');
$('#controlsmodal').popup('close'); $('#controlsmodal').popup('close');
$(ARTIST_TABLE).empty(); $(ARTIST_TABLE).empty();
@ -244,7 +286,10 @@ function showArtist(nwuri) {
//TODO cache //TODO cache
$('#h_artistname').html(''); $('#h_artistname').html('');
showLoading(true); showLoading(true);
mopidy.library.lookup(nwuri).then(processArtistResults, console.error); mopidy.library.lookup(nwuri).then(function(resultArr) {
resultArr.uri = nwuri;
processArtistResults(resultArr);
}, console.error);
switchContent('artists', nwuri); switchContent('artists', nwuri);
scrollToTop(); scrollToTop();
setSongInfo(); setSongInfo();
@ -252,12 +297,13 @@ function showArtist(nwuri) {
} }
function showAlbum(uri) { function showAlbum(uri) {
$('#popupQueue').popup('close');
$('#popupTracks').popup('close'); $('#popupTracks').popup('close');
$('#controlsmodal').popup('close'); $('#controlsmodal').popup('close');
$(ALBUM_TABLE).empty(); $(ALBUM_TABLE).empty();
//fill from cache //fill from cache
var pl = getTracksFromUri(uri); var pl = getTracksFromUri(uri);
if (pl) { if (pl.length>0) {
albumTracksToTable(pl, ALBUM_TABLE, uri); albumTracksToTable(pl, ALBUM_TABLE, uri);
var albumname = getAlbum(pl); var albumname = getAlbum(pl);
var artistname = getArtist(pl); var artistname = getArtist(pl);
@ -266,13 +312,19 @@ function showAlbum(uri) {
$('#coverpopupalbumname').html(albumname); $('#coverpopupalbumname').html(albumname);
$('#coverpopupartist').html(artistname); $('#coverpopupartist').html(artistname);
showLoading(false); showLoading(false);
getCover(artistname, albumname, '#albumviewcover, #coverpopupimage', 'extralarge'); mopidy.library.lookup(uri).then(function(resultArr) {
mopidy.library.lookup(uri).then(processAlbumResults, console.error); resultArr.uri = uri;
processAlbumResults(resultArr);
}, console.error);
// getCover(pl, '#albumviewcover, #coverpopupimage', 'extralarge');
} else { } else {
showLoading(true); showLoading(true);
$('#h_albumname').html(''); $('#h_albumname').html('');
$('#h_albumartist').html(''); $('#h_albumartist').html('');
mopidy.library.lookup(uri).then(processAlbumResults, console.error); mopidy.library.lookup(uri).then(function(resultArr) {
resultArr.uri = uri;
processAlbumResults(resultArr);
}, console.error);
} }
//show page //show page
switchContent('albums', uri); switchContent('albums', uri);
@ -297,4 +349,4 @@ function getSearchSchemes() {
$("#selectSearchService").selectmenu( "refresh", true ); $("#selectSearchService").selectmenu( "refresh", true );
}, console.error }, console.error
); );
} }

View File

@ -9,7 +9,6 @@
* process results of a (new) currently playing track * process results of a (new) currently playing track
*********************************************************/ *********************************************************/
function processCurrenttrack(data) { function processCurrenttrack(data) {
// console.log(data);
setSongInfo(data); setSongInfo(data);
} }
@ -60,18 +59,13 @@ function processPlaystate(data) {
* process results of a browse list * process results of a browse list
*********************************************************/ *********************************************************/
function processBrowseDir(resultArr) { function processBrowseDir(resultArr) {
/*<p><ul><li>Donec id elit non mi porta</li><li>Gravida at eget metus. Fusce dapibus.</li><li>Tellus ac cursus commodo</li></p> var backHtml = '<li style="background-color:#ccc"><a href="#" onclick="return getBrowseDir();"><h1 class="trackname"><i class="fa fa-arrow-circle-left"></i> Back</h1></a></li>'
<p><a class="btn" href="#">More &raquo;</a></p> if ( (!resultArr) || (resultArr == '') || (resultArr.length == 0) ) {
*/ $('#browsepath').html('No tracks found...');
$('#browselist').html(backHtml);
if ((!resultArr) || (resultArr == '')) { showLoading(false);
return; return;
} }
// console.log(resultArr);
if (resultArr.length == 0) {
return;
}
$('#browselist').empty(); $('#browselist').empty();
@ -88,8 +82,6 @@ function processBrowseDir(resultArr) {
if (resultArr[0].type == 'track' ) { if (resultArr[0].type == 'track' ) {
rooturi = rooturi.replace(":track:", ":directory:"); rooturi = rooturi.replace(":track:", ":directory:");
} }
colonindex = rooturi.lastIndexOf(':'); colonindex = rooturi.lastIndexOf(':');
slashindex = rooturi.lastIndexOf('/'); slashindex = rooturi.lastIndexOf('/');
@ -97,8 +89,7 @@ function processBrowseDir(resultArr) {
rooturi = rooturi.slice(0, lastindex); rooturi = rooturi.slice(0, lastindex);
if (browseStack.length > 0) { if (browseStack.length > 0) {
// child += '<li><a href="#" onclick="return getBrowseDir();"><h1 class="trackname">..</h1></a></li>'; child += backHtml;
child += '<li style="background-color:#ccc"><a href="#" onclick="return getBrowseDir();"><h1 class="trackname"><i class="fa fa-arrow-circle-left"></i> Back</h1></a></li>';
} }
for (var i = 0; i < resultArr.length; i++) { for (var i = 0; i < resultArr.length; i++) {
@ -132,7 +123,7 @@ function processBrowseDir(resultArr) {
} else { } else {
$('#browsepath').html(''); $('#browsepath').html('');
} }
updatePlayIcons(songdata.uri); updatePlayIcons(songdata.uri);
showLoading(false); showLoading(false);
@ -186,10 +177,6 @@ function processGetTracklist(resultArr) {
setSongInfo(); setSongInfo();
resultsToTables(playlists[newplaylisturi].tracks, PLAYLIST_TABLE, newplaylisturi); resultsToTables(playlists[newplaylisturi].tracks, PLAYLIST_TABLE, newplaylisturi);
showLoading(false); showLoading(false);
// scrollToTracklist();
// if (isMobileWebkit) {
// playlisttracksScroll.refresh();
// }
} }
/******************************************************** /********************************************************
@ -206,6 +193,12 @@ function processCurrentPlaylist(resultArr) {
* process results of an artist lookup * process results of an artist lookup
*********************************************************/ *********************************************************/
function processArtistResults(resultArr) { function processArtistResults(resultArr) {
if (!resultArr || (resultArr.length == 0)) {
$('#h_artistname').text('Artist not found...');
getCover('', '#artistviewimage, #artistpopupimage', 'extralarge');
showLoading(false);
return;
}
customTracklists[resultArr.uri] = resultArr; customTracklists[resultArr.uri] = resultArr;
resultsToTables(resultArr, ARTIST_TABLE, resultArr.uri); resultsToTables(resultArr, ARTIST_TABLE, resultArr.uri);
@ -220,6 +213,13 @@ function processArtistResults(resultArr) {
* process results of an album lookup * process results of an album lookup
*********************************************************/ *********************************************************/
function processAlbumResults(resultArr) { function processAlbumResults(resultArr) {
// console.log(resultArr);
if (!resultArr || (resultArr.length == 0)) {
$('#h_albumname').text('Album not found...');
getCover('', '#albumviewcover, #coverpopupimage', 'extralarge');
showLoading(false);
return;
}
customTracklists[resultArr.uri] = resultArr; customTracklists[resultArr.uri] = resultArr;
albumTracksToTable(resultArr, ALBUM_TABLE, resultArr.uri); albumTracksToTable(resultArr, ALBUM_TABLE, resultArr.uri);
var albumname = getAlbum(resultArr); var albumname = getAlbum(resultArr);
@ -228,7 +228,7 @@ function processAlbumResults(resultArr) {
$('#h_albumartist').html(artistname); $('#h_albumartist').html(artistname);
$('#coverpopupalbumname').html(albumname); $('#coverpopupalbumname').html(albumname);
$('#coverpopupartist').html(artistname); $('#coverpopupartist').html(artistname);
getCover(artistname, albumname, '#albumviewcover, #coverpopupimage', 'extralarge');
setSongInfo(); setSongInfo();
getCover(resultArr[0].album, '#albumviewcover, #coverpopupimage', 'extralarge');
showLoading(false); showLoading(false);
} }

View File

@ -1,16 +0,0 @@
/**
* Default Radiostations which appear in the webinterface. Edit if you like.
* Take care when editting. Only edit the stuff between ''
* And don't use the default Windows Notepad for this (use Notepad++ on Windows)
*/
var radioStations = [];
//fill with defaults
radioStations.push(['NPR 24', 'http://nprdmp.ic.llnwd.net/stream/nprdmp_live01_mp3']);
radioStations.push(['3FM Dutch', 'http://icecast.omroep.nl/3fm-bb-mp3']);
radioStations.push(['BBC WorldService', 'http://vprbbc.streamguys.net:8000/vprbbc24.mp3']);
radioStations.push(['Arrow Jazz', 'http://81.173.3.132:8082']);
radioStations.push(['PBS Australia', 'http://eno.emit.com:8000/pbsfm_live_64.mp3']);
radioStations.push(['Groove Salad - Soma FM', 'http://somafm.com/groovesalad.pls']);
radioStations.push(['Kiss FM Berlin', 'http://stream.kissfm.de/kissfm/mp3-128/internetradio/']);
radioStations.push(['Pinguin Radio', 'http://pr320.pinguinradio.com/listen.pls']);

View File

@ -0,0 +1,17 @@
/**
* Default streamuris which appear in the webinterface. Edit if you like.
* Take care when editting. Only edit the stuff between ''
* And don't use the default Windows Notepad for this (use Notepad++ on Windows)
*/
var streamUris = [];
//fill with defaults
streamUris.push(['NPR 24', 'http://nprdmp.ic.llnwd.net/stream/nprdmp_live01_mp3']);
streamUris.push(['3FM Dutch', 'http://icecast.omroep.nl/3fm-bb-mp3']);
streamUris.push(['BBC WorldService', 'http://vprbbc.streamguys.net:8000/vprbbc24.mp3']);
streamUris.push(['Arrow Jazz', 'http://81.173.3.132:8082']);
streamUris.push(['Queen Live Aid at Wembley (YouTube)', 'yt:http://www.youtube.com/watch?v=eQsM6u0a038']);
streamUris.push(['Groove Salad - Soma FM', 'http://somafm.com/groovesalad.pls']);
streamUris.push(['Kiss FM Berlin', 'http://stream.kissfm.de/kissfm/mp3-128/internetradio/']);
streamUris.push(['Muse - Newborn (SoundCloud)', 'sc:https://soundcloud.com/muse/01-new-born']);
streamUris.push(['Pinguin Radio', 'http://pr320.pinguinradio.com/listen.pls']);