- pthread_create(<id, 0, listen_thread, 0);
-#if API_ALSA
- {
- struct packet *p;
- int escape, err;
-
- /* Open the sound device */
- setup_alsa();
- pthread_mutex_lock(&lock);
- for(;;) {
- /* Wait for the buffer to fill up a bit */
- fill_buffer();
- if(!alsa_prepared) {
- if((err = snd_pcm_prepare(pcm)))
- fatal(0, "error calling snd_pcm_prepare: %d", err);
- alsa_prepared = 1;
- }
- escape = 0;
- info("Playing...");
- /* Keep playing until the buffer empties out, or ALSA tells us to get
- * lost */
- while(nsamples >= minbuffer && !escape) {
- /* Wait for ALSA to ask us for more data */
- pthread_mutex_unlock(&lock);
- wait_alsa();
- pthread_mutex_lock(&lock);
- /* ALSA is ready for more data, find something to play */
- p = next_packet();
- /* Play it or play some silence */
- if(contains(p, next_timestamp))
- escape = alsa_play(p);
- else
- escape = alsa_infill(p);
- }
- active = 0;
- /* We stop playing for a bit until the buffer re-fills */
- pthread_mutex_unlock(&lock);
- alsa_reset(escape);
- pthread_mutex_lock(&lock);
- }
-
- }
-#elif HAVE_COREAUDIO_AUDIOHARDWARE_H
- {
- OSStatus status;
- UInt32 propertySize;
- AudioDeviceID adid;
- AudioStreamBasicDescription asbd;
-
- /* If this looks suspiciously like libao's macosx driver there's an
- * excellent reason for that... */
-
- /* TODO report errors as strings not numbers */
- propertySize = sizeof adid;
- status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
- &propertySize, &adid);
- if(status)
- fatal(0, "AudioHardwareGetProperty: %d", (int)status);
- if(adid == kAudioDeviceUnknown)
- fatal(0, "no output device");
- propertySize = sizeof asbd;
- status = AudioDeviceGetProperty(adid, 0, false,
- kAudioDevicePropertyStreamFormat,
- &propertySize, &asbd);
- if(status)
- fatal(0, "AudioHardwareGetProperty: %d", (int)status);
- D(("mSampleRate %f", asbd.mSampleRate));
- D(("mFormatID %08lx", asbd.mFormatID));
- D(("mFormatFlags %08lx", asbd.mFormatFlags));
- D(("mBytesPerPacket %08lx", asbd.mBytesPerPacket));
- D(("mFramesPerPacket %08lx", asbd.mFramesPerPacket));
- D(("mBytesPerFrame %08lx", asbd.mBytesPerFrame));
- D(("mChannelsPerFrame %08lx", asbd.mChannelsPerFrame));
- D(("mBitsPerChannel %08lx", asbd.mBitsPerChannel));
- D(("mReserved %08lx", asbd.mReserved));
- if(asbd.mFormatID != kAudioFormatLinearPCM)
- fatal(0, "audio device does not support kAudioFormatLinearPCM");
- status = AudioDeviceAddIOProc(adid, adioproc, 0);
- if(status)
- fatal(0, "AudioDeviceAddIOProc: %d", (int)status);
- pthread_mutex_lock(&lock);
- for(;;) {
- /* Wait for the buffer to fill up a bit */
- fill_buffer();
- /* Start playing now */
- info("Playing...");
- next_timestamp = pheap_first(&packets)->timestamp;
- active = 1;
- status = AudioDeviceStart(adid, adioproc);
- if(status)
- fatal(0, "AudioDeviceStart: %d", (int)status);
- /* Wait until the buffer empties out */
- while(nsamples >= minbuffer)
- pthread_cond_wait(&cond, &lock);
- /* Stop playing for a bit until the buffer re-fills */
- status = AudioDeviceStop(adid, adioproc);
- if(status)
- fatal(0, "AudioDeviceStop: %d", (int)status);
- active = 0;
- /* Go back round */
- }
- }
-#else
-# error No known audio API
-#endif