From 73da449dc8f1c91a37cf32dba1bc6ece25fd119f Mon Sep 17 00:00:00 2001 From: Adam Tow Date: Wed, 13 Jan 2021 13:45:03 -0800 Subject: [PATCH 1/5] Implemented the following commands: KeOn, CKOn, CDsL, DskS to set and get the status of the upstream and downstream keyers. Added test scripts to control the USK 1 and DSK 1 on M/E 0. --- Package.swift | 6 +- Sources/Atem/Messages/Actions.swift | 127 ++++++++++++++++++++++++++++ Sources/DSK/main.swift | 44 ++++++++++ Sources/USK/main.swift | 44 ++++++++++ 4 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 Sources/DSK/main.swift create mode 100644 Sources/USK/main.swift diff --git a/Package.swift b/Package.swift index 8cdb13c..ede3912 100644 --- a/Package.swift +++ b/Package.swift @@ -14,7 +14,9 @@ let package = Package( .executable(name: "TitleGenerator", targets: ["TitleGenerator"]), .executable(name: "PreviewSwitcher", targets: ["PreviewSwitcher"]), .executable(name: "SourceLabeler", targets: ["SourceLabeler"]), - .executable(name: "MessageDecoder", targets: ["MessageDecoder"]) + .executable(name: "MessageDecoder", targets: ["MessageDecoder"]), + .executable(name: "DSK", targets: ["DSK"]), + .executable(name: "USK", targets: ["USK"]) ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -33,6 +35,8 @@ let package = Package( .target(name: "PreviewSwitcher", dependencies: ["Atem"]), .target(name: "SourceLabeler", dependencies: ["Atem"]), .target(name: "MessageDecoder", dependencies: ["Atem"]), + .target(name: "DSK", dependencies: ["Atem"]), + .target(name: "USK", dependencies: ["Atem"]), .testTarget( name: "AtemTests", dependencies: ["Atem"] diff --git a/Sources/Atem/Messages/Actions.swift b/Sources/Atem/Messages/Actions.swift index 4453888..d79c313 100644 --- a/Sources/Atem/Messages/Actions.swift +++ b/Sources/Atem/Messages/Actions.swift @@ -450,3 +450,130 @@ public extension Message.Did { } } +// MARK: - Change Downstream Keyer + +extension Message.Do { + /// Informs a switcher that the downstream keyer on air status should be set + public struct ChangeDownstreamKeyerOnAir: SerializableMessage { + public static let title = Message.Title(string: "CDsL") + + public let keyer: UInt8 + public let onAir: Bool + + public init(with bytes: ArraySlice) throws { + self.keyer = bytes[relative: 0] + self.onAir = bytes[relative: 1] == 1 + } + + public init(to keyer: UInt8, onAir: Bool) { + self.keyer = keyer + self.onAir = onAir + } + + public var dataBytes: [UInt8] { + let onAirInt: UInt8 = onAir == true ? 1 : 0 + return [keyer, onAirInt , 0, 0] + } + + public var debugDescription: String {return "Change DSK \(keyer) On Air to \(onAir)"} + } +} +extension Message.Did { + /// Informs a controller that the downstream keyer on air status has changed + public struct ChangeDownstreamKeyerOnAir: SerializableMessage { + public static let title = Message.Title(string: "DskS") + + public let keyer: UInt8 + public let onAir: Bool + public let inTransition: Bool + public let isAutoTransitioning: Bool + public let framesRemaining: UInt8 + + public init(with bytes: ArraySlice) throws { + keyer = bytes[relative: 0] + onAir = bytes[relative: 1] == 1 + inTransition = bytes[relative: 2] == 1 + isAutoTransitioning = bytes[relative: 3] == 1 + framesRemaining = bytes[relative: 4] + } + + public init(to keyer: UInt8, onAir: Bool, inTransition: Bool, isAutoTransitioning: Bool, framesRemaining: UInt8 = 0) { + self.keyer = keyer + self.onAir = onAir + self.inTransition = inTransition + self.isAutoTransitioning = isAutoTransitioning + self.framesRemaining = framesRemaining + } + + public var dataBytes: [UInt8] { + let onAirInt: UInt8 = onAir ? 1 : 0 + let inTransitionInt: UInt8 = inTransition ? 1 : 0 + let isAutoTransitioningInt: UInt8 = isAutoTransitioning ? 1 : 0 + + return [keyer, onAirInt, inTransitionInt, isAutoTransitioningInt, framesRemaining, 0, 0, 0] + } + public var debugDescription: String { + return "DSK \(keyer) changed to On Air \(onAir) inTransition \(inTransition) isAutoTransitioning \(isAutoTransitioning) with \(framesRemaining) frames remaining" + } + } +} + +// MARK: - Change Upstream Keyer + +extension Message.Do { + /// Informs a switcher that the downstream keyer on air status should be set + public struct ChangeKeyerOnAir: SerializableMessage { + public static let title = Message.Title(string: "CKOn") + + public let mixEffect: UInt8 + public let keyer: UInt8 + public let enabled: Bool + + public init(with bytes: ArraySlice) throws { + self.mixEffect = bytes[relative: 0] + self.keyer = bytes[relative: 1] + self.enabled = bytes[relative: 2] == 1 + } + + public init(to mixEffect: UInt8, keyer: UInt8, enabled: Bool) { + self.mixEffect = mixEffect + self.keyer = keyer + self.enabled = enabled + } + + public var dataBytes: [UInt8] { + let enabledInt: UInt8 = enabled == true ? 1 : 0 + return [mixEffect, keyer, enabledInt , 0] + } + + public var debugDescription: String {return "Change M/E \(mixEffect) USK \(keyer) to \(enabled)"} + } +} +extension Message.Did { + /// Informs a controller that the downstream keyer on air status has changed + public struct ChangeKeyerOnAir: SerializableMessage { + public static let title = Message.Title(string: "KeOn") + + public let mixEffect: UInt8 + public let keyer: UInt8 + public let enabled: Bool + + public init(with bytes: ArraySlice) throws { + self.mixEffect = bytes[relative: 0] + self.keyer = bytes[relative: 1] + self.enabled = bytes[relative: 2] == 1 + } + + public init(to mixEffect: UInt8, keyer: UInt8, enabled: Bool) { + self.mixEffect = mixEffect + self.keyer = keyer + self.enabled = enabled + } + + public var dataBytes: [UInt8] { + let enabledInt: UInt8 = enabled == true ? 1 : 0 + return [mixEffect, keyer, enabledInt , 0] + } + public var debugDescription: String {return "Change M/E \(mixEffect) USK \(keyer) to \(enabled)"} + } +} diff --git a/Sources/DSK/main.swift b/Sources/DSK/main.swift new file mode 100644 index 0000000..84c1e5d --- /dev/null +++ b/Sources/DSK/main.swift @@ -0,0 +1,44 @@ +// +// main.swift +// +// +// Created by adamtow on 12/01/2021. +// + +import Foundation +import Atem + +let address: String +if CommandLine.arguments.count > 1 { + address = CommandLine.arguments[1] +} else { + print("Enter switcher IP address: ", terminator: "") + address = readLine() ?? "10.1.0.210" +} +print("Trying to connect to switcher with IP addres", address) + +let controller = try Controller(ipAddress: address) { connection in + connection.when{ (change: Did.ChangeDownstreamKeyerOnAir) in + print(change) // prints: 'Preview bus changed to input(x)' + } + + connection.when { (connected: Config.InitiationComplete) in + print(connected) + print("Type 1 or 0 and to change the On Air status of the DSK 0") + } + + connection.whenDisconnected = { + print("Disconnected") + } +} + +var sourceString: String +while true { + sourceString = readLine() ?? "1" + guard let sourceNumber = UInt16(sourceString) else { + print("invalid source") + continue + } + + controller.send(message: Do.ChangeDownstreamKeyerOnAir(to: 0, onAir: sourceNumber == 1)) +} diff --git a/Sources/USK/main.swift b/Sources/USK/main.swift new file mode 100644 index 0000000..1773ff1 --- /dev/null +++ b/Sources/USK/main.swift @@ -0,0 +1,44 @@ +// +// main.swift +// +// +// Created by adamtow on 12/01/2021. +// + +import Foundation +import Atem + +let address: String +if CommandLine.arguments.count > 1 { + address = CommandLine.arguments[1] +} else { + print("Enter switcher IP address: ", terminator: "") + address = readLine() ?? "10.1.0.210" +} +print("Trying to connect to switcher with IP addres", address) + +let controller = try Controller(ipAddress: address) { connection in + connection.when{ (change: Did.ChangeKeyerOnAir) in + print(change) // prints: 'Preview bus changed to input(x)' + } + + connection.when { (connected: Config.InitiationComplete) in + print(connected) + print("Type 1 or 0 and to change the Enabled status of the USK 0 on M/E 0") + } + + connection.whenDisconnected = { + print("Disconnected") + } +} + +var sourceString: String +while true { + sourceString = readLine() ?? "1" + guard let sourceNumber = UInt16(sourceString) else { + print("invalid source") + continue + } + + controller.send(message: Do.ChangeKeyerOnAir(to: 0, keyer: 0, enabled: sourceNumber == 1)) +} From 14bbe23a9a37ece33c57dce0221ad2012bf237e0 Mon Sep 17 00:00:00 2001 From: Adam Tow Date: Wed, 13 Jan 2021 16:05:23 -0800 Subject: [PATCH 2/5] Change framesRemaining to remainingFrames in ChangeDownstreamKeyerOnAir message. Add Config.MacroPro and Do.MacroAction commands. Added Macro test script. --- Package.resolved | 8 +-- Package.swift | 4 +- Sources/Atem/Messages/Actions.swift | 53 ++++++++++++++-- Sources/Atem/Messages/Configuration.swift | 76 +++++++++++++++++++++++ Sources/Macro/main.swift | 48 ++++++++++++++ 5 files changed, 178 insertions(+), 11 deletions(-) create mode 100644 Sources/Macro/main.swift diff --git a/Package.resolved b/Package.resolved index 421c660..54fc185 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "120acb15c39aa3217e9888e515de160378fbcc1e", - "version": "2.18.0" + "revision": "43931b7a7daf8120a487601530c8bc03ce711992", + "version": "2.25.1" } }, { @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/apple/swift-nio-extras.git", "state": { "branch": null, - "revision": "7cd24c0efcf9700033f671b6a8eaa64a77dd0b72", - "version": "1.5.1" + "revision": "e5b5d191a80667a14827bfeb0ae4a511f7677942", + "version": "1.7.0" } } ] diff --git a/Package.swift b/Package.swift index ede3912..44f79b2 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,8 @@ let package = Package( .executable(name: "SourceLabeler", targets: ["SourceLabeler"]), .executable(name: "MessageDecoder", targets: ["MessageDecoder"]), .executable(name: "DSK", targets: ["DSK"]), - .executable(name: "USK", targets: ["USK"]) + .executable(name: "USK", targets: ["USK"]), + .executable(name: "Macro", targets: ["Macro"]) ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -37,6 +38,7 @@ let package = Package( .target(name: "MessageDecoder", dependencies: ["Atem"]), .target(name: "DSK", dependencies: ["Atem"]), .target(name: "USK", dependencies: ["Atem"]), + .target(name: "Macro", dependencies: ["Atem"]), .testTarget( name: "AtemTests", dependencies: ["Atem"] diff --git a/Sources/Atem/Messages/Actions.swift b/Sources/Atem/Messages/Actions.swift index d79c313..3d48a8b 100644 --- a/Sources/Atem/Messages/Actions.swift +++ b/Sources/Atem/Messages/Actions.swift @@ -487,22 +487,22 @@ extension Message.Did { public let onAir: Bool public let inTransition: Bool public let isAutoTransitioning: Bool - public let framesRemaining: UInt8 + public let remainingFrames: UInt8 public init(with bytes: ArraySlice) throws { keyer = bytes[relative: 0] onAir = bytes[relative: 1] == 1 inTransition = bytes[relative: 2] == 1 isAutoTransitioning = bytes[relative: 3] == 1 - framesRemaining = bytes[relative: 4] + remainingFrames = bytes[relative: 4] } - public init(to keyer: UInt8, onAir: Bool, inTransition: Bool, isAutoTransitioning: Bool, framesRemaining: UInt8 = 0) { + public init(to keyer: UInt8, onAir: Bool, inTransition: Bool, isAutoTransitioning: Bool, remainingFrames: UInt8 = 0) { self.keyer = keyer self.onAir = onAir self.inTransition = inTransition self.isAutoTransitioning = isAutoTransitioning - self.framesRemaining = framesRemaining + self.remainingFrames = remainingFrames } public var dataBytes: [UInt8] { @@ -510,10 +510,10 @@ extension Message.Did { let inTransitionInt: UInt8 = inTransition ? 1 : 0 let isAutoTransitioningInt: UInt8 = isAutoTransitioning ? 1 : 0 - return [keyer, onAirInt, inTransitionInt, isAutoTransitioningInt, framesRemaining, 0, 0, 0] + return [keyer, onAirInt, inTransitionInt, isAutoTransitioningInt, remainingFrames, 0, 0, 0] } public var debugDescription: String { - return "DSK \(keyer) changed to On Air \(onAir) inTransition \(inTransition) isAutoTransitioning \(isAutoTransitioning) with \(framesRemaining) frames remaining" + return "DSK \(keyer) changed to On Air \(onAir) inTransition \(inTransition) isAutoTransitioning \(isAutoTransitioning) with \(remainingFrames) frames remaining" } } } @@ -577,3 +577,44 @@ extension Message.Did { public var debugDescription: String {return "Change M/E \(mixEffect) USK \(keyer) to \(enabled)"} } } + +// MARK: - Macro Action + +extension Message.Do { + /// Informs a switcher that the downstream keyer on air status should be set + public struct MacroAction: SerializableMessage { + public static let title = Message.Title(string: "MAct") + + public let index: UInt16 + public let action: UInt8 + + enum Action { + static let run = 0 + static let stop = 1 + static let stopRecording = 2 + static let insertWait = 3 + static let continueMacro = 4 + static let delete = 5 + } + + public init(with bytes: ArraySlice) throws { + self.index = UInt16(from: bytes[relative: 0..<2]) + self.action = bytes[relative: 2] + } + + public init(index: UInt16, action: UInt8) { + self.index = index + self.action = action + } + + public var dataBytes: [UInt8] { + let indexArray = index.bytes + + return indexArray + [action, 0] + } + + public var debugDescription: String { + return "Macro: \(index) action: \(action)" + } + } +} diff --git a/Sources/Atem/Messages/Configuration.swift b/Sources/Atem/Messages/Configuration.swift index b0f2818..a216e95 100644 --- a/Sources/Atem/Messages/Configuration.swift +++ b/Sources/Atem/Messages/Configuration.swift @@ -234,6 +234,82 @@ extension Message.Config { "Media pool with capacity for \(stillCapacity) stills and \(clipCapacity) clips" } } + + public struct MacroPool: SerializableMessage { + public static let title = Message.Title(string: "_MAC") + + /// The number of macro banks that are available + public let banks: UInt8 + + public init(with bytes: ArraySlice) throws { + banks = bytes[relative: 0] + } + + public init(banks: UInt8) { + self.banks = banks + } + + public var dataBytes: [UInt8] { + return [banks, 0, 0, 0] + } + + public var debugDescription: String { + "Number of macros: \(banks)" + } + } + + public struct MacroProperties: SerializableMessage { + public static let title = Message.Title(string: "MPrp") + static let defaultText = " ".data(using: .utf8)! + [0] + + /// The number of macro banks that are available + public let macroIndex: UInt8 + public let isUsed: Bool + public let nameLength: UInt16 + public let descriptionLength: UInt16 + public let nameBytes: ArraySlice + public let descriptionBytes: ArraySlice + + public var name: String? { + String(bytes: nameBytes, encoding: .utf8) + } + public var description: String? { + String(bytes: descriptionBytes, encoding: .utf8) + } + + public init(with bytes: ArraySlice) throws { + self.macroIndex = bytes[relative: 1] + self.isUsed = bytes[relative: 2] == 1 + self.nameLength = UInt16(from: bytes[relative: 4..<6]) + self.descriptionLength = UInt16(from: bytes[relative: 6..<8]) + + let nameEnd: Int = Int(8 + nameLength) + self.nameBytes = bytes[relative: 8.. 1 { + address = CommandLine.arguments[1] +} else { + print("Enter switcher IP address: ", terminator: "") + address = readLine() ?? "10.1.0.210" +} +print("Trying to connect to switcher with IP addres", address) + +let controller = try Controller(ipAddress: address) { connection in + connection.when{ (change: Config.MacroPool) in + print(change) // prints: 'Number of macro pool banks: input(x)' + } + + connection.when { (change: Config.MacroProperties) in + print(change) // prints: list of macros + } + + connection.when { (connected: Config.InitiationComplete) in + print(connected) + print("Type a number to run the macro at that index") + } + + connection.whenDisconnected = { + print("Disconnected") + } +} + +var macroIndexString: String +while true { + macroIndexString = readLine() ?? "1" + guard let macroIndex = UInt8(macroIndexString) else { + print("invalid macroIndex") + continue + } + + controller.send(message: Do.MacroAction(index: UInt16(macroIndex), action: 0)) +} From ae1b300a215d8f16709bfa549dbf8620eceee20f Mon Sep 17 00:00:00 2001 From: Adam Tow Date: Wed, 13 Jan 2021 20:20:53 -0800 Subject: [PATCH 3/5] ProductName configuration message. --- Package.swift | 4 ++- Sources/Atem/Messages/Configuration.swift | 38 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 44f79b2..50a165f 100644 --- a/Package.swift +++ b/Package.swift @@ -17,7 +17,8 @@ let package = Package( .executable(name: "MessageDecoder", targets: ["MessageDecoder"]), .executable(name: "DSK", targets: ["DSK"]), .executable(name: "USK", targets: ["USK"]), - .executable(name: "Macro", targets: ["Macro"]) + .executable(name: "Macro", targets: ["Macro"]), + .executable(name: "ProductInfo", targets: ["ProductInfo"]) ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -39,6 +40,7 @@ let package = Package( .target(name: "DSK", dependencies: ["Atem"]), .target(name: "USK", dependencies: ["Atem"]), .target(name: "Macro", dependencies: ["Atem"]), + .target(name: "ProductInfo", dependencies: ["Atem"]), .testTarget( name: "AtemTests", dependencies: ["Atem"] diff --git a/Sources/Atem/Messages/Configuration.swift b/Sources/Atem/Messages/Configuration.swift index a216e95..f3def86 100644 --- a/Sources/Atem/Messages/Configuration.swift +++ b/Sources/Atem/Messages/Configuration.swift @@ -35,6 +35,44 @@ extension Message.Config { public var debugDescription: String { return "Version: \(major).\(minor)"} } + + /// Information about the ATEM product + public struct ProductName: SerializableMessage { + public static let title = Message.Title(string: "_pin") + static let namePosition = 0..<44 + static let tooLongNameCount = namePosition.count + 1 + static let truncationDots = Array("...".utf8) + public let name: String + + public init(with bytes: ArraySlice) throws { + // Stores the string constructed from the first non-zero bytes + guard let string = String(bytes: bytes.prefix(upTo: bytes[relative: Self.namePosition].firstIndex {$0==0} ?? 44), encoding: .utf8) else { + throw Message.Error.titleNotDeserializable + } + self.name = string + } + + public init(name: String) { + self.name = name + } + + public var dataBytes: [UInt8] { + let binaryString = Array(name.utf8).prefix(Self.tooLongNameCount) + let fixedString: [UInt8] + switch binaryString.count { + case Self.tooLongNameCount... : + fixedString = binaryString.prefix(Self.namePosition.upperBound - Self.truncationDots.count) + Self.truncationDots + default: + fixedString = binaryString + Array(repeating: UInt8(0), count: Self.namePosition.count - binaryString.count) + } + return fixedString + } + + public var debugDescription: String { + return name + } + } + /// Information about the ATEM product public struct ProductInfo: SerializableMessage { public static let title = Message.Title(string: "_pin") From ac129c1ccb5f6cc297c2acd7d09780061436c22a Mon Sep 17 00:00:00 2001 From: Adam Tow Date: Wed, 13 Jan 2021 20:24:30 -0800 Subject: [PATCH 4/5] ProductName test script. --- Package.swift | 4 ++-- Sources/ProductName/main.swift | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 Sources/ProductName/main.swift diff --git a/Package.swift b/Package.swift index 50a165f..0527603 100644 --- a/Package.swift +++ b/Package.swift @@ -18,7 +18,7 @@ let package = Package( .executable(name: "DSK", targets: ["DSK"]), .executable(name: "USK", targets: ["USK"]), .executable(name: "Macro", targets: ["Macro"]), - .executable(name: "ProductInfo", targets: ["ProductInfo"]) + .executable(name: "ProductName", targets: ["ProductName"]) ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -40,7 +40,7 @@ let package = Package( .target(name: "DSK", dependencies: ["Atem"]), .target(name: "USK", dependencies: ["Atem"]), .target(name: "Macro", dependencies: ["Atem"]), - .target(name: "ProductInfo", dependencies: ["Atem"]), + .target(name: "ProductName", dependencies: ["Atem"]), .testTarget( name: "AtemTests", dependencies: ["Atem"] diff --git a/Sources/ProductName/main.swift b/Sources/ProductName/main.swift new file mode 100644 index 0000000..8605de2 --- /dev/null +++ b/Sources/ProductName/main.swift @@ -0,0 +1,37 @@ +// +// main.swift +// +// +// Created by adamtow on 12/01/2021. +// + +import Foundation +import Atem + +let address: String +if CommandLine.arguments.count > 1 { + address = CommandLine.arguments[1] +} else { + print("Enter switcher IP address: ", terminator: "") + address = readLine() ?? "10.1.0.210" +} +print("Trying to connect to switcher with IP addres", address) + +let controller = try Controller(ipAddress: address) { connection in + connection.when{ (change: Config.ProductName) in + print(change) + } + + connection.when { (connected: Config.InitiationComplete) in + print(connected) + } + + connection.whenDisconnected = { + print("Disconnected") + } +} + +var sourceString: String +while true { + +} From f6df3c217b5b90801f52dc24c944b5be7d635c9d Mon Sep 17 00:00:00 2001 From: Adam Tow Date: Wed, 13 Jan 2021 22:20:19 -0800 Subject: [PATCH 5/5] Commands to set the fill and key source for the Downstream Keyers. --- Package.swift | 2 + Sources/Atem/Messages/Actions.swift | 90 +++++++++++++++++++++++++++++ Sources/DSK/main.swift | 2 +- Sources/DSKSource/main.swift | 50 ++++++++++++++++ Sources/USK/main.swift | 2 +- 5 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 Sources/DSKSource/main.swift diff --git a/Package.swift b/Package.swift index 0527603..db6e721 100644 --- a/Package.swift +++ b/Package.swift @@ -16,6 +16,7 @@ let package = Package( .executable(name: "SourceLabeler", targets: ["SourceLabeler"]), .executable(name: "MessageDecoder", targets: ["MessageDecoder"]), .executable(name: "DSK", targets: ["DSK"]), + .executable(name: "DSKSource", targets: ["DSKSource"]), .executable(name: "USK", targets: ["USK"]), .executable(name: "Macro", targets: ["Macro"]), .executable(name: "ProductName", targets: ["ProductName"]) @@ -38,6 +39,7 @@ let package = Package( .target(name: "SourceLabeler", dependencies: ["Atem"]), .target(name: "MessageDecoder", dependencies: ["Atem"]), .target(name: "DSK", dependencies: ["Atem"]), + .target(name: "DSKSource", dependencies: ["Atem"]), .target(name: "USK", dependencies: ["Atem"]), .target(name: "Macro", dependencies: ["Atem"]), .target(name: "ProductName", dependencies: ["Atem"]), diff --git a/Sources/Atem/Messages/Actions.swift b/Sources/Atem/Messages/Actions.swift index 3d48a8b..074034e 100644 --- a/Sources/Atem/Messages/Actions.swift +++ b/Sources/Atem/Messages/Actions.swift @@ -518,6 +518,96 @@ extension Message.Did { } } +// MARK: - Downstream Keyer + +extension Message.Do { + /// Informs a switcher that the downstream keyer fill source should be set + public struct ChangeDownstreamKeyerFillSource: SerializableMessage { + public static let title = Message.Title(string: "CDsF") + + public let keyer: UInt8 + public let fillSource: VideoSource + + public init(with bytes: ArraySlice) throws { + self.keyer = bytes[relative: 0] + let fillSourceNumber = UInt16(from: bytes[relative: 2..<4]) + self.fillSource = try VideoSource.decode(from: fillSourceNumber) + + } + + public init(to keyer: UInt8, fillSource: VideoSource) { + self.keyer = keyer + self.fillSource = fillSource + } + + public var dataBytes: [UInt8] { + return [keyer, 0] + fillSource.rawValue.bytes + } + public var debugDescription: String { + return "Set DSK \(keyer) fillSource to: \(fillSource)" + } + } + + /// Informs a switcher that the downstream keyer key source should be set + public struct ChangeDownstreamKeyerKeySource: SerializableMessage { + public static let title = Message.Title(string: "CDsC") + + public let keyer: UInt8 + public let keySource: VideoSource + + public init(with bytes: ArraySlice) throws { + self.keyer = bytes[relative: 0] + let keySourceNumber = UInt16(from: bytes[relative: 2..<4]) + self.keySource = try VideoSource.decode(from: keySourceNumber) + } + + public init(to keyer: UInt8, keySource: VideoSource) { + self.keyer = keyer + self.keySource = keySource + } + + public var dataBytes: [UInt8] { + return [keyer, 0] + keySource.rawValue.bytes + } + public var debugDescription: String { + return "Set DSK \(keyer) keySource to: \(keySource)" + } + } +} + +extension Message.Did { + /// informs a controller that the Downstream keyer source and fill has changed + public struct ChangeDownstreamKeyer: SerializableMessage { + public static let title = Message.Title(string: "DskB") + + public let keyer: UInt8 + public let fillSource: VideoSource + public let keySource: VideoSource + + public init(with bytes: ArraySlice) throws { + self.keyer = bytes[relative: 0] + let fillSourceNumber = UInt16(from: bytes[relative: 2..<4]) + self.fillSource = try VideoSource.decode(from: fillSourceNumber) + + let keySourceNumber = UInt16(from: bytes[relative: 4..<6]) + self.keySource = try VideoSource.decode(from: keySourceNumber) + } + + public init(to keyer: UInt8, fillSource: VideoSource, keySource: VideoSource) { + self.keyer = keyer + self.fillSource = fillSource + self.keySource = keySource + } + + public var dataBytes: [UInt8] { + return [keyer, 0] + fillSource.rawValue.bytes + keySource.rawValue.bytes + } + public var debugDescription: String { + return "DSK \(keyer) fillSource: \(fillSource) keySource: \(keySource)" + } + } +} + // MARK: - Change Upstream Keyer extension Message.Do { diff --git a/Sources/DSK/main.swift b/Sources/DSK/main.swift index 84c1e5d..83efee2 100644 --- a/Sources/DSK/main.swift +++ b/Sources/DSK/main.swift @@ -24,7 +24,7 @@ let controller = try Controller(ipAddress: address) { connection in connection.when { (connected: Config.InitiationComplete) in print(connected) - print("Type 1 or 0 and to change the On Air status of the DSK 0") + print("Type 1 or 0 and to change the On Air status of the DSK 1") } connection.whenDisconnected = { diff --git a/Sources/DSKSource/main.swift b/Sources/DSKSource/main.swift new file mode 100644 index 0000000..20a2c09 --- /dev/null +++ b/Sources/DSKSource/main.swift @@ -0,0 +1,50 @@ +// +// main.swift +// +// +// Created by adamtow on 12/01/2021. +// + +import Foundation +import Atem + +let address: String +if CommandLine.arguments.count > 1 { + address = CommandLine.arguments[1] +} else { + print("Enter switcher IP address: ", terminator: "") + address = readLine() ?? "10.1.0.210" +} +print("Trying to connect to switcher with IP addres", address) + +let controller = try Controller(ipAddress: address) { connection in + connection.when{ (change: Did.ChangeDownstreamKeyerOnAir) in + print(change) // prints: 'Preview bus changed to input(x)' + } + + connection.when{ (change: Did.ChangeDownstreamKeyer) in + print(change) // prints: 'Preview bus changed to input(x)' + } + + connection.when { (connected: Config.InitiationComplete) in + print(connected) + print("Type a source to change the fill source of the DSK 1") + } + + connection.whenDisconnected = { + print("Disconnected") + } +} + +var sourceString: String +while true { + sourceString = readLine() ?? "1" + guard let sourceNumber = UInt16(sourceString) else { + print("invalid source") + continue + } + + let fillSource = VideoSource(rawValue: sourceNumber) + + controller.send(message: Do.ChangeDownstreamKeyerFillSource(to: 0, fillSource: fillSource)) +} diff --git a/Sources/USK/main.swift b/Sources/USK/main.swift index 1773ff1..f9cb320 100644 --- a/Sources/USK/main.swift +++ b/Sources/USK/main.swift @@ -24,7 +24,7 @@ let controller = try Controller(ipAddress: address) { connection in connection.when { (connected: Config.InitiationComplete) in print(connected) - print("Type 1 or 0 and to change the Enabled status of the USK 0 on M/E 0") + print("Type 1 or 0 and to change the Enabled status of the USK 1 on M/E 0") } connection.whenDisconnected = {