broken webserver

This commit is contained in:
Phil Schatzmann 2021-10-25 17:12:12 +02:00
parent 3b1bee1071
commit 357877db07
6 changed files with 111 additions and 117 deletions

View File

@ -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);

View File

@ -5,8 +5,8 @@
*
* @author Phil Schatzmann
* @copyright GPLv3
*
*/
#include "TTS.h"
#include "AudioTools.h"

View File

@ -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);

View File

@ -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");

View File

@ -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<int16_t>(*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<int16_t> *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<int16_t> *converter=nullptr) {
LOGD(LOG_METHOD);
this->in = &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<int16_t> *converter=nullptr) {
LOGD(LOG_METHOD);
this->in = &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);
}
}
};

View File

@ -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