Skip to content

Commit

Permalink
project upgrade edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
aolsenjazz committed Oct 27, 2024
1 parent b9b3c85 commit ff84aac
Show file tree
Hide file tree
Showing 20 changed files with 195 additions and 63 deletions.
22 changes: 9 additions & 13 deletions src/helper/v5-to-v6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ function upgradeInput(
function upgradeSupportedDevice(
d: V5SupportedDeviceConfig,
plugins: BasePlugin[],
inputs: BaseInputConfig[]
inputs: BaseInputConfig[],
configId?: string
): SupportedDeviceConfig {
const config = new SupportedDeviceConfig(
d.portName,
Expand All @@ -316,7 +317,12 @@ function upgradeSupportedDevice(
}

d.inputs.forEach((i) => {
const newInputs = upgradeInput(config.id, config.portName, i, plugins);
const newInputs = upgradeInput(
configId || config.id,
config.portName,
i,
plugins
);

if (newInputs && newInputs.length > 0) inputs.push(...newInputs);
});
Expand Down Expand Up @@ -368,7 +374,7 @@ function upgradeAdapterDevice(
inputs: BaseInputConfig[]
): AdapterDeviceConfig {
const oldChild = d.child!;
const newChild = upgradeSupportedDevice(oldChild, plugins, inputs);
const newChild = upgradeSupportedDevice(oldChild, plugins, inputs, d.id);

const config = new AdapterDeviceConfig(
d.portName,
Expand All @@ -377,16 +383,6 @@ function upgradeAdapterDevice(
newChild
);

if (d.shareSustain.length > 0) {
const shareSustain = new ShareSustainPlugin(
config.id,
undefined,
d.shareSustain
);
plugins.push(shareSustain);
config.plugins.push(shareSustain.id);
}

return config;
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/config-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { BasePluginManifest } from '@plugins/core/base-plugin-manifest';
import { InputPluginManifest } from '@plugins/core/input-plugin-manifest';
import { getQualifiedInputId } from '@shared/util';

import { DeviceRegistry } from './device-registry';
import { InputRegistry } from './input-registry';
import { PluginRegistry } from './plugin-registry';
import { DeviceRegistry } from './registry/device-registry';
import { InputRegistry } from './registry/input-registry';
import { PluginRegistry } from './registry/plugin-registry';
import { HardwarePortService } from './port-service';
import { VirtualPortService } from './port-service/virtual/virtual-port-service';
import { WindowProvider } from './window-provider';
Expand Down
11 changes: 0 additions & 11 deletions src/main/input-registry.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/ipc/initialize-device-config-ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ConfigManager } from '@main/config-manager';

import { DEVICE_CONFIG } from './ipc-channels';
import { WindowProvider } from '../window-provider';
import { DeviceRegistry } from '../device-registry';
import { DeviceRegistry } from '../registry/device-registry';
import { createDevicePluginMenu } from '../menu/device-plugin-menu';

const { MainWindow } = WindowProvider;
Expand Down
2 changes: 1 addition & 1 deletion src/main/ipc/initialize-input-config-ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ConfigManager } from '@main/config-manager';

import { INPUT_CONFIG } from './ipc-channels';
import { WindowProvider } from '../window-provider';
import { InputRegistry } from '../input-registry';
import { InputRegistry } from '../registry/input-registry';
import { createInputPluginMenu } from '../menu/input-plugin-menu';

const { MainWindow } = WindowProvider;
Expand Down
2 changes: 1 addition & 1 deletion src/main/ipc/initialize-plugin-ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { PluginDTO } from '@plugins/core/base-plugin';
import { HardwarePortService } from '@main/port-service';

import { WindowProvider } from '../window-provider';
import { PluginRegistry } from '../plugin-registry';
import { PluginRegistry } from '../registry/plugin-registry';
import { PLUGIN } from './ipc-channels';

const { MainWindow } = WindowProvider;
Expand Down
6 changes: 3 additions & 3 deletions src/main/port-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import { ipcMain, IpcMainEvent } from 'electron';
import type { DeviceConfig } from '@shared/hardware-config/device-config';
import { idForMsg } from '@shared/midi-util';

import { DeviceRegistry } from '@main/device-registry';
import { PluginRegistry } from '@main/plugin-registry';
import { InputRegistry } from '@main/input-registry';
import { DeviceRegistry } from '@main/registry/device-registry';
import { PluginRegistry } from '@main/registry/plugin-registry';
import { InputRegistry } from '@main/registry/input-registry';
import { MessageTransport } from '@shared/message-transport';
import { getQualifiedInputId } from '@shared/util';
import { SupportedDeviceConfig } from '@shared/hardware-config/supported-device-config';
Expand Down
2 changes: 1 addition & 1 deletion src/main/port-service/virtual/virtual-port-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DeviceRegistry } from '@main/device-registry';
import { DeviceRegistry } from '@main/registry/device-registry';
import { DeviceConfig } from '@shared/hardware-config/device-config';

import { PortScanResult } from '../port-manager';
Expand Down
56 changes: 40 additions & 16 deletions src/main/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ import { deviceConfigFromDTO } from '@shared/hardware-config';
import { inputConfigsFromDTO } from '@shared/hardware-config/input-config';
import { BaseInputConfig } from '@plugins/types';
import { DeviceConfig } from '@shared/hardware-config/device-config';
import { DRIVERS } from '@shared/drivers';
import { DeviceDriver } from '@shared/driver-types/device-driver';

import { upgradeProject } from 'helper/project-upgrader';

import { HardwarePortService } from './port-service';
import { VirtualPortService } from './port-service/virtual/virtual-port-service';
import { WindowProvider } from './window-provider';
import { dialogs } from './dialogs';
import { InputRegistry } from './input-registry';
import { PluginRegistry } from './plugin-registry';
import { DeviceRegistry } from './device-registry';
import { InputRegistry } from './registry/input-registry';
import { PluginRegistry } from './registry/plugin-registry';
import { DeviceRegistry } from './registry/device-registry';

import {
createDevicePluginFromDTO,
Expand All @@ -44,23 +46,28 @@ function getRecommendedDir(): string {
}

async function loadInputPlugins(config: BaseInputConfig, proj: ProjectPOJO) {
// TODO: if inputs and devices are responsible for initializing their
// own plugins, we don't need a getPlugins() function
await Promise.all(
config.getPlugins().map(async (id) => {
const dto = proj.plugins[id];
const plugin = await createInputPluginFromDTO(dto, config.driver);
PluginRegistry.register(plugin.id, plugin);

const plugins = await config.initPluginsFromDTO(
createInputPluginFromDTO.bind(null, dto)
);

plugins.forEach((p) => PluginRegistry.register(p.id, p));
})
);
}

async function loadDevicePlugins(config: DeviceConfig, proj: ProjectPOJO) {
await Promise.all(
config.plugins.map(async (id) => {
const dto = proj.plugins[id];
const plugin = await createDevicePluginFromDTO(dto);
PluginRegistry.register(plugin.id, plugin);
})
);
const initDevicePlugin = async (id: string) => {
return createDevicePluginFromDTO(proj.plugins[id]);
};

const plugins = await config.initPluginsFromDTO(initDevicePlugin);
plugins.forEach((p) => PluginRegistry.register(p.id, p));
}

/**
Expand All @@ -70,7 +77,24 @@ async function loadDevicePlugins(config: DeviceConfig, proj: ProjectPOJO) {
async function loadInputs(proj: ProjectPOJO) {
await Promise.all(
Object.values(proj.inputs).map(async (inputDTO) => {
const config = inputConfigsFromDTO(inputDTO);
const parentConfigDTO = proj.devices[inputDTO.deviceId];
let parentDriver: DeviceDriver | undefined;

if (parentConfigDTO.type === 'adapter') {
if (parentConfigDTO.child === undefined) {
throw new Error('cannot look up inputs for unset adapter child');
}

parentDriver = DRIVERS.get(parentConfigDTO.child.driverName);
} else {
parentDriver = DRIVERS.get(parentConfigDTO.driverName);
}

if (parentDriver === undefined) {
throw new Error('unable to load device driver');
}

const config = inputConfigsFromDTO(parentDriver, inputDTO);
const qualifiedInputId = getQualifiedInputId(
inputDTO.deviceId,
inputDTO.id
Expand Down Expand Up @@ -124,8 +148,6 @@ export async function initDefault(): Promise<void> {
* @param filePath - The path to the project file.
*/
export async function loadProject(filePath: string): Promise<void> {
app.addRecentDocument(filePath);

const jsonString = fs.readFileSync(filePath, 'utf8');
const proj = upgradeProject(jsonString) as ProjectPOJO;

Expand All @@ -146,7 +168,9 @@ export async function loadProject(filePath: string): Promise<void> {

MainWindow.setPlugins(PluginRegistry.getAll().map((p) => p.toDTO()));
MainWindow.setInputConfigs(InputRegistry.getAll().map((p) => p.toDTO()));
MainWindow.setConfiguredDevices(Object.values(proj.devices));
MainWindow.setConfiguredDevices(
DeviceRegistry.getAll().map((d) => d.toDTO())
);
}

/**
Expand Down
File renamed without changes.
59 changes: 59 additions & 0 deletions src/main/registry/input-registry-with-subregistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { BaseInteractiveInputDriver } from '@plugins/types';
import {
BaseInputConfig,
InputDTO,
} from '@shared/hardware-config/input-config/base-input-config';
import { SwitchConfig } from '@shared/hardware-config/input-config/switch-config';
import { XYConfig } from '@shared/hardware-config/input-config/xy-config';

import { Registry } from './registry';

/**
* Similar to a simple input registry, but includes an additional registry
* to store temporary references to configs. This is useful when a device
* receives a message from a Switch or XY input, because those child configs
* (switch steps or x-axis/y-axis configs) are stored here.
*
* Also guarantees that child configs won't be serialized with the rest of
* the project.
*/
export class InputRegistryWithSubregistry extends Registry<
InputDTO,
BaseInputConfig
> {
/**
* Stores the child configs of XY and Switch configs.
*/
InputSubregistry = new Registry<InputDTO, BaseInputConfig>();

/**
* Tries to return the requested item from its class' own store. If undefined,
* tries to return the requested item from the subregistry.
*/
public get<
U extends BaseInputConfig<
InputDTO,
BaseInteractiveInputDriver
> = BaseInputConfig<InputDTO, BaseInteractiveInputDriver>
>(id: string): U | undefined {
return super.get(id) || this.InputSubregistry.get(id);
}

public register(
key: string,
item: BaseInputConfig<InputDTO, BaseInteractiveInputDriver>
): void {
super.register(key, item);

if (item instanceof SwitchConfig) {
item.steps.forEach((s) => {
this.InputSubregistry.register(s.qualifiedId, s);
});
}

if (item instanceof XYConfig) {
this.InputSubregistry.register(item.x.qualifiedId, item.x);
this.InputSubregistry.register(item.y.qualifiedId, item.y);
}
}
}
7 changes: 7 additions & 0 deletions src/main/registry/input-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { InputRegistryWithSubregistry } from './input-registry-with-subregistry';

/**
* Normalized store of `InputConfig`s. Objects must be stored and retrieved
* using the qualifiedId of inputConfigs.
*/
export const InputRegistry = new InputRegistryWithSubregistry();
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BasePlugin, PluginDTO } from '../plugins/core/base-plugin';
import type { BasePlugin, PluginDTO } from '../../plugins/core/base-plugin';
import { Registry } from './registry';

export const PluginRegistry = new Registry<PluginDTO, BasePlugin>();
2 changes: 1 addition & 1 deletion src/main/registry.ts → src/main/registry/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* in the backend.
*/
export class Registry<V, T extends { id: string; toDTO: () => V }> {
private items: Map<string, T>;
protected items: Map<string, T>;

public constructor() {
this.items = new Map<string, T>();
Expand Down
2 changes: 1 addition & 1 deletion src/main/renderer-inclusive-plugin-provider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PluginProvider } from '@shared/plugin-provider';

import { PluginRegistry } from './plugin-registry';
import { PluginRegistry } from './registry/plugin-registry';
import { WindowProvider } from './window-provider';

const { MainWindow } = WindowProvider;
Expand Down
14 changes: 14 additions & 0 deletions src/shared/hardware-config/adapter-device-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { SupportedDeviceConfig } from './supported-device-config';
import { DeviceConfig } from './device-config';
import { MessageProcessorMeta } from '../message-processor';
import { MessageTransport } from '../message-transport';
import { BaseDevicePlugin } from '../../plugins/core/base-device-plugin';
import { BasePlugin } from '../../plugins/core/base-plugin';

export class AdapterDeviceConfig extends DeviceConfig {
child?: SupportedDeviceConfig;
Expand All @@ -20,6 +22,18 @@ export class AdapterDeviceConfig extends DeviceConfig {
// no-op
}

public async initPluginsFromDTO(
initPlugin: (id: string) => Promise<BaseDevicePlugin>
) {
const plugins = await super.initPluginsFromDTO(initPlugin);
let childPlugins: BasePlugin[] = [];

if (this.child)
childPlugins = await this.child.initPluginsFromDTO(initPlugin);

return [...plugins, ...childPlugins];
}

public setChild(config: SupportedDeviceConfig) {
this.child = config;
}
Expand Down
23 changes: 21 additions & 2 deletions src/shared/hardware-config/device-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { PluginProvider } from '../plugin-provider';
import type { BaseIcicle } from '../freezable';
import { Anonymous, getDriver } from '../drivers';

import { MessageProcessor, MessageProcessorMeta } from '../message-processor';
import { MessageTransport } from '../message-transport';
import type {
MessageProcessor,
MessageProcessorMeta,
} from '../message-processor';
import type { MessageTransport } from '../message-transport';
import type { BaseDevicePlugin } from '../../plugins/core/base-device-plugin';
import type { BasePlugin } from '../../plugins/core/base-plugin';

export interface DeviceConfigDTO extends BaseIcicle {
id: string;
Expand Down Expand Up @@ -114,6 +119,20 @@ export abstract class DeviceConfig<T extends DeviceConfigDTO = DeviceConfigDTO>

public abstract toDTO(): T;

public async initPluginsFromDTO(
initPlugin: (id: string) => Promise<BaseDevicePlugin>
) {
const plugins: BasePlugin[] = [];

await Promise.all(
this.plugins.map(async (id) => {
plugins.push(await initPlugin(id));
})
);

return plugins;
}

/**
* Processes a MIDI message through a series of plugins, updating the message as it
* passes through each plugin in sequence. If any plugin returns `undefined`, processing
Expand Down
Loading

0 comments on commit ff84aac

Please sign in to comment.