Annotation of driverkit/libDriver/Kernel/snd_server.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:  * snd_server.m
                     26:  *
                     27:  * Copyright (c) 1991, NeXT Computer, Inc.  All rights reserved.
                     28:  *
                     29:  *     Field old SoundDSP driver user messages for audio driver.
                     30:  *
                     31:  * HISTORY
                     32:  *     08/10/92/mtm    Original coding.
                     33:  */
                     34: 
                     35: #import "audioLog.h"
                     36: #import "snd_reply.h"
                     37: #import "snd_server.h"
                     38: #import "audio_server.h"
                     39: #import <driverkit/IOAudioPrivate.h>
                     40: #import "AudioChannel.h"
                     41: #import "AudioStream.h"
                     42: #import "audio_kern_server.h"
                     43: #import <driverkit/NXSoundParameterTags.h>
                     44: #import <bsd/dev/snd_msgs.h>
                     45: #import <bsd/dev/audioTypes.h>
                     46: #import <mach/mach_types.h>
                     47: #import <kernserv/queue.h>
                     48: #import        <bsd/sys/time.h>
                     49: #import <driverkit/kernelDriver.h>     // for IOVmTaskSelf()
                     50: 
                     51: #define SND_DIR_PLAY   0
                     52: #define SND_DIR_RECORD 1
                     53: 
                     54: /*
                     55:  * DO NOT PUT ANY STATIC DATA IN THIS FILE.
                     56:  * These routines may be used by multiple AudioDevice instances
                     57:  * if more sound boards are added.
                     58:  */
                     59: 
                     60: static int snd_nx_encoding(int encoding)
                     61: {
                     62:     switch (encoding) {
                     63:       case SND_STREAM_FORMAT_ENCODING_LINEAR_16:
                     64:        return NX_SoundStreamDataEncoding_Linear16;
                     65:       case SND_STREAM_FORMAT_ENCODING_LINEAR_8:
                     66:        return NX_SoundStreamDataEncoding_Linear8;
                     67:       case SND_STREAM_FORMAT_ENCODING_MULAW_8:
                     68:       default:
                     69:        return NX_SoundStreamDataEncoding_Mulaw8;
                     70:     }
                     71: }
                     72:        
                     73: static void snd_set_stream_format(int dir, void *stream,
                     74:                                  int srate, int encoding, int chans,
                     75:                                  int low_water, int high_water)
                     76: {
                     77:     int parray[] = { NX_SoundStreamLowWaterMark,
                     78:                          NX_SoundStreamHighWaterMark,
                     79:                          NX_SoundStreamSamplingRate,
                     80:                          NX_SoundStreamDataEncoding,
                     81:                          NX_SoundStreamChannelCount };
                     82:     int pcount = sizeof(parray)/sizeof(int);
                     83:     int pvalues[pcount];
                     84:     kern_return_t kerr;
                     85:     
                     86:     pvalues[0] = low_water;
                     87:     pvalues[1] = high_water;
                     88:     pvalues[2] = srate;
                     89:     pvalues[3] = snd_nx_encoding(encoding);
                     90:     pvalues[4] = chans;
                     91:     kerr = _NXAudioSetStreamParameters(stream, parray, pcount, pvalues);
                     92:     if (kerr != KERN_SUCCESS)
                     93:        xpr_audio_user("AU: snd_set_stream_format: setStreamParams returns "
                     94:                        "%d\n", kerr, 2,3,4,5);
                     95: }
                     96: 
                     97: /*
                     98:  * Handle stream port messages.
                     99:  */
                    100: static int snd_stream_msg(msg_header_t *in_msg, msg_header_t *out_msg)
                    101: {
                    102:     kern_return_t kerr;
                    103:     int size;
                    104:     snd_msg_type_t *msg_type;
                    105:     vm_address_t snd_data = 0;
                    106:     vm_size_t snd_size = 0;
                    107:     int snd_control = 0;
                    108:     int options = 0;
                    109:     int error = 0;
                    110:     int direction = -1;
                    111:     int high_water = 0;
                    112:     int low_water = 0;
                    113:     u_int dma_size, dma_count;
                    114:     struct timeval time_now;
                    115:     snd_stream_msg_t *stream_msg = (snd_stream_msg_t *)in_msg;
                    116:     int data_tag = stream_msg->data_tag;
                    117:     port_t reply_port = PORT_NULL;
                    118:     u_int bytes_processed, time_stamp;
                    119:     int sample_rate = 0, data_encoding = 0, chan_count = 0;
                    120:     boolean_t set_format = FALSE;
                    121:     AudioStream *audioStream = [AudioChannel
                    122:                                   streamForUserPort:in_msg->msg_local_port];
                    123: 
                    124:     xpr_audio_user("AU: snd_stream_msg: stream 0x%x\n", audioStream, 
                    125:                2,3,4,5);
                    126: 
                    127:     if (in_msg->msg_id == SND_MSG_STREAM_NSAMPLES) {
                    128:        xpr_audio_user("AU: snd_stream_msg: nsamples\n", 1,2,3,4,5);
                    129:        kerr = _NXAudioStreamInfo(audioStream, &bytes_processed, 
                    130:                                &time_stamp);
                    131:        if (kerr != KERN_SUCCESS)
                    132:            xpr_audio_user("AU: snd_stream_msg: streamInfo returns %d\n", 
                    133:                        kerr, 2,3,4,5);
                    134:        audio_snd_reply_ret_samples(out_msg, in_msg->msg_remote_port,
                    135:                              bytes_processed, time_stamp);
                    136:        return 0;
                    137:     }
                    138: 
                    139:     /*
                    140:      * NOTE: snddriver_client.c sends options and play/record data
                    141:      * in the same message.
                    142:      */
                    143:     size = in_msg->msg_size - sizeof(*stream_msg);
                    144:     msg_type = (snd_msg_type_t *)(stream_msg + 1);
                    145:     while (size > 0) {
                    146:        switch (msg_type->type) {
                    147:          case SND_MT_PLAY_DATA: {
                    148: #ifdef DDM_DEBUG
                    149:              snd_stream_play_data_t *stream_play_data =
                    150:                  (snd_stream_play_data_t *)msg_type;
                    151: #endif DDM_DEBUG
                    152:              
                    153:              *(int *)&msg_type += sizeof(snd_stream_play_data_t);
                    154:              size -= sizeof(snd_stream_play_data_t);
                    155:              
                    156:              if (!error && direction == SND_DIR_RECORD)
                    157:                  error = SND_BAD_PARM;
                    158: #ifdef DDM_DEBUG
                    159:              options = stream_play_data->options;
                    160:              snd_data = (vm_address_t)stream_play_data->data;
                    161:              snd_size = (vm_size_t)
                    162:                  stream_play_data->dataType.msg_type_long_number;
                    163: #endif DDM_DEBUG
                    164:              xpr_audio_user("AU: snd_stream_msg: play data=0x%x, size=%d\n", 
                    165:                snd_data, snd_size, 3,4,5);
                    166:              direction = SND_DIR_PLAY;
                    167:              break;
                    168:          }
                    169:          case SND_MT_RECORD_DATA: {
                    170:              int r;
                    171:              //char *filename;
                    172:              int filename_len;
                    173:              snd_stream_record_data_t *record_data =
                    174:                  (snd_stream_record_data_t *)msg_type;
                    175: 
                    176:              filename_len = record_data->filenameType.msg_type_number;
                    177:              r = sizeof(*record_data) + filename_len;
                    178:              *(int *)&msg_type += r;
                    179:              size -= r;
                    180:              xpr_audio_user("AU: snd_stream_msg: record data\n", 1,2,3,4,5);
                    181:              break;
                    182:          }
                    183:          case SND_MT_CONTROL: {
                    184:              snd_stream_control_t *stream_control =
                    185:                  (snd_stream_control_t *)msg_type;
                    186: 
                    187:              xpr_audio_user("AU: snd_stream_msg: control\n", 1,2,3,4,5);
                    188:              *(int *)&msg_type += sizeof(snd_stream_control_t);
                    189:              size -= sizeof(snd_stream_control_t);
                    190: 
                    191:              xpr_audio_user("AU: snd_stream_msg: control 0x%x\n",
                    192:                             stream_control->snd_control, 2,3,4,5);
                    193:              snd_control |= stream_control->snd_control;
                    194:              break;
                    195:          }
                    196:          case SND_MT_FORMAT: {
                    197:              snd_stream_format_t *stream_format =
                    198:                  (snd_stream_format_t *)msg_type;
                    199:              *(int *)&msg_type += sizeof(snd_stream_format_t);
                    200:              size -= sizeof(snd_stream_format_t);
                    201:              
                    202:              sample_rate = stream_format->rate;
                    203:              data_encoding = stream_format->encoding;
                    204:              chan_count = stream_format->chan_count;
                    205:              set_format = TRUE;
                    206:              xpr_audio_user("AU: snd_stream_msg: format sr=%d de=%d cc=%d\n",
                    207:                             stream_format->rate,
                    208:                             stream_format->encoding,
                    209:                             stream_format->chan_count, 4,5);
                    210:              break;
                    211:          }
                    212:          case SND_MT_OPTIONS: {
                    213:              snd_stream_options_t *stream_options =
                    214:                  (snd_stream_options_t *)msg_type;
                    215:              xpr_audio_user("AU: snd_stream_msg: options hw=%d lw=%d "
                    216:                             "size=%d\n",
                    217:                             stream_options->high_water,
                    218:                             stream_options->low_water,
                    219:                             stream_options->dma_size, 4,5);
                    220:              *(int *)&msg_type += sizeof(snd_stream_options_t);
                    221:              size -= sizeof(snd_stream_options_t);
                    222:              /*
                    223:               * Save water marks for later use by play/record stream call.
                    224:               */
                    225:              high_water = stream_options->high_water;
                    226:              low_water = stream_options->low_water;
                    227:              
                    228:              kerr = _NXAudioGetBufferOptions([audioStream channel],
                    229:                                              &dma_size, &dma_count);
                    230:              if (kerr != KERN_SUCCESS)
                    231:                  xpr_audio_user("AU: snd_stream_msg: getBufferOpts returns "
                    232:                                "%d\n", kerr, 2,3,4,5);
                    233:              kerr = _NXAudioSetBufferOptions([audioStream channel], 0,
                    234:                                              stream_options->dma_size,
                    235:                                              dma_count);
                    236:              if (kerr != KERN_SUCCESS)
                    237:                  xpr_audio_user("AU: snd_stream_msg: setBufferOpts returns "
                    238:                                "%d\n", kerr, 2,3,4,5);
                    239:              break;
                    240:          }
                    241:          case SND_MT_NDMA: {
                    242:              snd_stream_ndma_t *stream_ndma = (snd_stream_ndma_t *)msg_type;
                    243:              xpr_audio_user("AU: snd_stream_msg: ndma %d\n", 
                    244:                             stream_ndma->ndma, 2,3,4,5);
                    245:              *(int *)&msg_type += sizeof(snd_stream_ndma_t);
                    246:              size -= sizeof(snd_stream_ndma_t);
                    247:              kerr = _NXAudioGetBufferOptions([audioStream channel],
                    248:                                              &dma_size, &dma_count);
                    249:              if (kerr != KERN_SUCCESS)
                    250:                  xpr_audio_user("AU: snd_stream_msg: getBufferOpts returns "
                    251:                                "%d\n",kerr, 2,3,4,5);
                    252:              kerr = _NXAudioSetBufferOptions([audioStream channel], 0,
                    253:                                              dma_size,
                    254:                                              stream_ndma->ndma);
                    255:              if (kerr != KERN_SUCCESS)
                    256:                  xpr_audio_user("AU: snd_stream_msg: setBufferOpts returns "
                    257:                                "%d\n", kerr, 2,3,4,5);
                    258:              break;
                    259:          }
                    260:          default:
                    261:            error = SND_BAD_MSG;
                    262:            size = 0;
                    263:            break;
                    264:        }
                    265:     }
                    266:        
                    267:     /*
                    268:      * If we found any errors, cleanup and return an error.
                    269:      */
                    270:     if (error) {
                    271:        size = in_msg->msg_size - sizeof(*stream_msg);
                    272:        msg_type = (snd_msg_type_t *)(stream_msg + 1);
                    273:        while (size > 0) {
                    274:            switch (msg_type->type) {
                    275:              case SND_MT_PLAY_DATA: {
                    276:                  snd_stream_play_data_t *stream_play_data =
                    277:                      (snd_stream_play_data_t *)msg_type;
                    278:                  
                    279:                  *(int *)&msg_type +=
                    280:                      sizeof(snd_stream_play_data_t);
                    281:                  size -= sizeof(snd_stream_play_data_t);
                    282:                  
                    283:                  vm_deallocate(IOVmTaskSelf(),
                    284:                                (vm_address_t)stream_play_data->data,
                    285:                                stream_play_data->
                    286:                                dataType.msg_type_long_number);
                    287:                  break;
                    288:              }
                    289:              case SND_MT_RECORD_DATA:
                    290:                *(int *)&msg_type +=
                    291:                    sizeof(snd_stream_record_data_t);
                    292:                size -= sizeof(snd_stream_record_data_t);
                    293:                break;
                    294:              case SND_MT_CONTROL:
                    295:                *(int *)&msg_type +=
                    296:                    sizeof(snd_stream_control_t);
                    297:                size -= sizeof(snd_stream_control_t);
                    298:                break;
                    299:              case SND_MT_FORMAT:
                    300:                *(int *)&msg_type +=
                    301:                    sizeof(snd_stream_format_t);
                    302:                size -= sizeof(snd_stream_format_t);
                    303:                break;
                    304:              case SND_MT_OPTIONS:
                    305:                *(int *)&msg_type +=
                    306:                    sizeof(snd_stream_options_t);
                    307:                size -= sizeof(snd_stream_options_t);
                    308:                break;
                    309:              case SND_MT_NDMA:
                    310:                *(int *)&msg_type +=
                    311:                    sizeof(snd_stream_ndma_t);
                    312:                size -= sizeof(snd_stream_ndma_t);
                    313:                break;
                    314:              default:
                    315:                /*
                    316:                 * This shouldn't happen.
                    317:                 */
                    318:                break;
                    319:            }
                    320:        }
                    321:        return error;
                    322:     }
                    323:     
                    324:     /*
                    325:      * Process control requests.
                    326:      */
                    327:     timerclear(&time_now);
                    328: 
                    329:     if (snd_control&SND_DC_ABORT) {
                    330:        kerr = _NXAudioStreamControl(audioStream, _NXAUDIO_STREAM_ABORT,
                    331:                                    time_now);
                    332:        if (kerr != KERN_SUCCESS)
                    333:            xpr_audio_user("AU: snd_stream_msg: streamControl returns %d\n", 
                    334:                           kerr,2,3,4,5);
                    335:     }
                    336:     if (snd_control&SND_DC_AWAIT) {
                    337:        kerr = _NXAudioStreamControl(audioStream, _NXAUDIO_STREAM_RETURN_DATA,
                    338:                                    time_now);
                    339:        if (kerr != KERN_SUCCESS)
                    340:            xpr_audio_user("AU: snd_stream_msg: streamControl returns %d\n", 
                    341:                           kerr,2,3,4,5);
                    342:     }
                    343:     if (snd_control&SND_DC_PAUSE) {
                    344:        kerr = _NXAudioStreamControl(audioStream, _NXAUDIO_STREAM_PAUSE,
                    345:                                    time_now);
                    346:        if (kerr != KERN_SUCCESS)
                    347:            xpr_audio_user("AU: snd_stream_msg: streamControl returns %d\n", 
                    348:                           kerr, 2,3,4,5);
                    349:     }
                    350:     /*
                    351:      * Resume control handled below after (possible) data enqueue.
                    352:      */
                    353: 
                    354:     /*
                    355:      * This time for sure.
                    356:      */
                    357:     size = in_msg->msg_size - sizeof(*stream_msg);
                    358:     msg_type = (snd_msg_type_t *)(stream_msg + 1);
                    359:     while (size > 0) {
                    360:        snd_size = 0;
                    361:        switch (msg_type->type) {
                    362:          case SND_MT_PLAY_DATA: {
                    363:              snd_stream_play_data_t *stream_play_data =
                    364:                  (snd_stream_play_data_t *)msg_type;
                    365:              
                    366:              *(int *)&msg_type += sizeof(snd_stream_play_data_t);
                    367:              size -= sizeof(snd_stream_play_data_t);
                    368:              
                    369:              options = stream_play_data->options;
                    370:              snd_data = (vm_address_t)stream_play_data->data;
                    371:              snd_size = (vm_size_t)
                    372:                  stream_play_data->dataType.msg_type_long_number;
                    373:              reply_port = stream_play_data->reg_port;
                    374:              break;
                    375:          }
                    376:          case SND_MT_RECORD_DATA: {
                    377:              snd_stream_record_data_t *record_data =
                    378:                  (snd_stream_record_data_t *)msg_type;
                    379: 
                    380:              *(int *)&msg_type += sizeof(*record_data);
                    381:              size -= sizeof(*record_data);
                    382: 
                    383:              options = record_data->options;
                    384:              snd_size = (vm_size_t)record_data->nbytes;
                    385:              /*
                    386:               * Note: record data is allocated in audio_server.
                    387:               */
                    388:              reply_port = record_data->reg_port;
                    389:              break;
                    390:          }
                    391:          case SND_MT_CONTROL:
                    392:            *(int *)&msg_type += sizeof(snd_stream_control_t);
                    393:            size -= sizeof(snd_stream_control_t);
                    394:            break;
                    395:          case SND_MT_FORMAT:
                    396:            *(int *)&msg_type += sizeof(snd_stream_format_t);
                    397:            size -= sizeof(snd_stream_format_t);
                    398:            break;
                    399:          case SND_MT_OPTIONS:
                    400:            *(int *)&msg_type += sizeof(snd_stream_options_t);
                    401:            size -= sizeof(snd_stream_options_t);
                    402:            break;
                    403:          case SND_MT_NDMA:
                    404:            *(int *)&msg_type += sizeof(snd_stream_ndma_t);
                    405:            size -= sizeof(snd_stream_ndma_t);
                    406:            break;
                    407:          default:
                    408:            /*
                    409:             * This shouldn't happen.
                    410:             */
                    411:            break;
                    412:        }
                    413: 
                    414:        /*
                    415:         * Enqueue the region.
                    416:         */
                    417:        if (snd_size) {
                    418:            u_int messages = 0;
                    419: 
                    420:            if ((options&SND_DM_STARTED_MSG) != 0)
                    421:                messages |= _NXAUDIO_MSG_STARTED;
                    422:            /*
                    423:             * Old recording code cannot handle completed msg.
                    424:             */
                    425:            if (direction == SND_DIR_PLAY &&
                    426:                (options&SND_DM_COMPLETED_MSG) != 0)
                    427:                messages |= _NXAUDIO_MSG_COMPLETED;
                    428:            if ((options&SND_DM_PAUSED_MSG) != 0)
                    429:                messages |= _NXAUDIO_MSG_PAUSED;
                    430:            if ((options&SND_DM_RESUMED_MSG) != 0)
                    431:                messages |= _NXAUDIO_MSG_RESUMED;
                    432:            if ((options&SND_DM_ABORTED_MSG) != 0)
                    433:                messages |= _NXAUDIO_MSG_ABORTED;
                    434:            if ((options&SND_DM_OVERFLOW_MSG) != 0)
                    435:                messages |= _NXAUDIO_MSG_UNDERRUN;
                    436:            
                    437:            if (direction == SND_DIR_PLAY) {
                    438:                if (set_format) {
                    439:                    snd_set_stream_format(direction, audioStream,
                    440:                                          sample_rate,
                    441:                                          data_encoding,
                    442:                                          chan_count,
                    443:                                          low_water, high_water);
                    444:                    kerr = _NXAudioPlayStreamData((OutputStream *)audioStream,
                    445:                                                  snd_data,
                    446:                                                  snd_size, data_tag,
                    447:                                                  reply_port, messages);
                    448:                    if (kerr != KERN_SUCCESS) {
                    449:                        xpr_audio_user("AU: snd_stream_msg: playStreamD "
                    450:                                       "returns %d\n", kerr, 2,3,4,5);
                    451:                    }
                    452:                } else {
                    453:                    if ([audioStream type] == _NXAUDIO_STREAM_TYPE_SND_22)
                    454:                        sample_rate = _NXAUDIO_RATE_22050;
                    455:                    else
                    456:                        sample_rate = _NXAUDIO_RATE_44100;
                    457:                    kerr = _NXAudioPlayStream((OutputStream *)audioStream,
                    458:                                              snd_data,
                    459:                                              snd_size,
                    460:                                              data_tag, 2, sample_rate,
                    461:                                              32768, 32768,     /* gains */
                    462:                                              low_water, high_water,
                    463:                                              reply_port, messages);
                    464:                    if (kerr != KERN_SUCCESS) {
                    465:                        /* audio_server deallocs data if error */
                    466:                        xpr_audio_user("AU: snd_stream_msg: playStream returns"
                    467:                                       " %d\n",kerr, 2,3,4,5);
                    468:                    }
                    469:                }
                    470:                /*
                    471:                 * Data has been enqueued. Send a message to the client
                    472:                 * telling that it is okay to enqueue more data. 
                    473:                 */
                    474:            } else {
                    475:                if (set_format) {
                    476:                    snd_set_stream_format(direction, audioStream,
                    477:                                          sample_rate,
                    478:                                          data_encoding,
                    479:                                          chan_count,
                    480:                                          low_water, high_water);
                    481:                    kerr = _NXAudioRecordStreamData((InputStream *)audioStream,
                    482:                                                    snd_size, data_tag,
                    483:                                                    reply_port, messages);
                    484:                    if (kerr != KERN_SUCCESS) {
                    485:                        xpr_audio_user("AU: snd_stream_msg: recStreamD returns"
                    486:                                       " %d\n",kerr, 2,3,4,5);
                    487:                    }
                    488:                } else {
                    489:                    kerr = _NXAudioRecordStream((InputStream *)audioStream,
                    490:                                                snd_size,
                    491:                                                data_tag,
                    492:                                                low_water, high_water,
                    493:                                                reply_port, messages);
                    494:                    if (kerr != KERN_SUCCESS)
                    495:                        xpr_audio_user("AU: snd_stream_msg: recordStream "
                    496:                                        "returns %d\n", kerr, 2,3,4,5);
                    497:                }
                    498:            }
                    499:        }
                    500:     }
                    501:        
                    502:     if (snd_control&SND_DC_RESUME) {
                    503:        kerr = _NXAudioStreamControl(audioStream, _NXAUDIO_STREAM_RESUME,
                    504:                                    time_now);
                    505:        if (kerr != KERN_SUCCESS)
                    506:            xpr_audio_user("AU: snd_stream_msg: streamControl returns %d\n",
                    507:                           kerr, 2,3,4,5);
                    508:     }
                    509: 
                    510:     return (error ? error : SND_NO_ERROR);
                    511: }
                    512: 
                    513: static void snd_get_stream_formats(void *dev, int *rates,
                    514:                                   int *low_rate, int *high_rate,
                    515:                                   int *encodings, int *chans)
                    516: {
                    517:     int parms[_NXAUDIO_PARAM_MAX];
                    518:     int count, continuous, i;
                    519:     kern_return_t kerr;
                    520: 
                    521:     kerr = _NXAudioGetSamplingRates(dev, &continuous, low_rate,
                    522:                                    high_rate, parms, &count);
                    523:     if (kerr != KERN_SUCCESS)
                    524:        xpr_audio_user("AU: snd_get_stream_formats: getSamplingRates returns "
                    525:                       "%d\n", kerr, 2,3,4,5);
                    526: 
                    527:     *rates = 0;
                    528:     if (continuous)
                    529:        *rates |= SND_STREAM_FORMAT_RATE_CONTINUOUS;
                    530:     for (i = 0; i < count; i++) {
                    531:        if (parms[i] >= 8000 && parms[i] <= 8013)
                    532:            *rates |= SND_STREAM_FORMAT_RATE_8000;
                    533:         else switch (parms[i]) {
                    534:          case 11025:
                    535:            *rates |= SND_STREAM_FORMAT_RATE_11025;
                    536:            break;
                    537:          case 16000:
                    538:            *rates |= SND_STREAM_FORMAT_RATE_16000;
                    539:            break;
                    540:          case 22050:
                    541:            *rates |= SND_STREAM_FORMAT_RATE_22050;
                    542:            break;
                    543:          case 32000:
                    544:            *rates |= SND_STREAM_FORMAT_RATE_32000;
                    545:            break;
                    546:          case 44100:
                    547:            *rates |= SND_STREAM_FORMAT_RATE_44100;
                    548:            break;
                    549:          case 48000:
                    550:            *rates |= SND_STREAM_FORMAT_RATE_48000;
                    551:            break;
                    552:          default:
                    553:            break;
                    554:        }
                    555:     }
                    556: 
                    557:     kerr = _NXAudioGetDataEncodings(dev, parms, &count);
                    558:     if (kerr != KERN_SUCCESS)
                    559:        xpr_audio_user("AU: snd_get_stream_formats: getDataEncodings returns "
                    560:                       "%d\n", kerr,2,3,4,5);
                    561: 
                    562:     *encodings = 0;
                    563:     for (i = 0; i < count; i++)
                    564:        switch (parms[i]) {
                    565:          case NX_SoundStreamDataEncoding_Mulaw8:
                    566:            *encodings |= SND_STREAM_FORMAT_ENCODING_MULAW_8;
                    567:            break;
                    568:          case NX_SoundStreamDataEncoding_Linear8:
                    569:            *encodings |= SND_STREAM_FORMAT_ENCODING_LINEAR_8;
                    570:            break;
                    571:          case NX_SoundStreamDataEncoding_Linear16:
                    572:            *encodings |= SND_STREAM_FORMAT_ENCODING_LINEAR_16;
                    573:            break;
                    574:          default:
                    575:            break;
                    576:        }
                    577:     kerr = _NXAudioGetChannelCountLimit(dev, chans);
                    578:     if (kerr != KERN_SUCCESS)
                    579:        xpr_audio_user("AU: snd_get_stream_formats: getChanCount returns %d\n", 
                    580:                        kerr, 2,3,4,5);
                    581: }
                    582: 
                    583: /*
                    584:  * Handle device port messages.
                    585:  */
                    586: static int snd_device_msg(msg_header_t *in_msg, msg_header_t *out_msg)
                    587: {
                    588:     int ret = SND_NO_ERROR;
                    589:     snd_get_stream_t *get_stream;
                    590:     snd_set_parms_t *set_parms;
                    591:     snd_get_volume_t *get_volume;
                    592:     snd_set_volume_t *set_volume;
                    593:     snd_set_owner_t *set_owner;
                    594:     snd_get_stream_formats_t *get_formats;
                    595:     snd_reset_owner_t *reset_owner;
                    596:     snd_new_device_t *new_device;
                    597:     u_int new_parms = 0, parms = 0;
                    598:     u_int vol;
                    599:     int lv, rv;
                    600:     int rates, low, high, encodings, chans;
                    601:     kern_return_t kerr;
                    602:     id audioChan;
                    603:     port_t new_stream, new_port;
                    604:     int stream_type;
                    605:     struct timeval time_now;
                    606:     AudioStream *audioStream;
                    607: 
                    608:     timerclear(&time_now);
                    609: 
                    610:     /*
                    611:      * The return values mean:
                    612:      * SND_NO_ERROR - no error but need a reply msg sent
                    613:      * 0 - no error, and no reply needed (we sent a reply)
                    614:      * other - error, send a reply message
                    615:      */
                    616: 
                    617:     switch (in_msg->msg_id) {
                    618:       case SND_MSG_GET_STREAM:
                    619:        if (in_msg->msg_size != sizeof(snd_get_stream_t))
                    620:            return SND_BAD_PARM;
                    621:        get_stream = (snd_get_stream_t *)in_msg;
                    622:        xpr_audio_user("AU: snd_dev_msg: get_stream 0x%x\n", 
                    623:                        get_stream->stream,2,3,4,5);
                    624: 
                    625:        if (get_stream->stream == SND_GD_SIN) {
                    626:            audioChan =
                    627:                [IOAudio _inputChannelForSndPort:in_msg->msg_local_port];
                    628:            xpr_audio_user("AU: snd_dev_msg: input chan 0x%x\n", audioChan, 
                    629:                                2,3,4,5);
                    630:            if (!(new_stream =
                    631:                  [audioChan streamUserForOwnerPort:get_stream->owner])) {
                    632:                kerr = _NXAudioAddStream(audioChan, &new_stream,
                    633:                                         get_stream->owner, 0, /* id */
                    634:                                         _NXAUDIO_STREAM_TYPE_SND);
                    635:                if (kerr != KERN_SUCCESS)
                    636:                    xpr_audio_user("AU: snd_dev_msg: addStream returns %d\n", 
                    637:                                        kerr, 2,3,4,5);
                    638:            }
                    639:        } else {
                    640:            if (get_stream->stream == SND_GD_SOUT_22)
                    641:                stream_type = _NXAUDIO_STREAM_TYPE_SND_22;
                    642:            else
                    643:                stream_type = _NXAUDIO_STREAM_TYPE_SND_44;
                    644:            audioChan =
                    645:                [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    646:            xpr_audio_user("AU: snd_dev_msg: output chan 0x%x\n", audioChan, 
                    647:                                2,3,4,5);
                    648:            if (!(new_stream =
                    649:                 [audioChan streamUserForOwnerPort:get_stream->owner])) {
                    650:                kerr = _NXAudioAddStream(audioChan, &new_stream,
                    651:                                         get_stream->owner, 0, /* id */
                    652:                                         stream_type);
                    653:                if (kerr != KERN_SUCCESS)
                    654:                    xpr_audio_user("AU: snd_dev_msg: addStream returns %d\n", 
                    655:                                        kerr,2,3,4,5);
                    656:            }
                    657:        }
                    658:        audio_snd_reply_ret_stream(out_msg, in_msg->msg_remote_port, new_stream);
                    659:        ret = 0;
                    660:        break;
                    661:       case SND_MSG_SET_PARMS:
                    662:        xpr_audio_user("AU: snd_dev_msg: set_parms\n", 1,2,3,4,5);
                    663:        if (in_msg->msg_size != sizeof(snd_set_parms_t))
                    664:            return SND_BAD_PARM;
                    665:        set_parms = (snd_set_parms_t *)in_msg;
                    666: 
                    667:        audioChan = [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    668:        kerr = _NXAudioGetSndoutOptions(audioChan, &new_parms);
                    669:        if (kerr != KERN_SUCCESS)
                    670:            xpr_audio_user("AU: snd_dev_msg: getSndoutOptions returns %d\n", 
                    671:                                kerr, 2,3,4,5);
                    672:        if (set_parms->parms&SND_PARM_ZEROFILL)
                    673:            new_parms |= _NXAUDIO_SNDOUT_ZEROFILL;
                    674:        else
                    675:            new_parms &= ~_NXAUDIO_SNDOUT_ZEROFILL;
                    676:        if (set_parms->parms&SND_PARM_SPEAKER)
                    677:            new_parms |= _NXAUDIO_SNDOUT_SPEAKER_ON;    
                    678:        else
                    679:            new_parms &= ~_NXAUDIO_SNDOUT_SPEAKER_ON;
                    680:        if (set_parms->parms&SND_PARM_LOWPASS)
                    681:            new_parms |= _NXAUDIO_SNDOUT_DEEMPHASIS;
                    682:        else
                    683:            new_parms &= ~_NXAUDIO_SNDOUT_DEEMPHASIS;
                    684: 
                    685:        kerr = _NXAudioSetSndoutOptions(audioChan, 0, new_parms);
                    686:        if (kerr != KERN_SUCCESS)
                    687:            xpr_audio_user("AU: snd_dev_msg: setSndoutOptions returns %d\n",
                    688:                                 kerr, 2,3,4,5);
                    689:        break;
                    690:       case SND_MSG_GET_PARMS:
                    691:        xpr_audio_user("AU: snd_dev_msg: get_parms\n", 1,2,3,4,5);
                    692:        if (in_msg->msg_size != sizeof(snd_get_parms_t))
                    693:            return SND_BAD_PARM;
                    694: 
                    695:        audioChan = [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    696:        kerr = _NXAudioGetSndoutOptions(audioChan, &new_parms);
                    697:        if (kerr != KERN_SUCCESS)
                    698:            xpr_audio_user("AU: snd_dev_msg: getSndoutOptions returns %d\n", 
                    699:                                kerr,2,3,4,5);
                    700:        if (new_parms&_NXAUDIO_SNDOUT_ZEROFILL)
                    701:            parms |= SND_PARM_ZEROFILL;
                    702:        if (new_parms&_NXAUDIO_SNDOUT_SPEAKER_ON)
                    703:            parms |= SND_PARM_SPEAKER;
                    704:        if (new_parms&_NXAUDIO_SNDOUT_DEEMPHASIS)
                    705:            parms |= SND_PARM_LOWPASS;
                    706: 
                    707:        audio_snd_reply_ret_parms(out_msg, in_msg->msg_remote_port, parms);
                    708:        ret = 0;
                    709:        break;
                    710:       case SND_MSG_SET_VOLUME:
                    711:        xpr_audio_user("AU: snd_dev_msg: set_vol\n", 1,2,3,4,5);
                    712:        if (in_msg->msg_size != sizeof(snd_set_volume_t))
                    713:            return SND_BAD_PARM;
                    714:        set_volume = (snd_set_volume_t *)in_msg;
                    715: 
                    716:        vol = set_volume->volume;
                    717:        lv = ((vol&SND_VOLUME_LCHAN_MASK) >>SND_VOLUME_LCHAN_SHIFT);
                    718:        rv = ((vol&SND_VOLUME_RCHAN_MASK) >>SND_VOLUME_RCHAN_SHIFT);
                    719:        xpr_audio_user("AU: snd_dev_msg: set_vol: %d %d\n", lv, rv, 3,4,5);
                    720:        /*
                    721:         * Convert from range [1,43] to [-84,0].
                    722:         */
                    723:        lv = ((lv-1)*2)-84;
                    724:        rv = ((rv-1)*2)-84;
                    725:        audioChan = [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    726:        kerr = _NXAudioSetSpeaker(audioChan, 0, lv, rv);
                    727:        if (kerr != KERN_SUCCESS)
                    728:            xpr_audio_user("AU: snd_dev_msg: setSpeaker returns %d\n", kerr,
                    729:                           2,3,4,5);
                    730:        break;
                    731:       case SND_MSG_GET_VOLUME:
                    732:        xpr_audio_user("AU: snd_dev_msg: get_vol\n", 1,2,3,4,5);
                    733:        if (in_msg->msg_size != sizeof(snd_get_volume_t))
                    734:            return SND_BAD_PARM;
                    735:        get_volume = (snd_get_volume_t *)in_msg;
                    736: 
                    737:        audioChan = [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    738:        kerr = _NXAudioGetSpeaker(audioChan, &lv, &rv);
                    739:        if (kerr != KERN_SUCCESS)
                    740:            xpr_audio_user("AU: snd_dev_msg: getSpeaker returns %d\n", kerr,
                    741:                           2,3,4,5);
                    742:        /*
                    743:         * Convert from range [-84,0] to [1,43].
                    744:         */
                    745:        lv = 43 + (lv/2);
                    746:        rv = 43 + (rv/2);
                    747:        vol = (lv<<SND_VOLUME_LCHAN_SHIFT) | (rv<<SND_VOLUME_RCHAN_SHIFT);
                    748: 
                    749:        xpr_audio_user("AU: snd_dev_msg: get_vol: %d %d\n", lv, rv, 3,4,5);
                    750:        audio_snd_reply_ret_volume(out_msg, in_msg->msg_remote_port, vol);
                    751:        ret = 0;
                    752:        break;
                    753:        /* New for 3.1 */
                    754:       case SND_MSG_GET_SNDOUT_FORMATS:
                    755:        xpr_audio_user("AU: snd_dev_msg: get_sndout_formats\n", 1,2,3,4,5);
                    756:        if (in_msg->msg_size != sizeof(snd_get_stream_formats_t))
                    757:            return SND_BAD_PARM;
                    758:        get_formats = (snd_get_stream_formats_t *)in_msg;
                    759:          
                    760:        audioChan = [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    761:        snd_get_stream_formats(audioChan, &rates, &low, &high,
                    762:                               &encodings, &chans);
                    763:        audio_snd_reply_ret_formats(out_msg, in_msg->msg_remote_port,
                    764:                              rates, low, high,
                    765:                              encodings, chans);
                    766:        ret = 0;
                    767:        break;
                    768:       case SND_MSG_GET_SNDIN_FORMATS:
                    769:        xpr_audio_user("AU: snd_dev_msg: get_sndin_formats\n", 1,2,3,4,5);
                    770:        if (in_msg->msg_size != sizeof(snd_get_stream_formats_t))
                    771:            return SND_BAD_PARM;
                    772:        get_formats = (snd_get_stream_formats_t *)in_msg;
                    773:          
                    774:        audioChan = [IOAudio _inputChannelForSndPort:in_msg->msg_local_port];
                    775:        snd_get_stream_formats(audioChan, &rates, &low, &high,
                    776:                               &encodings, &chans);
                    777:        audio_snd_reply_ret_formats(out_msg, in_msg->msg_remote_port,
                    778:                              rates, low, high,
                    779:                              encodings, chans);
                    780:        ret = 0;
                    781:        break;
                    782:       case SND_MSG_SET_RAMP:
                    783:        xpr_audio_user("AU: snd_dev_msg: set_ramp\n", 1,2,3,4,5);
                    784:        if (in_msg->msg_size != sizeof(snd_set_parms_t))
                    785:            return SND_BAD_PARM;
                    786:        set_parms = (snd_set_parms_t *)in_msg;
                    787: 
                    788:        audioChan = [IOAudio _outputChannelForSndPort:in_msg->msg_local_port];
                    789:        kerr = _NXAudioGetSndoutOptions(audioChan, &new_parms);
                    790:        if (kerr != KERN_SUCCESS)
                    791:            xpr_audio_user("AU: snd_dev_msg: getSndoutOptions returns %d\n", 
                    792:                        kerr, 2,3,4,5);
                    793:        if (set_parms->parms&SND_PARM_RAMPUP)
                    794:            new_parms |= _NXAUDIO_SNDOUT_RAMPUP;
                    795:        else
                    796:            new_parms &= ~_NXAUDIO_SNDOUT_RAMPUP;
                    797:        if (set_parms->parms&SND_PARM_RAMPDOWN)
                    798:            new_parms |= _NXAUDIO_SNDOUT_RAMPDOWN;
                    799:        else
                    800:            new_parms &= ~_NXAUDIO_SNDOUT_RAMPDOWN;
                    801: 
                    802:        kerr = _NXAudioSetSndoutOptions(audioChan, 0, new_parms);
                    803:        if (kerr != KERN_SUCCESS)
                    804:            xpr_audio_user("AU: snd_dev_msg: setSndoutOptions returns %d\n", 
                    805:                        kerr,2,3,4,5);
                    806:        break;
                    807:       case SND_MSG_SET_DSPOWNER:
                    808:        xpr_audio_user("AU: snd_dev_msg: set_dspowner\n", 1,2,3,4,5);
                    809:        /*
                    810:         * DSP is never available.
                    811:         */
                    812:        return SND_SEARCH;
                    813:        break;
                    814:       case SND_MSG_SET_SNDINOWNER:
                    815:        if (in_msg->msg_size != sizeof(snd_set_owner_t))
                    816:            return SND_BAD_PARM;
                    817:        set_owner = (snd_set_owner_t *)in_msg;
                    818:        xpr_audio_user("AU: snd_dev_msg: set_sndinowner 0x%x\n", 
                    819:                        set_owner->owner,2,3,4,5);
                    820:        /*
                    821:         * Abort (reset) stream if asserting same owner port.
                    822:         */
                    823:        if ((audioStream =
                    824:             [AudioChannel streamForOwnerPort:set_owner->owner])) {
                    825:            kerr = _NXAudioStreamControl(audioStream,
                    826:                                         _NXAUDIO_STREAM_ABORT, time_now);
                    827:            if (kerr != KERN_SUCCESS)
                    828:                xpr_audio_user("AU: snd_dev_msg: streamControl returns %d\n", 
                    829:                                kerr,2,3,4,5);
                    830:        }
                    831:        break;
                    832:       case SND_MSG_SET_SNDOUTOWNER:
                    833:        if (in_msg->msg_size != sizeof(snd_set_owner_t))
                    834:            return SND_BAD_PARM;
                    835:        set_owner = (snd_set_owner_t *)in_msg;
                    836:        xpr_audio_user("AU: snd_dev_msg: set_sndoutowner 0x%x\n", 
                    837:                        set_owner->owner, 2,3,4,5);
                    838:        /*
                    839:         * Abort (reset) stream if asserting same owner port.
                    840:         */
                    841:        if ((audioStream =
                    842:             [AudioChannel streamForOwnerPort:set_owner->owner])) {
                    843:            kerr = _NXAudioStreamControl(audioStream,
                    844:                                         _NXAUDIO_STREAM_ABORT, time_now);
                    845:            if (kerr != KERN_SUCCESS)
                    846:                xpr_audio_user("AU: snd_dev_msg: streamControl returns %d\n", 
                    847:                                kerr, 2,3,4,5);
                    848:        }
                    849:        break;
                    850:       case SND_MSG_NEW_DEVICE_PORT:
                    851:        /*
                    852:         * This is only marginally useful now, since the NXSound device
                    853:         * ports do NOT get reset by this message.
                    854:         */
                    855:        if (in_msg->msg_size != sizeof(snd_new_device_t))
                    856:            return SND_BAD_PARM;
                    857:        new_device = (snd_new_device_t *)in_msg;
                    858:        xpr_audio_user("AU: snd_dev_msg: new_device_port\n", 1,2,3,4,5);
                    859:        /*
                    860:         * Note: input and output chans share the same user msg device port.
                    861:         */
                    862:        audioChan = [IOAudio _outputChannelForSndPort: in_msg->msg_local_port];
                    863:        new_port = audio_reset_snd_dev_port([audioChan audioDevice],
                    864:                                            new_device->priv);
                    865:        if (new_port == PORT_NULL)
                    866:            return SND_BAD_HOST_PRIV;
                    867: 
                    868:        [audioChan removeSndStreams];
                    869:        audioChan = [IOAudio _inputChannelForSndPort: in_msg->msg_local_port];
                    870:        [audioChan removeSndStreams];
                    871: 
                    872:        audio_snd_reply_ret_device(out_msg, in_msg->msg_remote_port, new_port);
                    873:        ret = 0;
                    874:        break;
                    875:       case SND_MSG_RESET_SNDINOWNER:
                    876:        if (in_msg->msg_size != sizeof(snd_reset_owner_t))
                    877:            return SND_BAD_PARM;
                    878:        reset_owner = (snd_reset_owner_t *)in_msg;
                    879:        xpr_audio_user("AU: snd_dev_msg: reset_sndinowner 0x%x\n",
                    880:                       reset_owner->old_owner, 2,3,4,5);
                    881:        audioStream = [AudioChannel streamForOwnerPort:reset_owner->old_owner];
                    882:        if (!audioStream)
                    883:            return SND_NOT_OWNER;
                    884:        kerr = _NXAudioRemoveStream(audioStream);
                    885:        if (kerr != KERN_SUCCESS)
                    886:            xpr_audio_user("AU: snd_dev_msg: removeStream returns %d\n", kerr,
                    887:                           2,3,4,5);
                    888:        break;
                    889:       case SND_MSG_RESET_SNDOUTOWNER:
                    890:        if (in_msg->msg_size != sizeof(snd_reset_owner_t))
                    891:            return SND_BAD_PARM;
                    892:        reset_owner = (snd_reset_owner_t *)in_msg;
                    893:        xpr_audio_user("AU: snd_dev_msg: reset_sndoutowner 0x%x\n",
                    894:                       reset_owner->old_owner, 2,3,4,5);
                    895:        audioStream = [AudioChannel streamForOwnerPort:reset_owner->old_owner];
                    896:        if (!audioStream)
                    897:            return SND_NOT_OWNER;
                    898:        kerr = _NXAudioRemoveStream(audioStream);
                    899:        if (kerr != KERN_SUCCESS)
                    900:            xpr_audio_user("AU: snd_dev_msg: removeStream returns %d\n", kerr,
                    901:                           2,3,4,5);
                    902:        break;
                    903:       case SND_MSG_DSP_PROTO:
                    904:       case SND_MSG_GET_DSP_CMD_PORT:
                    905:       case SND_MSG_RESET_DSPOWNER:
                    906:        xpr_audio_user("AU: snd_dev_msg: dsp msg\n", 1,2,3,4,5);
                    907:        /*
                    908:         * DSP is never available.
                    909:         */
                    910:        return SND_SEARCH;
                    911:        break;
                    912:       default:
                    913:        /* impossible */
                    914:        break;
                    915:     }
                    916:     return ret;
                    917: }
                    918: 
                    919: /*
                    920:  * Handle in_msg and setup out_msg for reply.
                    921:  */
                    922: boolean_t snd_server(msg_header_t *in_msg, msg_header_t *out_msg)
                    923: {
                    924:     boolean_t ret = TRUE;
                    925:     int reply_val = 0;
                    926: 
                    927:     /*
                    928:      * Standard reply header.
                    929:      */
                    930:     out_msg->msg_simple = TRUE;
                    931:     out_msg->msg_size = sizeof(msg_header_t);
                    932:     out_msg->msg_type = MSG_TYPE_NORMAL;
                    933:     out_msg->msg_local_port = PORT_NULL;
                    934:     out_msg->msg_remote_port = PORT_NULL;
                    935:     out_msg->msg_id = 0;
                    936: 
                    937:     if (in_msg->msg_id >= SND_MSG_STREAM_BASE &&
                    938:        in_msg->msg_id <= SND_MSG_STREAM_NSAMPLES)
                    939:        reply_val = snd_stream_msg(in_msg, out_msg);
                    940:     else if (in_msg->msg_id >= SND_MSG_DEVICE_BASE &&
                    941:             in_msg->msg_id <= SND_MSG_GET_SNDIN_FORMATS)
                    942:        reply_val = snd_device_msg(in_msg, out_msg);
                    943:     else if (in_msg->msg_id >= SND_MSG_DSP_BASE &&
                    944:             in_msg->msg_id <= SND_MSG_DSP_REQ_ERR) {
                    945:        /*
                    946:         * Should not happen since you can't set a dsp owner port.
                    947:         */
                    948:        log_error(("Audio: received dsp cmd port msg!\n"));
                    949:        audio_snd_reply_illegal_msg(out_msg, PORT_NULL, in_msg->msg_remote_port,
                    950:                              in_msg->msg_id, SND_BAD_MSG);
                    951:        ret = FALSE;
                    952:     } else {
                    953:        audio_snd_reply_illegal_msg(out_msg, PORT_NULL, in_msg->msg_remote_port,
                    954:                              in_msg->msg_id, SND_BAD_MSG);
                    955:        ret = FALSE;
                    956:     }
                    957:     /*
                    958:      * Send a reply if msg handler routine didn't.
                    959:      */
                    960:     if (reply_val)
                    961:        audio_snd_reply_illegal_msg(out_msg, PORT_NULL, in_msg->msg_remote_port,
                    962:                              in_msg->msg_id, reply_val);
                    963:     return ret;
                    964: }

unix.superglobalmegacorp.com

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