-
Notifications
You must be signed in to change notification settings - Fork 388
Add support for ASIO messages #519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c81352a
6c36a1e
b55b096
bd6c026
c8fcac9
d128d1e
24dda01
e0e5606
b644781
ae1d6f0
f4e6219
fa1d138
0308b1e
49c4af0
d0bb322
69450fa
0b3301c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1629,6 +1629,9 @@ typedef struct PaAsioStream | |
| PaStreamCallbackFlags callbackFlags; | ||
|
|
||
| PaAsioStreamBlockingState *blockingState; /**< Blocking i/o data struct, or NULL when using callback interface. */ | ||
|
|
||
| /* Message callbacks copied from PaAsioStreamInfo */ | ||
| PaAsio_MessageCallback *messageCallback[2]; | ||
| } | ||
| PaAsioStream; | ||
|
|
||
|
|
@@ -1871,10 +1874,28 @@ static PaError ValidateAsioSpecificStreamInfo( | |
| { | ||
| if( streamInfo ) | ||
| { | ||
| if( streamInfo->size != sizeof( PaAsioStreamInfo ) | ||
| || streamInfo->version != 1 ) | ||
| switch( streamInfo->version ) | ||
| { | ||
| case 0: | ||
| /* NOTE: Struct version 0 is invalid, possibly indicative of uninitialized data. */ | ||
| return paIncompatibleHostApiSpecificStreamInfo; | ||
|
|
||
| case 1: | ||
| /* NOTE: V1 structure's size is smaller by one pointer. */ | ||
| if( streamInfo->size < sizeof( PaAsioStreamInfo ) - sizeof(PaAsio_MessageCallback*) ) | ||
|
philburk marked this conversation as resolved.
RossBencina marked this conversation as resolved.
|
||
| return paIncompatibleHostApiSpecificStreamInfo; | ||
| break; | ||
|
|
||
| case 2: | ||
| if( streamInfo->size != sizeof( PaAsioStreamInfo ) ) | ||
| return paIncompatibleHostApiSpecificStreamInfo; | ||
| break; | ||
|
|
||
| default: | ||
| /* Newer versions of the struct must not be smaller. */ | ||
| if( streamInfo->size < sizeof( PaAsioStreamInfo ) ) | ||
| return paIncompatibleHostApiSpecificStreamInfo; | ||
| break; | ||
| } | ||
|
|
||
| if( streamInfo->flags & paAsioUseChannelSelectors ) | ||
|
EvanBalster marked this conversation as resolved.
|
||
|
|
@@ -1889,6 +1910,12 @@ static PaError ValidateAsioSpecificStreamInfo( | |
| return paInvalidChannelCount; | ||
| } | ||
| } | ||
|
|
||
| if( streamInfo->flags & paAsioUseMessageCallback ) | ||
| { | ||
| if( streamInfo->version < 2 || !streamInfo->messageCallback ) | ||
| return paIncompatibleHostApiSpecificStreamInfo; | ||
| } | ||
| } | ||
|
|
||
| return paNoError; | ||
|
|
@@ -2002,7 +2029,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, | |
| PaError result = paNoError; | ||
| PaAsioHostApiRepresentation *asioHostApi = (PaAsioHostApiRepresentation*)hostApi; | ||
| PaAsioStream *stream = 0; | ||
| PaAsioStreamInfo *inputStreamInfo, *outputStreamInfo; | ||
| PaAsioStreamInfo *inputStreamInfo = NULL, *outputStreamInfo = NULL; | ||
| unsigned long framesPerHostBuffer; | ||
| int inputChannelCount, outputChannelCount; | ||
| PaSampleFormat inputSampleFormat, outputSampleFormat; | ||
|
|
@@ -2742,6 +2769,21 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, | |
| stream->isStopped = 1; | ||
| stream->isActive = 0; | ||
|
|
||
| stream->messageCallback[0] = NULL; | ||
| stream->messageCallback[1] = NULL; | ||
| if( usingBlockingIo ) | ||
| { | ||
| /* Disable message callback due to policy of overwriting userData above. */ | ||
| } | ||
| else | ||
| { | ||
| /* Message callback may be defined in versions >= 2 of ASIO streamInfo. */ | ||
| if( inputStreamInfo && ( inputStreamInfo->flags & paAsioUseMessageCallback) ) | ||
| stream->messageCallback[0] = inputStreamInfo->messageCallback; | ||
| if( outputStreamInfo && (outputStreamInfo->flags & paAsioUseMessageCallback) ) | ||
| stream->messageCallback[1] = outputStreamInfo->messageCallback; | ||
| } | ||
|
|
||
| asioHostApi->openAsioDeviceIndex = asioDeviceIndex; | ||
|
|
||
| theAsioStream = stream; | ||
|
|
@@ -3176,6 +3218,26 @@ previousTime = paTimeInfo.currentTime; | |
| } | ||
|
|
||
|
|
||
| static long fireMessageCallback( PaAsioStream *asioStream, long messageType, long value, void* message, double* opt ) | ||
| { | ||
| void *userData = asioStream->streamRepresentation.userData; | ||
|
|
||
| long ret = 0; | ||
|
|
||
| /* Fire callbacks and determine whether one and/or the other handles the message. */ | ||
| if( asioStream->messageCallback[0] ) | ||
| { | ||
| if( (*asioStream->messageCallback[0])( messageType, value, message, opt, userData ) ) ret = 1; | ||
| } | ||
| if( asioStream->messageCallback[1] ) | ||
| { | ||
| if( (*asioStream->messageCallback[1])( messageType, value, message, opt, userData ) ) ret = 1; | ||
| } | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
|
|
||
| static void sampleRateChanged(ASIOSampleRate sRate) | ||
| { | ||
| // TAKEN FROM THE ASIO SDK | ||
|
|
@@ -3186,28 +3248,52 @@ static void sampleRateChanged(ASIOSampleRate sRate) | |
| // AES/EBU or S/PDIF digital input at the audio device. | ||
| // You might have to update time/sample related conversion routines, etc. | ||
|
|
||
| (void) sRate; /* unused parameter */ | ||
| PA_DEBUG( ("sampleRateChanged : %d \n", sRate)); | ||
| double opt = sRate; | ||
|
|
||
| PA_DEBUG( ("asioSampleRateChanged : %f hz\n", opt)); | ||
|
|
||
| if (!theAsioStream) | ||
| { | ||
| /* Some ASIO drivers will fire messages during OpenStream. We ignore them. */ | ||
| PA_DEBUG( (" ...message blocked, device not open yet.\n")); | ||
| return; | ||
| } | ||
|
|
||
| fireMessageCallback( theAsioStream, paAsioSampleRateChanged, 0, 0, &opt ); | ||
| } | ||
|
|
||
| static long asioMessages(long selector, long value, void* message, double* opt) | ||
| { | ||
| // TAKEN FROM THE ASIO SDK | ||
| // currently the parameters "value", "message" and "opt" are not used. | ||
| int doClientCallback = 0, paAsioMessageType = 0; | ||
| long ret = 0; | ||
|
|
||
| (void) message; /* unused parameters */ | ||
| (void) opt; | ||
|
|
||
| PA_DEBUG( ("asioMessages : %d , %d \n", selector, value)); | ||
|
|
||
| if (!theAsioStream) | ||
| { | ||
| /* Some ASIO drivers will fire messages during OpenStream. We ignore them. */ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like incomplete code (same in the To me, it seems that if we're going to pass through driver messages, we should pass through all of them. All it would take would be to stash the required callback data for use here even before the stream is fully created.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It has been quite a while since I visited this code. My faint recollection is that some ASIO drivers were generating spurious ResetRequest messages while opening the stream, but I'd need to look into it. |
||
| PA_DEBUG( (" ...message blocked, device not open yet.\n")); | ||
| return 0; | ||
| } | ||
|
|
||
| switch(selector) | ||
| { | ||
| case kAsioSelectorSupported: | ||
| if(value == kAsioResetRequest | ||
| || value == kAsioEngineVersion | ||
| || value == kAsioResyncRequest | ||
| || value == kAsioLatenciesChanged | ||
| || value == kAsioBufferSizeChange) | ||
| { | ||
| /* Did the client register a callback? */ | ||
| if( theAsioStream->messageCallback[0] || theAsioStream->messageCallback[1] ) | ||
| ret = 1L; | ||
| } | ||
| if(value == kAsioEngineVersion | ||
| // the following three were added for ASIO 2.0, you don't necessarily have to support them | ||
| || value == kAsioSupportsTimeInfo | ||
| || value == kAsioSupportsTimeCode | ||
|
|
@@ -3217,6 +3303,8 @@ static long asioMessages(long selector, long value, void* message, double* opt) | |
|
|
||
| case kAsioBufferSizeChange: | ||
| //printf("kAsioBufferSizeChange \n"); | ||
| paAsioMessageType = paAsioBufferSizeChange; | ||
| doClientCallback = 1; | ||
| break; | ||
|
|
||
| case kAsioResetRequest: | ||
|
|
@@ -3225,13 +3313,9 @@ static long asioMessages(long selector, long value, void* message, double* opt) | |
| // Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction | ||
| // Afterwards you initialize the driver again. | ||
|
|
||
| /*FIXME: commented the next line out | ||
|
|
||
| see: "PA/ASIO ignores some driver notifications it probably shouldn't" | ||
| http://www.portaudio.com/trac/ticket/108 | ||
| */ | ||
| //asioDriverInfo.stopped; // In this sample the processing will just stop | ||
| ret = 1L; | ||
| // Notify the application, which should then reset the stream. | ||
| paAsioMessageType = paAsioResetRequest; | ||
| doClientCallback = 1; | ||
| break; | ||
|
|
||
| case kAsioResyncRequest: | ||
|
|
@@ -3241,14 +3325,16 @@ static long asioMessages(long selector, long value, void* message, double* opt) | |
| // Windows Multimedia system, which could loose data because the Mutex was hold too long | ||
| // by another thread. | ||
| // However a driver can issue it in other situations, too. | ||
| ret = 1L; | ||
| paAsioMessageType = paAsioResyncRequest; | ||
| doClientCallback = 1; | ||
| break; | ||
|
|
||
| case kAsioLatenciesChanged: | ||
| // This will inform the host application that the drivers were latencies changed. | ||
| // Beware, it this does not mean that the buffer sizes have changed! | ||
| // You might need to update internal delay data. | ||
| ret = 1L; | ||
| paAsioMessageType = paAsioLatenciesChanged; | ||
| doClientCallback = 1; | ||
| //printf("kAsioLatenciesChanged \n"); | ||
| break; | ||
|
|
||
|
|
@@ -3274,6 +3360,10 @@ static long asioMessages(long selector, long value, void* message, double* opt) | |
| ret = 0; | ||
| break; | ||
| } | ||
|
|
||
| if( doClientCallback != 0 ) | ||
| ret = fireMessageCallback( theAsioStream, paAsioMessageType, value, message, opt ); | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.