shithub: sox

Download patch

ref: 48d4c6c3b9c56f16f5227754fd93d3b1cb004647
parent: f9c7137a5e8469a19b7d81d97d9dbbf9ca3d2b38
author: rrt <rrt>
date: Fri May 4 19:26:36 EDT 2007

Load format modules properly dynamically, by scanning the directory,
and remove the compile-time list from handlers.c.

Fix copyright notice in sox.c to refer to "program" rather than
"library". Especially confusing as it was correct about the GPL rather
than the LPGL!

--- a/src/handlers.c
+++ b/src/handlers.c
@@ -9,97 +9,9 @@
 
 #include "sox_i.h"
 
-/*
- * libSoX file format and effect tables.
- */
-
-#define PLUGIN(module) {#module, NULL}
-
-/* File format handlers. */
-sox_format_tab_t sox_format_fns[] = {
-  /* Built-in formats */
-  PLUGIN(auto),
-
-  /* Raw file formats */
-  PLUGIN(raw),
-  PLUGIN(s1),
-  PLUGIN(s2),
-  PLUGIN(s3),
-  PLUGIN(s4),
-  PLUGIN(u1),
-  PLUGIN(u2),
-  PLUGIN(u3),
-  PLUGIN(u4),
-  PLUGIN(al),
-  PLUGIN(la),
-  PLUGIN(ul),
-  PLUGIN(lu),
-
-  /* Plugin file formats */
-  PLUGIN(aiff),
-  PLUGIN(aifc),
-#ifdef HAVE_LIBAMRWB
-  PLUGIN(amr_wb),
-#endif
-  PLUGIN(au),
-  PLUGIN(avr),
-  PLUGIN(cdr),
-  PLUGIN(cvsd),
-  PLUGIN(dvms),
-  PLUGIN(dat),
-#ifdef HAVE_LIBAVPLUGIN
-  PLUGIN(ffmpeg),
-#endif
-#ifdef HAVE_LIBFLAC
-  PLUGIN(flac),
-#endif
-  PLUGIN(gsm),
-  PLUGIN(hcom),
-  PLUGIN(lpc10),
-  PLUGIN(maud),
-#if defined(HAVE_LIBMAD) || defined(HAVE_LIBMP3LAME)
-  PLUGIN(mp3),
-#endif
-  PLUGIN(nul),
-  PLUGIN(prc),
-  PLUGIN(sf),
-  PLUGIN(smp),
-  PLUGIN(sndrtool),
-  PLUGIN(sphere),
-  PLUGIN(svx),
-  PLUGIN(txw),
-  PLUGIN(voc),
-#if defined HAVE_LIBVORBISENC && defined HAVE_LIBVORBISFILE
-  PLUGIN(vorbis),
-#endif
-  PLUGIN(vox),
-  PLUGIN(ima),
-  PLUGIN(wav),
-  PLUGIN(wve),
-  PLUGIN(xa),
-  /* Prefer internal formats over libsndfile by placing sndfile last
-     Can be overridden by using -t sndfile. */
-#ifdef HAVE_SNDFILE_H
-  PLUGIN(sndfile),
-#endif
-
-  /* I/O formats */
-#ifdef HAVE_ALSA
-  PLUGIN(alsa),
-#endif
-#ifdef HAVE_LIBAO
-  PLUGIN(ao),
-#endif
-#ifdef HAVE_OSS
-  PLUGIN(oss),
-#endif
-#ifdef HAVE_SUN_AUDIO
-  PLUGIN(sun),
-#endif
-
-  /* End marker */
-  {NULL, NULL}
-};
+#define MAX_FORMATS 256
+unsigned sox_formats = 0;
+sox_format_tab_t sox_format_fns[MAX_FORMATS];
 
 /* Effects handlers. */
 
--- a/src/sox.c
+++ b/src/sox.c
@@ -6,12 +6,12 @@
  * Copyright 1991 Lance Norskog And Sundry Contributors
  * Copyright 1998-2007 Chris Bagnall and SoX contributors
  *
- * This library is free software; you can redistribute it and/or
+ * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
@@ -58,7 +58,7 @@
 #endif
 
 static sox_bool play = sox_false, rec = sox_false;
-static plugins_initted = sox_false;
+static sox_bool plugins_initted = sox_false;
 static enum {sox_sequence, sox_concatenate, sox_mix, sox_merge} combine_method = sox_concatenate;
 static sox_size_t mixing_clips = 0;
 static sox_bool repeatable_random = sox_false;  /* Whether to invoke srand. */
@@ -446,10 +446,32 @@
   }
 }
 
-static void init_plugins(void)
+#define MAX_NAME_LEN 1024
+static int init_format(const char *file, lt_ptr data)
 {
+  lt_dlhandle lth = lt_dlopenext(file);
+  char *end = file + strlen(file);
+  const char prefix[] = "libsox_fmt_";
+  char fnname[MAX_NAME_LEN];
+  char *start = strstr(file, prefix) + sizeof(prefix) - 1;
+
+  (void)data;
+  if (start < end) {
+    int ret = snprintf(fnname, MAX_NAME_LEN, "sox_%.*s_format_fn", end - start, start);
+    if (ret > 0 && ret < MAX_NAME_LEN) {
+      sox_format_fns[sox_formats].fn = (sox_format_fn_t)lt_dlsym(lth, fnname);
+      sox_debug("opening format plugin `%s': library %p, entry point %p\n", fnname, lth, sox_format_fns[sox_formats].fn);
+      sox_formats++;
+      return 0;
+    }
+  }
+
+  return -1;
+}
+
+static void find_formats(void)
+{
   int ret;
-  size_t i;
 
   if ((ret = lt_dlinit()) != 0) {
     sox_fail("lt_dlinit failed with %d error(s): %s", ret, lt_dlerror());
@@ -457,23 +479,7 @@
   }
   plugins_initted = sox_true;
 
-  for (i = 0; sox_format_fns[i].name || sox_format_fns[i].fn; i++) {
-    if (sox_format_fns[i].name) { /* Try to load plugin */
-#define MAX_NAME_LEN 1024
-      char name[MAX_NAME_LEN];
-      int sn = snprintf(name, MAX_NAME_LEN, PKGLIBDIR "/libsox_fmt_%s.la", sox_format_fns[i].name);
-      
-      if (sn < MAX_NAME_LEN) {
-        char fnname[MAX_NAME_LEN];
-        lt_dlhandle lth = lt_dlopen(name);
-        
-        snprintf(fnname, MAX_NAME_LEN, "sox_%s_format_fn", sox_format_fns[i].name);
-        sox_format_fns[i].fn = (sox_format_fn_t)lt_dlsym(lth, fnname);
-        sox_debug("opening format plugin `%s': library %p, entry point %p\n", name, lth, sox_format_fns[i].fn);
-      }
-    } else
-      sox_debug("opening builtin format `%s': entry point %p\n", sox_format_fns[i].fn()->names[0], sox_format_fns[i].fn);
-  }
+  lt_dlforeachfile(PKGLIBDIR, init_format, NULL);
 }
 
 int main(int argc, char **argv)
@@ -500,7 +506,7 @@
 
   /* Load plugins (after options so we can output debugging messages
      if desired) */
-  init_plugins();
+  find_formats();
   
   /* Allocate buffers, size of which may have been set by --buffer */
   ibufl = xcalloc(sox_bufsiz / 2, sizeof(sox_ssample_t));
@@ -1948,7 +1954,7 @@
          "\n");
 
   printf("SUPPORTED FILE FORMATS:");
-  for (i = 0, formats = 0; sox_format_fns[i].name || sox_format_fns[i].fn; i++) {
+  for (i = 0, formats = 0; i < sox_formats; i++) {
     if (sox_format_fns[i].fn) {
       char const * const *names = sox_format_fns[i].fn()->names;
       while (*names++)
@@ -1957,7 +1963,7 @@
   }
   formats += 2;
   format_list = (const char **)xmalloc(formats * sizeof(char *));
-  for (i = 0, formats = 0; sox_format_fns[i].name || sox_format_fns[i].fn; i++) {
+  for (i = 0, formats = 0; i < sox_formats; i++) {
     if (sox_format_fns[i].fn) {
       char const * const *names = sox_format_fns[i].fn()->names;
       while (*names)
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -64,6 +64,11 @@
 sox_bool is_uri(char const * text);
 FILE * xfopen(char const * identifier, char const * mode);
 
+/* Function we supply if it's missing from system libc */
+#ifndef HAVE_STRRSTR
+char *strrstr(const char *s, const char *t);
+#endif
+
 /* Define fseeko and ftello for platforms lacking them */
 #ifndef HAVE_FSEEKO
 #define fseeko fseek
@@ -226,6 +231,7 @@
   sox_format_fn_t fn;
 } sox_format_tab_t;
 
+extern unsigned sox_formats;
 extern sox_format_tab_t sox_format_fns[];
 
 const sox_format_t *sox_auto_format_fn(void);
--- a/src/sunaudio.c
+++ b/src/sunaudio.c
@@ -309,13 +309,13 @@
 }
 
 /* Sun /dev/audio player */
-static const char *sunnames[] = {
+static const char *names[] = {
   "sunau",
   NULL
 };
 
-static sox_format_t sox_sun_format = {
-  sunnames,
+static sox_format_t sox_sunau_format = {
+  names,
   SOX_FILE_DEVICE,
   sox_sunstartread,
   sox_rawread,
@@ -326,11 +326,11 @@
   sox_format_nothing_seek
 };
 
-const sox_format_t *sox_sun_format_fn(void);
+const sox_format_t *sox_sunau_format_fn(void);
 
-const sox_format_t *sox_sun_format_fn(void)
+const sox_format_t *sox_sunau_format_fn(void)
 {
-    return &sox_sun_format;
+    return &sox_sunau_format;
 }
 
 #endif
--- a/src/util.c
+++ b/src/util.c
@@ -123,8 +123,8 @@
         sox_fail_errno(formp, SOX_EFMT, "Filetype was not specified");
         return SOX_EFMT;
     }
-    for (i = 0; sox_format_fns[i].fn || sox_format_fns[i].name; i++) {
-      /* FIXME: make this code easier to write  */
+    for (i = 0; i < sox_formats; i++) {
+      /* FIXME: add only non-NULL formats to the list */
       if (sox_format_fns[i].fn) {
         const sox_format_t *f = sox_format_fns[i].fn();
         if (is_file_extension && (f->flags & SOX_FILE_DEVICE))