Release v2.1.0

This commit is contained in:
jcass 2016-02-04 18:25:06 +02:00
commit efb840b79f
50 changed files with 1190 additions and 16890 deletions

View File

@ -1,3 +1,5 @@
sudo: false
language: python
python:
@ -8,10 +10,6 @@ env:
- TOX_ENV=flake8
install:
- "wget -O - http://apt.mopidy.com/mopidy.gpg | sudo apt-key add -"
- "sudo wget -O /etc/apt/sources.list.d/mopidy.list http://apt.mopidy.com/mopidy.list"
- "sudo apt-get update || true"
- "sudo apt-get install mopidy"
- "pip install tox"
script:

View File

@ -10,15 +10,19 @@ Mopidy-MusicBox-Webclient
:target: https://pypi.python.org/pypi/Mopidy-MusicBox-Webclient/
:alt: Number of PyPI downloads
With Mopidy MusicBox Webclient, you can play your music on your computer (`Rapsberry Pi <http://www.raspberrypi.org/>`_) and remotely control it using your computer, tablet or phone.
With Mopidy MusicBox Webclient, you can play your music on your computer (`Rapsberry Pi <http://www.raspberrypi.org/>`_)
and remotely control it using your computer, tablet or phone.
This is a responsive webclient especially written for Mopidy, a music server. Responsive, so it works on desktop and mobile browsers. You can browse, search and play albums, artists, playlists, and it has cover art from Last.fm.
This is a responsive webclient especially written for Mopidy, a music server. Responsive, so it works on desktop and
mobile browsers. You can browse, search and play albums, artists, playlists, and it has cover art from Last.fm.
`Mopidy <http://www.mopidy.com/>`_ is a music server which can play music from Spotify, Google Music, SoundCloud, etc or from your hard drive.
`Mopidy <http://www.mopidy.com/>`_ is a music server which can play music from Spotify, Google Music, SoundCloud, etc.
or from your hard drive.
If you want to run Mopidy with this webclient on a Raspberry Pi, do yourself a favor and use my custom built SD-image: `Pi MusicBox <http://www.woutervanwijk.nl/pimusicbox/>`_.
If you want to run Mopidy with this webclient on a Raspberry Pi, do yourself a favor and use my custom built SD-image:
`Pi MusicBox <http://www.pimusicbox.com/>`_.
.. image:: https://github.com/woutervanwijk/Mopidy-MusicBox-Webclient/raw/master/screenshots/playlists_desktop.png
.. image:: https://github.com/pimusicbox/mopidy-musicbox-webclient/raw/master/screenshots/playlists_desktop.png
Installation
@ -31,30 +35,85 @@ Install by running::
Alternatively, clone the repository and run ``sudo python setup.py install`` from within the project directory. e.g. ::
$ git clone https://github.com/woutervanwijk/Mopidy-MusicBox-Webclient
$ cd Mopidy-MusicBox-Webclient
$ git clone https://github.com/pimusicbox/mopidy-musicbox-webclient
$ cd mopidy-musicbox-webclient
$ sudo python setup.py install
Usage
=====
Point your (modern) browser at Mopidy-MusicBox-Webclient running on your Mopidy server e.g. http://localhost:6680/musicbox_webclient.
Point your (modern) browser at Mopidy-MusicBox-Webclient running on your Mopidy server e.g.
http://localhost:6680/musicbox_webclient.
Project resources
=================
- `Source code <https://github.com/woutervanwijk/mopidy-musicbox-webclient>`_
- `Issue tracker <https://github.com/woutervanwijk/mopidy-musicbox-webclient/issues>`_
- `Download development snapshot <https://github.com/woutervanwijk/mopidy-musicbox-webclient/archive/master.tar.gz#egg=Mopidy-MusicBox-Webclient-dev>`_
- `Source code <https://github.com/pimusicbox/mopidy-musicbox-webclient>`_
- `Issue tracker <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues>`_
- `Download development snapshot <https://github.com/pimusicbox/mopidy-musicbox-webclient/archive/develop.tar.gz#egg=Mopidy-MusicBox-Webclient-dev>`_
Changelog
=========
v2.0 (26-3-2015)
----------------
v2.1.0 (UNRELEASED)
-------------------
**Enhancements and improvements**
- Added optional ``websocket_host`` and ``websocket_port`` config settings.
- Added link to `Alarm Clock <https://pypi.python.org/pypi/Mopidy-AlarmClock/>`_ (if present).
- Added ability to save Queue as local Playlist. (Addresses: `#106 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/106>`_).
- Add support for ``static_dir`` configurations.
(Addresses: `#105 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/105>`_).
- Added ability to manually initiate refresh of Playlists.
(Addresses: `#107 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/107>`_).
- Now updates the track name when the stream title changes.
- Adding a browsed radio station to the tracklist now also starts playback of the station.
(Addresses: `#98 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/98>`_).
- Increase volume slider handle by 30% to make it easier to grab on mobile devices.
- Add application cache manifest file for quicker loads and to allow client devices to detect when local caches should
be invalidated.
- Use standard Mopidy mixer methods to mute / un-mute playback.
- Streams are now saved to the '[Radio Streams].m3u' playlist and are accessible from all clients.
Users with existing streamUris stored as browser cookies will be prompted to convert them to the new m3u backed scheme.
- Mopidy-Musicbox-Webclient now requires at least Mopidy v1.1.0 or greater to be installed.
**Fixes**
- Ensure that only the currently playing track is highlighted in the queue.
(Fixes: `#81 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/81>`_).
- Fixed slow to start playing from a large tracklist of browsed tracks.
(Fixes: `#85 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/85>`_).
- Clean up unused Javascript code. (Fixes: `#100 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/100>`_).
- Mopidy 1.1.0 compatibility fixes. (Fixes: `#109 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/109>`_,
`#111 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/111>`_,
`#121 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/121>`_, and
`#123 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/123>`_).
- Fix incorrect identification of user's Spotify starred playlist.
(Fixes: `#110 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/110>`_).
- Initiating track playback from a folder that contains subfolders now correctly identifies the tracks that should be
played. (Fixes: `#112 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/112>`_).
- Adding search results to tracklist now works as expected.
(Fixes: `#49 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/49>`_ and
`#135 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/135>`_).
- Fix Javascript syntax errors. (Fixes: `#122 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/122>`_).
- Fix vertical alignment of playback control buttons in footer.
- Increase width of header so that more text can be rendered in the title bar.
(Fixes: `#144 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/144>`_).
- Re-align the menu and search buttons in the title bar.
(Fixes: `#148 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/148>`_).
- Use explicit Mopidy.js calling convention. (Fixes: `#79 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/79>`_).
- Added event handling for 'muteChanged' event. (Fixes: `#141 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/141>`_).
- Remove support for defunct Grooveshark service.
(Fixes: `#120 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/120>`_).
v2.0.0 (2015-03-26)
-------------------
- Pausing a stream will now actually stop it.
- Fix keyboard shortcuts in some browsers.
- Use relative path for script files to fix proxy support.
@ -65,45 +124,45 @@ v2.0 (26-3-2015)
- Added popup tracks menu to the Browse interface.
- Fixed wrong jQuery version on some pages.
v1.0.4
v1.0.4 (2014-11-24)
-------------------
- Added AudioAddict icon
- Bugfixes of course
- Added AudioAddict icon.
- Bugfixes of course.
v1.0.2
------
- 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.
- Enhanced radio/streams interface.
- Search: select service to search.
- Fixed single quote bug. (Fixes: `#39 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/39>`_).
- Better handling of coverart.
- Youtube icons added.
- Bugfixes (search, popups, etc.).
v1.0.1 (2014-09-20)
-------------------
- 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
- Enhanced radio/streams interface
- Search: select service to search
- Fixed single quote bug #39
- Better handling of coverart
- Youtube icons added
- Bugfixes (search, popups, etc)
- Small fixes for PyPI distro.
v1.0.1 (20-9-2014)
v1.0.0 (2014-09-20)
-------------------
- Small fixes for Pypi distro
v1.0.0 (20-9-2014)
-------------------
- Compatible with Mopidy v0.19
- Made pip installable
- A lot of fixes
- Works with mopidy-websettings extension
- Compatible with Mopidy v0.19.
- Made pip installable.
- A lot of fixes.
- Works with mopidy-websettings extension.
v0.1.0 (2013-07-21)
-------------------
- Compatible with Mopidy 0.14+
- More ways to add a song to the Queue (play next, add to bottom, etc)
- Better Queue popup
- Button to clear the Queue
- A bit more speed
- Local files show up in search
- Bugs fixed
- New instructions in the read me
- Compatible with Mopidy 0.14+.
- More ways to add a song to the Queue (play next, add to bottom, etc).
- Better Queue popup.
- Button to clear the Queue.
- A bit more speed.
- Local files show up in search.
- Bugs fixed.
- New instructions in the read me.

View File

@ -4,7 +4,7 @@ import os
from mopidy import config, ext
__version__ = '2.0.0'
__version__ = '2.1.0'
class MusicBoxExtension(ext.Extension):
@ -19,7 +19,9 @@ class MusicBoxExtension(ext.Extension):
def get_config_schema(self):
schema = super(MusicBoxExtension, self).get_config_schema()
schema['musicbox'] = config.Boolean()
schema['musicbox'] = config.Boolean(optional=True)
schema['websocket_host'] = config.Hostname(optional=True)
schema['websocket_port'] = config.Port(optional=True)
return schema
def setup(self, registry):

View File

@ -1,3 +1,5 @@
[musicbox_webclient]
enabled = true
musicbox = false
websocket_host =
websocket_port =

View File

@ -1,160 +0,0 @@
/**
*
* Main container
*
*/
#addToHomeScreen {
z-index:9999;
-webkit-user-select:none;
user-select:none;
-webkit-box-sizing:border-box;
box-sizing:border-box;
-webkit-touch-callout:none;
touch-callout:none;
width:240px;
font-size:15px;
padding:12px 14px;
text-align:left;
font-family:helvetica;
background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(0,#fff),color-stop(0.02,#eee),color-stop(0.98,#ccc),color-stop(1,#a3a3a3));
border:1px solid #505050;
-webkit-border-radius:8px;
-webkit-background-clip:padding-box;
color:#333;
text-shadow:0 1px 0 rgba(255,255,255,0.75);
line-height:130%;
-webkit-box-shadow:0 0 4px rgba(0,0,0,0.5);
}
#addToHomeScreen.addToHomeIpad {
width:268px;
font-size:18px;
padding:14px;
}
/**
*
* The 'wide' class is added when the popup contains the touch icon
*
*/
#addToHomeScreen.addToHomeWide {
width:296px;
}
#addToHomeScreen.addToHomeIpad.addToHomeWide {
width:320px;
font-size:18px;
padding:14px;
}
/**
*
* The balloon arrow
*
*/
#addToHomeScreen .addToHomeArrow {
position:absolute;
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(204,204,204,0)),color-stop(0.4,rgba(204,204,204,0)),color-stop(0.4,#ccc));
border-width:0 1px 1px 0;
border-style:solid;
border-color:#505050;
width:16px; height:16px;
-webkit-transform:rotateZ(45deg);
bottom:-9px; left:50%;
margin-left:-8px;
-webkit-box-shadow:inset -1px -1px 0 #a9a9a9;
-webkit-border-bottom-right-radius:2px;
}
/**
*
* The balloon arrow for iPad
*
*/
#addToHomeScreen.addToHomeIpad .addToHomeArrow {
-webkit-transform:rotateZ(-135deg);
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(238,238,238,0)),color-stop(0.4,rgba(238,238,238,0)),color-stop(0.4,#eee));
-webkit-box-shadow:inset -1px -1px 0 #fff;
top:-9px; bottom:auto; left:50%;
}
/**
*
* Close button
*
*/
#addToHomeScreen .addToHomeClose {
-webkit-box-sizing:border-box;
position:absolute;
right:4px;
top:4px;
width:18px;
height:18px; line-height:14px;
text-align:center;
text-indent:1px;
-webkit-border-radius:9px;
background:rgba(0,0,0,0.12);
color:#707070;
-webkit-box-shadow:0 1px 0 #fff;
font-size:16px;
}
/**
*
* The '+' icon, displayed only on iOS < 4.2
*
*/
#addToHomeScreen .addToHomePlus {
font-weight:bold;
font-size:1.3em;
}
/**
*
* The 'share' icon, displayed only on iOS >= 4.2
*
*/
#addToHomeScreen .addToHomeShare {
display:inline-block;
width:18px;
height:15px;
background-repeat:no-repeat;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAQAAADu6HTYAAADPElEQVR4Xq3TX2gcRRzA8e/M7mVv2+TSNpc/TZtrY6jUGqgaSAmEChKLrYK0YH0RFC2CSCkEfCghiKU04J8qNigq6os+iQV98MHWFwVBrQQRWs21lBw5cw3NNb1/udu72RGG5Y77IzXW77D7sAwf5scyYoL6BGXSDKFZwaGpLvIUaeoCkvX1MmsM0Ny6oRSQYOLuIS+YZOpfQdqslpUxcZrzTVAz4qPwW2O3CeIwC/RSzeY6Ow1QhUrkr+YOWfEKDkEP8Rij7CHKJmrFSDHBdwGEE5wiGChPN+PnT8VdRtEIl1d4gRj/1EVe5ZSBKGh8iqQpo/Fo5+3C/gz0MYg4zgwbqday1/Q4B8BGQ45d/Hi54lakCrU5obOcidJpu1+Lg9whjabyaOYLnrIBFFaRD+xe2ybMDWY66GmP/WA9cGfGp0CWhy0wkMN8inepFiH2rV1j0NQSNQbFLRQnS8/8YSDBBpadfv4CYDub2fmeHDNAsL1MBWUel0iA+Xik6eHcyvD3vAMSU1TGuA/YRS+dD7ovCQN43GKRFCU20Kd3V/avDVVyAZ5niTEuLA5/zBGWg9EEEhfJKN200Tat8CmRAQb9+wv7soPlHt2tQorsz1uPbr0HTY4sJwrH47zJZwABBAKLMBoQXepwgTwdHCo+fXMkQ4lrxEmQ5AaXipPqDY9V2vn09tgvTPI71EEGYxM+/uMJLJ4svpgaWGKOi/xKgmqLSUGSUd5f2vIVJ/CgBaTIUsZ7ZBsn0+NzfMOXLFCXQyTcybN6ep5ZZgUOHn7jpfUpsZshdugPGf+E5zjbyHTSRyQ8xfRPPM/s63RHeuknSoT22mjmmnAOIMkUZ6D1xSfPPAfd1WFKM3sO2CMaHx8M1NjnXKHaAGGkOW0C02WeYHUz4qMtx+w5gUDS8NckYe5lHsMYwCZEPyEEmjLDZFmAS7CDviMdxyTkMNVBKEmYLvbiQQBIBBbCQG04bGQvFWz6CfsCQLWCigILFwcfkGYBiOpbYuOizTAyYyDdCtrGaRG1LCkIgMYEFhI0WqQZoSlbGRyHKe4qOx7iv2bVQW9dp4dlM/x6kmwnWQcd/Q3FCqwTEiT5s+6D5v/pb0SSHyg7uhMWAAAAAElFTkSuQmCC);
background-size:18px 15px;
text-indent:-9999em;
overflow:hidden;
}
#addToHomeScreen .addToHomeShare.addToHomeShareOS7 {
width:11px;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAA8CAYAAAAQTCjdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAASCQAAEgkB80sG3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKjSURBVGiB7dpPiFVVHMDxz7m9NCtMyI2bEJEC25WrEkzHUXCRraIwdNE8ZxfYIlcis1ZEbGEzT1QCF4XgH1CyWhUoJKIWNRGEiCNKmkSiYTzfcfGuOokx77x3ZlS8382959zfn+/invvn3RdijHIRBrwkOINCYXEcdjpb7VyiYdBsLScwt5y6IloYdzqXo36Ro0gY9IKWo+5JwmzBt2HQnBw9ehYNazyn5TBee8Dh+Vq+CWu92GufnkTDR6ab7gDeBNHouMM/l9tXTXM0fGBmL726Fg1Dam74EsvKqR8VNowL2Yzj5f7rnnE4DHq2235diYYhhTGfC94up35T0y+6di/ITU0rKVd+sEi0P7xr2pSJOu8zvF+OzqEv7vDH/WFxt7/cshy/ticsN8sXYUht0kXDOlsF9XJ4UaEvNoz9X3zc5bKaZThbyr5jzJ4wlNY7KTgM+ES0vhz+KeiPw36fKC/ucAF9uFBOrTZm26SJCtaV27+xIo7cXdkTEhvOoh+XyxprU1qnim7CQdGK2HAyKRexYVShT3RItDElN+mkjiP2Ym+S3f01hv2EVal5WW6hU0ElmptaqJuBpXg6MbeFH2LDpU6CQ93zWIKnEvs0cayGU3glMfkOo1jQYewZzOuyz7FC95Jwo5OgUFfgeg993hh/eTqCTxOSm/iuk8DY0Ap1b2GhtHXxsfZN4j/X0fOx4auEIknEhqv4OiUn1L13Z/+xWfWVaG4q0dxUormpRHNTieamEs1NJZqbJ1Q0jHvdiJo5S2cVjSNOCHZhn3/SnuYnIvl3yomIIz7MXZMn9hydRCrR3FSiualEc1OJ5qYSzU0lmptKNDePjWgwcPePT7/g+4cp8wCW4GXaryK3tL+mLdD5x62ppllgu7bso8q/2HIbzGWdNmWnSJwAAAAASUVORK5CYII=);
background-size:11px 15px;
}
/**
*
* The touch icon (if available)
*
*/
#addToHomeScreen .addToHomeTouchIcon {
display:block;
float:left;
-webkit-border-radius:6px;
border-radius:6px;
-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5),
inset 0 0 2px rgba(255,255,255,0.9);
box-shadow:0 1px 3px rgba(0,0,0,0.5),
inset 0 0 2px rgba(255,255,255,0.9);
background-repeat:no-repeat;
width:57px; height:57px;
-webkit-background-size:57px 57px;
background-size:57px 57px;
margin:0 12px 0 0;
border:1px solid #333;
-webkit-background-clip:padding-box;
background-clip:padding-box;
}

File diff suppressed because it is too large Load Diff

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

File diff suppressed because one or more lines are too long

View File

@ -1,589 +0,0 @@
/*!
* jQuery Mobile 1.4.0-alpha.2
* Git HEAD hash: 1e27844a1c0b9103a0948480637e6a67f5212dfd <> Date: Thu Aug 15 2013 13:53:49 UTC
* http://jquerymobile.com
*
* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
*/
/* Globals */
/* Font
-----------------------------------------------------------------------------------------------------------*/
html {
font-size: 100%;
}
body,
input,
select,
textarea,
button,
.ui-btn {
font-size: 1em;
line-height: 1.3;
font-family: sans-serif /*{global-font-family}*/;
}
legend,
.ui-input-text input,
.ui-input-search input {
color: inherit;
text-shadow: inherit;
}
/* Form labels (overrides font-weight bold in bars, and mini font-size) */
.ui-mobile label,
div.ui-controlgroup-label {
font-weight: normal;
font-size: 16px;
}
/* Field contain separator (< 28em)
-----------------------------------------------------------------------------------------------------------*/
.ui-field-contain {
border-bottom-color: #828282;
border-bottom-color: rgba(0,0,0,.15);
border-bottom-width: 1px;
border-bottom-style: solid;
}
/* Buttons
-----------------------------------------------------------------------------------------------------------*/
.ui-btn,
label.ui-btn {
font-weight: bold;
border-width: 1px;
border-style: solid;
}
.ui-btn:link {
text-decoration: none !important;
}
.ui-btn-active {
cursor: pointer;
}
/* Corner rounding
-----------------------------------------------------------------------------------------------------------*/
/* Class ui-btn-corner-all deprecated in 1.4 */
.ui-corner-all {
-webkit-border-radius: .6em /*{global-radii-blocks}*/;
border-radius: .6em /*{global-radii-blocks}*/;
}
/* Buttons */
.ui-btn-corner-all,
.ui-btn.ui-corner-all,
/* Slider track */
.ui-slider-track.ui-corner-all,
/* Flipswitch */
.ui-flipswitch.ui-corner-all,
/* Count bubble */
.ui-li-count {
-webkit-border-radius: .3125em /*{global-radii-buttons}*/;
border-radius: .3125em /*{global-radii-buttons}*/;
}
/* Icon-only buttons */
.ui-btn-icon-notext.ui-btn-corner-all,
.ui-btn-icon-notext.ui-corner-all {
-webkit-border-radius: 1em;
border-radius: 1em;
}
/* Radius clip workaround for cleaning up corner trapping */
.ui-btn-corner-all,
.ui-corner-all {
-webkit-background-clip: padding;
background-clip: padding-box;
}
/* Popup arrow */
.ui-popup.ui-corner-all > .ui-popup-arrow-guide {
left: .6em /*{global-radii-blocks}*/;
right: .6em /*{global-radii-blocks}*/;
top: .6em /*{global-radii-blocks}*/;
bottom: .6em /*{global-radii-blocks}*/;
}
/* Shadow
-----------------------------------------------------------------------------------------------------------*/
.ui-shadow {
-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ rgba(0,0,0,.15) /*{global-box-shadow-color}*/;
-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ rgba(0,0,0,.15) /*{global-box-shadow-color}*/;
box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ rgba(0,0,0,.15) /*{global-box-shadow-color}*/
}
.ui-shadow-inset {
-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ rgba(0,0,0,.2) /*{global-box-shadow-color}*/;
-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ rgba(0,0,0,.2) /*{global-box-shadow-color}*/;
box-shadow: inset 0 1px 3px 0 1px 3px /*{global-box-shadow-size}*/ rgba(0,0,0,.2) /*{global-box-shadow-color}*/;
}
.ui-overlay-shadow {
-webkit-box-shadow: 0 0 12px rgba(0,0,0,.6);
-moz-box-shadow: 0 0 12px rgba(0,0,0,.6);
box-shadow: 0 0 12px rgba(0,0,0,.6);
}
/* Icons
-----------------------------------------------------------------------------------------------------------*/
.ui-btn-icon-left:after,
.ui-btn-icon-right:after,
.ui-btn-icon-top:after,
.ui-btn-icon-bottom:after,
.ui-btn-icon-notext:after,
html .ui-btn.ui-icon-checkbox-off:after,
html .ui-btn.ui-icon-radio-off:after {
background-color: #999 /*{global-icon-color}*/;
background-color: rgba(0,0,0,.3) /*{global-icon-disc}*/;
background-position: center center;
background-repeat: no-repeat;
-webkit-border-radius: 1em;
border-radius: 1em;
}
/* Alt icons */
.ui-icon-alt.ui-btn:after,
.ui-icon-alt .ui-btn:after,
html .ui-icon-alt.ui-icon-checkbox-off:after,
html .ui-icon-alt.ui-icon-radio-off:after,
html .ui-icon-alt .ui-icon-checkbox-off:after,
html .ui-icon-alt .ui-icon-radio-off:after {
background-color: #999 /*{global-icon-color}*/;
background-color: rgba(255,255,255,.3) /*{global-icon-disc-alt}*/;
}
/* No disc */
.ui-icon-nodisc.ui-btn:after,
.ui-icon-nodisc .ui-btn:after {
background-color: transparent;
}
/* Icon shadow */
.ui-shadow-icon.ui-btn:after,
.ui-shadow-icon .ui-btn:after {
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,.3) /*{global-icon-shadow}*/;
-moz-box-shadow: 0 1px 0 rgba(255,255,255,.3) /*{global-icon-shadow}*/;
box-shadow: 0 1px 0 rgba(255,255,255,.3) /*{global-icon-shadow}*/;
}
/* Checkbox and radio */
html .ui-btn.ui-icon-checkbox-off:after,
html .ui-btn.ui-icon-checkbox-on:after,
html .ui-btn.ui-icon-radio-off:after,
html .ui-btn.ui-icon-radio-on:after {
display: block;
width: 18px;
height: 18px;
margin: -9px 2px 0 2px;
}
.ui-btn.ui-icon-checkbox-off:after,
.ui-btn.ui-icon-radio-off:after {
background-image: none;
filter: Alpha(Opacity=30);
opacity: .3;
}
html .ui-btn.ui-icon-checkbox-off:after,
html .ui-btn.ui-icon-checkbox-on:after {
-webkit-border-radius: .1875em;
border-radius: .1875em;
}
.ui-radio .ui-btn.ui-icon-radio-on:after {
background-image: none;
background-color: #fff;
width: 8px;
height: 8px;
border-width: 5px;
border-style: solid;
}
.ui-icon-alt.ui-btn.ui-icon-radio-on:after,
.ui-icon-alt .ui-btn.ui-icon-radio-on:after {
background-color: #000;
}
/* Loader */
.ui-icon-loading {
background: url(images/ajax-loader.gif);
background-size: 2.875em 2.875em;
}
/* Swatches */
/* A
-----------------------------------------------------------------------------------------------------------*/
/* Bar: Toolbars, dividers, slider track */
.ui-bar-a,
.ui-overlay-a .ui-bar-inherit,
.ui-page-theme-a .ui-bar-inherit,
html .ui-bar-a .ui-bar-inherit,
html .ui-body-a .ui-bar-inherit,
html body .ui-group-theme-a .ui-bar-inherit {
background: #f1f1f1 /*{a-bar-background-color}*/;
border-color: #ddd /*{a-bar-border}*/;
color: #111 /*{a-bar-color}*/;
text-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ #eee /*{a-bar-shadow-color}*/;
font-weight: bold;
}
.ui-bar-a {
border-width: 1px;
border-style: solid;
}
/* Page and overlay */
.ui-overlay-a,
.ui-page-theme-a,
.ui-page-theme-a .ui-panel-wrapper {
background: #f9f9f9 /*{a-page-background-color}*/;
border-color: #bbb /*{a-page-border}*/;
color: #111 /*{a-page-color}*/;
text-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ #eee /*{a-body-shadow-color}*/;
}
/* Body: Read-only lists, text inputs, collapsible content */
.ui-body-a,
.ui-overlay-a .ui-body-inherit,
.ui-page-theme-a .ui-body-inherit,
html .ui-bar-a .ui-body-inherit,
html .ui-body-a .ui-body-inherit,
html body .ui-group-theme-a .ui-body-inherit,
html .ui-panel-page-container-a {
background: #fff /*{a-body-background-color}*/;
border-color: #ddd /*{a-body-border}*/;
color: #111 /*{a-body-color}*/;
text-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ #eee /*{a-body-shadow-color}*/;
}
.ui-body-a {
border-width: 1px;
border-style: solid;
}
/* Links */
.ui-overlay-a a,
.ui-page-theme-a a,
html .ui-bar-a a,
html .ui-body-a a,
html body .ui-group-theme-a a {
color: #0066ff /*{a-link-color}*/;
font-weight: bold;
}
.ui-overlay-a a:visited,
.ui-page-theme-a a:visited,
html .ui-bar-a a:visited,
html .ui-body-a a:visited,
html body .ui-group-theme-a a:visited {
color: #0066ff /*{a-link-visited}*/;
}
.ui-overlay-a a:hover,
.ui-page-theme-a a:hover,
html .ui-bar-a a:hover,
html .ui-body-a a:hover,
html body .ui-group-theme-a a:hover {
color: #0033ff /*{a-link-hover}*/;
}
.ui-overlay-a a:active,
.ui-page-theme-a a:active,
html .ui-bar-a a:active,
html .ui-body-a a:active,
html body .ui-group-theme-a a:active {
color: #0033ff /*{a-link-active}*/;
}
/* Button up */
.ui-overlay-a .ui-btn,
.ui-page-theme-a .ui-btn,
html .ui-bar-a .ui-btn,
html .ui-body-a .ui-btn,
html body .ui-group-theme-a .ui-btn,
html head + body .ui-btn.ui-btn-a,
/* Button visited */
.ui-overlay-a .ui-btn:visited,
.ui-page-theme-a .ui-btn:visited,
html .ui-bar-a .ui-btn:visited,
html .ui-body-a .ui-btn:visited,
html body .ui-group-theme-a .ui-btn:visited,
html head + body .ui-btn.ui-btn-a:visited {
background: #f6f6f6 /*{a-bup-background-color}*/;
border-color: #ddd /*{a-bup-border}*/;
color: #111 /*{a-bup-color}*/;
text-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #eee /*{a-bup-shadow-color}*/;
}
/* Button hover */
.ui-overlay-a .ui-btn:hover,
.ui-page-theme-a .ui-btn:hover,
html .ui-bar-a .ui-btn:hover,
html .ui-body-a .ui-btn:hover,
html body .ui-group-theme-a .ui-btn:hover,
html head + body .ui-btn.ui-btn-a:hover {
background: #ededed /*{a-bhover-background-color}*/;
border-color: #ddd /*{a-bhover-border}*/;
color: #111 /*{a-bhover-color}*/;
text-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #eee /*{a-bhover-shadow-color}*/;
}
/* Button down */
.ui-overlay-a .ui-btn:active,
.ui-page-theme-a .ui-btn:active,
html .ui-bar-a .ui-btn:active,
html .ui-body-a .ui-btn:active,
html body .ui-group-theme-a .ui-btn:active,
html head + body .ui-btn.ui-btn-a:active {
background: #e8e8e8 /*{a-bdown-background-color}*/;
border-color: #ddd /*{a-bdown-border}*/;
color: #111 /*{a-bdown-color}*/;
text-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #eee /*{a-bdown-shadow-color}*/;
}
/* Active button */
.ui-overlay-a .ui-btn.ui-btn-active,
.ui-page-theme-a .ui-btn.ui-btn-active,
html .ui-bar-a .ui-btn.ui-btn-active,
html .ui-body-a .ui-btn.ui-btn-active,
html body .ui-group-theme-a .ui-btn.ui-btn-active,
html head + body .ui-btn.ui-btn-a.ui-btn-active,
/* Active checkbox icon */
.ui-overlay-a .ui-icon-checkbox-on:after,
.ui-page-theme-a .ui-icon-checkbox-on:after,
html .ui-bar-a .ui-icon-checkbox-on:after,
html .ui-body-a .ui-icon-checkbox-on:after,
html body .ui-group-theme-a .ui-icon-checkbox-on:after,
.ui-btn.ui-icon-checkbox-on.ui-btn-a:after,
/* Active flipswitch background */
.ui-overlay-a .ui-flipswitch-active,
.ui-page-theme-a .ui-flipswitch-active,
html .ui-bar-a .ui-flipswitch-active,
html .ui-body-a .ui-flipswitch-active,
html body .ui-group-theme-a .ui-flipswitch-active,
html body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,
/* Active slider track */
.ui-overlay-a .ui-slider-track .ui-btn-active,
.ui-page-theme-a .ui-slider-track .ui-btn-active,
html .ui-bar-a .ui-slider-track .ui-btn-active,
html .ui-body-a .ui-slider-track .ui-btn-active,
html body .ui-group-theme-a .ui-slider-track .ui-btn-active,
html body div.ui-slider-track.ui-body-a .ui-btn-active {
background-color: #0066ff /*{a-active-background-color}*/;
border-color: #0033ff /*{a-active-border}*/;
color: #fff /*{a-active-color}*/;
text-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #0033ff /*{a-active-shadow-color}*/;
}
/* Active radio button icon */
.ui-overlay-a .ui-icon-radio-on:after,
.ui-page-theme-a .ui-icon-radio-on:after,
html .ui-bar-a .ui-icon-radio-on:after,
html .ui-body-a .ui-icon-radio-on:after,
html body .ui-group-theme-a .ui-icon-radio-on:after,
.ui-btn.ui-icon-radio-on.ui-btn-a:after {
border-color: #0066ff /*{a-active-background-color}*/;
}
/* Focus */
.ui-overlay-a .ui-btn:focus,
.ui-page-theme-a .ui-btn:focus,
html .ui-bar-a .ui-btn:focus,
html .ui-body-a .ui-btn:focus,
html body .ui-group-theme-a .ui-btn:focus,
html head + body .ui-btn.ui-btn-a:focus,
/* Focus buttons and text inputs with div wrap */
.ui-overlay-a .ui-focus,
.ui-page-theme-a .ui-focus,
html .ui-bar-a .ui-focus,
html .ui-body-a .ui-focus,
html body .ui-group-theme-a .ui-focus,
html head + body .ui-btn-a.ui-focus,
html head + body .ui-body-a.ui-focus {
-webkit-box-shadow: 0 0 12px #0066ff /*{a-active-background-color}*/;
-moz-box-shadow: 0 0 12px #0066ff /*{a-active-background-color}*/;
box-shadow: 0 0 12px #0066ff /*{a-active-background-color}*/;
}
/* B
-----------------------------------------------------------------------------------------------------------*/
/* Bar: Toolbars, dividers, slider track */
.ui-bar-b,
.ui-overlay-b .ui-bar-inherit,
.ui-page-theme-b .ui-bar-inherit,
html .ui-bar-b .ui-bar-inherit,
html .ui-body-b .ui-bar-inherit,
html body .ui-group-theme-b .ui-bar-inherit {
background: #1d1d1d /*{b-bar-background-color}*/;
border-color: #1b1b1b /*{b-bar-border}*/;
color: #fff /*{b-bar-color}*/;
text-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ #111 /*{b-bar-shadow-color}*/;
font-weight: bold;
}
.ui-bar-b {
border-width: 1px;
border-style: solid;
}
/* Page and overlay */
.ui-overlay-b,
.ui-page-theme-b,
.ui-page-theme-b .ui-panel-wrapper {
background: #252525 /*{b-page-background-color}*/;
border-color: #454545 /*{b-page-border}*/;
color: #fff /*{b-page-color}*/;
text-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ #111 /*{b-body-shadow-color}*/;
}
/* Body: Read-only lists, text inputs, collapsible content */
.ui-body-b,
.ui-overlay-b .ui-body-inherit,
.ui-page-theme-b .ui-body-inherit,
html .ui-bar-b .ui-body-inherit,
html .ui-body-b .ui-body-inherit,
html body .ui-group-theme-b .ui-body-inherit,
html .ui-panel-page-container-b {
background: #2a2a2a /*{b-body-background-color}*/;
border-color: #1d1d1d /*{b-body-border}*/;
color: #fff /*{b-body-color}*/;
text-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ #111 /*{b-body-shadow-color}*/;
}
.ui-body-b {
border-width: 1px;
border-style: solid;
}
/* Links */
.ui-overlay-b a,
.ui-page-theme-b a,
html .ui-bar-b a,
html .ui-body-b a,
html body .ui-group-theme-b a {
color: #33ccff /*{b-link-color}*/;
font-weight: bold;
}
.ui-overlay-b a:visited,
.ui-page-theme-b a:visited,
html .ui-bar-b a:visited,
html .ui-body-b a:visited,
html body .ui-group-theme-b a:visited {
color: #33ccff /*{b-link-visited}*/;
}
.ui-overlay-b a:hover,
.ui-page-theme-b a:hover,
html .ui-bar-b a:hover,
html .ui-body-b a:hover,
html body .ui-group-theme-b a:hover {
color: #3399ff /*{b-link-hover}*/;
}
.ui-overlay-b a:active,
.ui-page-theme-b a:active,
html .ui-bar-b a:active,
html .ui-body-b a:active,
html body .ui-group-theme-b a:active {
color: #3399ff /*{b-link-active}*/;
}
/* Button up */
.ui-overlay-b .ui-btn,
.ui-page-theme-b .ui-btn,
html .ui-bar-b .ui-btn,
html .ui-body-b .ui-btn,
html body .ui-group-theme-b .ui-btn,
html head + body .ui-btn.ui-btn-b,
/* Button visited */
.ui-overlay-b .ui-btn:visited,
.ui-page-theme-b .ui-btn:visited,
html .ui-bar-b .ui-btn:visited,
html .ui-body-b .ui-btn:visited,
html body .ui-group-theme-b .ui-btn:visited,
html head + body .ui-btn.ui-btn-b:visited {
background: #333 /*{b-bup-background-color}*/;
border-color: #1f1f1f /*{b-bup-border}*/;
color: #fff /*{b-bup-color}*/;
text-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;
}
/* Button hover */
.ui-overlay-b .ui-btn:hover,
.ui-page-theme-b .ui-btn:hover,
html .ui-bar-b .ui-btn:hover,
html .ui-body-b .ui-btn:hover,
html body .ui-group-theme-b .ui-btn:hover,
html head + body .ui-btn.ui-btn-b:hover {
background: #373737 /*{b-bhover-background-color}*/;
border-color: #1f1f1f /*{b-bhover-border}*/;
color: #fff /*{b-bhover-color}*/;
text-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;
}
/* Button down */
.ui-overlay-b .ui-btn:active,
.ui-page-theme-b .ui-btn:active,
html .ui-bar-b .ui-btn:active,
html .ui-body-b .ui-btn:active,
html body .ui-group-theme-b .ui-btn:active,
html head + body .ui-btn.ui-btn-b:active {
background: #404040 /*{b-bdown-background-color}*/;
border-color: #1f1f1f /*{b-bdown-border}*/;
color: #fff /*{b-bdown-color}*/;
text-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;
}
/* Active button */
.ui-overlay-b .ui-btn.ui-btn-active,
.ui-page-theme-b .ui-btn.ui-btn-active,
html .ui-bar-b .ui-btn.ui-btn-active,
html .ui-body-b .ui-btn.ui-btn-active,
html body .ui-group-theme-b .ui-btn.ui-btn-active,
html head + body .ui-btn.ui-btn-b.ui-btn-active,
/* Active checkbox icon */
.ui-overlay-b .ui-icon-checkbox-on:after,
.ui-page-theme-b .ui-icon-checkbox-on:after,
html .ui-bar-b .ui-icon-checkbox-on:after,
html .ui-body-b .ui-icon-checkbox-on:after,
html body .ui-group-theme-b .ui-icon-checkbox-on:after,
.ui-btn.ui-icon-checkbox-on.ui-btn-b:after,
/* Active flipswitch background */
.ui-overlay-b .ui-flipswitch-active,
.ui-page-theme-b .ui-flipswitch-active,
html .ui-bar-b .ui-flipswitch-active,
html .ui-body-b .ui-flipswitch-active,
html body .ui-group-theme-b .ui-flipswitch-active,
html body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,
/* Active slider track */
.ui-overlay-b .ui-slider-track .ui-btn-active,
.ui-page-theme-b .ui-slider-track .ui-btn-active,
html .ui-bar-b .ui-slider-track .ui-btn-active,
html .ui-body-b .ui-slider-track .ui-btn-active,
html body .ui-group-theme-b .ui-slider-track .ui-btn-active,
html body div.ui-slider-track.ui-body-b .ui-btn-active {
background-color: #33ccff /*{b-active-background-color}*/;
border-color: #3399ff /*{b-active-border}*/;
color: #fff /*{b-active-color}*/;
text-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #3399ff /*{b-active-shadow-color}*/;
}
/* Active radio button icon */
.ui-overlay-b .ui-icon-radio-on:after,
.ui-page-theme-b .ui-icon-radio-on:after,
html .ui-bar-b .ui-icon-radio-on:after,
html .ui-body-b .ui-icon-radio-on:after,
html body .ui-group-theme-b .ui-icon-radio-on:after,
.ui-btn.ui-icon-radio-on.ui-btn-b:after {
border-color: #33ccff /*{b-active-background-color}*/;
}
/* Focus */
.ui-overlay-b .ui-btn:focus,
.ui-page-theme-b .ui-btn:focus,
html .ui-bar-b .ui-btn:focus,
html .ui-body-b .ui-btn:focus,
html body .ui-group-theme-b .ui-btn:focus,
html head + body .ui-btn.ui-btn-b:focus,
/* Focus buttons and text inputs with div wrap */
.ui-overlay-b .ui-focus,
.ui-page-theme-b .ui-focus,
html .ui-bar-b .ui-focus,
html .ui-body-b .ui-focus,
html body .ui-group-theme-b .ui-focus,
html head + body .ui-btn-b.ui-focus,
html head + body .ui-body-b.ui-focus {
-webkit-box-shadow: 0 0 12px #33ccff /*{b-active-background-color}*/;
-moz-box-shadow: 0 0 12px #33ccff /*{b-active-background-color}*/;
box-shadow: 0 0 12px #33ccff /*{b-active-background-color}*/;
}
/* Disabled
-----------------------------------------------------------------------------------------------------------*/
/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */
.ui-disabled,
.ui-state-disabled,
button[disabled],
.ui-select .ui-btn.ui-state-disabled {
filter: Alpha(Opacity=30);
opacity: .3;
cursor: default !important;
pointer-events: none;
}
/* Focus state outline
-----------------------------------------------------------------------------------------------------------*/
.ui-btn:focus,
.ui-btn.ui-focus {
outline: 0;
}
/* Unset box-shadow in browsers that don't do it right */
.ui-noboxshadow .ui-shadow,
.ui-noboxshadow .ui-shadow-inset,
.ui-noboxshadow .ui-overlay-shadow,
.ui-noboxshadow .ui-shadow-icon.ui-btn:after,
.ui-noboxshadow .ui-shadow-icon .ui-btn:after,
.ui-noboxshadow .ui-focus,
.ui-noboxshadow .ui-btn:focus,
.ui-noboxshadow input:focus,
.ui-noboxshadow .ui-panel {
-webkit-box-shadow: none !important;
-moz-box-shadow: none !important;
box-shadow: none !important;
}
.ui-noboxshadow .ui-btn:focus,
.ui-noboxshadow .ui-focus {
outline-width: 1px;
outline-style: auto;
}

File diff suppressed because one or more lines are too long

View File

@ -18,52 +18,58 @@
.header-breakpoint.ui-grid-b .ui-block-a {
width: 30%;
}
.header-breakpoint.ui-grid-b .ui-block-b {
width: 30%;
}
.header-breakpoint.ui-grid-b .ui-block-c {
width: 30.1%;
}
/*playlists*/
.pl-breakpoint.ui-grid-a .ui-block-a {
width: 32.95%;
}
.pl-breakpoint.ui-grid-a .ui-block-b {
width: 65.4%;
}
.pl-breakpoint.ui-grid-a .ui-block-a {
clear: left;
}
.pl-breakpoint.ui-grid-a .ui-block-a {
clear: left;
}
#playlisttracksdiv {
margin-left: 10px;
}
#playlisttracksback {
display:none;
}
#playlisttracksdiv {
display:block;
}
#playlistslistdiv {
display:block;
}
/*search*/
.srch-breakpoint.ui-grid-a .ui-block-b {
margin-left: .5em;
}
.srch-breakpoint.ui-grid-a .ui-block-a, .srch-breakpoint.ui-grid-a .ui-block-b {
width: 49%;
}
/* .scroll {
overflow-y: auto;
overflow-x: hidden;
}
*/
}
/* phone landscape */
@media all and (max-width: 960px) {
/*header*/
@ -71,45 +77,50 @@
width: 35%;
clear: left;
}
.header-breakpoint.ui-grid-b .ui-block-b {
display: none;
}
.header-breakpoint.ui-grid-b .ui-block-c {
width: 33%;
}
/*playlists*/
.pl-breakpoint .ui-block-a, .pl-breakpoint .ui-block-b {
width: 100%;
}
/*search*/
.srch-breakpoint.ui-grid-a .ui-block-a, .srch-breakpoint.ui-grid-a .ui-block-b {
width: 100%;
}
/* .scroll {
width: 100%;
heigth: 99%;
}
*/
#playlisttracksback {
display:block;
}
#playlisttracksdiv {
display:none;
}
#playlistslistdiv {
display:block;
}
}
/***********
* Side Panel and Navigation
*/
/*****************************
* Side Panel and Navigation *
*****************************/
.mainNav .fa{
float: right;
}
.mainNav .navtxt{
float: left;
}
.mainNav .navtxt:after{
clear: left;
}
@ -121,35 +132,25 @@
}
/**headers and controls**/
#playimg {
margin-top: 2px;
}
#nextimg, #previmg, #backimg, #controlsimg {
margin-top: 6px;
}
#contentHeadline a {
color:white;
margin-left: 20%;
}
#headermenubtn{
width: 50px;
#headermenubtn {
padding-top: 2px;
}
#headersearchbtn{
text-align: right;
}
#headersearchbtn .ui-btn-inner{
padding: 6px;
#headersearchbtn span {
font-size: 15px;
}
/***********************
* Track Slider
***********************/
/******************
* Track Slider *
******************/
#trackslider {
display: inline;
@ -167,6 +168,13 @@
margin-right: 35px;
}
/* Increase slider handle by 30%. */
.ui-slider-track.ui-mini .ui-slider-handle {
height: 22px;
width: 22px;
margin: -12px 0 0 -12px;
}
.ui-slider-input {
display: none !important;
}
@ -180,6 +188,7 @@
* Volume Slider
***********************/
#mutebt {
color: white;
float: left;
margin-left: 8px;
margin-top: 8px;
@ -189,14 +198,22 @@
display: inline;
}
/***********
* pages, content
*/
/********************
* Pages, content *
********************/
#page{
background-color: #fff;
}
#searchresults {
#searchartists {
display: none;
}
#searchalbums {
display: none;
}
#searchtracks {
display: none;
}
@ -204,16 +221,13 @@
display: none;
}
#artistviewimage, #albumviewcover {
float: right;
heigth: 90px;
height: 90px;
max-width: 90%;
}
/*** home ***/
#homerows div {
text-align:center;
background-color: #2C3E50;
@ -226,9 +240,9 @@
#homerows div i {
font-size: 28px;
}
/*********************
* listviews
********************/
/***************
* listviews *
***************/
.table li a {
color: #555 !important;
font-size: 80% !important;
@ -250,22 +264,7 @@
list-style-type:none;
}
/*.table li:first-child { */
/*-moz-border-radius-topleft: 2px;*/
/*-moz-border-radius-topright: 2px;*/
/*-webkit-border-top-left-radius: 2px;*/
/*-webkit-border-top-right-radius: 2px;*/
/*border-top-right-radius: 2px;*/
/*border-top-left-radius: 2px;*/
/*}*/
.table li:last-child {
/*-moz-border-radius-bottomleft: 2px;*/
/*-moz-border-radius-bottomright: 2px;*/
/*-webkit-border-bottom-left-radius: 2px;*/
/*-webkit-border-bottom-right-radius: 2px;*/
/*border-bottom-left-radius: 2px;*/
/*border-bottom-right-radius: 2px;*/
border-bottom: 1px solid #CECECE;
}
@ -279,7 +278,7 @@
.smalldivider {
font-size: 25% !important;
heigth: 5px !important;
height: 5px !important;
background-color: #ddd !important;
}
@ -290,7 +289,6 @@
#playlistslist, #playlisttracks {
margin: 0 !important;
padding: 0 !important;
/* border: 1px solid blue; */
}
.albumli {
@ -304,7 +302,7 @@
.artistcover {
float: right;
width: 30px;
heigth: 30px;
height: 30px;
margin-right: 3px;
margin-top: 3px;
}
@ -336,27 +334,38 @@
}
/*******************
* Now Playing area
*******************/
.nowPlayingControls {
font-size: 20px;
line-height: 45px;
padding-left: 10px;
}
.nowPlayingControls .fa{
vertical-align: -webkit-baseline-middle;
}
.nowPlayingControls #btplayNowPlaying{
font-size: 190%;
margin-left: 15px;
margin-right: 15px;
/**********************
* Now Playing area *
**********************/
#nowPlayingFooter{
height: 50px;
line-height: 48px;
text-align: center;
}
.footerControls {
height: 100%;
font-size: 25px;
padding-right: 10px;
}
/*******************
* Popups
*******************/
.footerControls div span {
padding-left: 3px;
padding-right: 3px;
height: 100%;
vertical-align: middle;
}
.footerControls #btplayNowPlaying {
font-size: 42px;
margin-left: 10px;
margin-right: 10px;
}
/************
* Popups *
************/
#modalalbum a, #modalartist a {
color: #444;
text-decoration: none;
@ -392,10 +401,6 @@
margin-bottom: 15px;
}
#btplayNowPlaying {
padding-top: 15px;
}
#popupTracksLv li, #popupQueueLv li {
border-bottom: 1px solid #aaa;
}
@ -409,15 +414,12 @@
display:block !important;
}
/***************
* common use
***************/
/****************
* Common use *
****************/
#playlistspane {
/* height: 90% !important;*/
margin: 0px !important;
padding: 2px !important;
}
a {
@ -450,22 +452,23 @@ a {
float: right;
}
/**********************
* Song information
* Song information *
**********************/
.ui-footer{
border: 0px;
}
#normalFooter{
height: 48px;
}
#nowPlayingFooter{
height: 50px;
line-height: 48px;
text-align: center;
color: white;
}
#infoname {
overflow: hidden;
white-space: nowrap;
font: bold;
font-weight: bold;
font-size: 14px;
}
@ -476,54 +479,39 @@ a {
}
#infocover {
height: 48px;
width: 48px;
position: absolute;
height: 50px;
width: 50px;
}
.playicon {
width: 10%;
float: right;
text-align: right;
}
.songinfo-text{
display:inline-block;
padding: 6px;
#btplay {
color: white;
position: absolute;
padding-left: 50px;
padding-right: 50px;
}
.playPausebtn{
padding-right: 10px;
position: absolute;
right: 0px;
}
#controldiv{
background: none repeat scroll 0% 0% rgb(44, 62, 80);
height: 48px;
padding: 8px 8px 8px 8px;
.songinfo {
height: 100%;
width: 90%;
float: left;
}
#controldiv img {
margin-left: auto;
margin-right: auto;
display: block;
.songinfo-text {
text-align: left;
line-height: 22px;
color: white;
overflow: hidden;
padding: 3px;
}
#nowPlayingpane{
text-align: center;
}
.footer {
position: fixed;
z-index: 1000;
bottom: 0;
width: 100%;
}
/*helper*/
.hidden{
display: none;
}
@ -531,7 +519,6 @@ a {
color: #efefef;
}
.settingscoll label {
font-size: 120%;
font-weight: bold;
@ -546,12 +533,14 @@ a {
.ui-responsive-panel.ui-page-panel-open .ui-panel-content-wrap-open.ui-panel-content-wrap-display-reveal {
margin-right: 17em;
}
.ui-responsive-panel.ui-page-panel-open .ui-panel-content-fixed-toolbar-open.ui-panel-content-wrap-display-push.ui-panel-content-fixed-toolbar-position-right,
.ui-responsive-panel.ui-page-panel-open .ui-panel-content-fixed-toolbar-open.ui-panel-content-wrap-display-reveal.ui-panel-content-fixed-toolbar-position-right,
.ui-responsive-panel.ui-page-panel-open .ui-panel-content-wrap-open.ui-panel-content-wrap-display-push.ui-panel-content-wrap-position-right,
.ui-responsive-panel.ui-page-panel-open .ui-panel-content-wrap-open.ui-panel-content-wrap-display-reveal.ui-panel-content-wrap-position-right {
margin: 0 0 0 17em;
}
.ui-responsive-panel .ui-panel-dismiss-display-reveal {
display: none;
}
@ -561,29 +550,34 @@ a {
#nowPlayingpane{
padding: 15px 25px 0px 25px;
}
#nowPlayingpane #controlspopupimage{
max-width:90%;
max-height:90%;
}
.nowPlaying-artistInfo {
font-size: 12px;
}
.nowPlaying-artistInfo h4{
margin: 0px;
font-weight: normal;
font-size: 12px;
}
.nowPlaying-artistInfo h3{
margin: 0px 0px 3px 00px;
white-space: nowrap;
overflow: hidden;
}
#controlspopupimage{
max-width:90%;
max-height:90%;
margin-bottom: 3px;
}
#nowPlayingpane #slidercontainer {
margin-left: -5px;
margin-right: -5px;
@ -591,12 +585,12 @@ a {
.nowPlayingControls{
font-size: 1.3em;
line-height: 50px;
height: 50px;
line-height: 48px;
}
}
/* disable text selection for mouse swipe */
body * {
-webkit-user-select: none;
-moz-user-select: none;
@ -604,23 +598,16 @@ body * {
-o-user-select: none;
user-select: none;
}
/* but fix for text input (safari certainly needs it)*/
input[type=text] {
-moz-user-select: text;
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
-o-user-select: text;
user-select: text;
}
/* type/source of media in listviews */
/*a[id^="spotify"] {
margin-left:20px;
background-image: url('../images/icons/play_alt_12x12.png');
border: 2px solid black;
display:block;
}
*/
.mediaicon {
float: right;
}

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
<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.min.css"/>
<script src="js/jquery.mobile-1.3.2.min.js"></script>
</head>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,19 +1,14 @@
<!DOCTYPE html>
<!-- <html manifest="mb.manifest"> -->
<html>
<html manifest="mb.manifest">
<head>
<meta charset="utf-8">
<script src="js/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/jquery.mobile.flatui.css"/>
<!-- <script type='application/javascript' src='js/fastclick.js'></script> -->
<link rel="stylesheet" type="text/css" href="css/jquery.mobile.flatui.min.css"/>
<script>
//configuration
// var wsLocation = location.host + ':6680'; //for normal operation of mopidy http
var wsLocation = location.host; //for running on port 80
if (wsLocation == location.hostname) {
wsLocation = location.hostname + ':6680';
}
var isMusicBox = {{musicbox}}; // Remove MusicBox only content (e.g. settings, system pages)
var isMusicBox = '{{musicbox}}' == 'True'; // Remove MusicBox only content (e.g. settings, system pages)
var websocketUrl = ('{{useWebsocketUrl}}' == 'True') ? '{{websocket_url}}' : ''
var hasAlarmClock = '{{alarmclock}}' == 'True'; // Add Alarm Clock icons
$(document).bind("mobileinit", function () {
$.extend($.mobile, {
@ -58,12 +53,11 @@
<script src="js/jquery.mobile-1.3.2.min.js"></script>
<meta name="description" content="MusicBox" />
<meta name="author" content="Wouter van Wijk" />
<meta name="copyright" content="(c) 2012-2013 Wouter van Wijk" />
<meta name="copyright" content="(c) 2012-2015 Wouter van Wijk" />
<link href="css/webclient.css" rel="stylesheet" />
<link href="css/jquery.mobile.iscrollview.css" rel="stylesheet" />
<link rel="stylesheet" href="css/font-awesome.min.css" />
<!-- <link rel="stylesheet" href="css/add2home.css"> -->
</head>
<body>
@ -100,6 +94,10 @@
<a href="#search" onclick="switchContent('search' ); return false;">
<span class="navtxt">Search </span><i class="fa fa-search"></i></a>
</li>
<li id="navAlarmClock" data-icon="false">
<a href="/alarmclock/">
<span class="navtxt"> Alarm Clock </span><i class="fa fa-clock-o"></i></a>
</li>
<li id="navEnterFullscreen" data-icon="false">
<a href="#">
<span class="navtxt"> Fullscreen </span><i class="fa fa-desktop"></i></a>
@ -118,7 +116,7 @@
</li>
<li id="" data-icon="false">
<div><!-- slider for volume -->
<a href="#" onclick="doMute(); return false;"><i class="fa fa-volume-up" id="mutebt"></i></a>
<a href="#" onclick="doMute(); return false;"><span title="Toggle mute"><i id="mutebt" class="fa fa-volume-up"></i></span></a>
<label for="volumeslider" class="ui-hidden-accessible">Volume</label>
<input id="volumeslider" data-highlight="true" name="volumeslider" data-mini="true" type="range" min="0"
value="0" max="100" onchange="doVolume(this.value);"/>
@ -169,7 +167,7 @@
<div data-role="collapsible-set">
<ul data-role="listview" data-icon="false" id="popupTracksLv">
<li>
<a href="#" onclick="return playTrack();">Play <span class="popupTrackName"></span></a>
<a href="#" onclick="return playTrack(PLAY_NOW);">Play <span class="popupTrackName"></span></a>
</li>
<li class="addqueue">
<a href="#" onclick="return playTrack(PLAY_NEXT);">Play Track Next</a>
@ -224,11 +222,10 @@
<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>
<div data-role="header" data-tap-toggle="false" id="header" data-position="fixed" class="header-breakpoint headerbtn">
<a id="headermenubtn" href="#panel"><i class="fa fa-align-justify"></i></a>
<h1 id="contentHeadline">Musicbox</h1>
<a id="headersearchbtn" href="#" class="ui-btn-icon-right headerbtn" onclick="switchContent('search' ); return false;" title="Search">
<i class="fa fa-search"></i></a>
<a id="headersearchbtn" href="#" onclick="switchContent('search' ); return false;" title="Search"><i class="fa fa-search"></i></a>
</div>
<!-- /header -->
@ -270,14 +267,20 @@
<h4>Search</h4>
</div>
</a>
<a id="homesettings" href="/settings/">
<a id="homeAlarmClock" href="/alarmclock/">
<div class="ui-block-a">
<i class="fa fa-clock-o"></i>
<h4>Alarm Clock</h4>
</div>
</a>
<a id="homesettings" href="/settings/">
<div class="ui-block-b">
<i class="fa fa-gear"></i>
<h4>Settings</h4>
</div>
</a>
<a id="homeshutdown" href="system.html">
<div class="ui-block-b">
<div class="ui-block-a">
<i class="fa fa-power-off"></i>
<h4>System</h4>
</div>
@ -304,11 +307,13 @@
<label for="trackslider" disabled="disabled" class="ui-hidden-accessible">Position</label>
<input id="trackslider" name="trackslider" data-mini="true" type="range" onchange="doSeekPos(this.value);" />
</div>
</div>
<!-- /nowplaying -->
<div data-role="content" id="playlistspane" class="pane ui-grid-a pl-breakpoint">
<div data-role="content" id="playlistspane" class="pane">
<a style="float:right; padding: 1.2em 10px" onclick="return refreshPlaylists();"><i class="fa fa-refresh"></i></a>
<h4>Playlists</h4>
<div class="ui-grid-a pl-breakpoint">
<div class="ui-block-a scroll" id="playlistslistdiv">
<ul id="playlistslist" class="table"></ul>
</div>
@ -316,19 +321,20 @@
<div id="playlisttracksback" style="height: 30px; margin: 2px; padding-top: 2px; background-color: #aaa;"><a style="display:block; padding: 5px;" href="#" onclick="return togglePlaylists();"><i class="fa fa-arrow-circle-left"></i> Back</a></div>
<ul class="table" id="playlisttracks"></ul>
</div>
</div>
</div>
<!--/playlistspane-->
<div data-role="content" id="browsepane" class="pane">
<h3>Browse</h3>
<h4 id="browsepath"></h4>
<h4>Browse</h4>
<h5 id="browsepath"></h5>
<ul id="browselist" class="table"></ul>
</div>
<!--/browsepane-->
<div data-role="content" class="pane" id="currentpane">
<a style="float:right" onclick="return clearQueue();" data-role="button">Clear</a><h4>Play Queue</h4>
<a style="float:right" onclick="return clearQueue();" data-role="button">Clear</a>
<a style="float:right; margin-right: 0.5em" onclick="return saveQueue();" data-role="button">Save</a><h4>Play Queue</h4>
<!-- <ul data-role="listview" data-icon="false" data-theme="d" data-inset="true" id="currenttable"></ul>
<ul data-role="listview" data-icon="false" data-theme="d" data-inset="true" id="currenttable"></ul> -->
<ul class="table" id="currenttable"></ul>
@ -351,21 +357,24 @@
</div>
<div data-role="content" class="pane" id="searchpane">
<div class="">
<h4>Search</h4>
<div class="ui-grid pl-breakpoint">
<div class="ui-block">
<form>
<p>Search for artists, albums, or specific tracks.
<select id="selectSearchService"> <!-- data-native-menu="false"> <!-- multiple="multiple" data-native-menu="false">
<option data-placeholder="true">Choose services</option> -->
</select>
<input id="searchinput" class="span2" data-clear-btn="true"
<input id="searchinput" placeholder="Search term" class="span2" data-clear-btn="true"
onkeypress="return searchPressed(event.keyCode);" id="appendedInputButton" type="text"/>
<button class="btn" type="button" onclick="return initSearch(event.value);">
Search!
</button>
</form>
</div>
</div>
<div id="searchresults">
<div class="ui-grid-a srch-breakpoint">
<div class="ui-block-a" id="searchartists">
<div data-role="listview" data-inset="true">
@ -393,84 +402,70 @@
<h4>Tracks</h4>
<ul id="trackresulttable" class="table"></ul>
</div>
</div>
</div>
<!-- search div -->
<div data-role="content" class="pane" id="streampane">
<h4>Streams</h4>
<div>
<form>
<div class="ui-grid-a pl-breakpoint">
<div class="ui-block-a" style="padding: 5px">
<p>Add an url of a stream that you want to listen to in the box below. You can add uri's for Spotify, SoundCloud, YouTube, Podcasts.
<select id="selectstreamservice" data-native-menu="true">
<option value="">Internet Radio (mp3, m3u, asx, etc)</option>
<option value="yt">YouTube</option>
<option value="">Spotify Uri</option>
<option value="sc">SoundCloud</option>
<option value="podcast">Podcast</option>
</select>
<form>
<p>Play a specific stream/track and optionally save it to your favourites.
<button class="btn" type="button" onclick="return getCurrentlyPlaying();">
Get currently playing
</button>
<input id="streamuriinput" placeholder="URI" class="span2" data-clear-btn="true"
onkeypress="return streamPressed(event.keyCode);" id="appendedInputButton" type="text"/>
<button class="btn" type="button" onclick="return playStreamUri();">
Play
</button>
<p>Put in a name and hit the Save button to save the url (locally, in the browser not
on the server yet). <!-- To find stations, use the Browse function with extensions like Dirble or TuneIn, the right values will appear in these boxes automatically. Or use websites like <a href="http://www.listenlive.eu/" target="_blank">Listenlive</a> or <a
href="http://www.dirble.com/" target="_blank">Dirble</a>.</p> -->
<input id="streamnameinput" placeholder="Name" class="span2" data-clear-btn="true"
onkeypress="return streamPressed(event.keyCode);" id="appendedInputButton" type="text"/>
<button class="btn" type="button" onclick="return saveStreamUri();">
<button class="btn" type="button" onclick="return addFavourite();">
Save
</button>
<br/>
<button class="btn" type="button" onclick="$('#streamuriinput').val(songdata.uri); return true;">
Add currently playing url
</button>
</form>
</div>
<div class="ui-block-b" style="padding: 5px">
<ul id="streamuristable" class="table"></ul>
</div>
</div>
</div>
</div>
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="normalFooter">
<div id="songinfo" class="">
<a href="#"><img id="infocover" src="images/default_cover.png" width="36" height="36"/></a>
<div class="footerControls">
<div class="songinfo" id="songinfo">
<a href="#"><div style="float: left"><img id="infocover" src="images/default_cover.png"/></div></a>
<div class="songinfo-text">
<div id="infoname"></div>
<div id="infoartist"></div>
</div>
</div>
<div id="controldiv" class="playPausebtn">
<a href="#" onclick="doPlay(); return false"><span id="btplay"><img src="images/icons/pause_32x32.png"
alt="Play" id="playimg" title="Play"/></span></a>
<div class="playicon">
<a href="#" onclick="doPlay(); return false"><span id="btplay" title="Play"><i class="fa fa-play"></i></span></a>
</div>
</div>
</div>
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="nowPlayingFooter">
<p id="buttons" style="float:right; margin-top: 20px; margin-right: 5px;">
<a href="#" onclick="doRandom(); return false" title="Random"><i class="fa fa-random" id="randombt"></i></a>
&nbsp; <a href="#" onclick="doRepeat(); return false" title="Repeat"><i class="fa fa-repeat" id="repeatbt"></i></a>
&nbsp; <a href="#" onclick="doConsume(); return false" title="Consume"><i class="fa fa-cutlery" id="consumebt"></i></a>
&nbsp; <a href="#" onclick="doSingle(); return false" title="Single"><i class="fa fa-dot-circle-o" id="singlebt"></i></a>
&nbsp; <a href="#" onclick="doShuffle(); return false" title="Shuffle"><i class="fa fa-arrows-v" id="shufflebt"></i></a>
</p>
<div class="nowPlayingControls" style="float:left; margin-left: 5px;">
<div class="footerControls" style="padding-left: 10px;">
<div style="float: left;">
<a href="#" onclick="doPrevious(); return false"><span id="btprev" title="Previous"><i class="fa fa-fast-backward"></i></span></a>
&nbsp; <a href="#" onclick="doPlay(); return false"><span id="btplayNowPlaying" title="Play"><i class="fa fa-play"></i></span></a>
&nbsp; <a href="#" onclick="doNext(); return false"><span id="btnext" title="Next"><i class="fa fa-fast-forward"></i></span></a>
<a href="#" onclick="doPlay(); return false"><span id="btplayNowPlaying" title="Play"><i class="fa fa-play"></i></span></a>
<a href="#" onclick="doNext(); return false"><span id="btnext" title="Next"><i class="fa fa-fast-forward"></i></span></a>
</div>
<div style="float: right; margin-right: 10px;">
<a href="#" onclick="doRandom(); return false"><span id="randombt" title="Random"><i class="fa fa-random"></i></span></a>
<a href="#" onclick="doRepeat(); return false"><span id="repeatbt" title="Repeat"><i class="fa fa-repeat"></i></span></a>
<a href="#" onclick="doConsume(); return false"><span id="consumebt" title="Consume"><i class="fa fa-cutlery"></i></span></a>
<a href="#" onclick="doSingle(); return false"><span id="singlebt" title="Single"><i class="fa fa-dot-circle-o"></i></span></a>
<a href="#" onclick="doShuffle(); return false"><span id="shufflebt" title="Shuffle"><i class="fa fa-arrows-v"></i></span></a>
</div>
</div>
</div>
<!-- /footer -->
@ -479,15 +474,12 @@
<!-- /page one -->
<script type="text/javascript" src="../mopidy/mopidy.min.js"></script>
<script type="text/javascript" src="js/iscroll-lite.js"></script>
<!-- <script type="text/javascript" src="js/jquery.mobile.iscrollview-closure-min.js"></script> -->
<script src="js/jquery.cookie.js"></script>
<script src="js/jquery.truncate.min.js"></script>
<!-- <script type="text/javascript" src="js/add2home.js" charset="utf-8"></script> -->
<script src="js/controls.js"></script>
<script src="js/library.js"></script>
<script src="js/functionsvars.js"></script>
<script src="js/process_ws.js"></script>
<script src="js/streamuris.js"></script>
<!-- use lastfm -->
<script type="text/javascript" src="js/lastfm.api.md5.js"></script>

View File

@ -1,162 +1,113 @@
/********************************************************
* play tracks from a browse list
*********************************************************/
function playBrowsedTracks(addtoqueue, trackid) {
//stop directly, for user feedback.
if (addtoqueue == PLAY_ALL) {
mopidy.playback.stop();
mopidy.tracklist.clear();
}
/***********************************
* play tracks from a browse list *
***********************************/
function playBrowsedTracks(action, trackIndex) {
$('#popupBrowse').popup('close');
toast('Loading...');
trackid = typeof trackid !== 'undefined' ? trackid : $('#popupBrowse').data("track");
var selected = 0, counter = 0;
var isStream = isStreamUri(trackid);
//only add one uri for dirble, tunein; otherwise add all tracks
if (isStream) {
mopidy.tracklist.add(null, null, trackid);
} else {
switch (addtoqueue) {
if (typeof trackIndex === 'undefined') {
trackIndex = $('#popupBrowse').data("tlid");
}
if (action == PLAY_ALL) {
mopidy.tracklist.clear();
// Default for radio streams is to just add the selected URI.
if (isStreamUri(browseTracks[trackIndex].uri)) {
action = PLAY_NOW;
}
}
var trackUris = [];
switch (action) {
case PLAY_NOW:
case PLAY_NEXT:
//find track that is playing
for (var playing = 0; playing < currentplaylist.length; playing++) {
if (currentplaylist[playing].uri == songdata.uri) {
break;
}
}
mopidy.tracklist.add(null, playing + 1, trackid);
break;
case ADD_THIS_BOTTOM:
mopidy.tracklist.add(null, null, trackid);
trackUris.push(browseTracks[trackIndex].uri);
break;
case ADD_ALL_BOTTOM:
case PLAY_ALL:
//add selected item to the playlist
$('.browsetrack').each(function() {
if (this.id == trackid) {
selected = counter;
}
mopidy.tracklist.add(null, null, this.id);
counter++;
});
case ADD_ALL_BOTTOM:
trackUris = getUris(browseTracks);
break;
default:
break;
}
var maybePlay = function(tlTracks) {
if (action === PLAY_NOW || action === PLAY_ALL) {
var playIndex = (action === PLAY_ALL) ? trackIndex : 0;
mopidy.playback.play({'tl_track': tlTracks[playIndex]});
}
};
switch (action) {
case PLAY_NOW:
case PLAY_NEXT:
mopidy.tracklist.index().then(function (currentIndex) {
mopidy.tracklist.add({'at_position': currentIndex + 1, 'uris': trackUris}).then(maybePlay);
});
break;
case ADD_THIS_BOTTOM:
case ADD_ALL_BOTTOM:
case PLAY_ALL:
mopidy.tracklist.add({'uris': trackUris}).then(maybePlay);
break;
default:
break;
}
//play selected item
if (addtoqueue == PLAY_ALL) {
mopidy.playback.stop();
for (var i = 0; i <= selected; i++) {
mopidy.playback.next();
}
mopidy.playback.play(); //tracks[selected]);
} else if (addtoqueue == PLAY_NOW) {
mopidy.playback.stop();
mopidy.playback.next();
mopidy.playback.play();
}
//add all items, but selected to the playlist
selected = 0;
counter = 0
/* if(!isStream) {
$('.browsetrack').each(function() {
//do not add selected song again
if (this.id == trackid) {
selected = counter;
} else {
mopidy.tracklist.add(null, counter, this.id);
}
counter++;
} );
}
*/
return false;
}
/********************************************************
* play an uri from a tracklist
*********************************************************/
function playTrack(addtoqueue) {
/*********************************
* play an uri from a tracklist *
*********************************/
function playTrack(action) {
var hash = document.location.hash.split('?');
var divid = hash[0].substr(1);
if (!addtoqueue) {
addtoqueue = PLAY_NOW;
// Search page default click behaviour adds and plays selected track only.
if (action == PLAY_NOW && divid == 'search') {
action = PLAY_NOW_SEARCH;
}
// console.log(addtoqueue, divid);
//stop directly, for user feedback. If searchresults, also clear queue
if (!addtoqueue || ((addtoqueue == PLAY_NOW) && (divid == 'search'))) {
mopidy.playback.stop();
mopidy.tracklist.clear();
}
$('#popupTracks').popup('close');
$('#controlspopup').popup('close');
toast('Loading...');
playlisturi = $('#popupTracks').data("list");
uri = $('#popupTracks').data("track");
var trackslist = new Array();
var track, tracksbefore, tracksafter;
var tracks = getTracksFromUri(playlisturi);
var trackUris = getTracksFromUri(playlisturi);
//find track that was selected
for (var selected = 0; selected < tracks.length; selected++) {
if (tracks[selected].uri == uri) {
for (var selected = 0; selected < trackUris.length; selected++) {
if (trackUris[selected] == uri) {
break;
}
}
//find track that is playing
for (var playing = 0; playing < currentplaylist.length; playing++) {
if (currentplaylist[playing].uri == songdata.uri) {
break;
}
}
//switch popup options
switch (addtoqueue) {
case PLAY_NOW:
if (divid == 'search') {
mopidy.tracklist.add(tracks.slice(selected, selected + 1));
mopidy.playback.play();
return false;
}
switch (action) {
case ADD_THIS_BOTTOM:
mopidy.tracklist.add(tracks.slice(selected, selected + 1));
return false;
case PLAY_NEXT:
mopidy.tracklist.add(tracks.slice(selected, selected + 1), playing + 1);
return false;
case PLAY_NOW_SEARCH:
trackUris = [trackUris[selected]];
selected = 0;
}
switch (action) {
case PLAY_NOW:
case PLAY_NOW_SEARCH:
mopidy.tracklist.clear().then(
mopidy.tracklist.add({'uris': trackUris}).then(
function(tlTracks) {
mopidy.playback.play({'tl_track': tlTracks[selected]})
}
)
);
break;
case PLAY_NEXT:
mopidy.tracklist.index().then(function(currentIndex) {
mopidy.tracklist.add({'at_position': currentIndex + 1, 'uris': trackUris});
});
break;
case ADD_THIS_BOTTOM:
case ADD_ALL_BOTTOM:
mopidy.tracklist.add(tracks);
return false;
mopidy.tracklist.add({'uris': trackUris});
break;
}
// PLAY_NOW, play the selected track
// mopidy.tracklist.add(null, null, uri); //tracks);
mopidy.tracklist.add(tracks);
if (!addtoqueue) {
mopidy.playback.stop();
for (var i = 0; i <= selected; i++) {
mopidy.playback.next();
}
mopidy.playback.play();
}
return false;
}
@ -167,20 +118,20 @@ function playTrack(addtoqueue) {
*/
function playTrackByUri(track_uri, playlist_uri) {
function findAndPlayTrack(tltracks) {
// console.log('fa', tltracks, track_uri);
if (tltracks == []) { return;}
if (tltracks.length > 0) {
// 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]);
mopidy.playback.play({'tl_track': tltracks[selected]});
return;
}
}
console.log('Failed to play selected track ', track_uri);
}
console.error('Failed to find and play selected track ', track_uri);
return;
}
// Stop directly, for user feedback
mopidy.playback.stop();
mopidy.tracklist.clear();
//this is deprecated, remove when popuptracks is removed completly
@ -190,18 +141,15 @@ function playTrackByUri(track_uri, playlist_uri) {
toast('Loading...');
var func;
func = mopidy.tracklist.add(null, null, playlist_uri);
func.then(
function(tltracks) {
//check if tltracks is filled, some backends (gmusic) do not support adding by uri, it seems
mopidy.tracklist.add({'uris': [playlist_uri]}).then(function(tltracks) {
// Can fail for all sorts of reasons. If so, just add individually.
if (tltracks.length == 0) {
var tracks = getTracksFromUri(playlist_uri);
mopidy.tracklist.add(tracks).then(findAndPlayTrack);
}
var trackUris = getTracksFromUri(playlist_uri, false);
mopidy.tracklist.add({'uris': trackUris}).then(findAndPlayTrack);
} else {
findAndPlayTrack(tltracks);
}
).then(getCurrentPlaylist()); // Updates some state
});
return false;
}
@ -212,25 +160,25 @@ function playTrackByUri(track_uri, playlist_uri) {
/***
* Plays a Track from a Playlist.
* @param uri
* @param playlisturi
* @param tlid
* @returns {boolean}
*/
function playTrackQueueByUri(uri, playlisturi) {
// console.log('playquuri');
function playTrackQueueByTlid(uri, tlid) {
//stop directly, for user feedback
mopidy.playback.stop();
$('#popupQueue').popup('close');
toast('Loading...');
tlid = parseInt(tlid);
mopidy.tracklist.filter({
'uri': [uri]
'tlid': [tlid]
}).then(
function(tltracks) {
if (tltracks.length > 0) {
mopidy.playback.play(tltracks[0]);
mopidy.playback.play({'tl_track': tltracks[0]});
return;
}
console.log('Failed to play selected track ', uri);
console.log('Failed to play selected track ', tlid);
}
);
return false;
@ -241,31 +189,21 @@ function playTrackQueueByUri(uri, playlisturi) {
* @returns {boolean}
*/
function playTrackQueue() {
// console.log('playqu');
playlisturi = $('#popupQueue').data("list");
uri = $('#popupQueue').data("track");
return playTrackQueueByUri(uri, playlisturi);
tlid = $('#popupQueue').data("tlid");
return playTrackQueueByTlid(uri, tlid);
}
/********************************************************
* remove a track from the queue
*********************************************************/
/***********************************
* remove a track from the queue *
***********************************/
function removeTrack() {
$('#popupQueue').popup('close');
toast('Deleting...');
uri = $('#popupQueue').data("track");
console.log(uri);
for (var i = 0; i < currentplaylist.length; i++) {
if (currentplaylist[i].uri == uri) {
break;
}
}
var track = {};
track.uri = [currentplaylist[i].uri];
mopidy.tracklist.remove({'uri':track.uri});
// console.log(currentplaylist[i].uri);
tlid = parseInt($('#popupQueue').data("tlid"));
console.log(tlid);
mopidy.tracklist.remove({'tlid': [tlid]});
}
function clearQueue() {
@ -276,9 +214,38 @@ function clearQueue() {
return false;
}
/**********************
* Buttons
*/
function saveQueue() {
mopidy.tracklist.getTracks().then(function(tracks) {
if (tracks.length > 0) {
var plname = window.prompt("Playlist name:", "").trim();
if (plname != null && plname != "") {
mopidy.playlists.filter({"name": plname}).then(function(existing) {
var exists = false;
for (var i = 0; i < existing.length; i++) {
exists = exists || existing[i].uri.indexOf("m3u:") == 0 || existing[i].uri.indexOf("local:") == 0;
}
if (!exists || window.confirm("Overwrite existing playlist \"" + plname + "\"?")) {
mopidy.playlists.create({'name': plname, 'uri_scheme': "local"}).then(function(playlist) {
playlist.tracks = tracks;
mopidy.playlists.save({'playlist': playlist}).then();
getPlaylists();
});
}
});
}
}
});
return false;
}
function refreshPlaylists() {
mopidy.playlists.refresh();
return false;
}
/*************
* Buttons *
*************/
function doShuffle() {
mopidy.playback.stop();
@ -289,15 +256,15 @@ function doShuffle() {
/* Toggle state of play button */
function setPlayState(nwplay) {
if (nwplay) {
$("#playimg").attr('src', 'images/icons/pause_32x32.png');
$("#playimg").attr('title', 'Pause');
$("#btplayNowPlaying >i").removeClass('fa-play').addClass('fa-pause');
$("#btplayNowPlaying").attr('title', 'Pause');
$("#btplay >i").removeClass('fa-play').addClass('fa-pause');
$("#btplay").attr('title', 'Pause');
} else {
$("#playimg").attr('src', 'images/icons/play_alt_32x32.png');
$("#playimg").attr('title', 'Play');
$("#btplayNowPlaying >i").removeClass('fa-pause').addClass('fa-play');
$("#btplayNowPlaying").attr('title', 'Play');
$("#btplay >i").removeClass('fa-pause').addClass('fa-play');
$("#btplay").attr('title', 'Play');
}
play = nwplay;
}
@ -308,7 +275,7 @@ function doPlay() {
if (!play) {
mopidy.playback.play();
} else {
if(isStreamUri(songdata.uri)) {
if(isStreamUri(songdata.track.uri)) {
mopidy.playback.stop();
} else {
mopidy.playback.pause();
@ -332,10 +299,9 @@ function backbt() {
return false;
}
/***************
* Options
***************/
/*************
* Options *
*************/
function setTracklistOption(name, new_value) {
if (!new_value) {
$("#"+name+"bt").attr('style', 'color:#2489ce');
@ -370,27 +336,26 @@ function setSingle(nwsingle) {
}
function doRandom() {
mopidy.tracklist.setRandom(!random).then();
mopidy.tracklist.setRandom({'value': !random}).then();
}
function doRepeat() {
mopidy.tracklist.setRepeat(!repeat).then();
mopidy.tracklist.setRepeat({'value': !repeat}).then();
}
function doConsume() {
mopidy.tracklist.setConsume(!consume).then();
mopidy.tracklist.setConsume({'value': !consume}).then();
}
function doSingle() {
mopidy.tracklist.setSingle(!single).then();
mopidy.tracklist.setSingle({'value': !single}).then();
}
/*********************
* Track Slider
* Use a timer to prevent looping of commands
*********************/
/***********************************************
* Track Slider *
* Use a timer to prevent looping of commands *
***********************************************/
function doSeekPos(value) {
var val = $("#trackslider").val();
newposition = Math.round(val);
@ -406,10 +371,7 @@ function doSeekPos(value) {
function triggerPos() {
if (mopidy) {
posChanging = true;
// mopidy.playback.pause();
// console.log(newposition);
mopidy.playback.seek(newposition);
// mopidy.playback.resume();
mopidy.playback.seek({'time_position': newposition});
resumePosTimer();
posChanging = false;
}
@ -431,54 +393,51 @@ function setPosition(pos) {
$("#songelapsed").html(timeFromSeconds(currentposition / 1000));
}
/********************
* Volume slider
* Use a timer to prevent looping of commands
*/
/***********************************************
* Volume slider *
* Use a timer to prevent looping of commands *
***********************************************/
function setVolume(value) {
var oldval = initgui;
initgui = true;
if ($("#volumeslider").val() != value) {
$("#volumeslider").val(value).slider('refresh');
initgui = oldval;
}
}
function doVolume(value) {
if (!initgui) {
volumeChanging = value;
clearInterval(volumeTimer);
volumeTimer = setTimeout(triggerVolume, 500);
}
}
function triggerVolume() {
mopidy.playback.setVolume(parseInt(volumeChanging));
mopidy.playback.setVolume({'volume': parseInt(volumeChanging)});
volumeChanging = 0;
}
function doMute() {
//only emit the event, not the status
if (muteVolume == -1) {
$("#mutebt").attr('src', 'images/icons/volume_mute_24x18.png');
muteVolume = currentVolume;
mopidy.playback.setVolume(0).then();
function setMute(nwmute) {
if (mute != nwmute) {
mute = nwmute;
if (mute) {
$("#mutebt").attr('class', 'fa fa-volume-off');
} else {
$("#mutebt").attr('src', 'images/icons/volume_24x18.png');
mopidy.playback.setVolume(muteVolume).then();
muteVolume = -1;
$("#mutebt").attr('class', 'fa fa-volume-up');
}
}
}
/*******
* Track position timer
*/
function doMute() {
mopidy.mixer.setMute({'mute': !mute});
}
/**************************
* Track position timer *
**************************/
//timer function to update interface
function updatePosTimer() {
currentposition += TRACK_TIMER;
setPosition(currentposition);
// $("#songelapsed").html(timeFromSeconds(currentposition / 1000));
}
function resumePosTimer() {
@ -498,9 +457,9 @@ function pausePosTimer() {
clearInterval(posTimer);
}
/*********************************
* Stream
*********************************/
/************
* Stream *
************/
function streamPressed(key) {
if (key == 13) {
playStreamUri();
@ -522,9 +481,9 @@ function playStreamUri(uri) {
mopidy.playback.stop();
//hide ios/android keyboard
document.activeElement.blur();
$("input").blur();
clearQueue();
mopidy.tracklist.add(null, null, nwuri);
$("input").blur();
mopidy.tracklist.add({'uris': [nwuri]});
mopidy.playback.play();
} else {
toast('No valid url!');
@ -532,71 +491,179 @@ function playStreamUri(uri) {
return false;
}
function saveStreamUri(nwuri) {
var i = 0;
var name = $('#streamnameinput').val().trim();
var uri = nwuri || $('#streamuriinput').val().trim();
var service = $('#selectstreamservice').val();
if (service) {
uri = serviceupdateStreamUris + ':' + uri;
function getCurrentlyPlaying() {
$('#streamuriinput').val(songdata.track.uri);
var name = songdata.track.name;
if (songdata.track.artists) {
var artistStr = artistsToString(songdata.track.artists);
if (artistStr) {
name = artistStr + ' - ' + name;
}
toast('Adding stream ' + uri, 500);
//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;
$('#streamnameinput').val(name);
return true;
}
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];
function getUriSchemes() {
uriSchemes = {};
return mopidy.getUriSchemes().then(function(schemes) {
for (var i = 0; i < schemes.length; i++) {
uriSchemes[schemes[i].toLowerCase()] = true;
}
}
}
$.cookie.json = true;
$.cookie('streamUris', streamUris);
updateStreamUris();
return false;
});
}
function updateStreamUris() {
var tmp = '';
function getPlaylistByName(name, scheme, create) {
var uri_scheme = scheme || '';
var uri = '';
if (uri_scheme && !uriSchemes[uri_scheme]) {
return Mopidy.when(false);
}
return mopidy.playlists.asList().catch(console.error.bind(console)).then(function(plists) {
for (var i = 0; i < plists.length; i++) {
if ((plists[i].name === name) && (uri_scheme === '' || getScheme(plists[i].uri) === uri_scheme)) {
return plists[i];
}
}
if (create) {
return mopidy.playlists.create({'name': name, 'uri_scheme': uri_scheme}).done(function(plist) {
console.log("Created playlist '%s'", plist.name);
return plist;
});
}
console.log("Can't find playist '%s", name);
return Mopidy.when(false);
});
}
function getPlaylistFull(uri) {
return mopidy.playlists.lookup({'uri': uri}).then(function(pl) {
playlists[uri] = pl;
return pl;
});
}
function getFavourites() {
return getPlaylistByName(STREAMS_PLAYLIST_NAME,
STREAMS_PLAYLIST_SCHEME,
true).then(function(playlist) {
if (playlist) {
return getPlaylistFull(playlist.uri);
}
return Mopidy.when(false);
});
}
function addToFavourites(newTracks) {
getFavourites().catch(console.error.bind(console)).then(function(favourites) {
if (favourites) {
if (favourites.tracks) {
Array.prototype.push.apply(favourites.tracks, newTracks)
} else {
favourites.tracks = newTracks;
}
mopidy.playlists.save({'playlist': favourites}).then(function(s) {
showFavourites();
});
}
});
}
function addFavourite(uri, name) {
var uri = uri || $('#streamuriinput').val().trim();
var name = name || $('#streamnameinput').val().trim();
mopidy.library.lookup({'uris': [uri]}).then(function(results) {
var newTracks = results[uri];
if (newTracks.length == 1) {
// TODO: Supporting adding an entire playlist?
if (name) {
newTracks[0].name = name; // User overrides name.
}
addToFavourites(newTracks);
} else {
if (newTracks.length == 0) {
console.log('No tracks to add');
} else {
console.log('Too many tracks (%d) to add', tracks.length);
}
}
});
}
function deleteFavourite(index) {
getFavourites().then(function(favourites) {
if (favourites && favourites.tracks && index < favourites.tracks.length) {
var name = favourites.tracks[index].name;
if (confirm("Are you sure you want to remove '" + name + "'?")) {
favourites.tracks.splice(index, 1);
mopidy.playlists.save({'playlist': favourites}).then(function(s) {
showFavourites();
});
}
}
});
}
function showFavourites() {
$('#streamuristable').empty();
getFavourites().then(function(favourites) {
if (!favourites) {
return;
}
var tmp = '';
$.cookie.json = true;
if ($.cookie('streamUris')) {
tmp = '<button class="btn" style="padding: 5px; width: 100%" type="button" onclick="return upgradeStreamUrisToFavourites();">Convert StreamUris</button>'
}
if (favourites.tracks) {
var child = '';
for (var key in streamUris) {
var rs = streamUris[key];
if (rs) {
name = 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>' +
for (var i = 0; i < favourites.tracks.length; i++) {
child = '<li><span class="ui-icon ui-icon-delete ui-icon-shadow" style="float:right; margin: .5em; margin-top: .8em;"><a href="#" onclick="return deleteFavourite(\'' + i + '\');">&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>';
' <a style="margin-left: 20px" href="#" onclick="return playStreamUri(\'' + favourites.tracks[i].uri + '\');">';
child += '<h1>' + favourites.tracks[i].name + '</h1></a></li>';
tmp += child;
}
}
$('#streamuristable').html(tmp);
});
}
function initStreams() {
// TODO: Remove this upgrade path in next major release.
function upgradeStreamUrisToFavourites() {
toast('Converting streamUris...');
$.cookie.json = true;
tmpRS = $.cookie('streamUris');
streamUris = tmpRS || streamUris;
updateStreamUris();
var streamUris = $.cookie('streamUris'); // Read the cookie.
if (streamUris) {
var uris = []; // Prepare a list of uris to lookup.
for (var key in streamUris) {
var rs = streamUris[key];
if (rs) {
uris.push(rs[1]);
}
}
mopidy.library.lookup({'uris': uris}).then(function(results) {
var tracks = []; // Prepare a list of tracks to add.
for (var key in streamUris) {
var rs = streamUris[key];
if (rs) {
var track = results[rs[1]][0];
if (track) {
track.name = rs[0] || track.name; // Use custom name if provided.
tracks.push(track);
} else {
console.log("Skipping unplayable streamUri " + rs[1]);
}
}
}
addToFavourites(tracks);
$.cookie('streamUris', null); // Delete the cookie now we're done.
console.log(tracks.length + " streamUris added to favourites");
});
} else {
console.log("No streamUris cookie found");
}
}
function haltSystem() {

View File

@ -4,12 +4,6 @@
* 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
@ -19,7 +13,7 @@ var repeat;
var consume;
var single;
var currentVolume = -1;
var muteVolume = -1;
var mute;
var volumeChanging = false;
var posChanging = false;
@ -34,19 +28,23 @@ var songlength = 0;
var artistshtml = '';
var artiststext = '';
var songname = '';
var songdata = '';
var songdata = {'track': {}, 'tlid': -1};
var newposition = 0;
var playlisttracksScroll;
var playlistslistScroll;
var STREAMS_PLAYLIST_NAME = '[Radio Streams]';
var STREAMS_PLAYLIST_SCHEME = 'm3u';
var uriSchemes = {};
//array of cached playlists (not only user-playlists, also search, artist, album-playlists)
var playlists = {};
var currentplaylist;
var customPlaylists = [];
var customTracklists = [];
var browseStack = [];
var browseTracks = [];
var ua = navigator.userAgent,
isMobileSafari = /Mac/.test(ua) && /Mobile/.test(ua),
@ -56,7 +54,6 @@ var ua = navigator.userAgent,
//constants
PROGRAM_NAME = 'MusicBox';
//PROGRAM_NAME = 'Mopidy';
ARTIST_TABLE = '#artiststable';
ALBUM_TABLE = '#albumstable';
PLAYLIST_TABLE = '#playlisttracks';
@ -66,11 +63,14 @@ SEARCH_ALBUM_TABLE = '#albumresulttable';
SEARCH_ARTIST_TABLE = '#artistresulttable';
SEARCH_TRACK_TABLE = '#trackresulttable';
URI_SCHEME = 'mbw';
PLAY_NOW = 0;
PLAY_NEXT = 1;
ADD_THIS_BOTTOM = 2;
ADD_ALL_BOTTOM = 3;
PLAY_ALL = 4;
PLAY_NOW_SEARCH = 5;
MAX_TABLEROWS = 50;
@ -87,6 +87,7 @@ var uriClassList = [
['spotify', 'fa-spotify'],
['spotifytunigo', 'fa-spotify'],
['local', 'fa-file-sound-o'],
['m3u', 'fa-file-sound-o'],
['podcast', 'fa-rss-square'],
['dirble', 'fa-microphone'],
['tunein', 'fa-headphones'],
@ -105,6 +106,7 @@ var uriHumanList = [
['spotify', 'Spotify'],
['spotifytunigo', 'Spotify Browse'],
['local', 'Local Files'],
['m3u', 'Local Playlists'],
['podcast', 'Podcasts'],
['dirble', 'Dirble'],
['tunein', 'TuneIn'],
@ -117,11 +119,6 @@ var uriHumanList = [
['subsonic', 'Subsonic']
];
var uriServiceDetectList = [
['youtube.com', 'yt'],
['soundcloud.com', 'sc']
];
function scrollToTop() {
var divtop = 0;
$('body,html').animate({
@ -130,11 +127,7 @@ function scrollToTop() {
}
function scrollToTracklist() {
/* if (isMobileWebkit) {
playlistslistScroll.refresh();
}
*/
var divtop = $("#playlisttracksdiv").offset().top - 50;
var divtop = $("#playlisttracksdiv").offset().top - 120;
$('body,html').animate({
scrollTop: divtop
}, 250);
@ -161,6 +154,20 @@ function getAlbum(pl) {
};
}
function artistsToString(artists, max) {
var result = '';
max = max || 3;
for (var i = 0; i < artists.length && i < max; i++) {
if (artists[i].name) {
if (i > 0) {
result += ', ';
}
result += artists[i].name;
}
}
return result;
}
/********************************************************
* break up results and put them in album tables
*********************************************************/
@ -172,14 +179,14 @@ function albumTracksToTable(pl, target, uri) {
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 += renderSongLi(pl[i], liID, uri);
};
tmp += '</ul>';
$(target).html(tmp);
$(target).attr('data', uri);
}
function renderSongLi(song, liID, uri, playlistType) {
function renderSongLi(song, liID, uri) {
var name;
if (!song.name || song.name == '') {
name = uri.split('/');
@ -187,15 +194,28 @@ function renderSongLi(song, liID, uri, playlistType) {
} 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>' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackByUri(\'' + song.uri + '\',\'' + uri + '\');">' +
'<h1 class="trackname">' + name + '</h1></a>' +
'</li>';
return songLi;
}
function renderQueueSongLi(song, liID, uri, tlid) {
var name;
if (!song.name || song.name == '') {
name = uri.split('/');
name = decodeURI(name[name.length - 1]);
} else {
name = song.name;
}
songLi = '<li class="song albumli" id="' + liID + '" tlid="' + tlid + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + '\',\'' + tlid + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackQueueByTlid(\'' + song.uri + '\',\'' + tlid + '\');">' +
'<h1 class="trackname">' + name + '</h1></a>' +
'</li>';
return songLi;
}
@ -204,15 +224,16 @@ function resultsToTables(results, target, uri) {
if (!results) {
return
}
if (target == '#currenttable') {
playlistType = 'playTrackQueueByUri';
} else if (target == SEARCH_TRACK_TABLE) {
playlistType = 'playTrackByUri';
} else {
playlistType = 'playTrackByUri';
var tlids = [];
if (target == CURRENT_PLAYLIST_TABLE) {
for (i = 0; i < results.length; i++) {
tlids[i] = results[i].tlid;
results[i] = results[i].track;
}
}
var newalbum = [];
var newtlids = [];
//keep a list of albums for retreiving of covers
var coversList = [];
var nextname = '';
@ -228,7 +249,7 @@ function resultsToTables(results, target, uri) {
for (i = 0; i < length; i++) {
//create album if none extists
if (!results[i].album) {
results[i].album = {};
results[i].album = {"__model__": "Album"};
}
//create album uri if there is none
if (!results[i].album.uri) {
@ -247,6 +268,7 @@ function resultsToTables(results, target, uri) {
if (results[i].name.substring(0, 12) == '[unplayable]') continue;
newalbum.push(results[i]);
newtlids.push(tlids[i]);
nextname = '';
if ((i < length - 1) && results[i + 1].album && results[i + 1].album.name) {
nextname = results[i + 1].album.name;
@ -254,6 +276,7 @@ function resultsToTables(results, target, uri) {
if (results[i].length == -1) {
html += '<li class="albumli"><a href="#"><h1><i class="' + iconClass + '"></i> ' + results[i].name + ' [Stream]</h1></a></li>';
newalbum = [];
newtlids = [];
nextname = '';
} else {
if ((results[i].album.name != nextname) || (nextname == '')) {
@ -264,12 +287,21 @@ function resultsToTables(results, target, uri) {
html += '<li class="smalldivider"> &nbsp;</li>';
}
iconClass = getMediaClass(newalbum[0].uri);
html += '<li class="song albumli" id="' + targetmin + '-' + newalbum[0].uri + '">' +
var liID = targetmin + '-' + newalbum[0].uri;
if (target == CURRENT_PLAYLIST_TABLE) {
html += '<li class="song albumli" id="' + liID + '" tlid="' + newtlids[0] + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[0].uri + '\',\'' + newtlids[0] + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackQueueByTlid(\'' + newalbum[0].uri + '\',\'' + newtlids[0] + '\');">' +
'<h1><i class="' + iconClass + '"></i> ' + newalbum[0].name + "</h1><p>";
} else {
html += '<li class="song albumli" id="' + liID + '">' +
'<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 + '\');">' +
'<a href="#" onclick="return playTrackByUri(\'' + 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;
@ -289,9 +321,9 @@ function resultsToTables(results, target, uri) {
popupData[newalbum[0].uri] = newalbum[0];
newalbum = [];
newtlids = [];
} 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="' +
@ -311,16 +343,16 @@ function resultsToTables(results, target, uri) {
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>';
if (target == CURRENT_PLAYLIST_TABLE) {
html += renderQueueSongLi(newalbum[j], liID, uri, newtlids[j]);
} else {
html += renderSongLi(newalbum[j], liID, uri);
}
}
newalbum = [];
newtlids = [];
if (results[i].album) {
coversList.push([results[i].album, i]);
}
@ -336,7 +368,6 @@ function resultsToTables(results, target, 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');
}
}
@ -354,7 +385,6 @@ function playlisttotable(pl, target, 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;
@ -376,21 +406,33 @@ function playlisttotable(pl, target, uri) {
$(target).attr('data', uri);
}
function getPlaylistFromUri(uri) {
if (playlists[uri]) {
return playlists[uri];
}
if (customPlaylists[uri]) {
return customPlaylists[uri];
function getPlaylistTracks(uri) {
if (playlists[uri] && playlists[uri].tracks) {
return Mopidy.when(playlists[uri].tracks);
} else {
showLoading(true);
return mopidy.playlists.getItems({'uri': uri}).then(function(refs) {
return processPlaylistItems({'uri': uri, 'items': refs});
}, console.error);
}
}
function getTracksFromUri(uri) {
var pl = getPlaylistFromUri(uri);
if (pl) {
return pl.tracks;
} else if (customTracklists[uri]) {
return customTracklists[uri];
function getUris(tracks) {
var results = [];
for (var i = 0; i < tracks.length; i++) {
results.push(tracks[i].uri);
}
return results;
}
function getTracksFromUri(uri, full_track_data) {
var returnTracksOrUris = function(tracks) {
return (full_track_data || false) ? tracks : getUris(tracks);
}
if (customTracklists[uri]) {
return returnTracksOrUris(customTracklists[uri]);
} else if (playlists[uri] && playlists[uri].tracks) {
return returnTracksOrUris(playlists[uri].tracks);
}
return [];
}
@ -404,7 +446,6 @@ function timeFromSeconds(length) {
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;
@ -423,9 +464,9 @@ function toast(message, delay, textOnly) {
}
}
/*****************
* Modal dialogs
*****************/
/******************
* Modal dialogs *
******************/
function showLoading(on) {
if (on) {
$("body").css("cursor", "progress");
@ -456,7 +497,6 @@ function showOffline(on) {
// 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);
}
@ -464,17 +504,20 @@ function validServiceUri(str) {
return validUri(str) || isServiceUri(str);
}
function getScheme(uri) {
return uri.split(':')[0].toLowerCase();
}
function isStreamUri(uri) {
var uriSplit = uri.split(":");
var a = validUri(uri);
var b = radioExtensionsList.indexOf(uriSplit[0].toLowerCase()) >= 0;
var b = radioExtensionsList.indexOf(getScheme(uri)) >= 0;
return a || b;
}
function getMediaClass(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
var scheme = getScheme(uri);
for (var i = 0; i < uriClassList.length; i++) {
if (uriSplit == uriClassList[i][0]) {
if (scheme == uriClassList[i][0]) {
return "fa " + uriClassList[i][1];
}
}
@ -482,9 +525,9 @@ function getMediaClass(uri) {
}
function getMediaHuman(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
var scheme = getScheme(uri);
for (var i = 0; i < uriHumanList.length; i++) {
if (uriSplit == uriHumanList[i][0]) {
if (scheme == uriHumanList[i][0]) {
return uriHumanList[i][1];
}
}
@ -492,19 +535,26 @@ function getMediaHuman(uri) {
}
function isServiceUri(uri) {
var uriSplit = uri.split(":")[0].toLowerCase();
var retVal = false;
var scheme = getScheme(uri);
for (var i = 0; i < uriClassList.length; i++) {
if (uriSplit == uriClassList[i][0]) {
retVal = true;
if (scheme == uriClassList[i][0]) {
return true;
}
}
for (var i = 0; i < radioExtensionsList.length; i++) {
if (uriSplit == radioExtensionsList[i]) {
retVal = true;
if (scheme == radioExtensionsList[i]) {
return true;
}
}
return retVal;
return false;
}
function isFavouritesPlaylist(playlist) {
return (playlist.name == STREAMS_PLAYLIST_NAME &&
getScheme(playlist.uri) == STREAMS_PLAYLIST_SCHEME);
}
function isSpotifyStarredPlaylist(playlist) {
var starredRegex = /spotify:user:.*:starred/g;
return (starredRegex.test(playlist.uri) && playlist.name == 'Starred');
}

View File

@ -4,7 +4,7 @@
* show- functions do both
*/
/********************
* Song Info Sreen
* Song Info Sreen *
********************/
function resetSong() {
if (!posChanging) {
@ -12,17 +12,21 @@ function resetSong() {
setPlayState(false);
setPosition(0);
var data = new Object;
data.name = '';
data.artists = '';
data.length = 0;
data.uri = ' ';
data.tlid = -1;
data.track = new Object;
data.track.name = '';
data.track.artists = '';
data.track.length = 0;
data.track.uri = ' ';
setSongInfo(data);
}
}
function resizeMb() {
$("#infoname").html(songdata.name);
$("#infoname").html(songdata.track.name);
$("#infoname").truncate();
$("#infoartist").html(artiststext);
$("#infoartist").truncate();
if ($(window).width() <= 960) {
// $('#playlisttracksdiv').hide();
@ -69,61 +73,69 @@ function resizeMb() {
*/
}
function setSongTitle(title, refresh_ui) {
songdata.track.name = title;
$("#modalname").html(title);
if (refresh_ui) {
resizeMb();
}
}
function setSongInfo(data) {
// console.log(data, songdata);
if (!data ) { return; }
if ( (data.uri == songdata.uri) ) { return;}
if (!data.name || data.name == '') {
var name = data.uri.split('/');
data.name = decodeURI(name[name.length - 1]);
if (data.tlid == songdata.tlid) { return; }
if (!data.track.name || data.track.name == '') {
var name = data.track.uri.split('/');
data.track.name = decodeURI(name[name.length - 1]);
};
updatePlayIcons(data.uri);
updatePlayIcons(data.track.uri, data.tlid);
artistshtml = '';
artiststext = '';
if (validUri(data.name)) {
if (validUri(data.track.name)) {
for (var key in streamUris) {
rs = streamUris[key];
if (rs && rs[1] == data.name) {
data.name = (rs[0] || rs[1]);
if (rs && rs[1] == data.track.name) {
data.track.name = (rs[0] || rs[1]);
}
};
}
songdata = data;
$("#modalname").html(data.name);
setSongTitle(data.track.name, false);
if (!data.length || data.length == 0) {
if (!data.track.length || data.track.length == 0) {
songlength = 0;
$("#songlength").html('');
pausePosTimer();
$('#trackslider').slider('disable');
// $('#streamnameinput').val(data.name);
// $('#streamuriinput').val(data.uri);
// $('#streamnameinput').val(data.track.name);
// $('#streamuriinput').val(data.track.uri);
} else {
songlength = data.length;
$("#songlength").html(timeFromSeconds(data.length / 1000));
songlength = data.track.length;
$("#songlength").html(timeFromSeconds(data.track.length / 1000));
$('#trackslider').slider('enable');
}
var arttmp = '';
if(data.artists) {
for (var j = 0; j < data.artists.length; j++) {
artistshtml += '<a href="#" onclick="return showArtist(\'' + data.artists[j].uri + '\');">' + data.artists[j].name + '</a>';
artiststext += data.artists[j].name;
if (j != data.artists.length - 1) {
if(data.track.artists) {
for (var j = 0; j < data.track.artists.length; j++) {
artistshtml += '<a href="#" onclick="return showArtist(\'' + data.track.artists[j].uri + '\');">' + data.track.artists[j].name + '</a>';
artiststext += data.track.artists[j].name;
if (j != data.track.artists.length - 1) {
artistshtml += ', ';
artiststext += ', ';
}
}
arttmp = artistshtml;
}
if (data.album && data.album.name) {
$("#modalalbum").html('<a href="#" onclick="return showAlbum(\'' + data.album.uri + '\');">' + data.album.name + '</a>');
getCover(data.album, '#infocover, #controlspopupimage', 'extralarge');
if (data.track.album && data.track.album.name) {
$("#modalalbum").html('<a href="#" onclick="return showAlbum(\'' + data.track.album.uri + '\');">' + data.track.album.name + '</a>');
getCover(data.track.album, '#infocover, #controlspopupimage', 'extralarge');
} else {
$("#modalalbum").html('');
$("#infocover").attr('src', 'images/default_cover.png');
@ -133,14 +145,14 @@ function setSongInfo(data) {
$("#modalartist").html(arttmp);
$("#trackslider").attr("min", 0);
$("#trackslider").attr("max", data.length);
$("#trackslider").attr("max", data.track.length);
resizeMb();
}
/***************
* display popups
*/
/******************
* display popups *
******************/
function closePopups() {
$('#popupTracks').popup('close');
$('#artistpopup').popup('close');
@ -149,8 +161,7 @@ function closePopups() {
$('#controlspopup').popup('close');
}
function popupTracks(e, listuri, trackuri) {
function popupTracks(e, listuri, trackuri, tlid) {
if (!e)
var e = window.event;
$('.popupTrackName').html(popupData[trackuri].name);
@ -192,10 +203,18 @@ function popupTracks(e, listuri, trackuri) {
var popupName = '#popupTracks';
}
if (typeof tlid != 'undefined' && tlid != '') {
$(popupName).data("list", listuri).data("track", trackuri).data("tlid", tlid).popup("open", {
x : e.pageX,
y : e.pageY
});
} else {
$(popupName).data("list", listuri).data("track", trackuri).popup("open", {
x : e.pageX,
y : e.pageY
});
}
return false;
}
@ -204,9 +223,9 @@ function showAlbumPopup(popupId) {
showAlbum(popupData[uri].album.uri);
}
/*********************
* initialize sockets
*********************/
/**********************
* initialize sockets *
**********************/
function initSocketevents() {
mopidy.on("state:online", function() {
@ -214,6 +233,9 @@ function initSocketevents() {
getCurrentPlaylist();
updateStatusOfAll();
getPlaylists();
getUriSchemes().then(function() {
showFavourites();
});
getBrowseDir();
getSearchSchemes();
showLoading(false);
@ -230,12 +252,11 @@ function initSocketevents() {
mopidy.on("event:trackPlaybackStarted", function(data) {
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
setPlayState(true);
setSongInfo(data.tl_track.track);
setSongInfo(data.tl_track);
initPosTimer();
});
mopidy.on("event:trackPlaybackPaused", function(data) {
//setSongInfo(data.tl_track.track);
pausePosTimer();
setPlayState(false);
});
@ -251,6 +272,10 @@ function initSocketevents() {
}
});
mopidy.on("event:muteChanged", function(data) {
setMute(data["mute"]);
});
mopidy.on("event:playbackStateChanged", function(data) {
switch (data["new_state"]) {
case "stopped":
@ -271,6 +296,10 @@ function initSocketevents() {
mopidy.on("event:seeked", function(data) {
setPosition(parseInt(data["time_position"]));
});
mopidy.on("event:streamTitleChanged", function(data) {
setSongTitle(data["title"], true);
});
}
$(document).bind("pageinit", function() {
@ -278,9 +307,9 @@ $(document).bind("pageinit", function() {
});
/************************
* gui stuff
************************/
/**************
* gui stuff *
**************/
function enterFullscreen() {
if (isMobileSafari) { alert ("To get this app in Full Screen, you have to add it to your home-screen using the Share button."); exit(); }
var elem = document.querySelector("#page");
@ -297,6 +326,7 @@ function enterFullscreen() {
}
}
}
function exitFullscreen() {
document.webkitExitFullscreen();
document.mozCancelFullscreen();
@ -322,7 +352,6 @@ function switchContent(divid, uri) {
if (uri) {
hash += "?" + uri;
}
// $.mobile.changePage("#" + hash);
location.hash = "#" + hash;
}
@ -337,8 +366,7 @@ function setHeadline(site){
//update timer
function updateStatusTimer() {
// console.log('statustimer');
mopidy.playback.getCurrentTrack().then(processCurrenttrack, console.error);
mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error);
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
//TODO check offline?
}
@ -353,13 +381,14 @@ function updateOptions() {
//update everything as if reloaded
function updateStatusOfAll() {
mopidy.playback.getCurrentTrack().then(processCurrenttrack, console.error);
mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error);
mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
mopidy.playback.getState().then(processPlaystate, console.error);
updateOptions()
mopidy.playback.getVolume().then(processVolume, console.error);
mopidy.mixer.getMute().then(processMute, console.error);
}
function locationHashChanged() {
@ -400,7 +429,7 @@ function locationHashChanged() {
case 'search':
$('#navsearch a').addClass($.mobile.activeBtnClass);
$("#searchinput").focus();
if (customTracklists['allresultscache'] == '') {
if (customTracklists['mbw:allresultscache'] == '') {
initSearch($('#searchinput').val());
}
break;
@ -419,7 +448,6 @@ function locationHashChanged() {
break;
}
//switch the footer
switch(divid) {
case 'nowPlaying':
@ -435,9 +463,9 @@ function locationHashChanged() {
return false;
}
/**********************
* initialize software
**********************/
/***********************
* initialize software *
***********************/
$(document).ready(function(event) {
//check for websockets
if (!window.WebSocket) {
@ -453,14 +481,15 @@ $(document).ready(function(event) {
$(window).hashchange();
// Connect to server
// mopidy = new Mopidy();
// console.log(wsLocation);
// $.getScript( wsLocation + '/mopidy/mopidy.min.js');
if (websocketUrl) {
mopidy = new Mopidy({
webSocketUrl: 'ws://' + wsLocation + '/mopidy/ws/' // wslocation is set in index.html "ws://localhost:6680/mopidy/ws/"
webSocketUrl: websocketUrl, // wslocation is set in index.html from the extention config.
callingConvention: 'by-position-or-by-name'
});
// mopidy.on(console.log.bind(console)); // Log all events
// mopidy.on(console.error.bind(console));
} else {
mopidy = new Mopidy({callingConvention: 'by-position-or-by-name'});
}
//initialize events
initSocketevents();
@ -470,7 +499,6 @@ $(document).ready(function(event) {
switchContent("home");
}
initgui = false;
window.onhashchange = locationHashChanged;
@ -510,6 +538,13 @@ $(document).ready(function(event) {
$('#homeshutdown').hide();
}
// remove Alarm Clock if it is not present
if (!hasAlarmClock) {
$('#navAlarmClock').hide();
$('#homeAlarmClock').hide();
$('#homeAlarmClock').nextAll().find('.ui-block-a, .ui-block-b').toggleClass('ui-block-a').toggleClass('ui-block-b');
}
//navigation stuff
$(document).keypress( function (event) {
@ -534,7 +569,7 @@ $(document).ready(function(event) {
return true;
}
});
initStreams();
if ($(window).width() < 980) {
$("#panel").panel("close");
@ -549,7 +584,6 @@ $(document).ready(function(event) {
$.event.special.swipe.horizontalDistanceThreshold = 125; // (default: 30px) Swipe horizontal displacement must be more than this.
$.event.special.swipe.verticalDistanceThreshold = 50; // (default: 75px) Swipe vertical displacement must be less than this.
// $.event.special.swipe.scrollSupressionThreshold = 20;
$.event.special.swipe.durationThreshold = 500;
// swipe songinfo and panel
@ -567,10 +601,14 @@ $(document).ready(function(event) {
} );
});
function updatePlayIcons (uri) {
function updatePlayIcons (uri, tlid) {
//update styles of listviews
$('#currenttable li').each(function() {
if (this.id == 'currenttable-' + uri) {
var eachTlid = $(this).attr('tlid');
if (typeof eachTlid != 'undefined') {
eachTlid = parseInt(eachTlid);
}
if (this.id == 'currenttable-' + uri && eachTlid == tlid) {
$(this).addClass('currenttrack');
} else {
$(this).removeClass("currenttrack");
@ -584,6 +622,7 @@ function updatePlayIcons (uri) {
$(this).removeClass("currenttrack2");
}
});
$('#trackresulttable li').each(function() {
if (this.id == 'trackresulttable-' + uri) {
$(this).addClass('currenttrack2');

View File

@ -2,14 +2,13 @@
* @author Wouter van Wijk
*/
API_KEY= 'b6d34c3af91d62ab0ae00ab1b6fa8733';
API_KEY = 'b6d34c3af91d62ab0ae00ab1b6fa8733';
API_SECRET = '2c631802c2285d5d5d1502462fe42a2b';
var fmcache;
var lastfm;
$(window).load(function() {
$(window).load(function () {
// create a Cache object
fmcache = new LastFMCache();
// create a LastFM object
@ -20,7 +19,6 @@ $(window).load(function() {
});
});
function getCover(album, images, size) {
var defUrl = 'images/default_cover.png';
$(images).attr('src', defUrl);
@ -32,7 +30,6 @@ function getCover(album, images, size) {
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 {

View File

@ -1,9 +0,0 @@
/*
* jQuery hashchange event - v1.3 - 7/21/2010
* http://benalman.com/projects/jquery-hashchange-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);

View File

@ -23,14 +23,16 @@ function initSearch() {
document.activeElement.blur();
$("input").blur();
delete customTracklists['allresultscache'];
delete customTracklists['artistresultscache'];
delete customTracklists['albumresultscache'];
delete customTracklists['trackresultscache'];
$("#searchresults").hide();
delete customTracklists[URI_SCHEME+':allresultscache'];
delete customTracklists[URI_SCHEME+':artistresultscache'];
delete customTracklists[URI_SCHEME+':albumresultscache'];
delete customTracklists[URI_SCHEME+':trackresultscache'];
$("#searchartists").hide();
$("#searchalbums").hide();
$("#searchtracks").hide();
if (searchService != 'all') {
mopidy.library.search({any:[value]}, [searchService + ':']).then(processSearchResults, console.error);
mopidy.library.search({'query': {any:[value]}, 'uris': [searchService + ':']}).then(processSearchResults, console.error);
} else {
mopidy.getUriSchemes().then(function (schemes) {
var query = {},
@ -48,7 +50,7 @@ function initSearch() {
} else {
query = {any: [value]};
}
mopidy.library.search(query, uris).then(processSearchResults, console.error);
mopidy.library.search({'query': query, 'uris': uris}).then(processSearchResults, console.error);
});
}
}
@ -79,15 +81,6 @@ function processSearchResults(resultArr) {
var results = {'tracks': [], 'artists': [], 'albums': []};
var j, emptyResult = true;
/* for (var i = 0; i < resultArr.length; ++i) {
for (var prop in results) {
if (resultArr[i][prop] && resultArr[i][prop].length) {
results[prop] = results[prop].concat(resultArr[i][prop]);
emptyResult = false;
}
}
}
*/
for (var i = 0; i < resultArr.length; i++) {
if (resultArr[i].tracks) {
for (j = 0; j < resultArr[i].tracks.length; j++) {
@ -109,11 +102,7 @@ function processSearchResults(resultArr) {
}
}
// console.log(resultArr, results);
customTracklists['trackresultscache'] = results.tracks;
customTracklists[URI_SCHEME+':trackresultscache'] = results.tracks;
if (emptyResult) {
toast('No results');
@ -121,7 +110,17 @@ function processSearchResults(resultArr) {
return false;
}
$("#searchresults").show();
if (results.artists.length > 0) {
$("#searchartists").show();
}
if (results.albums.length > 0) {
$("#searchalbums").show();
}
if (results.tracks.length > 0) {
$("#searchtracks").show();
}
// Returns a string where {x} in template is replaced by tokens[x].
function theme(template, tokens) {
@ -196,10 +195,8 @@ function processSearchResults(resultArr) {
$('#expandsearch').show();
// Track results
// playlisttotable(results.tracks, SEARCH_TRACK_TABLE, 'trackresultscache');
resultsToTables(results.tracks, SEARCH_TRACK_TABLE, 'trackresultscache');
resultsToTables(results.tracks, SEARCH_TRACK_TABLE, URI_SCHEME+':trackresultscache');
setSongInfo();
showLoading(false);
}
@ -214,7 +211,7 @@ function toggleSearch() {
function getPlaylists() {
// get playlists without tracks
mopidy.playlists.getPlaylists(false).then(processGetPlaylists, console.error);
mopidy.playlists.asList().then(processGetPlaylists, console.error);
}
function getBrowseDir(rootdir) {
@ -226,11 +223,14 @@ function getBrowseDir(rootdir) {
} else {
browseStack.push(rootdir);
}
mopidy.library.browse(rootdir).then(processBrowseDir, console.error);
if (!rootdir) {
rootdir = null;
}
mopidy.library.browse({'uri': rootdir}).then(processBrowseDir, console.error);
}
function getCurrentPlaylist() {
mopidy.tracklist.getTracks().then(processCurrentPlaylist, console.error);
mopidy.tracklist.getTlTracks().then(processCurrentPlaylist, console.error);
}
/********************************************************
@ -251,13 +251,10 @@ function togglePlaylists() {
function showTracklist(uri) {
$(PLAYLIST_TABLE).empty();
togglePlaylists();
var pl = getPlaylistFromUri(uri);
//load from cache
if (pl) {
resultsToTables(pl.tracks, PLAYLIST_TABLE, uri);
} else {
showLoading(true);
}
var tracks = getPlaylistTracks(uri).then(function(tracks) {
resultsToTables(tracks, PLAYLIST_TABLE, uri);
});
showLoading(false);
updatePlayIcons(uri);
$('#playlistslist li a').each(function() {
$(this).removeClass("playlistactive");
@ -265,10 +262,6 @@ function showTracklist(uri) {
$(this).addClass('playlistactive');
}
});
// scrollToTracklist();
//lookup recent tracklist
mopidy.playlists.lookup(uri).then(processGetTracklist, console.error);
return false;
}
@ -281,18 +274,17 @@ function showArtist(nwuri) {
$('#popupTracks').popup('close');
$('#controlsmodal').popup('close');
$(ARTIST_TABLE).empty();
//fill from cache
// var pl = getTracksFromUri(nwuri);
//TODO cache
$('#h_artistname').html('');
showLoading(true);
mopidy.library.lookup(nwuri).then(function(resultArr) {
mopidy.library.lookup({'uris': [nwuri]}).then(function(resultDict) {
var resultArr = resultDict[nwuri];
resultArr.uri = nwuri;
processArtistResults(resultArr);
}, console.error);
switchContent('artists', nwuri);
scrollToTop();
setSongInfo();
return false;
}
@ -302,7 +294,7 @@ function showAlbum(uri) {
$('#controlsmodal').popup('close');
$(ALBUM_TABLE).empty();
//fill from cache
var pl = getTracksFromUri(uri);
var pl = getTracksFromUri(uri, true);
if (pl.length>0) {
albumTracksToTable(pl, ALBUM_TABLE, uri);
var albumname = getAlbum(pl);
@ -312,16 +304,17 @@ function showAlbum(uri) {
$('#coverpopupalbumname').html(albumname);
$('#coverpopupartist').html(artistname);
showLoading(false);
mopidy.library.lookup(uri).then(function(resultArr) {
mopidy.library.lookup({'uris': [uri]}).then(function(resultDict) {
var resultArr = resultDict[uri];
resultArr.uri = uri;
processAlbumResults(resultArr);
}, console.error);
// getCover(pl, '#albumviewcover, #coverpopupimage', 'extralarge');
} else {
showLoading(true);
$('#h_albumname').html('');
$('#h_albumartist').html('');
mopidy.library.lookup(uri).then(function(resultArr) {
mopidy.library.lookup({'uris': [uri]}).then(function(resultDict) {
var resultArr = resultDict[uri];
resultArr.uri = uri;
processAlbumResults(resultArr);
}, console.error);
@ -329,7 +322,6 @@ function showAlbum(uri) {
//show page
switchContent('albums', uri);
scrollToTop();
setSongInfo();
return false;
}

View File

@ -21,6 +21,13 @@ function processVolume(data) {
}
}
/********************************************************
* process results of mute
*********************************************************/
function processMute(data) {
setMute(data);
}
/********************************************************
* process results of a repeat
*********************************************************/
@ -106,18 +113,22 @@ function processBrowseDir(resultArr) {
child += backHtml;
}
for (var i = 0; i < resultArr.length; i++) {
browseTracks = [];
for (var i = 0, index = 0; i < resultArr.length; i++) {
iconClass = getMediaClass(resultArr[i].uri);
if(resultArr[i].type == 'track' ) {
// console.log(resultArr[i]);
mopidy.library.lookup(resultArr[i].uri).then(function (resultArr) {
popupData[resultArr[0].uri] = resultArr[0];
if (resultArr[i].type == 'track') {
//console.log(resultArr[i]);
mopidy.library.lookup({'uris': [resultArr[i].uri]}).then(function (resultDict) {
var lookup_uri = Object.keys(resultDict)[0];
popupData[lookup_uri] = resultDict[lookup_uri][0];
browseTracks.push(resultDict[lookup_uri][0]);
}, console.error);
child += '<li class="song albumli" id="browselisttracks-' + resultArr[i].uri + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\', \'' + resultArr[i].uri + '\');">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\', \'' + resultArr[i].uri + '\', \'' + index + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" class="browsetrack" onclick="return playBrowsedTracks(PLAY_ALL, this.id);" id="' + resultArr[i].uri +
'<a href="#" class="browsetrack" onclick="return playBrowsedTracks(PLAY_ALL, ' + index + ');" id="' + resultArr[i].uri +
'"><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>';
index++
} else {
if (browseStack.length > 0) {
iconClass="fa fa-folder-o";
@ -125,26 +136,18 @@ function processBrowseDir(resultArr) {
child += '<li><a href="#" onclick="return getBrowseDir(this.id);" id="' + resultArr[i].uri +
'""><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>';
}
};
}
$('#browselist').html(child);
if (browseStack.length > 0 ) {
/* child = '';
for (var i = 0; i < browseStack.length; i++) {
child += browseStack[i] + ' / ';
}
child = getMediaHuman(browseStack[0]);
iconClass = getMediaClass(browseStack[0]);
*/
child = getMediaHuman(resultArr[0].uri);
iconClass = getMediaClass(resultArr[0].uri);
child = getMediaHuman(uri);
iconClass = getMediaClass(uri);
$('#browsepath').html('<i class="' + iconClass + '"></i> ' + child);
} else {
$('#browsepath').html('');
}
updatePlayIcons(songdata.uri);
updatePlayIcons(songdata.track.uri, songdata.tlid);
showLoading(false);
}
@ -153,50 +156,53 @@ function processBrowseDir(resultArr) {
* process results of list of playlists of the user
*********************************************************/
function processGetPlaylists(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>
<p><a class="btn" href="#">More &raquo;</a></p>
*/
if ((!resultArr) || (resultArr == '')) {
$('#playlistslist').empty();
return;
}
var child, tmp = '',
starredRegex = /spotify:user:.*:starred/g,
iconClass, starred;
var tmp = '', favourites = '', starred = '';
for (var i = 0; i < resultArr.length; i++) {
iconClass = getMediaClass(resultArr[i].uri);
// Check if this is Spotify's "Starred" playlist
if(starredRegex.test(resultArr[i].uri)) {
starred = '<li><a href="#" onclick="return showTracklist(this.id);" id="' + resultArr[i].uri + '"">&#9733; Spotify Starred Tracks</a></li>';
var li_html = '<li><a href="#" onclick="return showTracklist(this.id);" id="' + resultArr[i].uri + '">';
if(isSpotifyStarredPlaylist(resultArr[i])) {
starred = li_html + '&#9733; Spotify Starred Tracks</a></li>' + tmp;
} else if (isFavouritesPlaylist(resultArr[i])) {
favourites = li_html + '&hearts; Musicbox Favourites</a></li>';
} else {
child = '<li><a href="#" onclick="return showTracklist(this.id);" id="' + resultArr[i].uri + '"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</a></li>';
tmp += child;
tmp = tmp + li_html + '<i class="' + getMediaClass(resultArr[i].uri) + '"></i> ' + resultArr[i].name + '</a></li>';
}
};
// Move Spotify "Starred" playlist to top as this is the way Spotify does it
if(starred)
tmp = starred + tmp;
$('#playlistslist').empty();
// Prepend the user's Spotify "Starred" playlist and favourites to the results. (like Spotify official client).
tmp = favourites + starred + tmp;
$('#playlistslist').html(tmp);
scrollToTracklist();
showLoading(false);
}
/********************************************************
* process results of a returned playlist
* process results of a returned list of playlist track refs
*********************************************************/
function processGetTracklist(resultArr) {
//cache result
var newplaylisturi = resultArr.uri;
//console.log(resultArr);
playlists[newplaylisturi] = resultArr;
setSongInfo();
resultsToTables(playlists[newplaylisturi].tracks, PLAYLIST_TABLE, newplaylisturi);
function processPlaylistItems(resultDict) {
if (resultDict.items.length == 0) {
console.log('Playlist', resultDict.uri, 'is empty');
showLoading(false);
return;
}
var trackUris = []
for (i = 0; i < resultDict.items.length; i++) {
trackUris.push(resultDict.items[i].uri);
}
return mopidy.library.lookup({'uris': trackUris}).then(function(tracks) {
// Transform from dict to list and cache result
var newplaylisturi = resultDict.uri;
playlists[newplaylisturi] = {'uri':newplaylisturi, 'tracks':[]};
for (i = 0; i < trackUris.length; i++) {
playlists[newplaylisturi].tracks.push(tracks[trackUris[i]][0]);
}
showLoading(false);
return playlists[newplaylisturi].tracks;
});
return false;
}
/********************************************************
@ -204,9 +210,9 @@ function processGetTracklist(resultArr) {
*********************************************************/
function processCurrentPlaylist(resultArr) {
currentplaylist = resultArr;
resultsToTables(resultArr, CURRENT_PLAYLIST_TABLE);
mopidy.playback.getCurrentTrack().then(processCurrenttrack, console.error);
updatePlayIcons(songdata.uri);
resultsToTables(currentplaylist, CURRENT_PLAYLIST_TABLE);
mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error);
updatePlayIcons(songdata.track.uri, songdata.tlid);
}
/********************************************************
@ -225,7 +231,6 @@ function processArtistResults(resultArr) {
var artistname = getArtist(resultArr);
$('#h_artistname, #artistpopupname').html(artistname);
getArtistImage(artistname, '#artistviewimage, #artistpopupimage', 'extralarge');
setSongInfo();
showLoading(false);
}
@ -233,7 +238,6 @@ function processArtistResults(resultArr) {
* process results of an album lookup
*********************************************************/
function processAlbumResults(resultArr) {
// console.log(resultArr);
if (!resultArr || (resultArr.length == 0)) {
$('#h_albumname').text('Album not found...');
getCover('', '#albumviewcover, #coverpopupimage', 'extralarge');
@ -241,6 +245,7 @@ function processAlbumResults(resultArr) {
return;
}
customTracklists[resultArr.uri] = resultArr;
albumTracksToTable(resultArr, ALBUM_TABLE, resultArr.uri);
var albumname = getAlbum(resultArr);
var artistname = getArtist(resultArr);
@ -248,7 +253,6 @@ function processAlbumResults(resultArr) {
$('#h_albumartist').html(artistname);
$('#coverpopupalbumname').html(albumname);
$('#coverpopupartist').html(artistname);
setSongInfo();
getCover(resultArr[0].album, '#albumviewcover, #coverpopupimage', 'extralarge');
showLoading(false);
}

View File

@ -1,17 +0,0 @@
/**
* 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']);

View File

@ -1,196 +1,78 @@
CACHE MANIFEST
CACHE:
index.html
/mopidy/mopidy.js
/css/add2home.css
/css/bootstrap-responsive.css
/css/bootstrap-responsive.min.css
/css/bootstrap.css
/css/bootstrap.min.css
/css/iscroll-pull-icon@2x.png
/css/jquery.mobile-1.3.0.css
/css/jquery.mobile-1.3.0.min.css
/css/jquery.mobile.iscrollview-pull.css
/css/jquery.mobile.iscrollview.css
/css/jquery.mobile.structure-1.3.0.css
/css/jquery.mobile.structure-1.3.0.min.css
/css/jquery.mobile.theme-1.3.0.css
/css/jquery.mobile.theme-1.3.0.min.css
/css/ws.css
/images/ajax-loader.gif
/images/empty.png
/images/icons-18-black.png
/images/icons-18-white.png
/images/icons-36-black.png
/images/icons-36-white.png
/images/loader.gif
/images/start.jpg
/images/icons/arrow_down_12x12.png
/images/icons/arrow_down_16x16.png
/images/icons/arrow_down_24x24.png
/images/icons/arrow_down_32x32.png
/images/icons/arrow_down_8x8.png
/images/icons/arrow_down_alt1_12x12.png
/images/icons/arrow_down_alt1_16x16.png
/images/icons/arrow_down_alt1_24x24.png
/images/icons/arrow_down_alt1_32x32.png
/images/icons/arrow_down_alt1_8x8.png
/images/icons/arrow_left_alt1_12x12.png
/images/icons/arrow_left_alt1_16x16.png
/images/icons/arrow_left_alt1_24x24.png
/images/icons/arrow_left_alt1_32x32.png
/images/icons/cd_12x12.png
/images/icons/cd_16x16.png
/images/icons/cd_24x24.png
/images/icons/cd_32x32.png
/images/icons/cd_8x8.png
/images/icons/cog_12x12.png
/images/icons/cog_16x16.png
/images/icons/cog_24x24.png
/images/icons/cog_32x32.png
/images/icons/cog_8x8.png
/images/icons/first_12x12.png
/images/icons/first_16x16.png
/images/icons/first_24x24.png
/images/icons/first_32x32.png
/images/icons/first_8x8.png
/images/icons/fork_21x24.png
/images/icons/headphones_12x11.png
/images/icons/headphones_16x14.png
/images/icons/headphones_24x21.png
/images/icons/headphones_32x28.png
/images/icons/headphones_8x7.png
/images/icons/heart_fill_12x11.png
/images/icons/heart_fill_16x14.png
/images/icons/heart_fill_24x21.png
/images/icons/heart_fill_32x28.png
/images/icons/heart_fill_8x7.png
/images/icons/heart_stroke_12x11.png
/images/icons/heart_stroke_16x14.png
/images/icons/heart_stroke_24x21.png
/images/icons/heart_stroke_32x28.png
/images/icons/heart_stroke_8x7.png
/images/icons/info_12x24.png
/images/icons/info_16x32.png
/images/icons/info_4x8.png
/images/icons/info_6x12.png
/images/icons/info_8x16.png
/images/icons/last_12x12.png
/images/icons/last_16x16.png
/images/icons/last_24x24.png
/images/icons/last_32x32.png
/images/icons/last_8x8.png
/images/icons/layers_24x21.png
/images/icons/list_12x11.png
/images/icons/list_16x14.png
/images/icons/list_24x21.png
/images/icons/list_32x28.png
/images/icons/list_8x7.png
/images/icons/list_nested_12x11.png
/images/icons/list_nested_16x14.png
/images/icons/list_nested_24x21.png
/images/icons/list_nested_32x28.png
/images/icons/list_nested_8x7.png
/images/icons/loop_12x12.png
/images/icons/loop_16x16.png
/images/icons/loop_24x24.png
/images/icons/loop_32x32.png
/images/icons/loop_8x8.png
/images/icons/loop_alt1_12x9.png
/images/icons/loop_alt1_16x12.png
/images/icons/loop_alt1_24x18.png
/images/icons/loop_alt1_32x24.png
/images/icons/loop_alt1_8x6.png
/images/icons/loop_alt2_12x11.png
/images/icons/loop_alt2_16x14.png
/images/icons/loop_alt2_24x21.png
/images/icons/loop_alt2_32x28.png
/images/icons/loop_alt2_8x7.png
/images/icons/loop_alt3_12x9.png
/images/icons/loop_alt3_16x12.png
/images/icons/loop_alt3_24x18.png
/images/icons/loop_alt3_32x24.png
/images/icons/loop_alt3_8x6.png
/images/icons/loop_alt4_12x9.png
/images/icons/loop_alt4_16x12.png
/images/icons/loop_alt4_24x18.png
/images/icons/loop_alt4_32x24.png
/images/icons/loop_alt4_8x6.png
/images/icons/magnifying_glass_12x12.png
/images/icons/magnifying_glass_16x16.png
/images/icons/magnifying_glass_24x24.png
/images/icons/magnifying_glass_32x32.png
/images/icons/magnifying_glass_8x8.png
/images/icons/new_window_16x16.png
/images/icons/new_window_24x24.png
/images/icons/pause_12x16.png
/images/icons/pause_18x24.png
/images/icons/pause_24x32.png
/images/icons/pause_32x32.png
/images/icons/pause_6x8.png
/images/icons/pause_9x12.png
/images/icons/play_12x16.png
/images/icons/play_18x24.png
/images/icons/play_24x32.png
/images/icons/play_32x32.png
/images/icons/play_6x8.png
/images/icons/play_9x12.png
/images/icons/play_alt_12x12.png
/images/icons/play_alt_16x16.png
/images/icons/play_alt_24x24.png
/images/icons/play_alt_32x32.png
/images/icons/play_alt_8x8.png
/images/icons/reload_12x14.png
/images/icons/reload_18x21.png
/images/icons/reload_24x28.png
/images/icons/reload_6x7.png
/images/icons/reload_9x11.png
/images/icons/reload_alt_12x14.png
/images/icons/reload_alt_18x21.png
/images/icons/reload_alt_24x28.png
/images/icons/reload_alt_6x7.png
/images/icons/reload_alt_9x11.png
/images/icons/user_24x32.png
/images/icons/volume_12x9.png
/images/icons/volume_16x12.png
/images/icons/volume_24x18.png
/images/icons/volume_32x24.png
/images/icons/volume_8x6.png
/images/icons/volume_mute_12x9.png
/images/icons/volume_mute_16x12.png
/images/icons/volume_mute_24x18.png
/images/icons/volume_mute_32x24.png
/images/icons/volume_mute_8x6.png
/js/add2home.js
/js/controls.js
/js/fastclick.js
/js/functionsvars.js
/js/gui.js
/js/iscroll-lite.js
/js/iscroll.js
/js/jquery-1.8.3.js
/js/jquery-1.8.3.min.js
/js/jquery.ba-hashchange.min.js
/js/jquery.mobile-1.3.0-rc.1.js
/js/jquery.mobile-1.3.0-rc.1.min.js
/js/jquery.mobile-1.3.0.js
/js/jquery.mobile-1.3.0.min.js
/js/jquery.mobile.iscrollview-closure-min.js
/js/jquery.mobile.iscrollview-yui-min.js
/js/jquery.mobile.iscrollview.js
/js/jquery.touchwipe.min.js
/js/jquery.truncate.min.js
/js/lastfm.api.cache.js
/js/lastfm.api.js
/js/lastfm.api.md5.js
/js/lastfm.js
/js/library.js
/js/process_ws.js
# 2016-02-4:v2
NETWORK:
*
CACHE:
css/font-awesome.css
css/font-awesome.min.css
css/fonts/Flat-UI-Icons-24.ttf
css/fonts/Flat-UI-Icons-24.woff
css/fonts/fontawesome-webfont.eot
css/fonts/fontawesome-webfont.svg
css/fonts/fontawesome-webfont.ttf
css/fonts/fontawesome-webfont.woff
css/fonts/FontAwesome.otf
css/fonts/lato-black.ttf
css/fonts/lato-black.woff
css/fonts/lato-bold.ttf
css/fonts/lato-bold.woff
css/fonts/lato-italic.ttf
css/fonts/lato-italic.woff
css/fonts/lato-regular.ttf
css/fonts/lato-regular.woff
css/images/ajax-loader.gif
css/images/icons-18-black.png
css/images/icons-18-white.png
css/images/icons-36-black.png
css/images/icons-36-white.png
css/iscroll-pull-icon@2x.png
css/jquery.mobile.flatui.css
css/jquery.mobile.flatui.min.css
css/jquery.mobile.iscrollview-pull.css
css/jquery.mobile.iscrollview.css
css/webclient.css
dialog-success.html
images/default_cover.png
images/empty.png
images/icons/AUTHORS
images/icons/LICENSE
images/icons/musicbox114.png
images/icons/musicbox32.gif
images/icons/musicbox32.png
images/icons/musicbox57.png
images/icons/musicbox72.png
images/icons/play_alt_12x12.png
images/icons/play_alt_16x16.png
images/loader.gif
images/startup.png
images/user_24x32.png
index.html
js/add2home.js
js/controls.js
js/fastclick.js
js/functionsvars.js
js/gui.js
js/images.js
js/iscroll-lite.js
js/iscroll.js
js/jquery-1.11.1.min.js
js/jquery-1.11.1.min.map
js/jquery.cookie.js
js/jquery.mobile-1.3.2.min.js
js/jquery.mobile-1.3.2.min.map
js/jquery.mobile.iscrollview-closure-min.js
js/jquery.mobile.iscrollview-yui-min.js
js/jquery.mobile.iscrollview.js
js/jquery.touchwipe.min.js
js/jquery.truncate.min.js
js/lastfm.api.cache.js
js/lastfm.api.js
js/lastfm.api.md5.js
js/lastfm.js
js/library.js
js/process_ws.js
mb.manifest
system.html

View File

@ -8,7 +8,7 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<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.min.css"/>
<script src="js/jquery.mobile-1.3.2.min.js"></script>
<script src="js/controls.js"></script>
<script src="js/functionsvars.js"></script>

View File

@ -1,7 +1,6 @@
from __future__ import unicode_literals
import logging
import string
import tornado.web
@ -29,21 +28,33 @@ class IndexHandler(tornado.web.RequestHandler):
def initialize(self, config, path):
ext_config = config[MusicBoxExtension.ext_name]
host, port = ext_config['websocket_host'], ext_config['websocket_port']
ws_url = ''
if host or port:
if not host:
host = self.request.host.partition(':')[0]
logger.warning('Musicbox websocket_host not specified, '
'using %s', host)
elif not port:
port = config['http']['port']
logger.warning('Musicbox websocket_port not specified, '
'using %s', port)
protocol = 'ws'
if self.request.protocol == 'https':
protocol = 'wss'
ws_url = "%s://%s:%d/mopidy/ws" % (protocol, host, port)
self.__dict = {
'version': MusicBoxExtension.version,
'musicbox': int(ext_config['musicbox'])
'musicbox': ext_config.get('musicbox', False),
'useWebsocketUrl': ws_url != '',
'websocket_url': ws_url,
'alarmclock': config.get('alarmclock', {}).get('enabled', False),
}
self.__path = path
self.__title = string.Template('MusicBox on $hostname')
def get(self, path):
return self.render('index.html', title=self.get_title(), **self.__dict)
def get_title(self):
hostname, sep, port = self.request.host.rpartition(':')
if not sep or not port.isdigit():
hostname, port = self.request.host, '80'
return self.__title.safe_substitute(hostname=hostname, port=port)
return self.render('index.html', **self.__dict)
def get_template_path(self):
return self.__path

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -25,7 +25,7 @@ setup(
include_package_data=True,
install_requires=[
'setuptools',
'Mopidy >= 0.19',
'Mopidy >= 1.1.0',
],
entry_points={
'mopidy.ext': [

View File

@ -2,14 +2,12 @@
envlist = py27, flake8
[testenv]
sitepackages = true
deps =
mock
mopidy==dev
mopidy
pytest
pytest-cov
pytest-xdist
install_command = pip install --allow-unverified=mopidy --pre {opts} {packages}
commands =
py.test \
--basetemp={envtmpdir} \
@ -21,4 +19,5 @@ commands =
deps =
flake8
flake8-import-order
skip_install = true
commands = flake8