sACN  HEAD (unstable)
Implementation of ANSI E1.31 (Streaming ACN)
View other versions:
Loading...
Searching...
No Matches
receiver.h
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright 2024 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_RECEIVER_H_
21#define SACN_CPP_RECEIVER_H_
22
28#include <vector>
29
30#include "sacn/cpp/common.h"
31
32#include "sacn/receiver.h"
33#include "etcpal/cpp/inet.h"
35
42namespace sacn
43{
44
45namespace detail
46{
48{
49};
50}; // namespace detail
51
62{
63public:
66
72 {
73 public:
74 NotifyHandler() = default;
75 virtual ~NotifyHandler() = default;
76
81 NotifyHandler(const NotifyHandler& other) = default;
82
88 NotifyHandler& operator=(const NotifyHandler& other) = default;
89
94 NotifyHandler(NotifyHandler&& other) = default;
95
102
128 virtual void HandleUniverseData(Handle receiver_handle,
129 const etcpal::SockAddr& source_addr,
130 const SacnRemoteSource& source_info,
131 const SacnRecvUniverseData& universe_data) = 0;
132
140 uint16_t universe,
141 const std::vector<SacnLostSource>& lost_sources) = 0;
142
152 virtual void HandleSamplingPeriodStarted(Handle handle, uint16_t universe)
153 {
154 ETCPAL_UNUSED_ARG(handle);
155 ETCPAL_UNUSED_ARG(universe);
156 }
157
168 virtual void HandleSamplingPeriodEnded(Handle handle, uint16_t universe)
169 {
170 ETCPAL_UNUSED_ARG(handle);
171 ETCPAL_UNUSED_ARG(universe);
172 }
173
180 virtual void HandleSourcePapLost(Handle handle, uint16_t universe, const SacnRemoteSource& source)
181 {
182 ETCPAL_UNUSED_ARG(handle);
183 ETCPAL_UNUSED_ARG(universe);
184 ETCPAL_UNUSED_ARG(source);
185 }
186
193 virtual void HandleSourceLimitExceeded(Handle handle, uint16_t universe)
194 {
195 ETCPAL_UNUSED_ARG(handle);
196 ETCPAL_UNUSED_ARG(universe);
197 }
198 };
199
204 struct Settings
205 {
206 /********* Required values **********/
207
208 uint16_t universe_id{0};
210 /********* Optional values **********/
211
214
219 unsigned int flags{0};
224 Settings() = default;
225
229 Settings(uint16_t new_universe_id);
230
231 bool IsValid() const;
232 };
233
239 {
242
245 std::vector<SacnMcastInterface> netints;
246
248 bool no_netints{false};
249
251 NetintList() = default;
252 NetintList(sacn_receiver_t receiver_handle, McastMode mcast_mode);
253 NetintList(sacn_receiver_t receiver_handle, const std::vector<SacnMcastInterface>& network_interfaces);
254 };
255
256 Receiver() = default;
257 virtual ~Receiver() = default;
258
259 Receiver(const Receiver& other) = delete;
260 Receiver& operator=(const Receiver& other) = delete;
261 Receiver(Receiver&& other) = default;
262 Receiver& operator=(Receiver&& other) = default;
264 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler, McastMode mcast_mode);
265 etcpal::Error Startup(const Settings& settings,
266 NotifyHandler& notify_handler,
267 std::vector<SacnMcastInterface>& netints);
268 void Shutdown();
271 etcpal::Error ChangeUniverse(uint16_t new_universe_id);
273 etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange& new_footprint);
274 std::vector<EtcPalMcastNetintId> GetNetworkInterfaces();
275
276 // Lesser used functions. These apply to all instances of this class.
277 static void SetExpiredWait(uint32_t wait_ms);
278 static uint32_t GetExpiredWait();
279
280 static etcpal::Error ResetNetworking(McastMode mcast_mode);
281 static etcpal::Error ResetNetworking(std::vector<SacnMcastInterface>& netints);
282 static etcpal::Error ResetNetworking(std::vector<SacnMcastInterface>& sys_netints,
283 std::vector<NetintList>& netint_lists);
284
285 constexpr Handle handle() const;
286
287private:
288 static SacnReceiverConfig TranslateConfig(const Settings& settings, NotifyHandler& notify_handler);
289
290 Handle handle_;
291};
292
297namespace internal
298{
299extern "C" inline void ReceiverCbUniverseData(sacn_receiver_t receiver_handle,
300 const EtcPalSockAddr* source_addr,
301 const SacnRemoteSource* source_info,
302 const SacnRecvUniverseData* universe_data,
303 void* context)
304{
305 if (source_addr && source_info && universe_data && context)
306 {
307 static_cast<Receiver::NotifyHandler*>(context)->HandleUniverseData(Receiver::Handle(receiver_handle), *source_addr,
308 *source_info, *universe_data);
309 }
310}
311
312extern "C" inline void ReceiverCbSourcesLost(sacn_receiver_t handle,
313 uint16_t universe,
314 const SacnLostSource* lost_sources,
315 size_t num_lost_sources,
316 void* context)
317{
318 if (context && lost_sources && (num_lost_sources > 0))
319 {
320 std::vector<SacnLostSource> lost_vec(lost_sources, lost_sources + num_lost_sources);
321 static_cast<Receiver::NotifyHandler*>(context)->HandleSourcesLost(Receiver::Handle(handle), universe, lost_vec);
322 }
323}
324
325extern "C" inline void ReceiverCbSamplingPeriodStarted(sacn_receiver_t handle, uint16_t universe, void* context)
326{
327 if (context)
328 {
329 static_cast<Receiver::NotifyHandler*>(context)->HandleSamplingPeriodStarted(Receiver::Handle(handle), universe);
330 }
331}
332
333extern "C" inline void ReceiverCbSamplingPeriodEnded(sacn_receiver_t handle, uint16_t universe, void* context)
334{
335 if (context)
336 {
337 static_cast<Receiver::NotifyHandler*>(context)->HandleSamplingPeriodEnded(Receiver::Handle(handle), universe);
338 }
339}
340
341extern "C" inline void ReceiverCbPapLost(sacn_receiver_t handle,
342 uint16_t universe,
343 const SacnRemoteSource* source,
344 void* context)
345{
346 if (context && source)
347 {
348 static_cast<Receiver::NotifyHandler*>(context)->HandleSourcePapLost(Receiver::Handle(handle), universe, *source);
349 }
350}
351
352extern "C" inline void ReceiverCbSourceLimitExceeded(sacn_receiver_t handle, uint16_t universe, void* context)
353{
354 if (context)
355 {
356 static_cast<Receiver::NotifyHandler*>(context)->HandleSourceLimitExceeded(Receiver::Handle(handle), universe);
357 }
358}
359
360}; // namespace internal
361
371inline Receiver::Settings::Settings(uint16_t new_universe_id) : universe_id(new_universe_id)
372{
373}
374
379{
380 return (universe_id > 0) && (footprint.start_address >= 1) && (footprint.start_address <= kSacnDmxAddressCount) &&
381 (footprint.address_count >= 1) &&
382 (footprint.address_count <= (kSacnDmxAddressCount - footprint.start_address + 1));
383}
384
391 McastMode mcast_mode = McastMode::kEnabledOnAllInterfaces)
392 : handle(receiver_handle), no_netints(mcast_mode == McastMode::kDisabledOnAllInterfaces)
393{
394}
395
403 const std::vector<SacnMcastInterface>& network_interfaces)
404 : handle(receiver_handle), netints(network_interfaces)
405{
406}
407
434 NotifyHandler& notify_handler,
435 McastMode mcast_mode = McastMode::kEnabledOnAllInterfaces)
436{
437 SacnReceiverConfig config = TranslateConfig(settings, notify_handler);
438
440 if (mcast_mode == McastMode::kDisabledOnAllInterfaces)
441 netint_config.no_netints = true;
442
444 etcpal::Error result = sacn_receiver_create(&config, &c_handle, &netint_config);
445
446 handle_.SetValue(c_handle);
447
448 return result;
449}
450
479 NotifyHandler& notify_handler,
480 std::vector<SacnMcastInterface>& netints)
481{
482 SacnReceiverConfig config = TranslateConfig(settings, notify_handler);
483
486
487 if (netints.empty())
488 {
489 result = sacn_receiver_create(&config, &c_handle, nullptr);
490 }
491 else
492 {
494 netint_config.netints = netints.data();
495 netint_config.num_netints = netints.size();
496
497 result = sacn_receiver_create(&config, &c_handle, &netint_config);
498 }
499
500 handle_.SetValue(c_handle);
501
502 return result;
503}
504
516{
517 sacn_receiver_destroy(handle_.value());
518 handle_.Clear();
519}
520
527{
528 uint16_t result = 0;
529 etcpal_error_t err = sacn_receiver_get_universe(handle_.value(), &result);
530 if (err == kEtcPalErrOk)
531 return result;
532
533 return err;
534}
535
544{
546 etcpal_error_t err = sacn_receiver_get_footprint(handle_.value(), &result);
547 if (err == kEtcPalErrOk)
548 return result;
549
550 return err;
551}
552
570inline etcpal::Error Receiver::ChangeUniverse(uint16_t new_universe_id)
571{
572 return sacn_receiver_change_universe(handle_.value(), new_universe_id);
573}
574
586{
587 return sacn_receiver_change_footprint(handle_.value(), &new_footprint);
588}
589
602 const SacnRecvUniverseSubrange& new_footprint)
603{
604 return sacn_receiver_change_universe_and_footprint(handle_.value(), new_universe_id, &new_footprint);
605}
606
612inline std::vector<EtcPalMcastNetintId> Receiver::GetNetworkInterfaces()
613{
614 // This uses a guessing algorithm with a while loop to avoid race conditions.
615 size_t size_guess = 4u;
616 std::vector<EtcPalMcastNetintId> netints(size_guess);
617 size_t num_netints = sacn_receiver_get_network_interfaces(handle_.value(), netints.data(), netints.size());
618
619 while (num_netints > netints.size())
620 {
621 size_guess = num_netints + 4u;
622 netints.resize(size_guess);
623 num_netints = sacn_receiver_get_network_interfaces(handle_.value(), netints.data(), netints.size());
624 }
625
626 netints.resize(num_netints);
627 return netints;
628}
629
639inline void Receiver::SetExpiredWait(uint32_t wait_ms)
640{
642}
643
654{
656}
657
682inline etcpal::Error Receiver::ResetNetworking(McastMode mcast_mode = McastMode::kEnabledOnAllInterfaces)
683{
685 if (mcast_mode == McastMode::kDisabledOnAllInterfaces)
686 netint_config.no_netints = true;
687
688 return sacn_receiver_reset_networking(&netint_config);
689}
690
714inline etcpal::Error Receiver::ResetNetworking(std::vector<SacnMcastInterface>& sys_netints)
715{
716 if (sys_netints.empty())
717 return sacn_receiver_reset_networking(nullptr);
718
720 netint_config.netints = sys_netints.data();
721 netint_config.num_netints = sys_netints.size();
722
723 return sacn_receiver_reset_networking(&netint_config);
724}
725
754inline etcpal::Error Receiver::ResetNetworking(std::vector<SacnMcastInterface>& sys_netints,
755 std::vector<NetintList>& per_receiver_netint_lists)
756{
757 std::vector<SacnReceiverNetintList> netint_lists_c;
758 netint_lists_c.reserve(per_receiver_netint_lists.size());
759 std::transform(per_receiver_netint_lists.begin(), per_receiver_netint_lists.end(), std::back_inserter(netint_lists_c),
760 [](NetintList& list) {
761 // clang-format off
762 SacnReceiverNetintList c_list = {
763 list.handle,
764 list.netints.data(),
765 list.netints.size(),
766 list.no_netints
767 };
768 // clang-format on
769
770 return c_list;
771 });
772
774 sys_netint_config.netints = sys_netints.data();
775 sys_netint_config.num_netints = sys_netints.size();
776
777 return sacn_receiver_reset_networking_per_receiver(&sys_netint_config, netint_lists_c.data(), netint_lists_c.size());
778}
779
786{
787 return handle_;
788}
789
790inline SacnReceiverConfig Receiver::TranslateConfig(const Settings& settings, NotifyHandler& notify_handler)
791{
792 // clang-format off
793 SacnReceiverConfig config = {
794 settings.universe_id,
795 {
796 internal::ReceiverCbUniverseData,
797 internal::ReceiverCbSourcesLost,
798 internal::ReceiverCbSamplingPeriodStarted,
799 internal::ReceiverCbSamplingPeriodEnded,
800 internal::ReceiverCbPapLost,
801 internal::ReceiverCbSourceLimitExceeded,
802 &notify_handler
803 },
804 settings.footprint,
805 settings.source_count_max,
806 settings.flags,
807 settings.ip_supported
808 };
809 // clang-format on
810
811 return config;
812}
813
814}; // namespace sacn
815
816#endif // SACN_CPP_RECEIVER_H_
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 common notification callbacks from sACN.
Definition common.h:73
A base class for a class that receives notification callbacks from a sACN receiver.
Definition receiver.h:72
virtual void HandleSamplingPeriodEnded(Handle handle, uint16_t universe)
Notify that a receiver's sampling period has ended.
Definition receiver.h:168
NotifyHandler(NotifyHandler &&other)=default
Defaulted move constructor.
virtual void HandleSamplingPeriodStarted(Handle handle, uint16_t universe)
Notify that a receiver's sampling period has begun.
Definition receiver.h:152
NotifyHandler & operator=(NotifyHandler &&other)=default
Defaulted move assignment operator.
NotifyHandler(const NotifyHandler &other)=default
Defaulted copy constructor.
NotifyHandler & operator=(const NotifyHandler &other)=default
Defaulted copy assignment operator.
virtual void HandleSourcesLost(Handle handle, uint16_t universe, const std::vector< SacnLostSource > &lost_sources)=0
Notify that one or more sources have entered a source loss state.
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 receiver.h:193
virtual void HandleSourcePapLost(Handle handle, uint16_t universe, const SacnRemoteSource &source)
Notify that a source has stopped transmission of per-address priority packets.
Definition receiver.h:180
virtual void HandleUniverseData(Handle receiver_handle, const etcpal::SockAddr &source_addr, const SacnRemoteSource &source_info, const SacnRecvUniverseData &universe_data)=0
Notify that new universe data within the configured footprint has been received.
An instance of sACN Receiver functionality; see Using the sACN Receiver API.
Definition receiver.h:62
Receiver & operator=(Receiver &&other)=default
Move a receiver instance.
etcpal::Expected< uint16_t > GetUniverse() const
Get the universe this receiver is listening to.
Definition receiver.h:526
etcpal::Error ChangeFootprint(const SacnRecvUniverseSubrange &new_footprint)
Change the footprint within the universe this receiver is listening to.
Definition receiver.h:585
static uint32_t GetExpiredWait()
Get the current value of the expired notification wait time.
Definition receiver.h:653
void Shutdown()
Stop listening for sACN data on a universe.
Definition receiver.h:515
constexpr Handle handle() const
Get the current handle to the underlying C receiver.
Definition receiver.h:785
static etcpal::Error ResetNetworking(McastMode mcast_mode)
Resets the underlying network sockets and packet receipt state for all sACN receivers.
Definition receiver.h:682
static void SetExpiredWait(uint32_t wait_ms)
Set the expired notification wait time.
Definition receiver.h:639
Receiver(Receiver &&other)=default
Move a receiver instance.
etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange &new_footprint)
Change the universe and footprint this receiver is listening to.
Definition receiver.h:601
std::vector< EtcPalMcastNetintId > GetNetworkInterfaces()
Obtain a vector of this receiver's network interfaces.
Definition receiver.h:612
etcpal::Error ChangeUniverse(uint16_t new_universe_id)
Change the universe this receiver is listening to.
Definition receiver.h:570
etcpal::Expected< SacnRecvUniverseSubrange > GetFootprint() const
Get the footprint within the universe this receiver is listening to.
Definition receiver.h:543
etcpal::Error Startup(const Settings &settings, NotifyHandler &notify_handler, McastMode mcast_mode)
Start listening for sACN data on a universe.
Definition receiver.h:433
Definition receiver.h:48
C++ wrapper for the sACN init/deinit functions.
etcpal_error_t
kEtcPalErrOk
sacn_ip_support_t
This enum defines how the API module will use IPv4 and IPv6 networking.
Definition common.h:75
#define SACN_NETINT_CONFIG_DEFAULT_INIT
Initializes the members of a SacnNetintConfig to defaults.
Definition common.h:187
@ kSacnIpV4AndIpV6
Use both IPv4 and IPv6.
Definition common.h:81
@ kSacnDmxAddressCount
The number of addresses in a DMX universe.
Definition common.h:60
etcpal_error_t sacn_receiver_reset_networking_per_receiver(const SacnNetintConfig *sys_netint_config, const SacnReceiverNetintList *per_receiver_netint_lists, size_t num_per_receiver_netint_lists)
Resets underlying network sockets and packet receipt state, determines network interfaces for each re...
Definition receiver.c:439
etcpal_error_t sacn_receiver_get_footprint(sacn_receiver_t handle, SacnRecvUniverseSubrange *footprint)
Get the footprint within the universe on which a sACN receiver is currently listening.
Definition receiver.c:233
etcpal_error_t sacn_receiver_destroy(sacn_receiver_t handle)
Destroy a sACN receiver instance.
Definition receiver.c:145
etcpal_error_t sacn_receiver_reset_networking(const SacnNetintConfig *sys_netint_config)
Resets underlying network sockets and packet receipt state, determines network interfaces for all rec...
Definition receiver.c:363
size_t sacn_receiver_get_network_interfaces(sacn_receiver_t handle, EtcPalMcastNetintId *netints, size_t netints_size)
Obtain a list of a receiver's network interfaces.
Definition receiver.c:537
static const sacn_receiver_t kSacnReceiverInvalid
An invalid sACN receiver handle value.
Definition receiver.h:60
etcpal_error_t sacn_receiver_change_footprint(sacn_receiver_t handle, const SacnRecvUniverseSubrange *new_footprint)
Change the footprint within the universe on which an sACN receiver is listening.
Definition receiver.c:308
etcpal_error_t sacn_receiver_change_universe(sacn_receiver_t handle, uint16_t new_universe_id)
Change the universe on which an sACN receiver is listening.
Definition receiver.c:272
uint32_t sacn_receiver_get_expired_wait()
Get the current value of the expired notification wait time.
Definition receiver.c:583
void sacn_receiver_set_expired_wait(uint32_t wait_ms)
Set the expired notification wait time.
Definition receiver.c:562
etcpal_error_t sacn_receiver_create(const SacnReceiverConfig *config, sacn_receiver_t *handle, const SacnNetintConfig *netint_config)
Create a new sACN receiver to listen for sACN data on a universe.
Definition receiver.c:92
etcpal_error_t sacn_receiver_get_universe(sacn_receiver_t handle, uint16_t *universe_id)
Get the universe on which a sACN receiver is currently listening.
Definition receiver.c:190
etcpal_error_t sacn_receiver_change_universe_and_footprint(sacn_receiver_t handle, uint16_t new_universe_id, const SacnRecvUniverseSubrange *new_footprint)
Change the universe and footprint on which an sACN receiver is listening.
Definition receiver.c:328
int sacn_receiver_t
A handle to an sACN receiver.
Definition receiver.h:58
@ kSacnReceiverInfiniteSources
Constant for "infinite" when listening or merging sACN universes.
Definition receiver.h:70
A namespace which contains all C++ language definitions in the sACN library.
Definition common.h:50
McastMode
Determines whether multicast traffic is allowed through all interfaces or none.
Definition common.h:53
sACN Receiver API definitions
Information about a sACN source that was lost.
Definition receiver.h:153
Network interface configuration information to give the sACN library.
Definition common.h:114
SacnMcastInterface * netints
An array of network interface IDs to which to restrict multicast traffic.
Definition common.h:117
size_t num_netints
Size of netints array.
Definition common.h:119
bool no_netints
If this is true, no network interfaces will be used for multicast.
Definition common.h:122
A set of configuration information for an sACN receiver.
Definition receiver.h:313
uint16_t universe_id
Universe number on which to listen for sACN.
Definition receiver.h:317
A complete description of newly received universe data within the configured footprint.
Definition receiver.h:92
Defines a range of addresses within a sACN universe.
Definition receiver.h:83
Information about a remote sACN source being tracked by a receiver.
Definition receiver.h:142
A set of network interfaces for a particular receiver.
Definition receiver.h:239
bool no_netints
If this is true, this receiver will not use any network interfaces for multicast traffic.
Definition receiver.h:248
NetintList()=default
Create an empty, invalid data structure by default.
sacn_receiver_t handle
The receiver's handle.
Definition receiver.h:241
std::vector< SacnMcastInterface > netints
If !empty, this is the list of interfaces the application wants to use, and the status codes are fill...
Definition receiver.h:245
A set of configuration settings that a receiver needs to initialize.
Definition receiver.h:205
int source_count_max
The maximum number of sources this universe will listen to.
Definition receiver.h:218
SacnRecvUniverseSubrange footprint
The footprint within the universe to monitor.
Definition receiver.h:213
Settings()=default
Create an empty, invalid data structure by default.
bool IsValid() const
Determine whether a Reciever Settings instance contains valid data for sACN operation.
Definition receiver.h:378
sacn_ip_support_t ip_supported
What IP networking the receiver will support.
Definition receiver.h:221
uint16_t universe_id
The sACN universe number the receiver is listening to.
Definition receiver.h:208
unsigned int flags
A set of option flags.
Definition receiver.h:219