~ubuntu-branches/ubuntu/precise/puredata/precise

« back to all changes in this revision

Viewing changes to portaudio/src/common/pa_skeleton.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Brossier
  • Date: 2009-12-22 21:29:31 UTC
  • mfrom: (1.2.6 upstream) (4.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091222212931-nhwkzapjwsmjao1l
Tags: 0.42.5-3
* debian/control:
  - add community site to homepage field
  - improve long description
  - remove Replaces and Conflicts fields
  - add Suggests on pd-csound, pd-pdp, pd-zexy, pd-aubio
* debian/rules: add per-arch configuration flags
* debian/patches/02_kfreebsd.diff:
  - also define pd_tilde_dllextent on FreeBSD
  - fix typo (really closing #414414 this time)
  - also add hurd glue
* debian/patches/04_hurd.diff:
  - add hurd glue and s_midi_dummy.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: pa_skeleton.c 1097 2006-08-26 08:27:53Z rossb $
 
3
 * Portable Audio I/O Library skeleton implementation
 
4
 * demonstrates how to use the common functions to implement support
 
5
 * for a host API
 
6
 *
 
7
 * Based on the Open Source API proposed by Ross Bencina
 
8
 * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
 
9
 *
 
10
 * Permission is hereby granted, free of charge, to any person obtaining
 
11
 * a copy of this software and associated documentation files
 
12
 * (the "Software"), to deal in the Software without restriction,
 
13
 * including without limitation the rights to use, copy, modify, merge,
 
14
 * publish, distribute, sublicense, and/or sell copies of the Software,
 
15
 * and to permit persons to whom the Software is furnished to do so,
 
16
 * subject to the following conditions:
 
17
 *
 
18
 * The above copyright notice and this permission notice shall be
 
19
 * included in all copies or substantial portions of the Software.
 
20
 *
 
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
22
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
23
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
24
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 
25
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 
26
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
27
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
28
 */
 
29
 
 
30
/*
 
31
 * The text above constitutes the entire PortAudio license; however, 
 
32
 * the PortAudio community also makes the following non-binding requests:
 
33
 *
 
34
 * Any person wishing to distribute modifications to the Software is
 
35
 * requested to send the modifications to the original developer so that
 
36
 * they can be incorporated into the canonical version. It is also 
 
37
 * requested that these non-binding requests be included along with the 
 
38
 * license above.
 
39
 */
 
40
 
 
41
/** @file
 
42
 @ingroup common_src
 
43
 
 
44
 @brief Skeleton implementation of support for a host API.
 
45
 
 
46
 @note This file is provided as a starting point for implementing support for
 
47
 a new host API. IMPLEMENT ME comments are used to indicate functionality
 
48
 which much be customised for each implementation.
 
49
*/
 
50
 
 
51
 
 
52
#include <string.h> /* strlen() */
 
53
 
 
54
#include "pa_util.h"
 
55
#include "pa_allocation.h"
 
56
#include "pa_hostapi.h"
 
57
#include "pa_stream.h"
 
58
#include "pa_cpuload.h"
 
59
#include "pa_process.h"
 
60
 
 
61
 
 
62
/* prototypes for functions declared in this file */
 
63
 
 
64
#ifdef __cplusplus
 
65
extern "C"
 
66
{
 
67
#endif /* __cplusplus */
 
68
 
 
69
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
 
70
 
 
71
#ifdef __cplusplus
 
72
}
 
73
#endif /* __cplusplus */
 
74
 
 
75
 
 
76
static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
 
77
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
 
78
                                  const PaStreamParameters *inputParameters,
 
79
                                  const PaStreamParameters *outputParameters,
 
80
                                  double sampleRate );
 
81
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
 
82
                           PaStream** s,
 
83
                           const PaStreamParameters *inputParameters,
 
84
                           const PaStreamParameters *outputParameters,
 
85
                           double sampleRate,
 
86
                           unsigned long framesPerBuffer,
 
87
                           PaStreamFlags streamFlags,
 
88
                           PaStreamCallback *streamCallback,
 
89
                           void *userData );
 
90
static PaError CloseStream( PaStream* stream );
 
91
static PaError StartStream( PaStream *stream );
 
92
static PaError StopStream( PaStream *stream );
 
93
static PaError AbortStream( PaStream *stream );
 
94
static PaError IsStreamStopped( PaStream *s );
 
95
static PaError IsStreamActive( PaStream *stream );
 
96
static PaTime GetStreamTime( PaStream *stream );
 
97
static double GetStreamCpuLoad( PaStream* stream );
 
98
static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
 
99
static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
 
100
static signed long GetStreamReadAvailable( PaStream* stream );
 
101
static signed long GetStreamWriteAvailable( PaStream* stream );
 
102
 
 
103
 
 
104
/* IMPLEMENT ME: a macro like the following one should be used for reporting
 
105
 host errors */
 
106
#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
 
107
    PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
 
108
 
 
109
/* PaSkeletonHostApiRepresentation - host api datastructure specific to this implementation */
 
110
 
 
111
typedef struct
 
112
{
 
113
    PaUtilHostApiRepresentation inheritedHostApiRep;
 
114
    PaUtilStreamInterface callbackStreamInterface;
 
115
    PaUtilStreamInterface blockingStreamInterface;
 
116
 
 
117
    PaUtilAllocationGroup *allocations;
 
118
 
 
119
    /* implementation specific data goes here */
 
120
}
 
121
PaSkeletonHostApiRepresentation;  /* IMPLEMENT ME: rename this */
 
122
 
 
123
 
 
124
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
 
125
{
 
126
    PaError result = paNoError;
 
127
    int i, deviceCount;
 
128
    PaSkeletonHostApiRepresentation *skeletonHostApi;
 
129
    PaDeviceInfo *deviceInfoArray;
 
130
 
 
131
    skeletonHostApi = (PaSkeletonHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaSkeletonHostApiRepresentation) );
 
132
    if( !skeletonHostApi )
 
133
    {
 
134
        result = paInsufficientMemory;
 
135
        goto error;
 
136
    }
 
137
 
 
138
    skeletonHostApi->allocations = PaUtil_CreateAllocationGroup();
 
139
    if( !skeletonHostApi->allocations )
 
140
    {
 
141
        result = paInsufficientMemory;
 
142
        goto error;
 
143
    }
 
144
 
 
145
    *hostApi = &skeletonHostApi->inheritedHostApiRep;
 
146
    (*hostApi)->info.structVersion = 1;
 
147
    (*hostApi)->info.type = paInDevelopment;            /* IMPLEMENT ME: change to correct type id */
 
148
    (*hostApi)->info.name = "skeleton implementation";  /* IMPLEMENT ME: change to correct name */
 
149
 
 
150
    (*hostApi)->info.defaultInputDevice = paNoDevice;  /* IMPLEMENT ME */
 
151
    (*hostApi)->info.defaultOutputDevice = paNoDevice; /* IMPLEMENT ME */
 
152
 
 
153
    (*hostApi)->info.deviceCount = 0;  
 
154
 
 
155
    deviceCount = 0; /* IMPLEMENT ME */
 
156
    
 
157
    if( deviceCount > 0 )
 
158
    {
 
159
        (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
 
160
                skeletonHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
 
161
        if( !(*hostApi)->deviceInfos )
 
162
        {
 
163
            result = paInsufficientMemory;
 
164
            goto error;
 
165
        }
 
166
 
 
167
        /* allocate all device info structs in a contiguous block */
 
168
        deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
 
169
                skeletonHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
 
170
        if( !deviceInfoArray )
 
171
        {
 
172
            result = paInsufficientMemory;
 
173
            goto error;
 
174
        }
 
175
 
 
176
        for( i=0; i < deviceCount; ++i )
 
177
        {
 
178
            PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
 
179
            deviceInfo->structVersion = 2;
 
180
            deviceInfo->hostApi = hostApiIndex;
 
181
            deviceInfo->name = 0; /* IMPLEMENT ME: allocate block and copy name eg:
 
182
                deviceName = (char*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, strlen(srcName) + 1 );
 
183
                if( !deviceName )
 
184
                {
 
185
                    result = paInsufficientMemory;
 
186
                    goto error;
 
187
                }
 
188
                strcpy( deviceName, srcName );
 
189
                deviceInfo->name = deviceName;
 
190
            */
 
191
 
 
192
            deviceInfo->maxInputChannels = 0;  /* IMPLEMENT ME */
 
193
            deviceInfo->maxOutputChannels = 0;  /* IMPLEMENT ME */
 
194
            
 
195
            deviceInfo->defaultLowInputLatency = 0.;  /* IMPLEMENT ME */
 
196
            deviceInfo->defaultLowOutputLatency = 0.;  /* IMPLEMENT ME */
 
197
            deviceInfo->defaultHighInputLatency = 0.;  /* IMPLEMENT ME */
 
198
            deviceInfo->defaultHighOutputLatency = 0.;  /* IMPLEMENT ME */  
 
199
 
 
200
            deviceInfo->defaultSampleRate = 0.; /* IMPLEMENT ME */
 
201
            
 
202
            (*hostApi)->deviceInfos[i] = deviceInfo;
 
203
            ++(*hostApi)->info.deviceCount;
 
204
        }
 
205
    }
 
206
 
 
207
    (*hostApi)->Terminate = Terminate;
 
208
    (*hostApi)->OpenStream = OpenStream;
 
209
    (*hostApi)->IsFormatSupported = IsFormatSupported;
 
210
 
 
211
    PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
 
212
                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
 
213
                                      GetStreamTime, GetStreamCpuLoad,
 
214
                                      PaUtil_DummyRead, PaUtil_DummyWrite,
 
215
                                      PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
 
216
 
 
217
    PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface, CloseStream, StartStream,
 
218
                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
 
219
                                      GetStreamTime, PaUtil_DummyGetCpuLoad,
 
220
                                      ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
 
221
 
 
222
    return result;
 
223
 
 
224
error:
 
225
    if( skeletonHostApi )
 
226
    {
 
227
        if( skeletonHostApi->allocations )
 
228
        {
 
229
            PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
 
230
            PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
 
231
        }
 
232
                
 
233
        PaUtil_FreeMemory( skeletonHostApi );
 
234
    }
 
235
    return result;
 
236
}
 
237
 
 
238
 
 
239
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
 
240
{
 
241
    PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
 
242
 
 
243
    /*
 
244
        IMPLEMENT ME:
 
245
            - clean up any resources not handled by the allocation group
 
246
    */
 
247
 
 
248
    if( skeletonHostApi->allocations )
 
249
    {
 
250
        PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
 
251
        PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
 
252
    }
 
253
 
 
254
    PaUtil_FreeMemory( skeletonHostApi );
 
255
}
 
256
 
 
257
 
 
258
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
 
259
                                  const PaStreamParameters *inputParameters,
 
260
                                  const PaStreamParameters *outputParameters,
 
261
                                  double sampleRate )
 
262
{
 
263
    int inputChannelCount, outputChannelCount;
 
264
    PaSampleFormat inputSampleFormat, outputSampleFormat;
 
265
    
 
266
    if( inputParameters )
 
267
    {
 
268
        inputChannelCount = inputParameters->channelCount;
 
269
        inputSampleFormat = inputParameters->sampleFormat;
 
270
 
 
271
        /* all standard sample formats are supported by the buffer adapter,
 
272
            this implementation doesn't support any custom sample formats */
 
273
        if( inputSampleFormat & paCustomFormat )
 
274
            return paSampleFormatNotSupported;
 
275
            
 
276
        /* unless alternate device specification is supported, reject the use of
 
277
            paUseHostApiSpecificDeviceSpecification */
 
278
 
 
279
        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
 
280
            return paInvalidDevice;
 
281
 
 
282
        /* check that input device can support inputChannelCount */
 
283
        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
 
284
            return paInvalidChannelCount;
 
285
 
 
286
        /* validate inputStreamInfo */
 
287
        if( inputParameters->hostApiSpecificStreamInfo )
 
288
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
 
289
    }
 
290
    else
 
291
    {
 
292
        inputChannelCount = 0;
 
293
    }
 
294
 
 
295
    if( outputParameters )
 
296
    {
 
297
        outputChannelCount = outputParameters->channelCount;
 
298
        outputSampleFormat = outputParameters->sampleFormat;
 
299
 
 
300
        /* all standard sample formats are supported by the buffer adapter,
 
301
            this implementation doesn't support any custom sample formats */
 
302
        if( outputSampleFormat & paCustomFormat )
 
303
            return paSampleFormatNotSupported;
 
304
            
 
305
        /* unless alternate device specification is supported, reject the use of
 
306
            paUseHostApiSpecificDeviceSpecification */
 
307
 
 
308
        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
 
309
            return paInvalidDevice;
 
310
 
 
311
        /* check that output device can support outputChannelCount */
 
312
        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
 
313
            return paInvalidChannelCount;
 
314
 
 
315
        /* validate outputStreamInfo */
 
316
        if( outputParameters->hostApiSpecificStreamInfo )
 
317
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
 
318
    }
 
319
    else
 
320
    {
 
321
        outputChannelCount = 0;
 
322
    }
 
323
    
 
324
    /*
 
325
        IMPLEMENT ME:
 
326
 
 
327
            - if a full duplex stream is requested, check that the combination
 
328
                of input and output parameters is supported if necessary
 
329
 
 
330
            - check that the device supports sampleRate
 
331
 
 
332
        Because the buffer adapter handles conversion between all standard
 
333
        sample formats, the following checks are only required if paCustomFormat
 
334
        is implemented, or under some other unusual conditions.
 
335
 
 
336
            - check that input device can support inputSampleFormat, or that
 
337
                we have the capability to convert from inputSampleFormat to
 
338
                a native format
 
339
 
 
340
            - check that output device can support outputSampleFormat, or that
 
341
                we have the capability to convert from outputSampleFormat to
 
342
                a native format
 
343
    */
 
344
 
 
345
 
 
346
    /* suppress unused variable warnings */
 
347
    (void) sampleRate;
 
348
 
 
349
    return paFormatIsSupported;
 
350
}
 
351
 
 
352
/* PaSkeletonStream - a stream data structure specifically for this implementation */
 
353
 
 
354
typedef struct PaSkeletonStream
 
355
{ /* IMPLEMENT ME: rename this */
 
356
    PaUtilStreamRepresentation streamRepresentation;
 
357
    PaUtilCpuLoadMeasurer cpuLoadMeasurer;
 
358
    PaUtilBufferProcessor bufferProcessor;
 
359
 
 
360
    /* IMPLEMENT ME:
 
361
            - implementation specific data goes here
 
362
    */
 
363
    unsigned long framesPerHostCallback; /* just an example */
 
364
}
 
365
PaSkeletonStream;
 
366
 
 
367
/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
 
368
 
 
369
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
 
370
                           PaStream** s,
 
371
                           const PaStreamParameters *inputParameters,
 
372
                           const PaStreamParameters *outputParameters,
 
373
                           double sampleRate,
 
374
                           unsigned long framesPerBuffer,
 
375
                           PaStreamFlags streamFlags,
 
376
                           PaStreamCallback *streamCallback,
 
377
                           void *userData )
 
378
{
 
379
    PaError result = paNoError;
 
380
    PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
 
381
    PaSkeletonStream *stream = 0;
 
382
    unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */
 
383
    int inputChannelCount, outputChannelCount;
 
384
    PaSampleFormat inputSampleFormat, outputSampleFormat;
 
385
    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
 
386
 
 
387
 
 
388
    if( inputParameters )
 
389
    {
 
390
        inputChannelCount = inputParameters->channelCount;
 
391
        inputSampleFormat = inputParameters->sampleFormat;
 
392
 
 
393
        /* unless alternate device specification is supported, reject the use of
 
394
            paUseHostApiSpecificDeviceSpecification */
 
395
 
 
396
        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
 
397
            return paInvalidDevice;
 
398
 
 
399
        /* check that input device can support inputChannelCount */
 
400
        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
 
401
            return paInvalidChannelCount;
 
402
 
 
403
        /* validate inputStreamInfo */
 
404
        if( inputParameters->hostApiSpecificStreamInfo )
 
405
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
 
406
 
 
407
        /* IMPLEMENT ME - establish which  host formats are available */
 
408
        hostInputSampleFormat =
 
409
            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
 
410
    }
 
411
    else
 
412
    {
 
413
        inputChannelCount = 0;
 
414
        inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
 
415
    }
 
416
 
 
417
    if( outputParameters )
 
418
    {
 
419
        outputChannelCount = outputParameters->channelCount;
 
420
        outputSampleFormat = outputParameters->sampleFormat;
 
421
        
 
422
        /* unless alternate device specification is supported, reject the use of
 
423
            paUseHostApiSpecificDeviceSpecification */
 
424
 
 
425
        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
 
426
            return paInvalidDevice;
 
427
 
 
428
        /* check that output device can support inputChannelCount */
 
429
        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
 
430
            return paInvalidChannelCount;
 
431
 
 
432
        /* validate outputStreamInfo */
 
433
        if( outputParameters->hostApiSpecificStreamInfo )
 
434
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
 
435
 
 
436
        /* IMPLEMENT ME - establish which  host formats are available */
 
437
        hostOutputSampleFormat =
 
438
            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
 
439
    }
 
440
    else
 
441
    {
 
442
        outputChannelCount = 0;
 
443
        outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
 
444
    }
 
445
 
 
446
    /*
 
447
        IMPLEMENT ME:
 
448
 
 
449
        ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )
 
450
 
 
451
            - check that input device can support inputSampleFormat, or that
 
452
                we have the capability to convert from outputSampleFormat to
 
453
                a native format
 
454
 
 
455
            - check that output device can support outputSampleFormat, or that
 
456
                we have the capability to convert from outputSampleFormat to
 
457
                a native format
 
458
 
 
459
            - if a full duplex stream is requested, check that the combination
 
460
                of input and output parameters is supported
 
461
 
 
462
            - check that the device supports sampleRate
 
463
 
 
464
            - alter sampleRate to a close allowable rate if possible / necessary
 
465
 
 
466
            - validate suggestedInputLatency and suggestedOutputLatency parameters,
 
467
                use default values where necessary
 
468
    */
 
469
 
 
470
 
 
471
 
 
472
 
 
473
    /* validate platform specific flags */
 
474
    if( (streamFlags & paPlatformSpecificFlags) != 0 )
 
475
        return paInvalidFlag; /* unexpected platform specific flag */
 
476
 
 
477
 
 
478
    stream = (PaSkeletonStream*)PaUtil_AllocateMemory( sizeof(PaSkeletonStream) );
 
479
    if( !stream )
 
480
    {
 
481
        result = paInsufficientMemory;
 
482
        goto error;
 
483
    }
 
484
 
 
485
    if( streamCallback )
 
486
    {
 
487
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
 
488
                                               &skeletonHostApi->callbackStreamInterface, streamCallback, userData );
 
489
    }
 
490
    else
 
491
    {
 
492
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
 
493
                                               &skeletonHostApi->blockingStreamInterface, streamCallback, userData );
 
494
    }
 
495
 
 
496
    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
 
497
 
 
498
 
 
499
    /* we assume a fixed host buffer size in this example, but the buffer processor
 
500
        can also support bounded and unknown host buffer sizes by passing 
 
501
        paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
 
502
        paUtilFixedHostBufferSize below. */
 
503
        
 
504
    result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
 
505
              inputChannelCount, inputSampleFormat, hostInputSampleFormat,
 
506
              outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
 
507
              sampleRate, streamFlags, framesPerBuffer,
 
508
              framesPerHostBuffer, paUtilFixedHostBufferSize,
 
509
              streamCallback, userData );
 
510
    if( result != paNoError )
 
511
        goto error;
 
512
 
 
513
 
 
514
    /*
 
515
        IMPLEMENT ME: initialise the following fields with estimated or actual
 
516
        values.
 
517
    */
 
518
    stream->streamRepresentation.streamInfo.inputLatency =
 
519
            PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);
 
520
    stream->streamRepresentation.streamInfo.outputLatency =
 
521
            PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);
 
522
    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
 
523
 
 
524
    
 
525
    /*
 
526
        IMPLEMENT ME:
 
527
            - additional stream setup + opening
 
528
    */
 
529
 
 
530
    stream->framesPerHostCallback = framesPerHostBuffer;
 
531
 
 
532
    *s = (PaStream*)stream;
 
533
 
 
534
    return result;
 
535
 
 
536
error:
 
537
    if( stream )
 
538
        PaUtil_FreeMemory( stream );
 
539
 
 
540
    return result;
 
541
}
 
542
 
 
543
/*
 
544
    ExampleHostProcessingLoop() illustrates the kind of processing which may
 
545
    occur in a host implementation.
 
546
 
 
547
*/
 
548
static void ExampleHostProcessingLoop( void *inputBuffer, void *outputBuffer, void *userData )
 
549
{
 
550
    PaSkeletonStream *stream = (PaSkeletonStream*)userData;
 
551
    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
 
552
    int callbackResult;
 
553
    unsigned long framesProcessed;
 
554
    
 
555
    PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
 
556
    
 
557
    /*
 
558
        IMPLEMENT ME:
 
559
            - generate timing information
 
560
            - handle buffer slips
 
561
    */
 
562
 
 
563
    /*
 
564
        If you need to byte swap or shift inputBuffer to convert it into a
 
565
        portaudio format, do it here.
 
566
    */
 
567
 
 
568
 
 
569
 
 
570
    PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );
 
571
 
 
572
    /*
 
573
        depending on whether the host buffers are interleaved, non-interleaved
 
574
        or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
 
575
        PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
 
576
    */
 
577
    
 
578
    PaUtil_SetInputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
 
579
    PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
 
580
            0, /* first channel of inputBuffer is channel 0 */
 
581
            inputBuffer,
 
582
            0 ); /* 0 - use inputChannelCount passed to init buffer processor */
 
583
 
 
584
    PaUtil_SetOutputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
 
585
    PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
 
586
            0, /* first channel of outputBuffer is channel 0 */
 
587
            outputBuffer,
 
588
            0 ); /* 0 - use outputChannelCount passed to init buffer processor */
 
589
 
 
590
    /* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
 
591
        in general you would pass paContinue for normal operation, and
 
592
        paComplete to drain the buffer processor's internal output buffer.
 
593
        You can check whether the buffer processor's output buffer is empty
 
594
        using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
 
595
    */
 
596
    callbackResult = paContinue;
 
597
    framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
 
598
 
 
599
    
 
600
    /*
 
601
        If you need to byte swap or shift outputBuffer to convert it to
 
602
        host format, do it here.
 
603
    */
 
604
 
 
605
    PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
 
606
 
 
607
 
 
608
    if( callbackResult == paContinue )
 
609
    {
 
610
        /* nothing special to do */
 
611
    }
 
612
    else if( callbackResult == paAbort )
 
613
    {
 
614
        /* IMPLEMENT ME - finish playback immediately  */
 
615
 
 
616
        /* once finished, call the finished callback */
 
617
        if( stream->streamRepresentation.streamFinishedCallback != 0 )
 
618
            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
 
619
    }
 
620
    else
 
621
    {
 
622
        /* User callback has asked us to stop with paComplete or other non-zero value */
 
623
 
 
624
        /* IMPLEMENT ME - finish playback once currently queued audio has completed  */
 
625
 
 
626
        /* once finished, call the finished callback */
 
627
        if( stream->streamRepresentation.streamFinishedCallback != 0 )
 
628
            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
 
629
    }
 
630
}
 
631
 
 
632
 
 
633
/*
 
634
    When CloseStream() is called, the multi-api layer ensures that
 
635
    the stream has already been stopped or aborted.
 
636
*/
 
637
static PaError CloseStream( PaStream* s )
 
638
{
 
639
    PaError result = paNoError;
 
640
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
641
 
 
642
    /*
 
643
        IMPLEMENT ME:
 
644
            - additional stream closing + cleanup
 
645
    */
 
646
 
 
647
    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
 
648
    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
 
649
    PaUtil_FreeMemory( stream );
 
650
 
 
651
    return result;
 
652
}
 
653
 
 
654
 
 
655
static PaError StartStream( PaStream *s )
 
656
{
 
657
    PaError result = paNoError;
 
658
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
659
 
 
660
    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
 
661
 
 
662
    /* IMPLEMENT ME, see portaudio.h for required behavior */
 
663
 
 
664
    /* suppress unused function warning. the code in ExampleHostProcessingLoop or
 
665
       something similar should be implemented to feed samples to and from the
 
666
       host after StartStream() is called.
 
667
    */
 
668
    (void) ExampleHostProcessingLoop;
 
669
 
 
670
    return result;
 
671
}
 
672
 
 
673
 
 
674
static PaError StopStream( PaStream *s )
 
675
{
 
676
    PaError result = paNoError;
 
677
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
678
 
 
679
    /* suppress unused variable warnings */
 
680
    (void) stream;
 
681
 
 
682
    /* IMPLEMENT ME, see portaudio.h for required behavior */
 
683
 
 
684
    return result;
 
685
}
 
686
 
 
687
 
 
688
static PaError AbortStream( PaStream *s )
 
689
{
 
690
    PaError result = paNoError;
 
691
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
692
 
 
693
    /* suppress unused variable warnings */
 
694
    (void) stream;
 
695
    
 
696
    /* IMPLEMENT ME, see portaudio.h for required behavior */
 
697
 
 
698
    return result;
 
699
}
 
700
 
 
701
 
 
702
static PaError IsStreamStopped( PaStream *s )
 
703
{
 
704
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
705
 
 
706
    /* suppress unused variable warnings */
 
707
    (void) stream;
 
708
    
 
709
    /* IMPLEMENT ME, see portaudio.h for required behavior */
 
710
 
 
711
    return 0;
 
712
}
 
713
 
 
714
 
 
715
static PaError IsStreamActive( PaStream *s )
 
716
{
 
717
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
718
 
 
719
    /* suppress unused variable warnings */
 
720
    (void) stream;
 
721
    
 
722
    /* IMPLEMENT ME, see portaudio.h for required behavior */
 
723
 
 
724
    return 0;
 
725
}
 
726
 
 
727
 
 
728
static PaTime GetStreamTime( PaStream *s )
 
729
{
 
730
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
731
 
 
732
    /* suppress unused variable warnings */
 
733
    (void) stream;
 
734
    
 
735
    /* IMPLEMENT ME, see portaudio.h for required behavior*/
 
736
 
 
737
    return 0;
 
738
}
 
739
 
 
740
 
 
741
static double GetStreamCpuLoad( PaStream* s )
 
742
{
 
743
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
744
 
 
745
    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
 
746
}
 
747
 
 
748
 
 
749
/*
 
750
    As separate stream interfaces are used for blocking and callback
 
751
    streams, the following functions can be guaranteed to only be called
 
752
    for blocking streams.
 
753
*/
 
754
 
 
755
static PaError ReadStream( PaStream* s,
 
756
                           void *buffer,
 
757
                           unsigned long frames )
 
758
{
 
759
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
760
 
 
761
    /* suppress unused variable warnings */
 
762
    (void) buffer;
 
763
    (void) frames;
 
764
    (void) stream;
 
765
    
 
766
    /* IMPLEMENT ME, see portaudio.h for required behavior*/
 
767
 
 
768
    return paNoError;
 
769
}
 
770
 
 
771
 
 
772
static PaError WriteStream( PaStream* s,
 
773
                            const void *buffer,
 
774
                            unsigned long frames )
 
775
{
 
776
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
777
 
 
778
    /* suppress unused variable warnings */
 
779
    (void) buffer;
 
780
    (void) frames;
 
781
    (void) stream;
 
782
    
 
783
    /* IMPLEMENT ME, see portaudio.h for required behavior*/
 
784
 
 
785
    return paNoError;
 
786
}
 
787
 
 
788
 
 
789
static signed long GetStreamReadAvailable( PaStream* s )
 
790
{
 
791
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
792
 
 
793
    /* suppress unused variable warnings */
 
794
    (void) stream;
 
795
    
 
796
    /* IMPLEMENT ME, see portaudio.h for required behavior*/
 
797
 
 
798
    return 0;
 
799
}
 
800
 
 
801
 
 
802
static signed long GetStreamWriteAvailable( PaStream* s )
 
803
{
 
804
    PaSkeletonStream *stream = (PaSkeletonStream*)s;
 
805
 
 
806
    /* suppress unused variable warnings */
 
807
    (void) stream;
 
808
    
 
809
    /* IMPLEMENT ME, see portaudio.h for required behavior*/
 
810
 
 
811
    return 0;
 
812
}
 
813
 
 
814
 
 
815
 
 
816