]> code.delx.au - pulseaudio/blobdiff - src/utils/pacat.c
pacat: allow configuration of latency in msec
[pulseaudio] / src / utils / pacat.c
index d6c04db77e464a979a6e28af7d993301fbcd879c..1036af650ba091a2fb2a1b706a3fbc765f2d1522 100644 (file)
@@ -45,6 +45,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/sndfile-util.h>
+#include <pulsecore/core-util.h>
 
 #define TIME_EVENT_USEC 50000
 
@@ -86,6 +87,7 @@ static sf_count_t (*writef_function)(SNDFILE *_sndfile, const void *ptr, sf_coun
 static pa_stream_flags_t flags = 0;
 
 static size_t latency = 0, process_time = 0;
+static int32_t latency_msec = 0, process_time_msec = 0;
 
 static pa_bool_t raw = TRUE;
 static int file_format = -1;
@@ -430,19 +432,29 @@ static void context_state_callback(pa_context *c, void *userdata) {
             pa_stream_set_event_callback(stream, stream_event_callback, NULL);
             pa_stream_set_buffer_attr_callback(stream, stream_buffer_attr_callback, NULL);
 
-            if (latency > 0) {
-                memset(&buffer_attr, 0, sizeof(buffer_attr));
-                buffer_attr.tlength = (uint32_t) latency;
-                buffer_attr.minreq = (uint32_t) process_time;
-                buffer_attr.maxlength = (uint32_t) -1;
-                buffer_attr.prebuf = (uint32_t) -1;
-                buffer_attr.fragsize = (uint32_t) latency;
+            pa_zero(buffer_attr);
+            buffer_attr.maxlength = (uint32_t) -1;
+            buffer_attr.prebuf = (uint32_t) -1;
+
+            if (latency_msec > 0) {
+                buffer_attr.fragsize = buffer_attr.tlength = pa_usec_to_bytes(latency_msec * PA_USEC_PER_MSEC, &sample_spec);
                 flags |= PA_STREAM_ADJUST_LATENCY;
-            }
+            } else if (latency > 0) {
+                buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) latency;
+                flags |= PA_STREAM_ADJUST_LATENCY;
+            } else
+                buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) -1;
+
+            if (process_time_msec > 0) {
+                buffer_attr.minreq = pa_usec_to_bytes(process_time_msec * PA_USEC_PER_MSEC, &sample_spec);
+            } else if (process_time > 0)
+                buffer_attr.minreq = (uint32_t) process_time;
+            else
+                buffer_attr.minreq = (uint32_t) -1;
 
             if (mode == PLAYBACK) {
                 pa_cvolume cv;
-                if (pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL) < 0) {
+                if (pa_stream_connect_playback(stream, device, &buffer_attr, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL) < 0) {
                     pa_log(_("pa_stream_connect_playback() failed: %s"), pa_strerror(pa_context_errno(c)));
                     goto fail;
                 }
@@ -630,9 +642,11 @@ static void help(const char *argv0) {
              "      --no-remap                        Map channels by index instead of name.\n"
              "      --latency=BYTES                   Request the specified latency in bytes.\n"
              "      --process-time=BYTES              Request the specified process time per request in bytes.\n"
+             "      --latency-msec=MSEC               Request the specified latency in msec.\n"
+             "      --process-time-msec=MSEC          Request the specified process time per request in msec.\n"
              "      --property=PROPERTY=VALUE         Set the specified property to the specified value.\n"
              "      --raw                             Record/play raw PCM data.\n"
-             "      --file-format=FFORMAT             Record/play formatted PCM data.\n"
+             "      --file-format[=FFORMAT]           Record/play formatted PCM data.\n"
              "      --list-file-formats               List available file formats.\n")
            , argv0);
 }
@@ -655,7 +669,9 @@ enum {
     ARG_RAW,
     ARG_PROPERTY,
     ARG_FILE_FORMAT,
-    ARG_LIST_FILE_FORMATS
+    ARG_LIST_FILE_FORMATS,
+    ARG_LATENCY_MSEC,
+    ARG_PROCESS_TIME_MSEC
 };
 
 int main(int argc, char *argv[]) {
@@ -691,6 +707,8 @@ int main(int argc, char *argv[]) {
         {"raw",          0, NULL, ARG_RAW},
         {"file-format",  2, NULL, ARG_FILE_FORMAT},
         {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS},
+        {"latency-msec", 1, NULL, ARG_LATENCY_MSEC},
+        {"process-time-msec", 1, NULL, ARG_PROCESS_TIME_MSEC},
         {NULL,           0, NULL, 0}
     };
 
@@ -768,7 +786,6 @@ int main(int argc, char *argv[]) {
 
             case ARG_STREAM_NAME: {
                 char *t;
-                t = pa_locale_to_utf8(optarg);
 
                 if (!(t = pa_locale_to_utf8(optarg)) ||
                     pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) {
@@ -851,6 +868,20 @@ int main(int argc, char *argv[]) {
                 }
                 break;
 
+            case ARG_LATENCY_MSEC:
+                if (((latency_msec = (int32_t) atoi(optarg))) <= 0) {
+                    pa_log(_("Invalid latency specification '%s'"), optarg);
+                    goto quit;
+                }
+                break;
+
+            case ARG_PROCESS_TIME_MSEC:
+                if (((process_time_msec = (int32_t) atoi(optarg))) <= 0) {
+                    pa_log(_("Invalid process time specification '%s'"), optarg);
+                    goto quit;
+                }
+                break;
+
             case ARG_PROPERTY: {
                 char *t;
 
@@ -903,7 +934,7 @@ int main(int argc, char *argv[]) {
 
         filename = argv[optind];
 
-        if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
+        if ((fd = pa_open_cloexec(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
             pa_log(_("open(): %s"), strerror(errno));
             goto quit;
         }