To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / portaudio_20161030_catalina_patch / src / hostapi / skeleton / pa_hostapi_skeleton.c @ 162:d43aab368df9

History | View | Annotate | Download (27.6 KB)

1
/*
2
 * $Id$
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
            (PaTime)PaUtil_GetBufferProcessorInputLatencyFrames(&stream->bufferProcessor) / sampleRate; /* inputLatency is specified in _seconds_ */
522
    stream->streamRepresentation.streamInfo.outputLatency =
523
            (PaTime)PaUtil_GetBufferProcessorOutputLatencyFrames(&stream->bufferProcessor) / sampleRate; /* outputLatency is specified in _seconds_ */
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