static boolean rdpsnd_pulse_connect(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_context_state_t state; if (!pulse->context) return False; if (pa_context_connect(pulse->context, NULL, 0, NULL)) { DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return False; } pa_threaded_mainloop_lock(pulse->mainloop); if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return False; } for (;;) { state = pa_context_get_state(pulse->context); if (state == PA_CONTEXT_READY) break; if (!PA_CONTEXT_IS_GOOD(state)) { DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_CONTEXT_READY) { DEBUG_SVC("connected"); return True; } else { pa_context_disconnect(pulse->context); return False; } }
static BOOL tsmf_pulse_connect(TSMFPulseAudioDevice *pulse) { pa_context_state_t state; if(!pulse->context) return FALSE; if(pa_context_connect(pulse->context, NULL, 0, NULL)) { CLOG_ERR("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return FALSE; } pa_threaded_mainloop_lock(pulse->mainloop); if(pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); CLOG_ERR("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return FALSE; } for(;;) { state = pa_context_get_state(pulse->context); if(state == PA_CONTEXT_READY) break; if(!PA_CONTEXT_IS_GOOD(state)) { DEBUG_TSMF("bad context state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if(state == PA_CONTEXT_READY) { DEBUG_TSMF("connected"); return TRUE; } else { pa_context_disconnect(pulse->context); return FALSE; } }
/* * Create a new pulse audio main loop and connect to the server * * Returns a negative value on error */ static int pulse_connect(struct pulse_data *data) { data->mainloop = pa_mainloop_new(); if (!data->mainloop) { blog(LOG_ERROR, "pulse-input: Unable to create main loop"); return -1; } data->context = pa_context_new_with_proplist( pa_mainloop_get_api(data->mainloop), "OBS Studio", data->props); if (!data->context) { blog(LOG_ERROR, "pulse-input: Unable to create context"); return -1; } int status = pa_context_connect( data->context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); if (status < 0) { blog(LOG_ERROR, "pulse-input: Unable to connect! Status: %d", status); return -1; } // wait until connected for (;;) { pulse_iterate(data); pa_context_state_t state = pa_context_get_state(data->context); if (state == PA_CONTEXT_READY) { blog(LOG_DEBUG, "pulse-input: Context ready"); break; } if (!PA_CONTEXT_IS_GOOD(state)) { blog(LOG_ERROR, "pulse-input: Context connect failed"); return -1; } } return 0; }
void Context::contextStateCallback(pa_context *c) { qCDebug(PLASMAPA) << "state callback"; pa_context_state_t state = pa_context_get_state(c); if (state == PA_CONTEXT_READY) { qCDebug(PLASMAPA) << "ready"; // 1. Register for the stream changes (except during probe) if (m_context == c) { pa_context_set_subscribe_callback(c, subscribe_cb, this); if (!PAOperation(pa_context_subscribe(c, (pa_subscription_mask_t) (PA_SUBSCRIPTION_MASK_SINK| PA_SUBSCRIPTION_MASK_SOURCE| PA_SUBSCRIPTION_MASK_CLIENT| PA_SUBSCRIPTION_MASK_SINK_INPUT| PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| PA_SUBSCRIPTION_MASK_CARD| PA_SUBSCRIPTION_MASK_SERVER), nullptr, nullptr))) { qCWarning(PLASMAPA) << "pa_context_subscribe() failed"; return; } } if (!PAOperation(pa_context_get_sink_info_list(c, sink_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_sink_info_list() failed"; return; } if (!PAOperation(pa_context_get_source_info_list(c, source_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_source_info_list() failed"; return; } if (!PAOperation(pa_context_get_client_info_list(c, client_cb, this))) { qCWarning(PLASMAPA) << "pa_context_client_info_list() failed"; return; } if (!PAOperation(pa_context_get_card_info_list(c, card_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_card_info_list() failed"; return; } if (!PAOperation(pa_context_get_sink_input_info_list(c, sink_input_callback, this))) { qCWarning(PLASMAPA) << "pa_context_get_sink_input_info_list() failed"; return; } if (!PAOperation(pa_context_get_source_output_info_list(c, source_output_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_source_output_info_list() failed"; return; } if (!PAOperation(pa_context_get_server_info(c, server_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_server_info() failed"; return; } if (PAOperation(pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, this))) { pa_ext_stream_restore_set_subscribe_cb(c, ext_stream_restore_subscribe_cb, this); PAOperation(pa_ext_stream_restore_subscribe(c, 1, nullptr, this)); } else { qCWarning(PLASMAPA) << "Failed to initialize stream_restore extension"; } } else if (!PA_CONTEXT_IS_GOOD(state)) { qCWarning(PLASMAPA) << "context kaput"; if (m_context) { pa_context_unref(m_context); m_context = nullptr; } reset(); QTimer::singleShot(1000, this, &Context::connectToDaemon); } }
static int PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) { struct SDL_PrivateAudioData *h = NULL; Uint16 test_format = 0; pa_sample_spec paspec; pa_buffer_attr paattr; pa_channel_map pacmap; pa_stream_flags_t flags = 0; int state = 0; /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { return SDL_OutOfMemory(); } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); h = this->hidden; paspec.format = PA_SAMPLE_INVALID; /* Try for a closest match on audio format */ for (test_format = SDL_FirstAudioFormat(this->spec.format); (paspec.format == PA_SAMPLE_INVALID) && test_format;) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x\n", test_format); #endif switch (test_format) { case AUDIO_U8: paspec.format = PA_SAMPLE_U8; break; case AUDIO_S16LSB: paspec.format = PA_SAMPLE_S16LE; break; case AUDIO_S16MSB: paspec.format = PA_SAMPLE_S16BE; break; case AUDIO_S32LSB: paspec.format = PA_SAMPLE_S32LE; break; case AUDIO_S32MSB: paspec.format = PA_SAMPLE_S32BE; break; case AUDIO_F32LSB: paspec.format = PA_SAMPLE_FLOAT32LE; break; case AUDIO_F32MSB: paspec.format = PA_SAMPLE_FLOAT32BE; break; default: paspec.format = PA_SAMPLE_INVALID; break; } if (paspec.format == PA_SAMPLE_INVALID) { test_format = SDL_NextAudioFormat(); } } if (paspec.format == PA_SAMPLE_INVALID) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Couldn't find any hardware audio formats"); } this->spec.format = test_format; /* Calculate the final parameters for this audio specification */ #ifdef PA_STREAM_ADJUST_LATENCY this->spec.samples /= 2; /* Mix in smaller chunck to avoid underruns */ #endif SDL_CalculateAudioSpec(&this->spec); /* Allocate mixing buffer */ h->mixlen = this->spec.size; h->mixbuf = (Uint8 *) SDL_AllocAudioMem(h->mixlen); if (h->mixbuf == NULL) { PULSEAUDIO_CloseDevice(this); return SDL_OutOfMemory(); } SDL_memset(h->mixbuf, this->spec.silence, this->spec.size); paspec.channels = this->spec.channels; paspec.rate = this->spec.freq; /* Reduced prebuffering compared to the defaults. */ #ifdef PA_STREAM_ADJUST_LATENCY /* 2x original requested bufsize */ paattr.tlength = h->mixlen * 4; paattr.prebuf = -1; paattr.maxlength = -1; /* -1 can lead to pa_stream_writable_size() >= mixlen never being true */ paattr.minreq = h->mixlen; flags = PA_STREAM_ADJUST_LATENCY; #else paattr.tlength = h->mixlen*2; paattr.prebuf = h->mixlen*2; paattr.maxlength = h->mixlen*2; paattr.minreq = h->mixlen; #endif /* The SDL ALSA output hints us that we use Windows' channel mapping */ /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels, PA_CHANNEL_MAP_WAVEEX); /* Set up a new main loop */ if (!(h->mainloop = PULSEAUDIO_pa_mainloop_new())) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("pa_mainloop_new() failed"); } h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop); h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName()); if (!h->context) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("pa_context_new() failed"); } /* Connect to the PulseAudio server */ if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not setup connection to PulseAudio"); } do { if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("pa_mainloop_iterate() failed"); } state = PULSEAUDIO_pa_context_get_state(h->context); if (!PA_CONTEXT_IS_GOOD(state)) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not connect to PulseAudio"); } } while (state != PA_CONTEXT_READY); h->stream = PULSEAUDIO_pa_stream_new( h->context, "Simple DirectMedia Layer", /* stream description */ &paspec, /* sample format spec */ &pacmap /* channel map */ ); if (h->stream == NULL) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not set up PulseAudio stream"); } if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags, NULL, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not connect PulseAudio stream"); } do { if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("pa_mainloop_iterate() failed"); } state = PULSEAUDIO_pa_stream_get_state(h->stream); if (!PA_STREAM_IS_GOOD(state)) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not create to PulseAudio stream"); } } while (state != PA_STREAM_READY); /* We're ready to rock and roll. :-) */ return 0; }
/*! Starts up audio streaming to the host. */ void HostAudio::open() { m_mainloop = pa_threaded_mainloop_new(); if (!m_mainloop) { qDebug("Could not acquire PulseAudio main loop"); return; } m_api = pa_threaded_mainloop_get_api(m_mainloop); m_context = pa_context_new(m_api, "emumaster"); pa_context_set_state_callback(m_context, contextStreamCallback, this); if (!m_context) { qDebug("Could not acquire PulseAudio device context"); return; } #if defined(MEEGO_EDITION_HARMATTAN) if (pa_context_connect(m_context, 0, PA_CONTEXT_NOFLAGS, 0) < 0) { #elif defined(Q_WS_MAEMO_5) if (pa_context_connect(m_context, 0, (pa_context_flags_t)0, 0) < 0) { #endif int error = pa_context_errno(m_context); qDebug("Could not connect to PulseAudio server: %s", pa_strerror(error)); return; } pa_threaded_mainloop_lock(m_mainloop); if (pa_threaded_mainloop_start(m_mainloop) < 0) { qDebug("Could not start mainloop"); return; } waitForStreamReady(); pa_sample_spec fmt; fmt.channels = 2; fmt.format = PA_SAMPLE_S16LE; fmt.rate = 44100; pa_buffer_attr buffer_attributes; buffer_attributes.tlength = pa_bytes_per_second(&fmt) / 5; buffer_attributes.maxlength = buffer_attributes.tlength * 3; buffer_attributes.minreq = buffer_attributes.tlength / 3; buffer_attributes.prebuf = buffer_attributes.tlength; m_stream = pa_stream_new(m_context, "emumaster", &fmt, 0); if (!m_stream) { int error = pa_context_errno(m_context); qDebug("Could not acquire new PulseAudio stream: %s", pa_strerror(error)); return; } pa_stream_flags_t flags = (pa_stream_flags_t)(PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE); // pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS); if (pa_stream_connect_playback(m_stream, 0, &buffer_attributes, flags, 0, 0) < 0) { m_stream = 0; int error = pa_context_errno(m_context); qDebug("Could not connect for playback: %s", pa_strerror(error)); return; } waitForStreamReady(); pa_threaded_mainloop_unlock(m_mainloop); } /*! Stops audio streaming. */ void HostAudio::close() { if (m_mainloop) pa_threaded_mainloop_stop(m_mainloop); if (m_stream) { pa_stream_unref(m_stream); m_stream = 0; } if (m_context) { pa_context_disconnect(m_context); pa_context_unref(m_context); m_context = 0; } if (m_mainloop) { pa_threaded_mainloop_free(m_mainloop); m_mainloop = 0; } } /*! Streams a frame of audio from emulated system to the host. */ void HostAudio::sendFrame() { if (!m_stream) return; pa_threaded_mainloop_lock(m_mainloop); void *data; #if defined(MEEGO_EDITION_HARMATTAN) size_t size = -1; pa_stream_begin_write(m_stream, &data, &size); #elif defined(Q_WS_MAEMO_5) size_t size = 4096; static char buf[4096]; data = buf; #endif size = qMin(size, pa_stream_writable_size(m_stream)); if (size) size = m_emu->fillAudioBuffer(reinterpret_cast<char *>(data), size); if (size) pa_stream_write(m_stream, data, size, 0, 0, PA_SEEK_RELATIVE); #if defined(MEEGO_EDITION_HARMATTAN) else pa_stream_cancel_write(m_stream); #endif pa_threaded_mainloop_unlock(m_mainloop); } /*! \internal */ void HostAudio::waitForStreamReady() { pa_context_state_t context_state = pa_context_get_state(m_context); while (context_state != PA_CONTEXT_READY) { context_state = pa_context_get_state(m_context); if (!PA_CONTEXT_IS_GOOD(context_state)) { int error = pa_context_errno(m_context); qDebug("Context state is not good: %s", pa_strerror(error)); return; } else if (context_state == PA_CONTEXT_READY) { break; } else { //qDebug("PulseAudio context state is %d", context_state); } pa_threaded_mainloop_wait(m_mainloop); } }
static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec) { int state; Uint16 test_format; pa_sample_spec paspec; pa_buffer_attr paattr; pa_channel_map pacmap; pa_stream_flags_t flags = 0; paspec.format = PA_SAMPLE_INVALID; for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) { switch ( test_format ) { case AUDIO_U8: paspec.format = PA_SAMPLE_U8; break; case AUDIO_S16LSB: paspec.format = PA_SAMPLE_S16LE; break; case AUDIO_S16MSB: paspec.format = PA_SAMPLE_S16BE; break; } if ( paspec.format != PA_SAMPLE_INVALID ) break; test_format = SDL_NextAudioFormat(); } if (paspec.format == PA_SAMPLE_INVALID ) { SDL_SetError("Couldn't find any suitable audio formats"); return(-1); } spec->format = test_format; paspec.channels = spec->channels; paspec.rate = spec->freq; #ifdef PA_STREAM_ADJUST_LATENCY spec->samples /= 2; #endif SDL_CalculateAudioSpec(spec); mixlen = spec->size; mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); if ( mixbuf == NULL ) { return(-1); } SDL_memset(mixbuf, spec->silence, spec->size); #ifdef PA_STREAM_ADJUST_LATENCY paattr.tlength = mixlen * 4; paattr.prebuf = -1; paattr.maxlength = -1; paattr.minreq = mixlen; flags = PA_STREAM_ADJUST_LATENCY; #else paattr.tlength = mixlen*2; paattr.prebuf = mixlen*2; paattr.maxlength = mixlen*2; paattr.minreq = mixlen; #endif SDL_NAME(pa_channel_map_init_auto)( &pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX); if (!(mainloop = SDL_NAME(pa_mainloop_new)())) { PULSE_CloseAudio(this); SDL_SetError("pa_mainloop_new() failed"); return(-1); } if (this->hidden->caption == NULL) { char *title = NULL; SDL_WM_GetCaption(&title, NULL); PULSE_SetCaption(this, title); } mainloop_api = SDL_NAME(pa_mainloop_get_api)(mainloop); if (!(context = SDL_NAME(pa_context_new)(mainloop_api, this->hidden->caption))) { PULSE_CloseAudio(this); SDL_SetError("pa_context_new() failed"); return(-1); } if (SDL_NAME(pa_context_connect)(context, NULL, 0, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("Could not setup connection to PulseAudio"); return(-1); } do { if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("pa_mainloop_iterate() failed"); return(-1); } state = SDL_NAME(pa_context_get_state)(context); if (!PA_CONTEXT_IS_GOOD(state)) { PULSE_CloseAudio(this); SDL_SetError("Could not connect to PulseAudio"); return(-1); } } while (state != PA_CONTEXT_READY); stream = SDL_NAME(pa_stream_new)( context, "Simple DirectMedia Layer", &paspec, &pacmap ); if ( stream == NULL ) { PULSE_CloseAudio(this); SDL_SetError("Could not setup PulseAudio stream"); return(-1); } if (SDL_NAME(pa_stream_connect_playback)(stream, NULL, &paattr, flags, NULL, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("Could not connect PulseAudio stream"); return(-1); } do { if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("pa_mainloop_iterate() failed"); return(-1); } state = SDL_NAME(pa_stream_get_state)(stream); if (!PA_STREAM_IS_GOOD(state)) { PULSE_CloseAudio(this); SDL_SetError("Could not create to PulseAudio stream"); return(-1); } } while (state != PA_STREAM_READY); return(0); }
/* common */ static void *qpa_audio_init(Audiodev *dev) { paaudio *g; AudiodevPaOptions *popts = &dev->u.pa; const char *server; if (!popts->has_server) { char pidfile[64]; char *runtime; struct stat st; runtime = getenv("XDG_RUNTIME_DIR"); if (!runtime) { return NULL; } snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime); if (stat(pidfile, &st) != 0) { return NULL; } } assert(dev->driver == AUDIODEV_DRIVER_PA); g = g_malloc(sizeof(paaudio)); server = popts->has_server ? popts->server : NULL; g->dev = dev; g->mainloop = NULL; g->context = NULL; g->mainloop = pa_threaded_mainloop_new (); if (!g->mainloop) { goto fail; } g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop), server); if (!g->context) { goto fail; } pa_context_set_state_callback (g->context, context_state_cb, g); if (pa_context_connect(g->context, server, 0, NULL) < 0) { qpa_logerr (pa_context_errno (g->context), "pa_context_connect() failed\n"); goto fail; } pa_threaded_mainloop_lock (g->mainloop); if (pa_threaded_mainloop_start (g->mainloop) < 0) { goto unlock_and_fail; } for (;;) { pa_context_state_t state; state = pa_context_get_state (g->context); if (state == PA_CONTEXT_READY) { break; } if (!PA_CONTEXT_IS_GOOD (state)) { qpa_logerr (pa_context_errno (g->context), "Wrong context state\n"); goto unlock_and_fail; } /* Wait until the context is ready */ pa_threaded_mainloop_wait (g->mainloop); } pa_threaded_mainloop_unlock (g->mainloop); return g; unlock_and_fail: pa_threaded_mainloop_unlock (g->mainloop); fail: AUD_log (AUDIO_CAP, "Failed to initialize PA context"); qpa_audio_fini(g); return NULL; }
static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{ { pulse_data *data = ppa_xmalloc0(sizeof(pulse_data)); pa_context_state_t state; if(ppa_get_binary_name(data->path_name, sizeof(data->path_name))) data->context_name = ppa_path_get_filename(data->path_name); else data->context_name = "OpenAL Soft"; if(!(data->loop = ppa_threaded_mainloop_new())) { AL_PRINT("pa_threaded_mainloop_new() failed!\n"); goto out; } if(ppa_threaded_mainloop_start(data->loop) < 0) { AL_PRINT("pa_threaded_mainloop_start() failed\n"); goto out; } ppa_threaded_mainloop_lock(data->loop); data->context = ppa_context_new(ppa_threaded_mainloop_get_api(data->loop), data->context_name); if(!data->context) { AL_PRINT("pa_context_new() failed: %s\n", ppa_strerror(ppa_context_errno(data->context))); ppa_threaded_mainloop_unlock(data->loop); goto out; } if(ppa_context_connect(data->context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) { AL_PRINT("Context did not connect: %s\n", ppa_strerror(ppa_context_errno(data->context))); ppa_context_unref(data->context); data->context = NULL; ppa_threaded_mainloop_unlock(data->loop); goto out; } while((state=ppa_context_get_state(data->context)) != PA_CONTEXT_READY) { if(!PA_CONTEXT_IS_GOOD(state)) { AL_PRINT("Context did not get ready: %s\n", ppa_strerror(ppa_context_errno(data->context))); ppa_context_unref(data->context); data->context = NULL; ppa_threaded_mainloop_unlock(data->loop); goto out; } ppa_threaded_mainloop_unlock(data->loop); Sleep(1); ppa_threaded_mainloop_lock(data->loop); } device->szDeviceName = strdup(device_name); device->ExtraData = data; ppa_threaded_mainloop_unlock(data->loop); return ALC_TRUE; out: if(data->loop) { ppa_threaded_mainloop_stop(data->loop); ppa_threaded_mainloop_free(data->loop); } ppa_xfree(data); return ALC_FALSE; } //}}}
void SetupSound (void) { int error_number; // Acquire mainloop /////////////////////////////////////////////////////// device.mainloop = pa_threaded_mainloop_new (); if (device.mainloop == NULL) { fprintf (stderr, "Could not acquire PulseAudio main loop\n"); return; } // Acquire context //////////////////////////////////////////////////////// device.api = pa_threaded_mainloop_get_api (device.mainloop); device.context = pa_context_new (device.api, "PCSXR"); pa_context_set_state_callback (device.context, context_state_cb, &device); if (device.context == NULL) { fprintf (stderr, "Could not acquire PulseAudio device context\n"); return; } // Connect to PulseAudio server /////////////////////////////////////////// if (pa_context_connect (device.context, NULL, 0, NULL) < 0) { error_number = pa_context_errno (device.context); fprintf (stderr, "Could not connect to PulseAudio server: %s\n", pa_strerror(error_number)); return; } // Run mainloop until sever context is ready ////////////////////////////// pa_threaded_mainloop_lock (device.mainloop); if (pa_threaded_mainloop_start (device.mainloop) < 0) { fprintf (stderr, "Could not start mainloop\n"); return; } pa_context_state_t context_state; context_state = pa_context_get_state (device.context); while (context_state != PA_CONTEXT_READY) { context_state = pa_context_get_state (device.context); if (! PA_CONTEXT_IS_GOOD (context_state)) { error_number = pa_context_errno (device.context); fprintf (stderr, "Context state is not good: %s\n", pa_strerror (error_number)); return; } else if (context_state == PA_CONTEXT_READY) break; else fprintf (stderr, "PulseAudio context state is %d\n", context_state); pa_threaded_mainloop_wait (device.mainloop); } // Set sample spec //////////////////////////////////////////////////////// device.spec.format = PA_SAMPLE_S16NE; if (iDisStereo) device.spec.channels = 1; else device.spec.channels = 2; device.spec.rate = settings.frequency; pa_buffer_attr buffer_attributes; buffer_attributes.tlength = pa_bytes_per_second (& device.spec) / 5; buffer_attributes.maxlength = buffer_attributes.tlength * 3; buffer_attributes.minreq = buffer_attributes.tlength / 3; buffer_attributes.prebuf = buffer_attributes.tlength; //maxlength = buffer_attributes.maxlength; //fprintf (stderr, "Total space: %u\n", buffer_attributes.maxlength); //fprintf (stderr, "Minimum request size: %u\n", buffer_attributes.minreq); //fprintf (stderr, "Bytes needed before playback: %u\n", buffer_attributes.prebuf); //fprintf (stderr, "Target buffer size: %lu\n", buffer_attributes.tlength); // Acquire new stream using spec ////////////////////////////////////////// device.stream = pa_stream_new (device.context, "PCSXR", &device.spec, NULL); if (device.stream == NULL) { error_number = pa_context_errno (device.context); fprintf (stderr, "Could not acquire new PulseAudio stream: %s\n", pa_strerror (error_number)); return; } // Set callbacks for server events //////////////////////////////////////// pa_stream_set_state_callback (device.stream, stream_state_cb, &device); pa_stream_set_write_callback (device.stream, stream_request_cb, &device); pa_stream_set_latency_update_callback (device.stream, stream_latency_update_cb, &device); // Ready stream for playback ////////////////////////////////////////////// pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE); //pa_stream_flags_t flags = (pa_stream_flags_t) (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS); if (pa_stream_connect_playback (device.stream, NULL, &buffer_attributes, flags, NULL, NULL) < 0) { pa_context_errno (device.context); fprintf (stderr, "Could not connect for playback: %s\n", pa_strerror (error_number)); return; } // Run mainloop until stream is ready ///////////////////////////////////// pa_stream_state_t stream_state; stream_state = pa_stream_get_state (device.stream); while (stream_state != PA_STREAM_READY) { stream_state = pa_stream_get_state (device.stream); if (stream_state == PA_STREAM_READY) break; else if (! PA_STREAM_IS_GOOD (stream_state)) { error_number = pa_context_errno (device.context); fprintf (stderr, "Stream state is not good: %s\n", pa_strerror (error_number)); return; } else fprintf (stderr, "PulseAudio stream state is %d\n", stream_state); pa_threaded_mainloop_wait (device.mainloop); } pa_threaded_mainloop_unlock (device.mainloop); fprintf (stderr, "PulseAudio should be connected\n"); return; }
static gboolean gst_pulsesrc_open (GstAudioSrc * asrc) { GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc); gchar *name = gst_pulse_client_name (); pa_threaded_mainloop_lock (pulsesrc->mainloop); g_assert (!pulsesrc->context); g_assert (!pulsesrc->stream); GST_DEBUG_OBJECT (pulsesrc, "opening device"); if (!(pulsesrc->context = pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop), name))) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"), (NULL)); goto unlock_and_fail; } pa_context_set_state_callback (pulsesrc->context, gst_pulsesrc_context_state_cb, pulsesrc); GST_DEBUG_OBJECT (pulsesrc, "connect to server %s", GST_STR_NULL (pulsesrc->server)); if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s", pa_strerror (pa_context_errno (pulsesrc->context))), (NULL)); goto unlock_and_fail; } for (;;) { pa_context_state_t state; state = pa_context_get_state (pulsesrc->context); if (!PA_CONTEXT_IS_GOOD (state)) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s", pa_strerror (pa_context_errno (pulsesrc->context))), (NULL)); goto unlock_and_fail; } if (state == PA_CONTEXT_READY) break; /* Wait until the context is ready */ pa_threaded_mainloop_wait (pulsesrc->mainloop); } GST_DEBUG_OBJECT (pulsesrc, "connected"); pa_threaded_mainloop_unlock (pulsesrc->mainloop); g_free (name); return TRUE; /* ERRORS */ unlock_and_fail: { gst_pulsesrc_destroy_context (pulsesrc); pa_threaded_mainloop_unlock (pulsesrc->mainloop); g_free (name); return FALSE; } }
pa_simple* pa_simple_new( const char *server, const char *name, pa_stream_direction_t dir, const char *dev, const char *stream_name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_buffer_attr *attr, int *rerror) { pa_simple *p; int error = PA_ERR_INTERNAL, r; CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL); CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL); CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL); CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL); CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL) p = pa_xnew0(pa_simple, 1); p->direction = dir; if (!(p->mainloop = pa_threaded_mainloop_new())) goto fail; if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name))) goto fail; pa_context_set_state_callback(p->context, context_state_cb, p); if (pa_context_connect(p->context, server, 0, NULL) < 0) { error = pa_context_errno(p->context); goto fail; } pa_threaded_mainloop_lock(p->mainloop); if (pa_threaded_mainloop_start(p->mainloop) < 0) goto unlock_and_fail; for (;;) { pa_context_state_t state; state = pa_context_get_state(p->context); if (state == PA_CONTEXT_READY) break; if (!PA_CONTEXT_IS_GOOD(state)) { error = pa_context_errno(p->context); goto unlock_and_fail; } /* Wait until the context is ready */ pa_threaded_mainloop_wait(p->mainloop); } if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) { error = pa_context_errno(p->context); goto unlock_and_fail; } pa_stream_set_state_callback(p->stream, stream_state_cb, p); pa_stream_set_read_callback(p->stream, stream_request_cb, p); pa_stream_set_write_callback(p->stream, stream_request_cb, p); pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p); if (dir == PA_STREAM_PLAYBACK) r = pa_stream_connect_playback(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING |PA_STREAM_ADJUST_LATENCY |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); else r = pa_stream_connect_record(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING |PA_STREAM_ADJUST_LATENCY |PA_STREAM_AUTO_TIMING_UPDATE); if (r < 0) { error = pa_context_errno(p->context); goto unlock_and_fail; } for (;;) { pa_stream_state_t state; state = pa_stream_get_state(p->stream); if (state == PA_STREAM_READY) break; if (!PA_STREAM_IS_GOOD(state)) { error = pa_context_errno(p->context); goto unlock_and_fail; } /* Wait until the stream is ready */ pa_threaded_mainloop_wait(p->mainloop); } pa_threaded_mainloop_unlock(p->mainloop); return p; unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); fail: if (rerror) *rerror = error; pa_simple_free(p); return NULL; }
int main(int argc, char **argv) { M6502 *mpu; Strudel *mb; pa_mainloop_api *api; pa_context *context; pa_stream *stream; pa_context_state_t state; pa_sample_spec spec; int r; gtk_init(&argc, &argv); if (argc != 2) { fprintf(stderr, "You must specify a disk image.\n"); return EXIT_FAILURE; } mb = calloc(1, sizeof(*mb)); mb->main = calloc(65536, sizeof(*mb->main)); mb->aux = calloc(65536, sizeof(*mb->aux)); mb->firmware = calloc(65536, sizeof(*mb->firmware)); mb->key = calloc(256, 1); mb->keyr = 0; mb->keyw = 0; mpu = M6502_new(mb, call_cb, read_cb, write_cb); loop = pa_threaded_mainloop_new(); api = pa_threaded_mainloop_get_api(loop); context = pa_context_new(api, "strudel"); pa_context_connect(context, NULL, 0, NULL); pa_threaded_mainloop_start(loop); for (;;) { state = pa_context_get_state(context); if (state == PA_CONTEXT_READY) break; else if (!PA_CONTEXT_IS_GOOD(state)) { fprintf(stderr, "bad context state (%d)\n", pa_context_errno(context)); return EXIT_FAILURE; } } spec.rate = 44100; spec.channels = 1; spec.format = PA_SAMPLE_S16LE; stream = pa_stream_new(context, "output", &spec, NULL); if (!stream) { fprintf(stderr, "pa_stream_new failed\n"); return EXIT_FAILURE; } pa_stream_set_write_callback(stream, stream_request_cb, mpu); r = pa_stream_connect_playback(stream, NULL, NULL, 0, NULL, NULL); if (r < 0) { fprintf(stderr, "pa_stream_connect_playback failed\n"); return EXIT_FAILURE; } mb->s6d1 = fopen(argv[1], "r+"); if (mb->s6d1 == NULL) { fprintf(stderr, "Can't open '%s'.\n", argv[1]); return EXIT_FAILURE; } load(mpu, "./firmware.rom"); /* Create buffers for raw and scaled screen */ screen = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 560, 384); /* Create main window. */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Strudel"); g_signal_connect(window, "delete-event", G_CALLBACK(delete_event), NULL); g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL); g_signal_connect(window, "key-press-event", G_CALLBACK(key), mpu); /* Create screen widget. */ drawing_area = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(window), drawing_area); gtk_widget_set_events(drawing_area, GDK_EXPOSURE_MASK); gtk_widget_set_size_request(drawing_area, 560, 384); M6502_do(mpu, M6502_RST); g_idle_add(idle, mpu); /* Go. */ gtk_widget_show_all(window); gtk_main(); M6502_delete(mpu); return 0; }
static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec) { int state; Uint16 test_format; pa_sample_spec paspec; pa_buffer_attr paattr; pa_channel_map pacmap; pa_stream_flags_t flags = 0; paspec.format = PA_SAMPLE_INVALID; for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) { switch ( test_format ) { case AUDIO_U8: paspec.format = PA_SAMPLE_U8; break; case AUDIO_S16LSB: paspec.format = PA_SAMPLE_S16LE; break; case AUDIO_S16MSB: paspec.format = PA_SAMPLE_S16BE; break; } if ( paspec.format != PA_SAMPLE_INVALID ) break; } if (paspec.format == PA_SAMPLE_INVALID ) { SDL_SetError("Couldn't find any suitable audio formats"); return(-1); } spec->format = test_format; paspec.channels = spec->channels; paspec.rate = spec->freq; /* Calculate the final parameters for this audio specification */ #ifdef PA_STREAM_ADJUST_LATENCY spec->samples /= 2; /* Mix in smaller chunck to avoid underruns */ #endif SDL_CalculateAudioSpec(spec); /* Allocate mixing buffer */ mixlen = spec->size; mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); if ( mixbuf == NULL ) { return(-1); } SDL_memset(mixbuf, spec->silence, spec->size); /* Reduced prebuffering compared to the defaults. */ #ifdef PA_STREAM_ADJUST_LATENCY paattr.tlength = mixlen * 4; /* 2x original requested bufsize */ paattr.prebuf = -1; paattr.maxlength = -1; paattr.minreq = mixlen; /* -1 can lead to pa_stream_writable_size() >= mixlen never becoming true */ flags = PA_STREAM_ADJUST_LATENCY; #else paattr.tlength = mixlen*2; paattr.prebuf = mixlen*2; paattr.maxlength = mixlen*2; paattr.minreq = mixlen; #endif /* The SDL ALSA output hints us that we use Windows' channel mapping */ /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ SDL_NAME(pa_channel_map_init_auto)( &pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX); /* Set up a new main loop */ if (!(mainloop = SDL_NAME(pa_mainloop_new)())) { PULSE_CloseAudio(this); SDL_SetError("pa_mainloop_new() failed"); return(-1); } mainloop_api = SDL_NAME(pa_mainloop_get_api)(mainloop); if (!(context = SDL_NAME(pa_context_new)(mainloop_api, get_progname()))) { PULSE_CloseAudio(this); SDL_SetError("pa_context_new() failed"); return(-1); } /* Connect to the PulseAudio server */ if (SDL_NAME(pa_context_connect)(context, NULL, 0, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("Could not setup connection to PulseAudio"); return(-1); } do { if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("pa_mainloop_iterate() failed"); return(-1); } state = SDL_NAME(pa_context_get_state)(context); if (!PA_CONTEXT_IS_GOOD(state)) { PULSE_CloseAudio(this); SDL_SetError("Could not connect to PulseAudio"); return(-1); } } while (state != PA_CONTEXT_READY); stream = SDL_NAME(pa_stream_new)( context, "Simple DirectMedia Layer", /* stream description */ &paspec, /* sample format spec */ &pacmap /* channel map */ ); if ( stream == NULL ) { PULSE_CloseAudio(this); SDL_SetError("Could not setup PulseAudio stream"); return(-1); } if (SDL_NAME(pa_stream_connect_playback)(stream, NULL, &paattr, flags, NULL, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("Could not connect PulseAudio stream"); return(-1); } do { if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { PULSE_CloseAudio(this); SDL_SetError("pa_mainloop_iterate() failed"); return(-1); } state = SDL_NAME(pa_stream_get_state)(stream); if (!PA_STREAM_IS_GOOD(state)) { PULSE_CloseAudio(this); SDL_SetError("Could not create to PulseAudio stream"); return(-1); } } while (state != PA_STREAM_READY); return(0); }
static int pa_init_boilerplate(struct ao *ao) { struct priv *priv = ao->priv; char *host = priv->cfg_host && priv->cfg_host[0] ? priv->cfg_host : NULL; bool locked = false; pthread_mutex_init(&priv->wakeup_lock, NULL); pthread_cond_init(&priv->wakeup, NULL); if (!(priv->mainloop = pa_threaded_mainloop_new())) { MP_ERR(ao, "Failed to allocate main loop\n"); goto fail; } if (pa_threaded_mainloop_start(priv->mainloop) < 0) goto fail; pa_threaded_mainloop_lock(priv->mainloop); locked = true; if (!(priv->context = pa_context_new(pa_threaded_mainloop_get_api( priv->mainloop), ao->client_name))) { MP_ERR(ao, "Failed to allocate context\n"); goto fail; } MP_VERBOSE(ao, "Library version: %s\n", pa_get_library_version()); MP_VERBOSE(ao, "Proto: %lu\n", (long)pa_context_get_protocol_version(priv->context)); MP_VERBOSE(ao, "Server proto: %lu\n", (long)pa_context_get_server_protocol_version(priv->context)); pa_context_set_state_callback(priv->context, context_state_cb, ao); pa_context_set_subscribe_callback(priv->context, subscribe_cb, ao); if (pa_context_connect(priv->context, host, 0, NULL) < 0) goto fail; /* Wait until the context is ready */ while (1) { int state = pa_context_get_state(priv->context); if (state == PA_CONTEXT_READY) break; if (!PA_CONTEXT_IS_GOOD(state)) goto fail; pa_threaded_mainloop_wait(priv->mainloop); } pa_threaded_mainloop_unlock(priv->mainloop); return 0; fail: if (locked) pa_threaded_mainloop_unlock(priv->mainloop); if (priv->context) { pa_threaded_mainloop_lock(priv->mainloop); if (!(pa_context_errno(priv->context) == PA_ERR_CONNECTIONREFUSED && ao->probing)) GENERIC_ERR_MSG("Init failed"); pa_threaded_mainloop_unlock(priv->mainloop); } uninit(ao); return -1; }
INT16 m1sdr_Init(int sample_rate) { int format, stereo, rate, fsize, err, state; unsigned int nfreq, periodtime; snd_pcm_hw_params_t *hwparams; #ifdef USE_SDL SDL_AudioSpec aspec; #endif pa_channel_map chanmap; pa_buffer_attr my_pa_attr; hw_present = 0; m1sdr_Callback = NULL; nDSoundSegLen = sample_rate / 60; switch (lnxdrv_apimode) { case 0: // SDL #ifdef USE_SDL SDL_InitSubSystem(SDL_INIT_AUDIO); m1sdr_SetSamplesPerTick(sample_rate/60); playbuf = 0; writebuf = 1; aspec.freq = sample_rate; aspec.format = AUDIO_S16SYS; // keep endian independant aspec.channels = 2; aspec.samples = 512; // has to be a power of 2, and we want it smaller than our buffer size aspec.callback = sdl_callback; aspec.userdata = 0; if (SDL_OpenAudio(&aspec, NULL) < 0) { printf("ERROR: can't open SDL audio\n"); return 0; } // make sure we don't start yet SDL_PauseAudio(1); #endif break; case 1: // ALSA // Try to open audio device if ((err = snd_pcm_open(&pHandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "ALSA: Could not open soundcard (%s)\n", snd_strerror(err)); hw_present = 0; return 0; } if ((err = snd_pcm_hw_params_malloc(&hwparams)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); return 0; } // Init hwparams with full configuration space if ((err = snd_pcm_hw_params_any(pHandle, hwparams)) < 0) { fprintf(stderr, "ALSA: couldn't set hw params (%s)\n", snd_strerror(err)); hw_present = 0; return 0; } // Set access type if ((err = snd_pcm_hw_params_set_access(pHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "ALSA: can't set access (%s)\n", snd_strerror(err)); return 0; } // Set sample format if ((err = snd_pcm_hw_params_set_format(pHandle, hwparams, SND_PCM_FORMAT_S16)) < 0) { fprintf(stderr, "ALSA: can't set format (%s)\n", snd_strerror(err)); return 0; } // Set sample rate (nearest possible) nfreq = sample_rate; if ((err = snd_pcm_hw_params_set_rate_near(pHandle, hwparams, &nfreq, 0)) < 0) { fprintf(stderr, "ALSA: can't set sample rate (%s)\n", snd_strerror(err)); return 0; } // Set number of channels if ((err = snd_pcm_hw_params_set_channels(pHandle, hwparams, 2)) < 0) { fprintf(stderr, "ALSA: can't set stereo (%s)\n", snd_strerror(err)); return 0; } // Set period time (nearest possible) periodtime = 16; if ((err = snd_pcm_hw_params_set_period_time_near(pHandle, hwparams, &periodtime, 0)) < 0) { fprintf(stderr, "ALSA: can't set period time (%s)\n", snd_strerror(err)); return 0; } // Apply HW parameter settings to PCM device and prepare device if ((err = snd_pcm_hw_params(pHandle, hwparams)) < 0) { fprintf(stderr, "ALSA: unable to install hw_params (%s)\n", snd_strerror(err)); snd_pcm_hw_params_free(hwparams); return 0; } snd_pcm_hw_params_free(hwparams); if ((err = snd_pcm_prepare(pHandle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror(err)); return 0; } break; case 2: // OSS audiofd = open("/dev/dsp", O_WRONLY, 0); if (audiofd == -1) { audiofd = open("/dev/dsp1", O_WRONLY, 0); if (audiofd == -1) { perror("/dev/dsp1"); return(0); } } // reset things ioctl(audiofd, SNDCTL_DSP_RESET, 0); is_broken_driver = 0; num_frags = NUM_FRAGS_NORMAL; // set the buffer size we want fsize = OSS_FRAGMENT; if (ioctl(audiofd, SNDCTL_DSP_SETFRAGMENT, &fsize) == - 1) { perror("SNDCTL_DSP_SETFRAGMENT"); return(0); } // set 16-bit output format = AFMT_S16_NE; // 16 bit signed "native"-endian if (ioctl(audiofd, SNDCTL_DSP_SETFMT, &format) == - 1) { perror("SNDCTL_DSP_SETFMT"); return(0); } // now set stereo stereo = 1; if (ioctl(audiofd, SNDCTL_DSP_STEREO, &stereo) == - 1) { perror("SNDCTL_DSP_STEREO"); return(0); } // and the sample rate rate = sample_rate; if (ioctl(audiofd, SNDCTL_DSP_SPEED, &rate) == - 1) { perror("SNDCTL_DSP_SPEED"); return(0); } // and make sure that did what we wanted ioctl(audiofd, SNDCTL_DSP_GETBLKSIZE, &fsize); break; case 3: // PulseAudio sample_spec.format = PA_SAMPLE_S16NE; sample_spec.rate = sample_rate; sample_spec.channels = 2; my_pa_context = NULL; my_pa_stream = NULL; my_pa_mainloop = NULL; my_pa_mainloop_api = NULL; #if !PULSE_USE_SIMPLE // get default channel mapping pa_channel_map_init_auto(&chanmap, sample_spec.channels, PA_CHANNEL_MAP_WAVEEX); if (!(my_pa_mainloop = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed\n"); return 0; } my_pa_mainloop_api = pa_mainloop_get_api(my_pa_mainloop); /* if (pa_signal_init(my_pa_mainloop_api) != 0) { fprintf(stderr, "pa_signal_init() failed\n"); return 0; }*/ /* Create a new connection context */ if (!(my_pa_context = pa_context_new(my_pa_mainloop_api, "Audio Overload"))) { fprintf(stderr, "pa_context_new() failed\n"); return 0; } /* set the context state CB */ // pa_context_set_state_callback(my_pa_context, context_state_callback, NULL); /* Connect the context */ if (pa_context_connect(my_pa_context, NULL, (pa_context_flags_t)0, NULL) < 0) { fprintf(stderr, "pa_context_connect() failed: %s", pa_strerror(pa_context_errno(my_pa_context))); return 0; } do { pa_mainloop_iterate(my_pa_mainloop, 1, NULL); state = pa_context_get_state(my_pa_context); if (!PA_CONTEXT_IS_GOOD((pa_context_state_t)state)) { printf("PA CONTEXT NOT GOOD\n"); hw_present = 0; return 0; } } while (state != PA_CONTEXT_READY); if (!(my_pa_stream = pa_stream_new(my_pa_context, "Audio Overload", &sample_spec, &chanmap))) { fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(my_pa_context))); return 0; } memset(&my_pa_attr, 0, sizeof(my_pa_attr)); my_pa_attr.tlength = nDSoundSegLen * 4 * 4; my_pa_attr.prebuf = -1; my_pa_attr.maxlength = -1; my_pa_attr.minreq = nDSoundSegLen * 4 * 2; if ((err = pa_stream_connect_playback(my_pa_stream, NULL, &my_pa_attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL)) < 0) { fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(my_pa_context))); return 0; } do { pa_mainloop_iterate(my_pa_mainloop, 1, NULL); state = pa_stream_get_state(my_pa_stream); if (!PA_STREAM_IS_GOOD((pa_stream_state_t)state)) { printf("PA STREAM NOT GOOD\n"); hw_present = 0; return 0; } } while (state != PA_STREAM_READY); // printf("PulseAudio setup OK so far, len %d\n", nDSoundSegLen*4); #else my_simple = NULL; #endif break; } hw_present = 1; return (1); }