Rob Browning <[EMAIL PROTECTED]> writes:

> I've nearly finished a patch here that should address these issues.

OK, here's the new patch.  As I mentioned, it does add a couple of
additional dependencies -- it uses popen/pclose, and it defines
_GNU_SOURCE so it can use GNU getline.  I don't know whether or not
that's acceptable.

With this patch saytime should automatically detect and prefer alsa
when it's available, fall back to oss otherwise, and use sox for the
output in both cases.  It also adds the -b argument to allow manual
selection of the backend.

diff --git a/debian/changelog b/debian/changelog
index 38617fa..d0135c6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+saytime (1.0-21~) unstable; urgency=low
+
+  * Add support for audio "backends", and add alsa support (in addition to
+    existing oss support).  Prefer alsa when available.
+  * Specify the rate when invoking sox so that it won't print a message.
+
+ -- Rob Browning <[EMAIL PROTECTED]>  Thu, 18 Oct 2007 22:31:37 -0700
+
 saytime (1.0-20) unstable; urgency=low
 
   * saytime.c: call sox with -q option to suppress text output (thanks to
diff --git a/debian/control b/debian/control
index ab9b245..94f10db 100644
--- a/debian/control
+++ b/debian/control
@@ -7,7 +7,7 @@ Standards-Version: 3.5.6
 
 Package: saytime
 Architecture: any
-Depends: ${shlibs:Depends}, sox (>= 12.17.9-1)
+Depends: ${shlibs:Depends}, sox (>= 12.17.9-1), libsox-fmt-oss | libsox-fmt-alsa
 Description: speaks the current time through your sound card
  Say the current time through your sound card.  Requires you have a
  sound output device available.
diff --git a/debian/local/saytime.1 b/debian/local/saytime.1
index 18cc994..088c783 100644
--- a/debian/local/saytime.1
+++ b/debian/local/saytime.1
@@ -43,7 +43,10 @@ below).
 Display simple help.
 .TP
 .BI "\-o" " dev"
-Output to alternate file (default /dev/audio).
+Specify output device.
+.TP
+.BI "\-b" " audio-backend"
+Specify audio backend.  Choose oss or alsa (default is alsa, if available).
 .SH FORMAT STRING
 A format string can be specified to control the time message.
 Valid format characters are:
diff --git a/saytime.c b/saytime.c
index d3bcb00..24d73cf 100644
--- a/saytime.c
+++ b/saytime.c
@@ -14,6 +14,8 @@
 /* modified on 2004/09/05 by David Dawson */
 /* added sanity check for negative interval on 2004/10/1 by Oohara Yuuma */
 
+#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <time.h>
 #include <sys/file.h>
@@ -29,7 +31,7 @@
 #include <sys/wait.h>
 #include <signal.h>
 
-#define DEFAULT_SOUND_DEVICE "/dev/audio"
+#define DEFAULT_OSS_SOUND_DEVICE "/dev/audio"
 #define DEFAULT_SOUND_DIR "/usr/share/saytime"
 #define DEFAULT_TIME_FORMAT "%P%l%M%S"
 #define DEFAULT_INTERVAL 1
@@ -93,6 +95,7 @@ It took about 10 minutes.
 #define PH_PM		36
 
 int opt_to_stdout = 0;
+char *opt_backend = NULL;
 char *opt_sound_device = NULL;
 char *opt_sound_dir = DEFAULT_SOUND_DIR;
 char *opt_time_format = NULL;
@@ -105,8 +108,12 @@ char *opt_test_sec;
 #endif
 void kill_daemon(int signal);
 void saynumber(), saydigit(), sayphrase(), sayfile(), usage();
+void detect_available_backends(int *alsa_available, int *oss_available);
 void sayformat(struct tm *, char *);
 int die = 0;
+int alsa_backend_available = 0;
+int oss_backend_available = 0;
+
 int main( argc, argv )
 int argc;
 char *argv[];
@@ -114,9 +121,9 @@ char *argv[];
     long clock;
     struct tm *t;
 #if defined TTEST
-    char *opt_string="v:r:co:d:f:h:H:N:C:";
+    char *opt_string="v:b:r:co:d:f:h:H:N:C:";
 #else
-    char *opt_string="v:r:co:d:f:h";
+    char *opt_string="v:b:r:co:d:f:h";
 #endif
     int  op ;
 	pid_t fpid;
@@ -148,6 +155,8 @@ char *argv[];
 						   break;
                case 'c' :  opt_to_stdout = 1;
                            break;
+               case 'b' :  opt_backend = optarg;
+                           break;
                case 'o' :  opt_sound_device = optarg;
                            break;
                case 'd' :  opt_sound_dir = optarg;
@@ -159,12 +168,35 @@ char *argv[];
          }
     }
 
+    detect_available_backends(&alsa_backend_available, &oss_backend_available);
+
+    if (opt_backend) {
+        if (strcmp("oss", opt_backend) == 0) {
+          if (!oss_backend_available) {
+              fprintf(stderr,
+                      "Specified oss backend,"
+                      " but installed sox does not support it.\n");
+              exit(1);
+          }
+        }
+        else if (strcmp("alsa", opt_backend) == 0) {
+          if (!alsa_backend_available) {
+              fprintf(stderr,
+                      "Specified alsa backend,"
+                      " but installed sox does not support it.\n");
+              exit(1);
+          }
+        }
+        else {
+            fprintf(stderr, "specified unknown backend.\n");
+            usage();
+        }
+    }
+
     if (opt_to_stdout && opt_sound_device != NULL) {
 	printf("Specifying alternate device and stdout makes no sense.\n");
 	usage();
     }
-    else if (opt_sound_device == NULL)
-	opt_sound_device = DEFAULT_SOUND_DEVICE;
 
     if (opt_time_format == NULL)
         opt_time_format = DEFAULT_TIME_FORMAT;
@@ -232,8 +264,8 @@ usage( )
     fprintf( stderr, " -f fmt\tspecify alternate time format [%s]\n",
         DEFAULT_TIME_FORMAT ) ;
     fprintf( stderr, " -h\tbrief help message\n" );
-    fprintf( stderr, " -o dev\tspecify audio device [%s]\n", 
-        DEFAULT_SOUND_DEVICE );
+    fprintf( stderr, " -o dev\tspecify audio device\n");
+    fprintf( stderr, " -b backend\tspecify audio playback system [oss|alsa]\n");
     exit( 1 );
     }
 
@@ -657,6 +689,59 @@ int phrase;
     }
 
 void
+detect_available_backends( alsa_available, oss_available )
+int *alsa_available;
+int *oss_available;
+{
+  FILE *sox_pipe;
+  char *line = NULL;
+  size_t line_n = 0;
+  int found_formats = 0;
+
+  *alsa_available = 0;
+  *oss_available = 0;
+
+  sox_pipe = popen("sox --help", "r");
+  if (!sox_pipe)
+  {
+    fprintf(stderr, "failed to run sox");
+    exit(1);
+  }
+
+  while (!found_formats && (getline(&line, &line_n, sox_pipe) >= 0))
+  {
+    const char *target = "SUPPORTED FILE FORMATS:";
+    if (strncmp(target, line, strlen(target)) == 0)
+    {
+      found_formats = 1;
+      if (strstr(line, " alsa") != NULL)
+        *alsa_available = 1;
+      if (strstr(line, " oss") != NULL)
+        *oss_available = 1;
+    }
+  }
+  if (line) free(line);
+
+  if (!found_formats && !feof(sox_pipe))
+  {
+    fprintf(stderr, "error while communicating with sox\n");
+    exit(1);
+  }
+
+  if (pclose(sox_pipe) != 0)
+  {
+    fprintf(stderr, "sox command failed\n");
+    exit(1);
+  }
+
+  if (!found_formats)
+  {
+    fprintf(stderr, "unable to find sox supported format list\n");
+    exit(1);
+  }
+}
+
+void
 sayfile( filename )
      char *filename;
 {
@@ -678,16 +763,41 @@ sayfile( filename )
   else if (pid == 0)
   {
     /* child */
+    char *backend = NULL;
+    char *device = NULL;
+
+    if (!opt_backend) /* Prefer alsa as a default if available. */
+    {
+      struct stat st;
+      if (alsa_backend_available && (stat("/proc/asound", &st) == 0))
+        opt_backend = "alsa";
+      else
+        opt_backend = "oss";
+    }
+
     if (opt_to_stdout)
     {
-      execl("/usr/bin/sox", "sox", "-q", "-v", opt_volume,"-t.ul", "-c", "1",
-            pathname, "-t", "raw", "/dev/stdout", NULL);
+      backend = "raw";
+      device = "/dev/stdout";
     }
-    else
+    else if (strcmp("alsa", opt_backend) == 0)
     {
-      execl("/usr/bin/sox", "sox", "-q", "-v", opt_volume,"-t.ul", "-c", "1",
-            pathname, "-t", "ossdsp", opt_sound_device, NULL);
+      backend = "alsa";
+      device = opt_sound_device ? opt_sound_device : "default";
     }
+    else if (strcmp("oss", opt_backend) == 0)
+    {
+      backend = "oss";
+      device = opt_sound_device ? opt_sound_device : DEFAULT_OSS_SOUND_DEVICE;
+    }
+    else /* should be impossible */
+    {
+      fprintf(stderr, "invalid backend selected (not \"oss\" or \"alsa\")\n");
+      exit(1);
+    }
+
+    execl("/usr/bin/sox", "sox", "-q", "-v", opt_volume, "-r", "8000",
+          "-t.ul", "-c", "1", pathname, "-t", backend, device, NULL);
     fprintf(stderr, "execl failed\n");
     exit(1);
   }
Thanks
-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG as of 2002-11-03 14DD 432F AE39 534D B592 F9A0 25C8 D377 8C7E 73A4

Reply via email to