int main(int argc, char *argv[]) { pa_mainloop *m; m = pa_mainloop_new(); assert(m); pa_cpu_limit_init(pa_mainloop_get_api(m)); time(&start); #ifdef TEST2 pa_signal_init(pa_mainloop_get_api(m)); pa_signal_new(SIGUSR1, func, NULL); raise(SIGUSR1); pa_mainloop_run(m, NULL); pa_signal_done(); #else for (;;) { time_t now; time(&now); if ((now - start) >= 30) { fprintf(stderr, "Test failed\n"); break; } } #endif pa_cpu_limit_done(); pa_mainloop_free(m); return 0; }
int PulseAudioDriver::thread_body() { m_main_loop = pa_mainloop_new(); pa_mainloop_api* api = pa_mainloop_get_api(m_main_loop); pa_io_event* ioev = api->io_new(api, m_pipe[0], PA_IO_EVENT_INPUT, pipe_callback, this); m_ctx = pa_context_new(api, "Hydrogen"); pa_context_set_state_callback(m_ctx, ctx_state_callback, this); pa_context_connect(m_ctx, 0, pa_context_flags_t(0), 0); int retval; pa_mainloop_run(m_main_loop, &retval); if (m_stream) { pa_stream_set_state_callback(m_stream, 0, 0); pa_stream_set_write_callback(m_stream, 0, 0); pa_stream_unref(m_stream); m_stream = 0; } api->io_free(ioev); pa_context_unref(m_ctx); pa_mainloop_free(m_main_loop); return retval; }
bool PulseHandler::Init(void) { if (m_initialised) return m_valid; m_initialised = true; // Initialse our connection to the server m_loop = pa_mainloop_new(); if (!m_loop) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get PulseAudio mainloop"); return m_valid; } pa_mainloop_api *api = pa_mainloop_get_api(m_loop); if (!api) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get PulseAudio api"); return m_valid; } if (pa_signal_init(api) != 0) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialise signaling"); return m_valid; } const char *client = "mythtv"; m_ctx = pa_context_new(api, client); if (!m_ctx) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create context"); return m_valid; } // remember which thread created this object for later sanity debugging m_thread = QThread::currentThread(); // we set the callback, connect and then run the main loop 'by hand' // until we've successfully connected (or not) pa_context_set_state_callback(m_ctx, StatusCallback, this); pa_context_connect(m_ctx, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); int ret = 0; int tries = 0; while ((tries++ < 100) && !IS_READY(m_ctx_state)) { pa_mainloop_iterate(m_loop, 0, &ret); usleep(10000); } if (PA_CONTEXT_READY != m_ctx_state) { LOG(VB_GENERAL, LOG_ERR, LOC + "Context not ready after 1000ms"); return m_valid; } LOG(VB_AUDIO, LOG_INFO, LOC + "Initialised handler"); m_valid = true; return m_valid; }
/* * Initialize pulseAudio */ static int init_pa(recorder_context_t *rctx) { pa_mainloop_api *pa_mlapi; pa_proplist *ctx_properties = pa_proplist_new(); pa_proplist *stream_properties = pa_proplist_new(); int retval = 0; rctx->pa_ml = pa_mainloop_new(); pa_mlapi = pa_mainloop_get_api(rctx->pa_ml); rctx->pa_ctx = pa_context_new_with_proplist(pa_mlapi, "NoApp recorder", ctx_properties); pa_context_connect(rctx->pa_ctx, NULL, 0, NULL); rctx->pa_ready = 0; pa_context_set_state_callback(rctx->pa_ctx, pa_state_cb, rctx); while (rctx->pa_ready == 0){ pa_mainloop_iterate(rctx->pa_ml, 1, NULL); } if (rctx->pa_ready == 2){ retval = -1; goto exit; } rctx->recording_stream = pa_stream_new_with_proplist(rctx->pa_ctx, "NoApp recorder", &rctx->pa_ss, NULL, stream_properties); retval = pa_stream_connect_record(rctx->recording_stream, NULL, NULL, 0); if (retval < 0){ Log(LOG_ERR, "pa_stream_connect_playback failed\n"); goto exit; } exit: return retval; }
int main(int argc, char *argv[]) { // Define our pulse audio loop and connection variables pa_mainloop *pa_ml; pa_mainloop_api *pa_mlapi; pa_operation *pa_op; pa_time_event *time_event; // Create a mainloop API and connection to the default server pa_ml = pa_mainloop_new(); pa_mlapi = pa_mainloop_get_api(pa_ml); context = pa_context_new(pa_mlapi, "Device list"); // This function connects to the pulse server pa_context_connect(context, NULL, 0, NULL); // This function defines a callback so the server will tell us its state. pa_context_set_state_callback(context, context_state_cb, NULL); if (pa_mainloop_run(pa_ml, &ret) < 0) { printf("pa_mainloop_run() failed."); exit(1); } }
void vis::PulseAudioSource::populate_default_source_name() { #ifdef _ENABLE_PULSE pa_mainloop_api *mainloop_api; pa_context *pulseaudio_context; // Create a mainloop API and connection to the default server m_pulseaudio_mainloop = pa_mainloop_new(); mainloop_api = pa_mainloop_get_api(m_pulseaudio_mainloop); pulseaudio_context = pa_context_new(mainloop_api, "vis device list"); // This function connects to the pulse server pa_context_connect(pulseaudio_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr); // This function defines a callback so the server will tell us its state. pa_context_set_state_callback(pulseaudio_context, pulseaudio_context_state_callback, reinterpret_cast<void *>(this)); int ret; if (pa_mainloop_run(m_pulseaudio_mainloop, &ret) < 0) { VIS_LOG(vis::LogLevel::ERROR, "Could not open pulseaudio mainloop to " "find default device name: %d", ret); } #endif }
Error AudioDriverPulseAudio::init() { active = false; thread_exited = false; exit_thread = false; mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); pa_ml = pa_mainloop_new(); ERR_FAIL_COND_V(pa_ml == NULL, ERR_CANT_OPEN); pa_ctx = pa_context_new(pa_mainloop_get_api(pa_ml), "Godot"); ERR_FAIL_COND_V(pa_ctx == NULL, ERR_CANT_OPEN); pa_ready = 0; pa_context_set_state_callback(pa_ctx, pa_state_cb, (void *)this); int ret = pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFLAGS, NULL); if (ret < 0) { if (pa_ctx) { pa_context_unref(pa_ctx); pa_ctx = NULL; } if (pa_ml) { pa_mainloop_free(pa_ml); pa_ml = NULL; } return ERR_CANT_OPEN; } while (pa_ready == 0) { pa_mainloop_iterate(pa_ml, 1, NULL); } if (pa_ready < 0) { if (pa_ctx) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_ctx = NULL; } if (pa_ml) { pa_mainloop_free(pa_ml); pa_ml = NULL; } return ERR_CANT_OPEN; } Error err = init_device(); if (err == OK) { mutex = Mutex::create(); thread = Thread::create(AudioDriverPulseAudio::thread_func, this); } return OK; }
static int pa_get_devicelist(AudioDeviceInfoList& input) { pa_mainloop *pa_ml; pa_mainloop_api *pa_mlapi; pa_operation *pa_op; pa_context *pa_ctx; int state = 0; int pa_ready = 0; pa_ml = pa_mainloop_new(); pa_mlapi = pa_mainloop_get_api(pa_ml); pa_ctx = pa_context_new(pa_mlapi, "USBqemu-devicelist"); pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFLAGS, NULL); pa_context_set_state_callback(pa_ctx, pa_context_state_cb, &pa_ready); for (;;) { if (pa_ready == 0) { pa_mainloop_iterate(pa_ml, 1, NULL); continue; } // Connection failed if (pa_ready == 2) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return -1; } switch (state) { case 0: pa_op = pa_context_get_source_info_list(pa_ctx, pa_sourcelist_cb, &input); state++; break; case 1: if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { pa_operation_unref(pa_op); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return 0; } break; default: return -1; } pa_mainloop_iterate(pa_ml, 1, NULL); } }
bool PulseDeviceFinder::Initialise() { mainloop_ = pa_mainloop_new(); if (!mainloop_) { qLog(Warning) << "Failed to create pulseaudio mainloop"; return false; } return Reconnect(); }
bool PulseAudio::init(bool) { pa_ml = pa_mainloop_new(); pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml); pa_context* pa_ctx = pa_context_new(pa_mlapi, "MuseScore"); if (pa_context_connect(pa_ctx, NULL, pa_context_flags_t(0), NULL) != 0) qDebug("PulseAudio Context Connect Failed with Error: %s", pa_strerror(pa_context_errno(pa_ctx))); int pa_ready = 0; pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); while (pa_ready == 0) pa_mainloop_iterate(pa_ml, 1, NULL); if (pa_ready == 2) return false; ss.rate = _sampleRate; ss.channels = 2; ss.format = PA_SAMPLE_FLOAT32LE; pa_stream* playstream = pa_stream_new(pa_ctx, "Playback", &ss, NULL); if (!playstream) { qDebug("pa_stream_new failed"); return false; } pa_stream_set_write_callback(playstream, paCallback, this); bufattr.fragsize = (uint32_t)-1; bufattr.maxlength = FRAMES * 2 * sizeof(float); bufattr.minreq = FRAMES * 1 * sizeof(float); // pa_usec_to_bytes(0, &ss); bufattr.prebuf = (uint32_t)-1; bufattr.tlength = bufattr.maxlength; int r = pa_stream_connect_playback(playstream, NULL, &bufattr, pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); if (r < 0) { // Old pulse audio servers don't like the ADJUST_LATENCY flag, so retry without that r = pa_stream_connect_playback(playstream, NULL, &bufattr, pa_stream_flags_t(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); } if (r < 0) { qDebug("pa_stream_connect_playback failed"); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); pa_ml = 0; return false; } return true; }
int main(int argc, char *argv[]) { pa_mainloop_api *a; pa_io_event *ioe; pa_time_event *te; struct timeval tv; #ifdef GLIB_MAIN_LOOP pa_glib_mainloop *g; glib_main_loop = g_main_loop_new(NULL, FALSE); assert(glib_main_loop); g = pa_glib_mainloop_new(NULL); assert(g); a = pa_glib_mainloop_get_api(g); assert(a); #else /* GLIB_MAIN_LOOP */ pa_mainloop *m; m = pa_mainloop_new(); assert(m); a = pa_mainloop_get_api(m); assert(a); #endif /* GLIB_MAIN_LOOP */ ioe = a->io_new(a, 0, PA_IO_EVENT_INPUT, iocb, NULL); assert(ioe); de = a->defer_new(a, dcb, NULL); assert(de); te = a->time_new(a, pa_timeval_rtstore(&tv, pa_rtclock_now() + 2 * PA_USEC_PER_SEC, TRUE), tcb, NULL); #if defined(GLIB_MAIN_LOOP) g_main_loop_run(glib_main_loop); #else pa_mainloop_run(m, NULL); #endif a->time_free(te); a->defer_free(de); a->io_free(ioe); #ifdef GLIB_MAIN_LOOP pa_glib_mainloop_free(g); g_main_loop_unref(glib_main_loop); #else pa_mainloop_free(m); #endif return 0; }
int pa_get_devicelist(pa_devicelist_t *output) { pa_mainloop *pa_ml = NULL; pa_mainloop_api *pa_mlapi = NULL; pa_operation *pa_op = NULL; pa_context *pa_ctx = NULL; uint8_t state = 0; int pa_ready = 0; memset(output, 0, sizeof(pa_devicelist_t) * 16); if ( (pa_ml = pa_mainloop_new()) == NULL) return -1; if ( (pa_mlapi = pa_mainloop_get_api(pa_ml)) == NULL ) return -2; if ( (pa_ctx = pa_context_new(pa_mlapi, "test")) == NULL) return -3; pa_context_connect(pa_ctx, NULL, 0, NULL); pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); while (1) { if (pa_ready == 0) { pa_mainloop_iterate(pa_ml, 1, NULL); continue; } if (pa_ready == 2) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return -1; } switch (state) { case 0: pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, output); state++; break; case 1: if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { pa_operation_unref(pa_op); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return 0; } break; default: return -1; } pa_mainloop_iterate(pa_ml, 1, NULL); } }
bool PulseAudio::PulseInit() { m_pa_error = 0; m_pa_connected = 0; // create pulseaudio main loop and context // also register the async state callback which is called when the connection to the pa server has changed m_pa_ml = pa_mainloop_new(); m_pa_mlapi = pa_mainloop_get_api(m_pa_ml); m_pa_ctx = pa_context_new(m_pa_mlapi, "dolphin-emu"); m_pa_error = pa_context_connect(m_pa_ctx, nullptr, PA_CONTEXT_NOFLAGS, nullptr); pa_context_set_state_callback(m_pa_ctx, StateCallback, this); // wait until we're connected to the pulseaudio server while (m_pa_connected == 0 && m_pa_error >= 0) m_pa_error = pa_mainloop_iterate(m_pa_ml, 1, nullptr); if (m_pa_connected == 2 || m_pa_error < 0) { ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", pa_strerror(m_pa_error)); return false; } // create a new audio stream with our sample format // also connect the callbacks for this stream pa_sample_spec ss; ss.format = PA_SAMPLE_S16LE; ss.channels = 2; ss.rate = m_mixer->GetSampleRate(); m_pa_s = pa_stream_new(m_pa_ctx, "Playback", &ss, nullptr); pa_stream_set_write_callback(m_pa_s, WriteCallback, this); pa_stream_set_underflow_callback(m_pa_s, UnderflowCallback, this); // connect this audio stream to the default audio playback // limit buffersize to reduce latency m_pa_ba.fragsize = -1; m_pa_ba.maxlength = -1; // max buffer, so also max latency m_pa_ba.minreq = -1; // don't read every byte, try to group them _a bit_ m_pa_ba.prebuf = -1; // start as early as possible m_pa_ba.tlength = BUFFER_SIZE; // designed latency, only change this flag for low latency output pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); m_pa_error = pa_stream_connect_playback(m_pa_s, nullptr, &m_pa_ba, flags, nullptr, nullptr); if (m_pa_error < 0) { ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", pa_strerror(m_pa_error)); return false; } INFO_LOG(AUDIO, "Pulse successfully initialized"); return true; }
int main(int argc, const char *argv[]) { pa_mainloop *pa_ml = NULL; pa_mainloop_api *pa_mlapi = NULL; pa_operation *pa_op = NULL; pa_context *pa_ctx = NULL; int pa_ready = 0; int state = 0; pa_ml = pa_mainloop_new(); pa_mlapi = pa_mainloop_get_api(pa_ml); pa_ctx = pa_context_new(pa_mlapi, "deepin"); pa_context_connect(pa_ctx, NULL, 0, NULL); pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); for (;;) { if (pa_ready == 0) { pa_mainloop_iterate(pa_ml, 1, NULL); continue; } if (pa_ready == 2) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return -1; } switch (state) { case 0: pa_op = pa_context_get_source_output_info_list(pa_ctx, pa_source_output_cb, NULL); state++; break; case 1: if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { pa_operation_unref(pa_op); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return 0; } break; default: fprintf(stderr, "in state %d\n", state); return -1; } pa_mainloop_iterate(pa_ml, 1, NULL); } return 0; }
bool PulseAudio::init(bool) { pa_ml = pa_mainloop_new(); pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml); pa_context* pa_ctx = pa_context_new(pa_mlapi, "MuseScore"); if (pa_context_connect(pa_ctx, NULL, pa_context_flags_t(0), NULL) != 0) { qDebug("PulseAudio Context Connect Failed with Error: %s", pa_strerror(pa_context_errno(pa_ctx))); return false; } int pa_ready = 0; pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); while (pa_ready == 0) pa_mainloop_iterate(pa_ml, 1, NULL); if (pa_ready == 2) return false; ss.rate = _sampleRate; ss.channels = 2; ss.format = PA_SAMPLE_FLOAT32LE; pa_stream* playstream = pa_stream_new(pa_ctx, "Playback", &ss, NULL); if (!playstream) { qDebug("pa_stream_new failed: %s", pa_strerror(pa_context_errno(pa_ctx))); return false; } pa_stream_set_write_callback(playstream, paCallback, this); bufattr.fragsize = (uint32_t)-1; bufattr.maxlength = FRAMES * 2 * sizeof(float); bufattr.minreq = FRAMES * 1 * sizeof(float); // pa_usec_to_bytes(0, &ss); bufattr.prebuf = (uint32_t)-1; bufattr.tlength = bufattr.maxlength; int r = pa_stream_connect_playback(playstream, nullptr, &bufattr, PA_STREAM_NOFLAGS, nullptr, nullptr); if (r < 0) { qDebug("pa_stream_connect_playback failed"); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); pa_ml = 0; return false; } return true; }
static int create_mainloop(client_t *c) { if (!c->glib) { c->pa = pa_mainloop_new(); c->ml = mrp_mainloop_pulse_get(pa_mainloop_get_api(c->pa)); } else { c->gml = g_main_loop_new(NULL, FALSE); c->ml = mrp_mainloop_glib_get(c->gml); } if (c->ml != NULL) return TRUE; else return FALSE; }
int main(int argc, char *argv[]) { struct stat st; off_t size; ssize_t nread; // We'll need these state variables to keep track of our requests int state = 0; int pa_ready = 0; if (argc != 2) { fprintf(stderr, "Usage: %s file\n", argv[0]); exit(1); } // slurp the whole file into buffer if ((fdin = open(argv[1], O_RDONLY)) == -1) { perror("open"); exit(1); } // Create a mainloop API and connection to the default server mainloop = pa_mainloop_new(); mainloop_api = pa_mainloop_get_api(mainloop); context = pa_context_new(mainloop_api, "test"); // This function connects to the pulse server pa_context_connect(context, NULL, 0, NULL); printf("Connecting\n"); // This function defines a callback so the server will tell us it's state. // Our callback will wait for the state to be ready. The callback will // modify the variable to 1 so we know when we have a connection and it's // ready. // If there's an error, the callback will set pa_ready to 2 pa_context_set_state_callback(context, state_cb, &pa_ready); if (pa_mainloop_run(mainloop, &ret) < 0) { printf("pa_mainloop_run() failed."); exit(1); // goto quit } }
/** * Pulsaudio init */ static void pa_init () { int r; int i; if (!pa_sample_spec_valid (&sample_spec)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong Spec\n")); } /* set up main record loop */ if (!(m = pa_mainloop_new ())) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_new() failed.\n")); } mainloop_api = pa_mainloop_get_api (m); /* listen to signals */ r = pa_signal_init (mainloop_api); GNUNET_assert (r == 0); pa_signal_new (SIGINT, &exit_signal_callback, NULL); pa_signal_new (SIGTERM, &exit_signal_callback, NULL); /* connect to the main pulseaudio context */ if (!(context = pa_context_new (mainloop_api, "GNUNET VoIP"))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_new() failed.\n")); } pa_context_set_state_callback (context, &context_state_callback, NULL); if (pa_context_connect (context, NULL, 0, NULL) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_connect() failed: %s\n"), pa_strerror (pa_context_errno (context))); } if (pa_mainloop_run (m, &i) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_run() failed.\n")); } }
pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pa_threaded_mainloop *m; pa_init_i18n(); m = pa_xnew0(pa_threaded_mainloop, 1); if (!(m->real_mainloop = pa_mainloop_new())) { pa_xfree(m); return NULL; } m->mutex = pa_mutex_new(true, true); m->cond = pa_cond_new(); m->accept_cond = pa_cond_new(); pa_mainloop_set_poll_func(m->real_mainloop, poll_func, m->mutex); return m; }
int main(int argc, char *argv[]) { pa_mainloop* m = NULL; int i, ret = 0; for (i = 0; i < SAMPLE_HZ; i++) data[i] = (float) sin(((double) i/SAMPLE_HZ)*2*M_PI*SINE_HZ)/2; for (i = 0; i < NSTREAMS; i++) streams[i] = NULL; /* Set up a new main loop */ m = pa_mainloop_new(); assert(m); mainloop_api = pa_mainloop_get_api(m); context = pa_context_new(mainloop_api, argv[0]); assert(context); pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ if (pa_context_connect(context, NULL, 0, NULL) < 0) { fprintf(stderr, "pa_context_connect() failed.\n"); goto quit; } if (pa_mainloop_run(m, &ret) < 0) fprintf(stderr, "pa_mainloop_run() failed.\n"); quit: pa_context_unref(context); for (i = 0; i < NSTREAMS; i++) if (streams[i]) pa_stream_unref(streams[i]); pa_mainloop_free(m); return ret; }
APULSE_EXPORT pa_threaded_mainloop * pa_threaded_mainloop_new(void) { trace_info_f("F %s (void)\n", __func__); pthread_mutexattr_t mutex_attr; pa_threaded_mainloop *m = calloc(1, sizeof(*m)); m->m = pa_mainloop_new(); pthread_mutexattr_init(&mutex_attr); pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&m->lock, &mutex_attr); pthread_mutexattr_destroy(&mutex_attr); pthread_cond_init(&m->cond, NULL); pa_mainloop_set_poll_func(m->m, poll_func, &m->lock); return m; }
/* * 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 executeRequest( StateData* stateData ) { // Create mainloop pa_mainloop* mainLoop = pa_mainloop_new(); // Create mainloop API pa_mainloop_api* mainLoopApi = pa_mainloop_get_api( mainLoop ); // Create context pa_context* context = pa_context_new( mainLoopApi, "cinder-requests" ); // Set context state callback stateData->mainLoopApi = mainLoopApi; pa_context_set_state_callback( context, processContextState, static_cast<void*>( stateData ) ); // Connect context if( pa_context_connect( context, nullptr, PA_CONTEXT_NOFLAGS, nullptr ) >= 0 ) { // Run mainloop int result = 0; if( pa_mainloop_run( mainLoop, &result ) < 0 ) { // Handle error } } pa_context_unref( context ); pa_mainloop_free( mainLoop ); }
int pulse_init(struct pulseaudio_t *pulse) { enum pa_context_state state = PA_CONTEXT_CONNECTING; pulse->mainloop = pa_mainloop_new(); pulse->cxt = pa_context_new(pa_mainloop_get_api(pulse->mainloop), "pavol"); pulse->default_sink = NULL; pulse->muted = 0; pulse->volume = 0; pa_context_set_state_callback(pulse->cxt, pulse_connect_state_cb, &state); pa_context_connect(pulse->cxt, NULL, PA_CONTEXT_NOFLAGS, NULL); while (state != PA_CONTEXT_READY && state != PA_CONTEXT_FAILED) pa_mainloop_iterate(pulse->mainloop, 1, NULL); if (state != PA_CONTEXT_READY) { fprintf(stderr, "failed to connect to pulse daemon: %s\n", pa_strerror(pa_context_errno(pulse->cxt))); return 1; } return 0; }
/* The implementation of create_output_device_name_list() is based on the * example code in * http://www.ypass.net/blog/2009/10/ * pulseaudio-an-async-example-to-get-device-lists/ */ mbx_error_code mbx_create_output_device_name_list(char ***dev_names, size_t *n_devs) { pa_mainloop *pa_ml = pa_mainloop_new(); pa_mainloop_api *pa_mlapi = pa_mainloop_get_api(pa_ml); pa_context *pa_ctx = pa_context_new(pa_mlapi, "music box (listing output " "devices)"); pa_operation *pa_op; pa_context_state_t pa_context_state = PA_CONTEXT_UNCONNECTED; int do_iterate = 1; int error = 0; pa_context_connect(pa_ctx, NULL, 0, NULL); /* The state callback will update the state when we are connected to the * PulseAudio server, or if an error occurs. */ pa_context_set_state_callback(pa_ctx, pa_context_state_cb, &pa_context_state); while ( do_iterate ) { switch ( pa_context_state ) { case PA_CONTEXT_UNCONNECTED: case PA_CONTEXT_CONNECTING: case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: pa_mainloop_iterate(pa_ml, 1, NULL); // we must wait. break; case PA_CONTEXT_READY: do_iterate = 0; break; case PA_CONTEXT_FAILED: mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "Connection to PulseAudio server failed: " "%s", pa_strerror(pa_context_errno(pa_ctx))); error = 1; break; case PA_CONTEXT_TERMINATED: mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "Connection to PulseAudio server " "terminated unexpectedly."); error = 1; break; default: mbx_log_error(MBX_LOG_AUDIO_OUTPUT, "The PulseAudio context has an unexpected " "state: %d", pa_context_state); error = 1; break; } if ( error ) { do_iterate = 0; } } if ( ! error ) { struct list_of_strings result = { NULL, 0, 0 }; pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, &result); while ( pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING ) { pa_mainloop_iterate(pa_ml, 1, NULL); // wait. } pa_operation_unref(pa_op); *dev_names = result.strings; *n_devs = result.n_strings; } pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return error ? MBX_PULSEAUDIO_ERROR : MBX_SUCCESS; }
int pa_get_devicelist(pa_devicelist_t *input, pa_devicelist_t *output) { // Define our pulse audio loop and connection variables pa_mainloop *pa_ml; pa_mainloop_api *pa_mlapi; pa_operation *pa_op; pa_context *pa_ctx; // We'll need these state variables to keep track of our requests int state = 0; int pa_ready = 0; // Initialize our device lists memset(input, 0, sizeof(pa_devicelist_t) * 16); memset(output, 0, sizeof(pa_devicelist_t) * 16); // Create a mainloop API and connection to the default server pa_ml = pa_mainloop_new(); pa_mlapi = pa_mainloop_get_api(pa_ml); pa_ctx = pa_context_new(pa_mlapi, "test"); // This function connects to the pulse server pa_context_connect(pa_ctx, NULL, 0, NULL); // This function defines a callback so the server will tell us it's state. // Our callback will wait for the state to be ready. The callback will // modify the variable to 1 so we know when we have a connection and it's // ready. // If there's an error, the callback will set pa_ready to 2 pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); // Now we'll enter into an infinite loop until we get the data we receive // or if there's an error for (;;) { // We can't do anything until PA is ready, so just iterate the mainloop // and continue if (pa_ready == 0) { pa_mainloop_iterate(pa_ml, 1, NULL); continue; } // We couldn't get a connection to the server, so exit out if (pa_ready == 2) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return -1; } // At this point, we're connected to the server and ready to make // requests switch (state) { // State 0: we haven't done anything yet case 0: // This sends an operation to the server. pa_sinklist_info is // our callback function and a pointer to our devicelist will // be passed to the callback The operation ID is stored in the // pa_op variable pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, output ); // Update state for next iteration through the loop state++; break; case 1: // Now we wait for our operation to complete. When it's // complete our pa_output_devicelist is filled out, and we move // along to the next state if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { pa_operation_unref(pa_op); // Now we perform another operation to get the source // (input device) list just like before. This time we pass // a pointer to our input structure pa_op = pa_context_get_source_info_list(pa_ctx, pa_sourcelist_cb, input ); // Update the state so we know what to do next state++; } break; case 2: if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { // Now we're done, clean up and disconnect and return pa_operation_unref(pa_op); pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return 0; } break; default: // We should never see this state fprintf(stderr, "in state %d\n", state); return -1; } // Iterate the main loop and go again. The second argument is whether // or not the iteration should block until something is ready to be // done. Set it to zero for non-blocking. pa_mainloop_iterate(pa_ml, 1, NULL); } }
int set_active_port(pa_devicelist_t device, pa_portlist_t port) { pa_mainloop *pa_ml; pa_mainloop_api *pa_mlapi; pa_operation *pa_op; pa_context *pa_ctx; int pa_ready = 0; int state = 0; pa_ml = pa_mainloop_new(); pa_mlapi = pa_mainloop_get_api(pa_ml); pa_ctx = pa_context_new(pa_mlapi, "test"); pa_context_connect(pa_ctx, NULL, 0, NULL); pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready); pa_device_port_t dev_port_set; dev_port_set.device = device; dev_port_set.port = port; pa_clientlist_t clientlist[30]; int i = 0; for (;;) { // We can't do anything until PA is ready, so just iterate the mainloop // and continue if (pa_ready == 0) { pa_mainloop_iterate(pa_ml, 1, NULL); continue; } // We couldn't get a connection to the server, so exit out if (pa_ready == 2) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return -1; } switch(state) { case 0: // Set source or sink switch(device.type) { case JOAPA_SOURCE: pa_op = pa_context_set_source_port_by_index( pa_ctx, device.index, port.name, set_active_port_cb, &dev_port_set); break; case JOAPA_SINK: pa_op = pa_context_set_sink_port_by_index( pa_ctx, device.index, port.name, set_active_port_cb, &dev_port_set); break; } state++; break; case 1: // get clients using a source or sink if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { pa_operation_unref(pa_op); switch(device.type) { case JOAPA_SOURCE: pa_op = pa_context_get_source_output_info_list(pa_ctx, pa_source_info_cb, &clientlist); break; case JOAPA_SINK: pa_op = pa_context_get_sink_input_info_list(pa_ctx, pa_sink_info_cb, &clientlist); break; } state++; } break; case 2: // move the clients to the new source or sink if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) { pa_operation_unref(pa_op); if(!clientlist[i].initialized) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); pa_mainloop_free(pa_ml); return 0; } //printf("CLIENT: %d\n", clientlist[i].index); switch(device.type) { case JOAPA_SOURCE: pa_op = pa_context_move_source_output_by_index( pa_ctx, clientlist[i].index, device.index, set_active_port_cb, NULL); break; case JOAPA_SINK: pa_op = pa_context_move_sink_input_by_index( pa_ctx, clientlist[i].index, device.index, set_active_port_cb, NULL); break; } i++; } break; default: fprintf(stderr, "in state %d\n", state); return -1; } pa_mainloop_iterate(pa_ml, 1, NULL); } }
struct pulse_conn_t *pulse_conn_open(const char *name, amp_audio_f func, void *arg, const struct pulse_conf_t *conf) { int err; unsigned int i; pthread_attr_t attr; struct sched_param param; struct pulse_conn_t *conn; conn = malloc(sizeof(struct pulse_conn_t)); conn->quit = 0; conn->width = (conf->in > conf->out) ? conf->in : conf->out; conn->lat = conf->rate * (conf->lat / 1000.0f); conn->conf = *conf; conn->func = func; conn->arg = arg; conn->rd = 0; conn->wr = conn->lat; conn->startup = 2; conn->reset[0] = conn->reset[1] = 1; conn->nrd = conn->nwr = conf->rate; //printf("width: %u\n", conn->width); conn->buf = malloc(conn->width * sizeof(void *)); for(i = 0; i < conn->width; i++) memset(conn->buf[i] = malloc(2 * conn->lat * sizeof(float)), 0x00, 2 * conn->lat * sizeof(float)); if(pipe(conn->pipe) < 0) fprintf(stderr, "Cannot create pipe."), exit(1); conn->loop = pa_mainloop_new(); conn->api = pa_mainloop_get_api(conn->loop); pa_mainloop_set_poll_func(conn->loop, conn_poll, conn); conn->context = pa_context_new(conn->api, name); pa_context_set_state_callback(conn->context, conn_state, conn); pa_context_connect(conn->context, NULL, 0, NULL); err = pthread_attr_init(&attr); if(err != 0) fprintf(stderr, "Failed to initialize thread attributes. %s.", strerror(err)), exit(1); err = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); if(err != 0) fprintf(stderr, "Failed to set schedular inheritance. %s.", strerror(err)), exit(1); err = pthread_attr_setschedpolicy(&attr, SCHED_FIFO); if(err != 0) fprintf(stderr, "Failed to set schedular policy. %s.", strerror(err)), exit(1); param.sched_priority = 99; err = pthread_attr_setschedparam(&attr, ¶m); if(err != 0) fprintf(stderr, "Failed to set schedular parameter. %s.", strerror(err)), exit(1); err = pthread_create(&conn->thread, &attr, conn_thread, conn); if(err != 0) { err = pthread_create(&conn->thread, NULL, conn_thread, conn); if(err != 0) fprintf(stderr, "Failed to start thread. %s.", strerror(err)), exit(1); } pthread_attr_destroy(&attr); if(err != 0) fprintf(stderr, "Failed to destroy thread attributes. %s.", strerror(err)), exit(1); return conn; }
int main(int argc, char *argv[]) { pa_mainloop* m = NULL; int ret = 1, c; char *bn, *server = NULL; pa_time_event *time_event = NULL; const char *filename = NULL; static const struct option long_options[] = { {"record", 0, NULL, 'r'}, {"playback", 0, NULL, 'p'}, {"device", 1, NULL, 'd'}, {"server", 1, NULL, 's'}, {"client-name", 1, NULL, 'n'}, {"stream-name", 1, NULL, ARG_STREAM_NAME}, {"version", 0, NULL, ARG_VERSION}, {"help", 0, NULL, 'h'}, {"verbose", 0, NULL, 'v'}, {"volume", 1, NULL, ARG_VOLUME}, {"rate", 1, NULL, ARG_SAMPLERATE}, {"format", 1, NULL, ARG_SAMPLEFORMAT}, {"channels", 1, NULL, ARG_CHANNELS}, {"channel-map", 1, NULL, ARG_CHANNELMAP}, {"fix-format", 0, NULL, ARG_FIX_FORMAT}, {"fix-rate", 0, NULL, ARG_FIX_RATE}, {"fix-channels", 0, NULL, ARG_FIX_CHANNELS}, {"no-remap", 0, NULL, ARG_NO_REMAP}, {"no-remix", 0, NULL, ARG_NO_REMIX}, {"latency", 1, NULL, ARG_LATENCY}, {"process-time", 1, NULL, ARG_PROCESS_TIME}, {"property", 1, NULL, ARG_PROPERTY}, {"raw", 0, NULL, ARG_RAW}, {"file-format", 2, NULL, ARG_FILE_FORMAT}, {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS}, {"latency-msec", 1, NULL, ARG_LATENCY_MSEC}, {"process-time-msec", 1, NULL, ARG_PROCESS_TIME_MSEC}, {NULL, 0, NULL, 0} }; setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); bn = pa_path_get_filename(argv[0]); if (strstr(bn, "play")) { mode = PLAYBACK; raw = FALSE; } else if (strstr(bn, "record")) { mode = RECORD; raw = FALSE; } else if (strstr(bn, "cat")) { mode = PLAYBACK; raw = TRUE; } if (strstr(bn, "rec") || strstr(bn, "mon")) { mode = RECORD; raw = TRUE; } proplist = pa_proplist_new(); while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) { switch (c) { case 'h' : help(bn); ret = 0; goto quit; case ARG_VERSION: printf(_("pacat %s\n" "Compiled with libpulse %s\n" "Linked with libpulse %s\n"), PACKAGE_VERSION, pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; case 'r': mode = RECORD; break; case 'p': mode = PLAYBACK; break; case 'd': pa_xfree(device); device = pa_xstrdup(optarg); break; case 's': pa_xfree(server); server = pa_xstrdup(optarg); break; case 'n': { char *t; if (!(t = pa_locale_to_utf8(optarg)) || pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) { pa_log(_("Invalid client name '%s'"), t ? t : optarg); pa_xfree(t); goto quit; } pa_xfree(t); break; } case ARG_STREAM_NAME: { char *t; if (!(t = pa_locale_to_utf8(optarg)) || pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) { pa_log(_("Invalid stream name '%s'"), t ? t : optarg); pa_xfree(t); goto quit; } pa_xfree(t); break; } case 'v': verbose = 1; break; case ARG_VOLUME: { int v = atoi(optarg); volume = v < 0 ? 0U : (pa_volume_t) v; volume_is_set = TRUE; break; } case ARG_CHANNELS: sample_spec.channels = (uint8_t) atoi(optarg); sample_spec_set = TRUE; break; case ARG_SAMPLEFORMAT: sample_spec.format = pa_parse_sample_format(optarg); sample_spec_set = TRUE; break; case ARG_SAMPLERATE: sample_spec.rate = (uint32_t) atoi(optarg); sample_spec_set = TRUE; break; case ARG_CHANNELMAP: if (!pa_channel_map_parse(&channel_map, optarg)) { pa_log(_("Invalid channel map '%s'"), optarg); goto quit; } channel_map_set = TRUE; break; case ARG_FIX_CHANNELS: flags |= PA_STREAM_FIX_CHANNELS; break; case ARG_FIX_RATE: flags |= PA_STREAM_FIX_RATE; break; case ARG_FIX_FORMAT: flags |= PA_STREAM_FIX_FORMAT; break; case ARG_NO_REMIX: flags |= PA_STREAM_NO_REMIX_CHANNELS; break; case ARG_NO_REMAP: flags |= PA_STREAM_NO_REMAP_CHANNELS; break; case ARG_LATENCY: if (((latency = (size_t) atoi(optarg))) <= 0) { pa_log(_("Invalid latency specification '%s'"), optarg); goto quit; } break; case ARG_PROCESS_TIME: if (((process_time = (size_t) atoi(optarg))) <= 0) { pa_log(_("Invalid process time specification '%s'"), optarg); goto quit; } break; case ARG_LATENCY_MSEC: if (((latency_msec = (int32_t) atoi(optarg))) <= 0) { pa_log(_("Invalid latency specification '%s'"), optarg); goto quit; } break; case ARG_PROCESS_TIME_MSEC: if (((process_time_msec = (int32_t) atoi(optarg))) <= 0) { pa_log(_("Invalid process time specification '%s'"), optarg); goto quit; } break; case ARG_PROPERTY: { char *t; if (!(t = pa_locale_to_utf8(optarg)) || pa_proplist_setp(proplist, t) < 0) { pa_xfree(t); pa_log(_("Invalid property '%s'"), optarg); goto quit; } pa_xfree(t); break; } case ARG_RAW: raw = TRUE; break; case ARG_FILE_FORMAT: raw = FALSE; if (optarg) { if ((file_format = pa_sndfile_format_from_string(optarg)) < 0) { pa_log(_("Unknown file format %s."), optarg); goto quit; } } raw = FALSE; break; case ARG_LIST_FILE_FORMATS: pa_sndfile_dump_formats(); ret = 0; goto quit; default: goto quit; } } if (!pa_sample_spec_valid(&sample_spec)) { pa_log(_("Invalid sample specification")); goto quit; } if (optind+1 == argc) { int fd; filename = argv[optind]; if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { pa_log(_("open(): %s"), strerror(errno)); goto quit; } if (dup2(fd, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO) < 0) { pa_log(_("dup2(): %s"), strerror(errno)); goto quit; } pa_close(fd); } else if (optind+1 <= argc) { pa_log(_("Too many arguments.")); goto quit; } if (!raw) { SF_INFO sfi; pa_zero(sfi); if (mode == RECORD) { /* This might patch up the sample spec */ if (pa_sndfile_write_sample_spec(&sfi, &sample_spec) < 0) { pa_log(_("Failed to generate sample specification for file.")); goto quit; } /* Transparently upgrade classic .wav to wavex for multichannel audio */ if (file_format <= 0) { if ((sample_spec.channels == 2 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_LEFT && channel_map.map[1] == PA_CHANNEL_POSITION_RIGHT))) || (sample_spec.channels == 1 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_MONO)))) file_format = SF_FORMAT_WAV; else file_format = SF_FORMAT_WAVEX; } sfi.format |= file_format; } if (!(sndfile = sf_open_fd(mode == RECORD ? STDOUT_FILENO : STDIN_FILENO, mode == RECORD ? SFM_WRITE : SFM_READ, &sfi, 0))) { pa_log(_("Failed to open audio file.")); goto quit; } if (mode == PLAYBACK) { if (sample_spec_set) pa_log(_("Warning: specified sample specification will be overwritten with specification from file.")); if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) { pa_log(_("Failed to determine sample specification from file.")); goto quit; } sample_spec_set = TRUE; if (!channel_map_set) { /* Allow the user to overwrite the channel map on the command line */ if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) { if (sample_spec.channels > 2) pa_log(_("Warning: Failed to determine channel map from file.")); } else channel_map_set = TRUE; } } } if (!channel_map_set) pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); if (!pa_channel_map_compatible(&channel_map, &sample_spec)) { pa_log(_("Channel map doesn't match sample specification")); goto quit; } if (!raw) { pa_proplist *sfp; if (mode == PLAYBACK) readf_function = pa_sndfile_readf_function(&sample_spec); else { if (pa_sndfile_write_channel_map(sndfile, &channel_map) < 0) pa_log(_("Warning: failed to write channel map to file.")); writef_function = pa_sndfile_writef_function(&sample_spec); } /* Fill in libsndfile prop list data */ sfp = pa_proplist_new(); pa_sndfile_init_proplist(sndfile, sfp); pa_proplist_update(proplist, PA_UPDATE_MERGE, sfp); pa_proplist_free(sfp); } if (verbose) { char tss[PA_SAMPLE_SPEC_SNPRINT_MAX], tcm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'."), mode == RECORD ? _("recording") : _("playback"), pa_sample_spec_snprint(tss, sizeof(tss), &sample_spec), pa_channel_map_snprint(tcm, sizeof(tcm), &channel_map)); } /* Fill in client name if none was set */ if (!pa_proplist_contains(proplist, PA_PROP_APPLICATION_NAME)) { char *t; if ((t = pa_locale_to_utf8(bn))) { pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t); pa_xfree(t); } } /* Fill in media name if none was set */ if (!pa_proplist_contains(proplist, PA_PROP_MEDIA_NAME)) { const char *t; if ((t = filename) || (t = pa_proplist_gets(proplist, PA_PROP_APPLICATION_NAME))) pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t); } /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { pa_log(_("pa_mainloop_new() failed.")); goto quit; } mainloop_api = pa_mainloop_get_api(m); pa_assert_se(pa_signal_init(mainloop_api) == 0); pa_signal_new(SIGINT, exit_signal_callback, NULL); pa_signal_new(SIGTERM, exit_signal_callback, NULL); #ifdef SIGUSR1 pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); #endif pa_disable_sigpipe(); if (raw) { if (!(stdio_event = mainloop_api->io_new(mainloop_api, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { pa_log(_("io_new() failed.")); goto quit; } } /* Create a new connection context */ if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) { pa_log(_("pa_context_new() failed.")); goto quit; } pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ if (pa_context_connect(context, server, 0, NULL) < 0) { pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); goto quit; } if (verbose) { if (!(time_event = pa_context_rttime_new(context, pa_rtclock_now() + TIME_EVENT_USEC, time_event_callback, NULL))) { pa_log(_("pa_context_rttime_new() failed.")); goto quit; } } /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { pa_log(_("pa_mainloop_run() failed.")); goto quit; } quit: if (stream) pa_stream_unref(stream); if (context) pa_context_unref(context); if (stdio_event) { pa_assert(mainloop_api); mainloop_api->io_free(stdio_event); } if (time_event) { pa_assert(mainloop_api); mainloop_api->time_free(time_event); } if (m) { pa_signal_done(); pa_mainloop_free(m); } pa_xfree(buffer); pa_xfree(server); pa_xfree(device); if (sndfile) sf_close(sndfile); if (proplist) pa_proplist_free(proplist); return ret; }
int PulseAudioDriver::setup(bool capture, bool playback, const QString& ) { PENTER; sample_spec.rate = frame_rate; sample_spec.channels = 2; sample_spec.format = PA_SAMPLE_FLOAT32NE; assert(pa_sample_spec_valid(&sample_spec)); if (channel_map_set && channel_map.channels != sample_spec.channels) { fprintf(stderr, "Channel map doesn't match file.\n"); return -1; } /* Set up a new main loop */ if (!(mainloop = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); return -1; } mainloop_api = pa_mainloop_get_api(mainloop); int r = pa_signal_init(mainloop_api); assert(r == 0); /* Create a new connection context */ if (!(context = pa_context_new(mainloop_api, "Traverso"))) { fprintf(stderr, "pa_context_new() failed.\n"); return -1; } pa_context_set_state_callback(context, context_state_callback, this); /* Connect the context */ pa_context_connect(context, "", (pa_context_flags_t)0, NULL); int ret; /* Run the main loop */ // if (pa_mainloop_run(mainloop, &ret) < 0) { // fprintf(stderr, "pa_mainloop_run() failed.\n"); // return -1; // } AudioChannel* audiochannel; int port_flags; char buf[32]; // TODO use the found maxchannel count for the playback stream, instead of assuming 2 !! for (int chn = 0; chn < 2; chn++) { snprintf (buf, sizeof(buf) - 1, "playback_%d", chn+1); audiochannel = device->register_playback_channel(buf, "32 bit float audio", port_flags, frames_per_cycle, chn); audiochannel->set_latency( frames_per_cycle + capture_frame_latency ); playbackChannels.append(audiochannel); } // TODO use the found maxchannel count for the capture stream, instead of assuming 0 !! for (int chn = 0; chn < 2; chn++) { snprintf (buf, sizeof(buf) - 1, "capture_%d", chn+1); audiochannel = device->register_capture_channel(buf, "32 bit float audio", port_flags, frames_per_cycle, chn); audiochannel->set_latency( frames_per_cycle + capture_frame_latency ); captureChannels.append(audiochannel); } return 1; }