forked from platypush/platypush
Implemented music search from web panel
This commit is contained in:
parent
f3d725c890
commit
decadee00a
6 changed files with 607 additions and 136 deletions
|
@ -20,6 +20,43 @@ header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 999;
|
||||||
|
background-color: rgba(10,10,10,0.85);
|
||||||
|
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-container {
|
||||||
|
margin: 5% auto auto auto;
|
||||||
|
width: 70%;
|
||||||
|
background: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
margin: 0.5rem auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 10px 10px 0 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 400px;
|
||||||
|
letter-spacing: .1rem;
|
||||||
|
line-height: 38px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
padding: 2.5rem 2rem 1.5rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
#date-time {
|
#date-time {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
|
@ -56,138 +93,10 @@ button[disabled] {
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-controls {
|
|
||||||
text-align: center;
|
|
||||||
border-bottom: 1px solid #e8eaf0;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playback-controls * > button.enabled {
|
|
||||||
color: #59df3e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button[disabled] {
|
.button[disabled] {
|
||||||
background: rgba(240,240,240,1)
|
background: rgba(240,240,240,1)
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-info {
|
|
||||||
text-align: center;
|
|
||||||
margin: -20px -20px 0 -20px;
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-info > .artist {
|
|
||||||
font-weight: bold;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#player-left-side {
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#player-right-side {
|
|
||||||
margin-left: 0;
|
|
||||||
width: 78%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#playlist-controls, #browser-controls {
|
|
||||||
margin-bottom: 7.5px;
|
|
||||||
padding-bottom: 7.5px;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
height: 3.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#playlist-controls {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#playlist-content, #music-browser {
|
|
||||||
height: 27.2rem;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
#music-browser {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#browser-filter {
|
|
||||||
width: 95%;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#playlist-filter-container {
|
|
||||||
height: 5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#playlist-filter {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-pane {
|
|
||||||
height: 40rem;
|
|
||||||
padding: 15px 15px 0 5px;
|
|
||||||
background: #f8f8f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-item {
|
|
||||||
padding: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-item.selected {
|
|
||||||
background-color: #c8ffd0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-item:hover {
|
|
||||||
background-color: #daf8e2 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.music-item:nth-child(odd) {
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlist-track.active {
|
|
||||||
height: 4rem;
|
|
||||||
padding-top: 1.5rem;
|
|
||||||
font-size: 1.7rem;
|
|
||||||
border-radius: 10px;
|
|
||||||
animation: active-track 5s;
|
|
||||||
-moz-animation: active-track 5s infinite;
|
|
||||||
-webkit-animation: active-track 5s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes active-track {
|
|
||||||
0% { background: #d4ffe3; }
|
|
||||||
50% { background: #9cdfb0; }
|
|
||||||
100% { background: #d4ffe3; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@-moz-keyframes active-track {
|
|
||||||
0% { background: #d4ffe3; }
|
|
||||||
50% { background: #9cdfb0; }
|
|
||||||
100% { background: #d4ffe3; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes active-track {
|
|
||||||
0% { background: #d4ffe3; }
|
|
||||||
50% { background: #9cdfb0; }
|
|
||||||
100% { background: #d4ffe3; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlist-track > .track-time {
|
|
||||||
text-align: right;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
#track-seeker-container {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#volume-ctrl-container {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider {
|
.slider {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
@ -226,3 +135,12 @@ button[disabled] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #d8ffe0 !important;
|
||||||
|
border: 1px solid #98efb0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-side {
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
173
platypush/backend/http/static/css/music.mpd.css
Normal file
173
platypush/backend/http/static/css/music.mpd.css
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
#player-left-side {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#player-right-side {
|
||||||
|
margin-left: 0;
|
||||||
|
width: 78%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playback-controls {
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #e8eaf0;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playback-controls * > button.enabled {
|
||||||
|
color: #59df3e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.track-info {
|
||||||
|
text-align: center;
|
||||||
|
margin: -20px -20px 0 -20px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-info > .artist {
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#playlist-controls, #browser-controls {
|
||||||
|
margin-bottom: 7.5px;
|
||||||
|
padding-bottom: 7.5px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
height: 3.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#playlist-controls {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#playlist-content, #music-browser {
|
||||||
|
height: 27.2rem;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-browser {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#browser-filter {
|
||||||
|
width: 95%;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#playlist-filter-container {
|
||||||
|
height: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#playlist-filter {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-pane {
|
||||||
|
height: 40rem;
|
||||||
|
padding: 15px 15px 0 5px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-item {
|
||||||
|
padding: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-item.selected {
|
||||||
|
background-color: #c8ffd0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-item:hover {
|
||||||
|
background-color: #daf8e2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-item:nth-child(odd) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-track.active {
|
||||||
|
height: 4rem;
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
font-size: 1.7rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
animation: active-track 5s;
|
||||||
|
-moz-animation: active-track 5s infinite;
|
||||||
|
-webkit-animation: active-track 5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes active-track {
|
||||||
|
0% { background: #d4ffe3; }
|
||||||
|
50% { background: #9cdfb0; }
|
||||||
|
100% { background: #d4ffe3; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@-moz-keyframes active-track {
|
||||||
|
0% { background: #d4ffe3; }
|
||||||
|
50% { background: #9cdfb0; }
|
||||||
|
100% { background: #d4ffe3; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes active-track {
|
||||||
|
0% { background: #d4ffe3; }
|
||||||
|
50% { background: #9cdfb0; }
|
||||||
|
100% { background: #d4ffe3; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-track > .track-time {
|
||||||
|
text-align: right;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#track-seeker-container {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#volume-ctrl-container {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-search-form {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-search-form * > input[type=text] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-search-form > .row {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-form-bottom {
|
||||||
|
text-align: right;
|
||||||
|
margin-top: 2rem;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-form-bottom input {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-search-results-form {
|
||||||
|
display: none;
|
||||||
|
margin-top: -2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-search-results-container {
|
||||||
|
display: none;
|
||||||
|
max-height: 50rem;
|
||||||
|
margin-top: -1.4rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#music-search-results-head {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background-color: #eaeaea;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
border-bottom: 1px solid #bbb;
|
||||||
|
letter-spacing: .1rem;
|
||||||
|
line-height: 3.5rem;
|
||||||
|
}
|
||||||
|
|
|
@ -144,10 +144,32 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var initModalOpenBindings = function() {
|
||||||
|
$('body').on('click touch', '[data-modal]', function(event) {
|
||||||
|
var $source = $(event.target);
|
||||||
|
var $modal = $($source.data('modal'));
|
||||||
|
$modal.fadeIn();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var initModalCloseBindings = function() {
|
||||||
|
$('body').on('click touch', '[data-dismiss-modal]', function(event) {
|
||||||
|
var $source = $(event.target);
|
||||||
|
var $modal = $($source.data('dismiss-modal'));
|
||||||
|
$modal.fadeOut();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var initModals = function() {
|
||||||
|
initModalOpenBindings();
|
||||||
|
initModalCloseBindings();
|
||||||
|
};
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
initWebsocket();
|
initWebsocket();
|
||||||
initElements();
|
initElements();
|
||||||
initDateTime();
|
initDateTime();
|
||||||
|
initModals();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.registerEventListener = registerEventListener;
|
window.registerEventListener = registerEventListener;
|
||||||
|
|
|
@ -6,7 +6,16 @@ $(document).ready(function() {
|
||||||
curTrackElapsed = {
|
curTrackElapsed = {
|
||||||
timestamp: null,
|
timestamp: null,
|
||||||
elapsed: null,
|
elapsed: null,
|
||||||
};
|
},
|
||||||
|
|
||||||
|
$musicSearchForm = $('#music-search-form'),
|
||||||
|
$musicSearchResults = $('#music-search-results'),
|
||||||
|
$musicSearchResultsContainer = $('#music-search-results-container'),
|
||||||
|
$musicSearchResultsForm = $('#music-search-results-form'),
|
||||||
|
$musicResultsAddBtn = $('#music-results-add'),
|
||||||
|
$musicResultsPlayBtn = $('#music-results-play'),
|
||||||
|
$resetSearchBtn = $('#music-search-reset');
|
||||||
|
$doSearchBtns = $('.do-search-btns');
|
||||||
|
|
||||||
var execute = function(request, onSuccess, onError, onComplete) {
|
var execute = function(request, onSuccess, onError, onComplete) {
|
||||||
request['target'] = 'localhost';
|
request['target'] = 'localhost';
|
||||||
|
@ -39,6 +48,24 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var formatMinutes = function(time) {
|
||||||
|
if (typeof time === 'string') {
|
||||||
|
time = parseInt(time);
|
||||||
|
} else if (isNaN(time)) {
|
||||||
|
console.warn('Unexpected non-numeric value in formatMinutes');
|
||||||
|
console.log(time);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!time) {
|
||||||
|
return '-:--';
|
||||||
|
}
|
||||||
|
|
||||||
|
var minutes = parseInt(time/60);
|
||||||
|
var seconds = time%60;
|
||||||
|
return (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
|
||||||
|
};
|
||||||
|
|
||||||
var updateControls = function(status, track) {
|
var updateControls = function(status, track) {
|
||||||
var $playbackControls = $('.playback-controls');
|
var $playbackControls = $('.playback-controls');
|
||||||
var $playlistContent = $('#playlist-content');
|
var $playlistContent = $('#playlist-content');
|
||||||
|
@ -80,7 +107,7 @@ $(document).ready(function() {
|
||||||
$curTrack.find('.track').hide();
|
$curTrack.find('.track').hide();
|
||||||
$curTrack.find('.no-track').show();
|
$curTrack.find('.no-track').show();
|
||||||
|
|
||||||
$trackSeeker.attr('disabled', true);
|
$trackSeeker.prop('disabled', true);
|
||||||
$('.seek-time').text('-:--');
|
$('.seek-time').text('-:--');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -91,7 +118,7 @@ $(document).ready(function() {
|
||||||
$curTrack.find('.track').show();
|
$curTrack.find('.track').show();
|
||||||
$curTrack.find('.no-track').hide();
|
$curTrack.find('.no-track').hide();
|
||||||
|
|
||||||
$trackSeeker.removeAttr('disabled');
|
$trackSeeker.prop('disabled', false);
|
||||||
$('#seek-time-elapsed').text(elapsed ? elapsed : '-:--');
|
$('#seek-time-elapsed').text(elapsed ? elapsed : '-:--');
|
||||||
$('#seek-time-length').text(length ? length : '-:--');
|
$('#seek-time-length').text(length ? length : '-:--');
|
||||||
break;
|
break;
|
||||||
|
@ -103,7 +130,7 @@ $(document).ready(function() {
|
||||||
$curTrack.find('.track').show();
|
$curTrack.find('.track').show();
|
||||||
$curTrack.find('.no-track').hide();
|
$curTrack.find('.no-track').hide();
|
||||||
|
|
||||||
$trackSeeker.removeAttr('disabled');
|
$trackSeeker.prop('disabled', false);
|
||||||
$('#seek-time-elapsed').text(elapsed ? elapsed : '-:--');
|
$('#seek-time-elapsed').text(elapsed ? elapsed : '-:--');
|
||||||
$('#seek-time-length').text(length ? length : '-:--');
|
$('#seek-time-length').text(length ? length : '-:--');
|
||||||
|
|
||||||
|
@ -424,9 +451,9 @@ $(document).ready(function() {
|
||||||
|
|
||||||
$parentElement.on('click touch', onDirectorySelect);
|
$parentElement.on('click touch', onDirectorySelect);
|
||||||
$parentElement.appendTo($browserContent);
|
$parentElement.appendTo($browserContent);
|
||||||
$addButton.removeAttr('disabled');
|
$addButton.prop('disabled', false);
|
||||||
} else {
|
} else {
|
||||||
$addButton.attr('disabled', 'disabled');
|
$addButton.prop('disabled', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var directory of directories.sort()) {
|
for (var directory of directories.sort()) {
|
||||||
|
@ -506,7 +533,7 @@ $(document).ready(function() {
|
||||||
$playbackControls.on('click', function(evt) {
|
$playbackControls.on('click', function(evt) {
|
||||||
var action = $(this).data('action');
|
var action = $(this).data('action');
|
||||||
var $btn = $(this);
|
var $btn = $(this);
|
||||||
$btn.attr('disabled', true);
|
$btn.prop('disabled', true);
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
{
|
{
|
||||||
|
@ -520,7 +547,7 @@ $(document).ready(function() {
|
||||||
|
|
||||||
onError=undefined,
|
onError=undefined,
|
||||||
onComplete = function() {
|
onComplete = function() {
|
||||||
$btn.removeAttr('disabled');
|
$btn.prop('disabled', false);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -618,10 +645,237 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var initSearch = function() {
|
||||||
|
$musicSearchForm.on('submit', function(event) {
|
||||||
|
var searchData = $(this).serializeArray().reduce(function(obj, item) {
|
||||||
|
var value = item.value.trim();
|
||||||
|
if (value.length > 0) {
|
||||||
|
obj[item.name] = item.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
var args = {};
|
||||||
|
var searchFilters = {};
|
||||||
|
|
||||||
|
if ('any' in searchData) {
|
||||||
|
args = {
|
||||||
|
type: 'any',
|
||||||
|
filter: searchData.any
|
||||||
|
};
|
||||||
|
|
||||||
|
searchFilters.any = searchData.any;
|
||||||
|
} else {
|
||||||
|
if ('albumartist' in searchData) {
|
||||||
|
args = {
|
||||||
|
type: 'albumartist',
|
||||||
|
filter: searchData.albumartist
|
||||||
|
};
|
||||||
|
|
||||||
|
searchFilters.albumartist = searchData.albumartist;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('album' in searchData) {
|
||||||
|
args = {
|
||||||
|
type: 'album',
|
||||||
|
filter: searchData.album
|
||||||
|
};
|
||||||
|
|
||||||
|
searchFilters.album = searchData.album;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('title' in searchData) {
|
||||||
|
args = {
|
||||||
|
type: 'title',
|
||||||
|
filter: searchData.title
|
||||||
|
};
|
||||||
|
|
||||||
|
searchFilters.title = searchData.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).find('input').prop('disabled', true);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
{
|
||||||
|
type: 'request',
|
||||||
|
action: 'music.mpd.search',
|
||||||
|
args: args
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuccess = function(response) {
|
||||||
|
var results = response.response.output;
|
||||||
|
if (!results) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(searchFilters).length > 1) {
|
||||||
|
results = results.filter(function(item) {
|
||||||
|
return (
|
||||||
|
('title' in searchFilters && 'title' in item
|
||||||
|
? item.title.toLowerCase().indexOf(
|
||||||
|
searchFilters.title.toLowerCase()) >= 0 : true) &&
|
||||||
|
('album' in searchFilters && 'album' in item
|
||||||
|
? item.album.toLowerCase().indexOf(
|
||||||
|
searchFilters.album.toLowerCase()) >= 0 : true) &&
|
||||||
|
('albumartist' in searchFilters && 'artist' in item
|
||||||
|
? item.artist.toLowerCase().indexOf(
|
||||||
|
searchFilters.albumartist.toLowerCase()) >= 0 : true)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var item of results) {
|
||||||
|
var $item = $('<div></div>')
|
||||||
|
.addClass('row').addClass('music-item')
|
||||||
|
.addClass('music-search-item')
|
||||||
|
.data('file', item.file);
|
||||||
|
|
||||||
|
var $artist = $('<div></div>')
|
||||||
|
.addClass('three columns').addClass('artist')
|
||||||
|
.addClass('music-search-item-artist')
|
||||||
|
|
||||||
|
if ('artist' in item) {
|
||||||
|
$artist.text(item.artist);
|
||||||
|
} else {
|
||||||
|
$artist.html(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
var $title = $('<div></div>')
|
||||||
|
.addClass('four columns').addClass('title')
|
||||||
|
.addClass('music-search-item-title');
|
||||||
|
|
||||||
|
if ('title' in item) {
|
||||||
|
$title.text(item.title);
|
||||||
|
} else {
|
||||||
|
$title.html(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
var $album = $('<div></div>')
|
||||||
|
.addClass('four columns').addClass('album')
|
||||||
|
.addClass('music-search-item-album');
|
||||||
|
|
||||||
|
if ('album' in item) {
|
||||||
|
$album.text(item.album);
|
||||||
|
} else {
|
||||||
|
$album.html(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
var $time = $('<div></div>')
|
||||||
|
.addClass('one column').addClass('time')
|
||||||
|
.addClass('music-search-item-time')
|
||||||
|
.text('time' in item ? formatMinutes(item.time) : '-:--');
|
||||||
|
|
||||||
|
$artist.appendTo($item);
|
||||||
|
$title.appendTo($item);
|
||||||
|
$album.appendTo($item);
|
||||||
|
$time.appendTo($item);
|
||||||
|
$item.appendTo($musicSearchResults);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onError = function(xhr, status, error) {
|
||||||
|
console.error(error);
|
||||||
|
},
|
||||||
|
|
||||||
|
onComplete = function() {
|
||||||
|
$musicSearchForm.find('input').prop('disabled', false);
|
||||||
|
$musicSearchForm.hide();
|
||||||
|
$musicSearchResultsContainer.show();
|
||||||
|
$musicSearchResultsForm.show();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$resetSearchBtn.on('click', function(event) {
|
||||||
|
$musicSearchResultsForm.hide();
|
||||||
|
$musicSearchResultsContainer.hide();
|
||||||
|
$musicSearchResults.html('');
|
||||||
|
$musicSearchForm.show();
|
||||||
|
|
||||||
|
$musicResultsAddBtn.removeData('file');
|
||||||
|
$musicResultsAddBtn.prop('disabled', true);
|
||||||
|
$musicResultsPlayBtn.removeData('file');
|
||||||
|
$musicResultsPlayBtn.prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$musicSearchResults.on('click', '.music-search-item', function(event) {
|
||||||
|
var isCurrentlySelected = $(this).hasClass('selected');
|
||||||
|
$('.music-search-item').removeClass('selected');
|
||||||
|
|
||||||
|
if (isCurrentlySelected) {
|
||||||
|
$musicResultsAddBtn.removeData('file');
|
||||||
|
$musicResultsAddBtn.prop('disabled', true);
|
||||||
|
$musicResultsPlayBtn.removeData('file');
|
||||||
|
$musicResultsPlayBtn.prop('disabled', true);
|
||||||
|
|
||||||
|
$(this).removeClass('selected');
|
||||||
|
} else {
|
||||||
|
var file = $(this).data('file');
|
||||||
|
|
||||||
|
$musicResultsAddBtn.data('file', file);
|
||||||
|
$musicResultsAddBtn.prop('disabled', false);
|
||||||
|
$musicResultsPlayBtn.data('file', file);
|
||||||
|
$musicResultsPlayBtn.prop('disabled', false);
|
||||||
|
$(this).addClass('selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$musicSearchResultsForm.on('submit', function(event) {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$musicResultsAddBtn.on('click', function(event) {
|
||||||
|
var file = $(this).data('file');
|
||||||
|
if (!file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(
|
||||||
|
{
|
||||||
|
type: 'request',
|
||||||
|
action: 'music.mpd.add',
|
||||||
|
args: {
|
||||||
|
resource: file
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuccess = function(response) {
|
||||||
|
initPlaylist();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$musicResultsPlayBtn.on('click', function(event) {
|
||||||
|
var file = $(this).data('file');
|
||||||
|
if (!file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(
|
||||||
|
{
|
||||||
|
type: 'request',
|
||||||
|
action: 'music.mpd.play',
|
||||||
|
args: {
|
||||||
|
resource: file
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuccess = function(response) {
|
||||||
|
initPlaylist();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var init = function() {
|
var init = function() {
|
||||||
initStatus();
|
initStatus();
|
||||||
initPlaylist();
|
initPlaylist();
|
||||||
initBrowser();
|
initBrowser();
|
||||||
|
initSearch();
|
||||||
initBindings();
|
initBindings();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,90 @@
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/music.mpd.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/music.mpd.js') }}"></script>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/music.mpd.css') }}"></script>
|
||||||
|
|
||||||
|
<div id="music-search-modal" class="modal">
|
||||||
|
<div class="modal-container">
|
||||||
|
<div class="modal-header">
|
||||||
|
Search For Music
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="music-search-form" action="#">
|
||||||
|
<div class="row form-row">
|
||||||
|
<div class="two columns">
|
||||||
|
<label for="music-search-any">Any</label>
|
||||||
|
</div>
|
||||||
|
<div class="ten columns">
|
||||||
|
<input type="text" name="any">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row form-row">
|
||||||
|
<div class="two columns">
|
||||||
|
<label for="music-search-artist">Artist</label>
|
||||||
|
</div>
|
||||||
|
<div class="ten columns">
|
||||||
|
<input type="text" name="albumartist">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row form-row">
|
||||||
|
<div class="two columns">
|
||||||
|
<label for="music-search-title">Title</label>
|
||||||
|
</div>
|
||||||
|
<div class="ten columns">
|
||||||
|
<input type="text" name="title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row form-row">
|
||||||
|
<div class="two columns">
|
||||||
|
<label for="music-search-album">Album</label>
|
||||||
|
</div>
|
||||||
|
<div class="ten columns">
|
||||||
|
<input type="text" name="album">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row music-form-bottom">
|
||||||
|
<div class="six columns offset-by-six do-search-btns">
|
||||||
|
<input type="button" class="btn-default" data-dismiss-modal="#music-search-modal"
|
||||||
|
value="Close">
|
||||||
|
<input type="submit" class="btn-primary" value="Search">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="row" id="music-search-results-form">
|
||||||
|
<div class="six columns">
|
||||||
|
<button class="btn-default" id="music-results-add" disabled="disabled">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-default" id="music-results-play" disabled="disabled">
|
||||||
|
<i class="fa fa-play"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="six columns right-side">
|
||||||
|
<input type="button" class="btn-default"
|
||||||
|
data-dismiss-modal="#music-search-modal" value="Close">
|
||||||
|
<input type="button" class="btn-primary"
|
||||||
|
id="music-search-reset" value="Reset">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="music-search-results-container" class="row">
|
||||||
|
<div id="music-search-results-head" class="row">
|
||||||
|
<div class="three columns">Artist</div>
|
||||||
|
<div class="four columns">Title</div>
|
||||||
|
<div class="four columns">Album</div>
|
||||||
|
<div class="one column">Time</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="music-search-results" class="row"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row track-info">
|
<div class="row track-info">
|
||||||
<span class="no-track">No media is being played</span>
|
<span class="no-track">No media is being played</span>
|
||||||
|
@ -63,6 +149,9 @@
|
||||||
<button data-action="add">
|
<button data-action="add">
|
||||||
<i class="fa fa-plus"></i>
|
<i class="fa fa-plus"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button data-action="search" data-modal="#music-search-modal">
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="browser-filter-container">
|
<div id="browser-filter-container">
|
||||||
|
|
|
@ -121,6 +121,21 @@ class MusicMpdPlugin(MusicPlugin):
|
||||||
def plchanges(self, version):
|
def plchanges(self, version):
|
||||||
return Response(output=self.client.plchanges(version))
|
return Response(output=self.client.plchanges(version))
|
||||||
|
|
||||||
|
def find(self, type, filter, *args, **kwargs):
|
||||||
|
return Response(
|
||||||
|
output=self.client.find(type, filter, *args, **kwargs))
|
||||||
|
|
||||||
|
def findadd(self, type, filter, *args, **kwargs):
|
||||||
|
return Response(
|
||||||
|
output=self.client.findadd(type, filter, *args, **kwargs))
|
||||||
|
|
||||||
|
def search(self, type, filter, *args, **kwargs):
|
||||||
|
return Response(
|
||||||
|
output=self.client.search(type, filter, *args, **kwargs))
|
||||||
|
|
||||||
|
def searchadd(self, type, filter, *args, **kwargs):
|
||||||
|
return Response(
|
||||||
|
output=self.client.searchadd(type, filter, *args, **kwargs))
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue