#!/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))