Exemplo n.º 1
0
int main(int argc, char *argv[]) {
    pa_mempool *pool;
    pa_sample_spec a, b;
    pa_cvolume v;

    pa_log_set_level(PA_LOG_DEBUG);

    pa_assert_se(pool = pa_mempool_new(FALSE, 0));

    a.channels = b.channels = 1;
    a.rate = b.rate = 44100;

    v.channels = a.channels;
    v.values[0] = pa_sw_volume_from_linear(0.5);

    for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
        for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) {
            pa_resampler *forth, *back;
            pa_memchunk i, j, k;

            printf("=== %s -> %s -> %s -> /2\n",
                   pa_sample_format_to_string(a.format),
                   pa_sample_format_to_string(b.format),
                   pa_sample_format_to_string(a.format));

            pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, 0));
            pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, 0));

            i.memblock = generate_block(pool, &a);
            i.length = pa_memblock_get_length(i.memblock);
            i.index = 0;
            pa_resampler_run(forth, &i, &j);
            pa_resampler_run(back, &j, &k);

            printf("before:  ");
            dump_block(&a, &i);
            printf("after :  ");
            dump_block(&b, &j);
            printf("reverse: ");
            dump_block(&a, &k);

            pa_memblock_unref(j.memblock);
            pa_memblock_unref(k.memblock);

            pa_volume_memchunk(&i, &a, &v);
            printf("volume:  ");
            dump_block(&a, &i);

            pa_memblock_unref(i.memblock);

            pa_resampler_free(forth);
            pa_resampler_free(back);
        }
    }

    pa_mempool_free(pool);

    return 0;
}
Exemplo n.º 2
0
/**
 * Source info callback
 *
 * We use the default stream settings for recording here unless pulse is
 * configured to something obs can't deal with.
 */
static void pulse_source_info(pa_context *c, const pa_source_info *i, int eol,
	void *userdata)
{
	UNUSED_PARAMETER(c);
	PULSE_DATA(userdata);
	// An error occured
	if (eol < 0) {
		data->format = PA_SAMPLE_INVALID;
		goto skip;
	}
	// Terminating call for multi instance callbacks
	if (eol > 0)
		goto skip;

	blog(LOG_INFO, "Audio format: %s, %"PRIu32" Hz"
		", %"PRIu8" channels",
		pa_sample_format_to_string(i->sample_spec.format),
		i->sample_spec.rate,
		i->sample_spec.channels);

	pa_sample_format_t format = i->sample_spec.format;
	if (pulse_to_obs_audio_format(format) == AUDIO_FORMAT_UNKNOWN) {
		format = PA_SAMPLE_S16LE;

		blog(LOG_INFO, "Sample format %s not supported by OBS,"
			"using %s instead for recording",
			pa_sample_format_to_string(i->sample_spec.format),
			pa_sample_format_to_string(format));
	}

	uint8_t channels = i->sample_spec.channels;
	if (pulse_channels_to_obs_speakers(channels) == SPEAKERS_UNKNOWN) {
		channels = 2;

		blog(LOG_INFO, "%c channels not supported by OBS,"
			"using %c instead for recording",
			i->sample_spec.channels,
			channels);
	}

	data->format          = format;
	data->samples_per_sec = i->sample_spec.rate;
	data->channels        = channels;

skip:
	pulse_signal(0);
}
Exemplo n.º 3
0
static int publish_spec(pa_sample_spec *sample_spec) {
    /* Publish spec and set state to XenbusStateInitWait*/
    int ret;

    ret = publish_param("format", pa_sample_format_to_string(sample_spec->format));
    ret += publish_param_int("rate", sample_spec->rate);
    ret += publish_param_int("channels", sample_spec->channels);

    return ret;
}
Exemplo n.º 4
0
/** Pretty print a sample type specification to a string */
char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
 if ( s == NULL || l == 0 || spec == NULL )
  return NULL;

 if ( pa_sample_spec_valid(spec) ) {
  snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
 } else {
  snprintf(s, l, "Invalid");
 }

 return s;
}
Exemplo n.º 5
0
APULSE_EXPORT
char *
pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec)
{
    trace_info_f("F %s s=%p, l=%u, spec=%p\n", __func__, s, (unsigned)l, spec);

    if (spec && pa_sample_spec_valid(spec)) {
        snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels,
                 spec->rate);
    } else {
        snprintf(s, l, "invalid");
    }

    return s;
}
Exemplo n.º 6
0
/*
 * Server info callback, this is called from pa_mainloop_dispatch
 * TODO: how to free the server info struct ?
 */
static void pulse_get_server_info_cb(pa_context *c, const pa_server_info *i,
	void *userdata)
{
	UNUSED_PARAMETER(c);
	PULSE_DATA(userdata);

	const pa_sample_spec *spec = &i->sample_spec;
	data->format = spec->format;
	data->samples_per_sec = spec->rate;

	blog(LOG_DEBUG, "pulse-input: Default format: %s, %u Hz, %u channels",
		pa_sample_format_to_string(spec->format),
		spec->rate,
		spec->channels);
}
Exemplo n.º 7
0
/*
 * Server info callback
 */
static void pulse_server_info(pa_context *c, const pa_server_info *i,
	void *userdata)
{
	UNUSED_PARAMETER(c);
	PULSE_DATA(userdata);

	data->format          = i->sample_spec.format;
	data->samples_per_sec = i->sample_spec.rate;
	data->channels        = i->sample_spec.channels;

	blog(LOG_DEBUG, "pulse-input: Default format: %s, %u Hz, %u channels",
		pa_sample_format_to_string(i->sample_spec.format),
		i->sample_spec.rate,
		i->sample_spec.channels);

	pulse_signal(0);
}
Exemplo n.º 8
0
/**
 * Server info callback
 */
static void pulse_server_info(pa_context *c, const pa_server_info *i,
	void *userdata)
{
	UNUSED_PARAMETER(c);
	PULSE_DATA(userdata);

	blog(LOG_INFO, "pulse-input: Server name: '%s %s'",
		i->server_name, i->server_version);

	data->format          = i->sample_spec.format;
	data->samples_per_sec = i->sample_spec.rate;
	data->channels        = i->sample_spec.channels;

	blog(LOG_INFO, "pulse-input: "
		"Audio format: %s, %u Hz, %u channels",
		pa_sample_format_to_string(i->sample_spec.format),
		i->sample_spec.rate,
		i->sample_spec.channels);

	pulse_signal(0);
}
Exemplo n.º 9
0
char *pa_daemon_conf_dump(pa_daemon_conf *c) {
    static const char* const log_level_to_string[] = {
        [PA_LOG_DEBUG] = "debug",
        [PA_LOG_INFO] = "info",
        [PA_LOG_NOTICE] = "notice",
        [PA_LOG_WARN] = "warning",
        [PA_LOG_ERROR] = "error"
    };

#ifdef HAVE_DBUS
    static const char* const server_type_to_string[] = {
        [PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
        [PA_SERVER_TYPE_USER] = "user",
        [PA_SERVER_TYPE_SYSTEM] = "system",
        [PA_SERVER_TYPE_NONE] = "none"
    };
#endif

    pa_strbuf *s;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
    char *log_target = NULL;

    pa_assert(c);

    s = pa_strbuf_new();

    if (c->config_file)
        pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file);

    pa_assert(c->log_level < PA_LOG_LEVEL_MAX);

    if (c->log_target)
        log_target = pa_log_target_to_string(c->log_target);

    pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize));
    pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail));
    pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority));
    pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level);
    pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling));
    pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority);
    pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading));
    pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit));
    pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));
    pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance));
#ifdef HAVE_DBUS
    pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]);
#endif
    pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit));
    pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm));
    pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
    pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
    pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
    pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
    pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
    pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
    pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
    pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
    pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
    pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
    pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(!c->avoid_resampling));
    pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
    pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
    pa_strbuf_printf(s, "enable-lfe-remixing = %s\n", pa_yes_no(!c->disable_lfe_remixing));
    pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq);
    pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
    pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
    pa_strbuf_printf(s, "alternate-sample-rate = %u\n", c->alternate_sample_rate);
    pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
    pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
    pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
    pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
    pa_strbuf_printf(s, "enable-deferred-volume = %s\n", pa_yes_no(c->deferred_volume));
    pa_strbuf_printf(s, "deferred-volume-safety-margin-usec = %u\n", c->deferred_volume_safety_margin_usec);
    pa_strbuf_printf(s, "deferred-volume-extra-delay-usec = %d\n", c->deferred_volume_extra_delay_usec);
    pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
    pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta));
    pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time));
    pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace);
#ifdef HAVE_SYS_RESOURCE_H
    pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
    pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
    pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
    pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
#ifdef RLIMIT_RSS
    pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1);
#endif
#ifdef RLIMIT_AS
    pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
#endif
#ifdef RLIMIT_NPROC
    pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
#endif
#ifdef RLIMIT_NOFILE
    pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
#endif
#ifdef RLIMIT_MEMLOCK
    pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
#endif
#ifdef RLIMIT_LOCKS
    pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1);
#endif
#ifdef RLIMIT_SIGPENDING
    pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1);
#endif
#ifdef RLIMIT_MSGQUEUE
    pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1);
#endif
#ifdef RLIMIT_NICE
    pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1);
#endif
#ifdef RLIMIT_RTPRIO
    pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1);
#endif
#ifdef RLIMIT_RTTIME
    pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1);
#endif
#endif

    pa_xfree(log_target);

    return pa_strbuf_to_string_free(s);
}
Exemplo n.º 10
0
void PulseSrc::get_source_info_callback(pa_context* pulse_context,
                                        const pa_source_info* i,
                                        int is_last,
                                        void* user_data) {
  PulseSrc* context = static_cast<PulseSrc*>(user_data);
  if (is_last < 0) {
    g_debug("Failed to get source information: %s", pa_strerror(pa_context_errno(pulse_context)));
    return;
  }
  if (is_last) {
    pa_operation* operation = pa_context_drain(pulse_context, nullptr, nullptr);
    if (operation) pa_operation_unref(operation);
    // registering enum for devices
    context->update_capture_device();

    context->devices_id_ = context->pmanage<MPtr(&PContainer::make_selection<>)>(
        "device",
        [context](const size_t& val) {
          context->devices_.select(val);
          return true;
        },
        [context]() { return context->devices_.get(); },
        "Device",
        "Audio capture device to use",
        context->devices_);
    // signal init we are done
    std::unique_lock<std::mutex> lock(context->devices_mutex_);
    context->devices_cond_.notify_all();
    return;
  }
  DeviceDescription description;
  switch (i->state) {
    case PA_SOURCE_INIT:
      description.state_ = "INIT";
      // g_print ("state: INIT \n");
      break;
    case PA_SOURCE_UNLINKED:
      description.state_ = "UNLINKED";
      // g_print ("state: UNLINKED \n");
      break;
    case PA_SOURCE_INVALID_STATE:
      description.state_ = "n/a";
      // g_print ("state: n/a \n");
      break;
    case PA_SOURCE_RUNNING:
      description.state_ = "RUNNING";
      // g_print ("state: RUNNING \n");
      break;
    case PA_SOURCE_IDLE:
      description.state_ = "IDLE";
      // g_print ("state: IDLE \n");
      break;
    case PA_SOURCE_SUSPENDED:
      description.state_ = "SUSPENDED";
      // g_print ("state: SUSPENDED \n");
      break;
  }
  description.name_ = i->name;
  if (i->description == nullptr)
    description.description_ = "";
  else
    description.description_ = i->description;
  description.sample_format_ = pa_sample_format_to_string(i->sample_spec.format);
  gchar* rate = g_strdup_printf("%u", i->sample_spec.rate);
  description.sample_rate_ = rate;
  g_free(rate);
  gchar* channels = g_strdup_printf("%u", i->sample_spec.channels);
  description.channels_ = channels;
  g_free(channels);
  // g_print ("Name: %s\n"
  //      "Description: %s\n"
  //      " format: %s\n"
  //      " rate: %u\n"
  //      " channels: %u\n",
  //      //"Channel Map: %s\n",
  //      i->name,
  //      i->description,// warning this can be nullptr
  //      pa_sample_format_to_string (i->sample_spec.format),
  //      i->sample_spec.rate,
  //      i->sample_spec.channels//,
  //      // pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map)
  //      );
  if (i->ports) {
    pa_source_port_info** p;
    // printf("\tPorts:\n");
    for (p = i->ports; *p; p++) {
      // printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description,
      // (*p)->priority);
      description.ports_.push_back(std::make_pair((*p)->name, (*p)->description));
    }
  }
  if (i->active_port) {
    // printf("\tActive Port: %s\n", i->active_port->name);
    description.active_port_ = i->active_port->description;
  } else
    description.active_port_ = "n/a";
  context->capture_devices_.push_back(description);
  // if (i->formats) {
  //   uint8_t j;
  //   printf("\tFormats:\n");
  //   for (j = 0; j < i->n_formats; j++)
  // printf("\t\t%s\n", pa_format_info_snprint(f, sizeof(f), i->formats[j]));
  // }
}
Exemplo n.º 11
0
static void resolver_cb(
        AvahiServiceResolver *r,
        AvahiIfIndex interface, AvahiProtocol protocol,
        AvahiResolverEvent event,
        const char *name, const char *type, const char *domain,
        const char *host_name, const AvahiAddress *a, uint16_t port,
        AvahiStringList *txt,
        AvahiLookupResultFlags flags,
        void *userdata) {

    struct userdata *u = userdata;
    struct tunnel *tnl;

    pa_assert(u);

    tnl = tunnel_new(interface, protocol, name, type, domain);

    if (event != AVAHI_RESOLVER_FOUND)
        pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client)));
    else {
        char *device = NULL, *dname, *module_name, *args;
        const char *t;
        char at[AVAHI_ADDRESS_STR_MAX], cmt[PA_CHANNEL_MAP_SNPRINT_MAX];
        pa_sample_spec ss;
        pa_channel_map cm;
        AvahiStringList *l;
        pa_bool_t channel_map_set = FALSE;
        pa_module *m;

        ss = u->core->default_sample_spec;
        cm = u->core->default_channel_map;

        for (l = txt; l; l = l->next) {
            char *key, *value;
            pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0);

            if (pa_streq(key, "device")) {
                pa_xfree(device);
                device = value;
                value = NULL;
            } else if (pa_streq(key, "rate"))
                ss.rate = (uint32_t) atoi(value);
            else if (pa_streq(key, "channels"))
                ss.channels = (uint8_t) atoi(value);
            else if (pa_streq(key, "format"))
                ss.format = pa_parse_sample_format(value);
            else if (pa_streq(key, "channel_map")) {
                pa_channel_map_parse(&cm, value);
                channel_map_set = TRUE;
            }

            avahi_free(key);
            avahi_free(value);
        }

        if (!channel_map_set && cm.channels != ss.channels)
            pa_channel_map_init_extend(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT);

        if (!pa_sample_spec_valid(&ss)) {
            pa_log("Service '%s' contains an invalid sample specification.", name);
            avahi_free(device);
            goto finish;
        }

        if (!pa_channel_map_valid(&cm) || cm.channels != ss.channels) {
            pa_log("Service '%s' contains an invalid channel map.", name);
            avahi_free(device);
            goto finish;
        }

        if (device)
            dname = pa_sprintf_malloc("tunnel.%s.%s", host_name, device);
        else
            dname = pa_sprintf_malloc("tunnel.%s", host_name);

        if (!pa_namereg_is_valid_name(dname)) {
            pa_log("Cannot construct valid device name from credentials of service '%s'.", dname);
            avahi_free(device);
            pa_xfree(dname);
            goto finish;
        }

        t = strstr(type, "sink") ? "sink" : "source";

        module_name = pa_sprintf_malloc("module-tunnel-%s", t);
        args = pa_sprintf_malloc("server=[%s]:%u "
                                 "%s=%s "
                                 "format=%s "
                                 "channels=%u "
                                 "rate=%u "
                                 "%s_name=%s "
                                 "channel_map=%s",
                                 avahi_address_snprint(at, sizeof(at), a), port,
                                 t, device,
                                 pa_sample_format_to_string(ss.format),
                                 ss.channels,
                                 ss.rate,
                                 t, dname,
                                 pa_channel_map_snprint(cmt, sizeof(cmt), &cm));

        pa_log_debug("Loading %s with arguments '%s'", module_name, args);

        if ((m = pa_module_load(u->core, module_name, args))) {
            tnl->module_index = m->index;
            pa_hashmap_put(u->tunnels, tnl, tnl);
            tnl = NULL;
        }

        pa_xfree(module_name);
        pa_xfree(dname);
        pa_xfree(args);
        avahi_free(device);
    }

finish:

    avahi_service_resolver_free(r);

    if (tnl)
        tunnel_free(tnl);
}
Exemplo n.º 12
0
void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
    pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
}
Exemplo n.º 13
0
int main(int argc, char *argv[]) {
    pa_mempool *pool = NULL;
    pa_sample_spec a, b;
    int ret = 1, c;
    bool all_formats = true;
    pa_resample_method_t method;
    int seconds;
    unsigned crossover_freq = 120;

    static const struct option long_options[] = {
        {"help",                  0, NULL, 'h'},
        {"verbose",               0, NULL, 'v'},
        {"version",               0, NULL, ARG_VERSION},
        {"from-rate",             1, NULL, ARG_FROM_SAMPLERATE},
        {"from-format",           1, NULL, ARG_FROM_SAMPLEFORMAT},
        {"from-channels",         1, NULL, ARG_FROM_CHANNELS},
        {"to-rate",               1, NULL, ARG_TO_SAMPLERATE},
        {"to-format",             1, NULL, ARG_TO_SAMPLEFORMAT},
        {"to-channels",           1, NULL, ARG_TO_CHANNELS},
        {"seconds",               1, NULL, ARG_SECONDS},
        {"resample-method",       1, NULL, ARG_RESAMPLE_METHOD},
        {"dump-resample-methods", 0, NULL, ARG_DUMP_RESAMPLE_METHODS},
        {NULL,                    0, NULL, 0}
    };

    setlocale(LC_ALL, "");
#ifdef ENABLE_NLS
    bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
#endif

    pa_log_set_level(PA_LOG_WARN);
    if (!getenv("MAKE_CHECK"))
        pa_log_set_level(PA_LOG_INFO);

    pa_assert_se(pool = pa_mempool_new(false, 0));

    a.channels = b.channels = 1;
    a.rate = b.rate = 44100;
    a.format = b.format = PA_SAMPLE_S16LE;

    method = PA_RESAMPLER_AUTO;
    seconds = 60;

    while ((c = getopt_long(argc, argv, "hv", long_options, NULL)) != -1) {

        switch (c) {
            case 'h' :
                help(argv[0]);
                ret = 0;
                goto quit;

            case 'v':
                pa_log_set_level(PA_LOG_DEBUG);
                break;

            case ARG_VERSION:
                printf(_("%s %s\n"), argv[0], PACKAGE_VERSION);
                ret = 0;
                goto quit;

            case ARG_DUMP_RESAMPLE_METHODS:
                dump_resample_methods();
                ret = 0;
                goto quit;

            case ARG_FROM_CHANNELS:
                a.channels = (uint8_t) atoi(optarg);
                break;

            case ARG_FROM_SAMPLEFORMAT:
                a.format = pa_parse_sample_format(optarg);
                all_formats = false;
                break;

            case ARG_FROM_SAMPLERATE:
                a.rate = (uint32_t) atoi(optarg);
                break;

            case ARG_TO_CHANNELS:
                b.channels = (uint8_t) atoi(optarg);
                break;

            case ARG_TO_SAMPLEFORMAT:
                b.format = pa_parse_sample_format(optarg);
                all_formats = false;
                break;

            case ARG_TO_SAMPLERATE:
                b.rate = (uint32_t) atoi(optarg);
                break;

            case ARG_SECONDS:
                seconds = atoi(optarg);
                break;

            case ARG_RESAMPLE_METHOD:
                if (*optarg == '\0' || pa_streq(optarg, "help")) {
                    dump_resample_methods();
                    ret = 0;
                    goto quit;
                }
                method = pa_parse_resample_method(optarg);
                break;

            default:
                goto quit;
        }
    }

    ret = 0;
    pa_assert_se(pool = pa_mempool_new(false, 0));

    if (!all_formats) {

        pa_resampler *resampler;
        pa_memchunk i, j;
        pa_usec_t ts;

        pa_log_debug("Compilation CFLAGS: %s", PA_CFLAGS);
        pa_log_debug("=== %d seconds: %d Hz %d ch (%s) -> %d Hz %d ch (%s)", seconds,
                   a.rate, a.channels, pa_sample_format_to_string(a.format),
                   b.rate, b.channels, pa_sample_format_to_string(b.format));

        ts = pa_rtclock_now();
        pa_assert_se(resampler = pa_resampler_new(pool, &a, NULL, &b, NULL, crossover_freq, method, 0));
        pa_log_info("init: %llu", (long long unsigned)(pa_rtclock_now() - ts));

        i.memblock = pa_memblock_new(pool, pa_usec_to_bytes(1*PA_USEC_PER_SEC, &a));

        ts = pa_rtclock_now();
        i.length = pa_memblock_get_length(i.memblock);
        i.index = 0;
        while (seconds--) {
            pa_resampler_run(resampler, &i, &j);
            if (j.memblock)
                pa_memblock_unref(j.memblock);
        }
        pa_log_info("resampling: %llu", (long long unsigned)(pa_rtclock_now() - ts));
        pa_memblock_unref(i.memblock);

        pa_resampler_free(resampler);

        goto quit;
    }

    for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
        for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) {
            pa_resampler *forth, *back;
            pa_memchunk i, j, k;

            pa_log_debug("=== %s -> %s -> %s -> /2",
                       pa_sample_format_to_string(a.format),
                       pa_sample_format_to_string(b.format),
                       pa_sample_format_to_string(a.format));

            pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, crossover_freq, method, 0));
            pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, crossover_freq, method, 0));

            i.memblock = generate_block(pool, &a);
            i.length = pa_memblock_get_length(i.memblock);
            i.index = 0;
            pa_resampler_run(forth, &i, &j);
            pa_resampler_run(back, &j, &k);

            dump_block("before", &a, &i);
            dump_block("after", &b, &j);
            dump_block("reverse", &a, &k);

            pa_memblock_unref(i.memblock);
            pa_memblock_unref(j.memblock);
            pa_memblock_unref(k.memblock);

            pa_resampler_free(forth);
            pa_resampler_free(back);
        }
    }

 quit:
    if (pool)
        pa_mempool_free(pool);

    return ret;
}
Exemplo n.º 14
0
static int drvHostPulseAudioOpen(bool fIn, const char *pszName,
                                 pa_sample_spec *pSampleSpec, pa_buffer_attr *pBufAttr,
                                 pa_stream **ppStream)
{
    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    AssertPtrReturn(pSampleSpec, VERR_INVALID_POINTER);
    AssertPtrReturn(pBufAttr, VERR_INVALID_POINTER);
    AssertPtrReturn(ppStream, VERR_INVALID_POINTER);

    if (!pa_sample_spec_valid(pSampleSpec))
    {
        LogRel(("PulseAudio: Unsupported sample specification for stream \"%s\"\n",
                pszName));
        return VERR_NOT_SUPPORTED;
    }

    int rc = VINF_SUCCESS;

    pa_stream *pStream = NULL;
    uint32_t   flags = PA_STREAM_NOFLAGS;

    LogFunc(("Opening \"%s\", rate=%dHz, channels=%d, format=%s\n",
             pszName, pSampleSpec->rate, pSampleSpec->channels,
             pa_sample_format_to_string(pSampleSpec->format)));

    pa_threaded_mainloop_lock(g_pMainLoop);

    do
    {
        if (!(pStream = pa_stream_new(g_pContext, pszName, pSampleSpec,
                                      NULL /* pa_channel_map */)))
        {
            LogRel(("PulseAudio: Could not create stream \"%s\"\n", pszName));
            rc = VERR_NO_MEMORY;
            break;
        }

        pa_stream_set_state_callback(pStream, drvHostPulseAudioCbStreamState, NULL);

#if PA_API_VERSION >= 12
        /* XXX */
        flags |= PA_STREAM_ADJUST_LATENCY;
#endif

#if 0
        /* Not applicable as we don't use pa_stream_get_latency() and pa_stream_get_time(). */
        flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
#endif
        /* No input/output right away after the stream was started. */
        flags |= PA_STREAM_START_CORKED;

        if (fIn)
        {
            LogFunc(("Input stream attributes: maxlength=%d fragsize=%d\n",
                     pBufAttr->maxlength, pBufAttr->fragsize));

            if (pa_stream_connect_record(pStream, /*dev=*/NULL, pBufAttr, (pa_stream_flags_t)flags) < 0)
            {
                LogRel(("PulseAudio: Could not connect input stream \"%s\": %s\n",
                        pszName, pa_strerror(pa_context_errno(g_pContext))));
                rc = VERR_AUDIO_BACKEND_INIT_FAILED;
                break;
            }
        }
        else
        {
            LogFunc(("Output buffer attributes: maxlength=%d tlength=%d prebuf=%d minreq=%d\n",
                     pBufAttr->maxlength, pBufAttr->tlength, pBufAttr->prebuf, pBufAttr->minreq));

            if (pa_stream_connect_playback(pStream, /*dev=*/NULL, pBufAttr, (pa_stream_flags_t)flags,
                                           /*cvolume=*/NULL, /*sync_stream=*/NULL) < 0)
            {
                LogRel(("PulseAudio: Could not connect playback stream \"%s\": %s\n",
                        pszName, pa_strerror(pa_context_errno(g_pContext))));
                rc = VERR_AUDIO_BACKEND_INIT_FAILED;
                break;
            }
        }

        /* Wait until the stream is ready. */
        for (;;)
        {
            if (!g_fAbortMainLoop)
                pa_threaded_mainloop_wait(g_pMainLoop);
            g_fAbortMainLoop = false;

            pa_stream_state_t sstate = pa_stream_get_state(pStream);
            if (sstate == PA_STREAM_READY)
                break;
            else if (   sstate == PA_STREAM_FAILED
                     || sstate == PA_STREAM_TERMINATED)
            {
                LogRel(("PulseAudio: Failed to initialize stream \"%s\" (state %ld)\n",
                        pszName, sstate));
                rc = VERR_AUDIO_BACKEND_INIT_FAILED;
                break;
            }
        }

        if (RT_FAILURE(rc))
            break;

        const pa_buffer_attr *pBufAttrObtained = pa_stream_get_buffer_attr(pStream);
        AssertPtr(pBufAttrObtained);
        memcpy(pBufAttr, pBufAttrObtained, sizeof(pa_buffer_attr));

        if (fIn)
            LogFunc(("Obtained record buffer attributes: maxlength=%RU32, fragsize=%RU32\n",
                     pBufAttr->maxlength, pBufAttr->fragsize));
        else
            LogFunc(("Obtained playback buffer attributes: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d\n",
                     pBufAttr->maxlength, pBufAttr->tlength, pBufAttr->prebuf, pBufAttr->minreq));

    }
    while (0);

    if (   RT_FAILURE(rc)
        && pStream)
        pa_stream_disconnect(pStream);

    pa_threaded_mainloop_unlock(g_pMainLoop);

    if (RT_FAILURE(rc))
    {
        if (pStream)
            pa_stream_unref(pStream);
    }
    else
        *ppStream = pStream;

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Exemplo n.º 15
0
static int publish_service(struct service *s) {
    int r = -1;
    TXTRecordRef txt;
    DNSServiceErrorType err;
    const char *name = NULL, *t;
    pa_proplist *proplist = NULL;
    pa_sample_spec ss;
    pa_channel_map map;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX], tmp[64];
    enum service_subtype subtype;

    const char * const subtype_text[] = {
        [SUBTYPE_HARDWARE] = "hardware",
        [SUBTYPE_VIRTUAL] = "virtual",
        [SUBTYPE_MONITOR] = "monitor"
    };

    pa_assert(s);

    if (s->service) {
        DNSServiceRefDeallocate(s->service);
        s->service = NULL;
    }

    TXTRecordCreate(&txt, 0, NULL);

    txt_record_server_data(s->userdata->core, &txt);

    get_service_data(s, &ss, &map, &name, &proplist, &subtype);
    TXTRecordSetValue(&txt, "device", strlen(name), name);

    snprintf(tmp, sizeof(tmp), "%u", ss.rate);
    TXTRecordSetValue(&txt, "rate", strlen(tmp), tmp);

    snprintf(tmp, sizeof(tmp), "%u", ss.channels);
    TXTRecordSetValue(&txt, "channels", strlen(tmp), tmp);

    t = pa_sample_format_to_string(ss.format);
    TXTRecordSetValue(&txt, "format", strlen(t), t);

    t = pa_channel_map_snprint(cm, sizeof(cm), &map);
    TXTRecordSetValue(&txt, "channel_map", strlen(t), t);

    t = subtype_text[subtype];
    TXTRecordSetValue(&txt, "subtype", strlen(t), t);

    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION)))
        TXTRecordSetValue(&txt, "description", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME)))
        TXTRecordSetValue(&txt, "icon-name", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME)))
        TXTRecordSetValue(&txt, "vendor-name", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME)))
        TXTRecordSetValue(&txt, "product-name", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS)))
        TXTRecordSetValue(&txt, "class", strlen(t), t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR)))
        TXTRecordSetValue(&txt, "form-factor", strlen(t), t);

    err = DNSServiceRegister(&s->service,
                             0,         /* flags */
                             kDNSServiceInterfaceIndexAny,
                             s->service_name,
                             pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                             NULL,      /* domain */
                             NULL,      /* host */
                             compute_port(s->userdata),
                             TXTRecordGetLength(&txt),
                             TXTRecordGetBytesPtr(&txt),
                             dns_service_register_reply, s);

    if (err != kDNSServiceErr_NoError) {
        pa_log("DNSServiceRegister() returned err %d", err);
        goto finish;
    }

    pa_log_debug("Successfully registered Bonjour services for >%s<.", s->service_name);
    return 0;

finish:

    /* Remove this service */
    if (r < 0)
        service_free(s);

    TXTRecordDeallocate(&txt);

    return r;
}
static int publish_service(struct service *s) {
    int r = -1;
    AvahiStringList *txt = NULL;
    const char *name = NULL, *t;
    pa_proplist *proplist = NULL;
    pa_sample_spec ss;
    pa_channel_map map;
    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
    enum service_subtype subtype;

    const char * const subtype_text[] = {
        [SUBTYPE_HARDWARE] = "hardware",
        [SUBTYPE_VIRTUAL] = "virtual",
        [SUBTYPE_MONITOR] = "monitor"
    };

    pa_assert(s);

    if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
        return 0;

    if (!s->entry_group) {
        if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) {
            pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    } else
        avahi_entry_group_reset(s->entry_group);

    txt = txt_record_server_data(s->userdata->core, txt);

    get_service_data(s, &ss, &map, &name, &proplist, &subtype);
    txt = avahi_string_list_add_pair(txt, "device", name);
    txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
    txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
    txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
    txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map));
    txt = avahi_string_list_add_pair(txt, "subtype", subtype_text[subtype]);

    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION)))
        txt = avahi_string_list_add_pair(txt, "description", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME)))
        txt = avahi_string_list_add_pair(txt, "icon-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME)))
        txt = avahi_string_list_add_pair(txt, "vendor-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME)))
        txt = avahi_string_list_add_pair(txt, "product-name", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS)))
        txt = avahi_string_list_add_pair(txt, "class", t);
    if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR)))
        txt = avahi_string_list_add_pair(txt, "form-factor", t);

    if (avahi_entry_group_add_service_strlst(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                NULL,
                compute_port(s->userdata),
                txt) < 0) {

        pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (avahi_entry_group_add_service_subtype(
                s->entry_group,
                AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                0,
                s->service_name,
                pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE,
                NULL,
                pa_sink_isinstance(s->device) ? (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SINK_HARDWARE : SERVICE_SUBTYPE_SINK_VIRTUAL) :
                (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) {

        pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    if (pa_source_isinstance(s->device) && subtype != SUBTYPE_MONITOR) {
        if (avahi_entry_group_add_service_subtype(
                    s->entry_group,
                    AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
                    0,
                    s->service_name,
                    SERVICE_TYPE_SOURCE,
                    NULL,
                    SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) {

            pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
            goto finish;
        }
    }

    if (avahi_entry_group_commit(s->entry_group) < 0) {
        pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client)));
        goto finish;
    }

    r = 0;
    pa_log_debug("Successfully created entry group for %s.", s->service_name);

finish:

    /* Remove this service */
    if (r < 0)
        service_free(s);

    avahi_string_list_free(txt);

    return r;
}