Skip to content

Commit 88a594d

Browse files
authored
Merge pull request #29 from dsmurfin/should-output
Should output
2 parents 5c45cc9 + 362aec4 commit 88a594d

File tree

1 file changed

+69
-30
lines changed

1 file changed

+69
-30
lines changed

Sources/sACNKit/Source/sACNSource.swift

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,35 @@ final public class sACNSource {
5555

5656
/// Whether this source should actively output sACN Universe Discovery and Data messages.
5757
/// This may be useful for backup scenarios to ensure the source is ready to output as soon as required.
58-
///
59-
/// Calling this before `startOutput()` will have no effect.
6058
public var shouldOutput: Bool {
6159
get { socketDelegateQueue.sync { _shouldOutput } }
62-
set { socketDelegateQueue.sync { _shouldOutput = newValue } }
6360
}
6461

6562
/// The private state of should output.
6663
private var _shouldOutput: Bool
6764

65+
/// Updates whether this source source should actively output sACN Universe Discovery and Data messages.
66+
///
67+
/// This may be useful for backup scenarios to ensure the source is ready to output as soon as required.
68+
///
69+
/// Calling this before `startOutput()` will have no effect.
70+
///
71+
/// - Parameters:
72+
/// - output: Whether the source should output.
73+
///
74+
public func shouldOutput(_ output: Bool) {
75+
socketDelegateQueue.sync {
76+
guard _shouldOutput != output else { return }
77+
if output {
78+
universes.forEach { $0.reset() }
79+
} else {
80+
// terminate all universes on all sockets, but keep the sockets and universes present
81+
universes.forEach { $0.terminate(remove: false) }
82+
}
83+
_shouldOutput = output
84+
}
85+
}
86+
6887
// MARK: Delegate
6988

7089
/// Changes the source delegate of this source to the the object passed.
@@ -303,13 +322,18 @@ final public class sACNSource {
303322
if existingInterfaces.isEmpty {
304323
// not possible for IPv6
305324

306-
// terminate all universes on existing sockets, removing the sockets but not the universes
307-
let socketIds = sockets.reduce(into: [String: Bool]()) { dict, socket in
308-
dict[socket.key] = true
309-
}
310-
socketsShouldTerminate = socketIds
311-
universes.forEach { universe in
312-
universe.terminateSockets()
325+
if universes.isEmpty || !_isListening {
326+
// deinit first stops listening
327+
sockets.removeAll()
328+
} else {
329+
// terminate all universes on existing sockets, removing the sockets but not the universes
330+
let socketIds = sockets.reduce(into: [String: Bool]()) { dict, socket in
331+
dict[socket.key] = true
332+
}
333+
socketsShouldTerminate = socketIds
334+
universes.forEach { universe in
335+
universe.terminateSockets()
336+
}
313337
}
314338

315339
// add each new interfaces
@@ -326,13 +350,18 @@ final public class sACNSource {
326350
} else if newInterfaces.isEmpty {
327351
// not possible for IPv6
328352

329-
// terminate all universes on existing sockets, removing the sockets but not the universes
330-
let socketIds = sockets.reduce(into: [String: Bool]()) { dict, socket in
331-
dict[socket.key] = true
332-
}
333-
socketsShouldTerminate = socketIds
334-
universes.forEach { universe in
335-
universe.terminateSockets()
353+
if universes.isEmpty || !_isListening {
354+
// deinit first stops listening
355+
sockets.removeAll()
356+
} else {
357+
// terminate all universes on existing sockets, removing the sockets but not the universes
358+
let socketIds = sockets.reduce(into: [String: Bool]()) { dict, socket in
359+
dict[socket.key] = true
360+
}
361+
socketsShouldTerminate = socketIds
362+
universes.forEach { universe in
363+
universe.terminateSockets()
364+
}
336365
}
337366

338367
// add socket for all interfaces
@@ -351,12 +380,19 @@ final public class sACNSource {
351380
// terminate all universes on sockets no longer needed, removing the sockets but not the universes
352381
let socketsToRemove = sockets.filter { interfacesToRemove.contains($0.key) }
353382
if !socketsToRemove.isEmpty {
354-
let socketIds = socketsToRemove.reduce(into: [String: Bool]()) { dict, socket in
355-
dict[socket.key] = true
356-
}
357-
socketsShouldTerminate = socketIds
358-
universes.forEach { universe in
359-
universe.terminateSockets()
383+
if universes.isEmpty || !_isListening {
384+
for socketToRemove in socketsToRemove.keys {
385+
// deinit first stops listening
386+
sockets.removeValue(forKey: socketToRemove)
387+
}
388+
} else {
389+
let socketIds = socketsToRemove.reduce(into: [String: Bool]()) { dict, socket in
390+
dict[socket.key] = true
391+
}
392+
socketsShouldTerminate = socketIds
393+
universes.forEach { universe in
394+
universe.terminateSockets()
395+
}
360396
}
361397
}
362398

@@ -756,8 +792,6 @@ private extension sACNSource {
756792

757793
/// Sends the data messages for this source.
758794
private func sendDataMessages() {
759-
guard _shouldOutput else { return }
760-
761795
// remove all universes which are full terminated and should be removed
762796
let universesToRemove = universes.filter { $0.removeAfterTerminate && $0.shouldTerminate && $0.dirtyCounter < 1 }
763797
let universesReadyForSocketRemoval = universes.filter { $0.pendingSocketRemoval && $0.dirtyCounter < 1 }
@@ -848,7 +882,6 @@ private extension sACNSource {
848882
let dmpLayer = universe.dmpLevelsLayer
849883

850884
let levels = rootLayer+framingLayer+dmpLayer
851-
universeMessages.append((universeNumber: universe.number, data: levels))
852885

853886
if !socketsShouldTerminate.isEmpty {
854887
let framingOptions: DataFramingLayer.Options = [.terminated]
@@ -859,7 +892,10 @@ private extension sACNSource {
859892
socketTerminationMessages.append((universeNumber: universe.number, data: levels))
860893
}
861894

862-
universe.incrementSequence()
895+
if _shouldOutput || (universe.shouldTerminate && universe.dirtyCounter > 0) {
896+
universeMessages.append((universeNumber: universe.number, data: levels))
897+
universe.incrementSequence()
898+
}
863899
universe.decrementDirty()
864900
}
865901

@@ -871,17 +907,20 @@ private extension sACNSource {
871907
let dmpLayer = universe.dmpPrioritiesLayer
872908

873909
let priorities = rootLayer+framingLayer+dmpLayer
874-
universeMessages.append((universeNumber: universe.number, data: priorities))
875910

876-
universe.incrementSequence()
877-
universe.prioritySent()
911+
if _shouldOutput || (universe.shouldTerminate && universe.dirtyCounter > 0) {
912+
universeMessages.append((universeNumber: universe.number, data: priorities))
913+
universe.incrementSequence()
914+
universe.prioritySent()
915+
}
878916
}
879917

880918
universe.incrementCounter()
881919
}
882920

883921
sockets.forEach { interface, socket in
884922
let messages = socketsShouldTerminate[interface] != nil ? socketTerminationMessages : universeMessages
923+
885924
for universeMessage in messages {
886925
if ipMode.usesIPv4() {
887926
let hostname = IPv4.multicastHostname(for: universeMessage.universeNumber)

0 commit comments

Comments
 (0)