Annotation of driverkit/libDriver/Kernel/AudioChannel.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*
                     25:  * AudioChannel.m
                     26:  *
                     27:  * Copyright (c) 1991, NeXT Computer, Inc.  All rights reserved.
                     28:  *
                     29:  *      Audio driver channel object.
                     30:  *
                     31:  * HISTORY
                     32:  *     06/22/94/wmg    HP modifications.
                     33:  *      11/17/93/rkd    Added XPRs.
                     34:  *      07/14/92/mtm    Original coding.
                     35:  */
                     36:  
                     37: #import "AudioChannel.h"
                     38: #import "AudioStream.h"
                     39: #import "InputStream.h"
                     40: #import "OutputStream.h"
                     41: #import <driverkit/IOAudio.h>
                     42: #import <driverkit/IOAudioPrivate.h>
                     43: #import "AudioCommand.h"
                     44: #import "audio_peak.h"
                     45: #import "audio_msgs.h"
                     46: #import "audioLog.h"
                     47: #import "AudioCommand.h"
                     48: #import "audio_kern_server.h"
                     49: #import <mach/vm_param.h>              // PAGE_SIZE
                     50: #import <driverkit/generalFuncs.h>
                     51: #import <driverkit/kernelDriver.h>     // IOPhysicalFromVirtual / IOVmTaskSelf
                     52: #import <bsd/string.h>                 // bzero
                     53: 
                     54: #if    i386
                     55: /*
                     56:  * Temporary function prototype for alloc_cnvmem
                     57:  * copied from <machdep/i386/i386_init.c)
                     58:  */
                     59: vm_offset_t alloc_cnvmem(vm_size_t size, vm_offset_t align);
                     60: #endif i386
                     61: #if    hppa
                     62: #import <machdep/hppa/pmap.h>
                     63: extern hpaudiobuffer;
                     64: extern hpaudiosilent;
                     65: #endif hppa
                     66: #if    sparc
                     67: //
                     68: // set in device init routine
                     69: //
                     70: u_int AudioIn_dmaSize = 0;
                     71: u_int AudioIn_dmaCount = 0;
                     72: caddr_t AudioIn_dmaBuf = 0;
                     73: u_int AudioOut_dmaSize = 0;
                     74: u_int AudioOut_dmaCount = 0;
                     75: caddr_t AudioOut_dmaBuf = 0;
                     76: #endif sparc
                     77: 
                     78: #if ppc
                     79: extern void *kernel_map;
                     80: #endif
                     81: 
                     82: @implementation AudioChannel
                     83: 
                     84: /* Factory variables */
                     85: static id allStreams = nil;
                     86: 
                     87: /*
                     88:  * Both input and output channels share one buffer. 
                     89:  */
                     90: static BOOL sharedChannelBuffer = YES;
                     91: static vm_offset_t sharedChannelBufferPtr = 0;
                     92: 
                     93: /*
                     94:  * Add a stream.
                     95:  */
                     96: + addStream:stream
                     97: {
                     98:     if (!allStreams)
                     99:        allStreams = [[List alloc] init];
                    100:     [allStreams addObject:stream];
                    101:     return self;
                    102: }
                    103: 
                    104: /*
                    105:  * Remove a stream.
                    106:  */
                    107: + removeStream:stream
                    108: {
                    109:     [allStreams removeObject:stream];
                    110:     return self;
                    111: }
                    112: 
                    113: /*
                    114:  * Search for a stream given a user port.
                    115:  */
                    116: + streamForUserPort:(port_t)port
                    117: {
                    118:     int i;
                    119:     id stream;
                    120: 
                    121:     for (i = 0; i < [allStreams count]; i++) {
                    122:        stream = [allStreams objectAt:i];
                    123:        if ([stream userPort] == port)
                    124:            return stream;
                    125:     }
                    126:     return nil;
                    127: }
                    128: 
                    129: /*
                    130:  * Search for a stream given an owner port.
                    131:  * Returns the FIRST such stream found.
                    132:  */
                    133: + streamForOwnerPort:(port_t)port
                    134: {
                    135:     int i;
                    136:     id stream;
                    137: 
                    138:     for (i = 0; i < [allStreams count]; i++) {
                    139:        stream = [allStreams objectAt:i];
                    140:        if ([stream ownerPort] == port)
                    141:            return stream;
                    142:     }
                    143:     return nil;
                    144: }
                    145: 
                    146: /*
                    147:  * Initialize.
                    148:  */
                    149:  
                    150: - initOnDevice: device read: (BOOL)isRead
                    151: {
                    152:     [super init];
                    153:     audioDevice = device;
                    154:     
                    155:     _isRead = isRead;
                    156:     
                    157:     if (isRead)
                    158:         streamClass = [InputStream class];
                    159:     else
                    160:         streamClass = [OutputStream class];
                    161:     
                    162:     exclusiveUser = PORT_NULL;
                    163:     streamList = [[List alloc] init];
                    164:     streamListLock = [[NXLock alloc] init];
                    165:     queue_init(&dmaQueue);
                    166:     queue_init(&freeQueue);
                    167: #if    hppa
                    168:     queue_init(&devQueue);
                    169:     queue_init(&dfreeQueue);
                    170: #endif hppa
                    171:     peakHistory = 1;
                    172:     
                    173:     channelBufferPtr = 0;
                    174:     /*
                    175:      * Note:
                    176:      * Until the DMA buffer can be reallocated, the dmaSize cannot be changed.
                    177:      */
                    178: #if    i386
                    179:     if ([audioDevice isEISAPresent])   {
                    180:        [self setDMASize: PAGE_SIZE * 16];
                    181:        (void) [self setDescriptorSize: PAGE_SIZE];
                    182:     } else {
                    183:        [self setDMASize: PAGE_SIZE * 8];               // 64K limit
                    184:        (void) [self setDescriptorSize: PAGE_SIZE];
                    185:     }
                    186: #elif  hppa
                    187:        // uses 64k too
                    188:        dmaSize = PAGE_SIZE * 8;
                    189:        dmaCount = 16;
                    190:        (void) [self setDescriptorSize: (dmaSize/dmaCount)];
                    191: #elif sparc
                    192:     // dmaSize = PAGE_SIZE * 8;
                    193:     // dmaCount = 16;
                    194:        // 16 - 4K buffers
                    195:        if (isRead) {
                    196:                dmaSize = AudioIn_dmaSize;
                    197:                dmaCount = AudioIn_dmaCount;
                    198:        } else {
                    199:                dmaSize = AudioOut_dmaSize;
                    200:                dmaCount = AudioOut_dmaCount;
                    201:        }
                    202:        (void) [self setDescriptorSize: (dmaSize/dmaCount)];
                    203: #elif ppc
                    204:         dmaCount = 32;
                    205:         dmaSize = PAGE_SIZE * dmaCount;
                    206:         (void) [self setDescriptorSize: (dmaSize/dmaCount)];
                    207: #else
                    208:     dmaSize = PAGE_SIZE * 8;
                    209:     dmaCount = 16;
                    210: #endif
                    211: 
                    212:     
                    213:     return self;
                    214: }
                    215:     
                    216: /*
                    217:  * Currently cannot free, but if want to someday, worry about:
                    218:  * destroyDMABuffers; and
                    219:  * Free peak history buffers
                    220:  */
                    221: - free
                    222: {
                    223:     IOLog("AudioChannel: -free not supported\n");
                    224:     return [super free];
                    225: }
                    226: 
                    227: /*
                    228:  *
                    229:  */
                    230: - (u_int) descriptorSize
                    231: {
                    232:     return descriptorSize;
                    233: }
                    234: 
                    235: /*
                    236:  * Returns the desciptorSize which may be different from the one requested. 
                    237:  */
                    238: - (u_int) setDescriptorSize:(u_int) size
                    239: {
                    240:     dmaCount = [self dmaSize] / size;
                    241: 
                    242: #ifndef ppc
                    243:     if (dmaCount < 4 || dmaCount > 16) {
                    244:        dmaCount = 8;
                    245:        size = [self dmaSize] / dmaCount;
                    246:     }
                    247: #endif
                    248: 
                    249:     descriptorSize = size;
                    250:     
                    251:     return descriptorSize;
                    252: }
                    253: 
                    254: - (u_int) dmaSize
                    255: {
                    256:     return dmaSize;
                    257: }
                    258: 
                    259: - (void) setDMASize:(u_int) size
                    260: {
                    261:     dmaSize = size;
                    262: }
                    263: 
                    264: - (u_int)dmaCount
                    265: {
                    266:     return dmaCount;
                    267: }
                    268: 
                    269: - (BOOL) isRead
                    270: {
                    271:     return _isRead;
                    272: }
                    273: 
                    274: /*
                    275:  * Return number of outstanding (enqueued) dma descriptors on dmaQueue.
                    276:  */
                    277: - (u_int)enqueueCount
                    278: {
                    279:     return enqueueCount;
                    280: }
                    281: 
                    282: /*
                    283:  * Create channel dma buffers.
                    284:  * There must be no active streams when this is called.
                    285:  */
                    286: - (BOOL) createChannelBuffer
                    287: {
                    288:     BOOL status;
                    289:     int len;
                    290: #ifdef hppa
                    291:     extern pmap_t audio_pmap;  // defined in IOAudio.m
                    292: #endif
                    293:     
                    294:     /*
                    295:      * To Do: Until better versions of IOMallocLow and IOFreeLow are available,
                    296:      * the channel will use alloc_cnvmem (allocate conventional memory) which
                    297:      * can allocate more than one physically contiguous page. The memory cannot
                    298:      * be freed; therefore, the code checks to see if the channelBuffer has
                    299:      * been created.
                    300:      */        
                    301:     if (channelBufferPtr)
                    302:        return TRUE;
                    303:        
                    304: #if    i386
                    305:     if ((sharedChannelBuffer) && (sharedChannelBufferPtr))     {
                    306:        channelBufferPtr = sharedChannelBufferPtr;
                    307:        
                    308:        channelBuffer = [audioDevice createDMABufferFor: &channelBufferPtr
                    309:            length: dmaSize
                    310:            read:(BOOL) _isRead
                    311:            needsLowMemory: TRUE
                    312:            limitSize: NO];
                    313:     
                    314:        [self initializeFreeQueue];
                    315:        return TRUE;
                    316:     }
                    317: 
                    318:     /*
                    319:      * We treat ISA systems as special case since other systems do not have
                    320:      * DMA memory restrictions like it. For ISA we assign memory using
                    321:      * alloc_envmem() and for others we will use an IOBuffer object
                    322:      * (eventually). 
                    323:      */
                    324:     if (![audioDevice isEISAPresent])  {
                    325:         channelBufferPtr = alloc_cnvmem(dmaSize, 65536);       // 64K align
                    326:        if (!channelBufferPtr)  {
                    327:            IOLog("Audio: no memory for allocating buffers.\n");
                    328:            return FALSE;
                    329:        }
                    330:     } else if ([audioDevice isEISAPresent])    {
                    331:         channelBufferPtr = alloc_cnvmem(dmaSize, PAGE_SIZE);
                    332:        if (!channelBufferPtr)  {
                    333:            IOLog("Audio: no memory for allocating buffers.\n");
                    334:            return FALSE;
                    335:        }
                    336:     }
                    337: #elif  hppa
                    338:     if (_isRead) {
                    339:        // if read it is read buffer
                    340:        channelBufferPtr = (vm_address_t)(&hpaudiosilent);
                    341:     } else {
                    342:        channelBufferPtr = (vm_address_t)(&hpaudiobuffer);
                    343:     }
                    344: #elif sparc
                    345:        if (_isRead) 
                    346:                channelBufferPtr = (vm_offset_t)AudioIn_dmaBuf;
                    347:        else 
                    348:                channelBufferPtr = (vm_offset_t)AudioOut_dmaBuf;
                    349: #elif ppc
                    350:    {
                    351:      int       kr;
                    352:      kr = kmem_alloc_wired( kernel_map, (vm_offset_t)&channelBufferPtr, dmaSize );
                    353:      if ( kr != KERN_SUCCESS )
                    354:      {
                    355:        IOLog("Audio: no memory for allocating buffers.\n");
                    356:        return FALSE;
                    357:      }
                    358:    }
                    359: #else
                    360: #warning       AudioChannel class only supports i386 , hppa or sparc
                    361: #endif
                    362: 
                    363:     sharedChannelBufferPtr = channelBufferPtr;
                    364:     
                    365: #if    i386
                    366:     channelBuffer = [audioDevice createDMABufferFor: &channelBufferPtr
                    367:         length: dmaSize
                    368:         read:(BOOL) _isRead
                    369:         needsLowMemory: TRUE
                    370:         limitSize: NO];
                    371: #else
                    372:     // for hppa and sparc there is no seperate setups for DMA
                    373:     channelBuffer = (void *)channelBufferPtr;
                    374: #endif
                    375: 
                    376:     [self initializeFreeQueue];
                    377: #if    hppa
                    378:     [self initializeDFreeQueue];
                    379: #endif
                    380:     return TRUE;
                    381: }
                    382: 
                    383: - (void) initializeFreeQueue
                    384: {
                    385:     dma_desc_t *ddp;
                    386:     int i;
                    387:     vm_address_t ptr;
                    388:     
                    389:     while (!queue_empty(&freeQueue)) {
                    390:        queue_remove_first(&freeQueue, ddp, dma_desc_t *, link);
                    391:        IOFree((void *)ddp, sizeof(dma_desc_t));
                    392:     }
                    393: 
                    394:     bzero((void *)channelBufferPtr, dmaSize);
                    395: 
                    396:     ptr = channelBufferPtr;
                    397: 
                    398:     for (i = 0; i < dmaCount; i++) {
                    399:        ddp = (dma_desc_t *)IOMalloc(sizeof(dma_desc_t));
                    400:        ddp->size = 0;
                    401:        ddp->mem = ptr;
                    402:        ptr += descriptorSize;
                    403:        queue_enter(&freeQueue, ddp, dma_desc_t *, link);
                    404:     }
                    405: }
                    406: 
                    407: #if    hppa
                    408: - (void) initializeDFreeQueue
                    409: {
                    410:     dma_desc_t *ddp;
                    411:     int i;
                    412:     vm_address_t ptr;
                    413:     
                    414:     while (!queue_empty(&dfreeQueue)) {
                    415:        queue_remove_first(&dfreeQueue, ddp, dma_desc_t *, link);
                    416:        IOFree((void *)ddp, sizeof(dma_desc_t));
                    417:     }
                    418: 
                    419:     bzero((void *)channelBufferPtr, dmaSize);
                    420: 
                    421:        pmap_flush_range(kernel_pmap, (vm_offset_t)channelBufferPtr, dmaSize);
                    422: 
                    423: 
                    424:     ptr = channelBufferPtr;
                    425: 
                    426:     for (i = 0; i < dmaCount; i++) {
                    427:                ddp = (dma_desc_t *)IOMalloc(sizeof(dma_desc_t));
                    428:                ddp->size = 0;
                    429:                ddp->mem = ptr;
                    430:                ptr += descriptorSize;
                    431:                queue_enter(&dfreeQueue, ddp, dma_desc_t *, link);
                    432:     }
                    433: }
                    434: 
                    435: /* returns the device dma address also releases the queue
                    436:  * 
                    437:  */
                    438: 
                    439: - (vm_offset_t) getDevDmaAddress
                    440: {
                    441:     dma_desc_t *ddp_d; // for the dev queue
                    442:     vm_offset_t dev_dma_addr = (vm_offset_t)NULL;
                    443:     vm_offset_t addr;
                    444:      extern pmap_t audio_pmap; // defined in IOAudio.m
                    445: 
                    446:        if (queue_empty(&devQueue)) return (vm_offset_t)NULL;
                    447:        queue_remove_first(&devQueue, ddp_d, dma_desc_t *, link);
                    448:        // now the buffer is a kernel buffer mapped 1 to 1
                    449:        // dev_dma_addr = ddp_d->mem;
                    450:        dev_dma_addr = pmap_extract(kernel_pmap,ddp_d->mem);
                    451:        
                    452:        queue_enter(&dfreeQueue, ddp_d, dma_desc_t *, link);
                    453:        return dev_dma_addr;
                    454: }
                    455: #endif hppa
                    456: 
                    457: /*
                    458:  * Destroy dma buffers.
                    459:  * There must be no active streams when this is called.
                    460:  */
                    461: - (void) destroyChannelBuffer
                    462: {
                    463:     
                    464:     /*
                    465:      * The channelBuffer cannot be freed until a better version
                    466:      *         of IOFreeLow is available.
                    467:      */
                    468: }
                    469: 
                    470: /*
                    471:  * enqueue a dma descriptor using the current device parameters.
                    472:  */
                    473: - (BOOL) enqueueDescriptor: (u_int *) rate
                    474:        dataFormat: (IOAudioDataFormat *) format
                    475:        channelCount: (u_int *) count
                    476: {
                    477:     id stream;
                    478:     int i;
                    479:     u_int bufferSize = 0;
                    480:     u_int streamCount;
                    481:     u_int streamSize;
                    482:     dma_desc_t *ddp;
                    483: #if    hppa
                    484:     dma_desc_t *ddp_d; // for the dev queue
                    485: #endif hppa
                    486: 
                    487:     xpr_audio_channel("AC: enqueueDescriptor: rate %d dataFormat %d "
                    488:                "channelCount %d\n", rate, format, count, 4,5);
                    489:     [streamListLock lock];
                    490:     streamCount = [streamList count];
                    491:     if (streamCount == 0 || queue_empty(&freeQueue)) {
                    492:        [streamListLock unlock];
                    493:        return FALSE;
                    494:     }
                    495:     queue_remove_first(&freeQueue, ddp, dma_desc_t *, link);
                    496:     for (i = 0; i < streamCount; i++) {
                    497:        stream = [streamList objectAt:i];
                    498:        streamSize = [stream mixBuffer:ddp->mem maxCount:descriptorSize
                    499:                                  rate:rate format:format
                    500:                          channelCount:count descriptor:ddp
                    501:                                 virgin:(bufferSize == 0)
                    502:                            streamCount:streamCount];
                    503:        if (streamSize > bufferSize)
                    504:            bufferSize = streamSize;
                    505:     }
                    506:     [streamListLock unlock];
                    507:     if (bufferSize == 0) {
                    508:        queue_enter_first(&freeQueue, ddp, dma_desc_t *, link);
                    509:        return(FALSE);
                    510:     }
                    511:     
                    512:     ddp->size = bufferSize;    
                    513: #ifdef sparc
                    514:        vac_flush((caddr_t)ddp->mem, ddp->size);
                    515: #endif
                    516: #ifdef hppa
                    517:        pmap_flush_range(kernel_pmap,(vm_offset_t)ddp->mem,ddp->size);
                    518: #endif
                    519: #ifdef ppc
                    520:         flush_cache_v((vm_offset_t)ddp->mem,ddp->size);
                    521: #endif
                    522:     queue_enter(&dmaQueue, ddp, dma_desc_t *, link);
                    523: #ifdef hppa
                    524:     if (!queue_empty(&dfreeQueue)) {
                    525:            queue_remove_first(&dfreeQueue, ddp_d, dma_desc_t *, link);
                    526:            ddp_d->mem = ddp->mem;
                    527:            ddp_d->size = ddp->size;
                    528:            queue_enter(&devQueue, ddp_d, dma_desc_t *, link);
                    529:     }
                    530: #endif
                    531: 
                    532:     enqueueCount++;
                    533: 
                    534:     xpr_audio_channel("AC: enqueueDescriptor done\n",1,2,3,4,5);
                    535:     
                    536:     return(TRUE);
                    537: }
                    538: 
                    539: 
                    540: /*
                    541:  * dequeue a DMA descriptor
                    542:  */
                    543: - (void) dequeueDescriptor
                    544: {
                    545:     dma_desc_t *ddp;
                    546:     int i;
                    547:     id stream;
                    548:     u_int peak_left = 0, peak_right = 0;
                    549:     u_int numStreams;
                    550: 
                    551:     xpr_audio_channel("AC: dequeueDescriptor\n",1,2,3,4,5);
                    552:     
                    553:     queue_remove_first(&dmaQueue, ddp, dma_desc_t *, link);
                    554: 
                    555:     [streamListLock lock];
                    556:     numStreams = [streamList count];
                    557:     if (numStreams > 0) {
                    558:        if (peakEnabled) {
                    559:            switch ([audioDevice dataEncoding]) {
                    560:              case NX_SoundStreamDataEncoding_Linear16:
                    561:                audio_linear16_peak([audioDevice channelCount],
                    562:                                    (short *)ddp->mem, ddp->size/2,
                    563:                                    &peak_left, &peak_right);
                    564:                break;
                    565:                
                    566:              case NX_SoundStreamDataEncoding_Linear8:
                    567:                audio_linear8_peak([audioDevice channelCount],
                    568:                                   (char *)ddp->mem, ddp->size,
                    569:                                   &peak_left, &peak_right);
                    570:                break;
                    571:                
                    572:              case NX_SoundStreamDataEncoding_Mulaw8:
                    573:                audio_mulaw8_peak([audioDevice channelCount],
                    574:                                  (unsigned char *)ddp->mem,
                    575:                                  ddp->size, &peak_left, &peak_right);
                    576:                break;
                    577:                
                    578:              default:
                    579:                /* FIXME: A-law and AES peak not supported */
                    580:                break;
                    581:            }
                    582:            audio_add_peak(peaksLeft, peak_left, &currentPeak, peakHistory);
                    583:            audio_add_peak(peaksRight, peak_right, &currentPeak, peakHistory);
                    584:        }
                    585:        
                    586:        for (i = 0; i < numStreams; i++) {
                    587:            stream = [streamList objectAt:i];
                    588:            /*
                    589:             * Note: transfer count is only valid for input channel
                    590:             * (0 sent for output channel).
                    591:             */
                    592:            [stream dmaCompleteDescriptor:ddp transfered:ddp->size];
                    593:            
                    594:            /*
                    595:             * In the original driver, the dequeueDMA operation would return
                    596:             * the actually transfer count. We need to offer a similar
                    597:             * solution at some point:
                    598:             * [stream dmaCompleteDescriptor:ddp transfered:count];
                    599:             */
                    600:        }
                    601:     }
                    602:     [streamListLock unlock];
                    603: 
                    604:     bzero((void *)ddp->mem, descriptorSize);
                    605: 
                    606: #ifdef ppc
                    607:     flush_cache_v((vm_offset_t)ddp->mem,descriptorSize);
                    608: #endif
                    609: 
                    610:     queue_enter(&freeQueue, ddp, dma_desc_t *, link);
                    611:     
                    612:     --enqueueCount;
                    613:     xpr_audio_channel("AC: dequeueDescriptor done\n",1,2,3,4,5);
                    614: }
                    615: 
                    616: 
                    617: /*
                    618:  * returns the channel buffer as a void *
                    619:  */
                    620: - (void *) channelBuffer
                    621: {
                    622:     return channelBuffer;
                    623: }
                    624: 
                    625: - (vm_address_t) channelBufferAddress
                    626: {
                    627:     return channelBufferPtr;
                    628: }
                    629: 
                    630: - (void) freeDescriptors
                    631: {
                    632:     /*
                    633:      * When a DMA operation is aborted, descriptors might still remain on
                    634:      * the DMA queue.
                    635:      */
                    636:     while (!queue_empty(&dmaQueue)) 
                    637:         [self dequeueDescriptor];
                    638: 
                    639:    [self initializeFreeQueue];
                    640: }
                    641: 
                    642: - (void) setLocalChannel:(u_int) channel
                    643: {
                    644:     localChannel = channel;
                    645: }
                    646: 
                    647: - (u_int) localChannel
                    648: {
                    649:     return localChannel;
                    650: }
                    651: 
                    652: /*
                    653:  * Get and set user channel and snd ports.
                    654:  */
                    655: - setUserChannelPort:(port_t)port
                    656: {
                    657:     userChannelPort = port;
                    658:     return self;
                    659: }
                    660: - (port_t)userChannelPort
                    661: {
                    662:     return userChannelPort;
                    663: }
                    664: - setUserSndPort:(port_t)port
                    665: {
                    666:     userSndPort = port;
                    667:     return self;
                    668: }
                    669: - (port_t)userSndPort
                    670: {
                    671:     return userSndPort;
                    672: }
                    673: 
                    674: /*
                    675:  * Search for the FIRST stream with the given owner port
                    676:  * (used by the snd interface, which has one stream per channel).
                    677:  * Returns the stream's user port.
                    678:  */
                    679: - (port_t)streamUserForOwnerPort:(port_t)port
                    680: {
                    681:     int i;
                    682:     id stream;
                    683: 
                    684:     for (i = 0; i < [streamList count]; i++) {
                    685:        stream = [streamList objectAt:i];
                    686:        if ([stream ownerPort] == port)
                    687:            return [stream userPort];
                    688:     }
                    689:     return PORT_NULL;
                    690: }
                    691: 
                    692: /*
                    693:  * Remove all snd type streams.
                    694:  */
                    695: - removeSndStreams
                    696: {
                    697:     id stream;
                    698:     List *remList = [[List alloc] init];
                    699:     int i;
                    700: 
                    701:     [streamListLock lock];
                    702:     for (i = 0; i < [streamList count]; i++) {
                    703:        stream = [streamList objectAt:i];
                    704:        if ([stream type] != AS_TypeUser)
                    705:            [remList addObject:stream];
                    706:     }
                    707:     [streamListLock unlock];
                    708: 
                    709:     for (i = 0; i < [remList count]; i++)
                    710:        [self removeStream:[remList objectAt:i]];
                    711: 
                    712:     [remList free];
                    713:     return self;
                    714: }
                    715: 
                    716: /*
                    717:  * Get and set exclusive user.
                    718:  */
                    719: - (void)setExclusiveUser:(port_t)streamPort
                    720: {
                    721:     int streamCount, i;
                    722: 
                    723:     exclusiveUser = streamPort;
                    724:     /*
                    725:      * Cause other owner's streams to abort with excluded messages.
                    726:      */
                    727:     [streamListLock lock];
                    728:     streamCount = [streamList count];
                    729:     if (streamCount == 0) {
                    730:        [streamListLock unlock];
                    731:        return;
                    732:     }
                    733:     for (i = 0; i < streamCount; i++)
                    734:        [[streamList objectAt:i] control:AC_ControlExclude];
                    735:     [streamListLock unlock];
                    736: }
                    737: - (port_t)exclusiveUser
                    738: {
                    739:     return exclusiveUser;
                    740: }
                    741: 
                    742: /*
                    743:  * Check prospective owner port against current exclusive user port.
                    744:  */
                    745: - (BOOL)checkOwner:(port_t)owner
                    746: {
                    747:     if (exclusiveUser != PORT_NULL && owner != exclusiveUser)
                    748:        return NO;
                    749:     else
                    750:        return YES;
                    751: }
                    752: 
                    753: /*
                    754:  * 
                    755:  */
                    756: - streamClass
                    757: {
                    758:     return streamClass;
                    759: }
                    760: 
                    761: /*
                    762:  * Return number of streams
                    763:  */
                    764: - (u_int)streamCount
                    765: {
                    766:     u_int count;
                    767: 
                    768:     [streamListLock lock];
                    769:     count = [streamList count];
                    770:     [streamListLock unlock];
                    771:     return count;
                    772: }
                    773: 
                    774: /*
                    775:  * When a stream is added, its user port must be registered with the
                    776:  * audio loadable kernel server.
                    777:  */
                    778: - (BOOL)addStreamTag:(int)tag user:(port_t *)userPort
                    779:       owner:(port_t)owner type:(u_int)type
                    780: {
                    781:     id aStream;
                    782: 
                    783:     xpr_audio_channel("AC: addStreamTag tag=%d user=%x owner=%x"
                    784:                 " type=%d\n", tag, userPort, owner, type, 5);
                    785:     
                    786:     if (![audioDevice _channelWillAddStream])  {
                    787:         xpr_audio_channel("AC: audioDevice can not add stream.\n",1,2,3,4,5);
                    788:        return NO;
                    789:     }
                    790: 
                    791:     aStream = [[[self streamClass] alloc] initChannel:self tag:tag
                    792:                                                 user:userPort
                    793:                                                owner:owner type:type];
                    794:     if (!aStream)      {
                    795:         xpr_audio_channel("AC: addStreamTag: can not add stream.\n",1,2,3,4,5);
                    796:        return NO;
                    797:     }
                    798: 
                    799:     [streamListLock lock];
                    800: 
                    801:     if ([streamList count] == 0) {
                    802:        if (![self createChannelBuffer]) {
                    803:            [streamListLock unlock];
                    804:            xpr_audio_channel("AC: addStreamTag: can not create"
                    805:                " channel buffer.\n",1,2,3,4,5);
                    806:            return NO;
                    807:        }
                    808:     }
                    809: 
                    810:     [streamList addObject:aStream];
                    811:     [streamListLock unlock];
                    812:     [AudioChannel addStream:aStream];
                    813:     
                    814:     return audio_enroll_stream_port(*userPort, TRUE);
                    815: }
                    816: 
                    817: /*
                    818:  * Remove a stream.
                    819:  */
                    820: - (void)removeStream:stream
                    821: {
                    822:     unsigned int count;
                    823:     
                    824:     audio_enroll_stream_port([stream userPort], FALSE);
                    825:     [streamListLock lock];
                    826:     count = [streamList count];
                    827:     
                    828:     /*
                    829:      * When only one stream remains, DMA is aborted when the stream is removed.
                    830:      */
                    831:     if (count == 1) {
                    832:     
                    833:         /*
                    834:         * The streamListLock needs to be unlocked to prevent deadlock. When
                    835:         * the abort command is sent to the IO thread, the dequeueDescriptor
                    836:         * method will be executed. This method needs to acquire the lock. 
                    837:         */
                    838:        [streamListLock unlock];
                    839: 
                    840:         if ([self isRead])
                    841:            [[audioDevice _audioCommand] send: abortInputChannel];
                    842:        else
                    843:            [[audioDevice _audioCommand] send: abortOutputChannel];
                    844:            
                    845:        [streamListLock lock];
                    846:        
                    847:        if (peaksLeft)
                    848:            audio_clear_peaks(peaksLeft, MAX_PEAK_HISTORY);
                    849:        if (peaksRight)
                    850:            audio_clear_peaks(peaksRight, MAX_PEAK_HISTORY);
                    851:        clipCount = 0;
                    852: 
                    853:     }
                    854: 
                    855:     [streamList removeObject:stream];
                    856:     [AudioChannel removeStream:stream];
                    857:     [stream free];
                    858:     [streamListLock unlock];
                    859: 
                    860: }
                    861: 
                    862: 
                    863: /*
                    864:  * Send stream control to all streams.
                    865:  */
                    866: - (void)controlStreams:(ACStreamControl)action
                    867: {
                    868:     int streamCount, i;
                    869: 
                    870:     [streamListLock lock];
                    871:     streamCount = [streamList count];
                    872:     if (streamCount == 0) {
                    873:        [streamListLock unlock];
                    874:        return;
                    875:     }
                    876:     for (i = 0; i < streamCount; i++)
                    877:        [[streamList objectAt:i] control:action];
                    878:     [streamListLock unlock];
                    879: }
                    880: 
                    881: - (BOOL)isDetectingPeaks
                    882: {
                    883:     return peakEnabled;
                    884: }
                    885: 
                    886: - (void)setDetectPeaks:(BOOL)flag;
                    887: {
                    888:     /*
                    889:      * FIXME: unsupport history.
                    890:      */
                    891:     peakEnabled = flag;
                    892:     if (peakEnabled && !peaksLeft) {
                    893:        peaksLeft = (u_int *)IOMalloc(MAX_PEAK_HISTORY*sizeof(u_int));
                    894:        peaksRight = (u_int *)IOMalloc(MAX_PEAK_HISTORY*sizeof(u_int));
                    895:        audio_clear_peaks(peaksLeft, MAX_PEAK_HISTORY);
                    896:        audio_clear_peaks(peaksRight, MAX_PEAK_HISTORY);
                    897:     }
                    898: }
                    899: 
                    900: /*
                    901:  * Get peaks and clip count.
                    902:  */
                    903: - (void)getPeakLeft:(u_int *)leftPeak right:(u_int *)rightPeak
                    904: {
                    905:     if (peakEnabled) {
                    906:        *leftPeak = audio_max_peak(peaksLeft, peakHistory);
                    907:        *rightPeak = audio_max_peak(peaksRight, peakHistory);
                    908:     } else
                    909:        *leftPeak = *rightPeak = 0;
                    910: }
                    911: - (u_int)clipCount
                    912: {
                    913:     return clipCount;
                    914: }
                    915: - incrementClipCount:(u_int)count
                    916: {
                    917:     clipCount += count;
                    918:     return self;
                    919: }
                    920: 
                    921: /*
                    922:  * Return device.
                    923:  */
                    924: - audioDevice
                    925: {
                    926:     return audioDevice;
                    927: }
                    928: 
                    929: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.