void WebSocketApi::vendor_event_emit_cb(void *priv_data, calldata_t *cd)
{
auto c = static_cast<WebSocketApi *>(priv_data);
Vendor *v = get_vendor(cd);
if (!v)
RETURN_FAILURE();
const char *eventType;
if (!calldata_get_string(cd, "type", &eventType) || strlen(eventType) == 0) {
blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `type` string.",
v->_name.c_str());
RETURN_FAILURE();
}
void *voidEventData;
if (!calldata_get_ptr(cd, "data", &voidEventData)) {
blog(LOG_WARNING, "[WebSocketApi::vendor_event_emit_cb] [vendorName: %s] Failed due to missing `data` pointer.",
v->_name.c_str());
RETURN_FAILURE();
}
auto eventData = static_cast<obs_data_t *>(voidEventData);
if (!c->_eventCallback)
RETURN_FAILURE();
c->_eventCallback(v->_name, eventType, eventData);
// ATTN: jr adding code to let vendors receive events emited by other vendors
c->jrSendVendorEmitToOtherVendors(v, eventType, eventData);
RETURN_SUCCESS();
}
// ATTN: JR - my new function that allows vendors to get emit broadcast notifications from other vendors
// to get these, the vendor should register a request "ReceiveVendorBroadcastEvent"
// that request will be triggered when other vendors emit a broadcast
//
void WebSocketApi::jrSendVendorEmitToOtherVendors(Vendor *senderV, const char *eventType, obs_data_t * eventData) {
// iterate through all vendors (other than *v) and if they have a registered request called "ReceiveVendorBroadcastEvent" then send them the event data
char requestType[] = "ReceiveVendorBroadcastEvent";
// create response data which we discard at the end
obs_data_t *obsResponseData = NULL;
obs_data_t *wrappedEventData = NULL;
for (auto vpair : _vendors) {
auto v = vpair.second;
if (v == senderV) {
// never send to yourself
continue;
}
// ok does this vendor have a registered calledback for request for broardcast emits
if (v->_requests.count(requestType) == 0) {
// no such request registered for this consumer vendor
continue;
}
// yes they want to receive other vendor emits!
std::shared_lock v_l(v->_mutex);
auto cb = v->_requests[requestType];
v_l.unlock();
// build it if first call
if (obsResponseData == NULL) {
// we defer doing this until we have our first receipient that wants to hear from us, since most of the time we might not
obsResponseData = obs_data_create();
// we wrap the data just as it would be received in an obs websocket client, with vendorName and eventType in outer data, and inner object named eventData
wrappedEventData = obs_data_create();
obs_data_set_string(wrappedEventData,"vendorName",senderV->_name.c_str());
obs_data_set_string(wrappedEventData,"eventType",eventType);
obs_data_set_obj(wrappedEventData,"eventData",eventData);
}
// call the vendor's request to send them the broardcast
cb.callback(wrappedEventData, obsResponseData, cb.priv_data);
}
if (wrappedEventData != NULL) {
obs_data_release(wrappedEventData);
}
if (obsResponseData != NULL) {
obs_data_release(obsResponseData);
}
}