commit 66a3b9f5428fa197d05545b531fcf6879bb65f60 Author: Patrick Marsee Date: Mon May 10 00:07:58 2021 -0400 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49c95b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +bin +include +lib +lib64 +pyvenv.cfg +aplaymidi_gui.geany + diff --git a/README.md b/README.md new file mode 100644 index 0000000..b044711 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# aplaymidi_gui + +It's terrible, but it gets the job done. Requires Python 3 and tkinter. diff --git a/main.py b/main.py new file mode 100644 index 0000000..a345cb1 --- /dev/null +++ b/main.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# main.py +# +# Copyright 2021 Patrick Marsee +# +# 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 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# + +from tkinter import * +from tkinter import ttk +from tkinter import filedialog as fd +import subprocess as sp +import os + +class MidiPort: + + def __init__(self, port, client_name, port_name): + self.port = port + self.client_name = client_name + self.port_name = port_name + + def __str__(self): + return "{} {}".format(self.port, self.port_name) + +class App(ttk.Frame): + + def __init__(self, master): + super(App, self).__init__(master) + self.devices = self.get_midi_list() + self.create_widgets() + self.midi_port_var.set(str(self.devices[0])) + + def create_widgets(self): + self.midi_port_label = ttk.Label(self, text="Midi Device") + self.midi_port_label.grid(column=0, row=0) + self.midi_port_var = StringVar() + self.midi_port_selector = ttk.Combobox(self, textvariable=self.midi_port_var) + self.midi_port_selector.state(["readonly"]) + self.midi_port_selector['values'] = [str(i) for i in self.devices] + self.midi_port_selector.grid(column=1, row=0, columnspan=2, sticky=(E, W)) + + self.midi_file_label = ttk.Label(self, text="File") + self.midi_file_label.grid(column=0, row=1) + self.midi_file_var = StringVar() + self.midi_file_text = ttk.Entry(self, textvariable=self.midi_file_var, width=80) + self.midi_file_text.grid(column=1, row=1) + self.midi_file_button = ttk.Button(self, + text="Open...", + command=lambda: self.midi_file_var.set(fd.askopenfilename(defaultextension=".mid", filetypes=[("MIDI", ".mid")], initialdir=os.environ['HOME']))) + self.midi_file_button.grid(column=2, row=1, sticky=(E, W)) + + self.play_button = ttk.Button(self, text="Play", command=self.play_midi) + self.play_button.grid(column=1, row=2) + + self.columnconfigure(1, weight=1) + + @staticmethod + def get_midi_list() -> list: + result = sp.run(["aplaymidi", "-l"], stdout=sp.PIPE, encoding="utf-8") + devices = result.stdout.split('\n') + port_start = devices[0].find("Port") + client_name_start = devices[0].find("Client name") + port_name_start = devices[0].find("Port name") + return [MidiPort(i[port_start:client_name_start].strip(), i[client_name_start:port_name_start].strip(), i[port_name_start:].strip()) for i in devices[1:]] + + def play_midi(self): + sp.run(["aplaymidi", "-p", self.devices[self.midi_port_selector.current()].port, self.midi_file_var.get()]) + + def open_file(self): + initial_dir = os.pwd() + if 'HOME' in os.environ: + initial_dir = os.environ['HOME'] + self.midi_file_var.set(fd.askopenfilename(defaultextension=".mid", filetypes=[("MIDI", ".mid")], initialdir=initial_dir)) + +def main(args): + root = Tk() + root.title('aplaymidi_gui') + #root.geometry("1024x768") + #root.resizable(FALSE, FALSE) + root.option_add('*tearOff', FALSE) + root.columnconfigure(0, weight = 1) + root.rowconfigure(0, weight = 1) + newApp = App(root) + newApp.grid(sticky = (N, S, E, W)) + root.mainloop() + return 0 + +if __name__ == '__main__': + import sys + sys.exit(main(sys.argv))