JACK port for the QNX operating system
JACK can be build for QNX and is working fine. I tested with different playback use cases so far.
I provided a makefile calling the WAF build tooling.
I used the following commands for testing
jackd -R -P 80 -d alsa -P pcmC0D0p -p 768 -n 3 -S
jack_simple_client
The latest update introduces the following diff:
diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp
index a8962e1..6fcdf48 100644
--- a/linux/alsa/JackAlsaDriver.cpp
+++ b/linux/alsa/JackAlsaDriver.cpp
@@ -205,7 +205,6 @@ int JackAlsaDriver::Detach()
}
#ifndef __QNXNTO__
-/* del6kor : ToDo : why is strndup not avaiable despite the indludes*/
extern "C" char* get_control_device_name(const char * device_name)
{
char * ctl_name;
@@ -238,7 +237,6 @@ extern "C" char* get_control_device_name(const char * device_name)
#endif
#ifndef __QNXNTO__
-/* del6kor : ToDo : is this needed ? */
static int card_to_num(const char* device)
{
int err;
@@ -969,8 +967,13 @@ void SetTime(jack_time_t time)
int Restart()
{
int res;
- if ((res = g_alsa_driver->Stop()) == 0) {
- res = g_alsa_driver->Start();
+ if ((res = g_alsa_driver->Stop()) != 0) {
+ jack_error("restart: stop driver failed");
+ return res;
+ }
+ if ((res = g_alsa_driver->Start()) != 0) {
+ jack_error("restart: start driver failed");
+ return res;
}
return res;
}
diff --git a/linux/alsa/alsa_driver.c b/linux/alsa/alsa_driver.c
index 72f97a6..1e7eeb4 100644
--- a/linux/alsa/alsa_driver.c
+++ b/linux/alsa/alsa_driver.c
@@ -411,7 +411,6 @@ alsa_driver_allocate_buffer(alsa_driver_t *driver, int frames, int channels, boo
}
jack_error ("ALSA: could not allocate audio buffer");
- alsa_driver_delete(driver);
return -1;
}
@@ -1401,6 +1400,7 @@ alsa_driver_start (alsa_driver_t *driver)
if (alsa_driver_get_channel_addresses (driver,
0, &pavail, 0, &poffset)) {
+ jack_error("silence failed, get channel addresses");
return -1;
}
@@ -1481,7 +1481,8 @@ alsa_driver_stop (alsa_driver_t *driver)
if (driver->playback_handle) {
#ifdef __QNXNTO__
- err = snd_pcm_plugin_flush(driver->playback_handle, SND_PCM_CHANNEL_PLAYBACK);
+ /* In case of playback: Drain discards the frames */
+ err = snd_pcm_plugin_playback_drain(driver->playback_handle);
#else
err = snd_pcm_drop (driver->playback_handle);
#endif
@@ -1496,6 +1497,7 @@ alsa_driver_stop (alsa_driver_t *driver)
|| driver->capture_and_playback_not_synced) {
if (driver->capture_handle) {
#ifdef __QNXNTO__
+ /* In case of capture: Flush discards the frames */
err = snd_pcm_plugin_flush(driver->capture_handle, SND_PCM_CHANNEL_CAPTURE);
#else
err = snd_pcm_drop (driver->capture_handle);
@@ -1556,7 +1558,6 @@ alsa_driver_get_status (alsa_driver_t *driver)
}
#ifdef __QNXNTO__
- /* ToDo : ldevi : Can be moved a different func? s*/
memset (&status, 0, sizeof (status));
status.channel = driver->capture_handle ? SND_PCM_CHANNEL_CAPTURE :
SND_PCM_CHANNEL_PLAYBACK;
@@ -1598,7 +1599,7 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs)
&& driver->process_count > XRUN_REPORT_DELAY) {
driver->xrun_count++;
#ifdef __QNXNTO__
- /* ldevi : ToDo Check if there is a replacement*/
+ /* Timestamp api's are not available as per QNX Documentation */
*delayed_usecs = 0;
#else
struct timeval now, diff, tstamp;
@@ -1625,6 +1626,7 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs)
}
if (alsa_driver_restart (driver)) {
+ jack_error("xrun recovery failed to restart driver");
return -1;
}
return 0;
@@ -1663,22 +1665,7 @@ alsa_driver_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int s
static snd_pcm_sframes_t
alsa_driver_avail(alsa_driver_t *driver, snd_pcm_t *pcm, bool is_capture)
{
- int err;
- snd_pcm_channel_status_t status = {0, };
-
- status.channel = is_capture;
- err = snd_pcm_plugin_status (pcm, &status);
- if (err < 0)
- return err;
-
- switch (status.status) {
- case SND_PCM_STATUS_UNDERRUN:
- case SND_PCM_STATUS_OVERRUN:
- case SND_PCM_STATUS_UNSECURE:
- case SND_PCM_STATUS_CHANGE:
- return -EPIPE;
- }
-
+ /* QNX guarantees that after poll() event at least one perido is available */
return driver->frames_per_cycle;
}
#else
@@ -2485,23 +2472,27 @@ alsa_driver_open (alsa_driver_t *driver, bool is_capture)
case EINVAL:
jack_error ("the state of handle or the mode is invalid "
- "or invalid state change occured \"%s\" for playback",
- is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
+ "or invalid state change occured \"%s\" for %s",
+ is_capture ? driver->alsa_name_capture : driver->alsa_name_playback,
+ is_capture ? "capture" : "playback");
break;
case ENOENT:
- jack_error ("device \"%s\" does not exist for playback",
- is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
+ jack_error ("device \"%s\" does not exist for %s",
+ is_capture ? driver->alsa_name_capture : driver->alsa_name_playback,
+ is_capture ? "capture" : "playback");
break;
case ENOMEM:
- jack_error ("Not enough memory available for allocation for \"%s\" for playback",
- is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
+ jack_error ("Not enough memory available for allocation for \"%s\" for %s",
+ is_capture ? driver->alsa_name_capture : driver->alsa_name_playback,
+ is_capture ? "capture" : "playback");
break;
case SND_ERROR_INCOMPATIBLE_VERSION:
- jack_error ("Version mismatch \"%s\" for playback",
- is_capture ? driver->alsa_name_capture : driver->alsa_name_playback);
+ jack_error ("Version mismatch \"%s\" for %s",
+ is_capture ? driver->alsa_name_capture : driver->alsa_name_playback,
+ is_capture ? "capture" : "playback");
break;
}
alsa_driver_delete (driver);
It mainly removes TODO comments and solves some minor QNX specific issues.
Merging this is tricky, because I have no device with such architecture. Is there any way we can add a CI check for QNX? (the osx CI build is broken at the moment, I know, will fix sometime soon. just takes ages to verify any possible fix)
Hello @falkTX,
I have not yet touched CI. Are you aware of any good introduction? What would we need to provide to get it build for QNX? I expect the build is running on Linux with some cross compile environment, right?
Mostly all it needs is a script or set of instructions to automatically build what is needed, even better if it can be tested afterwards. If you can tell me how you cross-compile, I might be able to add it in.
Hi @falkTX, I have done a short research. The instructions to install the QNX compiler and the headers can be found in [1].
But I am not sure if QNX would provide a license for free for this purpose. You can get a 30-day evaluation license for free [2]. Licenses for education are also provided for free [3]. There it is mentioned that such licenses are for research purpose. Therefore may be QNX would offer such a license for this project. Would you like to raise this question to QNX as the maintainer of this project?
[1] http://www.qnx.com/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.momentics_installation_guide%2Flinux_hosts.html&anchor=Install [2] http://www.qnx.com/products/evaluation/ [3] http://www.qnx.com/company/education/
oh, so QNX is not an open system? nevermind then, I have no interest on such things.
you can leave the PR open so others can check the status and know that this exists. but I won't be the one merging it.