void audio_play(int n,short *data) { int endian = 1; #define little_endian ((*((char *)&endian) == 1)) int priv = 0; AuEvent ev; Sound s = SoundCreate(SoundFileFormatNone, little_endian ? AuFormatLinearSigned16LSB : AuFormatLinearSigned16MSB, 1, samp_rate, n, "Chit chat"); if (aud) { #ifdef USE_ALL_ARGS AuStatus ret_status; AuFlowID flow = 0; int monitor = 0; int multiplier = 0; if (!AuSoundPlayFromData(aud, s, data, AuNone, AuFixedPointFromFraction(volume, 100), done, &priv, &flow, &multiplier, &monitor, &ret_status)) #else if (!AuSoundPlayFromData(aud, s, data, AuNone, AuFixedPointFromFraction(volume, 100), done, &priv, NULL, NULL, NULL, NULL)) #endif perror("problems playing data"); else { while (1) { AuNextEvent(aud, AuTrue, &ev); AuDispatchEvent(aud, &ev); if (priv) break; } } } SoundDestroy(s); }
static int sound_nas_play(audio_job_t aj) { /* stream stuff */ Lisp_Media_Stream *ms; media_substream *mss; /* thread stuff */ media_thread_play_state mtp; /* device stuff */ Lisp_Object device; Lisp_Audio_Device *lad = NULL; sound_nas_data_t *snd = NULL; /* nas stuff */ AuElement elms[3]; AuStatus as; int bsize = 0; /* subthread stuff */ sound_nas_aj_data_t _snsd, *snsd = &_snsd; sxe_mse_volume_args _volargs, *volargs = &_volargs; sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs; /* cache stuff */ int alloced_myself = 0; SOUND_UNPACK_MT(aj, device, ms, mss, lad, snd, snsd->mtap); /* refuse to do anything if the AuServer pointer is not set */ if (snd->aud == NULL) { NAS_DEBUG_C("b0rked connection, gute Nacht!\n"); return 0; } /* install error handlers before anything else */ AuSetErrorHandler(snd->aud, nas_error_handler); AuSetIOErrorHandler(snd->aud, nas_IOerror_handler); /* find physical output device */ snsd->dev = nas_find_device(snd->aud, snsd->mtap->channels); if (snsd->dev == AuNone || !(snsd->flow = AuCreateFlow(snd->aud, NULL))) { /* No physical output device found or flow creation failed. */ NAS_DEBUG_C("no physical devices for this stream\n"); return 0; } /* A system call interrupted with a SIGALRM or SIGIO comes back here */ if (SETJMP(nas_server_sig)) { NAS_CRITICAL("Caught the lethal signal.\n"); snd->aud = NULL; sound_nas_finish(snd); goto uhoh; } /* init the snsd */ snsd->samplerate = 0; snsd->framesize = (snsd->channels = snsd->mtap->channels) * sizeof(int16_t); snsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16); snsd->coe_ch_cnt = 0; snsd->resolution = (snsd->mtap->samplerate * MTPSTATE_REACT_TIME) / 1000000; bsize = (snsd->resolution + NAS_FRAG_SIZE - 1) & ~(NAS_FRAG_SIZE-1); snsd->snd = snd; snsd->buffer_size = bsize; snsd->writepos = snsd->readpos = 0; snsd->overfill = snsd->underrun = 0; /* set up flow */ AuMakeElementImportClient(elms+0, snsd->mtap->samplerate, AuFormatLinearSigned16LSB, snsd->mtap->channels, AuTrue, bsize, bsize / 2, 0, NULL); snsd->gain = AuFixedPointFromFraction(1, 1); AuMakeElementMultiplyConstant(elms+1, 0, snsd->gain); AuMakeElementExportDevice(elms+2, 0, snsd->dev, snsd->mtap->samplerate, AuUnlimitedSamples, 0, NULL); AuSetElements(snd->aud, snsd->flow, AuTrue, 3, elms, &as); if (as != AuSuccess) { NAS_DEBUG_C("play(): AuSetElements failed\n"); return 0; } #if 0 /* atm we insist on having stereo access */ /* the channel effect */ ADD_MEDIA_SAMPLE_EFFECT( snsd->coe_chain, snsd->coe_ch_cnt, MEDIA_SAMPLE_EFFECT(sxe_mse_2ch_to_1ch), NULL); #endif /* the volume effect */ ADD_MEDIA_SAMPLE_EFFECT( snsd->coe_chain, snsd->coe_ch_cnt, MEDIA_SAMPLE_EFFECT(sxe_mse_volume), volargs); volargs->num_channels = snsd->channels; snsd->volargs = volargs; /* the rerate effect */ ADD_MEDIA_SAMPLE_EFFECT( snsd->coe_chain, snsd->coe_ch_cnt, MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs); rrargs->num_channels = snsd->channels; rrargs->srcrate = rrargs->tgtrate = 1; snsd->rrargs = rrargs; AuRegisterEventHandler(snd->aud, AuEventHandlerIDMask | AuEventHandlerTypeMask, AuEventTypeElementNotify, snsd->flow, nas_event_handler, (AuPointer)aj); /* rewind the stream */ media_stream_meth(ms, rewind)(mss); /* play chunks of the stream */ SXE_MUTEX_LOCK(&aj->mtx); if (aj->buffer_alloc_size < SOUND_MAX_AUDIO_FRAME_SIZE) { alloced_myself = 1; aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE); aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE; } SXE_MUTEX_UNLOCK(&aj->mtx); snsd->mtp = MTPSTATE_STOP; snsd->volume = -1; audio_job_device_data(aj) = snsd; /* prefill the buffer */ NAS_DEBUG_S("prefill the buffer: %d\n", 4*bsize); if (!nas_fill(aj, 4*bsize)) goto uhoh; while (aj->play_state != MTPSTATE_STOP) { #if 0 if (aj->volume != snsd->volume) { AuElementParameters aep; NAS_DEBUG_S("Setting volume.\n"); snsd->volume = aj->volume; snsd->gain = AU_FIXED_POINT_SCALE*(snsd->volume)/127; aep.parameters[AuParmsMultiplyConstantConstant] = snsd->gain; aep.flow = snd->flow; aep.element_num = 1; aep.num_parameters = AuParmsMultiplyConstant; AuSetElementParameters(snd->aud, 1, &aep, &as); if (as != AuSuccess) { NAS_DEBUG_S("Setting volume failed.\n"); } } #endif #ifdef EF_USE_ASYNEQ /* events for me audio-job? */ if (audio_job_queue(aj)) { sound_nas_handle_aj_events(aj); } #endif SXE_MUTEX_LOCK(&aj->mtx); mtp = aj->play_state; SXE_MUTEX_UNLOCK(&aj->mtx); switch (mtp) { case MTPSTATE_RUN: if (snsd->mtp != mtp) { NAS_DEBUG("ah, gotta work again\n"); AuStartFlow(snd->aud, snsd->flow, &as); if (as != AuSuccess) { NAS_DEBUG_C("play(): " "AuStartFlow failed\n"); aj->play_state = MTPSTATE_STOP; } } nas_empty_event_queue(snsd); usleep(snsd->resolution); break; case MTPSTATE_PAUSE: if (snsd->mtp != mtp) { NAS_DEBUG("sleeping for %d\n", snsd->resolution); AuStopFlow(snd->aud, snsd->flow, &as); } usleep(snsd->resolution); break; case MTPSTATE_UNKNOWN: case MTPSTATE_STOP: case NUMBER_OF_MEDIA_THREAD_PLAY_STATES: default: NAS_DEBUG("ACK, quit\n"); AuStopFlow(snd->aud, snsd->flow, &as); SXE_MUTEX_LOCK(&aj->mtx); aj->play_state = MTPSTATE_STOP; SXE_MUTEX_UNLOCK(&aj->mtx); break; } snsd->mtp = mtp; } uhoh: /* -- Close and shutdown -- */ SXE_MUTEX_LOCK(&aj->mtx); if (alloced_myself && aj->buffer) { xfree(aj->buffer); } aj->buffer = NULL; aj->buffer_alloc_size = 0; SXE_MUTEX_UNLOCK(&aj->mtx); return 1; }