~ubuntu-branches/ubuntu/utopic/openal-soft/utopic

« back to all changes in this revision

Viewing changes to OpenAL32/alSource.c

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2012-05-22 10:14:53 UTC
  • mfrom: (7.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120522101453-knsv1m1m8vl5ccfp
Tags: 1:1.14-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  - Add a symbols file for libopenal1
* debian/libopenal1.symbols:
  - Update for 1.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include "alAuxEffectSlot.h"
34
34
 
35
35
 
36
 
resampler_t DefaultResampler;
37
 
const ALsizei ResamplerPadding[RESAMPLER_MAX] = {
 
36
enum Resampler DefaultResampler = LinearResampler;
 
37
const ALsizei ResamplerPadding[ResamplerMax] = {
38
38
    0, /* Point */
39
39
    1, /* Linear */
40
40
    2, /* Cubic */
41
41
};
42
 
const ALsizei ResamplerPrePadding[RESAMPLER_MAX] = {
 
42
const ALsizei ResamplerPrePadding[ResamplerMax] = {
43
43
    0, /* Point */
44
44
    0, /* Linear */
45
45
    1, /* Cubic */
48
48
 
49
49
static ALvoid InitSourceParams(ALsource *Source);
50
50
static ALvoid GetSourceOffset(ALsource *Source, ALenum eName, ALdouble *Offsets, ALdouble updateLen);
51
 
static ALboolean ApplyOffset(ALsource *Source);
52
 
static ALint GetByteOffset(ALsource *Source);
 
51
static ALint GetSampleOffset(ALsource *Source);
53
52
 
54
 
#define LookupSource(m, k) ((ALsource*)LookupUIntMapKey(&(m), (k)))
55
 
#define LookupBuffer(m, k) ((ALbuffer*)LookupUIntMapKey(&(m), (k)))
56
 
#define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k)))
57
 
#define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
58
53
 
59
54
AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources)
60
55
{
61
56
    ALCcontext *Context;
62
 
    ALCdevice *Device;
63
57
 
64
 
    Context = GetContextSuspended();
 
58
    Context = GetContextRef();
65
59
    if(!Context) return;
66
60
 
67
 
    Device = Context->Device;
68
61
    if(n < 0 || IsBadWritePtr((void*)sources, n * sizeof(ALuint)))
69
62
        alSetError(Context, AL_INVALID_VALUE);
70
 
    else if((ALuint)n > Device->MaxNoOfSources - Context->SourceMap.size)
71
 
        alSetError(Context, AL_INVALID_VALUE);
72
63
    else
73
64
    {
74
65
        ALenum err;
85
76
                alDeleteSources(i, sources);
86
77
                break;
87
78
            }
 
79
            InitSourceParams(source);
88
80
 
89
 
            source->source = (ALuint)ALTHUNK_ADDENTRY(source);
90
 
            err = InsertUIntMapEntry(&Context->SourceMap, source->source,
91
 
                                     source);
 
81
            err = NewThunkEntry(&source->source);
 
82
            if(err == AL_NO_ERROR)
 
83
                err = InsertUIntMapEntry(&Context->SourceMap, source->source, source);
92
84
            if(err != AL_NO_ERROR)
93
85
            {
94
 
                ALTHUNK_REMOVEENTRY(source->source);
 
86
                FreeThunkEntry(source->source);
95
87
                memset(source, 0, sizeof(ALsource));
96
88
                free(source);
97
89
 
101
93
            }
102
94
 
103
95
            sources[i++] = source->source;
104
 
            InitSourceParams(source);
105
96
        }
106
97
    }
107
98
 
108
 
    ProcessContext(Context);
 
99
    ALCcontext_DecRef(Context);
109
100
}
110
101
 
111
102
 
115
106
    ALsource *Source;
116
107
    ALsizei i, j;
117
108
    ALbufferlistitem *BufferList;
118
 
    ALboolean SourcesValid = AL_FALSE;
119
109
 
120
 
    Context = GetContextSuspended();
 
110
    Context = GetContextRef();
121
111
    if(!Context) return;
122
112
 
123
113
    if(n < 0)
124
114
        alSetError(Context, AL_INVALID_VALUE);
125
115
    else
126
116
    {
127
 
        SourcesValid = AL_TRUE;
128
117
        // Check that all Sources are valid (and can therefore be deleted)
129
118
        for(i = 0;i < n;i++)
130
119
        {
131
 
            if(LookupSource(Context->SourceMap, sources[i]) == NULL)
 
120
            if(LookupSource(Context, sources[i]) == NULL)
132
121
            {
133
122
                alSetError(Context, AL_INVALID_NAME);
134
 
                SourcesValid = AL_FALSE;
 
123
                n = 0;
135
124
                break;
136
125
            }
137
126
        }
138
 
    }
139
127
 
140
 
    if(SourcesValid)
141
 
    {
142
128
        // All Sources are valid, and can be deleted
143
129
        for(i = 0;i < n;i++)
144
130
        {
145
 
            // Recheck that the Source is valid, because there could be duplicated Source names
146
 
            if((Source=LookupSource(Context->SourceMap, sources[i])) == NULL)
 
131
            ALsource **srclist, **srclistend;
 
132
 
 
133
            // Remove Source from list of Sources
 
134
            if((Source=RemoveSource(Context, sources[i])) == NULL)
147
135
                continue;
148
136
 
149
 
            for(j = 0;j < Context->ActiveSourceCount;j++)
 
137
            FreeThunkEntry(Source->source);
 
138
 
 
139
            LockContext(Context);
 
140
            srclist = Context->ActiveSources;
 
141
            srclistend = srclist + Context->ActiveSourceCount;
 
142
            while(srclist != srclistend)
150
143
            {
151
 
                if(Context->ActiveSources[j] == Source)
 
144
                if(*srclist == Source)
152
145
                {
153
 
                    ALsizei end = --(Context->ActiveSourceCount);
154
 
                    Context->ActiveSources[j] = Context->ActiveSources[end];
 
146
                    Context->ActiveSourceCount--;
 
147
                    *srclist = *(--srclistend);
155
148
                    break;
156
149
                }
 
150
                srclist++;
157
151
            }
 
152
            UnlockContext(Context);
158
153
 
159
154
            // For each buffer in the source's queue...
160
155
            while(Source->queue != NULL)
163
158
                Source->queue = BufferList->next;
164
159
 
165
160
                if(BufferList->buffer != NULL)
166
 
                    BufferList->buffer->refcount--;
 
161
                    DecrementRef(&BufferList->buffer->ref);
167
162
                free(BufferList);
168
163
            }
169
164
 
170
165
            for(j = 0;j < MAX_SENDS;++j)
171
166
            {
172
167
                if(Source->Send[j].Slot)
173
 
                    Source->Send[j].Slot->refcount--;
 
168
                    DecrementRef(&Source->Send[j].Slot->ref);
174
169
                Source->Send[j].Slot = NULL;
175
170
            }
176
171
 
177
 
            // Remove Source from list of Sources
178
 
            RemoveUIntMapKey(&Context->SourceMap, Source->source);
179
 
            ALTHUNK_REMOVEENTRY(Source->source);
180
 
 
181
172
            memset(Source,0,sizeof(ALsource));
182
173
            free(Source);
183
174
        }
184
175
    }
185
176
 
186
 
    ProcessContext(Context);
 
177
    ALCcontext_DecRef(Context);
187
178
}
188
179
 
189
180
 
192
183
    ALCcontext *Context;
193
184
    ALboolean  result;
194
185
 
195
 
    Context = GetContextSuspended();
 
186
    Context = GetContextRef();
196
187
    if(!Context) return AL_FALSE;
197
188
 
198
 
    result = (LookupSource(Context->SourceMap, source) ? AL_TRUE : AL_FALSE);
 
189
    result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
199
190
 
200
 
    ProcessContext(Context);
 
191
    ALCcontext_DecRef(Context);
201
192
 
202
193
    return result;
203
194
}
205
196
 
206
197
AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
207
198
{
208
 
    ALCcontext    *pContext;
209
 
    ALsource    *Source;
 
199
    ALCcontext *pContext;
 
200
    ALsource   *Source;
210
201
 
211
 
    pContext = GetContextSuspended();
 
202
    pContext = GetContextRef();
212
203
    if(!pContext) return;
213
204
 
214
 
    if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
205
    if((Source=LookupSource(pContext, source)) != NULL)
215
206
    {
216
207
        switch(eParam)
217
208
        {
360
351
            case AL_BYTE_OFFSET:
361
352
                if(flValue >= 0.0f)
362
353
                {
 
354
                    LockContext(pContext);
363
355
                    Source->lOffsetType = eParam;
364
356
 
365
357
                    // Store Offset (convert Seconds into Milliseconds)
368
360
                    else
369
361
                        Source->lOffset = (ALint)flValue;
370
362
 
371
 
                    if ((Source->state == AL_PLAYING) || (Source->state == AL_PAUSED))
 
363
                    if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
 
364
                       !pContext->DeferUpdates)
372
365
                    {
373
366
                        if(ApplyOffset(Source) == AL_FALSE)
374
367
                            alSetError(pContext, AL_INVALID_VALUE);
375
368
                    }
 
369
                    UnlockContext(pContext);
376
370
                }
377
371
                else
378
372
                    alSetError(pContext, AL_INVALID_VALUE);
389
383
        alSetError(pContext, AL_INVALID_NAME);
390
384
    }
391
385
 
392
 
    ProcessContext(pContext);
 
386
    ALCcontext_DecRef(pContext);
393
387
}
394
388
 
395
389
 
396
390
AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue1,ALfloat flValue2,ALfloat flValue3)
397
391
{
398
 
    ALCcontext    *pContext;
399
 
    ALsource    *Source;
 
392
    ALCcontext *pContext;
 
393
    ALsource   *Source;
400
394
 
401
 
    pContext = GetContextSuspended();
 
395
    pContext = GetContextRef();
402
396
    if(!pContext) return;
403
397
 
404
 
    if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
398
    if((Source=LookupSource(pContext, source)) != NULL)
405
399
    {
406
400
        switch(eParam)
407
401
        {
408
402
            case AL_POSITION:
409
 
                Source->vPosition[0] = flValue1;
410
 
                Source->vPosition[1] = flValue2;
411
 
                Source->vPosition[2] = flValue3;
412
 
                Source->NeedsUpdate = AL_TRUE;
 
403
                if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
 
404
                {
 
405
                    LockContext(pContext);
 
406
                    Source->vPosition[0] = flValue1;
 
407
                    Source->vPosition[1] = flValue2;
 
408
                    Source->vPosition[2] = flValue3;
 
409
                    UnlockContext(pContext);
 
410
                    Source->NeedsUpdate = AL_TRUE;
 
411
                }
 
412
                else
 
413
                    alSetError(pContext, AL_INVALID_VALUE);
413
414
                break;
414
415
 
415
416
            case AL_VELOCITY:
416
 
                Source->vVelocity[0] = flValue1;
417
 
                Source->vVelocity[1] = flValue2;
418
 
                Source->vVelocity[2] = flValue3;
419
 
                Source->NeedsUpdate = AL_TRUE;
 
417
                if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
 
418
                {
 
419
                    LockContext(pContext);
 
420
                    Source->vVelocity[0] = flValue1;
 
421
                    Source->vVelocity[1] = flValue2;
 
422
                    Source->vVelocity[2] = flValue3;
 
423
                    UnlockContext(pContext);
 
424
                    Source->NeedsUpdate = AL_TRUE;
 
425
                }
 
426
                else
 
427
                    alSetError(pContext, AL_INVALID_VALUE);
420
428
                break;
421
429
 
422
430
            case AL_DIRECTION:
423
 
                Source->vOrientation[0] = flValue1;
424
 
                Source->vOrientation[1] = flValue2;
425
 
                Source->vOrientation[2] = flValue3;
426
 
                Source->NeedsUpdate = AL_TRUE;
 
431
                if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
 
432
                {
 
433
                    LockContext(pContext);
 
434
                    Source->vOrientation[0] = flValue1;
 
435
                    Source->vOrientation[1] = flValue2;
 
436
                    Source->vOrientation[2] = flValue3;
 
437
                    UnlockContext(pContext);
 
438
                    Source->NeedsUpdate = AL_TRUE;
 
439
                }
 
440
                else
 
441
                    alSetError(pContext, AL_INVALID_VALUE);
427
442
                break;
428
443
 
429
444
            default:
434
449
    else
435
450
        alSetError(pContext, AL_INVALID_NAME);
436
451
 
437
 
    ProcessContext(pContext);
 
452
    ALCcontext_DecRef(pContext);
438
453
}
439
454
 
440
455
 
441
456
AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *pflValues)
442
457
{
443
 
    ALCcontext    *pContext;
444
 
 
445
 
    pContext = GetContextSuspended();
 
458
    ALCcontext *pContext;
 
459
 
 
460
    if(pflValues)
 
461
    {
 
462
        switch(eParam)
 
463
        {
 
464
            case AL_PITCH:
 
465
            case AL_CONE_INNER_ANGLE:
 
466
            case AL_CONE_OUTER_ANGLE:
 
467
            case AL_GAIN:
 
468
            case AL_MAX_DISTANCE:
 
469
            case AL_ROLLOFF_FACTOR:
 
470
            case AL_REFERENCE_DISTANCE:
 
471
            case AL_MIN_GAIN:
 
472
            case AL_MAX_GAIN:
 
473
            case AL_CONE_OUTER_GAIN:
 
474
            case AL_CONE_OUTER_GAINHF:
 
475
            case AL_SEC_OFFSET:
 
476
            case AL_SAMPLE_OFFSET:
 
477
            case AL_BYTE_OFFSET:
 
478
            case AL_AIR_ABSORPTION_FACTOR:
 
479
            case AL_ROOM_ROLLOFF_FACTOR:
 
480
                alSourcef(source, eParam, pflValues[0]);
 
481
                return;
 
482
 
 
483
            case AL_POSITION:
 
484
            case AL_VELOCITY:
 
485
            case AL_DIRECTION:
 
486
                alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]);
 
487
                return;
 
488
        }
 
489
    }
 
490
 
 
491
    pContext = GetContextRef();
446
492
    if(!pContext) return;
447
493
 
448
494
    if(pflValues)
449
495
    {
450
 
        if(LookupSource(pContext->SourceMap, source) != NULL)
 
496
        if(LookupSource(pContext, source) != NULL)
451
497
        {
452
498
            switch(eParam)
453
499
            {
454
 
                case AL_PITCH:
455
 
                case AL_CONE_INNER_ANGLE:
456
 
                case AL_CONE_OUTER_ANGLE:
457
 
                case AL_GAIN:
458
 
                case AL_MAX_DISTANCE:
459
 
                case AL_ROLLOFF_FACTOR:
460
 
                case AL_REFERENCE_DISTANCE:
461
 
                case AL_MIN_GAIN:
462
 
                case AL_MAX_GAIN:
463
 
                case AL_CONE_OUTER_GAIN:
464
 
                case AL_CONE_OUTER_GAINHF:
465
 
                case AL_SEC_OFFSET:
466
 
                case AL_SAMPLE_OFFSET:
467
 
                case AL_BYTE_OFFSET:
468
 
                case AL_AIR_ABSORPTION_FACTOR:
469
 
                case AL_ROOM_ROLLOFF_FACTOR:
470
 
                    alSourcef(source, eParam, pflValues[0]);
471
 
                    break;
472
 
 
473
 
                case AL_POSITION:
474
 
                case AL_VELOCITY:
475
 
                case AL_DIRECTION:
476
 
                    alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]);
477
 
                    break;
478
 
 
479
500
                default:
480
501
                    alSetError(pContext, AL_INVALID_ENUM);
481
502
                    break;
487
508
    else
488
509
        alSetError(pContext, AL_INVALID_VALUE);
489
510
 
490
 
    ProcessContext(pContext);
 
511
    ALCcontext_DecRef(pContext);
491
512
}
492
513
 
493
514
 
494
515
AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
495
516
{
496
 
    ALCcontext          *pContext;
497
 
    ALsource            *Source;
498
 
    ALbufferlistitem    *BufferListItem;
499
 
 
500
 
    pContext = GetContextSuspended();
 
517
    ALCcontext       *pContext;
 
518
    ALsource         *Source;
 
519
    ALbufferlistitem *BufferListItem;
 
520
 
 
521
    switch(eParam)
 
522
    {
 
523
        case AL_MAX_DISTANCE:
 
524
        case AL_ROLLOFF_FACTOR:
 
525
        case AL_CONE_INNER_ANGLE:
 
526
        case AL_CONE_OUTER_ANGLE:
 
527
        case AL_REFERENCE_DISTANCE:
 
528
            alSourcef(source, eParam, (ALfloat)lValue);
 
529
            return;
 
530
    }
 
531
 
 
532
    pContext = GetContextRef();
501
533
    if(!pContext) return;
502
534
 
503
 
    if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
535
    if((Source=LookupSource(pContext, source)) != NULL)
504
536
    {
505
537
        ALCdevice *device = pContext->Device;
506
538
 
507
539
        switch(eParam)
508
540
        {
509
 
            case AL_MAX_DISTANCE:
510
 
            case AL_ROLLOFF_FACTOR:
511
 
            case AL_CONE_INNER_ANGLE:
512
 
            case AL_CONE_OUTER_ANGLE:
513
 
            case AL_REFERENCE_DISTANCE:
514
 
                alSourcef(source, eParam, (ALfloat)lValue);
515
 
                break;
516
 
 
517
541
            case AL_SOURCE_RELATIVE:
518
542
                if(lValue == AL_FALSE || lValue == AL_TRUE)
519
543
                {
532
556
                break;
533
557
 
534
558
            case AL_BUFFER:
 
559
                LockContext(pContext);
535
560
                if(Source->state == AL_STOPPED || Source->state == AL_INITIAL)
536
561
                {
 
562
                    ALbufferlistitem *oldlist;
537
563
                    ALbuffer *buffer = NULL;
538
564
 
539
 
                    if(lValue == 0 ||
540
 
                       (buffer=LookupBuffer(device->BufferMap, lValue)) != NULL)
 
565
                    if(lValue == 0 || (buffer=LookupBuffer(device, lValue)) != NULL)
541
566
                    {
542
 
                        // Remove all elements in the queue
543
 
                        while(Source->queue != NULL)
544
 
                        {
545
 
                            BufferListItem = Source->queue;
546
 
                            Source->queue = BufferListItem->next;
547
 
 
548
 
                            if(BufferListItem->buffer)
549
 
                                BufferListItem->buffer->refcount--;
550
 
                            free(BufferListItem);
551
 
                        }
552
567
                        Source->BuffersInQueue = 0;
 
568
                        Source->BuffersPlayed = 0;
553
569
 
554
570
                        // Add the buffer to the queue (as long as it is NOT the NULL buffer)
555
571
                        if(buffer != NULL)
562
578
                            BufferListItem->buffer = buffer;
563
579
                            BufferListItem->next = NULL;
564
580
                            BufferListItem->prev = NULL;
 
581
                            // Increment reference counter for buffer
 
582
                            IncrementRef(&buffer->ref);
565
583
 
566
 
                            Source->queue = BufferListItem;
 
584
                            oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
567
585
                            Source->BuffersInQueue = 1;
568
586
 
 
587
                            ReadLock(&buffer->lock);
 
588
                            Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
 
589
                            Source->SampleSize  = BytesFromFmt(buffer->FmtType);
 
590
                            ReadUnlock(&buffer->lock);
569
591
                            if(buffer->FmtChannels == FmtMono)
570
592
                                Source->Update = CalcSourceParams;
571
593
                            else
572
594
                                Source->Update = CalcNonAttnSourceParams;
573
 
 
574
 
                            // Increment reference counter for buffer
575
 
                            buffer->refcount++;
 
595
                            Source->NeedsUpdate = AL_TRUE;
576
596
                        }
577
597
                        else
578
598
                        {
579
599
                            // Source is now in UNDETERMINED mode
580
600
                            Source->lSourceType = AL_UNDETERMINED;
581
 
                        }
582
 
                        Source->BuffersPlayed = 0;
583
 
 
584
 
                        // Update AL_BUFFER parameter
585
 
                        Source->Buffer = buffer;
586
 
                        Source->NeedsUpdate = AL_TRUE;
 
601
                            oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
 
602
                        }
 
603
 
 
604
                        // Delete all previous elements in the queue
 
605
                        while(oldlist != NULL)
 
606
                        {
 
607
                            BufferListItem = oldlist;
 
608
                            oldlist = BufferListItem->next;
 
609
 
 
610
                            if(BufferListItem->buffer)
 
611
                                DecrementRef(&BufferListItem->buffer->ref);
 
612
                            free(BufferListItem);
 
613
                        }
587
614
                    }
588
615
                    else
589
616
                        alSetError(pContext, AL_INVALID_VALUE);
590
617
                }
591
618
                else
592
619
                    alSetError(pContext, AL_INVALID_OPERATION);
 
620
                UnlockContext(pContext);
593
621
                break;
594
622
 
595
623
            case AL_SOURCE_STATE:
602
630
            case AL_BYTE_OFFSET:
603
631
                if(lValue >= 0)
604
632
                {
 
633
                    LockContext(pContext);
605
634
                    Source->lOffsetType = eParam;
606
635
 
607
636
                    // Store Offset (convert Seconds into Milliseconds)
610
639
                    else
611
640
                        Source->lOffset = lValue;
612
641
 
613
 
                    if(Source->state == AL_PLAYING || Source->state == AL_PAUSED)
 
642
                    if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
 
643
                       !pContext->DeferUpdates)
614
644
                    {
615
645
                        if(ApplyOffset(Source) == AL_FALSE)
616
646
                            alSetError(pContext, AL_INVALID_VALUE);
617
647
                    }
 
648
                    UnlockContext(pContext);
618
649
                }
619
650
                else
620
651
                    alSetError(pContext, AL_INVALID_VALUE);
623
654
            case AL_DIRECT_FILTER: {
624
655
                ALfilter *filter = NULL;
625
656
 
626
 
                if(lValue == 0 ||
627
 
                   (filter=LookupFilter(pContext->Device->FilterMap, lValue)) != NULL)
 
657
                if(lValue == 0 || (filter=LookupFilter(pContext->Device, lValue)) != NULL)
628
658
                {
 
659
                    LockContext(pContext);
629
660
                    if(!filter)
630
661
                    {
631
 
                        Source->DirectFilter.type = AL_FILTER_NULL;
632
 
                        Source->DirectFilter.filter = 0;
 
662
                        Source->DirectGain = 1.0f;
 
663
                        Source->DirectGainHF = 1.0f;
633
664
                    }
634
665
                    else
635
 
                        memcpy(&Source->DirectFilter, filter, sizeof(*filter));
 
666
                    {
 
667
                        Source->DirectGain = filter->Gain;
 
668
                        Source->DirectGainHF = filter->GainHF;
 
669
                    }
 
670
                    UnlockContext(pContext);
636
671
                    Source->NeedsUpdate = AL_TRUE;
637
672
                }
638
673
                else
669
704
                    alSetError(pContext, AL_INVALID_VALUE);
670
705
                break;
671
706
 
 
707
            case AL_DIRECT_CHANNELS_SOFT:
 
708
                if(lValue == AL_TRUE || lValue == AL_FALSE)
 
709
                {
 
710
                    Source->DirectChannels = lValue;
 
711
                    Source->NeedsUpdate = AL_TRUE;
 
712
                }
 
713
                else
 
714
                    alSetError(pContext, AL_INVALID_VALUE);
 
715
                break;
 
716
 
672
717
            case AL_DISTANCE_MODEL:
673
718
                if(lValue == AL_NONE ||
674
719
                   lValue == AL_INVERSE_DISTANCE ||
694
739
    else
695
740
        alSetError(pContext, AL_INVALID_NAME);
696
741
 
697
 
    ProcessContext(pContext);
 
742
    ALCcontext_DecRef(pContext);
698
743
}
699
744
 
700
745
 
703
748
    ALCcontext *pContext;
704
749
    ALsource   *Source;
705
750
 
706
 
    pContext = GetContextSuspended();
 
751
    switch(eParam)
 
752
    {
 
753
        case AL_POSITION:
 
754
        case AL_VELOCITY:
 
755
        case AL_DIRECTION:
 
756
            alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
 
757
            return;
 
758
    }
 
759
 
 
760
    pContext = GetContextRef();
707
761
    if(!pContext) return;
708
762
 
709
 
    if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
763
    if((Source=LookupSource(pContext, source)) != NULL)
710
764
    {
711
765
        ALCdevice *device = pContext->Device;
712
766
 
713
 
        switch (eParam)
 
767
        switch(eParam)
714
768
        {
715
 
            case AL_POSITION:
716
 
            case AL_VELOCITY:
717
 
            case AL_DIRECTION:
718
 
                alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
719
 
                break;
720
 
 
721
769
            case AL_AUXILIARY_SEND_FILTER: {
722
770
                ALeffectslot *ALEffectSlot = NULL;
723
771
                ALfilter     *ALFilter = NULL;
724
772
 
 
773
                LockContext(pContext);
725
774
                if((ALuint)lValue2 < device->NumAuxSends &&
726
 
                   (lValue1 == 0 ||
727
 
                    (ALEffectSlot=LookupEffectSlot(pContext->EffectSlotMap, lValue1)) != NULL) &&
728
 
                   (lValue3 == 0 ||
729
 
                    (ALFilter=LookupFilter(device->FilterMap, lValue3)) != NULL))
 
775
                   (lValue1 == 0 || (ALEffectSlot=LookupEffectSlot(pContext, lValue1)) != NULL) &&
 
776
                   (lValue3 == 0 || (ALFilter=LookupFilter(device, lValue3)) != NULL))
730
777
                {
731
778
                    /* Release refcount on the previous slot, and add one for
732
779
                     * the new slot */
733
 
                    if(Source->Send[lValue2].Slot)
734
 
                        Source->Send[lValue2].Slot->refcount--;
735
 
                    Source->Send[lValue2].Slot = ALEffectSlot;
736
 
                    if(Source->Send[lValue2].Slot)
737
 
                        Source->Send[lValue2].Slot->refcount++;
 
780
                    if(ALEffectSlot) IncrementRef(&ALEffectSlot->ref);
 
781
                    ALEffectSlot = ExchangePtr((XchgPtr*)&Source->Send[lValue2].Slot, ALEffectSlot);
 
782
                    if(ALEffectSlot) DecrementRef(&ALEffectSlot->ref);
738
783
 
739
784
                    if(!ALFilter)
740
785
                    {
741
786
                        /* Disable filter */
742
 
                        Source->Send[lValue2].WetFilter.type = 0;
743
 
                        Source->Send[lValue2].WetFilter.filter = 0;
 
787
                        Source->Send[lValue2].WetGain = 1.0f;
 
788
                        Source->Send[lValue2].WetGainHF = 1.0f;
744
789
                    }
745
790
                    else
746
 
                        memcpy(&Source->Send[lValue2].WetFilter, ALFilter, sizeof(*ALFilter));
 
791
                    {
 
792
                        Source->Send[lValue2].WetGain = ALFilter->Gain;
 
793
                        Source->Send[lValue2].WetGainHF = ALFilter->GainHF;
 
794
                    }
747
795
                    Source->NeedsUpdate = AL_TRUE;
748
796
                }
749
797
                else
750
798
                    alSetError(pContext, AL_INVALID_VALUE);
751
 
            }    break;
 
799
                UnlockContext(pContext);
 
800
            }   break;
752
801
 
753
802
            default:
754
803
                alSetError(pContext, AL_INVALID_ENUM);
758
807
    else
759
808
        alSetError(pContext, AL_INVALID_NAME);
760
809
 
761
 
    ProcessContext(pContext);
 
810
    ALCcontext_DecRef(pContext);
762
811
}
763
812
 
764
813
 
765
814
AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plValues)
766
815
{
767
 
    ALCcontext    *pContext;
768
 
 
769
 
    pContext = GetContextSuspended();
 
816
    ALCcontext *pContext;
 
817
 
 
818
    if(plValues)
 
819
    {
 
820
        switch(eParam)
 
821
        {
 
822
            case AL_SOURCE_RELATIVE:
 
823
            case AL_CONE_INNER_ANGLE:
 
824
            case AL_CONE_OUTER_ANGLE:
 
825
            case AL_LOOPING:
 
826
            case AL_BUFFER:
 
827
            case AL_SOURCE_STATE:
 
828
            case AL_SEC_OFFSET:
 
829
            case AL_SAMPLE_OFFSET:
 
830
            case AL_BYTE_OFFSET:
 
831
            case AL_MAX_DISTANCE:
 
832
            case AL_ROLLOFF_FACTOR:
 
833
            case AL_REFERENCE_DISTANCE:
 
834
            case AL_DIRECT_FILTER:
 
835
            case AL_DIRECT_FILTER_GAINHF_AUTO:
 
836
            case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
 
837
            case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
 
838
            case AL_DISTANCE_MODEL:
 
839
            case AL_DIRECT_CHANNELS_SOFT:
 
840
                alSourcei(source, eParam, plValues[0]);
 
841
                return;
 
842
 
 
843
            case AL_POSITION:
 
844
            case AL_VELOCITY:
 
845
            case AL_DIRECTION:
 
846
            case AL_AUXILIARY_SEND_FILTER:
 
847
                alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
 
848
                return;
 
849
        }
 
850
    }
 
851
 
 
852
    pContext = GetContextRef();
770
853
    if(!pContext) return;
771
854
 
772
855
    if(plValues)
773
856
    {
774
 
        if(LookupSource(pContext->SourceMap, source) != NULL)
 
857
        if(LookupSource(pContext, source) != NULL)
775
858
        {
776
859
            switch(eParam)
777
860
            {
778
 
                case AL_SOURCE_RELATIVE:
779
 
                case AL_CONE_INNER_ANGLE:
780
 
                case AL_CONE_OUTER_ANGLE:
781
 
                case AL_LOOPING:
782
 
                case AL_BUFFER:
783
 
                case AL_SOURCE_STATE:
784
 
                case AL_SEC_OFFSET:
785
 
                case AL_SAMPLE_OFFSET:
786
 
                case AL_BYTE_OFFSET:
787
 
                case AL_MAX_DISTANCE:
788
 
                case AL_ROLLOFF_FACTOR:
789
 
                case AL_REFERENCE_DISTANCE:
790
 
                case AL_DIRECT_FILTER:
791
 
                case AL_DIRECT_FILTER_GAINHF_AUTO:
792
 
                case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
793
 
                case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
794
 
                case AL_DISTANCE_MODEL:
795
 
                    alSourcei(source, eParam, plValues[0]);
796
 
                    break;
797
 
 
798
 
                case AL_POSITION:
799
 
                case AL_VELOCITY:
800
 
                case AL_DIRECTION:
801
 
                case AL_AUXILIARY_SEND_FILTER:
802
 
                    alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
803
 
                    break;
804
 
 
805
861
                default:
806
862
                    alSetError(pContext, AL_INVALID_ENUM);
807
863
                    break;
813
869
    else
814
870
        alSetError(pContext, AL_INVALID_VALUE);
815
871
 
816
 
    ProcessContext(pContext);
 
872
    ALCcontext_DecRef(pContext);
817
873
}
818
874
 
819
875
 
824
880
    ALdouble    Offsets[2];
825
881
    ALdouble    updateLen;
826
882
 
827
 
    pContext = GetContextSuspended();
 
883
    pContext = GetContextRef();
828
884
    if(!pContext) return;
829
885
 
830
886
    if(pflValue)
831
887
    {
832
 
        if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
888
        if((Source=LookupSource(pContext, source)) != NULL)
833
889
        {
834
890
            switch(eParam)
835
891
            {
868
924
                case AL_SEC_OFFSET:
869
925
                case AL_SAMPLE_OFFSET:
870
926
                case AL_BYTE_OFFSET:
 
927
                    LockContext(pContext);
871
928
                    updateLen = (ALdouble)pContext->Device->UpdateSize /
872
929
                                pContext->Device->Frequency;
873
930
                    GetSourceOffset(Source, eParam, Offsets, updateLen);
874
 
                    *pflValue = Offsets[0];
 
931
                    UnlockContext(pContext);
 
932
                    *pflValue = (ALfloat)Offsets[0];
875
933
                    break;
876
934
 
877
935
                case AL_CONE_INNER_ANGLE:
909
967
    else
910
968
        alSetError(pContext, AL_INVALID_VALUE);
911
969
 
912
 
    ProcessContext(pContext);
 
970
    ALCcontext_DecRef(pContext);
913
971
}
914
972
 
915
973
 
916
974
AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
917
975
{
918
 
    ALCcontext    *pContext;
919
 
    ALsource    *Source;
 
976
    ALCcontext *pContext;
 
977
    ALsource   *Source;
920
978
 
921
 
    pContext = GetContextSuspended();
 
979
    pContext = GetContextRef();
922
980
    if(!pContext) return;
923
981
 
924
982
    if(pflValue1 && pflValue2 && pflValue3)
925
983
    {
926
 
        if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
984
        if((Source=LookupSource(pContext, source)) != NULL)
927
985
        {
928
986
            switch(eParam)
929
987
            {
930
988
                case AL_POSITION:
 
989
                    LockContext(pContext);
931
990
                    *pflValue1 = Source->vPosition[0];
932
991
                    *pflValue2 = Source->vPosition[1];
933
992
                    *pflValue3 = Source->vPosition[2];
 
993
                    UnlockContext(pContext);
934
994
                    break;
935
995
 
936
996
                case AL_VELOCITY:
 
997
                    LockContext(pContext);
937
998
                    *pflValue1 = Source->vVelocity[0];
938
999
                    *pflValue2 = Source->vVelocity[1];
939
1000
                    *pflValue3 = Source->vVelocity[2];
 
1001
                    UnlockContext(pContext);
940
1002
                    break;
941
1003
 
942
1004
                case AL_DIRECTION:
 
1005
                    LockContext(pContext);
943
1006
                    *pflValue1 = Source->vOrientation[0];
944
1007
                    *pflValue2 = Source->vOrientation[1];
945
1008
                    *pflValue3 = Source->vOrientation[2];
 
1009
                    UnlockContext(pContext);
946
1010
                    break;
947
1011
 
948
1012
                default:
956
1020
    else
957
1021
        alSetError(pContext, AL_INVALID_VALUE);
958
1022
 
959
 
    ProcessContext(pContext);
 
1023
    ALCcontext_DecRef(pContext);
960
1024
}
961
1025
 
962
1026
 
967
1031
    ALdouble    Offsets[2];
968
1032
    ALdouble    updateLen;
969
1033
 
970
 
    pContext = GetContextSuspended();
 
1034
    switch(eParam)
 
1035
    {
 
1036
        case AL_PITCH:
 
1037
        case AL_GAIN:
 
1038
        case AL_MIN_GAIN:
 
1039
        case AL_MAX_GAIN:
 
1040
        case AL_MAX_DISTANCE:
 
1041
        case AL_ROLLOFF_FACTOR:
 
1042
        case AL_DOPPLER_FACTOR:
 
1043
        case AL_CONE_OUTER_GAIN:
 
1044
        case AL_SEC_OFFSET:
 
1045
        case AL_SAMPLE_OFFSET:
 
1046
        case AL_BYTE_OFFSET:
 
1047
        case AL_CONE_INNER_ANGLE:
 
1048
        case AL_CONE_OUTER_ANGLE:
 
1049
        case AL_REFERENCE_DISTANCE:
 
1050
        case AL_CONE_OUTER_GAINHF:
 
1051
        case AL_AIR_ABSORPTION_FACTOR:
 
1052
        case AL_ROOM_ROLLOFF_FACTOR:
 
1053
            alGetSourcef(source, eParam, pflValues);
 
1054
            return;
 
1055
 
 
1056
        case AL_POSITION:
 
1057
        case AL_VELOCITY:
 
1058
        case AL_DIRECTION:
 
1059
            alGetSource3f(source, eParam, pflValues+0, pflValues+1, pflValues+2);
 
1060
            return;
 
1061
    }
 
1062
 
 
1063
    pContext = GetContextRef();
971
1064
    if(!pContext) return;
972
1065
 
973
1066
    if(pflValues)
974
1067
    {
975
 
        if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
1068
        if((Source=LookupSource(pContext, source)) != NULL)
976
1069
        {
977
1070
            switch(eParam)
978
1071
            {
979
 
                case AL_PITCH:
980
 
                case AL_GAIN:
981
 
                case AL_MIN_GAIN:
982
 
                case AL_MAX_GAIN:
983
 
                case AL_MAX_DISTANCE:
984
 
                case AL_ROLLOFF_FACTOR:
985
 
                case AL_DOPPLER_FACTOR:
986
 
                case AL_CONE_OUTER_GAIN:
987
 
                case AL_SEC_OFFSET:
988
 
                case AL_SAMPLE_OFFSET:
989
 
                case AL_BYTE_OFFSET:
990
 
                case AL_CONE_INNER_ANGLE:
991
 
                case AL_CONE_OUTER_ANGLE:
992
 
                case AL_REFERENCE_DISTANCE:
993
 
                case AL_CONE_OUTER_GAINHF:
994
 
                case AL_AIR_ABSORPTION_FACTOR:
995
 
                case AL_ROOM_ROLLOFF_FACTOR:
996
 
                    alGetSourcef(source, eParam, pflValues);
997
 
                    break;
998
 
 
999
 
                case AL_POSITION:
1000
 
                case AL_VELOCITY:
1001
 
                case AL_DIRECTION:
1002
 
                    alGetSource3f(source, eParam, pflValues+0, pflValues+1, pflValues+2);
1003
 
                    break;
1004
 
 
1005
1072
                case AL_SAMPLE_RW_OFFSETS_SOFT:
1006
1073
                case AL_BYTE_RW_OFFSETS_SOFT:
 
1074
                    LockContext(pContext);
1007
1075
                    updateLen = (ALdouble)pContext->Device->UpdateSize /
1008
1076
                                pContext->Device->Frequency;
1009
1077
                    GetSourceOffset(Source, eParam, Offsets, updateLen);
1010
 
                    pflValues[0] = Offsets[0];
1011
 
                    pflValues[1] = Offsets[1];
 
1078
                    UnlockContext(pContext);
 
1079
                    pflValues[0] = (ALfloat)Offsets[0];
 
1080
                    pflValues[1] = (ALfloat)Offsets[1];
1012
1081
                    break;
1013
1082
 
1014
1083
                default:
1022
1091
    else
1023
1092
        alSetError(pContext, AL_INVALID_VALUE);
1024
1093
 
1025
 
    ProcessContext(pContext);
 
1094
    ALCcontext_DecRef(pContext);
1026
1095
}
1027
1096
 
1028
1097
 
1029
1098
AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValue)
1030
1099
{
 
1100
    ALbufferlistitem *BufferList;
1031
1101
    ALCcontext *pContext;
1032
1102
    ALsource   *Source;
1033
1103
    ALdouble   Offsets[2];
1034
1104
    ALdouble   updateLen;
1035
1105
 
1036
 
    pContext = GetContextSuspended();
 
1106
    pContext = GetContextRef();
1037
1107
    if(!pContext) return;
1038
1108
 
1039
1109
    if(plValue)
1040
1110
    {
1041
 
        if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
1111
        if((Source=LookupSource(pContext, source)) != NULL)
1042
1112
        {
1043
1113
            switch(eParam)
1044
1114
            {
1071
1141
                    break;
1072
1142
 
1073
1143
                case AL_BUFFER:
1074
 
                    *plValue = (Source->Buffer ? Source->Buffer->buffer : 0);
 
1144
                    LockContext(pContext);
 
1145
                    BufferList = Source->queue;
 
1146
                    if(Source->lSourceType != AL_STATIC)
 
1147
                    {
 
1148
                        ALuint i = Source->BuffersPlayed;
 
1149
                        while(i > 0)
 
1150
                        {
 
1151
                            BufferList = BufferList->next;
 
1152
                            i--;
 
1153
                        }
 
1154
                    }
 
1155
                    *plValue = ((BufferList && BufferList->buffer) ?
 
1156
                                BufferList->buffer->buffer : 0);
 
1157
                    UnlockContext(pContext);
1075
1158
                    break;
1076
1159
 
1077
1160
                case AL_SOURCE_STATE:
1083
1166
                    break;
1084
1167
 
1085
1168
                case AL_BUFFERS_PROCESSED:
 
1169
                    LockContext(pContext);
1086
1170
                    if(Source->bLooping || Source->lSourceType != AL_STREAMING)
1087
1171
                    {
1088
1172
                        /* Buffers on a looping source are in a perpetual state
1091
1175
                    }
1092
1176
                    else
1093
1177
                        *plValue = Source->BuffersPlayed;
 
1178
                    UnlockContext(pContext);
1094
1179
                    break;
1095
1180
 
1096
1181
                case AL_SOURCE_TYPE:
1100
1185
                case AL_SEC_OFFSET:
1101
1186
                case AL_SAMPLE_OFFSET:
1102
1187
                case AL_BYTE_OFFSET:
 
1188
                    LockContext(pContext);
1103
1189
                    updateLen = (ALdouble)pContext->Device->UpdateSize /
1104
1190
                                pContext->Device->Frequency;
1105
1191
                    GetSourceOffset(Source, eParam, Offsets, updateLen);
 
1192
                    UnlockContext(pContext);
1106
1193
                    *plValue = (ALint)Offsets[0];
1107
1194
                    break;
1108
1195
 
1109
 
                case AL_DIRECT_FILTER:
1110
 
                    *plValue = Source->DirectFilter.filter;
1111
 
                    break;
1112
 
 
1113
1196
                case AL_DIRECT_FILTER_GAINHF_AUTO:
1114
1197
                    *plValue = Source->DryGainHFAuto;
1115
1198
                    break;
1126
1209
                    *plValue = (ALint)Source->DopplerFactor;
1127
1210
                    break;
1128
1211
 
 
1212
                case AL_DIRECT_CHANNELS_SOFT:
 
1213
                    *plValue = Source->DirectChannels;
 
1214
                    break;
 
1215
 
1129
1216
                case AL_DISTANCE_MODEL:
1130
1217
                    *plValue = Source->DistanceModel;
1131
1218
                    break;
1141
1228
    else
1142
1229
        alSetError(pContext, AL_INVALID_VALUE);
1143
1230
 
1144
 
    ProcessContext(pContext);
 
1231
    ALCcontext_DecRef(pContext);
1145
1232
}
1146
1233
 
1147
1234
 
1150
1237
    ALCcontext  *pContext;
1151
1238
    ALsource    *Source;
1152
1239
 
1153
 
    pContext = GetContextSuspended();
 
1240
    pContext = GetContextRef();
1154
1241
    if(!pContext) return;
1155
1242
 
1156
1243
    if(plValue1 && plValue2 && plValue3)
1157
1244
    {
1158
 
        if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
1245
        if((Source=LookupSource(pContext, source)) != NULL)
1159
1246
        {
1160
1247
            switch(eParam)
1161
1248
            {
1162
1249
                case AL_POSITION:
 
1250
                    LockContext(pContext);
1163
1251
                    *plValue1 = (ALint)Source->vPosition[0];
1164
1252
                    *plValue2 = (ALint)Source->vPosition[1];
1165
1253
                    *plValue3 = (ALint)Source->vPosition[2];
 
1254
                    UnlockContext(pContext);
1166
1255
                    break;
1167
1256
 
1168
1257
                case AL_VELOCITY:
 
1258
                    LockContext(pContext);
1169
1259
                    *plValue1 = (ALint)Source->vVelocity[0];
1170
1260
                    *plValue2 = (ALint)Source->vVelocity[1];
1171
1261
                    *plValue3 = (ALint)Source->vVelocity[2];
 
1262
                    UnlockContext(pContext);
1172
1263
                    break;
1173
1264
 
1174
1265
                case AL_DIRECTION:
 
1266
                    LockContext(pContext);
1175
1267
                    *plValue1 = (ALint)Source->vOrientation[0];
1176
1268
                    *plValue2 = (ALint)Source->vOrientation[1];
1177
1269
                    *plValue3 = (ALint)Source->vOrientation[2];
 
1270
                    UnlockContext(pContext);
1178
1271
                    break;
1179
1272
 
1180
1273
                default:
1188
1281
    else
1189
1282
        alSetError(pContext, AL_INVALID_VALUE);
1190
1283
 
1191
 
    ProcessContext(pContext);
 
1284
    ALCcontext_DecRef(pContext);
1192
1285
}
1193
1286
 
1194
1287
 
1199
1292
    ALdouble    Offsets[2];
1200
1293
    ALdouble    updateLen;
1201
1294
 
1202
 
    pContext = GetContextSuspended();
 
1295
    switch(eParam)
 
1296
    {
 
1297
        case AL_SOURCE_RELATIVE:
 
1298
        case AL_CONE_INNER_ANGLE:
 
1299
        case AL_CONE_OUTER_ANGLE:
 
1300
        case AL_LOOPING:
 
1301
        case AL_BUFFER:
 
1302
        case AL_SOURCE_STATE:
 
1303
        case AL_BUFFERS_QUEUED:
 
1304
        case AL_BUFFERS_PROCESSED:
 
1305
        case AL_SEC_OFFSET:
 
1306
        case AL_SAMPLE_OFFSET:
 
1307
        case AL_BYTE_OFFSET:
 
1308
        case AL_MAX_DISTANCE:
 
1309
        case AL_ROLLOFF_FACTOR:
 
1310
        case AL_DOPPLER_FACTOR:
 
1311
        case AL_REFERENCE_DISTANCE:
 
1312
        case AL_SOURCE_TYPE:
 
1313
        case AL_DIRECT_FILTER:
 
1314
        case AL_DIRECT_FILTER_GAINHF_AUTO:
 
1315
        case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
 
1316
        case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
 
1317
        case AL_DISTANCE_MODEL:
 
1318
        case AL_DIRECT_CHANNELS_SOFT:
 
1319
            alGetSourcei(source, eParam, plValues);
 
1320
            return;
 
1321
 
 
1322
        case AL_POSITION:
 
1323
        case AL_VELOCITY:
 
1324
        case AL_DIRECTION:
 
1325
            alGetSource3i(source, eParam, plValues+0, plValues+1, plValues+2);
 
1326
            return;
 
1327
    }
 
1328
 
 
1329
    pContext = GetContextRef();
1203
1330
    if(!pContext) return;
1204
1331
 
1205
1332
    if(plValues)
1206
1333
    {
1207
 
        if((Source=LookupSource(pContext->SourceMap, source)) != NULL)
 
1334
        if((Source=LookupSource(pContext, source)) != NULL)
1208
1335
        {
1209
1336
            switch(eParam)
1210
1337
            {
1211
 
                case AL_SOURCE_RELATIVE:
1212
 
                case AL_CONE_INNER_ANGLE:
1213
 
                case AL_CONE_OUTER_ANGLE:
1214
 
                case AL_LOOPING:
1215
 
                case AL_BUFFER:
1216
 
                case AL_SOURCE_STATE:
1217
 
                case AL_BUFFERS_QUEUED:
1218
 
                case AL_BUFFERS_PROCESSED:
1219
 
                case AL_SEC_OFFSET:
1220
 
                case AL_SAMPLE_OFFSET:
1221
 
                case AL_BYTE_OFFSET:
1222
 
                case AL_MAX_DISTANCE:
1223
 
                case AL_ROLLOFF_FACTOR:
1224
 
                case AL_DOPPLER_FACTOR:
1225
 
                case AL_REFERENCE_DISTANCE:
1226
 
                case AL_SOURCE_TYPE:
1227
 
                case AL_DIRECT_FILTER:
1228
 
                case AL_DIRECT_FILTER_GAINHF_AUTO:
1229
 
                case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1230
 
                case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1231
 
                case AL_DISTANCE_MODEL:
1232
 
                    alGetSourcei(source, eParam, plValues);
1233
 
                    break;
1234
 
 
1235
 
                case AL_POSITION:
1236
 
                case AL_VELOCITY:
1237
 
                case AL_DIRECTION:
1238
 
                    alGetSource3i(source, eParam, plValues+0, plValues+1, plValues+2);
1239
 
                    break;
1240
 
 
1241
1338
                case AL_SAMPLE_RW_OFFSETS_SOFT:
1242
1339
                case AL_BYTE_RW_OFFSETS_SOFT:
 
1340
                    LockContext(pContext);
1243
1341
                    updateLen = (ALdouble)pContext->Device->UpdateSize /
1244
1342
                                pContext->Device->Frequency;
1245
1343
                    GetSourceOffset(Source, eParam, Offsets, updateLen);
 
1344
                    UnlockContext(pContext);
1246
1345
                    plValues[0] = (ALint)Offsets[0];
1247
1346
                    plValues[1] = (ALint)Offsets[1];
1248
1347
                    break;
1258
1357
    else
1259
1358
        alSetError(pContext, AL_INVALID_VALUE);
1260
1359
 
1261
 
    ProcessContext(pContext);
 
1360
    ALCcontext_DecRef(pContext);
1262
1361
}
1263
1362
 
1264
1363
 
1271
1370
{
1272
1371
    ALCcontext       *Context;
1273
1372
    ALsource         *Source;
1274
 
    ALbufferlistitem *BufferList;
1275
 
    ALsizei          i, j;
 
1373
    ALsizei          i;
1276
1374
 
1277
 
    Context = GetContextSuspended();
 
1375
    Context = GetContextRef();
1278
1376
    if(!Context) return;
1279
1377
 
1280
1378
    if(n < 0)
1291
1389
    // Check that all the Sources are valid
1292
1390
    for(i = 0;i < n;i++)
1293
1391
    {
1294
 
        if(!LookupSource(Context->SourceMap, sources[i]))
 
1392
        if(!LookupSource(Context, sources[i]))
1295
1393
        {
1296
1394
            alSetError(Context, AL_INVALID_NAME);
1297
1395
            goto done;
1298
1396
        }
1299
1397
    }
1300
1398
 
 
1399
    LockContext(Context);
1301
1400
    while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
1302
1401
    {
1303
1402
        void *temp = NULL;
1309
1408
                           sizeof(*Context->ActiveSources) * newcount);
1310
1409
        if(!temp)
1311
1410
        {
 
1411
            UnlockContext(Context);
1312
1412
            alSetError(Context, AL_OUT_OF_MEMORY);
1313
1413
            goto done;
1314
1414
        }
1319
1419
 
1320
1420
    for(i = 0;i < n;i++)
1321
1421
    {
1322
 
        Source = (ALsource*)ALTHUNK_LOOKUPENTRY(sources[i]);
1323
 
 
1324
 
        // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1325
 
        BufferList = Source->queue;
1326
 
        while(BufferList)
1327
 
        {
1328
 
            if(BufferList->buffer != NULL && BufferList->buffer->size)
1329
 
                break;
1330
 
            BufferList = BufferList->next;
1331
 
        }
1332
 
 
1333
 
        if(!BufferList)
1334
 
        {
1335
 
            Source->state = AL_STOPPED;
1336
 
            Source->BuffersPlayed = Source->BuffersInQueue;
1337
 
            Source->position = 0;
1338
 
            Source->position_fraction = 0;
1339
 
            Source->lOffset = 0;
1340
 
            continue;
1341
 
        }
1342
 
 
1343
 
        if(Source->state != AL_PAUSED)
1344
 
        {
1345
 
            Source->state = AL_PLAYING;
1346
 
            Source->position = 0;
1347
 
            Source->position_fraction = 0;
1348
 
            Source->BuffersPlayed = 0;
1349
 
 
1350
 
            Source->Buffer = Source->queue->buffer;
1351
 
        }
1352
 
        else
1353
 
            Source->state = AL_PLAYING;
1354
 
 
1355
 
        // Check if an Offset has been set
1356
 
        if(Source->lOffset)
1357
 
            ApplyOffset(Source);
1358
 
 
1359
 
        // If device is disconnected, go right to stopped
1360
 
        if(!Context->Device->Connected)
1361
 
        {
1362
 
            Source->state = AL_STOPPED;
1363
 
            Source->BuffersPlayed = Source->BuffersInQueue;
1364
 
            Source->position = 0;
1365
 
            Source->position_fraction = 0;
1366
 
        }
1367
 
        else
1368
 
        {
1369
 
            for(j = 0;j < Context->ActiveSourceCount;j++)
1370
 
            {
1371
 
                if(Context->ActiveSources[j] == Source)
1372
 
                    break;
1373
 
            }
1374
 
            if(j == Context->ActiveSourceCount)
1375
 
                Context->ActiveSources[Context->ActiveSourceCount++] = Source;
1376
 
        }
 
1422
        Source = LookupSource(Context, sources[i]);
 
1423
        if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
 
1424
        else SetSourceState(Source, Context, AL_PLAYING);
1377
1425
    }
 
1426
    UnlockContext(Context);
1378
1427
 
1379
1428
done:
1380
 
    ProcessContext(Context);
 
1429
    ALCcontext_DecRef(Context);
1381
1430
}
1382
1431
 
1383
1432
AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
1391
1440
    ALsource *Source;
1392
1441
    ALsizei i;
1393
1442
 
1394
 
    Context = GetContextSuspended();
 
1443
    Context = GetContextRef();
1395
1444
    if(!Context) return;
1396
1445
 
1397
1446
    if(n < 0)
1408
1457
    // Check all the Sources are valid
1409
1458
    for(i = 0;i < n;i++)
1410
1459
    {
1411
 
        if(!LookupSource(Context->SourceMap, sources[i]))
 
1460
        if(!LookupSource(Context, sources[i]))
1412
1461
        {
1413
1462
            alSetError(Context, AL_INVALID_NAME);
1414
1463
            goto done;
1415
1464
        }
1416
1465
    }
1417
1466
 
 
1467
    LockContext(Context);
1418
1468
    for(i = 0;i < n;i++)
1419
1469
    {
1420
 
        Source = (ALsource*)ALTHUNK_LOOKUPENTRY(sources[i]);
1421
 
        if(Source->state == AL_PLAYING)
1422
 
            Source->state = AL_PAUSED;
 
1470
        Source = LookupSource(Context, sources[i]);
 
1471
        if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
 
1472
        else SetSourceState(Source, Context, AL_PAUSED);
1423
1473
    }
 
1474
    UnlockContext(Context);
1424
1475
 
1425
1476
done:
1426
 
    ProcessContext(Context);
 
1477
    ALCcontext_DecRef(Context);
1427
1478
}
1428
1479
 
1429
1480
AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
1437
1488
    ALsource *Source;
1438
1489
    ALsizei i;
1439
1490
 
1440
 
    Context = GetContextSuspended();
 
1491
    Context = GetContextRef();
1441
1492
    if(!Context) return;
1442
1493
 
1443
1494
    if(n < 0)
1454
1505
    // Check all the Sources are valid
1455
1506
    for(i = 0;i < n;i++)
1456
1507
    {
1457
 
        if(!LookupSource(Context->SourceMap, sources[i]))
 
1508
        if(!LookupSource(Context, sources[i]))
1458
1509
        {
1459
1510
            alSetError(Context, AL_INVALID_NAME);
1460
1511
            goto done;
1461
1512
        }
1462
1513
    }
1463
1514
 
 
1515
    LockContext(Context);
1464
1516
    for(i = 0;i < n;i++)
1465
1517
    {
1466
 
        Source = (ALsource*)ALTHUNK_LOOKUPENTRY(sources[i]);
1467
 
        if(Source->state != AL_INITIAL)
1468
 
        {
1469
 
            Source->state = AL_STOPPED;
1470
 
            Source->BuffersPlayed = Source->BuffersInQueue;
1471
 
        }
1472
 
        Source->lOffset = 0;
 
1518
        Source = LookupSource(Context, sources[i]);
 
1519
        Source->new_state = AL_NONE;
 
1520
        SetSourceState(Source, Context, AL_STOPPED);
1473
1521
    }
 
1522
    UnlockContext(Context);
1474
1523
 
1475
1524
done:
1476
 
    ProcessContext(Context);
 
1525
    ALCcontext_DecRef(Context);
1477
1526
}
1478
1527
 
1479
1528
AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
1487
1536
    ALsource *Source;
1488
1537
    ALsizei i;
1489
1538
 
1490
 
    Context = GetContextSuspended();
 
1539
    Context = GetContextRef();
1491
1540
    if(!Context) return;
1492
1541
 
1493
1542
    if(n < 0)
1504
1553
    // Check all the Sources are valid
1505
1554
    for(i = 0;i < n;i++)
1506
1555
    {
1507
 
        if(!LookupSource(Context->SourceMap, sources[i]))
 
1556
        if(!LookupSource(Context, sources[i]))
1508
1557
        {
1509
1558
            alSetError(Context, AL_INVALID_NAME);
1510
1559
            goto done;
1511
1560
        }
1512
1561
    }
1513
1562
 
 
1563
    LockContext(Context);
1514
1564
    for(i = 0;i < n;i++)
1515
1565
    {
1516
 
        Source = (ALsource*)ALTHUNK_LOOKUPENTRY(sources[i]);
1517
 
        if(Source->state != AL_INITIAL)
1518
 
        {
1519
 
            Source->state = AL_INITIAL;
1520
 
            Source->position = 0;
1521
 
            Source->position_fraction = 0;
1522
 
            Source->BuffersPlayed = 0;
1523
 
            if(Source->queue)
1524
 
                Source->Buffer = Source->queue->buffer;
1525
 
        }
1526
 
        Source->lOffset = 0;
 
1566
        Source = LookupSource(Context, sources[i]);
 
1567
        Source->new_state = AL_NONE;
 
1568
        SetSourceState(Source, Context, AL_INITIAL);
1527
1569
    }
 
1570
    UnlockContext(Context);
1528
1571
 
1529
1572
done:
1530
 
    ProcessContext(Context);
 
1573
    ALCcontext_DecRef(Context);
1531
1574
}
1532
1575
 
1533
1576
 
1536
1579
    ALCcontext *Context;
1537
1580
    ALCdevice *device;
1538
1581
    ALsource *Source;
1539
 
    ALbuffer *buffer;
1540
1582
    ALsizei i;
1541
 
    ALbufferlistitem *BufferListStart;
 
1583
    ALbufferlistitem *BufferListStart = NULL;
1542
1584
    ALbufferlistitem *BufferList;
1543
1585
    ALbuffer *BufferFmt;
1544
1586
 
1545
1587
    if(n == 0)
1546
1588
        return;
1547
1589
 
1548
 
    Context = GetContextSuspended();
 
1590
    Context = GetContextRef();
1549
1591
    if(!Context) return;
1550
1592
 
1551
1593
    if(n < 0)
1552
1594
    {
1553
1595
        alSetError(Context, AL_INVALID_VALUE);
1554
 
        goto done;
 
1596
        goto error;
1555
1597
    }
1556
1598
 
1557
1599
    // Check that all buffers are valid or zero and that the source is valid
1558
1600
 
1559
1601
    // Check that this is a valid source
1560
 
    if((Source=LookupSource(Context->SourceMap, source)) == NULL)
 
1602
    if((Source=LookupSource(Context, source)) == NULL)
1561
1603
    {
1562
1604
        alSetError(Context, AL_INVALID_NAME);
1563
 
        goto done;
 
1605
        goto error;
1564
1606
    }
1565
1607
 
 
1608
    LockContext(Context);
1566
1609
    // Check that this is not a STATIC Source
1567
1610
    if(Source->lSourceType == AL_STATIC)
1568
1611
    {
 
1612
        UnlockContext(Context);
1569
1613
        // Invalid Source Type (can't queue on a Static Source)
1570
1614
        alSetError(Context, AL_INVALID_OPERATION);
1571
 
        goto done;
 
1615
        goto error;
1572
1616
    }
1573
1617
 
1574
1618
    device = Context->Device;
1589
1633
 
1590
1634
    for(i = 0;i < n;i++)
1591
1635
    {
1592
 
        if(!buffers[i])
1593
 
            continue;
1594
 
 
1595
 
        if((buffer=LookupBuffer(device->BufferMap, buffers[i])) == NULL)
 
1636
        ALbuffer *buffer = NULL;
 
1637
        if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
1596
1638
        {
 
1639
            UnlockContext(Context);
1597
1640
            alSetError(Context, AL_INVALID_NAME);
1598
 
            goto done;
1599
 
        }
1600
 
 
 
1641
            goto error;
 
1642
        }
 
1643
 
 
1644
        if(!BufferListStart)
 
1645
        {
 
1646
            BufferListStart = malloc(sizeof(ALbufferlistitem));
 
1647
            BufferListStart->buffer = buffer;
 
1648
            BufferListStart->next = NULL;
 
1649
            BufferListStart->prev = NULL;
 
1650
            BufferList = BufferListStart;
 
1651
        }
 
1652
        else
 
1653
        {
 
1654
            BufferList->next = malloc(sizeof(ALbufferlistitem));
 
1655
            BufferList->next->buffer = buffer;
 
1656
            BufferList->next->next = NULL;
 
1657
            BufferList->next->prev = BufferList;
 
1658
            BufferList = BufferList->next;
 
1659
        }
 
1660
        if(!buffer) continue;
 
1661
 
 
1662
        // Increment reference counter for buffer
 
1663
        IncrementRef(&buffer->ref);
 
1664
        ReadLock(&buffer->lock);
1601
1665
        if(BufferFmt == NULL)
1602
1666
        {
1603
1667
            BufferFmt = buffer;
1604
1668
 
 
1669
            Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
 
1670
            Source->SampleSize  = BytesFromFmt(buffer->FmtType);
1605
1671
            if(buffer->FmtChannels == FmtMono)
1606
1672
                Source->Update = CalcSourceParams;
1607
1673
            else
1613
1679
                BufferFmt->OriginalChannels != buffer->OriginalChannels ||
1614
1680
                BufferFmt->OriginalType != buffer->OriginalType)
1615
1681
        {
 
1682
            ReadUnlock(&buffer->lock);
 
1683
            UnlockContext(Context);
1616
1684
            alSetError(Context, AL_INVALID_OPERATION);
1617
 
            goto done;
 
1685
            goto error;
1618
1686
        }
 
1687
        ReadUnlock(&buffer->lock);
1619
1688
    }
1620
1689
 
1621
1690
    // Change Source Type
1622
1691
    Source->lSourceType = AL_STREAMING;
1623
1692
 
1624
 
    buffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(buffers[0]);
1625
 
 
1626
 
    // All buffers are valid - so add them to the list
1627
 
    BufferListStart = malloc(sizeof(ALbufferlistitem));
1628
 
    BufferListStart->buffer = buffer;
1629
 
    BufferListStart->next = NULL;
1630
 
    BufferListStart->prev = NULL;
1631
 
 
1632
 
    // Increment reference counter for buffer
1633
 
    if(buffer) buffer->refcount++;
1634
 
 
1635
 
    BufferList = BufferListStart;
1636
 
 
1637
 
    for(i = 1;i < n;i++)
1638
 
    {
1639
 
        buffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(buffers[i]);
1640
 
 
1641
 
        BufferList->next = malloc(sizeof(ALbufferlistitem));
1642
 
        BufferList->next->buffer = buffer;
1643
 
        BufferList->next->next = NULL;
1644
 
        BufferList->next->prev = BufferList;
1645
 
 
1646
 
        // Increment reference counter for buffer
1647
 
        if(buffer) buffer->refcount++;
1648
 
 
1649
 
        BufferList = BufferList->next;
1650
 
    }
1651
 
 
1652
1693
    if(Source->queue == NULL)
1653
 
    {
1654
1694
        Source->queue = BufferListStart;
1655
 
        // Update Current Buffer
1656
 
        Source->Buffer = BufferListStart->buffer;
1657
 
    }
1658
1695
    else
1659
1696
    {
1660
1697
        // Find end of queue
1662
1699
        while(BufferList->next != NULL)
1663
1700
            BufferList = BufferList->next;
1664
1701
 
 
1702
        BufferListStart->prev = BufferList;
1665
1703
        BufferList->next = BufferListStart;
1666
 
        BufferList->next->prev = BufferList;
1667
1704
    }
1668
1705
 
1669
1706
    // Update number of buffers in queue
1670
1707
    Source->BuffersInQueue += n;
1671
1708
 
1672
 
done:
1673
 
    ProcessContext(Context);
 
1709
    UnlockContext(Context);
 
1710
    ALCcontext_DecRef(Context);
 
1711
    return;
 
1712
 
 
1713
error:
 
1714
    while(BufferListStart)
 
1715
    {
 
1716
        BufferList = BufferListStart;
 
1717
        BufferListStart = BufferList->next;
 
1718
 
 
1719
        if(BufferList->buffer)
 
1720
            DecrementRef(&BufferList->buffer->ref);
 
1721
        free(BufferList);
 
1722
    }
 
1723
    ALCcontext_DecRef(Context);
1674
1724
}
1675
1725
 
1676
1726
 
1686
1736
    if(n == 0)
1687
1737
        return;
1688
1738
 
1689
 
    Context = GetContextSuspended();
 
1739
    Context = GetContextRef();
1690
1740
    if(!Context) return;
1691
1741
 
1692
1742
    if(n < 0)
1695
1745
        goto done;
1696
1746
    }
1697
1747
 
1698
 
    if((Source=LookupSource(Context->SourceMap, source)) == NULL)
 
1748
    if((Source=LookupSource(Context, source)) == NULL)
1699
1749
    {
1700
1750
        alSetError(Context, AL_INVALID_NAME);
1701
1751
        goto done;
1702
1752
    }
1703
1753
 
 
1754
    LockContext(Context);
1704
1755
    if(Source->bLooping || Source->lSourceType != AL_STREAMING ||
1705
1756
       (ALuint)n > Source->BuffersPlayed)
1706
1757
    {
 
1758
        UnlockContext(Context);
1707
1759
        // Some buffers can't be unqueue because they have not been processed
1708
1760
        alSetError(Context, AL_INVALID_VALUE);
1709
1761
        goto done;
1713
1765
    {
1714
1766
        BufferList = Source->queue;
1715
1767
        Source->queue = BufferList->next;
 
1768
        Source->BuffersInQueue--;
 
1769
        Source->BuffersPlayed--;
1716
1770
 
1717
1771
        if(BufferList->buffer)
1718
1772
        {
1719
1773
            // Record name of buffer
1720
1774
            buffers[i] = BufferList->buffer->buffer;
1721
1775
            // Decrement buffer reference counter
1722
 
            BufferList->buffer->refcount--;
 
1776
            DecrementRef(&BufferList->buffer->ref);
1723
1777
        }
1724
1778
        else
1725
1779
            buffers[i] = 0;
1726
1780
 
1727
1781
        // Release memory for buffer list item
1728
1782
        free(BufferList);
1729
 
        Source->BuffersInQueue--;
1730
1783
    }
1731
1784
    if(Source->queue)
1732
1785
        Source->queue->prev = NULL;
1733
 
 
1734
 
    if(Source->state != AL_PLAYING)
1735
 
    {
1736
 
        if(Source->queue)
1737
 
            Source->Buffer = Source->queue->buffer;
1738
 
        else
1739
 
            Source->Buffer = NULL;
1740
 
    }
1741
 
    Source->BuffersPlayed -= n;
 
1786
    UnlockContext(Context);
1742
1787
 
1743
1788
done:
1744
 
    ProcessContext(Context);
 
1789
    ALCcontext_DecRef(Context);
1745
1790
}
1746
1791
 
1747
1792
 
1748
1793
static ALvoid InitSourceParams(ALsource *Source)
1749
1794
{
 
1795
    ALuint i;
 
1796
 
1750
1797
    Source->flInnerAngle = 360.0f;
1751
1798
    Source->flOuterAngle = 360.0f;
1752
1799
    Source->flPitch = 1.0f;
1775
1822
    Source->AirAbsorptionFactor = 0.0f;
1776
1823
    Source->RoomRolloffFactor = 0.0f;
1777
1824
    Source->DopplerFactor = 1.0f;
 
1825
    Source->DirectChannels = AL_FALSE;
1778
1826
 
1779
 
    Source->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
 
1827
    Source->DistanceModel = DefaultDistanceModel;
1780
1828
 
1781
1829
    Source->Resampler = DefaultResampler;
1782
1830
 
1783
1831
    Source->state = AL_INITIAL;
 
1832
    Source->new_state = AL_NONE;
1784
1833
    Source->lSourceType = AL_UNDETERMINED;
 
1834
    Source->lOffset = -1;
 
1835
 
 
1836
    Source->DirectGain = 1.0f;
 
1837
    Source->DirectGainHF = 1.0f;
 
1838
    for(i = 0;i < MAX_SENDS;i++)
 
1839
    {
 
1840
        Source->Send[i].WetGain = 1.0f;
 
1841
        Source->Send[i].WetGainHF = 1.0f;
 
1842
    }
1785
1843
 
1786
1844
    Source->NeedsUpdate = AL_TRUE;
1787
1845
 
1788
 
    Source->Buffer = NULL;
1789
 
}
1790
 
 
 
1846
    Source->HrtfMoving = AL_FALSE;
 
1847
    Source->HrtfCounter = 0;
 
1848
}
 
1849
 
 
1850
 
 
1851
/*
 
1852
 * SetSourceState
 
1853
 *
 
1854
 * Sets the source's new play state given its current state
 
1855
 */
 
1856
ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
 
1857
{
 
1858
    if(state == AL_PLAYING)
 
1859
    {
 
1860
        ALbufferlistitem *BufferList;
 
1861
        ALsizei j, k;
 
1862
 
 
1863
        /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */
 
1864
        BufferList = Source->queue;
 
1865
        while(BufferList)
 
1866
        {
 
1867
            if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
 
1868
                break;
 
1869
            BufferList = BufferList->next;
 
1870
        }
 
1871
 
 
1872
        if(Source->state != AL_PLAYING)
 
1873
        {
 
1874
            for(j = 0;j < MAXCHANNELS;j++)
 
1875
            {
 
1876
                for(k = 0;k < SRC_HISTORY_LENGTH;k++)
 
1877
                    Source->HrtfHistory[j][k] = 0.0f;
 
1878
                for(k = 0;k < HRIR_LENGTH;k++)
 
1879
                {
 
1880
                    Source->HrtfValues[j][k][0] = 0.0f;
 
1881
                    Source->HrtfValues[j][k][1] = 0.0f;
 
1882
                }
 
1883
            }
 
1884
        }
 
1885
 
 
1886
        if(Source->state != AL_PAUSED)
 
1887
        {
 
1888
            Source->state = AL_PLAYING;
 
1889
            Source->position = 0;
 
1890
            Source->position_fraction = 0;
 
1891
            Source->BuffersPlayed = 0;
 
1892
        }
 
1893
        else
 
1894
            Source->state = AL_PLAYING;
 
1895
 
 
1896
        // Check if an Offset has been set
 
1897
        if(Source->lOffset != -1)
 
1898
            ApplyOffset(Source);
 
1899
 
 
1900
        /* If there's nothing to play, or device is disconnected, go right to
 
1901
         * stopped */
 
1902
        if(!BufferList || !Context->Device->Connected)
 
1903
        {
 
1904
            SetSourceState(Source, Context, AL_STOPPED);
 
1905
            return;
 
1906
        }
 
1907
 
 
1908
        for(j = 0;j < Context->ActiveSourceCount;j++)
 
1909
        {
 
1910
            if(Context->ActiveSources[j] == Source)
 
1911
                break;
 
1912
        }
 
1913
        if(j == Context->ActiveSourceCount)
 
1914
            Context->ActiveSources[Context->ActiveSourceCount++] = Source;
 
1915
    }
 
1916
    else if(state == AL_PAUSED)
 
1917
    {
 
1918
        if(Source->state == AL_PLAYING)
 
1919
        {
 
1920
            Source->state = AL_PAUSED;
 
1921
            Source->HrtfMoving = AL_FALSE;
 
1922
            Source->HrtfCounter = 0;
 
1923
        }
 
1924
    }
 
1925
    else if(state == AL_STOPPED)
 
1926
    {
 
1927
        if(Source->state != AL_INITIAL)
 
1928
        {
 
1929
            Source->state = AL_STOPPED;
 
1930
            Source->BuffersPlayed = Source->BuffersInQueue;
 
1931
            Source->HrtfMoving = AL_FALSE;
 
1932
            Source->HrtfCounter = 0;
 
1933
        }
 
1934
        Source->lOffset = -1;
 
1935
    }
 
1936
    else if(state == AL_INITIAL)
 
1937
    {
 
1938
        if(Source->state != AL_INITIAL)
 
1939
        {
 
1940
            Source->state = AL_INITIAL;
 
1941
            Source->position = 0;
 
1942
            Source->position_fraction = 0;
 
1943
            Source->BuffersPlayed = 0;
 
1944
            Source->HrtfMoving = AL_FALSE;
 
1945
            Source->HrtfCounter = 0;
 
1946
        }
 
1947
        Source->lOffset = -1;
 
1948
    }
 
1949
}
1791
1950
 
1792
1951
/*
1793
1952
    GetSourceOffset
1799
1958
{
1800
1959
    const ALbufferlistitem *BufferList;
1801
1960
    const ALbuffer         *Buffer = NULL;
1802
 
    enum UserFmtType OriginalType;
1803
 
    ALsizei BufferFreq;
1804
 
    ALint   Channels, Bytes;
 
1961
    ALuint  BufferFreq = 0;
1805
1962
    ALuint  readPos, writePos;
1806
 
    ALuint  TotalBufferDataSize;
 
1963
    ALuint  totalBufferLen;
1807
1964
    ALuint  i;
1808
1965
 
1809
1966
    // Find the first non-NULL Buffer in the Queue
1813
1970
        if(BufferList->buffer)
1814
1971
        {
1815
1972
            Buffer = BufferList->buffer;
 
1973
            BufferFreq = Buffer->Frequency;
1816
1974
            break;
1817
1975
        }
1818
1976
        BufferList = BufferList->next;
1825
1983
        return;
1826
1984
    }
1827
1985
 
1828
 
    // Get Current Buffer Size and frequency (in milliseconds)
1829
 
    BufferFreq = Buffer->Frequency;
1830
 
    OriginalType = Buffer->OriginalType;
1831
 
    Channels = ChannelsFromFmt(Buffer->FmtChannels);
1832
 
    Bytes = BytesFromFmt(Buffer->FmtType);
 
1986
    if(updateLen > 0.0 && updateLen < 0.015)
 
1987
        updateLen = 0.015;
1833
1988
 
1834
 
    // Get Current BytesPlayed (NOTE : This is the byte offset into the *current* buffer)
1835
 
    readPos = Source->position * Channels * Bytes;
1836
 
    // Add byte length of any processed buffers in the queue
1837
 
    TotalBufferDataSize = 0;
 
1989
    // Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
 
1990
    readPos = Source->position;
 
1991
    // Add length of any processed buffers in the queue
 
1992
    totalBufferLen = 0;
1838
1993
    BufferList = Source->queue;
1839
1994
    for(i = 0;BufferList;i++)
1840
1995
    {
1841
1996
        if(BufferList->buffer)
1842
1997
        {
1843
1998
            if(i < Source->BuffersPlayed)
1844
 
                readPos += BufferList->buffer->size;
1845
 
            TotalBufferDataSize += BufferList->buffer->size;
 
1999
                readPos += BufferList->buffer->SampleLen;
 
2000
            totalBufferLen += BufferList->buffer->SampleLen;
1846
2001
        }
1847
2002
        BufferList = BufferList->next;
1848
2003
    }
1849
2004
    if(Source->state == AL_PLAYING)
1850
 
        writePos = readPos + ((ALuint)(updateLen*BufferFreq) * Channels * Bytes);
 
2005
        writePos = readPos + (ALuint)(updateLen*BufferFreq);
1851
2006
    else
1852
2007
        writePos = readPos;
1853
2008
 
1854
2009
    if(Source->bLooping)
1855
2010
    {
1856
 
        readPos %= TotalBufferDataSize;
1857
 
        writePos %= TotalBufferDataSize;
 
2011
        readPos %= totalBufferLen;
 
2012
        writePos %= totalBufferLen;
1858
2013
    }
1859
2014
    else
1860
2015
    {
1861
2016
        // Wrap positions back to 0
1862
 
        if(readPos >= TotalBufferDataSize)
 
2017
        if(readPos >= totalBufferLen)
1863
2018
            readPos = 0;
1864
 
        if(writePos >= TotalBufferDataSize)
 
2019
        if(writePos >= totalBufferLen)
1865
2020
            writePos = 0;
1866
2021
    }
1867
2022
 
1868
2023
    switch(name)
1869
2024
    {
1870
2025
        case AL_SEC_OFFSET:
1871
 
            offset[0] = (ALdouble)readPos / (Channels * Bytes * BufferFreq);
1872
 
            offset[1] = (ALdouble)writePos / (Channels * Bytes * BufferFreq);
 
2026
            offset[0] = (ALdouble)readPos / Buffer->Frequency;
 
2027
            offset[1] = (ALdouble)writePos / Buffer->Frequency;
1873
2028
            break;
1874
2029
        case AL_SAMPLE_OFFSET:
1875
2030
        case AL_SAMPLE_RW_OFFSETS_SOFT:
1876
 
            offset[0] = (ALdouble)(readPos / (Channels * Bytes));
1877
 
            offset[1] = (ALdouble)(writePos / (Channels * Bytes));
 
2031
            offset[0] = (ALdouble)readPos;
 
2032
            offset[1] = (ALdouble)writePos;
1878
2033
            break;
1879
2034
        case AL_BYTE_OFFSET:
1880
2035
        case AL_BYTE_RW_OFFSETS_SOFT:
1881
2036
            // Take into account the original format of the Buffer
1882
 
            if(OriginalType == UserFmtIMA4)
 
2037
            if(Buffer->OriginalType == UserFmtIMA4)
1883
2038
            {
1884
 
                ALuint FrameBlockSize = 65 * Bytes * Channels;
1885
 
                ALuint BlockSize = 36 * Channels;
 
2039
                ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
 
2040
                ALuint FrameBlockSize = 65;
1886
2041
 
1887
2042
                // Round down to nearest ADPCM block
1888
2043
                offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
1897
2052
            }
1898
2053
            else
1899
2054
            {
1900
 
                ALuint OrigBytes = BytesFromUserFmt(OriginalType);
1901
 
                offset[0] = (ALdouble)(readPos / Bytes * OrigBytes);
1902
 
                offset[1] = (ALdouble)(writePos / Bytes * OrigBytes);
 
2055
                ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
 
2056
                offset[0] = (ALdouble)(readPos * FrameSize);
 
2057
                offset[1] = (ALdouble)(writePos * FrameSize);
1903
2058
            }
1904
2059
            break;
1905
2060
    }
1912
2067
    Apply a playback offset to the Source.  This function will update the queue (to correctly
1913
2068
    mark buffers as 'pending' or 'processed' depending upon the new offset.
1914
2069
*/
1915
 
static ALboolean ApplyOffset(ALsource *Source)
 
2070
ALboolean ApplyOffset(ALsource *Source)
1916
2071
{
1917
2072
    const ALbufferlistitem *BufferList;
1918
2073
    const ALbuffer         *Buffer;
1919
 
    ALint lBufferSize, lTotalBufferSize;
1920
 
    ALint BuffersPlayed;
1921
 
    ALint lByteOffset;
 
2074
    ALint bufferLen, totalBufferLen;
 
2075
    ALint buffersPlayed;
 
2076
    ALint offset;
1922
2077
 
1923
2078
    // Get true byte offset
1924
 
    lByteOffset = GetByteOffset(Source);
 
2079
    offset = GetSampleOffset(Source);
1925
2080
 
1926
2081
    // If the offset is invalid, don't apply it
1927
 
    if(lByteOffset == -1)
 
2082
    if(offset == -1)
1928
2083
        return AL_FALSE;
1929
2084
 
1930
2085
    // Sort out the queue (pending and processed states)
1931
2086
    BufferList = Source->queue;
1932
 
    lTotalBufferSize = 0;
1933
 
    BuffersPlayed = 0;
 
2087
    totalBufferLen = 0;
 
2088
    buffersPlayed = 0;
1934
2089
 
1935
2090
    while(BufferList)
1936
2091
    {
1937
2092
        Buffer = BufferList->buffer;
1938
 
        lBufferSize = Buffer ? Buffer->size : 0;
 
2093
        bufferLen = Buffer ? Buffer->SampleLen : 0;
1939
2094
 
1940
 
        if(lBufferSize <= lByteOffset-lTotalBufferSize)
 
2095
        if(bufferLen <= offset-totalBufferLen)
1941
2096
        {
1942
2097
            // Offset is past this buffer so increment BuffersPlayed
1943
 
            BuffersPlayed++;
 
2098
            buffersPlayed++;
1944
2099
        }
1945
 
        else if(lTotalBufferSize <= lByteOffset)
 
2100
        else if(totalBufferLen <= offset)
1946
2101
        {
1947
2102
            // Offset is within this buffer
1948
 
            // Set Current Buffer
1949
 
            Source->Buffer = BufferList->buffer;
1950
 
            Source->BuffersPlayed = BuffersPlayed;
 
2103
            Source->BuffersPlayed = buffersPlayed;
1951
2104
 
1952
2105
            // SW Mixer Positions are in Samples
1953
 
            Source->position = (lByteOffset - lTotalBufferSize) /
1954
 
                                FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
 
2106
            Source->position = offset - totalBufferLen;
1955
2107
            return AL_TRUE;
1956
2108
        }
1957
2109
 
1958
2110
        // Increment the TotalBufferSize
1959
 
        lTotalBufferSize += lBufferSize;
 
2111
        totalBufferLen += bufferLen;
1960
2112
 
1961
2113
        // Move on to next buffer in the Queue
1962
2114
        BufferList = BufferList->next;
1967
2119
 
1968
2120
 
1969
2121
/*
1970
 
    GetByteOffset
 
2122
    GetSampleOffset
1971
2123
 
1972
 
    Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
1973
 
    offset supplied by the application).   This takes into account the fact that the buffer format
1974
 
    may have been modifed by AL (e.g 8bit samples are converted to float)
 
2124
    Returns the sample offset into the Source's queue (from the Sample, Byte or Millisecond offset
 
2125
    supplied by the application). This takes into account the fact that the buffer format may have
 
2126
    been modifed by AL
1975
2127
*/
1976
 
static ALint GetByteOffset(ALsource *Source)
 
2128
static ALint GetSampleOffset(ALsource *Source)
1977
2129
{
1978
2130
    const ALbuffer *Buffer = NULL;
1979
2131
    const ALbufferlistitem *BufferList;
1980
 
    ALint ByteOffset = -1;
 
2132
    ALint Offset = -1;
1981
2133
 
1982
2134
    // Find the first non-NULL Buffer in the Queue
1983
2135
    BufferList = Source->queue;
1993
2145
 
1994
2146
    if(!Buffer)
1995
2147
    {
1996
 
        Source->lOffset = 0;
 
2148
        Source->lOffset = -1;
1997
2149
        return -1;
1998
2150
    }
1999
2151
 
2002
2154
    {
2003
2155
    case AL_BYTE_OFFSET:
2004
2156
        // Take into consideration the original format
2005
 
        ByteOffset = Source->lOffset;
 
2157
        Offset = Source->lOffset;
2006
2158
        if(Buffer->OriginalType == UserFmtIMA4)
2007
2159
        {
2008
2160
            // Round down to nearest ADPCM block
2009
 
            ByteOffset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
 
2161
            Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2010
2162
            // Multiply by compression rate (65 sample frames per block)
2011
 
            ByteOffset *= 65;
 
2163
            Offset *= 65;
2012
2164
        }
2013
2165
        else
2014
 
            ByteOffset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2015
 
        ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
 
2166
            Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2016
2167
        break;
2017
2168
 
2018
2169
    case AL_SAMPLE_OFFSET:
2019
 
        ByteOffset = Source->lOffset * FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
 
2170
        Offset = Source->lOffset;
2020
2171
        break;
2021
2172
 
2022
2173
    case AL_SEC_OFFSET:
2023
2174
        // Note - lOffset is internally stored as Milliseconds
2024
 
        ByteOffset  = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency);
2025
 
        ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType);
 
2175
        Offset = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency);
2026
2176
        break;
2027
2177
    }
2028
2178
    // Clear Offset
2029
 
    Source->lOffset = 0;
 
2179
    Source->lOffset = -1;
2030
2180
 
2031
 
    return ByteOffset;
 
2181
    return Offset;
2032
2182
}
2033
2183
 
2034
2184
 
2048
2198
            temp->queue = BufferList->next;
2049
2199
 
2050
2200
            if(BufferList->buffer != NULL)
2051
 
                BufferList->buffer->refcount--;
 
2201
                DecrementRef(&BufferList->buffer->ref);
2052
2202
            free(BufferList);
2053
2203
        }
2054
2204
 
2055
2205
        for(j = 0;j < MAX_SENDS;++j)
2056
2206
        {
2057
2207
            if(temp->Send[j].Slot)
2058
 
                temp->Send[j].Slot->refcount--;
 
2208
                DecrementRef(&temp->Send[j].Slot->ref);
2059
2209
            temp->Send[j].Slot = NULL;
2060
2210
        }
2061
2211
 
2062
2212
        // Release source structure
2063
 
        ALTHUNK_REMOVEENTRY(temp->source);
 
2213
        FreeThunkEntry(temp->source);
2064
2214
        memset(temp, 0, sizeof(ALsource));
2065
2215
        free(temp);
2066
2216
    }