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"
10 #define NOT_ENOUGH_MEMORY_MSG "Could not allocate enough memory: %d bytes"
54 LOGI(
"buffer_size=%d",buffer_size);
56 LOGE(NOT_ENOUGH_MEMORY_MSG, buffer_size);
62 if (is_cleanup_from) {
64 is_cleanup_from =
false;
72 is_cleanup_from =
true;
97 p_converter =
nullptr;
103 p_converter = &converter;
109 LOGD(
"copy %d bytes %s", (
int) bytes, log_name);
110 if (!active)
return 0;
112 if (from==
nullptr && to==
nullptr)
return 0;
118 int to_write = to->availableForWrite();
119 if (check_available_for_write && to_write==0){
125 if (buffer.size() < bytes){
126 LOGI(
"Resize to %d", (
int) bytes);
127 buffer.resize(bytes);
131 size_t delayCount = 0;
133 if (check_available) {
136 size_t bytes_to_read = bytes;
137 size_t bytes_read = 0;
140 bytes_to_read = min(len,
static_cast<size_t>(buffer_size));
143 bytes_to_read = min((
int)bytes_to_read, to_write);
155 if (bytes_to_read>0){
156 bytes_read = from->readBytes((uint8_t*)&buffer[0], bytes_to_read);
163 if (p_converter!=
nullptr) p_converter->convert((uint8_t*)buffer.data(), result );
166 result =
write(bytes_read, delayCount);
169 if (onWrite!=
nullptr) onWrite(onWriteObj, &buffer[0], result);
172 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);
179 delay(delay_on_no_data);
186 delay(delay_on_no_data);
187 LOGD(
"no data %s", log_name);
195 if (!active)
return 0;
197 for (
size_t j=0;j<pages;j++){
205 if (!active)
return 0;
211 size_t copyAll(
int retryCount=5,
int retryWaitMs=200){
213 if (!active)
return 0;
217 if (from==
nullptr || to ==
nullptr)
233 if (retry>retryCount){
244 if (availableCallback!=
nullptr){
245 result = availableCallback((
Stream*)from);
247 result = from->available();
250 LOGW(
"source not defined");
252 LOGD(
"available: %d", result);
258 delay_on_no_data = delayMs;
269 this->notifyMimeCallback = callback;
275 this->onWrite = onWrite;
276 this->onWriteObj = obj;
281 availableCallback = callback;
296 check_available_for_write = flag;
301 return check_available_for_write;
306 check_available = flag;
311 return check_available;
317 buffer.resize(buffer_size);
342 if (min_copy_size==0){
346 return min_copy_size;
351 min_copy_size = size;
356 is_sync_audio_info = active;
363 int buffer_size = DEFAULT_BUFFER_SIZE;
364 void (*onWrite)(
void*obj,
void*buffer,
size_t len) =
nullptr;
365 void (*notifyMimeCallback)(
const char*
mime) =
nullptr;
366 int (*availableCallback)(Stream*stream)=
nullptr;
367 void *onWriteObj =
nullptr;
368 bool is_first =
false;
369 bool is_cleanup_from =
false;
370 bool check_available_for_write =
false;
371 bool check_available =
true;
372 const char* actual_mime =
nullptr;
373 int retryLimit = COPY_RETRY_LIMIT;
374 int delay_on_no_data = COPY_DELAY_ON_NODATA;
376 const char* log_name =
"";
377 int retry_delay = 10;
379 int min_copy_size = 1;
380 bool is_sync_audio_info =
false;
381 AudioInfoSupport *p_audio_info_support =
nullptr;
382 BaseConverter* p_converter =
nullptr;
385 void syncAudioInfo(){
387 if (is_sync_audio_info && from !=
nullptr && p_audio_info_support !=
nullptr){
389 AudioInfo info_to = p_audio_info_support->audioInfo();
390 if (info_from != info_to){
391 LOGI(
"--> StreamCopy: ");
392 p_audio_info_support->setAudioInfo(info_from);
398 size_t write(
size_t len,
size_t &delayCount ){
399 if (!buffer || len==0)
return 0;
400 LOGD(
"write: %d", (
int)len);
405 size_t written = to->write((
const uint8_t*)buffer.data()+total, open);
406 LOGD(
"write: %d -> %d", (
int) open, (
int) written);
413 if (written>0) retry = 0;
416 if (retry++ > retryLimit){
417 LOGE(
"write %s to target has failed after %d retries! (%ld bytes)", log_name, retry, open);
424 LOGI(
"try write %s - %d (open %ld bytes) ",log_name, retry, open);
435 if (is_first && len>4) {
436 const uint8_t *start = (
const uint8_t *) data;
437 actual_mime =
"audio/basic";
438 if (start[0]==0xFF && start[1]==0xF1){
439 actual_mime =
"audio/aac";
440 }
else if (memcmp(start,
"ID3",3) || start[0]==0xFF || start[0]==0xFE ){
441 actual_mime =
"audio/mpeg";
442 }
else if (memcmp(start,
"RIFF",4)){
443 actual_mime =
"audio/vnd.wave";
445 if (notifyMimeCallback!=
nullptr){
446 notifyMimeCallback(actual_mime);