コード例 #1
0
ファイル: cubeb_pulse.c プロジェクト: brendandahl/positron
/*static*/ int
pulse_init(cubeb ** context, char const * context_name)
{
  void * libpulse = NULL;
  cubeb * ctx;

  *context = NULL;

#ifndef DISABLE_LIBPULSE_DLOPEN
  libpulse = dlopen("libpulse.so.0", RTLD_LAZY);
  if (!libpulse) {
    return CUBEB_ERROR;
  }

#define LOAD(x) {                               \
    cubeb_##x = dlsym(libpulse, #x);            \
    if (!cubeb_##x) {                           \
      dlclose(libpulse);                        \
      return CUBEB_ERROR;                       \
    }                                           \
  }

  LIBPULSE_API_VISIT(LOAD);
#undef LOAD
#endif

  ctx = calloc(1, sizeof(*ctx));
  assert(ctx);

  ctx->ops = &pulse_ops;
  ctx->libpulse = libpulse;

  ctx->mainloop = WRAP(pa_threaded_mainloop_new)();
  ctx->default_sink_info = NULL;

  WRAP(pa_threaded_mainloop_start)(ctx->mainloop);

  ctx->context_name = context_name ? strdup(context_name) : NULL;
  if (pulse_context_init(ctx) != 0) {
    pulse_destroy(ctx);
    return CUBEB_ERROR;
  }

  WRAP(pa_threaded_mainloop_lock)(ctx->mainloop);
  WRAP(pa_context_get_server_info)(ctx->context, server_info_callback, ctx);
  WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);

  *context = ctx;

  return CUBEB_OK;
}
コード例 #2
0
ファイル: cubeb_pulse.c プロジェクト: brendandahl/positron
static int
pulse_stream_init(cubeb * context,
                  cubeb_stream ** stream,
                  char const * stream_name,
                  cubeb_devid input_device,
                  cubeb_stream_params * input_stream_params,
                  cubeb_devid output_device,
                  cubeb_stream_params * output_stream_params,
                  unsigned int latency,
                  cubeb_data_callback data_callback,
                  cubeb_state_callback state_callback,
                  void * user_ptr)
{
  cubeb_stream * stm;
  pa_buffer_attr battr;
  int r;

  assert(context);

  // If the connection failed for some reason, try to reconnect
  if (context->error == 1 && pulse_context_init(context) != 0) {
    return CUBEB_ERROR;
  }

  *stream = NULL;

  stm = calloc(1, sizeof(*stm));
  assert(stm);

  stm->context = context;
  stm->data_callback = data_callback;
  stm->state_callback = state_callback;
  stm->user_ptr = user_ptr;
  stm->volume = PULSE_NO_GAIN;

  WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
  if (output_stream_params) {
    r = create_pa_stream(stm, &stm->output_stream, output_stream_params, stream_name);
    if (r != CUBEB_OK) {
      WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
      pulse_stream_destroy(stm);
      return r;
    }

    stm->output_sample_spec = *(WRAP(pa_stream_get_sample_spec)(stm->output_stream));

    WRAP(pa_stream_set_state_callback)(stm->output_stream, stream_state_callback, stm);
    WRAP(pa_stream_set_write_callback)(stm->output_stream, stream_write_callback, stm);

    battr = set_buffering_attribute(latency, &stm->output_sample_spec);
    WRAP(pa_stream_connect_playback)(stm->output_stream,
                                     output_device,
                                     &battr,
                                     PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
                                     PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY,
                                     NULL, NULL);
  }

  // Set up input stream
  if (input_stream_params) {
    r = create_pa_stream(stm, &stm->input_stream, input_stream_params, stream_name);
    if (r != CUBEB_OK) {
      WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
      pulse_stream_destroy(stm);
      return r;
    }

    stm->input_sample_spec = *(WRAP(pa_stream_get_sample_spec)(stm->input_stream));

    WRAP(pa_stream_set_state_callback)(stm->input_stream, stream_state_callback, stm);
    WRAP(pa_stream_set_read_callback)(stm->input_stream, stream_read_callback, stm);

    battr = set_buffering_attribute(latency, &stm->input_sample_spec);
    WRAP(pa_stream_connect_record)(stm->input_stream,
                                   input_device,
                                   &battr,
                                   PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
                                   PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY);
  }

  r = wait_until_stream_ready(stm);
  if (r == 0) {
    /* force a timing update now, otherwise timing info does not become valid
       until some point after initialization has completed. */
    r = stream_update_timing_info(stm);
  }

  WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);

  if (r != 0) {
    pulse_stream_destroy(stm);
    return CUBEB_ERROR;
  }

#ifdef LOGGING_ENABLED
  if (output_stream_params){
    const pa_buffer_attr * output_att;
    output_att = WRAP(pa_stream_get_buffer_attr)(stm->output_stream);
    LOG("Output buffer attributes maxlength %u, tlength %u, prebuf %u, minreq %u, fragsize %u\n",output_att->maxlength, output_att->tlength,
        output_att->prebuf, output_att->minreq, output_att->fragsize);
  }

  if (input_stream_params){
    const pa_buffer_attr * input_att;
    input_att = WRAP(pa_stream_get_buffer_attr)(stm->input_stream);
    LOG("Input buffer attributes maxlength %u, tlength %u, prebuf %u, minreq %u, fragsize %u\n",input_att->maxlength, input_att->tlength,
        input_att->prebuf, input_att->minreq, input_att->fragsize);
  }
#endif

  *stream = stm;

  return CUBEB_OK;
}
コード例 #3
0
ファイル: cubeb_pulse.c プロジェクト: chenhequn/gecko
static int
pulse_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
                  cubeb_stream_params stream_params, unsigned int latency,
                  cubeb_data_callback data_callback, cubeb_state_callback state_callback,
                  void * user_ptr)
{
  pa_sample_spec ss;
  cubeb_stream * stm;
  pa_operation * o;
  pa_buffer_attr battr;
  int r;

  assert(context);

  *stream = NULL;

  switch (stream_params.format) {
  case CUBEB_SAMPLE_S16LE:
    ss.format = PA_SAMPLE_S16LE;
    break;
  case CUBEB_SAMPLE_S16BE:
    ss.format = PA_SAMPLE_S16BE;
    break;
  case CUBEB_SAMPLE_FLOAT32LE:
    ss.format = PA_SAMPLE_FLOAT32LE;
    break;
  case CUBEB_SAMPLE_FLOAT32BE:
    ss.format = PA_SAMPLE_FLOAT32BE;
    break;
  default:
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  // If the connection failed for some reason, try to reconnect
  if (context->error == 1 && pulse_context_init(context) != 0) {
    return CUBEB_ERROR;
  }

  ss.rate = stream_params.rate;
  ss.channels = stream_params.channels;

  stm = calloc(1, sizeof(*stm));
  assert(stm);

  stm->context = context;

  stm->data_callback = data_callback;
  stm->state_callback = state_callback;
  stm->user_ptr = user_ptr;

  stm->sample_spec = ss;

  battr.maxlength = -1;
  battr.tlength = WRAP(pa_usec_to_bytes)(latency * PA_USEC_PER_MSEC, &stm->sample_spec);
  battr.prebuf = -1;
  battr.minreq = battr.tlength / 4;
  battr.fragsize = -1;

  WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
  stm->stream = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, NULL);
  if (!stm->stream) {
    pulse_stream_destroy(stm);
    return CUBEB_ERROR;
  }
  WRAP(pa_stream_set_state_callback)(stm->stream, stream_state_callback, stm);
  WRAP(pa_stream_set_write_callback)(stm->stream, stream_request_callback, stm);
  WRAP(pa_stream_connect_playback)(stm->stream, NULL, &battr,
                             PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
                             PA_STREAM_START_CORKED,
                             NULL, NULL);

  r = wait_until_stream_ready(stm);
  if (r == 0) {
    /* force a timing update now, otherwise timing info does not become valid
       until some point after initialization has completed. */
    o = WRAP(pa_stream_update_timing_info)(stm->stream, stream_success_callback, stm);
    if (o) {
      r = operation_wait(stm->context, stm->stream, o);
      WRAP(pa_operation_unref)(o);
    }
  }
  WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);

  if (r != 0) {
    pulse_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  *stream = stm;

  return CUBEB_OK;
}
コード例 #4
0
ファイル: cubeb_pulse.c プロジェクト: chenhequn/gecko
/*static*/ int
pulse_init(cubeb ** context, char const * context_name)
{
  void * libpulse = NULL;
  cubeb * ctx;

  *context = NULL;

#ifndef DISABLE_LIBPULSE_DLOPEN
  libpulse = dlopen("libpulse.so.0", RTLD_LAZY);
  if (!libpulse) {
    return CUBEB_ERROR;
  }

#define LOAD(x) do { \
    cubeb_##x = dlsym(libpulse, #x); \
    if (!cubeb_##x) { \
      dlclose(libpulse); \
      return CUBEB_ERROR; \
    } \
  } while(0)
  LOAD(pa_channel_map_can_balance);
  LOAD(pa_channel_map_init_auto);
  LOAD(pa_context_connect);
  LOAD(pa_context_disconnect);
  LOAD(pa_context_drain);
  LOAD(pa_context_get_server_info);
  LOAD(pa_context_get_sink_info_by_name);
  LOAD(pa_context_get_state);
  LOAD(pa_context_new);
  LOAD(pa_context_rttime_new);
  LOAD(pa_context_set_sink_input_volume);
  LOAD(pa_context_set_state_callback);
  LOAD(pa_context_unref);
  LOAD(pa_cvolume_set);
  LOAD(pa_cvolume_set_balance);
  LOAD(pa_frame_size);
  LOAD(pa_operation_get_state);
  LOAD(pa_operation_unref);
  LOAD(pa_rtclock_now);
  LOAD(pa_stream_begin_write);
  LOAD(pa_stream_cancel_write);
  LOAD(pa_stream_connect_playback);
  LOAD(pa_stream_cork);
  LOAD(pa_stream_disconnect);
  LOAD(pa_stream_get_channel_map);
  LOAD(pa_stream_get_index);
  LOAD(pa_stream_get_latency);
  LOAD(pa_stream_get_sample_spec);
  LOAD(pa_stream_get_state);
  LOAD(pa_stream_get_time);
  LOAD(pa_stream_new);
  LOAD(pa_stream_set_state_callback);
  LOAD(pa_stream_set_write_callback);
  LOAD(pa_stream_unref);
  LOAD(pa_stream_update_timing_info);
  LOAD(pa_stream_write);
  LOAD(pa_sw_volume_from_linear);
  LOAD(pa_threaded_mainloop_free);
  LOAD(pa_threaded_mainloop_get_api);
  LOAD(pa_threaded_mainloop_in_thread);
  LOAD(pa_threaded_mainloop_lock);
  LOAD(pa_threaded_mainloop_new);
  LOAD(pa_threaded_mainloop_signal);
  LOAD(pa_threaded_mainloop_start);
  LOAD(pa_threaded_mainloop_stop);
  LOAD(pa_threaded_mainloop_unlock);
  LOAD(pa_threaded_mainloop_wait);
  LOAD(pa_usec_to_bytes);
#undef LOAD
#endif

  ctx = calloc(1, sizeof(*ctx));
  assert(ctx);

  ctx->ops = &pulse_ops;
  ctx->libpulse = libpulse;

  ctx->mainloop = WRAP(pa_threaded_mainloop_new)();
  ctx->default_sink_info = NULL;

  WRAP(pa_threaded_mainloop_start)(ctx->mainloop);

  ctx->context_name = context_name ? strdup(context_name) : NULL;
  if (pulse_context_init(ctx) != 0) {
    pulse_destroy(ctx);
    return CUBEB_ERROR;
  }

  WRAP(pa_threaded_mainloop_lock)(ctx->mainloop);
  WRAP(pa_context_get_server_info)(ctx->context, server_info_callback, ctx);
  WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);

  *context = ctx;

  return CUBEB_OK;
}