3#include "AudioConfig.h"
4#include "AudioTools/CoreAudio/AudioTypes.h"
5#include "AudioTools/CoreAudio/Buffers.h"
6#include "AudioTools/CoreAudio/BaseConverter.h"
7#include "AudioTools/CoreAudio/AudioLogger.h"
8#include "AudioTools/CoreAudio/AudioStreams.h"
9#include "AudioTools/CoreAudio/AudioMetaData/MimeDetector.h"
11#define NOT_ENOUGH_MEMORY_MSG "Could not allocate enough memory: %d bytes"
52 if (p_mime_detector!=
nullptr) {
53 p_mime_detector->begin();
57 LOGI(
"buffer_size=%d",buffer_size);
59 LOGE(NOT_ENOUGH_MEMORY_MSG, buffer_size);
79 this->from_audio = &from;
96 p_converter =
nullptr;
102 p_converter = &converter;
108 LOGD(
"copy %d bytes %s", (
int)
bytes, log_name);
109 if (!active)
return 0;
111 if (from==
nullptr && to==
nullptr)
return 0;
117 int to_write = to->availableForWrite();
118 if (check_available_for_write &&
to_write==0){
124 if (buffer.size() <
bytes){
125 LOGI(
"Resize to %d", (
int)
bytes);
126 buffer.resize(
bytes);
132 if (check_available) {
159 if (p_mime_detector !=
nullptr){
164 if (p_converter!=
nullptr) p_converter->convert((
uint8_t*)buffer.data(),
bytes_read );
170 if (onWrite!=
nullptr) onWrite(onWriteObj, &buffer[0], result);
173 LOGI(
"StreamCopy::copy %s %u -> %u -> %u bytes - in %u hops",log_name, (
unsigned int)
bytes_to_read,(
unsigned int)
bytes_read, (
unsigned int)result, (
unsigned int)
delayCount);
180 delay(delay_on_no_data);
187 delay(delay_on_no_data);
188 LOGD(
"no data %s", log_name);
196 if (!active)
return 0;
206 if (!active)
return 0;
214 if (!active)
return 0;
218 if (from==
nullptr || to ==
nullptr)
245 if (availableCallback!=
nullptr){
246 result = availableCallback((
Stream*)from);
248 result = from->available();
251 LOGW(
"source not defined");
253 LOGD(
"available: %d", result);
265 this->onWrite = onWrite;
266 this->onWriteObj =
obj;
271 availableCallback = callback;
286 check_available_for_write =
flag;
291 return check_available_for_write;
296 check_available =
flag;
301 return check_available;
307 buffer.resize(buffer_size);
332 if (min_copy_size==0 && from_audio !=
nullptr){
336 return min_copy_size;
341 min_copy_size = size;
346 is_sync_audio_info = active;
351 p_mime_detector = &mime;
359 int buffer_size = DEFAULT_BUFFER_SIZE;
360 void (*onWrite)(
void*obj,
void*buffer,
size_t len) =
nullptr;
361 int (*availableCallback)(Stream*stream)=
nullptr;
362 void *onWriteObj =
nullptr;
363 bool check_available_for_write =
false;
364 bool check_available =
true;
365 int retryLimit = COPY_RETRY_LIMIT;
366 int delay_on_no_data = COPY_DELAY_ON_NODATA;
368 const char* log_name =
"";
369 int retry_delay = 10;
371 int min_copy_size = 1;
372 bool is_sync_audio_info =
false;
373 AudioInfoSupport *p_audio_info_support =
nullptr;
374 BaseConverter* p_converter =
nullptr;
375 MimeDetector* p_mime_detector =
nullptr;
377 void syncAudioInfo(){
379 if (is_sync_audio_info && from_audio !=
nullptr && p_audio_info_support !=
nullptr){
381 AudioInfo info_to = p_audio_info_support->audioInfo();
382 if (info_from != info_to){
383 LOGI(
"--> StreamCopy: ");
384 p_audio_info_support->setAudioInfo(info_from);
391 if (!buffer || len==0)
return 0;
392 LOGD(
"write: %d", (
int)len);
397 size_t written = to->write((
const uint8_t*)buffer.data()+total, open);
398 LOGD(
"write: %d -> %d", (
int) open, (
int) written);
405 if (written>0)
retry = 0;
408 if (
retry++ > retryLimit){
409 LOGE(
"write %s to target has failed after %d retries! (%ld bytes)", log_name,
retry, open);
416 LOGI(
"try write %s - %d (open %ld bytes) ",log_name,
retry, open);