123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- from GtkSelectionList import GtkSelectionList
- from GtkButtonGrid import GtkButtonGrid
- from gi.repository import Gdk
- from gi.repository import Gtk
- from pad import *
- import os
- import simplemidi
- import sys
- gtk=Gtk
- from MidiConst import *
- def when_button_is_clicked(label):
- '''
- Quand le bouton est cliqué
- '''
- label.set_text('Hello world!')
- def ok(btn):
- print("OK clicked")
- _GAMME = {
- "Personalisée": "",
- "Majeur" : GAMME_MAJEUR,
- "Mineur naturelle" : GAMME_MINEUR_NATURELLE,
- "Mineur harmonique" : GAMME_MINEUR_HARMONIQUE,
- "Mineur mélodique" : GAMME_MINEUR_MELODIQUE
- }
- class Pane:
- def __init__(self, app):
- self.app = app
- self.pad=app.pad
- self.builder = app.builder
- def connect(self, name, signal, fct):
- self.builder.get_object(name).connect(signal, fct)
- def widget(self, name):
- return self.builder.get_object(name)
- class _Dialog:
- def __init__(self, parent, name):
- self.builder=parent.builder
- self.parent=parent
- self.dialog=self.widget(name)
- self.dialog.connect("delete-event", self.drop)
- self.modify=False
- self.isInit=False
- def on_ok(self, btn):
- self.dialog.hide()
- self.dialog.hide()
- if self.modify:
- self.parent.on_modify_return(self.get_data())
- else:
- self.parent.on_add_return(self.get_data())
- def on_cancel(self, x=None):
- self.dialog.hide()
- self.dialog.hide()
- def run(self):
- if not self.isInit:
- self.dialog.show()
- self.isInit=True
- self.dialog.hide()
- self.update(None)
- self.dialog.show()
- def get_data(self):
- raise NotImplementedError
- def _init(self, data, ):
- raise NotImplementedError
- def drop(self,a,b):
- self.dialog.hide()
- return True
- def connect(self, name, signal, fct):
- self.builder.get_object(name).connect(signal, fct)
- def widget(self, name):
- return self.builder.get_object(name)
- def init(self, data):
- self.modify=data!=None
- self._init(data)
- self.update(None)
- class NewDialog(_Dialog):
- def __init__(self, pane):
- super().__init__(pane, "new_pad_conf_dialog")
- self.cb=self.widget("cb_new_pad")
- l=PadManager.pad_list()
- for k in l: self.cb.append(k,k)
- if len(l): self.cb.set_active(0)
- self.widget("new_pad").connect("clicked", self.on_valid)
- self.app=pane
- def on_valid(self, x):
- self.app.on_new(self.cb.get_active_id())
- self.drop(None,None)
- def update(self, x): pass
- class InitDialog(_Dialog):
- def __init__(self, pane):
- super().__init__(pane, "init_dialog")
- self.wchannel=[self.widget("init_enable_channel"),self.widget("init_channel_value"),self.widget("init_channel_absolute")]
- self.wkey=[self.widget("init_enable_key"),self.widget("init_key_value"),self.widget("init_key_absolute")]
- self.wvelocity=[self.widget("init_enable_velocity"),self.widget("init_velocity_value"),self.widget("init_velocity_absolute")]
- self.widget("init_ok").connect("clicked", self.on_ok)
- self.widget("init_cancel").connect("clicked", self.on_cancel)
- self.wchannel[0].connect("toggled", self.update)
- self.wkey[0].connect("toggled", self.update)
- self.wvelocity[0].connect("toggled", self.update)
- self.message=self.widget("init_message")
- def get_data(self):
- return [
- self.message.get_active_id(),
- int(self.wchannel[1].get_value()) if self.wchannel[0].get_active() else -1,
- int(self.wkey[1].get_value()) if self.wkey[0].get_active() else -1,
- int(self.wvelocity[1].get_value()) if self.wvelocity[0].get_active() else -1
- ]
- def _init(self, data):
- self.message.set_active(0)
- self.wchannel[0].set_active(False)
- self.wkey[0].set_active(False)
- self.wvelocity[0].set_active(False)
- self.wchannel[1].set_sensitive(False)
- self.wkey[1].set_sensitive(False)
- self.wvelocity[1].set_sensitive(False)
- self.wchannel[1].set_value(0)
- self.wkey[1].set_value(0)
- self.wvelocity[1].set_value(0)
- if data:
- self.message.set_active_id(data[0])
- self.wchannel[0].set_active(data[1]>=0)
- self.wkey[0].set_active(data[2]>=0)
- self.wvelocity[0].set_active(data[3]>=0)
- self.wchannel[1].set_sensitive(data[1]>=0)
- self.wkey[1].set_sensitive(data[2]>=0)
- self.wvelocity[1].set_sensitive(data[3]>=0)
- self.wchannel[1].set_value(data[1])
- self.wkey[1].set_value(data[2])
- self.wvelocity[1].set_value(data[3])
- def update(self, x):
- self.wchannel[1].set_sensitive(self.wchannel[0].get_active())
- self.wkey[1].set_sensitive(self.wkey[0].get_active())
- self.wvelocity[1].set_sensitive(self.wvelocity[0].get_active())
- class OperationDialog(_Dialog):
- def __init__(self, pane):
- super().__init__(pane, "operation_dialog")
- self.cbtype=self.widget("operation_type")
- self.cbtype.connect("changed", self.update)
- self.current_type="TRANSLATE"
- self.widget("operation_ok").connect("clicked", self.on_ok)
- self.widget("operation_cancel").connect("clicked", self.on_cancel)
- self.frames={
- "TRANSLATE" : self.widget("operation_translate"),
- "RANGE" : self.widget("operation_range"),
- "REORDER" : self.widget("operation_reorder"),
- "DROP" : self.widget("operation_drop")
- }
- self.reorder_offest=self.widget("operation_offset")
- self.gamme_note=self.widget("operation_gamme_note")
- self.gamme_gamme=self.widget("operation_gamme_gamme")
- self.gamme_custom=self.widget("operation_gamme_custom")
- self.gamme_octave=self.widget("operation_gamme_note_octave")
- self.trans_ch=[self.widget("operation_translate_channel"), self.widget("operation_translate_channel_absolute")]
- self.trans_key=[self.widget("operation_translate_key"), self.widget("operation_translate_key_absolute")]
- self.trans_vel=[self.widget("operation_translate_velocity"), self.widget("operation_translate_velocity_absolute")]
- for k in _GAMME: self.gamme_gamme.append(k, k)
- for k in ARR_NOTE: self.gamme_note.append(k, k)
- self.update()
- def update(self, x=None):
- self.current_type=self.cbtype.get_active_id()
- for k in self.frames:
- if k==self.current_type:
- self.frames[k].show()
- else:
- self.frames[k].hide()
- def get_data(self):
- if self.current_type=="TRANSLATE":
- values=[self.trans_ch[0].get_value(),self.trans_key[0].get_value(),self.trans_vel[0].get_value()]
- modes=[self.trans_ch[1].get_active(),self.trans_key[1].get_active(),self.trans_vel[1].get_active()]
- return TranslateOperation.new(values, modes)
- elif self.current_type=="DROP":
- return DropOperation.new()
- elif self.current_type=="RANGE":
- gamme=self.gamme_gamme.get_active_id()
- gamme=_GAMME[gamme] if gamme else json.loads("["+self.gamme_custom.get_text()+"]")
- note=Note.parse(self.gamme_note.get_active_id()+self.gamme_octave.get_active_id())
- return RangeOperation.new(gamme, note)
- elif self.current_type=="REORDER":
- return ReorderOperation.new(int(self.reorder_offest.get_value()))
- def _init(self, data):
- self.gamme_gamme.set_active(0)
- self.gamme_note.set_active(0)
- self.gamme_octave.set_active(5)
- self.gamme_custom.set_text("")
- self.trans_ch[0].set_value(0)
- self.trans_key[0].set_value(0)
- self.trans_vel[0].set_value(0)
- self.trans_ch[1].set_active(False)
- self.trans_key[1].set_active(False)
- self.trans_vel[1].set_active(False)
- self.reorder_offest.set_value(0)
- if data:
- self.cbtype.set_active_id(data.type)
- if isinstance(data, RangeOperation):
- self.gamme_note.set_active(Note.get_note(data.key))
- self.gamme_octave.set_active(Note.get_octave(data.key))
- range_set=False
- for i in _GAMME:
- if _GAMME[i]!="" and _GAMME[i]==data.range:
- range_set=True
- self.gamme_gamme.set_active_id(i)
- if not range_set:
- self.gamme_custom.set_text(str(data.range)[1:-1])
- if isinstance(data, ReorderOperation):
- self.reorder_offest.set_value(int(data.offset))
- if isinstance(data, TranslateOperation):
- self.trans_ch[0].set_value(data.channel)
- self.trans_key[0].set_value(data.key)
- self.trans_vel[0].set_value(data.velocity)
- self.trans_ch[1].set_active(data.channelmode=="FIXED")
- self.trans_key[1].set_active(data.keymode=="FIXED")
- self.trans_vel[1].set_active(data.velocitymode=="FIXED")
- class CRUDPane(Pane):
- def __init__(self, app, prefix):
- super().__init__(app)
- #self.widget(prefix+"_down").connect("clicked", self.on_down)
- self.widget(prefix+"_up").connect("clicked", self._on_up)
- self.widget(prefix+"_remove").connect("clicked", self._on_remove)
- self.widget(prefix+"_add").connect("clicked", self._on_add)
- self.widget(prefix+"_edit").connect("clicked", self._on_edit)
- self.list=self.widget(prefix+"_listbox")
- self.dialog=None
- self.data=[]
- def print(self, tmp="After"):
- pass
- def get_index(self): return self.find_index(self.list.get_selected_row())
- def find_index(self, widget):
- n=-1
- if not widget: return -1
- widget=widget.get_child()
- for i in range(len(self.data)):
- k=self.data[i]
- if k[1]==widget:
- return i
- return -1
- def insert(self, i, data):
- self.data.append(None)
- for j in reversed(range(i,len(self.data)-1)):
- self.data[j+1]=self.data[j]
- lbl=Gtk.Label.new(str(data))
- self.data[j] =(data, lbl)
- self.list.insert(lbl, i)
- self.list.show_all()
- def _on_up(self, btn):
- if not self.app.sel_pane.get_current_selection(): return
- n=self.get_index()
- if n>0:
- x=self.data[n]
- self.list.remove(x[1].get_parent())
- self.insert(n-1, x[0])
- self.data.remove(x)
- self.list.select_row(self.data[n-1][1].get_parent())
- self.on_up(n)
- self.print("up")
- def _on_down(self, btn):
- if not self.app.sel_pane.get_current_selection(): return
- n=self.get_index()
- if n>=0 and n<=len(self.data)-1:
- x=self.data[n]
- self.list.remove(x[1].get_parent())
- self.insert(n+1, x[0])
- self.data.remove(x)
- self.list.select_row(self.data[n+1][1].get_parent())
- self.on_down(n)
- self.print("down")
- def _on_remove(self, btn):
- if not self.app.sel_pane.get_current_selection(): return
- n=self.get_index()
- if n>=0:
- x=self.data[n]
- self.list.remove(x[1].get_parent())
- self.data.remove(x)
- self.on_remove(n)
- self.print("remove")
- def _on_add(self, btn):
- if not self.app.sel_pane.get_current_selection(): return
- self.dialog.init(None)
- self.dialog.run()
- def _on_edit(self, btn):
- if not self.app.sel_pane.get_current_selection(): return
- n=self.get_index()
- if n>=0:
- self.dialog.init(self.data[n][0])
- self.dialog.run()
- def init(self, data):
- self.data=[]
- ch = self.list.get_children()
- for i in ch: self.list.remove(i)
- for d in data:
- self.add_on_ui(d)
- def data_to_str(self, x):
- return str(x)
- def add_on_ui(self, data):
- lbl=Gtk.Label.new(self.data_to_str(data))
- lbl.set_alignment(0,0)
- self.data.append((data, lbl))
- self.list.add(lbl)
- self.list.show_all()
- def on_add_return(self, data):
- self.add_on_ui(data)
- self.on_add(data)
- self.print("add")
- def on_modify_return(self, data):
- n=self.find_index(self.list.get_selected_row())
- lbl=self.data[n][1]
- lbl.set_label(self.data_to_str(data))
- self.data[n]=(data, lbl)
- self.on_modify(n, data)
- self.print("modify")
- def on_add(self, x): raise NotImplementedError
- def on_modify(self, i, x): raise NotImplementedError
- def on_remove(self, i): raise NotImplementedError
- def on_up(self, i): raise NotImplementedError
- def on_down(self, i): raise NotImplementedError
- class InitPane(CRUDPane):
- def __init__(self, app):
- super().__init__(app, "init")
- self.dialog=InitDialog(self)
- def data_to_str(self, x):
- out=""
- if x[0]=="noteon": out="NoteOn("
- if x[0]=="noteoff": out="NoteOff("
- args=[]
- if x[1]>=0: args.append("channel %d"%x[1])
- if x[2]>=0: args.append("key %d"%x[2])
- if x[3]>=0: args.append("velocity %d"%x[3])
- return out+",".join(args)+")"
- def on_add(self, x):
- sel = self.app.sel_pane.get_current_selection()
- sel.init.actions.append(InputAction(x))
- def on_modify(self, i, x):
- sel = self.app.sel_pane.get_current_selection()
- sel.init.actions[i]=InputAction(x)
- def on_remove(self, i):
- sel = self.app.sel_pane.get_current_selection()
- sel.init.actions.remove(sel.init.actions[i])
- def on_up(self, i):
- sel = self.app.sel_pane.get_current_selection()
- tmp=sel.init.actions[i]
- sel.init.actions[i]=sel.init.actions[i-1]
- sel.init.actions[i-1]=tmp
- def on_down(self, i):
- sel = self.app.sel_pane.get_current_selection()
- tmp=sel.init.actions[i]
- sel.init.actions[i]=sel.init.actions[i+1]
- sel.init.actions[i+1]=tmp
- class OperationPane(CRUDPane):
- def __init__(self, app):
- super().__init__(app, "operation")
- self.dialog=OperationDialog(self)
- def on_add(self, x):
- sel = self.app.sel_pane.get_current_selection()
- sel.operations.append(x)
- def on_modify(self, i, x):
- sel = self.app.sel_pane.get_current_selection()
- sel.operations[i]=x
- def on_remove(self, i):
- sel = self.app.sel_pane.get_current_selection()
- sel.operations.remove(sel.operations[i])
- def on_up(self, i):
- sel = self.app.sel_pane.get_current_selection()
- tmp=sel.operations[i]
- sel.operations[i]=sel.operations[i-1]
- sel.operations[i-1]=tmp
- def on_down(self, i):
- sel = self.app.sel_pane.get_current_selection()
- tmp=sel.operations[i]
- sel.operations[i]=sel.operations[i+1]
- sel.operations[i+1]=tmp
- class SelectionPane(Pane):
- def __init__(self, app):
- super().__init__(app)
- self.input_new_pad=self.builder.get_object("input_new_pad")
- self.sel_list=GtkSelectionList()
- self.pad=app.pad
- self.builder.get_object("sel_pane_root").pack_start(self.sel_list, True, True, 0)
- self.builder.get_object("sel_pane_root").reorder_child(self.sel_list,1)
- self.sel_list.set_on_selected(self.on_selections_changed)
- self.connect("button_new_sel", "clicked", self.on_new_sel)
- self.grid=GtkButtonGrid()
- self.grid.set_on_select(self.on_button_selected)
- self.grid.set_on_unselect(self.on_button_unselected)
- self.widget("grid_root").pack_start(self.grid, True, True, 0)
- self.entry_name=self.widget("entry_sel_name")
- self.widget("rename_sel").connect("clicked", self.on_name_change)
- self.sel_edit_box=self.widget("sel_edit_box")
- self.modifying=False
- self.init_pane=InitPane(self.app)
- self.op_pane=OperationPane(self.app)
- def on_name_change(self, editable):
- old=self.sel_list.current_selection_name
- new=self.entry_name.get_text()
- self.pad.rename_selection(old, new)
- self.sel_list.rename(old, new)
- def on_new_sel(self, btn):
- name = self.input_new_pad.get_text()
- sel=self.pad.new_sel(name)
- self.sel_list.append(name, sel)
- self.input_new_pad.set_text("")
- def on_selections_changed(self, sel, selection):
- self.set_selection(sel, selection)
- self.entry_name.set_text(sel if sel else "")
- def set_selection(self, name, selection):
- self.modifying=True
- self.grid.unselect_all()
- if name:
- for i in selection.inputs:
- self.grid[i].select()
- self.sel_edit_box.set_visible(True)
- self.sel_edit_box.show()
- self.sel_edit_box.queue_draw()
- self.init_pane.init(selection.init.json())
- self.op_pane.init(selection.operations)
- self.sel_edit_box.show()
- else:
- self.init_pane.init([])
- self.op_pane.init([])
- self.sel_edit_box.hide()
- self.grid.update()
- self.modifying=False
- def init(self, pad):
- self.modifying=True
- self.pad=pad
- self.sel_list.init()
- print(self.sel_list.get_children())
- for k in self.pad.selections:
- self.sel_list.append(k, self.pad.selections[k])
- self.grid.set_grid_size(self.pad.width, self.pad.height)
- for i in range(self.pad.width*self.pad.height):
- sel = self.pad.find_selection_of(i)
- if sel: sel=self.pad.selections[sel]
- self.grid[i]=(sel, self.pad.matrix[i], i)
- self.modifying=False
- def get_current_selection_name(self):
- return self.sel_list.current_selection_name
- def get_current_selection(self):
- n=self.sel_list.current_selection_name
- if n and n in self.pad.selections:
- return self.pad.selections[n]
- return None
- def on_button_selected(self, i, btn):
- if not self.modifying and self.get_current_selection_name():
- self.pad.add_button_to(self.sel_list.current_selection_name, i)
- btn.select()
- def on_button_unselected(self, i, btn):
- if not self.modifying and self.get_current_selection_name():
- self.pad.remove_button_selection(i)
- btn.unselect()
- class Application:
- def __init__(self):
- self.builder = Gtk.Builder()
- self.builder.add_from_file('ui.glade')
- self.window=self.builder.get_object('main_window')
- self.window.connect('delete-event', Gtk.main_quit)
- self.pad=None
- self.sel_pane=SelectionPane(self)
- self.window.show_all()
- self.widget("menu_open").connect("activate", self.open_dialog)
- self.widget("menu_save").connect("activate", self.on_save_as)
- self.widget("menu_save_as").connect("activate", self.save_dialog)
- self.widget("menu_new").connect("activate", self.new_dialog)
- self.widget("toolbox_start").connect("clicked", self.start_simple_midi)
- self.widget("toolbox_clear").connect("clicked", self.reset_simple_midi)
- self.file_open=None
- self.file_dir_open=None
- self.changed=False
- self.simplemidi= simplemidi.SimpleMidi()
- self.simplemidi.run()
- self.widget("notebook").hide()
- self.dialog_new=NewDialog(self)
- def widget(self, name):
- return self.builder.get_object(name)
- def connect(self, name, signal, fct):
- self.builder.get_object(name).connect(signal, fct)
- def set_pad_configuration(self, conf):
- self.pad=PadConfiguration.parse(conf)
- self.init()
- def set_new_pad(self, pad):
- self.pad=PadConfiguration.new(pad)
- self.init()
- def set_changed(self):
- self.cahnged=True
- self.window.set_title("*"+os.path.basename(self.file_open))
- def init(self):
- self.sel_pane.init(self.pad)
- def open(self, file :str):
- self.set_pad_configuration(file)
- self.window.show_all()
- self.sel_pane.set_selection(None, None)
- self.file_open=file
- self.file_dir_open=os.path.dirname(file)
- self.widget("selection_root_pane").set_position(100)
- self.window.set_title(os.path.basename(self.file_open))
- self.simplemidi.set_pad(self.pad.name)
- def save(self, file):
- with open(file, "w") as f:
- f.write(json.dumps(self.pad.json(), indent=4))
- self.changed=False
- def test(self):
- with open("test", "w") as f:
- f.write(json.dumps(self.pad.json(), indent=4))
- def open_dialog(self, x):
- dialog = Gtk.FileChooserDialog("Please choose a file", self.window,
- Gtk.FileChooserAction.OPEN,
- (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
- Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
- response = dialog.run()
- if response == Gtk.ResponseType.OK:
- file_path = dialog.get_filename()
- self.open(file_path)
- elif response == Gtk.ResponseType.CANCEL:
- pass
- dialog.destroy()
- def save_dialog(self, x):
- dialog = Gtk.FileChooserDialog("Please choose a file", self.window,
- Gtk.FileChooserAction.SAVE,
- (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
- Gtk.STOCK_SAVE_AS, Gtk.ResponseType.OK))
- dialog.set_current_folder(self.file_dir_open if self.file_dir_open else ".")
- dialog.set_filename(os.path.basename(self.file_open))
- response = dialog.run()
- if response == Gtk.ResponseType.OK:
- file_path = dialog.get_filename()
- self.save(file_path)
- elif response == Gtk.ResponseType.CANCEL:
- pass
- dialog.destroy()
- def on_save_as(self, x):
- if self.file_dir_open:
- self.save(self.file_open)
- else:
- self.save_dialog(None)
- def new_dialog(self, x):
- self.dialog_new.run()
- def reset_simple_midi(self, x):
- if self.pad:
- self.simplemidi.clear()
- def start_simple_midi(self, x):
- if self.pad:
- self.simplemidi.set_configuration_data(self.pad)
- def on_new(self, pad):
- self.set_new_pad(pad)
- self.file_open=pad+" configuration"
- self.file_dir_open=None
- self.set_changed()
- self.window.show_all()
- def main(self):
- self.window.show()
- Gtk.main()
- app = Application()
- app.open("conf3.conf")
- app.main()
|