Add (optional) GUI

This commit is contained in:
Gergely Polonkai 2016-06-09 17:54:09 +02:00
parent 91afc2def3
commit 1bdd8a7b79
2 changed files with 532 additions and 0 deletions

View File

@ -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
View 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>