[pulseaudio-commits] 9 commits - man/pactl.1.xml.in src/modules src/pulse src/pulsecore src/utils
Arun Raghavan
arun at kemper.freedesktop.org
Mon Aug 15 00:38:49 PDT 2011
man/pactl.1.xml.in | 8 +++
src/modules/alsa/alsa-sink.c | 69 +++++++++++++++++++++++++++++++++
src/modules/module-device-restore.c | 57 ++++++++++++++++++++++-----
src/pulse/format.c | 75 ++++++++++++++++++++++++++++++------
src/pulse/format.h | 7 +++
src/pulsecore/sink.c | 16 +++++++
src/pulsecore/sink.h | 11 ++++-
src/utils/pactl.c | 66 ++++++++++++++++++++++++++++++-
8 files changed, 282 insertions(+), 27 deletions(-)
New commits:
commit 50b420aebd876557a64f9015e1197e7d12201f5f
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Mon Aug 15 12:07:02 2011 +0530
device-restore: Log invalid sink index while setting formats
This makes it easier to catch errors when using 'pactl set-sink-formats'
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 671ffd4..6c5c27e 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -826,8 +826,10 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
}
/* Now find our sink */
- if (!(sink = pa_idxset_get_by_index(u->core->sinks, sink_index)))
+ if (!(sink = pa_idxset_get_by_index(u->core->sinks, sink_index))) {
+ pa_log("Could not find sink #%d", sink_index);
goto fail;
+ }
/* Read or create an entry */
name = pa_sprintf_malloc("sink:%s", sink->name);
commit b9d517cd515a6d53de592b7c33e47caaff738b6c
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Mon Aug 15 11:23:59 2011 +0530
sink: Fix lazy commenting
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 0bd5e81..3f89784 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -217,17 +217,17 @@ struct pa_sink {
/* Called whenever the port shall be changed. Called from main
* thread. */
- int (*set_port)(pa_sink *s, pa_device_port *port); /* ditto */
+ int (*set_port)(pa_sink *s, pa_device_port *port); /* may be NULL */
/* Called to get the list of formats supported by the sink, sorted
* in descending order of preference. */
- pa_idxset* (*get_formats)(pa_sink *s); /* ditto */
+ pa_idxset* (*get_formats)(pa_sink *s); /* may be NULL */
/* Called to set the list of formats supported by the sink. Can be
* NULL if the sink does not support this. Returns TRUE on success,
* FALSE otherwise (for example when an unsupportable format is
* set). Makes a copy of the formats passed in. */
- pa_bool_t (*set_formats)(pa_sink *s, pa_idxset *formats); /* ditto */
+ pa_bool_t (*set_formats)(pa_sink *s, pa_idxset *formats); /* may be NULL */
/* Contains copies of the above data so that the real-time worker
* thread can work without access locking */
commit 0f3be7b72b2a1ba72a209628e19789dcf8132f11
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Mon Aug 15 09:47:09 2011 +0530
pactl: Add a set-sink-formats command
This uses the module-device-restore protocol extension to save formats
on sinks that support it.
diff --git a/man/pactl.1.xml.in b/man/pactl.1.xml.in
index 3a70fb6..f0060fb 100644
--- a/man/pactl.1.xml.in
+++ b/man/pactl.1.xml.in
@@ -218,6 +218,14 @@ USA.
</option>
<option>
+ <p><opt>set-sink-formats</opt> <arg>SINK</arg> <arg>FORMATS</arg></p>
+ <optdesc><p>Set the supported formats of the specified sink (identified by its numerical index) if supported by the sink.
+ <arg>FORMATS</arg> is specified as a semi-colon (;) separated list of formats in the form
+ 'encoding[, key1=value1, key2=value2, ...]' (for example, AC3 at 32000, 44100 and 48000 Hz would be specified as
+ 'ac3-iec61937, format.rate = "[ 32000, 44100, 48000 ]"').
+ </p></optdesc> </option>
+
+ <option>
<p><opt>subscribe</opt></p>
<optdesc><p>Subscribe to events, pactl does not exit by itself, but keeps waiting for new events.</p></optdesc>
</option>
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 2c5be93..947c6e9 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -36,6 +36,7 @@
#include <sndfile.h>
#include <pulse/pulseaudio.h>
+#include <pulse/ext-device-restore.h>
#include <pulsecore/i18n.h>
#include <pulsecore/macro.h>
@@ -55,11 +56,13 @@ static char
*module_args = NULL,
*card_name = NULL,
*profile_name = NULL,
- *port_name = NULL;
+ *port_name = NULL,
+ *formats = NULL;
static uint32_t
sink_input_idx = PA_INVALID_INDEX,
- source_output_idx = PA_INVALID_INDEX;
+ source_output_idx = PA_INVALID_INDEX,
+ sink_idx = PA_INVALID_INDEX;
static pa_bool_t short_list_format = FALSE;
static uint32_t module_index;
@@ -111,6 +114,7 @@ static enum {
SET_SINK_MUTE,
SET_SOURCE_MUTE,
SET_SINK_INPUT_MUTE,
+ SET_SINK_FORMATS,
SUBSCRIBE
} action = NONE;
@@ -882,6 +886,44 @@ static void get_source_output_volume_callback(pa_context *c, const pa_source_out
pa_operation_unref(pa_context_set_source_output_volume(c, source_output_idx, &cv, simple_callback, NULL));
}
+/* PA_MAX_FORMATS is defined in internal.h so we just define a sane value here */
+#define MAX_FORMATS 256
+
+static void set_sink_formats(pa_context *c, uint32_t sink, const char *str) {
+ pa_format_info *f_arr[MAX_FORMATS];
+ char *format = NULL;
+ const char *state = NULL;
+ int i = 0;
+
+ while ((format = pa_split(str, ";", &state))) {
+ pa_format_info *f = pa_format_info_from_string(pa_strip(format));
+
+ if (!f) {
+ pa_log(_("Failed to set format: invalid format string %s"), format);
+ goto error;
+ }
+
+ f_arr[i++] = f;
+ pa_xfree(format);
+ }
+
+ pa_operation_unref(pa_ext_device_restore_save_sink_formats(c, sink, i, f_arr, simple_callback, NULL));
+
+done:
+ if (format)
+ pa_xfree(format);
+ while(i--)
+ pa_format_info_free(f_arr[i]);
+
+ return;
+
+error:
+ while(i--)
+ pa_format_info_free(f_arr[i]);
+ quit(1);
+ goto done;
+}
+
static void stream_state_callback(pa_stream *s, void *userdata) {
pa_assert(s);
@@ -1157,6 +1199,10 @@ static void context_state_callback(pa_context *c, void *userdata) {
}
break;
+ case SET_SINK_FORMATS:
+ set_sink_formats(c, sink_idx, formats);
+ break;
+
case SUBSCRIBE:
pa_context_set_subscribe_callback(c, context_subscribe_callback, NULL);
@@ -1270,6 +1316,7 @@ static void help(const char *argv0) {
printf("%s %s %s %s\n", argv0, _("[options]"), "set-(sink-input|source-output)-volume", _("#N VOLUME"));
printf("%s %s %s %s\n", argv0, _("[options]"), "set-(sink|source)-mute", _("NAME|#N 1|0"));
printf("%s %s %s %s\n", argv0, _("[options]"), "set-sink-input-mute", _("#N 1|0"));
+ printf("%s %s %s %s\n", argv0, _("[options]"), "set-sink-formats", _("#N FORMATS"));
printf("%s %s %s\n", argv0, _("[options]"), "subscribe");
printf(_("\n"
@@ -1662,7 +1709,19 @@ int main(int argc, char *argv[]) {
action = SUBSCRIBE;
- else if (pa_streq(argv[optind], "help")) {
+ else if (pa_streq(argv[optind], "set-sink-formats")) {
+ int32_t tmp;
+
+ if (argc != optind+3 || pa_atoi(argv[optind+1], &tmp) < 0) {
+ pa_log(_("You have to specify a sink index and a semicolon-separated list of supported formats"));
+ goto quit;
+ }
+
+ sink_idx = tmp;
+ action = SET_SINK_FORMATS;
+ formats = pa_xstrdup(argv[optind+2]);
+
+ } else if (pa_streq(argv[optind], "help")) {
help(bn);
ret = 0;
goto quit;
@@ -1723,6 +1782,7 @@ quit:
pa_xfree(card_name);
pa_xfree(profile_name);
pa_xfree(port_name);
+ pa_xfree(formats);
if (sndfile)
sf_close(sndfile);
commit 8bffbcde1b9ac41703be9c242f4f9f172d5649bb
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Fri Aug 12 21:55:48 2011 +0530
format: Add string to pa_format_info conversion function
This will help accept string formats from the command like (so we can
set formats using pactl).
diff --git a/src/pulse/format.c b/src/pulse/format.c
index 112b103..f4eed83 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -41,20 +41,30 @@
static int pa_format_info_prop_compatible(const char *one, const char *two);
-const char *pa_encoding_to_string(pa_encoding_t e) {
- static const char* const table[]= {
- [PA_ENCODING_PCM] = "pcm",
- [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
- [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
- [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
- [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
- [PA_ENCODING_ANY] = "any",
- };
+static const char* const _encoding_str_table[]= {
+ [PA_ENCODING_PCM] = "pcm",
+ [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
+ [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
+ [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
+ [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
+ [PA_ENCODING_ANY] = "any",
+};
+const char *pa_encoding_to_string(pa_encoding_t e) {
if (e < 0 || e >= PA_ENCODING_MAX)
return NULL;
- return table[e];
+ return _encoding_str_table[e];
+}
+
+pa_encoding_t pa_encoding_from_string(const char *encoding) {
+ pa_encoding_t e;
+
+ for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
+ if (pa_streq(_encoding_str_table[e], encoding))
+ return e;
+
+ return PA_ENCODING_INVALID;
}
pa_format_info* pa_format_info_new(void) {
@@ -125,6 +135,44 @@ char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
return s;
}
+pa_format_info* pa_format_info_from_string(const char *str) {
+ pa_format_info *f = pa_format_info_new();
+ char *encoding = NULL, *properties = NULL;
+ size_t pos;
+
+ pos = strcspn(str, ",");
+
+ encoding = pa_xstrndup(str, pos);
+ f->encoding = pa_encoding_from_string(pa_strip(encoding));
+ if (f->encoding == PA_ENCODING_INVALID)
+ goto error;
+
+ if (pos != strlen(str)) {
+ pa_proplist *plist;
+
+ properties = pa_xstrdup(&str[pos+1]);
+ plist = pa_proplist_from_string(properties);
+
+ if (!plist)
+ goto error;
+
+ pa_proplist_free(f->plist);
+ f->plist = plist;
+ }
+
+out:
+ if (encoding)
+ pa_xfree(encoding);
+ if (properties)
+ pa_xfree(properties);
+ return f;
+
+error:
+ pa_format_info_free(f);
+ f = NULL;
+ goto out;
+}
+
int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
const char *key;
void *state = NULL;
diff --git a/src/pulse/format.h b/src/pulse/format.h
index 821149c..b8b829e 100644
--- a/src/pulse/format.h
+++ b/src/pulse/format.h
@@ -62,6 +62,9 @@ typedef enum pa_encoding {
/** Returns a printable string representing the given encoding type. \since 1.0 */
const char *pa_encoding_to_string(pa_encoding_t e) PA_GCC_CONST;
+/** Converts a string of the form returned by \a pa_encoding_to_string() back to a \a pa_encoding_t. \since 1.0 */
+pa_encoding_t pa_encoding_from_string(const char *encoding);
+
/**< Represents the format of data provided in a stream or processed by a sink. \since 1.0 */
typedef struct pa_format_info {
pa_encoding_t encoding;
@@ -105,6 +108,10 @@ int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second);
/** Return a human-readable string representing the given format. \since 1.0 */
char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f);
+/** Parse a human-readable string of the form generated by
+ * \a pa_format_info_snprint() into a pa_format_info structure. \since 1.0 */
+pa_format_info* pa_format_info_from_string(const char *str);
+
/** Sets an integer property on the given format info */
void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value);
/** Sets a property with a list of integer values on the given format info */
commit 348c51bfcdfa58bc99e44329b3aa1067adc0e920
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Fri Aug 12 21:04:38 2011 +0530
format: Make pa_format_info_snprint() more parseable
Removes the comma as the proplist separator since that makes
pa_proplist_from_string() break and prints only the encoding if there
are no properties (instead of "<encoding>, (no properties)").
diff --git a/src/pulse/format.c b/src/pulse/format.c
index 81c329f..112b103 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -114,8 +114,11 @@ char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
if (!pa_format_info_valid(f))
pa_snprintf(s, l, _("(invalid)"));
else {
- tmp = pa_proplist_to_string_sep(f->plist, ", ");
- pa_snprintf(s, l, _("%s, %s"), pa_encoding_to_string(f->encoding), tmp[0] ? tmp : _("(no properties)"));
+ tmp = pa_proplist_to_string_sep(f->plist, " ");
+ if (tmp[0])
+ pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
+ else
+ pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
pa_xfree(tmp);
}
commit 248394c8bfdaea5b57e2e68df89bebb498b22601
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Fri Aug 12 20:27:34 2011 +0530
device-restore: Set sink format when possible
This implements the actual setting of sink formats when a new sink is
added or when the set of available formats changes.
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 9441813..671ffd4 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -63,7 +63,8 @@ PA_MODULE_LOAD_ONCE(TRUE);
PA_MODULE_USAGE(
"restore_port=<Save/restore port?> "
"restore_volume=<Save/restore volumes?> "
- "restore_muted=<Save/restore muted states?>");
+ "restore_muted=<Save/restore muted states?> "
+ "restore_formats=<Save/restore saved formats?>");
#define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
@@ -71,6 +72,7 @@ static const char* const valid_modargs[] = {
"restore_volume",
"restore_muted",
"restore_port",
+ "restore_formats",
NULL
};
@@ -81,6 +83,7 @@ struct userdata {
pa_hook_slot
*sink_new_hook_slot,
*sink_fixate_hook_slot,
+ *sink_put_hook_slot,
*source_new_hook_slot,
*source_fixate_hook_slot,
*connection_unlink_hook_slot;
@@ -93,6 +96,7 @@ struct userdata {
pa_bool_t restore_volume;
pa_bool_t restore_muted;
pa_bool_t restore_port;
+ pa_bool_t restore_formats;
};
/* Protocol extention commands */
@@ -590,6 +594,30 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
return PA_HOOK_OK;
}
+static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
+ char *name;
+ struct entry *e;
+
+ pa_assert(c);
+ pa_assert(sink);
+ pa_assert(u);
+ pa_assert(u->restore_formats);
+
+ name = pa_sprintf_malloc("sink:%s", sink->name);
+
+ if ((e = entry_read(u, name))) {
+
+ if (!pa_sink_set_formats(sink, e->formats))
+ pa_log_debug("Could not set format on sink %s", sink->name);
+
+ entry_free(e);
+ }
+
+ pa_xfree(name);
+
+ return PA_HOOK_OK;
+}
+
static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
char *name;
struct entry *e;
@@ -828,7 +856,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
goto fail;
}
- if (entry_write(u, name, e))
+ if (pa_sink_set_formats(sink, e->formats) && entry_write(u, name, e))
trigger_save(u, sink_index);
else
pa_log_warn("Could not save format info for sink %s", sink->name);
@@ -870,7 +898,7 @@ int pa__init(pa_module*m) {
pa_sink *sink;
pa_source *source;
uint32_t idx;
- pa_bool_t restore_volume = TRUE, restore_muted = TRUE, restore_port = TRUE;
+ pa_bool_t restore_volume = TRUE, restore_muted = TRUE, restore_port = TRUE, restore_formats = TRUE;
pa_assert(m);
@@ -881,12 +909,13 @@ int pa__init(pa_module*m) {
if (pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
- pa_modargs_get_value_boolean(ma, "restore_port", &restore_port) < 0) {
- pa_log("restore_port=, restore_volume= and restore_muted= expect boolean arguments");
+ pa_modargs_get_value_boolean(ma, "restore_port", &restore_port) < 0 ||
+ pa_modargs_get_value_boolean(ma, "restore_formats", &restore_formats) < 0) {
+ pa_log("restore_port, restore_volume, restore_muted and restore_formats expect boolean arguments");
goto fail;
}
- if (!restore_muted && !restore_volume && !restore_port)
+ if (!restore_muted && !restore_volume && !restore_port && !restore_formats)
pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring port enabled!");
m->userdata = u = pa_xnew0(struct userdata, 1);
@@ -895,6 +924,7 @@ int pa__init(pa_module*m) {
u->restore_volume = restore_volume;
u->restore_muted = restore_muted;
u->restore_port = restore_port;
+ u->restore_formats = restore_formats;
u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
@@ -915,6 +945,9 @@ int pa__init(pa_module*m) {
u->source_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_fixate_hook_callback, u);
}
+ if (restore_formats)
+ u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_EARLY, (pa_hook_cb_t) sink_put_hook_callback, u);
+
if (!(fname = pa_state_path("device-volumes", TRUE)))
goto fail;
@@ -964,6 +997,8 @@ void pa__done(pa_module*m) {
pa_hook_slot_free(u->sink_new_hook_slot);
if (u->source_new_hook_slot)
pa_hook_slot_free(u->source_new_hook_slot);
+ if (u->sink_put_hook_slot)
+ pa_hook_slot_free(u->sink_put_hook_slot);
if (u->connection_unlink_hook_slot)
pa_hook_slot_free(u->connection_unlink_hook_slot);
commit ba163b8b23bcd72c35b028eb0b43c31a6ae1724d
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Fri Aug 12 19:33:41 2011 +0530
device-restore: Make bools not be bit fields
This makes the pa_bool_t members of userdata not be a single bit field
since pa_bool_t can be an int, potentially causing signedness issues in
comparisons.
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 75b1e40..9441813 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -90,9 +90,9 @@ struct userdata {
pa_native_protocol *protocol;
pa_idxset *subscribed;
- pa_bool_t restore_volume:1;
- pa_bool_t restore_muted:1;
- pa_bool_t restore_port:1;
+ pa_bool_t restore_volume;
+ pa_bool_t restore_muted;
+ pa_bool_t restore_port;
};
/* Protocol extention commands */
commit 51fcee89029063998913d1ccab7df54134d72b8d
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Fri Aug 12 16:36:00 2011 +0530
alsa: Implement get/set_formats()
This implements the sink get_formats() and set_formats() API in
alsa-sink. Modules can use this to allow users to specify what formats
their receivers support.
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index c4aa75b..44331a3 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -36,6 +36,7 @@
#include <pulse/timeval.h>
#include <pulse/volume.h>
#include <pulse/xmalloc.h>
+#include <pulse/internal.h>
#include <pulsecore/core.h>
#include <pulsecore/i18n.h>
@@ -144,6 +145,8 @@ struct userdata {
pa_usec_t smoother_interval;
pa_usec_t last_smoother_update;
+ pa_idxset *formats;
+
pa_reserve_wrapper *reserve;
pa_hook_slot *reserve_slot;
pa_reserve_monitor_wrapper *monitor;
@@ -152,6 +155,15 @@ struct userdata {
static void userdata_free(struct userdata *u);
+/* FIXME: Is there a better way to do this than device names? */
+static pa_bool_t is_iec958(struct userdata *u) {
+ return (strncmp("iec958", u->device_name, 6) == 0);
+}
+
+static pa_bool_t is_hdmi(struct userdata *u) {
+ return (strncmp("hdmi", u->device_name, 4) == 0);
+}
+
static pa_hook_result_t reserve_cb(pa_reserve_wrapper *r, void *forced, struct userdata *u) {
pa_assert(r);
pa_assert(u);
@@ -1475,6 +1487,45 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
}
}
+static pa_idxset* sink_get_formats(pa_sink *s) {
+ struct userdata *u = s->userdata;
+ pa_idxset *ret = pa_idxset_new(NULL, NULL);
+ pa_format_info *f;
+ uint32_t idx;
+
+ pa_assert(u);
+
+ PA_IDXSET_FOREACH(f, u->formats, idx) {
+ pa_idxset_put(ret, pa_format_info_copy(f), NULL);
+ }
+
+ return ret;
+}
+
+static pa_bool_t sink_set_formats(pa_sink *s, pa_idxset *formats) {
+ struct userdata *u = s->userdata;
+ pa_format_info *f;
+ uint32_t idx;
+
+ pa_assert(u);
+
+ /* FIXME: also validate sample rates against what the device supports */
+ PA_IDXSET_FOREACH(f, formats, idx) {
+ if (is_iec958(u) && f->encoding == PA_ENCODING_EAC3_IEC61937)
+ /* EAC3 cannot be sent over over S/PDIF */
+ return FALSE;
+ }
+
+ pa_idxset_free(u->formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
+ u->formats = pa_idxset_new(NULL, NULL);
+
+ PA_IDXSET_FOREACH(f, formats, idx) {
+ pa_idxset_put(u->formats, pa_format_info_copy(f), NULL);
+ }
+
+ return TRUE;
+}
+
static int process_rewind(struct userdata *u) {
snd_pcm_sframes_t unused;
size_t rewind_nbytes, unused_nbytes, limit_nbytes;
@@ -2182,6 +2233,21 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
if ((data.volume_is_set || data.muted_is_set) && u->sink->write_volume)
u->sink->write_volume(u->sink);
+ if (is_iec958(u) || is_hdmi(u)) {
+ /* For S/PDIF and HDMI, allow getting/setting custom formats */
+ pa_format_info *format;
+
+ /* To start with, we only support PCM formats. Other formats may be added
+ * with pa_sink_set_formats().*/
+ format = pa_format_info_new();
+ format->encoding = PA_ENCODING_PCM;
+ u->formats = pa_idxset_new(NULL, NULL);
+ pa_idxset_put(u->formats, format, NULL);
+
+ u->sink->get_formats = sink_get_formats;
+ u->sink->set_formats = sink_set_formats;
+ }
+
pa_sink_put(u->sink);
if (profile_set)
@@ -2247,6 +2313,9 @@ static void userdata_free(struct userdata *u) {
if (u->smoother)
pa_smoother_free(u->smoother);
+ if (u->formats)
+ pa_idxset_free(u->formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
+
reserve_done(u);
monitor_done(u);
commit 485d4dd54260b680b0e5d0af35ad380280a4c826
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date: Fri Aug 12 16:34:28 2011 +0530
sink: Add a set_formats() API
This adds API to let external sources specify what formats a sink
supports. Sinks must opt-in to allow this, and can perform some
validation if required.
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 42a8eb3..6277698 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -180,6 +180,7 @@ static void reset_callbacks(pa_sink *s) {
s->update_requested_latency = NULL;
s->set_port = NULL;
s->get_formats = NULL;
+ s->set_formats = NULL;
}
/* Called from main context */
@@ -3429,6 +3430,21 @@ pa_idxset* pa_sink_get_formats(pa_sink *s) {
}
/* Called from the main thread */
+/* Allows an external source to set what formats a sink supports if the sink
+ * permits this. The function makes a copy of the formats on success. */
+pa_bool_t pa_sink_set_formats(pa_sink *s, pa_idxset *formats) {
+ pa_assert(s);
+ pa_assert(formats);
+
+ if (s->set_formats)
+ /* Sink supports setting formats -- let's give it a shot */
+ return s->set_formats(s, formats);
+ else
+ /* Sink doesn't support setting this -- bail out */
+ return FALSE;
+}
+
+/* Called from the main thread */
/* Checks if the sink can accept this format */
pa_bool_t pa_sink_check_format(pa_sink *s, pa_format_info *f)
{
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 8aa04b8..0bd5e81 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -223,6 +223,12 @@ struct pa_sink {
* in descending order of preference. */
pa_idxset* (*get_formats)(pa_sink *s); /* ditto */
+ /* Called to set the list of formats supported by the sink. Can be
+ * NULL if the sink does not support this. Returns TRUE on success,
+ * FALSE otherwise (for example when an unsupportable format is
+ * set). Makes a copy of the formats passed in. */
+ pa_bool_t (*set_formats)(pa_sink *s, pa_idxset *formats); /* ditto */
+
/* Contains copies of the above data so that the real-time worker
* thread can work without access locking */
struct {
@@ -434,6 +440,7 @@ void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save);
void pa_sink_move_all_fail(pa_queue *q);
pa_idxset* pa_sink_get_formats(pa_sink *s);
+pa_bool_t pa_sink_set_formats(pa_sink *s, pa_idxset *formats);
pa_bool_t pa_sink_check_format(pa_sink *s, pa_format_info *f);
pa_idxset* pa_sink_check_formats(pa_sink *s, pa_idxset *in_formats);
More information about the pulseaudio-commits
mailing list