Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Dec 19, 2024
1 parent c458adc commit 6008a30
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 32 deletions.
19 changes: 18 additions & 1 deletion companion/lib/Controls/ControlTypes/Button/Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type { DrawStyleButtonModel } from '@companion-app/shared/Model/StyleMode
import type { CompanionVariableValues } from '@companion-module/base'
import type { ControlDependencies } from '../../ControlDependencies.js'
import { ControlActionRunner } from '../../ActionRunner.js'
import type { FragmentActionInstance } from '../../Fragments/FragmentActionInstance.js'
import { FeedbackInstance } from '@companion-app/shared/Model/FeedbackModel.js'

/**
* Abstract class for a editable button control.
Expand Down Expand Up @@ -206,6 +208,20 @@ export abstract class ButtonControlBase<TJson, TOptions extends Record<string, a
return actions
}

/**
* Get all the feedbacks belonging to actions on this control
*/
getFlattenedActionFeedbackInstances(onlyConnectionId?: string): FeedbackInstance[] {
const actions: FeedbackInstance[] = []

for (const step of Object.values(this.steps)) {
if (!step) continue
actions.push(...step.getFlattenedFeedbackInstances(onlyConnectionId))
}

return actions
}

/**
* Get the size of the bitmap render of this control
*/
Expand Down Expand Up @@ -325,9 +341,10 @@ export abstract class ButtonControlBase<TJson, TOptions extends Record<string, a
*/
renameVariables(labelFrom: string, labelTo: string): void {
const allFeedbacks = this.feedbacks.getAllFeedbacks()
const allActions = []
const allActions: FragmentActionInstance[] = []
for (const step of Object.values(this.steps)) {
allActions.push(...step.getAllActions())
allFeedbacks.push(...step.getAllFeedbacks())
}

// Fix up references
Expand Down
4 changes: 3 additions & 1 deletion companion/lib/Controls/ControlTypes/Button/Normal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
} from '@companion-app/shared/Model/ActionModel.js'
import type { DrawStyleButtonModel } from '@companion-app/shared/Model/StyleModel.js'
import type { ControlDependencies } from '../../ControlDependencies.js'
import type { FragmentActionInstance } from '../../Fragments/FragmentActionInstance.js'

/**
* Class for the stepped button control.
Expand Down Expand Up @@ -479,10 +480,11 @@ export class ControlButtonNormal
*/
collectReferencedConnections(foundConnectionIds: Set<string>, foundConnectionLabels: Set<string>): void {
const allFeedbacks = this.feedbacks.getAllFeedbacks()
const allActions = []
const allActions: FragmentActionInstance[] = []

for (const step of Object.values(this.steps)) {
allActions.push(...step.getAllActions())
allFeedbacks.push(...step.getAllFeedbacks())
}

for (const feedback of allFeedbacks) {
Expand Down
12 changes: 10 additions & 2 deletions companion/lib/Controls/ControlTypes/Triggers/Trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { EventInstance } from '@companion-app/shared/Model/EventModel.js'
import type { ActionInstance, ActionOwner, ActionSetId } from '@companion-app/shared/Model/ActionModel.js'
import type { ControlDependencies } from '../../ControlDependencies.js'
import { ControlActionRunner } from '../../ActionRunner.js'
import type { FeedbackInstance } from '@companion-app/shared/Model/FeedbackModel.js'

/**
* Class for an interval trigger.
Expand Down Expand Up @@ -388,13 +389,20 @@ export class ControlTrigger
return this.actions.getFlattenedActionInstances()
}

/**
* Get all the feedbacks belonging to actions on this control
*/
getFlattenedActionFeedbackInstances(onlyConnectionId?: string): FeedbackInstance[] {
return this.actions.getFlattenedFeedbackInstances(onlyConnectionId)
}

/**
* Collect the instance ids and labels referenced by this control
* @param foundConnectionIds - instance ids being referenced
* @param foundConnectionLabels - instance labels being referenced
*/
collectReferencedConnections(foundConnectionIds: Set<string>, foundConnectionLabels: Set<string>) {
const allFeedbacks = this.feedbacks.getAllFeedbacks()
const allFeedbacks = this.feedbacks.getAllFeedbacks().concat(this.actions.getAllFeedbacks())
const allActions = this.actions.getAllActions()

for (const feedback of allFeedbacks) {
Expand Down Expand Up @@ -534,7 +542,7 @@ export class ControlTrigger
* @access public
*/
renameVariables(labelFrom: string, labelTo: string): void {
const allFeedbacks = this.feedbacks.getAllFeedbacks()
const allFeedbacks = this.feedbacks.getAllFeedbacks().concat(this.actions.getAllFeedbacks())
const allActions = this.actions.getAllActions()

// Fix up references
Expand Down
172 changes: 172 additions & 0 deletions companion/lib/Controls/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,178 @@ export class ControlsController extends CoreBase {
}
})

client.onPromise(
'controls:action:feedback:add',
(controlId, stepId, setId, actionId, ownerId, connectionId, feedbackId) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
const feedbackItem = this.instance.definitions.createFeedbackItem(connectionId, feedbackId, true)
if (feedbackItem) {
return control.actionFeedbackAdd(stepId, setId, actionId, feedbackItem, ownerId)
} else {
return false
}
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
}
)

client.onPromise('controls:action:feedback:learn', async (controlId, stepId, setId, actionId, id) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
if (this.#activeLearnRequests.has(id)) throw new Error('Learn is already running')
try {
this.#setIsLearning(id, true)

control.feedbacks
.feedbackLearn(id)
.catch((e) => {
this.logger.error(`Learn failed: ${e}`)
})
.then(() => {
this.#setIsLearning(id, false)
})

return true
} catch (e) {
this.#setIsLearning(id, false)
throw e
}
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise('controls:action:feedback:enabled', (controlId, stepId, setId, actionId, id, enabled) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackEnabled(id, enabled)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise('controls:action:feedback:set-headline', (controlId, stepId, setId, actionId, id, headline) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackHeadline(id, headline)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise('controls:action:feedback:remove', (controlId, stepId, setId, actionId, id) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackRemove(id)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise('controls:action:feedback:duplicate', (controlId, stepId, setId, actionId, id) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackDuplicate(id)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise('controls:action:feedback:set-option', (controlId, stepId, setId, actionId, id, key, value) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supporsupportsActionstsFeedbacks) {
return control.feedbacks.feedbackSetOptions(id, key, value)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise(
'controls:action:feedback:set-connection',
(controlId, stepId, setId, actionId, feedbackId, connectionId) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackSetConnection(feedbackId, connectionId)
} else {
throw new Error(
`Trying to set connection of feedback ${feedbackId} to ${connectionId} but control ${controlId} does not support feedbacks`
)
}
}
)

client.onPromise('controls:action:feedback:set-inverted', (controlId, stepId, setId, actionId, id, isInverted) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackSetInverted(id, isInverted)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
})

client.onPromise(
'controls:action:feedback:move',
(controlId, stepId, setId, actionId, moveFeedbackId, newOwnerId, newIndex) => {
const control = this.getControl(controlId)
if (!control) return false

if (newOwnerId && moveFeedbackId === newOwnerId.parentFeedbackOrActionId)
throw new Error('Cannot move feedback to itself')

if (control.supportsActions) {
return control.feedbacks.feedbackMoveTo(moveFeedbackId, newOwnerId, newIndex)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
}
)
client.onPromise(
'controls:action:feedback:set-style-selection',
(controlId, stepId, setId, actionId, id, selected) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackSetStyleSelection(id, selected)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
}
)
client.onPromise(
'controls:action:feedback:set-style-value',
(controlId, stepId, setId, actionId, id, key, value) => {
const control = this.getControl(controlId)
if (!control) return false

if (control.supportsActions) {
return control.feedbacks.feedbackSetStyleValue(id, key, value)
} else {
throw new Error(`Control "${controlId}" does not support feedbacks`)
}
}
)

client.onPromise('controls:hot-press', (location, direction, surfaceId) => {
this.logger.silly(`being told from gui to hot press ${formatLocation(location)} ${direction} ${surfaceId}`)
if (!surfaceId) throw new Error('Missing surfaceId')
Expand Down
17 changes: 17 additions & 0 deletions companion/lib/Controls/Fragments/FragmentActionInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { ActionDefinition } from '@companion-app/shared/Model/ActionDefinit
import type { ActionInstance } from '@companion-app/shared/Model/ActionModel.js'
import { visitActionInstance } from '../../Resources/Visitors/ActionInstanceVisitor.js'
import { FragmentFeedbackList } from './FragmentFeedbackList.js'
import { FragmentFeedbackInstance } from './FragmentFeedbackInstance.js'

export class FragmentActionInstance {
/**
Expand Down Expand Up @@ -373,6 +374,22 @@ export class FragmentActionInstance {
return actions
}

/**
* Recursively get all the actions
*/
getAllChildFeedbacks(): FragmentFeedbackInstance[] {
const feedbacks: FragmentFeedbackInstance[] = []

for (const actionGroup of this.#childActions.values()) {
feedbacks.push(...actionGroup.getAllFeedbacks())
}
for (const feedbackGroup of this.#childFeedbacks.values()) {
feedbacks.push(...feedbackGroup.getAllFeedbacks())
}

return feedbacks
}

/**
* Cleanup and forget any children belonging to the given connection
*/
Expand Down
10 changes: 9 additions & 1 deletion companion/lib/Controls/Fragments/FragmentActionList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { InstanceDefinitions } from '../../Instance/Definitions.js'
import type { InternalController } from '../../Internal/Controller.js'
import type { ModuleHost } from '../../Instance/Host.js'
import type { ActionInstance, ActionOwner } from '@companion-app/shared/Model/ActionModel.js'
import { FragmentFeedbackInstance } from './FragmentFeedbackInstance.js'

export class FragmentActionList {
readonly #instanceDefinitions: InstanceDefinitions
Expand Down Expand Up @@ -38,12 +39,19 @@ export class FragmentActionList {
}

/**
* Get all the actions
* Recursively get all the actions
*/
getAllActions(): FragmentActionInstance[] {
return [...this.#actions, ...this.#actions.flatMap((action) => action.getAllChildren())]
}

/**
* Recursively get all the feedbacks
*/
getAllFeedbacks(): FragmentFeedbackInstance[] {
return this.#actions.flatMap((action) => action.getAllChildFeedbacks())
}

/**
* Get the contained actions as `ActionInstance`s
*/
Expand Down
Loading

0 comments on commit 6008a30

Please sign in to comment.