sACN  2.0.2
Implementation of ANSI E1.31 (Streaming ACN)
View other versions:
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"
34 #include "etcpal/cpp/opaque_id.h"
35 
42 namespace sacn
43 {
44 
45 namespace detail
46 {
48 {
49 };
50 }; // namespace detail
51 
61 class Receiver
62 {
63 public:
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 
199  struct NetintList
200  {
203 
207 
209  NetintList() = default;
210  NetintList(sacn_receiver_t receiver_handle);
211  };
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 
241 private:
242  SacnReceiverConfig TranslateConfig(const Settings& settings, NotifyHandler& notify_handler);
243 
244  Handle handle_;
245 };
246 
251 namespace internal
252 {
253 extern "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 
264 extern "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 
274 extern "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 
282 extern "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 
290 extern "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 
299 extern "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 
318 inline Receiver::Settings::Settings(uint16_t new_universe_id) : universe_id(new_universe_id)
319 {
320 }
321 
325 inline bool Receiver::Settings::IsValid() const
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 
337 inline Receiver::NetintList::NetintList(sacn_receiver_t receiver_handle) : handle(receiver_handle)
338 {
339 }
340 
363 inline etcpal::Error Receiver::Startup(const Settings& settings, NotifyHandler& notify_handler)
364 {
366  return Startup(settings, notify_handler, netints);
367 }
368 
395 inline etcpal::Error Receiver::Startup(const Settings& settings, NotifyHandler& notify_handler,
397 {
398  SacnReceiverConfig config = TranslateConfig(settings, notify_handler);
399 
401  etcpal::Error result = kEtcPalErrOk;
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 
424 inline void Receiver::Shutdown()
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 
479 inline 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 
510 inline etcpal::Error Receiver::ChangeUniverseAndFootprint(uint16_t new_universe_id,
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 
548 inline void Receiver::SetExpiredWait(uint32_t wait_ms)
549 {
551 }
552 
562 inline uint32_t Receiver::GetExpiredWait()
563 {
565 }
566 
590 {
592  return ResetNetworking(netints);
593 }
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 
682 inline constexpr Receiver::Handle Receiver::handle() const
683 {
684  return handle_;
685 }
686 
687 inline 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
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
etcpal::OpaqueId< detail::ReceiverHandleType, sacn_receiver_t, SACN_RECEIVER_INVALID > Handle
Definition: receiver.h:65
Receiver(Receiver &&other)=default
Receiver & operator=(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)