Skip to content

Commit aeb40d0

Browse files
authored
Add files via upload
1 parent c8183a4 commit aeb40d0

File tree

7 files changed

+278
-22
lines changed

7 files changed

+278
-22
lines changed

actions.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,45 @@ function getActionDefinitions(self) {
135135
},
136136
}
137137

138+
actions['playlist_jump_to_item'] = {
139+
name: 'Playlist Jump to Item',
140+
options: [
141+
cueNumberOption,
142+
{
143+
type: 'textinput',
144+
id: 'targetIndex',
145+
label: 'Item Index (0-based)',
146+
default: '0',
147+
tooltip: 'Zero-based index of the playlist item to jump to (first item is 0).',
148+
},
149+
],
150+
callback: async (action) => {
151+
const cueId = await resolveCueIdFromOptions(action.options)
152+
if (!cueId) {
153+
self.log('warn', 'Playlist Jump to Item: Cue number out of range or invalid')
154+
return
155+
}
156+
const targetIndexRaw = action.options.targetIndex != null ? String(action.options.targetIndex) : '0'
157+
const targetIndexParsed = self.parseVariablesInString ? await self.parseVariablesInString(targetIndexRaw) : targetIndexRaw
158+
const targetIndex = parseInt(targetIndexParsed, 10)
159+
if (Number.isNaN(targetIndex) || targetIndex < 0) {
160+
self.log('warn', 'Playlist Jump to Item: Invalid target index')
161+
return
162+
}
163+
if (self.ws && self.ws.readyState === 1) {
164+
self.ws.send(
165+
JSON.stringify({
166+
action: 'playlistJumpToItem',
167+
payload: {
168+
cueId,
169+
targetIndex,
170+
},
171+
}),
172+
)
173+
}
174+
},
175+
}
176+
138177
return actions
139178
}
140179

companion/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "accompaniment",
44
"shortname": "accompaniment",
55
"description": "Connects to the AcCompaniment app via a websocket server",
6-
"version": "1.1.8",
6+
"version": "1.1.9",
77
"license": "MIT",
88
"repository": "git+https://github.com/bitfocus/companion-module-highpass-accompaniment.git",
99
"bugs": "https://github.com/bitfocus/companion-module-highpass-accompaniment/issues",

feedbacks.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,86 @@ function getFeedbackDefinitions(self) {
7979
return status === 'stopped' || status === 'error' || !status
8080
},
8181
},
82+
cue_is_fading: {
83+
type: 'boolean',
84+
name: 'Cue is Fading',
85+
description: 'If the specified cue is currently fading in or fading out.',
86+
defaultStyle: {
87+
color: combineRgb(0, 0, 0),
88+
bgcolor: combineRgb(255, 165, 0), // Orange/amber for fading
89+
},
90+
options: [
91+
{
92+
type: 'textinput',
93+
label: 'Cue Number (1-based)',
94+
id: 'cueNumber',
95+
default: '',
96+
tooltip: 'Maps to the current cue list.',
97+
},
98+
],
99+
callback: (feedback) => {
100+
let cueId = ''
101+
const num = parseInt(feedback.options.cueNumber, 10)
102+
if (!Number.isNaN(num) && num > 0 && self.cues && self.cues[num - 1]) {
103+
cueId = self.cues[num - 1].id
104+
}
105+
return self.cuePlayStates[cueId] === 'fading'
106+
},
107+
},
108+
cue_is_fading_in: {
109+
type: 'boolean',
110+
name: 'Cue is Fading In',
111+
description: 'If the specified cue is currently fading in.',
112+
defaultStyle: {
113+
color: combineRgb(0, 0, 0),
114+
bgcolor: combineRgb(255, 165, 0), // Orange/amber for fading in
115+
},
116+
options: [
117+
{
118+
type: 'textinput',
119+
label: 'Cue Number (1-based)',
120+
id: 'cueNumber',
121+
default: '',
122+
tooltip: 'Maps to the current cue list.',
123+
},
124+
],
125+
callback: (feedback) => {
126+
let cueId = ''
127+
const num = parseInt(feedback.options.cueNumber, 10)
128+
if (!Number.isNaN(num) && num > 0 && self.cues && self.cues[num - 1]) {
129+
cueId = self.cues[num - 1].id
130+
}
131+
const fadeState = self.cueFadeStates[cueId]
132+
return self.cuePlayStates[cueId] === 'fading' && fadeState && fadeState.isFadingIn
133+
},
134+
},
135+
cue_is_fading_out: {
136+
type: 'boolean',
137+
name: 'Cue is Fading Out',
138+
description: 'If the specified cue is currently fading out.',
139+
defaultStyle: {
140+
color: combineRgb(255, 255, 255),
141+
bgcolor: combineRgb(255, 100, 0), // Darker orange/red for fading out
142+
},
143+
options: [
144+
{
145+
type: 'textinput',
146+
label: 'Cue Number (1-based)',
147+
id: 'cueNumber',
148+
default: '',
149+
tooltip: 'Maps to the current cue list.',
150+
},
151+
],
152+
callback: (feedback) => {
153+
let cueId = ''
154+
const num = parseInt(feedback.options.cueNumber, 10)
155+
if (!Number.isNaN(num) && num > 0 && self.cues && self.cues[num - 1]) {
156+
cueId = self.cues[num - 1].id
157+
}
158+
const fadeState = self.cueFadeStates[cueId]
159+
return self.cuePlayStates[cueId] === 'fading' && fadeState && fadeState.isFadingOut
160+
},
161+
},
82162
}
83163
}
84164

main.js

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ class SoundboardInstance extends InstanceBase {
1313
this.cues = [] // Store the cues received from the soundboard app
1414
this.reconnectInterval = null
1515
this.currentlyPlayingCueId = null // Track which cue is considered "currently playing"
16-
this.cuePlayStates = {} // cueId: 'playing' | 'paused' | 'stopped'
16+
this.cuePlayStates = {} // cueId: 'playing' | 'paused' | 'stopped' | 'fading'
1717
this.cueStartTimestamps = {} // cueId: number (ms since epoch)
18+
this.cueFadeStates = {} // cueId: { isFadingIn: boolean, isFadingOut: boolean }
1819
}
1920

2021
async init(config) {
@@ -134,27 +135,72 @@ class SoundboardInstance extends InstanceBase {
134135

135136
// Trigger feedback updates if status changed
136137
if (oldStatus !== status) {
137-
this.checkFeedbacks('cue_is_playing', 'cue_is_paused', 'cue_is_stopped')
138+
if (status === 'stopped') {
139+
delete this.cueFadeStates[cueId]
140+
} else if (status === 'fading') {
141+
this.cueFadeStates[cueId] = {
142+
isFadingIn: message.payload.isFadingIn || false,
143+
isFadingOut: message.payload.isFadingOut || false,
144+
}
145+
} else {
146+
delete this.cueFadeStates[cueId]
147+
}
148+
this.checkFeedbacks('cue_is_playing', 'cue_is_paused', 'cue_is_stopped', 'cue_is_fading', 'cue_is_fading_in', 'cue_is_fading_out')
138149
}
139150
}
140151
} else if (message.event === 'playbackTimeUpdate' && message.payload) {
141152
// Determine transitions and update current-cue semantics
142-
const { cueId, status } = message.payload
143-
let oldStatus
144-
if (cueId && status) {
145-
oldStatus = this.cuePlayStates[cueId]
146-
const setAsCurrentNow = status === 'playing' && oldStatus !== 'playing'
147-
if (setAsCurrentNow) {
148-
this.cueStartTimestamps[cueId] = Date.now()
149-
}
150-
if (status === 'stopped') {
151-
delete this.cueStartTimestamps[cueId]
152-
}
153-
updateVariablesForCue(this, message.payload, { setAsCurrentNow })
154-
this.cuePlayStates[cueId] = status
155-
if (oldStatus !== status) {
156-
this.checkFeedbacks('cue_is_playing', 'cue_is_paused', 'cue_is_stopped')
157-
}
153+
const { cueId, status } = message.payload
154+
let oldStatus
155+
if (cueId && status) {
156+
oldStatus = this.cuePlayStates[cueId]
157+
const oldFadeState = this.cueFadeStates[cueId]
158+
const setAsCurrentNow = (status === 'playing' || status === 'fading') && oldStatus !== 'playing' && oldStatus !== 'fading'
159+
if (setAsCurrentNow) {
160+
this.cueStartTimestamps[cueId] = Date.now()
161+
}
162+
if (status === 'stopped') {
163+
delete this.cueStartTimestamps[cueId]
164+
delete this.cueFadeStates[cueId]
165+
// Update state first so feedbacks evaluate correctly
166+
this.cuePlayStates[cueId] = status
167+
updateVariablesForCue(this, message.payload, { setAsCurrentNow })
168+
// Clear fade feedbacks if it was fading before
169+
if (oldStatus === 'fading') {
170+
this.checkFeedbacks('cue_is_fading_in', 'cue_is_fading_out', 'cue_is_fading')
171+
}
172+
if (oldStatus !== status) {
173+
this.checkFeedbacks('cue_is_playing', 'cue_is_paused', 'cue_is_stopped')
174+
}
175+
} else if (status === 'fading') {
176+
// Store fade state for feedbacks
177+
const newFadeState = {
178+
isFadingIn: message.payload.isFadingIn || false,
179+
isFadingOut: message.payload.isFadingOut || false,
180+
}
181+
this.cueFadeStates[cueId] = newFadeState
182+
this.cuePlayStates[cueId] = status
183+
updateVariablesForCue(this, message.payload, { setAsCurrentNow })
184+
// Check if fade direction changed
185+
const fadeDirectionChanged = !oldFadeState ||
186+
oldFadeState.isFadingIn !== newFadeState.isFadingIn ||
187+
oldFadeState.isFadingOut !== newFadeState.isFadingOut
188+
if (oldStatus !== status) {
189+
// Status changed to fading
190+
this.checkFeedbacks('cue_is_playing', 'cue_is_paused', 'cue_is_stopped', 'cue_is_fading', 'cue_is_fading_in', 'cue_is_fading_out')
191+
} else if (fadeDirectionChanged) {
192+
// Fade direction changed while status remained fading
193+
this.checkFeedbacks('cue_is_fading_in', 'cue_is_fading_out')
194+
}
195+
} else {
196+
// Clear fade state when not fading
197+
delete this.cueFadeStates[cueId]
198+
this.cuePlayStates[cueId] = status
199+
updateVariablesForCue(this, message.payload, { setAsCurrentNow })
200+
if (oldStatus !== status) {
201+
this.checkFeedbacks('cue_is_playing', 'cue_is_paused', 'cue_is_stopped', 'cue_is_fading', 'cue_is_fading_in', 'cue_is_fading_out')
202+
}
203+
}
158204

159205
// If the current cue stopped, switch to the most recently started remaining playing cue
160206
if (status === 'stopped' && this.currentlyPlayingCueId === cueId) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "highpass-accompaniment",
3-
"version": "1.1.8",
3+
"version": "1.1.9",
44
"description": "Companion module for the AcCompaniment soundboard app",
55
"main": "main.js",
66
"scripts": {

presets.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ function getPresetDefinitions(self) {
4242
bgcolor: combineRgb(255, 165, 0),
4343
},
4444
},
45+
{
46+
feedbackId: 'cue_is_fading_in',
47+
options: { cueNumber: `${i}` },
48+
style: {
49+
bgcolor: combineRgb(255, 165, 0), // Orange/amber for fading in
50+
},
51+
},
52+
{
53+
feedbackId: 'cue_is_fading_out',
54+
options: { cueNumber: `${i}` },
55+
style: {
56+
bgcolor: combineRgb(255, 100, 0), // Darker orange/red for fading out
57+
},
58+
},
4559
],
4660
})
4761
}

0 commit comments

Comments
 (0)