SOUND4 x1.CLOUD Library [1.2.6]
sound4.x1.cloud-pipe-cxx.cpp
Go to the documentation of this file.
1 
4 #include <unistd.h>
5 #include <iostream>
6 #include <strings.h>
7 #include <sys/types.h>
8 #include <filesystem>
9 #if defined(_WIN32) || defined(WIN32)
10  #include <io.h>
11  #include <fcntl.h>
12 #endif
13 
14 #include "sound4.x1.cloud.hpp"
15 
16 // --------------------------------------------------------------
39 std::string GetEnv(const std::string& name)
40 {
41  char *data=getenv(name.c_str());
42  if (!data) return {};
43  return std::string(data);
44 }
45 
46 
47 // Reads from stdin, write to stdout
49 {
50 bool stopthread=false;
51 
52  #if defined(_WIN32) || defined(WIN32)
53  // Windows: The stdin, stdout, and stderr streams always open in text mode by default
54  _setmode(_fileno(stdin), _O_BINARY);
55  _setmode(_fileno(stdout), _O_BINARY);
56  #endif
57 
59  while (!stopthread)
60  {
61  // Read a chunk from stdin
62  if (std::fread(instance.GetBufferIn().data(), sizeof(float), sound4::cloudx1::InputSampleSize, stdin) != sound4::cloudx1::InputSampleSize) {
63  std::cerr << "ProcessLoop: input stopped"<< std::endl;
64  stopthread=true;
65  break;
66  }
67  if (stopthread) break;
68  // Process it
69  instance.ProcessAudio();
70  // Write it to stdout
71  if (fwrite(instance.GetBufferOut().data(), sizeof(float), sound4::cloudx1::OutputSampleSize, stdout) != sound4::cloudx1::OutputSampleSize) {
72  std::cerr << "Failed to write audio output" << std::endl;
73  stopthread=true;
74  }
75  }
77 }
78 
79 void Usage(const char *progname)
80 {
81  std::cerr << "Usage: " << progname << std::endl;;
82  std::cerr << " Reads audio from stdin and return processed audio in stdout" << std::endl;
83  std::cerr << "Environment:"<< std::endl;;
84  std::cerr << " - S4STORE_PATH : path to store config [default: (no storage)]"<< std::endl;;
85  std::cerr << " - S4LOGINKEY : SOUND4 Login key (or S4USERID)"<< std::endl;;
86  std::cerr << " - RADIO_NAME : SOUND4 Radio Name"<< std::endl;;
87  std::cerr << " - S4_AWS_ACCESS_KEY_ID : SOUND4 Access Key ID"<< std::endl;;
88  std::cerr << " - S4_AWS_SECRET_ACCESS_KEY: SOUND4 Access Key Secret"<< std::endl;;
89  std::cerr << std::endl;
90  std::cerr << "Example:"<< std::endl;
91  std::cerr << "ffmpeg -re -i file.wav -ar "<<sound4::cloudx1::GetSampleRate()<<" -ac "<<sound4::cloudx1::GetChannelCount()<<" -f f32le - | "<<progname<<" | ffplay -f f32le -ar "<<sound4::cloudx1::GetSampleRate()<<" -ac "<<sound4::cloudx1::GetChannelCount()<<" -i -" << std::endl;;
92  #if defined(_WIN32) || defined(WIN32)
93  std::cerr << "ffmpeg -f dshow -i audio=\"Microphone\" -ar "<<sound4::cloudx1::GetSampleRate()<<" -ac "<<sound4::cloudx1::GetChannelCount()<<" -f f32le - | "<<progname<<" | ffplay -f f32le -ar "<<sound4::cloudx1::GetSampleRate()<<" -ac "<<sound4::cloudx1::GetChannelCount()<<" -i -" << std::endl;;
94  #else
95  std::cerr << "ffmpeg -f pulse -i default -ar "<<sound4::cloudx1::GetSampleRate()<<" -ac "<<sound4::cloudx1::GetChannelCount()<<" -f f32le - | "<<progname<<" | ffplay -f f32le -ar "<<sound4::cloudx1::GetSampleRate()<<" -ac "<<sound4::cloudx1::GetChannelCount()<<" -i -" << std::endl;;
96  #endif
97 }
98 
99 void MyLogger(sound4::cloudx1::LogSeverity severity,const std::string& msg)
100 {
101  std::cerr << msg << std::endl;
102 }
103 
104 int main(int argc, const char **argv)
105 {
106  int listen_port = 8080;
107  auto store_path=GetEnv("S4STORE_PATH");
108 
109  // Get credentials from environment
110  auto LoginKey=GetEnv("S4LOGINKEY");
111  if (LoginKey.empty()) {
112  LoginKey=GetEnv("S4USERID");
113  }
114  auto RadioName=GetEnv("RADIO_NAME");
115  auto KeyId=GetEnv("S4_AWS_ACCESS_KEY_ID");
116  auto AccessKey=GetEnv("S4_AWS_SECRET_ACCESS_KEY");
117 
118  const char *progname=argv[0];
119 
120  if (argc>1) {
121  if ((strcasecmp(argv[1],"-h")==0) || (strcasecmp(argv[1],"--help")==0)) {
122  Usage(progname);
123  return 0;
124  }
125  }
126  if (LoginKey.empty() || RadioName.empty() || KeyId.empty() || AccessKey.empty()) {
127  std::cerr << "Missing credentials in environment" << std::endl;
128  Usage(progname);
129  return 1;
130  }
131  if (!store_path.empty()) {
132  if (!std::filesystem::exists(store_path) || !std::filesystem::is_directory(store_path)) {
133  std::cerr << "Storage folder '"<<store_path<<"' is not a valid directory" << std::endl;
134  Usage(progname);
135  return 1;
136  }
137  }
138 
140  sound4::cloudx1::SetLogSeverity(verbose5);
141  sound4::cloudx1::SetLoggerCallback(MyLogger);
142 
144  instance.SetParam("ADMIN_USER","admin");
145  instance.SetParam("ADMIN_SECRET","admin");
147 
148  std::cerr << "Creating" << std::endl;
150  if (!instance.Create(LoginKey, RadioName, KeyId, AccessKey, store_path)) {
151  std::cerr << "Failed to create the processing instance" << std::endl;
152  return 1;
153  }
155 
156  std::cerr << "Starting web server" << std::endl;
158  if (!instance.StartWebServer(listen_port,0)) {
159  std::cerr << "Failed to create the web server on port " << listen_port << std::endl;
160  return 1;
161  }
163 
164  {
166  auto client = instance.NewClient();
167  auto answer = client->ProcessJson(R"JSON({"get":{"processorname":null}})JSON");
168  std::cerr << "Request for processor name returned "<<answer<<std::endl;
170  }
171 
172  ProcessLoop(instance);
173 
174  std::cerr << "Stopping now" << std::endl;
175  instance.Stop();
176 
177  std::cerr << "End" << std::endl;
178  return 0;
179 }
std::shared_ptr< CClient > NewClient()
bool Create(const std::string &LoginKey, const std::string &RadioName, const std::string &AWS_Access_ID, const std::string &AWS_Access_Secret, const std::string &save_path, int json_port=0)
bool StartWebServer(int http_port, int https_port=0)
std::array< float, OutputSampleSize > & GetBufferOut()
std::array< float, InputSampleSize > & GetBufferIn()
void SetParam(const std::string &name, const std::string &value)
cloudx1_LogSeverity
@ verbose5
const size_t OutputSampleSize
const size_t InputSampleSize
void ProcessLoop(sound4::cloudx1::CInstance &instance)
int main(int argc, const char **argv)
std::string GetEnv(const std::string &name)
void Usage(const char *progname)
void MyLogger(sound4::cloudx1::LogSeverity severity, const std::string &msg)
C++ wrapper for library.