diff --git a/gradint-build/Makefile b/gradint-build/Makefile index 8197cad075dd98f34520e996ecc6d609addd366d..068d8a972c7422c735d708fd61357c656a7d1ded 100644 --- a/gradint-build/Makefile +++ b/gradint-build/Makefile @@ -1,5 +1,5 @@ # This file is part of the source code of -# gradint v3.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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/samples/utils/trace.py b/gradint-build/samples/utils/trace.py index c7fa90665dca79da54fade2825fa3945c48adbef..94822f207b4fcf354abfa3dc55fa7b8a0c6d2f17 100644 --- a/gradint-build/samples/utils/trace.py +++ b/gradint-build/samples/utils/trace.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # trace.py: script to generate raytraced animations of Gradint lessons -# Version 1.11 (c) 2018-19 Silas S. Brown. License: GPL +# Version 1.2 (c) 2018-19,2021 Silas S. Brown. License: GPL # The Disney Pixar film "Inside Out" (2015) represented # memories as spheres. I don't have their CGI models, but @@ -20,7 +20,11 @@ # placed onto the spheres, and projected onto the back wall # when that word is being recalled) # e.g. word1_en.wav, word1_zh.wav, word1.jpg -# (or png or gif, static only for now). +# (or png or gif). + +# Optionally add an mp4 video of a word in a particular language +# e.g. word1_en.mp4 (probably best synchronised to word1_en.wav) +# (can also do this for commentsToAdd and orderlessCommentsToAdd files) # Requires POV-Ray, ffmpeg, and the Python packages vapory # and futures (use sudo pip install futures vapory) - @@ -40,10 +44,10 @@ width_height_antialias = (640,480,0.001) # 480p (DVD) translucent_spheres_when_picture_visible = False # True slows down the rendering debug_frame_limit = None -# debug_frame_limit = 60*theFPS # first minute only povray_quality=9 # default 9: 1=ambient light only, 2=lighting, 4,5=shadows, 8=reflections 9-11=radiosity etc -# povray_quality = 2 + +# debug_frame_limit = 60*theFPS ; povray_quality = 2 # first minute only + rough import sys,os,traceback oldName = __name__ ; from vapory import * ; __name__ = oldName @@ -53,6 +57,10 @@ assert os.path.exists("gradint.py"), "You must move trace.py to the top-level Gr import gradint assert gradint.outputFile, "You must run trace.py with gradint parameters that include outputFile" +try: xrange +except: xrange = range +S,B = gradint.S,gradint.B + class MovableParam: def __init__(self): self.fixed = [] def fixAt(self,t,value): @@ -100,7 +108,7 @@ class MovableSphere(MovablePos): if self.imageFilename: if translucent_spheres_when_picture_visible and bkgScrFade.getPos(t) < 1: transmittence = 0.5 else: transmittence = 0.3 - return Sphere(list(pos),r,colour(self.colour,t),Texture(Pigment(ImageMap('"'+self.imageFilename+'"',"once","interpolate 2","transmit all "+str(transmittence)),'scale',[1.5*r,1.5*r,1],'translate',list(pos),'translate',[-.75*r,-.75*r,0]))) + return Sphere(list(pos),r,colour(self.colour,t),Texture(Pigment(ImageMap('"'+S(self.imageFilename)+'"',"once","interpolate 2","transmit all "+str(transmittence)),'scale',[1.5*r,1.5*r,1],'translate',list(pos),'translate',[-.75*r,-.75*r,0]))) else: return Sphere(list(pos),r,colour(self.colour,t)) class ObjCollection: @@ -161,9 +169,18 @@ bkgScrX = MovableParam() def wall(t): picToUse = None for st,et,pic in background_screen: - if st <= t: picToUse = pic - else: break - if picToUse and bkgScrFade.getPos(t) < 1: return [Plane([0, 0, 1], 60, Texture(Pigment('color', [1, 1, 1])), Texture(Pigment(ImageMap('"'+picToUse+'"',"once","transmit all "+str(bkgScrFade.getPos(t))),'scale',[background_screen_size,background_screen_size,1],'translate',[bkgScrX.getPos(t)-background_screen_size/2,0,0])), Finish('ambient',0.9))] + if st <= t <= et: + picToUse = pic + if B(picToUse).endswith(B(os.extsep+"mp4")): + # need to take single frame from time t-st + out = B(picToUse)[:-4]+B("-"+str(t-st)+os.extsep+"jpg") + if not os.path.exists(out): # (TODO: if its frame rate is low enough, we might already have the same frame even at a slightly different t-st) + cmd = "ffmpeg -n -threads 1 -accurate_seek -ss "+str(t-st)+" -i "+S(picToUse)+" -vframes 1 -q:v 1 "+S(out)+" </dev/null >/dev/null" + print (cmd) + os.system(cmd) + picToUse = out + elif st > t: break + if picToUse and bkgScrFade.getPos(t) < 1: return [Plane([0, 0, 1], 60, Texture(Pigment('color', [1, 1, 1])), Texture(Pigment(ImageMap('"'+S(picToUse)+'"',"once","transmit all "+str(bkgScrFade.getPos(t))),'scale',[background_screen_size,background_screen_size,1],'translate',[bkgScrX.getPos(t)-background_screen_size/2,0,0])), Finish('ambient',0.9))] else: return [Plane([0, 0, 1], 60, Texture(Pigment('color', [1, 1, 1])), Finish('ambient',0.9))] # TODO: why does this look brighter than with ImageMap at transmit all 1.0 ? ground = Plane( [0, 1, 0], -1, Texture( Pigment( 'color', [1, 1, 1]), Finish( 'phong', 0.1, 'reflection',0.4, 'metallic', 0.3))) # from vapory example @@ -227,29 +244,18 @@ def eDraw(startTime,length,rowNo,colour): else: r.fixAt(startTime+length/2.0,maxR) def SampleEvent_draw(self,startTime,rowNo,inRepeat): - if self.file.startswith(gradint.partialsDirectory): l=self.file.split(os.sep)[1] + if B(self.file).startswith(B(gradint.partialsDirectory)): l=B(self.file).split(B(os.sep))[1] else: l = gradint.languageof(self.file) - eDraw(startTime,self.length,rowNo,self.colour(l)) + eDraw(startTime,self.length,rowNo,self.colour(S(l))) gradint.SampleEvent.draw = SampleEvent_draw def SynthEvent_draw(self,startTime,rowNo,inRepeat): eDraw(startTime,self.length,rowNo,self.colour(self.language)) gradint.SynthEvent.draw = SynthEvent_draw -def sgn(i): - if i>0: return 1 - elif i<0: return -1 - else: return 0 - -def byFirstLen(e1,e2): - r = e1[0].glue.length+e1[0].glue.adjustment-e2[0].glue.length-e2[0].glue.adjustment - # but it must return int not float, so - return sgn(r) -def byStart(e1,e2): return sgn(e1.start-e2.start) - def runGradint(): gradint.gluedListTracker=[] gradint.waitBeforeStart=0 gradint.main() - gradint.gluedListTracker.sort(byFirstLen) + gradint.gluedListTracker.sort(key=lambda e:e[0].glue.length+e[0].glue.adjustment) duration = 0 for l,row in zip(gradint.gluedListTracker,xrange(len(gradint.gluedListTracker))): def check_for_pictures(): @@ -261,9 +267,9 @@ def runGradint(): try: el2=j.eventList except: el2=[j] for i in el2: - if hasattr(i,"file") and "_" in i.file: + if hasattr(i,"file") and B("_") in B(i.file): for imgExt in ["gif","png","jpeg","jpg"]: - imageFilename = i.file[:i.file.rindex("_")]+os.extsep+imgExt # TODO: we're assuming no _en etc in the image filename (projected onto both L1 and L2) + imageFilename = B(i.file)[:B(i.file).rindex(B("_"))]+B(os.extsep+imgExt) # TODO: we're assuming no _en etc in the image filename (projected onto both L1 and L2) if os.path.exists(imageFilename): return EventTracker(row,os.path.abspath(imageFilename)) check_for_pictures() @@ -275,9 +281,20 @@ def runGradint(): i.event.draw(i.getEventStart(glueStart),row,False) glueStart = i.getAdjustedEnd(glueStart) duration = max(duration,glueStart) + for t,e in gradint.lastLessonMade.events: + if hasattr(e,"file") and hasattr(e,"exactLen"): + video = B(e.file)[:B(e.file).rindex(B(os.extsep))]+B(os.extsep+"mp4") + if os.path.exists(video): # overwrite static image while playing + background_screen.append((t,t+e.exactLen,os.path.abspath(video))) background_screen.sort() i = 0 while i < len(background_screen)-1: + if background_screen[i][1] > background_screen[i+1][1]: # overlap: we end after next one ends: insert a jump-back-to-us after + background_screen.insert(i+2,(background_screen[i+1][1],background_screen[i][1],background_screen[i][2])) # restore old after new one ends + if background_screen[i][1] > background_screen[i+1][0] and background_screen[i][0] < background_screen[i+1][0]: # overlap: we end after next one starts, but we start before it starts + background_screen[i] = (background_screen[i][0],background_screen[i+1][0],background_screen[i][2]) # new one takes precedence + if background_screen[i][0]==background_screen[i+1][0]: # equal start, but next one might be longer + background_screen[i+1]=(background_screen[i][1],background_screen[i+1][1],background_screen[i+1][2]) if background_screen[i][-1]==background_screen[i+1][-1] and background_screen[i][1]+5>=background_screen[i+1][0]: # turning off for 5 seconds or less, then turning back on again with the SAME image: might as well merge background_screen[i] = (background_screen[i][0],background_screen[i+1][1],background_screen[i][2]) @@ -285,25 +302,31 @@ def runGradint(): else: i += 1 for i in xrange(len(background_screen)): startTime,endTime,img = background_screen[i] - bkgScrFade.fixAt(startTime,1) + if i and startTime > background_screen[i-1][1] + 0.5: + bkgScrFade.fixAt(startTime,1) # start faded out + # else (less than 0.5sec between images) don't try to fade out fadeOutTime = endTime if i<len(background_screen)-1: - fadeOutTime = max(fadeOutTime,min(background_screen[i+1][0]-1,fadeOutTime+5)) - # and don't move the screen while fading out: - for ii in xrange(len(bkgScrX.fixed)): - if bkgScrX.fixed[ii][0]==endTime: - bkgScrX.fixed[ii]=((fadeOutTime,bkgScrX.fixed[ii][1])) - break - bkgScrFade.fixAt(fadeOutTime,1) + if endTime + 0.5 > background_screen[i-1][0]: + fadeOutTime = None # as above (< 0.5sec between images) + else: fadeOutTime = max(fadeOutTime,min(background_screen[i+1][0]-1,fadeOutTime+5)) + if not fadeOutTime == None: + # don't move the screen during any extended fade-out: + for ii in xrange(len(bkgScrX.fixed)): + if bkgScrX.fixed[ii][0]==endTime: + bkgScrX.fixed[ii]=((fadeOutTime,bkgScrX.fixed[ii][1])) + break + if not fadeOutTime==None: bkgScrFade.fixAt(fadeOutTime,1) if endTime >= startTime+1: bkgScrFade.fixAt(startTime+0.5,0.3) bkgScrFade.fixAt(endTime-0.5,0.3) else: - bkgScrFade.fixAt((startTime+endTime)/2.0,0.5) # TODO: do we really want to bother with fade, or even any background image at all, if it's less than 1 second ?? + bkgScrFade.fixAt((startTime+endTime)/2.0,0.3) return duration -def tryFrame((frame,numFrames)): - print "Making frame",frame,"of",numFrames +def tryFrame(f): + frame,numFrames = f + print ("Making frame "+str(frame)+" of "+str(numFrames)) try: try: os.mkdir("/tmp/"+repr(frame)) # vapory writes a temp .pov file and does not change its name per process, so better be in a process-unique directory except: pass @@ -328,7 +351,7 @@ def main(): "ffmpeg -nostdin -y -framerate "+repr(theFPS)+" -i /tmp/frame%05d.png -i "+gradint.outputFile+" -movflags faststart -pix_fmt yuv420p /tmp/gradint.mp4 && if test -d /Volumes; then open /tmp/gradint.mp4; fi" # (could alternatively run with -vcodec huffyuv /tmp/gradint.avi for lossless, insead of --movflags etc, but will get over 6 gig and may get A/V desync problems in mplayer/VLC that -delay doesn't fix, however -b:v 1000k seems to look OK; for WeChat etc you need to recode to h.264, and for HTML 5 video need recode to WebM (but ffmpeg -c:v libvpx no good if not compiled with support for those libraries; may hv to convert on another machine i.e. ffmpeg -i gradint.mp4 -vf scale=320:240 -c:v libvpx -b:v 500k gradint.webm)) ]: if c: # patch up skipped frames, then run ffmpeg - print c ; os.system(c) + print (c) ; os.system(c) for f in xrange(numFrames): os.remove("/tmp/frame%05d.png" % f) # wildcard from command line could get 'argument list too long' on BSD etc if __name__=="__main__": main() -else: print __name__ +else: print (__name__) diff --git a/gradint-build/src/booktime.py b/gradint-build/src/booktime.py index 44bfe2c0dda64295169af62970972d0df98b146a..30ee79420a876c3d3248a5890540741d11a5ecd0 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 84ca59dca911b51777a339a0e0f7161168e8012a..32c4af08399b3e53275b031f65903e86da3238c3 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 846db2061f600db27b25053b92936b826c616901..fa6e6166a092e73911e4321dab386cc3fae80b13 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 133140376c1fe31398775b61ab284eb3a3b1e7d1..dc533affd77e0041d9966daba5a9ece08cf7e9aa 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 c54db759ec7d33d94f6137dc5540c9f6a18c3d20..23dde229c800f76258d0e33606f3073fd12aa036 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 @@ -42,6 +42,8 @@ def doOneLesson(dbase): app.setLabel("Starting lesson") app.cancelling = 0 lesson.play() + if not gluedListTracker==None: + global lastLessonMade ; lastLessonMade = lesson # used by utils/trace.py if dbase and saveProgress and not dbase.saved_completely: # justSaveLesson is a no-op if not first time through lesson (because scripts that use it probably mean "save if not already save"; certainly don't mean "play if is saved") if cancelledFiles: dbase.savePartial(cancelledFiles) else: dbase.save() diff --git a/gradint-build/src/makeevent.py b/gradint-build/src/makeevent.py index c77944fa6df5993968fdab8e0d2ceba5e01d9ea8..bf45a188005133d4f7afffcccc2e342dbe564791 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 @@ -467,7 +467,7 @@ def optimise_partial_playing(ce): if wavPlayer=="aplay": wpMod="aplay -q" elif wavPlayer.strip().endswith("<"): wpMod=wavPlayer.strip()[:-1] # nc etc else: wpMod='sox -t wav - '+sox_type+' '+oss_sound_device - s=ShellEvent('set -o pipefail;('+'&&'.join(['cat "%s" | sox -t %s - -t wav - $Vol$ 2>/dev/null' % (ce.eventList[0].file,fileType)]+['cat "%s" | sox -t %s - -t raw - $Vol$'%(e.file,fileType) for e in ce.eventList[1:]])+')'+sox_ignoreLen+'|'+wpMod,True) + s=ShellEvent('set -o pipefail;('+'&&'.join(['cat "%s" | sox -t %s - -t wav - $Vol$ 2>/dev/null' % (S(ce.eventList[0].file),fileType)]+['cat "%s" | sox -t %s - -t raw - $Vol$'%(S(e.file),fileType) for e in ce.eventList[1:]])+')'+sox_ignoreLen+'|'+wpMod,True) s.VolReplace="sox_effect" elif wavPlayer=="aplay" and not sox_effect: s=ShellEvent('aplay -q '+''.join(map(lambda x:' "'+x.file+'"', ce.eventList)),True) # (which is not quite as good but is the next best thing) (and hope they don't then try to re-play a saved lesson with a volume adjustment) if s: diff --git a/gradint-build/src/play.py b/gradint-build/src/play.py index 284b9c2b6b31590d4f79639f58c062424f7e0e33..15ad66a94e86c201d2b5b52f4724402b8b4a99f8 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 @@ -273,7 +273,7 @@ class SampleEvent(Event): if not fileExists_stat(self.file): break # unlink suceeded and still threw exception ?? def makesSenseToLog(self): if hasattr(self,"is_prompt"): return not self.is_prompt # e.g. prompt from synth-cache - return not self.file.startswith(promptsDirectory) # (NB "not prompts" doesn't necessarily mean it'll be a sample - may be a customised additional comment) + return not B(self.file).startswith(B(promptsDirectory)) # (NB "not prompts" doesn't necessarily mean it'll be a sample - may be a customised additional comment) def play(self): # returns a non-{False,0,None} value on error if paranoid_file_management: if not hasattr(self,"isTemp"): open(self.file) # ensure ready for reading @@ -348,7 +348,7 @@ class SampleEvent(Event): # riscos can't do re-direction (so hope not using a buggy sox) (but again don't have to worry about this if playing because will use PlayIt) # + on some setups (e.g. Linux 2.6 ALSA with OSS emulation), it can fail without returning an error code if the DSP is busy, which it might be if (for example) the previous event is done by festival and is taking slightly longer than estimated t = time.time() - play_error = system('cat "%s" | sox -t %s - %s %s%s >/dev/null' % (self.file,fileType,sox_type,oss_sound_device,sox_effect)) + play_error = system('cat "%s" | sox -t %s - %s %s%s >/dev/null' % (S(self.file),fileType,sox_type,oss_sound_device,sox_effect)) if play_error: return play_error else: # no error, but did it take long enough? @@ -359,7 +359,7 @@ class SampleEvent(Event): return 1 elif wavPlayer=="aplay" and ((not fileType=="mp3") or madplay_path or gotSox): if madplay_path and fileType=="mp3": return system(madplay_path+' -q -A '+str(soundVolume_dB)+' "'+self.file+'" -o wav:-|aplay -q') # changeToDirOf() not needed because this won't be cygwin (hopefully) - elif gotSox and (sox_effect or fileType=="mp3"): return system('cat "'+self.file+'" | sox -t '+fileType+' - -t wav '+sox_16bit+' - '+sox_effect+' 2>/dev/null|aplay -q') # (make sure o/p is 16-bit even if i/p is 8-bit, because if sox_effect says "vol 0.1" or something then applying that to 8-bit would lose too many bits) + elif gotSox and (sox_effect or fileType=="mp3"): return system('cat "'+S(self.file)+'" | sox -t '+fileType+' - -t wav '+sox_16bit+' - '+sox_effect+' 2>/dev/null|aplay -q') # (make sure o/p is 16-bit even if i/p is 8-bit, because if sox_effect says "vol 0.1" or something then applying that to 8-bit would lose too many bits) # (2>/dev/null to suppress sox "can't seek to fix wav header" problems, but don't pick 'au' as the type because sox wav->au conversion can take too long on NSLU2 (probably involves rate conversion)) else: return system('aplay -q "'+self.file+'"') # May also be able to support alsa directly with sox (aplay not needed), if " alsa" is in sox -h's output and there is /dev/snd/pcmCxDxp (e.g. /dev/snd/pcmC0D0p), but sometimes it doesn't work, so best stick with aplay @@ -489,7 +489,7 @@ class SoundCollector(object): os.system("sox -t %s \"%s\" %s tmp0" % (fileType,file,self.soxParams())) handle=open("tmp0","rb") elif winsound or mingw32: handle = os.popen(("sox -t %s - %s - < \"%s\"" % (fileType,self.soxParams(),file)),popenRB) - else: handle = os.popen(("cat \"%s\" | sox -t %s - %s -" % (file,fileType,self.soxParams())),popenRB) + else: handle = os.popen(("cat \"%s\" | sox -t %s - %s -" % (S(file),fileType,self.soxParams())),popenRB) self.theLen += outfile_writeFile(self.o,handle,file) if riscos_sound: handle.close() ; os.unlink("tmp0") @@ -531,7 +531,7 @@ def outfile_writeFile(o,handle,filename): data = readB(handle,102400) outfile_writeBytes(o,data) theLen += len(data) - if not filename.startswith(partialsDirectory+os.sep): assert theLen, "No data when reading "+filename+": check for sox crash" # (but allow empty partials e.g. r5. TODO if it's from EkhoSynth it could be a buggy version of Ekho) + if not B(filename).startswith(B(partialsDirectory+os.sep)): assert theLen, "No data when reading "+S(filename)+": check for sox crash" # (but allow empty partials e.g. r5. TODO if it's from EkhoSynth it could be a buggy version of Ekho) return theLen def outfile_write_error(): raise IOError("Error writing to outputFile: either you are missing an encoder for "+out_type+", or the disk is full or something.") def oggenc(): # 2016: some Windows builds are now called oggenc2 @@ -618,7 +618,7 @@ tail -1 "$S" | bash\nexit\n""" % (sox_16bit,sox_signed) # S=script P=params for self.seconds += length if not checkIn(file,self.file2command): if fileType=="mp3": fileData,fileType = decode_mp3(file),"wav" # because remote sox may not be able to do it - elif compress_SH and unix: handle=os.popen("cat \""+file+"\" | sox -t "+fileType+" - -t "+fileType+" "+sox_8bit+" - 2>/dev/null",popenRB) # 8-bit if possible (but don't change sample rate, as we might not have floating point) + elif compress_SH and unix: handle=os.popen("cat \""+S(file)+"\" | sox -t "+fileType+" - -t "+fileType+" "+sox_8bit+" - 2>/dev/null",popenRB) # 8-bit if possible (but don't change sample rate, as we might not have floating point) else: handle = open(file,"rb") offset, length = self.bytesWritten, outfile_writeFile(self.o,handle,file) self.bytesWritten += length @@ -689,7 +689,7 @@ def decode_mp3(file): # Returns WAV data including header. TODO: this assumes i elif unix: if soxMp3: warn_sox_decode() - return readB(os.popen("cat \""+file+"\" | sox -t mp3 - -t wav"+cond(compress_SH," "+sox_8bit,"")+" - ",popenRB)) + return readB(os.popen("cat \""+S(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. Try installing madplay or mpg123.") return "" diff --git a/gradint-build/src/recording.py b/gradint-build/src/recording.py index ad3e45c87316ef8e56bab9c35da2ffa5286d2749..f23c8e5a061b06d0be6f071a7dfac2989ef452db 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 35b93809eb298d3dd0a9dc978b5f0f0a0c6c3c53..0d6758fb7627fc77021dcc3dc81fcda1fbac3406 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 0259c0b534cd4f636820eac5ebb8e096351daaef..3eff1d0200c4af294acdc9380ebab1522a052af3 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 398a0aa053e68aa7ab7da8ce6a87d1851251f455..46e4f7b7740b83049996b0f1660a209af3db9056 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 c1134e631e83bbbfbdee1b4e5451283e0d71e088..460e0c35473a334d993154c6187320ded93c3d2b 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.062 (c) 2002-21 Silas S. Brown. GPL v3+." +program_name = "gradint v3.063 (c) 2002-21 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 diff --git a/gradint-build/src/users.py b/gradint-build/src/users.py index c31669b9e17e9f2b054e117144c891d1b47dbae3..95399f5677b5b806cef605f44fbd7f48467aef3a 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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 d5e295e21cb2915863a55db6121c0db0298bbd45..9e479a28d00cf87b5a729f02928dfe8511e11dd0 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.062 (c) 2002-21 Silas S. Brown. GPL v3+. +# gradint v3.063 (c) 2002-21 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