studiox-mixer/frontend/src/hooks/use-osc-reducer.js

108 lines
3 KiB
JavaScript

import { useState, useReducer, useEffect } from 'react'
import osc from '../lib/osc'
import Debug from 'debug'
// const STATE = '/s'
// const COMMAND = '/c'
const debug = Debug('ui:osc:reducer')
/**
* Listen on a OSC value change over time.
*/
export function useOscValue (address, defaultValue, opts = {}) {
// TODO: Global store.
const [state, setState] = useState(defaultValue)
useEffect(() => {
// const stateAddress = STATE + address
// console.log('useOscValue init', stateAddress)
const unwatch = osc.on(address, message => {
const { address, args } = message
if (opts.single) setState(args[0])
else setState(args)
// setState(state => ({ ...state, [address]: args }))
})
return unwatch
}, [address])
return state
}
/**
* Write to an OSC value.
*/
export function useOscWritable (address, defaultValue, opts = {}) {
const state = useOscValue(address, defaultValue, opts)
return [state, setState]
function setState (nextValue) {
if (typeof nextValue === 'function') nextValue = nextValue(state)
// const commandAddress = COMMAND + address
// const parts = address.split('/')
// const last = parts.pop()
// const cmdAddress = [...parts, 'cmd', last].join('/')
console.log('useOscWritable write', address, nextValue)
osc.send(address, nextValue)
}
}
export function useOscReducer (reducer, initialState, prefix = '') {
const [state, localDispatch] = useReducer(reducer, initialState)
const prefixLen = prefix.split('/').length
// Listen for all state change messages and dispatch into the reducer.
useEffect(() => {
const wildcardAddress = prefix + '/*'
const unwatch = osc.on(wildcardAddress, message => {
const { address, args } = message
const key = address.split('/').slice(prefixLen + 1).join('/')
localDispatch({ cmd: 'set', address: key, args })
})
return unwatch
})
return [state, dispatch]
function dispatch (action) {
console.log('useOscReducer dispatch', action)
send(action)
}
function send (action) {
const { address, args } = action
const fullAddress = COMMAND + prefix + address
osc.send(fullAddress, args)
}
}
// TODO: Broken, fix address paths.
export function useOscReducerOld (reducer, initialState, prefix) {
const [state, localDispatch] = useReducer(reducer, initialState)
// const [remoteState, remoteDispatch] = useReducer(reducer, initialState)
//
useEffect(() => {
const path = prefix + '/state/*'
const unwatch = osc.on(path, message => {
const { address, args } = message
// console.log('RECVV!!!!', message)
const key = address.split('/').pop()
localDispatch({ cmd: 'set', key, args })
})
return unwatch
}, [])
return [state, dispatch]
function dispatch (action) {
console.log('dispatch', action)
send(action)
// localDispatch(action)
}
function send (action) {
const { cmd, args } = action
const address = [prefix, 'cmd', cmd].join('/')
osc.send(address, args)
}
}