[pulseaudio-commits] 8 commits - src/map-file src/pulse src/pulsecore src/tests

Arun Raghavan arun at kemper.freedesktop.org
Mon Mar 5 07:07:39 PST 2012


 src/map-file                  |    8 -
 src/pulse/format.c            |  310 ++++++++++++++++++++++++++++++++++++------
 src/pulse/format.h            |   54 +++++++
 src/pulse/internal.h          |    5 
 src/pulsecore/sink-input.c    |   13 -
 src/pulsecore/source-output.c |   13 -
 src/tests/format-test.c       |   47 ++++++
 7 files changed, 381 insertions(+), 69 deletions(-)

New commits:
commit a0706e7c84d8228f136e9d1c9894a5854cae7bde
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Mar 5 20:30:33 2012 +0530

    format: Allow format->sample spec conversion for compressed formats
    
    This allows clients to get a "fake" sample space for compressed formats
    that we can support. This should make size/time conversion for things
    like calculating buffer attributes simpler.

diff --git a/src/map-file b/src/map-file
index 5730fdf..69cf25b 100644
--- a/src/map-file
+++ b/src/map-file
@@ -189,7 +189,6 @@ pa_format_info_set_rate;
 pa_format_info_set_sample_format;
 pa_format_info_snprint;
 pa_format_info_to_sample_spec;
-pa_format_info_to_sample_spec_fake;
 pa_format_info_valid;
 pa_frame_size;
 pa_get_binary_name;
diff --git a/src/pulse/format.c b/src/pulse/format.c
index f6965c6..542d119 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -218,6 +218,28 @@ pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_m
     return f;
 }
 
+/* For compressed streams */
+static int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
+    int rate;
+
+    pa_assert(f);
+    pa_assert(ss);
+
+    /* Note: When we add support for non-IEC61937 encapsulated compressed
+     * formats, this function should return a non-zero values for these. */
+
+    ss->format = PA_SAMPLE_S16LE;
+    ss->channels = 2;
+
+    pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
+    ss->rate = (uint32_t) rate;
+
+    if (f->encoding == PA_ENCODING_EAC3_IEC61937)
+        ss->rate *= 4;
+
+    return 0;
+}
+
 /* For PCM streams */
 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
     char *sf = NULL, *m = NULL;
@@ -226,7 +248,9 @@ int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_chan
 
     pa_assert(f);
     pa_assert(ss);
-    pa_return_val_if_fail(f->encoding == PA_ENCODING_PCM, FALSE);
+
+    if (!pa_format_info_is_pcm(f))
+        return pa_format_info_to_sample_spec_fake(f, ss);
 
     if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
         goto out;
@@ -260,26 +284,6 @@ out:
     return ret;
 }
 
-/* For compressed streams */
-int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
-    int rate;
-
-    pa_assert(f);
-    pa_assert(ss);
-    pa_return_val_if_fail(f->encoding != PA_ENCODING_PCM, -PA_ERR_INVALID);
-
-    ss->format = PA_SAMPLE_S16LE;
-    ss->channels = 2;
-
-    pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
-    ss->rate = (uint32_t) rate;
-
-    if (f->encoding == PA_ENCODING_EAC3_IEC61937)
-        ss->rate *= 4;
-
-    return 0;
-}
-
 pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
     const char *str;
     json_object *o, *o1;
diff --git a/src/pulse/format.h b/src/pulse/format.h
index 643a099..4694773 100644
--- a/src/pulse/format.h
+++ b/src/pulse/format.h
@@ -118,8 +118,11 @@ pa_format_info* pa_format_info_from_string(const char *str);
 /** Utility function to take a \a pa_sample_spec and generate the corresponding \a pa_format_info. \since 2.0 */
 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map);
 
-/** Utility function to generate a \a pa_sample_spec and \a pa_channel_map corresponding to a given \a pa_format_info. Returns
- * a negative integer if conversion failed and 0 on success. \since 2.0 */
+/** Utility function to generate a \a pa_sample_spec and \a pa_channel_map corresponding to a given \a pa_format_info. The
+ * conversion for PCM formats is straight-forward. For non-PCM formats, if there is a fixed size-time conversion (i.e. all
+ * IEC61937-encapsulated formats), a "fake" sample spec whose size-time conversion corresponds to this format is provided and
+ * the channel map argument is ignored. For formats with variable size-time conversion, this function will fail. Returns a
+ * negative integer if conversion failed and 0 on success. \since 2.0 */
 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map);
 
 /** Represents the type of value type of a property on a \ref pa_format_info. \since 2.0 */
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index e826454..c5bdcb1 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -304,7 +304,6 @@ void pa_ext_device_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t)
 void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t);
 
 void pa_format_info_free2(pa_format_info *f, void *userdata);
-int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss);
 
 pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m);
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 1e7d3e5..b8412bd 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -292,15 +292,10 @@ int pa_sink_input_new(
 
     /* Now populate the sample spec and format according to the final
      * format that we've negotiated */
-    if (PA_LIKELY(data->format->encoding == PA_ENCODING_PCM)) {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map) == 0, -PA_ERR_INVALID);
-        pa_sink_input_new_data_set_sample_spec(data, &ss);
-        if (pa_channel_map_valid(&map))
-            pa_sink_input_new_data_set_channel_map(data, &map);
-    } else {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss) == 0, -PA_ERR_INVALID);
-        pa_sink_input_new_data_set_sample_spec(data, &ss);
-    }
+    pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map) == 0, -PA_ERR_INVALID);
+    pa_sink_input_new_data_set_sample_spec(data, &ss);
+    if (pa_format_info_is_pcm(data->format) && pa_channel_map_valid(&map))
+        pa_sink_input_new_data_set_channel_map(data, &map);
 
     pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
     pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED), -PA_ERR_INVALID);
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 0859ba1..fbfea9c 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -272,15 +272,10 @@ int pa_source_output_new(
 
     /* Now populate the sample spec and format according to the final
      * format that we've negotiated */
-    if (PA_LIKELY(data->format->encoding == PA_ENCODING_PCM)) {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map) == 0, -PA_ERR_INVALID);
-        pa_source_output_new_data_set_sample_spec(data, &ss);
-        if (pa_channel_map_valid(&map))
-            pa_source_output_new_data_set_channel_map(data, &map);
-    } else {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss) == 0, -PA_ERR_INVALID);
-        pa_source_output_new_data_set_sample_spec(data, &ss);
-    }
+    pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map) == 0, -PA_ERR_INVALID);
+    pa_source_output_new_data_set_sample_spec(data, &ss);
+    if (pa_format_info_is_pcm(data->format) && pa_channel_map_valid(&map))
+        pa_source_output_new_data_set_channel_map(data, &map);
 
     pa_return_val_if_fail(PA_SOURCE_IS_LINKED(pa_source_get_state(data->source)), -PA_ERR_BADSTATE);
     pa_return_val_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of, -PA_ERR_INVALID);

commit 8baf8e90c2c6b8b1cb63658e7d46d770bb86560b
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Feb 6 17:17:34 2012 +0530

    format: Add API to query a property's type
    
    Since a given property can be single-valued, an array or (in the case of
    ints) a range, clients need an API to figure out what type of value a
    property holds. This adds such an API. The actual property type
    enumeration is kept in the PA_PROP_* namespace and not the
    PA_FORMAT_INFO* namespace so that it can later be reused for properties
    generically if required.

diff --git a/src/map-file b/src/map-file
index ee3d31d..5730fdf 100644
--- a/src/map-file
+++ b/src/map-file
@@ -168,6 +168,7 @@ pa_format_info_free;
 pa_format_info_free2;
 pa_format_info_from_string;
 pa_format_info_from_sample_spec;
+pa_format_info_get_prop_type;
 pa_format_info_get_prop_int;
 pa_format_info_get_prop_int_range;
 pa_format_info_get_prop_int_array;
diff --git a/src/pulse/format.c b/src/pulse/format.c
index 6176846..f6965c6 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -280,6 +280,80 @@ int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
     return 0;
 }
 
+pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
+    const char *str;
+    json_object *o, *o1;
+    pa_prop_type_t type;
+
+    pa_assert(f);
+    pa_assert(key);
+
+    str = pa_proplist_gets(f->plist, key);
+    if (!str)
+        return PA_PROP_TYPE_INVALID;
+
+    o = json_tokener_parse(str);
+    if (is_error(o))
+        return PA_PROP_TYPE_INVALID;
+
+    switch (json_object_get_type(o)) {
+        case json_type_int:
+            type = PA_PROP_TYPE_INT;
+            break;
+
+        case json_type_string:
+            type = PA_PROP_TYPE_STRING;
+            break;
+
+        case json_type_array:
+            if (json_object_array_length(o) == 0) {
+                /* Unlikely, but let's account for this anyway. We need at
+                 * least one element to figure out the array type. */
+                type = PA_PROP_TYPE_INVALID;
+                break;
+            }
+
+            o1 = json_object_array_get_idx(o, 1);
+
+            if (json_object_get_type(o1) == json_type_int)
+                type = PA_PROP_TYPE_INT_ARRAY;
+            else if (json_object_get_type(o1) == json_type_string)
+                type = PA_PROP_TYPE_STRING_ARRAY;
+            else
+                type = PA_PROP_TYPE_INVALID;
+
+            json_object_put(o1);
+            break;
+
+        case json_type_object:
+            /* We actually know at this point that it's a int range, but let's
+             * confirm. */
+            o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
+            if (!o1) {
+                type = PA_PROP_TYPE_INVALID;
+                break;
+            }
+            json_object_put(o1);
+
+            o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
+            if (!o1) {
+                type = PA_PROP_TYPE_INVALID;
+                break;
+            }
+            json_object_put(o1);
+
+            type = PA_PROP_TYPE_INT_RANGE;
+            break;
+
+        default:
+            type = PA_PROP_TYPE_INVALID;
+            break;
+    }
+
+    json_object_put(o);
+    return type;
+}
+
 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
     const char *str;
     json_object *o;
diff --git a/src/pulse/format.h b/src/pulse/format.h
index 5f71044..643a099 100644
--- a/src/pulse/format.h
+++ b/src/pulse/format.h
@@ -122,6 +122,30 @@ pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_m
  * a negative integer if conversion failed and 0 on success. \since 2.0 */
 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map);
 
+/** Represents the type of value type of a property on a \ref pa_format_info. \since 2.0 */
+typedef enum pa_prop_type_t {
+    PA_PROP_TYPE_INT,
+    /**< Integer property */
+
+    PA_PROP_TYPE_INT_RANGE,
+    /**< Integer range property */
+
+    PA_PROP_TYPE_INT_ARRAY,
+    /**< Integer array property */
+
+    PA_PROP_TYPE_STRING,
+    /**< String property */
+
+    PA_PROP_TYPE_STRING_ARRAY,
+    /**< String array property */
+
+    PA_PROP_TYPE_INVALID = -1,
+    /**< Represents an invalid type */
+} pa_prop_type_t;
+
+/** Gets the type of property \a key in a given \ref pa_format_info. \since 2.0 */
+pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key);
+
 /** Gets an integer property from the given format info. Returns 0 on success and a negative integer on failure. \since 2.0 */
 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v);
 /** Gets an integer range property from the given format info. Returns 0 on success and a negative integer on failure.
diff --git a/src/tests/format-test.c b/src/tests/format-test.c
index 1a3aade..bb66c85 100644
--- a/src/tests/format-test.c
+++ b/src/tests/format-test.c
@@ -105,18 +105,21 @@ int main(int argc, char *argv[]) {
     /* 9. Verify setting/getting an int */
     REINIT(f1);
     pa_format_info_set_prop_int(f1, "format.test_string", 42);
+    pa_assert(pa_format_info_get_prop_type(f1, "format.test_string") == PA_PROP_TYPE_INT);
     pa_assert(pa_format_info_get_prop_int(f1, "format.test_string", &temp_int1) == 0);
     pa_assert(temp_int1 == 42);
 
     /* 10. Verify setting/getting an int range */
     REINIT(f1);
     pa_format_info_set_prop_int_range(f1, "format.test_string", 0, 100);
+    pa_assert(pa_format_info_get_prop_type(f1, "format.test_string") == PA_PROP_TYPE_INT_RANGE);
     pa_assert(pa_format_info_get_prop_int_range(f1, "format.test_string", &temp_int1, &temp_int2) == 0);
     pa_assert(temp_int1 == 0 && temp_int2 == 100);
 
     /* 11. Verify setting/getting an int array */
     REINIT(f1);
     pa_format_info_set_prop_int_array(f1, "format.test_string", rates1, PA_ELEMENTSOF(rates1));
+    pa_assert(pa_format_info_get_prop_type(f1, "format.test_string") == PA_PROP_TYPE_INT_ARRAY);
     pa_assert(pa_format_info_get_prop_int_array(f1, "format.test_string", &temp_int_array, &temp_int1) == 0);
     pa_assert(temp_int1 == PA_ELEMENTSOF(rates1));
     for (i = 0; i < temp_int1; i++)
@@ -126,6 +129,7 @@ int main(int argc, char *argv[]) {
     /* 12. Verify setting/getting a string */
     REINIT(f1);
     pa_format_info_set_prop_string(f1, "format.test_string", "foo");
+    pa_assert(pa_format_info_get_prop_type(f1, "format.test_string") == PA_PROP_TYPE_STRING);
     pa_assert(pa_format_info_get_prop_string(f1, "format.test_string", &temp_str) == 0);
     pa_assert(pa_streq(temp_str, "foo"));
     pa_xfree(temp_str);
@@ -133,6 +137,7 @@ int main(int argc, char *argv[]) {
     /* 13. Verify setting/getting an int array */
     REINIT(f1);
     pa_format_info_set_prop_string_array(f1, "format.test_string", strings, PA_ELEMENTSOF(strings));
+    pa_assert(pa_format_info_get_prop_type(f1, "format.test_string") == PA_PROP_TYPE_STRING_ARRAY);
     pa_assert(pa_format_info_get_prop_string_array(f1, "format.test_string", &temp_str_array, &temp_int1) == 0);
     pa_assert(temp_int1 == PA_ELEMENTSOF(strings));
     for (i = 0; i < temp_int1; i++)

commit 8f850403c0a1184fd0c77166172ec02b565bb58e
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Feb 6 16:34:53 2012 +0530

    format: Trivial reorganisation
    
    Moves all the property setters together

diff --git a/src/pulse/format.c b/src/pulse/format.c
index c0a96db..6176846 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -280,26 +280,6 @@ int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
     return 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));
-}
-
-void pa_format_info_set_rate(pa_format_info *f, int rate) {
-    pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
-}
-
-void pa_format_info_set_channels(pa_format_info *f, int channels) {
-    pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
-}
-
-void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
-    char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
-
-    pa_channel_map_snprint(map_str, sizeof(map_str), map);
-
-    pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
-}
-
 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
     const char *str;
     json_object *o;
@@ -491,6 +471,26 @@ void pa_format_info_free_string_array(char **values, int n_values) {
     pa_xfree(values);
 }
 
+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));
+}
+
+void pa_format_info_set_rate(pa_format_info *f, int rate) {
+    pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
+}
+
+void pa_format_info_set_channels(pa_format_info *f, int channels) {
+    pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
+}
+
+void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
+    char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
+
+    pa_channel_map_snprint(map_str, sizeof(map_str), map);
+
+    pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
+}
+
 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
     json_object *o;
 

commit d9cdaffefe1ca8ce6321e5caa87fdd6e71a64cc7
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Tue Feb 7 13:10:59 2012 +0530

    format: Update map-file
    
    Adding property getters manually for now.

diff --git a/src/map-file b/src/map-file
index c98ac72..ee3d31d 100644
--- a/src/map-file
+++ b/src/map-file
@@ -168,6 +168,12 @@ pa_format_info_free;
 pa_format_info_free2;
 pa_format_info_from_string;
 pa_format_info_from_sample_spec;
+pa_format_info_get_prop_int;
+pa_format_info_get_prop_int_range;
+pa_format_info_get_prop_int_array;
+pa_format_info_get_prop_string;
+pa_format_info_get_prop_string_array;
+pa_format_info_free_string_array;
 pa_format_info_is_compatible;
 pa_format_info_is_pcm;
 pa_format_info_new;

commit 59af940dd5990588ccfd593efab71c3007ea632e
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Feb 6 16:18:49 2012 +0530

    format: Add more property getters
    
    This adds integer range/array and string array property getters to the
    pa_format_info API. Corresponding tests added as well to ensure the code
    is valgrind-clean.
    
    The corresponding functions are added to map-file manually for now.

diff --git a/src/pulse/format.c b/src/pulse/format.c
index 6e8e707..c0a96db 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -327,6 +327,90 @@ int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
     return 0;
 }
 
+int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
+    const char *str;
+    json_object *o, *o1;
+    int ret = -PA_ERR_INVALID;
+
+    pa_assert(f);
+    pa_assert(key);
+    pa_assert(min);
+    pa_assert(max);
+
+    str = pa_proplist_gets(f->plist, key);
+    if (!str)
+        return -PA_ERR_NOENTITY;
+
+    o = json_tokener_parse(str);
+    if (is_error(o))
+        return -PA_ERR_INVALID;
+
+    if (json_object_get_type(o) != json_type_object)
+        goto out;
+
+    if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
+        goto out;
+
+    *min = json_object_get_int(o1);
+    json_object_put(o1);
+
+    if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
+        goto out;
+
+    *max = json_object_get_int(o1);
+    json_object_put(o1);
+
+    ret = 0;
+
+out:
+    json_object_put(o);
+    return ret;
+}
+
+int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values)
+{
+    const char *str;
+    json_object *o, *o1;
+    int i, ret = -PA_ERR_INVALID;
+
+    pa_assert(f);
+    pa_assert(key);
+    pa_assert(values);
+    pa_assert(n_values);
+
+    str = pa_proplist_gets(f->plist, key);
+    if (!str)
+        return -PA_ERR_NOENTITY;
+
+    o = json_tokener_parse(str);
+    if (is_error(o))
+        return -PA_ERR_INVALID;
+
+    if (json_object_get_type(o) != json_type_array)
+        goto out;
+
+    *n_values = json_object_array_length(o);
+    *values = pa_xnew(int, *n_values);
+
+    for (i = 0; i < *n_values; i++) {
+        o1 = json_object_array_get_idx(o, i);
+
+        if (json_object_get_type(o1) != json_type_int) {
+            json_object_put(o1);
+            goto out;
+        }
+
+        (*values)[i] = json_object_get_int(o1);
+        json_object_put(o1);
+    }
+
+    ret = 0;
+
+out:
+    json_object_put(o);
+    return ret;
+}
+
 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
     const char *str = NULL;
     json_object *o;
@@ -354,6 +438,59 @@ int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v)
     return 0;
 }
 
+int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values)
+{
+    const char *str;
+    json_object *o, *o1;
+    int i, ret = -PA_ERR_INVALID;
+
+    pa_assert(f);
+    pa_assert(key);
+    pa_assert(values);
+    pa_assert(n_values);
+
+    str = pa_proplist_gets(f->plist, key);
+    if (!str)
+        return -PA_ERR_NOENTITY;
+
+    o = json_tokener_parse(str);
+    if (is_error(o))
+        return -PA_ERR_INVALID;
+
+    if (json_object_get_type(o) != json_type_array)
+        goto out;
+
+    *n_values = json_object_array_length(o);
+    *values = pa_xnew(char *, *n_values);
+
+    for (i = 0; i < *n_values; i++) {
+        o1 = json_object_array_get_idx(o, i);
+
+        if (json_object_get_type(o1) != json_type_string) {
+            json_object_put(o1);
+            goto out;
+        }
+
+        (*values)[i] = pa_xstrdup(json_object_get_string(o1));
+        json_object_put(o1);
+    }
+
+    ret = 0;
+
+out:
+    json_object_put(o);
+    return ret;
+}
+
+void pa_format_info_free_string_array(char **values, int n_values) {
+    int i;
+
+    for (i = 0; i < n_values; i++)
+        pa_xfree(values[i]);
+
+    pa_xfree(values);
+}
+
 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
     json_object *o;
 
diff --git a/src/pulse/format.h b/src/pulse/format.h
index fd5727b..5f71044 100644
--- a/src/pulse/format.h
+++ b/src/pulse/format.h
@@ -124,9 +124,23 @@ int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_chan
 
 /** Gets an integer property from the given format info. Returns 0 on success and a negative integer on failure. \since 2.0 */
 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v);
+/** Gets an integer range property from the given format info. Returns 0 on success and a negative integer on failure.
+ * \since 2.0 */
+int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max);
+/** Gets an integer array property from the given format info. \a values contains the values and \a n_values contains the
+ * number of elements. The caller must free \a values using \ref pa_xfree. Returns 0 on success and a negative integer on
+ * failure. \since 2.0 */
+int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values);
 /** Gets a string property from the given format info.  The caller must free the returned string using \ref pa_xfree. Returns
  * 0 on success and a negative integer on failure. \since 2.0 */
 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v);
+/** Gets a string array property from the given format info. \a values contains the values and \a n_values contains
+ * the number of elements. The caller must free \a values using \ref pa_format_info_free_string_array. Returns 0 on success and
+ * a negative integer on failure. \since 2.0 */
+int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values);
+
+/** Frees a string array returned by \ref pa_format_info_get_prop_string_array. \since 2.0 */
+void pa_format_info_free_string_array(char **values, int n_values);
 
 /** Sets an integer property on the given format info. \since 1.0 */
 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value);
diff --git a/src/tests/format-test.c b/src/tests/format-test.c
index fc3a599..1a3aade 100644
--- a/src/tests/format-test.c
+++ b/src/tests/format-test.c
@@ -24,7 +24,9 @@
 #include <stdlib.h>
 
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 #include <pulse/format.h>
+#include <pulse/xmalloc.h>
 
 #define INIT(f) f = pa_format_info_new()
 #define DEINIT(f) pa_format_info_free(f);
@@ -32,8 +34,9 @@
 
 int main(int argc, char *argv[]) {
     pa_format_info *f1 = NULL, *f2 = NULL;
-    int rates1[] = { 32000, 44100, 48000 };
+    int rates1[] = { 32000, 44100, 48000 }, i, temp_int1 = -1, temp_int2 = -1, *temp_int_array;
     const char *strings[] = { "thing1", "thing2", "thing3" };
+    char *temp_str, **temp_str_array;
 
     /* 1. Simple fixed format int check */
     INIT(f1); INIT(f2);
@@ -99,6 +102,43 @@ int main(int argc, char *argv[]) {
     pa_assert(!pa_format_info_is_compatible(f1, f2));
     pa_assert(!pa_format_info_is_compatible(f2, f1));
 
+    /* 9. Verify setting/getting an int */
+    REINIT(f1);
+    pa_format_info_set_prop_int(f1, "format.test_string", 42);
+    pa_assert(pa_format_info_get_prop_int(f1, "format.test_string", &temp_int1) == 0);
+    pa_assert(temp_int1 == 42);
+
+    /* 10. Verify setting/getting an int range */
+    REINIT(f1);
+    pa_format_info_set_prop_int_range(f1, "format.test_string", 0, 100);
+    pa_assert(pa_format_info_get_prop_int_range(f1, "format.test_string", &temp_int1, &temp_int2) == 0);
+    pa_assert(temp_int1 == 0 && temp_int2 == 100);
+
+    /* 11. Verify setting/getting an int array */
+    REINIT(f1);
+    pa_format_info_set_prop_int_array(f1, "format.test_string", rates1, PA_ELEMENTSOF(rates1));
+    pa_assert(pa_format_info_get_prop_int_array(f1, "format.test_string", &temp_int_array, &temp_int1) == 0);
+    pa_assert(temp_int1 == PA_ELEMENTSOF(rates1));
+    for (i = 0; i < temp_int1; i++)
+        pa_assert(temp_int_array[i] == rates1[i]);
+    pa_xfree(temp_int_array);
+
+    /* 12. Verify setting/getting a string */
+    REINIT(f1);
+    pa_format_info_set_prop_string(f1, "format.test_string", "foo");
+    pa_assert(pa_format_info_get_prop_string(f1, "format.test_string", &temp_str) == 0);
+    pa_assert(pa_streq(temp_str, "foo"));
+    pa_xfree(temp_str);
+
+    /* 13. Verify setting/getting an int array */
+    REINIT(f1);
+    pa_format_info_set_prop_string_array(f1, "format.test_string", strings, PA_ELEMENTSOF(strings));
+    pa_assert(pa_format_info_get_prop_string_array(f1, "format.test_string", &temp_str_array, &temp_int1) == 0);
+    pa_assert(temp_int1 == PA_ELEMENTSOF(strings));
+    for (i = 0; i < temp_int1; i++)
+        pa_assert(pa_streq(temp_str_array[i], strings[i]));
+    pa_format_info_free_string_array(temp_str_array, temp_int1);
+
     DEINIT(f1);
     DEINIT(f2);
 

commit c60f698f1e1614309b0a568a20da840409adad2f
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Feb 6 11:34:47 2012 +0530

    format: Expose pa_format_info<->pa_sample_spec conversion functions
    
    These utility functions could be handy to clients.
    pa_format_info_to_sample_spec_fake() isn't made public, but the return
    value is changed to keep in sync with pa_format_info_to_sample_spec().

diff --git a/src/pulse/format.c b/src/pulse/format.c
index 4de6e89..6e8e707 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -219,10 +219,10 @@ pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_m
 }
 
 /* For PCM streams */
-pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
+int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
     char *sf = NULL, *m = NULL;
     int rate, channels;
-    pa_bool_t ret = FALSE;
+    int ret = -PA_ERR_INVALID;
 
     pa_assert(f);
     pa_assert(ss);
@@ -249,7 +249,7 @@ pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, p
                 goto out;
     }
 
-    ret = TRUE;
+    ret = 0;
 
 out:
     if (sf)
@@ -261,23 +261,23 @@ out:
 }
 
 /* For compressed streams */
-pa_bool_t pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
+int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
     int rate;
 
     pa_assert(f);
     pa_assert(ss);
-    pa_return_val_if_fail(f->encoding != PA_ENCODING_PCM, FALSE);
+    pa_return_val_if_fail(f->encoding != PA_ENCODING_PCM, -PA_ERR_INVALID);
 
     ss->format = PA_SAMPLE_S16LE;
     ss->channels = 2;
 
-    pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, FALSE);
+    pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
     ss->rate = (uint32_t) rate;
 
     if (f->encoding == PA_ENCODING_EAC3_IEC61937)
         ss->rate *= 4;
 
-    return TRUE;
+    return 0;
 }
 
 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
diff --git a/src/pulse/format.h b/src/pulse/format.h
index 2e19e70..fd5727b 100644
--- a/src/pulse/format.h
+++ b/src/pulse/format.h
@@ -115,6 +115,13 @@ char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f);
  * \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);
 
+/** Utility function to take a \a pa_sample_spec and generate the corresponding \a pa_format_info. \since 2.0 */
+pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map);
+
+/** Utility function to generate a \a pa_sample_spec and \a pa_channel_map corresponding to a given \a pa_format_info. Returns
+ * a negative integer if conversion failed and 0 on success. \since 2.0 */
+int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map);
+
 /** Gets an integer property from the given format info. Returns 0 on success and a negative integer on failure. \since 2.0 */
 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v);
 /** Gets a string property from the given format info.  The caller must free the returned string using \ref pa_xfree. Returns
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 7ab98b8..e826454 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -304,9 +304,7 @@ void pa_ext_device_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t)
 void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t);
 
 void pa_format_info_free2(pa_format_info *f, void *userdata);
-pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map);
-pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map);
-pa_bool_t pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss);
+int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss);
 
 pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m);
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 7f824fa..1e7d3e5 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -293,12 +293,12 @@ int pa_sink_input_new(
     /* Now populate the sample spec and format according to the final
      * format that we've negotiated */
     if (PA_LIKELY(data->format->encoding == PA_ENCODING_PCM)) {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map), -PA_ERR_INVALID);
+        pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map) == 0, -PA_ERR_INVALID);
         pa_sink_input_new_data_set_sample_spec(data, &ss);
         if (pa_channel_map_valid(&map))
             pa_sink_input_new_data_set_channel_map(data, &map);
     } else {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss), -PA_ERR_INVALID);
+        pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss) == 0, -PA_ERR_INVALID);
         pa_sink_input_new_data_set_sample_spec(data, &ss);
     }
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 2f38af5..0859ba1 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -273,12 +273,12 @@ int pa_source_output_new(
     /* Now populate the sample spec and format according to the final
      * format that we've negotiated */
     if (PA_LIKELY(data->format->encoding == PA_ENCODING_PCM)) {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map), -PA_ERR_INVALID);
+        pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map) == 0, -PA_ERR_INVALID);
         pa_source_output_new_data_set_sample_spec(data, &ss);
         if (pa_channel_map_valid(&map))
             pa_source_output_new_data_set_channel_map(data, &map);
     } else {
-        pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss), -PA_ERR_INVALID);
+        pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss) == 0, -PA_ERR_INVALID);
         pa_source_output_new_data_set_sample_spec(data, &ss);
     }
 

commit 63429b67c744562cb6f3467ff9393788650996d7
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Feb 6 11:20:17 2012 +0530

    format: Don't assert on errors in getters
    
    This makes handling errors in getter functions more graceful, rather
    than triggering warnings/asserts. Better to be less trigger-happy about
    these things since this is now public-facing API.

diff --git a/src/pulse/format.c b/src/pulse/format.c
index d37356d..4de6e89 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -308,9 +308,14 @@ int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
     pa_assert(key);
     pa_assert(v);
 
-    pa_return_val_if_fail(str = pa_proplist_gets(f->plist, key), -PA_ERR_NOENTITY);
+    str = pa_proplist_gets(f->plist, key);
+    if (!str)
+        return -PA_ERR_NOENTITY;
+
     o = json_tokener_parse(str);
-    pa_return_val_if_fail(!is_error(o), -PA_ERR_INVALID);
+    if (is_error(o))
+        return -PA_ERR_INVALID;
+
     if (json_object_get_type(o) != json_type_int) {
         json_object_put(o);
         return -PA_ERR_INVALID;
@@ -335,7 +340,9 @@ int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v)
         return -PA_ERR_NOENTITY;
 
     o = json_tokener_parse(str);
-    pa_return_val_if_fail(!is_error(o), -PA_ERR_INVALID);
+    if (is_error(o))
+        return -PA_ERR_INVALID;
+
     if (json_object_get_type(o) != json_type_string) {
         json_object_put(o);
         return -PA_ERR_INVALID;

commit 6f20d39a1c55c4f6b0fc0dce16c5f75e3bd84004
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Mon Feb 6 11:14:53 2012 +0530

    format: Export pa_format_info int and string property getters
    
    We currently only have setters and clients need to be able to query
    these values as well. The return types for these functions needed to be
    changed to int since this is public API now.

diff --git a/src/pulse/format.c b/src/pulse/format.c
index eee3b54..d37356d 100644
--- a/src/pulse/format.c
+++ b/src/pulse/format.c
@@ -228,11 +228,11 @@ pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, p
     pa_assert(ss);
     pa_return_val_if_fail(f->encoding == PA_ENCODING_PCM, FALSE);
 
-    if (!pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
+    if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
         goto out;
-    if (!pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
+    if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
         goto out;
-    if (!pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
+    if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
         goto out;
 
     if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
@@ -244,7 +244,7 @@ pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, p
     if (map) {
         pa_channel_map_init(map);
 
-        if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m))
+        if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m) == 0)
             if (pa_channel_map_parse(map, m) == NULL)
                 goto out;
     }
@@ -271,7 +271,7 @@ pa_bool_t pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *
     ss->format = PA_SAMPLE_S16LE;
     ss->channels = 2;
 
-    pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate), FALSE);
+    pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, FALSE);
     ss->rate = (uint32_t) rate;
 
     if (f->encoding == PA_ENCODING_EAC3_IEC61937)
@@ -300,7 +300,7 @@ void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map
     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
 }
 
-pa_bool_t pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
+int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
     const char *str;
     json_object *o;
 
@@ -308,21 +308,21 @@ pa_bool_t pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v
     pa_assert(key);
     pa_assert(v);
 
-    pa_return_val_if_fail(str = pa_proplist_gets(f->plist, key), FALSE);
+    pa_return_val_if_fail(str = pa_proplist_gets(f->plist, key), -PA_ERR_NOENTITY);
     o = json_tokener_parse(str);
-    pa_return_val_if_fail(!is_error(o), FALSE);
+    pa_return_val_if_fail(!is_error(o), -PA_ERR_INVALID);
     if (json_object_get_type(o) != json_type_int) {
         json_object_put(o);
-        return FALSE;
+        return -PA_ERR_INVALID;
     }
 
     *v = json_object_get_int(o);
     json_object_put(o);
 
-    return TRUE;
+    return 0;
 }
 
-pa_bool_t pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
+int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
     const char *str = NULL;
     json_object *o;
 
@@ -332,19 +332,19 @@ pa_bool_t pa_format_info_get_prop_string(pa_format_info *f, const char *key, cha
 
     str = pa_proplist_gets(f->plist, key);
     if (!str)
-        return FALSE;
+        return -PA_ERR_NOENTITY;
 
     o = json_tokener_parse(str);
-    pa_return_val_if_fail(!is_error(o), FALSE);
+    pa_return_val_if_fail(!is_error(o), -PA_ERR_INVALID);
     if (json_object_get_type(o) != json_type_string) {
         json_object_put(o);
-        return FALSE;
+        return -PA_ERR_INVALID;
     }
 
     *v = pa_xstrdup(json_object_get_string(o));
     json_object_put(o);
 
-    return TRUE;
+    return 0;
 }
 
 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
diff --git a/src/pulse/format.h b/src/pulse/format.h
index db23cca..2e19e70 100644
--- a/src/pulse/format.h
+++ b/src/pulse/format.h
@@ -115,6 +115,12 @@ char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f);
  * \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);
 
+/** Gets an integer property from the given format info. Returns 0 on success and a negative integer on failure. \since 2.0 */
+int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v);
+/** Gets a string property from the given format info.  The caller must free the returned string using \ref pa_xfree. Returns
+ * 0 on success and a negative integer on failure. \since 2.0 */
+int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v);
+
 /** Sets an integer property on the given format info. \since 1.0 */
 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. \since 1.0 */
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 60b3799..7ab98b8 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -307,8 +307,6 @@ void pa_format_info_free2(pa_format_info *f, void *userdata);
 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map);
 pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map);
 pa_bool_t pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss);
-pa_bool_t pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v);
-pa_bool_t pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v);
 
 pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m);
 



More information about the pulseaudio-commits mailing list