166 lines
4.1 KiB
Vue
166 lines
4.1 KiB
Vue
<template>
|
|
<div class="soundboard">
|
|
<div class="soundboard__controls">
|
|
<DeviceVolume />
|
|
</div>
|
|
<div class="soundboard__sounds" style="--color-theme: var(--color-lime)">
|
|
<template v-for="node in nodes" :key="node">
|
|
<Playlist
|
|
v-if="node.type === 'playlist'"
|
|
:node="node"
|
|
@delete="deleteNode(node)"
|
|
/>
|
|
<Sfx
|
|
v-else-if="node.type === 'sfx'"
|
|
:node="node"
|
|
@delete="deleteNode(node)"
|
|
/>
|
|
<TabSource
|
|
v-else-if="node.type === 'tabSource'"
|
|
:node="node"
|
|
@delete="deleteNode(node)"
|
|
/>
|
|
</template>
|
|
</div>
|
|
<div class="a-card add-card" style="--box-color: var(--color-zinc)">
|
|
<div class="a-card__label-wrapper">
|
|
<div class="a-card__label">Add</div>
|
|
</div>
|
|
<div @click="addNode('playlist')" class="soundboard-add-card__btn">
|
|
Playlist
|
|
</div>
|
|
<div @click="addNode('sfx')" class="soundboard-add-card__btn">
|
|
Sfx
|
|
</div>
|
|
<div @click="addNode('tab')" class="soundboard-add-card__btn">
|
|
Tab Source
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import {inject, reactive, ref, watch} from 'vue';
|
|
import Playlist from './Playlist.vue';
|
|
import {PlaylistGroupNode} from '../../model/Audio/PlaylistGroupNode';
|
|
import {AudioContextSymbol, MountedFsSymbol, RemoteDeviceManagerSymbol} from '../../model/injectionSymbols';
|
|
import {SfxGroupNode} from '../../model/Audio/SfxGroupNode';
|
|
import Sfx from './Sfx.vue';
|
|
import Modal from './modal.vue';
|
|
import {TabSourceNode} from '../../model/Audio/TabSourceNode';
|
|
import TabSource from './TabSource.vue';
|
|
import DeviceVolume from './DeviceVolume.vue';
|
|
import {AudioNodeManager} from '../../model/Audio/AudioNodesManager';
|
|
import {debounce} from '../../utils/debounce';
|
|
import IconPlus from '../Icons/IconPlus.vue';
|
|
import {SoundNode} from '../../model/Audio/SoundNode';
|
|
|
|
const fs = inject(MountedFsSymbol)!;
|
|
const audioContext = inject(AudioContextSymbol) as AudioContext;
|
|
const deviceManager = inject(RemoteDeviceManagerSymbol)!;
|
|
|
|
const audioNodesManager = new AudioNodeManager();
|
|
const nodes = reactive(audioNodesManager.restore({fs, audioContext}));
|
|
|
|
function addNode(name: string) {
|
|
if (name === 'playlist') {
|
|
nodes.push(reactive(new PlaylistGroupNode({
|
|
currentTrack: 0,
|
|
currentTrackTime: 0,
|
|
volume: 100,
|
|
isMuted: false,
|
|
sounds: [],
|
|
}, {
|
|
fs,
|
|
audioContext,
|
|
})))
|
|
} else if (name === 'sfx') {
|
|
nodes.push(reactive(new SfxGroupNode({
|
|
isMuted: false,
|
|
volume: 100,
|
|
sounds: [],
|
|
}, {
|
|
fs,
|
|
audioContext,
|
|
})))
|
|
} else if (name === 'tab') {
|
|
nodes.push(reactive(new TabSourceNode({
|
|
isMuted: false,
|
|
volume: 100,
|
|
sounds: [],
|
|
}, {
|
|
fs,
|
|
audioContext,
|
|
})))
|
|
}
|
|
}
|
|
|
|
const deleteNode = (node: SoundNode) => {
|
|
node.stop?.();
|
|
node.disconnect();
|
|
// @ts-ignore
|
|
nodes.splice(nodes.indexOf(node), 1);
|
|
}
|
|
|
|
watch(() => nodes, debounce((newNodes) => {
|
|
console.log('NEW_NODES', newNodes);
|
|
audioNodesManager.store(newNodes);
|
|
}, 500), {
|
|
deep: true,
|
|
})
|
|
|
|
const dest = audioContext.createGain();
|
|
|
|
// for (const node of nodes) {
|
|
// // node.connect(audioContext.destination);
|
|
// node.connect(dest);
|
|
// }
|
|
|
|
|
|
watch(() => deviceManager.audioDevices.length, () => {
|
|
console.log('DEVICE_MANAGER', deviceManager)
|
|
for(const device of deviceManager.audioDevices) {
|
|
dest.connect(device.audioSink);
|
|
console.log('DEVICES', device, device.audioSink);
|
|
}
|
|
}, {immediate: true})
|
|
|
|
</script>
|
|
<style>
|
|
.soundboard {
|
|
|
|
}
|
|
|
|
|
|
.soundboard__controls {
|
|
display: flex;
|
|
flex-direction: row;
|
|
padding: 0 1rem 2rem 1rem;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.soundboard__sounds {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
gap: 3rem 1rem;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.soundboard-add-card {
|
|
|
|
}
|
|
|
|
.soundboard-add-card__btn {
|
|
text-align: center;
|
|
border: 1px solid;
|
|
margin: 0.25rem;
|
|
background: var(--box-color-900);
|
|
border: 1px solid rgba(from var(--box-color) r g b / 0.2);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.soundboard-add-card__btn:hover {
|
|
background: var(--box-color-800);
|
|
}
|
|
</style>
|
|
|