~ubuntu-branches/ubuntu/trusty/teeworlds/trusty-updates

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Jack Coulter
  • Date: 2008-04-13 18:48:12 UTC
  • Revision ID: james.westby@ubuntu.com-20080413184812-efc80waq2er6p1bs
Tags: upstream-0.4.2
ImportĀ upstreamĀ versionĀ 0.4.2

Show diffs side-by-side

added added

removed removed

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