arduino-audio-tools
URLStreamBuffered.h
1 #pragma once
2 #include "AudioConfig.h"
3 #if defined(USE_CONCURRENCY) && defined(USE_URL_ARDUINO)
4 #include "URLStream.h"
5 #include "AudioTools/AudioLibs/Concurrency.h"
6 #include "AudioTools/CoreAudio/AudioStreams.h"
7 
8 #ifndef URL_STREAM_CORE
9 # define URL_STREAM_CORE 0
10 #endif
11 
12 #ifndef URL_STREAM_PRIORITY
13 # define URL_STREAM_PRIORITY 2
14 #endif
15 
16 #ifndef URL_STREAM_BUFFER_COUNT
17 # define URL_STREAM_BUFFER_COUNT 10
18 #endif
19 
20 #ifndef STACK_SIZE
21 # define STACK_SIZE 30000
22 #endif
23 
24 
25 namespace audio_tools {
26 
35  public:
36  BufferedTaskStream() { TRACEI(); };
37 
39  TRACEI();
40  setInput(input);
41  }
42 
44  TRACEI();
45  stop();
46  }
47 
49  void setBufferSize(int bufferSize, int bufferCount){
50  buffers.resize(bufferSize, bufferCount);
51  }
52 
53  virtual void begin(bool wait = true) {
54  TRACED();
55  active = true;
56  ready = false;
57  task.begin(std::bind(&BufferedTaskStream::processTask, this));
58  if (!wait) ready = true;
59  }
60 
61  virtual void end() {
62  TRACED();
63  task.end();
64  active = false;
65  ready = false;
66  }
67 
68  virtual void setInput(AudioStream &input) {
69  TRACED();
70  p_stream = &input;
71  }
72 
74  virtual size_t write(uint8_t c) override { return 0; }
75 
77  virtual size_t write(const uint8_t *data, size_t len) override { return 0; }
78 
80  virtual void flush() override {}
81 
83  virtual int read() override {
84  // if (!ready) return -1;
85  int result = -1;
86  result = buffers.read();
87  return result;
88  }
89 
91  virtual int peek() override {
92  // if (!ready) return -1;
93  int result = -1;
94  result = buffers.peek();
95  return result;
96  };
97 
99  virtual size_t readBytes(uint8_t *data, size_t len) override {
100  // if (!ready) return 0;
101  size_t result = 0;
102  result = buffers.readArray(data, len);
103  LOGD("%s: %zu -> %zu", LOG_METHOD, len, result);
104  return result;
105  }
106 
108  virtual int available() override {
109  // if (!ready) return 0;
110  int result = 0;
111  result = buffers.available();
112  return result;
113  }
114 
115 
116  protected:
117  AudioStream *p_stream = nullptr;
118  bool active = false;
119  Task task{"BufferedTaskStream", STACK_SIZE, URL_STREAM_PRIORITY,
120  URL_STREAM_CORE};
121  SynchronizedNBuffer<uint8_t> buffers{DEFAULT_BUFFER_SIZE,
122  URL_STREAM_BUFFER_COUNT};
123  bool ready = false;
124 
125  void processTask() {
126  size_t available_to_write = this->buffers.availableForWrite();
127  if (*(this->p_stream) && available_to_write > 0) {
128  size_t to_read = min(available_to_write, (size_t)512);
129  uint8_t buffer[to_read];
130  size_t avail_read = this->p_stream->readBytes((uint8_t *)buffer, to_read);
131  size_t written = this->buffers.writeArray(buffer, avail_read);
132 
133  if (written != avail_read) {
134  LOGE("DATA Lost! %zu reqested, %zu written!", avail_read, written);
135  }
136 
137  } else {
138  // 3ms at 44100 stereo is about 529.2 bytes
139  delay(3);
140  }
141  // buffer is full we start to provide data
142  if (available_to_write == 0) {
143  this->ready = true;
144  }
145  }
146 };
147 
157  public:
158  URLStreamBuffered(int readBufferSize = DEFAULT_BUFFER_SIZE) {
159  TRACED();
160  urlStream.setReadBufferSize(readBufferSize);
161  taskStream.setInput(urlStream);
162  }
163 
164  URLStreamBuffered(Client &clientPar,
165  int readBufferSize = DEFAULT_BUFFER_SIZE) {
166  TRACED();
167  urlStream.setReadBufferSize(readBufferSize);
168  setClient(clientPar);
169  taskStream.setInput(urlStream);
170  }
171 
172  URLStreamBuffered(const char *network, const char *password,
173  int readBufferSize = DEFAULT_BUFFER_SIZE) {
174  TRACED();
175  urlStream.setReadBufferSize(readBufferSize);
176  setSSID(network);
177  setPassword(password);
178  taskStream.setInput(urlStream);
179  }
180 
181  void setBufferSize(int bufferSize, int bufferCount){
182  taskStream.setBufferSize(bufferSize, bufferCount);
183  }
184 
185  bool begin(const char *urlStr, const char *acceptMime = nullptr,
186  MethodID action = GET, const char *reqMime = "",
187  const char *reqData = "") {
188  TRACED();
189  // start real stream
190  bool result = urlStream.begin(urlStr, acceptMime, action, reqMime, reqData);
191  // start buffer task
192  taskStream.begin();
193  return result;
194  }
195 
196  virtual int available() { return taskStream.available(); }
197 
198  virtual size_t readBytes(uint8_t *data, size_t len) {
199  size_t result = taskStream.readBytes(data, len);
200  LOGD("%s: %zu -> %zu", LOG_METHOD, len, result);
201  return result;
202  }
203 
204  virtual int read() { return taskStream.read(); }
205 
206  virtual int peek() { return taskStream.peek(); }
207 
208  virtual void flush() {}
209 
210  void end() {
211  TRACED();
212  taskStream.end();
213  urlStream.end();
214  }
215 
217  HttpRequest &httpRequest() { return urlStream.httpRequest(); }
218 
220  void setClient(Client &client) override { urlStream.setClient(client); }
221 
223  void setSSID(const char *ssid) override { urlStream.setSSID(ssid); }
224 
226  void setPassword(const char *password) override {
227  urlStream.setPassword(password);
228  }
229 
230  void setPowerSave(bool ps) override { urlStream.setPowerSave(ps); }
231 
232 
233  protected:
234  BufferedTaskStream taskStream;
235  URLStream urlStream;
236 };
237 
238 } // namespace audio_tools
239 
240 #endif
Abstract Base class for all URLStream implementations.
Definition: AbstractURLStream.h:11
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition: BaseStream.h:109
virtual int readArray(T data[], int len)
reads multiple values
Definition: Buffers.h:41
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition: Buffers.h:65
A FreeRTOS task is filling the buffer from the indicated stream. Only to be used on the ESP32.
Definition: URLStreamBuffered.h:34
virtual size_t write(const uint8_t *data, size_t len) override
Use this method: write an array.
Definition: URLStreamBuffered.h:77
void setBufferSize(int bufferSize, int bufferCount)
Define an explicit the buffer size in bytes.
Definition: URLStreamBuffered.h:49
virtual int read() override
reads a byte - to be avoided
Definition: URLStreamBuffered.h:83
virtual size_t readBytes(uint8_t *data, size_t len) override
Use this method !!
Definition: URLStreamBuffered.h:99
virtual int peek() override
peeks a byte - to be avoided
Definition: URLStreamBuffered.h:91
virtual size_t write(uint8_t c) override
writes a byte to the buffer
Definition: URLStreamBuffered.h:74
virtual void flush() override
empties the buffer
Definition: URLStreamBuffered.h:80
virtual int available() override
Returns the available bytes in the buffer: to be avoided.
Definition: URLStreamBuffered.h:108
Definition: NoArduino.h:139
Simple API to process get, put, post, del http requests I tried to use Arduino HttpClient,...
Definition: HttpRequest.h:26
int available()
provides the number of entries that are available to read
Definition: Buffers.h:621
T peek()
peeks the actual entry from the buffer
Definition: Buffers.h:583
int availableForWrite()
provides the number of entries that are available to write
Definition: Buffers.h:638
T read()
reads a single value
Definition: Buffers.h:574
FreeRTOS task.
Definition: Task.h:20
void end()
suspends the task
Definition: Task.h:64
URLStream implementation for the ESP32 based on a separate FreeRTOS task.
Definition: URLStreamBuffered.h:156
void setPowerSave(bool ps) override
Definition: URLStreamBuffered.h:230
void setSSID(const char *ssid) override
Sets the ssid that will be used for logging in (when calling begin)
Definition: URLStreamBuffered.h:223
void setClient(Client &client) override
(Re-)defines the client
Definition: URLStreamBuffered.h:220
void setPassword(const char *password) override
Sets the password that will be used for logging in (when calling begin)
Definition: URLStreamBuffered.h:226
HttpRequest & httpRequest()
provides access to the HttpRequest
Definition: URLStreamBuffered.h:217
Represents the content of a URL as Stream. We use the WiFi.h API.
Definition: URLStream.h:26
virtual HttpRequest & httpRequest() override
provides access to the HttpRequest
Definition: URLStream.h:185
virtual bool begin(const char *urlStr, const char *acceptMime=nullptr, MethodID action=GET, const char *reqMime="", const char *reqData="") override
Execute http request: by default we use a GET request.
Definition: URLStream.h:80
void setPowerSave(bool ps)
Definition: URLStream.h:194
void setSSID(const char *ssid) override
Sets the ssid that will be used for logging in (when calling begin)
Definition: URLStream.h:70
void setClient(Client &clientPar) override
(Re-)defines the client
Definition: URLStream.h:67
void setPassword(const char *password) override
Sets the password that will be used for logging in (when calling begin)
Definition: URLStream.h:73
void stop()
Public generic methods.
Definition: AudioRuntime.h:27
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823