Browse Source

WineASIO 0.8.1

tags/v1.0.0
Joakim B Hernberg 14 years ago
parent
commit
1b63dc1d25
2 changed files with 112 additions and 172 deletions
  1. +4
    -0
      README.TXT
  2. +108
    -172
      asio.c

+ 4
- 0
README.TXT View File

@@ -120,6 +120,10 @@ todo:


4. CHANGE LOG 4. CHANGE LOG
------------- -------------
0.8.1.0:
05-OCT-2010: Code from Win32 callback thread moved to JACK process callback, except for bufferSwitch() call.
05-OCT-2010: Switch from int to float for samples.

0.8: 0.8:
08-AUG-2010: Forward port JackWASIO changes... needs testing hard. (PLJ) 08-AUG-2010: Forward port JackWASIO changes... needs testing hard. (PLJ)




+ 108
- 172
asio.c View File

@@ -36,11 +36,11 @@ static const char* DEFAULT_OUTPORT = "Output";
#endif #endif
#include "port.h" #include "port.h"


//#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <sys/time.h> #include <sys/time.h>
#include <stdlib.h> #include <stdlib.h>
#include <memory.h>


#include <wine/windows/windef.h> #include <wine/windows/windef.h>
#include <wine/windows/winbase.h> #include <wine/windows/winbase.h>
@@ -157,7 +157,7 @@ enum


typedef struct _Channel { typedef struct _Channel {
ASIOBool active; ASIOBool active;
int *buffer;
char* buffer;
jack_ringbuffer_t *ring; jack_ringbuffer_t *ring;
const char *port_name; const char *port_name;
jack_port_t *port; jack_port_t *port;
@@ -184,28 +184,17 @@ struct IWineASIOImpl
ASIOBufferInfo *bufferInfos; ASIOBufferInfo *bufferInfos;
ASIOCallbacks *callbacks; ASIOCallbacks *callbacks;
char error_message[256]; char error_message[256];
// long in_map[MAX_INPUTS];
// long out_map[MAX_OUTPUTS];
// void *input_buffers[MAX_INPUTS][2];
// void *output_buffers[MAX_OUTPUTS][2];
long active_inputs; long active_inputs;
long active_outputs; long active_outputs;
BOOL time_info_mode; BOOL time_info_mode;
BOOL tc_read; BOOL tc_read;
long state; long state;
// unsigned int sample_size;
// int sample_type;


/* JACK stuff */ /* JACK stuff */
char *client_name; char *client_name;
unsigned int num_inputs; unsigned int num_inputs;
// jack_port_t *input_port[MAX_INPUTS];
// const char *input_names[MAX_INPUTS];
unsigned int num_outputs; unsigned int num_outputs;
// jack_port_t *output_port[MAX_OUTPUTS];
// const char *output_names[MAX_INPUTS];
jack_client_t *client; jack_client_t *client;
long client_state;
long toggle; long toggle;
SCHED_PARAM jack_client_priority; SCHED_PARAM jack_client_priority;


@@ -220,8 +209,6 @@ struct IWineASIOImpl


Channel *input; Channel *input;
Channel *output; Channel *output;

float *tempbuf;
}; };


typedef struct IWineASIOImpl IWineASIOImpl; typedef struct IWineASIOImpl IWineASIOImpl;
@@ -245,15 +232,20 @@ static ULONG WINAPI IWineASIOImpl_Release(LPWINEASIO iface)
TRACE("(%p) ref was %d\n", This, ref + 1); TRACE("(%p) ref was %d\n", This, ref + 1);


if (!ref) { if (!ref) {
TRACE("Entering state = Exit\n");
This->state = Exit; This->state = Exit;


jack_client_close(This->client); jack_client_close(This->client);
TRACE("JACK client closed\n"); TRACE("JACK client closed\n");


TRACE("Setting Win32 thread termination to TRUE\n");
This->terminate = TRUE; This->terminate = TRUE;
sem_post(&This->semaphore1); sem_post(&This->semaphore1);


WaitForSingleObject(This->stop_event, INFINITE); WaitForSingleObject(This->stop_event, INFINITE);
TRACE("Win32 thread terminated\n");
CloseHandle(This->stop_event);
This->stop_event = INVALID_HANDLE_VALUE;


sem_destroy(&This->semaphore1); sem_destroy(&This->semaphore1);
sem_destroy(&This->semaphore2); sem_destroy(&This->semaphore2);
@@ -393,31 +385,31 @@ static int GetEXEName(DWORD dwProcessID, char* name) {
unsigned int i; unsigned int i;
char szEXEName[MAX_PATH]; char szEXEName[MAX_PATH];
//Enumerate all processes
/* Enumerate all processes */
if(!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) return FALSE; if(!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) return FALSE;


// Calculate how many process identifiers were returned.
Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD); cProcesses = cbNeeded / sizeof(DWORD);


//Loop through all process to find the one that matches
//the one we are looking for
/* Loop through all process to find the one that matches
the one we are looking for */


for (i = 0; i < cProcesses; i++) { for (i = 0; i < cProcesses; i++) {
if (aProcesses [i] == dwProcessID) { if (aProcesses [i] == dwProcessID) {
// Get a handle to the process
/* Get a handle to the process */
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ, FALSE, dwProcessID); PROCESS_VM_READ, FALSE, dwProcessID);
// Get the process name
/* Get the process name */
if (NULL != hProcess) { if (NULL != hProcess) {
HMODULE hMod; HMODULE hMod;
DWORD cbNeeded; DWORD cbNeeded;
if(EnumProcessModules(hProcess, &hMod,sizeof(hMod), &cbNeeded)) { if(EnumProcessModules(hProcess, &hMod,sizeof(hMod), &cbNeeded)) {
int len; int len;
//Get the name of the exe file
/* Get the name of the exe file */
GetModuleBaseNameA(hProcess,hMod,szEXEName,sizeof(szEXEName)/sizeof(char)); GetModuleBaseNameA(hProcess,hMod,szEXEName,sizeof(szEXEName)/sizeof(char));
len = strlen((char*)szEXEName) - 3; // remove ".exe"
len = strlen((char*)szEXEName) - 3; /* remove ".exe" */
lstrcpynA(name,(char*)szEXEName,len); lstrcpynA(name,(char*)szEXEName,len);
name[len] = '\0'; name[len] = '\0';
return TRUE; return TRUE;
@@ -520,7 +512,7 @@ static void set_clientname(IWineASIOImpl *This)
asprintf(&This->client_name, "%s_%s", DEFAULT_PREFIX, line); asprintf(&This->client_name, "%s_%s", DEFAULT_PREFIX, line);
#else #else
char proc_name[256]; char proc_name[256];
memset(&proc_name[0],0x0,sizeof(char)*256); //size of char is redundant.. but dunno i like to write it:)
memset(&proc_name[0],0x0,sizeof(char)*256); /* size of char is redundant.. but dunno i like to write it:) */


if(!GetEXEName(GetCurrentProcessId(),&proc_name[0])) { if(!GetEXEName(GetCurrentProcessId(),&proc_name[0])) {
strcpy(&proc_name[0],"Wine_ASIO"); strcpy(&proc_name[0],"Wine_ASIO");
@@ -561,7 +553,6 @@ WRAP_THISCALL( ASIOBool __stdcall, IWineASIOImpl_init, (LPWINEASIO iface, void *
This->input_latency = This->block_frames; This->input_latency = This->block_frames;
This->output_latency = This->block_frames; This->output_latency = This->block_frames;
This->miliseconds = (long)((double)(This->block_frames * 1000) / This->sample_rate); This->miliseconds = (long)((double)(This->block_frames * 1000) / This->sample_rate);
This->callbacks = NULL;
This->sample_position = 0; This->sample_position = 0;
strcpy(This->error_message, "No Error"); strcpy(This->error_message, "No Error");
This->num_inputs = 0; This->num_inputs = 0;
@@ -569,23 +560,15 @@ WRAP_THISCALL( ASIOBool __stdcall, IWineASIOImpl_init, (LPWINEASIO iface, void *
This->active_inputs = 0; This->active_inputs = 0;
This->active_outputs = 0; This->active_outputs = 0;
This->toggle = 0; This->toggle = 0;
This->client_state = Init;
This->callbacks = NULL;
This->time_info_mode = FALSE; This->time_info_mode = FALSE;
This->tc_read = FALSE; This->tc_read = FALSE;
This->terminate = FALSE;
This->state = Init; 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);


set_clientname(This); set_clientname(This);


#ifndef JackWASIO #ifndef JackWASIO
// uses This->client_name
/* uses This->client_name */
read_config(This); read_config(This);
#else #else
ReadJPPrefs(); ReadJPPrefs();
@@ -603,13 +586,20 @@ WRAP_THISCALL( ASIOBool __stdcall, IWineASIOImpl_init, (LPWINEASIO iface, void *
if (status & JackServerStarted) if (status & JackServerStarted)
TRACE("(%p) JACK server started\n", This); TRACE("(%p) JACK server started\n", This);


/* get maximum reccomended client priority from JACK */
/* Thread initialisation */
sem_init(&This->semaphore1, 0, 0);
sem_init(&This->semaphore2, 0, 0);


This->jack_client_priority.sched_priority = jack_client_real_time_priority (This->client);
This->terminate = FALSE;
This->jack_client_priority.sched_priority = -1;
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); This->thread = CreateThread(NULL, 0, win32_callback, (LPVOID)This, 0, &This->thread_id);
if (This->thread) if (This->thread)
{ {
TRACE("Wait for Win32 thread to start\n", This);
WaitForSingleObject(This->start_event, INFINITE); WaitForSingleObject(This->start_event, INFINITE);
TRACE("Win32 thread started\n", This);
CloseHandle(This->start_event); CloseHandle(This->start_event);
This->start_event = INVALID_HANDLE_VALUE; This->start_event = INVALID_HANDLE_VALUE;
} }
@@ -702,8 +692,6 @@ WRAP_THISCALL( ASIOBool __stdcall, IWineASIOImpl_init, (LPWINEASIO iface, void *
} }
} }


This->tempbuf = HeapAlloc(GetProcessHeap(), 0, This->block_frames * sizeof(float));

return ASIOTrue; return ASIOTrue;
} }


@@ -716,7 +704,7 @@ WRAP_THISCALL( void __stdcall, IWineASIOImpl_getDriverName, (LPWINEASIO iface, c
WRAP_THISCALL( long __stdcall, IWineASIOImpl_getDriverVersion, (LPWINEASIO iface)) WRAP_THISCALL( long __stdcall, IWineASIOImpl_getDriverVersion, (LPWINEASIO iface))
{ {
TRACE("(%p)\n", iface); TRACE("(%p)\n", iface);
return 80; // 0.8 (patch level 0)
return 81; /* 0.8.1.x */
} }


WRAP_THISCALL( void __stdcall, IWineASIOImpl_getErrorMessage, (LPWINEASIO iface, char *string)) WRAP_THISCALL( void __stdcall, IWineASIOImpl_getErrorMessage, (LPWINEASIO iface, char *string))
@@ -752,7 +740,13 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_start, (LPWINEASIO iface))
return ASE_NotPresent; return ASE_NotPresent;
} }


// get list of port names
/* get maximum reccomended client priority from JACK */
This->jack_client_priority.sched_priority = jack_client_real_time_priority(This->client);

/* Win32 thread should now be able to query jack for priority */
sem_post(&This->semaphore1);

/* get list of port names */
ports = jack_get_ports(This->client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); ports = jack_get_ports(This->client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
for(numports = 0; ports && ports[numports]; numports++); for(numports = 0; ports && ports[numports]; numports++);
TRACE("(%p) inputs desired: %d; JACK outputs: %d\n", This, This->num_inputs, numports); TRACE("(%p) inputs desired: %d; JACK outputs: %d\n", This, This->num_inputs, numports);
@@ -763,7 +757,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_start, (LPWINEASIO iface))
continue; continue;


if (autoconnect) { if (autoconnect) {
// Get the desired JACK output (source) name, if there is one, for this ASIO input
/* Get the desired JACK output (source) name, if there is one, for this ASIO input */
envi = get_targetname(This, ENVVAR_INMAP, i); envi = get_targetname(This, ENVVAR_INMAP, i);
envi = envi ? envi : j < numports ? ports[j++] : NULL; envi = envi ? envi : j < numports ? ports[j++] : NULL;
if (!envi) continue; if (!envi) continue;
@@ -784,7 +778,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_start, (LPWINEASIO iface))
if (ports) if (ports)
free(ports); free(ports);


// get list of port names
/* get list of port names */
ports = jack_get_ports(This->client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); ports = jack_get_ports(This->client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
for(numports = 0; ports && ports[numports]; numports++); for(numports = 0; ports && ports[numports]; numports++);
TRACE("(%p) JACK inputs: %d; outputs desired: %d\n", This, numports, This->num_outputs); TRACE("(%p) JACK inputs: %d; outputs desired: %d\n", This, numports, This->num_outputs);
@@ -795,7 +789,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_start, (LPWINEASIO iface))
continue; continue;


if (autoconnect) { if (autoconnect) {
// Get the desired JACK input (target) name, if there is one, for this ASIO output
/* Get the desired JACK input (target) name, if there is one, for this ASIO output */
envi = get_targetname(This, ENVVAR_OUTMAP, i); envi = get_targetname(This, ENVVAR_OUTMAP, i);
envi = envi ? envi : j < numports ? ports[j++] : NULL; envi = envi ? envi : j < numports ? ports[j++] : NULL;


@@ -815,8 +809,8 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_start, (LPWINEASIO iface))
if (ports) if (ports)
free(ports); free(ports);


TRACE("Entering state = Run\n");
This->state = Run; This->state = Run;
TRACE("started\n");


return ASE_OK; return ASE_OK;
} }
@@ -962,7 +956,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_setClockSource, (LPWINEASIO if
WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_getSamplePosition, (LPWINEASIO iface, ASIOSamples *sPos, ASIOTimeStamp *tStamp)) WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_getSamplePosition, (LPWINEASIO iface, ASIOSamples *sPos, ASIOTimeStamp *tStamp))
{ {
IWineASIOImpl * This = (IWineASIOImpl*)iface; IWineASIOImpl * This = (IWineASIOImpl*)iface;
// TRACE("(%p, %p, %p)\n", iface, sPos, tStamp);
TRACE("(%p, %p, %p)\n", iface, sPos, tStamp);


tStamp->lo = This->system_time.lo; tStamp->lo = This->system_time.lo;
tStamp->hi = This->system_time.hi; tStamp->hi = This->system_time.hi;
@@ -984,17 +978,12 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_getSamplePosition, (LPWINEASIO
WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_getChannelInfo, (LPWINEASIO iface, ASIOChannelInfo *info)) WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_getChannelInfo, (LPWINEASIO iface, ASIOChannelInfo *info))
{ {
IWineASIOImpl * This = (IWineASIOImpl*)iface; IWineASIOImpl * This = (IWineASIOImpl*)iface;
// int i;
// const char * name;
TRACE("(%p, %p)\n", iface, info); TRACE("(%p, %p)\n", iface, info);


if (info->channel < 0 || (info->isInput ? info->channel >= This->num_inputs : info->channel >= This->num_outputs)) if (info->channel < 0 || (info->isInput ? info->channel >= This->num_inputs : info->channel >= This->num_outputs))
return ASE_InvalidParameter; return ASE_InvalidParameter;


// TRACE("info->channel = %ld\n", info->channel);
// TRACE("info->isInput = %ld\n", info->isInput);

info->type = ASIOSTInt32LSB; // info->type = This->sample_type;
info->type = ASIOSTFloat32LSB; /* info->type = This->sample_type; */
info->channelGroup = 0; info->channelGroup = 0;


if (info->isInput) if (info->isInput)
@@ -1016,11 +1005,6 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_getChannelInfo, (LPWINEASIO if
#endif #endif
} }


// TRACE("info->isActive = %ld\n", info->isActive);
// TRACE("info->channelGroup = %ld\n", info->channelGroup);
// TRACE("info->type = %ld\n", info->type);
// TRACE("info->name = %s\n", info->name);

return ASE_OK; return ASE_OK;
} }


@@ -1065,7 +1049,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_createBuffers, (LPWINEASIO ifa
int i, j; int i, j;
TRACE("(%p, %p, %ld, %ld, %p)\n", iface, bufferInfos, numChannels, bufferSize, callbacks); TRACE("(%p, %p, %ld, %ld, %p)\n", iface, bufferInfos, numChannels, bufferSize, callbacks);


// Just to be on the safe side:
/* Just to be on the safe side: */
This->active_inputs = 0; This->active_inputs = 0;
for(i = 0; i < This->num_inputs; i++) This->input[i].active = ASIOFalse; for(i = 0; i < This->num_inputs; i++) This->input[i].active = ASIOFalse;
This->active_outputs = 0; This->active_outputs = 0;
@@ -1090,8 +1074,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_createBuffers, (LPWINEASIO ifa
goto ERROR_PARAM; goto ERROR_PARAM;
} }


// ASIOSTInt32LSB support only
This->input[This->active_inputs].buffer = HeapAlloc(GetProcessHeap(), 0, 2 * This->block_frames * sizeof(int));
This->input[This->active_inputs].buffer = HeapAlloc(GetProcessHeap(), 0, 2 * This->block_frames * sizeof(float)); /* ASIOSTFloat32LSB support only */
if (This->input[This->active_inputs].buffer) if (This->input[This->active_inputs].buffer)
{ {
info->buffers[0] = &This->input[This->active_inputs].buffer[0]; info->buffers[0] = &This->input[This->active_inputs].buffer[0];
@@ -1124,8 +1107,7 @@ WRAP_THISCALL( ASIOError __stdcall, IWineASIOImpl_createBuffers, (LPWINEASIO ifa
goto ERROR_PARAM; goto ERROR_PARAM;
} }


// ASIOSTInt32LSB support only
This->output[This->active_outputs].buffer = HeapAlloc(GetProcessHeap(), 0, 2 * This->block_frames * sizeof(int));
This->output[This->active_outputs].buffer = HeapAlloc(GetProcessHeap(), 0, 2 * This->block_frames * sizeof(float)); /* ASIOSTFloat32LSB support only */
if (This->output[This->active_outputs].buffer) if (This->output[This->active_outputs].buffer)
{ {
info->buffers[0] = &This->output[This->active_outputs].buffer[0]; info->buffers[0] = &This->output[This->active_outputs].buffer[0];
@@ -1287,66 +1269,6 @@ static void getNanoSeconds(ASIOTimeStamp* ts)
ts->lo = (unsigned long)(nanoSeconds - (ts->hi * twoRaisedTo32)); ts->lo = (unsigned long)(nanoSeconds - (ts->hi * twoRaisedTo32));
} }


static int jack_process(jack_nframes_t nframes, void * arg)
{
IWineASIOImpl * This = (IWineASIOImpl*)arg;
int i;
char *in, *out;
// jack_transport_state_t ts;
// jack_position_t transport;

// ASIOSTInt32LSB support only
//int *buffer;

if (This->state != Run)
return 0;

// ts = jack_transport_query(This->client, &transport);
// if (ts == JackTransportRolling)
// {
if (This->client_state == Init)
This->client_state = Run;

This->sample_position += nframes; //= transport.frame;

/* get the input data from JACK and copy it to the ASIO buffers */
for (i = 0; i < This->active_inputs; i++)
{
if (This->input[i].active == ASIOTrue) {

//buffer = &This->input[i].buffer[This->block_frames * This->toggle];
in = jack_port_get_buffer(This->input[i].port, nframes);

jack_ringbuffer_write(This->input[i].ring, in, nframes * sizeof(float));
}
}

/* wake up the WIN32 thread so it can do its callback */
sem_post(&This->semaphore1);

/* wait for the WIN32 thread to complete before continuing */
sem_wait(&This->semaphore2);

/* copy the ASIO data to JACK */
for (i = 0; i < This->num_outputs; i++)
{
if (This->output[i].active == ASIOTrue) {

//buffer = &This->output[i].buffer[This->block_frames * (This->toggle)];
out = jack_port_get_buffer(This->output[i].port, nframes);

jack_ringbuffer_read(This->output[i].ring, out, nframes * sizeof(float));
}
}

// This->toggle = This->toggle ? 0 : 1;

// This->callbacks->bufferSwitch(This->toggle, ASIOTrue);
// }

return 0;
}

/* /*
* The ASIO callback can make WIN32 calls which require a WIN32 thread. * The ASIO callback can make WIN32 calls which require a WIN32 thread.
* Do the callback in this thread and then switch back to the Jack callback thread. * Do the callback in this thread and then switch back to the Jack callback thread.
@@ -1354,10 +1276,13 @@ static int jack_process(jack_nframes_t nframes, void * arg)
static DWORD CALLBACK win32_callback(LPVOID arg) static DWORD CALLBACK win32_callback(LPVOID arg)
{ {
IWineASIOImpl * This = (IWineASIOImpl*)arg; IWineASIOImpl * This = (IWineASIOImpl*)arg;
TRACE("(%p) Win32 thread starting\n", arg);


//TRACE("(%p)\n", arg);
TRACE ("win32 callback thread started\n");
/* let IWineASIO_Init know we are alive */
SetEvent(This->start_event);


/* wait for JACK client to be connected and set sched_priority */
sem_wait(&This->semaphore1);
/* set the priority of the win32 callback thread as suggested by JACK */ /* set the priority of the win32 callback thread as suggested by JACK */
#ifndef JackWASIO #ifndef JackWASIO
if (This->jack_client_priority.sched_priority != -1) /* skip if not running realtime */ if (This->jack_client_priority.sched_priority != -1) /* skip if not running realtime */
@@ -1373,72 +1298,83 @@ static DWORD CALLBACK win32_callback(LPVOID arg)
setThreadToPriority(pthread_self(),96,TRUE,10000000); setThreadToPriority(pthread_self(),96,TRUE,10000000);
#endif #endif


/* let IWineASIO_Init know we are alive */
SetEvent(This->start_event);
TRACE("Win32 thread running...\n");

while (1) while (1)
{ {
/* wait to be woken up by the JACK callback thread */ /* wait to be woken up by the JACK callback thread */
sem_wait(&This->semaphore1); sem_wait(&This->semaphore1);


/* check for termination */
if (This->terminate) if (This->terminate)
{ {
TRACE("Win32 thread terminating\n");
SetEvent(This->stop_event); SetEvent(This->stop_event);
TRACE("Win32 thread terminated\n");
return 0; return 0;
} }
getNanoSeconds(&This->system_time);


/* make sure we are in the run state */
if (This->state == Run)
{
int i;
if (This->state != Run)
return 0;


if (This->time_info_mode)
{
getNanoSeconds(&This->system_time);
This->sample_position += This->block_frames; This->sample_position += This->block_frames;


for (i = 0; i < This->active_inputs; i++) {
if (This->input[i].active == ASIOTrue) {
int j, *buffer = &This->input[i].buffer[This->block_frames * This->toggle];

jack_ringbuffer_read(This->input[i].ring, (char*)This->tempbuf, This->block_frames * sizeof(float));

for (j = 0; j < This->block_frames; j++) buffer[j] = (int)(This->tempbuf[j] * (float)(0x7fffffff));
}
}

if (This->time_info_mode)
__wrapped_IWineASIOImpl_getSamplePosition((LPWINEASIO)This,
&This->asio_time.timeInfo.samplePosition, &This->asio_time.timeInfo.systemTime);
if (This->tc_read)
{ {
__wrapped_IWineASIOImpl_getSamplePosition((LPWINEASIO)This,
&This->asio_time.timeInfo.samplePosition, &This->asio_time.timeInfo.systemTime);
if (This->tc_read)
{
This->asio_time.timeCode.timeCodeSamples.lo = This->asio_time.timeInfo.samplePosition.lo;
This->asio_time.timeCode.timeCodeSamples.hi = 0;
}
This->callbacks->bufferSwitchTimeInfo(&This->asio_time, This->toggle, ASIOTrue);
This->asio_time.timeInfo.flags &= ~(kSampleRateChanged | kClockSourceChanged);
}
else
This->callbacks->bufferSwitch(This->toggle, ASIOTrue);

/* let the JACK thread know we are done */
sem_post(&This->semaphore2);

for (i = 0; i < This->num_outputs; i++) {
if (This->output[i].active == ASIOTrue) {
int j, *buffer = &This->output[i].buffer[This->block_frames * This->toggle];
for (j = 0; j < This->block_frames; j++) This->tempbuf[j] = ((float)(buffer[j]) / (float)(0x7fffffff));
jack_ringbuffer_write(This->output[i].ring, (char*)This->tempbuf, This->block_frames * sizeof(float));
}
This->asio_time.timeCode.timeCodeSamples.lo = This->asio_time.timeInfo.samplePosition.lo;
This->asio_time.timeCode.timeCodeSamples.hi = 0;
} }
This->toggle = This->toggle ? 0 : 1;
This->callbacks->bufferSwitchTimeInfo(&This->asio_time, This->toggle, ASIOTrue);
This->asio_time.timeInfo.flags &= ~(kSampleRateChanged | kClockSourceChanged);
} }
else
This->callbacks->bufferSwitch(This->toggle, ASIOTrue);

/* let the JACK thread know we are done */
sem_post(&This->semaphore2);
} }


return 0; return 0;
} }

static int jack_process(jack_nframes_t nframes, void * arg)
{
IWineASIOImpl * This = (IWineASIOImpl*)arg;
int i;
/*
jack_position_t transport;
jack_transport_state ts = jack_transport_query(This->client, &transport);
if (ts == JackTransportRolling)
This->sample_position = transport.frame;
else
*/
This->sample_position += nframes;

/* copy the JACK date to ASIO */
for (i = 0; i < This->active_inputs; i++)
if (This->input[i].active == ASIOTrue)
memcpy(
&This->input[i].buffer[This->block_frames * This->toggle], /* dest: ASIO */
jack_port_get_buffer(This->input[i].port, nframes), /* src: JACK */
This->block_frames * sizeof(float));

/* wake up the WIN32 thread so it can do its callback */
sem_post(&This->semaphore1);

/* wait for the WIN32 thread to complete before continuing */
sem_wait(&This->semaphore2);

/* copy the ASIO data to JACK */
for (i = 0; i < This->num_outputs; i++)
if (This->output[i].active == ASIOTrue)
memcpy(
jack_port_get_buffer(This->output[i].port, nframes), /* dest: JACK */
&This->output[i].buffer[This->block_frames * This->toggle], /* src: ASIO */
This->block_frames * sizeof(float)
);

This->toggle = This->toggle ? 0 : 1;

return 0;
}

Loading…
Cancel
Save