sACN  2.0.2
Implementation of ANSI E1.31 (Streaming ACN)
View other versions:
source.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_SOURCE_H_
21 #define SACN_CPP_SOURCE_H_
22 
28 #include "sacn/cpp/common.h"
29 
30 #include <cstring>
31 #include "sacn/source.h"
32 #include "etcpal/cpp/uuid.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 
60 class Source
61 {
62 public:
65 
70  struct Settings
71  {
72  /********* Required values **********/
73 
78 
79  /********* Optional values **********/
80 
83 
88 
91 
95 
97  Settings() = default;
98  Settings(const etcpal::Uuid& new_cid, const std::string& new_name);
99 
100  bool IsValid() const;
101  };
102 
108  {
109  /********* Required values **********/
110 
113  uint16_t universe{0};
114 
115  /********* Optional values **********/
116 
119  uint8_t priority{100};
120 
122  bool send_preview{false};
123 
125  bool send_unicast_only{false};
126 
130 
133  uint16_t sync_universe{0};
134 
136  UniverseSettings() = default;
137  UniverseSettings(uint16_t universe_id);
138 
139  bool IsValid() const;
140  };
141 
147  {
151  uint16_t universe;
152 
156 
158  UniverseNetintList() = default;
159  UniverseNetintList(sacn_source_t source_handle, uint16_t universe_id);
160  UniverseNetintList(sacn_source_t source_handle, uint16_t universe_id,
161  const std::vector<SacnMcastInterface>& network_interfaces);
162  };
163 
164  Source() = default;
165  Source(const Source& other) = delete;
166  Source& operator=(const Source& other) = delete;
167  Source(Source&& other) = default;
168  Source& operator=(Source&& other) = default;
170  etcpal::Error Startup(const Settings& settings);
171  void Shutdown();
172 
173  etcpal::Error ChangeName(const std::string& new_name);
174 
175  etcpal::Error AddUniverse(const UniverseSettings& settings);
177  void RemoveUniverse(uint16_t universe);
179 
180  etcpal::Error AddUnicastDestination(uint16_t universe, const etcpal::IpAddr& dest);
181  void RemoveUnicastDestination(uint16_t universe, const etcpal::IpAddr& dest);
183 
184  etcpal::Error ChangePriority(uint16_t universe, uint8_t new_priority);
185  etcpal::Error ChangePreviewFlag(uint16_t universe, bool new_preview_flag);
186  etcpal::Error ChangeSynchronizationUniverse(uint16_t universe, uint16_t new_sync_universe);
187 
188  etcpal::Error SendNow(uint16_t universe, uint8_t start_code, const uint8_t* buffer, size_t buflen);
189  etcpal::Error SendSynchronization(uint16_t universe);
190 
191  void UpdateLevels(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size);
192  void UpdateLevelsAndPap(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size,
193  const uint8_t* new_priorities, size_t new_priorities_size);
194  void UpdateLevelsAndForceSync(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size);
195  void UpdateLevelsAndPapAndForceSync(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size,
196  const uint8_t* new_priorities, size_t new_priorities_size);
197 
199 
200  constexpr Handle handle() const;
201 
202  static int ProcessManual();
203 
207  std::vector<UniverseNetintList>& netint_lists);
208 
209 private:
210  class TranslatedUniverseConfig
211  {
212  public:
213  explicit TranslatedUniverseConfig(const UniverseSettings& settings);
214  const SacnSourceUniverseConfig& get() noexcept;
215 
216  private:
217  std::vector<EtcPalIpAddr> unicast_destinations_;
218  SacnSourceUniverseConfig config_;
219  };
220 
221  SacnSourceConfig TranslateConfig(const Settings& settings);
222 
223  Handle handle_;
224 };
225 
231 inline Source::Settings::Settings(const etcpal::Uuid& new_cid, const std::string& new_name)
232  : cid(new_cid), name(new_name)
233 {
234 }
235 
239 inline bool Source::Settings::IsValid() const
240 {
241  return !cid.IsNull();
242 }
243 
249 inline Source::UniverseSettings::UniverseSettings(uint16_t universe_id) : universe(universe_id)
250 {
251 }
252 
257 {
258  return ((universe != 0) && (universe < 64000));
259 }
260 
266 inline Source::UniverseNetintList::UniverseNetintList(sacn_source_t source_handle, uint16_t universe_id)
267  : handle(source_handle), universe(universe_id)
268 {
269 }
270 
277 inline Source::UniverseNetintList::UniverseNetintList(sacn_source_t source_handle, uint16_t universe_id,
278  const std::vector<SacnMcastInterface>& network_interfaces)
279  : handle(source_handle), universe(universe_id), netints(network_interfaces)
280 {
281 }
282 
299 inline etcpal::Error Source::Startup(const Settings& settings)
300 {
301  SacnSourceConfig config = TranslateConfig(settings);
303  etcpal::Error result = sacn_source_create(&config, &c_handle);
304  handle_.SetValue(c_handle);
305  return result;
306 }
307 
315 inline void Source::Shutdown()
316 {
317  sacn_source_destroy(handle_.value());
318  handle_.Clear();
319 }
320 
340 {
341  return sacn_source_change_name(handle_.value(), new_name.c_str());
342 }
343 
367 {
368  TranslatedUniverseConfig config(settings);
369  return sacn_source_add_universe(handle_.value(), &config.get(), nullptr);
370 }
371 
397 {
398  TranslatedUniverseConfig config(settings);
399 
400  if (netints.empty())
401  return sacn_source_add_universe(handle_.value(), &config.get(), nullptr);
402 
403  SacnNetintConfig netint_config = {netints.data(), netints.size()};
404  return sacn_source_add_universe(handle_.value(), &config.get(), &netint_config);
405 }
406 
418 inline void Source::RemoveUniverse(uint16_t universe)
419 {
420  sacn_source_remove_universe(handle_.value(), universe);
421 }
422 
429 {
430  // This uses a guessing algorithm with a while loop to avoid race conditions.
431  std::vector<uint16_t> universes;
432  size_t size_guess = 4u;
433  size_t num_universes = 0u;
434 
435  do
436  {
437  universes.resize(size_guess);
438  num_universes = sacn_source_get_universes(handle_.value(), universes.data(), universes.size());
439  size_guess = num_universes + 4u;
440  } while (num_universes > universes.size());
441 
442  universes.resize(num_universes);
443  return universes;
444 }
445 
461 inline etcpal::Error Source::AddUnicastDestination(uint16_t universe, const etcpal::IpAddr& dest)
462 {
463  return sacn_source_add_unicast_destination(handle_.value(), universe, &dest.get());
464 }
465 
475 inline void Source::RemoveUnicastDestination(uint16_t universe, const etcpal::IpAddr& dest)
476 {
477  sacn_source_remove_unicast_destination(handle_.value(), universe, &dest.get());
478 }
479 
487 {
488  // This uses a guessing algorithm with a while loop to avoid race conditions.
489  std::vector<EtcPalIpAddr> destinations;
490  size_t size_guess = 4u;
491  size_t num_destinations = 0u;
492 
493  do
494  {
495  destinations.resize(size_guess);
496  num_destinations =
497  sacn_source_get_unicast_destinations(handle_.value(), universe, destinations.data(), destinations.size());
498  size_guess = num_destinations + 4u;
499  } while (num_destinations > destinations.size());
500 
501  destinations.resize(num_destinations);
502 
503  // Convert vector<EtcPalIpAddr> to vector<etcpal::IpAddr>.
505  if (!destinations.empty())
506  {
507  result.reserve(destinations.size());
508  std::transform(destinations.begin(), destinations.end(), std::back_inserter(result),
509  [](const EtcPalIpAddr& dest) { return etcpal::IpAddr(dest); });
510  }
511 
512  return result;
513 }
514 
530 inline etcpal::Error Source::ChangePriority(uint16_t universe, uint8_t new_priority)
531 {
532  return sacn_source_change_priority(handle_.value(), universe, new_priority);
533 }
534 
553 inline etcpal::Error Source::ChangePreviewFlag(uint16_t universe, bool new_preview_flag)
554 {
555  return sacn_source_change_preview_flag(handle_.value(), universe, new_preview_flag);
556 }
557 
577 inline etcpal::Error Source::ChangeSynchronizationUniverse(uint16_t universe, uint16_t new_sync_universe)
578 {
579  return sacn_source_change_synchronization_universe(handle_.value(), universe, new_sync_universe);
580 }
581 
600 inline etcpal::Error Source::SendNow(uint16_t universe, uint8_t start_code, const uint8_t* buffer, size_t buflen)
601 {
602  return sacn_source_send_now(handle_.value(), universe, start_code, buffer, buflen);
603 }
604 
620 inline etcpal::Error Source::SendSynchronization(uint16_t sync_universe)
621 {
622  return sacn_source_send_synchronization(handle_.value(), sync_universe);
623 }
624 
638 inline void Source::UpdateLevels(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size)
639 {
640  sacn_source_update_levels(handle_.value(), universe, new_levels, new_levels_size);
641 }
642 
665 inline void Source::UpdateLevelsAndPap(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size,
666  const uint8_t* new_priorities, size_t new_priorities_size)
667 {
668  sacn_source_update_levels_and_pap(handle_.value(), universe, new_levels, new_levels_size, new_priorities,
669  new_priorities_size);
670 }
671 
688 inline void Source::UpdateLevelsAndForceSync(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size)
689 {
690  sacn_source_update_levels_and_force_sync(handle_.value(), universe, new_levels, new_levels_size);
691 }
692 
719 inline void Source::UpdateLevelsAndPapAndForceSync(uint16_t universe, const uint8_t* new_levels, size_t new_levels_size,
720  const uint8_t* new_priorities, size_t new_priorities_size)
721 {
722  sacn_source_update_levels_and_pap_and_force_sync(handle_.value(), universe, new_levels, new_levels_size,
723  new_priorities, new_priorities_size);
724 }
725 
743 {
745 }
746 
772 {
774  return ResetNetworking(netints);
775 }
776 
802 {
803  if (sys_netints.empty())
804  return sacn_source_reset_networking(nullptr);
805 
806  SacnNetintConfig netint_config = {sys_netints.data(), sys_netints.size()};
807  return sacn_source_reset_networking(&netint_config);
808 }
809 
840  std::vector<UniverseNetintList>& per_universe_netint_lists)
841 {
843  netint_lists_c.reserve(per_universe_netint_lists.size());
845  per_universe_netint_lists.begin(), per_universe_netint_lists.end(), std::back_inserter(netint_lists_c),
846  [](UniverseNetintList& list) {
847  // clang-format off
848  SacnSourceUniverseNetintList c_list = {
849  list.handle,
850  list.universe,
851  list.netints.data(),
852  list.netints.size()
853  };
854  // clang-format on
855 
856  return c_list;
857  });
858 
859  SacnNetintConfig sys_netint_config = {sys_netints.data(), sys_netints.size()};
860  return sacn_source_reset_networking_per_universe(&sys_netint_config, netint_lists_c.data(), netint_lists_c.size());
861 }
862 
870 {
871  // This uses a guessing algorithm with a while loop to avoid race conditions.
873  size_t size_guess = 4u;
874  size_t num_netints = 0u;
875 
876  do
877  {
878  netints.resize(size_guess);
879  num_netints = sacn_source_get_network_interfaces(handle_.value(), universe, netints.data(), netints.size());
880  size_guess = num_netints + 4u;
881  } while (num_netints > netints.size());
882 
883  netints.resize(num_netints);
884  return netints;
885 }
886 
892 inline constexpr Source::Handle Source::handle() const
893 {
894  return handle_;
895 }
896 
897 inline SacnSourceConfig Source::TranslateConfig(const Settings& settings)
898 {
899  // clang-format off
900  SacnSourceConfig config = {
901  settings.cid.get(),
902  settings.name.c_str(),
903  settings.universe_count_max,
904  settings.manually_process_source,
905  settings.ip_supported,
906  settings.keep_alive_interval
907  };
908  // clang-format on
909 
910  return config;
911 }
912 
913 inline const SacnSourceUniverseConfig& Source::TranslatedUniverseConfig::get() noexcept
914 {
915  if (!unicast_destinations_.empty())
916  {
917  config_.unicast_destinations = unicast_destinations_.data();
918  config_.num_unicast_destinations = unicast_destinations_.size();
919  }
920 
921  return config_;
922 }
923 
924 // clang-format off
925 inline Source::TranslatedUniverseConfig::TranslatedUniverseConfig(const UniverseSettings& settings)
926  : config_{
927  settings.universe,
928  settings.priority,
929  settings.send_preview,
930  settings.send_unicast_only,
931  nullptr,
932  0,
933  settings.sync_universe
934  }
935 {
936  // clang-format on
937 
938  if (!settings.unicast_destinations.empty())
939  {
940  unicast_destinations_.reserve(settings.unicast_destinations.size());
941  std::transform(settings.unicast_destinations.begin(), settings.unicast_destinations.end(),
942  std::back_inserter(unicast_destinations_), [](const etcpal::IpAddr& dest) { return dest.get(); });
943  }
944 }
945 
946 }; // namespace sacn
947 
948 #endif // SACN_CPP_SOURCE_H_
T back_inserter(T... args)
T begin(T... args)
T c_str(T... args)
constexpr const EtcPalIpAddr & get() const noexcept
ETCPAL_CONSTEXPR_14 void Clear()
ETCPAL_CONSTEXPR_14 void SetValue(const ValueType &new_value)
constexpr ValueType value() const
An instance of sACN Source functionality; see Using the sACN Source API.
Definition: source.h:61
static etcpal::Error ResetNetworking()
Resets the underlying network sockets for all universes of all sources.
Definition: source.h:771
void RemoveUnicastDestination(uint16_t universe, const etcpal::IpAddr &dest)
Remove a unicast destination on a universe.
Definition: source.h:475
etcpal::Error SendNow(uint16_t universe, uint8_t start_code, const uint8_t *buffer, size_t buflen)
Immediately sends the provided sACN start code & data.
Definition: source.h:600
etcpal::Error ChangePriority(uint16_t universe, uint8_t new_priority)
Change the priority of a universe.
Definition: source.h:530
void UpdateLevelsAndPap(uint16_t universe, const uint8_t *new_levels, size_t new_levels_size, const uint8_t *new_priorities, size_t new_priorities_size)
Copies the universe's DMX levels and per-address priorities into packets that are sent on the next th...
Definition: source.h:665
etcpal::Error ChangePreviewFlag(uint16_t universe, bool new_preview_flag)
Change the send_preview option on a universe.
Definition: source.h:553
constexpr Handle handle() const
Get the current handle to the underlying C source.
Definition: source.h:892
etcpal::Error AddUnicastDestination(uint16_t universe, const etcpal::IpAddr &dest)
Add a unicast destination for a universe.
Definition: source.h:461
etcpal::Error ChangeSynchronizationUniverse(uint16_t universe, uint16_t new_sync_universe)
Changes the synchronization universe for a universe.
Definition: source.h:577
Source & operator=(Source &&other)=default
std::vector< etcpal::IpAddr > GetUnicastDestinations(uint16_t universe)
Obtain a vector of a universe's unicast destinations.
Definition: source.h:486
void RemoveUniverse(uint16_t universe)
Remove a universe from a source.
Definition: source.h:418
etcpal::Error ChangeName(const std::string &new_name)
Change the name of an sACN source.
Definition: source.h:339
etcpal::Error Startup(const Settings &settings)
Create a new sACN source to send sACN data.
Definition: source.h:299
Source(Source &&other)=default
void UpdateLevelsAndForceSync(uint16_t universe, const uint8_t *new_levels, size_t new_levels_size)
Like UpdateLevels(), but also sets the force_sync flag on the packet.
Definition: source.h:688
std::vector< EtcPalMcastNetintId > GetNetworkInterfaces(uint16_t universe)
Obtain a vector of a universe's network interfaces.
Definition: source.h:869
void Shutdown()
Destroy an sACN source instance.
Definition: source.h:315
void UpdateLevels(uint16_t universe, const uint8_t *new_levels, size_t new_levels_size)
Copies the universe's DMX levels into the packet to be sent on the next threaded or manual update.
Definition: source.h:638
static int ProcessManual()
Trigger the transmission of sACN packets for all universes of sources that were created with manually...
Definition: source.h:742
etcpal::Error AddUniverse(const UniverseSettings &settings)
Add a universe to an sACN source, which will use all network interfaces.
Definition: source.h:366
std::vector< uint16_t > GetUniverses()
Obtain a vector of this source's universes.
Definition: source.h:428
void UpdateLevelsAndPapAndForceSync(uint16_t universe, const uint8_t *new_levels, size_t new_levels_size, const uint8_t *new_priorities, size_t new_priorities_size)
Like UpdateLevelsAndPap(), but also sets the force_sync flag on the packet.
Definition: source.h:719
etcpal::Error SendSynchronization(uint16_t universe)
Indicate that a new synchronization packet should be sent on the given synchronization universe.
Definition: source.h:620
Definition: source.h:48
C++ wrapper for the sACN init/deinit functions.
T data(T... args)
T empty(T... args)
T end(T... args)
sacn_ip_support_t
Definition: common.h:71
@ kSacnIpV4AndIpV6
Definition: common.h:77
int sacn_source_process_manual(void)
Trigger the transmission of sACN packets for all universes of sources that were created with manually...
Definition: source.c:990
etcpal_error_t sacn_source_change_name(sacn_source_t handle, const char *new_name)
Change the name of an sACN source.
Definition: source.c:168
etcpal_error_t sacn_source_send_synchronization(sacn_source_t handle, uint16_t universe)
Indicate that a new synchronization packet should be sent on the given synchronization universe.
Definition: source.c:780
etcpal_error_t sacn_source_change_priority(sacn_source_t handle, uint16_t universe, uint8_t new_priority)
Change the priority of a universe on a sACN source.
Definition: source.c:554
size_t sacn_source_get_unicast_destinations(sacn_source_t handle, uint16_t universe, EtcPalIpAddr *destinations, size_t destinations_size)
Obtain a list of a universe's unicast destinations.
Definition: source.c:516
#define SACN_SOURCE_INFINITE_UNIVERSES
Constant for "infinite" when sending sACN universes.
Definition: source.h:66
etcpal_error_t sacn_source_add_universe(sacn_source_t handle, const SacnSourceUniverseConfig *config, const SacnNetintConfig *netint_config)
Add a universe to an sACN source.
Definition: source.c:261
void sacn_source_update_levels(sacn_source_t handle, uint16_t universe, const uint8_t *new_levels, size_t new_levels_size)
Copies the universe's DMX levels into the packet to be sent on the next threaded or manual update.
Definition: source.c:804
etcpal_error_t sacn_source_add_unicast_destination(sacn_source_t handle, uint16_t universe, const EtcPalIpAddr *dest)
Add a unicast destination for a source's universe.
Definition: source.c:406
etcpal_error_t sacn_source_reset_networking(const SacnNetintConfig *sys_netint_config)
Resets the underlying network sockets for all universes of all sources.
Definition: source.c:1020
etcpal_error_t sacn_source_create(const SacnSourceConfig *config, sacn_source_t *handle)
Create a new sACN source to send sACN data.
Definition: source.c:103
#define SACN_SOURCE_INVALID
Definition: source.h:58
void sacn_source_remove_unicast_destination(sacn_source_t handle, uint16_t universe, const EtcPalIpAddr *dest)
Remove a unicast destination on a source's universe.
Definition: source.c:481
void sacn_source_update_levels_and_force_sync(sacn_source_t handle, uint16_t universe, const uint8_t *new_levels, size_t new_levels_size)
Like sacn_source_update_levels(), but also sets the force_sync flag on the packet.
Definition: source.c:895
void sacn_source_update_levels_and_pap(sacn_source_t handle, uint16_t universe, const uint8_t *new_levels, size_t new_levels_size, const uint8_t *new_priorities, size_t new_priorities_size)
Copies the universe's DMX levels and per-address priorities into packets that are sent on the next th...
Definition: source.c:852
etcpal_error_t sacn_source_send_now(sacn_source_t handle, uint16_t universe, uint8_t start_code, const uint8_t *buffer, size_t buflen)
Immediately sends the provided sACN start code & data.
Definition: source.c:707
void sacn_source_remove_universe(sacn_source_t handle, uint16_t universe)
Remove a universe from a source.
Definition: source.c:349
size_t sacn_source_get_universes(sacn_source_t handle, uint16_t *universes, size_t universes_size)
Obtain a list of a source's universes.
Definition: source.c:373
etcpal_error_t sacn_source_change_preview_flag(sacn_source_t handle, uint16_t universe, bool new_preview_flag)
Change the send_preview option on a universe of a sACN source.
Definition: source.c:615
#define SACN_SOURCE_KEEP_ALIVE_INTERVAL_DEFAULT
Definition: source.h:69
void sacn_source_update_levels_and_pap_and_force_sync(sacn_source_t handle, uint16_t universe, const uint8_t *new_levels, size_t new_levels_size, const uint8_t *new_priorities, size_t new_priorities_size)
Like sacn_source_update_levels_and_pap(), but also sets the force_sync flag on the packet.
Definition: source.c:948
etcpal_error_t sacn_source_change_synchronization_universe(sacn_source_t handle, uint16_t universe, uint16_t new_sync_universe)
Changes the synchronization universe for a universe of a sACN source.
Definition: source.c:677
etcpal_error_t sacn_source_reset_networking_per_universe(const SacnNetintConfig *sys_netint_config, const SacnSourceUniverseNetintList *per_universe_netint_lists, size_t num_per_universe_netint_lists)
Resets the underlying network sockets and determines network interfaces for each universe of each sou...
Definition: source.c:1084
int sacn_source_t
Definition: source.h:56
size_t sacn_source_get_network_interfaces(sacn_source_t handle, uint16_t universe, EtcPalMcastNetintId *netints, size_t netints_size)
Obtain a list of a universe's network interfaces.
Definition: source.c:1176
void sacn_source_destroy(sacn_source_t handle)
Destroy an sACN source instance.
Definition: source.c:218
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)
sACN Source API definitions
Definition: common.h:102
Definition: source.h:73
EtcPalUuid cid
Definition: source.h:77
Definition: source.h:112
const EtcPalIpAddr * unicast_destinations
Definition: source.h:133
A set of configuration settings that a source needs to initialize.
Definition: source.h:71
bool manually_process_source
Definition: source.h:87
int keep_alive_interval
Definition: source.h:94
std::string name
Definition: source.h:77
sacn_ip_support_t ip_supported
Definition: source.h:90
etcpal::Uuid cid
Definition: source.h:75
bool IsValid() const
Definition: source.h:239
size_t universe_count_max
Definition: source.h:82
A set of network interfaces for a particular universe.
Definition: source.h:147
uint16_t universe
Definition: source.h:151
std::vector< SacnMcastInterface > netints
Definition: source.h:155
sacn_source_t handle
Definition: source.h:149
A set of configuration settings for a new universe on a source.
Definition: source.h:108
uint8_t priority
Definition: source.h:119
uint16_t universe
Definition: source.h:113
bool send_preview
Definition: source.h:122
uint16_t sync_universe
Definition: source.h:133
const std::vector< etcpal::IpAddr > unicast_destinations
Definition: source.h:129
bool IsValid() const
Definition: source.h:256
bool send_unicast_only
Definition: source.h:125
T transform(T... args)