void on_event(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { if((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { /* sink input changed */ if((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE) { if(idx != PA_INVALID_INDEX) pa_context_get_sink_input_info(c, idx, on_sink_input_update, NULL); } /* sink input removed */ if((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { if(idx != PA_INVALID_INDEX) { sink_input_remove(idx); view_update(); } } /* sink input added */ if((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { if(idx != PA_INVALID_INDEX) pa_context_get_sink_input_info(c, idx, on_sink_input_update, NULL); } } if((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) { /* sink changed */ if((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE) { if(idx != PA_INVALID_INDEX) pa_context_get_sink_info_by_index(c, idx, on_sink_update, NULL); } } }
/** * @brief Callback function called when the state of the daemon changes * @param c Context in which the state of the daemon changes * @param t Subscription event type * @param idx Index of the sink * @param this_gen pulse_driver_t pointer for the PulseAudio output * instance. */ static void __xine_pa_context_subscribe_callback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *this_gen) { pulse_driver_t * this = (pulse_driver_t*) this_gen; int index; if (this->stream == NULL) return; index = pa_stream_get_index(this->stream); if (index != idx) return; if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) return; pa_operation *operation = pa_context_get_sink_input_info( this->context, index, __xine_pa_sink_info_callback, this); if (operation == NULL) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to get sink info: %s\n", pa_strerror(pa_context_errno (this->context))); return; } pa_operation_unref(operation); }
int xmms_pulse_backend_volume_get (xmms_pulse *p, unsigned int *vol) { pa_operation *o; int idx; if (p == NULL) { return FALSE; } pa_threaded_mainloop_lock (p->mainloop); *vol = -1; if (p->stream != NULL) { idx = pa_stream_get_index (p->stream); o = pa_context_get_sink_input_info (p->context, idx, volume_get_cb, vol); if (o) { while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (p->mainloop); } pa_operation_unref (o); } } pa_threaded_mainloop_unlock (p->mainloop); return *vol != -1; }
void SinkInput::update() { pa_operation *o; o = pa_context_get_sink_input_info(d->context->cObject(), d->index, SinkInput::sink_input_cb, this); pa_operation_unref(o); }
void AudioSinksManager::update_sink_input_map(uint32_t sink_idx, pa_subscription_event_type_t event_type) { pa_operation* op = pa_context_get_sink_input_info(context, sink_idx, sink_input_info_callback, new SinkInfoRequest(this, event_type)); if (op) { pa_operation_unref(op); } else { logger->error("(AudioSinksManager) Failed to start getting sink {} info: {}", sink_idx, get_pa_error()); } }
static int control(int cmd, void *arg) { switch (cmd) { case AOCONTROL_GET_VOLUME: { ao_control_vol_t *vol = arg; uint32_t devidx = pa_stream_get_index(stream); pa_threaded_mainloop_lock(mainloop); if (!waitop(pa_context_get_sink_input_info(context, devidx, info_func, NULL))) { GENERIC_ERR_MSG(context, "pa_stream_get_sink_input_info() failed"); return CONTROL_ERROR; } if (volume.channels != 2) vol->left = vol->right = pa_cvolume_avg(&volume)*100/PA_VOLUME_NORM; else { vol->left = volume.values[0]*100/PA_VOLUME_NORM; vol->right = volume.values[1]*100/PA_VOLUME_NORM; } return CONTROL_OK; } case AOCONTROL_SET_VOLUME: { const ao_control_vol_t *vol = arg; pa_operation *o; if (volume.channels != 2) pa_cvolume_set(&volume, volume.channels, (pa_volume_t)vol->left*PA_VOLUME_NORM/100); else { volume.values[0] = (pa_volume_t)vol->left*PA_VOLUME_NORM/100; volume.values[1] = (pa_volume_t)vol->right*PA_VOLUME_NORM/100; } pa_threaded_mainloop_lock(mainloop); o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL); if (!o) { pa_threaded_mainloop_unlock(mainloop); GENERIC_ERR_MSG(context, "pa_context_set_sink_input_volume() failed"); return CONTROL_ERROR; } /* We don't wait for completion here */ pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); return CONTROL_OK; } default: return CONTROL_UNKNOWN; } }
static void SinkInputInfoChangedCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { CAESinkPULSE* p = (CAESinkPULSE*) userdata; if (!p || !p->IsInitialized()) return; if (idx != pa_stream_get_index(p->GetInternalStream())) return; pa_operation* op = pa_context_get_sink_input_info(c, idx, SinkInputInfoCallback, p); if (op == NULL) CLog::Log(LOGERROR, "PulseAudio: Failed to sync volume"); else pa_operation_unref(op); }
static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { pa_operation *o; assert(c); if (!stream || index != pa_stream_get_index(stream) || (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW))) return; if (!(o = pa_context_get_sink_input_info(c, index, info_cb, NULL))) { AUDDBG("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(c))); return; } pa_operation_unref(o); }
void PulseOutput::context_subscribe_callback(pa_context * pulse_context, pa_subscription_event_type_t type, uint32_t index, void *userdata){ PulseOutput * out = static_cast<PulseOutput*>(userdata); if (out->stream==nullptr) return; if (pa_stream_get_index(out->stream)!=index) return; if ((type&PA_SUBSCRIPTION_EVENT_FACILITY_MASK)!=PA_SUBSCRIPTION_EVENT_SINK_INPUT) return; if ((type&PA_SUBSCRIPTION_EVENT_TYPE_MASK)==PA_SUBSCRIPTION_EVENT_CHANGE || (type&PA_SUBSCRIPTION_EVENT_TYPE_MASK)==PA_SUBSCRIPTION_EVENT_NEW) { pa_operation *operation = pa_context_get_sink_input_info(pulse_context,index,sink_info_callback,userdata); if (operation) pa_operation_unref(operation); } }
/** Issue special libao controls on the device */ static int control(int cmd, void *arg) { if (!context || !stream) return CONTROL_ERROR; switch (cmd) { case AOCONTROL_SET_DEVICE: /* Change the playback device */ sink = (char*)arg; return CONTROL_OK; case AOCONTROL_GET_DEVICE: /* Return the playback device */ *(char**)arg = sink; return CONTROL_OK; case AOCONTROL_GET_VOLUME: { /* Return the current volume of the playback stream */ ao_control_vol_t *vol = (ao_control_vol_t*) arg; volume = PA_VOLUME_NORM; wait_for_operation(pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_func, NULL)); vol->left = vol->right = (int) (pa_volume_to_user(volume)*100); return CONTROL_OK; } case AOCONTROL_SET_VOLUME: { /* Set the playback volume of the stream */ const ao_control_vol_t *vol = (ao_control_vol_t*) arg; int v = vol->left; if (vol->right > v) v = vol->left; wait_for_operation(pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), pa_volume_from_user((double)v/100), NULL, NULL)); return CONTROL_OK; } default: /* Unknown CONTROL command */ return CONTROL_UNKNOWN; } }
void backend_volume_set(context_t *c, backend_entry_type type, uint32_t idx, int i, int v) { volume_callback_t *volume = (volume_callback_t*)malloc(sizeof(volume_callback_t)); volume->index = i; volume->value = v; switch(type) { case SINK: pa_context_get_sink_info_by_index(c->context, idx, _cb_s_sink, volume); break; case SINK_INPUT: pa_context_get_sink_input_info(c->context, idx, _cb_s_sink_input, volume); break; case SOURCE: pa_context_get_source_info_by_index(c->context, idx, _cb_s_source, volume); break; case SOURCE_OUTPUT: pa_context_get_source_output_info(c->context, idx, _cb_s_source_output, volume); break; default: break; } }
static void sink_input_event(pa_context *ctx, pa_subscription_event_type_t type, uint32_t idx, audio_output_t *aout) { pa_operation *op; /* Gee... PA will not provide the infos directly in the event. */ switch (type) { case PA_SUBSCRIPTION_EVENT_REMOVE: msg_Err(aout, "sink input killed!"); break; default: op = pa_context_get_sink_input_info(ctx, idx, sink_input_info_cb, aout); if (likely(op != NULL)) pa_operation_unref(op); break; } }
static void subscription_event_callback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { pa_audio_mode_t *pam = (pa_audio_mode_t *)userdata; pa_operation *o; if(pam->stream == NULL || pa_stream_get_state(pam->stream) != PA_STREAM_READY) return; if((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) != PA_SUBSCRIPTION_EVENT_SINK_INPUT) return; if(pa_stream_get_index(pam->stream) != idx) return; o = pa_context_get_sink_input_info(pam->context, idx, update_sink_input_info, pam); if(o != NULL) pa_operation_unref(o); }
void Context::subscribeCallback(pa_context *context, pa_subscription_event_type_t type, uint32_t index) { Q_ASSERT(context == m_context); switch (type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sinks.removeEntry(index); } else { if (!PAOperation(pa_context_get_sink_info_by_index(context, index, sink_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_sink_info_by_index() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SOURCE: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sources.removeEntry(index); } else { if (!PAOperation(pa_context_get_source_info_by_index(context, index, source_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_source_info_by_index() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sinkInputs.removeEntry(index); } else { if (!PAOperation(pa_context_get_sink_input_info(context, index, sink_input_callback, this))) { qCWarning(PLASMAPA) << "pa_context_get_sink_input_info() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sourceOutputs.removeEntry(index); } else { if (!PAOperation(pa_context_get_source_output_info(context, index, source_output_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_sink_input_info() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_CLIENT: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_clients.removeEntry(index); } else { if (!PAOperation(pa_context_get_client_info(context, index, client_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_client_info() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_CARD: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_cards.removeEntry(index); } else { if (!PAOperation(pa_context_get_card_info_by_index(context, index, card_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_card_info_by_index() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SERVER: if (!PAOperation(pa_context_get_server_info(context, server_cb, this))) { qCWarning(PLASMAPA) << "pa_context_get_server_info() failed"; return; } break; } }
static int control(struct ao *ao, enum aocontrol cmd, void *arg) { struct priv *priv = ao->priv; switch (cmd) { case AOCONTROL_GET_MUTE: case AOCONTROL_GET_VOLUME: { uint32_t devidx = pa_stream_get_index(priv->stream); pa_threaded_mainloop_lock(priv->mainloop); if (!waitop(priv, pa_context_get_sink_input_info(priv->context, devidx, info_func, ao))) { GENERIC_ERR_MSG(priv->context, "pa_stream_get_sink_input_info() failed"); return CONTROL_ERROR; } // Warning: some information in pi might be unaccessible, because // we naively copied the struct, without updating pointers etc. // Pointers might point to invalid data, accessors might fail. if (cmd == AOCONTROL_GET_VOLUME) { ao_control_vol_t *vol = arg; if (priv->pi.volume.channels != 2) vol->left = vol->right = pa_cvolume_avg(&priv->pi.volume) * 100 / PA_VOLUME_NORM; else { vol->left = priv->pi.volume.values[0] * 100 / PA_VOLUME_NORM; vol->right = priv->pi.volume.values[1] * 100 / PA_VOLUME_NORM; } } else if (cmd == AOCONTROL_GET_MUTE) { bool *mute = arg; *mute = priv->pi.mute; } return CONTROL_OK; } case AOCONTROL_SET_MUTE: case AOCONTROL_SET_VOLUME: { pa_operation *o; pa_threaded_mainloop_lock(priv->mainloop); uint32_t stream_index = pa_stream_get_index(priv->stream); if (cmd == AOCONTROL_SET_VOLUME) { const ao_control_vol_t *vol = arg; struct pa_cvolume volume; pa_cvolume_reset(&volume, ao->channels); if (volume.channels != 2) pa_cvolume_set(&volume, volume.channels, vol->left * PA_VOLUME_NORM / 100); else { volume.values[0] = vol->left * PA_VOLUME_NORM / 100; volume.values[1] = vol->right * PA_VOLUME_NORM / 100; } o = pa_context_set_sink_input_volume(priv->context, stream_index, &volume, NULL, NULL); if (!o) { pa_threaded_mainloop_unlock(priv->mainloop); GENERIC_ERR_MSG(priv->context, "pa_context_set_sink_input_volume() failed"); return CONTROL_ERROR; } } else if (cmd == AOCONTROL_SET_MUTE) { const bool *mute = arg; o = pa_context_set_sink_input_mute(priv->context, stream_index, *mute, NULL, NULL); if (!o) { pa_threaded_mainloop_unlock(priv->mainloop); GENERIC_ERR_MSG(priv->context, "pa_context_set_sink_input_mute() failed"); return CONTROL_ERROR; } } else abort(); /* We don't wait for completion here */ pa_operation_unref(o); pa_threaded_mainloop_unlock(priv->mainloop); return CONTROL_OK; } default: return CONTROL_UNKNOWN; } }
static int pulse_open(int fmt, int rate, int nch) { pa_sample_spec ss; pa_operation *o = NULL; int success; assert(!mainloop); assert(!context); assert(!stream); assert(!connected); switch(fmt) { case FMT_U8: ss.format = PA_SAMPLE_U8; break; case FMT_S16_LE: ss.format = PA_SAMPLE_S16LE; break; case FMT_S16_BE: ss.format = PA_SAMPLE_S16BE; break; #ifdef PA_SAMPLE_S24_32LE case FMT_S24_LE: ss.format = PA_SAMPLE_S24_32LE; break; case FMT_S24_BE: ss.format = PA_SAMPLE_S24_32BE; break; #endif #ifdef PA_SAMPLE_S32LE case FMT_S32_LE: ss.format = PA_SAMPLE_S32LE; break; case FMT_S32_BE: ss.format = PA_SAMPLE_S32BE; break; #endif case FMT_FLOAT: ss.format = PA_SAMPLE_FLOAT32NE; break; default: return FALSE; } ss.rate = rate; ss.channels = nch; if (!pa_sample_spec_valid(&ss)) return FALSE; if (!(mainloop = pa_threaded_mainloop_new())) { ERROR ("Failed to allocate main loop"); goto fail; } pa_threaded_mainloop_lock(mainloop); if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Audacious"))) { ERROR ("Failed to allocate context"); goto unlock_and_fail; } pa_context_set_state_callback(context, context_state_cb, NULL); pa_context_set_subscribe_callback(context, subscribe_cb, NULL); if (pa_context_connect(context, NULL, 0, NULL) < 0) { ERROR ("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } if (pa_threaded_mainloop_start(mainloop) < 0) { ERROR ("Failed to start main loop"); goto unlock_and_fail; } /* Wait until the context is ready */ pa_threaded_mainloop_wait(mainloop); if (pa_context_get_state(context) != PA_CONTEXT_READY) { ERROR ("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } if (!(stream = pa_stream_new(context, "Audacious", &ss, NULL))) { ERROR ("Failed to create stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_stream_set_state_callback(stream, stream_state_cb, NULL); pa_stream_set_write_callback(stream, stream_request_cb, NULL); pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL); /* Connect stream with sink and default volume */ /* Buffer struct */ int aud_buffer = aud_get_int(NULL, "output_buffer_size"); size_t buffer_size = pa_usec_to_bytes(aud_buffer, &ss) * 1000; pa_buffer_attr buffer = {(uint32_t) -1, buffer_size, (uint32_t) -1, (uint32_t) -1, buffer_size}; if (pa_stream_connect_playback(stream, NULL, &buffer, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { ERROR ("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } /* Wait until the stream is ready */ pa_threaded_mainloop_wait(mainloop); if (pa_stream_get_state(stream) != PA_STREAM_READY) { ERROR ("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } /* Now subscribe to events */ if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { ERROR ("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!success) { ERROR ("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_operation_unref(o); /* Now request the initial stream info */ if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) { ERROR ("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!volume_valid) { ERROR ("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_operation_unref(o); do_trigger = 0; written = 0; flush_time = 0; bytes_per_second = FMT_SIZEOF (fmt) * nch * rate; connected = 1; volume_time_event = NULL; pa_threaded_mainloop_unlock(mainloop); return TRUE; unlock_and_fail: if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); fail: pulse_close(); return FALSE; }
FXbool PulseOutput::configure(const AudioFormat & fmt){ const pa_sample_spec * config=nullptr; pa_operation *operation=nullptr; if (!open()) return false; if (stream && fmt==af) return true; if (stream) { pa_stream_disconnect(stream); pa_stream_unref(stream); stream=nullptr; } pa_sample_spec spec; pa_channel_map cmap; if (!to_pulse_format(fmt,spec.format)) goto failed; spec.rate = fmt.rate; spec.channels = fmt.channels; // setup channel map pa_channel_map_init(&cmap); cmap.channels = fmt.channels; for (FXint i=0;i<fmt.channels;i++) { switch(fmt.channeltype(i)) { case Channel::None : cmap.map[i] = PA_CHANNEL_POSITION_INVALID; break; case Channel::Mono : cmap.map[i] = PA_CHANNEL_POSITION_MONO; break; case Channel::FrontLeft : cmap.map[i] = PA_CHANNEL_POSITION_FRONT_LEFT; break; case Channel::FrontRight : cmap.map[i] = PA_CHANNEL_POSITION_FRONT_RIGHT; break; case Channel::FrontCenter : cmap.map[i] = PA_CHANNEL_POSITION_FRONT_CENTER; break; case Channel::BackLeft : cmap.map[i] = PA_CHANNEL_POSITION_REAR_LEFT; break; case Channel::BackRight : cmap.map[i] = PA_CHANNEL_POSITION_REAR_RIGHT; break; case Channel::BackCenter : cmap.map[i] = PA_CHANNEL_POSITION_REAR_CENTER; break; case Channel::SideLeft : cmap.map[i] = PA_CHANNEL_POSITION_SIDE_LEFT; break; case Channel::SideRight : cmap.map[i] = PA_CHANNEL_POSITION_SIDE_RIGHT; break; case Channel::LFE : cmap.map[i] = PA_CHANNEL_POSITION_LFE; break; default: goto failed; } } stream = pa_stream_new(pulse_context,"Goggles Music Manager",&spec,&cmap); if (stream == nullptr) goto failed; #ifdef DEBUG pa_stream_set_state_callback(stream,stream_state_callback,this); #endif //pa_stream_set_write_callback(stream,stream_write_callback,this); if (pa_stream_connect_playback(stream,nullptr,nullptr,PA_STREAM_NOFLAGS,nullptr,nullptr)<0) goto failed; /// Wait until stream is ready pa_stream_state_t state; while((state=pa_stream_get_state(stream))!=PA_STREAM_READY) { if (state==PA_STREAM_FAILED || state==PA_STREAM_TERMINATED){ goto failed; } context->wait_plugin_events(); } /// Get Actual Format config = pa_stream_get_sample_spec(stream); if (!to_gap_format(config->format,af)) goto failed; af.channels=config->channels; af.rate=config->rate; af.channelmap=fmt.channelmap; /// Get Current Volume operation = pa_context_get_sink_input_info(pulse_context,pa_stream_get_index(stream),sink_info_callback,this); if (operation) pa_operation_unref(operation); return true; failed: GM_DEBUG_PRINT("[pulse] Unsupported pulse configuration:\n"); fmt.debug(); return false; }
void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index) { switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) //w->removeSink(index); printf("INF: suppose to removeSink(index)\n"); else { pa_operation *o; if (!(o = pa_context_get_sink_info_by_index(c, index, sink_cb, NULL))) { //show_error("pa_context_get_sink_info_by_index() failed"); printf("func.c:<error> pa_context_get_sink_info_by_index() failed\n"); return; } pa_operation_unref(o); } break; case PA_SUBSCRIPTION_EVENT_SOURCE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) //w->removeSource(index); printf("func.c:INF: suppose to removeSource(index)\n"); else { pa_operation *o; if (!(o = pa_context_get_source_info_by_index(c, index, source_cb, NULL))) { //show_error("pa_context_get_source_info_by_index() failed"); printf("func.c:<error> pa_context_get_source_info_by_index() failed\n"); return; } pa_operation_unref(o); } break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) //w->removeSinkInput(index); printf("func.c:INF: suppose to removeSinkInput(index)\n"); else { pa_operation *o; if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, NULL))) { //show_error("pa_context_get_sink_input_info() failed"); printf("func.c:<error> pa_context_get_sink_input_info() failed"); return; } pa_operation_unref(o); } break; case PA_SUBSCRIPTION_EVENT_CLIENT: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) //w->removeClient(index); printf("func.c:INF: suppose to removeClient(index)\n"); else { pa_operation *o; if (!(o = pa_context_get_client_info(c, index, client_cb, NULL))) { //show_error("pa_context_get_client_info() failed"); printf("func.c:<error> pa_context_get_client_info() failed\n"); return; } pa_operation_unref(o); } break; case PA_SUBSCRIPTION_EVENT_SERVER: printf("func.c: pa_subscription_event_server triggered\n"); { pa_operation *o; if (!(o = pa_context_get_server_info(c, server_info_cb, NULL))) { //show_error("pa_context_get_server_info() failed"); printf("func.c:<error> pa_context_get_server_info() failed\n"); return; } pa_operation_unref(o); } break; } }