diff --git a/src/actions/graph.ts b/src/actions/graph.ts index 914a411..7a5a393 100644 --- a/src/actions/graph.ts +++ b/src/actions/graph.ts @@ -8,10 +8,9 @@ import { getConnectionsForSourceNodeAndPort, getNode, getPatcherNodeByIndex, get import { showNotification } from "./notifications"; import { NotificationLevel } from "../models/notification"; import { PatcherInstanceRecord } from "../models/instance"; -import { deleteInstance, setInstance, setInstanceMessageInports, setInstanceMessageOutports, setInstanceParameters, setInstances } from "./instances"; -import { getInstance } from "../selectors/instances"; -import { PatcherRecord } from "../models/patcher"; -import { getPatchers } from "../selectors/instances"; +import { deleteInstance, setInstance, setInstanceMessageInports, setInstanceMessageOutports, setInstanceParameters, setInstances } from "./patchers"; +import { getPatcherInstance, getPatcherExports } from "../selectors/patchers"; +import { PatcherExportRecord } from "../models/patcher"; import { defaultNodeGap, nodeDefaultWidth, nodeHeaderHeight } from "../lib/constants"; import { getGraphEditorInstance } from "../selectors/editor"; import { ParameterRecord } from "../models/parameter"; @@ -545,7 +544,7 @@ export const updateSystemOrControlPortInfo = (type: ConnectionType, direction: P let systemInputY = -defaultNodeGap; let systemOutputY = -defaultNodeGap; - const patchers = getPatchers(state).valueSeq(); + const patchers = getPatcherExports(state).valueSeq(); const missingSystemOrControlJackName = Array.from(systemOrControlJackNames.values()) .filter(name => !patchers.find(patcher => name.startsWith(`${patcher.name}-`))); @@ -629,7 +628,7 @@ export const unloadPatcherNodeByIndexOnRemote = (instanceIndex: number): AppThun } }; -export const loadPatcherNodeOnRemote = (patcher: PatcherRecord): AppThunk => +export const loadPatcherNodeOnRemote = (patcher: PatcherExportRecord): AppThunk => (dispatch) => { try { const message = { @@ -715,7 +714,7 @@ export const removePatcherNode = (index: number): AppThunk => if (node?.type !== NodeType.Patcher) return; dispatch(deleteNode(node)); - const instance = getInstance(state, node.id); + const instance = getPatcherInstance(state, node.id); if (!instance) return; dispatch(deleteInstance(instance)); diff --git a/src/actions/instances.ts b/src/actions/instances.ts deleted file mode 100644 index 68fd76e..0000000 --- a/src/actions/instances.ts +++ /dev/null @@ -1,918 +0,0 @@ -import Router from "next/router"; -import { ActionBase, AppThunk } from "../lib/store"; -import { OSCQueryRNBOInstance, OSCQueryRNBOInstancePresetEntries, OSCQueryRNBOPatchersState, OSCValue } from "../lib/types"; -import { PatcherInstanceRecord } from "../models/instance"; -import { getInstanceByIndex, getInstance, getParameter, getInstanceParameters, getInstanceParameterByName, getParameterByPath, getInstanceMessageInports, getInstanceMessageOutports, getInstanceMessageOutportByTag, getInstanceMessageInportByTag, getMessageInportByPath, getMessageOutportByPath } from "../selectors/instances"; -import { getAppSetting } from "../selectors/settings"; -import { ParameterRecord } from "../models/parameter"; -import { MessagePortRecord } from "../models/messageport"; -import { OSCArgument, OSCMessage, writePacket } from "osc"; -import { showNotification } from "./notifications"; -import { NotificationLevel } from "../models/notification"; -import { oscQueryBridge } from "../controller/oscqueryBridgeController"; -import throttle from "lodash.throttle"; -import { PresetRecord } from "../models/preset"; -import { AppSetting } from "../models/settings"; -import { DataRefRecord } from "../models/dataref"; -import { DataFileRecord } from "../models/datafile"; -import { PatcherRecord } from "../models/patcher"; - -export enum InstanceActionType { - INIT_PATCHERS = "INIT_PATCHERS", - - SET_INSTANCE = "SET_INSTANCE", - SET_INSTANCES = "SET_INSTANCES", - DELETE_INSTANCE = "DELETE_INSTANCE", - DELETE_INSTANCES = "DELETE_INSTANCES", - - SET_PARAMETER = "SET_PARAMETER", - SET_PARAMETERS = "SET_PARAMETERS", - DELETE_PARAMETER = "DELETE_PARAMETER", - DELETE_PARAMETERS = "DELETE_PARAMETERS", - - SET_MESSAGE_INPORT = "SET_MESSAGE_INPORT", - SET_MESSAGE_INPORTS = "SET_MESSAGE_INPORTS", - DELETE_MESSAGE_INPORT = "DELETE_MESSAGE_INPORT", - DELETE_MESSAGE_INPORTS = "DELETE_MESSAGE_INPORTS", - - SET_MESSAGE_OUTPORT = "SET_MESSAGE_OUTPORT", - SET_MESSAGE_OUTPORTS = "SET_MESSAGE_OUTPORTS", - DELETE_MESSAGE_OUTPORT = "DELETE_MESSAGE_OUTPORT", - DELETE_MESSAGE_OUTPORTS = "DELETE_MESSAGE_OUTPORTS" -} - -export interface IInitPatchers extends ActionBase { - type: InstanceActionType.INIT_PATCHERS; - payload: { - patchers: PatcherRecord[]; - }; -} - -export interface ISetInstance extends ActionBase { - type: InstanceActionType.SET_INSTANCE; - payload: { - instance: PatcherInstanceRecord; - }; -} - -export interface ISetInstances extends ActionBase { - type: InstanceActionType.SET_INSTANCES; - payload: { - instances: PatcherInstanceRecord[]; - }; -} - -export interface IDeleteInstance extends ActionBase { - type: InstanceActionType.DELETE_INSTANCE; - payload: { - instance: PatcherInstanceRecord; - }; -} - -export interface IDeleteInstances extends ActionBase { - type: InstanceActionType.DELETE_INSTANCES; - payload: { - instances: PatcherInstanceRecord[]; - }; -} - -export interface ISetInstanceParameter extends ActionBase { - type: InstanceActionType.SET_PARAMETER; - payload: { - parameter: ParameterRecord; - }; -} - -export interface ISetInstanceParameters extends ActionBase { - type: InstanceActionType.SET_PARAMETERS; - payload: { - parameters: ParameterRecord[]; - }; -} - -export interface IDeleteInstanceParameter extends ActionBase { - type: InstanceActionType.DELETE_PARAMETER; - payload: { - parameter: ParameterRecord; - }; -} - -export interface IDeleteInstanceParameters extends ActionBase { - type: InstanceActionType.DELETE_PARAMETERS; - payload: { - parameters: ParameterRecord[]; - }; -} - -export interface ISetInstanceMessageInport extends ActionBase { - type: InstanceActionType.SET_MESSAGE_INPORT; - payload: { - port: MessagePortRecord; - }; -} - -export interface ISetInstanceMessageInports extends ActionBase { - type: InstanceActionType.SET_MESSAGE_INPORTS; - payload: { - ports: MessagePortRecord[]; - }; -} - -export interface IDeleteInstanceMessageInport extends ActionBase { - type: InstanceActionType.DELETE_MESSAGE_INPORT; - payload: { - port: MessagePortRecord; - }; -} - -export interface IDeleteInstanceMessageInports extends ActionBase { - type: InstanceActionType.DELETE_MESSAGE_INPORTS; - payload: { - ports: MessagePortRecord[]; - }; -} - -export interface ISetInstanceMessageOutport extends ActionBase { - type: InstanceActionType.SET_MESSAGE_OUTPORT; - payload: { - port: MessagePortRecord; - }; -} - -export interface ISetInstanceMessageOutports extends ActionBase { - type: InstanceActionType.SET_MESSAGE_OUTPORTS; - payload: { - ports: MessagePortRecord[]; - }; -} - -export interface IDeleteInstanceMessageOutport extends ActionBase { - type: InstanceActionType.DELETE_MESSAGE_OUTPORT; - payload: { - port: MessagePortRecord; - }; -} - -export interface IDeleteInstanceMessageOutports extends ActionBase { - type: InstanceActionType.DELETE_MESSAGE_OUTPORTS; - payload: { - ports: MessagePortRecord[]; - }; -} - -export type InstanceAction = IInitPatchers | ISetInstance | ISetInstances | IDeleteInstance | IDeleteInstances | -ISetInstanceParameter | ISetInstanceParameters | IDeleteInstanceParameter | IDeleteInstanceParameters | -ISetInstanceMessageInport | ISetInstanceMessageInports | IDeleteInstanceMessageInport | IDeleteInstanceMessageInports | -ISetInstanceMessageOutport | ISetInstanceMessageOutports | IDeleteInstanceMessageOutport | IDeleteInstanceMessageOutports; - -export const initPatchers = (patchersInfo: OSCQueryRNBOPatchersState): IInitPatchers => { - - const patchers: PatcherRecord[] = []; - for (const [name, desc] of Object.entries(patchersInfo.CONTENTS || {})) { - patchers.push(PatcherRecord.fromDescription(name, desc)); - } - - return { - type: InstanceActionType.INIT_PATCHERS, - payload: { - patchers - } - }; -}; - -export const destroyPatcherOnRemote = (patcher: PatcherRecord): AppThunk => - (dispatch) => { - try { - const message: OSCMessage = { - address: `/rnbo/patchers/${patcher.name}/destroy`, - args: [] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to delete patcher ${patcher.name}`, - message: "Please check the console for further details." - })); - console.error(err); - } - }; - - -export const renamePatcherOnRemote = (patcher: PatcherRecord, newName: string): AppThunk => - (dispatch) => { - try { - const message = { - address: `/rnbo/patchers/${patcher.name}/rename`, - args: [ - { type: "s", value: newName } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to rename patcher ${patcher.name} -> ${newName}`, - message: "Please check the console for further details." - })); - console.error(err); - } - }; - - -export const setInstance = (instance: PatcherInstanceRecord): ISetInstance => ({ - type: InstanceActionType.SET_INSTANCE, - payload: { - instance - } -}); - -export const setInstances = (instances: PatcherInstanceRecord[]): ISetInstances => ({ - type: InstanceActionType.SET_INSTANCES, - payload: { - instances - } -}); - -export const deleteInstance = (instance: PatcherInstanceRecord): IDeleteInstance => ({ - type: InstanceActionType.DELETE_INSTANCE, - payload: { - instance - } -}); - -export const deleteInstances = (instances: PatcherInstanceRecord[]): IDeleteInstances => ({ - type: InstanceActionType.DELETE_INSTANCES, - payload: { - instances - } -}); - -export const setInstanceParameter = (param: ParameterRecord): ISetInstanceParameter => ({ - type: InstanceActionType.SET_PARAMETER, - payload: { - parameter: param - } -}); - -export const setInstanceParameters = (params: ParameterRecord[]): ISetInstanceParameters => ({ - type: InstanceActionType.SET_PARAMETERS, - payload: { - parameters: params - } -}); - -export const deleteInstanceParameter = (param: ParameterRecord): IDeleteInstanceParameter => ({ - type: InstanceActionType.DELETE_PARAMETER, - payload: { - parameter: param - } -}); - -export const deleteInstanceParameters = (params: ParameterRecord[]): IDeleteInstanceParameters => ({ - type: InstanceActionType.DELETE_PARAMETERS, - payload: { - parameters: params - } -}); - -export const setInstanceMessageInport = (port: MessagePortRecord): ISetInstanceMessageInport => ({ - type: InstanceActionType.SET_MESSAGE_INPORT, - payload: { - port - } -}); - -export const setInstanceMessageInports = (ports: MessagePortRecord[]): ISetInstanceMessageInports => ({ - type: InstanceActionType.SET_MESSAGE_INPORTS, - payload: { - ports - } -}); - -export const deleteInstanceMessageInport = (port: MessagePortRecord): IDeleteInstanceMessageInport => ({ - type: InstanceActionType.DELETE_MESSAGE_INPORT, - payload: { - port - } -}); - -export const deleteInstanceMessageInports = (ports: MessagePortRecord[]): IDeleteInstanceMessageInports => ({ - type: InstanceActionType.DELETE_MESSAGE_INPORTS, - payload: { - ports - } -}); - -export const setInstanceMessageOutport = (port: MessagePortRecord): ISetInstanceMessageOutport => ({ - type: InstanceActionType.SET_MESSAGE_OUTPORT, - payload: { - port - } -}); - -export const setInstanceMessageOutports = (ports: MessagePortRecord[]): ISetInstanceMessageOutports => ({ - type: InstanceActionType.SET_MESSAGE_OUTPORTS, - payload: { - ports - } -}); - -export const deleteInstanceMessageOutport = (port: MessagePortRecord): IDeleteInstanceMessageOutport => ({ - type: InstanceActionType.DELETE_MESSAGE_OUTPORT, - payload: { - port - } -}); - -export const deleteInstanceMessageOutports = (ports: MessagePortRecord[]): IDeleteInstanceMessageOutports => ({ - type: InstanceActionType.DELETE_MESSAGE_OUTPORTS, - payload: { - ports - } -}); - -// Trigger Events on Remote OSCQuery Runner -export const loadPresetOnRemoteInstance = (instance: PatcherInstanceRecord, preset: PresetRecord): AppThunk => - (dispatch) => { - try { - const message = { - address: `${instance.path}/presets/load`, - args: [ - { type: "s", value: preset.name } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to load preset ${preset.name}`, - message: "Please check the console for further details." - })); - console.log(err); - } - }; - -export const savePresetToRemoteInstance = (instance: PatcherInstanceRecord, name: string): AppThunk => - (dispatch) => { - try { - const message = { - address: `${instance.path}/presets/save`, - args: [ - { type: "s", value: name } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to save preset ${name}`, - message: "Please check the console for further details." - })); - console.log(err); - } - }; - -export const destroyPresetOnRemoteInstance = (instance: PatcherInstanceRecord, preset: PresetRecord): AppThunk => - (dispatch) => { - try { - const message = { - address: `${instance.path}/presets/delete`, - args: [ - { type: "s", value: preset.name } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to delete preset ${preset.name}`, - message: "Please check the console for further details." - })); - console.log(err); - } - }; - -export const renamePresetOnRemoteInstance = (instance: PatcherInstanceRecord, preset: PresetRecord, name: string): AppThunk => - (dispatch) => { - try { - const message = { - address: `${instance.path}/presets/rename`, - args: [ - { type: "s", value: preset.name }, - { type: "s", value: name } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to rename preset ${preset.name} to ${name}`, - message: "Please check the console for further details." - })); - console.log(err); - } - }; - -export const setInitialPresetOnRemoteInstance = (instance: PatcherInstanceRecord, preset: PresetRecord): AppThunk => - (dispatch) => { - try { - const message = { - address: `${instance.path}/presets/initial`, - args: [ - { type: "s", value: preset.name } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: `Error while trying to set initial preset to ${preset.name}`, - message: "Please check the console for further details." - })); - console.log(err); - } - }; - -export const sendInstanceMessageToRemote = (instance: PatcherInstanceRecord, inportId: string, value: string): AppThunk => - (dispatch) => { - const values = value.split(" ").reduce((values, v) => { - const fv = parseFloat(v.replaceAll(",", ".").trim()); - if (!isNaN(fv)) values.push({ type: "f", value: fv }); - return values; - }, [] as OSCArgument[]); - - if (!values.length) { - dispatch(showNotification({ - title: "Invalid Message Input", - level: NotificationLevel.warn, - message: `Could not send message input "${value}" as it appears to contain non-valid number input. Please provide a single or multiple numbers separated by a space.` - })); - return; - } - - - const message = { - address: `/rnbo/inst/${instance.index}/messages/in/${inportId}`, - args: values - }; - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const triggerInstanceMidiNoteOnEventOnRemote = (instance: PatcherInstanceRecord, note: number): AppThunk => - () => { - - const midiChannel = 0; - const routeByte = 144 + midiChannel; - const velocityByte = 100; - - const message = { - address: `${instance.path}/midi/in`, - args: [routeByte, note, velocityByte].map(byte => ({ type: "i", value: byte })) - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const triggerInstanceMidiNoteOffEventOnRemote = (instance: PatcherInstanceRecord, note: number): AppThunk => - () => { - - const midiChannel = 0; - const routeByte = 128 + midiChannel; - const velocityByte = 0; - - const message = { - address: `${instance.path}/midi/in`, - args: [routeByte, note, velocityByte].map(byte => ({ type: "i", value: byte })) - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const setInstanceParameterValueNormalizedOnRemote = throttle((instance: PatcherInstanceRecord, param: ParameterRecord, value: number): AppThunk => - (dispatch) => { - - const message = { - address: `${param.path}/normalized`, - args: [ - { type: "f", value } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - // optimistic local state update - dispatch(setInstanceParameter(param.setNormalizedValue(value))); - }, 10); - -export const setInstanceDataRefValueOnRemote = (instance: PatcherInstanceRecord, dataref: DataRefRecord, file?: DataFileRecord): AppThunk => - () => { - - const message = { - address: `${instance.path}/data_refs/${dataref.id}`, - args: [ - { type: "s", value: file?.fileName || "" } // no files unsets - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const setInstanceParameterMetaOnRemote = (_instance: PatcherInstanceRecord, param: ParameterRecord, value: string): AppThunk => - () => { - const message = { - address: `${param.path}/meta`, - args: [ - { type: "s", value } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const restoreDefaultParameterMetaOnRemote = (_instance: PatcherInstanceRecord, param: ParameterRecord): AppThunk => - () => { - const message = { - address: `${param.path}/meta`, - args: [ - { type: "s", value: "" } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const activateParameterMIDIMappingFocus = (instance: PatcherInstanceRecord, param: ParameterRecord): AppThunk => - (dispatch, getState) => { - - const state = getState(); - const params = getInstanceParameters(state, instance.index); - - dispatch(setInstanceParameters( - params.valueSeq().toArray().map(p => p.setWaitingForMidiMapping(p.id === param.id)) - )); - }; - -export const clearParameterMidiMappingOnRemote = (id: PatcherInstanceRecord["id"], paramId: ParameterRecord["id"]): AppThunk => - (_dispatch, getState) => { - const state = getState(); - const instance = getInstance(state, id); - if (!instance) return; - - const param = getParameter(state, paramId); - if (!param) return; - - const meta = param.getParsedMetaObject(); - delete meta.midi; - const message = { - address: `${param.path}/meta`, - args: [ - { type: "s", value: JSON.stringify(meta) } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const setInstanceMessagePortMetaOnRemote = (_instance: PatcherInstanceRecord, port: MessagePortRecord, value: string): AppThunk => - () => { - const message = { - address: `${port.path}/meta`, - args: [ - { type: "s", value } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -export const restoreDefaultMessagePortMetaOnRemote = (_instance: PatcherInstanceRecord, port: MessagePortRecord): AppThunk => - () => { - const message = { - address: `${port.path}/meta`, - args: [ - { type: "s", value: "" } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - }; - -// Updates in response to remote OSCQuery Updates -export const updateInstancePresetEntries = (index: number, entries: OSCQueryRNBOInstancePresetEntries): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - dispatch(setInstance(instance.updatePresets(entries))); - } catch (e) { - console.log(e); - } - }; - -export const updateInstancePresetLatest = (index: number, name: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - dispatch(setInstance(instance.setPresetLatest(name))); - } catch (e) { - console.log(e); - } - }; - -export const updateInstancePresetInitial = (index: number, name: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - dispatch(setInstance(instance.setPresetInitial(name))); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceMessages = (index: number, desc: OSCQueryRNBOInstance["CONTENTS"]["messages"]): AppThunk => - (dispatch, getState) => { - try { - if (!desc) return; - - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - const currentMessageInports = getInstanceMessageInports(state, instance.index); - const currentMessageOutports = getInstanceMessageOutports(state, instance.index); - dispatch(deleteInstanceMessageInports(currentMessageInports.valueSeq().toArray())); - dispatch(deleteInstanceMessageOutports(currentMessageOutports.valueSeq().toArray())); - - const messageInports = MessagePortRecord.fromDescription(desc.CONTENTS?.in); - const messageOutports = MessagePortRecord.fromDescription(desc.CONTENTS?.out); - - dispatch(setInstanceMessageInports(messageInports)); - dispatch(setInstanceMessageOutports(messageOutports)); - - } catch (e) { - console.log(e); - } - }; - -export const removeInstanceMessageInportByPath = (path: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const port = getMessageInportByPath(state, path); - if (!port) return; - - dispatch(deleteInstanceMessageInport(port)); - } catch (e) { - console.log(e); - } - }; - -export const removeInstanceMessageOutportByPath = (path: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const port = getMessageOutportByPath(state, path); - if (!port) return; - - dispatch(deleteInstanceMessageOutport(port)); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceMessageOutportValue = (index: number, tag: MessagePortRecord["tag"], value: OSCValue | OSCValue[]): AppThunk => - (dispatch, getState) => { - try { - - const state = getState(); - - // Debug enabled?! - const enabled = getAppSetting(state, AppSetting.debugMessageOutput)?.value || false; - if (!enabled) return; - - // Active Instance view?! - if (Router.pathname !== "/instances/[index]" || Router.query.index !== `${index}`) return; - - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - const port = getInstanceMessageOutportByTag(state, instance.index, tag); - if (!port) return; - - dispatch(setInstanceMessageOutport(port.setValue(Array.isArray(value) ? value.join(", ") : `${value}`))); - } catch (e) { - console.log(e); - } - }; - -export const removeInstanceParameterByPath = (path: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const param = getParameterByPath(state, path); - if (!param) return; - - dispatch(deleteInstanceParameter(param)); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceParameters = (index: number, desc: OSCQueryRNBOInstance["CONTENTS"]["params"]): AppThunk => - (dispatch, getState) => { - try { - if (!desc) return; - - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - const currentParams = getInstanceParameters(state, instance.index); - dispatch(deleteInstanceParameters(currentParams.valueSeq().toArray())); - - const newParams = ParameterRecord.fromDescription(instance.index, desc); - dispatch(setInstanceParameters(newParams)); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceDataRefValue = (index: number, name: string, value: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - dispatch(setInstance( - instance.setDataRefValue(name, value) - )); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceParameterValue = (index: number, name: ParameterRecord["name"], value: number): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const param = getInstanceParameterByName(state, index, name); - if (!param) return; - - dispatch(setInstanceParameter(param.setValue(value))); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceParameterValueNormalized = (index: number, name: ParameterRecord["name"], value: number): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const param = getInstanceParameterByName(state, index, name); - if (!param) return; - - dispatch(setInstanceParameter(param.setNormalizedValue(value))); - } catch (e) { - console.log(e); - } - }; - -export const setInstanceWaitingForMidiMappingOnRemote = (id: PatcherInstanceRecord["id"], value: boolean): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstance(state, id); - if (!instance) return; - - dispatch(setInstance(instance.setWaitingForMapping(value))); - const params = getInstanceParameters(state, instance.index).valueSeq().map(p => p.setWaitingForMidiMapping(false)); - dispatch(setInstanceParameters(params.toArray())); - - try { - const message = { - address: `${instance.path}/midi/last/report`, - args: [ - { type: value ? "T" : "F", value: value ? "true" : "false" } - ] - }; - oscQueryBridge.sendPacket(writePacket(message)); - } catch (err) { - dispatch(showNotification({ - level: NotificationLevel.error, - title: "Error while trying set midi mapping mode on remote", - message: "Please check the console for further details." - })); - console.log(err); - } - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceMIDIReport = (index: number, value: boolean): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - dispatch(setInstance(instance.setWaitingForMapping(value))); - const params = getInstanceParameters(state, instance.index).valueSeq().map(p => p.setWaitingForMidiMapping(false)); - dispatch(setInstanceParameters(params.toArray())); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceMIDILastValue = (index: number, value: string): AppThunk => - (dispatch, getState) => { - try { - - const state = getState(); - - const instance = getInstanceByIndex(state, index); - if (!instance?.waitingForMidiMapping) return; - - const midiMeta = JSON.parse(value); - - // find waiting, update their meta, set them no longer waiting and update map - const parameters: ParameterRecord[] = []; - getInstanceParameters(state, instance.index).forEach(param => { - if (param.waitingForMidiMapping) { - const meta = param.getParsedMetaObject(); - meta.midi = midiMeta; - - const message = { - address: `${param.path}/meta`, - args: [ - { type: "s", value: JSON.stringify(meta) } - ] - }; - - oscQueryBridge.sendPacket(writePacket(message)); - parameters.push(param.setWaitingForMidiMapping(false)); - } - }); - - dispatch(setInstanceParameters(parameters)); - - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceParameterMeta = (index: number, name: ParameterRecord["name"], value: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const param = getInstanceParameterByName(state, index, name); - if (!param) return; - - dispatch(setInstanceParameter(param.setMeta(value))); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceMessageOutportMeta = (index: number, tag: MessagePortRecord["tag"], value: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - const port = getInstanceMessageOutportByTag(state, instance.index, tag); - if (!port) return; - - dispatch(setInstanceMessageOutport(port.setMeta(value))); - } catch (e) { - console.log(e); - } - }; - -export const updateInstanceMessageInportMeta = (index: number, tag: MessagePortRecord["tag"], value: string): AppThunk => - (dispatch, getState) => { - try { - const state = getState(); - const instance = getInstanceByIndex(state, index); - if (!instance) return; - - const port = getInstanceMessageInportByTag(state, instance.index, tag); - if (!port) return; - - dispatch(setInstanceMessageInport(port.setMeta(value))); - } catch (e) { - console.log(e); - } - }; - -// Events from remote diff --git a/src/components/instance/datarefTab.tsx b/src/components/instance/datarefTab.tsx index 9e2829c..26b5fbe 100644 --- a/src/components/instance/datarefTab.tsx +++ b/src/components/instance/datarefTab.tsx @@ -4,7 +4,7 @@ import { useAppDispatch } from "../../hooks/useAppDispatch"; import DataRefList from "../dataref/list"; import classes from "./instance.module.css"; import { PatcherInstanceRecord } from "../../models/instance"; -import { setInstanceDataRefValueOnRemote } from "../../actions/instances"; +import { setInstanceDataRefValueOnRemote } from "../../actions/patchers"; import { DataRefRecord } from "../../models/dataref"; import { modals } from "@mantine/modals"; import { DataFileRecord } from "../../models/datafile"; diff --git a/src/components/instance/messageTab.tsx b/src/components/instance/messageTab.tsx index a386f29..bb4a7a9 100644 --- a/src/components/instance/messageTab.tsx +++ b/src/components/instance/messageTab.tsx @@ -7,9 +7,9 @@ import { SectionTitle } from "../page/sectionTitle"; import MessageOutportList from "../messages/outportList"; import classes from "./instance.module.css"; import { PatcherInstanceRecord } from "../../models/instance"; -import { sendInstanceMessageToRemote } from "../../actions/instances"; +import { sendInstanceMessageToRemote } from "../../actions/patchers"; import { MessagePortRecord } from "../../models/messageport"; -import { restoreDefaultMessagePortMetaOnRemote, setInstanceMessagePortMetaOnRemote } from "../../actions/instances"; +import { restoreDefaultMessagePortMetaOnRemote, setInstanceMessagePortMetaOnRemote } from "../../actions/patchers"; export type InstanceMessageTabProps = { instance: PatcherInstanceRecord; diff --git a/src/components/instance/paramTab.tsx b/src/components/instance/paramTab.tsx index a4f7d35..893939c 100644 --- a/src/components/instance/paramTab.tsx +++ b/src/components/instance/paramTab.tsx @@ -11,7 +11,7 @@ import { setInstanceParameterValueNormalizedOnRemote, setInstanceWaitingForMidiMappingOnRemote, clearParameterMidiMappingOnRemote, activateParameterMIDIMappingFocus -} from "../../actions/instances"; +} from "../../actions/patchers"; import { OrderedSet as ImmuOrderedSet, Map as ImmuMap } from "immutable"; import { setAppSetting } from "../../actions/settings"; import { AppSetting, AppSettingRecord } from "../../models/settings"; diff --git a/src/components/keyroll/modal.tsx b/src/components/keyroll/modal.tsx index 5b60bdc..918cc47 100644 --- a/src/components/keyroll/modal.tsx +++ b/src/components/keyroll/modal.tsx @@ -2,7 +2,7 @@ import { FunctionComponent, memo, useCallback, useEffect } from "react"; import { useAppDispatch } from "../../hooks/useAppDispatch"; import KeyRoll from "../keyroll"; import { PatcherInstanceRecord } from "../../models/instance"; -import { triggerInstanceMidiNoteOffEventOnRemote, triggerInstanceMidiNoteOnEventOnRemote } from "../../actions/instances"; +import { triggerInstanceMidiNoteOffEventOnRemote, triggerInstanceMidiNoteOnEventOnRemote } from "../../actions/patchers"; import { Group, Modal } from "@mantine/core"; import { useIsMobileDevice } from "../../hooks/useIsMobileDevice"; import { IconElement } from "../elements/icon"; diff --git a/src/components/patchers/index.tsx b/src/components/patchers/index.tsx index f35dafe..766ce70 100644 --- a/src/components/patchers/index.tsx +++ b/src/components/patchers/index.tsx @@ -1,7 +1,7 @@ import { Alert, Drawer, Group, Stack, Text } from "@mantine/core"; import { FunctionComponent, memo, useCallback } from "react"; import { Seq } from "immutable"; -import { PatcherRecord } from "../../models/patcher"; +import { PatcherExportRecord } from "../../models/patcher"; import { PatcherItem } from "./item"; import { modals } from "@mantine/modals"; import { IconElement } from "../elements/icon"; @@ -10,10 +10,10 @@ import { mdiFileExport } from "@mdi/js"; export type PatcherDrawerProps = { open: boolean; onClose: () => any; - onLoadPatcher: (patcher: PatcherRecord) => any; - onDeletePatcher: (patcher: PatcherRecord) => any; - onRenamePatcher: (patcher: PatcherRecord, newName: string) => any; - patchers: Seq.Indexed; + onLoadPatcher: (patcher: PatcherExportRecord) => any; + onDeletePatcher: (patcher: PatcherExportRecord) => any; + onRenamePatcher: (patcher: PatcherExportRecord, newName: string) => any; + patchers: Seq.Indexed; }; const PatcherDrawer: FunctionComponent = memo(function WrappedPatcherDrawer({ @@ -25,7 +25,7 @@ const PatcherDrawer: FunctionComponent = memo(function Wrapp patchers }: PatcherDrawerProps) { - const onTriggerDeletePatcher = useCallback((p: PatcherRecord) => { + const onTriggerDeletePatcher = useCallback((p: PatcherExportRecord) => { modals.openConfirmModal({ title: "Delete Patcher", centered: true, diff --git a/src/components/patchers/item.tsx b/src/components/patchers/item.tsx index cae1dbe..5d2c753 100644 --- a/src/components/patchers/item.tsx +++ b/src/components/patchers/item.tsx @@ -1,16 +1,16 @@ import { ChangeEvent, FormEvent, FunctionComponent, KeyboardEvent, MouseEvent, memo, useCallback, useEffect, useRef, useState } from "react"; import { ActionIcon, Button, Group, Menu, TextInput, Tooltip } from "@mantine/core"; -import { PatcherRecord } from "../../models/patcher"; +import { PatcherExportRecord } from "../../models/patcher"; import { keyEventIsValidForName, replaceInvalidNameChars } from "../../lib/util"; import classes from "./patchers.module.css"; import { IconElement } from "../elements/icon"; import { mdiCheck, mdiClose, mdiDotsVertical, mdiPencil, mdiPlus, mdiTrashCan } from "@mdi/js"; export type PatcherItemProps = { - patcher: PatcherRecord; - onLoad: (p: PatcherRecord) => any; - onDelete: (p: PatcherRecord) => any; - onRename: (p: PatcherRecord, name: string) => any; + patcher: PatcherExportRecord; + onLoad: (p: PatcherExportRecord) => any; + onDelete: (p: PatcherExportRecord) => any; + onRename: (p: PatcherExportRecord, name: string) => any; }; export const PatcherItem: FunctionComponent = memo(function WrappedPatcherItem({ diff --git a/src/controller/oscqueryBridgeController.ts b/src/controller/oscqueryBridgeController.ts index d2a70ef..1a392d1 100644 --- a/src/controller/oscqueryBridgeController.ts +++ b/src/controller/oscqueryBridgeController.ts @@ -6,7 +6,7 @@ import { ReconnectingWebsocket } from "../lib/reconnectingWs"; import { AppStatus, RunnerCmdMethod } from "../lib/constants"; import { OSCQueryRNBOState, OSCQueryRNBOInstance, OSCQueryRNBOJackConnections, OSCQueryRNBOPatchersState, OSCValue, OSCQueryRNBOInstancesMetaState, OSCQueryListValue } from "../lib/types"; import { addPatcherNode, deletePortAliases, initConnections, initNodes, removePatcherNode, setPortAliases, updateSetMetaFromRemote, updateSourcePortConnections, updateSystemOrControlPortInfo } from "../actions/graph"; -import { initPatchers } from "../actions/instances"; +import { initPatchers } from "../actions/patchers"; import { initRunnerConfig, updateRunnerConfig } from "../actions/settings"; import { initSets, setGraphSetLatest, initSetPresets, setGraphSetPresetLatest } from "../actions/sets"; import { initDataFiles } from "../actions/datafiles"; @@ -21,7 +21,7 @@ import { removeInstanceParameterByPath, removeInstanceMessageInportByPath, removeInstanceMessageOutportByPath -} from "../actions/instances"; +} from "../actions/patchers"; import { ConnectionType, PortDirection } from "../models/graph"; import { showNotification } from "../actions/notifications"; import { NotificationLevel } from "../models/notification"; diff --git a/src/models/patcher.ts b/src/models/patcher.ts index 401487a..85a954e 100644 --- a/src/models/patcher.ts +++ b/src/models/patcher.ts @@ -3,20 +3,20 @@ import { OSCQueryRNBOPatcher } from "../lib/types"; export const UNLOAD_PATCHER_NAME = ""; -export type PatcherRecordProps = { +export type PatcherExportRecordProps = { name: string; io: [number, number, number, number]; } -export class PatcherRecord extends ImmuRecord({ +export class PatcherExportRecord extends ImmuRecord({ name: "", io: [0, 0, 0, 0] }) { - static fromDescription(name: string, desc: OSCQueryRNBOPatcher): PatcherRecord { - return new PatcherRecord({ + static fromDescription(name: string, desc: OSCQueryRNBOPatcher): PatcherExportRecord { + return new PatcherExportRecord({ name, io: desc.CONTENTS.io.VALUE }); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 037d215..5f3664e 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,7 +2,7 @@ import { Button, Group, Stack, Text, Tooltip } from "@mantine/core"; import { FunctionComponent, useCallback, useEffect } from "react"; import { useAppDispatch, useAppSelector } from "../hooks/useAppDispatch"; import { RootStateType } from "../lib/store"; -import { getPatchersSortedByName } from "../selectors/instances"; +import { getPatchersSortedByName } from "../selectors/patchers"; import { getConnections, getNodes } from "../selectors/graph"; import GraphEditor from "../components/editor"; import PresetDrawer from "../components/presets"; @@ -19,12 +19,12 @@ import { } from "../actions/editor"; import SetsDrawer from "../components/sets"; import { destroySetPresetOnRemote, loadSetPresetOnRemote, saveSetPresetToRemote, renameSetPresetOnRemote, clearGraphSetOnRemote, destroyGraphSetOnRemote, loadGraphSetOnRemote, renameGraphSetOnRemote, saveGraphSetOnRemote } from "../actions/sets"; -import { destroyPatcherOnRemote, renamePatcherOnRemote } from "../actions/instances"; +import { destroyPatcherOnRemote, renamePatcherOnRemote } from "../actions/patchers"; import { PresetRecord } from "../models/preset"; import { getGraphSetPresetsSortedByName, getGraphSetsSortedByName } from "../selectors/sets"; import { useDisclosure } from "@mantine/hooks"; import PatcherDrawer from "../components/patchers"; -import { PatcherRecord } from "../models/patcher"; +import { PatcherExportRecord } from "../models/patcher"; import { SortOrder } from "../lib/constants"; import { GraphSetRecord } from "../models/set"; import { modals } from "@mantine/modals"; @@ -58,7 +58,7 @@ const Index: FunctionComponent> = () => { const [presetDrawerIsOpen, { close: closePresetDrawer, toggle: togglePresetDrawer }] = useDisclosure(); // Instances - const onAddInstance = useCallback((patcher: PatcherRecord) => { + const onAddInstance = useCallback((patcher: PatcherExportRecord) => { dispatch(loadPatcherNodeOnRemote(patcher)); closePatcherDrawer(); }, [dispatch, closePatcherDrawer]); @@ -181,11 +181,11 @@ const Index: FunctionComponent> = () => { dispatch(renameSetPresetOnRemote(preset, name)); }, [dispatch]); - const onDeletePatcher = useCallback((p: PatcherRecord) => { + const onDeletePatcher = useCallback((p: PatcherExportRecord) => { dispatch(destroyPatcherOnRemote(p)); }, [dispatch]); - const onRenamePatcher = useCallback((p: PatcherRecord, name: string) => { + const onRenamePatcher = useCallback((p: PatcherExportRecord, name: string) => { dispatch(renamePatcherOnRemote(p, name)); }, [dispatch]); diff --git a/src/pages/instances/[index].tsx b/src/pages/instances/[index].tsx index 622831a..c409605 100644 --- a/src/pages/instances/[index].tsx +++ b/src/pages/instances/[index].tsx @@ -8,13 +8,13 @@ import classes from "../../components/instance/instance.module.css"; import { getAppStatus } from "../../selectors/appStatus"; import { AppStatus, SortOrder } from "../../lib/constants"; import Link from "next/link"; -import { getInstanceByIndex, getInstanceMessageInports, getInstanceMessageOutports, getInstanceParameters, getInstances } from "../../selectors/instances"; +import { getPatcherInstanceByIndex, getPatcherInstanceParametersByInstanceIndex, getPatcherInstances, getPatcherInstanceMessageInportsByInstanceIndex, getPatcherInstanceMesssageOutportsByInstanceIndex } from "../../selectors/patchers"; import { unloadPatcherNodeByIndexOnRemote } from "../../actions/graph"; import { getAppSetting } from "../../selectors/settings"; import { AppSetting } from "../../models/settings"; import PresetDrawer from "../../components/presets"; import { PresetRecord } from "../../models/preset"; -import { destroyPresetOnRemoteInstance, renamePresetOnRemoteInstance, setInitialPresetOnRemoteInstance, loadPresetOnRemoteInstance, savePresetToRemoteInstance } from "../../actions/instances"; +import { destroyPresetOnRemoteInstance, renamePresetOnRemoteInstance, setInitialPresetOnRemoteInstance, loadPresetOnRemoteInstance, savePresetToRemoteInstance } from "../../actions/patchers"; import { useDisclosure } from "@mantine/hooks"; import { getDataFilesSortedByName } from "../../selectors/datafiles"; import InstanceKeyboardModal from "../../components/keyroll/modal"; @@ -47,15 +47,15 @@ export default function Instance() { sortAttr, sortOrder ] = useAppSelector((state: RootStateType) => { - const currentInstance = getInstanceByIndex(state, instanceIndex); + const currentInstance = getPatcherInstanceByIndex(state, instanceIndex); return [ currentInstance, - currentInstance ? getInstanceParameters(state, currentInstance.index) : undefined, - currentInstance ? getInstanceMessageInports(state, currentInstance.index) : undefined, - currentInstance ? getInstanceMessageOutports(state, currentInstance.index) : undefined, + currentInstance ? getPatcherInstanceParametersByInstanceIndex(state, currentInstance.index) : undefined, + currentInstance ? getPatcherInstanceMessageInportsByInstanceIndex(state, currentInstance.index) : undefined, + currentInstance ? getPatcherInstanceMesssageOutportsByInstanceIndex(state, currentInstance.index) : undefined, getAppStatus(state), - getInstances(state), + getPatcherInstances(state), getDataFilesSortedByName(state, SortOrder.Asc), getAppSetting(state, AppSetting.debugMessageOutput), getAppSetting(state, AppSetting.keyboardMIDIInput), diff --git a/src/reducers/index.ts b/src/reducers/index.ts index 5281ed1..c9d76a9 100644 --- a/src/reducers/index.ts +++ b/src/reducers/index.ts @@ -3,7 +3,7 @@ import { combineReducers } from "redux"; import { appStatus } from "./appStatus"; import { datafiles } from "./datafiles"; import { editor } from "./editor"; -import { instances } from "./instances"; +import { patchers } from "./patchers"; import { graph } from "./graph"; import { nofitications } from "./notifications"; import { settings } from "./settings"; @@ -14,9 +14,9 @@ export const rootReducer = combineReducers({ appStatus, datafiles, editor, - instances, graph, nofitications, + patchers, settings, sets, transport diff --git a/src/reducers/instances.ts b/src/reducers/instances.ts deleted file mode 100644 index 77a1fe5..0000000 --- a/src/reducers/instances.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { Map as ImmuMap } from "immutable"; -import { PatcherInstanceRecord } from "../models/instance"; -import { InstanceAction, InstanceActionType } from "../actions/instances"; -import { ParameterRecord } from "../models/parameter"; -import { MessagePortRecord } from "../models/messageport"; -import { PatcherRecord } from "../models/patcher"; - -export interface InstanceInstancesState { - instances: ImmuMap; - messageInports: ImmuMap; - messageOutports: ImmuMap; - parameters: ImmuMap; - patchers: ImmuMap; -} - -export const instances = (state: InstanceInstancesState = { - - instances: ImmuMap(), - messageInports: ImmuMap(), - messageOutports: ImmuMap(), - parameters: ImmuMap(), - patchers: ImmuMap() - -}, action: InstanceAction): InstanceInstancesState => { - - switch(action.type) { - - case InstanceActionType.INIT_PATCHERS: { - const { patchers } = action.payload; - - return { - ...state, - patchers: ImmuMap(patchers.map(p => [p.id, p])) - }; - } - - case InstanceActionType.SET_INSTANCE: { - const { instance } = action.payload; - - return { - ...state, - instances: state.instances.set(instance.id, instance) - }; - } - - case InstanceActionType.SET_INSTANCES: { - const { instances } = action.payload; - - return { - ...state, - instances: state.instances.withMutations(map => { - for (const instance of instances) { - map.set(instance.id, instance); - } - }) - }; - } - - case InstanceActionType.DELETE_INSTANCE: { - const { instance } = action.payload; - - return { - ...state, - instances: state.instances.delete(instance.id), - parameters: state.parameters.filter(param => param.instanceIndex !== instance.index), - messageInports: state.messageInports.filter(port => port.instanceIndex !== instance.index), - messageOutports: state.messageOutports.filter(port => port.instanceIndex !== instance.index) - }; - } - - case InstanceActionType.DELETE_INSTANCES: { - const { instances } = action.payload; - const indexSet = new Set(instances.map(i => i.index)); - - return { - ...state, - instances: state.instances.deleteAll(instances.map(d => d.id)), - parameters: state.parameters.filter(param => !indexSet.has(param.instanceIndex)), - messageInports: state.messageInports.filter(port => !indexSet.has(port.instanceIndex)), - messageOutports: state.messageOutports.filter(port => !indexSet.has(port.instanceIndex)) - }; - } - - case InstanceActionType.SET_PARAMETER: { - const { parameter } = action.payload; - - return { - ...state, - parameters: state.parameters.set(parameter.id, parameter) - }; - } - - case InstanceActionType.SET_PARAMETERS: { - const { parameters } = action.payload; - - return { - ...state, - parameters: state.parameters.withMutations(map => { - for (const param of parameters) { - map.set(param.id, param); - } - }) - }; - } - - case InstanceActionType.DELETE_PARAMETER: { - const { parameter } = action.payload; - - return { - ...state, - parameters: state.parameters.delete(parameter.id) - }; - } - - case InstanceActionType.DELETE_PARAMETERS: { - const { parameters } = action.payload; - - return { - ...state, - parameters: state.parameters.deleteAll(parameters.map(d => d.id)) - }; - } - - case InstanceActionType.SET_MESSAGE_INPORT: { - const { port } = action.payload; - - return { - ...state, - messageInports: state.messageInports.set(port.id, port) - }; - } - - case InstanceActionType.SET_MESSAGE_INPORTS: { - const { ports } = action.payload; - - return { - ...state, - messageInports: state.messageInports.withMutations(map => { - for (const port of ports) { - map.set(port.id, port); - } - }) - }; - } - - case InstanceActionType.DELETE_MESSAGE_INPORT: { - const { port } = action.payload; - - return { - ...state, - messageInports: state.messageInports.delete(port.id) - }; - } - - case InstanceActionType.DELETE_MESSAGE_INPORTS: { - const { ports } = action.payload; - - return { - ...state, - messageInports: state.messageInports.deleteAll(ports.map(d => d.id)) - }; - } - - case InstanceActionType.SET_MESSAGE_OUTPORT: { - const { port } = action.payload; - - return { - ...state, - messageOutports: state.messageOutports.set(port.id, port) - }; - } - - case InstanceActionType.SET_MESSAGE_OUTPORTS: { - const { ports } = action.payload; - - return { - ...state, - messageOutports: state.messageOutports.withMutations(map => { - for (const port of ports) { - map.set(port.id, port); - } - }) - }; - } - - case InstanceActionType.DELETE_MESSAGE_OUTPORT: { - const { port } = action.payload; - - return { - ...state, - messageOutports: state.messageOutports.delete(port.id) - }; - } - - case InstanceActionType.DELETE_MESSAGE_OUTPORTS: { - const { ports } = action.payload; - - return { - ...state, - messageOutports: state.messageOutports.deleteAll(ports.map(d => d.id)) - }; - } - - default: - return state; - } -}; diff --git a/src/selectors/instances.ts b/src/selectors/instances.ts deleted file mode 100644 index aa18279..0000000 --- a/src/selectors/instances.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { Map as ImmuMap, Seq } from "immutable"; -import { RootStateType } from "../lib/store"; -import { PatcherInstanceRecord } from "../models/instance"; -import { createSelector } from "reselect"; -import { getPatcherIdsByIndex } from "./graph"; -import { ParameterRecord } from "../models/parameter"; -import { MessagePortRecord } from "../models/messageport"; -import { PatcherRecord } from "../models/patcher"; -import { SortOrder } from "../lib/constants"; - -export const getPatchers = (state: RootStateType): ImmuMap => { - return state.instances.patchers; -}; - -export const getPatcher = createSelector( - [ - getPatchers, - (state: RootStateType, name: string): string => name - ], - (patchers, name): PatcherRecord | undefined => { - return patchers.get(name); - } -); - -const collator = new Intl.Collator("en-US"); -export const getPatchersSortedByName = createSelector( - [ - getPatchers, - (state: RootStateType, order: SortOrder): SortOrder => order - ], - (patchers, order): Seq.Indexed => { - return patchers.valueSeq().sort((pA, pB) => { - return collator.compare(pA.name.toLowerCase(), pB.name.toLowerCase()) * (order === SortOrder.Asc ? 1 : -1); - }); - } -); - - -export const getInstances = (state: RootStateType): ImmuMap => state.instances.instances; - -export const getInstance = createSelector( - [ - getInstances, - (state: RootStateType, id: PatcherInstanceRecord["id"]): PatcherInstanceRecord["id"] => id - ], - (instances, id): PatcherInstanceRecord | undefined => instances.get(id) -); - -export const getInstanceByIndex = createSelector( - [ - getInstances, - (state: RootStateType, index: PatcherInstanceRecord["index"]): PatcherInstanceRecord["id"] | undefined => state.graph.patcherNodeIdByIndex.get(index) - ], - (instances, id): PatcherInstanceRecord | undefined => id ? instances.get(id) : undefined -); - -export const getInstancesByIndex = createSelector( - [ - getInstances, - getPatcherIdsByIndex - ], - (instances, idsByIndex): ImmuMap => { - return ImmuMap().withMutations(map => { - idsByIndex.forEach((id, index) => { - const node = instances.get(id); - if (node) map.set(index, node); - }); - }); - } -); - -export const getParameters = (state: RootStateType): ImmuMap => state.instances.parameters; - -export const getParameter = createSelector( - [ - getParameters, - (state: RootStateType, id: ParameterRecord["id"]): ParameterRecord["id"] => id - ], - (parameters, id): ParameterRecord | undefined => { - return parameters.get(id); - } -); - -export const getParameterByPath = createSelector( - [ - getParameters, - (state: RootStateType, path: ParameterRecord["path"]): ParameterRecord["path"] => path - ], - (parameters, path): ParameterRecord | undefined => { - return parameters.find(p => p.path === path); - } -); - -export const getInstanceParameters = createSelector( - [ - getParameters, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex - ], - (parameters, instanceIndex): ImmuMap => { - return parameters.filter(p => { - return p.instanceIndex === instanceIndex; - }); - } -); - - -export const getInstanceParameterByName = createSelector( - [ - getParameters, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"], name: ParameterRecord["name"]): ParameterRecord["name"] => name - ], - (parameters, instanceIndex, name): ParameterRecord | undefined => { - return parameters.find(p => p.instanceIndex === instanceIndex && p.name === name); - } -); - -export const getMessageInports = (state: RootStateType): ImmuMap => state.instances.messageInports; - -export const getMessageInport = createSelector( - [ - getMessageInports, - (state: RootStateType, id: MessagePortRecord["id"]): MessagePortRecord["id"] => id - ], - (ports, id): MessagePortRecord | undefined => { - return ports.get(id); - } -); - -export const getMessageInportByPath = createSelector( - [ - getMessageInports, - (state: RootStateType, path: MessagePortRecord["path"]): MessagePortRecord["path"] => path - ], - (ports, path): MessagePortRecord | undefined => { - return ports.find(p => p.path === path); - } -); - -export const getInstanceMessageInports = createSelector( - [ - getMessageInports, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex - ], - (ports, instanceIndex): ImmuMap => { - return ports.filter(p => { - return p.instanceIndex === instanceIndex; - }); - } -); - -export const getInstanceMessageInportByTag = createSelector( - [ - getMessageInports, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"], tag: MessagePortRecord["tag"]): MessagePortRecord["tag"] => tag - ], - (ports, instanceIndex, tag): MessagePortRecord | undefined => { - return ports.find(p => p.instanceIndex === instanceIndex && p.tag === tag); - } -); - -export const getMessageOutports = (state: RootStateType): ImmuMap => state.instances.messageOutports; - -export const getMessageOutport = createSelector( - [ - getMessageOutports, - (state: RootStateType, id: MessagePortRecord["id"]): MessagePortRecord["id"] => id - ], - (ports, id): MessagePortRecord | undefined => { - return ports.get(id); - } -); - -export const getMessageOutportByPath = createSelector( - [ - getMessageOutports, - (state: RootStateType, path: MessagePortRecord["path"]): MessagePortRecord["path"] => path - ], - (ports, path): MessagePortRecord | undefined => { - return ports.find(p => p.path === path); - } -); - -export const getInstanceMessageOutports = createSelector( - [ - getMessageOutports, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex - ], - (ports, instanceIndex): ImmuMap => { - return ports.filter(p => { - return p.instanceIndex === instanceIndex; - }); - } -); - -export const getInstanceMessageOutportByTag = createSelector( - [ - getMessageOutports, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex, - (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"], tag: MessagePortRecord["tag"]): MessagePortRecord["tag"] => tag - ], - (ports, instanceIndex, tag): MessagePortRecord | undefined => { - return ports.find(p => p.instanceIndex === instanceIndex && p.tag === tag); - } -); diff --git a/src/selectors/patchers.ts b/src/selectors/patchers.ts index 9bd3d73..a0b4577 100644 --- a/src/selectors/patchers.ts +++ b/src/selectors/patchers.ts @@ -1,19 +1,23 @@ import { Map as ImmuMap, Seq } from "immutable"; import { RootStateType } from "../lib/store"; -import { PatcherRecord } from "../models/patcher"; +import { PatcherInstanceRecord } from "../models/instance"; import { createSelector } from "reselect"; +import { getPatcherIdsByIndex } from "./graph"; +import { ParameterRecord } from "../models/parameter"; +import { MessagePortRecord } from "../models/messageport"; +import { PatcherExportRecord } from "../models/patcher"; import { SortOrder } from "../lib/constants"; -export const getPatchers = (state: RootStateType): ImmuMap => { - return state.patchers.patchers; +export const getPatcherExports = (state: RootStateType): ImmuMap => { + return state.patchers.exports; }; -export const getPatcher = createSelector( +export const getPatcherExport = createSelector( [ - getPatchers, + getPatcherExports, (state: RootStateType, name: string): string => name ], - (patchers, name): PatcherRecord | undefined => { + (patchers, name): PatcherExportRecord | undefined => { return patchers.get(name); } ); @@ -21,12 +25,183 @@ export const getPatcher = createSelector( const collator = new Intl.Collator("en-US"); export const getPatchersSortedByName = createSelector( [ - getPatchers, + getPatcherExports, (state: RootStateType, order: SortOrder): SortOrder => order ], - (patchers, order): Seq.Indexed => { + (patchers, order): Seq.Indexed => { return patchers.valueSeq().sort((pA, pB) => { return collator.compare(pA.name.toLowerCase(), pB.name.toLowerCase()) * (order === SortOrder.Asc ? 1 : -1); }); } ); + + +export const getPatcherInstances = (state: RootStateType): ImmuMap => state.patchers.instances; + +export const getPatcherInstance = createSelector( + [ + getPatcherInstances, + (state: RootStateType, id: PatcherInstanceRecord["id"]): PatcherInstanceRecord["id"] => id + ], + (instances, id): PatcherInstanceRecord | undefined => instances.get(id) +); + +export const getPatcherInstanceByIndex = createSelector( + [ + getPatcherInstances, + (state: RootStateType, index: PatcherInstanceRecord["index"]): PatcherInstanceRecord["id"] | undefined => state.graph.patcherNodeIdByIndex.get(index) + ], + (instances, id): PatcherInstanceRecord | undefined => id ? instances.get(id) : undefined +); + +export const getPatcherInstancesByIndex = createSelector( + [ + getPatcherInstances, + getPatcherIdsByIndex + ], + (instances, idsByIndex): ImmuMap => { + return ImmuMap().withMutations(map => { + idsByIndex.forEach((id, index) => { + const node = instances.get(id); + if (node) map.set(index, node); + }); + }); + } +); + +export const getPatcherInstanceParameters = (state: RootStateType): ImmuMap => state.patchers.instanceParameters; + +export const getPatcherInstanceParameter = createSelector( + [ + getPatcherInstanceParameters, + (state: RootStateType, id: ParameterRecord["id"]): ParameterRecord["id"] => id + ], + (parameters, id): ParameterRecord | undefined => { + return parameters.get(id); + } +); + +export const getPatcherInstanceParameterByPath = createSelector( + [ + getPatcherInstanceParameters, + (state: RootStateType, path: ParameterRecord["path"]): ParameterRecord["path"] => path + ], + (parameters, path): ParameterRecord | undefined => { + return parameters.find(p => p.path === path); + } +); + +export const getPatcherInstanceParametersByInstanceIndex = createSelector( + [ + getPatcherInstanceParameters, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex + ], + (parameters, instanceIndex): ImmuMap => { + return parameters.filter(p => { + return p.instanceIndex === instanceIndex; + }); + } +); + + +export const getPatcherInstanceParametersByInstanceIndexAndName = createSelector( + [ + getPatcherInstanceParameters, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"], name: ParameterRecord["name"]): ParameterRecord["name"] => name + ], + (parameters, instanceIndex, name): ParameterRecord | undefined => { + return parameters.find(p => p.instanceIndex === instanceIndex && p.name === name); + } +); + +export const getPatcherInstanceMessageInports = (state: RootStateType): ImmuMap => state.patchers.instanceMessageInports; + +export const getPatcherInstanceMessageInport = createSelector( + [ + getPatcherInstanceMessageInports, + (state: RootStateType, id: MessagePortRecord["id"]): MessagePortRecord["id"] => id + ], + (ports, id): MessagePortRecord | undefined => { + return ports.get(id); + } +); + +export const getPatcherInstanceMessageInportByPath = createSelector( + [ + getPatcherInstanceMessageInports, + (state: RootStateType, path: MessagePortRecord["path"]): MessagePortRecord["path"] => path + ], + (ports, path): MessagePortRecord | undefined => { + return ports.find(p => p.path === path); + } +); + +export const getPatcherInstanceMessageInportsByInstanceIndex = createSelector( + [ + getPatcherInstanceMessageInports, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex + ], + (ports, instanceIndex): ImmuMap => { + console.log(ports.valueSeq().toArray().map(p => p.toJSON())); + return ports.filter(p => { + return p.instanceIndex === instanceIndex; + }); + } +); + +export const getPatcherInstanceMessageInportsByInstanceIndexAndTag = createSelector( + [ + getPatcherInstanceMessageInports, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"], tag: MessagePortRecord["tag"]): MessagePortRecord["tag"] => tag + ], + (ports, instanceIndex, tag): MessagePortRecord | undefined => { + return ports.find(p => p.instanceIndex === instanceIndex && p.tag === tag); + } +); + +export const getPatcherInstanceMessageOutports = (state: RootStateType): ImmuMap => state.patchers.instanceMessageOutports; + +export const getPatcherInstanceMessageOutport = createSelector( + [ + getPatcherInstanceMessageOutports, + (state: RootStateType, id: MessagePortRecord["id"]): MessagePortRecord["id"] => id + ], + (ports, id): MessagePortRecord | undefined => { + return ports.get(id); + } +); + +export const getPatcherInstanceMessageOutportByPath = createSelector( + [ + getPatcherInstanceMessageOutports, + (state: RootStateType, path: MessagePortRecord["path"]): MessagePortRecord["path"] => path + ], + (ports, path): MessagePortRecord | undefined => { + return ports.find(p => p.path === path); + } +); + +export const getPatcherInstanceMesssageOutportsByInstanceIndex = createSelector( + [ + getPatcherInstanceMessageOutports, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex + ], + (ports, instanceIndex): ImmuMap => { + return ports.filter(p => { + return p.instanceIndex === instanceIndex; + }); + } +); + +export const getPatcherInstanceMesssageOutportsByInstanceIndexAndTag = createSelector( + [ + getPatcherInstanceMessageOutports, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"]): PatcherInstanceRecord["index"] => instanceIndex, + (state: RootStateType, instanceIndex: PatcherInstanceRecord["index"], tag: MessagePortRecord["tag"]): MessagePortRecord["tag"] => tag + ], + (ports, instanceIndex, tag): MessagePortRecord | undefined => { + return ports.find(p => p.instanceIndex === instanceIndex && p.tag === tag); + } +);