From 357877db07bbe0484eb5abf4e77beb8eba857b62 Mon Sep 17 00:00:00 2001 From: Phil Schatzmann Date: Mon, 25 Oct 2021 17:12:12 +0200 Subject: [PATCH] broken webserver --- .../streams-flite-webserver_wav.ino | 2 +- .../streams-i2s-webserver_wav.ino | 2 +- .../streams-sam-webserver_wav.ino | 2 +- .../streams-tts-webserver_wav.ino | 2 +- src/AudioHttp/AudioServer.h | 141 +++++++++--------- src/AudioTools/AudioOutput.h | 79 +++++----- 6 files changed, 111 insertions(+), 117 deletions(-) diff --git a/examples/examples-webserver/streams-flite-webserver_wav/streams-flite-webserver_wav.ino b/examples/examples-webserver/streams-flite-webserver_wav/streams-flite-webserver_wav.ino index e77c817c8..e83a7eee2 100644 --- a/examples/examples-webserver/streams-flite-webserver_wav/streams-flite-webserver_wav.ino +++ b/examples/examples-webserver/streams-flite-webserver_wav/streams-flite-webserver_wav.ino @@ -14,7 +14,7 @@ using namespace audio_tools; AudioWAVServer server("ssid","password"); // Callback which provides the audio data -void outputData(Stream *out){ +void outputData(Print *out){ Serial.print("providing data..."); Flite flite(*out); diff --git a/examples/examples-webserver/streams-i2s-webserver_wav/streams-i2s-webserver_wav.ino b/examples/examples-webserver/streams-i2s-webserver_wav/streams-i2s-webserver_wav.ino index be6dd5336..61d521f96 100644 --- a/examples/examples-webserver/streams-i2s-webserver_wav/streams-i2s-webserver_wav.ino +++ b/examples/examples-webserver/streams-i2s-webserver_wav/streams-i2s-webserver_wav.ino @@ -5,8 +5,8 @@ * * @author Phil Schatzmann * @copyright GPLv3 - * */ + #include "TTS.h" #include "AudioTools.h" diff --git a/examples/examples-webserver/streams-sam-webserver_wav/streams-sam-webserver_wav.ino b/examples/examples-webserver/streams-sam-webserver_wav/streams-sam-webserver_wav.ino index e967573dd..e373d9d4f 100644 --- a/examples/examples-webserver/streams-sam-webserver_wav/streams-sam-webserver_wav.ino +++ b/examples/examples-webserver/streams-sam-webserver_wav/streams-sam-webserver_wav.ino @@ -15,7 +15,7 @@ int channels = 1; int bits_per_sample = 8; // Callback which provides the audio data -void outputData(Stream *out){ +void outputData(Print *out){ Serial.print("providing data..."); SAM sam(*out, false); sam.setOutputChannels(channels); diff --git a/examples/examples-webserver/streams-tts-webserver_wav/streams-tts-webserver_wav.ino b/examples/examples-webserver/streams-tts-webserver_wav/streams-tts-webserver_wav.ino index c4e080fa6..6b4d5cfd8 100644 --- a/examples/examples-webserver/streams-tts-webserver_wav/streams-tts-webserver_wav.ino +++ b/examples/examples-webserver/streams-tts-webserver_wav/streams-tts-webserver_wav.ino @@ -13,7 +13,7 @@ using namespace audio_tools; AudioWAVServer server("ssid","password"); // Callback which provides the audio data -void outputData(Stream *out){ +void outputData(Print *out){ Serial.print("providing data..."); TTS tts = TTS(*out); tts.sayText("Hallo, my name is Alice"); diff --git a/src/AudioHttp/AudioServer.h b/src/AudioHttp/AudioServer.h index 689ef832f..81afe71c9 100644 --- a/src/AudioHttp/AudioServer.h +++ b/src/AudioHttp/AudioServer.h @@ -10,12 +10,15 @@ namespace audio_tools { /// Calback which writes the sound data to the stream -typedef void (*AudioServerDataCallback)(Stream *out); +typedef void (*AudioServerDataCallback)(Print *out); /** * @brief A simple Arduino Webserver which streams the result * This class is based on the WiFiServer class. All you need to do is to provide the data - * with a callback method or from an Arduino Stream. + * with a callback method or from an Arduino Stream: in -copy> client + + * + * * @author Phil Schatzmann * @copyright GPLv3 */ @@ -46,6 +49,7 @@ class AudioServer { * @param contentType Mime Type of result */ void begin(Stream &in, const char* contentType) { + LOGD(LOG_METHOD); this->in = ∈ this->content_type = contentType; @@ -62,6 +66,7 @@ class AudioServer { * @param contentType Mime Type of result */ void begin(AudioServerDataCallback cb, const char* contentType) { + LOGD(LOG_METHOD); this->in =nullptr; this->callback = cb; this->content_type = contentType; @@ -90,12 +95,12 @@ class AudioServer { bool doLoop() { //LOGD("doLoop"); bool active = true; - if (!client.connected()) { - client = server.available(); // listen for incoming clients + if (!client_obj.connected()) { + client_obj = server.available(); // listen for incoming clients processClient(); } else { // We are connected: copy input from source to wav output - if (client){ + if (client_obj){ if (callback==nullptr) { LOGI("copy data..."); if (converter_ptr==nullptr) { @@ -104,9 +109,9 @@ class AudioServer { copier.copy(*converter_ptr); } // if we limit the size of the WAV the encoder gets automatically closed when all has been sent - if (!client) { + if (!client_obj) { LOGI("stop client..."); - client.stop(); + client_obj.stop(); active = false; } } @@ -122,23 +127,30 @@ class AudioServer { converter_ptr = c; } + Stream& out() { + return client_obj; + } + + Stream* out_ptr() { + return &client_obj; + } protected: // WIFI WiFiServer server = WiFiServer(80); - WiFiClient client; + WiFiClient client_obj; char *password = nullptr; char *network = nullptr; // Content - const char *content_type; + const char *content_type=nullptr; AudioServerDataCallback callback = nullptr; Stream *in = nullptr; StreamCopy copier; BaseConverter *converter_ptr = nullptr; void connectWiFi() { - LOGD("connectWiFi"); + LOGD(LOG_METHOD); if (WiFi.status() != WL_CONNECTED && network!=nullptr && password != nullptr){ WiFi.begin(network, password); //WiFi.setSleep(false); @@ -152,43 +164,49 @@ class AudioServer { Serial.println(WiFi.localIP()); } - virtual void sendReply(){ - LOGD("sendReply"); + virtual void sendReplyHeader(){ + LOGD(LOG_METHOD); // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: - client.println("HTTP/1.1 200 OK"); - client.print("Content-type:"); - client.println(content_type); - client.println(); + client_obj.println("HTTP/1.1 200 OK"); + if (content_type!=nullptr){ + client_obj.print("Content-type:"); + client_obj.println(content_type); + } + client_obj.println(); + } + + virtual void sendReplyContent() { + LOGD(LOG_METHOD); if (callback!=nullptr){ // provide data via Callback LOGI("sendReply - calling callback"); - callback(&client); - client.stop(); - } else { + callback(&client_obj); + client_obj.stop(); + } else if (in!=nullptr){ // provide data for stream LOGI("sendReply - Returning WAV stream..."); - copier.begin(client, *in); + copier.begin(client_obj, *in); } } - // Handle an new client connection and return the data void processClient() { //LOGD("processClient"); - if (client) { // if you get a client, + if (client_obj) { // if you get a client, LOGI("New Client."); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client - while (client.connected()) { // loop while the client's connected - if (client.available()) { // if there's bytes to read from the client, - char c = client.read(); // read a byte, then + while (client_obj.connected()) { // loop while the client's connected + if (client_obj.available()) { // if there's bytes to read from the client, + char c = client_obj.read(); // read a byte, then if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0){ - sendReply(); + sendReplyHeader(); + sendReplyContent(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: @@ -209,6 +227,8 @@ class AudioServer { * @brief A simple Arduino Webserver which streams the audio using the indicated encoder.. * This class is based on the WiFiServer class. All you need to do is to provide the data * with a callback method or from a Stream. + * + * in -copy> client */ class AudioEncoderServer : public AudioServer { @@ -220,7 +240,6 @@ class AudioEncoderServer : public AudioServer { */ AudioEncoderServer(AudioEncoder *encoder) : AudioServer() { this->encoder = encoder; - this->encoded_stream = new AudioOutputStream(*encoder); } /** @@ -231,16 +250,12 @@ class AudioEncoderServer : public AudioServer { */ AudioEncoderServer(AudioEncoder *encoder, const char* network, const char *password) : AudioServer(network, password) { this->encoder = encoder; - encoded_stream = new AudioOutputStream(*encoder); } /** * @brief Destructor release the memory **/ ~AudioEncoderServer() { - if (encoded_stream!=nullptr){ - delete encoded_stream; - } } @@ -252,17 +267,14 @@ class AudioEncoderServer : public AudioServer { * @param channels */ void begin(Stream &in, int sample_rate, int channels, int bits_per_sample=16, BaseConverter *converter=nullptr) { + LOGD(LOG_METHOD); this->in = ∈ audio_info.sample_rate = sample_rate; audio_info.channels = channels; audio_info.bits_per_sample = bits_per_sample; encoder->setAudioInfo(audio_info); - setConverter(converter); - - connectWiFi(); - - // start server - server.begin(); + encoded_stream.begin(&client_obj, encoder); + AudioServer::begin(in, encoder->mime()); } /** @@ -273,15 +285,13 @@ class AudioEncoderServer : public AudioServer { * @param converter */ void begin(Stream &in, AudioBaseInfo info, BaseConverter *converter=nullptr) { + LOGD(LOG_METHOD); this->in = ∈ this->audio_info = info; encoder->setAudioInfo(audio_info); - setConverter(converter); + encoded_stream.begin(&client_obj, encoder); - connectWiFi(); - - // start server - server.begin(); + AudioServer::begin(in, encoder->mime()); } /** @@ -292,16 +302,13 @@ class AudioEncoderServer : public AudioServer { * @param channels */ void begin(AudioServerDataCallback cb, int sample_rate, int channels, int bits_per_sample=16) { - this->in =nullptr; - this->callback = cb; + LOGD(LOG_METHOD); audio_info.sample_rate = sample_rate; audio_info.channels = channels; audio_info.bits_per_sample = bits_per_sample; encoder->setAudioInfo(audio_info); - connectWiFi(); - // start server - server.begin(); + AudioServer::begin(cb, encoder->mime()); } // provides a pointer to the encoder @@ -313,35 +320,27 @@ class AudioEncoderServer : public AudioServer { protected: // Sound Generation + EncodedAudioStream encoded_stream; AudioBaseInfo audio_info; AudioEncoder *encoder = nullptr; - AudioOutputStream *encoded_stream = nullptr; - virtual void beginEncoder() { - encoder->begin(); + + virtual void sendReplyContent() { + LOGD(LOG_METHOD); + if (callback!=nullptr){ + encoded_stream.begin(out_ptr(), encoder); + // provide data via Callback to encoded_stream + LOGI("sendReply - calling callback"); + callback(&encoded_stream); + client_obj.stop(); + } else if (in!=nullptr){ + // provide data for stream: in -copy> encoded_stream -> out + LOGI("sendReply - Returning WAV stream..."); + encoded_stream.begin(out_ptr(), encoder); + copier.begin(encoded_stream, *in); + } } - void sendReply(){ - LOGD("sendReply"); - // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) - // and a content-type so the client knows what's coming, then a blank line: - client.println("HTTP/1.1 200 OK"); - client.println("Content-type:audio/wav"); - client.println(); - - beginEncoder(); - - if (callback!=nullptr && encoded_stream!=nullptr){ - // provide data via Callback - LOGI("sendReply - calling callback"); - callback((Stream*)encoded_stream); - client.stop(); - } else { - // provide data for stream - LOGI("sendReply - Returning WAV stream..."); - copier.begin(*encoded_stream, *in); - } - } }; diff --git a/src/AudioTools/AudioOutput.h b/src/AudioTools/AudioOutput.h index df2a1b7ab..1e696396d 100644 --- a/src/AudioTools/AudioOutput.h +++ b/src/AudioTools/AudioOutput.h @@ -181,44 +181,6 @@ class HexDumpStream : public AudioPrint { bool active = false; }; -/** - * @brief Construct a new Encoded Stream object which is supporting defined Audio File types - * @author Phil Schatzmann - * @copyright GPLv3 - */ -class AudioOutputStream : public AudioPrint { - public: - AudioOutputStream(){ - active = true; - } - - AudioOutputStream(AudioWriter &writer){ - decoder_ptr = &writer; - active = true; - } - - void begin() { - active = true; - } - - void end() { - active = false; - } - - operator bool() { - return active && *decoder_ptr; - } - - virtual size_t write(const uint8_t* data, size_t len) { - if (decoder_ptr==nullptr || !active) return 0; - LOGD(LOG_METHOD); - return decoder_ptr->write(data, len); - } - - protected: - AudioWriter *decoder_ptr; - bool active; -}; /** * @brief A more natural Stream class to process encoded data (aac, wav, mp3...). @@ -270,7 +232,6 @@ class EncodedAudioStream : public AudioPrint, public AudioBaseInfoSource { active = false; } - /** * @brief Construct a new Encoded Audio Stream object - used for encoding * @@ -284,6 +245,16 @@ class EncodedAudioStream : public AudioPrint, public AudioBaseInfoSource { writer_ptr = encoder_ptr; active = false; } + + /** + * @brief Construct a new Encoded Audio Stream object - the Output and Encoder/Decoder needs to be defined with the begin method + * + */ + EncodedAudioStream(){ + LOGD(LOG_METHOD); + active = false; + } + /** * @brief Destroy the Encoded Audio Stream object * @@ -300,12 +271,36 @@ class EncodedAudioStream : public AudioPrint, public AudioBaseInfoSource { decoder_ptr->setNotifyAudioChange(bi); } + + /// Starts the processing - sets the status to active + void begin(Print *outputStream, AudioEncoder *encoder) { + LOGD(LOG_METHOD); + encoder_ptr = encoder; + encoder_ptr->setOutputStream(*outputStream); + writer_ptr = encoder_ptr; + begin(); + } + + /// Starts the processing - sets the status to active + void begin(Print *outputStream, AudioDecoder *decoder) { + LOGD(LOG_METHOD); + decoder_ptr = decoder; + decoder_ptr->setOutputStream(*outputStream); + writer_ptr = decoder_ptr; + begin(); + } + /// Starts the processing - sets the status to active void begin() { LOGD(LOG_METHOD); - decoder_ptr->begin(); - encoder_ptr->begin(); - active = true; + const CodecNOP *nop = CodecNOP::instance(); + if (decoder_ptr != nop || encoder_ptr != nop){ + decoder_ptr->begin(); + encoder_ptr->begin(); + active = true; + } else { + LOGW("no decoder or encoder defined"); + } } /// Ends the processing