From 7a74b83c76a4c14501cccb2494bc5a58b514335d Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 30 May 2019 02:07:28 +0200 Subject: [PATCH] music.mpd plugin vue.js refactoring - WIP --- .../http/static/css/source/common/layout.scss | 1 + .../css/source/common/notifications.scss | 1 + .../http/static/css/source/common/vars.scss | 19 +- .../static/css/source/webpanel/header.scss | 34 -- .../static/css/source/webpanel/index.scss | 25 +- .../http/static/css/source/webpanel/nav.scss | 4 +- .../webpanel/plugins/light.hue/index.scss | 4 +- .../webpanel/plugins/music.mpd/index.scss | 162 +++++++++ .../webpanel/plugins/music.mpd/vars.scss | 17 + .../static/js/plugins/music.mpd/browser.js | 8 + .../http/static/js/plugins/music.mpd/index.js | 331 ++++++++++++++++++ platypush/backend/http/templates/header.html | 18 - platypush/backend/http/templates/index.html | 28 +- platypush/backend/http/templates/nav.html | 9 - .../templates/plugins/music.mpd/browser.html | 13 + .../templates/plugins/music.mpd/index.html | 88 +++++ platypush/backend/music/mopidy.py | 6 +- platypush/plugins/music/mpd/__init__.py | 84 +++-- 18 files changed, 724 insertions(+), 128 deletions(-) delete mode 100644 platypush/backend/http/static/css/source/webpanel/header.scss create mode 100644 platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss create mode 100644 platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss create mode 100644 platypush/backend/http/static/js/plugins/music.mpd/browser.js create mode 100644 platypush/backend/http/static/js/plugins/music.mpd/index.js delete mode 100644 platypush/backend/http/templates/header.html create mode 100644 platypush/backend/http/templates/plugins/music.mpd/browser.html create mode 100644 platypush/backend/http/templates/plugins/music.mpd/index.html diff --git a/platypush/backend/http/static/css/source/common/layout.scss b/platypush/backend/http/static/css/source/common/layout.scss index 2e6cc4cae..beaad3c5c 100644 --- a/platypush/backend/http/static/css/source/common/layout.scss +++ b/platypush/backend/http/static/css/source/common/layout.scss @@ -26,6 +26,7 @@ $widths: ( float: left; box-sizing: border-box; width: ((100%/12)*$i); + margin: 0; } @if $i < 12 { diff --git a/platypush/backend/http/static/css/source/common/notifications.scss b/platypush/backend/http/static/css/source/common/notifications.scss index e568208cd..989a55b3d 100644 --- a/platypush/backend/http/static/css/source/common/notifications.scss +++ b/platypush/backend/http/static/css/source/common/notifications.scss @@ -3,6 +3,7 @@ bottom: 0; right: 0; width: 25em; + z-index: 1000; .notification { background: $notification-bg; diff --git a/platypush/backend/http/static/css/source/common/vars.scss b/platypush/backend/http/static/css/source/common/vars.scss index 0ec0872ae..5db4af812 100644 --- a/platypush/backend/http/static/css/source/common/vars.scss +++ b/platypush/backend/http/static/css/source/common/vars.scss @@ -1,7 +1,11 @@ //// Common defaults -$default-bg: #f4f5f6 !default; +$default-bg: white !default; +$default-bg-2: #f4f5f6 !default; +$default-bg-3: #f1f3f2 !default; +$default-bg-4: #edf0ee !default; $default-fg: black !default; $default-fg-2: #333333 !default; +$default-font-size: 1.5rem !default; $default-font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif !default; $default-border: 1px solid #e1e4e8 !default; @@ -9,6 +13,7 @@ $default-border-2: 1px solid #dddddd !default; $default-bottom: $default-border !default; $default-link-fg: #5f7869 !default; +$font-size: $default-font-size !default; $selected-bg: #c8ffd0 !default; $hover-bg: #def6ea !default; $header-bg: $default_bg !default; @@ -26,12 +31,12 @@ $fade-in-transition-duration: $fade-transition-duration !default; $fade-out-transition-duration: $fade-transition-duration !default; //// Notifications -$notification-bg: rgba(185, 255, 193, 0.85) !default; -$notification-hover-bg: rgba(160,245,178,0.9) !default; -$notification-warning-bg: rgba(228, 255, 78, 0.85) !default; -$notification-warning-hover-bg: rgba(218, 245, 68, 0.9) !default; -$notification-error-bg: rgba(255, 100, 100, 0.85) !default; -$notification-error-hover-bg: rgba(245, 90, 90, 0.9) !default; +$notification-bg: rgba(185, 255, 193, 0.9) !default; +$notification-hover-bg: rgba(160,245,178,0.95) !default; +$notification-warning-bg: rgba(228, 255, 78, 0.9) !default; +$notification-warning-hover-bg: rgba(218, 245, 68, 0.95) !default; +$notification-error-bg: rgba(255, 100, 100, 0.9) !default; +$notification-error-hover-bg: rgba(245, 90, 90, 0.95) !default; $notification-border: 1px solid rgba(109, 205, 134, 0.62) !default; $notification-warning-border: 1px solid rgba(205, 205, 109, 0.62) !default; $notification-error-border: 1px solid rgba(205, 109, 109, 0.62) !default; diff --git a/platypush/backend/http/static/css/source/webpanel/header.scss b/platypush/backend/http/static/css/source/webpanel/header.scss deleted file mode 100644 index 8e0f14d74..000000000 --- a/platypush/backend/http/static/css/source/webpanel/header.scss +++ /dev/null @@ -1,34 +0,0 @@ -header { - .row { - width: 100%; - background: $header-bg; - padding: 1rem 2.5rem; - // margin: 0 1rem 3.5rem -1rem; - border-bottom: $header-bottom; - display: flex; - align-items: center; - - .logo { - font-size: 25px; - - .logo-1 { - font-weight: bold; - } - } - - .date-time { - text-align: right; - padding-right: 3rem; - - .date { - color: #666; - } - - .time { - font-weight: bold; - font-size: 25px; - } - } - } -} - diff --git a/platypush/backend/http/static/css/source/webpanel/index.scss b/platypush/backend/http/static/css/source/webpanel/index.scss index f9d3a09f2..5f65e8bf8 100644 --- a/platypush/backend/http/static/css/source/webpanel/index.scss +++ b/platypush/backend/http/static/css/source/webpanel/index.scss @@ -7,27 +7,34 @@ @import 'common/modal'; @import 'common/notifications'; -@import 'header'; @import 'nav'; body { width: 100%; overflow-x: hidden; font-family: $default-font-family; + font-size: $default-font-size; +} + +body::-webkit-scrollbar { + width: 1em; +} + +body::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); +} + +body::-webkit-scrollbar-thumb { + background-color: darkgrey; + outline: 1px solid slategrey; } main { - margin: 6rem auto; + padding: 4.9rem 0; + margin: 0; } a { color: $default-link-fg; } -.plugin-container { - border: $default-border-2; - border-radius: 1rem; - margin: 1.5rem; - box-shadow: 8px 8px 6px -1px rgba(187,187,187,0.75); -} - diff --git a/platypush/backend/http/static/css/source/webpanel/nav.scss b/platypush/backend/http/static/css/source/webpanel/nav.scss index bb902ac21..f485f1f75 100644 --- a/platypush/backend/http/static/css/source/webpanel/nav.scss +++ b/platypush/backend/http/static/css/source/webpanel/nav.scss @@ -4,7 +4,7 @@ nav { top: 0; width: 100%; z-index: 10; - opacity: 0.9; + opacity: 0.95; ul { position: relative; @@ -23,9 +23,9 @@ nav { margin: 0; text-transform: uppercase; letter-spacing: .1rem; + border-radius: 2rem; &:hover { - border-radius: 2rem; background: $hover-bg; letter-spacing: .4rem; } diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/light.hue/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/light.hue/index.scss index da02f79f0..4e3aadd59 100644 --- a/platypush/backend/http/static/css/source/webpanel/plugins/light.hue/index.scss +++ b/platypush/backend/http/static/css/source/webpanel/plugins/light.hue/index.scss @@ -8,6 +8,8 @@ font-weight: 400; line-height: 3.8rem; letter-spacing: .1rem; + border-bottom: $default-border-2; + border-radius: 0 0 1em 1em; %panel { margin: 1.5rem auto; @@ -28,7 +30,7 @@ .title { padding: .75rem; - background: $default-bg; + background: $default-bg-2; border-bottom: $default-border-2; &:last-child { diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss new file mode 100644 index 000000000..56184d982 --- /dev/null +++ b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss @@ -0,0 +1,162 @@ +@import 'common/vars'; +@import 'common/layout'; +@import 'webpanel/plugins/music.mpd/vars'; + +// background-image: linear-gradient(to right bottom, rgb(123, 84, 30), rgb(0, 0, 0)), linear-gradient(transparent, rgb(0, 0, 0) 70%); + +.music-mpd-container { + line-height: 3rem; + letter-spacing: .03rem; + overflow: hidden; + + * > .item { + cursor: pointer; + border-radius: 1rem; + padding: .5rem; + + &:nth-child(odd) { background: rgba(255, 255, 255, 0.0); } + &:nth-child(even) { background: $default-bg-3; } + + .artist { + font-size: $artist-font-size; + } + } + + * > .duration { + color: $duration-color; + font-size: $duration-font-size; + } + + .panels { + display: flex; + + .browser, .playlist { + height: 100vh - 16rem; + overflow: auto; + } + + .browser { + background: $browser-panel-bg; + border-right: $default-border-2; + padding: .3rem 1rem 6rem 1rem; + font-size: $browser-font-size; + + .item { + background: none; + } + + .fa { + color: #666; + } + } + + .playlist { + padding: .5rem 1rem 6rem 1rem; + } + } + + .controls { + @extend .vertical-center; + position: fixed; + width: 100%; + min-height: 6rem; + bottom: 0; + border-top: $default-border-2; + padding: 1rem; + background: $control-panel-bg; + box-shadow: $control-panel-shadow; + z-index: 2; + + .track-container { + @extend .vertical-center; + line-height: 2.6rem; + + .track-info { + .artist { + font-weight: bold; + } + } + } + + .playback-controls { + .row { + @extend .vertical-center; + justify-content: center; + } + + } + + * > button { + border: 0; + padding: 0 1.5rem; + + &.enabled { + color: $button-enabled-color; + } + + &:hover { + .fa { + color: $button-hover-color; + } + } + + .fa-play, .fa-pause { + color: $button-hover-color; + font-size: $font-size * 2; + margin-top: .3rem; + + &:hover { + color: $play-button-hover-color; + } + } + } + + .pull-right { + padding-right: 2.5rem; + button { + &:not(last-child) { + padding: 0 .7rem; + } + + &:last-child { + padding: 0; + } + } + + .volume-container { + button { + padding: 0 .3rem 0 0; + background: none; + } + } + } + + * > .seek-slider { + width: 75%; + } + + * > .volume-slider { + width: 75%; + margin-right: 1rem; + } + + * > .elapsed-time, + * > .total-time { + font-size: $control-time-font-size; + color: $control-time-color; + } + + * > .elapsed-time { + margin-right: 1.5rem; + } + + * > .total-time { + margin-left: 1.5rem; + } + } + + * > .item:hover { + background: $hover-bg !important; + } +} + diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss new file mode 100644 index 000000000..b9975a035 --- /dev/null +++ b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss @@ -0,0 +1,17 @@ +$button-enabled-color: #59df3e; +$button-hover-color: $button-enabled-color; +$play-button-hover-color: #64ef4a; + +$artist-font-size: $font-size * 0.9333; + +$duration-color: #666; +$duration-font-size: $font-size * 0.86666; + +$control-panel-bg: rgba(245,245,245,0.95); +$control-panel-shadow: 0 -2.5px 4px 0 #c0c0c0; +$control-time-color: #666; +$control-time-font-size: $font-size * 0.666666; + +$browser-panel-bg: rgba(248,250,250,0.95); +$browser-font-size: $font-size * 0.8666; + diff --git a/platypush/backend/http/static/js/plugins/music.mpd/browser.js b/platypush/backend/http/static/js/plugins/music.mpd/browser.js new file mode 100644 index 000000000..539e60d76 --- /dev/null +++ b/platypush/backend/http/static/js/plugins/music.mpd/browser.js @@ -0,0 +1,8 @@ +Vue.component('music-mpd-browser-item', { + template: '#tmpl-music-mpd-browser-item', + props: ['type','name'], + + methods: { + }, +}); + diff --git a/platypush/backend/http/static/js/plugins/music.mpd/index.js b/platypush/backend/http/static/js/plugins/music.mpd/index.js new file mode 100644 index 000000000..cb27abc22 --- /dev/null +++ b/platypush/backend/http/static/js/plugins/music.mpd/index.js @@ -0,0 +1,331 @@ +Vue.component('music-mpd', { + template: '#tmpl-music-mpd', + props: ['config'], + data: function() { + return { + track: {}, + status: {}, + playlist: [], + timer: null, + browserPath: [], + browserItems: [], + syncTime: { + timestamp: null, + elapsed: null, + }, + }; + }, + + methods: { + refresh: async function() { + const getStatus = request('music.mpd.status'); + const getTrack = request('music.mpd.currentsong'); + const getPlaylist = request('music.mpd.playlistinfo'); + const getBrowserItems = request('music.mpd.lsinfo'); + + let [status, track, playlist, browserItems] = await Promise.all([getStatus, getTrack, getPlaylist, getBrowserItems]); + + this._parseStatus(status); + this._parseTrack(track); + this._parsePlaylist(playlist); + this._parseBrowserItems(browserItems); + + if (this.status.state === 'play') { + this.startTimer(); + } + }, + + _parseStatus: async function(status) { + if (!status || status.length === 0) { + status = await request('music.mpd.status'); + } + + for (const [attr, value] of Object.entries(status)) { + if (['consume','random','repeat','single','bitrate'].indexOf(attr) >= 0) { + Vue.set(this.status, attr, !!parseInt(value)); + } else if (['nextsong','nextsongid','playlist','playlistlength', + 'volume','xfade','song','songid'].indexOf(attr) >= 0) { + Vue.set(this.status, attr, parseInt(value)); + } else if (['elapsed'].indexOf(attr) >= 0) { + Vue.set(this.status, attr, parseFloat(value)); + } else { + Vue.set(this.status, attr, value); + } + } + }, + + _parseTrack: async function(track) { + if (!track || track.length === 0) { + track = await request('music.mpd.currentsong'); + } + + for (const [attr, value] of Object.entries(track)) { + if (['id','pos','time'].indexOf(attr) >= 0) { + Vue.set(this.track, attr, parseInt(value)); + } else { + Vue.set(this.track, attr, value); + } + } + }, + + _parsePlaylist: function(playlist) { + if (!playlist || playlist.length === 0) { + return; + } + + this.playlist = []; + + for (var track of playlist) { + for (const [attr, value] of Object.entries(track)) { + if (['time','pos','id'].indexOf(attr) >= 0) { + track[attr] = parseInt(value); + } else { + track[attr] = value; + } + } + + this.playlist.push(track); + } + }, + + _parseBrowserItems: function(browserItems) { + if (!browserItems || browserItems.length === 0) { + return; + } + + this.browserItems = []; + + for (var item of browserItems) { + if (item.directory) { + this.browserItems.push({ + type: 'directory', + name: item.directory, + }); + } else if (item.playlist) { + this.browserItems.push({ + type: 'playlist', + name: item.playlist, + 'last-modified': item['last-modified'], + }); + } + } + }, + + convertTime: function(time) { + time = parseFloat(time); // Normalize strings + var t = {}; + t.h = '' + parseInt(time/3600); + t.m = '' + parseInt(time/60 - t.h*60); + t.s = '' + parseInt(time - t.m*60); + + for (var attr of ['m','s']) { + if (parseInt(t[attr]) < 10) { + t[attr] = '0' + t[attr]; + } + } + + var ret = []; + if (parseInt(t.h)) { + ret.push(t.h); + } + + ret.push(t.m, t.s); + return ret.join(':'); + }, + + previous: async function() { + await request('music.mpd.previous'); + let track = await request('music.mpd.currentsong'); + this.onNewPlayingTrack({track: track}); + }, + + repeat: async function() { + await request('music.mpd.repeat'); + let status = await request('music.mpd.status'); + this._parseStatus(status); + }, + + playPause: async function() { + await request('music.mpd.pause'); + let status = await request('music.mpd.status'); + const method = status.state === 'play' ? this.onMusicPlay : this.onMusicPause; + method({ status: status }); + }, + + stop: async function() { + await request('music.mpd.stop'); + this.onMusicStop({}); + }, + + random: async function() { + await request('music.mpd.random'); + let status = await request('music.mpd.status'); + this._parseStatus(status); + }, + + next: async function() { + await request('music.mpd.next'); + let track = await request('music.mpd.currentsong'); + this.onNewPlayingTrack({track: track}); + }, + + seek: async function(event) { + var value; + + if (event.target) { + value = parseFloat(event.target.value); + } else if (event.value) { + value = parseFloat(event.value); + } else { + value = parseFloat(event); + } + + const status = await request('music.mpd.seekcur', {value: value}); + this.onSeekChange({status: status}); + }, + + volume: async function(event) { + var value; + + if (event.target) { + value = parseFloat(event.target.value); + } else if (event.value) { + value = parseFloat(event.value); + } else { + value = parseFloat(event); + } + + const status = await request('music.mpd.setvol', {vol: value}); + this.onVolumeChange({status: status}); + }, + + onNewPlayingTrack: async function(event) { + var previousTrack = { + file: this.track.file, + artist: this.track.artist, + title: this.track.title, + }; + + this.status.state = 'play'; + this.status.elapsed = 0; + this.track = {}; + + let status = await request('music.mpd.status'); + this._parseStatus(status); + this._parseTrack(event.track); + this.startTimer(); + + if (this.track.file != previousTrack.file + || this.track.artist != previousTrack.artist + || this.track.title != previousTrack.title) { + this.showNewTrackNotification(); + } + }, + + showNewTrackNotification: function() { + createNotification({ + html: '' + (this.track.artist || '[No Artist]') + '
' + + (this.track.title || '[No Title]'), + image: { + icon: 'play', + } + }); + }, + + onMusicStop: function(event) { + this.status.state = 'stop'; + this._parseStatus(event.status); + this._parseTrack(event.track); + this.stopTimer(); + }, + + onMusicPlay: function(event) { + this.status.state = 'play'; + this._parseStatus(event.status); + this._parseTrack(event.track); + this.startTimer(); + }, + + onMusicPause: function(event) { + this.status.state = 'pause'; + this._parseStatus(event.status); + this._parseTrack(event.track); + + this.syncTime.timestamp = new Date(); + this.syncTime.elapsed = this.status.elapsed; + }, + + onSeekChange: function(event) { + if (event.position != null) + this.status.elapsed = parseFloat(event.position); + if (event.status) + this._parseStatus(event.status); + if (event.track) + this._parseTrack(event.track); + + this.syncTime.timestamp = new Date(); + this.syncTime.elapsed = this.status.elapsed; + }, + + onPlaylistChange: function(event) { + console.log(event); + }, + + onVolumeChange: function(event) { + if (event.volume != null) + this.status.volume = parseFloat(event.volume); + if (event.status) + this._parseStatus(event.status); + if (event.track) + this._parseTrack(event.track); + }, + + onRepeatChange: function(event) { + this.status.repeat = event.state; + }, + + onRandomChange: function(event) { + this.status.random = event.state; + }, + + startTimer: function() { + if (this.timer != null) { + this.stopTimer(); + } + + this.syncTime.timestamp = new Date(); + this.syncTime.elapsed = this.status.elapsed; + this.timer = setInterval(this.timerFunc, 1000); + }, + + stopTimer: function() { + if (this.timer == null) { + clearInterval(this.timer); + this.timer = null; + } + }, + + timerFunc: function() { + if (this.status.state !== 'play' || this.status.elapsed == null) { + return; + } + + this.status.elapsed = this.syncTime.elapsed + + ((new Date()).getTime()/1000) - (this.syncTime.timestamp.getTime()/1000); + }, + }, + + created: function() { + this.refresh(); + registerEventHandler(this.onNewPlayingTrack, 'platypush.message.event.music.NewPlayingTrackEvent'); + registerEventHandler(this.onMusicStop, 'platypush.message.event.music.MusicStopEvent'); + registerEventHandler(this.onMusicPlay, 'platypush.message.event.music.MusicPlayEvent'); + registerEventHandler(this.onMusicPause, 'platypush.message.event.music.MusicPauseEvent'); + registerEventHandler(this.onSeekChange, 'platypush.message.event.music.SeekChangeEvent'); + registerEventHandler(this.onPlaylistChange, 'platypush.message.event.music.PlaylistChangeEvent'); + registerEventHandler(this.onVolumeChange, 'platypush.message.event.music.VolumeChangeEvent'); + registerEventHandler(this.onRepeatChange, 'platypush.message.event.music.PlaybackRepeatModeChangeEvent'); + registerEventHandler(this.onRandomChange, 'platypush.message.event.music.PlaybackRandomModeChangeEvent'); + }, +}); + diff --git a/platypush/backend/http/templates/header.html b/platypush/backend/http/templates/header.html deleted file mode 100644 index 24e7af4bf..000000000 --- a/platypush/backend/http/templates/header.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - diff --git a/platypush/backend/http/templates/index.html b/platypush/backend/http/templates/index.html index 0028a7805..79dd02a0d 100644 --- a/platypush/backend/http/templates/index.html +++ b/platypush/backend/http/templates/index.html @@ -40,25 +40,31 @@ {% include 'elements.html' %} + + {% for plugin, conf in templates.items() %} + {% with configuration=templates[plugin] %} + {% include conf['_template_file'] %} + {% endwith %} + {% endfor %} + + {% for script in scripts.values() %} + + {% endfor %}
- {# include 'header.html' #} - {% with plugins=templates.keys() %} {% include 'nav.html' %} {% endwith %}
- {% for plugin, conf in templates.items() %} - {% with configuration=templates[plugin], utils=utils %} - {% include conf['_template_file'] %} - - {% endwith %} - {% endfor %} +
@@ -67,10 +73,6 @@ {% include 'plugins/template.html' %} - {% for script in scripts.values() %} - - {% endfor %} - diff --git a/platypush/backend/http/templates/nav.html b/platypush/backend/http/templates/nav.html index a701f63f7..83968be36 100644 --- a/platypush/backend/http/templates/nav.html +++ b/platypush/backend/http/templates/nav.html @@ -6,18 +6,9 @@ {{ plugin }} - {% endfor %} -
  • - Test tab 2 -
  • -
  • - Test tab 3 -
  • -
    -
    diff --git a/platypush/backend/http/templates/plugins/music.mpd/browser.html b/platypush/backend/http/templates/plugins/music.mpd/browser.html new file mode 100644 index 000000000..f256d4654 --- /dev/null +++ b/platypush/backend/http/templates/plugins/music.mpd/browser.html @@ -0,0 +1,13 @@ + + + + diff --git a/platypush/backend/http/templates/plugins/music.mpd/index.html b/platypush/backend/http/templates/plugins/music.mpd/index.html new file mode 100644 index 000000000..37d23fc92 --- /dev/null +++ b/platypush/backend/http/templates/plugins/music.mpd/index.html @@ -0,0 +1,88 @@ +{% include 'plugins/music.mpd/browser.html' %} + + + diff --git a/platypush/backend/music/mopidy.py b/platypush/backend/music/mopidy.py index 5ac5b68dc..2e9d6fce7 100644 --- a/platypush/backend/music/mopidy.py +++ b/platypush/backend/music/mopidy.py @@ -185,11 +185,11 @@ class MusicMopidyBackend(Backend): new_status = self._get_tracklist_status() if new_status['random'] != self._latest_status.get('random'): self.bus.post(PlaybackRandomModeChangeEvent(state=new_status['random'])) - if new_status['repeat'] != self._latest_status('repeat'): + if new_status['repeat'] != self._latest_status['repeat']: self.bus.post(PlaybackRepeatModeChangeEvent(state=new_status['repeat'])) - if new_status['single'] != self._latest_status('single'): + if new_status['single'] != self._latest_status['single']: self.bus.post(PlaybackSingleModeChangeEvent(state=new_status['single'])) - if new_status['consume'] != self._latest_status('consume'): + if new_status['consume'] != self._latest_status['consume']: self.bus.post(PlaybackConsumeModeChangeEvent(state=new_status['consume'])) self._latest_status = new_status diff --git a/platypush/plugins/music/mpd/__init__.py b/platypush/plugins/music/mpd/__init__.py index de52ec503..3339a9e56 100644 --- a/platypush/plugins/music/mpd/__init__.py +++ b/platypush/plugins/music/mpd/__init__.py @@ -37,37 +37,50 @@ class MusicMpdPlugin(MusicPlugin): self.port = port self.client = None - def _connect(self): - if not self.client: - self.client = mpd.MPDClient(use_unicode=True) - self.client.connect(self.host, self.port) - return self.client + def _connect(self, n_tries=2): + with self._client_lock: + if self.client: + return + + error = None + while n_tries > 0: + try: + n_tries -= 1 + self.client = mpd.MPDClient(use_unicode=True) + self.client.connect(self.host, self.port) + return self.client + except Exception as e: + error = e + self.logger.warning('Connection exception: {}{}'. + format(str(e), (': Retrying' if n_tries > 0 else ''))) + time.sleep(0.5) + + self.client = None + raise error def _exec(self, method, *args, **kwargs): - n_tries = int(kwargs.pop('n_tries')) if 'n_tries' in kwargs else 1 + error = None + n_tries = int(kwargs.pop('n_tries')) if 'n_tries' in kwargs else 2 return_status = kwargs.pop('return_status') \ if 'return_status' in kwargs else True - try: - self._connect() - response = None - with self._client_lock: - response = getattr(self.client, method)(*args, **kwargs) + while n_tries > 0: + try: + self._connect() + n_tries -= 1 + with self._client_lock: + response = getattr(self.client, method)(*args, **kwargs) - if return_status: - return self.status().output - return response - except Exception as e: - self.logger.warning('Exception while executing MPD method {}: {}'. - format(method, str(e))) - self.client = None + if return_status: + return self.status().output + return response + except Exception as e: + error = str(e) + self.logger.warning('Exception while executing MPD method {}: {}'. + format(method, error)) + self.client = None - if n_tries > 0: - kwargs['return_status'] = return_status - kwargs['n_tries'] = n_tries-1 - return self._exec(method, *args, **kwargs) - else: - return (None, str(e)) + return None, error @action def play(self, resource=None): @@ -346,14 +359,21 @@ class MusicMpdPlugin(MusicPlugin): } """ - try: - self._connect() - return self.client.status() - except Exception as e: - self.logger.warning('Exception while getting MPD status: {}'. - format(str(e))) - self.client = None - return (None, str(e)) + n_tries = 2 + error = None + + while n_tries > 0: + try: + n_tries -= 1 + self._connect() + return self.client.status() + except Exception as e: + error = e + self.logger.warning('Exception while getting MPD status: {}'. + format(str(e))) + self.client = None + + return None, error @action def currentsong(self):