diff --git a/engine/media_streamer.go b/engine/media_streamer.go
index e6dc265ae..70f7ac846 100644
--- a/engine/media_streamer.go
+++ b/engine/media_streamer.go
@@ -150,7 +150,7 @@ func (m *transcodedMediaStream) Read(p []byte) (n int, err error) {
// a Seek happens. This is ok-ish for audio, but would kill the server for video.
func (m *transcodedMediaStream) Seek(offset int64, whence int) (int64, error) {
size := int64((m.mf.Duration)*m.bitRate*1000) / 8
- log.Trace(m.ctx, "Seeking file", "path", m.mf.Path, "offset", offset, "whence", whence, "size", size)
+ log.Trace(m.ctx, "Seeking transcoded stream", "path", m.mf.Path, "offset", offset, "whence", whence, "size", size)
switch whence {
case io.SeekEnd:
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 291e80ba0..ece79a2bd 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -2491,6 +2491,14 @@
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="
},
+ "add-dom-event-listener": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz",
+ "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==",
+ "requires": {
+ "object-assign": "4.x"
+ }
+ },
"address": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz",
@@ -4039,11 +4047,24 @@
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
},
+ "component-classes": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz",
+ "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=",
+ "requires": {
+ "component-indexof": "0.0.3"
+ }
+ },
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
},
+ "component-indexof": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz",
+ "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ="
+ },
"compose-function": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz",
@@ -4352,6 +4373,15 @@
"urix": "^0.1.0"
}
},
+ "css-animation": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz",
+ "integrity": "sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==",
+ "requires": {
+ "babel-runtime": "6.x",
+ "component-classes": "^1.2.5"
+ }
+ },
"css-blank-pseudo": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
@@ -4906,6 +4936,11 @@
"esutils": "^2.0.2"
}
},
+ "dom-align": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.10.4.tgz",
+ "integrity": "sha512-wytDzaru67AmqFOY4B9GUb/hrwWagezoYYK97D/vpK+ezg+cnuZO0Q2gltUPa7KfNmIqfRIYVCF8UhRDEHAmgQ=="
+ },
"dom-converter": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -4992,6 +5027,11 @@
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
},
+ "downloadjs": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
+ "integrity": "sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw="
+ },
"downshift": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/downshift/-/downshift-3.2.7.tgz",
@@ -7564,6 +7604,11 @@
"resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
"integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
},
+ "is-mobile": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.1.0.tgz",
+ "integrity": "sha512-M5OhlZwh+aTlmRUvDg0Wq3uWVNa+w4DyZ2SjbrS+BhSLu9Po+JXHendC305ZEu+Hh7lywb19Zu4kYXu3L1Oo8A=="
+ },
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -13046,6 +13091,92 @@
}
}
},
+ "rc-align": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.5.tgz",
+ "integrity": "sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==",
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "dom-align": "^1.7.0",
+ "prop-types": "^15.5.8",
+ "rc-util": "^4.0.4"
+ }
+ },
+ "rc-animate": {
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.10.2.tgz",
+ "integrity": "sha512-cE/A7piAzoWFSgUD69NmmMraqCeqVBa51UErod8NS3LUEqWfppSVagHfa0qHAlwPVPiIBg3emRONyny3eiH0Dg==",
+ "requires": {
+ "babel-runtime": "6.x",
+ "classnames": "^2.2.6",
+ "css-animation": "^1.3.2",
+ "prop-types": "15.x",
+ "raf": "^3.4.0",
+ "rc-util": "^4.15.3",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "rc-slider": {
+ "version": "8.7.1",
+ "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
+ "integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
+ "requires": {
+ "babel-runtime": "6.x",
+ "classnames": "^2.2.5",
+ "prop-types": "^15.5.4",
+ "rc-tooltip": "^3.7.0",
+ "rc-util": "^4.0.4",
+ "react-lifecycles-compat": "^3.0.4",
+ "shallowequal": "^1.1.0",
+ "warning": "^4.0.3"
+ }
+ },
+ "rc-switch": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz",
+ "integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==",
+ "requires": {
+ "classnames": "^2.2.1",
+ "prop-types": "^15.5.6",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "rc-tooltip": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
+ "integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
+ "requires": {
+ "babel-runtime": "6.x",
+ "prop-types": "^15.5.8",
+ "rc-trigger": "^2.2.2"
+ }
+ },
+ "rc-trigger": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz",
+ "integrity": "sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==",
+ "requires": {
+ "babel-runtime": "6.x",
+ "classnames": "^2.2.6",
+ "prop-types": "15.x",
+ "rc-align": "^2.4.0",
+ "rc-animate": "2.x",
+ "rc-util": "^4.4.0",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "rc-util": {
+ "version": "4.19.0",
+ "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.19.0.tgz",
+ "integrity": "sha512-mptALlLwpeczS3nrv83DbwJNeupolbuvlIEjcvimSiWI8NUBjpF0HgG3kWp1RymiuiRCNm9yhaXqDz0a99dpgQ==",
+ "requires": {
+ "add-dom-event-listener": "^1.1.0",
+ "babel-runtime": "6.x",
+ "prop-types": "^15.5.10",
+ "react-lifecycles-compat": "^3.0.4",
+ "shallowequal": "^1.1.0"
+ }
+ },
"react": {
"version": "16.12.0",
"resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz",
@@ -13231,6 +13362,23 @@
"scheduler": "^0.18.0"
}
},
+ "react-drag-listview": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/react-drag-listview/-/react-drag-listview-0.1.6.tgz",
+ "integrity": "sha512-0nSWkR1bMLKgLZIYY2YVURYapppzy46FNSs9uAcCxceo2lnajngzLQ3tBgWaTjKTlWMXD0MAcDUWFDYdqMPYUg==",
+ "requires": {
+ "prop-types": "^15.5.8"
+ }
+ },
+ "react-draggable": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-3.3.2.tgz",
+ "integrity": "sha512-oaz8a6enjbPtx5qb0oDWxtDNuybOylvto1QLydsXgKmwT7e3GXC2eMVDwEMIUYJIFqVG72XpOv673UuuAq6LhA==",
+ "requires": {
+ "classnames": "^2.2.5",
+ "prop-types": "^15.6.0"
+ }
+ },
"react-dropzone": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-10.2.1.tgz",
@@ -13263,11 +13411,40 @@
"@babel/runtime": "^7.4.5"
}
},
+ "react-icon-base": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/react-icon-base/-/react-icon-base-2.1.0.tgz",
+ "integrity": "sha1-oZbjP98eeqof2jrvu2i9rZ6Cp50="
+ },
+ "react-icons": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-2.2.7.tgz",
+ "integrity": "sha512-0n4lcGqzJFcIQLoQytLdJCE0DKSA9dkwEZRYoGrIDJZFvIT6Hbajx5mv9geqhqFiNjUgtxg8kPyDfjlhymbGFg==",
+ "requires": {
+ "react-icon-base": "2.1.0"
+ }
+ },
"react-is": {
"version": "16.12.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
},
+ "react-jinke-music-player": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/react-jinke-music-player/-/react-jinke-music-player-4.7.2.tgz",
+ "integrity": "sha512-r2P1gf7nsOBBXqVaKbN73POomWXAYiHuOq5q6AIiUPCVvKx19pCiOsVqwN0vB3kN5tK3Vypm1tO0GkFBVVK11Q==",
+ "requires": {
+ "classnames": "^2.2.6",
+ "downloadjs": "^1.4.7",
+ "is-mobile": "^2.1.0",
+ "prop-types": "^15.7.2",
+ "rc-slider": "^8.7.1",
+ "rc-switch": "^1.9.0",
+ "react-drag-listview": "^0.1.6",
+ "react-draggable": "^3.3.2",
+ "react-icons": "^2.2.5"
+ }
+ },
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
@@ -14262,6 +14439,11 @@
}
}
},
+ "shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+ },
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
diff --git a/ui/package.json b/ui/package.json
index c6275ae00..98de4890a 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -12,6 +12,7 @@
"react": "^16.12.0",
"react-admin": "^3.1.2",
"react-dom": "^16.12.0",
+ "react-jinke-music-player": "^4.7.2",
"react-scripts": "3.3.0"
},
"scripts": {
diff --git a/ui/src/App.js b/ui/src/App.js
index 2448597a3..65dad963c 100644
--- a/ui/src/App.js
+++ b/ui/src/App.js
@@ -1,31 +1,41 @@
-// in src/App.js
import React from 'react'
import { Admin, Resource } from 'react-admin'
import dataProvider from './dataProvider'
import authProvider from './authProvider'
-import { Login, Layout, DarkTheme } from './layout'
+import { DarkTheme, Layout, Login } from './layout'
import user from './user'
import song from './song'
import album from './album'
import artist from './artist'
import { createMuiTheme } from '@material-ui/core/styles'
+import { Player, playQueueReducer } from './player'
const theme = createMuiTheme(DarkTheme)
const App = () => (
-