From 473580484f904f47badd2d6af2f377faa49ea7c2 Mon Sep 17 00:00:00 2001 From: Skyler Lehmkuhl Date: Fri, 4 Jan 2013 00:59:38 -0500 Subject: [PATCH] Added sounds. --- base.js | 26 ++++++++- lightningbeam.py | 77 ++++++++++++++++++++++--- svlgui.py | 146 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 219 insertions(+), 30 deletions(-) diff --git a/base.js b/base.js index 801c6d1..015e902 100644 --- a/base.js +++ b/base.js @@ -661,7 +661,7 @@ function TextField() { } } -makeNonEnumerable(TextField); +// makeNonEnumerable(TextField); var _rootFrame = new Frame() var _root = new MovieClip() @@ -717,6 +717,30 @@ Object.prototype.isPropertyEnumerable = function (name) { Object.defineProperty( Object.prototype, "addProperty", {enumerable: false}); Object.defineProperty( Object.prototype, "isPropertyEnumerable", {enumerable: false}); + +function Sound() { + this._sound = undefined; + this.duration = undefined + this.getVolume = function () { + return parseInt(this._sound.volume*100); + } + this.loadSound = function (url) { + this._sound = new Audio (url); + this._sound.load(); + this.duration = this._sound.duration + } + this.setVolume = function (vol) { + this._sound.volume = vol; + } + this.start = function () { + this._sound.play(); + } + this.stop = function () { + this._sound.pause(); + } +} +Sound.addProperty('position', function () {return parseInt(this._sound.position*1000)}) + function Point (x, y) { this.x = x this.y = y diff --git a/lightningbeam.py b/lightningbeam.py index 6327337..a26ffd2 100755 --- a/lightningbeam.py +++ b/lightningbeam.py @@ -3,7 +3,7 @@ # © 2012 Skyler Lehmkuhl # Released under the GPLv3. For more information, see gpl.txt. -import os, shutil, tarfile, tempfile, StringIO, urllib +import os, shutil, tarfile, tempfile, StringIO, urllib, subprocess # Workaround for broken menubar under Ubuntu os.putenv("UBUNTU_MENUPROXY", "0") @@ -280,10 +280,19 @@ def onKeyDownObj(self, key): add_keyframe() elif key=="F8": convert_to_symbol() + elif key=="left_arrow": + self.x-=1 + elif key=="right_arrow": + self.x+=1 + elif key=="up_arrow": + self.y-=1 + elif key=="down_arrow": + self.y+=1 def create_sc(root): #retval = ".flash bbox="+str(svlgui.WIDTH)+"x"+str(svlgui.HEIGHT)+" background=#ffffff \ #fps="+str(svlgui.FRAMERATE)+"\n"+root.print_sc()+".end" + print svlgui.Library retval = ".flash bbox="+str(svlgui.WIDTH)+"x"+str(svlgui.HEIGHT)+" background=#ffffff \ fps="+str(svlgui.FRAMERATE)+"\n"+"".join([i.print_sc() for i in svlgui.Library])+root.print_sc()+".end" return retval @@ -562,14 +571,64 @@ def save_file_as(widget=None): svlgui.FILE = thetarfile pass def import_to_stage(widget=None): - thefile = svlgui.file_dialog("open",None,["jpg","png","bmp"]).path - im = svlgui.Image(thefile) - im.onMouseDown = onMouseDownObj - im.onMouseMove = onMouseMoveObj - im.onMouseDrag = onMouseDragObj - im.onMouseUp = onMouseUpObj - im.onKeyDown = onKeyDownObj - root.descendItem().add(im) + thefile = svlgui.file_dialog("open",None,["jpg","png","bmp","wav"]).path + for i in ("jpg","png","bmp"): + if thefile.endswith(i): + im = svlgui.Image(thefile) + im.onMouseDown = onMouseDownObj + im.onMouseMove = onMouseMoveObj + im.onMouseDrag = onMouseDragObj + im.onMouseUp = onMouseUpObj + im.onKeyDown = onKeyDownObj + root.descendItem().add(im) + break + else: + if thefile.endswith("wav"): + if svlgui.PLATFORM=="osx": + if not os.path.exists('sox/sox'): + try: + import numpy as NP + result = svlgui.alert("To import sound you must install SoX. This will take about 1 MB of space. Install?", confirm=True) + if not result: + return + urllib.urlretrieve('http://downloads.sourceforge.net/project/sox/sox/14.4.0/sox-14.4.0-macosx.zip?r=&ts=1357270265&use_mirror=iweb', 'sox.zip') + os.system('ditto -V -x -k --sequesterRsrc --rsrc sox.zip .') + os.system('mv sox-14.4.0 sox') + except: + result = svlgui.alert("To import sound you must install NumPy and SoX. This will take about 10 MB of space. Install?", confirm=True) + if not result: + return + os.system("""osascript -e 'do shell script "easy_install numpy" with administrator privileges'""") + import numpy as NP + urllib.urlretrieve('http://downloads.sourceforge.net/project/sox/sox/14.4.0/sox-14.4.0-macosx.zip?r=&ts=1357270265&use_mirror=iweb', 'sox.zip') + os.system('ditto -V -x -k --sequesterRsrc --rsrc sox.zip .') + os.system('mv sox-14.4.0 sox') + else: + try: + import numpy as NP + except: + result = svlgui.alert("To import sound you must install NumPy. This will take about 9 MB of space. Install?", confirm=True) + if not result: + return + os.system("""osascript -e 'do shell script "easy_install numpy" with administrator privileges'""") + import numpy as NP + SOX_EXEC = 'sox/sox' + svlgui.NP = NP + num_channels = 1 + out_byps = 2 # Bytes per sample you want, must be 1, 2, 4, or 8 + cmd = [SOX_EXEC, + thefile, # input filename + '-t','raw', # output file type raw + '-e','signed-integer', # output encode as signed ints + '-L', # output little endin + '-b',str(out_byps*8), # output bytes per sample + '-'] # output to stdout] + data = NP.fromstring(subprocess.check_output(cmd),'>sys.stderr, "Unhandled:",l + self.sample_rate = int(sample_rate) + self.duration_samples = int(duration_samples) + self.duration_time = int(duration_time.split(':')[0])*3600+int(duration_time.split(':')[1])*60+float(duration_time.split(':')[2]) + def draw(self, cr, transform): + pass + def draw_frame(self, cr, transform): + if SYSTEM=="osx": + cr.newpath() + # cr.moveto(0,16) + chunk_size = int(self.duration_samples/(self.duration_time*FRAMERATE*16)) + print chunk_size + print self.duration_samples/chunk_size + for i in xrange(self.duration_samples/chunk_size): + j = abs(NP.amax(self.data[i*chunk_size:(i+1)*chunk_size])/65536.0) + cr.moveto(i,16-j*16) + cr.lineto(i,16+j*16) + # cr.lineto(self.duration_time*16*FRAMERATE,16) + cr.stroke() + def hitTest(self, x, y): + return False + def print_sc(self): + retval = ".sound "+self.name+" \""+self.path+"\"\n" + return retval + def print_html(self): + retval = "var "+self.name.replace(".","_")+" = new Sound();\n"+self.name.replace(".","_")+"._sound = new Audio('"+self.path.split("/")[-1]+"');\n" + retval = retval + self.name.replace(".","_")+"._sound.load();\n"+self.name.replace(".","_")+".duration = "+self.name.replace(".","_")+"._sound.duration" + return retval class framewrapper (object): #def __getstate__(self): @@ -2111,22 +2186,26 @@ class frame: retval = "" if self==self.parent.frames[0]: for i in self.objs: - if i.obj.iname: + if isinstance(i.obj, Sound): + retval = retval+".play "+i.obj.name+"\n" + elif i.obj.iname: retval = retval+".put "+i.obj.iname+"="+i.name+" x="+str(i.x)+" y="+str(i.y)+" scalex="+str(i.xscale*100)+" scaley="+str(i.yscale*100)+"\n" else: - retval = retval+".put "+i.name+" x="+str(i.x)+" y="+str(i.y)+" scalex="+str(i.xscale*100)+"%% scaley="+str(i.yscale*100)+"%%\n" + retval = retval+".put "+i.name+" x="+str(i.x)+" y="+str(i.y)+" scalex="+str(i.xscale*100)+"% scaley="+str(i.yscale*100)+"%\n" else: for i in self.objs: - if not i.obj in [j.obj for j in misc_funcs.lastval(self.parent.frames,self.parent.frames.index(self)).objs]: + if isinstance(i.obj, Sound): + retval = retval+".play "+i.obj.name+"\n" + elif not i.obj in [j.obj for j in misc_funcs.lastval(self.parent.frames,self.parent.frames.index(self)).objs]: if not hasattr(i.obj, "iname"): i.obj.iname = None if i.obj.iname: - retval = retval+".put "+i.obj.iname+"="+i.name+" x="+str(i.x)+" y="+str(i.y)+" scalex="+str(i.xscale*100)+" scaley="+str(i.yscale*100)+"\n" + retval = retval+".put "+i.obj.iname+"="+i.name+" x="+str(i.x)+" y="+str(i.y)+" scalex="+str(i.xscale*100)+"% scaley="+str(i.yscale*100)+"%\n" else: - retval = retval+".put "+i.name+" x="+str(i.x)+" y="+str(i.y)+"scalex="+str(i.xscale*100)+" scaley="+str(i.yscale*100)+"\n" + retval = retval+".put "+i.name+" x="+str(i.x)+" y="+str(i.y)+"scalex="+str(i.xscale*100)+"% scaley="+str(i.yscale*100)+"%\n" else: retval = retval+".move "+i.name+" x="+str(i.x)+" y="+str(i.y)+"\n" - retval = retval+".change "+i.name+" scalex="+str(i.xscale*100)+" scaley="+str(i.yscale*100)+"\n" + retval = retval+".change "+i.name+" scalex="+str(i.xscale*100)+"% scaley="+str(i.yscale*100)+"%\n" if not self.actions.strip()=='': retval = retval + ".action:\n"+self.actions+"\n.end\n" return retval @@ -2463,7 +2542,7 @@ class Group (object): if self.activelayer.currentselect and MODE=="s": global SCALING if (self.activelayer.currentselect.minx-5self1.maxx/2: self1.xscale = (x-self1.x)/self1.maxx else: - # I don't understand why I need 2*self1.maxx instead of just maxx, but it works. self1.xscale = (2*self1.maxx+self1.x-(x-self1.initx)-x)/self1.maxx self1.x = x if self1.inity>self1.maxy/2: @@ -2653,9 +2735,26 @@ class TemporaryGroup(Group): self1.y = y def onMouseUp(self, self1, x, y, button=1, clicks=1): self.clicked = False - # def hitTest(self, x, y): - # print self.x, self.y, x, y - # return True + def onKeyDown(self, self1, key): + if key in ("delete", "backspace"): + del self1.parent[self1.parent.index(self1)] # Need to clean up deletion + elif key in [" ", "s", "r", "e", "b", "p"]: + svlgui.MODE=key + svlgui.set_cursor({" ":"arrow","s":"arrow","r":"crosshair","e":"crosshair", + "b":"arrow","p":"arrow"}[key], MainWindow.stage) + misc_funcs.update_tooloptions() + elif key=="F6": + add_keyframe() + elif key=="F8": + convert_to_symbol() + elif key=="left_arrow": + self1.x-=1 + elif key=="right_arrow": + self1.x+=1 + elif key=="up_arrow": + self1.y-=1 + elif key=="down_arrow": + self1.y+=1 def set_cursor(curs, widget=None): @@ -3065,6 +3164,13 @@ class FramesCanvas(Canvas): dst_rect = [i*16, k*32, 16+i*16, 32+k*32] self.inacfr.draw(cr, src_rect, dst_rect) cr.grestore() + for i in xrange(len(FRAMES)): + if FRAMES[i]: + try: + sounds = [i.obj for i in FRAMES[i].objs if isinstance(i.obj, Sound)] + [i.draw_frame(cr, None) for i in sounds] + except: + traceback.print_exc() # print max(len(FRAMES),int(update_rect[0]/16-1)),int(update_rect[2]/16+1) for i in xrange(max(len(FRAMES),int(update_rect[0]/16-1)),int(update_rect[2]/16+1)): cr.newpath()