diff --git a/demo-project/DWS - Beep Boop/index.json b/demo-project/DWS - Beep Boop/index.json index 3b358e2a..0ab7ddbc 100644 --- a/demo-project/DWS - Beep Boop/index.json +++ b/demo-project/DWS - Beep Boop/index.json @@ -1,7 +1,7 @@ { "controllers": [ { - "port": "Launchpad MK2", + "port": null, "loopLength": 16, "chunkPositions": { "Perc": [ @@ -29,7 +29,7 @@ 0 ] }, - "node": "controller/launchpad-mk2" + "node": "controller/qwerty" }, { "port": "Launchpad MK2 2", @@ -622,7 +622,7 @@ "node": "modulatorChunk" } ], - "selectedChunkId": "Perc", + "selectedChunkId": "bass", "volume": 1, "globalScale": { "offset": 0, diff --git a/index.js b/index.js index 383c8d0a..d80a6bde 100644 --- a/index.js +++ b/index.js @@ -55,9 +55,23 @@ var rootContext = window.rootContext = { nodes: nodes.objectLookup, nodeInfo: nodes, zoom: Property(1.1), - version: version + version: version, + alternateOutputs: [], + alternateInputs: [] } +function addAlternates(deviceInfos) { + deviceInfos.forEach(function (device) { + var miniInfo = { label: device.label, deviceId: device.deviceId } + if (device.kind === 'audioinput') rootContext.alternateInputs.push(miniInfo) + if (device.kind === 'audiooutput') rootContext.alternateOutputs.push(miniInfo) + }) +} + +navigator.mediaDevices.enumerateDevices().then(addAlternates).catch(function (e) { + console.log('unable to get any alternate devices', e) +}); + watch(rootContext.zoom, function (value) { electron.webFrame.setZoomFactor(value || 1) }) diff --git a/nodes/setup/object.js b/nodes/setup/object.js index 3fbc9248..d8156c85 100644 --- a/nodes/setup/object.js +++ b/nodes/setup/object.js @@ -34,7 +34,8 @@ function Setup (parentContext) { globalScale: Property({ offset: 0, notes: [0, 2, 4, 5, 7, 9, 11] - }) + }), + selectedOutputId: Property('default') }) node.overrideVolume = Property(1) @@ -61,7 +62,12 @@ function Setup (parentContext) { context.output.connect(outputLowPass) outputLowPass.connect(outputHighPass) node.output = YankSilence(audioContext, outputHighPass) - node.output.connect(parentContext.output) + //node.output.connect(parentContext.output)// + var dest = audioContext.createMediaStreamDestination() + node.output.connect(dest) + node.audioElement = new Audio() + node.audioElement.srcObject = dest.stream + node.audioElement.play() context.active = node.output.active @@ -70,6 +76,17 @@ function Setup (parentContext) { }) var releases = [ + watch(node.selectedOutputId, function (value) { + node.output.disconnect() + node.audioElement = new Audio() + node.audioElement.setSinkId(value).then(() => { + var dest = audioContext.createMediaStreamDestination() + node.output.connect(dest) + node.audioElement.srcObject = dest.stream + node.audioElement.play() + }) + }), + watch(computed([node.volume, node.overrideVolume], (a, b) => a * b), function (value) { node.output.gain.value = value }), diff --git a/nodes/setup/view.js b/nodes/setup/view.js index d31f8446..9ecbc430 100644 --- a/nodes/setup/view.js +++ b/nodes/setup/view.js @@ -3,6 +3,7 @@ var send = require('mutant/send') var Collection = require('lib/widgets/collection') var Spawner = require('lib/widgets/spawner') +var Select = require('lib/params/select') var QueryParam = require('lib/query-param') var ScaleChooser = require('lib/params/scale-chooser') var Range = require('lib/params/range') @@ -49,15 +50,29 @@ function renderSetup (setup) { h('div.options', [ renderScaleChooser(setup.globalScale), - renderMasterVolume(setup.volume) + renderMasterVolume(setup.volume), + renderOutputSelector(setup), ]) ]) } +function renderOutputSelector(setup) { + var outputOptions = setup.context.alternateOutputs.map(function (info) { + return [info.label, info.deviceId] + }) + var params = [ + Select(QueryParam(setup, 'selectedOutputId'), { + options: outputOptions, + flex: true, + missingPrefix: ' (unknown)' + }) + ] + return h('ParamList', params) +} + function renderMasterVolume (volume) { return h('section.volume', [ - h('h1', 'Master Volume'), h('div.param', [ Range(volume, {