diff --git a/include/baresip.h b/include/baresip.h index 37e85d0e7a..a5f00adb6d 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -581,6 +581,8 @@ typedef void (ausrc_error_h)(int err, const char *str, void *arg); typedef int (ausrc_alloc_h)(struct ausrc_st **stp, const struct ausrc *ausrc, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); +typedef int (ausrc_info_h)(const struct ausrc *ausrc, + struct ausrc_prm *prm, const char *device); /** Defines an Audio Source */ struct ausrc { @@ -588,6 +590,7 @@ struct ausrc { const char *name; struct list dev_list; ausrc_alloc_h *alloch; + ausrc_info_h *infoh; }; int ausrc_register(struct ausrc **asp, struct list *ausrcl, const char *name, @@ -597,6 +600,8 @@ int ausrc_alloc(struct ausrc_st **stp, struct list *ausrcl, const char *name, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); +int ausrc_info(struct list *ausrcl, + const char *name, struct ausrc_prm *prm, const char *device); /* diff --git a/modules/aufile/aufile.c b/modules/aufile/aufile.c index 55df91c8f7..d2340796b5 100644 --- a/modules/aufile/aufile.c +++ b/modules/aufile/aufile.c @@ -32,6 +32,10 @@ static int module_init(void) aufile_src_alloc); err |= auplay_register(&auplay, baresip_auplayl(), "aufile", aufile_play_alloc); + if (err) + return err; + + ausrc->infoh = aufile_info_handler; return err; } diff --git a/modules/aufile/aufile.h b/modules/aufile/aufile.h index 0e6176a856..caa88d0083 100644 --- a/modules/aufile/aufile.h +++ b/modules/aufile/aufile.h @@ -10,3 +10,5 @@ int aufile_play_alloc(struct auplay_st **stp, const struct auplay *ap, int aufile_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); +int aufile_info_handler(const struct ausrc *as, + struct ausrc_prm *prm, const char *dev); diff --git a/modules/aufile/aufile_src.c b/modules/aufile/aufile_src.c index 5df5981764..b7fe847072 100644 --- a/modules/aufile/aufile_src.c +++ b/modules/aufile/aufile_src.c @@ -231,7 +231,6 @@ int aufile_src_alloc(struct ausrc_st **stp, const struct ausrc *as, /* return wav format to caller */ prm->srate = fprm.srate; prm->ch = fprm.channels; - prm->duration = aufile_get_length(st->aufile, &fprm); if (!rh) goto out; @@ -271,3 +270,31 @@ int aufile_src_alloc(struct ausrc_st **stp, const struct ausrc *as, return err; } + + +int aufile_info_handler(const struct ausrc *as, + struct ausrc_prm *prm, const char *dev) +{ + int err; + (void)as; + + if (!prm || !str_isset(dev)) + return EINVAL; + + struct aufile *aufile; + struct aufile_prm fprm; + err = aufile_open(&aufile, &fprm, dev, AUFILE_READ); + if (err) { + warning("aufile: failed to open file '%s' (%m)\n", dev, err); + goto out; + } + + prm->srate = fprm.srate; + prm->ch = fprm.channels; + prm->fmt = fprm.fmt; + prm->duration = aufile_get_length(aufile, &fprm); + +out: + mem_deref(aufile); + return err; +} diff --git a/modules/debug_cmd/debug_cmd.c b/modules/debug_cmd/debug_cmd.c index 46f4ed127c..3867a542d5 100644 --- a/modules/debug_cmd/debug_cmd.c +++ b/modules/debug_cmd/debug_cmd.c @@ -183,11 +183,11 @@ static void fileinfo_destruct(void *arg) } -static void print_fileinfo(struct fileinfo_st *st) +static void print_fileinfo(struct ausrc_prm *prm) { - double s = ((float) st->prm.duration) / 1000; + double s = ((float) prm->duration) / 1000; - if (st->prm.duration) { + if (prm->duration) { info("debug_cmd: length = %1.3lf seconds\n", s); module_event("debug_cmd", "aufileinfo", NULL, NULL, "length = %lf seconds", s); @@ -222,7 +222,7 @@ static int cmd_aufileinfo(struct re_printf *pf, void *arg) char *path; char aumod[16]; const char *file = carg->prm; - struct fileinfo_st *st = NULL; + struct ausrc_prm prm; if (!str_isset(file)) { re_hprintf(pf, "fileplay: filename not specified\n"); @@ -247,25 +247,16 @@ static int cmd_aufileinfo(struct re_printf *pf, void *arg) conf_config()->audio.audio_path, file) < 0) return ENOMEM; - st = mem_zalloc(sizeof(*st), fileinfo_destruct); - if (!st) { - err = ENOMEM; - goto out; - } - - err = ausrc_alloc(&st->ausrc, baresip_ausrcl(), - aumod, - &st->prm, path, NULL, NULL, st); + err = ausrc_info(baresip_ausrcl(), aumod, &prm, path); if (err) { - warning("debug_cmd: %s - ausrc %s does not support empty read " - "handler or reading source %s failed. (%m)\n", - __func__, aumod, carg->prm, err); + warning("debug_cmd: %s - ausrc %s does not support info query " + "or reading source %s failed. (%m)\n", + __func__, aumod, carg->prm, err); goto out; } - print_fileinfo(st); + print_fileinfo(&prm); out: - mem_deref(st); mem_deref(path); return err; diff --git a/modules/gst/gst.c b/modules/gst/gst.c index b15bdcb1ff..279ac2024b 100644 --- a/modules/gst/gst.c +++ b/modules/gst/gst.c @@ -345,13 +345,13 @@ static int gst_setup(struct ausrc_st *st) } -static int setup_uri(struct ausrc_st *st, const char *device) +static int setup_uri(char **urip, const char *device) { int err = 0; if (g_regex_match_simple( uri_regex, device, 0, G_REGEX_MATCH_NOTEMPTY)) { - err = str_dup(&st->uri, device); + err = str_dup(urip, device); } else { if (!access(device, R_OK)) { @@ -360,7 +360,7 @@ static int setup_uri(struct ausrc_st *st, const char *device) if (re_snprintf(uri, urilength, "file://%s", device) < 0) return ENOMEM; - st->uri = uri; + *urip = uri; } else { err = errno; @@ -437,7 +437,7 @@ static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as, st->rh = rh; st->arg = arg; - err = setup_uri(st, device); + err = setup_uri(&st->uri, device); if (err) goto out; st->ptime = prm->ptime; @@ -487,18 +487,67 @@ static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as, mem_deref(st); else { *stp = st; - gst_element_get_state(st->pipeline, NULL, NULL, 500*1000*1000); - gint64 duration = 0; - gst_element_query_duration(st->pipeline, - GST_FORMAT_TIME, - &duration); - prm->duration = duration / 1000000; } return err; } +static int gst_info_handler(const struct ausrc *as, + struct ausrc_prm *prm, const char *device) +{ + int err; + (void)as; + + if (!prm || !str_isset(device)) + return EINVAL; + + char *uri = NULL; + err = setup_uri(&uri, device); + if (err) goto out; + + GstElement *pipeline = gst_pipeline_new("pipeline"); + if (!pipeline) { + warning("gst: failed to create pipeline element\n"); + return ENOMEM; + } + + GstElement *playbin = gst_element_factory_make("playbin", NULL); + GstElement *sink = gst_element_factory_make("fakesink", NULL); + if (!playbin || !sink) { + err = ENOMEM; + if (playbin) + gst_object_unref(playbin); + if (sink) + gst_object_unref(sink); + gst_object_unref(pipeline); + goto out; + } + + gst_bin_add(GST_BIN(pipeline), playbin); + g_object_set(G_OBJECT(playbin), + "uri", uri, + "audio-sink", sink, NULL); + + gst_element_set_state(pipeline, GST_STATE_PLAYING); + gst_element_get_state(pipeline, NULL, NULL, 500*1000*1000); + gint64 duration = 0; + gst_element_query_duration(pipeline, + GST_FORMAT_TIME, + &duration); + + prm->duration = (size_t) duration; + + /* Note: other prm fields are currently not set */ + +out: + gst_element_set_state(pipeline, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(pipeline)); + mem_deref(uri); + return err; +} + + static int mod_gst_init(void) { gchar *s; @@ -511,7 +560,12 @@ static int mod_gst_init(void) g_free(s); - return ausrc_register(&ausrc, baresip_ausrcl(), "gst", gst_alloc); + int err = ausrc_register(&ausrc, baresip_ausrcl(), "gst", gst_alloc); + if (err) + return err; + + ausrc->infoh = gst_info_handler; + return 0; } diff --git a/src/ausrc.c b/src/ausrc.c index b72153b4ee..5408c2406e 100644 --- a/src/ausrc.c +++ b/src/ausrc.c @@ -105,3 +105,29 @@ int ausrc_alloc(struct ausrc_st **stp, struct list *ausrcl, return as->alloch(stp, as, prm, device, rh, errh, arg); } + + +/** + * Retreive audio parameters of an audio source + * + * @param ausrcl List of Audio Sources + * @param name Name of Audio Source + * @param prm Audio Source parameters + * @param device Name of Audio Source device (driver specific) + * + * @return 0 if success, otherwise errorcode + */ +int ausrc_info(struct list *ausrcl, + const char *name, struct ausrc_prm *prm, const char *device) +{ + struct ausrc *as; + + as = (struct ausrc *)ausrc_find(ausrcl, name); + if (!as) + return ENOENT; + + if (!as->infoh) + return EINVAL; + + return as->infoh(as, prm, device); +}