|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.