diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib b/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib index 2f3e6e302..3385e40c0 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib @@ -28,7 +28,7 @@ - + @@ -43,7 +43,7 @@ - + @@ -58,7 +58,7 @@ - + @@ -73,7 +73,7 @@ - + diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index b3b6330c6..b04ae9304 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -304,7 +304,15 @@ class MachineDocument: } // MARK: Activity display. - fileprivate var activityLevelIndicators: [String: NSLevelIndicator] = [:] + class LED { + let levelIndicator: NSLevelIndicator + init(levelIndicator: NSLevelIndicator) { + self.levelIndicator = levelIndicator + } + var isLit = false + var isBlinking = false + } + fileprivate var leds: [String: LED] = [:] func setupActivityDisplay() { var leds = machine.leds if leds.count > 0 { @@ -337,9 +345,39 @@ class MachineDocument: activityIndicators[c].removeFromSuperview() } - // Apply labels. + // Apply labels and create leds entries. for c in 0 ..< leds.count { textFields[c].stringValue = leds[c] + self.leds[leds[c]] = LED(levelIndicator: activityIndicators[c]) + } + } + } + + func machine(_ machine: CSMachine, ledShouldBlink ledName: String) { + // If there is such an LED, switch it off for 0.03 of a second; if it's meant + // to be off at the end of that, leave it off. Don't allow the blinks to + // pile up — allow there to be only one in flight at a time. + if let led = leds[ledName] { + DispatchQueue.main.async { + if !led.isBlinking { + led.levelIndicator.floatValue = 0.0 + led.isBlinking = true + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) { + led.levelIndicator.floatValue = led.isLit ? 1.0 : 0.0 + led.isBlinking = false + } + } + } + } + } + + func machine(_ machine: CSMachine, led ledName: String, didChangeToLit isLit: Bool) { + // If there is such an LED, switch it appropriately. + if let led = leds[ledName] { + DispatchQueue.main.async { + led.levelIndicator.floatValue = isLit ? 1.0 : 0.0 + led.isLit = isLit } } } diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h index 670a446ce..0f6bb7636 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.h +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.h @@ -16,6 +16,8 @@ @class CSMachine; @protocol CSMachineDelegate - (void)machineSpeakerDidChangeInputClock:(nonnull CSMachine *)machine; +- (void)machine:(nonnull CSMachine *)machine led:(nonnull NSString *)led didChangeToLit:(BOOL)isLit; +- (void)machine:(nonnull CSMachine *)machine ledShouldBlink:(nonnull NSString *)led; @end typedef NS_ENUM(NSInteger, CSMachineVideoSignal) { diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 910773d5a..ee3335573 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -61,9 +61,11 @@ struct ActivityObserver: public Activity::Observer { } void set_led_status(const std::string &name, bool lit) override { + [machine.delegate machine:machine led:[NSString stringWithUTF8String:name.c_str()] didChangeToLit:lit]; } void announce_drive_event(const std::string &name, DriveEvent event) override { + [machine.delegate machine:machine ledShouldBlink:[NSString stringWithUTF8String:name.c_str()]]; } void set_drive_motor_status(const std::string &name, bool is_on) override {