3 #include "AudioConfig.h"
4 #include "AudioTools/AudioTypes.h"
5 #include "AudioTools/Buffers.h"
6 #include "AudioTools/BaseConverter.h"
7 #include "AudioTools/AudioLogger.h"
8 #include "AudioTools/AudioStreams.h"
10 #define NOT_ENOUGH_MEMORY_MSG "Could not allocate enough memory: %d bytes"
32 LOGE(NOT_ENOUGH_MEMORY_MSG, buffer_size);
41 LOGE(NOT_ENOUGH_MEMORY_MSG, buffer_size);
49 LOGE(NOT_ENOUGH_MEMORY_MSG, buffer_size);
56 LOGI(
"buffer_size=%d",buffer_size);
70 LOGI(
"buffer_size=%d",buffer_size);
78 LOGI(
"buffer_size=%d",buffer_size);
93 LOGD(
"copy %s", log_name);
94 if (!active)
return 0;
96 if (from==
nullptr && to==
nullptr)
return 0;
102 int to_write = to->availableForWrite();
103 if (check_available_for_write && to_write==0){
109 size_t delayCount = 0;
110 size_t len = buffer_size;
111 if (check_available) {
114 size_t bytes_to_read = buffer_size;
115 size_t bytes_read = 0;
118 bytes_to_read = min(len,
static_cast<size_t>(buffer_size));
121 bytes_to_read = min((
int)bytes_to_read, to_write);
133 if (bytes_to_read>0){
134 bytes_read = from->readBytes((uint8_t*)&buffer[0], bytes_to_read);
141 result =
write(bytes_read, delayCount);
144 if (onWrite!=
nullptr) onWrite(onWriteObj, &buffer[0], result);
147 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);
154 delay(delay_on_no_data);
161 delay(delay_on_no_data);
162 LOGD(
"no data %s", log_name);
173 if (availableCallback!=
nullptr){
174 result = availableCallback((
Stream*)from);
176 result = from->available();
179 LOGW(
"source not defined");
181 LOGD(
"available: %d", result);
187 delay_on_no_data = delayMs;
192 if (!active)
return 0;
194 for (
size_t j=0;j<pages;j++){
202 if (!active)
return 0;
208 size_t copyAll(
int retryCount=5,
int retryWaitMs=200){
210 if (!active)
return 0;
214 if (from==
nullptr || to ==
nullptr)
230 if (retry>retryCount){
245 this->notifyMimeCallback = callback;
251 this->onWrite = onWrite;
252 this->onWriteObj = obj;
257 availableCallback = callback;
272 check_available_for_write = flag;
277 return check_available_for_write;
282 check_available = flag;
287 return check_available;
293 buffer.resize(buffer_size);
318 if (min_copy_size==0){
322 return min_copy_size;
327 min_copy_size = size;
332 is_sync_audio_info = active;
340 void (*onWrite)(
void*obj,
void*buffer,
size_t len) =
nullptr;
341 void (*notifyMimeCallback)(
const char*
mime) =
nullptr;
342 int (*availableCallback)(Stream*stream)=
nullptr;
343 void *onWriteObj =
nullptr;
344 bool is_first =
false;
345 bool check_available_for_write =
false;
346 bool check_available =
true;
347 const char* actual_mime =
nullptr;
348 int retryLimit = COPY_RETRY_LIMIT;
349 int delay_on_no_data = COPY_DELAY_ON_NODATA;
351 const char* log_name =
"";
352 int retry_delay = 10;
354 int min_copy_size = 1;
355 bool is_sync_audio_info =
false;
356 AudioInfoSupport *p_audio_info_support =
nullptr;
358 void syncAudioInfo(){
360 if (is_sync_audio_info && from !=
nullptr && p_audio_info_support !=
nullptr){
362 AudioInfo info_to = p_audio_info_support->audioInfo();
363 if (info_from != info_to){
364 LOGI(
"--> StreamCopy: ");
365 p_audio_info_support->setAudioInfo(info_from);
371 size_t write(
size_t len,
size_t &delayCount ){
372 if (!buffer || len==0)
return 0;
373 LOGD(
"write: %d", (
int)len);
378 size_t written = to->write((
const uint8_t*)buffer.data()+total, open);
379 LOGD(
"write: %d -> %d", (
int) open, (
int) written);
386 if (written>0) retry = 0;
389 if (retry++ > retryLimit){
390 LOGE(
"write %s to target has failed after %d retries! (%ld bytes)", log_name, retry, open);
397 LOGI(
"try write %s - %d (open %ld bytes) ",log_name, retry, open);
408 if (is_first && len>4) {
409 const uint8_t *start = (
const uint8_t *) data;
410 actual_mime =
"audio/basic";
411 if (start[0]==0xFF && start[1]==0xF1){
412 actual_mime =
"audio/aac";
413 }
else if (memcmp(start,
"ID3",3) || start[0]==0xFF || start[0]==0xFE ){
414 actual_mime =
"audio/mpeg";
415 }
else if (memcmp(start,
"RIFF",4)){
416 actual_mime =
"audio/vnd.wave";
418 if (notifyMimeCallback!=
nullptr){
419 notifyMimeCallback(actual_mime);
441 p_audio_info_support = &to;
446 p_audio_info_support = &to;
460 size_t delayCount = 0;
464 size_t bytes_to_read = min(result,
static_cast<size_t>(buffer_size) );
465 result = from->readBytes((uint8_t*)&buffer[0], bytes_to_read);
472 if (onWrite!=
nullptr) onWrite(onWriteObj, buffer.data(), result);
475 coverter_ptr->convert((uint8_t*)buffer.data(), result );
476 write(result, delayCount);
478 LOGI(
"StreamCopy::copy %u bytes - in %u hops", (
unsigned int)result,(
unsigned int) delayCount);
482 delay(delay_on_no_data);