Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ecc0ce5cd | ||
|
|
04f2f4c905 | ||
|
|
cb3867e1c6 | ||
|
|
4093ba9e15 | ||
|
|
b4d59b6f25 | ||
|
|
5595066a5b | ||
|
|
719b223bb3 | ||
|
|
7171557499 | ||
|
|
3dc5c241f5 | ||
|
|
301fab210e | ||
|
|
3a729004b0 | ||
|
|
20e9a5d3d3 | ||
|
|
56adb67b07 | ||
|
|
fd7c70839c | ||
|
|
0f32fd2f49 | ||
|
|
1fdd94e99f | ||
|
|
c2966a7483 | ||
|
|
86d8266385 | ||
|
|
4f95ea9e9d | ||
|
|
7ba9d1f84b | ||
|
|
7d96a05118 | ||
|
|
f3bd1979fa | ||
|
|
0a262b0474 | ||
|
|
5db4b5d6aa | ||
|
|
c1e9446515 | ||
|
|
c882a020a8 | ||
|
|
2a3dc8596e | ||
|
|
56a904bc2d | ||
|
|
8fff561d17 | ||
|
|
3036ceb81b | ||
|
|
1ca7d668b6 | ||
|
|
ae1e368149 | ||
|
|
f10ce1c9dc | ||
|
|
0697c69017 | ||
|
|
c20f918258 | ||
|
|
c4e946e01b | ||
|
|
6306606bf6 | ||
|
|
14e4193e13 | ||
|
|
9c5078e330 | ||
|
|
d62633c54d | ||
|
|
c4f009d62c | ||
|
|
2d875f1f26 | ||
|
|
75c1e2443a | ||
|
|
8ed1db8e1d | ||
|
|
880719355d | ||
|
|
046b1cf449 | ||
|
|
cf8d952932 | ||
|
|
b0d3e9df07 | ||
|
|
8c6f0a5ea4 | ||
|
|
cfaadc9a39 | ||
|
|
4f2f11d50a | ||
|
|
151292c602 | ||
|
|
db75a01f96 | ||
|
|
f41d8ac7b5 | ||
|
|
9d8b111002 | ||
|
|
bcfd6c08eb | ||
|
|
9a7f8019b9 | ||
|
|
ccfe00d6d5 | ||
|
|
31592bff60 | ||
|
|
c0a9ae3ddc | ||
|
|
f15500257a | ||
|
|
95eaafc350 | ||
|
|
815edc112a | ||
|
|
30088a83d9 | ||
|
|
a40dc2ae84 | ||
|
|
34541d1a90 | ||
|
|
8e1da203af | ||
|
|
697ae4060b | ||
|
|
df5118e75b | ||
|
|
132fd92798 | ||
|
|
bf1be2b246 | ||
|
|
d0ea95e63b | ||
|
|
0aaeb1fba6 | ||
|
|
6d19ddc881 | ||
|
|
57457e22b9 | ||
|
|
87795e5b5d | ||
|
|
d9288333c6 | ||
|
|
072f1cdf0c | ||
|
|
6af0d1b9d1 |
No files matched your search
@@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: josephdadams # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Bug report
|
||||
description: Create a bug report to help us improve.
|
||||
labels:
|
||||
- BUG
|
||||
title: '[BUG]'
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Make sure you have updated to the latest version of the module
|
||||
description: This may be a beta version of the module, or may require you to update your companion.
|
||||
options:
|
||||
- label: I have checked this on the latest version of the module
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is. Screenshots are always helpful to understand the problem.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps To Reproduce
|
||||
description: Steps to reproduce the behavior.
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A concise description of what you expected to happen.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment (please complete the following information)
|
||||
description: |
|
||||
examples:
|
||||
- **OS**: Windows 10
|
||||
- **Browser**: Chrome 94
|
||||
- **Companion Version**: 2.2.0-b177f8fb-3722
|
||||
- **Module Version**: 1.0.0
|
||||
- **Device Firmware/Software Version (If applicable)**: 3.0.6
|
||||
- **Device Model (If applicable)**: My Device PRO
|
||||
value: |
|
||||
- OS:
|
||||
- Browser:
|
||||
- Companion Version:
|
||||
- Module Version:
|
||||
- Device Firmware/Software Version (If applicable):
|
||||
- Device Model (If applicable):
|
||||
render: markdown
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context about the problem here.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: BUG OR FEATURE REQUEST FOR COMPANION ITSELF
|
||||
url: https://github.com/bitfocus/companion/issues
|
||||
about: Report it against the companion itself, to get the relevant people notified.
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Feature Request
|
||||
description: Request a new feature within this module
|
||||
title: '[Feature]: '
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Make sure you have updated to the latest version of the module
|
||||
description: This may be a beta version of the module, or may require you to update your companion.
|
||||
options:
|
||||
- label: I have checked this on the latest version of the module
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the feature.
|
||||
options:
|
||||
- label: I have searched for similar existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the feature
|
||||
description: A clear and concise description of what the feature does. Mocked up screenshots (no matter how rough) are always helpful in understanding.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Usecases
|
||||
description: Add a couple of usecases for why this should be implemented and when/why to use it.
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,18 @@
|
||||
name: Companion Module Checks
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check module
|
||||
|
||||
if: ${{ !contains(github.repository, 'companion-module-template-') }}
|
||||
|
||||
permissions:
|
||||
packages: read
|
||||
|
||||
uses: bitfocus/actions/.github/workflows/module-checks.yaml@main
|
||||
# with:
|
||||
# upload-artifact: true # uncomment this to upload the built package as an artifact to this workflow that you can download and share with others
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
node_modules/
|
||||
|
||||
# Companion 3
|
||||
/pkg
|
||||
/pkg.tgz
|
||||
.DS_Store
|
||||
@@ -1,34 +0,0 @@
|
||||
## Ross Carbonite/Vision
|
||||
|
||||
To make sense of the input and output names available in the actions provided by this module, you might want to read the bottom of this [reference manual.](http://help.rossvideo.com/carbonite-device/Topics/Protocol/RossTalk/CNT/RT-CNT-Comm.html)
|
||||
|
||||
**Available commands for Ross Carbonite/Vision**
|
||||
|
||||
* Trigger GPI
|
||||
* Fire custom control
|
||||
* Load Set
|
||||
* Cut
|
||||
* Auto Transition
|
||||
* XPT
|
||||
* Transition Keyer
|
||||
* Fade to black
|
||||
|
||||
**Available commands for Ross Xpression**
|
||||
|
||||
* CLFB buffer:layer
|
||||
* CLRA
|
||||
* CUE takeid:buffer:layer
|
||||
* DOWN
|
||||
* FOCUS takeid
|
||||
* GPI gpi
|
||||
* LAYEROFF buffer:layer
|
||||
* NEXT
|
||||
* READ
|
||||
* RESUME buffer
|
||||
* RESUME buffer:layer
|
||||
* SEQI takeid:layer
|
||||
* SEQO takeid
|
||||
* SWAP buffer
|
||||
* TAKE takeid:buffer:layer
|
||||
* UP
|
||||
* UPNEXT takeid
|
||||
@@ -0,0 +1,30 @@
|
||||
## Ross Carbonite/Vision
|
||||
|
||||
To make sense of the input and output names available in the actions provided by this module, you might want to read the bottom of this [reference manual.](http://help.rossvideo.com/carbonite-device/Topics/Protocol/RossTalk/CNT/RT-CNT-Comm.html)
|
||||
|
||||
|
||||
|
||||
**Available commands for All Versions**
|
||||
* Trigger GPI
|
||||
* Trigger GPI by Name
|
||||
* Run Custom Command
|
||||
|
||||
**Available commands for Ross Carbonite / Vision**
|
||||
|
||||
* Fire custom control
|
||||
* Load Set
|
||||
* Cut
|
||||
* Auto Transition
|
||||
* XPT
|
||||
* Transition Keyer
|
||||
* Fade to black
|
||||
|
||||
**Available commands for Ross Xpression**
|
||||
|
||||
This module does not support Xpression, instead use the dedicated module: [companion-module-rossvideo-xpression](https://github.com/bitfocus/companion-module-rossvideo-xpression)
|
||||
|
||||
**Ultrix**
|
||||
|
||||
* RUN, PAUSE, STOP, END timers
|
||||
|
||||
If you wish to control the Ross Ultrix router crosspoints then the Companion SWP-08 module is the best method.
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"id": "rossvideo-rosstalk",
|
||||
"name": "rossvideo-rosstalk",
|
||||
"shortname": "rosstalk",
|
||||
"description": "rosstalk plugin for Companion",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"repository": "git+https://github.com/bitfocus/companion-module-rossvideo-rosstalk.git",
|
||||
"bugs": "https://github.com/bitfocus/companion-module-rossvideo-rosstalk/issues",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "William Viker",
|
||||
"email": "william@bitfocus.io"
|
||||
}
|
||||
],
|
||||
"legacyIds": [
|
||||
"rosstalk"
|
||||
],
|
||||
"runtime": {
|
||||
"type": "node18",
|
||||
"api": "nodejs-ipc",
|
||||
"apiVersion": "0.0.0",
|
||||
"entrypoint": "../rosstalk.js"
|
||||
},
|
||||
"manufacturer": "Ross Video",
|
||||
"products": [
|
||||
"Rosstalk"
|
||||
],
|
||||
"keywords": [
|
||||
"Protocol",
|
||||
"Vision Mixer",
|
||||
"Software"
|
||||
]
|
||||
}
|
||||
+13
-17
@@ -1,23 +1,19 @@
|
||||
{
|
||||
"name": "rossvideo-rosstalk",
|
||||
"legacy": [
|
||||
"rosstalk"
|
||||
],
|
||||
"version": "1.2.8",
|
||||
"api_version": "1.0.0",
|
||||
"keywords": [
|
||||
"Protocol",
|
||||
"Vision Mixer",
|
||||
"Software"
|
||||
],
|
||||
"manufacturer": "Ross Video",
|
||||
"product": "Rosstalk",
|
||||
"shortname": "rosstalk",
|
||||
"description": "rosstalk plugin for Companion",
|
||||
"version": "2.1.0",
|
||||
"main": "rosstalk.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "William Viker <william@bitfocus.io>",
|
||||
"license": "MIT"
|
||||
}
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bitfocus/companion-module-rossvideo-rosstalk.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@companion-module/base": "^1.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@companion-module/tools": "^2.8.0"
|
||||
}
|
||||
}
|
||||
+84
-665
@@ -1,683 +1,102 @@
|
||||
var tcp = require('../../tcp');
|
||||
var instance_skel = require('../../instance_skel');
|
||||
var debug;
|
||||
var log;
|
||||
const { TCPHelper, InstanceBase, InstanceStatus, runEntrypoint } = require('@companion-module/base')
|
||||
|
||||
function instance(system, id, config) {
|
||||
var self = this;
|
||||
const config = require('./src/config')
|
||||
const actions = require('./src/actions')
|
||||
const upgrades = require('./src/upgrades')
|
||||
|
||||
// super-constructor
|
||||
instance_skel.apply(this, arguments);
|
||||
|
||||
self.actions(); // export actions
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
instance.GetUpgradeScripts = function() {
|
||||
return [
|
||||
function (context, config, actions, feedbacks) {
|
||||
let changed = false;
|
||||
|
||||
for(let actionsItem of actions){
|
||||
if(actionsItem['action'] == 'transKey'){
|
||||
if(actionsItem['options']['mle'] != undefined){
|
||||
actionsItem['options']['mle'] = "ME:"+actionsItem['options']['mle'];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
instance.prototype.updateConfig = function (config) {
|
||||
var self = this;
|
||||
|
||||
self.config = config;
|
||||
self.init_tcp();
|
||||
};
|
||||
|
||||
instance.prototype.init = function () {
|
||||
var self = this;
|
||||
|
||||
debug = self.debug;
|
||||
log = self.log;
|
||||
|
||||
self.status(self.STATE_UNKNOWN);
|
||||
|
||||
self.init_tcp();
|
||||
};
|
||||
|
||||
instance.prototype.init_tcp = function () {
|
||||
var self = this;
|
||||
|
||||
if (self.socket !== undefined) {
|
||||
self.socket.destroy();
|
||||
delete self.socket;
|
||||
class RossTalkInstance extends InstanceBase {
|
||||
constructor(internal) {
|
||||
super(internal)
|
||||
let self = this
|
||||
// Assign the methods from the listed files to this class
|
||||
Object.assign(self, {
|
||||
...config,
|
||||
...actions,
|
||||
})
|
||||
}
|
||||
|
||||
if (self.config.host) {
|
||||
if (self.config.port === undefined) {
|
||||
self.config.port = 7788;
|
||||
}
|
||||
self.socket = new tcp(self.config.host, self.config.port);
|
||||
|
||||
self.socket.on('status_change', function (status, message) {
|
||||
self.status(status, message);
|
||||
});
|
||||
|
||||
self.socket.on('error', function (err) {
|
||||
debug("Network error", err);
|
||||
self.status(self.STATE_ERROR, err);
|
||||
self.log('error', "Network error: " + err.message);
|
||||
});
|
||||
|
||||
self.socket.on('connect', function () {
|
||||
self.status(self.STATE_OK);
|
||||
debug("Connected");
|
||||
});
|
||||
|
||||
self.socket.on('data', function (data) { });
|
||||
}
|
||||
};
|
||||
|
||||
// Return config fields for web config
|
||||
instance.prototype.config_fields = function () {
|
||||
var self = this;
|
||||
return [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'info',
|
||||
width: 12,
|
||||
label: 'Information',
|
||||
value: 'To make sense of the input and output names available in the actions provided by this module, you might want to read the bottom of <a href="http://help.rossvideo.com/carbonite-device/Topics/Protocol/RossTalk/CNT/RT-CNT-Comm.html" target="_new">this reference manual</a>.'
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'host',
|
||||
label: 'Switcher Frame/XPression IP',
|
||||
width: 6,
|
||||
regex: self.REGEX_IP
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'port',
|
||||
label: 'Switcher Frame/XPression Port',
|
||||
width: 6,
|
||||
default: "7788",
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
// When module gets deleted
|
||||
instance.prototype.destroy = function () {
|
||||
var self = this;
|
||||
|
||||
if (self.socket !== undefined) {
|
||||
self.socket.destroy();
|
||||
static GetUpgradeScripts() {
|
||||
return [upgrades.legacy_upgrade]
|
||||
}
|
||||
|
||||
debug("destroy", self.id);
|
||||
};
|
||||
async init(config) {
|
||||
let self = this
|
||||
self.config = config
|
||||
|
||||
|
||||
instance.prototype.actions = function (system) {
|
||||
var self = this;
|
||||
self.system.emit('instance_actions', self.id, {
|
||||
|
||||
'gpi': {
|
||||
label: 'Trigger GPI',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Number',
|
||||
id: 'gpi',
|
||||
default: '1',
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'gpiByName': {
|
||||
label: 'Trigger GPI by Name',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Name',
|
||||
id: 'gpi',
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Parameter',
|
||||
id: 'parameter',
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'cc': {
|
||||
label: 'Fire custom control',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'CC Bank',
|
||||
id: 'bank',
|
||||
default: '1',
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'CC Number',
|
||||
id: 'cc',
|
||||
default: '1',
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'loadset': {
|
||||
label: 'Load Set',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Set name',
|
||||
id: 'set',
|
||||
default: 'set1'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'cut': {
|
||||
label: 'Cut',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
default: 'ME:1'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'autotrans': {
|
||||
label: 'Auto Transition',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
default: 'ME:1'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'xpt': {
|
||||
label: 'XPT',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Destination',
|
||||
id: 'vidDest',
|
||||
default: 'ME:1:PGM',
|
||||
tooltip: 'Program - ME:(ME-number):PGM, AuxBus — AUX:(aux-number), Key — ME:(ME-number):KEY:(key-number), MiniME™ — MME:(ME-number), Preset — ME:(ME-number):PST'
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Source',
|
||||
id: 'vidSource',
|
||||
default: 'IN:20',
|
||||
tooltip: 'Aux Bus — AUX:(aux-number), Black — BK, Clean — ME:(ME-number):CLN, Input Source — IN:(input-number), Key — ME:(ME-number):KEY:(key-number), Matte Color — BG, Media-Store — MS:(channel-number), MiniME™ — MME:(ME-number), Preview — ME:(ME-number):PV, Program — ME:(ME-number):PGM, XPression Alpha — XP:(channel-number):A [Graphite only], XPression Video — XP:(channel-number):V [Graphite only], Chroma Key Video — CK:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only], Chroma Key Alpha — CKA:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only]'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'transKey': {
|
||||
label: 'Transition Keyer',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
default: "ME:1"
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Keyer',
|
||||
id: 'key',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Transition On/Off Air (On & Off options may not be available in all switchers)',
|
||||
id: 'transD',
|
||||
default: 'TOGGLE',
|
||||
choices: [
|
||||
{ id: 'TOGGLE', label: 'Toggle Keyer' },
|
||||
{ id: 'ON', label: 'Transition OnAir' },
|
||||
{ id: 'OFF', label: 'Transition OffAir' }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Transition type',
|
||||
id: 'transT',
|
||||
default: 'CUT',
|
||||
choices: [
|
||||
{ id: 'AUTO', label: 'Auto Transition' },
|
||||
{ id: 'CUT', label: 'Cut Transition ' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'ftb': { label: 'Fade to black' },
|
||||
|
||||
'CLFB': {
|
||||
label: 'Clear Framebuffer',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Framebuffer',
|
||||
id: 'fb',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'CLFB_layer': {
|
||||
label: 'Clear Layer',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Framebuffer',
|
||||
id: 'fb',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'layer (OPTIONAL)',
|
||||
id: 'layer',
|
||||
default: '',
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'CLRA': { label: 'Clear All Framebuffers' },
|
||||
|
||||
'CUE': {
|
||||
label: 'CUE',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'frameBuffer',
|
||||
id: 'fb',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'layer',
|
||||
id: 'layer',
|
||||
default: '',
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'DOWN': { label: 'DOWN' },
|
||||
|
||||
'FOCUS': {
|
||||
label: 'FOCUS',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'LAYEROFF': {
|
||||
label: 'LAYEROFF',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'frameBuffer',
|
||||
id: 'fb',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Layer',
|
||||
id: 'layer',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'MEM': {
|
||||
label: 'MEM',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Memory ID',
|
||||
id: 'memID',
|
||||
default: '1:1',
|
||||
regex: self.REGEX_STRING
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
'NEXT': { label: 'NEXT' },
|
||||
|
||||
'READ': { label: 'READ' },
|
||||
|
||||
'RESUME': {
|
||||
label: 'RESUME FRAMEBUFFER',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Framebuffer',
|
||||
id: 'fb',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'RESUME_layer': {
|
||||
label: 'RESUME LAYER',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Framebuffer',
|
||||
id: 'fb',
|
||||
default: 1,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Layer',
|
||||
id: 'layer',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'SEQI': {
|
||||
label: 'SEQI',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Layer',
|
||||
id: 'Layer',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'SEQO': {
|
||||
label: 'SEQO',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'SWAP': {
|
||||
label: 'SWAP',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Framebuffer',
|
||||
id: 'fb',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'TAKE': {
|
||||
label: 'TAKE',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Framebuffer',
|
||||
id: 'fb',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Layer',
|
||||
id: 'layer',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
'UP': { label: 'UP' },
|
||||
|
||||
'UPNEXT': {
|
||||
label: 'UPNEXT',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: self.REGEX_NUMBER
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
instance.prototype.action = function (action) {
|
||||
var self = this;
|
||||
var id = action.action;
|
||||
var opt = action.options;
|
||||
|
||||
// parseInt(action.options.int)
|
||||
var cmd;
|
||||
|
||||
switch (action.action) {
|
||||
|
||||
case 'gpi':
|
||||
var gpi = parseInt(opt.gpi);
|
||||
cmd = 'GPI ' + (gpi > 9 ? '' : '0') + gpi;
|
||||
break;
|
||||
|
||||
case 'gpiByName':
|
||||
if (opt.parameter === null) {
|
||||
cmd = 'GPI ' + opt.gpi;
|
||||
} else {
|
||||
cmd = 'GPI ' + opt.gpi + ':' + opt.parameter;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'cc':
|
||||
var cc = parseInt(opt.cc);
|
||||
cmd = 'CC ' + parseInt(opt.bank) + ':' + (cc > 9 ? '' : '0') + cc;
|
||||
break;
|
||||
|
||||
case 'xpt':
|
||||
var src = opt.vidSource;
|
||||
var dst = opt.vidDest;
|
||||
cmd = 'XPT ' + dst + ':' + src;
|
||||
console.log('ross xpt:', cmd);
|
||||
break;
|
||||
|
||||
case 'ftb':
|
||||
cmd = 'FTB';
|
||||
break;
|
||||
|
||||
case 'loadset':
|
||||
cmd = 'LOADSET ' + opt.set;
|
||||
break;
|
||||
|
||||
case 'cut':
|
||||
cmd = 'MECUT ' + opt.mle;
|
||||
break;
|
||||
|
||||
case 'autotrans':
|
||||
cmd = 'MEAUTO ' + opt.mle;
|
||||
break;
|
||||
|
||||
case 'transKey':
|
||||
if (opt.transD === 'TOGGLE') {
|
||||
cmd = 'KEY' + opt.transT + ' ' + opt.mle + ':' + opt.key;
|
||||
} else {
|
||||
cmd = 'KEY' + opt.transT + opt.transD + ' ' + opt.mle + ':' + opt.key;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'CLFB':
|
||||
var frameBuffer = parseInt(opt.fb) - 1; // Framebuffer is 0 index so framebuffer 1 is actually 0 in rosstalk
|
||||
cmd = 'CLFB ' + frameBuffer;
|
||||
break;
|
||||
|
||||
case 'CLFB_layer':
|
||||
var frameBuffer = parseInt(opt.fb) - 1; // Framebuffer is 0 index so framebuffer 1 is actually 0 in rosstalk
|
||||
var layer = opt.layer;
|
||||
cmd = 'CLFB ' + frameBuffer + ':' + opt.layer;
|
||||
break;
|
||||
|
||||
case 'CLRA':
|
||||
cmd = 'CLRA';
|
||||
break;
|
||||
|
||||
case 'DOWN':
|
||||
cmd = 'DOWN';
|
||||
break;
|
||||
|
||||
case 'MEM':
|
||||
var memID = opt.memID;
|
||||
cmd = 'MEM ' + memID;
|
||||
break;
|
||||
|
||||
case 'FOCUS':
|
||||
var takeID = opt.takeID;
|
||||
cmd = 'FOCUS ' + takeID;
|
||||
break;
|
||||
|
||||
case 'LAYEROFF':
|
||||
var layer = opt.layer;
|
||||
cmd = 'LAYEROFF ' + layer;
|
||||
break;
|
||||
|
||||
case 'NEXT':
|
||||
cmd = 'NEXT';
|
||||
break;
|
||||
|
||||
case 'READ':
|
||||
cmd = 'READ';
|
||||
break;
|
||||
|
||||
case 'RESUME':
|
||||
var frameBuffer = parseInt(opt.fb) - 1;
|
||||
cmd = 'RESUME ' + frameBuffer;
|
||||
break;
|
||||
|
||||
case 'RESUME_layer':
|
||||
var frameBuffer = parseInt(opt.fb) - 1;
|
||||
var layer = opt.layer;
|
||||
cmd = 'RESUME ' + frameBuffer + ':' + layer;
|
||||
|
||||
break;
|
||||
|
||||
case 'SEQI':
|
||||
var takeID = opt.takeID;
|
||||
var layer = opt.layer;
|
||||
cmd = 'SEQI ' + takeID + ':' + layer;
|
||||
break;
|
||||
|
||||
case 'SEQO':
|
||||
var takeID = opt.takeID;
|
||||
cmd = 'SEQO ' + takeID;
|
||||
break;
|
||||
|
||||
case 'SWAP':
|
||||
var frameBuffer = parseInt(opt.fb) - 1;
|
||||
cmd = 'SWAP ' + frameBuffer;
|
||||
|
||||
case 'TAKE':
|
||||
var takeID = opt.takeID;
|
||||
var frameBuffer = parseInt(opt.fb) - 1;
|
||||
var layer = opt.layer;
|
||||
cmd = 'TAKE ' + takeID + ':' + frameBuffer + ':' + layer;
|
||||
break;
|
||||
|
||||
case 'UP':
|
||||
cmd = 'UP';
|
||||
break;
|
||||
|
||||
case 'UPNEXT':
|
||||
var takeID = opt.takeID;
|
||||
cmd = 'UPNEXT ' + takeID;
|
||||
break;
|
||||
self.updateStatus('connecting', 'Waiting To Connect')
|
||||
await self.configUpdated(config)
|
||||
}
|
||||
|
||||
if (cmd !== undefined) {
|
||||
async configUpdated(config) {
|
||||
let self = this
|
||||
self.config = config
|
||||
self.actions()
|
||||
|
||||
debug('sending tcp', cmd, "to", self.config.host);
|
||||
|
||||
if (self.socket !== undefined && self.socket.connected) {
|
||||
self.socket.send(cmd + "\r\n");
|
||||
if (self.config.keepAlive) {
|
||||
self.init_tcp();
|
||||
}
|
||||
else {
|
||||
debug('Socket not connected :(');
|
||||
self.updateStatus(InstanceStatus.Ok);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
debug('action():', action);
|
||||
init_tcp(cmd) {
|
||||
var self = this
|
||||
|
||||
if (self.socket !== undefined) {
|
||||
self.socket.destroy()
|
||||
delete self.socket
|
||||
}
|
||||
|
||||
};
|
||||
self.log('debug', 'Opening socket.');
|
||||
|
||||
instance_skel.extendedBy(instance);
|
||||
exports = module.exports = instance;
|
||||
if (self.config.host) {
|
||||
if (self.config.port === undefined) {
|
||||
self.config.port = 7788
|
||||
}
|
||||
self.socket = new TCPHelper(self.config.host, self.config.port)
|
||||
|
||||
self.socket.on('status_change', function (status, message) {
|
||||
if (status !== 'unknown_error') {
|
||||
self.updateStatus(status, message)
|
||||
}
|
||||
})
|
||||
|
||||
self.socket.on('error', function (err) {
|
||||
self.log('debug', 'Network error', JSON.stringify(err))
|
||||
self.updateStatus('error', err.code)
|
||||
self.log('error', 'Network error: ' + err.message)
|
||||
})
|
||||
|
||||
self.socket.on('connect', function () {
|
||||
self.updateStatus(InstanceStatus.Ok)
|
||||
self.log('debug', 'Connected')
|
||||
if (cmd !== undefined) {
|
||||
self.log('debug', `sending tcp ${cmd} to ${self.config.host}`);
|
||||
self.socket.send(cmd + '\r\n');
|
||||
|
||||
if (!self.config.keepAlive) {
|
||||
self.log('debug', 'Closing socket.');
|
||||
self.socket.destroy()
|
||||
delete self.socket
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
self.socket.on('data', function (data) {})
|
||||
}
|
||||
}
|
||||
|
||||
// When module gets deleted
|
||||
async destroy() {
|
||||
var self = this
|
||||
|
||||
if (self.socket !== undefined) {
|
||||
self.socket.destroy()
|
||||
}
|
||||
|
||||
self.log('debug', 'destroy', self.id)
|
||||
}
|
||||
}
|
||||
|
||||
runEntrypoint(RossTalkInstance, RossTalkInstance.GetUpgradeScripts())
|
||||
+665
@@ -0,0 +1,665 @@
|
||||
const { Regex } = require('@companion-module/base')
|
||||
module.exports = {
|
||||
actions() {
|
||||
let self = this
|
||||
|
||||
const re_meSource_meNumber = '/^(ME|MME|MSC):[0-9]{1,2}$/'
|
||||
|
||||
const sendCommand = (cmd) => {
|
||||
if (cmd !== undefined) {
|
||||
if (!self.config.keepAlive) {
|
||||
self.init_tcp(cmd);
|
||||
}
|
||||
else if (self.socket !== undefined && self.socket.isConnected) {
|
||||
self.log('debug', `sending tcp ${cmd} to ${self.config.host}`)
|
||||
self.socket.send(cmd + '\r\n')
|
||||
} else {
|
||||
self.log('debug', 'Socket not connected :(')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let actions = {
|
||||
gpi: {
|
||||
name: 'Trigger GPI',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Number',
|
||||
id: 'gpi',
|
||||
default: '1',
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let gpiText = await context.parseVariablesInString(opt.gpi)
|
||||
var gpi = parseInt(gpiText)
|
||||
cmd =
|
||||
'GPI ' + (gpi <= 9 && (self.config.model == 'carbonite' || self.config.model == 'acuity') ? '0' : '') + gpi
|
||||
sendCommand(cmd)
|
||||
},
|
||||
},
|
||||
|
||||
gpiByName: {
|
||||
name: 'Trigger GPI by Name',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Name',
|
||||
id: 'gpi',
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Parameter',
|
||||
id: 'parameter',
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
|
||||
if (opt.gpi) {
|
||||
let gpi = await context.parseVariablesInString(opt.gpi)
|
||||
let parameter = await context.parseVariablesInString(opt.parameter)
|
||||
if (parameter === null) {
|
||||
cmd = 'GPI ' + gpi
|
||||
} else {
|
||||
cmd = 'GPI ' + gpi + ':' + parameter
|
||||
}
|
||||
sendCommand(cmd)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
custom: {
|
||||
name: 'Send a custom command',
|
||||
description: 'Refer to RossTalk Guide',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Command',
|
||||
id: 'cmd',
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let cmd = await context.parseVariablesInString(opt.cmd)
|
||||
sendCommand(cmd)
|
||||
},
|
||||
},
|
||||
}
|
||||
if (self.config.model == 'carbonite') {
|
||||
actions.cc = {
|
||||
name: 'Fire custom control',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'CC Bank',
|
||||
id: 'bank',
|
||||
default: '1',
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'CC Number',
|
||||
id: 'cc',
|
||||
default: '1',
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let bankText = await context.parseVariablesInString(opt.bank)
|
||||
let ccText = await context.parseVariablesInString(opt.cc)
|
||||
var cc = parseInt(ccText)
|
||||
cmd = 'CC ' + parseInt(bankText) + ':' + (cc > 9 ? '' : '0') + cc
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.loadset = {
|
||||
name: 'Load Set',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Set name',
|
||||
id: 'set',
|
||||
useVariables: true,
|
||||
default: 'set1',
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let set = await context.parseVariablesInString(opt.set)
|
||||
cmd = 'LOADSET ' + set
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.cut = {
|
||||
name: 'Cut',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
useVariables: true,
|
||||
default: 'ME:1',
|
||||
regex: re_meSource_meNumber,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
cmd = 'MECUT ' + mle
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.autotrans = {
|
||||
name: 'Auto Transition',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
useVariables: true,
|
||||
default: 'ME:1',
|
||||
regex: re_meSource_meNumber,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
cmd = 'MEAUTO ' + mle
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.xpt = {
|
||||
name: 'XPT',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Destination',
|
||||
id: 'vidDest',
|
||||
default: 'ME:1:PGM',
|
||||
tooltip:
|
||||
'Program - ME:(ME-number):PGM, AuxBus — AUX:(aux-number), Key — ME:(ME-number):KEY:(key-number), MiniME™ — MME:(ME-number), Preset — ME:(ME-number):PST',
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Source',
|
||||
id: 'vidSource',
|
||||
default: 'IN:20',
|
||||
tooltip:
|
||||
'Aux Bus — AUX:(aux-number), Black — BK, Clean — ME:(ME-number):CLN, Input Source — IN:(input-number), Key — ME:(ME-number):KEY:(key-number), Matte Color — BG, Media-Store — MS:(channel-number), MiniME™ — MME:(ME-number), Preview — ME:(ME-number):PV, Program — ME:(ME-number):PGM, [Graphite only], Chroma Key Video — CK:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only], Chroma Key Alpha — CKA:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only]',
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var src = await context.parseVariablesInString(opt.vidSource)
|
||||
var dst = await context.parseVariablesInString(opt.vidDest)
|
||||
cmd = 'XPT ' + dst + ':' + src
|
||||
console.log('ross xpt:', cmd)
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.transKey = {
|
||||
name: 'Transition Keyer',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
useVariables: true,
|
||||
default: 'ME:1',
|
||||
regex: re_meSource_meNumber,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Keyer',
|
||||
id: 'key',
|
||||
default: 1,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Transition On/Off Air ',
|
||||
id: 'transD',
|
||||
default: 'TOGGLE',
|
||||
choices: [
|
||||
{ id: 'TOGGLE', label: 'Toggle Keyer' },
|
||||
{ id: 'ON', label: 'Transition OnAir' },
|
||||
{ id: 'OFF', label: 'Transition OffAir' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Transition type',
|
||||
id: 'transT',
|
||||
default: 'CUT',
|
||||
choices: [
|
||||
{ id: 'AUTO', label: 'Auto Transition' },
|
||||
{ id: 'CUT', label: 'Cut Transition ' },
|
||||
],
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
let keyText = await context.parseVariablesInString(opt.key)
|
||||
if (opt.transD === 'TOGGLE') {
|
||||
cmd = 'KEY' + opt.transT + ' ' + mle + ':' + keyText
|
||||
} else {
|
||||
cmd = 'KEY' + opt.transT + opt.transD + ' ' + mle + ':' + keyText
|
||||
}
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.ftb = {
|
||||
label: 'Fade to black',
|
||||
options: [],
|
||||
callback: async (event, context) => {
|
||||
cmd = 'FTB'
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.MEM = {
|
||||
name: 'MEM',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Memory ID',
|
||||
id: 'memID',
|
||||
default: '1:1',
|
||||
regex: '/^[0-9]{1,2}(:(ME|MME|MSC):[0-9]{1,2})+$/',
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var memID = await context.parseVariablesInString(opt.memID)
|
||||
cmd = 'MEM ' + memID
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.SEQI = {
|
||||
name: 'SEQI',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Layer',
|
||||
id: 'Layer',
|
||||
default: 0,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var takeID = await context.parseVariablesInString(opt.takeID)
|
||||
var layer = await context.parseVariablesInString(opt.Layer)
|
||||
cmd = 'SEQI ' + takeID + ':' + layer
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.SEQO = {
|
||||
name: 'SEQO',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'take ID',
|
||||
id: 'takeID',
|
||||
default: 0,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var takeID = await context.parseVariablesInString(opt.takeID)
|
||||
cmd = 'SEQO ' + takeID
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.MVBOX = {
|
||||
name: "Change multiviewer box",
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Multiviewer Number',
|
||||
id: 'mvID',
|
||||
default: 1,
|
||||
regex: Regex.NUMBER,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Box Number',
|
||||
id: 'boxID',
|
||||
default: 1,
|
||||
regex: Regex.NUMBER,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Source',
|
||||
id: 'vidSource',
|
||||
default: 'IN:5',
|
||||
tooltip:
|
||||
'Aux Bus — AUX:(aux-number), Black — BK, Clean — ME:(ME-number):CLN, Input Source — IN:(input-number), Key — ME:(ME-number):KEY:(key-number), Matte Color — BG, Media-Store — MS:(channel-number), MiniME™ — MME:(ME-number), Preview — ME:(ME-number):PV, Program — ME:(ME-number):PGM, [Graphite only], Chroma Key Video — CK:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only], Chroma Key Alpha — CKA:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only]',
|
||||
useVariables: true
|
||||
}
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mvID = parseInt(opt.mvID)
|
||||
let boxID = parseInt(opt.boxID)
|
||||
var src = await context.parseVariablesInString(opt.vidSource)
|
||||
|
||||
cmd = 'MVBOX:' + mvID + ":" + boxID + ":" + src
|
||||
sendCommand(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self.config.model == 'acuity') {
|
||||
actions.cc = {
|
||||
name: 'Fire custom control',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'CC Bank',
|
||||
id: 'bank',
|
||||
default: '1',
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'CC Number',
|
||||
id: 'cc',
|
||||
default: '1',
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let bankText = await context.parseVariablesInString(opt.bank)
|
||||
let ccText = await context.parseVariablesInString(opt.cc)
|
||||
var cc = parseInt(ccText)
|
||||
cmd = 'CC ' + parseInt(bankText) + ':' + (cc > 9 ? '' : '0') + cc
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.transKey = {
|
||||
name: 'Transition Keyer',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
default: 'ME:1',
|
||||
useVariables: true,
|
||||
regex: re_meSource_meNumber,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Keyer',
|
||||
id: 'key',
|
||||
default: 1,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Transition type',
|
||||
id: 'transT',
|
||||
default: 'CUT',
|
||||
choices: [
|
||||
{ id: 'AUTO', label: 'Auto Transition' },
|
||||
{ id: 'CUT', label: 'Cut Transition ' },
|
||||
],
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
let keyText = await context.parseVariablesInString(opt.key)
|
||||
cmd = 'KEY' + opt.transT + ' ' + mle + ':' + keyText
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.loadset = {
|
||||
name: 'Load Set',
|
||||
options: [
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Load Location',
|
||||
id: 'location',
|
||||
default: 'USB',
|
||||
choices: [
|
||||
{ id: 'USB', label: 'USB' },
|
||||
{ id: 'HD', label: 'HD' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Set name',
|
||||
useVariables: true,
|
||||
id: 'set',
|
||||
default: 'set1',
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let set = await context.parseVariablesInString(opt.set)
|
||||
let location = await context.parseVariablesInString(opt.location)
|
||||
cmd = 'LOADSET ' + location + ':' + set
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.cut = {
|
||||
name: 'Cut',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
useVariables: true,
|
||||
default: '1',
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
cmd = 'MECUT ' + mle
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
actions.ftb = {
|
||||
label: 'Fade to black',
|
||||
options: [],
|
||||
callback: async (event, context) => {
|
||||
cmd = 'FTB'
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.MEM = {
|
||||
name: 'MEM',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Memory ID',
|
||||
id: 'memID',
|
||||
default: '1:1',
|
||||
regex: '/^[0-9]{1,2}|?(:[0-9]{1,2})+$/',
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var memID = await context.parseVariablesInString(opt.memID)
|
||||
cmd = 'MEM ' + memID
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.autotrans = {
|
||||
name: 'Auto Transition',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
useVariables: true,
|
||||
default: '1',
|
||||
regex: Regex.NUMBER,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
cmd = 'MEAUTO ' + mle
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.xpt = {
|
||||
name: 'XPT',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Destination',
|
||||
id: 'vidDest',
|
||||
default: 'ME:1:PGM',
|
||||
tooltip:
|
||||
'Program - ME:(ME-number):PGM, AuxBus — AUX:(aux-number), Key — ME:(ME-number):KEY:(key-number), MiniME™ — MME:(ME-number), Preset — ME:(ME-number):PST',
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Source',
|
||||
id: 'vidSource',
|
||||
default: 'IN:20',
|
||||
tooltip:
|
||||
'Aux Bus — AUX:(aux-number), Black — BK, Clean — ME:(ME-number):CLN, Input Source — IN:(input-number), Key — ME:(ME-number):KEY:(key-number), Matte Color — BG, Media-Store — MS:(channel-number), MiniME™ — MME:(ME-number), Preview — ME:(ME-number):PV, Program — ME:(ME-number):PGM, [Graphite only], Chroma Key Video — CK:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only], Chroma Key Alpha — CKA:(chroma key number) [UltraChromeHR, or Carbonite Black v14.0 or higher only]',
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var src = await context.parseVariablesInString(opt.vidSource)
|
||||
var dst = await context.parseVariablesInString(opt.vidDest)
|
||||
cmd = 'XPT ' + dst + ':' + src
|
||||
console.log('ross xpt:', cmd)
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
}
|
||||
if (self.config.model == 'ultrix') {
|
||||
actions.TIMER = {
|
||||
name: 'Ultrix Timer',
|
||||
options: [
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Action type',
|
||||
id: 'timerAction',
|
||||
default: 'RUN',
|
||||
choices: [
|
||||
{ id: 'RUN', label: 'Run Timer' },
|
||||
{ id: 'PAUSE', label: 'Pause Timer' },
|
||||
{ id: 'STOP', label: 'Stop Timer' },
|
||||
{ id: 'END', label: 'End Timer' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Timer Number',
|
||||
id: 'timerID',
|
||||
default: 0,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
var timerAction = opt.timerAction
|
||||
var timerIDText = await context.parseVariablesInString(opt.timerID)
|
||||
var timerID = parseInt(timerIDText)
|
||||
cmd = 'TIMER ' + timerID + ':' + timerAction
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
}
|
||||
if (self.config.model == 'opengear') {
|
||||
actions.ftb = {
|
||||
label: 'Fade to black',
|
||||
description: 'Not supported on the MDK-111A-K.',
|
||||
options: [],
|
||||
callback: async (event, context) => {
|
||||
cmd = 'FTB'
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
|
||||
actions.transKey = {
|
||||
name: 'Transition Keyer',
|
||||
options: [
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'MLE',
|
||||
id: 'mle',
|
||||
useVariables: true,
|
||||
default: 'ME:1',
|
||||
regex: re_meSource_meNumber,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
label: 'Keyer',
|
||||
id: 'key',
|
||||
default: 1,
|
||||
regex: Regex.NUMBER,
|
||||
useVariables: true,
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
label: 'Transition type',
|
||||
id: 'transT',
|
||||
default: 'CUT',
|
||||
choices: [
|
||||
{ id: 'AUTO', label: 'Auto Transition' },
|
||||
{ id: 'CUT', label: 'Cut Transition ' },
|
||||
],
|
||||
},
|
||||
],
|
||||
callback: async (event, context) => {
|
||||
let opt = event.options
|
||||
let mle = await context.parseVariablesInString(opt.mle)
|
||||
let keyText = await context.parseVariablesInString(opt.key)
|
||||
cmd = 'KEY' + opt.transT + ' ' + mle + ':' + keyText
|
||||
sendCommand(cmd)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
this.setActionDefinitions(actions)
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
const { Regex } = require('@companion-module/base')
|
||||
module.exports = {
|
||||
getConfigFields() {
|
||||
return [
|
||||
{
|
||||
type: 'static-text',
|
||||
id: 'info',
|
||||
width: 12,
|
||||
label: 'Information',
|
||||
value:
|
||||
'To make sense of the input and output names available in the actions provided by this module, you might want to read the bottom of <a href="http://help.rossvideo.com/carbonite-device/Topics/Protocol/RossTalk/CNT/RT-CNT-Comm.html" target="_new">this reference manual</a>.',
|
||||
},
|
||||
{
|
||||
type: 'static-text',
|
||||
id: 'info',
|
||||
width: 12,
|
||||
label: 'Model',
|
||||
value:
|
||||
'This module does not support Xpression, instead use the dedicated module: <a href="https://github.com/bitfocus/companion-module-rossvideo-xpression">companion-module-rossvideo-xpression</a>',
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
id: 'model',
|
||||
label: 'Model',
|
||||
width: 12,
|
||||
default: 'carbonite',
|
||||
choices: [
|
||||
{ id: 'carbonite', label: 'Carbonite/Graphite' },
|
||||
{ id: 'ultrix', label: 'Ultrix' },
|
||||
{ id: 'acuity', label: 'Acuity/Vision' },
|
||||
{ id: 'opengear', label: 'openGear' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'host',
|
||||
label: 'Switcher Frame IP',
|
||||
width: 6,
|
||||
regex: Regex.IP,
|
||||
},
|
||||
{
|
||||
type: 'textinput',
|
||||
id: 'port',
|
||||
label: 'Switcher Frame Port',
|
||||
width: 6,
|
||||
default: '7788',
|
||||
regex: Regex.PORT,
|
||||
},
|
||||
{
|
||||
type: 'checkbox',
|
||||
id: 'keepAlive',
|
||||
label: 'TCP Keep Alive',
|
||||
tooltip: 'TCP Keep Alive: Use a single TCP connection instead of one per command',
|
||||
width: 6,
|
||||
default: false,
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
legacy_upgrade(context, props) {
|
||||
/* props
|
||||
{
|
||||
config: Object | null,
|
||||
actions: [],
|
||||
feedbacks: [],
|
||||
}
|
||||
*/
|
||||
let result = {
|
||||
updatedConfig: null, // the config does not need updating
|
||||
updatedActions: [],
|
||||
updatedFeedbacks: [],
|
||||
}
|
||||
let actions = props.actions
|
||||
|
||||
for (let actionsItem of actions) {
|
||||
if (actionsItem['action'] == 'transKey') {
|
||||
if (actionsItem['options']['mle'] != undefined) {
|
||||
actionsItem['options']['mle'] = 'ME:' + actionsItem['options']['mle']
|
||||
result.updatedActions.push(actionsItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
}
|
||||
Reference in new issue
Block a user