Exemplo n.º 1
0
static int
cbjack_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)
{
  assert(!input_stream_params && "not supported.");
  if (input_device || output_device) {
    /* Device selection not yet implemented. */
    return CUBEB_ERROR_DEVICE_UNAVAILABLE;
  }

  if (stream == NULL || output_stream_params == NULL) {
    return CUBEB_ERROR_INVALID_PARAMETER;
  }

  if (output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
      output_stream_params->format != CUBEB_SAMPLE_S16NE) {
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  *stream = NULL;

  // Lock streams
  AutoLock lock(context->mutex);

  // Find a free stream.
  cubeb_stream * stm = context_alloc_stream(context, stream_name);

  // No free stream?
  if (stm == NULL) {
    return CUBEB_ERROR;
  }

  stm->user_ptr = user_ptr;
  stm->context = context;
  stm->params = *output_stream_params;
  stm->data_callback = data_callback;
  stm->state_callback = state_callback;
  stm->position = 0;
  stm->volume = 1.0f;

  if (stm->params.rate != stm->context->jack_sample_rate) {
    int resampler_error;
    stm->resampler = speex_resampler_init(stm->params.channels,
                                          stm->params.rate,
                                          stm->context->jack_sample_rate,
                                          10,
                                          &resampler_error);
    if (resampler_error != 0) {
      stm->in_use = false;
      return CUBEB_ERROR;
    }
  }

  for (unsigned int c = 0; c < stm->params.channels; c++) {
    char portname[256];
    snprintf(portname, 255, "%s_%d", stm->stream_name, c);
    stm->output_ports[c] = api_jack_port_register(stm->context->jack_client,
                                                  portname,
                                                  JACK_DEFAULT_AUDIO_TYPE,
                                                  JackPortIsOutput,
                                                  0);
  }

  if (AUTO_CONNECT_JACK_PORTS) {
    cbjack_connect_ports(stm);
  }

  stm->ports_ready = true;

  *stream = stm;

  return CUBEB_OK;
}
Exemplo n.º 2
0
static int
cbjack_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)
{
  int stream_actual_rate = 0;
  int jack_rate = api_jack_get_sample_rate(context->jack_client);

  if (output_stream_params
     && (output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
         output_stream_params->format != CUBEB_SAMPLE_S16NE)
     ) {
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  if (input_stream_params
     && (input_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
         input_stream_params->format != CUBEB_SAMPLE_S16NE)
     ) {
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  *stream = NULL;

  // Find a free stream.
  pthread_mutex_lock(&context->mutex);
  cubeb_stream * stm = context_alloc_stream(context, stream_name);

  // No free stream?
  if (stm == NULL) {
    pthread_mutex_unlock(&context->mutex);
    return CUBEB_ERROR;
  }

  // unlock context mutex
  pthread_mutex_unlock(&context->mutex);

  // Lock active stream
  pthread_mutex_lock(&stm->mutex);

  stm->ports_ready = false;
  stm->user_ptr = user_ptr;
  stm->context = context;
  stm->devs = NONE;
  if (output_stream_params && !input_stream_params) {
    stm->out_params = *output_stream_params;
    stream_actual_rate = stm->out_params.rate;
    stm->out_params.rate = jack_rate;
    stm->devs = OUT_ONLY;
    if (stm->out_params.format == CUBEB_SAMPLE_FLOAT32NE) {
      context->output_bytes_per_frame = sizeof(float);
    } else {
      context->output_bytes_per_frame = sizeof(short);
    }
  }
  if (input_stream_params && output_stream_params) {
    stm->in_params = *input_stream_params;
    stm->out_params = *output_stream_params;
    stream_actual_rate = stm->out_params.rate;
    stm->in_params.rate = jack_rate;
    stm->out_params.rate = jack_rate;
    stm->devs = DUPLEX;
    if (stm->out_params.format == CUBEB_SAMPLE_FLOAT32NE) {
      context->output_bytes_per_frame = sizeof(float);
      stm->in_params.format = CUBEB_SAMPLE_FLOAT32NE;
    } else {
      context->output_bytes_per_frame = sizeof(short);
      stm->in_params.format = CUBEB_SAMPLE_S16NE;
    }
  } else if (input_stream_params && !output_stream_params) {
    stm->in_params = *input_stream_params;
    stream_actual_rate = stm->in_params.rate;
    stm->in_params.rate = jack_rate;
    stm->devs = IN_ONLY;
    if (stm->in_params.format == CUBEB_SAMPLE_FLOAT32NE) {
      context->output_bytes_per_frame = sizeof(float);
    } else {
      context->output_bytes_per_frame = sizeof(short);
    }
  }

  stm->ratio = (float)stream_actual_rate / (float)jack_rate;

  stm->data_callback = data_callback;
  stm->state_callback = state_callback;
  stm->position = 0;
  stm->volume = 1.0f;
  context->jack_buffer_size = api_jack_get_buffer_size(context->jack_client);
  context->fragment_size = context->jack_buffer_size;

  if (stm->devs == NONE) {
    pthread_mutex_unlock(&stm->mutex);
    return CUBEB_ERROR;
  }

  stm->resampler = NULL;

  if (stm->devs == DUPLEX) {
    stm->resampler = cubeb_resampler_create(stm,
                                          &stm->in_params,
                                          &stm->out_params,
                                          stream_actual_rate,
                                          stm->data_callback,
                                          stm->user_ptr,
                                          CUBEB_RESAMPLER_QUALITY_DESKTOP);
  } else if (stm->devs == IN_ONLY) {
    stm->resampler = cubeb_resampler_create(stm,
                                          &stm->in_params,
                                          nullptr,
                                          stream_actual_rate,
                                          stm->data_callback,
                                          stm->user_ptr,
                                          CUBEB_RESAMPLER_QUALITY_DESKTOP);
  } else if (stm->devs == OUT_ONLY) {
    stm->resampler = cubeb_resampler_create(stm,
                                          nullptr,
                                          &stm->out_params,
                                          stream_actual_rate,
                                          stm->data_callback,
                                          stm->user_ptr,
                                          CUBEB_RESAMPLER_QUALITY_DESKTOP);
  }

  if (!stm->resampler) {
    stm->in_use = false;
    pthread_mutex_unlock(&stm->mutex);
    return CUBEB_ERROR;
  }

  if (stm->devs == DUPLEX || stm->devs == OUT_ONLY) {
    for (unsigned int c = 0; c < stm->out_params.channels; c++) {
      char portname[256];
      snprintf(portname, 255, "%s_out_%d", stm->stream_name, c);
      stm->output_ports[c] = api_jack_port_register(stm->context->jack_client,
                                                    portname,
                                                    JACK_DEFAULT_AUDIO_TYPE,
                                                    JackPortIsOutput,
                                                    0);
    }
  }

  if (stm->devs == DUPLEX || stm->devs == IN_ONLY) {
    for (unsigned int c = 0; c < stm->in_params.channels; c++) {
      char portname[256];
      snprintf(portname, 255, "%s_in_%d", stm->stream_name, c);
      stm->input_ports[c] = api_jack_port_register(stm->context->jack_client,
                                                    portname,
                                                    JACK_DEFAULT_AUDIO_TYPE,
                                                    JackPortIsInput,
                                                    0);
    }
  }

  cbjack_connect_ports(stm);

  *stream = stm;

  stm->ports_ready = true;
  stm->pause = true;
  pthread_mutex_unlock(&stm->mutex);

  return CUBEB_OK;
}