SOUND4 x1.CLOUD Library [1.5.7]
Loading...
Searching...
No Matches
sound4.x1.cloud_dyn.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <string>
10#include <exception>
11#include <thread>
12#include <functional>
13#include <memory>
14#include <array>
15#include <assert.h>
16#include <stdexcept>
17#include <filesystem>
18#include <string.h>
19
20#if defined(__unix__) || defined(__APPLE__)
21 #define UNIXLIKE 1
22#else
23 #define UNIXLIKE 0
24#endif
25
26#if UNIXLIKE
27 #include <dlfcn.h>
28#elif defined(_WIN32)
29 #include <libloaderapi.h>
30#else
31 #error "Unsupported OS"
32#endif
33
34// Needed to have function declarations
35#include "sound4.x1.cloud.h"
36
37
38#ifdef _WIN32
39 #include <stringapiset.h>
40 #include <wchar.h>
42 #define fs_strdup wcsdup
43 #ifdef _MSC_VER
44 #pragma warning(disable : 4996)
45 #endif
46#else // !_WIN32
48 #define fs_strdup strdup
49#endif // !_WIN32
50
51// bridge C callbacks to CPresetLoader
52extern "C" {
53 static char *cloudx1_custom_reader(const fs_char *filename, void* userdata);
54 static void cloudx1_custom_reader_free(char *content, void* userdata);
55 static int cloudx1_custom_writer(const fs_char *filename, const char *content, void* userdata);
56 static int cloudx1_custom_exists(const fs_char *filename, void* userdata);
57 static fs_char** cloudx1_custom_getall(void* userdata);
58 static void cloudx1_custom_getall_free(fs_char** all, void* userdata);
59 static int cloudx1_custom_remove(const fs_char *filename, void* userdata);
60 static int cloudx1_custom_rename(const fs_char *from, const fs_char *to, void* userdata);
61};
62
66namespace sound4 {
70namespace cloudx1 {
74namespace dyn {
75
79 namespace helper {
80
86 template <typename T>
88 // Storage definition, depending on OS
89 #if UNIXLIKE
90 using DynFunc_t = void *;
91 #else
92 using DynFunc_t = FARPROC;
93 #endif
94 private:
95 DynFunc_t m_ptr = NULL;
96 public:
97 DynFuncHolder() = default;
98 DynFuncHolder(DynFunc_t a_ptr) : m_ptr(a_ptr) {}
99 operator bool() const { return (m_ptr!=NULL); }
100 bool IsOk() const { return m_ptr!=NULL; }
101 operator T* () const { return reinterpret_cast<T*>(m_ptr); }
102 };
103
109 // Storage definition, depending on OS
110 #if UNIXLIKE
111 using DynLib_t = void *;
112 #else
113 using DynLib_t = HMODULE;
114 #endif
115 private:
116 DynLib_t m_lib {};
117 public:
118 CDynLoader() = default;
119 CDynLoader(CDynLoader&&) = default;
120 // No copy allowed
121 CDynLoader(const CDynLoader&) = delete;
122 CDynLoader& operator=(CDynLoader const&) = delete;
123 operator bool() const {
124 return (m_lib!=NULL);
125 }
126 bool IsOk() const {
127 return (m_lib!=NULL);
128 }
129 #if UNIXLIKE
130 void Close() {
131 if (IsOk()) {
132 #ifndef __SANITIZE_ADDRESS__ // avoid unloading to keep call stack
133 dlclose(m_lib);
134 #endif // __SANITIZE_ADDRESS__
135 m_lib=NULL;
136 }
137 }
138 bool Load(const std::filesystem::path& dynlib)
139 {
140 Close();
141 m_lib=dlopen(dynlib.c_str(), RTLD_NOW|RTLD_LOCAL);
142 return IsOk();
143 }
144 template <typename T>
145 DynFuncHolder<T> GetSymbol(const std::string& name) {
146 auto ptr=dlsym(m_lib, name.c_str());
147 if (!ptr) {
148 throw std::runtime_error("Missing function in library");
149 }
150 return DynFuncHolder<T>(ptr);
151 }
152 template <typename T>
153 DynFuncHolder<T> GetSymbol_safe(const std::string& name) {
154 auto ptr=dlsym(m_lib, name.c_str());
155 return DynFuncHolder<T>(ptr);
156 }
157 static std::filesystem::path GetThisLibraryPath(void) {
158 static Dl_info info;
159 if (! dladdr((void *) GetThisLibraryPath, & info)) return {};
160 auto rp=realpath(info.dli_fname, NULL);
161 std::filesystem::path p(rp);
162 free(rp);
163 return p;
164 }
165 #else
172 void Close() {
173 if (IsOk()) {
174 // NOTE: On Windows, FreeLibrary may create a lot of troubles, should use FreeLibraryAndExitThread but...
175 // So define SOUND4_CALL_FREELIBRARY before including this file if you really want to unload the library dynamically
176 #if defined(SOUND4_CALL_FREELIBRARYANDEXITTHREAD)
177 FreeLibraryAndExitThread(m_lib, 0);
178 #elif defined(SOUND4_CALL_FREELIBRARY)
179 FreeLibrary(m_lib);
180 #endif // SOUND4_CALL_FREELIBRARY
181 m_lib=NULL;
182 }
183 }
184 template <typename T>
185 DynFuncHolder<T> GetSymbol(const std::string& name) {
186 auto ptr=GetProcAddress(m_lib, name.c_str());
187 if (!ptr) {
188 throw std::runtime_error("Missing function in library");
189 }
190 return DynFuncHolder<T>(ptr);
191 }
192 template <typename T>
193 DynFuncHolder<T> GetSymbol_safe(const std::string& name) {
194 auto ptr=GetProcAddress(m_lib, name.c_str());
195 return DynFuncHolder<T>(ptr);
196 }
197 static std::filesystem::path GetThisLibraryPath(void) {
198 static wchar_t path[MAX_PATH]={};
199 HMODULE hm = NULL;
203 {
204 if (GetModuleFileNameW(hm, path, MAX_PATH) > 0) {
205 return std::filesystem::path(path);
206 }
207 }
208 return {};
209 }
210 #endif
211 virtual ~CDynLoader() {
212 Close();
213 }
214 }; // class CDynLoader
215 }; // namespace helper
216
223 class CDynLib {
224 private:
225 helper::CDynLoader m_lib;
226 bool m_bOK = false;
227 public:
228 CDynLib() = default;
229
230 // All those wrapped functions have the same signature as there C cloudx1_XXX
275#if CLOUDX1_HAS_WEBSERVER
281#endif // CLOUDX1_HAS_WEBSERVER
282
283 // added 2023-03-22
286
287 // added 2023-05-22
291
292 // added 2023-06-20
295
296 // added 2023-09-21
300
301#if CLOUDX1_HAS_CLOUDBUS
302 // added 2023-06-26
303 helper::DynFuncHolder< decltype(cloudx1_NewBus ) > NewBus ;
304 helper::DynFuncHolder< decltype(cloudx1_FreeBus ) > FreeBus ;
305 helper::DynFuncHolder< decltype(cloudx1_SetInstanceBus ) > SetInstanceBus ;
306#endif // CLOUDX1_HAS_CLOUDBUS
307
308 // added 2024-02-19
310
311#if CLOUDX1_HAS_WEBSERVER
312 // added 2024-05-23
316#endif // CLOUDX1_HAS_WEBSERVER
317
318#ifdef _WIN32
319 // added 2025-05-28
322#endif // _WIN32
323
331 bool Load(const std::filesystem::path& path = {}) {
332 std::string filename;
333 #if defined(__APPLE__)
334 filename="libsound4.x1.cloud.dylib";
335 #elif defined(__unix__)
336 filename="libsound4.x1.cloud.so";
337 #else
338 filename="sound4.x1.cloud.dll";
339 #endif
340 m_lib.Close();
341 // If a path is given, use it directly and do not try other path
342 if (!path.empty() && !m_lib.Load(path / filename)) {
343 return false;
344 } else if (!m_lib.IsOk()) {
345 auto thisdir=helper::CDynLoader::GetThisLibraryPath().parent_path();
346 #ifndef _WIN32
347 // Linux: if in a bin directory, try ../lib first
348 if (!m_lib.IsOk() && thisdir.filename()=="bin") {
349 auto libdir = thisdir.parent_path() / "lib";
350 m_lib.Load(libdir / filename);
351 }
352 #endif // !_WIN32
353 if (!m_lib.IsOk()) {
354 // Search in the same directory this code is in
355 m_lib.Load(thisdir / filename);
356 }
357 if (!m_lib.IsOk()) {
358 // Try current path
359 std::error_code ec;
360 auto p = std::filesystem::current_path(ec);
361 if (!ec) {
362 m_lib.Load(p / filename);
363 }
364 }
365 if (!m_lib.IsOk()) {
366 return false;
367 }
368 }
369 // Load all C functions
370 try {
371 GetVersion = m_lib.GetSymbol< decltype(cloudx1_GetVersion ) >("cloudx1_GetVersion" );
372 GetChunkSizeInFrames = m_lib.GetSymbol< decltype(cloudx1_GetChunkSizeInFrames ) >("cloudx1_GetChunkSizeInFrames" );
373 GetChannelCount = m_lib.GetSymbol< decltype(cloudx1_GetChannelCount ) >("cloudx1_GetChannelCount" );
374 GetAudioInputCount = m_lib.GetSymbol< decltype(cloudx1_GetAudioInputCount ) >("cloudx1_GetAudioInputCount" );
375 GetAudioOutputCount = m_lib.GetSymbol< decltype(cloudx1_GetAudioOutputCount ) >("cloudx1_GetAudioOutputCount" );
376 GetSampleRate = m_lib.GetSymbol< decltype(cloudx1_GetSampleRate ) >("cloudx1_GetSampleRate" );
377 SetLoggerCallback = m_lib.GetSymbol< decltype(cloudx1_SetLoggerCallback ) >("cloudx1_SetLoggerCallback" );
378 SetLogSeverity = m_lib.GetSymbol< decltype(cloudx1_SetLogSeverity ) >("cloudx1_SetLogSeverity" );
379 NewParameters = m_lib.GetSymbol< decltype(cloudx1_NewParameters ) >("cloudx1_NewParameters" );
380 FreeParameters = m_lib.GetSymbol< decltype(cloudx1_FreeParameters ) >("cloudx1_FreeParameters" );
381 SetParameter = m_lib.GetSymbol< decltype(cloudx1_SetParameter ) >("cloudx1_SetParameter" );
382 GetParameter = m_lib.GetSymbol< decltype(cloudx1_GetParameter ) >("cloudx1_GetParameter" );
383 FreeParameterValue = m_lib.GetSymbol< decltype(cloudx1_FreeParameterValue ) >("cloudx1_FreeParameterValue" );
384 InitProcess = m_lib.GetSymbol< decltype(cloudx1_InitProcess ) >("cloudx1_InitProcess" );
385 InitProcess2 = m_lib.GetSymbol< decltype(cloudx1_InitProcess2 ) >("cloudx1_InitProcess2" );
386 TerminateProcess = m_lib.GetSymbol< decltype(cloudx1_TerminateProcess ) >("cloudx1_TerminateProcess" );
387 ExitProcess = m_lib.GetSymbol< decltype(cloudx1_ExitProcess ) >("cloudx1_ExitProcess" );
388 StartUpdateThread = m_lib.GetSymbol< decltype(cloudx1_StartUpdateThread ) >("cloudx1_StartUpdateThread" );
389 StopUpdateThread = m_lib.GetSymbol< decltype(cloudx1_StopUpdateThread ) >("cloudx1_StopUpdateThread" );
390 WaitUpdateThreadReady = m_lib.GetSymbol< decltype(cloudx1_WaitUpdateThreadReady ) >("cloudx1_WaitUpdateThreadReady" );
391 ProcessAudio = m_lib.GetSymbol< decltype(cloudx1_ProcessAudio ) >("cloudx1_ProcessAudio" );
392 ProcessAudio_Planar = m_lib.GetSymbol< decltype(cloudx1_ProcessAudio_Planar ) >("cloudx1_ProcessAudio_Planar" );
393 GetBufferIn = m_lib.GetSymbol< decltype(cloudx1_GetBufferIn ) >("cloudx1_GetBufferIn" );
394 GetBufferOut = m_lib.GetSymbol< decltype(cloudx1_GetBufferOut ) >("cloudx1_GetBufferOut" );
395 GetEstimatedDelay = m_lib.GetSymbol< decltype(cloudx1_GetEstimatedDelay ) >("cloudx1_GetEstimatedDelay" );
396 GetFormatName = m_lib.GetSymbol< decltype(cloudx1_GetFormatName ) >("cloudx1_GetFormatName" );
397 GetFormatFromName = m_lib.GetSymbol< decltype(cloudx1_GetFormatFromName ) >("cloudx1_GetFormatFromName" );
398 GetBytesFromFormat = m_lib.GetSymbol< decltype(cloudx1_GetBytesFromFormat ) >("cloudx1_GetBytesFromFormat" );
399 GetMaxPacketFrame = m_lib.GetSymbol< decltype(cloudx1_GetMaxPacketFrame ) >("cloudx1_GetMaxPacketFrame" );
400 AddAudio = m_lib.GetSymbol< decltype(cloudx1_AddAudio ) >("cloudx1_AddAudio" );
401 AddPadAudio = m_lib.GetSymbol< decltype(cloudx1_AddPadAudio ) >("cloudx1_AddPadAudio" );
402 GetOutputCount = m_lib.GetSymbol< decltype(cloudx1_GetOutputCount ) >("cloudx1_GetOutputCount" );
403 GetAudio = m_lib.GetSymbol< decltype(cloudx1_GetAudio ) >("cloudx1_GetAudio" );
404 AudioConvertFrom = m_lib.GetSymbol< decltype(cloudx1_AudioConvertFrom ) >("cloudx1_AudioConvertFrom" );
405 AudioConvertTo = m_lib.GetSymbol< decltype(cloudx1_AudioConvertTo ) >("cloudx1_AudioConvertTo" );
406 StereoToMono = m_lib.GetSymbol< decltype(cloudx1_StereoToMono ) >("cloudx1_StereoToMono" );
407 MonoToStereo = m_lib.GetSymbol< decltype(cloudx1_MonoToStereo ) >("cloudx1_MonoToStereo" );
408 AudioMonoFromLiveStereo = m_lib.GetSymbol< decltype(cloudx1_AudioMonoFromLiveStereo) >("cloudx1_AudioMonoFromLiveStereo");
409 AudioMonoToLiveStereo = m_lib.GetSymbol< decltype(cloudx1_AudioMonoToLiveStereo ) >("cloudx1_AudioMonoToLiveStereo" );
410 NewClient = m_lib.GetSymbol< decltype(cloudx1_NewClient ) >("cloudx1_NewClient" );
411 DeleteClient = m_lib.GetSymbol< decltype(cloudx1_DeleteClient ) >("cloudx1_DeleteClient" );
412 ProcessJson = m_lib.GetSymbol< decltype(cloudx1_ProcessJson ) >("cloudx1_ProcessJson" );
413 FreeJsonAnswer = m_lib.GetSymbol< decltype(cloudx1_FreeJsonAnswer ) >("cloudx1_FreeJsonAnswer" );
414 SaveState = m_lib.GetSymbol< decltype(cloudx1_SaveState ) >("cloudx1_SaveState" );
415#if CLOUDX1_HAS_WEBSERVER
416 Webserver_tcp = m_lib.GetSymbol< decltype(cloudx1_Webserver_tcp ) >("cloudx1_Webserver_tcp" );
417 Webserver_tcp2 = m_lib.GetSymbol< decltype(cloudx1_Webserver_tcp2 ) >("cloudx1_Webserver_tcp2" );
418 Webserver = m_lib.GetSymbol< decltype(cloudx1_Webserver ) >("cloudx1_Webserver" );
419 Webserver_Stop = m_lib.GetSymbol< decltype(cloudx1_Webserver_Stop ) >("cloudx1_Webserver_Stop" );
420 Webserver_Status = m_lib.GetSymbol< decltype(cloudx1_Webserver_Status ) >("cloudx1_Webserver_Status" );
421#endif // CLOUDX1_HAS_WEBSERVER
422
423 // added 2023-03-22
424 StereoToMono_Planar = m_lib.GetSymbol< decltype(cloudx1_StereoToMono_Planar ) >("cloudx1_StereoToMono_Planar" );
425 MonoToStereo_Planar = m_lib.GetSymbol< decltype(cloudx1_MonoToStereo_Planar ) >("cloudx1_MonoToStereo_Planar" );
426
427 } catch (std::runtime_error& ) {
428 return false;
429 }
430 // C functions allowed to be missing
431 try {
432 // added 2023-05-22
433 SetMetadata = m_lib.GetSymbol< decltype(cloudx1_SetMetadata ) >("cloudx1_SetMetadata" );
434 GetMetadataInfos = m_lib.GetSymbol< decltype(cloudx1_GetMetadataInfos ) >("cloudx1_GetMetadataInfos" );
435 FreeMetadataInfos = m_lib.GetSymbol< decltype(cloudx1_FreeMetadataInfos ) >("cloudx1_FreeMetadataInfos" );
436 // added 2023-06-20
437 SetPresetManager = m_lib.GetSymbol< decltype(cloudx1_SetPresetManager ) >("cloudx1_SetPresetManager" );
438 PresetManager_InformChange = m_lib.GetSymbol< decltype(cloudx1_PresetManager_InformChange ) >("cloudx1_PresetManager_InformChange" );
439
440 // added 2023-09-21
441 GetPossibleChunkSizeInFrames = m_lib.GetSymbol< decltype(cloudx1_GetPossibleChunkSizeInFrames ) >("cloudx1_GetPossibleChunkSizeInFrames" );
442 GetProcessChunkFrames = m_lib.GetSymbol< decltype(cloudx1_GetProcessChunkFrames ) >("cloudx1_GetProcessChunkFrames" );
443 InitProcess3 = m_lib.GetSymbol< decltype(cloudx1_InitProcess3 ) >("cloudx1_InitProcess3" );
444
445#if CLOUDX1_HAS_CLOUDBUS
446 // added 2023-06-26
447 NewBus = m_lib.GetSymbol< decltype(cloudx1_NewBus ) >("cloudx1_NewBus" );
448 FreeBus = m_lib.GetSymbol< decltype(cloudx1_FreeBus ) >("cloudx1_FreeBus" );
449 SetInstanceBus = m_lib.GetSymbol< decltype(cloudx1_SetInstanceBus ) >("cloudx1_SetInstanceBus" );
450#endif // CLOUDX1_HAS_CLOUDBUS
451
452 // added 2024-02-19
453 SetMetadataMulti = m_lib.GetSymbol< decltype(cloudx1_SetMetadataMulti ) >("cloudx1_SetMetadataMulti" );
454
455#if CLOUDX1_HAS_WEBSERVER
456 // added 2024-05-23
457 Webserver_SetAppHealth = m_lib.GetSymbol< decltype(cloudx1_Webserver_SetAppHealth ) >("Webserver_SetAppHealth" );
458 Webserver_GetAppHealth = m_lib.GetSymbol< decltype(cloudx1_Webserver_GetAppHealth ) >("Webserver_GetAppHealth" );
459 Webserver_FreeString = m_lib.GetSymbol< decltype(cloudx1_Webserver_FreeString ) >("Webserver_FreeString" );
460 #endif // CLOUDX1_HAS_WEBSERVER
461
462#ifdef _WIN32
463 // added 2025-05-28
464 SetInstanceTracing = m_lib.GetSymbol< decltype(cloudx1_SetInstanceTracing ) >("SetInstanceTracing" );
465 SetInstanceTracingProcessActivity = m_lib.GetSymbol< decltype(cloudx1_SetInstanceTracingProcessActivity) >("SetInstanceTracingProcessActivity");
466#endif // _WIN32
467 } catch (std::runtime_error& ) {
468 // Ignored, handler will take care
469 }
470
471 m_bOK=true;
472 return true;
473 }
480 bool IsOk() const {
481 return m_bOK;
482 }
483
484 };
485
486
487
488 static constexpr const char *process_name = "SOUND4 x1.CLOUD";
489 static constexpr const char *process_shortname = "x1";
521
525 namespace helper {
526 #ifdef _WIN32
532 static inline std::string WStringToUTF8(const std::wstring& wstr) {
533 if (wstr.empty()) return {};
534 int size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
535 std::string str(size, 0);
536 WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &str[0], size, NULL, NULL);
537 return str;
538 }
544 static inline std::wstring UTF8ToWString(const std::string& str) {
545 if (str.empty()) return std::wstring();
546 int size = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
547 std::wstring wstr(size, 0);
548 MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstr[0], size);
549 return wstr;
550 }
551 #endif // _WIN32
552
558 template<typename T>
560 };
561 template<>
562 struct SampleFormat<int16_t> {
563 const cloudx1_SampleFormat format = S16_NATIVE;
564 };
565 template<>
566 struct SampleFormat<int32_t> {
567 const cloudx1_SampleFormat format = S32_NATIVE;
568 };
569 template<>
570 struct SampleFormat<float> {
571 const cloudx1_SampleFormat format = F32_NATIVE;
572 };
573
574 // --------------------------------------------------------------
586 static inline void AudioConvertFrom(CDynLib& dynlib, const uint8_t *payload, float *output, size_t nSpl, cloudx1_SampleFormat fmt) {
587 dynlib.AudioConvertFrom(payload, output, nSpl, fmt);
588 }
589
601 static inline void AudioConvertTo(CDynLib& dynlib, const float *input, uint8_t *payload, size_t nSpl, cloudx1_SampleFormat fmt) {
602 dynlib.AudioConvertTo(input, payload, nSpl, fmt);
603 }
604
615 static inline void StereoToMono(CDynLib& dynlib, const float *input, float *output, size_t nFrame) {
616 dynlib.StereoToMono(input, output, nFrame);
617 }
618
629 static inline void MonoToStereo(CDynLib& dynlib, const float *input, float *output, size_t nFrame) {
630 dynlib.MonoToStereo(input, output, nFrame);
631 }
632
644 static inline void StereoToMono_Planar(CDynLib& dynlib, const float *inputL, const float *inputR, float *output, size_t nFrame) {
645 dynlib.StereoToMono_Planar(inputL, inputR, output, nFrame);
646 }
647
659 static inline void MonoToStereo_Planar(CDynLib& dynlib, const float *input, float *outputL, float *outputR, size_t nFrame) {
660 dynlib.MonoToStereo_Planar(input, outputL, outputR, nFrame);
661 }
662
670 static inline void AudioMonoFromLiveStereo(CDynLib& dynlib, const uint8_t *payload, float *output) {
671 dynlib.AudioMonoFromLiveStereo(payload, output);
672 }
673
681 static inline void AudioMonoToLiveStereo(CDynLib& dynlib, const float *input, uint8_t *payload) {
682 dynlib.AudioMonoToLiveStereo(input, payload);
683 }
684
685 }; // namespace helper
686
693 static inline std::string GetVersion(CDynLib& dynlib)
694 {
695 return std::string(dynlib.GetVersion());
696 }
697
709 static inline unsigned int GetChunkSizeInFrames(CDynLib& dynlib)
710 {
711 return dynlib.GetChunkSizeInFrames();
712 }
713
723 static inline std::vector<unsigned int> GetPossibleChunkSizeInFrames(CDynLib& dynlib)
724 {
725 std::vector<unsigned int> list;
726 if (dynlib.GetPossibleChunkSizeInFrames) {
727 for (unsigned int* src=dynlib.GetPossibleChunkSizeInFrames();*src;src++) {
728 list.push_back(*src);
729 }
730 } else {
731 list.push_back(64);
732 }
733 return list;
734 }
735
742 static inline unsigned int GetChannelCount(CDynLib& dynlib)
743 {
744 return dynlib.GetChannelCount();
745 }
746
755 static inline unsigned int GetAudioInputCount(CDynLib& dynlib)
756 {
757 return dynlib.GetAudioInputCount();
758 }
759
768 static inline unsigned int GetAudioOutputCount(CDynLib& dynlib)
769 {
770 return dynlib.GetAudioOutputCount();
771 }
772
781 static inline unsigned int GetSampleRate(CDynLib& dynlib)
782 {
783 return dynlib.GetSampleRate();
784 }
785
793 static inline void SanityCheck(CDynLib& dynlib, bool a_bCheckFrames = true)
794 {
795 // Do some sanity checks
796 if (dynlib.GetSampleRate()!=CLOUDX1_SAMPLE_RATE) {
797 throw std::runtime_error("Bad library sampling rate");
798 }
799 if (a_bCheckFrames && dynlib.GetChunkSizeInFrames()!=ChunkFrames) {
800 throw std::runtime_error("Bad library frame size");
801 }
803 throw std::runtime_error("Bad library channel count");
804 }
806 throw std::runtime_error("Bad library input count");
807 }
809 throw std::runtime_error("Bad library output count");
810 }
811 }
812
820 static inline std::string GetFormatName(CDynLib& dynlib, const SampleFormat fmt)
821 {
822 return std::string(dynlib.GetFormatName(fmt));
823 }
824
832 static inline SampleFormat GetFormatFromName(CDynLib& dynlib, const std::string& name)
833 {
834 return dynlib.GetFormatFromName(name.c_str());
835 }
836
844 static inline unsigned int GetBytesFromFormat(CDynLib& dynlib, const SampleFormat fmt)
845 {
846 return dynlib.GetBytesFromFormat(fmt);
847 }
848
856 using log_cb_t = std::function<void(LogSeverity,const std::string&)>;
857
862 extern "C" {
863 static inline void _log_cb_c(cloudx1_LogSeverity severity, const char *c_msg) {
864 _log_cb(severity, std::string(c_msg));
865 }
866 }
870 static inline void SetLogSeverity(CDynLib& dynlib, LogSeverity severity)
871 {
872 dynlib.SetLogSeverity(severity);
873 }
877 static inline void SetLoggerCallback(CDynLib& dynlib, log_cb_t cb)
878 {
879 _log_cb=cb;
881 }
882
883#if CLOUDX1_HAS_CLOUDBUS
889 class CBus {
890 public:
891 CBus(CDynLib& dynlib)
892 : m_dynlib(dynlib)
893 {
894 if (m_dynlib.NewBus) {
895 m_bus=m_dynlib.NewBus();
896 }
897 }
898 ~CBus()
899 {
900 if (m_bus && m_dynlib.FreeBus) {
901 m_dynlib.FreeBus(m_bus);
902 }
903 m_bus = nullptr;
904 }
905 cloudx1_CBus *Get() const { return m_bus; }
906 private:
907 CDynLib& m_dynlib;
908 cloudx1_CBus *m_bus;
909 };
910#endif // CLOUDX1_HAS_CLOUDBUS
911
918 public:
919 CPresetLoader() = default;
920 virtual ~CPresetLoader() = default;
921
922 virtual bool IsReadOnly() = 0;
923 virtual bool Exists(const std::filesystem::path &name) = 0;
924 virtual bool Remove(const std::filesystem::path &name) = 0;
925 virtual bool Rename(const std::filesystem::path &from, const std::filesystem::path &to) = 0;
926 virtual std::vector<std::filesystem::path> GetAll() = 0;
927 virtual std::string Read(const std::filesystem::path &filename) = 0;
928 virtual bool Write(const std::filesystem::path &filename, const std::string &content) =0;
929 };
931
937 class CInstance {
938 public:
943 : m_dynlib(dynlib)
944 {
945 params = m_dynlib.NewParameters();
946 if (!params) throw std::bad_alloc();
947 }
948 // non-copyable
949 CInstance( const CInstance& ) = delete;
950 CInstance& operator=( const CInstance& ) = delete;
954 virtual ~CInstance()
955 {
956 Stop();
957 if (params) m_dynlib.FreeParameters(params);
958 }
962 bool IsOk() const { return instance!=nullptr; }
972 void SetParam(const std::string& name, const std::string& value)
973 {
974 assert(params);
975 m_dynlib.SetParameter(params, name.c_str(), value.c_str());
976 }
983 std::string GetParam(const std::string& name)
984 {
985 assert(params);
986 auto c_value=m_dynlib.GetParameter(params, name.c_str());
987 std::string ret(c_value);
988 m_dynlib.FreeParameterValue(c_value);
989 return ret;
990 }
991#if CLOUDX1_HAS_CLOUDBUS
1000 void SetBus(const CBus& bus) {
1001 assert(params);
1002 if (m_dynlib.SetInstanceBus) {
1003 m_dynlib.SetInstanceBus(params,bus.Get());
1004 }
1005 }
1006#endif // CLOUDX1_HAS_CLOUDBUS
1007
1018 void SetPresetManager(CPresetLoader *preset_manager)
1019 {
1020 if (!preset_manager) return;
1021 if (!m_dynlib.SetPresetManager) return;
1022 assert(params);
1023 m_dynlib.SetPresetManager(params,
1032 preset_manager->IsReadOnly(),
1033 preset_manager
1034 );
1035 }
1036
1059 bool Create(const std::string& LoginKey, const std::string& RadioName, const std::string& Access_Key_ID, const std::string& Access_Key_Secret, const std::filesystem::path& save_path, int json_port = 0, unsigned int frames_per_chunk=64)
1060 {
1061 assert(!instance);
1062 std::string l_save_path;
1063 if (!save_path.empty()) {
1064 l_save_path = save_path.u8string();
1065 }
1066 if (m_dynlib.InitProcess3) {
1067 instance = m_dynlib.InitProcess3(LoginKey.c_str(), RadioName.c_str(), Access_Key_ID.c_str(), Access_Key_Secret.c_str(), l_save_path.c_str(), params, frames_per_chunk);
1068 } else if (frames_per_chunk!=64) {
1069 return false;
1070 } else {
1071 instance = m_dynlib.InitProcess2(LoginKey.c_str(), RadioName.c_str(), Access_Key_ID.c_str(), Access_Key_Secret.c_str(), l_save_path.c_str(), params);
1072 }
1073 if (!instance) return false;
1074 if (!init_metadata.empty()) {
1075 for (auto&& [key,value]: init_metadata) {
1076 m_dynlib.SetMetadata(instance, key.c_str(), value.c_str());
1077 }
1078 init_metadata.clear();
1079 }
1080 update_thread = std::thread([this, json_port](){
1082 m_dynlib.StartUpdateThread(instance, json_port);
1084 });
1085 int timeout=5000;
1086 #ifdef DEBUG
1087 timeout=60*1000; // For debugger pauses
1088 #endif
1089 if (m_dynlib.WaitUpdateThreadReady(instance, timeout)<0) {
1090 return false;
1091 }
1092 return true;
1093 }
1094
1102 unsigned int GetChunkFrames() {
1103 if (instance && m_dynlib.GetProcessChunkFrames) {
1104 return m_dynlib.GetProcessChunkFrames(instance);
1105 }
1106 return 64;
1107 }
1108
1116 void PresetManager_InformChange(const std::filesystem::path& relative_path, PresetChange_Kind change_kind)
1117 {
1118 if (m_dynlib.PresetManager_InformChange) {
1119 m_dynlib.PresetManager_InformChange(instance, relative_path.c_str(), (cloudx1_PresetChange_Kind) change_kind);
1120 }
1121 }
1122
1134 void SetMetadata(const std::string& key, const char* value)
1135 {
1136 if (m_dynlib.SetMetadata) {
1137 if (instance) {
1138 m_dynlib.SetMetadata(instance, key.c_str(), value);
1139 } else {
1140 init_metadata.push_back( {key, value} );
1141 }
1142 }
1143 }
1144
1145
1155 void SetMetadataMulti(const std::unordered_map<std::string, const char*>& list)
1156 {
1157 if (instance) {
1158 if (m_dynlib.SetMetadataMulti) {
1159 typedef const char* pchar;
1160 pchar* keyvalue=new pchar[2*list.size()+1];
1161 size_t n=0;
1162 for (auto&& [key,value]: list) {
1163 keyvalue[2*n+0]=key.c_str();
1164 keyvalue[2*n+1]=value;
1165 n++;
1166 }
1167 keyvalue[2*n+0]=nullptr;
1168
1169 cloudx1_SetMetadataMulti(instance, keyvalue);
1170
1171 delete[] keyvalue;
1172 } else {
1173 for (auto&& [key,value]: list) {
1174 SetMetadata(key, value);
1175 }
1176 }
1177 } else {
1178 for (auto&& [key,value]: list) {
1179 if (value) {
1180 init_metadata.push_back( {key, value} );
1181 }
1182 }
1183 }
1184 }
1185
1191 std::vector< std::tuple<std::string,std::string> > GetMetadataInfos()
1192 {
1193 std::vector< std::tuple<std::string,std::string> > values;
1194 if (m_dynlib.GetMetadataInfos) {
1195 const char** c_values = m_dynlib.GetMetadataInfos(instance);
1196 if (c_values) {
1197 for (const char** c_value=c_values; *c_value; ) {
1198 std::string key(*c_value);
1199 c_value++;
1200 if (*c_value) {
1201 std::string descr(*c_value);
1202 c_value++;
1203 values.push_back( {key,descr} );
1204 }
1205 }
1206 m_dynlib.FreeMetadataInfos(instance, c_values);
1207 }
1208 }
1209 return values;
1210 }
1211
1215 virtual void OnUpdateThreadStart() {}
1219 virtual void OnUpdateThreadStop() {}
1220
1221#if CLOUDX1_HAS_WEBSERVER
1235 bool StartWebServer(int http_port, int https_port=0)
1236 {
1237 assert(instance);
1238 assert(webserver==SOUND4_INVALID_WEBSERVER_ID);
1239 webserver = m_dynlib.Webserver(http_port,https_port,instance);
1240 if (webserver==SOUND4_INVALID_WEBSERVER_ID) {
1241 return false;
1242 }
1243 int web_status=m_dynlib.Webserver_Status(webserver);
1244 if (http_port && (web_status & SOUND4_WEBSERVER_HTTP_OK) == 0) {
1245 return false;
1246 }
1247 if (https_port && (web_status & SOUND4_WEBSERVER_HTTPS_OK) == 0) {
1248 return false;
1249 }
1250 return true;
1251 }
1252
1260 void StopWebServer(int timeout_ms = 1000)
1261 {
1262 if (webserver != SOUND4_INVALID_WEBSERVER_ID) {
1263 m_dynlib.Webserver_Stop(webserver, timeout_ms);
1264 webserver = SOUND4_INVALID_WEBSERVER_ID;
1265 }
1266 }
1267
1271 void SetWebServerAppHealth(int httpcode, const std::string& contenttype, const std::string& content)
1272 {
1273 assert(instance);
1274 if (!m_dynlib.Webserver_SetAppHealth) return;
1275 m_dynlib.Webserver_SetAppHealth(instance, httpcode, contenttype.c_str(), content.c_str());
1276 }
1280 void GetWebServerAppHealth(int &httpcode, std::string& contenttype, std::string& content)
1281 {
1282 assert(instance);
1283 if (!m_dynlib.Webserver_GetAppHealth) return;
1284 char* c_contenttype=nullptr;
1285 char* c_content=nullptr;
1286 m_dynlib.Webserver_GetAppHealth(instance, &httpcode, &c_contenttype, &c_content);
1287 contenttype=c_contenttype;
1288 content=c_content;
1289 m_dynlib.Webserver_FreeString(c_contenttype);
1290 m_dynlib.Webserver_FreeString(c_content);
1291 }
1292#endif // CLOUDX1_HAS_WEBSERVER
1293
1303 {
1304 if (!instance) return 0;
1305 return m_dynlib.TerminateProcess(instance);
1306 }
1307
1311 void Stop()
1312 {
1313 if (!instance) return;
1314#if CLOUDX1_HAS_WEBSERVER
1315 StopWebServer();
1316#endif // CLOUDX1_HAS_WEBSERVER
1317 if (update_thread.joinable()) {
1318 m_dynlib.StopUpdateThread(instance); // this will exit the update thread
1319 update_thread.join();
1320 }
1321 m_dynlib.ExitProcess(instance);
1322 instance=nullptr;
1323 }
1324
1334 unsigned int GetEstimatedDelay()
1335 {
1336 assert(instance);
1337 return m_dynlib.GetEstimatedDelay(instance);
1338 }
1339
1352 std::array<float,InputSampleSize>& GetBufferIn()
1353 {
1354 assert(instance);
1355 float *buf=m_dynlib.GetBufferIn(instance);
1356 return reinterpret_cast< std::array<float,InputSampleSize>& >(*buf);
1357
1358 }
1370 std::array<float,OutputSampleSize>& GetBufferOut()
1371 {
1372 assert(instance);
1373 float *buf= m_dynlib.GetBufferOut(instance);
1374 return reinterpret_cast< std::array<float,OutputSampleSize>& >(*buf);
1375 }
1380 {
1381 assert(instance);
1382 m_dynlib.ProcessAudio(instance, m_dynlib.GetBufferIn(instance), m_dynlib.GetBufferOut(instance));
1383 }
1395 void ProcessAudio_Planar(float const * const *input, float * const *output)
1396 {
1397 assert(instance);
1398 m_dynlib.ProcessAudio_Planar(instance, input, output);
1399 }
1400
1412 template<typename T>
1413 std::vector<T> ProcessAnyAudio(const std::vector<T> input)
1414 {
1415 assert(instance);
1416 std::vector<T> output;
1417 unsigned int out_offset=0;
1418 unsigned int in_offset=0;
1419 unsigned int todo = input.size();
1420 while (todo>0) {
1421 unsigned int left = AddAudio(&input[in_offset], todo);
1422 unsigned int out_avail = m_dynlib.GetOutputCount(instance);
1423 output.resize(out_offset + out_avail);
1424 GetAudio(&output[out_offset], out_avail);
1425 out_offset+=out_avail;
1426 in_offset += todo-left;
1427 todo=left;
1428 }
1429 return output;
1430 }
1431
1437 class CClient {
1438 public:
1440 : m_dynlib(dynlib)
1441 {
1442 assert(instance);
1443 client=m_dynlib.NewClient(instance);
1444 if (!client) throw std::bad_alloc();
1445 }
1446 // non-copyable
1447 CClient( const CInstance& ) = delete;
1448 CClient& operator=( const CInstance& ) = delete;
1450 {
1451 if (client) {
1452 m_dynlib.DeleteClient(client);
1453 client=nullptr;
1454 }
1455 }
1463 std::string ProcessJson(const std::string &request, bool *NeedSave = nullptr)
1464 {
1465 assert(client);
1466 int need_save=0;
1467 const char *canswer = m_dynlib.ProcessJson(client, request.c_str(), &need_save);
1468 if (!canswer) return {};
1469 std::string answer(canswer);
1470 m_dynlib.FreeJsonAnswer (canswer);
1471 if (NeedSave) {
1472 *NeedSave=(need_save!=0);
1473 }
1474 return answer;
1475 }
1476 private:
1477 CDynLib& m_dynlib;
1478 cloudx1_CClientInstance *client = nullptr;
1479 };
1487 std::shared_ptr<CClient> NewClient()
1488 {
1489 assert(instance);
1490 return std::make_shared<CClient>(instance, m_dynlib);
1491 }
1492
1503 bool SaveState() {
1504 assert(instance);
1505 if (m_dynlib.SaveState(instance)!=0) {
1506 return false;
1507 }
1508 return true;
1509 }
1510#ifdef _WIN32
1517 void SetInstanceTracing(TraceLoggingHProvider tracing_provider, GUID activity_guid = {}) {
1518 if (m_dynlib.SetInstanceTracing) {
1519 m_dynlib.SetInstanceTracing(params, tracing_provider, activity_guid);
1520 }
1521 }
1528 void SetInstanceTracingProcessActivity(GUID activity_guid) {
1529 assert(instance);
1530 if (m_dynlib.SetInstanceTracingProcessActivity) {
1531 m_dynlib.SetInstanceTracingProcessActivity(instance, activity_guid);
1532 }
1533 }
1534#endif // _WIN32
1535 protected:
1536 template<typename T>
1537 unsigned int AddAudio(const T* payload, unsigned int nFrame)
1538 {
1539 assert(instance);
1540 return m_dynlib.AddAudio(instance, reinterpret_cast<const T*>(payload), nFrame, helper::SampleFormat<T>::format);
1541 }
1542 template<typename T>
1543 unsigned int GetAudio(T* payload, unsigned int max_nFrame)
1544 {
1545 assert(instance);
1546 return m_dynlib.GetAudio(instance, reinterpret_cast<T*>(payload), max_nFrame, helper::SampleFormat<T>::format);
1547 }
1548
1549 private:
1550 CDynLib& m_dynlib;
1551 cloudx1_CParameters* params = nullptr;
1552 cloudx1_CInstance* instance = nullptr;
1553 std::thread update_thread;
1554 std::vector< std::pair<std::string,std::string> > init_metadata;
1555#if CLOUDX1_HAS_WEBSERVER
1556 uint64_t webserver = SOUND4_INVALID_WEBSERVER_ID;
1557#endif // CLOUDX1_HAS_WEBSERVER
1558 };
1559
1560}; // namespace dyn
1561}; // namespace cloudx1
1562}; // namespace sound4
1563
1564// bridge C callbacks to CPresetLoader
1565extern "C" {
1566 static char *cloudx1_custom_reader(const fs_char *filename, void* userdata) {
1567 sound4::cloudx1::dyn::CPresetLoader *preset_loader=reinterpret_cast<sound4::cloudx1::dyn::CPresetLoader*>(userdata);
1568 std::string content=preset_loader->Read(filename);
1569 return strdup(content.c_str());
1570 }
1571 static void cloudx1_custom_reader_free(char *content, void* userdata) {
1572 if (!content) return;
1573 free(content);
1574 }
1575 static int cloudx1_custom_writer(const fs_char *filename, const char *content, void* userdata) {
1576 sound4::cloudx1::dyn::CPresetLoader *preset_loader=reinterpret_cast<sound4::cloudx1::dyn::CPresetLoader*>(userdata);
1577 auto res=preset_loader->Write(filename,content);
1578 return res?0:-1;
1579 }
1580 static int cloudx1_custom_exists(const fs_char *filename, void* userdata) {
1581 sound4::cloudx1::dyn::CPresetLoader *preset_loader=reinterpret_cast<sound4::cloudx1::dyn::CPresetLoader*>(userdata);
1582 auto res=preset_loader->Exists(filename);
1583 return res?0:-1;
1584 }
1585 static fs_char** cloudx1_custom_getall(void* userdata) {
1586 sound4::cloudx1::dyn::CPresetLoader *preset_loader=reinterpret_cast<sound4::cloudx1::dyn::CPresetLoader*>(userdata);
1587 auto res=preset_loader->GetAll();
1588 fs_char**all=(fs_char**)malloc((res.size()+1)*sizeof(const fs_char*));
1589 for (size_t n=0;n<res.size();n++) {
1590 all[n]=fs_strdup(res[n].c_str());
1591 }
1592 all[res.size()]=nullptr;
1593 return all;
1594 }
1595 static void cloudx1_custom_getall_free(fs_char** all, void* userdata) {
1596 if (!all) return;
1597 for (fs_char** one=all;*one;one++) {
1598 free(*one);
1599 }
1600 free(all);
1601 }
1602 static int cloudx1_custom_remove(const fs_char *filename, void* userdata) {
1603 sound4::cloudx1::dyn::CPresetLoader *preset_loader=reinterpret_cast<sound4::cloudx1::dyn::CPresetLoader*>(userdata);
1604 auto res=preset_loader->Remove(filename);
1605 return res?0:-1;
1606 }
1607 static int cloudx1_custom_rename(const fs_char *from, const fs_char *to, void* userdata) {
1608 sound4::cloudx1::dyn::CPresetLoader *preset_loader=reinterpret_cast<sound4::cloudx1::dyn::CPresetLoader*>(userdata);
1609 auto res=preset_loader->Rename(from,to);
1610 return res?0:-1;
1611 }
1612
1613};
Shared Bus.
Definition sound4cl.hpp:841
sound4cl_CBus * Get() const
Definition sound4cl.hpp:859
helper::DynFuncHolder< decltype(cloudx1_Webserver_Status) > Webserver_Status
helper::DynFuncHolder< decltype(cloudx1_SetPresetManager) > SetPresetManager
helper::DynFuncHolder< decltype(cloudx1_SetMetadata) > SetMetadata
helper::DynFuncHolder< decltype(cloudx1_FreeJsonAnswer) > FreeJsonAnswer
helper::DynFuncHolder< decltype(cloudx1_ProcessJson) > ProcessJson
helper::DynFuncHolder< decltype(cloudx1_GetProcessChunkFrames) > GetProcessChunkFrames
helper::DynFuncHolder< decltype(cloudx1_SetParameter) > SetParameter
helper::DynFuncHolder< decltype(cloudx1_DeleteClient) > DeleteClient
helper::DynFuncHolder< decltype(cloudx1_GetBytesFromFormat) > GetBytesFromFormat
helper::DynFuncHolder< decltype(cloudx1_Webserver_SetAppHealth) > Webserver_SetAppHealth
helper::DynFuncHolder< decltype(cloudx1_TerminateProcess) > TerminateProcess
helper::DynFuncHolder< decltype(cloudx1_WaitUpdateThreadReady) > WaitUpdateThreadReady
helper::DynFuncHolder< decltype(cloudx1_AudioMonoToLiveStereo) > AudioMonoToLiveStereo
helper::DynFuncHolder< decltype(cloudx1_Webserver_FreeString) > Webserver_FreeString
helper::DynFuncHolder< decltype(cloudx1_Webserver_tcp) > Webserver_tcp
helper::DynFuncHolder< decltype(cloudx1_NewParameters) > NewParameters
helper::DynFuncHolder< decltype(cloudx1_StartUpdateThread) > StartUpdateThread
helper::DynFuncHolder< decltype(cloudx1_StereoToMono_Planar) > StereoToMono_Planar
helper::DynFuncHolder< decltype(cloudx1_AddAudio) > AddAudio
helper::DynFuncHolder< decltype(cloudx1_GetBufferOut) > GetBufferOut
helper::DynFuncHolder< decltype(cloudx1_Webserver_tcp2) > Webserver_tcp2
helper::DynFuncHolder< decltype(cloudx1_SetLoggerCallback) > SetLoggerCallback
helper::DynFuncHolder< decltype(cloudx1_StopUpdateThread) > StopUpdateThread
helper::DynFuncHolder< decltype(cloudx1_ExitProcess) > ExitProcess
helper::DynFuncHolder< decltype(cloudx1_FreeParameters) > FreeParameters
helper::DynFuncHolder< decltype(cloudx1_GetMaxPacketFrame) > GetMaxPacketFrame
bool Load(const std::filesystem::path &path={})
Loads the library.
helper::DynFuncHolder< decltype(cloudx1_InitProcess) > InitProcess
helper::DynFuncHolder< decltype(cloudx1_MonoToStereo) > MonoToStereo
helper::DynFuncHolder< decltype(cloudx1_MonoToStereo_Planar) > MonoToStereo_Planar
helper::DynFuncHolder< decltype(cloudx1_GetAudioOutputCount) > GetAudioOutputCount
helper::DynFuncHolder< decltype(cloudx1_ProcessAudio_Planar) > ProcessAudio_Planar
helper::DynFuncHolder< decltype(cloudx1_GetPossibleChunkSizeInFrames) > GetPossibleChunkSizeInFrames
helper::DynFuncHolder< decltype(cloudx1_InitProcess3) > InitProcess3
helper::DynFuncHolder< decltype(cloudx1_ProcessAudio) > ProcessAudio
helper::DynFuncHolder< decltype(cloudx1_GetParameter) > GetParameter
helper::DynFuncHolder< decltype(cloudx1_GetAudio) > GetAudio
helper::DynFuncHolder< decltype(cloudx1_FreeParameterValue) > FreeParameterValue
helper::DynFuncHolder< decltype(cloudx1_AudioConvertTo) > AudioConvertTo
helper::DynFuncHolder< decltype(cloudx1_AudioMonoFromLiveStereo) > AudioMonoFromLiveStereo
helper::DynFuncHolder< decltype(cloudx1_AddPadAudio) > AddPadAudio
helper::DynFuncHolder< decltype(cloudx1_StereoToMono) > StereoToMono
helper::DynFuncHolder< decltype(cloudx1_GetChannelCount) > GetChannelCount
helper::DynFuncHolder< decltype(cloudx1_NewClient) > NewClient
helper::DynFuncHolder< decltype(cloudx1_Webserver) > Webserver
helper::DynFuncHolder< decltype(cloudx1_GetBufferIn) > GetBufferIn
helper::DynFuncHolder< decltype(cloudx1_GetSampleRate) > GetSampleRate
helper::DynFuncHolder< decltype(cloudx1_GetChunkSizeInFrames) > GetChunkSizeInFrames
helper::DynFuncHolder< decltype(cloudx1_InitProcess2) > InitProcess2
helper::DynFuncHolder< decltype(cloudx1_SetMetadataMulti) > SetMetadataMulti
helper::DynFuncHolder< decltype(cloudx1_AudioConvertFrom) > AudioConvertFrom
helper::DynFuncHolder< decltype(cloudx1_GetOutputCount) > GetOutputCount
helper::DynFuncHolder< decltype(cloudx1_PresetManager_InformChange) > PresetManager_InformChange
helper::DynFuncHolder< decltype(cloudx1_GetFormatName) > GetFormatName
helper::DynFuncHolder< decltype(cloudx1_GetMetadataInfos) > GetMetadataInfos
helper::DynFuncHolder< decltype(cloudx1_SetInstanceTracing) > SetInstanceTracing
helper::DynFuncHolder< decltype(cloudx1_SetLogSeverity) > SetLogSeverity
helper::DynFuncHolder< decltype(cloudx1_FreeMetadataInfos) > FreeMetadataInfos
helper::DynFuncHolder< decltype(cloudx1_Webserver_GetAppHealth) > Webserver_GetAppHealth
helper::DynFuncHolder< decltype(cloudx1_GetAudioInputCount) > GetAudioInputCount
bool IsOk() const
Check if the library was loaded correctly.
helper::DynFuncHolder< decltype(cloudx1_GetFormatFromName) > GetFormatFromName
helper::DynFuncHolder< decltype(cloudx1_SaveState) > SaveState
helper::DynFuncHolder< decltype(cloudx1_GetVersion) > GetVersion
helper::DynFuncHolder< decltype(cloudx1_Webserver_Stop) > Webserver_Stop
helper::DynFuncHolder< decltype(cloudx1_SetInstanceTracingProcessActivity) > SetInstanceTracingProcessActivity
helper::DynFuncHolder< decltype(cloudx1_GetEstimatedDelay) > GetEstimatedDelay
std::string ProcessJson(const std::string &request, bool *NeedSave=nullptr)
Process a JSON request and returns the answer.
CClient(cloudx1_CInstance *instance, CDynLib &dynlib)
CClient(const CInstance &)=delete
CClient & operator=(const CInstance &)=delete
void SetPresetManager(CPresetLoader *preset_manager)
void SetMetadata(const std::string &key, const char *value)
void SetParam(const std::string &name, const std::string &value)
void SetInstanceTracingProcessActivity(GUID activity_guid)
void SetMetadataMulti(const std::unordered_map< std::string, const char * > &list)
bool Create(const std::string &LoginKey, const std::string &RadioName, const std::string &Access_Key_ID, const std::string &Access_Key_Secret, const std::filesystem::path &save_path, int json_port=0, unsigned int frames_per_chunk=64)
CInstance & operator=(const CInstance &)=delete
void PresetManager_InformChange(const std::filesystem::path &relative_path, PresetChange_Kind change_kind)
unsigned int GetAudio(T *payload, unsigned int max_nFrame)
void GetWebServerAppHealth(int &httpcode, std::string &contenttype, std::string &content)
std::shared_ptr< CClient > NewClient()
void SetInstanceTracing(TraceLoggingHProvider tracing_provider, GUID activity_guid={})
std::vector< T > ProcessAnyAudio(const std::vector< T > input)
std::vector< std::tuple< std::string, std::string > > GetMetadataInfos()
CInstance(const CInstance &)=delete
std::array< float, InputSampleSize > & GetBufferIn()
void StopWebServer(int timeout_ms=1000)
std::array< float, OutputSampleSize > & GetBufferOut()
void ProcessAudio_Planar(float const *const *input, float *const *output)
unsigned int AddAudio(const T *payload, unsigned int nFrame)
void SetWebServerAppHealth(int httpcode, const std::string &contenttype, const std::string &content)
std::string GetParam(const std::string &name)
bool StartWebServer(int http_port, int https_port=0)
virtual std::vector< std::filesystem::path > GetAll()=0
virtual bool Remove(const std::filesystem::path &name)=0
virtual bool Rename(const std::filesystem::path &from, const std::filesystem::path &to)=0
virtual bool Exists(const std::filesystem::path &name)=0
virtual bool Write(const std::filesystem::path &filename, const std::string &content)=0
virtual std::string Read(const std::filesystem::path &filename)=0
CDynLoader & operator=(CDynLoader const &)=delete
static std::filesystem::path GetThisLibraryPath(void)
DynFuncHolder< T > GetSymbol_safe(const std::string &name)
bool Load(const std::filesystem::path &dynlib, uint32_t loadflags=LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR|LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_USER_DIRS|LOAD_LIBRARY_SEARCH_SYSTEM32)
DynFuncHolder< T > GetSymbol(const std::string &name)
CDynLoader(const CDynLoader &)=delete
enum cloudx1_SampleFormat cloudx1_GetFormatFromName(const char *name)
cloudx1_SampleFormat
const char * cloudx1_GetFormatName(const enum cloudx1_SampleFormat fmt)
unsigned int cloudx1_GetOutputCount(struct cloudx1_CInstance *instance)
unsigned int cloudx1_AddAudio(struct cloudx1_CInstance *instance, const uint8_t *payload, unsigned int nFrame, enum cloudx1_SampleFormat fmt)
unsigned int cloudx1_AddPadAudio(struct cloudx1_CInstance *instance)
unsigned int cloudx1_GetBytesFromFormat(const enum cloudx1_SampleFormat fmt)
unsigned int cloudx1_GetAudio(struct cloudx1_CInstance *instance, uint8_t *payload, unsigned int max_nFrame, enum cloudx1_SampleFormat fmt)
unsigned int cloudx1_GetMaxPacketFrame(struct cloudx1_CInstance *instance)
struct cloudx1_CClientInstance * cloudx1_NewClient(struct cloudx1_CInstance *instance)
int cloudx1_SaveState(struct cloudx1_CInstance *instance)
void cloudx1_DeleteClient(struct cloudx1_CClientInstance *client)
const char * cloudx1_ProcessJson(struct cloudx1_CClientInstance *client, const char *json_str, int *need_save)
void cloudx1_FreeJsonAnswer(const char *json_str)
void cloudx1_AudioConvertTo(const float *input, uint8_t *payload, size_t nSpl, enum cloudx1_SampleFormat fmt)
void cloudx1_AudioMonoToLiveStereo(const float *input, uint8_t *payload)
void cloudx1_MonoToStereo_Planar(const float *input, float *outputL, float *outputR, size_t nFrame)
void cloudx1_StereoToMono(const float *input, float *output, size_t nFrame)
void cloudx1_AudioConvertFrom(const uint8_t *payload, float *output, size_t nSpl, enum cloudx1_SampleFormat fmt)
void cloudx1_MonoToStereo(const float *input, float *output, size_t nFrame)
void cloudx1_AudioMonoFromLiveStereo(const uint8_t *payload, float *output)
void cloudx1_StereoToMono_Planar(const float *inputL, const float *inputR, float *output, size_t nFrame)
float * cloudx1_GetBufferOut(struct cloudx1_CInstance *instance)
void cloudx1_ProcessAudio_Planar(struct cloudx1_CInstance *instance, float const *const *input, float *const *output)
void cloudx1_ProcessAudio(struct cloudx1_CInstance *instance, const float *input, float *output)
unsigned int cloudx1_GetEstimatedDelay(struct cloudx1_CInstance *instance)
float * cloudx1_GetBufferIn(struct cloudx1_CInstance *instance)
unsigned int * cloudx1_GetPossibleChunkSizeInFrames()
unsigned int cloudx1_GetAudioInputCount()
#define CLOUDX1_AUDIO_INPUT_COUNT
cloudx1_LogSeverity
unsigned int cloudx1_GetChunkSizeInFrames()
#define CLOUDX1_AUDIOFRAME_COUNT
unsigned int cloudx1_GetAudioOutputCount()
unsigned int cloudx1_GetChannelCount()
void cloudx1_SetLoggerCallback(cloudx1_loggerfn logger)
unsigned int cloudx1_GetSampleRate()
#define CLOUDX1_SAMPLE_RATE
const char * cloudx1_GetVersion()
#define CLOUDX1_CHANNEL_COUNT
#define CLOUDX1_AUDIO_OUTPUT_COUNT
void cloudx1_SetLogSeverity(enum cloudx1_LogSeverity severity)
void cloudx1_FreeParameterValue(const char *value)
void cloudx1_ExitProcess(struct cloudx1_CInstance *instance)
void cloudx1_FreeParameters(struct cloudx1_CParameters *params)
void cloudx1_SetParameter(struct cloudx1_CParameters *params, const char *name, const char *value)
struct cloudx1_CParameters * cloudx1_NewParameters()
int cloudx1_TerminateProcess(struct cloudx1_CInstance *instance)
struct cloudx1_CInstance * cloudx1_InitProcess2(const char *LoginKey, const char *RadioName, const char *Access_Key_ID, const char *Access_Key_Secret, const char *save_path, const struct cloudx1_CParameters *parameters)
const char * cloudx1_GetParameter(struct cloudx1_CParameters *params, const char *name)
unsigned int cloudx1_GetProcessChunkFrames(struct cloudx1_CInstance *instance)
struct cloudx1_CInstance * cloudx1_InitProcess(const char *LoginKey, const char *RadioName, const char *Access_Key_ID, const char *Access_Key_Secret, const char *save_path)
struct cloudx1_CInstance * cloudx1_InitProcess3(const char *LoginKey, const char *RadioName, const char *Access_Key_ID, const char *Access_Key_Secret, const char *save_path, const struct cloudx1_CParameters *parameters, unsigned int frames_per_chunk)
const char ** cloudx1_GetMetadataInfos(struct cloudx1_CInstance *instance)
void cloudx1_SetMetadata(struct cloudx1_CInstance *instance, const char *key, const char *value)
void cloudx1_FreeMetadataInfos(struct cloudx1_CInstance *instance, const char **infos)
void cloudx1_SetMetadataMulti(struct cloudx1_CInstance *instance, const char **keyvalue)
cloudx1_PresetChange_Kind
void cloudx1_SetPresetManager(struct cloudx1_CParameters *params, cloudx1_storage_reader reader, cloudx1_storage_reader_free, cloudx1_storage_writer writer, cloudx1_storage_exists exists, cloudx1_storage_getall getall, cloudx1_storage_getall_free getall_free, cloudx1_storage_remove remove, cloudx1_storage_rename rename, int IsReadOnly, void *userdata)
void cloudx1_PresetManager_InformChange(struct cloudx1_CInstance *instance, const fs_char *relative_path, enum cloudx1_PresetChange_Kind change_kind)
wchar_t fs_char
void cloudx1_SetInstanceTracingProcessActivity(struct cloudx1_CInstance *instance, GUID activity_guid)
void cloudx1_SetInstanceTracing(struct cloudx1_CParameters *params, TraceLoggingHProvider tracing_provider, GUID activity_guid)
void cloudx1_StartUpdateThread(struct cloudx1_CInstance *instance, unsigned int port)
int cloudx1_WaitUpdateThreadReady(struct cloudx1_CInstance *instance, int milliseconds)
void cloudx1_StopUpdateThread(struct cloudx1_CInstance *instance)
#define SOUND4_WEBSERVER_HTTPS_OK
uint64_t cloudx1_Webserver_tcp2(unsigned int listenport, unsigned int listenport_secure, const char *socket_ip, unsigned int socket_port, const struct cloudx1_CParameters *parameters)
uint64_t cloudx1_Webserver(unsigned int listenport, unsigned int listenport_secure, struct cloudx1_CInstance *instance)
uint64_t cloudx1_Webserver_tcp(unsigned int listenport, unsigned int listenport_secure, const char *socket_ip, unsigned int socket_port)
void cloudx1_Webserver_FreeString(char *str)
int cloudx1_Webserver_Status(uint64_t id)
#define SOUND4_WEBSERVER_HTTP_OK
#define SOUND4_INVALID_WEBSERVER_ID
int cloudx1_Webserver_Stop(uint64_t id, int timeout_ms)
void cloudx1_Webserver_GetAppHealth(struct cloudx1_CInstance *instance, int *httpcode, char **contenttype, char **content)
void cloudx1_Webserver_SetAppHealth(struct cloudx1_CInstance *instance, int httpcode, const char *contenttype, const char *content)
static std::string WStringToUTF8(const std::wstring &wstr)
static void AudioConvertTo(CDynLib &dynlib, const float *input, uint8_t *payload, size_t nSpl, cloudx1_SampleFormat fmt)
static void AudioMonoToLiveStereo(CDynLib &dynlib, const float *input, uint8_t *payload)
static void MonoToStereo_Planar(CDynLib &dynlib, const float *input, float *outputL, float *outputR, size_t nFrame)
static void StereoToMono(CDynLib &dynlib, const float *input, float *output, size_t nFrame)
static void AudioConvertFrom(CDynLib &dynlib, const uint8_t *payload, float *output, size_t nSpl, cloudx1_SampleFormat fmt)
static std::wstring UTF8ToWString(const std::string &str)
static void StereoToMono_Planar(CDynLib &dynlib, const float *inputL, const float *inputR, float *output, size_t nFrame)
static void MonoToStereo(CDynLib &dynlib, const float *input, float *output, size_t nFrame)
static void AudioMonoFromLiveStereo(CDynLib &dynlib, const uint8_t *payload, float *output)
static void SetLogSeverity(CDynLib &dynlib, LogSeverity severity)
static void _log_cb_c(cloudx1_LogSeverity severity, const char *c_msg)
static constexpr const char * process_shortname
static SampleFormat GetFormatFromName(CDynLib &dynlib, const std::string &name)
static void SanityCheck(CDynLib &dynlib, bool a_bCheckFrames=true)
static std::string GetFormatName(CDynLib &dynlib, const SampleFormat fmt)
static void SetLoggerCallback(CDynLib &dynlib, log_cb_t cb)
static unsigned int GetBytesFromFormat(CDynLib &dynlib, const SampleFormat fmt)
static constexpr const char * process_name
std::function< void(LogSeverity, const std::string &)> log_cb_t
static unsigned int GetSampleRate()
static std::string GetVersion()
static unsigned int GetAudioOutputCount()
static unsigned int GetChannelCount()
static unsigned int GetAudioInputCount()
static std::vector< unsigned int > GetPossibleChunkSizeInFrames()
static unsigned int GetChunkSizeInFrames()
@ S32_NATIVE
32-bit signed integer, native
Definition sound4cl.hpp:72
@ F32_NATIVE
32-bit floating-point, native
Definition sound4cl.hpp:73
@ S16_NATIVE
16-bit signed integer, native
Definition sound4cl.hpp:70
@ info
info
Definition sound4cl.hpp:273
C interface for library.
struct _tlgProvider_t const * TraceLoggingHProvider
static void cloudx1_custom_getall_free(fs_char **all, void *userdata)
static void cloudx1_custom_reader_free(char *content, void *userdata)
static int cloudx1_custom_exists(const fs_char *filename, void *userdata)
static int cloudx1_custom_remove(const fs_char *filename, void *userdata)
static char * cloudx1_custom_reader(const fs_char *filename, void *userdata)
static int cloudx1_custom_rename(const fs_char *from, const fs_char *to, void *userdata)
static fs_char ** cloudx1_custom_getall(void *userdata)
static int cloudx1_custom_writer(const fs_char *filename, const char *content, void *userdata)
static void cloudx1_custom_getall_free(fs_char **all, void *userdata)
static void cloudx1_custom_reader_free(char *content, void *userdata)
static int cloudx1_custom_exists(const fs_char *filename, void *userdata)
static int cloudx1_custom_remove(const fs_char *filename, void *userdata)
static char * cloudx1_custom_reader(const fs_char *filename, void *userdata)
static int cloudx1_custom_rename(const fs_char *from, const fs_char *to, void *userdata)
static fs_char ** cloudx1_custom_getall(void *userdata)
static int cloudx1_custom_writer(const fs_char *filename, const char *content, void *userdata)