shithub: sox

Download patch

ref: a47bf7b62b44263a454c9c3f112dbf0d7b930bc1
parent: 21fd3cdec88d01cdbfbde2316e88fb2406f9abb6
author: robs <robs>
date: Sun Mar 11 03:50:58 EDT 2007

Added M3U and internet support.

--- a/AUTHORS
+++ b/AUTHORS
@@ -88,9 +88,10 @@
 		Build system makeover, Lua scripting, Secret Rabbit
                 Code resampling, much cleanup.
 	Rob Sykes		robs@users.sourceforge.net
-		Bass & treble effects, FLAC & AMR-WB formats, initial 24bit
-		support, filters makeover inc. octave plots, new flanger,
-                file merging, speed via resampling, soft-knee companding,
-                pad effect, various fixes, enhancements and clean-ups,
-		much manual improvement and expansion, play multiple
-                files with mixed format types.
+                Formats: M3U, FLAC, AMR-WB, 24bit support for popular formats.
+		Effects: pad, bass, treble, new flanger, soft-knee companding,
+                speed via resampling, filters makeover inc. octave plots.
+                Others: open input files via URL, file merging, play
+                multiple files with mixed format types, much manual
+                improvement and expansion, various fixes, enhancements
+                and clean-ups.
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,8 +11,8 @@
 
   o Added support for ADPCM-encoded PRC files, based on Danny Smith's
     rec2wav and sndcmp.
-
   o Added AMR-WB format.  (robs)
+  o Added M3U playlist format [FR# 1667341].  (robs)
 
   Effects:
 
@@ -23,6 +23,7 @@
   Other new features:
 
   o Show (with -S) if clipping is occurring.  (robs)
+  o Added internet input file support (needs wget).  (robs)
 
   Bug fixes:
 
@@ -38,6 +39,7 @@
     duplications with other existing libst libraries. (Rueben)
   o Renamed libst-config to more standard sox-config. (cbagwell)
   o Removed library information from sox-config --cflags. (cbagwell)
+  o Got rid of several hundred compiler warnings.  (robs)
 
 sox-13.0.0
 ----------
--- a/sox.1
+++ b/sox.1
@@ -375,6 +375,18 @@
 differently: pressing it once causes SoX to skip to the next file;
 pressing it twice in quick succession causes SoX to exit.
 .SH FILENAMES
+Filenames can be simple file names, absolute or relative path names,
+or URLs (inut files only).  Note that URL support requires that
+.BR wget (1)
+is available.
+.SP
+Note:
+Giving SoX an input or output filename that is the same as a SoX
+effect-name will not work since SoX will treat it as an effect
+specification.  The only work-around to this is to avoid such
+filenames; however, this is generally not difficult since most audio
+filenames have a filename `extension', whilst effect-names do not.
+.SP
 The following `special' filenames may be used in certain circumstances
 in place of a normal filename on the command line:
 .TP
@@ -425,13 +437,6 @@
 This is an alias of
 .B \-n
 and is retained for backwards compatibility only.
-.PP
-.B N.B.
-Giving SoX an input or output filename that is the same as a SoX
-effect-name will not work since SoX will treat it as an effect
-specification.  The only work-around to this is to avoid such
-filenames; however, this is generally not difficult since most audio
-filenames have a filename `extension', whilst effect-names do not.
 .SH OPTIONS
 .SS Global Options
 These options can be specified on the command line at any point
@@ -955,6 +960,12 @@
 \&\fB.mat\fR, \fB.mat4\fR, \fB.mat5\fR \fB(libsndfile)\fR
 Matlab 4.2/5.0 (respectively GNU Octave 2.0/2.1) format (.mat is the same as .mat4).
 .TP
+.B .m3u
+A
+.I playlist
+format; contains a list of audio files.
+See [5] for details of this format.
+.TP
 .B .maud
 An IFF-conforming audio file type, registered by
 MS MacroSystem Computer GmbH, published along
@@ -2229,7 +2240,8 @@
 (sox-users@lists.sourceforge.net).
 .SH SEE ALSO
 .BR soxexam (7),
-.BR libsox (3)
+.BR libsox (3),
+.BR wget (1)
 .SP
 The SoX web page at http://sox.sourceforge.net
 .SS References
@@ -2253,6 +2265,11 @@
 Wikipedia,
 .IR "Decibel" ,
 http://en.wikipedia.org/wiki/Decibel
+.TP
+[5]
+Wikipedia,
+.IR "M3U" ,
+http://en.wikipedia.org/wiki/M3U
 .SH LICENSE
 Copyright 1991 Lance Norskog and Sundry Contributors.
 Copyright 1998\-2007 by Chris Bagwell and SoX Contributors.
--- a/src/sox.c
+++ b/src/sox.c
@@ -30,6 +30,7 @@
 #include <signal.h>
 #include <sys/time.h>
 #include <time.h>
+#include <ctype.h>
 #include <errno.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>             /* for unlink() */
@@ -266,6 +267,99 @@
   }
 }
 
+static sox_bool is_playlist(char const * filename)
+{
+  size_t  i = strlen(filename);
+  return i >= sizeof(".m3u") - 1 &&
+    strcasecmp(filename + i - (sizeof(".m3u") - 1), ".m3u") == 0;
+}
+
+static void parse_playlist(const file_t f0, char const * const filename)
+{
+  size_t text_length = 100;
+  char * text = xmalloc(text_length + 1);
+  char * dirname = xstrdup(filename);
+#if defined(DOS) || defined(WIN32)
+  char * slash_pos = max(strrchr(dirname, '/'), strrchr(dirname, '\\'));
+#else
+  char * slash_pos = strrchr(dirname, '/');
+#endif
+  FILE * file = xfopen(filename, "r");
+  int c;
+
+  if (!slash_pos)
+    *dirname = '\0';
+  else
+    *slash_pos = '\0';
+
+  if (file == NULL) {
+    sox_fail("Can't open playlist file `%s': %s", filename, strerror(errno));
+    exit(1);
+  }
+
+  do {
+    size_t i = 0;
+    char * last = NULL;
+
+    while (isspace(c = getc(file)));
+    if (c == EOF)
+      break;
+    while (c != EOF && !strchr("#\r\n", c)) {
+      if (i == text_length)
+        text = xrealloc(text, (text_length <<= 1) + 1);
+      text[i] = c;
+      if (!strchr(" \t\f", c))
+        last = text + i;
+      ++i;
+      c = getc(file);
+    }
+    if (ferror(file))
+      break;
+    if (c == '#') {
+      do c = getc(file);
+      while (c != EOF && !strchr("\r\n", c));
+      if (ferror(file))
+        break;
+    }
+    if (last)  {
+      file_t f;
+
+      if (file_count >= MAX_FILES) {
+        sox_fail("Too many filenames; maximum is %d input files and 1 output file", MAX_INPUT_FILES);
+        exit(1);
+      }
+
+      last[1] = '\0';
+      f = new_file();
+      *f = *f0;
+      if (!dirname[0] || is_uri(text)
+#if defined(DOS) || defined(WIN32)
+          || text[0] == '\\' || text[1] == ':'
+#endif
+          || text[0] == '/')
+        f->filename = xstrdup(text);
+      else {
+        f->filename = xmalloc(strlen(dirname) + strlen(text) + 2); 
+        sprintf(f->filename, "%s/%s", dirname, text); 
+      }
+      if (is_playlist(f->filename)) {
+        parse_playlist(f, f->filename);
+        free(f->filename);
+        free(f);
+        continue;
+      }
+      files[file_count++] = f;
+    }
+  } while (c != EOF);
+  if (ferror(file)) {
+    sox_fail("Error reading playlist file `%s': %s", filename, strerror(errno));
+    exit(1);
+  }
+  fclose(file);
+  free(text);
+  free(dirname);
+}
+
 static void parse_options_and_filenames(int argc, char **argv)
 {
   file_t f = NULL;
@@ -288,6 +382,12 @@
     } else {
       if (optind >= argc || is_effect_name(argv[optind]))
         break;
+      if (is_playlist(argv[optind])) {
+        parse_playlist(f, argv[optind++]);
+        free(f);
+        f = NULL;
+        continue;
+      }
       f->filename = xstrdup(argv[optind++]);
     }
     files[file_count++] = f;
@@ -364,6 +464,7 @@
     usage("-v can only be given for an input file;\n"
             "\tuse 'vol' to set the output file volume");
 
+  signal(SIGINT, SIG_IGN); /* So child pipes aren't killed by track skip */
   for (i = 0; i < input_count; i++) {
     int j = input_count - 1 - i; /* Open in reverse order 'cos of rec (below) */
     file_t f = files[j];
@@ -396,6 +497,7 @@
     if (files[j]->desc->comment)
       set_replay_gain(files[j]->desc->comment, f);
   }
+  signal(SIGINT, SIG_DFL);
 
   /* Loop through the rest of the arguments looking for effects */
   parse_effects(argc, argv);
@@ -1761,6 +1863,7 @@
     while (*names++)
       formats++;
   }
+  ++formats;
   format_list = (const char **)xmalloc(formats * sizeof(char *));
   for (i = 0, formats = 0; sox_format_fns[i]; i++) {
     char const * const *names = sox_format_fns[i]()->names;
@@ -1767,6 +1870,7 @@
     while (*names)
       format_list[formats++] = *names++;
   }
+  format_list[formats++] = "m3u";
   qsort(format_list, formats, sizeof(char *), strcmp_p);
   for (i = 0; i < formats; i++)
     printf(" %s", format_list[i]);
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -149,6 +149,8 @@
 extern sox_output_message_handler_t sox_output_message_handler;
 extern int sox_output_verbosity_level;
 void sox_output_message(FILE *file, const char *filename, const char *fmt, va_list ap);
+sox_bool is_uri(char const * text);
+FILE * xfopen(char const * identifier, char const * mode);
 
 void sox_fail(const char *, ...);
 void sox_warn(const char *, ...);
--- a/src/soxio.c
+++ b/src/soxio.c
@@ -124,7 +124,7 @@
             SET_BINARY_MODE(stdin);
             ft->fp = stdin;
         }
-        else if ((ft->fp = fopen(ft->filename, "rb")) == NULL)
+        else if ((ft->fp = xfopen(ft->filename, "rb")) == NULL)
         {
             sox_warn("Can't open input file `%s': %s", ft->filename,
                     strerror(errno));
--- a/src/util.c
+++ b/src/util.c
@@ -20,6 +20,9 @@
 #include <string.h>
 #include <ctype.h>
 #include <stdarg.h>
+#ifdef _MSC_VER
+#define popen _popen
+#endif
 
 sox_output_message_handler_t sox_output_message_handler = NULL;
 int sox_output_verbosity_level = 2;
@@ -361,3 +364,30 @@
     }
     return NULL;
 }
+
+sox_bool is_uri(char const * text)
+{
+  if (!isalpha(*text))
+    return sox_false;
+  ++text;
+  do {
+    if (!isalnum(*text) && !strchr("+-.", *text))
+      return sox_false;
+    ++text;
+  } while (*text && *text != ':');
+  return *text == ':';
+}
+
+FILE * xfopen(char const * identifier, char const * mode) 
+{ 
+  if (is_uri(identifier)) {
+    FILE * f; 
+    char const * const command_format = "wget -q -O- \"%s\"";
+    char * command = xmalloc(strlen(command_format) + strlen(identifier)); 
+    sprintf(command, command_format, identifier); 
+    f = popen(command, "r"); 
+    free(command); 
+    return f;
+  }
+  return fopen(identifier, mode);
+}