forked from platypush/platypush
- Implemented support for shuffle, random and set volume on the UI
- Reduced the websocket ping poll frequency to 1 second
This commit is contained in:
parent
28bc4c748e
commit
968b71e946
5 changed files with 134 additions and 19 deletions
|
@ -123,7 +123,7 @@ class HttpBackend(Backend):
|
||||||
try:
|
try:
|
||||||
waiter = await websocket.ping()
|
waiter = await websocket.ping()
|
||||||
await asyncio.wait_for(waiter, timeout=5)
|
await asyncio.wait_for(waiter, timeout=5)
|
||||||
time.sleep(0.1)
|
time.sleep(1)
|
||||||
except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed) as e:
|
except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed) as e:
|
||||||
logging.info('Client {} closed connection'.format(websocket.remote_address[0]))
|
logging.info('Client {} closed connection'.format(websocket.remote_address[0]))
|
||||||
self.active_websockets.remove(websocket)
|
self.active_websockets.remove(websocket)
|
||||||
|
|
|
@ -95,3 +95,49 @@ main {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#track-seeker-container {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#volume-ctrl-container {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #e4e4e4;
|
||||||
|
outline: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
-webkit-transition: .2s;
|
||||||
|
transition: opacity .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #4CAF50;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider[disabled]::-webkit-slider-thumb {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider::-moz-range-thumb {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
background: #4CAF50;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var execute = function(request, onSuccess, onComplete) {
|
var execute = function(request, onSuccess, onError, onComplete) {
|
||||||
request['target'] = 'localhost';
|
request['target'] = 'localhost';
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
|
@ -12,6 +12,11 @@ $(document).ready(function() {
|
||||||
onComplete();
|
onComplete();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
if (onError) {
|
||||||
|
onError(xhr, status, error);
|
||||||
|
}
|
||||||
|
},
|
||||||
success: function(response, status, xhr) {
|
success: function(response, status, xhr) {
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess(response, status, xhr);
|
onSuccess(response, status, xhr);
|
||||||
|
@ -28,6 +33,7 @@ $(document).ready(function() {
|
||||||
var updateControls = function(status, track) {
|
var updateControls = function(status, track) {
|
||||||
var $playbackControls = $('.playback-controls');
|
var $playbackControls = $('.playback-controls');
|
||||||
var $curTrack = $('.track-info');
|
var $curTrack = $('.track-info');
|
||||||
|
var $volumeCtrl = $('#volume-ctrl');
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
switch (status.state.toLowerCase()) {
|
switch (status.state.toLowerCase()) {
|
||||||
|
@ -53,6 +59,11 @@ $(document).ready(function() {
|
||||||
$curTrack.find('.no-track').hide();
|
$curTrack.find('.no-track').hide();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('volume' in status) {
|
||||||
|
var volume = parseInt(status.volume);
|
||||||
|
$volumeCtrl.val(volume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (track) {
|
if (track) {
|
||||||
|
@ -183,6 +194,8 @@ $(document).ready(function() {
|
||||||
var initBindings = function() {
|
var initBindings = function() {
|
||||||
window.registerEventListener(onEvent);
|
window.registerEventListener(onEvent);
|
||||||
var $playbackControls = $('.playback-controls').find('button');
|
var $playbackControls = $('.playback-controls').find('button');
|
||||||
|
var $volumeCtrl = $('#volume-ctrl');
|
||||||
|
var prevVolume;
|
||||||
|
|
||||||
$playbackControls.on('click', function(evt) {
|
$playbackControls.on('click', function(evt) {
|
||||||
var action = $(this).data('action');
|
var action = $(this).data('action');
|
||||||
|
@ -196,11 +209,31 @@ $(document).ready(function() {
|
||||||
},
|
},
|
||||||
|
|
||||||
onSuccess=undefined,
|
onSuccess=undefined,
|
||||||
|
onError=undefined,
|
||||||
onComplete = function() {
|
onComplete = function() {
|
||||||
$btn.removeAttr('disabled');
|
$btn.removeAttr('disabled');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$volumeCtrl.on('mousedown', function(event) {
|
||||||
|
prevVolume = $(this).val();
|
||||||
|
});
|
||||||
|
|
||||||
|
$volumeCtrl.on('mouseup', function(event) {
|
||||||
|
execute(
|
||||||
|
{
|
||||||
|
type: 'request',
|
||||||
|
action: 'music.mpd.setvol',
|
||||||
|
args: { vol: $(this).val() }
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuccess=undefined,
|
||||||
|
onError = function() {
|
||||||
|
$volumeCtrl.val(prevVolume);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
|
|
|
@ -6,12 +6,23 @@
|
||||||
<span class="track"></span>
|
<span class="track"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row playback-controls">
|
<div class="playback-controls">
|
||||||
|
<div class="row">
|
||||||
|
<div class="six columns offset-by-three slider-container" id="track-seeker-container">
|
||||||
|
<input type="range" min="0" id="track-seeker" disabled="disabled" class="slider">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<div class="eight columns offset-by-two">
|
<div class="eight columns offset-by-two">
|
||||||
<button data-action="previous">
|
<button data-action="previous">
|
||||||
<i class="fa fa-step-backward"></i>
|
<i class="fa fa-step-backward"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button data-action="repeat">
|
||||||
|
<i class="fa fa-repeat"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button data-action="play">
|
<button data-action="play">
|
||||||
<i class="fa fa-play"></i>
|
<i class="fa fa-play"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -24,12 +35,25 @@
|
||||||
<i class="fa fa-stop"></i>
|
<i class="fa fa-stop"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button data-action="random">
|
||||||
|
<i class="fa fa-random"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button data-action="next">
|
<button data-action="next">
|
||||||
<i class="fa fa-step-forward"></i>
|
<i class="fa fa-step-forward"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="six columns offset-by-three slider-container" id="volume-ctrl-container">
|
||||||
|
<i class="fa fa-volume-down"></i>
|
||||||
|
<input type="range" min="0" max="100" id="volume-ctrl" class="slider" style="width:90%">
|
||||||
|
<i class="fa fa-volume-up"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="music-browser" class="three columns music-pane"></div>
|
<div id="music-browser" class="three columns music-pane"></div>
|
||||||
<div id="playlist-content" class="nine columns music-pane"></div>
|
<div id="playlist-content" class="nine columns music-pane"></div>
|
||||||
|
|
|
@ -64,6 +64,18 @@ class MusicMpdPlugin(MusicPlugin):
|
||||||
self.setvol(str(new_volume))
|
self.setvol(str(new_volume))
|
||||||
return self.status()
|
return self.status()
|
||||||
|
|
||||||
|
def random(self, value=None):
|
||||||
|
if value is None:
|
||||||
|
value = int(self.status().output['random'])
|
||||||
|
value = 1 if value == 0 else 0
|
||||||
|
self.client.random(value)
|
||||||
|
|
||||||
|
def repeat(self, value=None):
|
||||||
|
if value is None:
|
||||||
|
value = int(self.status().output['repeat'])
|
||||||
|
value = 1 if value == 0 else 0
|
||||||
|
self.client.repeat(value)
|
||||||
|
|
||||||
def add(self, resource):
|
def add(self, resource):
|
||||||
return self._exec('add', resource)
|
return self._exec('add', resource)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue