SOUND4 x1.CLOUD Library [1.5.5]
Loading...
Searching...
No Matches
sound4cl-pipe.cpp
Go to the documentation of this file.
1
6#include <unistd.h>
7#include <iostream>
8#include <strings.h>
9#include <sys/types.h>
10#include <filesystem>
11#include <fstream>
12#include <sstream>
13#if defined(_WIN32) || defined(WIN32)
14 #include <io.h>
15 #include <fcntl.h>
16#endif
17
18#include "sound4cl.hpp"
19
20// --------------------------------------------------------------
60std::string GetEnv(const std::string& name)
61{
62 char *data=getenv(name.c_str());
63 if (!data) return {};
64 return std::string(data);
65}
66
67
68// Reads from stdin, write to stdout
70{
71bool stopthread=false;
72
73 #if defined(_WIN32) || defined(WIN32)
74 // Windows: The stdin, stdout, and stderr streams always open in text mode by default
75 _setmode(_fileno(stdin), _O_BINARY);
76 _setmode(_fileno(stdout), _O_BINARY);
77 #endif
78
80 size_t input_sample_count = instance.GetChunkFrames() * processor.GetChannelCount();
81 size_t output_sample_count = instance.GetChunkFrames() * processor.GetChannelCount();
82 while (!stopthread)
83 {
84 // Read a chunk from stdin
85 if (std::fread(instance.GetBufferIn(), sizeof(float), input_sample_count, stdin) != input_sample_count) {
86 std::cerr << "ProcessLoop: input stopped"<< std::endl;
87 stopthread=true;
88 break;
89 }
90 if (stopthread) break;
91 // Process it
92 instance.ProcessAudio();
93 // Write it to stdout
94 if (fwrite(instance.GetBufferOut(), sizeof(float), output_sample_count, stdout) != output_sample_count) {
95 std::cerr << "Failed to write audio output" << std::endl;
96 stopthread=true;
97 }
98 }
100}
101
104public:
105 MyPresetManager() = default;
106 virtual ~MyPresetManager() = default;
107
108 bool SetupPath(const std::filesystem::path& a_preset_path)
109 {
110 m_preset_path=a_preset_path;
111 std::error_code ec;
112 if ( !std::filesystem::exists(m_preset_path,ec ) ) {
113 return false;
114 }
115 if ( !std::filesystem::is_directory(m_preset_path, ec) ) {
116 return false;
117 }
118 return true;
119 }
120 virtual bool IsReadOnly() override { return false; };
121 virtual bool Exists(const std::filesystem::path &name) override
122 {
123 std::error_code ec;
124 return std::filesystem::exists(GetRealPath(name), ec);
125 }
126 virtual bool Remove(const std::filesystem::path &name) override
127 {
128 std::error_code ec;
129 return std::filesystem::remove(GetRealPath(name), ec);
130 }
131 virtual bool Rename(const std::filesystem::path &from, const std::filesystem::path &to) override
132 {
133 std::error_code ec;
134 std::filesystem::rename(GetRealPath(from), GetRealPath(to), ec);
135 return (!ec);
136 }
137 virtual std::vector<std::filesystem::path> GetAll() override
138 {
139 std::vector<std::filesystem::path> list;
140 std::error_code ec;
141 for (auto it = std::filesystem::directory_iterator(m_preset_path.c_str(), std::filesystem::directory_options::skip_permission_denied, ec);
142 !ec && it != std::filesystem::directory_iterator{};
143 it.increment(ec) )
144 {
145 if (it->is_regular_file(ec)) {
146 list.push_back(it->path().lexically_relative(m_preset_path));
147 }
148 }
149 return list;
150 }
151 virtual std::string Read(const std::filesystem::path &filename) override
152 {
153 std::ifstream f(GetRealPath(filename));
154 if ( f.fail() ) {
155 return std::string();
156 }
157 std::ostringstream ss;
158 ss << f.rdbuf();
159 return ss.str();
160 }
161 virtual bool Write(const std::filesystem::path &filename, const std::string &content) override
162 {
163 std::ofstream f(GetRealPath(filename));
164 if ( f.fail() ) {
165 return false;
166 }
167 f << content;
168 if ( f.fail() ) {
169 return false;
170 }
171 return true;
172 }
173private:
174 std::filesystem::path m_preset_path;
175 std::filesystem::path GetRealPath(const std::filesystem::path &name)
176 {
177 return m_preset_path / name;
178 }
179};
181
182int main(int argc, const char **argv)
183{
184 int listen_port = 8080;
185 auto store_path_str=GetEnv("S4STORE_PATH");
187 std::string libname = "libsound4.x1.cloud.so";
189
190
191 // Get credentials from environment
192 auto LoginKey=GetEnv("S4LOGINKEY");
193 if (LoginKey.empty()) {
194 LoginKey=GetEnv("S4USERID");
195 }
196 auto RadioName=GetEnv("RADIO_NAME");
197 auto KeyId=GetEnv("ACCESS_KEY_ID");
198 auto AccessKey=GetEnv("ACCESS_KEY_SECRET");
199
200 const char *progname=argv[0];
201 for (int n=1;n<argc;n++) {
202 std::string arg = argv[n];
203 if (arg=="-p" || arg=="--port") {
204 if (argc<n+1) {
205 std::cerr << "--port needs a number"<< std::endl;
206 return 1;
207 }
208 n++;
209 listen_port=atoi(argv[n]);
210 } else if (arg=="-l" || arg=="--lib") {
211 if (argc<n+1) {
212 std::cerr << "--port needs a number"<< std::endl;
213 return 1;
214 }
215 n++;
216 libname=argv[n];
217 } else if (arg=="-h" || arg=="--help") {
218 std::cerr << "Usage: " << progname << " [-p port] [-l libname.so]"<<std::endl;;
219 std::cerr << " Reads audio from stdin and return processed audio in stdout" << std::endl;
220 std::cerr << " -l, --lib : library to load ["<<libname<<"]" << std::endl;
221 std::cerr << " -p, --port : port for web server ["<<listen_port<<"]" << std::endl;
222 std::cerr << std::endl;
223 std::cerr << "Environment:"<< std::endl;;
224 std::cerr << " - S4STORE_PATH : path to store config [default: (no storage)]"<< std::endl;;
225 std::cerr << " - S4LOGINKEY : SOUND4 Login key (or S4USERID)"<< std::endl;;
226 std::cerr << " - RADIO_NAME : SOUND4 Radio Name"<< std::endl;;
227 std::cerr << " - ACCESS_KEY_ID : SOUND4 Access Key ID"<< std::endl;;
228 std::cerr << " - ACCESS_KEY_SECRET : SOUND4 Access Key Secret"<< std::endl;
229 std::cerr << std::endl;
230 std::cerr << "Example:"<< std::endl;
231 std::cerr << " ffmpeg -re -i file.wav -ar 48000 -ac 2 -f f32le - | "<<progname<<" | ffplay -f f32le -ar 48000 -ac 2 -i -" << std::endl;;
232 #if defined(_WIN32) || defined(WIN32)
233 std::cerr << " ffmpeg -f dshow -i audio=\"Microphone\" -ar 48000 -ac 2 -f f32le - | "<<progname<<" | ffplay -f f32le -ar 48000 -ac 2 -i -" << std::endl;;
234 #else
235 std::cerr << " ffmpeg -f pulse -i default -ar 48000 -ac 2 -f f32le - | "<<progname<<" | ffplay -f f32le -ar 48000 -ac 2 -i -" << std::endl;;
236 #endif
237 return 0;
238 } else {
239 std::cerr << "unknown argument '"<<arg<<"'"<< std::endl;
240 return 1;
241 }
242 }
243
244
246 sound4::CProcessor processor;
247 if (!processor.Load(libname)) {
248 std::cerr << "Failed to load processing library" << std::endl;
249 return 1;
250 }
252
253 if (LoginKey.empty() || RadioName.empty() || KeyId.empty() || AccessKey.empty()) {
254 std::cerr << "Missing credentials in environment" << std::endl;
255 return 1;
256 }
257 std::filesystem::path store_path;
258 if (!store_path_str.empty()) {
259 store_path = std::filesystem::path(store_path_str);
260 std::error_code ec;
261 if (!std::filesystem::exists(store_path,ec) || !std::filesystem::is_directory(store_path,ec)) {
262 std::cerr << "Storage folder '"<<store_path.c_str()<<"' is not a valid directory" << std::endl;
263 return 1;
264 }
265 }
266
269 processor.SetLoggerCallback([](sound4::LogSeverity severity,const std::string& msg) {
270 std::cerr << msg << std::endl;
271 });
272
273 sound4::CInstance instance(processor);
274 instance.SetParam("ADMIN_USER","admin");
275 instance.SetParam("ADMIN_SECRET","admin");
277
279 MyPresetManager preset_manager;
280 if (!store_path.empty()) {
281 if (!preset_manager.SetupPath(store_path)) {
282 std::cerr << "Failed to setup the custom preset manager on path " << store_path.c_str() << std::endl;
283 return 1;
284 }
285 instance.SetPresetManager(&preset_manager);
286 }
288
289 std::cerr << "Creating" << std::endl;
291 if (!instance.Create(LoginKey, RadioName, KeyId, AccessKey, {})) {
292 std::cerr << "Failed to create the processing instance" << std::endl;
293 return 1;
294 }
296
297 std::cerr << "Starting web server" << std::endl;
299 if (!instance.StartWebServer(listen_port,0)) {
300 std::cerr << "Failed to create the web server on port " << listen_port << std::endl;
301 return 1;
302 }
304
305 {
307 auto client = instance.NewClient();
308 auto answer = client->ProcessJson(R"JSON({"get":{"processorname":null}})JSON");
309 std::cerr << "Request for processor name returned "<<answer<<std::endl;
311 }
312
313 ProcessLoop(instance, processor);
314
315 std::cerr << "Stopping now" << std::endl;
316 instance.Stop();
317
318 std::cerr << "End" << std::endl;
319 return 0;
320}
[Custom preset manager]
virtual bool Rename(const std::filesystem::path &from, const std::filesystem::path &to) override
virtual ~MyPresetManager()=default
virtual bool Exists(const std::filesystem::path &name) override
virtual bool IsReadOnly() override
virtual bool Write(const std::filesystem::path &filename, const std::string &content) override
MyPresetManager()=default
virtual bool Remove(const std::filesystem::path &name) override
virtual std::vector< std::filesystem::path > GetAll() override
virtual std::string Read(const std::filesystem::path &filename) override
bool SetupPath(const std::filesystem::path &a_preset_path)
Instance handling class.
Definition sound4cl.hpp:760
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)
Definition sound4cl.hpp:864
void SetPresetManager(CPresetLoader *preset_manager)
Definition sound4cl.hpp:831
unsigned int GetChunkFrames()
Definition sound4cl.hpp:910
void SetParam(const std::string &name, const std::string &value)
Definition sound4cl.hpp:793
bool StartWebServer(int http_port, int https_port=0)
std::shared_ptr< CClient > NewClient()
float * GetBufferOut()
float * GetBufferIn()
Custom preset handler helper.
Definition sound4cl.hpp:740
Dynamic library interface.
Definition sound4cl.hpp:276
bool Load(const std::filesystem::path &filepath)
Loads the library.
Definition sound4cl.hpp:385
void SetLogSeverity(LogSeverity severity)
Definition sound4cl.hpp:698
void SetLoggerCallback(log_cb_t cb)
Definition sound4cl.hpp:704
unsigned int GetChannelCount()
Definition sound4cl.hpp:635
const LogSeverity verbose5
Definition sound4cl.hpp:253
int main(int argc, const char **argv)
[Custom preset manager]
std::string GetEnv(const std::string &name)
void ProcessLoop(sound4::CInstance &instance, sound4::CProcessor &processor)
C++ wrapper for dynamic loading library.
sound4cl_LogSeverity