From 34e37f1bbf484bab039eb63d95bb809bb501a7d9 Mon Sep 17 00:00:00 2001
From: "Silas S. Brown" <ssb22@cam.ac.uk>
Date: Wed, 19 Feb 2020 00:04:58 +0000
Subject: [PATCH] check sox for mp3 capability (fixes #1 on GitHub)

---
 gradint-build/Makefile          |  2 +-
 gradint-build/src/booktime.py   |  2 +-
 gradint-build/src/filescan.py   |  2 +-
 gradint-build/src/frontend.py   |  2 +-
 gradint-build/src/lessonplan.py |  2 +-
 gradint-build/src/loop.py       |  2 +-
 gradint-build/src/makeevent.py  |  2 +-
 gradint-build/src/play.py       | 16 ++++++++--------
 gradint-build/src/recording.py  |  2 +-
 gradint-build/src/sequence.py   |  2 +-
 gradint-build/src/synth.py      |  2 +-
 gradint-build/src/system.py     |  2 +-
 gradint-build/src/top.py        | 15 ++++++++-------
 gradint-build/src/users.py      |  2 +-
 gradint-build/thindown.py       |  2 +-
 15 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/gradint-build/Makefile b/gradint-build/Makefile
index 97690c1..ee9f6f3 100644
--- a/gradint-build/Makefile
+++ b/gradint-build/Makefile
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/booktime.py b/gradint-build/src/booktime.py
index bc5fabd..6c74fa0 100644
--- a/gradint-build/src/booktime.py
+++ b/gradint-build/src/booktime.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/filescan.py b/gradint-build/src/filescan.py
index e65b76b..eaf1f0d 100644
--- a/gradint-build/src/filescan.py
+++ b/gradint-build/src/filescan.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/frontend.py b/gradint-build/src/frontend.py
index 15b55e0..68a8d44 100644
--- a/gradint-build/src/frontend.py
+++ b/gradint-build/src/frontend.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/lessonplan.py b/gradint-build/src/lessonplan.py
index 57c60aa..9ddc2fe 100644
--- a/gradint-build/src/lessonplan.py
+++ b/gradint-build/src/lessonplan.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/loop.py b/gradint-build/src/loop.py
index c82c9f8..f428e13 100644
--- a/gradint-build/src/loop.py
+++ b/gradint-build/src/loop.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/makeevent.py b/gradint-build/src/makeevent.py
index b0a050d..757a1dc 100644
--- a/gradint-build/src/makeevent.py
+++ b/gradint-build/src/makeevent.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/play.py b/gradint-build/src/play.py
index 78000d1..2ece0c6 100644
--- a/gradint-build/src/play.py
+++ b/gradint-build/src/play.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
@@ -131,11 +131,10 @@ if unix:
     else: sox_ignoreLen = "|sox --ignore-length -t wav - -t wav - 2>/dev/null"
     if soxMaj==14 and sf2[13]<'4': sox_8bit, sox_16bit = "-1", "-2" # see comment above
     else: sox_8bit, sox_16bit, sox_signed = "-b 8", "-b 16", "-e signed-integer" # TODO: check if 14.3 accepts these also (at least 14.4 complains -2 etc is deprecated)
-   if sf2.find("wav")>=0: return 1
-   else: return 0
-  gotSox = sox_check()
+   return sf2.find("wav")>=0, sf2.find("mp3")>=0
+  gotSox,soxMp3 = sox_check()
   if macsound:
-      if not gotSox and not os.system("mv sox-14.4.2 sox && rm sox.README"): gotSox = sox_check() # see if that one works instead (NB must use os.system here: our system() has not yet been defined)
+      if not gotSox and not os.system("mv sox-14.4.2 sox && rm sox.README"): gotSox,soxMp3 = sox_check() # see if that one works instead (NB must use os.system here: our system() has not yet been defined)
   if not gotSox and got_program("sox"):
       if macsound: xtra=". (If you're on 10.8 Mountain Lion, try downloading a more recent sox binary from sox.sourceforge.net and putting it inside Gradint.app, but that will break compatibility with older PowerPC Macs.)" # TODO: ship TWO binaries? but we don't want the default gradint to get too big. See sox.README for more notes.
       elif cygwin: xtra=""
@@ -328,7 +327,7 @@ class SampleEvent(Event):
             if wavPlayer.find("start")>=0: time.sleep(max(0,self.length-(time.time()-t))) # better do this - don't want events overtaking each other if there are delays.  exactLen not always enough.  (but do subtract the time already taken, in case command extensions have been disabled and "start" is synchronous.)
             os.chdir(oldDir)
         elif fileType=="mp3" and mp3Player and not sox_effect and not (wavPlayer=="aplay" and mp3Player==madplay_path): return system(mp3Player+' "'+self.file+'"')
-        elif wavPlayer=="sox":
+        elif wavPlayer=="sox" and (soxMp3 or not fileType=="mp3"):
             # To make it more difficult:
             # sox v12.x (c. 2001) - bug when filenames contain 2 spaces together, and needs input from re-direction in this case
             # sox 14.0 on Cygwin - bug when input is from redirection, unless using cat | ..
@@ -647,6 +646,7 @@ def warn_sox_decode():
         if r: show_warning('; '.join(r))
         warned_about_sox_decode = 1
 def decode_mp3(file): # Returns WAV data including header.  TODO: this assumes it's always small enough to read the whole thing into RAM (should be true if it's 1 word though, and decode_mp3 isn't usually used unless we're making a lesson file rather than running something in justSynthesize)
+    file = S(file)
     if riscos_sound:
         warn_sox_decode()
         os.system("sox -t mp3 \""+file+"\" -t wav"+cond(compress_SH," "+sox_8bit,"")+" tmp0")
@@ -670,11 +670,11 @@ def decode_mp3(file): # Returns WAV data including header.  TODO: this assumes i
         else: dat = open(tfil).read()
         os.unlink(tfil) ; return dat
     elif unix:
-        if gotSox:
+        if soxMp3:
             warn_sox_decode()
             return readB(os.popen("cat \""+file+"\" | sox -t mp3 - -t wav"+cond(compress_SH," "+sox_8bit,"")+" - ",popenRB))
         else:
-            show_warning("Don't know how to decode "+file+" on this system")
+            show_warning("Don't know how to decode "+file+" on this system.  Try installing madplay or mpg123.")
             return ""
     else: raise Exception("decode_mp3 called on a setup that's not Unix and doesn't have MADplay.  Need to implement non-cat sox redirect.")
 
diff --git a/gradint-build/src/recording.py b/gradint-build/src/recording.py
index 22d321b..919a5b0 100644
--- a/gradint-build/src/recording.py
+++ b/gradint-build/src/recording.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/sequence.py b/gradint-build/src/sequence.py
index a51c2f8..cb3de14 100644
--- a/gradint-build/src/sequence.py
+++ b/gradint-build/src/sequence.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/synth.py b/gradint-build/src/synth.py
index cc7a0cd..7feb0f4 100644
--- a/gradint-build/src/synth.py
+++ b/gradint-build/src/synth.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/system.py b/gradint-build/src/system.py
index 63667a4..700c9e3 100644
--- a/gradint-build/src/system.py
+++ b/gradint-build/src/system.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/src/top.py b/gradint-build/src/top.py
index 2f83d3b..2b9ae5f 100644
--- a/gradint-build/src/top.py
+++ b/gradint-build/src/top.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #   (Python 2 or Python 3, but more fully tested on 2)
 
-program_name = "gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+."
+program_name = "gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+."
 
 #    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
@@ -31,20 +31,21 @@ if sys.version_info[0]>2:
     raw_input,unichr,xrange = input,chr,range
     def chr(x): return unichr(x).encode('latin1')
     from subprocess import getoutput
-    def readB(f,m=None): return f.buffer.read(m)
     popenRB,popenWB = "r","w"
-    def writeB(f,b): f.buffer.write(b)
     def unicode(b,enc): return b.decode(enc)
 else: # Python 2
     def sort(l,c): l.sort(c)
-    def readB(f,m=None):
-        if m: return f.read(m)
-        else: return f.read() # no "None" in Python 2
     popenRB,popenWB = "rb","wb"
-    def writeB(f,b): f.write(b)
     bytes = str
     try: from commands import getoutput
     except ImportError: pass
+def readB(f,m=None):
+    if hasattr(f,"buffer"): f=f.buffer # Python 3 non-"b" file
+    if m: return f.read(m)
+    else: return f.read() # no "None" in Python 2
+def writeB(f,b):
+    if hasattr(f,"buffer"): f=f.buffer # Python 3 non-"b" file
+    f.write(b)
 def B(x):
     if type(x)==bytes: return x
     try: return x.encode('utf-8')
diff --git a/gradint-build/src/users.py b/gradint-build/src/users.py
index e855022..b632d78 100644
--- a/gradint-build/src/users.py
+++ b/gradint-build/src/users.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
diff --git a/gradint-build/thindown.py b/gradint-build/thindown.py
index 6054ebd..572db87 100644
--- a/gradint-build/thindown.py
+++ b/gradint-build/thindown.py
@@ -1,5 +1,5 @@
 # This file is part of the source code of
-# gradint v3.01 (c) 2002-20 Silas S. Brown. GPL v3+.
+# gradint v3.02 (c) 2002-20 Silas S. Brown. GPL v3+.
 #    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 3 of the License, or
-- 
GitLab