Skip to content

Commit

Permalink
#162 Streaming control
Browse files Browse the repository at this point in the history
  • Loading branch information
SteffeyDev committed Apr 24, 2021
1 parent aef8d13 commit 43f5152
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 3 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,14 @@ Feedback: Enabled for `clip`, `clip-time`, `timeline-time`, `state`, `single-cli
- **Switch which external media disk is used for recording** `/atem/recording/switch-disk`
- **Change recording filename** `/atem/recording/filename <string>`

Feedback: Recording state sent to address `/atem/recording/state`, will contain a string that is one of `idle` | `recording` | `stopping`
Feedback: Recording state sent to address `/atem/recording/state`, will contain a string that is one of `idle` | `recording` | `stopping` | `error`

### Streaming

- **Start Streaming** `/atem/stream/start`
- **Stop Streaming** `/atem/stream/stop`

Feedback: Stream state sent to address `/atem/stream/state`, will contain a string that is one of `idle` | `connecting` | `streaming` | `stopping` | `error`

### Other

Expand Down
18 changes: 17 additions & 1 deletion atemOSC/FeedbackMonitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class RecordAVMonitor : public GenericMonitor<IBMDSwitcherRecordAVCallback>, pub
RecordAVMonitor(Switcher *switcher) : GenericMonitor(switcher) { }
HRESULT NotifyStatus(BMDSwitcherRecordAVState stateType, BMDSwitcherRecordAVError error);
// Ignore these three, don't want to use them yet
HRESULT Notify(BMDSwitcherRecordAVEventType eventTye) { return S_OK; };
HRESULT Notify(BMDSwitcherRecordAVEventType eventType) { return S_OK; };
HRESULT NotifyWorkingSetChange(uint32_t workingSetIndex, BMDSwitcherRecordDiskId diskId) { return S_OK; };
HRESULT NotifyDiskAvailability(BMDSwitcherRecordDiskAvailabilityEventType eventType, BMDSwitcherRecordDiskId diskId) { return S_OK; };
float sendStatus() const;
Expand All @@ -347,4 +347,20 @@ class RecordAVMonitor : public GenericMonitor<IBMDSwitcherRecordAVCallback>, pub
void updateState(BMDSwitcherRecordAVState stateType, BMDSwitcherRecordAVError error) const;
};

class StreamMonitor : public GenericMonitor<IBMDSwitcherStreamRTMPCallback>, public SendStatusInterface
{
public:
StreamMonitor(Switcher *switcher) : GenericMonitor(switcher) { }
HRESULT NotifyStatus(BMDSwitcherStreamRTMPState stateType, BMDSwitcherStreamRTMPError error);
// Ignore these three, don't want to use them yet
HRESULT Notify(BMDSwitcherStreamRTMPEventType eventType) { return S_OK; };
float sendStatus() const;

protected:
virtual ~StreamMonitor() { }

private:
void updateState(BMDSwitcherStreamRTMPState stateType, BMDSwitcherStreamRTMPError error) const;
};

#endif /* SwitcherMonitor_h */
37 changes: 36 additions & 1 deletion atemOSC/FeedbackMonitors.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,9 @@
void RecordAVMonitor::updateState(BMDSwitcherRecordAVState stateType, BMDSwitcherRecordAVError error) const
{
NSString *stateString = @"";
if (stateType == bmdSwitcherRecordAVStateIdle)
if (error != bmdSwitcherRecordAVErrorNone)
stateString = @"error";
else if (stateType == bmdSwitcherRecordAVStateIdle)
stateString = @"idle";
else if (stateType == bmdSwitcherRecordAVStateRecording)
stateString = @"recording";
Expand All @@ -1214,3 +1216,36 @@

sendFeedbackMessage(switcher, @"/recording/state", [OSCValue createWithString:stateString]);
}

float StreamMonitor::sendStatus() const
{
BMDSwitcherStreamRTMPState stateType;
BMDSwitcherStreamRTMPError error;
[switcher mStreamRTMP]->GetStatus(&stateType, &error);
updateState(stateType, error);

return 0.05;
}

HRESULT StreamMonitor::NotifyStatus(BMDSwitcherStreamRTMPState stateType, BMDSwitcherStreamRTMPError error)
{
updateState(stateType, error);
return S_OK;
}

void StreamMonitor::updateState(BMDSwitcherStreamRTMPState stateType, BMDSwitcherStreamRTMPError error) const
{
NSString *stateString = @"";
if (error != bmdSwitcherStreamRTMPErrorNone)
stateString = @"error";
else if (stateType == bmdSwitcherStreamRTMPStateIdle)
stateString = @"idle";
else if (stateType == bmdSwitcherStreamRTMPStateConnecting)
stateString = @"connecting";
else if (stateType == bmdSwitcherStreamRTMPStateStreaming)
stateString = @"streaming";
else if (stateType == bmdSwitcherStreamRTMPStateStopping)
stateString = @"stopping";

sendFeedbackMessage(switcher, @"/stream/state", [OSCValue createWithString:stateString]);
}
21 changes: 21 additions & 0 deletions atemOSC/OSCAddressView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,27 @@ - (void)loadFromSwitcher:(Switcher *)switcher
}
}

if ([switcher mStreamRTMP])
{
[self addHeader:@"Streaming" toString:helpString];
for (OSCEndpoint* endpoint : [appDel endpoints])
{
if ([[endpoint addressTemplate] containsString:@"/stream/"])
{
NSString *address = [endpoint addressTemplate];
if (endpoint.valueType == OSCValInt)
address = [address stringByAppendingString:@" <int>"];
else if (endpoint.valueType == OSCValBool)
address = [address stringByAppendingString:@" <true|false>"];
else if (endpoint.valueType == OSCValFloat)
address = [address stringByAppendingString:@" <float>"];
else if (endpoint.valueType == OSCValString)
address = [address stringByAppendingString:@" <string>"];
[self addEntry:[endpoint label] forAddress:address toString:helpString];
}
}
}

[helpString appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nNote: Additional addresses are available that provide backward-compatibility with TouchOSC. See the Readme on Github for details.\n"]];

[helpString appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nWe add support for addresses on an as-needed basis. If you are in need of an additional address, open an issue on Github letting us know what it is.\n"]];
Expand Down
8 changes: 8 additions & 0 deletions atemOSC/OSCReceiver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,14 @@ - (instancetype) initWithDelegate:(AppDelegate *) delegate
[s mRecordAV]->SetFilename((__bridge CFStringRef)[v stringValue]);
}];

[self addEndpoint:@"/stream/start" label:@"Start RTMP Streaming" handler:^void(Switcher *s, NSDictionary *d, OSCValue *v) {
[s mStreamRTMP]->StartStreaming();
}];

[self addEndpoint:@"/stream/stop" label:@"Stop RTMP Streaming" handler:^void(Switcher *s, NSDictionary *d, OSCValue *v) {
[s mStreamRTMP]->StopStreaming();
}];

endpointPrefixList = [[NSMutableSet alloc] init];

// Recursively build the tree from the list
Expand Down
2 changes: 2 additions & 0 deletions atemOSC/Switcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
std::map<BMDSwitcherAudioInputId, FairlightAudioInputMonitor*> mFairlightAudioInputMonitors;
std::map<BMDSwitcherAudioInputId, std::map<BMDSwitcherFairlightAudioSourceId, FairlightAudioSourceMonitor*> > mFairlightAudioSourceMonitors;
RecordAVMonitor* mRecordAVMonitor;
StreamMonitor* mStreamMonitor;
FairlightAudioMixerMonitor* mFairlightAudioMixerMonitor;

std::vector<SendStatusInterface*> mMonitors;
Expand Down Expand Up @@ -73,6 +74,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) std::vector<IBMDSwitcherDownstreamKey*> dsk;
@property (readonly) IBMDSwitcherKeyFlyParameters* mDVEControl;
@property (readonly) IBMDSwitcherRecordAV* mRecordAV;
@property (readonly) IBMDSwitcherStreamRTMP* mStreamRTMP;

@property (readonly) std::map<BMDSwitcherAudioInputId, IBMDSwitcherAudioInput*> mAudioInputs;
@property (readonly) IBMDSwitcherAudioMixer* mAudioMixer;
Expand Down
20 changes: 20 additions & 0 deletions atemOSC/Switcher.mm
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ @implementation Switcher
@synthesize mInputs;
@synthesize mAuxInputs;
@synthesize mRecordAV;
@synthesize mStreamRTMP;

@synthesize mAudioInputs;
@synthesize mAudioMixer;
Expand Down Expand Up @@ -511,6 +512,15 @@ - (void)switcherConnected
[self logMessage:@"[Debug] Could not get IBMDSwitcherRecordAV interface"];
}

if (SUCCEEDED(mSwitcher->QueryInterface(IID_IBMDSwitcherStreamRTMP, (void**)&mStreamRTMP)))
{
mStreamRTMP->AddCallback(mStreamMonitor);
}
else
{
[self logMessage:@"[Debug] Could not get IBMDSwitcherStreamRTMP interface"];
}

[self setIsConnected: YES];
[self setConnectionStatus:@"Connected"];

Expand Down Expand Up @@ -813,6 +823,14 @@ - (void)cleanUpConnection
mRecordAVMonitor = NULL;
}

if (mStreamRTMP)
{
mStreamRTMP->RemoveCallback(mStreamMonitor);
mStreamRTMP->Release();
mStreamRTMP = NULL;
mStreamMonitor = NULL;
}

mMonitors.clear();
}

Expand All @@ -832,6 +850,8 @@ - (void)setupMonitors
mMonitors.push_back(mFairlightAudioMixerMonitor);
mRecordAVMonitor = new RecordAVMonitor(self);
mMonitors.push_back(mRecordAVMonitor);
mStreamMonitor = new StreamMonitor(self);
mMonitors.push_back(mStreamMonitor);
}

// We run this recursively so that we can get the
Expand Down

0 comments on commit 43f5152

Please sign in to comment.