rfc: wineasio patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello all,

I've made some changes to wineasio that I'd like some feedback on.

1. Fixes wrongly reported ASIO output latency
2. Changes the SCHED_FIFO priority of the win32 callback thread
     * Calls jack_client_real_time_priority() to get recommended priority
     * Removes hard coded SCHED_FIFO priority of 86 for the entire process
     * Sets win32 callback thread to SCHED_FIFO priority suggested by JACK
3. Adds a fork with call to qjackctl from the ASIOControlPanel()

I am going away for 3 weeks on 15/8, but am looking forwards to all and any 
feedback when I return.

Personally I use wineasio together with reaper under wine.  Best results so 
far have been achieved by running JACK realtime and set to default priority, 
with the entire wine session running SCHED_FIFO at priority 1, thus invoked by 
the following: chrt -f 1 env WINEPREFIX="/home/jack/.wine" wine "C:\Program 
Files\REAPER\reaper.exe"

   Joakim
--- asio.c.old	2009-08-10 19:08:32.000000000 +0200
+++ asio.c	2009-08-09 18:34:49.000000000 +0200
@@ -42,6 +42,7 @@
 #include "wine/debug.h"
 
 #include <jack/jack.h>
+#include <jack/thread.h>
 
 #define IEEE754_64FLOAT 1
 #include "asio.h"
@@ -139,6 +140,8 @@
    jack_port_t *port;
 } Channel;
 
+typedef struct sched_param SCHED_PARAM;
+
 struct IWineASIOImpl
 {
     /* COM stuff */
@@ -181,6 +184,7 @@
     jack_client_t       *client;
     long                client_state;
     long                toggle;
+    SCHED_PARAM		jack_client_priority;
 
     /* callback stuff */
     HANDLE              thread;
@@ -381,7 +385,7 @@
     This->sample_rate = 48000.0;
     This->block_frames = 1024;
     This->input_latency = This->block_frames;
-    This->output_latency = This->block_frames * 2;
+    This->output_latency = This->block_frames;
     This->miliseconds = (long)((double)(This->block_frames * 1000) / This->sample_rate);
     This->callbacks = NULL;
     This->sample_position = 0;
@@ -396,24 +400,13 @@
     This->tc_read = FALSE;
     This->terminate = FALSE;
     This->state = Init;
+    This->jack_client_priority.sched_priority = -1;
 
     sem_init(&This->semaphore1, 0, 0);
     sem_init(&This->semaphore2, 0, 0);
 
     This->start_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     This->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-    This->thread = CreateThread(NULL, 0, win32_callback, (LPVOID)This, 0, &This->thread_id);
-    if (This->thread)
-    {
-        WaitForSingleObject(This->start_event, INFINITE);
-        CloseHandle(This->start_event);
-        This->start_event = INVALID_HANDLE_VALUE;
-    }
-    else
-    {
-        WARN("(%p) Couldn't create thread\n", This);
-        return ASIOFalse;
-    }
 
     set_clientname(This);
 
@@ -437,6 +430,21 @@
 
     if (status & JackServerStarted)
         TRACE("(%p) JACK server started\n", This);
+    // get maximum reccomended client priority from JACK
+    This->jack_client_priority.sched_priority = jack_client_real_time_priority (This->client);
+
+    This->thread = CreateThread(NULL, 0, win32_callback, (LPVOID)This, 0, &This->thread_id);
+    if (This->thread)
+    {
+        WaitForSingleObject(This->start_event, INFINITE);
+        CloseHandle(This->start_event);
+        This->start_event = INVALID_HANDLE_VALUE;
+    }
+    else
+    {
+        WARN("(%p) Couldn't create thread\n", This);
+        return ASIOFalse;
+    }
 
 //  if (status & JackNameNotUnique)
 //  {
@@ -451,7 +459,7 @@
 
     This->miliseconds = (long)((double)(This->block_frames * 1000) / This->sample_rate);
     This->input_latency = This->block_frames;
-    This->output_latency = This->block_frames * 2;
+    This->output_latency = This->block_frames;
 
 //  TRACE("sample rate: %f\n", This->sample_rate);
 //  TRACE("buffer size: %ld\n", This->block_frames);
@@ -1024,8 +1032,16 @@
 
 WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_controlPanel, (LPWINEASIO iface))
 {
-    TRACE("(%p) stub!\n", iface);
+    char* arg_list[] = { "qjackctl", NULL };
 
+    TRACE ("Opening ASIO control panel\n");
+
+    if (fork() == 0)
+    {                                                                   /* Code only executed by child process */
+        TRACE ("Calling qjackctl\n");
+        execvp (arg_list[0], arg_list);
+        return ASE_OK;
+    }
     return ASE_OK;
 }
 
@@ -1189,11 +1205,18 @@
 static DWORD CALLBACK win32_callback(LPVOID arg)
 {
     IWineASIOImpl * This = (IWineASIOImpl*)arg;
-    struct sched_param attr;
+
     //TRACE("(%p)\n", arg);
+    TRACE ("win32 callback thread started\n");
 
-    attr.sched_priority = 86;
-    sched_setscheduler(0, SCHED_FIFO, &attr);
+    /* set the priority of the win32 callback thread as suggested by JACK */
+    if (This->jack_client_priority.sched_priority != -1)	/* skip if not running realtime */
+        if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &This->jack_client_priority) == 0)
+            TRACE ("win32 callback set to SCHED_FIFO priority %d\n", This->jack_client_priority.sched_priority);
+        else
+            TRACE ("Error trying to set realtime priority of win32 callback\n");
+    else
+            TRACE ("Unable to set realtime priority of win32 callback, not running with realtime priority\n");
 
     /* let IWineASIO_Init know we are alive */
     SetEvent(This->start_event);
_______________________________________________
Linux-audio-user mailing list
Linux-audio-user@xxxxxxxxxxxxxxxxxxxx
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-user

[Index of Archives]     [Linux Sound]     [ALSA Users]     [Pulse Audio]     [ALSA Devel]     [Sox Users]     [Linux Media]     [Kernel]     [Photo Sharing]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux