diff --git a/Dockerfile b/Dockerfile index b5e878502569a2df3e1a0dd53edcf04cc0a9425d..b067528c3666f43cd671f1d6c8f4d2914d4279a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,11 @@ FROM node:15 AS builder WORKDIR /app -COPY . . + +COPY package.json . RUN npm install -ci + +COPY . . RUN npm run build FROM nginx:1.20.0 diff --git a/src/components/AudioAndFrequencyPlayer.vue b/src/components/AudioAndFrequencyPlayer.vue index 0c40a438e36eac247a9489d7eb4e282d78293cac..ba046af2bae3ceb986d158e67a477ef4d59df065 100644 --- a/src/components/AudioAndFrequencyPlayer.vue +++ b/src/components/AudioAndFrequencyPlayer.vue @@ -89,6 +89,7 @@ export default { ] }) // add channel support + /* this.wavesurfer.panner = this.wavesurfer.backend.ac.createStereoPanner() this.panChannel = 0 if (localStorage.isLive !== undefined && localStorage.isLive === 'true') { @@ -96,6 +97,7 @@ export default { } this.wavesurfer.panner.pan.value = Number(this.panChannel) this.wavesurfer.backend.setFilter(this.wavesurfer.panner) + */ this.wavesurfer.on('ready', await (() => { this.isLoading = false this.wavesurfer.clearRegions() @@ -163,6 +165,7 @@ export default { this.wavesurfer.pause() }) this.$eventHub.$on('live_queue_settings', (queueSettings) => { + /* if (this.panChannel === 0 && queueSettings.isLive) { this.panChannel = 1 this.wavesurfer.panner.pan.value = Number(this.panChannel) @@ -174,6 +177,7 @@ export default { this.wavesurfer.backend.setFilter(this.wavesurfer.panner) this.wavesurfer.reload() } + */ }) }, beforeDestroy () { diff --git a/src/components/NavigationMenu.vue b/src/components/NavigationMenu.vue index 79644a24bb45063eb296cfddd5b746426a1f2835..7c19a0e7fd879d38abc5d66412d2b716eb7f206f 100644 --- a/src/components/NavigationMenu.vue +++ b/src/components/NavigationMenu.vue @@ -24,7 +24,14 @@ <vs-button @click="onOpenSequencesList" radius color="primary" type="gradient" icon="list"></vs-button> </div> <div style="display: none" v-if="queueSettings.isLive"> - <audio autoplay v-for="sequence in sequenceQueue.filter(x => canPlay.includes(x.orca_sequence_id))" + <!-- <audio autoplay v-for="sequence in sequenceQueue.filter(x => canPlay.includes(x.orca_sequence_id))" + @ended="sequenceEnded(sequence.orca_sequence_id)" + v-bind:id="sequence.orca_sequence_id" + v-on:canplay="canPlaySequence(sequence.orca_sequence_id)" + v-bind:key="sequence.orca_sequence_id"> + <source v-bind:src="sequence.url" type="audio/mp3" /> + </audio> --> + <audio autoplay v-for="sequence in sequenceQueue" @ended="sequenceEnded(sequence.orca_sequence_id)" v-bind:id="sequence.orca_sequence_id" v-on:canplay="canPlaySequence(sequence.orca_sequence_id)" @@ -86,7 +93,7 @@ export default { 'OrganizeSequencesView' ], queueSettings: { - length: 10, + // length: 10, speed: [2, 10], isLive: false }, @@ -102,72 +109,93 @@ export default { }) this.$eventHub.$on('live_queue_settings', (queueSettingsTemp) => { localStorage.isLive = queueSettingsTemp.isLive - console.log('New queue settings: ' + JSON.stringify(queueSettingsTemp)) - const elemsToDelete = this.sequenceQueue.length - queueSettingsTemp.length - // const tempSequenceQueue = [] + console.log('queue settings changed: ' + JSON.stringify(queueSettingsTemp)) - if (elemsToDelete > 0) { - /* for (let i = elemsToDelete; i < this.sequenceQueue.length; i++) { - tempSequenceQueue.push(this.sequenceQueue[i]) - } */ + this.queueSettings = Object.assign({}, queueSettingsTemp) - this.sequenceQueue.splice(0, elemsToDelete) + // const elemsToDelete = this.sequenceQueue.length - queueSettingsTemp.length + // // const tempSequenceQueue = [] + + // if (elemsToDelete > 0) { + // /* for (let i = elemsToDelete; i < this.sequenceQueue.length; i++) { + // tempSequenceQueue.push(this.sequenceQueue[i]) + // } */ + + // this.sequenceQueue.splice(0, elemsToDelete) + + // const data = [] + // for (let i = 0; i < this.sequenceQueue.length; i++) { + // data.push(this.sequenceQueue[i].orca_sequence_id) + // } + // this.$eventHub.$emit('change-queue-event', data) + // } - const data = [] - for (let i = 0; i < this.sequenceQueue.length; i++) { - data.push(this.sequenceQueue[i].orca_sequence_id) - } - this.$eventHub.$emit('change-queue-event', data) - } if (!queueSettingsTemp.isLive) { - console.log('Stop audio player') - this.canPlay = [] + console.log('stopping playback loops') + + // nothing to do, since audio elements should be removed + + // this.canPlay = [] } else if (queueSettingsTemp.isLive && !this.queueSettings.isLive) { - console.log('Start audio player') - this.queueSettings = Object.assign({}, queueSettingsTemp) - this.startSequences() + console.log('starting playback loops') + // this.queueSettings = Object.assign({}, queueSettingsTemp) + // this.startSequences() + + // nothing to do, since audio nodes should be recreated (v-if) and thus trigger can-play } // this.queueSettings = Object.create(queueSettingsTemp) - this.queueSettings = Object.assign({}, queueSettingsTemp) }) + this.$eventHub.$on('live_add_to_queue', async (sequence) => { - console.log('Add request get') - if (this.sequenceQueue.length > this.queueSettings.length - 1) { - this.sequenceQueue.splice(0, 1) - } + console.log(`add sequence ${sequence}`) + + // allow infinite queue + // if (this.sequenceQueue.length > this.queueSettings.length - 1) { + // this.sequenceQueue.splice(0, 1) + // } + // first we have to load before adding sequence.url = await this.audioSourceForSequence(sequence) - if (this.queueSettings.isLive) { - this.canPlay.push(sequence.orca_sequence_id) - } + // no more can-play queue; each element is looped individually + // if (this.queueSettings.isLive) { + // this.canPlay.push(sequence.orca_sequence_id) + // } + + // add to queue (which will render element and trigger playback) this.sequenceQueue.push(sequence) + this.updateStorage() }) this.$eventHub.$on('live_remove_from_queue', (id) => { this.sequenceQueue = this.sequenceQueue.filter(x => x.orca_sequence_id !== id) - if (this.canPlay.includes(id)) { - this.canPlay.splice(this.canPlay.indexOf(id), 1) - } + // if (this.canPlay.includes(id)) { + // this.canPlay.splice(this.canPlay.indexOf(id), 1) + // } this.updateStorage() }) this.$eventHub.$on('live_set_queue', async (sequences) => { - this.canPlay = [] - this.sequenceQueue.length = 0 - if (sequences.length > this.queueSettings.length) { - confirm('Too much sequences selected. The current maximum size of the queue is ' + this.queueSettings.length) - return - } + // this.canPlay = [] + // this.sequenceQueue.length = 0 + // if (sequences.length > this.queueSettings.length) { + // confirm('Too much sequences selected. The current maximum size of the queue is ' + this.queueSettings.length) + // return + // } + + // reset queue and fill again + this.sequenceQueue = [] for (let i = 0; i < sequences.length; i++) { sequences[i].url = await this.audioSourceForSequence(sequences[i]) this.sequenceQueue.push(sequences[i]) } + this.updateStorage() - if (this.queueSettings.isLive) { - await this.startSequences() - } + + // if (this.queueSettings.isLive) { + // await this.startSequences() + // } }) }, beforeDestroy () { @@ -175,16 +203,16 @@ export default { this.$destroy() }, async mounted () { - if (this.mock) { - const sequences = this.mockSequences() - for (let i = 0; i < sequences.length; i++) { - sequences[i].url = await this.audioSourceForSequence(sequences[i]) - if (this.queueSettings.isLive) { - this.canPlay.push(sequences[i].orca_sequence_id) - } - this.sequenceQueue.push(sequences[i]) - } - } + // if (this.mock) { + // const sequences = this.mockSequences() + // for (let i = 0; i < sequences.length; i++) { + // sequences[i].url = await this.audioSourceForSequence(sequences[i]) + // if (this.queueSettings.isLive) { + // this.canPlay.push(sequences[i].orca_sequence_id) + // } + // this.sequenceQueue.push(sequences[i]) + // } + // } this.userName = localStorage.user if (this.userName === undefined || this.userName === 'null' || this.userName === '') { @@ -223,22 +251,29 @@ export default { return url }, async sequenceEnded (id) { - console.log('ended ' + id) - this.canPlay.splice(this.canPlay.indexOf(id), 1) - console.log('removed from can play: ' + this.canPlay) - - if (this.sequenceQueue.filter(sequence => sequence.orca_sequence_id === id).length > 0) { - await this.delay(this.getRandomValue(this.queueSettings.speed)) - this.canPlay.push(id) - console.log('added to can play: ' + this.canPlay) - } + console.log(`${id} ended, waiting...`) - for (let i = 0; i < this.canPlay.length; i++) { - if (this.sequenceQueue.filter(sequence => sequence.orca_sequence_id === this.canPlay[i]).length <= 0) { - this.canPlay.splice(i, 1) - } - } - console.log('actual can play: ' + this.canPlay) + // this.canPlay.splice(this.canPlay.indexOf(id), 1) + // console.log('removed from can play: ' + this.canPlay) + + // wait for a random time, then restart playback + await this.delay(this.getRandomValue(this.queueSettings.speed)) + + // if (this.sequenceQueue.filter(sequence => sequence.orca_sequence_id === id).length > 0) { + // await this.delay(this.getRandomValue(this.queueSettings.speed)) + // this.canPlay.push(id) + // console.log('added to can play: ' + this.canPlay) + // } + + // for (let i = 0; i < this.canPlay.length; i++) { + // if (this.sequenceQueue.filter(sequence => sequence.orca_sequence_id === this.canPlay[i]).length <= 0) { + // this.canPlay.splice(i, 1) + // } + // } + // console.log('actual can play: ' + this.canPlay) + + // trigger playback + this.canPlaySequence(id) }, onUserChange (name) { this.userName = name @@ -303,25 +338,26 @@ export default { ] }, async startSequences () { - const times = {} - for (let i = 0; i < this.sequenceQueue.length; i++) { - times[this.sequenceQueue[i].orca_sequence_id] = this.getRandomValue(this.queueSettings.speed) - } + console.log('startSequences obsolete') + // const times = {} + // for (let i = 0; i < this.sequenceQueue.length; i++) { + // times[this.sequenceQueue[i].orca_sequence_id] = this.getRandomValue(this.queueSettings.speed) + // } - for (let i = 0; i < this.queueSettings.speed[1]; i++) { - for (let j = 0; j < this.sequenceQueue.length; j++) { - if (times[this.sequenceQueue[j].orca_sequence_id] === i) { - this.canPlay.push(this.sequenceQueue[j].orca_sequence_id) - } - } - if (!this.queueSettings.isLive) { - return - } - await this.delay(1) - if (!this.queueSettings.isLive) { - return - } - } + // for (let i = 0; i < this.queueSettings.speed[1]; i++) { + // for (let j = 0; j < this.sequenceQueue.length; j++) { + // if (times[this.sequenceQueue[j].orca_sequence_id] === i) { + // this.canPlay.push(this.sequenceQueue[j].orca_sequence_id) + // } + // } + // if (!this.queueSettings.isLive) { + // return + // } + // await this.delay(1) + // if (!this.queueSettings.isLive) { + // return + // } + // } }, getRandomValue (range) { return Math.floor(Math.random() * (range[1] - range[0] + 1) + range[0]) @@ -332,28 +368,31 @@ export default { }) }, canPlaySequence (id) { - console.log('can play adjusted') + console.log(`sequence ${id} ready, triggering playback`) + + // if (this.audioContext[id] !== undefined) { + // return + // } - if (this.audioContext[id] !== undefined) { - return - } const audio = document.getElementById(id) - console.log(audio) if (audio === undefined || audio === null) { return } - this.audioContext[id] = new AudioContext() - this.track[id] = this.audioContext[id].createMediaElementSource(audio) + console.log(audio) + audio.play() + + // this.audioContext[id] = new AudioContext() + // this.track[id] = this.audioContext[id].createMediaElementSource(audio) // this.stereoNode[id] = new StereoPannerNode(this.audioContext[id], { pan: -1 }) // this.track[id].connect(this.stereoNode[id]).connect(this.audioContext[id].destination) // remove other keys - const keys = Object.keys(this.track) - for (let i = 0; i < keys.length; i++) { - this.audioContext[keys[i]] = undefined - this.track[keys[i]] = undefined - this.stereoNode[keys[i]] = undefined - } + // const keys = Object.keys(this.track) + // for (let i = 0; i < keys.length; i++) { + // this.audioContext[keys[i]] = undefined + // this.track[keys[i]] = undefined + // this.stereoNode[keys[i]] = undefined + // } } }, watch: { diff --git a/src/components/RandomOrcaPlayer.vue b/src/components/RandomOrcaPlayer.vue index 51973731520c72105d50229b66151e1647267cb0..59f14d6c7d1884ecc26186683f9a687a10315393 100644 --- a/src/components/RandomOrcaPlayer.vue +++ b/src/components/RandomOrcaPlayer.vue @@ -7,21 +7,21 @@ <img class="pauseIconRandomPlayer" v-else src="../assets/pause-circle-solid.svg" alt=""> </div> </div> - <div class="titleSlider">Choose range of delay between noise:</div> + <div class="titleSlider">Range of delay for sequences loop</div> <vue-slider class="sliderSpeed" ref="sliderSpeed" v-model="valueRange" :enable-cross="false" - :min="2" - :max="60" - :min-range="3" - :max-range="58" + :min="1" + :max="10" + :min-range="1" + :max-range="10" :interval="1" :tooltip-placement="'bottom'" @drag-end="this.onSliderSpeedChanged"> </vue-slider> - <div class="titleSlider">Choose length of queue:</div> + <!-- <div class="titleSlider">Choose length of queue:</div> <vue-slider class="sliderAmount" ref="sliderAmount" @@ -31,7 +31,7 @@ :interval="1" :tooltip-placement="'bottom'" @drag-end="this.onSliderAmountChanged"> - </vue-slider> + </vue-slider> --> </div> </template> @@ -46,18 +46,18 @@ export default { }, name: 'RandomOrcaPlayer', props: { - length: Number, + // length: Number, speed: Number, isPlaying: Boolean }, data () { return { - valueRange: [2, 10], + valueRange: [2, 4], valueSliderSpeed: 1, - valueSliderAmount: 2, + // valueSliderAmount: 2, isPlayerPlaying: false, queueSettings: { - length: 10, + // length: 10, speed: [2, 10], isLive: false } @@ -65,8 +65,8 @@ export default { }, mounted () { this.queueSettings.isLive = this.isPlaying - this.queueSettings.length = this.length - this.$refs.sliderAmount.setValue(this.queueSettings.length) + // this.queueSettings.length = this.length + // this.$refs.sliderAmount.setValue(this.queueSettings.length) this.$eventHub.$emit('live_queue_settings', this.queueSettings) }, destroyed () { @@ -78,10 +78,10 @@ export default { this.queueSettings.speed = this.$refs.sliderSpeed.getValue() this.$eventHub.$emit('live_queue_settings', this.queueSettings) }, - onSliderAmountChanged (index) { - this.queueSettings.length = this.$refs.sliderAmount.getValue() - this.$eventHub.$emit('live_queue_settings', this.queueSettings) - }, + // onSliderAmountChanged (index) { + // this.queueSettings.length = this.$refs.sliderAmount.getValue() + // this.$eventHub.$emit('live_queue_settings', this.queueSettings) + // }, playRandomPlayer () { this.isPlayerPlaying = !this.isPlayerPlaying this.queueSettings.isLive = this.isPlayerPlaying diff --git a/src/views/OrganizeSequencesView.vue b/src/views/OrganizeSequencesView.vue index aae111091e666a723f15f06498b35686cb7ab92a..b603b9534f9a0d499b4f831f91c80423de9a541c 100644 --- a/src/views/OrganizeSequencesView.vue +++ b/src/views/OrganizeSequencesView.vue @@ -85,7 +85,7 @@ export default { panChannel: 0, track: null, stereoNode: null, - audioContext: new AudioContext(), + // audioContext: new AudioContext(), isEditable: false, bufferedAudioTapes: {}, rowIdPlaying: -1, @@ -326,13 +326,15 @@ export default { const blobAudioSliced = blobAudio.slice(startBytes, endBytes) const blobURL = window.URL.createObjectURL(blobAudioSliced) this.audio = new Audio(blobURL) - this.track = this.audioContext.createMediaElementSource(this.audio) - this.panChannel = 0 - if (localStorage.isLive !== undefined && localStorage.isLive === 'true') { - this.panChannel = 1 - } - this.stereoNode = new StereoPannerNode(this.audioContext, { pan: this.panChannel }) - this.track.connect(this.stereoNode).connect(this.audioContext.destination) + // this.track = this.audioContext.createMediaElementSource(this.audio) + // this.panChannel = 0 + // if (localStorage.isLive !== undefined && localStorage.isLive === 'true') { + // this.panChannel = 1 + // } + + // this.stereoNode = new StereoPannerNode(this.audioContext, { pan: this.panChannel }) + // this.track.connect(this.stereoNode).connect(this.audioContext.destination) + this.audio.addEventListener('canplaythrough', (event) => { this.audio.play() })