[pulseaudio-commits] r2121 - in /branches/glitch-free/src/pulse: context.c context.h def.h internal.h introspect.c introspect.h proplist.c proplist.h sample.c scache.c scache.h stream.c stream.h volume.h

svnmailer-noreply at 0pointer.de svnmailer-noreply at 0pointer.de
Sat Mar 15 08:18:56 PDT 2008


Author: lennart
Date: Sat Mar 15 16:18:55 2008
New Revision: 2121

URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=2121&root=pulseaudio&view=rev
Log:
commit glitch-free work

Modified:
    branches/glitch-free/src/pulse/context.c
    branches/glitch-free/src/pulse/context.h
    branches/glitch-free/src/pulse/def.h
    branches/glitch-free/src/pulse/internal.h
    branches/glitch-free/src/pulse/introspect.c
    branches/glitch-free/src/pulse/introspect.h
    branches/glitch-free/src/pulse/proplist.c
    branches/glitch-free/src/pulse/proplist.h
    branches/glitch-free/src/pulse/sample.c
    branches/glitch-free/src/pulse/scache.c
    branches/glitch-free/src/pulse/scache.h
    branches/glitch-free/src/pulse/stream.c
    branches/glitch-free/src/pulse/stream.h
    branches/glitch-free/src/pulse/volume.h

Modified: branches/glitch-free/src/pulse/context.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/context.c?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/context.c (original)
+++ branches/glitch-free/src/pulse/context.c Sat Mar 15 16:18:55 2008
@@ -35,6 +35,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <limits.h>
+#include <locale.h>
 
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
@@ -52,6 +53,8 @@
 
 #include <pulse/version.h>
 #include <pulse/xmalloc.h>
+#include <pulse/utf8.h>
+#include <pulse/util.h>
 
 #include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
@@ -108,20 +111,32 @@
 static void context_free(pa_context *c);
 
 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
+    return pa_context_new_with_proplist(mainloop, name, NULL);
+}
+
+pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
     pa_context *c;
 
     pa_assert(mainloop);
-    pa_assert(name);
+
+    if (!name && !pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
+        return NULL;
 
     c = pa_xnew(pa_context, 1);
     PA_REFCNT_INIT(c);
-    c->name = pa_xstrdup(name);
+
+    c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
+
+    if (name)
+        pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
+
     c->mainloop = mainloop;
     c->client = NULL;
     c->pstream = NULL;
     c->pdispatch = NULL;
     c->playback_streams = pa_dynarray_new();
     c->record_streams = pa_dynarray_new();
+    c->client_index = PA_INVALID_INDEX;
 
     PA_LLIST_HEAD_INIT(pa_stream, c->streams);
     PA_LLIST_HEAD_INIT(pa_operation, c->operations);
@@ -204,7 +219,9 @@
 
     pa_strlist_free(c->server_list);
 
-    pa_xfree(c->name);
+    if (c->proplist)
+        pa_proplist_free(c->proplist);
+
     pa_xfree(c->server);
     pa_xfree(c);
 }
@@ -415,7 +432,13 @@
             }
 
             reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
-            pa_tagstruct_puts(reply, c->name);
+
+            if (c->version >= 13) {
+                pa_init_proplist(c->proplist);
+                pa_tagstruct_put_proplist(reply, c->proplist);
+            } else
+                pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));
+
             pa_pstream_send_tagstruct(c->pstream, reply);
             pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
 
@@ -424,11 +447,19 @@
         }
 
         case PA_CONTEXT_SETTING_NAME :
+
+            if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 ||
+                                      c->client_index == PA_INVALID_INDEX)) ||
+                !pa_tagstruct_eof(t)) {
+                pa_context_fail(c, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+
             pa_context_set_state(c, PA_CONTEXT_READY);
             break;
 
         default:
-            pa_assert(0);
+            pa_assert_not_reached();
     }
 
 finish:
@@ -987,12 +1018,19 @@
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
-    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
-
-    t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
-    pa_tagstruct_puts(t, name);
-    pa_pstream_send_tagstruct(c->pstream, t);
-    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+    if (c->version >= 13) {
+        pa_proplist *p = pa_proplist_new();
+        pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
+        o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
+        pa_proplist_free(p);
+
+    } else {
+        o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+        t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
+        pa_tagstruct_puts(t, name);
+        pa_pstream_send_tagstruct(c->pstream, t);
+        pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+    }
 
     return o;
 }
@@ -1024,6 +1062,8 @@
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
+
     return c->version;
 }
 
@@ -1039,3 +1079,151 @@
 
     return t;
 }
+
+uint32_t pa_context_get_index(pa_context *c) {
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
+    PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
+
+    return c->client_index;
+}
+
+pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
+    pa_tagstruct_putu32(t, (uint32_t) mode);
+    pa_tagstruct_put_proplist(t, p);
+
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    /* Please note that we don't update c->proplist here, because we
+     * don't export that field */
+
+    return o;
+}
+
+pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+    const char * const *k;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
+
+    for (k = keys; *k; k++)
+        pa_tagstruct_puts(t, *k);
+
+    pa_tagstruct_puts(t, NULL);
+
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    /* Please note that we don't update c->proplist here, because we
+     * don't export that field */
+
+    return o;
+}
+
+void pa_init_proplist(pa_proplist *p) {
+    int a, b;
+#ifndef HAVE_DECL_ENVIRON
+    extern char **environ;
+#endif
+    char **e;
+
+    pa_assert(p);
+
+    for (e = environ; *e; e++) {
+
+        if (pa_startswith(*e, "PULSE_PROP_")) {
+            size_t kl = strcspn(*e+11, "=");
+            char *k;
+
+            if ((*e)[11+kl] != '=')
+                continue;
+
+            if (!pa_utf8_valid(*e+11+kl+1))
+                continue;
+
+            k = pa_xstrndup(*e+11, kl);
+
+            if (pa_proplist_contains(p, k)) {
+                pa_xfree(k);
+                continue;
+            }
+
+            pa_proplist_sets(p, k, *e+11+kl+1);
+            pa_xfree(k);
+        }
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
+        char t[32];
+        pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
+        pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
+        char t[64];
+        if (pa_get_user_name(t, sizeof(t))) {
+            char *c = pa_utf8_filter(t);
+            pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, c);
+            pa_xfree(c);
+        }
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
+        char t[64];
+        if (pa_get_host_name(t, sizeof(t))) {
+            char *c = pa_utf8_filter(t);
+            pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, c);
+            pa_xfree(c);
+        }
+    }
+
+    if (!(a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) ||
+        !(b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))) {
+        char t[PATH_MAX];
+        if (pa_get_binary_name(t, sizeof(t))) {
+            char *c = pa_utf8_filter(t);
+
+            if (!a)
+                pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
+            if (!b)
+                pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, c);
+
+            pa_xfree(c);
+        }
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
+        const char *l;
+
+        if ((l = setlocale(LC_MESSAGES, NULL)))
+            pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
+    }
+}

Modified: branches/glitch-free/src/pulse/context.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/context.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/context.h (original)
+++ branches/glitch-free/src/pulse/context.h Sat Mar 15 16:18:55 2008
@@ -30,6 +30,7 @@
 #include <pulse/mainloop-api.h>
 #include <pulse/cdecl.h>
 #include <pulse/operation.h>
+#include <pulse/proplist.h>
 
 /** \page async Asynchronous API
  *
@@ -166,8 +167,14 @@
 typedef void (*pa_context_success_cb_t) (pa_context *c, int success, void *userdata);
 
 /** Instantiate a new connection context with an abstract mainloop API
- * and an application name */
+ * and an application name. It is recommended to use pa_context_new_with_proplist()
+ * instead and specify some initial properties.*/
 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name);
+
+/** Instantiate a new connection context with an abstract mainloop API
+ * and an application name, and specify the the initial client property
+ * list. \since 0.9.10 */
+pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
 
 /** Decrease the reference counter of the context by one */
 void pa_context_unref(pa_context *c);
@@ -228,6 +235,21 @@
 /** Return the protocol version of the connected server. \since 0.8 */
 uint32_t pa_context_get_server_protocol_version(pa_context *c);
 
+/* Update the property list of the client, adding new entries. Please
+ * note that it is highly recommended to set as much properties
+ * initially via pa_context_new_with_proplist() as possible instead a
+ * posteriori with this function, since that information may then be
+ * used to route streams of the client to the right device. \since 0.9.10 */
+pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata);
+
+/* Update the property list of the client, remove entries. \since 0.9.10 */
+pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata);
+
+/** Return the client index this context is
+ * identified in the server with. This is useful for usage with the
+ * introspection functions, such as pa_context_get_client_info(). \since 0.9.10 */
+uint32_t pa_context_get_index(pa_context *s);
+
 PA_C_DECL_END
 
 #endif

Modified: branches/glitch-free/src/pulse/def.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/def.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/def.h (original)
+++ branches/glitch-free/src/pulse/def.h Sat Mar 15 16:18:55 2008
@@ -209,6 +209,8 @@
                                      * least PA 0.9.8. It is ignored
                                      * on older servers. \since
                                      * 0.9.8 */
+    PA_STREAM_PEAK_DETECT = 2048, /**< Find peaks instead of
+                                   * resampling. \since 0.9.9 */
 } pa_stream_flags_t;
 
 /** Playback and record buffer metrics */
@@ -378,7 +380,9 @@
     PA_SINK_HW_VOLUME_CTRL = 1,   /**< Supports hardware volume control */
     PA_SINK_LATENCY = 2,          /**< Supports latency querying */
     PA_SINK_HARDWARE = 4,         /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
-    PA_SINK_NETWORK = 8           /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SINK_NETWORK = 8,          /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SINK_HW_MUTE_CTRL = 16,    /**< Supports hardware mute control \since 0.9.10 */
+    PA_SINK_DECIBEL_VOLUME = 32   /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.10 */
 } pa_sink_flags_t;
 
 /** Special source flags. \since 0.8  */
@@ -386,7 +390,9 @@
     PA_SOURCE_HW_VOLUME_CTRL = 1,  /**< Supports hardware volume control */
     PA_SOURCE_LATENCY = 2,         /**< Supports latency querying */
     PA_SOURCE_HARDWARE = 4,        /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
-    PA_SOURCE_NETWORK = 8          /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SOURCE_NETWORK = 8,         /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SOURCE_HW_MUTE_CTRL = 16,   /**< Supports hardware mute control \since 0.9.10 */
+    PA_SOURCE_DECIBEL_VOLUME = 32  /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.10 */
 } pa_source_flags_t;
 
 /** A generic free() like callback prototype */

Modified: branches/glitch-free/src/pulse/internal.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/internal.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/internal.h (original)
+++ branches/glitch-free/src/pulse/internal.h Sat Mar 15 16:18:55 2008
@@ -50,7 +50,7 @@
 struct pa_context {
     PA_REFCNT_DECLARE;
 
-    char *name;
+    pa_proplist *proplist;
     pa_mainloop_api* mainloop;
 
     pa_socket_client *client;
@@ -85,6 +85,8 @@
     char *server;
 
     pa_client_conf *conf;
+
+    uint32_t client_index;
 };
 
 #define PA_MAX_WRITE_INDEX_CORRECTIONS 10
@@ -102,7 +104,7 @@
     pa_mainloop_api *mainloop;
     PA_LLIST_FIELDS(pa_stream);
 
-    char *name;
+    pa_proplist *proplist;
     pa_bool_t manual_buffer_attr;
     pa_buffer_attr buffer_attr;
     pa_sample_spec sample_spec;
@@ -226,5 +228,6 @@
 
 #define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, NULL)
 
+void pa_init_proplist(pa_proplist *p);
 
 #endif

Modified: branches/glitch-free/src/pulse/introspect.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/introspect.c?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/introspect.c (original)
+++ branches/glitch-free/src/pulse/introspect.c Sat Mar 15 16:18:55 2008
@@ -149,7 +149,9 @@
 
         while (!pa_tagstruct_eof(t)) {
             pa_sink_info i;
+
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -163,9 +165,11 @@
                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                pa_tagstruct_getu32(t, &flags) < 0) {
+                pa_tagstruct_getu32(t, &flags) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -175,6 +179,8 @@
                 pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -260,7 +266,9 @@
         while (!pa_tagstruct_eof(t)) {
             pa_source_info i;
             uint32_t flags;
+
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -274,9 +282,11 @@
                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                pa_tagstruct_getu32(t, &flags) < 0) {
+                pa_tagstruct_getu32(t, &flags) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -286,6 +296,8 @@
                 pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -370,13 +382,18 @@
 
         while (!pa_tagstruct_eof(t)) {
             pa_client_info i;
+
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
-                pa_tagstruct_gets(t, &i.driver) < 0 ) {
+                pa_tagstruct_gets(t, &i.driver) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
+
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -384,6 +401,8 @@
                 pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -521,7 +540,9 @@
 
         while (!pa_tagstruct_eof(t)) {
             pa_sink_input_info i;
+
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -535,9 +556,11 @@
                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0)) {
+                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0) ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -545,6 +568,8 @@
                 pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -608,6 +633,7 @@
             pa_source_output_info i;
 
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -619,9 +645,11 @@
                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
                 pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
-                pa_tagstruct_gets(t, &i.driver) < 0) {
+                pa_tagstruct_gets(t, &i.driver) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -629,6 +657,8 @@
                 pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -933,6 +963,7 @@
             pa_sample_info i;
 
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -942,7 +973,8 @@
                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
                 pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
-                pa_tagstruct_gets(t, &i.filename) < 0) {
+                pa_tagstruct_gets(t, &i.filename) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 goto finish;
@@ -952,6 +984,8 @@
                 pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 

Modified: branches/glitch-free/src/pulse/introspect.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/introspect.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/introspect.h (original)
+++ branches/glitch-free/src/pulse/introspect.h Sat Mar 15 16:18:55 2008
@@ -32,6 +32,7 @@
 #include <pulse/cdecl.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
+#include <pulse/proplist.h>
 
 /** \page introspect Server Query and Control
  *
@@ -205,6 +206,11 @@
  */
 
 PA_C_DECL_BEGIN
+
+#define PA_PORT_SPDIF "spdif"
+#define PA_PORT_ANALOG_STEREO "analog-stereo"
+#define PA_PORT_ANALOG_5_1 "analog-5-1"
+#define PA_PORT_ANALOG_4_0 "analog-4-0"
 
 /** Stores information about sinks */
 typedef struct pa_sink_info {
@@ -221,6 +227,7 @@
     pa_usec_t latency;                 /**< Length of filled playback buffer of this sink */
     const char *driver;                /**< Driver name. \since 0.8 */
     pa_sink_flags_t flags;             /**< Flags \since 0.8 */
+    pa_proplist *proplist;             /**< Property list \since 0.9.10 */
 } pa_sink_info;
 
 /** Callback prototype for pa_context_get_sink_info_by_name() and friends */
@@ -237,7 +244,7 @@
 
 /** Stores information about sources */
 typedef struct pa_source_info {
-    const char *name ;                  /**< Name of the source */
+    const char *name;                   /**< Name of the source */
     uint32_t index;                     /**< Index of the source */
     const char *description;            /**< Description of this source */
     pa_sample_spec sample_spec;         /**< Sample spec of this source */
@@ -250,6 +257,7 @@
     pa_usec_t latency;                  /**< Length of filled record buffer of this source. \since 0.5 */
     const char *driver;                 /**< Driver name \since 0.8 */
     pa_source_flags_t flags;            /**< Flags \since 0.8 */
+    pa_proplist *proplist;              /**< Property list \since 0.9.10 */
 } pa_source_info;
 
 /** Callback prototype for pa_context_get_source_info_by_name() and friends */
@@ -306,6 +314,7 @@
     const char *name;                    /**< Name of this client */
     uint32_t owner_module;               /**< Index of the owning module, or PA_INVALID_INDEX */
     const char *driver;                  /**< Driver name \since 0.8 */
+    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
 } pa_client_info;
 
 /** Callback prototype for pa_context_get_client_info() and firends*/
@@ -332,6 +341,7 @@
     const char *resample_method;         /**< Thre resampling method used by this sink input. \since 0.7 */
     const char *driver;                  /**< Driver name \since 0.8 */
     int mute;                            /**< Stream muted \since 0.9.7 */
+    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
 } pa_sink_input_info;
 
 /** Callback prototype for pa_context_get_sink_input_info() and firends*/
@@ -356,6 +366,7 @@
     pa_usec_t source_usec;               /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */
     const char *resample_method;         /**< Thre resampling method used by this source output. \since 0.7 */
     const char *driver;                  /**< Driver name \since 0.8 */
+    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
 } pa_source_output_info;
 
 /** Callback prototype for pa_context_get_source_output_info() and firends*/
@@ -423,6 +434,7 @@
     uint32_t bytes;                       /**< Length of this sample in bytes. \since 0.4 */
     int lazy;                             /**< Non-zero when this is a lazy cache entry. \since 0.5 */
     const char *filename;                 /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. \since 0.5 */
+    pa_proplist *proplist;                /**< Property list for this sample. \since 0.9.10 */
 } pa_sample_info;
 
 /** Callback prototype for pa_context_get_sample_info_by_name() and firends */

Modified: branches/glitch-free/src/pulse/proplist.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/proplist.c?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/proplist.c (original)
+++ branches/glitch-free/src/pulse/proplist.c Sat Mar 15 16:18:55 2008
@@ -69,16 +69,14 @@
 }
 
 void pa_proplist_free(pa_proplist* p) {
-    struct property *prop;
-
-    while ((prop = pa_hashmap_steal_first(MAKE_HASHMAP(p))))
-        property_free(prop);
-
+    pa_assert(p);
+
+    pa_proplist_clear(p);
     pa_hashmap_free(MAKE_HASHMAP(p), NULL, NULL);
 }
 
 /** Will accept only valid UTF-8 */
-int pa_proplist_puts(pa_proplist *p, const char *key, const char *value) {
+int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) {
     struct property *prop;
     pa_bool_t add = FALSE;
 
@@ -104,7 +102,7 @@
     return 0;
 }
 
-int pa_proplist_put(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
+int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
     struct property *prop;
     pa_bool_t add = FALSE;
 
@@ -175,18 +173,27 @@
     return 0;
 }
 
-void pa_proplist_merge(pa_proplist *p, pa_proplist *other) {
+void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, pa_proplist *other) {
     struct property *prop;
     void *state = NULL;
 
     pa_assert(p);
+    pa_assert(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE);
     pa_assert(other);
 
-    while ((prop = pa_hashmap_iterate(MAKE_HASHMAP(other), &state, NULL)))
-        pa_assert_se(pa_proplist_put(p, prop->key, prop->value, prop->nbytes) == 0);
-}
-
-int pa_proplist_remove(pa_proplist *p, const char *key) {
+    if (mode == PA_UPDATE_SET)
+        pa_proplist_clear(p);
+
+    while ((prop = pa_hashmap_iterate(MAKE_HASHMAP(other), &state, NULL))) {
+
+        if (mode == PA_UPDATE_MERGE && pa_proplist_contains(p, prop->key))
+            continue;
+
+        pa_assert_se(pa_proplist_set(p, prop->key, prop->value, prop->nbytes) == 0);
+    }
+}
+
+int pa_proplist_unset(pa_proplist *p, const char *key) {
     struct property *prop;
 
     pa_assert(p);
@@ -196,10 +203,28 @@
         return -1;
 
     if (!(prop = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
-        return -1;
+        return -2;
 
     property_free(prop);
     return 0;
+}
+
+int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]) {
+    const char * const * k;
+    int n = 0;
+
+    pa_assert(p);
+    pa_assert(keys);
+
+    for (k = keys; *k; k++)
+        if (!property_name_valid(*k))
+            return -1;
+
+    for (k = keys; *k; k++)
+        if (pa_proplist_unset(p, *k) >= 0)
+            n++;
+
+    return n;
 }
 
 const char *pa_proplist_iterate(pa_proplist *p, void **state) {
@@ -255,3 +280,22 @@
 
     return 1;
 }
+
+void pa_proplist_clear(pa_proplist *p) {
+    struct property *prop;
+    pa_assert(p);
+
+    while ((prop = pa_hashmap_steal_first(MAKE_HASHMAP(p))))
+        property_free(prop);
+}
+
+pa_proplist* pa_proplist_copy(pa_proplist *template) {
+    pa_proplist *p;
+
+    pa_assert_se(p = pa_proplist_new());
+
+    if (template)
+        pa_proplist_update(p, PA_UPDATE_REPLACE, template);
+
+    return p;
+}

Modified: branches/glitch-free/src/pulse/proplist.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/proplist.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/proplist.h (original)
+++ branches/glitch-free/src/pulse/proplist.h Sat Mar 15 16:18:55 2008
@@ -28,63 +28,154 @@
 
 /* Defined properties:
  *
- *    x11.xid
- *    x11.display
- *    x11.x_pointer
- *    x11.y_pointer
- *    x11.button
- *    media.name
- *    media.title
- *    media.artist
- *    media.language
+ *    media.name                    "Guns'N'Roses: Civil War"
+ *    media.title                   "Civil War"
+ *    media.artist                  "Guns'N'Roses"
+ *    media.language                "de_DE"
  *    media.filename
  *    media.icon
  *    media.icon_name
- *    media.role                    video, music, game, event, phone, production
- *    application.name
+ *    media.role                    video, music, game, event, phone, production, routing, abstract
+ *    event.id                      button-click, session-login
+ *    event.x11.display
+ *    event.x11.xid
+ *    event.x11.x_pointer
+ *    event.x11.y_pointer
+ *    event.x11.button
+ *    application.name              "Rhythmbox Media Player"
+ *    application.id                "org.gnome.rhythmbox"
  *    application.version
  *    application.icon
  *    application.icon_name
+ *    application.process.id
+ *    application.process.binary
+ *    application.process.user
+ *    application.process.host
+ *    device.string
+ *    device.api                     oss, alsa, sunaudio
+ *    device.description
+ *    device.bus_path
+ *    device.serial
+ *    device.vendor_product_id
+ *    device.class                   sound, modem, monitor
+ *    device.form_factor             laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset
+ *    device.connector               isa, pci, usb, firewire, bluetooth
+ *    device.access_mode             mmap, mmap_rewrite, serial
+ *    device.master_device
+ *    device.buffer_size
  */
 
-#define PA_PROP_X11_XID                  "x11.xid"
-#define PA_PROP_X11_DISPLAY              "x11.display"
-#define PA_PROP_X11_X_POINTER            "x11.x_pointer"
-#define PA_PROP_X11_Y_POINTER            "x11.y_pointer"
-#define PA_PROP_X11_BUTTON               "x11.button"
-#define PA_PROP_MEDIA_NAME               "media.name"
-#define PA_PROP_MEDIA_TITLE              "media.title"
-#define PA_PROP_MEDIA_ARTIST             "media.artist"
-#define PA_PROP_MEDIA_LANGUAGE           "media.language"
-#define PA_PROP_MEDIA_FILENAME           "media.filename"
-#define PA_PROP_MEDIA_ICON               "media.icon"
-#define PA_PROP_MEDIA_ICON_NAME          "media.icon_name"
-#define PA_PROP_MEDIA_ROLE               "media.role"
-#define PA_PROP_APPLICATION_NAME         "application.name"
-#define PA_PROP_APPLICATION_VERSION      "application.version"
-#define PA_PROP_APPLICATION_ICON         "application.icon"
-#define PA_PROP_APPLICATION_ICON_NAME    "application.icon_name"
+#define PA_PROP_MEDIA_NAME                  "media.name"
+#define PA_PROP_MEDIA_TITLE                 "media.title"
+#define PA_PROP_MEDIA_ARTIST                "media.artist"
+#define PA_PROP_MEDIA_LANGUAGE              "media.language"
+#define PA_PROP_MEDIA_FILENAME              "media.filename"
+#define PA_PROP_MEDIA_ICON                  "media.icon"
+#define PA_PROP_MEDIA_ICON_NAME             "media.icon_name"
+#define PA_PROP_MEDIA_ROLE                  "media.role"
+#define PA_PROP_EVENT_ID                    "event.id"
+#define PA_PROP_EVENT_X11_DISPLAY           "event.x11.display"
+#define PA_PROP_EVENT_X11_XID               "event.x11.xid"
+#define PA_PROP_EVENT_MOUSE_X               "event.mouse.x"
+#define PA_PROP_EVENT_MOUSE_Y               "event.mouse.y"
+#define PA_PROP_EVENT_MOUSE_BUTTON          "event.mouse.button"
+#define PA_PROP_APPLICATION_NAME            "application.name"
+#define PA_PROP_APPLICATION_ID              "application.id"
+#define PA_PROP_APPLICATION_VERSION         "application.version"
+#define PA_PROP_APPLICATION_ICON            "application.icon"
+#define PA_PROP_APPLICATION_ICON_NAME       "application.icon_name"
+#define PA_PROP_APPLICATION_LANGUAGE        "application.language"
+#define PA_PROP_APPLICATION_PROCESS_ID      "application.process.id"
+#define PA_PROP_APPLICATION_PROCESS_BINARY  "application.process.binary"
+#define PA_PROP_APPLICATION_PROCESS_USER    "application.process.user"
+#define PA_PROP_APPLICATION_PROCESS_HOST    "application.process.host"
+#define PA_PROP_DEVICE_STRING               "device.string"
+#define PA_PROP_DEVICE_API                  "device.api"
+#define PA_PROP_DEVICE_DESCRIPTION          "device.description"
+#define PA_PROP_DEVICE_BUS_PATH             "device.bus_path"
+#define PA_PROP_DEVICE_SERIAL               "device.serial"
+#define PA_PROP_DEVICE_VENDOR_PRODUCT_ID    "device.vendor_product_id"
+#define PA_PROP_DEVICE_CLASS                "device.class"
+#define PA_PROP_DEVICE_FORM_FACTOR          "device.form_factor"
+#define PA_PROP_DEVICE_CONNECTOR            "device.connector"
+#define PA_PROP_DEVICE_ACCESS_MODE          "device.access_mode"
+#define PA_PROP_DEVICE_MASTER_DEVICE        "device.master_device"
 
+/** A property list object. Basically a dictionary with UTF-8 strings
+ * as keys and arbitrary data as values. \since 0.9.10 */
 typedef struct pa_proplist pa_proplist;
 
+/** Allocate a property list. \since 0.9.10 */
 pa_proplist* pa_proplist_new(void);
+
+/** Free the property list. \since 0.9.10 */
 void pa_proplist_free(pa_proplist* p);
 
-/** Will accept only valid UTF-8 */
-int pa_proplist_puts(pa_proplist *p, const char *key, const char *value);
-int pa_proplist_put(pa_proplist *p, const char *key, const void *data, size_t nbytes);
+/** Append a new string entry to the property list, possibly
+ * overwriting an already existing entry with the same key. An
+ * internal copy of the data passed is made. Will accept only valid
+ * UTF-8. \since 0.9.10 */
+int pa_proplist_sets(pa_proplist *p, const char *key, const char *value);
 
-/* Will return NULL if the data is not valid UTF-8 */
+/** Append a new arbitrary data entry to the property list, possibly
+ * overwriting an already existing entry with the same key. An
+ * internal copy of the data passed is made. \since 0.9.10 */
+int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes);
+
+/* Return a string entry for the specified key. Will return NULL if
+ * the data is not valid UTF-8. Will return a NUL-terminated string in
+ * an internally allocated buffer. The caller should make a copy of
+ * the data before accessing the property list again. \since 0.9.10*/
 const char *pa_proplist_gets(pa_proplist *p, const char *key);
+
+/** Return the the value for the specified key. Will return a
+ * NUL-terminated string for string entries. The pointer returned will
+ * point to an internally allocated buffer. The caller should make a
+ * copy of the data before the property list is accessed again. \since 0.9.10 */
 int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *nbytes);
 
-void pa_proplist_merge(pa_proplist *p, pa_proplist *other);
-int pa_proplist_remove(pa_proplist *p, const char *key);
+/** Update mode enum for pa_proplist_update(). \since 0.9.10 */
+typedef enum pa_update_mode {
+    PA_UPDATE_SET,  /*< Replace the entirey property list with the new one. Don't keep any of the old data around */
+    PA_UPDATE_MERGE, /*< Merge new property list into the existing one, not replacing any old entries if they share a common key with the new property list. */
+    PA_UPDATE_REPLACE /*< Merge new property list into the existing one, replacing all old entries that share a common key with  the new property list. */
+} pa_update_mode_t;
 
+/** Merge property list "other" into "p", adhering the merge mode as
+ * specified in "mode". \since 0.9.10 */
+void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, pa_proplist *other);
+
+/** Removes a single entry from the property list, identified be the
+ * specified key name. \since 0.9.10 */
+int pa_proplist_unset(pa_proplist *p, const char *key);
+
+/** Similar to pa_proplist_remove() but takes an array of keys to
+ * remove. The array should be terminated by a NULL pointer. Return -1
+ * on failure, otherwise the number of entries actually removed (which
+ * might even be 0, if there where no matching entries to
+ * remove). \since 0.9.10 */
+int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]);
+
+/** Iterate through the property list. The user should allocate a
+ * state variable of type void* and initialize it with NULL. A pointer
+ * to this variable should then be passed to pa_proplist_iterate()
+ * which should be called in a loop until it returns NULL which
+ * signifies EOL. The property list should not be modified during
+ * iteration through the list. On each invication this function will
+ * return the key string for the next entry. The keys in the property
+ * list do not have any particular order. \since 0.9.10 */
 const char *pa_proplist_iterate(pa_proplist *p, void **state);
 
+/** Format the property list nicely as a human readable string. \since 0.9.10 */
 char *pa_proplist_to_string(pa_proplist *p);
 
+/** Returns 1 if an entry for the specified key is existant in the property list. \since 0.9.10 */
 int pa_proplist_contains(pa_proplist *p, const char *key);
 
+/** Remove all entries from the property list object. \since 0.9.10 */
+void pa_proplist_clear(pa_proplist *p);
+
+/** Allocate a new property list and copy over every single entry from the specific list. \since 0.9.10 */
+pa_proplist* pa_proplist_copy(pa_proplist *template);
+
 #endif

Modified: branches/glitch-free/src/pulse/sample.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/sample.c?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/sample.c (original)
+++ branches/glitch-free/src/pulse/sample.c Sat Mar 15 16:18:55 2008
@@ -32,6 +32,7 @@
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/macro.h>
+#include <pulse/timeval.h>
 
 #include "sample.h"
 
@@ -70,13 +71,13 @@
 pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
     pa_assert(spec);
 
-    return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate);
+    return (((pa_usec_t) (length / pa_frame_size(spec)) * PA_USEC_PER_SEC) / spec->rate);
 }
 
 size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
     pa_assert(spec);
 
-    return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
+    return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * pa_frame_size(spec);
 }
 
 int pa_sample_spec_valid(const pa_sample_spec *spec) {
@@ -97,7 +98,10 @@
     pa_assert(a);
     pa_assert(b);
 
-    return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels);
+    return
+        (a->format == b->format) &&
+        (a->rate == b->rate) &&
+        (a->channels == b->channels);
 }
 
 const char *pa_sample_format_to_string(pa_sample_format_t f) {

Modified: branches/glitch-free/src/pulse/scache.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/scache.c?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/scache.c (original)
+++ branches/glitch-free/src/pulse/scache.c Sat Mar 15 16:18:55 2008
@@ -49,12 +49,22 @@
     pa_stream_ref(s);
 
     s->direction = PA_STREAM_UPLOAD;
+    s->flags = 0;
 
     t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag);
-    pa_tagstruct_puts(t, s->name);
+
+    if (s->context->version < 13)
+        pa_tagstruct_puts(t, pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME));
+
     pa_tagstruct_put_sample_spec(t, &s->sample_spec);
     pa_tagstruct_put_channel_map(t, &s->channel_map);
     pa_tagstruct_putu32(t, length);
+
+    if (s->context->version >= 13) {
+        pa_init_proplist(s->proplist);
+        pa_tagstruct_put_proplist(t, s->proplist);
+    }
+
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
 
@@ -84,6 +94,73 @@
     pa_stream_unref(s);
     return 0;
 }
+
+static void play_sample_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_operation *o = userdata;
+    int success = 1;
+    uint32_t idx = PA_INVALID_INDEX;
+
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+    if (!o->context)
+        goto finish;
+
+    if (command != PA_COMMAND_REPLY) {
+        if (pa_context_handle_error(o->context, command, t) < 0)
+            goto finish;
+
+        success = 0;
+    } else if ((o->context->version >= 13 && pa_tagstruct_getu32(t, &idx) < 0) ||
+               !pa_tagstruct_eof(t)) {
+        pa_context_fail(o->context, PA_ERR_PROTOCOL);
+        goto finish;
+    } else if (o->context->version >= 13 && idx == PA_INVALID_INDEX)
+        success = 0;
+
+    if (o->callback) {
+        pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback;
+        cb(o->context, success, o->userdata);
+    }
+
+finish:
+    pa_operation_done(o);
+    pa_operation_unref(o);
+}
+
+static void play_sample_with_proplist_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_operation *o = userdata;
+    uint32_t idx;
+
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+    if (!o->context)
+        goto finish;
+
+    if (command != PA_COMMAND_REPLY) {
+        if (pa_context_handle_error(o->context, command, t) < 0)
+            goto finish;
+
+        idx = PA_INVALID_INDEX;
+    } else if (pa_tagstruct_getu32(t, &idx) < 0 ||
+               !pa_tagstruct_eof(t)) {
+        pa_context_fail(o->context, PA_ERR_PROTOCOL);
+        goto finish;
+    }
+
+    if (o->callback) {
+        pa_context_play_sample_cb_t cb = (pa_context_play_sample_cb_t) o->callback;
+        cb(o->context, idx, o->userdata);
+    }
+
+finish:
+    pa_operation_done(o);
+    pa_operation_unref(o);
+}
+
 
 pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char *dev, pa_volume_t volume, pa_context_success_cb_t cb, void *userdata) {
     pa_operation *o;
@@ -107,30 +184,69 @@
     pa_tagstruct_puts(t, dev);
     pa_tagstruct_putu32(t, volume);
     pa_tagstruct_puts(t, name);
+
+    if (c->version >= 13) {
+        pa_proplist *p = pa_proplist_new();
+        pa_tagstruct_put_proplist(t, p);
+        pa_proplist_free(p);
+    }
+
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, play_sample_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    return o;
+}
+
+pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *name, const char *dev, pa_volume_t volume, pa_proplist *p, pa_context_play_sample_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, p, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    if (!dev)
+        dev = c->conf->default_sink;
+
+    t = pa_tagstruct_command(c, PA_COMMAND_PLAY_SAMPLE, &tag);
+    pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+    pa_tagstruct_puts(t, dev);
+    pa_tagstruct_putu32(t, volume);
+    pa_tagstruct_puts(t, name);
+    pa_tagstruct_put_proplist(t, p);
+
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, play_sample_with_proplist_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    return o;
+}
+
+pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag);
+    pa_tagstruct_puts(t, name);
+
     pa_pstream_send_tagstruct(c->pstream, t);
     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
 }
-
-pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
-    pa_operation *o;
-    pa_tagstruct *t;
-    uint32_t tag;
-
-    pa_assert(c);
-    pa_assert(PA_REFCNT_VALUE(c) >= 1);
-
-    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-    PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
-
-    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
-
-    t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag);
-    pa_tagstruct_puts(t, name);
-    pa_pstream_send_tagstruct(c->pstream, t);
-    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
-
-    return o;
-}
-

Modified: branches/glitch-free/src/pulse/scache.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/scache.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/scache.h (original)
+++ branches/glitch-free/src/pulse/scache.h Sat Mar 15 16:18:55 2008
@@ -79,14 +79,25 @@
 
 PA_C_DECL_BEGIN
 
+/** Callback prototype for pa_context_play_sample_with_proplist(). The
+ * idx value is the index of the sink input object, or
+ * PA_INVALID_INDEX on failure. \since 0.9.10*/
+typedef void (*pa_context_play_sample_cb_t)(pa_context *c, uint32_t idx, void *userdata);
+
 /** Make this stream a sample upload stream */
 int pa_stream_connect_upload(pa_stream *s, size_t length);
 
-/** Finish the sample upload, the stream name will become the sample name. You cancel a samp
- * le upload by issuing pa_stream_disconnect() */
+/** Finish the sample upload, the stream name will become the sample
+ * name. You cancel a sample upload by issuing
+ * pa_stream_disconnect() */
 int pa_stream_finish_upload(pa_stream *s);
 
-/** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */
+/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */
+pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata);
+
+/** Play a sample from the sample cache to the specified device. If
+ * the latter is NULL use the default sink. Returns an operation
+ * object */
 pa_operation* pa_context_play_sample(
         pa_context *c               /**< Context */,
         const char *name            /**< Name of the sample to play */,
@@ -95,8 +106,18 @@
         pa_context_success_cb_t cb  /**< Call this function after successfully starting playback, or NULL */,
         void *userdata              /**< Userdata to pass to the callback */);
 
-/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */
-pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t, void *userdata);
+/** Play a sample from the sample cache to the specified device,
+ * allowing specification of a property list for the playback
+ * stream. If the latter is NULL use the default sink. Returns an
+ * operation object. \since 0.9.10 */
+pa_operation* pa_context_play_sample_with_proplist(
+        pa_context *c                   /**< Context */,
+        const char *name                /**< Name of the sample to play */,
+        const char *dev                 /**< Sink to play this sample on */,
+        pa_volume_t volume              /**< Volume to play this sample with */ ,
+        pa_proplist *proplist           /**< Property list for this sound. The property list of the cached entry will be merged into this property list */,
+        pa_context_play_sample_cb_t cb  /**< Call this function after successfully starting playback, or NULL */,
+        void *userdata                  /**< Userdata to pass to the callback */);
 
 PA_C_DECL_END
 

Modified: branches/glitch-free/src/pulse/stream.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/stream.c?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/stream.c (original)
+++ branches/glitch-free/src/pulse/stream.c Sat Mar 15 16:18:55 2008
@@ -44,6 +44,10 @@
 #define LATENCY_IPOL_INTERVAL_USEC (100000L)
 
 pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
+    return pa_stream_new_with_proplist(c, name, ss, map, NULL);
+}
+
+pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, pa_proplist *p) {
     pa_stream *s;
     int i;
     pa_channel_map tmap;
@@ -54,6 +58,7 @@
     PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, name || pa_proplist_contains(p, PA_PROP_MEDIA_NAME), PA_ERR_INVALID);
 
     if (!map)
         PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID);
@@ -83,10 +88,14 @@
     s->suspended_userdata = NULL;
 
     s->direction = PA_STREAM_NODIRECTION;
-    s->name = pa_xstrdup(name);
     s->sample_spec = *ss;
     s->channel_map = *map;
     s->flags = 0;
+
+    s->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
+
+    if (name)
+        pa_proplist_sets(c->proplist, PA_PROP_MEDIA_NAME, name);
 
     s->channel = 0;
     s->channel_valid = 0;
@@ -151,7 +160,9 @@
     if (s->record_memblockq)
         pa_memblockq_free(s->record_memblockq);
 
-    pa_xfree(s->name);
+    if (s->proplist)
+        pa_proplist_free(s->proplist);
+
     pa_xfree(s->device_name);
     pa_xfree(s);
 }
@@ -653,6 +664,7 @@
                 pa_frame_size(&s->sample_spec),
                 1,
                 0,
+                0,
                 NULL);
     }
 
@@ -692,19 +704,29 @@
 
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(direction == PA_STREAM_PLAYBACK || direction == PA_STREAM_RECORD);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
-    PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ?
-                                               PA_STREAM_START_CORKED|
-                                               PA_STREAM_INTERPOLATE_TIMING|
-                                               PA_STREAM_NOT_MONOTONOUS|
-                                               PA_STREAM_AUTO_TIMING_UPDATE|
-                                               PA_STREAM_NO_REMAP_CHANNELS|
-                                               PA_STREAM_NO_REMIX_CHANNELS|
-                                               PA_STREAM_FIX_FORMAT|
-                                               PA_STREAM_FIX_RATE|
-                                               PA_STREAM_FIX_CHANNELS|
-                                               PA_STREAM_DONT_MOVE : 0))), PA_ERR_INVALID);
+    PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|
+                                              PA_STREAM_INTERPOLATE_TIMING|
+                                              PA_STREAM_NOT_MONOTONOUS|
+                                              PA_STREAM_AUTO_TIMING_UPDATE|
+                                              PA_STREAM_NO_REMAP_CHANNELS|
+                                              PA_STREAM_NO_REMIX_CHANNELS|
+                                              PA_STREAM_FIX_FORMAT|
+                                              PA_STREAM_FIX_RATE|
+                                              PA_STREAM_FIX_CHANNELS|
+                                              PA_STREAM_DONT_MOVE|
+                                              PA_STREAM_VARIABLE_RATE|
+                                              PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
+
+    PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
+    PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
+    /* Althought some of the other flags are not supported on older
+     * version, we don't check for them here, because it doesn't hurt
+     * when they are passed but actually not supported. This makes
+     * client development easier */
+
     PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID);
     PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
 
@@ -737,9 +759,11 @@
             s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM,
             &tag);
 
+    if (s->context->version < 13)
+        pa_tagstruct_puts(t, pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME));
+
     pa_tagstruct_put(
             t,
-            PA_TAG_STRING, s->name,
             PA_TAG_SAMPLE_SPEC, &s->sample_spec,
             PA_TAG_CHANNEL_MAP, &s->channel_map,
             PA_TAG_U32, PA_INVALID_INDEX,
@@ -766,7 +790,7 @@
     } else
         pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
 
-    if (s->context->version >= 12 && s->direction != PA_STREAM_UPLOAD) {
+    if (s->context->version >= 12) {
         pa_tagstruct_put(
                 t,
                 PA_TAG_BOOLEAN, flags & PA_STREAM_NO_REMAP_CHANNELS,
@@ -776,6 +800,17 @@
                 PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_CHANNELS,
                 PA_TAG_BOOLEAN, flags & PA_STREAM_DONT_MOVE,
                 PA_TAG_BOOLEAN, flags & PA_STREAM_VARIABLE_RATE,
+                PA_TAG_INVALID);
+    }
+
+    if (s->context->version >= 13) {
+
+        pa_init_proplist(s->proplist);
+
+        pa_tagstruct_put(
+                t,
+                PA_TAG_BOOLEAN, flags & PA_STREAM_PEAK_DETECT,
+                PA_TAG_PROPLIST, s->proplist,
                 PA_TAG_INVALID);
     }
 
@@ -1835,5 +1870,72 @@
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_update_sample_rate_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
-
-}
+}
+
+pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_proplist *p, pa_stream_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(
+            s->context,
+            s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST,
+            &tag);
+    pa_tagstruct_putu32(t, s->channel);
+    pa_tagstruct_putu32(t, (uint32_t) mode);
+    pa_tagstruct_put_proplist(t, p);
+
+    pa_pstream_send_tagstruct(s->context->pstream, t);
+    pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    /* Please note that we don't update s->proplist here, because we
+     * don't export that field */
+
+    return o;
+}
+
+pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+    const char * const*k;
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, keys && keys[0], PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(
+            s->context,
+            s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST,
+            &tag);
+    pa_tagstruct_putu32(t, s->channel);
+
+    for (k = keys; *k; k++)
+        pa_tagstruct_puts(t, *k);
+
+    pa_tagstruct_puts(t, NULL);
+
+    pa_pstream_send_tagstruct(s->context->pstream, t);
+    pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    /* Please note that we don't update s->proplist here, because we
+     * don't export that field */
+
+    return o;
+}

Modified: branches/glitch-free/src/pulse/stream.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/stream.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/stream.h (original)
+++ branches/glitch-free/src/pulse/stream.h Sat Mar 15 16:18:55 2008
@@ -276,12 +276,24 @@
 /** A generic notification callback */
 typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata);
 
-/** Create a new, unconnected stream with the specified name and sample type */
+/** Create a new, unconnected stream with the specified name and
+ * sample type. It is recommended to use pa_stream_new_with_proplist()
+ * instead and specify some initial properties. */
 pa_stream* pa_stream_new(
         pa_context *c                     /**< The context to create this stream in */,
         const char *name                  /**< A name for this stream */,
         const pa_sample_spec *ss          /**< The desired sample format */,
         const pa_channel_map *map         /**< The desired channel map, or NULL for default */);
+
+/** Create a new, unconnected stream with the specified name and
+ * sample type, and specify the the initial stream property
+ * list. \since 0.9.10 */
+pa_stream* pa_stream_new_with_proplist(
+        pa_context *c                     /**< The context to create this stream in */,
+        const char *name                  /**< A name for this stream */,
+        const pa_sample_spec *ss          /**< The desired sample format */,
+        const pa_channel_map *map         /**< The desired channel map, or NULL for default */,
+        pa_proplist *p                    /**< The initial property list */);
 
 /** Decrease the reference counter by one */
 void pa_stream_unref(pa_stream *s);
@@ -510,6 +522,17 @@
  * is at least PulseAudio 0.9.8. \since 0.9.8 */
 pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata);
 
+/* Update the property list of the sink input/source output of this
+ * stream, adding new entries. Please note that it is highly
+ * recommended to set as much properties initially via
+ * pa_stream_new_with_proplist() as possible instead a posteriori with
+ * this function, since that information may then be used to route
+ * this stream to the right device. \since 0.9.10 */
+pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_proplist *p, pa_stream_success_cb_t cb, void *userdata);
+
+/* Update the property list of the sink input/source output of this stream, remove entries. \since 0.9.10 */
+pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata);
+
 PA_C_DECL_END
 
 #endif

Modified: branches/glitch-free/src/pulse/volume.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/pulse/volume.h?rev=2121&root=pulseaudio&r1=2120&r2=2121&view=diff
==============================================================================
--- branches/glitch-free/src/pulse/volume.h (original)
+++ branches/glitch-free/src/pulse/volume.h Sat Mar 15 16:18:55 2008
@@ -101,10 +101,10 @@
 typedef uint32_t pa_volume_t;
 
 /** Normal volume (100%) */
-#define PA_VOLUME_NORM (0x10000)
+#define PA_VOLUME_NORM ((pa_volume_t) 0x10000)
 
 /** Muted volume (0%) */
-#define PA_VOLUME_MUTED (0)
+#define PA_VOLUME_MUTED ((pa_volume_t) 0)
 
 /** A structure encapsulating a per-channel volume */
 typedef struct pa_cvolume {




More information about the pulseaudio-commits mailing list