Skip to content

Commit

Permalink
ARC support, refactoring feedback and multi-switcher support
Browse files Browse the repository at this point in the history
  • Loading branch information
SteffeyDev committed Feb 8, 2021
1 parent 765e05d commit 25b7b47
Show file tree
Hide file tree
Showing 17 changed files with 279 additions and 217 deletions.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ All addresses must start with `/atem/`. atemOSC will ignore all OSC commands it

### Multi-switcher support

By default, all commands will be sent to the first connected switcher. If you connect multiple switchers to atemOSC, you will need to provide a nickname for each switcher and use that nickname in the address to specify which switcher to send the command to.
If you only want to connect to a single ATEM switcher, leave the nickname field blank and use the addresses below as normal. By default, all commands without a nickname will be sent to the first switcher with no nickname.

If you connect multiple switchers to atemOSC, you will need to provide a nickname for each switcher and use that nickname in the address to specify which switcher to send the command to. If you add a nickname to a switcher, you **must** send the nickname in the address, and all feedback messages will contain the nickname in the address.

For example, `/atem/my-switcher-1/transition/auto` will trigger an automatic transition on the switcher whose nickname is `my-switcher-1`

Expand Down Expand Up @@ -236,6 +238,7 @@ Supports both standard and Fairlight audio mixers.
- **Change Mix Option for Audio Input $i** `/atem/audio/input/$i/mix <string>`
- Where `<string>` is 'on', 'off', or 'afv' (audio follow video)
- e.g. `/atem/audio/input/2/mix 'afv'`
- Also supports sending mix option in address (e.g. `/atem/audio/input/$i/mix/afv`)
- For Fairlight audio input in dual mono mode, will set mix option for both left & right. To control the left and right channels individually, use the addresses `/atem/audio/input/$i/left/mix` and `/atem/audio/input/$i/right/mix`.
- **Change Gain for Audio Output (Mix)** `/atem/audio/output/gain $x`
- Where `$x` is the gain in decibels (dB), ranging from `-60` to `6`
Expand Down Expand Up @@ -355,6 +358,14 @@ A lot of MIDI controls send two signals when a button is pressed, one signal whe
#### Solution
Tune your MIDI software to send only one of the two signals, either ok button press (rising edge) or button release (falling edge). See [#120](https://github.com/SteffeyDev/atemOSC/issues/120) for instructions for OSCulator.

### I want to send feedback messages to multiple devices with different IP address

#### Problem
Occasionally, you may want to send output messages to many devices on the same network, but this does not seem possible because the feedback IP address field only accepts one IP address

#### Solution
Set the IP address to be the broadcast address for your network. This will cause feedback messages to be sent to every device on the network. For a typical network, the broadcast address is calculated by replacing the last octet with `255` (e.g. for a `192.168.1.x` network, the broadcast address is `192.168.1.255`). However, the broadcast address may be different if the subnet mask is not `255.255.255.0`. You may be able to use [this subnet calculator](https://remotemonitoringsystems.ca/broadcast.php) to calculate the broadcast address for your network.

-----------

## Contributing
Expand All @@ -371,6 +382,14 @@ I welcome pull requests, but recommend that you open an issue first so that we c

## Developer Resources

### Build and run app locally

1. Download and install XCode
2. Clone repository or download the repository ZIP
3. Double click the .xcworkspace file to open in XCode
4. Click on the project, go to the "Signing & Capabilities" tab, change the Team to your personal team, and change Signing Certificate to “Sign to Run Locally”
5. Click the play button in the top left to run

### Find what line a crash occured on given a crash report (on MacOS)

People like to send crash reports in issues. You can use this method to find out which line of the program crashed from just the crash report and version number.
Expand Down
15 changes: 5 additions & 10 deletions atemOSC/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@

#import <Cocoa/Cocoa.h>

#import "FeedbackMonitors.h"
#import "OSCEndpoint.h"
#import "Window.h"
#import "Switcher.h"

@class OSCAddressPanel;
@class OSCReceiver;

@interface AppDelegate : NSObject <NSApplicationDelegate>
Expand All @@ -46,16 +44,13 @@
Window* window;
}

@property (strong) id activity;
@property (retain) id activity;
@property (assign) BOOL isActive;


@property(nonatomic, retain) NSMutableArray<OSCEndpoint *> *endpoints;
@property (assign, readonly) OSCInPort* inPort;
@property (assign, readonly) OSCManager* manager;
@property (assign, readonly) IBMDSwitcherDiscovery* mSwitcherDiscovery;
@property(nonatomic, retain) NSMutableArray* switchers;

@property (retain) NSMutableArray<OSCEndpoint *>* endpoints;
@property (retain) OSCInPort* inPort;
@property (retain) OSCManager* manager;
@property (retain) NSMutableArray* switchers;

- (void)incomingPortChanged:(int)inPortValue;
- (IBAction)githubPageButtonPressed:(id)sender;
Expand Down
24 changes: 12 additions & 12 deletions atemOSC/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ @implementation AppDelegate
@synthesize endpoints;
@synthesize inPort;
@synthesize manager;
@synthesize mSwitcherDiscovery;
@synthesize switchers;
@synthesize isActive;

Expand Down Expand Up @@ -66,11 +65,12 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
[self addSwitcher];
}

mSwitcherDiscovery = CreateBMDSwitcherDiscoveryInstance();
if (!mSwitcherDiscovery)
// Create switcher discovery instance here just to check if SDK is working
IBMDSwitcherDiscovery *switcherDiscovery = CreateBMDSwitcherDiscoveryInstance();
if (!switcherDiscovery)
{
NSBeginAlertSheet(@"Could not create Switcher Discovery Instance.\nATEM Switcher Software may not be installed.\n",
@"OK", nil, nil, window, self, @selector(sheetDidEndShouldTerminate:returnCode:contextInfo:), NULL, window, @"");
@"OK", nil, nil, window, self, @selector(sheetDidEndShouldTerminate:returnCode:contextInfo:), nil, nil, @"");
}
else
{
Expand Down Expand Up @@ -105,21 +105,21 @@ - (void)applicationWillBecomeActive:(NSNotification *)notification
Window *window = (Window *) [[NSApplication sharedApplication] mainWindow];
self->window = window;
}
[window loadSettingsFromPreferences];
[self->window loadSettingsFromPreferences];

if ([[window connectionView] switcher] != nil)
if ([[self->window connectionView] switcher] != nil)
{
[[window outlineView] refreshList];
[[window connectionView] loadFromSwitcher:[[window connectionView] switcher]];
[[self->window outlineView] refreshList];
[[self->window connectionView] loadFromSwitcher:[[self->window connectionView] switcher]];
}
else
{
[[window outlineView] reloadData];
[[self->window outlineView] reloadData];
NSIndexSet* indexes = [[NSIndexSet alloc] initWithIndex:1];
[[window outlineView] selectRowIndexes:indexes byExtendingSelection:NO];
[[self->window outlineView] selectRowIndexes:indexes byExtendingSelection:NO];
}

[[window logView] flushMessages];
[[self->window logView] flushMessages];
});
}

Expand Down Expand Up @@ -206,7 +206,7 @@ - (void) addSwitcher
Switcher *newSwitcher = [[Switcher alloc] init];
[newSwitcher setAppDelegate:self];
CFUUIDRef UUID = CFUUIDCreate(kCFAllocatorDefault);
[newSwitcher setUid: (NSString *) CFUUIDCreateString(kCFAllocatorDefault,UUID)];
[newSwitcher setUid: (NSString *) CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault,UUID))];
[newSwitcher saveChanges];
[switchers addObject:newSwitcher];

Expand Down
17 changes: 16 additions & 1 deletion atemOSC/ConnectionView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,26 @@ - (void)controlTextDidEndEditing:(NSNotification *)notification
{
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Invalid IP Adress"];
[alert setInformativeText:@"Please enter a valid IPv4 Address for 'OSC Out IP Address'"];
[alert setInformativeText:@"Please enter a valid IPv4 Address"];
[alert beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] completionHandler:nil];
return;
}

if (textField == feedbackIpAddressTextField || textField == feedbackPortTextField)
{
AppDelegate* appDel = (AppDelegate *) [[NSApplication sharedApplication] delegate];
if ([[feedbackIpAddressTextField stringValue] isEqualToString:@"127.0.0.1"] && [feedbackPortTextField intValue] == [[appDel inPort] port])
{
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Invalid Feedback Address"];
[alert setInformativeText:@"Can't send feedback to localhost on the same port atemOSC is listening on"];
[alert beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] completionHandler:nil];
[feedbackPortTextField setIntValue:switcher.feedbackPort];
[feedbackIpAddressTextField setStringValue:switcher.feedbackIpAddress];
return;
}
}

if (textField == feedbackIpAddressTextField)
{
[switcher setFeedbackIpAddress: [textField stringValue]];
Expand Down
4 changes: 2 additions & 2 deletions atemOSC/FeedbackMonitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class FairlightAudioInputMonitor : public GenericMonitor<IBMDSwitcherFairlightAu
public:
FairlightAudioInputMonitor(Switcher *switcher, BMDSwitcherAudioInputId inputId) : GenericMonitor(switcher), inputId_(inputId) { }
HRESULT STDMETHODCALLTYPE Notify (BMDSwitcherFairlightAudioInputEventType eventType);
float sendStatus() const {};
float sendStatus() const { return 0.0; };

protected:
virtual ~FairlightAudioInputMonitor() { }
Expand Down Expand Up @@ -284,7 +284,7 @@ class HyperDeckMonitor : public GenericMonitor<IBMDSwitcherHyperDeckCallback>, p
public:
HyperDeckMonitor(Switcher *switcher, BMDSwitcherHyperDeckId hyperdeckId) : GenericMonitor(switcher), hyperdeckId_(hyperdeckId) { }
HRESULT Notify(BMDSwitcherHyperDeckEventType eventType);
HRESULT NotifyError(BMDSwitcherHyperDeckErrorType eventType) { }
HRESULT NotifyError(BMDSwitcherHyperDeckErrorType eventType) { return 1; }
float sendStatus() const;

protected:
Expand Down
18 changes: 9 additions & 9 deletions atemOSC/FeedbackMonitors.mm
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@
{
// Have to delay slightly, otherwise fetch gets old name
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
NSString *name;
switcher.mInputs[inputId_]->GetLongName((CFStringRef*)&name);
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/input/%lld/long-name", inputId_], [OSCValue createWithString:name]);
CFStringRef name;
switcher.mInputs[inputId_]->GetLongName(&name);
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/input/%lld/long-name", inputId_], [OSCValue createWithString:(__bridge NSString*)name]);
});
}
}
Expand All @@ -201,9 +201,9 @@
{
// Have to delay slightly, otherwise fetch gets old name
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
NSString *name;
switcher.mInputs[inputId_]->GetShortName((CFStringRef*)&name);
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/input/%lld/short-name", inputId_], [OSCValue createWithString:name]);
CFStringRef name;
switcher.mInputs[inputId_]->GetShortName(&name);
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/input/%lld/short-name", inputId_], [OSCValue createWithString:(__bridge NSString*)name]);

});
}
Expand Down Expand Up @@ -878,7 +878,7 @@
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/audio/input/%lld/gain", inputId_], [OSCValue createWithFloat:(float)gain]);

NSString *address = @"/audio/input/%lld/left/gain";
if (sourceId_ == switcher.mFairlightAudioSources[inputId_].end()->first)
if (sourceId_ == std::prev(switcher.mFairlightAudioSources[inputId_].end())->first)
address = @"/audio/input/%lld/right/gain";
sendFeedbackMessage(switcher, [NSString stringWithFormat:address, inputId_], [OSCValue createWithFloat:(float)gain]);
}
Expand All @@ -894,7 +894,7 @@
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/audio/input/%lld/balance", inputId_], [OSCValue createWithFloat:(float)pan]);

NSString *address = @"/audio/input/%lld/left/balance";
if (sourceId_ == switcher.mFairlightAudioSources[inputId_].end()->first)
if (sourceId_ == std::prev(switcher.mFairlightAudioSources[inputId_].end())->first)
address = @"/audio/input/%lld/right/balance";
sendFeedbackMessage(switcher, [NSString stringWithFormat:address, inputId_], [OSCValue createWithFloat:(float)pan]);
}
Expand All @@ -918,7 +918,7 @@
sendFeedbackMessage(switcher, [NSString stringWithFormat:@"/audio/input/%lld/mix", inputId_], [OSCValue createWithString:mixOptionString]);

NSString *address = @"/audio/input/%lld/left/mix";
if (sourceId_ == switcher.mFairlightAudioSources[inputId_].end()->first)
if (sourceId_ == std::prev(switcher.mFairlightAudioSources[inputId_].end())->first)
address = @"/audio/input/%lld/right/mix";
sendFeedbackMessage(switcher, [NSString stringWithFormat:address, inputId_], [OSCValue createWithString:mixOptionString]);
}
Expand Down
2 changes: 1 addition & 1 deletion atemOSC/LogView.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
- (IBAction)debugChanged:(id)sender;


-(void)flushMessages;
- (void)flushMessages;
- (void)logMessage:(NSString *)message toForeground:(BOOL)active;

@end
Expand Down
1 change: 0 additions & 1 deletion atemOSC/LogView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ - (void)logMessage:(NSString *)message toForeground:(BOOL)active
[formatter setDateFormat:@"HH:mm:ss"];

NSString *messageWithNewLine = [NSString stringWithFormat:@"[%@] %@\n", [formatter stringFromDate:now], message];
[formatter release];
NSMutableAttributedString *attributedMessage = [[NSMutableAttributedString alloc]initWithString:messageWithNewLine];

[fullLog appendString:messageWithNewLine];
Expand Down
Loading

0 comments on commit 25b7b47

Please sign in to comment.