Add (optional) GUI
This commit is contained in:
parent
91afc2def3
commit
1bdd8a7b79
205
git-sound.py
205
git-sound.py
@ -110,6 +110,208 @@ def get_file_sha(commit, file_name):
|
||||
return t.hexsha
|
||||
|
||||
|
||||
class GitSoundWindow(object):
|
||||
def __init__(self):
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
self.Gtk = Gtk
|
||||
|
||||
from gi.repository import GLib
|
||||
self.GLib = GLib
|
||||
|
||||
self.builder = self.Gtk.Builder()
|
||||
self.builder.add_from_file('git-sound.ui')
|
||||
|
||||
self.play_button = self.builder.get_object('play-button')
|
||||
self.stop_button = self.builder.get_object('stop-button')
|
||||
|
||||
def read_branches(self, chooser_button):
|
||||
self.gitmidi = None
|
||||
repo_path = chooser_button.get_file().get_path()
|
||||
self.branch_combo.remove_all()
|
||||
self.branch_combo.set_button_sensitivity(False)
|
||||
self.set_buttons_sensitivity(disable_all=True)
|
||||
|
||||
try:
|
||||
repo = Repo(repo_path)
|
||||
except InvalidGitRepositoryError:
|
||||
dialog = self.Gtk.MessageDialog(
|
||||
chooser_button.get_toplevel(),
|
||||
self.Gtk.DialogFlags.MODAL,
|
||||
self.Gtk.MessageType.ERROR,
|
||||
self.Gtk.ButtonsType.OK,
|
||||
"{} is not a valid Git repository".format(
|
||||
repo_path))
|
||||
|
||||
dialog.connect('response',
|
||||
lambda dialog, response_id: dialog.destroy())
|
||||
dialog.run()
|
||||
|
||||
return
|
||||
|
||||
self.set_status('Opened repository: {}'.format(repo_path))
|
||||
self.branch_combo.set_button_sensitivity(True)
|
||||
|
||||
for head in repo.heads:
|
||||
self.branch_combo.append_text(head.name)
|
||||
|
||||
def set_status(self, text):
|
||||
self.statusbar.push(self.statusbar.get_context_id("git-sound"), text)
|
||||
|
||||
def settings_changed(self, button):
|
||||
self.gitmidi = None
|
||||
self.set_buttons_sensitivity()
|
||||
self.stop_midi()
|
||||
|
||||
def set_buttons_sensitivity(self, disable_all=False):
|
||||
generate_button = self.builder.get_object('generate-button')
|
||||
stop_button = self.builder.get_object('stop-button')
|
||||
save_button = self.builder.get_object('save-button')
|
||||
|
||||
if disable_all:
|
||||
generate_button.set_sensitive(False)
|
||||
self.play_button.set_sensitive(False)
|
||||
self.stop_button.set_sensitive(False)
|
||||
save_button.set_sensitive(False)
|
||||
|
||||
return
|
||||
|
||||
if self.gitmidi is not None:
|
||||
generate_button.set_sensitive(False)
|
||||
self.play_button.set_sensitive(True)
|
||||
self.stop_button.set_sensitive(False)
|
||||
save_button.set_sensitive(True)
|
||||
|
||||
return
|
||||
|
||||
branch_selected = self.branch_combo.get_active_text() is not None
|
||||
program_selected = self.program_combo.get_active_id() is not None
|
||||
scale_selected = self.scale_combo.get_active_id() is not None
|
||||
|
||||
if branch_selected and program_selected and scale_selected:
|
||||
generate_button.set_sensitive(True)
|
||||
self.play_button.set_sensitive(False)
|
||||
self.stop_button.set_sensitive(False)
|
||||
save_button.set_sensitive(False)
|
||||
|
||||
def generate_repo(self, button):
|
||||
chooser_button = self.builder.get_object('repo-chooser')
|
||||
repo_path = chooser_button.get_file().get_path()
|
||||
branch_selected = self.branch_combo.get_active_text()
|
||||
program_selected = self.program_combo.get_active_id()
|
||||
scale_selected = self.scale_combo.get_active_id()
|
||||
skip = int(self.skip_spin.get_value())
|
||||
vol_deviation = int(self.vol_spin.get_value())
|
||||
|
||||
self.set_status("Generating data")
|
||||
self.progressbar.set_fraction(0.0)
|
||||
self.progressbar.pulse()
|
||||
self.gitmidi = GitMIDI(repository=repo_path,
|
||||
branch=branch_selected,
|
||||
verbose=False,
|
||||
scale=scales[scale_selected][1],
|
||||
program=programs[program_selected],
|
||||
volume_range=vol_deviation,
|
||||
skip=skip)
|
||||
|
||||
self.gitmidi.gen_repo_data(callback=self.genrepo_cb)
|
||||
self.gitmidi.generate_midi(callback=self.genrepo_cb)
|
||||
self.gitmidi.write_mem()
|
||||
|
||||
self.set_buttons_sensitivity(disable_all=False)
|
||||
|
||||
def genrepo_cb(self, max_count=None, current=None):
|
||||
if max_count is None or current is None:
|
||||
self.progressbar.pulse()
|
||||
else:
|
||||
self.progressbar.set_fraction(current / max_count)
|
||||
|
||||
# Make sure the progress bar gets updated
|
||||
self.Gtk.main_iteration_do(False)
|
||||
|
||||
def update_play_pos(self):
|
||||
position = self.gitmidi.get_play_pos()
|
||||
|
||||
if position is None:
|
||||
self.set_status("Stopped")
|
||||
self.pos_label.set_text("0:00")
|
||||
self.play_button.set_sensitive(True)
|
||||
self.stop_button.set_sensitive(False)
|
||||
|
||||
return False
|
||||
|
||||
position = int(position / 1000)
|
||||
|
||||
minutes = int(position / 60)
|
||||
seconds = position - (minutes * 60)
|
||||
|
||||
self.pos_label.set_text("{}:{:02}".format(minutes, seconds))
|
||||
|
||||
return True
|
||||
|
||||
def play_midi(self):
|
||||
self.set_status(u"Playing…")
|
||||
self.gitmidi.play(track=True)
|
||||
self.GLib.timeout_add_seconds(1, self.update_play_pos)
|
||||
self.play_button.set_sensitive(False)
|
||||
self.stop_button.set_sensitive(True)
|
||||
|
||||
def stop_midi(self):
|
||||
if self.gitmidi is not None:
|
||||
self.gitmidi.stop()
|
||||
|
||||
def start(self):
|
||||
program_store = self.builder.get_object('program-list')
|
||||
self.program_combo = self.builder.get_object('program-combo')
|
||||
|
||||
for program_id, program in programs.items():
|
||||
program_store.append([program['name'], program_id])
|
||||
|
||||
renderer = self.Gtk.CellRendererText()
|
||||
self.program_combo.pack_start(renderer, True)
|
||||
self.program_combo.add_attribute(renderer, "text", 0)
|
||||
|
||||
scale_store = self.builder.get_object('scale-list')
|
||||
self.scale_combo = self.builder.get_object('scale-combo')
|
||||
|
||||
for scale_id, scale in scales.items():
|
||||
scale_store.append([scale[0], scale_id])
|
||||
|
||||
renderer = self.Gtk.CellRendererText()
|
||||
self.scale_combo.pack_start(renderer, True)
|
||||
self.scale_combo.add_attribute(renderer, "text", 0)
|
||||
|
||||
self.branch_combo = self.builder.get_object('branch-combo')
|
||||
self.statusbar = self.builder.get_object('statusbar')
|
||||
self.pos_label = self.builder.get_object('position-label')
|
||||
self.skip_spin = self.builder.get_object('skip-spin')
|
||||
self.vol_spin = self.builder.get_object('vol-spin')
|
||||
|
||||
self.builder.connect_signals({
|
||||
'read_branches': lambda button: self.read_branches(button),
|
||||
'settings_changed': lambda button: self.settings_changed(button),
|
||||
'generate_repo': lambda button: self.generate_repo(button),
|
||||
'play_midi': lambda button: self.play_midi(),
|
||||
'stop_midi': lambda button: self.stop_midi(),
|
||||
})
|
||||
|
||||
self.progressbar = self.builder.get_object('generate-progress')
|
||||
|
||||
win = self.builder.get_object('main-window')
|
||||
win.connect("delete-event", self.Gtk.main_quit)
|
||||
win.show_all()
|
||||
self.Gtk.main()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def start_gui():
|
||||
win = GitSoundWindow()
|
||||
win.start()
|
||||
|
||||
|
||||
class GitMIDI(MIDIFile):
|
||||
LOG_CHANNEL = 0
|
||||
FILE_CHANNEL = 1
|
||||
@ -420,6 +622,9 @@ if __name__ == '__main__':
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.scale is None and args.program is None:
|
||||
start_gui()
|
||||
|
||||
if args.scale is None and args.program != 'list':
|
||||
print("Please specify a scale!")
|
||||
|
||||
|
327
git-sound.ui
Normal file
327
git-sound.ui
Normal file
@ -0,0 +1,327 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.16.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.10"/>
|
||||
<object class="GtkImage" id="generate-image">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">applications-system</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="program-list">
|
||||
<columns>
|
||||
<!-- column-name program-name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name program-id -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkListStore" id="scale-list">
|
||||
<columns>
|
||||
<!-- column-name program-name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name program-id -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="skip-adjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="vol-adjustment">
|
||||
<property name="upper">63</property>
|
||||
<property name="value">10</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="main-window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Git Sound</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="scale-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes" context="MIDI scale to use">Scale</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="scale-combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">scale-list</property>
|
||||
<property name="id_column">1</property>
|
||||
<signal name="changed" handler="settings_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="repo-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes" context="The repository to generate music for">Repository</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton" id="repo-chooser">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="action">select-folder</property>
|
||||
<signal name="file-set" handler="read_branches" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="generate-button">
|
||||
<property name="label" translatable="yes">Generate</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="image">generate-image</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="generate_repo" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="play-button">
|
||||
<property name="label">gtk-media-play</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="play_midi" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="save-button">
|
||||
<property name="label">gtk-save-as</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="generate-progress">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pulse_step">0.01</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">7</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="program-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes" context="The MIDI program to use">Program</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="program-combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">program-list</property>
|
||||
<property name="id_column">1</property>
|
||||
<signal name="changed" handler="settings_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="branch-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Branch</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="branch-combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="button_sensitivity">off</property>
|
||||
<signal name="changed" handler="settings_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStatusbar" id="statusbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">8</property>
|
||||
<property name="width">4</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="position-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label">0:00</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">7</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="skip-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Skip commits</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="skip-spin">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="text" translatable="yes">0</property>
|
||||
<property name="adjustment">skip-adjustment</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="vol-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Maximum volume deviation</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="vol-spin">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="text" translatable="yes">10</property>
|
||||
<property name="adjustment">vol-adjustment</property>
|
||||
<property name="value">10</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">3</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="stop-button">
|
||||
<property name="label">gtk-media-stop</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
<signal name="clicked" handler="stop_midi" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
Loading…
Reference in New Issue
Block a user