|
|
@ -65,28 +65,41 @@ void AudioTaskMain(void* args) { |
|
|
|
element->HasUnprocessedInput()) && |
|
|
|
element->HasUnprocessedInput()) && |
|
|
|
!element->IsOverBuffered(); |
|
|
|
!element->IsOverBuffered(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (has_work_to_do) { |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "checking for events"); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "waiting for events"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If we have no new events to process and the element has nothing left to
|
|
|
|
// If we have no new events to process and the element has nothing left to
|
|
|
|
// do, then just delay forever waiting for a new event.
|
|
|
|
// do, then just delay forever waiting for a new event.
|
|
|
|
TickType_t ticks_to_wait = has_work_to_do ? 0 : portMAX_DELAY; |
|
|
|
TickType_t ticks_to_wait = has_work_to_do ? 0 : portMAX_DELAY; |
|
|
|
|
|
|
|
|
|
|
|
StreamEvent* event_ptr = nullptr; |
|
|
|
StreamEvent* new_event = nullptr; |
|
|
|
bool has_event = |
|
|
|
bool has_event = |
|
|
|
xQueueReceive(element->InputEventQueue(), &event_ptr, ticks_to_wait); |
|
|
|
xQueueReceive(element->InputEventQueue(), &new_event, ticks_to_wait); |
|
|
|
|
|
|
|
|
|
|
|
if (has_event && event_ptr != nullptr) { |
|
|
|
if (has_event) { |
|
|
|
std::unique_ptr<StreamEvent> event(event_ptr); |
|
|
|
if (new_event->tag == StreamEvent::UNINITIALISED) { |
|
|
|
if (event->tag == StreamEvent::CHUNK_NOTIFICATION) { |
|
|
|
ESP_LOGE(kTag, "discarding invalid event!!"); |
|
|
|
|
|
|
|
} else if (new_event->tag == StreamEvent::CHUNK_NOTIFICATION) { |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "marking chunk as used"); |
|
|
|
element->OnChunkProcessed(); |
|
|
|
element->OnChunkProcessed(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// This isn't an event that needs to be actioned immediately. Add it
|
|
|
|
// This isn't an event that needs to be actioned immediately. Add it
|
|
|
|
// to our work queue.
|
|
|
|
// to our work queue.
|
|
|
|
pending_events.push_back(std::move(event)); |
|
|
|
pending_events.emplace_back(new_event); |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "deferring event"); |
|
|
|
} |
|
|
|
} |
|
|
|
// Loop again, so that we service all incoming events before doing our
|
|
|
|
// Loop again, so that we service all incoming events before doing our
|
|
|
|
// possibly expensive processing.
|
|
|
|
// possibly expensive processing.
|
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (element->HasUnflushedOutput()) { |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "flushing output"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// We have no new events. Next, see if there's anything that needs to be
|
|
|
|
// We have no new events. Next, see if there's anything that needs to be
|
|
|
|
// flushed.
|
|
|
|
// flushed.
|
|
|
|
if (element->HasUnflushedOutput() && !element->FlushBufferedOutput()) { |
|
|
|
if (element->HasUnflushedOutput() && !element->FlushBufferedOutput()) { |
|
|
@ -99,6 +112,7 @@ void AudioTaskMain(void* args) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (element->HasUnprocessedInput()) { |
|
|
|
if (element->HasUnprocessedInput()) { |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "processing input events"); |
|
|
|
auto process_res = element->Process(); |
|
|
|
auto process_res = element->Process(); |
|
|
|
if (!process_res.has_error() || process_res.error() != OUT_OF_DATA) { |
|
|
|
if (!process_res.has_error() || process_res.error() != OUT_OF_DATA) { |
|
|
|
// TODO: log!
|
|
|
|
// TODO: log!
|
|
|
@ -109,27 +123,29 @@ void AudioTaskMain(void* args) { |
|
|
|
// The element ran out of data, so now it's time to let it process more
|
|
|
|
// The element ran out of data, so now it's time to let it process more
|
|
|
|
// input.
|
|
|
|
// input.
|
|
|
|
while (!pending_events.empty()) { |
|
|
|
while (!pending_events.empty()) { |
|
|
|
auto event = std::move(pending_events.front()); |
|
|
|
auto& event = pending_events.front(); |
|
|
|
pending_events.pop_front(); |
|
|
|
ESP_LOGI(kTag, "processing event, tag %i", event->tag); |
|
|
|
|
|
|
|
|
|
|
|
if (event->tag == StreamEvent::STREAM_INFO) { |
|
|
|
if (event->tag == StreamEvent::STREAM_INFO) { |
|
|
|
|
|
|
|
ESP_LOGI(kTag, "processing stream info"); |
|
|
|
auto process_res = element->ProcessStreamInfo(*event->stream_info); |
|
|
|
auto process_res = element->ProcessStreamInfo(*event->stream_info); |
|
|
|
|
|
|
|
pending_events.pop_front(); |
|
|
|
if (process_res.has_error()) { |
|
|
|
if (process_res.has_error()) { |
|
|
|
// TODO(jacqueline)
|
|
|
|
// TODO(jacqueline)
|
|
|
|
ESP_LOGE(kTag, "failed to process stream info"); |
|
|
|
ESP_LOGE(kTag, "failed to process stream info"); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (event->tag == StreamEvent::CHUNK_DATA) { |
|
|
|
} else if (event->tag == StreamEvent::CHUNK_DATA) { |
|
|
|
StreamEvent* callback = new StreamEvent(); |
|
|
|
ESP_LOGI(kTag, "processing chunk data"); |
|
|
|
callback->source = element->InputEventQueue(); |
|
|
|
auto callback = |
|
|
|
callback->tag = StreamEvent::CHUNK_NOTIFICATION; |
|
|
|
StreamEvent::CreateChunkNotification(element->InputEventQueue()); |
|
|
|
if (!xQueueSend(event->source, callback, 0)) { |
|
|
|
if (!xQueueSend(event->source, &callback, 0)) { |
|
|
|
// TODO: log? crash? hmm.
|
|
|
|
ESP_LOGW(kTag, "failed to send chunk notif"); |
|
|
|
pending_events.push_front(std::move(event)); |
|
|
|
|
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto process_chunk_res = |
|
|
|
auto process_chunk_res = |
|
|
|
element->ProcessChunk(event->chunk_data.bytes); |
|
|
|
element->ProcessChunk(event->chunk_data.bytes); |
|
|
|
|
|
|
|
pending_events.pop_front(); |
|
|
|
if (process_chunk_res.has_error()) { |
|
|
|
if (process_chunk_res.has_error()) { |
|
|
|
// TODO(jacqueline)
|
|
|
|
// TODO(jacqueline)
|
|
|
|
ESP_LOGE(kTag, "failed to process chunk"); |
|
|
|
ESP_LOGE(kTag, "failed to process chunk"); |
|
|
|