sACN  3.0.0
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 virtual ~NotifyHandler() = default;
75
101 virtual void HandleUniverseData(Handle receiver_handle, const etcpal::SockAddr& source_addr,
102 const SacnRemoteSource& source_info, const SacnRecvUniverseData& universe_data) = 0;
103
110 virtual void HandleSourcesLost(Handle handle, uint16_t universe,
111 const std::vector<SacnLostSource>& lost_sources) = 0;
112
122 virtual void HandleSamplingPeriodStarted(Handle handle, uint16_t universe)
123 {
124 ETCPAL_UNUSED_ARG(handle);
125 ETCPAL_UNUSED_ARG(universe);
126 }
127
138 virtual void HandleSamplingPeriodEnded(Handle handle, uint16_t universe)
139 {
140 ETCPAL_UNUSED_ARG(handle);
141 ETCPAL_UNUSED_ARG(universe);
142 }
143
150 virtual void HandleSourcePapLost(Handle handle, uint16_t universe, const SacnRemoteSource& source)
151 {
152 ETCPAL_UNUSED_ARG(handle);
153 ETCPAL_UNUSED_ARG(universe);
154 ETCPAL_UNUSED_ARG(source);
155 }
156
163 virtual void HandleSourceLimitExceeded(Handle handle, uint16_t universe)
164 {
165 ETCPAL_UNUSED_ARG(handle);
166 ETCPAL_UNUSED_ARG(universe);
167 }
168 };
169
174 struct Settings
175 {
176 /********* Required values **********/
177
178 uint16_t universe_id{0};
180 /********* Optional values **********/
181
184
189 unsigned int flags{0};
194 Settings() = default;
195
199 Settings(uint16_t new_universe_id);
200
201 bool IsValid() const;
202 };
203
209 {
212
216
218 bool no_netints{false};
219
221 NetintList() = default;
222 NetintList(sacn_receiver_t receiver_handle, McastMode mcast_mode);
223 NetintList(sacn_receiver_t receiver_handle, const std::vector<SacnMcastInterface>& network_interfaces);
224 };
225
226 Receiver() = default;
227 Receiver(const Receiver& other) = delete;
228 Receiver& operator=(const Receiver& other) = delete;
229 Receiver(Receiver&& other) = default;
230 Receiver& operator=(Receiver&& other) = default;
232 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler, McastMode mcast_mode);
233 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler,
235 void Shutdown();
238 etcpal::Error ChangeUniverse(uint16_t new_universe_id);
240 etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange& new_footprint);
242
243 // Lesser used functions. These apply to all instances of this class.
244 static void SetExpiredWait(uint32_t wait_ms);
245 static uint32_t GetExpiredWait();
246
247 static etcpal::Error ResetNetworking(McastMode mcast_mode);
250 std::vector<NetintList>& netint_lists);
251
252 constexpr Handle handle() const;
253
254private:
255 SacnReceiverConfig TranslateConfig(const Settings& settings, NotifyHandler& notify_handler);
256
257 Handle handle_;
258};
259
264namespace internal
265{
266extern "C" inline void ReceiverCbUniverseData(sacn_receiver_t receiver_handle, const EtcPalSockAddr* source_addr,
267 const SacnRemoteSource* source_info,
268 const SacnRecvUniverseData* universe_data, void* context)
269{
270 if (source_addr && source_info && universe_data && context)
271 {
272 static_cast<Receiver::NotifyHandler*>(context)->HandleUniverseData(Receiver::Handle(receiver_handle), *source_addr,
273 *source_info, *universe_data);
274 }
275}
276
277extern "C" inline void ReceiverCbSourcesLost(sacn_receiver_t handle, uint16_t universe,
278 const SacnLostSource* lost_sources, size_t num_lost_sources, void* context)
279{
280 if (context && lost_sources && (num_lost_sources > 0))
281 {
282 std::vector<SacnLostSource> lost_vec(lost_sources, lost_sources + num_lost_sources);
283 static_cast<Receiver::NotifyHandler*>(context)->HandleSourcesLost(Receiver::Handle(handle), universe, lost_vec);
284 }
285}
286
287extern "C" inline void ReceiverCbSamplingPeriodStarted(sacn_receiver_t handle, uint16_t universe, void* context)
288{
289 if (context)
290 {
291 static_cast<Receiver::NotifyHandler*>(context)->HandleSamplingPeriodStarted(Receiver::Handle(handle), universe);
292 }
293}
294
295extern "C" inline void ReceiverCbSamplingPeriodEnded(sacn_receiver_t handle, uint16_t universe, void* context)
296{
297 if (context)
298 {
299 static_cast<Receiver::NotifyHandler*>(context)->HandleSamplingPeriodEnded(Receiver::Handle(handle), universe);
300 }
301}
302
303extern "C" inline void ReceiverCbPapLost(sacn_receiver_t handle, uint16_t universe, const SacnRemoteSource* source,
304 void* context)
305{
306 if (context && source)
307 {
308 static_cast<Receiver::NotifyHandler*>(context)->HandleSourcePapLost(Receiver::Handle(handle), universe, *source);
309 }
310}
311
312extern "C" inline void ReceiverCbSourceLimitExceeded(sacn_receiver_t handle, uint16_t universe, void* context)
313{
314 if (context)
315 {
316 static_cast<Receiver::NotifyHandler*>(context)->HandleSourceLimitExceeded(Receiver::Handle(handle), universe);
317 }
318}
319
320}; // namespace internal
321
331inline Receiver::Settings::Settings(uint16_t new_universe_id) : universe_id(new_universe_id)
332{
333}
334
339{
340 return (universe_id > 0) && (footprint.start_address >= 1) && (footprint.start_address <= DMX_ADDRESS_COUNT) &&
341 (footprint.address_count >= 1) &&
342 (footprint.address_count <= (DMX_ADDRESS_COUNT - footprint.start_address + 1));
343}
344
351 McastMode mcast_mode = McastMode::kEnabledOnAllInterfaces)
352 : handle(receiver_handle), no_netints(mcast_mode == McastMode::kDisabledOnAllInterfaces)
353{
354}
355
363 const std::vector<SacnMcastInterface>& network_interfaces)
364 : handle(receiver_handle), netints(network_interfaces)
365{
366}
367
392inline etcpal::Error Receiver::Startup(const Settings& settings, NotifyHandler& notify_handler,
393 McastMode mcast_mode = McastMode::kEnabledOnAllInterfaces)
394{
395 SacnReceiverConfig config = TranslateConfig(settings, notify_handler);
396
397 SacnNetintConfig netint_config = SACN_NETINT_CONFIG_DEFAULT_INIT;
398 if (mcast_mode == McastMode::kDisabledOnAllInterfaces)
399 netint_config.no_netints = true;
400
402 etcpal::Error result = sacn_receiver_create(&config, &c_handle, &netint_config);
403
404 handle_.SetValue(c_handle);
405
406 return result;
407}
408
435inline etcpal::Error Receiver::Startup(const Settings& settings, NotifyHandler& notify_handler,
437{
438 SacnReceiverConfig config = TranslateConfig(settings, notify_handler);
439
442
443 if (netints.empty())
444 {
445 result = sacn_receiver_create(&config, &c_handle, NULL);
446 }
447 else
448 {
449 SacnNetintConfig netint_config = SACN_NETINT_CONFIG_DEFAULT_INIT;
450 netint_config.netints = netints.data();
451 netint_config.num_netints = netints.size();
452
453 result = sacn_receiver_create(&config, &c_handle, &netint_config);
454 }
455
456 handle_.SetValue(c_handle);
457
458 return result;
459}
460
468{
469 sacn_receiver_destroy(handle_.value());
470 handle_.Clear();
471}
472
479{
480 uint16_t result = 0;
481 etcpal_error_t err = sacn_receiver_get_universe(handle_.value(), &result);
482 if (err == kEtcPalErrOk)
483 return result;
484 else
485 return err;
486}
487
496{
498 etcpal_error_t err = sacn_receiver_get_footprint(handle_.value(), &result);
499 if (err == kEtcPalErrOk)
500 return result;
501 else
502 return err;
503}
504
522inline etcpal::Error Receiver::ChangeUniverse(uint16_t new_universe_id)
523{
524 return sacn_receiver_change_universe(handle_.value(), new_universe_id);
525}
526
538{
539 return sacn_receiver_change_footprint(handle_.value(), &new_footprint);
540}
541
554 const SacnRecvUniverseSubrange& new_footprint)
555{
556 return sacn_receiver_change_universe_and_footprint(handle_.value(), new_universe_id, &new_footprint);
557}
558
565{
566 // This uses a guessing algorithm with a while loop to avoid race conditions.
568 size_t size_guess = 4u;
569 size_t num_netints = 0u;
570
571 do
572 {
573 netints.resize(size_guess);
574 num_netints = sacn_receiver_get_network_interfaces(handle_.value(), netints.data(), netints.size());
575 size_guess = num_netints + 4u;
576 } while (num_netints > netints.size());
577
578 netints.resize(num_netints);
579 return netints;
580}
581
591inline void Receiver::SetExpiredWait(uint32_t wait_ms)
592{
594}
595
606{
608}
609
634inline etcpal::Error Receiver::ResetNetworking(McastMode mcast_mode = McastMode::kEnabledOnAllInterfaces)
635{
636 SacnNetintConfig netint_config = SACN_NETINT_CONFIG_DEFAULT_INIT;
637 if (mcast_mode == McastMode::kDisabledOnAllInterfaces)
638 netint_config.no_netints = true;
639
640 return sacn_receiver_reset_networking(&netint_config);
641}
642
667{
668 if (sys_netints.empty())
669 return sacn_receiver_reset_networking(nullptr);
670
671 SacnNetintConfig netint_config = SACN_NETINT_CONFIG_DEFAULT_INIT;
672 netint_config.netints = sys_netints.data();
673 netint_config.num_netints = sys_netints.size();
674
675 return sacn_receiver_reset_networking(&netint_config);
676}
677
707 std::vector<NetintList>& per_receiver_netint_lists)
708{
710 netint_lists_c.reserve(per_receiver_netint_lists.size());
712 per_receiver_netint_lists.begin(), per_receiver_netint_lists.end(), std::back_inserter(netint_lists_c),
713 [](NetintList& list) {
714 // clang-format off
715 SacnReceiverNetintList c_list = {
716 list.handle,
717 list.netints.data(),
718 list.netints.size(),
719 list.no_netints
720 };
721 // clang-format on
722
723 return c_list;
724 });
725
726 SacnNetintConfig sys_netint_config = SACN_NETINT_CONFIG_DEFAULT_INIT;
727 sys_netint_config.netints = sys_netints.data();
728 sys_netint_config.num_netints = sys_netints.size();
729
730 return sacn_receiver_reset_networking_per_receiver(&sys_netint_config, netint_lists_c.data(), netint_lists_c.size());
731}
732
738inline constexpr Receiver::Handle Receiver::handle() const
739{
740 return handle_;
741}
742
743inline SacnReceiverConfig Receiver::TranslateConfig(const Settings& settings, NotifyHandler& notify_handler)
744{
745 // clang-format off
746 SacnReceiverConfig config = {
747 settings.universe_id,
748 {
749 internal::ReceiverCbUniverseData,
750 internal::ReceiverCbSourcesLost,
751 internal::ReceiverCbSamplingPeriodStarted,
752 internal::ReceiverCbSamplingPeriodEnded,
753 internal::ReceiverCbPapLost,
754 internal::ReceiverCbSourceLimitExceeded,
755 &notify_handler
756 },
757 settings.footprint,
758 settings.source_count_max,
759 settings.flags,
760 settings.ip_supported
761 };
762 // clang-format on
763
764 return config;
765}
766
767}; // namespace sacn
768
769#endif // SACN_CPP_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 receiver.
Definition receiver.h:72
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.
virtual void HandleSamplingPeriodStarted(Handle handle, uint16_t universe)
Notify that a receiver's sampling period has begun.
Definition receiver.h:122
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:163
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 HandleSamplingPeriodEnded(Handle handle, uint16_t universe)
Notify that a receiver's sampling period has ended.
Definition receiver.h:138
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:150
An instance of sACN Receiver functionality; see Using the sACN Receiver API.
Definition receiver.h:62
static uint32_t GetExpiredWait()
Get the current value of the expired notification wait time.
Definition receiver.h:605
static void SetExpiredWait(uint32_t wait_ms)
Set the expired notification wait time.
Definition receiver.h:591
etcpal::Error Startup(const Settings &settings, NotifyHandler &notify_handler, McastMode mcast_mode)
Start listening for sACN data on a universe.
Definition receiver.h:392
std::vector< EtcPalMcastNetintId > GetNetworkInterfaces()
Obtain a vector of this receiver's network interfaces.
Definition receiver.h:564
etcpal::Expected< uint16_t > GetUniverse() const
Get the universe this receiver is listening to.
Definition receiver.h:478
Receiver & operator=(Receiver &&other)=default
etcpal::Error ChangeFootprint(const SacnRecvUniverseSubrange &new_footprint)
Change the footprint within the universe this receiver is listening to. TODO: Not yet implemented.
Definition receiver.h:537
Receiver(Receiver &&other)=default
etcpal::Error ChangeUniverse(uint16_t new_universe_id)
Change the universe this receiver is listening to.
Definition receiver.h:522
etcpal::Expected< SacnRecvUniverseSubrange > GetFootprint() const
Get the footprint within the universe this receiver is listening to.
Definition receiver.h:495
static etcpal::Error ResetNetworking(McastMode mcast_mode)
Resets the underlying network sockets and packet receipt state for all sACN receivers.
Definition receiver.h:634
etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange &new_footprint)
Change the universe and footprint this receiver is listening to. TODO: Not yet implemented.
Definition receiver.h:553
void Shutdown()
Stop listening for sACN data on a universe.
Definition receiver.h:467
constexpr Handle handle() const
Get the current handle to the underlying C receiver.
Definition receiver.h:738
Definition receiver.h:48
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_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:424
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:219
etcpal_error_t sacn_receiver_destroy(sacn_receiver_t handle)
Destroy a sACN receiver instance.
Definition receiver.c:140
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:348
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:522
#define SACN_RECEIVER_INVALID
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. TODO: Not yet implem...
Definition receiver.c:294
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:258
uint32_t sacn_receiver_get_expired_wait()
Get the current value of the expired notification wait time.
Definition receiver.c:568
void sacn_receiver_set_expired_wait(uint32_t wait_ms)
Set the expired notification wait time.
Definition receiver.c:547
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
#define SACN_RECEIVER_INFINITE_SOURCES
Constant for "infinite" when listening or merging sACN universes.
Definition receiver.h:68
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:176
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. TODO: Not yet implemented.
Definition receiver.c:314
int sacn_receiver_t
Definition receiver.h:58
A namespace which contains all C++ language definitions in the sACN library.
Definition common.h:50
McastMode
Definition common.h:53
sACN Receiver API definitions
T reserve(T... args)
T resize(T... args)
T size(T... args)
Definition receiver.h:138
Definition common.h:102
bool no_netints
Definition common.h:110
size_t num_netints
Definition common.h:107
SacnMcastInterface * netints
Definition common.h:105
Definition receiver.h:288
uint16_t universe_id
Definition receiver.h:292
Definition receiver.h:89
Definition receiver.h:80
Definition receiver.h:127
A set of network interfaces for a particular receiver.
Definition receiver.h:209
sacn_receiver_t handle
Definition receiver.h:211
std::vector< SacnMcastInterface > netints
Definition receiver.h:215
bool no_netints
Definition receiver.h:218
A set of configuration settings that a receiver needs to initialize.
Definition receiver.h:175
SacnRecvUniverseSubrange footprint
Definition receiver.h:183
uint16_t universe_id
Definition receiver.h:178
int source_count_max
Definition receiver.h:188
sacn_ip_support_t ip_supported
Definition receiver.h:191
bool IsValid() const
Definition receiver.h:338
unsigned int flags
Definition receiver.h:189
T transform(T... args)