#!/usr/bin/env python3 #Released under GNU General Public License version 3, see the file COPYING for details. from __future__ import print_function #Change the value of the following two lines if your sound device is not /dev/dsp soundin="alsa" soundout="alsa" import sys, time, os #python2 to python3 compatability code major_version=sys.version_info.major from six.moves import input as raw_input if major_version==2: from commands import getstatusoutput, getoutput if major_version==3: from subprocess import getstatusoutput, getoutput from pyeca import * e = ECA_CONTROL_INTERFACE(0) def escape_filename(raw_filename): return raw_filename.replace(' ','\ ') def busy(status, waitfor): done=['finished', 'stopped', 'not started', 'ready'] if waitfor != None: done.append(waitfor) busy=True for i in done: if status==i: busy=False break return busy def do_command(cmdstring, waitfor=None): try: # print(cmdstring,waitfor) result=e.command(cmdstring) status=e.command("engine-status") # print(status) while busy(status, waitfor): status=e.command("engine-status") # print(status) except: time.sleep(15) e.command(cmdstring) returned_error=e.last_error() if returned_error: print("an error occured while doing "+cmdstring+" the error was: "+returned_error) print("remember you should have a backup in "+infile+"~") print("exiting") exit() return result if len(sys.argv) == 1: print("no file given, using unknown.wav") do_command("cs-add chain1") do_command("cs-set-audio-format 16,2,44100") do_command("c-add chain1") do_command("ai-add rtnull") do_command("ao-add unknown.wav") do_command("cs-set-length 1") do_command("cs-connect chain1") do_command("run", "run") do_command("cs-disconnect chain1") do_command("cs-remove chain1") infile = "unknown.wav" else: os_infile = sys.argv.pop(1) infile=escape_filename(os_infile) if not (os.path.isfile(os_infile)): do_command("cs-add chain1") do_command("cs-set-audio-format 16,2,44100") do_command("c-add chain1") do_command("ai-add rtnull") do_command("ao-add "+infile) do_command("cs-set-length 1") do_command("cs-connect chain1") do_command("run", "run") do_command("cs-disconnect chain1") do_command("cs-remove chain1") print(infile+" is new and contains one second silense.") print("please wait while we make a backup of "+infile) backedup=getstatusoutput("cp "+infile+" "+infile+"~") if backedup[0]==0: print("backup complete") else: print("backup of "+infile+" failled, reason: "+backedup[1]) print("warning: proceding without a backup") buttons={"f1": "stop", "f2": "play", "f3": "fast rewind", "f4": "fast forward", "f5": "begin block", "f6": "end block", "f7": "play block", "f8": "write block", "f9": "remove block", "f10": "record", "shift_f10": "denoised recording", "ctrl_f10": "wireless recording", "f11": "insert from file", "f12": "go to end", "J": "go to last track mark", "l": "toggle half speed", "p": "wrote position", "S": "split tracks"} bs=False be=False forwarding=False denoise=False rewinding=False halfspeed=False key="" active_controls=['f1','f2','shift_f10','ctrl_f10','q','l'] global block_controls_active block_controls_active=True def deactivate_block_controls(): active_controls.remove('f5') active_controls.remove('f6') active_controls.remove('f7') active_controls.remove('f8') active_controls.remove('f9') active_controls.remove('f10') active_controls.remove('shift_f10') active_controls.remove('ctrl_f10') active_controls.remove('f11') global block_controls_active block_controls_active=False def reactivate_block_controls(): active_controls.append('f5') active_controls.append('f6') active_controls.append('f7') active_controls.append('f8') active_controls.append('f9') active_controls.append('f10') active_controls.append('shift_f10') active_controls.append('ctrl_f10') active_controls.append('f11') active_controls.append('l') global block_controls_active block_controls_active=True def currentpos(): result=do_command("get-position", "running") return result def init_write_position(): global poslines, prevpos, lastline if os.path.isfile(os_infile+".pos"): pf=open(infile+".pos", "r") poslines=pf.readlines() pf.close() lastline=poslines[len(poslines)-1] last_written=lastline.split(' ') prevpos=float(last_written[0])+float(last_written[1]) else: prevpos=0 poslines=[] return def write_position(): global poslines, prevpos, lastline if currentpos() <= prevpos: result="next track must follow previous track, no position written" return result tracklen=currentpos()-prevpos addline=str(prevpos)+" "+str(tracklen)+chr(10) pf=open(infile+".pos", "a") pf.write(addline) pf.close() poslines.append(addline) lastline=poslines[len(poslines)-1] last_written=lastline.split(' ') prevpos=float(last_written[0])+float(last_written[1]) return str(prevpos) def movearound(direction): #The code for rewinding in this function is currently not used as it is buggy. global forwarding,rewinding,oldpos,was_playing if not (rewinding or forwarding): oldpos=currentpos() result=do_command("engine-status", "running") if result=="running": was_playing=True else: was_playing=False do_command("stop") d=direction if d=='r': if rewinding==False: do_command("cs-disconnect chain1") do_command("cs-remove chain1") do_command("cs-add chain1") do_command("c-add chain1") do_command("c-select chain1") do_command("ai-add reverse,"+infile) do_command("ao-add "+soundout) do_command("cs-option -ei:400") do_command("cs-connect chain1") do_command("setpos "+str(oldpos)) do_command("start") rewinding=True return else: rewinding=False do_command("stop") do_command("cs-clear") rewindpos=currentpos() do_command("cs-disconnect chain1") do_command("cs-remove chain1") do_command("cs-add chain1") do_command("c-add chain1") do_command("c-select chain1") do_command("ai-add "+infile) do_command("ao-add "+soundout) do_command("cs-connect chain1") rewound=rewindpos-oldpos do_command("setpos "+str(oldpos-rewound)) if was_playing: do_command("start") return else: if forwarding==False: do_command("cs-option -ei:400", "running") forwarding=True else: if was_playing == False: do_command("engine-status") do_command("stop") do_command("engine-status") while e.last_string() == "running": do_command("stop") do_command("engine-status") do_command("c-clear") waitfortask forwarding=False return if (not block_controls_active) and d=='r' and currentpos() <= bs: #we are trying to rewind past block start when playinng block do_command("setpos "+str(bs)) if (not block_controls_active) and d=='f' and currentpos() >= be: #we are trying to forward past block end when playing block do_command("setpos "+str(be)) do_command("start") return def go_slow(): global halfspeed, was_playing result=do_command("engine-status", "running") if result=="running": was_playing=True else: was_playing=False if halfspeed==False: do_command("cs-option -ei:70") halfspeed=True else: if was_playing == False: do_command("engine-status") do_command("stop") do_command("engine-status") while e.last_string() == "running": do_command("stop") do_command("engine-status") do_command("c-clear") waitfortask halfspeed=False return return def blocktime(): if bs == be: print("no block") result=False return result if type(bs) !=type(0.0): print("No beginning of block marked") result=False return result if type(be) != type(0.0): print("No end of block marked") result=False return result if bs > be: print("start later than end") result=False return result result=be-bs return result def playagain(vanaf): do_command("cs-add default -i:infile -o alsa") do_command("cs-connect default") do_command("setpos "+str(vanaf)) do_command("start") def playblock(): if blocktime() == False: return mainlength=do_command("cs-get-length") mainpos=keepme do_command("stop") do_command("setpos "+str(bs)) do_command("cs-set-length "+str(be)) if blocktime() < 10: do_command("start") e.command("engine-status") while e.last_string() != 'finished': e.command("engine-status") do_command("run") e.command("engine-status") while e.last_string() != 'finished': e.command("engine-status") else: do_command("start") user_control() do_command("cs-set-length "+str(mainlength)) do_command("setpos "+str(mainpos)) print(blocktime()) def write_block(): if blocktime() == False: return mainlength=do_command("cs-get-length") mainpos=keepme do_command("stop") do_command("cs-disconnect chain1") do_command("cs-remove chain1") outblock=raw_input("write block as? ") if os.path.isfile(outblock): os.remove(outblock) do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() do_command("ai-add "+infile) do_command("ao-add "+escape_filename(outblock)) do_command("cop-select chain1") do_command("cs-connect chain1") do_command("ai-select "+infile) do_command("ai-setpos "+str(bs)) # do_command("setpos "+str(bs)) print("block start "+str(bs)) do_command("cs-set-length "+str(be-bs)) do_command("start") do_command("run", "running") do_command("cs-disconnect chain1") do_command("cs-remove chain1") do_command("cs-add chain1") do_command("c-add chain1") do_command("ai-add "+infile) do_command("ao-add "+soundout) do_command("cop-select chain1") do_command("cs-connect chain1") do_command("cs-set-length "+str(mainlength)) do_command("setpos "+str(mainpos)) print("wrote "+outblock+" ",blocktime()," seconds") return def split_tracks(): if len(poslines)==0: print("no tracks marked for splitting") return mainlength=do_command("cs-get-length") mainpos=keepme do_command("stop") do_command("cs-disconnect chain1") do_command("cs-remove chain1") trackno_length=len(str(len(poslines))) track_prefix="track_" trackno=0 while trackno < len(poslines): tracknumber=str(trackno+1) while len(tracknumber) < trackno_length: tracknumber='0'+tracknumber outblock=track_prefix+tracknumber+".wav" if os.path.isfile(outblock): os.remove(outblock) do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() do_command("ai-add "+infile) do_command("ao-add "+outblock) do_command("cop-select chain1") do_command("cs-connect chain1") do_command("ai-select "+infile) track=poslines[trackno].split(' ') trackstart=track[0] tracklength=track[1] do_command("ai-setpos "+trackstart) print("writing "+outblock) do_command("cs-set-length "+tracklength) do_command("start") do_command("run") do_command("cs-disconnect chain1") do_command("cs-remove chain1") trackno=trackno+1 do_command("cs-add chain1") do_command("c-add chain1") do_command("ai-add "+infile) do_command("ao-add "+soundout) do_command("cop-select chain1") do_command("cs-connect chain1") do_command("cs-set-length "+str(mainlength)) do_command("setpos "+str(mainpos)) print("wrote "+str(len(poslines))+" tracks") return def set_chain_format(): do_command("cs-option -f:"+bits+","+channels+","+srate) def remove_block(): if blocktime() == False: return result=do_command("cs-get-length") global bs,be mainlength=result-blocktime() # mainlength=e.last_float()-blocktime() mainpos=keepme if mainpos > bs and mainpos < be: mainpos=bs do_command("stop") do_command("cs-disconnect chain1") do_command("cs-remove chain1") do_command("cs-add chain1") set_chain_format() # do_command("c-add chain1") do_command("ai-add "+infile) do_command("ao-add "+infile) do_command("ai-select "+infile) do_command("ai-setpos "+str(be)) do_command("ao-select "+infile) do_command("ao-setpos "+str(bs)) do_command("cs-connect chain1") do_command("start") waitfortask() do_command("cs-disconnect chain1") do_command("cs-remove chain1") base_infile=os.path.basename(os_infile) dir_infile=os.path.dirname(os_infile) if dir_infile=="": dir_infile=os.path.curdir tempfile=dir_infile+"/tmp_"+base_infile os.rename(os_infile, tempfile) do_command("cs-add chain1") set_chain_format() # do_command("c-add chain1") do_command("ai-add "+escape_filename(tempfile)) do_command("ao-add "+infile) do_command("ao-select "+infile) # do_command("cop-select chain1") do_command("cs-connect chain1") do_command("cs-set-length "+str(mainlength)) do_command("start") waitfortask() do_command("cs-disconnect chain1") do_command("cs-remove chain1") os.unlink(tempfile) do_command("cs-add chain1") set_chain_format() # do_command("c-add chain1") do_command("ai-add "+infile) do_command("ao-add "+soundout) do_command("cs-connect chain1") if mainpos >= be: do_command("setpos "+str(mainpos - blocktime())) else: do_command("setpos "+str(mainpos)) print("removed ",blocktime()," second block now "+str(mainlength)) bs=0 be=0 return def range_check(start_end): global bs, be, block_controls_active if start_end=="start" and (not block_controls_active) and currentpos() be: do_command("setpos "+str(be)) return file_length=do_command("cs-get-length") if start_end=="end" and currentpos() > file_length: do_command("setpos "+str(file_length)) return return def waitfortask(): time.sleep(0.25) status=do_command("engine-status") while status == "running": status=do_command("engine-status") def record_realtime(): do_command("stop") global keepme, buttons, denoise mainpos=keepme buttons["f2"]="recording" do_command("cs-disconnect chain1") do_command("cs-remove chain1") if os.system("test -f realtime.wav") == 0: os.unlink("realtime.wav") do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() do_command("ai-add "+soundin) do_command("ao-add realtime.wav") do_command("cs-connect chain1") deactivate_block_controls() user_control() reactivate_block_controls() buttons["f2"]="play" do_command("cs-disconnect chain1") do_command("cs-remove chain1") if denoise: os.rename("realtime.wav", "with_noise.wav") print("denoising, please wait") denoised=getstatusoutput("sox with_noise.wav realtime.wav vol 0.5 speexdsp -denoise 90 norm") if denoised[0] !=0: print("Problem denoising, reason: "+denoised[1]) os.rename("with_noise.wav", "realtime.wav") insert_file("realtime.wav", mainpos) return def add_file(): global keepme mainpos=keepme do_command("stop") if os.system("which pickafile 2> /dev/null > /dev/null") == 0: rc=os.system("pickafile") if rc > 0: return else: newfile=getoutput("cat $HOME/.kies/.`getterm`file") else: newfile=raw_input("filename to insert? ") newfile=escape_filename(newfile) do_command("cs-disconnect chain1") do_command("cs-remove chain1") insert_file(newfile, mainpos) return def record_wifi(): global keepme mainpos=keepme do_command("stop") wifi=os.system('bash kies_wifi_microphone') if wifi != 0: print("wireless recording failed") return newfile="realtime.wav" do_command("cs-disconnect chain1") do_command("cs-remove chain1") insert_file(newfile, mainpos) return def sameformat(checkfile): do_command("cs-add checkchain") do_command("cs-select checkchain") do_command("c-add check") do_command("c-select check") do_command("ai-add "+checkfile) do_command("ao-add null") do_command("cs-connect checkchain") do_command("engine-launch") do_command("ai-select "+checkfile) newformat=do_command("ai-get-format") do_command("cs-disconnect checkchain") do_command("cs-remove checkchain") if newformat==masterformat: print("formats are the same") result=True return result print(checkfile+" is "+newformat) result=False return result def insert_file(newfile, plek): do_command("cs-add chain1") do_command("c-add chain1") do_command("ai-add "+newfile) do_command("ao-add null") do_command("cs-connect chain1") do_command("ai-select "+newfile) runfor=do_command("ai-get-length "+newfile) do_command("cs-disconnect chain1") do_command("cs-remove chain1") format_native=sameformat(newfile) do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() do_command("ai-add "+infile) do_command("ao-add tmp_l.wav") do_command("cs-select chain1") do_command("cs-connect chain1") waitfortask() do_command("cs-set-length "+str(plek)) waitfortask() do_command("ai-select "+infile) waitfortask() do_command("ai-setpos 0") waitfortask() do_command("start") waitfortask() print("written left side up to: ",currentpos()) do_command("cs-disconnect chain1") waitfortask() do_command("cs-remove chain1") waitfortask() do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() if format_native: do_command("ai-add "+newfile) else: do_command("ai-add resample-hq,auto,"+newfile) waitfortask() do_command("ao-add tmp_l.wav") do_command("cs-connect chain1") waitfortask() do_command("ao-select tmp_l.wav") do_command("ao-setpos "+str(plek)) waitfortask() do_command("cs-set-length "+str(runfor)) waitfortask() print("inserting "+newfile+" which is ",runfor," seconds long") do_command("start") status=do_command("engine-status") while status == "not started": status=do_command("engine-status") waitfortask() newpos=plek+currentpos() print("starting at "+str(plek)+" inserted up to "+str(newpos)) do_command("cs-disconnect chain1") waitfortask() do_command("cs-remove chain1") waitfortask() do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() do_command("ai-add "+infile) do_command("ao-add tmp_l.wav") do_command("cs-connect chain1") waitfortask() do_command("ai-select "+infile) do_command("ai-setpos "+str(plek)) waitfortask() do_command("ao-select tmp_l.wav") do_command("ao-setpos "+str(newpos)) waitfortask() status=do_command("engine-status") while status != "not started": status=do_command("engine-status") do_command("start") waitfortask() print("Finished inserting "+newfile) do_command("cs-disconnect chain1") waitfortask() do_command("engine-status") do_command("cs-remove chain1") waitfortask() os.unlink(os_infile) os.rename("tmp_l.wav", os_infile) do_command("cs-add chain1") do_command("c-add chain1") set_chain_format() do_command("ai-add "+infile) do_command("ao-add "+soundout) do_command("cs-connect chain1") waitfortask() do_command("cs-setpos "+str(plek)) do_command("start") return def user_control(): key='f2' global buttons, bs,be,keepme,block_controls_active, denoise while key != 'q': keepme = currentpos() if key == 'f1': print(buttons[key]) do_command("stop") if key == 'f2': print(buttons[key]) do_command("start", "running") if key == 'f3': print(buttons[key]) do_command("rewind 60") range_check("start") if key == 'f4': print(buttons[key]) do_command("forward 60") range_check("end") if key == 'f5': bs=currentpos() print('begin block at ',bs) if key == 'f6': be=currentpos() print('end block at ',be) if key == 'f7': deactivate_block_controls() playblock() print(buttons[key]) reactivate_block_controls() if key == 'f8': print(buttons[key]) write_block() if key == 'f9': print(buttons[key]) remove_block() if key == 'f10': print(buttons[key]) denoise=False record_realtime() if key == 'ctrl_f10': print(buttons[key]) denoise=False record_wifi() if key == 'shift_f10': print(buttons[key]) denoise=True record_realtime() if key == 'f11': print(buttons[key]) add_file() if key == 'f12': einde=do_command("cs-get-length", "running") do_command("setpos "+str(einde), "running") print('go to end at ',einde) if key == 'home': do_command("setpos 0.0", "running") if not block_controls_active: do_command("setpos "+str(bs)) print('go to start') if key == 'left': do_command("rewind 5") range_check("start") print('rewind') if key == 'right': movearound("f") print('forward') if key == 'w': print('now at: ',currentpos()) if key == 'j': jump=raw_input("jump to?") einde=do_command("cs-get-length") if float(jump) >= einde: print('jump value past end of file, going to end at ',einde) jump=einde do_command("setpos "+str(jump)) if key == 'J': jump=prevpos do_command("setpos "+str(jump)) print(buttons[key]+" : "+str(currentpos())) if key == 'l': print(buttons[key]) go_slow() if key=="p": print(buttons[key]+": "+write_position()+" track "+str(len(poslines))) if key=="S": print(buttons[key]) split_tracks() key=getoutput("catchkey") if key not in active_controls: print(key,' inactive here') key = '' #Main program starts here. do_command("cs-add chain1") do_command("c-add chain1") do_command("ai-add "+infile) do_command("ao-add "+soundout) do_command("cs-connect chain1") do_command("ai-select "+infile) do_command("start") keepme = currentpos() masterformat=do_command("ai-get-format") print("file: ",infile,"master format is: ",masterformat," position ",keepme) fm=masterformat.split(',') bits=fm[0] channels=fm[1] srate=fm[2] #print("bits: ",bits,"channels: ",channels,"samples: ",srate) init_write_position() key='f2' active_controls=['f1','f2','f3','f4','f5','f6','f7','f8','f9','f10','shift_f10','ctrl_f10','f11','f12','left','right','home','j','J','w','q','l','p','S'] user_control() do_command("cs-disconnect chain1") print("exiting" )