SOUND4 IMPACT.CL Library [1.3.12]
Loading...
Searching...
No Matches
sound4cl.hpp
Go to the documentation of this file.
1
8#pragma once
9
10#include <string>
11#include <exception>
12#include <thread>
13#include <functional>
14#include <memory>
15#include <array>
16#include <assert.h>
17#include <stdexcept>
18#include <filesystem>
19#include <string.h>
20
21#if defined(__unix__) || defined(__APPLE__)
22 #define UNIXLIKE 1
23#else
24 #define UNIXLIKE 0
25#endif
26
27#if UNIXLIKE
28 #include <dlfcn.h>
29#elif defined(_WIN32)
30 #include <libloaderapi.h>
31 #ifdef _MSC_VER
32 #pragma warning(disable : 4996)
33 #endif
34#else
35 #error "Unsupported OS"
36#endif
37
38#include "sound4cl_cdef.h"
39
40 // bridge C callbacks to CPresetLoader
41 extern "C" {
42 static char *sound4cl_custom_reader(const fs_char *filename, void* userdata);
43 static void sound4cl_custom_reader_free(char *content, void* userdata);
44 static int sound4cl_custom_writer(const fs_char *filename, const char *content, void* userdata);
45 static int sound4cl_custom_exists(const fs_char *filename, void* userdata);
46 static fs_char** sound4cl_custom_getall(void* userdata);
47 static void sound4cl_custom_getall_free(fs_char** all, void* userdata);
48 static int sound4cl_custom_remove(const fs_char *filename, void* userdata);
49 static int sound4cl_custom_rename(const fs_char *from, const fs_char *to, void* userdata);
50 };
51
55namespace sound4 {
56
75
79 namespace helper {
80 #ifdef _WIN32
86 static inline std::string WStringToUTF8(const std::wstring& wstr) {
87 if (wstr.empty()) return {};
88 int size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
89 std::string str(size, 0);
90 WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &str[0], size, NULL, NULL);
91 return str;
92 }
98 static inline std::wstring UTF8ToWString(const std::string& str) {
99 if (str.empty()) return std::wstring();
100 int size = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
101 std::wstring wstr(size, 0);
102 MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstr[0], size);
103 return wstr;
104 }
105 #endif // _WIN32
106
112 template<typename T>
114 };
115 template<>
116 struct SampleFormat<int16_t> {
117 const sound4::SampleFormat format = S16_NATIVE;
118 };
119 template<>
120 struct SampleFormat<int32_t> {
121 const sound4::SampleFormat format = S32_NATIVE;
122 };
123 template<>
124 struct SampleFormat<float> {
125 const sound4::SampleFormat format = F32_NATIVE;
126 };
127
133 template <typename T>
135 // Storage definition, depending on OS
136 #if UNIXLIKE
137 using DynFunc_t = void *;
138 #else
139 using DynFunc_t = FARPROC;
140 #endif
141 private:
142 DynFunc_t m_ptr = NULL;
143 public:
144 DynFuncHolder() = default;
146 operator bool() const { return (m_ptr!=NULL); }
147 bool IsOk() const { return m_ptr!=NULL; }
148 operator T* () const { return reinterpret_cast<T*>(m_ptr); }
149 };
150
156 // Storage definition, depending on OS
157 #if UNIXLIKE
158 using DynLib_t = void *;
159 #else
160 using DynLib_t = HMODULE;
161 #endif
162 private:
163 DynLib_t m_lib {};
164 public:
165 CDynLoader() = default;
166 CDynLoader(CDynLoader&&) = default;
167 // No copy allowed
168 CDynLoader(const CDynLoader&) = delete;
169 CDynLoader& operator=(CDynLoader const&) = delete;
170 operator bool() const {
171 return (m_lib!=NULL);
172 }
173 bool IsOk() const {
174 return (m_lib!=NULL);
175 }
176 #if UNIXLIKE
177 void Close() {
178 if (IsOk()) {
179 #ifndef __SANITIZE_ADDRESS__ // avoid unloading to keep call stack
180 dlclose(m_lib);
181 #endif // __SANITIZE_ADDRESS__
182 m_lib=NULL;
183 }
184 }
185 bool Load(const std::filesystem::path& dynlib)
186 {
187 Close();
188 m_lib=dlopen(dynlib.c_str(), RTLD_NOW|RTLD_LOCAL);
189 return IsOk();
190 }
191 template <typename T>
192 DynFuncHolder<T> GetSymbol(const std::string& name) {
193 auto ptr=dlsym(m_lib, name.c_str());
194 if (!ptr) {
195 throw std::runtime_error("Missing function in library");
196 }
197 return DynFuncHolder<T>(ptr);
198 }
199 template <typename T>
200 DynFuncHolder<T> GetSymbol_safe(const std::string& name) {
201 auto ptr=dlsym(m_lib, name.c_str());
202 return DynFuncHolder<T>(ptr);
203 }
204 static std::filesystem::path GetThisLibraryPath(void) {
205 static Dl_info info;
206 if (! dladdr((void *) GetThisLibraryPath, & info)) return {};
207 auto rp=realpath(info.dli_fname, NULL);
208 if (!rp) {
209 #if defined(__unix__)
210 rp=realpath("/proc/self/exe", NULL);
211 #elif defined(__APPLE__)
212 // How to solve this for Apple ?
213 #endif
214 }
215 std::filesystem::path p(rp);
216 free(rp);
217 return p;
218 }
219 #else
226 void Close() {
227 if (IsOk()) {
228 // NOTE: On Windows, FreeLibrary may create a lot of troubles, should use FreeLibraryAndExitThread but...
229 // So define SOUND4_CALL_FREELIBRARY before including this file if you really want to unload the library dynamically
230 #if defined(SOUND4_CALL_FREELIBRARYANDEXITTHREAD)
231 FreeLibraryAndExitThread(m_lib, 0);
232 #elif defined(SOUND4_CALL_FREELIBRARY)
233 FreeLibrary(m_lib);
234 #endif // SOUND4_CALL_FREELIBRARY
235 m_lib=NULL;
236 }
237 }
238 template <typename T>
239 DynFuncHolder<T> GetSymbol(const std::string& name) {
240 auto ptr=GetProcAddress(m_lib, name.c_str());
241 if (!ptr) {
242 throw std::runtime_error("Missing function in library");
243 }
244 return DynFuncHolder<T>(ptr);
245 }
246 template <typename T>
247 DynFuncHolder<T> GetSymbol_safe(const std::string& name) {
248 auto ptr=GetProcAddress(m_lib, name.c_str());
249 return DynFuncHolder<T>(ptr);
250 }
251 static std::filesystem::path GetThisLibraryPath(void) {
252 static wchar_t path[MAX_PATH]={};
253 HMODULE hm = NULL;
257 {
258 if (GetModuleFileNameW(hm, path, MAX_PATH) > 0) {
259 return std::filesystem::path(path);
260 }
261 }
262 return {};
263 }
264 #endif
265 virtual ~CDynLoader() {
266 Close();
267 }
268 }; // class CDynLoader
269 }; // namespace helper
270
271
276 none = sound4cl_none,
277 fatal = sound4cl_fatal,
278 error = sound4cl_error,
279 warning = sound4cl_warning,
280 info = sound4cl_info,
281 verbose = sound4cl_verbose,
282 verbose2 = sound4cl_verbose2,
283 verbose3 = sound4cl_verbose3,
284 verbose4 = sound4cl_verbose4,
285 verbose5 = sound4cl_verbose5,
286 };
287
291 using log_cb_t = std::function<void(LogSeverity,const std::string&)>;
292
297 extern "C" {
298 static inline void _log_cb_c(sound4cl_LogSeverity severity, const char *c_msg) {
299 _log_cb((LogSeverity)severity, std::string(c_msg));
300 }
301 }
302
310 private:
311 helper::CDynLoader m_lib;
312 bool m_bOK = false;
313 std::string m_prefix; // The prefix of functions, depends on the library (cloud_, impact_...)
314 protected:
315 friend class CBus;
316 friend class CInstance;
317
318 // All those wrapped functions have the same signature as there C sound4cl_XXX
319 helper::DynFuncHolder< decltype(sound4cl_GetVersion ) > fnGetVersion ;
320 helper::DynFuncHolder< decltype(sound4cl_GetChunkSizeInFrames ) > fnGetChunkSizeInFrames ;
321 helper::DynFuncHolder< decltype(sound4cl_GetChannelCount ) > fnGetChannelCount ;
322 helper::DynFuncHolder< decltype(sound4cl_GetAudioInputCount ) > fnGetAudioInputCount ;
323 helper::DynFuncHolder< decltype(sound4cl_GetAudioOutputCount ) > fnGetAudioOutputCount ;
324 helper::DynFuncHolder< decltype(sound4cl_GetSampleRate ) > fnGetSampleRate ;
325 helper::DynFuncHolder< decltype(sound4cl_SetLoggerCallback ) > fnSetLoggerCallback ;
326 helper::DynFuncHolder< decltype(sound4cl_SetLogSeverity ) > fnSetLogSeverity ;
327 helper::DynFuncHolder< decltype(sound4cl_NewParameters ) > fnNewParameters ;
328 helper::DynFuncHolder< decltype(sound4cl_FreeParameters ) > fnFreeParameters ;
329 helper::DynFuncHolder< decltype(sound4cl_SetParameter ) > fnSetParameter ;
330 helper::DynFuncHolder< decltype(sound4cl_GetParameter ) > fnGetParameter ;
331 helper::DynFuncHolder< decltype(sound4cl_FreeParameterValue ) > fnFreeParameterValue ;
332 helper::DynFuncHolder< decltype(sound4cl_InitProcess ) > fnInitProcess ;
333 helper::DynFuncHolder< decltype(sound4cl_InitProcess2 ) > fnInitProcess2 ;
334 helper::DynFuncHolder< decltype(sound4cl_TerminateProcess ) > fnTerminateProcess ;
335 helper::DynFuncHolder< decltype(sound4cl_ExitProcess ) > fnExitProcess ;
336 helper::DynFuncHolder< decltype(sound4cl_StartUpdateThread ) > fnStartUpdateThread ;
337 helper::DynFuncHolder< decltype(sound4cl_StopUpdateThread ) > fnStopUpdateThread ;
338 helper::DynFuncHolder< decltype(sound4cl_WaitUpdateThreadReady ) > fnWaitUpdateThreadReady ;
339 helper::DynFuncHolder< decltype(sound4cl_ProcessAudio ) > fnProcessAudio ;
340 helper::DynFuncHolder< decltype(sound4cl_ProcessAudio_Planar ) > fnProcessAudio_Planar ;
341 helper::DynFuncHolder< decltype(sound4cl_GetBufferIn ) > fnGetBufferIn ;
342 helper::DynFuncHolder< decltype(sound4cl_GetBufferOut ) > fnGetBufferOut ;
343 helper::DynFuncHolder< decltype(sound4cl_GetEstimatedDelay ) > fnGetEstimatedDelay ;
344 helper::DynFuncHolder< decltype(sound4cl_GetFormatName ) > fnGetFormatName ;
345 helper::DynFuncHolder< decltype(sound4cl_GetFormatFromName ) > fnGetFormatFromName ;
346 helper::DynFuncHolder< decltype(sound4cl_GetBytesFromFormat ) > fnGetBytesFromFormat ;
347 helper::DynFuncHolder< decltype(sound4cl_GetMaxPacketFrame ) > fnGetMaxPacketFrame ;
348 helper::DynFuncHolder< decltype(sound4cl_AddAudio ) > fnAddAudio ;
349 helper::DynFuncHolder< decltype(sound4cl_AddPadAudio ) > fnAddPadAudio ;
350 helper::DynFuncHolder< decltype(sound4cl_GetOutputCount ) > fnGetOutputCount ;
351 helper::DynFuncHolder< decltype(sound4cl_GetAudio ) > fnGetAudio ;
352 helper::DynFuncHolder< decltype(sound4cl_AudioConvertFrom ) > fnAudioConvertFrom ;
353 helper::DynFuncHolder< decltype(sound4cl_AudioConvertTo ) > fnAudioConvertTo ;
354 helper::DynFuncHolder< decltype(sound4cl_StereoToMono ) > fnStereoToMono ;
355 helper::DynFuncHolder< decltype(sound4cl_MonoToStereo ) > fnMonoToStereo ;
356 helper::DynFuncHolder< decltype(sound4cl_AudioMonoFromLiveStereo) > fnAudioMonoFromLiveStereo;
357 helper::DynFuncHolder< decltype(sound4cl_AudioMonoToLiveStereo ) > fnAudioMonoToLiveStereo ;
358 helper::DynFuncHolder< decltype(sound4cl_NewClient ) > fnNewClient ;
359 helper::DynFuncHolder< decltype(sound4cl_DeleteClient ) > fnDeleteClient ;
360 helper::DynFuncHolder< decltype(sound4cl_ProcessJson ) > fnProcessJson ;
361 helper::DynFuncHolder< decltype(sound4cl_FreeJsonAnswer ) > fnFreeJsonAnswer ;
362 helper::DynFuncHolder< decltype(sound4cl_SaveState ) > fnSaveState ;
363
364 // only for processes supporting webserver
365 helper::DynFuncHolder< decltype(sound4cl_Webserver_tcp ) > fnWebserver_tcp ;
366 helper::DynFuncHolder< decltype(sound4cl_Webserver_tcp2 ) > fnWebserver_tcp2 ;
367 helper::DynFuncHolder< decltype(sound4cl_Webserver ) > fnWebserver ;
368 helper::DynFuncHolder< decltype(sound4cl_Webserver_Stop ) > fnWebserver_Stop ;
369 helper::DynFuncHolder< decltype(sound4cl_Webserver_Status ) > fnWebserver_Status ;
370
371 // added 2023-03-22
372 helper::DynFuncHolder< decltype(sound4cl_StereoToMono_Planar ) > fnStereoToMono_Planar ;
373 helper::DynFuncHolder< decltype(sound4cl_MonoToStereo_Planar ) > fnMonoToStereo_Planar ;
374
375 // added 2023-05-22
376 helper::DynFuncHolder< decltype(sound4cl_SetMetadata ) > fnSetMetadata ;
377 helper::DynFuncHolder< decltype(sound4cl_GetMetadataInfos ) > fnGetMetadataInfos ;
378 helper::DynFuncHolder< decltype(sound4cl_FreeMetadataInfos ) > fnFreeMetadataInfos ;
379
380 // added 2023-06-20
381 helper::DynFuncHolder< decltype(sound4cl_SetPresetManager ) > fnSetPresetManager ;
382 helper::DynFuncHolder< decltype(sound4cl_PresetManager_InformChange ) > fnPresetManager_InformChange ;
383
384 // added 2023-09-21
385 helper::DynFuncHolder< decltype(sound4cl_GetPossibleChunkSizeInFrames ) > fnGetPossibleChunkSizeInFrames ;
386 helper::DynFuncHolder< decltype(sound4cl_GetProcessChunkFrames ) > fnGetProcessChunkFrames ;
387 helper::DynFuncHolder< decltype(sound4cl_InitProcess3 ) > fnInitProcess3 ;
388
389 // added 2023-06-26, only for processes supporting bus
390 helper::DynFuncHolder< decltype(sound4cl_NewBus ) > fnNewBus ;
391 helper::DynFuncHolder< decltype(sound4cl_FreeBus ) > fnFreeBus ;
392 helper::DynFuncHolder< decltype(sound4cl_SetInstanceBus ) > fnSetInstanceBus ;
393
394 // added 2024-02-19
395 helper::DynFuncHolder< decltype(sound4cl_SetMetadataMulti ) > fnSetMetadataMulti ;
396
397 // added 2024-05-23
398 helper::DynFuncHolder< decltype(sound4cl_Webserver_SetAppHealth ) > fnWebserver_SetAppHealth ;
399 helper::DynFuncHolder< decltype(sound4cl_Webserver_GetAppHealth ) > fnWebserver_GetAppHealth ;
400 helper::DynFuncHolder< decltype(sound4cl_Webserver_FreeString ) > fnWebserver_FreeString ;
401
402#ifdef _WIN32
403 // added 2025-05-28
404 helper::DynFuncHolder< decltype(sound4cl_SetInstanceTracing ) > fnSetInstanceTracing ;
405 helper::DynFuncHolder< decltype(sound4cl_SetInstanceTracingProcessActivity ) > fnSetInstanceTracingProcessActivity ;
406#endif // _WIN32
407
408 template <typename T>
409 helper::DynFuncHolder<T> GetPrefixSymbol(const std::string& name) {
410 std::string prefix_name = m_prefix+name;
411 return m_lib.GetSymbol<T>(prefix_name);
412 }
413
414 public:
415 CProcessor() = default;
416
424 bool Load(const std::filesystem::path& filepath) {
425 m_lib.Close();
426 // If a path is given, use it directly and do not try other path
427 if (filepath.has_parent_path() && !m_lib.Load(filepath)) {
428 return false;
429 } else if (!m_lib.IsOk()) {
430 auto thisdir=helper::CDynLoader::GetThisLibraryPath().parent_path();
431 auto filename = filepath.filename();
432 #ifndef _WIN32
433 // Linux: if in a bin directory, try ../lib first
434 if (!m_lib.IsOk() && thisdir.filename()=="bin") {
435 auto libdir = thisdir.parent_path() / "lib";
436 m_lib.Load(libdir / filename);
437 }
438 #endif // !_WIN32
439 if (!m_lib.IsOk()) {
440 // Search in the same directory this code is in
441 m_lib.Load(thisdir / filename);
442 }
443 if (!m_lib.IsOk()) {
444 // Try current path
445 std::error_code ec;
446 auto p = std::filesystem::current_path(ec);
447 if (!ec) {
448 m_lib.Load(p / filename);
449 }
450 }
451 if (!m_lib.IsOk()) {
452 return false;
453 }
454 }
455 // Get information from the library itself
456 try {
457 auto GetInfo = m_lib.GetSymbol< decltype(sound4cl_SOUND4_GetProcessInfo ) >("SOUND4_GetProcessInfo" );
458 auto info = GetInfo();
459 m_prefix = info->prefix;
460 } catch (std::runtime_error& ) {
461 // Compatibility: search in known libraries without this function
462 #ifdef _WIN32
463 std::string filename = helper::WStringToUTF8(filepath.stem());
464 #else // !_WIN32
465 std::string filename = filepath.stem();
466 // remove lib prefix
467 filename=filename.substr(3);
468 #endif // ! _WIN32
469 if (filename=="sound4.x1.cloud") {
470 m_prefix="cloudx1_";
471 } else if (filename=="sound4.impact.cl") {
472 m_prefix="impact_";
473 } else if (filename=="sound4.bigvoice.cl") {
474 m_prefix="bigvoice_";
475 } else {
476 return false;
477 }
478 }
479
480 // Load all C functions
481 try {
482 fnGetVersion = GetPrefixSymbol< decltype(sound4cl_GetVersion ) >("GetVersion" );
483 fnGetChunkSizeInFrames = GetPrefixSymbol< decltype(sound4cl_GetChunkSizeInFrames ) >("GetChunkSizeInFrames" );
484 fnGetChannelCount = GetPrefixSymbol< decltype(sound4cl_GetChannelCount ) >("GetChannelCount" );
485 fnGetAudioInputCount = GetPrefixSymbol< decltype(sound4cl_GetAudioInputCount ) >("GetAudioInputCount" );
486 fnGetAudioOutputCount = GetPrefixSymbol< decltype(sound4cl_GetAudioOutputCount ) >("GetAudioOutputCount" );
487 fnGetSampleRate = GetPrefixSymbol< decltype(sound4cl_GetSampleRate ) >("GetSampleRate" );
488 fnSetLoggerCallback = GetPrefixSymbol< decltype(sound4cl_SetLoggerCallback ) >("SetLoggerCallback" );
489 fnSetLogSeverity = GetPrefixSymbol< decltype(sound4cl_SetLogSeverity ) >("SetLogSeverity" );
490 fnNewParameters = GetPrefixSymbol< decltype(sound4cl_NewParameters ) >("NewParameters" );
491 fnFreeParameters = GetPrefixSymbol< decltype(sound4cl_FreeParameters ) >("FreeParameters" );
492 fnSetParameter = GetPrefixSymbol< decltype(sound4cl_SetParameter ) >("SetParameter" );
493 fnGetParameter = GetPrefixSymbol< decltype(sound4cl_GetParameter ) >("GetParameter" );
494 fnFreeParameterValue = GetPrefixSymbol< decltype(sound4cl_FreeParameterValue ) >("FreeParameterValue" );
495 fnInitProcess = GetPrefixSymbol< decltype(sound4cl_InitProcess ) >("InitProcess" );
496 fnInitProcess2 = GetPrefixSymbol< decltype(sound4cl_InitProcess2 ) >("InitProcess2" );
497 fnTerminateProcess = GetPrefixSymbol< decltype(sound4cl_TerminateProcess ) >("TerminateProcess" );
498 fnExitProcess = GetPrefixSymbol< decltype(sound4cl_ExitProcess ) >("ExitProcess" );
499 fnStartUpdateThread = GetPrefixSymbol< decltype(sound4cl_StartUpdateThread ) >("StartUpdateThread" );
500 fnStopUpdateThread = GetPrefixSymbol< decltype(sound4cl_StopUpdateThread ) >("StopUpdateThread" );
501 fnWaitUpdateThreadReady = GetPrefixSymbol< decltype(sound4cl_WaitUpdateThreadReady ) >("WaitUpdateThreadReady" );
502 fnProcessAudio = GetPrefixSymbol< decltype(sound4cl_ProcessAudio ) >("ProcessAudio" );
503 fnProcessAudio_Planar = GetPrefixSymbol< decltype(sound4cl_ProcessAudio_Planar ) >("ProcessAudio_Planar" );
504 fnGetBufferIn = GetPrefixSymbol< decltype(sound4cl_GetBufferIn ) >("GetBufferIn" );
505 fnGetBufferOut = GetPrefixSymbol< decltype(sound4cl_GetBufferOut ) >("GetBufferOut" );
506 fnGetEstimatedDelay = GetPrefixSymbol< decltype(sound4cl_GetEstimatedDelay ) >("GetEstimatedDelay" );
507 fnGetFormatName = GetPrefixSymbol< decltype(sound4cl_GetFormatName ) >("GetFormatName" );
508 fnGetFormatFromName = GetPrefixSymbol< decltype(sound4cl_GetFormatFromName ) >("GetFormatFromName" );
509 fnGetBytesFromFormat = GetPrefixSymbol< decltype(sound4cl_GetBytesFromFormat ) >("GetBytesFromFormat" );
510 fnGetMaxPacketFrame = GetPrefixSymbol< decltype(sound4cl_GetMaxPacketFrame ) >("GetMaxPacketFrame" );
511 fnAddAudio = GetPrefixSymbol< decltype(sound4cl_AddAudio ) >("AddAudio" );
512 fnAddPadAudio = GetPrefixSymbol< decltype(sound4cl_AddPadAudio ) >("AddPadAudio" );
513 fnGetOutputCount = GetPrefixSymbol< decltype(sound4cl_GetOutputCount ) >("GetOutputCount" );
514 fnGetAudio = GetPrefixSymbol< decltype(sound4cl_GetAudio ) >("GetAudio" );
515 fnAudioConvertFrom = GetPrefixSymbol< decltype(sound4cl_AudioConvertFrom ) >("AudioConvertFrom" );
516 fnAudioConvertTo = GetPrefixSymbol< decltype(sound4cl_AudioConvertTo ) >("AudioConvertTo" );
517 fnStereoToMono = GetPrefixSymbol< decltype(sound4cl_StereoToMono ) >("StereoToMono" );
518 fnMonoToStereo = GetPrefixSymbol< decltype(sound4cl_MonoToStereo ) >("MonoToStereo" );
519 fnAudioMonoFromLiveStereo = GetPrefixSymbol< decltype(sound4cl_AudioMonoFromLiveStereo) >("AudioMonoFromLiveStereo");
520 fnAudioMonoToLiveStereo = GetPrefixSymbol< decltype(sound4cl_AudioMonoToLiveStereo ) >("AudioMonoToLiveStereo" );
521 fnNewClient = GetPrefixSymbol< decltype(sound4cl_NewClient ) >("NewClient" );
522 fnDeleteClient = GetPrefixSymbol< decltype(sound4cl_DeleteClient ) >("DeleteClient" );
523 fnProcessJson = GetPrefixSymbol< decltype(sound4cl_ProcessJson ) >("ProcessJson" );
524 fnFreeJsonAnswer = GetPrefixSymbol< decltype(sound4cl_FreeJsonAnswer ) >("FreeJsonAnswer" );
525 fnSaveState = GetPrefixSymbol< decltype(sound4cl_SaveState ) >("SaveState" );
526 } catch (std::runtime_error& ) {
527 return false;
528 }
529 // Webserver : not for all projects
530 try {
531 fnWebserver_tcp = GetPrefixSymbol< decltype(sound4cl_Webserver_tcp ) >("Webserver_tcp" );
532 fnWebserver_tcp2 = GetPrefixSymbol< decltype(sound4cl_Webserver_tcp2 ) >("Webserver_tcp2" );
533 fnWebserver = GetPrefixSymbol< decltype(sound4cl_Webserver ) >("Webserver" );
534 fnWebserver_Stop = GetPrefixSymbol< decltype(sound4cl_Webserver_Stop ) >("Webserver_Stop" );
535 fnWebserver_Status = GetPrefixSymbol< decltype(sound4cl_Webserver_Status ) >("Webserver_Status" );
536 } catch (std::runtime_error& ) {
537 // Ignored, handler will take care
538 }
539 // Stereo/Mono conversion : must be present
540 try {
541 // added 2023-03-22
542 fnStereoToMono_Planar = GetPrefixSymbol< decltype(sound4cl_StereoToMono_Planar ) >("StereoToMono_Planar" );
543 fnMonoToStereo_Planar = GetPrefixSymbol< decltype(sound4cl_MonoToStereo_Planar ) >("MonoToStereo_Planar" );
544
545 } catch (std::runtime_error& ) {
546 return false;
547 }
548 // C functions allowed to be missing
549 try {
550 // added 2023-05-22
551 fnSetMetadata = GetPrefixSymbol< decltype(sound4cl_SetMetadata ) >("SetMetadata" );
552 fnGetMetadataInfos = GetPrefixSymbol< decltype(sound4cl_GetMetadataInfos ) >("GetMetadataInfos" );
553 fnFreeMetadataInfos = GetPrefixSymbol< decltype(sound4cl_FreeMetadataInfos ) >("FreeMetadataInfos" );
554 // added 2023-06-20
555 fnSetPresetManager = GetPrefixSymbol< decltype(sound4cl_SetPresetManager ) >("SetPresetManager" );
556 fnPresetManager_InformChange = GetPrefixSymbol< decltype(sound4cl_PresetManager_InformChange ) >("PresetManager_InformChange" );
557
558 // added 2023-09-21
559 fnGetPossibleChunkSizeInFrames = GetPrefixSymbol< decltype(sound4cl_GetPossibleChunkSizeInFrames ) >("GetPossibleChunkSizeInFrames" );
560 fnGetProcessChunkFrames = GetPrefixSymbol< decltype(sound4cl_GetProcessChunkFrames ) >("GetProcessChunkFrames" );
561 fnInitProcess3 = GetPrefixSymbol< decltype(sound4cl_InitProcess3 ) >("InitProcess3" );
562 } catch (std::runtime_error& ) {
563 // Ignored, handler will take care
564 }
565
566 // bus: not for all projects
567 try {
568 // added 2023-06-26
569 fnNewBus = GetPrefixSymbol< decltype(sound4cl_NewBus ) >("NewBus" );
570 fnFreeBus = GetPrefixSymbol< decltype(sound4cl_FreeBus ) >("FreeBus" );
571 fnSetInstanceBus = GetPrefixSymbol< decltype(sound4cl_SetInstanceBus ) >("SetInstanceBus" );
572 } catch (std::runtime_error& ) {
573 // Ignored, handler will take care
574 }
575
576 // Other optional
577 try {
578 // added 2024-02-19
579 fnSetMetadataMulti = GetPrefixSymbol< decltype(sound4cl_SetMetadataMulti ) >("SetMetadataMulti" );
580
581 } catch (std::runtime_error& ) {
582 // Ignored, handler will take care
583 }
584
585 // Other optional, web server only
586 try {
587 // added 2024-05-23
588 fnWebserver_SetAppHealth = GetPrefixSymbol< decltype(sound4cl_Webserver_SetAppHealth ) >("Webserver_SetAppHealth" );
589 fnWebserver_GetAppHealth = GetPrefixSymbol< decltype(sound4cl_Webserver_GetAppHealth ) >("Webserver_GetAppHealth" );
590 fnWebserver_FreeString = GetPrefixSymbol< decltype(sound4cl_Webserver_FreeString ) >("Webserver_FreeString" );
591 } catch (std::runtime_error& ) {
592 // Ignored, handler will take care
593 }
594
595#ifdef _WIN32
596 // Other optional, windows tracing
597 try {
598 // added 2025-05-28
599 fnSetInstanceTracing = GetPrefixSymbol< decltype(sound4cl_SetInstanceTracing ) >("SetInstanceTracing" );
600 fnSetInstanceTracingProcessActivity= GetPrefixSymbol< decltype(sound4cl_SetInstanceTracingProcessActivity ) >("SetInstanceTracingProcessActivity");
601 } catch (std::runtime_error& ) {
602 // Ignored, handler will take care
603 }
604#endif // _WIN32
605
606 m_bOK=true;
607 return true;
608 }
615 bool IsOk() const {
616 return m_bOK;
617 }
618
619 // --------------------------------------------------------------
626 // --------------------------------------------------------------
637 void AudioConvertFrom(const uint8_t *payload, float *output, size_t nSpl, SampleFormat fmt)
638 { fnAudioConvertFrom(payload, output, nSpl, (sound4cl_SampleFormat)fmt); }
639
650 void AudioConvertTo(const float *input, uint8_t *payload, size_t nSpl, SampleFormat fmt)
651 { fnAudioConvertTo(input, payload, nSpl, (sound4cl_SampleFormat)fmt); }
652
662 void StereoToMono(const float *input, float *output, size_t nFrame)
663 { fnStereoToMono(input, output, nFrame); }
664
674 void MonoToStereo(const float *input, float *output, size_t nFrame)
675 { fnMonoToStereo(input, output, nFrame); }
676
687 void StereoToMono_Planar(const float *inputL, const float *inputR, float *output, size_t nFrame)
688 { fnStereoToMono_Planar(inputL, inputR, output, nFrame); }
689
700 void MonoToStereo_Planar(const float *input, float *outputL, float *outputR, size_t nFrame)
701 { fnMonoToStereo_Planar(input, outputL, outputR, nFrame); }
702
709 void AudioMonoFromLiveStereo(const uint8_t *payload, float *output)
710 { fnAudioMonoFromLiveStereo(payload, output); }
711
718 void AudioMonoToLiveStereo(const float *input, uint8_t *payload)
719 { fnAudioMonoToLiveStereo(input, payload); }
720
728 std::string GetVersion()
729 { return std::string(fnGetVersion()); }
730
741 unsigned int GetChunkSizeInFrames()
742 { return fnGetChunkSizeInFrames(); }
743
752 std::vector<unsigned int> GetPossibleChunkSizeInFrames()
753 {
754 std::vector<unsigned int> list;
755 if (fnGetPossibleChunkSizeInFrames) {
756 for (unsigned int* src=fnGetPossibleChunkSizeInFrames();*src;src++) {
757 list.push_back(*src);
758 }
759 } else {
760 list.push_back(fnGetChunkSizeInFrames());
761 }
762 return list;
763 }
764
770 unsigned int GetChannelCount()
771 { return fnGetChannelCount(); }
772
780 unsigned int GetAudioInputCount()
781 { return fnGetAudioInputCount(); }
782
790 unsigned int GetAudioOutputCount()
791 { return fnGetAudioOutputCount(); }
792
800 unsigned int GetSampleRate()
801 { return fnGetSampleRate(); }
802
809 std::string GetFormatName( const SampleFormat fmt)
810 { return std::string(fnGetFormatName((sound4cl_SampleFormat)fmt)); }
811
818 SampleFormat GetFormatFromName( const std::string& name)
819 { return SampleFormat(fnGetFormatFromName(name.c_str())); }
820
827 unsigned int GetBytesFromFormat( const SampleFormat fmt)
828 { return fnGetBytesFromFormat((sound4cl_SampleFormat)fmt); }
829
834 { fnSetLogSeverity((sound4cl_LogSeverity)severity); }
835
840 { _log_cb=cb; fnSetLoggerCallback(&_log_cb_c); }
841 };
842
848 class CBus {
849 public:
851 : m_dynlib(dynlib)
852 {
853 if (m_dynlib.fnNewBus) {
854 m_bus=m_dynlib.fnNewBus();
855 }
856 }
858 {
859 if (m_bus && m_dynlib.fnFreeBus) {
860 m_dynlib.fnFreeBus(m_bus);
861 }
862 m_bus = nullptr;
863 }
864 protected:
865 friend class CInstance;
866 sound4cl_CBus *Get() const { return m_bus; }
867 private:
868 CProcessor& m_dynlib;
869 sound4cl_CBus *m_bus;
870 };
871
878 public:
879 CPresetLoader() = default;
880 virtual ~CPresetLoader() = default;
881
882 virtual bool IsReadOnly() = 0;
883 virtual bool Exists(const std::filesystem::path &name) = 0;
884 virtual bool Remove(const std::filesystem::path &name) = 0;
885 virtual bool Rename(const std::filesystem::path &from, const std::filesystem::path &to) = 0;
886 virtual std::vector<std::filesystem::path> GetAll() = 0;
887 virtual std::string Read(const std::filesystem::path &filename) = 0;
888 virtual bool Write(const std::filesystem::path &filename, const std::string &content) =0;
889 };
900 class CInstance {
901 public:
908 : m_dynlib(dynlib)
909 {
910 params = m_dynlib.fnNewParameters();
911 if (!params) throw std::bad_alloc();
912 }
913
922 CInstance(CProcessor& dynlib, void* _instance)
923 : m_dynlib(dynlib)
924 , instance(reinterpret_cast<sound4cl_CInstance*>(_instance))
925 , m_bOwned(false)
926 {
927 }
928 // non-copyable
929 CInstance( const CInstance& ) = delete;
930 CInstance& operator=( const CInstance& ) = delete;
934 virtual ~CInstance()
935 {
936 Stop();
937 if (params) m_dynlib.fnFreeParameters(params);
938 }
942 bool IsOk() const { return instance!=nullptr; }
952 void SetParam(const std::string& name, const std::string& value)
953 {
954 assert(params);
955 m_dynlib.fnSetParameter(params, name.c_str(), value.c_str());
956 }
963 std::string GetParam(const std::string& name)
964 {
965 assert(params);
966 auto c_value=m_dynlib.fnGetParameter(params, name.c_str());
967 std::string ret(c_value);
968 m_dynlib.fnFreeParameterValue(c_value);
969 return ret;
970 }
971
980 void SetBus(const CBus& bus) {
981 assert(params);
982 if (m_dynlib.fnSetInstanceBus) {
983 m_dynlib.fnSetInstanceBus(params,bus.Get());
984 }
985 }
986
997 void SetPresetManager(CPresetLoader *preset_manager)
998 {
999 if (!preset_manager) return;
1000 if (!m_dynlib.fnSetPresetManager) return;
1001 assert(params);
1002 m_dynlib.fnSetPresetManager(params,
1003 sound4cl_custom_reader,
1004 sound4cl_custom_reader_free,
1005 sound4cl_custom_writer,
1006 sound4cl_custom_exists,
1007 sound4cl_custom_getall,
1008 sound4cl_custom_getall_free,
1009 sound4cl_custom_remove,
1010 sound4cl_custom_rename,
1011 preset_manager->IsReadOnly(),
1012 preset_manager
1013 );
1014 }
1015
1038 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=0)
1039 {
1040 assert(!instance);
1041 std::string l_save_path;
1042 if (!save_path.empty()) {
1043 l_save_path = save_path.u8string();
1044 }
1045 if (frames_per_chunk==0) {
1046 frames_per_chunk=m_dynlib.GetChunkSizeInFrames();
1047 }
1048 if (m_dynlib.fnInitProcess3) {
1049 instance = m_dynlib.fnInitProcess3(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);
1050 } else if (frames_per_chunk!=m_dynlib.GetChunkSizeInFrames()) {
1051 return false;
1052 } else {
1053 instance = m_dynlib.fnInitProcess2(LoginKey.c_str(), RadioName.c_str(), Access_Key_ID.c_str(), Access_Key_Secret.c_str(), l_save_path.c_str(), params);
1054 }
1055 if (!instance) return false;
1056 if (!init_metadata.empty()) {
1057 for (auto&& [key,value]: init_metadata) {
1058 m_dynlib.fnSetMetadata(instance, key.c_str(), value.c_str());
1059 }
1060 init_metadata.clear();
1061 }
1062 update_thread = std::thread([this, json_port](){
1064 m_dynlib.fnStartUpdateThread(instance, json_port);
1066 });
1067 int timeout=5000;
1068 #ifdef DEBUG
1069 timeout=60*1000; // For debugger pauses
1070 #endif
1071 if (m_dynlib.fnWaitUpdateThreadReady(instance, timeout)<0) {
1072 return false;
1073 }
1074 return true;
1075 }
1076
1084 unsigned int GetChunkFrames() {
1085 if (instance && m_dynlib.fnGetProcessChunkFrames) {
1086 return m_dynlib.fnGetProcessChunkFrames(instance);
1087 }
1088 return m_dynlib.fnGetChunkSizeInFrames();
1089 }
1090
1098 void PresetManager_InformChange(const std::filesystem::path& relative_path, PresetChange_Kind change_kind)
1099 {
1100 if (m_dynlib.fnPresetManager_InformChange) {
1101 m_dynlib.fnPresetManager_InformChange(instance, relative_path.c_str(), (sound4cl_PresetChange_Kind) change_kind);
1102 }
1103 }
1104
1116 void SetMetadata(const std::string& key, const char* value)
1117 {
1118 if (m_dynlib.fnSetMetadata) {
1119 if (instance) {
1120 m_dynlib.fnSetMetadata(instance, key.c_str(), value);
1121 } else {
1122 init_metadata.push_back( {key, value} );
1123 }
1124 }
1125 }
1126
1136 void SetMetadataMulti(const std::unordered_map<std::string, const char*>& list)
1137 {
1138 if (instance) {
1139 if (m_dynlib.fnSetMetadataMulti) {
1140 typedef const char* pchar;
1141 pchar* keyvalue=new pchar[2*list.size()+1];
1142 size_t n=0;
1143 for (auto&& [key,value]: list) {
1144 keyvalue[2*n+0]=key.c_str();
1145 keyvalue[2*n+1]=value;
1146 n++;
1147 }
1148 keyvalue[2*n+0]=nullptr;
1149
1150 sound4cl_SetMetadataMulti(instance, keyvalue);
1151
1152 delete[] keyvalue;
1153 } else {
1154 for (auto&& [key,value]: list) {
1155 SetMetadata(key, value);
1156 }
1157 }
1158 } else {
1159 for (auto&& [key,value]: list) {
1160 if (value) {
1161 init_metadata.push_back( {key, value} );
1162 }
1163 }
1164 }
1165 }
1166
1172 std::vector< std::tuple<std::string,std::string> > GetMetadataInfos()
1173 {
1174 std::vector< std::tuple<std::string,std::string> > values;
1175 if (m_dynlib.fnGetMetadataInfos) {
1176 const char** c_values = m_dynlib.fnGetMetadataInfos(instance);
1177 if (c_values) {
1178 for (const char** c_value=c_values; *c_value; ) {
1179 std::string key(*c_value);
1180 c_value++;
1181 if (*c_value) {
1182 std::string descr(*c_value);
1183 c_value++;
1184 values.push_back( {key,descr} );
1185 }
1186 }
1187 m_dynlib.fnFreeMetadataInfos(instance, c_values);
1188 }
1189 }
1190 return values;
1191 }
1192
1196 virtual void OnUpdateThreadStart() {}
1200 virtual void OnUpdateThreadStop() {}
1201
1202
1216 bool StartWebServer(int http_port, int https_port=0)
1217 {
1218 assert(instance);
1219 assert(webserver==SOUND4_INVALID_WEBSERVER_ID);
1220 if (!m_dynlib.fnWebserver) {
1221 return false;
1222 }
1223 webserver = m_dynlib.fnWebserver(http_port,https_port,instance);
1224 if (webserver==SOUND4_INVALID_WEBSERVER_ID) {
1225 return false;
1226 }
1227 int web_status=m_dynlib.fnWebserver_Status(webserver);
1228 if (http_port && (web_status & SOUND4_WEBSERVER_HTTP_OK) == 0) {
1229 return false;
1230 }
1231 if (https_port && (web_status & SOUND4_WEBSERVER_HTTPS_OK) == 0) {
1232 return false;
1233 }
1234 return true;
1235 }
1236
1244 void StopWebServer(int timeout_ms = 1000)
1245 {
1246 if (!m_dynlib.fnWebserver_Stop) return;
1247 if (webserver != SOUND4_INVALID_WEBSERVER_ID) {
1248 m_dynlib.fnWebserver_Stop(webserver, timeout_ms);
1249 webserver = SOUND4_INVALID_WEBSERVER_ID;
1250 }
1251 }
1252
1256 void SetWebServerAppHealth(int httpcode, const std::string& contenttype, const std::string& content)
1257 {
1258 assert(instance);
1259 if (!m_dynlib.fnWebserver_SetAppHealth) return;
1260 m_dynlib.fnWebserver_SetAppHealth(instance, httpcode, contenttype.c_str(), content.c_str());
1261 }
1265 void GetWebServerAppHealth(int &httpcode, std::string& contenttype, std::string& content)
1266 {
1267 assert(instance);
1268 if (!m_dynlib.fnWebserver_GetAppHealth) return;
1269 char* c_contenttype=nullptr;
1270 char* c_content=nullptr;
1271 m_dynlib.fnWebserver_GetAppHealth(instance, &httpcode, &c_contenttype, &c_content);
1272 contenttype=c_contenttype;
1273 content=c_content;
1274 m_dynlib.fnWebserver_FreeString(c_contenttype);
1275 m_dynlib.fnWebserver_FreeString(c_content);
1276 }
1286 {
1287 if (!instance) return 0;
1288 return m_dynlib.fnTerminateProcess(instance);
1289 }
1290
1296 void Stop()
1297 {
1298 if (!instance) return;
1299 if (m_bOwned) {
1300 StopWebServer();
1301 if (update_thread.joinable()) {
1302 m_dynlib.fnStopUpdateThread(instance); // this will exit the update thread
1303 update_thread.join();
1304 }
1305 m_dynlib.fnExitProcess(instance);
1306 }
1307 instance=nullptr;
1308 }
1309
1319 unsigned int GetEstimatedDelay()
1320 {
1321 assert(instance);
1322 return m_dynlib.fnGetEstimatedDelay(instance);
1323 }
1324
1338 {
1339 assert(instance);
1340 return m_dynlib.fnGetBufferIn(instance);
1341
1342 }
1355 {
1356 assert(instance);
1357 return m_dynlib.fnGetBufferOut(instance);
1358 }
1363 {
1364 assert(instance);
1365 m_dynlib.fnProcessAudio(instance, GetBufferIn(), GetBufferOut());
1366 }
1378 void ProcessAudio_Planar(float const * const *input, float * const *output)
1379 {
1380 assert(instance);
1381 m_dynlib.fnProcessAudio_Planar(instance, input, output);
1382 }
1383
1395 template<typename T>
1396 std::vector<T> ProcessAnyAudio(const std::vector<T> input)
1397 {
1398 assert(instance);
1399 std::vector<T> output;
1400 unsigned int out_offset=0;
1401 unsigned int in_offset=0;
1402 unsigned int todo = input.size();
1403 while (todo>0) {
1404 unsigned int left = AddAudio(&input[in_offset], todo);
1405 unsigned int out_avail = m_dynlib.fnGetOutputCount(instance);
1406 output.resize(out_offset + out_avail);
1407 GetAudio(&output[out_offset], out_avail);
1408 out_offset+=out_avail;
1409 in_offset += todo-left;
1410 todo=left;
1411 }
1412 return output;
1413 }
1414
1420 class CClient {
1421 public:
1422 CClient(sound4cl_CInstance* instance, CProcessor& dynlib)
1423 : m_dynlib(dynlib)
1424 {
1425 assert(instance);
1426 client=m_dynlib.fnNewClient(instance);
1427 if (!client) throw std::bad_alloc();
1428 }
1429 // non-copyable
1430 CClient( const CInstance& ) = delete;
1431 CClient& operator=( const CInstance& ) = delete;
1433 {
1434 if (client) {
1435 m_dynlib.fnDeleteClient(client);
1436 client=nullptr;
1437 }
1438 }
1446 std::string ProcessJson(const std::string &request, bool *NeedSave = nullptr)
1447 {
1448 assert(client);
1449 int need_save=0;
1450 const char *canswer = m_dynlib.fnProcessJson(client, request.c_str(), &need_save);
1451 if (!canswer) return {};
1452 std::string answer(canswer);
1453 m_dynlib.fnFreeJsonAnswer (canswer);
1454 if (NeedSave) {
1455 *NeedSave=(need_save!=0);
1456 }
1457 return answer;
1458 }
1459 private:
1460 CProcessor& m_dynlib;
1461 sound4cl_CClientInstance *client = nullptr;
1462 };
1470 std::shared_ptr<CClient> NewClient()
1471 {
1472 assert(instance);
1473 return std::make_shared<CClient>(instance, m_dynlib);
1474 }
1475
1486 bool SaveState() {
1487 assert(instance);
1488 if (!m_dynlib.fnSaveState || m_dynlib.fnSaveState(instance)!=0) {
1489 return false;
1490 }
1491 return true;
1492 }
1493#ifdef _WIN32
1500 void SetInstanceTracing(TraceLoggingHProvider tracing_provider, GUID activity_guid = {}) {
1501 if (m_dynlib.fnSetInstanceTracing) {
1502 m_dynlib.fnSetInstanceTracing(params, tracing_provider, activity_guid);
1503 }
1504 }
1511 void SetInstanceTracingProcessActivity(GUID activity_guid) {
1512 assert(instance);
1513 if (m_dynlib.fnSetInstanceTracingProcessActivity) {
1514 m_dynlib.fnSetInstanceTracingProcessActivity(instance, activity_guid);
1515 }
1516 }
1517#endif // _WIN32
1518 protected:
1519 template<typename T>
1520 unsigned int AddAudio(const T* payload, unsigned int nFrame)
1521 {
1522 assert(instance);
1523 return m_dynlib.fnAddAudio(instance, reinterpret_cast<const T*>(payload), nFrame, helper::SampleFormat<T>::format);
1524 }
1525 template<typename T>
1526 unsigned int GetAudio(T* payload, unsigned int max_nFrame)
1527 {
1528 assert(instance);
1529 return m_dynlib.fnGetAudio(instance, reinterpret_cast<T*>(payload), max_nFrame, helper::SampleFormat<T>::format);
1530 }
1531
1532 private:
1533 CProcessor& m_dynlib;
1534 sound4cl_CParameters* params = nullptr;
1535 sound4cl_CInstance* instance = nullptr;
1536 std::thread update_thread;
1537 std::vector< std::pair<std::string,std::string> > init_metadata;
1538 uint64_t webserver = SOUND4_INVALID_WEBSERVER_ID;
1539 bool m_bOwned = true;
1540 };
1541
1542}; // namespace sound4
1543
1544
1545// bridge C callbacks to CPresetLoader
1546extern "C" {
1547 static char *sound4cl_custom_reader(const fs_char *filename, void* userdata) {
1548 sound4::CPresetLoader *preset_loader=reinterpret_cast<sound4::CPresetLoader*>(userdata);
1549 std::string content=preset_loader->Read(filename);
1550 return strdup(content.c_str());
1551 }
1552 static void sound4cl_custom_reader_free(char *content, void* userdata) {
1553 if (!content) return;
1554 free(content);
1555 }
1556 static int sound4cl_custom_writer(const fs_char *filename, const char *content, void* userdata) {
1557 sound4::CPresetLoader *preset_loader=reinterpret_cast<sound4::CPresetLoader*>(userdata);
1558 auto res=preset_loader->Write(filename,content);
1559 return res?0:-1;
1560 }
1561 static int sound4cl_custom_exists(const fs_char *filename, void* userdata) {
1562 sound4::CPresetLoader *preset_loader=reinterpret_cast<sound4::CPresetLoader*>(userdata);
1563 auto res=preset_loader->Exists(filename);
1564 return res?0:-1;
1565 }
1566 static fs_char** sound4cl_custom_getall(void* userdata) {
1567 sound4::CPresetLoader *preset_loader=reinterpret_cast<sound4::CPresetLoader*>(userdata);
1568 auto res=preset_loader->GetAll();
1569 fs_char**all=(fs_char**)malloc((res.size()+1)*sizeof(const fs_char*));
1570 for (size_t n=0;n<res.size();n++) {
1571 all[n]=fs_strdup(res[n].c_str());
1572 }
1573 all[res.size()]=nullptr;
1574 return all;
1575 }
1576 static void sound4cl_custom_getall_free(fs_char** all, void* userdata) {
1577 if (!all) return;
1578 for (fs_char** one=all;*one;one++) {
1579 free(*one);
1580 }
1581 free(all);
1582 }
1583 static int sound4cl_custom_remove(const fs_char *filename, void* userdata) {
1584 sound4::CPresetLoader *preset_loader=reinterpret_cast<sound4::CPresetLoader*>(userdata);
1585 auto res=preset_loader->Remove(filename);
1586 return res?0:-1;
1587 }
1588 static int sound4cl_custom_rename(const fs_char *from, const fs_char *to, void* userdata) {
1589 sound4::CPresetLoader *preset_loader=reinterpret_cast<sound4::CPresetLoader*>(userdata);
1590 auto res=preset_loader->Rename(from,to);
1591 return res?0:-1;
1592 }
1593
1594};
Shared Bus.
Definition sound4cl.hpp:848
sound4cl_CBus * Get() const
Definition sound4cl.hpp:866
CBus(CProcessor &dynlib)
Definition sound4cl.hpp:850
CClient(const CInstance &)=delete
CClient(sound4cl_CInstance *instance, CProcessor &dynlib)
std::string ProcessJson(const std::string &request, bool *NeedSave=nullptr)
Process a JSON request and returns the answer.
CClient & operator=(const CInstance &)=delete
Instance handling class.
Definition sound4cl.hpp:900
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=0)
void ProcessAudio_Planar(float const *const *input, float *const *output)
std::vector< T > ProcessAnyAudio(const std::vector< T > input)
virtual ~CInstance()
Definition sound4cl.hpp:934
CInstance & operator=(const CInstance &)=delete
CInstance(const CInstance &)=delete
void GetWebServerAppHealth(int &httpcode, std::string &contenttype, std::string &content)
void SetPresetManager(CPresetLoader *preset_manager)
Definition sound4cl.hpp:997
void SetBus(const CBus &bus)
Definition sound4cl.hpp:980
virtual void OnUpdateThreadStop()
unsigned int GetChunkFrames()
CInstance(CProcessor &dynlib, void *_instance)
Definition sound4cl.hpp:922
void SetWebServerAppHealth(int httpcode, const std::string &contenttype, const std::string &content)
CInstance(CProcessor &dynlib)
Definition sound4cl.hpp:907
void SetParam(const std::string &name, const std::string &value)
Definition sound4cl.hpp:952
virtual void OnUpdateThreadStart()
bool IsOk() const
Definition sound4cl.hpp:942
bool StartWebServer(int http_port, int https_port=0)
void StopWebServer(int timeout_ms=1000)
void PresetManager_InformChange(const std::filesystem::path &relative_path, PresetChange_Kind change_kind)
void SetMetadataMulti(const std::unordered_map< std::string, const char * > &list)
unsigned int AddAudio(const T *payload, unsigned int nFrame)
unsigned int GetEstimatedDelay()
std::vector< std::tuple< std::string, std::string > > GetMetadataInfos()
std::shared_ptr< CClient > NewClient()
float * GetBufferOut()
void SetMetadata(const std::string &key, const char *value)
void SetInstanceTracing(TraceLoggingHProvider tracing_provider, GUID activity_guid={})
float * GetBufferIn()
unsigned int GetAudio(T *payload, unsigned int max_nFrame)
std::string GetParam(const std::string &name)
Definition sound4cl.hpp:963
void SetInstanceTracingProcessActivity(GUID activity_guid)
Custom preset handler helper.
Definition sound4cl.hpp:877
virtual std::string Read(const std::filesystem::path &filename)=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 ~CPresetLoader()=default
virtual bool Remove(const std::filesystem::path &name)=0
virtual std::vector< std::filesystem::path > GetAll()=0
virtual bool IsReadOnly()=0
Dynamic library interface.
Definition sound4cl.hpp:309
bool Load(const std::filesystem::path &filepath)
Loads the library.
Definition sound4cl.hpp:424
void SetLogSeverity(LogSeverity severity)
Definition sound4cl.hpp:833
unsigned int GetAudioInputCount()
Definition sound4cl.hpp:780
void SetLoggerCallback(log_cb_t cb)
Definition sound4cl.hpp:839
unsigned int GetChunkSizeInFrames()
Definition sound4cl.hpp:741
SampleFormat GetFormatFromName(const std::string &name)
Definition sound4cl.hpp:818
std::vector< unsigned int > GetPossibleChunkSizeInFrames()
Definition sound4cl.hpp:752
std::string GetFormatName(const SampleFormat fmt)
Definition sound4cl.hpp:809
unsigned int GetBytesFromFormat(const SampleFormat fmt)
Definition sound4cl.hpp:827
unsigned int GetAudioOutputCount()
Definition sound4cl.hpp:790
helper::DynFuncHolder< T > GetPrefixSymbol(const std::string &name)
Definition sound4cl.hpp:409
unsigned int GetSampleRate()
Definition sound4cl.hpp:800
std::string GetVersion()
Definition sound4cl.hpp:728
bool IsOk() const
Check if the library was loaded correctly.
Definition sound4cl.hpp:615
unsigned int GetChannelCount()
Definition sound4cl.hpp:770
CProcessor()=default
Helper to load dynamic library.
Definition sound4cl.hpp:155
DynFuncHolder< T > GetSymbol_safe(const std::string &name)
Definition sound4cl.hpp:247
CDynLoader & operator=(CDynLoader const &)=delete
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)
Definition sound4cl.hpp:220
CDynLoader(const CDynLoader &)=delete
static std::filesystem::path GetThisLibraryPath(void)
Definition sound4cl.hpp:251
CDynLoader(CDynLoader &&)=default
DynFuncHolder< T > GetSymbol(const std::string &name)
Definition sound4cl.hpp:239
Helper to wrap a function pointer.
Definition sound4cl.hpp:134
DynFuncHolder(DynFunc_t a_ptr)
Definition sound4cl.hpp:145
void AudioConvertTo(const float *input, uint8_t *payload, size_t nSpl, SampleFormat fmt)
Definition sound4cl.hpp:650
void AudioMonoToLiveStereo(const float *input, uint8_t *payload)
Definition sound4cl.hpp:718
void StereoToMono_Planar(const float *inputL, const float *inputR, float *output, size_t nFrame)
Definition sound4cl.hpp:687
void MonoToStereo(const float *input, float *output, size_t nFrame)
Definition sound4cl.hpp:674
void AudioConvertFrom(const uint8_t *payload, float *output, size_t nSpl, SampleFormat fmt)
Definition sound4cl.hpp:637
void StereoToMono(const float *input, float *output, size_t nFrame)
Definition sound4cl.hpp:662
void AudioMonoFromLiveStereo(const uint8_t *payload, float *output)
Definition sound4cl.hpp:709
void MonoToStereo_Planar(const float *input, float *outputL, float *outputR, size_t nFrame)
Definition sound4cl.hpp:700
wchar_t fs_char
#define SOUND4_WEBSERVER_HTTPS_OK
#define SOUND4_WEBSERVER_HTTP_OK
#define SOUND4_INVALID_WEBSERVER_ID
static std::string WStringToUTF8(const std::wstring &wstr)
Definition sound4cl.hpp:86
static std::wstring UTF8ToWString(const std::string &str)
Definition sound4cl.hpp:98
@ S32_NATIVE
32-bit signed integer, native
Definition sound4cl.hpp:72
@ S16_LE
16-bit signed integer, little-endian
Definition sound4cl.hpp:62
@ S24_BE
24-bit signed integer, big-endian
Definition sound4cl.hpp:65
@ F32_LE
32-bit floating-point, little-endian
Definition sound4cl.hpp:68
@ S24_LE
24-bit signed integer, little-endian
Definition sound4cl.hpp:64
@ S32_LE
32-bit signed integer, little-endian
Definition sound4cl.hpp:66
@ F32_BE
32-bit floating-point, big-endian
Definition sound4cl.hpp:69
@ S16_BE
16-bit signed integer, big-endian
Definition sound4cl.hpp:63
@ S32_BE
32-bit signed integer, big-endian
Definition sound4cl.hpp:67
@ INVALID_FORMAT
Invalid.
Definition sound4cl.hpp:61
@ F32_NATIVE
32-bit floating-point, native
Definition sound4cl.hpp:73
@ S24_NATIVE
24-bit signed integer, native
Definition sound4cl.hpp:71
@ S16_NATIVE
16-bit signed integer, native
Definition sound4cl.hpp:70
@ fatal
fatal error
Definition sound4cl.hpp:277
@ verbose
verbose
Definition sound4cl.hpp:281
@ none
Not used.
Definition sound4cl.hpp:276
@ verbose3
verbose3
Definition sound4cl.hpp:283
@ verbose5
verbose5
Definition sound4cl.hpp:285
@ verbose2
verbose2
Definition sound4cl.hpp:282
@ warning
warning
Definition sound4cl.hpp:279
@ error
error
Definition sound4cl.hpp:278
@ info
info
Definition sound4cl.hpp:280
@ verbose4
verbose4
Definition sound4cl.hpp:284
static void _log_cb_c(sound4cl_LogSeverity severity, const char *c_msg)
Definition sound4cl.hpp:298
std::function< void(LogSeverity, const std::string &)> log_cb_t
Definition sound4cl.hpp:291
static log_cb_t _log_cb
Definition sound4cl.hpp:296
PresetChange_Kind
Definition sound4cl.hpp:890
@ change_kind_created
has been created
Definition sound4cl.hpp:891
@ change_kind_deleted
has been deleted
Definition sound4cl.hpp:893
@ change_kind_modified
has been modified
Definition sound4cl.hpp:892
struct _tlgProvider_t const * TraceLoggingHProvider
@ F32_NATIVE
32-bit floating-point, native
@ change_kind_modified
Path has been modified.
@ INVALID_FORMAT
Invalid.
@ S16_NATIVE
16-bit signed integer, native
@ change_kind_created
Path has been created.
@ F32_LE
32-bit floating-point, little-endian
@ S16_BE
16-bit signed integer, big-endian
@ S32_BE
32-bit signed integer, big-endian
@ S24_BE
24-bit signed integer, big-endian
@ S16_LE
16-bit signed integer, little-endian
@ F32_BE
32-bit floating-point, big-endian
@ S32_NATIVE
32-bit signed integer, native
@ change_kind_deleted
Path has been deleted.
@ S24_LE
24-bit signed integer, little-endian
@ S32_LE
32-bit signed integer, little-endian
@ S24_NATIVE
24-bit signed integer, native
Helper for Sample format types.
Definition sound4cl.hpp:113