sACN  2.0.1
Implementation of ANSI E1.31 (Streaming ACN)
View other versions:
Loading...
Searching...
No Matches
merge_receiver.h
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright 2022 ETC Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************
16 * This file is a part of sACN. For more information, go to:
17 * https://github.com/ETCLabs/sACN
18 *****************************************************************************/
19
20#ifndef SACN_CPP_MERGE_RECEIVER_H_
21#define SACN_CPP_MERGE_RECEIVER_H_
22
28#include "sacn/cpp/common.h"
29
30#include "sacn/merge_receiver.h"
31#include "etcpal/cpp/inet.h"
33#include "etcpal/cpp/uuid.h"
34
41namespace sacn
42{
43
44namespace detail
45{
49}; // namespace detail
50
61{
62public:
65
71 {
72 public:
73 virtual ~NotifyHandler() = default;
74
94 virtual void HandleMergedData(Handle handle, const SacnRecvMergedData& merged_data) = 0;
95
115 virtual void HandleNonDmxData(Handle receiver_handle, const etcpal::SockAddr& source_addr,
116 const SacnRemoteSource& source_info, const SacnRecvUniverseData& universe_data) = 0;
117
127 virtual void HandleSourceLimitExceeded(Handle handle, uint16_t universe)
128 {
129 ETCPAL_UNUSED_ARG(handle);
130 ETCPAL_UNUSED_ARG(universe);
131 }
132 };
133
138 struct Settings
139 {
140 /********* Required values **********/
141
143 uint16_t universe_id{0};
144
145 /********* Optional values **********/
146
149
152
157 bool use_pap{true};
158
161
163 Settings() = default;
164
168 Settings(uint16_t new_universe_id);
169
170 bool IsValid() const;
171 };
172
190
191 MergeReceiver() = default;
192 MergeReceiver(const MergeReceiver& other) = delete;
193 MergeReceiver& operator=(const MergeReceiver& other) = delete;
194 MergeReceiver(MergeReceiver&& other) = default;
197 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler);
198 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler,
200 void Shutdown();
203 etcpal::Error ChangeUniverse(uint16_t new_universe_id);
205 etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange& new_footprint);
207
211 std::vector<NetintList>& netint_lists);
212
213 constexpr Handle handle() const;
214
215private:
216 SacnMergeReceiverConfig TranslateConfig(const Settings& settings, NotifyHandler& notify_handler);
217
218 Handle handle_;
219};
220
225namespace internal
226{
227extern "C" inline void MergeReceiverCbMergedData(sacn_merge_receiver_t handle, const SacnRecvMergedData* merged_data,
228 void* context)
229{
230 if (context && merged_data)
231 {
232 static_cast<MergeReceiver::NotifyHandler*>(context)->HandleMergedData(MergeReceiver::Handle(handle), *merged_data);
233 }
234}
235
236extern "C" inline void MergeReceiverCbNonDmx(sacn_merge_receiver_t receiver_handle, const EtcPalSockAddr* source_addr,
237 const SacnRemoteSource* source_info,
238 const SacnRecvUniverseData* universe_data, void* context)
239{
240 if (context && source_addr && source_info && universe_data)
241 {
242 static_cast<MergeReceiver::NotifyHandler*>(context)->HandleNonDmxData(MergeReceiver::Handle(receiver_handle),
243 *source_addr, *source_info, *universe_data);
244 }
245}
246
247extern "C" inline void MergeReceiverCbSourceLimitExceeded(sacn_merge_receiver_t handle, uint16_t universe,
248 void* context)
249{
250 if (context)
251 {
252 static_cast<MergeReceiver::NotifyHandler*>(context)->HandleSourceLimitExceeded(MergeReceiver::Handle(handle),
253 universe);
254 }
255}
256
257}; // namespace internal
258
268inline MergeReceiver::Settings::Settings(uint16_t new_universe_id) : universe_id(new_universe_id)
269{
270}
271
274{
275 return (universe_id > 0) && (footprint.start_address >= 1) && (footprint.start_address <= DMX_ADDRESS_COUNT) &&
276 (footprint.address_count >= 1) &&
277 (footprint.address_count <= (DMX_ADDRESS_COUNT - footprint.start_address + 1));
278}
279
286 : handle(merge_receiver_handle)
287{
288}
289
312inline etcpal::Error MergeReceiver::Startup(const Settings& settings, NotifyHandler& notify_handler)
313{
315 return Startup(settings, notify_handler, netints);
316}
317
340inline etcpal::Error MergeReceiver::Startup(const Settings& settings, NotifyHandler& notify_handler,
342{
343 SacnMergeReceiverConfig config = TranslateConfig(settings, notify_handler);
344
347
348 if (netints.empty())
349 {
350 result = sacn_merge_receiver_create(&config, &c_handle, NULL);
351 }
352 else
353 {
354 SacnNetintConfig netint_config = {netints.data(), netints.size()};
355 result = sacn_merge_receiver_create(&config, &c_handle, &netint_config);
356 }
357
358 handle_.SetValue(c_handle);
359
360 return result;
361}
362
370{
372 handle_.Clear();
373}
374
381{
382 uint16_t result = 0;
383 etcpal_error_t err = sacn_merge_receiver_get_universe(handle_.value(), &result);
384 if (err == kEtcPalErrOk)
385 return result;
386 else
387 return err;
388}
389
398{
401 if (err == kEtcPalErrOk)
402 return result;
403 else
404 return err;
405}
406
422inline etcpal::Error MergeReceiver::ChangeUniverse(uint16_t new_universe_id)
423{
424 return sacn_merge_receiver_change_universe(handle_.value(), new_universe_id);
425}
426
437{
438 return sacn_merge_receiver_change_footprint(handle_.value(), &new_footprint);
439}
440
452 const SacnRecvUniverseSubrange& new_footprint)
453{
454 return sacn_merge_receiver_change_universe_and_footprint(handle_.value(), new_universe_id, &new_footprint);
455}
456
463{
464 // This uses a guessing algorithm with a while loop to avoid race conditions.
466 size_t size_guess = 4u;
467 size_t num_netints = 0u;
468
469 do
470 {
471 netints.resize(size_guess);
472 num_netints = sacn_merge_receiver_get_network_interfaces(handle_.value(), netints.data(), netints.size());
473 size_guess = num_netints + 4u;
474 } while (num_netints > netints.size());
475
476 netints.resize(num_netints);
477 return netints;
478}
479
507
532{
533 if (sys_netints.empty())
535
536 SacnNetintConfig netint_config = {sys_netints.data(), sys_netints.size()};
537 return sacn_merge_receiver_reset_networking(&netint_config);
538}
539
570 std::vector<NetintList>& per_receiver_netint_lists)
571{
573 netint_lists_c.reserve(per_receiver_netint_lists.size());
574 std::transform(per_receiver_netint_lists.begin(), per_receiver_netint_lists.end(), std::back_inserter(netint_lists_c),
575 [](NetintList& list) {
576 // clang-format off
577 SacnMergeReceiverNetintList c_list = {
578 list.handle,
579 list.netints.data(),
580 list.netints.size()
581 };
582 // clang-format on
583
584 return c_list;
585 });
586
587 SacnNetintConfig netint_config = {sys_netints.data(), sys_netints.size()};
588 return sacn_merge_receiver_reset_networking_per_receiver(&netint_config, netint_lists_c.data(),
589 netint_lists_c.size());
590}
591
598{
599 return handle_;
600}
601
602inline SacnMergeReceiverConfig MergeReceiver::TranslateConfig(const Settings& settings, NotifyHandler& notify_handler)
603{
604 // clang-format off
605 SacnMergeReceiverConfig config = {
606 settings.universe_id,
607 {
608 internal::MergeReceiverCbMergedData,
609 internal::MergeReceiverCbNonDmx,
610 internal::MergeReceiverCbSourceLimitExceeded,
611 &notify_handler
612 },
613 settings.footprint,
614 settings.source_count_max,
615 settings.use_pap,
616 settings.ip_supported
617 };
618 // clang-format on
619
620 return config;
621}
622
623}; // namespace sacn
624
625#endif // SACN_CPP_MERGE_RECEIVER_H_
T back_inserter(T... args)
T begin(T... args)
ETCPAL_CONSTEXPR_14 void Clear()
ETCPAL_CONSTEXPR_14 void SetValue(const ValueType &new_value)
constexpr ValueType value() const
A base class for a class that receives notification callbacks from a sACN merge receiver.
Definition merge_receiver.h:71
virtual void HandleMergedData(Handle handle, const SacnRecvMergedData &merged_data)=0
Notify that a new data packet has been received and merged.
virtual void HandleSourceLimitExceeded(Handle handle, uint16_t universe)
Notify that more than the configured maximum number of sources are currently sending on the universe ...
Definition merge_receiver.h:127
virtual void HandleNonDmxData(Handle receiver_handle, const etcpal::SockAddr &source_addr, const SacnRemoteSource &source_info, const SacnRecvUniverseData &universe_data)=0
Notify that a non-data packet has been received.
An instance of sACN Merge Receiver functionality; see Using the sACN Merge Receiver API.
Definition merge_receiver.h:61
static etcpal::Error ResetNetworking()
Resets the underlying network sockets and packet receipt state for all sACN merge receivers.
Definition merge_receiver.h:502
std::vector< EtcPalMcastNetintId > GetNetworkInterfaces()
Obtain a vector of this merge receiver's network interfaces.
Definition merge_receiver.h:462
etcpal::Expected< uint16_t > GetUniverse() const
Get the universe this merge receiver is listening to.
Definition merge_receiver.h:380
etcpal::Error ChangeFootprint(const SacnRecvUniverseSubrange &new_footprint)
Change the footprint within the universe this merge receiver is listening to. TODO: Not yet implement...
Definition merge_receiver.h:436
MergeReceiver & operator=(MergeReceiver &&other)=default
constexpr Handle handle() const
Get the current handle to the underlying C merge receiver.
Definition merge_receiver.h:597
etcpal::Error ChangeUniverse(uint16_t new_universe_id)
Change the universe this class is listening to.
Definition merge_receiver.h:422
etcpal::Expected< SacnRecvUniverseSubrange > GetFootprint() const
Get the footprint within the universe this merge receiver is listening to.
Definition merge_receiver.h:397
etcpal::Error Startup(const Settings &settings, NotifyHandler &notify_handler)
Start listening for sACN data on a universe.
Definition merge_receiver.h:312
etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange &new_footprint)
Change the universe and footprint this merge receiver is listening to. TODO: Not yet implemented.
Definition merge_receiver.h:451
void Shutdown()
Stop listening for sACN data on a universe.
Definition merge_receiver.h:369
MergeReceiver(MergeReceiver &&other)=default
Definition merge_receiver.h:47
C++ wrapper for the sACN init/deinit functions.
T data(T... args)
T empty(T... args)
T end(T... args)
etcpal_error_t
kEtcPalErrOk
sacn_ip_support_t
Definition common.h:71
#define DMX_ADDRESS_COUNT
Definition common.h:55
@ kSacnIpV4AndIpV6
Definition common.h:77
etcpal_error_t sacn_merge_receiver_reset_networking(const SacnNetintConfig *sys_netint_config)
Resets underlying network sockets and packet receipt state, determines network interfaces for all mer...
Definition merge_receiver.c:376
size_t sacn_merge_receiver_get_network_interfaces(sacn_merge_receiver_t handle, EtcPalMcastNetintId *netints, size_t netints_size)
Obtain a list of a merge receiver's network interfaces.
Definition merge_receiver.c:472
etcpal_error_t sacn_merge_receiver_destroy(sacn_merge_receiver_t handle)
Destroy a sACN Merge Receiver instance.
Definition merge_receiver.c:182
etcpal_error_t sacn_merge_receiver_change_footprint(sacn_merge_receiver_t handle, const SacnRecvUniverseSubrange *new_footprint)
Change the footprint within the universe on which an sACN receiver is listening. TODO: Not yet implem...
Definition merge_receiver.c:322
etcpal_error_t sacn_merge_receiver_reset_networking_per_receiver(const SacnNetintConfig *sys_netint_config, const SacnMergeReceiverNetintList *per_receiver_netint_lists, size_t num_per_receiver_netint_lists)
Resets underlying network sockets and packet receipt state, determines network interfaces for each me...
Definition merge_receiver.c:413
etcpal_error_t sacn_merge_receiver_get_footprint(sacn_merge_receiver_t handle, SacnRecvUniverseSubrange *footprint)
Get the footprint within the universe on which a sACN Merge Receiver is currently listening.
Definition merge_receiver.c:245
etcpal_error_t sacn_merge_receiver_get_universe(sacn_merge_receiver_t handle, uint16_t *universe_id)
Get the universe on which a sACN Merge Receiver is currently listening.
Definition merge_receiver.c:226
etcpal_error_t sacn_merge_receiver_change_universe(sacn_merge_receiver_t handle, uint16_t new_universe_id)
Change the universe on which a sACN Merge Receiver is listening.
Definition merge_receiver.c:268
etcpal_error_t sacn_merge_receiver_create(const SacnMergeReceiverConfig *config, sacn_merge_receiver_t *handle, const SacnNetintConfig *netint_config)
Create a new sACN Merge Receiver to listen and merge sACN data on a universe.
Definition merge_receiver.c:88
etcpal_error_t sacn_merge_receiver_change_universe_and_footprint(sacn_merge_receiver_t handle, uint16_t new_universe_id, const SacnRecvUniverseSubrange *new_footprint)
Change the universe and footprint on which an sACN merge receiver is listening. TODO: Not yet impleme...
Definition merge_receiver.c:342
int sacn_merge_receiver_t
Definition merge_receiver.h:53
#define SACN_MERGE_RECEIVER_INVALID
Definition merge_receiver.h:55
#define SACN_RECEIVER_INFINITE_SOURCES
Constant for "infinite" when listening or merging sACN universes.
Definition receiver.h:68
sACN Merge Receiver API definitions
A namespace which contains all C++ language definitions in the sACN library.
Definition common.h:50
T reserve(T... args)
T resize(T... args)
T size(T... args)
Definition merge_receiver.h:158
uint16_t universe_id
Definition merge_receiver.h:162
Definition common.h:102
Definition merge_receiver.h:61
Definition receiver.h:89
Definition receiver.h:80
Definition receiver.h:124
A set of network interfaces for a particular merge receiver.
Definition merge_receiver.h:178
std::vector< SacnMcastInterface > netints
Definition merge_receiver.h:184
sacn_merge_receiver_t handle
Definition merge_receiver.h:180
A set of configuration settings that a merge receiver needs to initialize.
Definition merge_receiver.h:139
SacnRecvUniverseSubrange footprint
Definition merge_receiver.h:148
uint16_t universe_id
Definition merge_receiver.h:143
int source_count_max
Definition merge_receiver.h:151
sacn_ip_support_t ip_supported
Definition merge_receiver.h:160
bool IsValid() const
Definition merge_receiver.h:273
bool use_pap
Definition merge_receiver.h:157
T transform(T... args)