diff --git a/linux/alsa/alsa_driver.c b/linux/alsa/alsa_driver.c index 5a1092d0..69045905 100644 --- a/linux/alsa/alsa_driver.c +++ b/linux/alsa/alsa_driver.c @@ -59,6 +59,44 @@ char* strcasestr(const char* haystack, const char* needle); /* Max re-try count for Alsa poll timeout handling */ #define MAX_RETRY_COUNT 5 +#ifdef __QNXNTO__ + +char qnx_channel_error_str[9][35] = { + "SND_PCM_STATUS_NOTREADY", + "SND_PCM_STATUS_READY", + "SND_PCM_STATUS_PREPARED", + "SND_PCM_STATUS_RUNNING", + "SND_PCM_STATUS_PAUSED", + "SND_PCM_STATUS_SUSPENDED", + "SND_PCM_STATUS_UNDERRUN", + "SND_PCM_STATUS_OVERRUN", + "SND_PCM_STATUS_UNKNOWN", +}; + +static char* alsa_channel_status_error_str(int code) +{ + switch(code) { + case SND_PCM_STATUS_NOTREADY: + return qnx_channel_error_str[0]; + case SND_PCM_STATUS_READY: + return qnx_channel_error_str[1]; + case SND_PCM_STATUS_PREPARED: + return qnx_channel_error_str[2]; + case SND_PCM_STATUS_RUNNING: + return qnx_channel_error_str[3]; + case SND_PCM_STATUS_PAUSED: + return qnx_channel_error_str[4]; + case SND_PCM_STATUS_SUSPENDED: + return qnx_channel_error_str[5]; + case SND_PCM_STATUS_UNDERRUN: + return qnx_channel_error_str[6]; + case SND_PCM_STATUS_OVERRUN: + return qnx_channel_error_str[7]; + } + return qnx_channel_error_str[8]; +} +#endif + static int alsa_driver_link (alsa_driver_t *driver); static int alsa_driver_open_device (alsa_driver_t *driver, alsa_device_t *device, bool is_capture); static int alsa_driver_get_state (snd_pcm_t *handle, int is_capture); @@ -1390,6 +1428,8 @@ alsa_driver_open (alsa_driver_t *driver) int do_capture = 0, do_playback = 0; if (!device->capture_handle && (i < driver->devices_c_count) && (device->capture_target_state != SND_PCM_STATE_NOTREADY)) { + jack_info("open C: %s", device->capture_name); + err = alsa_driver_open_device (driver, &driver->devices[i], SND_PCM_STREAM_CAPTURE); if (err < 0) { jack_error ("\n\nATTENTION: Opening of the capture device \"%s\" failed.", @@ -1401,6 +1441,8 @@ alsa_driver_open (alsa_driver_t *driver) } if (!device->playback_handle && (i < driver->devices_p_count) && (device->playback_target_state != SND_PCM_STATE_NOTREADY)) { + jack_info("open P: %s", device->playback_name); + err = alsa_driver_open_device (driver, &driver->devices[i], SND_PCM_STREAM_PLAYBACK); if (err < 0) { jack_error ("\n\nATTENTION: Opening of the playback device \"%s\" failed.", @@ -1439,21 +1481,27 @@ alsa_driver_link (alsa_driver_t *driver) continue; } + jack_info("link C: %s", device->capture_name); + if (device->capture_target_state != SND_PCM_STATE_RUNNING) { + jack_info("link skipped, device unused"); continue; } if (group_handle == NULL) { + jack_info("link, device is group master"); group_handle = device->capture_handle; device->capture_linked = 1; continue; } if (device->capture_linked) { + jack_info("link skipped, already done"); continue; } if (group_handle == device->capture_handle) { + jack_info("link skipped, master already done"); device->capture_linked = 1; continue; } @@ -1472,21 +1520,27 @@ alsa_driver_link (alsa_driver_t *driver) continue; } + jack_info("link P: %s", device->playback_name); + if (device->playback_target_state != SND_PCM_STATE_RUNNING) { + jack_info("link skipped, device unused"); continue; } if (group_handle == NULL) { + jack_info("link, device is group master"); group_handle = device->playback_handle; device->playback_linked = 1; continue; } if (device->playback_linked) { + jack_info("link skipped, already done"); continue; } if (group_handle == device->playback_handle) { + jack_info("link skipped, master already done"); device->playback_linked = 1; continue; } @@ -1520,7 +1574,10 @@ alsa_driver_start (alsa_driver_t *driver) continue; } + jack_info("prepare C: %s", device->capture_name); + if (device->capture_target_state == SND_PCM_STATE_NOTREADY) { + jack_info("prepare skipped, device unused"); continue; } @@ -1529,10 +1586,12 @@ alsa_driver_start (alsa_driver_t *driver) } if (group_done && device->capture_linked) { + jack_info("prepare skipped, already done by link group"); continue; } if (alsa_driver_get_state(device->capture_handle, 1) == SND_PCM_STATE_PREPARED) { + jack_info("prepare skipped, already prepared"); continue; } @@ -1553,7 +1612,10 @@ alsa_driver_start (alsa_driver_t *driver) continue; } + jack_info("prepare P: %s", device->playback_name); + if (device->playback_target_state == SND_PCM_STATE_NOTREADY) { + jack_info("prepare skipped, device unused"); continue; } @@ -1562,10 +1624,12 @@ alsa_driver_start (alsa_driver_t *driver) } if (group_done && device->playback_linked) { + jack_info("prepare skipped, already done by link group"); continue; } if (alsa_driver_get_state(device->playback_handle, 0) == SND_PCM_STATE_PREPARED) { + jack_info("prepare skipped, already prepared"); continue; } @@ -1612,7 +1676,10 @@ alsa_driver_start (alsa_driver_t *driver) continue; } + jack_info("silence P: %s", device->playback_name); + if (device->playback_target_state != SND_PCM_STATE_RUNNING) { + jack_info("silence skipped, device unused"); continue; } @@ -1655,8 +1722,8 @@ alsa_driver_start (alsa_driver_t *driver) device->playback_sample_bytes; if ((err = snd_pcm_plugin_write(device->playback_handle, device->playback_areas, bytes)) < bytes) { - jack_error ("ALSA: could not complete write of %" - PRIu32 " frames: error = %d", silence_frames, err); + jack_error ("ALSA: could not complete silence %s of %" + PRIu32 " frames: %u, error = %d", device->playback_name, silence_frames, err, errno); return -1; } #else @@ -1673,11 +1740,15 @@ alsa_driver_start (alsa_driver_t *driver) continue; } + jack_info("start C: %s", device->capture_name); + if (device->capture_target_state != SND_PCM_STATE_RUNNING) { + jack_info("start skipped, device unused"); continue; } if (group_done && device->capture_linked) { + jack_info("start skipped, already done by link group"); continue; } @@ -1699,11 +1770,15 @@ alsa_driver_start (alsa_driver_t *driver) continue; } + jack_info("start P: %s", device->playback_name); + if (device->playback_target_state != SND_PCM_STATE_RUNNING) { + jack_info("start skipped, device unused"); continue; } if (group_done && device->playback_linked) { + jack_info("start skipped, already done by link group"); continue; } @@ -1758,11 +1833,15 @@ alsa_driver_stop (alsa_driver_t *driver) continue; } + jack_info("stop C: %s", device->capture_name); + if (group_done && device->capture_linked) { + jack_info("stop skipped, already done by link group"); continue; } if (alsa_driver_get_state(device->capture_handle, 1) != SND_PCM_STATE_RUNNING) { + jack_info("stop skipped, device not running"); continue; } @@ -1788,11 +1867,15 @@ alsa_driver_stop (alsa_driver_t *driver) continue; } + jack_info("stop P: %s", device->playback_name); + if (group_done && device->playback_linked) { + jack_info("stop skipped, already done by link group"); continue; } if (alsa_driver_get_state(device->playback_handle, 0) != SND_PCM_STATE_RUNNING) { + jack_info("stop skipped, device not running"); continue; } @@ -1938,7 +2021,6 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs) if (device->playback_handle) { state = alsa_driver_get_state(device->playback_handle, SND_PCM_STREAM_PLAYBACK); - // TODO overrun if (state == SND_PCM_STATE_XRUN) { driver->xrun_count++; @@ -2092,12 +2174,13 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, alsa_driver_wait_status_t pfd_count - pfd_index, SND_PCM_STREAM_CAPTURE); if (pfd_cap_count[i] < 0) { - jack_log ("alsa_driver_poll_descriptors failed pfd_cap_count[%d]=%d", i ,pfd_cap_count[i] ); /* In case of xrun -EPIPE is returned perform xrun recovery*/ if (pfd_cap_count[i] == -EPIPE) { + jack_error("poll descriptors xrun C: %s pfd_cap_count[%d]=%d", device->capture_name, i, pfd_cap_count[i]); goto xrun; } /* for any other error return negative wait status to caller */ + jack_error("poll descriptors error C: %s pfd_cap_count[%d]=%d", device->capture_name, i, pfd_cap_count[i]); *status = ALSA_DRIVER_WAIT_ERROR; return 0; } else { @@ -2126,12 +2209,13 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, alsa_driver_wait_status_t pfd_count - pfd_index, SND_PCM_STREAM_PLAYBACK); if (pfd_play_count[i] < 0) { - jack_log ("alsa_driver_poll_descriptors failed pfd_play_count[%d]=%d", i ,pfd_play_count[i] ); /* In case of xrun -EPIPE is returned perform xrun recovery*/ if (pfd_cap_count[i] == -EPIPE) { + jack_error("poll descriptors xrun P: %s pfd_cap_count[%d]=%d", device->playback_name, i, pfd_play_count[i]); goto xrun; } /* for any other error return negative wait status to caller */ + jack_error("poll descriptors error P: %s pfd_cap_count[%d]=%d", device->playback_name, i, pfd_play_count[i]); *status = ALSA_DRIVER_WAIT_ERROR; return 0; } else { @@ -2200,6 +2284,14 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, alsa_driver_wait_status_t jack_error ("ALSA: poll time out, polled for %" PRIu64 " usecs, Retrying with a recovery, retry cnt = %d", poll_ret - poll_enter, retry_cnt); + for (int i = 0; i < driver->devices_count; ++i) { + if (driver->devices[i].capture_handle && i < driver->devices_c_count && cap_revents[i] == 0) { + jack_log("device C: %s poll was requested", driver->devices[i].capture_name); + } + if (driver->devices[i].playback_handle && i < driver->devices_p_count && play_revents[i] == 0) { + jack_log("device P: %s poll was requested", driver->devices[i].playback_name); + } + } goto xrun; } @@ -2217,6 +2309,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, alsa_driver_wait_status_t * to return from poll */ if (driver->pfd[pfd_index-1].revents == 0) { /* we timed out on the extra fd */ + jack_error("extra fd error"); *status = ALSA_DRIVER_WAIT_ERROR; return -1; } @@ -2449,8 +2542,12 @@ alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes) const size_t bytes = contiguous * device->capture_nchannels * device->capture_sample_bytes; if ((err = snd_pcm_plugin_read(device->capture_handle, device->capture_areas, bytes)) < bytes) { - jack_error ("ALSA: could not complete read of %" - PRIu32 " frames: error = %d", contiguous, err); + jack_error("read C: %s, requested %d, got %d, snd error %s, errno %d", + device->capture_name, + bytes, + err, + alsa_channel_status_error_str(alsa_driver_get_state(device->capture_handle, 1)), + errno); return -1; } #endif @@ -2476,8 +2573,8 @@ alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes) #ifndef __QNXNTO__ if ((err = snd_pcm_mmap_commit (device->capture_handle, offset, contiguous)) < 0) { - jack_error ("ALSA: could not complete read of %" - PRIu32 " frames: error = %d", contiguous, err); + jack_error ("ALSA: could not complete read commit %s of %" + PRIu32 " frames: error = %d", device->capture_name, contiguous, err); return -1; } #endif @@ -2586,15 +2683,19 @@ alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes) const size_t bytes = contiguous * device->playback_nchannels * device->playback_sample_bytes; if ((err = snd_pcm_plugin_write(device->playback_handle, device->playback_areas, bytes)) < bytes) { - jack_error ("ALSA: could not complete write of %" - PRIu32 " frames: error = %d", contiguous, err); + jack_error("write P: %s, requested %d, got %d, snd error %s, errno %d", + device->playback_name, + bytes, + err, + alsa_channel_status_error_str(alsa_driver_get_state(device->playback_handle, 0)), + errno); return -1; } #else if ((err = snd_pcm_mmap_commit (device->playback_handle, offset, contiguous)) < 0) { - jack_error ("ALSA: could not complete playback of %" - PRIu32 " frames: error = %d", contiguous, err); + jack_error ("ALSA: could not complete playback commit %s of %" + PRIu32 " frames: error = %d", device->playback_name, contiguous, err); if (err != -EPIPE && err != -ESTRPIPE) return -1; } @@ -2888,8 +2989,9 @@ alsa_driver_open_device (alsa_driver_t *driver, alsa_device_t *device, bool is_c case EPERM: jack_error ("you do not have permission to open " - "the audio device \"%s\" for playback", - is_capture ? device->capture_name : device->playback_name); + "the audio device \"%s\" for %s", + is_capture ? device->capture_name : device->playback_name, + is_capture ? "capture" : "playback"); break; case EINVAL: