C callbacks getting a value of 0! Bug in D?
    Johnson Jones via Digitalmars-d-learn 
    digitalmars-d-learn at puremagic.com
       
    Sun Aug 27 18:57:27 PDT 2017
    
    
  
Trying to set a callback for portaudio and it's seeing zero for 
the value passed.
Pa_OpenStream(&stream, input, output, sampleRate, cast(ulong)0, 
cast(PaStreamFlags)(PaStreamFlags.NoFlag + 
0*PaStreamFlags.PrimeOutputBuffersUsingStreamCallback),
									 cast(PaStreamCallback)(a,b,c,d,e,f){
		callbackCalled = true;
										 return 0;
									 }, null);
I am using a debug build of portaudio that prints out all the 
parameters before anything else, so it's not an issue with 
portaudio.
I've tried passing a normal function:
__gshared int sawtooth(const(void)* inputBuffer, void* 
outputBuffer, ulong framesPerBuffer, 
const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags 
statusFlags, void *userData)
{ return 0; }
and passing it as &sawtooth.
with the same issue.
I've tried changing the calling convention and using __gshared 
but the value is always 0. It seems other values are 0 too and 
can't seem to get any value in to the callback(Even a random one).
The output essentially always looks like this:
Opening Stream!
Pa_OpenStream called:
         PaStream** stream: 0x00823EA0
         PaStreamParameters *inputParameters: NULL
         PaStreamParameters *outputParameters: 0x02C6C1C0
         PaDeviceIndex outputParameters->device: 3
         int outputParameters->channelCount: 4
         PaSampleFormat outputParameters->sampleFormat: 1
         PaTime outputParameters->suggestedLatency: 0.135000
         void *outputParameters->hostApiSpecificStreamInfo: 
0x00000000
         double sampleRate: 44100
         unsigned long framesPerBuffer: 256
         PaStreamFlags streamFlags: 0x0
         PaStreamCallback *streamCallback: 0x00000000
         void *userData: 0x00000000
Pa_GetSampleSize called:
         PaSampleFormat format: 8
Pa_GetSampleSize returned:
         int: 2
Pa_GetSampleSize called:
         PaSampleFormat format: 8
Pa_GetSampleSize returned:
         int: 2
Pa_GetSampleSize called:
         PaSampleFormat format: 1
Pa_GetSampleSize returned:
         int: 4
Pa_GetSampleSize called:
         PaSampleFormat format: 8
Pa_GetSampleSize returned:
         int: 2
Pa_GetSampleSize called:
         PaSampleFormat format: 8
Pa_GetSampleSize returned:
         int: 2
Pa_OpenStream returned:
         *(PaStream** stream): 0x03BEAD50
         PaError: 0 ( Success )
everything seems correct except:
         PaStreamCallback *streamCallback: 0x00000000
         void *userData: 0x00000000
You can find the full code at
https://forum.dlang.org/thread/lkbswgpsgxynhfyzwfqz@forum.dlang.org			
This is either a bug in D, an issue with calling conventions, or 
how one passes the data.
The original portaudio open stream function, so you can see that 
it simply prints it's arguments:
PaError Pa_OpenStream( PaStream** stream,
                        const PaStreamParameters *inputParameters,
                        const PaStreamParameters *outputParameters,
                        double sampleRate,
                        unsigned long framesPerBuffer,
                        PaStreamFlags streamFlags,
                        PaStreamCallback *streamCallback,
                        void *userData )
{
     PaError result;
     PaUtilHostApiRepresentation *hostApi = 0;
     PaDeviceIndex hostApiInputDevice = paNoDevice, 
hostApiOutputDevice = paNoDevice;
     PaStreamParameters hostApiInputParameters, 
hostApiOutputParameters;
     PaStreamParameters *hostApiInputParametersPtr, 
*hostApiOutputParametersPtr;
#ifdef PA_LOG_API_CALLS
     PA_LOGAPI_ENTER_PARAMS( "Pa_OpenStream" );
     PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream ));
     if( inputParameters == NULL ){
         PA_LOGAPI(("\tPaStreamParameters *inputParameters: 
NULL\n" ));
     }else{
         PA_LOGAPI(("\tPaStreamParameters *inputParameters: 
0x%p\n", inputParameters ));
         PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: 
%d\n", inputParameters->device ));
         PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", 
inputParameters->channelCount ));
         PA_LOGAPI(("\tPaSampleFormat 
inputParameters->sampleFormat: %d\n", 
inputParameters->sampleFormat ));
         PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: 
%f\n", inputParameters->suggestedLatency ));
         PA_LOGAPI(("\tvoid 
*inputParameters->hostApiSpecificStreamInfo: 0x%p\n", 
inputParameters->hostApiSpecificStreamInfo ));
     }
     if( outputParameters == NULL ){
         PA_LOGAPI(("\tPaStreamParameters *outputParameters: 
NULL\n" ));
     }else{
         PA_LOGAPI(("\tPaStreamParameters *outputParameters: 
0x%p\n", outputParameters ));
         PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: 
%d\n", outputParameters->device ));
         PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", 
outputParameters->channelCount ));
         PA_LOGAPI(("\tPaSampleFormat 
outputParameters->sampleFormat: %d\n", 
outputParameters->sampleFormat ));
         PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: 
%f\n", outputParameters->suggestedLatency ));
         PA_LOGAPI(("\tvoid 
*outputParameters->hostApiSpecificStreamInfo: 0x%p\n", 
outputParameters->hostApiSpecificStreamInfo ));
     }
     PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
     PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", 
framesPerBuffer ));
     PA_LOGAPI(("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags 
));
     PA_LOGAPI(("\tPaStreamCallback *streamCallback: 0x%p\n", 
streamCallback ));
     PA_LOGAPI(("\tvoid *userData: 0x%p\n", userData ));
#endif
and this is how I define it in the code(which you can see if you 
follow the link):
PaError function(PaStream** stream, const PaStreamParameters 
*inputParameters, const PaStreamParameters *outputParameters, 
double sampleRate, ulong framesPerBuffer, PaStreamFlags 
streamFlags, PaStreamCallback streamCallback, void *userData) 
Pa_OpenStream;
I can play audio if I do a hard write, but obviously that is 
generally useless.
This seems like it might be a bug in D in that the last 
parameters are invalid. user_data, which is passing a simple 
pointer is also 0, when it isn't.
Even trying something like
PaError function(PaStream** stream, const PaStreamParameters 
*inputParameters, const PaStreamParameters *outputParameters, 
double sampleRate, ulong framesPerBuffer, PaStreamFlags 
streamFlags, size_t streamCallback, size_t userData) 
Pa_OpenStream;
and passing numbers still shows zero values!
Any ideas?
    
    
More information about the Digitalmars-d-learn
mailing list