diff --git a/.gitignore b/.gitignore index 74a7597..3e57046 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,6 @@ db.sqlite3 # Sessions file store sessions/* + +# Samples +samples/* diff --git a/config/default.json b/config/default.json index cc0ce72..0ca6299 100644 --- a/config/default.json +++ b/config/default.json @@ -1,10 +1,11 @@ { "Server": { "listeningPort": 3000, - "sessionFileStorePath": "./sessions", + "sessionFileStorePath": "sessions", + "sampleUploadPath": "samples", "sessionSecret": "cats", "tls": false, - "tlsKey": "./certs/key.pem", - "tlsCert": "./certs/cert.pem" + "tlsKey": "certs/key.pem", + "tlsCert": "certs/cert.pem" } } diff --git a/package-lock.json b/package-lock.json index bcc727e..dcbff4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "core-js": "^3.6.5", "express": "^4.17.1", "express-session": "^1.17.2", + "multer": "^1.4.3", "passport": "^0.4.1", "passport-local": "^1.0.0", "path": "^0.12.7", @@ -3116,6 +3117,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -3953,8 +3959,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-indexof": { "version": "1.1.1", @@ -3980,6 +3985,39 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/busboy/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/busboy/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/busboy/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4756,7 +4794,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, "engines": [ "node >= 0.8" ], @@ -5945,6 +5982,39 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dicer/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/dicer/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/dicer/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -10430,6 +10500,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/multicast-dns": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", @@ -14229,6 +14317,14 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -14959,8 +15055,7 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", @@ -16791,7 +16886,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, "engines": { "node": ">=0.4" } @@ -19305,6 +19399,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -19981,8 +20080,7 @@ "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-indexof": { "version": "1.1.1", @@ -20008,6 +20106,38 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -20629,7 +20759,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -21569,6 +21698,38 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -25050,6 +25211,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, "multicast-dns": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", @@ -28184,6 +28360,11 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -28760,8 +28941,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typedarray-to-buffer": { "version": "3.1.5", @@ -30213,8 +30393,7 @@ "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { "version": "4.0.3", diff --git a/package.json b/package.json index 3f9988e..03092f9 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "core-js": "^3.6.5", "express": "^4.17.1", "express-session": "^1.17.2", + "multer": "^1.4.3", "passport": "^0.4.1", "passport-local": "^1.0.0", "path": "^0.12.7", diff --git a/server/app.js b/server/app.js index 700e105..d1b81bf 100644 --- a/server/app.js +++ b/server/app.js @@ -8,6 +8,7 @@ const config = require('config') const authRouter = require('./routes/auth') const usersRouter = require('./routes/users') const profilesRouter = require('./routes/profiles') +const samplesRouter = require('./routes/samples') const app = express() const fileStoreOptions = { path: config.get('Server.sessionFileStorePath') @@ -22,6 +23,7 @@ app.use(cookieParser()) if (process.env.NODE_ENV === 'production') { app.use(express.static(path.join(__dirname, '../dist'))) } +app.use('/samples', express.static(path.join(__dirname, '../', config.get('Server.sampleUploadPath')))) app.use(session({ store: new FileStore(fileStoreOptions), secret: config.get('Server.sessionSecret'), @@ -42,5 +44,6 @@ app.use(passport.authenticate('session')) app.use('/', authRouter) app.use('/', usersRouter) app.use('/', profilesRouter) +app.use('/', samplesRouter) module.exports = app diff --git a/server/boot/db.js b/server/boot/db.js index 9d33f02..8dfaadc 100644 --- a/server/boot/db.js +++ b/server/boot/db.js @@ -29,7 +29,14 @@ module.exports = function () { tremolo_enabled INTEGER, tremolo_frequency REAL, tremolo_depth REAL, - FOREIGN KEY(user) REFERENCES user(id))` + FOREIGN KEY(user) REFERENCES users(id))` + ) + + db.run(`CREATE TABLE IF NOT EXISTS samples ( + id INTEGER PRIMARY KEY, + name TEXT UNIQUE, + user INTEGER, + FOREIGN KEY(user) REFERENCES users(id))` ) }) } diff --git a/server/routes/profiles.js b/server/routes/profiles.js index aac40fe..a321ef1 100644 --- a/server/routes/profiles.js +++ b/server/routes/profiles.js @@ -45,9 +45,9 @@ router.post('/profiles', function (req, res) { function (err) { if (err) { return res.sendStatus(500) + } else { + return res.sendStatus(200) } - - res.sendStatus(200) } ) }) @@ -86,6 +86,7 @@ router.get('/profiles/:profileId', function (req, res) { db.get(`SELECT name, + user, timer_enabled as isTimerEnabled, duration, volume, @@ -105,6 +106,10 @@ router.get('/profiles/:profileId', function (req, res) { return res.sendStatus(500) } + if (row.user.toString() !== req.user.id) { + return res.sendStatus(401) + } + profile.name = row.name profile.isTimerEnabled = row.isTimerEnabled === 1 profile.duration = row.duration @@ -142,11 +147,11 @@ router.delete('/profiles/:profileId', function (req, res) { db.run('DELETE FROM profiles WHERE id = ?', [req.params.profileId], (err) => { if (err) { return res.sendStatus(500) + } else { + return res.sendStatus(200) } }) }) - - res.sendStatus(200) }) module.exports = router diff --git a/server/routes/samples.js b/server/routes/samples.js new file mode 100644 index 0000000..c0f9f98 --- /dev/null +++ b/server/routes/samples.js @@ -0,0 +1,57 @@ +const express = require('express') +const config = require('config') +const multer = require('multer') +const storage = multer.diskStorage({ + destination: config.get('Server.sampleUploadPath'), + filename: function (req, file, cb) { + cb(null, req.body.name) + } +}) +const upload = multer({ storage: storage }) +const db = require('../db') +const router = express.Router() + +router.post('/samples', upload.single('sample'), function (req, res, next) { + if (!req.user) { + return res.sendStatus(401) + } + + db.run('INSERT INTO samples (name, user) VALUES (?, ?)', [ + req.body.name, + req.user.id + ], + function (err) { + if (err) { + return res.sendStatus(500) + } else { + return res.sendStatus(200) + } + }) +}) + +router.get('/samples', function (req, res) { + if (!req.user) { + return res.sendStatus(401) + } + + const samples = [] + + db.all('SELECT id, name FROM samples WHERE user = ?', [req.user.id], (err, rows) => { + if (err) { + return res.sendStatus(500) + } + + rows.forEach((row) => { + const sample = {} + + sample.id = row.id + sample.name = row.name + + samples.push(sample) + }) + + res.json({ samples: samples }) + }) +}) + +module.exports = router diff --git a/server/routes/users.js b/server/routes/users.js index 6d9ccb7..4888321 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -55,7 +55,7 @@ router.post('/users', function (req, res) { const salt = crypto.randomBytes(16) crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', function (err, hashedPassword) { if (err) { - res.sendStatus(500) + return res.sendStatus(500) } db.run('INSERT INTO users (username, hashed_password, salt, name, is_admin) VALUES (?, ?, ?, ?, ?)', [ @@ -66,7 +66,11 @@ router.post('/users', function (req, res) { req.body.isAdmin ], function (err) { if (err) { - res.sendStatus(500) + if (err.code === 'SQLITE_CONSTRAINT') { + return res.sendStatus(409) + } else { + return res.sendStatus(500) + } } const user = { @@ -76,12 +80,13 @@ router.post('/users', function (req, res) { } req.login(user, function (err) { if (err) { - res.sendStatus(500) + return res.sendStatus(500) + } else { + return res.sendStatus(200) } }) }) }) - res.sendStatus(200) }) router.patch('/users/:userId', function (req, res) { @@ -101,11 +106,11 @@ router.patch('/users/:userId', function (req, res) { db.run('UPDATE users SET is_admin = ? WHERE id = ?', [req.body.isAdmin ? 1 : 0, req.params.userId], (err) => { if (err) { return res.sendStatus(500) + } else { + return res.sendStatus(200) } }) }) - - res.sendStatus(200) }) router.delete('/users/:userId', function (req, res) { @@ -125,11 +130,11 @@ router.delete('/users/:userId', function (req, res) { db.run('DELETE FROM users WHERE id = ?', [req.params.userId], (err) => { if (err) { return res.sendStatus(500) + } else { + return res.sendStatus(200) } }) }) - - res.sendStatus(200) }) module.exports = router diff --git a/src/components/Noise.vue b/src/components/Noise.vue index d5b5424..1922056 100644 --- a/src/components/Noise.vue +++ b/src/components/Noise.vue @@ -273,6 +273,105 @@ + + + Samples + + + + + + + + + + + + {{ samples[index].volume }} + + + + + + + + + Upload Sample + + + + + Add a Sample + + + + + WARNING: Uploaded samples are publicly accessible. + + + + + + + + + + + + + + + Close + + + Upload + + + + + + Profiles diff --git a/src/components/noise.js b/src/components/noise.js index 0cbb8f0..c32e491 100644 --- a/src/components/noise.js +++ b/src/components/noise.js @@ -1,4 +1,4 @@ -import { Filter, LFO, Noise, Transport, Tremolo } from 'tone' +import { Filter, LFO, Noise, Players, Transport, Tremolo } from 'tone' export default { name: 'Noise', @@ -31,6 +31,12 @@ export default { isTremoloEnabled: false, tremoloFrequency: 0.5, tremoloDepth: 0.5, + samples: [], + checkedSamples: [], + selectedSample: null, + sampleDialog: false, + sampleName: '', + file: null, rules: { lt (n) { return value => (!isNaN(parseInt(value, 10)) && value < n) || 'Must be less than ' + n @@ -45,7 +51,9 @@ export default { this.filter = new Filter() this.tremolo = new Tremolo() this.lfo = new LFO() + this.players = new Players() this.populateProfileItems() + this.getSamples() }, methods: { play () { @@ -73,18 +81,22 @@ export default { } if (this.isTimerEnabled) { - console.log(this.hours) - console.log(this.minutes) - console.log(this.seconds) this.duration = parseInt((this.hours * 3600)) + parseInt((this.minutes * 60)) + parseInt(this.seconds) - console.log(this.duration) this.noise.sync().start(0).stop(this.duration) Transport.loopEnd = this.duration this.timeRemaining = this.duration this.transportInterval = setInterval(() => this.stop(), this.duration * 1000 + 100) this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000) + + this.checkedSamples.forEach(s => { + this.players.player(s).unsync().sync().start(0).stop(this.duration) + }) } else { this.noise.sync().start(0) + + this.checkedSamples.forEach(s => { + this.players.player(s).unsync().sync().start(0) + }) } Transport.start() @@ -222,6 +234,40 @@ export default { .catch(function (error) { console.error(error.response) }) + }, + getSamples () { + this.$http.get('/samples') + .then(response => { + if (response.status === 200) { + this.samples = response.data.samples + this.samples.forEach((s) => { + this.players.add(s.id, '/samples/' + s.name).toDestination() + }) + } + }) + .catch(function (error) { + console.error(error.response) + }) + }, + uploadSample () { + const formData = new FormData() + + formData.append('name', this.sampleName) + formData.append('sample', this.selectedSample) + + this.$http.post('/samples', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + .catch(function (error) { + console.error(error.response) + }) + + this.sampleDialog = false + }, + updateSampleVolume (id, index) { + this.players.player(id).volume.value = this.samples[index].volume } } }
{{ samples[index].volume }}
WARNING: Uploaded samples are publicly accessible.