* Ed Schouten <[EMAIL PROTECTED]> wrote:
> Maybe this evening I'll take a look if it's possible to delay the
> opening of the stream when the `ss' argument is NULL, so I can call
> pa_simple_new() to already instantiate the connection to the daemon
> before the chroot() call.

Done. I did fix it in another way though. I split up the pa_simple_new()
routine in two separate routines. The first one only opens the
connection to the server and the latter creates the actual stream. So
far it works quite good, with one nasty side-effect: it cannot unlink
the shared memory at shutdown.

I'm still thinking of a nice way to work around this. Anyway, here's a
first version of the patch, which also makes the mmap() calls work on
FreeBSD.

Yours,
-- 
 Ed Schouten <[EMAIL PROTECTED]>
 WWW: http://g-rave.nl/
--- src/pulse/simple.c	Fri Aug 18 23:29:25 2006
+++ src/pulse/simple.c	Tue Jun  5 17:44:38 2007
@@ -136,27 +136,16 @@
 pa_simple* pa_simple_new(
     const char *server,
     const char *name,
-    pa_stream_direction_t dir,
-    const char *dev,
-    const char *stream_name,
-    const pa_sample_spec *ss,
-    const pa_channel_map *map,
-    const pa_buffer_attr *attr,
     int *rerror) {
     
     pa_simple *p;
-    int error = PA_ERR_INTERNAL, r;
+    int error = PA_ERR_INTERNAL;
 
     CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
-    CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
-    CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
-    CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
-    CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL)
 
     p = pa_xnew(pa_simple, 1);
     p->context = NULL;
     p->stream = NULL;
-    p->direction = dir;
     p->read_data = NULL;
     p->read_index = p->read_length = 0;
 
@@ -186,47 +175,84 @@
         goto unlock_and_fail;
     }
 
-    if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
-        error = pa_context_errno(p->context);
+    pa_threaded_mainloop_unlock(p->mainloop);
+    
+    return p;
+
+unlock_and_fail:
+    pa_threaded_mainloop_unlock(p->mainloop);
+    
+fail:
+    if (rerror)
+        *rerror = error;
+    pa_simple_free(p);
+    return NULL;
+}
+
+int pa_simple_configure(
+    pa_simple *s,
+    pa_stream_direction_t dir,
+    const char *dev,
+    const char *stream_name,
+    const pa_sample_spec *ss,
+    const pa_channel_map *map,
+    const pa_buffer_attr *attr,
+    int *rerror) {
+
+    int error = PA_ERR_INTERNAL, r;
+
+    CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, -1);
+    CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, -1);
+    CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, -1);
+    CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, -1);
+
+    s->direction = dir;
+    
+    pa_threaded_mainloop_lock(s->mainloop);
+
+    /* Close the original stream */
+    if (s->stream)
+        pa_stream_unref(s->stream);
+    if (!(s->stream = pa_stream_new(s->context, stream_name, ss, map))) {
+        error = pa_context_errno(s->context);
         goto unlock_and_fail;
     }
 
-    pa_stream_set_state_callback(p->stream, stream_state_cb, p);
-    pa_stream_set_read_callback(p->stream, stream_request_cb, p);
-    pa_stream_set_write_callback(p->stream, stream_request_cb, p);
-    pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
+    pa_stream_set_state_callback(s->stream, stream_state_cb, s);
+    pa_stream_set_read_callback(s->stream, stream_request_cb, s);
+    pa_stream_set_write_callback(s->stream, stream_request_cb, s);
+    pa_stream_set_latency_update_callback(s->stream, stream_latency_update_cb, s);
 
     if (dir == PA_STREAM_PLAYBACK)
-        r = pa_stream_connect_playback(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
+        r = pa_stream_connect_playback(s->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
     else
-        r = pa_stream_connect_record(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE);
+        r = pa_stream_connect_record(s->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE);
 
     if (r < 0) {
-        error = pa_context_errno(p->context);
+        error = pa_context_errno(s->context);
         goto unlock_and_fail;
     }
 
     /* Wait until the stream is ready */
-    pa_threaded_mainloop_wait(p->mainloop);
+    pa_threaded_mainloop_wait(s->mainloop);
 
     /* Wait until the stream is ready */
-    if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
-        error = pa_context_errno(p->context);
+    if (pa_stream_get_state(s->stream) != PA_STREAM_READY) {
+        error = pa_context_errno(s->context);
         goto unlock_and_fail;
     }
 
-    pa_threaded_mainloop_unlock(p->mainloop);
-    
-    return p;
+    pa_threaded_mainloop_unlock(s->mainloop);
+
+    return 0;
 
 unlock_and_fail:
-    pa_threaded_mainloop_unlock(p->mainloop);
+    pa_threaded_mainloop_unlock(s->mainloop);
     
 fail:
     if (rerror)
         *rerror = error;
-    pa_simple_free(p);
-    return NULL;
+    return -1;
 }
 
 void pa_simple_free(pa_simple *s) {
--- src/pulse/simple.h	Tue Jun 20 01:53:23 2006
+++ src/pulse/simple.h	Tue Jun  5 17:39:11 2007
@@ -114,6 +114,12 @@
 pa_simple* pa_simple_new(
     const char *server,                 /**< Server name, or NULL for default */
     const char *name,                   /**< A descriptive name for this client (application name, ...) */
+    int *error                          /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */
+    );
+
+/** Configure a connection to the server */
+int pa_simple_configure(
+    pa_simple *s,			/**< Connection to the server */
     pa_stream_direction_t dir,          /**< Open this stream for recording or playback? */
     const char *dev,                    /**< Sink (resp. source) name, or NULL for default */
     const char *stream_name,            /**< A descriptive name for this client (application name, song title, ...) */
--- src/pulsecore/shm.c	Fri Aug 25 01:56:34 2006
+++ src/pulsecore/shm.c	Tue Jun  5 19:24:35 2007
@@ -67,8 +67,8 @@
         m->id = 0;
         m->size = size;
 
-#ifdef MAP_ANONYMOUS
-        if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+#ifdef MAP_ANON
+        if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
             pa_log("mmap() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
@@ -140,7 +140,7 @@
 #endif
 
 	if (!m->shared) {
-#ifdef MAP_ANONYMOUS
+#ifdef MAP_ANON
 	    if (munmap(m->ptr, m->size) < 0)
 	        pa_log("munmap() failed: %s", pa_cstrerror(errno));
 #elif defined(HAVE_POSIX_MEMALIGN)
@@ -158,7 +158,7 @@
 
     	    segment_name(fn, sizeof(fn), m->id);
 
-	        if (shm_unlink(fn) < 0)
+	        if (shm_unlink(fn) < 0 && errno != ENOENT)
     	        pa_log(__FILE__":shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
 	    }
 #else
@@ -251,7 +251,7 @@
         goto fail;
     }
 
-    m->do_unlink = 0;
+    m->do_unlink = 1;
     m->shared = 1;
     
     close(fd);
--- src/tests/pacat-simple.c	Fri Aug 18 23:29:26 2006
+++ src/tests/pacat-simple.c	Tue Jun  5 17:54:19 2007
@@ -66,8 +66,12 @@
     }
     
     /* Create a new playback stream */
-    if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) {
+    if (!(s = pa_simple_new(NULL, argv[0], &error))) {
         fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
+        goto finish;
+    }
+    if (pa_simple_configure(s, PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error) != 0) {
+        fprintf(stderr, __FILE__": pa_simple_configure() failed: %s\n", pa_strerror(error));
         goto finish;
     }
 
--- src/tests/parec-simple.c	Fri Aug 18 23:29:26 2006
+++ src/tests/parec-simple.c	Tue Jun  5 17:52:47 2007
@@ -67,8 +67,12 @@
     int error;
 
     /* Create the recording stream */
-    if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
+    if (!(s = pa_simple_new(NULL, argv[0], &error))) {
         fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
+        goto finish;
+    }
+    if (pa_simple_configure(s, PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error) != 0) {
+        fprintf(stderr, __FILE__": pa_simple_configure() failed: %s\n", pa_strerror(error));
         goto finish;
     }
 

Attachment: pgpB4APaY5Oq2.pgp
Description: PGP signature

_______________________________________________
pulseaudio-discuss mailing list
[email protected]
https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss

Reply via email to