aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xloopertrx.py129
1 files changed, 110 insertions, 19 deletions
diff --git a/loopertrx.py b/loopertrx.py
index 3296c47..569d5c5 100755
--- a/loopertrx.py
+++ b/loopertrx.py
@@ -21,6 +21,16 @@ import argparse
import usb.core
import usb.util
+try:
+ from tkinter import *
+ from tkinter import messagebox
+ from tkinter import filedialog
+ from tkinter.ttk import *
+ use_gui = True
+except ImportError:
+ use_gui = False
+
+PROG_NAME = "LooperTRX"
class USBLooper():
VID = 0x0483
@@ -32,7 +42,8 @@ class USBLooper():
COMMAND_SIZE = 0xfe
COMMAND_DATA = 0xff
- def __init__(self):
+ def __init__(self, ui):
+ self.ui = ui
self.dev = usb.core.find(idVendor=self.VID, idProduct=self.PID)
if not self.dev:
raise FileNotFoundError("Device not found.")
@@ -110,22 +121,21 @@ class USBLooper():
def receive_file(self, filename):
size = self.get_size()
if size == 0:
- print("No data available.")
- sys.exit(0)
+ self.ui.alert("No data available.")
with open(filename, 'wb') as outfile:
self.write_wav_header(outfile, size)
- print("Receiving ", end='', flush=True)
+ self.ui.init_progress(size, "Receiving")
while size > 0:
bufsize = (size >= 65536) and 65536 or size
# data needs to be transferred in multiples of 1k blocks
padding = (1024 - (bufsize % 1024)) % 1024
buf = self.get_data(bufsize + padding)
- print('.', end='', flush=True),
+ self.ui.update_progress(bufsize)
outfile.write(buf[:bufsize])
size -= bufsize
- print(" Done.")
+ self.ui.end_progress()
def transmit_file(self, filename):
with open(filename, 'rb') as infile:
@@ -134,35 +144,116 @@ class USBLooper():
# skip first 44 bytes for now; we assume valid file. TODO: validate
content = content[44:]
content_size = len(content)
- print("Transmitting ", end='', flush=True)
+ self.ui.init_progress(content_size, "Transmitting")
while len(content) > 0:
buf = content[:65536]
padsize = (1024 - (len(buf) % 1024)) % 1024
buf += b'\x00' * padsize
self.send_data(buf, tag)
- print('.', end='', flush=True),
+ self.ui.update_progress(len(buf))
content = content[65536:]
self.submit_data_len(content_size, tag)
- print(" Done.")
+ self.ui.end_progress()
+
+
+class Gui(Frame):
+ def __init__(self, root=None):
+ super().__init__(root)
+ root.geometry("400x300")
+ self.pack(fill=BOTH, expand=1)
+ self.create_widgets()
+
+ def set_device(self, dev):
+ self.dev = dev
+
+ def alert(self, msg):
+ messagebox.showwarning(PROG_NAME, msg)
+
+ def create_widgets(self):
+ self.label = Label(self, text=PROG_NAME)
+ self.label.pack(expand=1)
+
+ self.dl_button = Button(self, text="Download", command=self.download)
+ self.dl_button.pack(fill=BOTH, expand=1, padx=10, pady=5)
+
+ self.ul_button = Button(self, text="Upload", command=self.upload)
+ self.ul_button.pack(fill=BOTH, expand=1, padx=10, pady=5)
+
+ self.progress = Progressbar(self)
+ self.progress.pack(fill=BOTH)
+
+ def download(self):
+ fname = filedialog.asksaveasfilename(filetypes=[('WAVE audio', '.wav')], defaultextension='.wav')
+ if fname:
+ self.dev.receive_file(fname)
+
+ def upload(self):
+ fname = filedialog.askopenfilename(filetypes=[('WAVE audio', '.wav')], defaultextension='.wav')
+ if fname:
+ self.dev.transmit_file(fname)
+
+ def init_progress(self, max_amount, msg=None):
+ self.progress['maximum'] = max_amount
+
+ def update_progress(self, amount):
+ self.progress.step(amount)
+ self.update()
+
+ def end_progress(self):
+ self.update_idletasks()
+ messagebox.showinfo(PROG_NAME, "Transfer finished")
+
+
+class Cli():
+ def set_device(self, dev):
+ pass
+
+ def alert(self, msg):
+ print(msg)
+
+ def init_progress(self, max_amount, msg):
+ print(msg, end='', flush=True)
+
+ def update_progress(self, amount):
+ print('.', end='', flush=True),
+
+ def end_progress(self):
+ print(" Done.")
def main():
- argp = argparse.ArgumentParser()
- argp.add_argument('action', choices=['rx', 'tx'])
- argp.add_argument('filename')
- args = argp.parse_args()
+ global use_gui
+
+ if not use_gui or len(sys.argv) > 1:
+ use_gui = False
+ argp = argparse.ArgumentParser(epilog="Call without parameters to start GUI (if tkinter is available)")
+ argp.add_argument('action', choices=['rx', 'tx'], help="whether to send or receive audio data")
+ argp.add_argument('filename', help="the input/output file")
+ args = argp.parse_args()
+
+ if use_gui:
+ root = Tk()
+ root.withdraw()
+ ui = Gui(root)
+ else:
+ ui = Cli()
try:
- dev = USBLooper()
+ dev = USBLooper(ui)
except FileNotFoundError as e:
- print(e)
+ ui.alert(e)
sys.exit(1)
- if args.action == 'rx':
- dev.receive_file(args.filename)
- elif args.action == 'tx':
- dev.transmit_file(args.filename)
+ if use_gui:
+ root.deiconify()
+ ui.set_device(dev)
+ ui.mainloop()
+ else:
+ if args.action == 'rx':
+ dev.receive_file(args.filename)
+ elif args.action == 'tx':
+ dev.transmit_file(args.filename)
if __name__ == "__main__":