Skip to content

Commit

Permalink
Issue #13/#17 - Adding DSK & USK monitoring and feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
SteffeyDev committed Sep 25, 2017
1 parent 71b2d0f commit a164afb
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 92 deletions.
7 changes: 7 additions & 0 deletions atemOSC/SwitcherPanelAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

class MixEffectBlockMonitor;
class SwitcherMonitor;
class DownstreamKeyerMonitor;
class TransitionParametersMonitor;
class InputMonitor;

@interface SwitcherPanelAppDelegate : NSObject <NSApplicationDelegate, OSCDelegateProtocol, NSTextFieldDelegate>
Expand All @@ -52,6 +54,8 @@ class InputMonitor;
IBMDSwitcherTransitionParameters* switcherTransitionParameters;
IBMDSwitcherKeyFlyParameters* mDVEControl;
SwitcherMonitor* mSwitcherMonitor;
DownstreamKeyerMonitor* mDownstreamKeyerMonitor;
TransitionParametersMonitor* mTransitionParametersMonitor;
IBMDSwitcherMediaPool* mMediaPool;
IBMDSwitcherStills* mStills;
IBMDSwitcherInputSuperSource* mSuperSource;
Expand Down Expand Up @@ -118,6 +122,9 @@ class InputMonitor;
- (void)updateTransitionFramesTextField;
- (void)updateFTBFramesTextField;
- (void)mixEffectBlockBoxSetEnabled:(bool)enabled;
- (void)updateUSKTie;
- (void)updateDSKOnAir;
- (void)updateDSKTie;


// Serial Port Methods
Expand Down
233 changes: 141 additions & 92 deletions atemOSC/SwitcherPanelAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@
return CFEqual(&iid1, &iid2);
}

// Callback class for monitoring property changes on a mix effect block.
class MixEffectBlockMonitor : public IBMDSwitcherMixEffectBlockCallback
template <class T=IUnknown>
class GenericMonitor : public T
{
public:
MixEffectBlockMonitor(SwitcherPanelAppDelegate* uiDelegate) : mUiDelegate(uiDelegate), mRefCount(1) { }
GenericMonitor(SwitcherPanelAppDelegate* uiDelegate) : mUiDelegate(uiDelegate), mRefCount(1) { }

protected:
virtual ~MixEffectBlockMonitor() { }
virtual ~GenericMonitor() { }
SwitcherPanelAppDelegate* mUiDelegate;

public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
Expand All @@ -53,14 +54,14 @@ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)

if (iid == IID_IBMDSwitcherMixEffectBlockCallback)
{
*ppv = static_cast<IBMDSwitcherMixEffectBlockCallback*>(this);
*ppv = static_cast<T*>(this);
AddRef();
return S_OK;
}

if (CFEqual(&iid, IUnknownUUID))
{
*ppv = static_cast<IUnknown*>(this);
*ppv = static_cast<T*>(this);
AddRef();
return S_OK;
}
Expand All @@ -82,6 +83,20 @@ ULONG STDMETHODCALLTYPE Release(void)
return newCount;
}

private:
int mRefCount;
};

// Callback class for monitoring property changes on a mix effect block.
class MixEffectBlockMonitor : public GenericMonitor<IBMDSwitcherMixEffectBlockCallback>
{
public:
MixEffectBlockMonitor(SwitcherPanelAppDelegate* uiDelegate) : GenericMonitor(uiDelegate) { }

protected:
virtual ~MixEffectBlockMonitor() { }

public:
HRESULT PropertyChanged(BMDSwitcherMixEffectBlockPropertyId propertyId)
{
switch (propertyId)
Expand Down Expand Up @@ -109,68 +124,88 @@ HRESULT PropertyChanged(BMDSwitcherMixEffectBlockPropertyId propertyId)
}
return S_OK;
}

private:
SwitcherPanelAppDelegate* mUiDelegate;
int mRefCount;
};

// Monitor the properties on Switcher Inputs.
// In this sample app we're only interested in changes to the Long Name property to update the PopupButton list
class InputMonitor : public IBMDSwitcherInputCallback
class DownstreamKeyerMonitor : public GenericMonitor<IBMDSwitcherDownstreamKeyCallback>
{
public:
InputMonitor(IBMDSwitcherInput* input, SwitcherPanelAppDelegate* uiDelegate) : mInput(input), mUiDelegate(uiDelegate), mRefCount(1)
{
mInput->AddRef();
mInput->AddCallback(this);
}
DownstreamKeyerMonitor(SwitcherPanelAppDelegate* uiDelegate) : GenericMonitor(uiDelegate) { }

protected:
~InputMonitor()
{
mInput->RemoveCallback(this);
mInput->Release();
}
virtual ~DownstreamKeyerMonitor() { }

public:
// IBMDSwitcherInputCallback interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
HRESULT Notify (BMDSwitcherDownstreamKeyEventType eventType)
{
if (!ppv)
return E_POINTER;

if (iid == IID_IBMDSwitcherInputCallback)
switch (eventType)
{
*ppv = static_cast<IBMDSwitcherInputCallback*>(this);
AddRef();
return S_OK;
case bmdSwitcherDownstreamKeyEventTypeTieChanged:
[mUiDelegate performSelectorOnMainThread:@selector(updateDSKTie) withObject:nil waitUntilDone:YES];
break;
case bmdSwitcherDownstreamKeyEventTypeOnAirChanged:
[mUiDelegate performSelectorOnMainThread:@selector(updateDSKOnAir) withObject:nil waitUntilDone:YES];
break;
case bmdSwitcherDownstreamKeyEventTypeIsTransitioningChanged:
// Might want to do something with this down the road
break;
case bmdSwitcherDownstreamKeyEventTypeIsAutoTransitioningChanged:
// Might want to do something with this down the road
break;
default:
// ignore other property changes not used for this app
break;
}
return S_OK;
}
};

class TransitionParametersMonitor : public GenericMonitor<IBMDSwitcherTransitionParametersCallback>
{
public:
TransitionParametersMonitor(SwitcherPanelAppDelegate* uiDelegate) : GenericMonitor(uiDelegate) { }

protected:
virtual ~TransitionParametersMonitor() { }

public:
HRESULT Notify (BMDSwitcherTransitionParametersEventType eventType)
{

if (CFEqual(&iid, IUnknownUUID))
switch (eventType)
{
*ppv = static_cast<IUnknown*>(this);
AddRef();
return S_OK;
case bmdSwitcherTransitionParametersEventTypeNextTransitionSelectionChanged:
[mUiDelegate performSelectorOnMainThread:@selector(updateUSKTie) withObject:nil waitUntilDone:YES];
break;
case bmdSwitcherTransitionParametersEventTypeTransitionSelectionChanged:
[mUiDelegate performSelectorOnMainThread:@selector(updateUSKTie) withObject:nil waitUntilDone:YES];
break;
default:
// ignore other property changes not used for this app
break;
}

*ppv = NULL;
return E_NOINTERFACE;
return S_OK;
}

ULONG STDMETHODCALLTYPE AddRef(void)
};

// Monitor the properties on Switcher Inputs.
// In this sample app we're only interested in changes to the Long Name property to update the PopupButton list
class InputMonitor : public GenericMonitor<IBMDSwitcherInputCallback>
{
public:
InputMonitor(IBMDSwitcherInput* input, SwitcherPanelAppDelegate* uiDelegate) : mInput(input), GenericMonitor(uiDelegate)
{
return ::OSAtomicIncrement32(&mRefCount);
mInput->AddRef();
mInput->AddCallback(this);
}

ULONG STDMETHODCALLTYPE Release(void)
protected:
~InputMonitor()
{
int newCount = ::OSAtomicDecrement32(&mRefCount);
if (newCount == 0)
delete this;
return newCount;
mInput->RemoveCallback(this);
mInput->Release();
}

public:
HRESULT Notify(BMDSwitcherInputEventType eventType)
{
switch (eventType)
Expand All @@ -187,57 +222,18 @@ HRESULT Notify(BMDSwitcherInputEventType eventType)

private:
IBMDSwitcherInput* mInput;
SwitcherPanelAppDelegate* mUiDelegate;
int mRefCount;
};

// Callback class to monitor switcher disconnection
class SwitcherMonitor : public IBMDSwitcherCallback
class SwitcherMonitor : public GenericMonitor<IBMDSwitcherCallback>
{
public:
SwitcherMonitor(SwitcherPanelAppDelegate* uiDelegate) : mUiDelegate(uiDelegate), mRefCount(1) { }
SwitcherMonitor(SwitcherPanelAppDelegate* uiDelegate) : GenericMonitor(uiDelegate) { }

protected:
virtual ~SwitcherMonitor() { }

public:
// IBMDSwitcherCallback interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
{
if (!ppv)
return E_POINTER;

if (iid == IID_IBMDSwitcherCallback)
{
*ppv = static_cast<IBMDSwitcherCallback*>(this);
AddRef();
return S_OK;
}

if (CFEqual(&iid, IUnknownUUID))
{
*ppv = static_cast<IUnknown*>(this);
AddRef();
return S_OK;
}

*ppv = NULL;
return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE AddRef(void)
{
return ::OSAtomicIncrement32(&mRefCount);
}

ULONG STDMETHODCALLTYPE Release(void)
{
int newCount = ::OSAtomicDecrement32(&mRefCount);
if (newCount == 0)
delete this;
return newCount;
}

// Switcher events ignored by this sample app
HRESULT STDMETHODCALLTYPE Notify(BMDSwitcherEventType eventType, BMDSwitcherVideoMode coreVideoMode)
{
Expand All @@ -247,10 +243,6 @@ HRESULT STDMETHODCALLTYPE Notify(BMDSwitcherEventType eventType, BMDSwitcherVide
}
return S_OK;
}

private:
SwitcherPanelAppDelegate* mUiDelegate;
int mRefCount;
};

@implementation SwitcherPanelAppDelegate
Expand All @@ -275,6 +267,8 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
isConnectedToATEM = NO;

mSwitcherMonitor = new SwitcherMonitor(self);
mDownstreamKeyerMonitor = new DownstreamKeyerMonitor(self);
mTransitionParametersMonitor = new TransitionParametersMonitor(self);
mMixEffectBlockMonitor = new MixEffectBlockMonitor(self);

mMoveSliderDownwards = false;
Expand Down Expand Up @@ -1139,6 +1133,7 @@ - (void)switcherConnected
{
while (S_OK == dskIterator->Next(&downstreamKey)) {
dsk.push_back(downstreamKey);
downstreamKey->AddCallback(mDownstreamKeyerMonitor);
}
}
dskIterator->Release();
Expand Down Expand Up @@ -1202,6 +1197,7 @@ - (void)switcherConnected

switcherTransitionParameters = NULL;
mMixEffectBlock->QueryInterface(IID_IBMDSwitcherTransitionParameters, (void**)&switcherTransitionParameters);
switcherTransitionParameters->AddCallback(mTransitionParametersMonitor);


mMixEffectBlock->AddCallback(mMixEffectBlockMonitor);
Expand Down Expand Up @@ -1295,6 +1291,7 @@ - (void)cleanUpConnection
while (dsk.size())
{
dsk.back()->Release();
dsk.back()->RemoveCallback(mDownstreamKeyerMonitor);
dsk.pop_back();
}

Expand All @@ -1312,6 +1309,11 @@ - (void)cleanUpConnection
mSwitcher->Release();
mSwitcher = NULL;
}

if (switcherTransitionParameters)
{
switcherTransitionParameters->RemoveCallback(mTransitionParametersMonitor);
}
}

- (BOOL)isMacroValid:(uint32_t)index
Expand Down Expand Up @@ -1544,6 +1546,53 @@ - (void)updatePreviewButtonSelection
[self activateChannel:previewId isProgram:NO];
}

// Send OSC messages out when DSK Tie is changed on switcher
- (void)updateDSKTie
{
int i = 1;
for(std::list<IBMDSwitcherDownstreamKey*>::iterator iter = dsk.begin(); iter != dsk.end(); iter++) {
IBMDSwitcherDownstreamKey * key = *iter;
bool isTied;
key->GetTie(&isTied);

OSCMessage *newMsg = [OSCMessage createWithAddress:[NSString stringWithFormat:@"/atem/dsk/set-tie/%d",i++]];
[newMsg addInt: isTied];
[outPort sendThisMessage:newMsg];
}
}

// Send OSC messages out when DSK On Air is changed on switcher
- (void)updateDSKOnAir
{
int i = 1;
for(std::list<IBMDSwitcherDownstreamKey*>::iterator iter = dsk.begin(); iter != dsk.end(); i++, iter++) {
IBMDSwitcherDownstreamKey * key = *iter;
bool isOnAir;
key->GetOnAir(&isOnAir);

OSCMessage *newMsg = [OSCMessage createWithAddress:[NSString stringWithFormat:@"/atem/dsk/on-air/%d",i]];
[newMsg addInt: isOnAir];
[outPort sendThisMessage:newMsg];
}
}

// Send OSC messages out when USK Tie is changed on switcher
- (void)updateUSKTie
{
uint32_t transitionSelections[5] = { bmdSwitcherTransitionSelectionBackground, bmdSwitcherTransitionSelectionKey1, bmdSwitcherTransitionSelectionKey2, bmdSwitcherTransitionSelectionKey3, bmdSwitcherTransitionSelectionKey4 };

uint32_t currentTransitionSelection;
switcherTransitionParameters->GetNextTransitionSelection(&currentTransitionSelection);

for (int i = 0; i <= ((int) keyers.size()); i++) {
uint32_t requestedTransitionSelection = transitionSelections[i];

OSCMessage *newMsg = [OSCMessage createWithAddress:[NSString stringWithFormat:@"/atem/nextusk/%d",i]];
[newMsg addInt: ((requestedTransitionSelection & currentTransitionSelection) == requestedTransitionSelection)];
[outPort sendThisMessage:newMsg];
}
}

- (void)updateInTransitionState
{
bool inTransition;
Expand Down

0 comments on commit a164afb

Please sign in to comment.