sACN  2.0.1
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 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_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
118 virtual void HandleSamplingPeriodStarted(Handle handle, uint16_t universe)
119 {
120 ETCPAL_UNUSED_ARG(handle);
121 ETCPAL_UNUSED_ARG(universe);
122 }
123
129 virtual void HandleSamplingPeriodEnded(Handle handle, uint16_t universe)
130 {
131 ETCPAL_UNUSED_ARG(handle);
132 ETCPAL_UNUSED_ARG(universe);
133 }
134
141 virtual void HandleSourcePapLost(Handle handle, uint16_t universe, const SacnRemoteSource& source)
142 {
143 ETCPAL_UNUSED_ARG(handle);
144 ETCPAL_UNUSED_ARG(universe);
145 ETCPAL_UNUSED_ARG(source);
146 }
147
154 virtual void HandleSourceLimitExceeded(Handle handle, uint16_t universe)
155 {
156 ETCPAL_UNUSED_ARG(handle);
157 ETCPAL_UNUSED_ARG(universe);
158 }
159 };
160
165 struct Settings
166 {
167 /********* Required values **********/
168
169 uint16_t universe_id{0};
171 /********* Optional values **********/
172
175
180 unsigned int flags{0};
185 Settings() = default;
186
190 Settings(uint16_t new_universe_id);
191
192 bool IsValid() const;
193 };
194
212
213 Receiver() = default;
214 Receiver(const Receiver& other) = delete;
215 Receiver& operator=(const Receiver& other) = delete;
216 Receiver(Receiver&& other) = default;
217 Receiver& operator=(Receiver&& other) = default;
219 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler);
220 etcpal::Error Startup(const Settings& settings, NotifyHandler& notify_handler,
222 void Shutdown();
225 etcpal::Error ChangeUniverse(uint16_t new_universe_id);
227 etcpal::Error ChangeUniverseAndFootprint(uint16_t new_universe_id, const SacnRecvUniverseSubrange& new_footprint);
229
230 // Lesser used functions. These apply to all instances of this class.
231 static void SetExpiredWait(uint32_t wait_ms);
232 static uint32_t GetExpiredWait();
233
237 std::vector<NetintList>& netint_lists);
238
239 constexpr Handle handle() const;
240
241private:
242 SacnReceiverConfig TranslateConfig(const Settings& settings, NotifyHandler& notify_handler);
243
244 Handle handle_;
245};
246
251namespace internal
252{
253extern "C" inline void ReceiverCbUniverseData(sacn_receiver_t receiver_handle, const EtcPalSockAddr* source_addr,
254 const SacnRemoteSource* source_info,
255 const SacnRecvUniverseData* universe_data, void* context)
256{
257 if (source_addr && source_info && universe_data && context)
258 {
259 static_cast<Receiver::NotifyHandler*>(context)->HandleUniverseData(Receiver::Handle(receiver_handle), *source_addr,
260 *source_info, *universe_data);
261 }
262}
263
264extern "C" inline void ReceiverCbSourcesLost(sacn_receiver_t handle, uint16_t universe,
265 const SacnLostSource* lost_sources, size_t num_lost_sources, void* context)
266{
267 if (context && lost_sources && (num_lost_sources > 0))
268 {
269 std::vector<SacnLostSource> lost_vec(lost_sources, lost_sources + num_lost_sources);
270 static_cast<Receiver::NotifyHandler*>(context)->HandleSourcesLost(Receiver::Handle(handle), universe, lost_vec);
271 }
272}
273
274extern "C" inline void ReceiverCbSamplingPeriodStarted(sacn_receiver_t handle, uint16_t universe, void* context)
275{
276 if (context)
277 {
278 static_cast<Receiver::NotifyHandler*>(context)->HandleSamplingPeriodStarted(Receiver::Handle(handle), universe);
279 }
280}
281
282extern "C" inline void ReceiverCbSamplingPeriodEnded(sacn_receiver_t handle, uint16_t universe, void* context)
283{
284 if (context)
285 {
286 static_cast<Receiver::NotifyHandler*>(context)->HandleSamplingPeriodEnded(Receiver::Handle(handle), universe);
287 }
288}
289
290extern "C" inline void ReceiverCbPapLost(sacn_receiver_t handle, uint16_t universe, const SacnRemoteSource* source,
291 void* context)
292{
293 if (context && source)
294 {
295 static_cast<Receiver::NotifyHandler*>(context)->HandleSourcePapLost(Receiver::Handle(handle), universe, *source);
296 }
297}
298
299extern "C" inline void ReceiverCbSourceLimitExceeded(sacn_receiver_t handle, uint16_t universe, void* context)
300{
301 if (context)
302 {
303 static_cast<Receiver::NotifyHandler*>(context)->HandleSourceLimitExceeded(Receiver::Handle(handle), universe);
304 }
305}
306
307}; // namespace internal
308
318inline Receiver::Settings::Settings(uint16_t new_universe_id) : universe_id(new_universe_id)
319{
320}
321
326{
327 return (universe_id > 0) && (footprint.start_address >= 1) && (footprint.start_address <= DMX_ADDRESS_COUNT) &&
328 (footprint.address_count >= 1) &&
329 (footprint.address_count <= (DMX_ADDRESS_COUNT - footprint.start_address + 1));
330}
331
337inline Receiver::NetintList::NetintList(sacn_receiver_t receiver_handle) : handle(receiver_handle)
338{
339}
340
363inline etcpal::Error Receiver::Startup(const Settings& settings, NotifyHandler& notify_handler)
364{
366 return Startup(settings, notify_handler, netints);
367}
368
395inline etcpal::Error Receiver::Startup(const Settings& settings, NotifyHandler& notify_handler,
397{
398 SacnReceiverConfig config = TranslateConfig(settings, notify_handler);
399
402
403 if (netints.empty())
404 {
405 result = sacn_receiver_create(&config, &c_handle, NULL);
406 }
407 else
408 {
409 SacnNetintConfig netint_config = {netints.data(), netints.size()};
410 result = sacn_receiver_create(&config, &c_handle, &netint_config);
411 }
412
413 handle_.SetValue(c_handle);
414
415 return result;
416}
417
425{
426 sacn_receiver_destroy(handle_.value());
427 handle_.Clear();
428}
429
436{
437 uint16_t result = 0;
438 etcpal_error_t err = sacn_receiver_get_universe(handle_.value(), &result);
439 if (err == kEtcPalErrOk)
440 return result;
441 else
442 return err;
443}
444
453{
455 etcpal_error_t err = sacn_receiver_get_footprint(handle_.value(), &result);
456 if (err == kEtcPalErrOk)
457 return result;
458 else
459 return err;
460}
461
479inline etcpal::Error Receiver::ChangeUniverse(uint16_t new_universe_id)
480{
481 return sacn_receiver_change_universe(handle_.value(), new_universe_id);
482}
483
495{
496 return sacn_receiver_change_footprint(handle_.value(), &new_footprint);
497}
498
511 const SacnRecvUniverseSubrange& new_footprint)
512{
513 return sacn_receiver_change_universe_and_footprint(handle_.value(), new_universe_id, &new_footprint);
514}
515
522{
523 // This uses a guessing algorithm with a while loop to avoid race conditions.
525 size_t size_guess = 4u;
526 size_t num_netints = 0u;
527
528 do
529 {
530 netints.resize(size_guess);
531 num_netints = sacn_receiver_get_network_interfaces(handle_.value(), netints.data(), netints.size());
532 size_guess = num_netints + 4u;
533 } while (num_netints > netints.size());
534
535 netints.resize(num_netints);
536 return netints;
537}
538
548inline void Receiver::SetExpiredWait(uint32_t wait_ms)
549{
551}
552
563{
565}
566
594
619{
620 if (sys_netints.empty())
621 return sacn_receiver_reset_networking(nullptr);
622
623 SacnNetintConfig netint_config = {sys_netints.data(), sys_netints.size()};
624 return sacn_receiver_reset_networking(&netint_config);
625}
626
656 std::vector<NetintList>& per_receiver_netint_lists)
657{
659 netint_lists_c.reserve(per_receiver_netint_lists.size());
660 std::transform(per_receiver_netint_lists.begin(), per_receiver_netint_lists.end(), std::back_inserter(netint_lists_c),
661 [](NetintList& list) {
662 // clang-format off
663 SacnReceiverNetintList c_list = {
664 list.handle,
665 list.netints.data(),
666 list.netints.size()
667 };
668 // clang-format on
669
670 return c_list;
671 });
672
673 SacnNetintConfig sys_netint_config = {sys_netints.data(), sys_netints.size()};
674 return sacn_receiver_reset_networking_per_receiver(&sys_netint_config, netint_lists_c.data(), netint_lists_c.size());
675}
676
682inline constexpr Receiver::Handle Receiver::handle() const
683{
684 return handle_;
685}
686
687inline SacnReceiverConfig Receiver::TranslateConfig(const Settings& settings, NotifyHandler& notify_handler)
688{
689 // clang-format off
690 SacnReceiverConfig config = {
691 settings.universe_id,
692 {
693 internal::ReceiverCbUniverseData,
694 internal::ReceiverCbSourcesLost,
695 internal::ReceiverCbSamplingPeriodStarted,
696 internal::ReceiverCbSamplingPeriodEnded,
697 internal::ReceiverCbPapLost,
698 internal::ReceiverCbSourceLimitExceeded,
699 &notify_handler
700 },
701 settings.footprint,
702 settings.source_count_max,
703 settings.flags,
704 settings.ip_supported
705 };
706 // clang-format on
707
708 return config;
709}
710
711}; // namespace sacn
712
713#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:118
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:154
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:129
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:141
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:562
static void SetExpiredWait(uint32_t wait_ms)
Set the expired notification wait time.
Definition receiver.h:548
static etcpal::Error ResetNetworking()
Resets the underlying network sockets and packet receipt state for all sACN receivers.
Definition receiver.h:589
std::vector< EtcPalMcastNetintId > GetNetworkInterfaces()
Obtain a vector of this receiver's network interfaces.
Definition receiver.h:521
etcpal::Expected< uint16_t > GetUniverse() const
Get the universe this receiver is listening to.
Definition receiver.h:435
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:494
Receiver(Receiver &&other)=default
etcpal::Error ChangeUniverse(uint16_t new_universe_id)
Change the universe this receiver is listening to.
Definition receiver.h:479
etcpal::Expected< SacnRecvUniverseSubrange > GetFootprint() const
Get the footprint within the universe this receiver is listening to.
Definition receiver.h:452
etcpal::Error Startup(const Settings &settings, NotifyHandler &notify_handler)
Start listening for sACN data on a universe.
Definition receiver.h:363
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:510
void Shutdown()
Stop listening for sACN data on a universe.
Definition receiver.h:424
constexpr Handle handle() const
Get the current handle to the underlying C receiver.
Definition receiver.h:682
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:418
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:216
etcpal_error_t sacn_receiver_destroy(sacn_receiver_t handle)
Destroy a sACN receiver instance.
Definition receiver.c:139
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:345
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:505
#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:291
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:255
uint32_t sacn_receiver_get_expired_wait()
Get the current value of the expired notification wait time.
Definition receiver.c:551
void sacn_receiver_set_expired_wait(uint32_t wait_ms)
Set the expired notification wait time.
Definition receiver.c:530
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:173
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:311
int sacn_receiver_t
Definition receiver.h:58
A namespace which contains all C++ language definitions in the sACN library.
Definition common.h:50
sACN Receiver API definitions
T reserve(T... args)
T resize(T... args)
T size(T... args)
Definition receiver.h:135
Definition common.h:102
Definition receiver.h:276
uint16_t universe_id
Definition receiver.h:280
Definition receiver.h:89
Definition receiver.h:80
Definition receiver.h:124
A set of network interfaces for a particular receiver.
Definition receiver.h:200
sacn_receiver_t handle
Definition receiver.h:202
std::vector< SacnMcastInterface > netints
Definition receiver.h:206
A set of configuration settings that a receiver needs to initialize.
Definition receiver.h:166
SacnRecvUniverseSubrange footprint
Definition receiver.h:174
uint16_t universe_id
Definition receiver.h:169
int source_count_max
Definition receiver.h:179
sacn_ip_support_t ip_supported
Definition receiver.h:182
bool IsValid() const
Definition receiver.h:325
unsigned int flags
Definition receiver.h:180
T transform(T... args)