void AudioDriverALSA::thread_func(void *p_udata) { AudioDriverALSA *ad = (AudioDriverALSA *)p_udata; while (!ad->exit_thread) { ad->lock(); ad->start_counting_ticks(); if (!ad->active) { for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) { ad->samples_out[i] = 0; } } else { ad->audio_server_process(ad->period_size, ad->samples_in.ptrw()); for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) { ad->samples_out[i] = ad->samples_in[i] >> 16; } } int todo = ad->period_size; int total = 0; while (todo && !ad->exit_thread) { uint8_t *src = (uint8_t *)ad->samples_out.ptr(); int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo); if (wrote > 0) { total += wrote; todo -= wrote; } else if (wrote == -EAGAIN) { ad->stop_counting_ticks(); ad->unlock(); OS::get_singleton()->delay_usec(1000); ad->lock(); ad->start_counting_ticks(); } else { wrote = snd_pcm_recover(ad->pcm_handle, wrote, 0); if (wrote < 0) { ERR_PRINTS("ALSA: Failed and can't recover: " + String(snd_strerror(wrote))); ad->active = false; ad->exit_thread = true; } } } // User selected a new device, finish the current one so we'll init the new device if (ad->device_name != ad->new_device) { ad->device_name = ad->new_device; ad->finish_device(); Error err = ad->init_device(); if (err != OK) { ERR_PRINT("ALSA: init_device error"); ad->device_name = "Default"; ad->new_device = "Default"; err = ad->init_device(); if (err != OK) { ad->active = false; ad->exit_thread = true; } } } ad->stop_counting_ticks(); ad->unlock(); }; ad->thread_exited = true; };