#!/usr/bin/python3 # -*- coding: utf-8 -*- #################################### ### Módulos ### #################################### import dbus from gi.repository import Gtk from gi.repository import Gdk from dbus.mainloop.glib import DBusGMainLoop # Hay que hacer este llamado antes de definir el bus dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) #################################### ### Bus ### #################################### bus = dbus.SessionBus() jack_control_obj = bus.get_object("org.jackaudio.service", "/org/jackaudio/Controller") jack_control_ifa = dbus.Interface(jack_control_obj, "org.jackaudio.JackPatchbay") graph = jack_control_ifa.GetGraph(0) #################################### ### Funciones ### #################################### def match_func_tree(model, iter, data): column, key = data # data es una tupla que contiene número de columna, clave (key) value = model.get_value(iter, column) return value == key def search_tree(model, iter, func, data, include_children = False): while iter: if func(model, iter, data): return iter if include_children: result = search(model, model.iter_children(iter), func, data) if result: return result iter = model.iter_next(iter) return None def get_tree(model, iter, recursive = False): store = [] while iter: store.append(iter) if recursive: store.append(get_tree(model, model.iter_children(iter), recursive=True)) iter = model.iter_next(iter) return store def get_tree_len(model, iter, recursive = False): i = 0 while iter: i += 1 if recursive: i += get_tree_len(model, model.iter_children(iter), recursive=True) iter = model.iter_next(iter) return i def isInputOrOutput(JackPortFlags): if((JackPortFlags & 0x1) != 0): return "input" elif((JackPortFlags & 0x2) != 0): return "output" elif ((JackPortFlags & 0x1) != 0) & ((JackPortFlags & 0x2) != 0): print("Error: Un puerto no puede ser de entrada y salida a la vez") def getID(search, array, id_index): i = 0 exist = False for item in array: if item[id_index] == search: exist = True break i += 1 if exist: return i else: return None #################################### ### Variables ### ### Globales ### #################################### ### 0: Audio Input ### 1: Audio Output ### 2: Midi Input ### 3: Midi Output categorized_ports = [[], [], [], []] for client in graph[1]: for port in client[2]: # Una explicación breve, esto es para ahorrar un if category = int(isInputOrOutput(port[2]) == "output") + int(port[3] == 1) * 2 client_exist = False a_client_id = 0 for cclient in categorized_ports[category]: if cclient[0] == client[0]: client_exist = True break a_client_id += 1 if not client_exist: categorized_ports[category].append([client[0], client[1], []]) client_id = len(categorized_ports[category]) -1 categorized_ports[category][a_client_id][2].append([port[0], port[1], port[2], port[3]]) # Base de datos auxiliar de Clientes y Puertos # clients contiene: # [client_id, client_name, client_instances, client_active] # ports contiene: # [client_id, port_id, port_name, port_flags, port_type, port_selected, port_active] clients = [] ports = [] for client in graph[1]: clients.append([client[0], client[1], [], True]) for port in client[2]: ports.append([client[0], port[0], port[1], port[2], port[3], False, True]) # [client1_id, client1_name, port1_id, port1_name, client2_id, client2_name, port2_id, port2_name, connection_id] connections = graph[2] # [keyboard_id, keyboard_name, [effect_id, active]] effects = [] #################################### ### GUI ### #################################### class MyWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Jack Keyboard Manager") self.set_default_size(700, 500) # Estos dos Arrays contendrán los treestores y los treeviews self.TreeStores = [Gtk.TreeStore(int, str), # 0: Audio Input Gtk.TreeStore(int, str), # 1: Audio Output Gtk.TreeStore(int, str), # 2: MIDI Input Gtk.TreeStore(int, str), # 3: MIDI Output Gtk.TreeStore(int, str), # 4: Audio Input Selected Gtk.TreeStore(int, str), # 5: Audio Output Selected Gtk.TreeStore(int, str), # 6: MIDI Input Selected Gtk.TreeStore(int, str)] # 7: MIDI Output Selected self.TreeViews = [Gtk.TreeView(self.TreeStores[0]), # 0: Audio Input Gtk.TreeView(self.TreeStores[1]), # 1: Audio Output Gtk.TreeView(self.TreeStores[2]), # 2: MIDI Input Gtk.TreeView(self.TreeStores[3]), # 3: MIDI Output Gtk.TreeView(self.TreeStores[4]), # 4: Audio Input Sel Gtk.TreeView(self.TreeStores[5]), # 5: Audio Output Sel Gtk.TreeView(self.TreeStores[6]), # 6: MIDI Input Sel Gtk.TreeView(self.TreeStores[7])] # 7: MIDI Output Sel # Números y letras en orden de un teclado QUERTY español numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] letters1 = ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"] letters2 = ["a", "s", "d", "f", "g", "h", "j", "k", "l"] letters3 = ["z", "x", "c", "v", "b", "n", "m"] self.keymap = [letters3, None, letters1+letters2, numbers] k_numbers = [49,50,51,52,53,54,55,56,57,48] k_letters1 = [113,119,101,114,116,121,117,105,111,112] k_letters2 = [97,115,100,102,103,104,106,107,108] k_letters3 = [122,120,99,118,98,110,109] self.keyvals = [k_letters3, None, k_letters1+k_letters2, k_numbers] # Teclado seleccionado en la pestaña Rutas # [client_id, client_name, port_id, port_name] self.keyboard_selected = None # Bloquear los botones de sintetizador # Para que no se activen automáticamente self.lock_synth = False for num in range(8): cellRenderer = Gtk.CellRendererText() column0 = Gtk.TreeViewColumn("ID", cellRenderer, text=0) column1 = Gtk.TreeViewColumn("Puertos", cellRenderer, text=1) self.TreeViews[num].append_column(column0) self.TreeViews[num].append_column(column1) # Caja Principal main_box = Gtk.VBox(False, 3) # Toda la interfaz se organiza en tres pestañas # - La primera para seleccionar dispositivos # - La segunda para definir las rutas de Jack # - La tercera para configuraciones avanzadas notebook = Gtk.Notebook() notebook.set_tab_pos(2) ### Primera Pestaña: Selección de dispositivos ### box = Gtk.VBox(False, 3) title = "Seleccione los Teclados" frame = Gtk.Frame() frame.set_label(title) table = Gtk.Table(4,3,True) # Modelo teclados # Este modelo contiene los puertos para seleccionar los teclados # Puertos Midi de Salida swT1 = Gtk.ScrolledWindow() self.__create_model(3) swT1.add(self.TreeViews[3]) buttonTADD = Gtk.Button("Agregar ->") buttonTDEL = Gtk.Button("<- Quitar") swT2 = Gtk.ScrolledWindow() # Modelo de Teclados Seleccionados swT2.add(self.TreeViews[7]) table.attach(swT1, 0, 1, 0, 4) table.attach(buttonTADD, 1, 2, 1, 2) table.attach(buttonTDEL, 1, 2, 2, 3) table.attach(swT2, 2, 3, 0, 4) frame.add(table) box.add(frame) # Conexión de los botones para teclados buttonTADD.connect("clicked", self.__sel_item, self.TreeStores[3], self.TreeViews[3], self.TreeStores[7]) buttonTDEL.connect("clicked", self.__sel_item, self.TreeStores[7], self.TreeViews[7], self.TreeStores[3]) title = "Seleccione los Sintetizadores" frame = Gtk.Frame() frame.set_label(title) table = Gtk.Table(4,3,True) # Modelo de los sintetizadores # Este modelo muestra los puertos para seleccionar sintetizadores # Puertos Midi de entrada swS1 = Gtk.ScrolledWindow() self.__create_model(2) swS1.add(self.TreeViews[2]) buttonSADD = Gtk.Button("Agregar ->") buttonSDEL = Gtk.Button("<- Quitar") swS2 = Gtk.ScrolledWindow() # Modelo de Sintetizadores seleccionados swS2.add(self.TreeViews[6]) table.attach(swS1, 0, 1, 0, 4) table.attach(buttonSADD, 1, 2, 1, 2) table.attach(buttonSDEL, 1, 2, 2, 3) table.attach(swS2, 2, 3, 0, 4) frame.add(table) box.add(frame) # Conexión de los botones para sintetizadores buttonSADD.connect("clicked", self.__sel_item, self.TreeStores[2], self.TreeViews[2], self.TreeStores[6]) buttonSDEL.connect("clicked", self.__sel_item, self.TreeStores[6], self.TreeViews[6], self.TreeStores[2]) title = "Seleccione los Efectos" frame = Gtk.Frame() frame.set_label(title) table = Gtk.Table(4,3,True) swE1 = Gtk.ScrolledWindow() self.__create_model(0) swE1.add(self.TreeViews[0]) buttonEADD = Gtk.Button("Agregar ->") buttonEDEL = Gtk.Button("<- Quitar") swE2 = Gtk.ScrolledWindow() swE2.add(self.TreeViews[4]) table.attach(swE1, 0, 1, 0, 4) table.attach(buttonEADD, 1, 2, 1, 2) table.attach(buttonEDEL, 1, 2, 2, 3) table.attach(swE2, 2, 3, 0, 4) frame.add(table) box.add(frame) # Conexión de los botones para sintetizadores buttonEADD.connect("clicked", self.__sel_item, self.TreeStores[0], self.TreeViews[0], self.TreeStores[4], 2) buttonEDEL.connect("clicked", self.__sel_item, self.TreeStores[4], self.TreeViews[4], self.TreeStores[0], 2) self.TreeViews[0].get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) txt = "Puertos" label = Gtk.Label(txt) notebook.append_page(box, label) ### Segunda Pestaña: Selección de salidas ### box = Gtk.VBox(False, 3) txt = "Salidas" label = Gtk.Label(txt) notebook.append_page(box, label) ### Tercera Pestaña: Rutas Jack ### box = Gtk.VBox(False, 3) self.RoutesButtons = [[], None, [], []] self.RoutesLabels = [[], None, [], []] title = "Teclados" frame = Gtk.Frame() frame.set_label(title) box1 = Gtk.HBox(False, 3) i = 0 for number in numbers: self.RoutesLabels[3].append(Gtk.Label(number)) self.RoutesLabels[3][i].set_justify(2) self.RoutesButtons[3].append(Gtk.ToggleButton()) self.RoutesButtons[3][i].add(self.RoutesLabels[3][i]) self.RoutesButtons[3][i].set_size_request(60,60) self.RoutesButtons[3][i].connect("clicked", self.__keyboard, i) box1.pack_start(self.RoutesButtons[3][i], False, False, 0) i += 1 frame.add(box1) box.pack_start(frame, False, False, 0) title = "Sintetizadores" frame = Gtk.Frame() frame.set_label(title) box1 = Gtk.VBox(False, 3) # Primera Línea box2 = Gtk.HBox(False, 3) i = 0 for letter in letters1: self.RoutesLabels[2].append(Gtk.Label(letter)) self.RoutesLabels[2][i].set_justify(2) self.RoutesButtons[2].append(Gtk.ToggleButton()) self.RoutesButtons[2][i].add(self.RoutesLabels[2][i]) self.RoutesButtons[2][i].set_size_request(60,60) self.RoutesButtons[2][i].connect("clicked", self.__connect_synth, i) box2.pack_start(self.RoutesButtons[2][i], False, False, 0) i += 1 box1.pack_start(box2, False, False, 0) # Segunda Línea box2 = Gtk.HBox(False, 3) for letter in letters2: self.RoutesLabels[2].append(Gtk.Label(letter)) self.RoutesLabels[2][i].set_justify(2) self.RoutesButtons[2].append(Gtk.ToggleButton()) self.RoutesButtons[2][i].add(self.RoutesLabels[2][i]) self.RoutesButtons[2][i].set_size_request(60,60) self.RoutesButtons[2][i].connect("clicked", self.__connect_synth, i) box2.pack_start(self.RoutesButtons[2][i], False, False, 0) i += 1 box1.pack_start(box2, False, False, 0) frame.add(box1) box.pack_start(frame, False, False, 0) title = "Efectos" frame = Gtk.Frame() frame.set_label(title) box1 = Gtk.HBox(False, 3) i = 0 for letter in letters3: self.RoutesLabels[0].append(Gtk.Label(letter)) self.RoutesLabels[0][i].set_justify(2) self.RoutesButtons[0].append(Gtk.ToggleButton()) self.RoutesButtons[0][i].add(self.RoutesLabels[0][i]) self.RoutesButtons[0][i].set_size_request(60,60) box1.pack_start(self.RoutesButtons[0][i], False, False, 0) i += 1 frame.add(box1) box.pack_start(frame, False, False, 0) box1 = Gtk.HBox(False, 3) self.multiple_synth = Gtk.CheckButton("Múltiples Sintetizadores") box1.add(self.multiple_synth) box.pack_start(box1, False, False, 0) self.connect("key-press-event", self.keypress) txt = "Rutas" label = Gtk.Label(txt) notebook.append_page(box, label) ### Cuarta Pestaña: Presets ### box = Gtk.VBox(False, 3) txt = "Presets" label = Gtk.Label(txt) notebook.append_page(box, label) main_box.pack_start(notebook, True, True, 0) self.add(main_box) # Añadir o quitar clientes cuando aparecen o desaparaecent jack_control_ifa.connect_to_signal("ClientAppeared", self.__add_client) jack_control_ifa.connect_to_signal("PortAppeared", self.__add_port) jack_control_ifa.connect_to_signal("ClientDisappeared", self.__del_client) jack_control_ifa.connect_to_signal("PortDisappeared", self.__del_port) # Añadir conecciones cuando se producen jack_control_ifa.connect_to_signal("PortsConnected", self.__connection) jack_control_ifa.connect_to_signal("PortsDisconnected", self.__disconnection) def keypress(self, widget, event): for category in [0,2,3]: i = 0 for keyval in self.keyvals[category]: if event.keyval == keyval: value = self.RoutesButtons[category][i].get_active() self.RoutesButtons[category][i].set_active(not value) i += 1 def hide_buttons(self): for button in self.RoutesButtons[0]+self.RoutesButtons[2]+self.RoutesButtons[3]: button.hide() def __create_model(self, num): for client in categorized_ports[num]: iter = self.TreeStores[num].append(None) self.TreeStores[num].set(iter, 0, client[0], 1, client[1]) for port in client[2]: child_iter = self.TreeStores[num].append(iter) self.TreeStores[num].set(child_iter, 0, port[0], 1, port[1]) category = int(isInputOrOutput(port[2]) == "output") + int(port[3] == 1) * 2 caID = getID(client[0], clients, 0) if not category in clients[caID][2]: clients[caID][2].append(category) def __add_client (self, new_graph_version, client_id, client_name): caID = getID(client_name, clients, 1) if caID == None: clients.append([client_id, client_name, [], True]) else: clients[caID][0] = client_id clients[caID][3] = True for instance in [i+4 for i in clients[caID][2]]: changed_client = search_tree(self.TreeStores[instance], self.TreeStores[instance].iter_children(None), match_func_tree, (1, client_name)) self.TreeStores[instance].set(changed_client, 0, client_id) def __add_port (self, new_graph_version, client_id, client_name, port_id, port_name, port_flags, port_type): paID = getID(port_name, ports, 2) if paID == None: category = int(isInputOrOutput(port_flags) == "output") + int(port_type == 1) * 2 # Primero hay que agregar los clientes # a las bases de datos que corresponda in_client = search_tree(self.TreeStores[category], self.TreeStores[category].iter_children(None), match_func_tree, (0, client_id)) if not in_client: # Y aprovechamos de agregar las instancias del cliente clients[getID(client_id, clients, 0)][2].append(category) iter = self.TreeStores[category].append(None) self.TreeStores[category].set(iter, 0, client_id, 1, client_name) # Ahora agregamos los puertos in_client = search_tree(self.TreeStores[category], self.TreeStores[category].iter_children(None), match_func_tree, (0, client_id)) child_iter = self.TreeStores[category].append(in_client) self.TreeStores[category].set(child_iter, 0, port_id, 1, port_name) ports.append([client_id, port_id, port_name, port_flags, port_type, False, True]) else: ports[paID][0] = client_id ports[paID][1] = port_id ports[paID][6] = True category = int(isInputOrOutput(port_flags) == "output") + int(port_type == 1) * 2 + 4 in_client = search_tree(self.TreeStores[category], self.TreeStores[category].iter_children(None), match_func_tree, (1, client_name)) changed_port = search_tree(self.TreeStores[category], self.TreeStores[category].iter_children(in_client), match_func_tree, (1, port_name)) self.TreeStores[category].set(changed_port, 0, port_id) def __del_client (self, new_graph_version, client_id, client_name): caID = getID(client_id, clients, 0) instances = clients[caID][2] for instance in instances: disappeared_client = search_tree(self.TreeStores[instance], self.TreeStores[instance].iter_children(None), match_func_tree, (0, client_id)) if disappeared_client: self.TreeStores[instance].remove(disappeared_client) # Si el cliente tiene algún puerto seleccionado se borra # Si no se cambia su estado a inactivo some_port_selected = False for port in ports: if port[5] == True: some_port_selected = True break if some_port_selected: clients[caID][3] = False else: del clients[caID] def __del_port (self, new_graph_version, client_id, client_name, port_id, port_name): paID = getID(port_id, ports, 1) caID = getID(client_id, clients, 0) port_flags, port_type, port_selected = ports[paID][3:6] category = int(isInputOrOutput(port_flags) == "output") + int(port_type == 1) * 2 category_b = category + int(ports[paID][5])*4 not_category = category + int(not ports[paID][5])*4 # Si el puerto está seleccionado no lo borramos # sólo se cambia su estado a inactivo if port_selected: ports[paID][6] = False else: # Primero borramos el puerto in_client = search_tree(self.TreeStores[category_b], self.TreeStores[category_b].iter_children(None), match_func_tree, (0, client_id)) if in_client: disappeared_port = search_tree(self.TreeStores[category_b], self.TreeStores[category_b].iter_children(in_client), match_func_tree, (0, port_id)) self.TreeStores[category_b].remove(disappeared_port) del ports[paID] # Si el cliente no tiene puertos en la categoría # borrar el cliente y las instancias empty_client = search_tree(self.TreeStores[category_b], self.TreeStores[category_b].iter_children(None), match_func_tree, (0, client_id)) ppc = get_tree_len(self.TreeStores[category_b], self.TreeStores[category_b].iter_children(empty_client)) if ppc == 0: self.TreeStores[category_b].remove(empty_client) empty_not_client = search_tree(self.TreeStores[not_category], self.TreeStores[not_category].iter_children(None), match_func_tree, (0, client_id)) ppnc = get_tree_len(self.TreeStores[not_category], self.TreeStores[not_category].iter_children(empty_not_client)) if ppc == 0 and ppnc == 0: clients[caID][2].remove(category) def __connection(self, new_graph_version, client1_id, client1_name, port1_id, port1_name, client2_id, client2_name, port2_id, port2_name, connection_id): connections.append([client1_id, client1_name, port1_id, port1_name, client2_id, client2_name, port2_id, port2_name, connection_id]) def __disconnection(self, new_graph_version, client1_id, client1_name, port1_id, port1_name, client2_id, client2_name, port2_id, port2_name, connection_id): coaID = getID(connection_id, connections, 8) del connections[coaID] def __sel_item(self, widget, model, treeView, model_sel, max_items = 1): ### -- Selección en pestaña Puertos -- ### treeselection = treeView.get_selection() (sel_model, pathlist) = treeselection.get_selected_rows() sel_iter = model.get_iter(pathlist[0]) parent = model.iter_parent(sel_iter) error = False if treeselection.count_selected_rows() > 1: if not parent: msg = "La selección múltiple solo puede contener puertos no clientes" dialog = Gtk.MessageDialog(self, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, msg) dialog.run() dialog.destroy() error = True else: for path in pathlist: citer = model.get_iter(path) piter = model.iter_parent(citer) if not model.get_value(parent, 0) == model.get_value(piter, 0): msg = "Todos los puertos deben ser del mismo cliente" dialog = Gtk.MessageDialog(self, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, msg) dialog.run() dialog.destroy() error = True break if not error: if parent: parent_id = model.get_value(parent, 0) parent_name = model.get_value(parent, 1) children_colection = [] children_iters = [] for item in pathlist: child_iter = model.get_iter(item) child_id = model.get_value(child_iter, 0) child_name = model.get_value(child_iter, 1) children_colection.append([child_id, child_name]) children_iters.append(child_iter) if len(children_colection) <= max_items: for item in children_iters: model.remove(item) children_len = len(get_tree(model, model.iter_children(parent))) if not children_len: model.remove(parent) else: msg = "Error la seleccion contiene " + str(len(children_colection)) + " puertos, solo se admite " + str(max_items) dialog = Gtk.MessageDialog(self, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, msg) dialog.run() dialog.destroy() error = True else: children_iters = get_tree(model, model.iter_children(sel_iter)) children_colection = [] for item in children_iters: child_id = model.get_value(item, 0) child_name = model.get_value(item, 1) children_colection.append([child_id, child_name]) children_len = len(children_colection) if children_len <= max_items: parent_id = model.get_value(sel_iter, 0) parent_name = model.get_value(sel_iter, 1) for item in children_iters: model.remove(item) model.remove(sel_iter) else: msg = "Error la seleccion contiene " + str(children_len) + " puertos, solo se admite " + str(max_items) dialog = Gtk.MessageDialog(self, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, msg) dialog.run() dialog.destroy() error = True if not error: paID = getID(child_id, ports, 1) selected = ports[paID][5] exist = ports[paID][6] if exist: if selected: iter = search_tree(model_sel, model_sel.iter_children(None), match_func_tree, (0, parent_id)) if not selected or not iter: iter = model_sel.append(None) model_sel.set(iter, 0, parent_id, 1, parent_name) for item in children_colection: child_iter = model_sel.append(iter) child_id, child_name = item model_sel.set(child_iter, 0, child_id, 1, child_name) paID = getID(child_id, ports, 1) ports[paID][5] = not ports[paID][5] ## -- Selección en pestaña Salidas -- ## """ Estoy pensando como voy a hacer esta parte Creo que serán conexiones semejantes a qjackctl De momento estoy pensando en cómo hacerlo""" ## -- Selección en pestaña Rutas -- ## if not error: port_flags, port_type, port_selected = ports[paID][3:6] category = int(isInputOrOutput(port_flags) == "output") + int(port_type == 1) * 2 elements = get_tree(self.TreeStores[category + 4], self.TreeStores[category + 4].iter_children(None)) i = 0 for element in elements: children = self.TreeStores[category + 4].iter_children(element) txt1 = self.keymap[category][i] txt2 = self.TreeStores[category + 4].get_value(element, 1) txt3 = self.TreeStores[category + 4].get_value(children, 1) txt = txt1 + "\n" + txt2 + "\n" + txt3 self.RoutesLabels[category][i].set_text(txt) self.RoutesButtons[category][i].show() i += 1 nbut = len(self.RoutesButtons[category]) while i < nbut: self.RoutesButtons[category][i].hide() i += 1 # Reseteamos todos los botones for i in [0,2,3]: for button in self.RoutesButtons[i]: button.set_active(False) # Si hemos seleccionado un teclado # reseteamos el teclado seleccionado if category == 3: self.keyboard_selected = None def __keyboard(self, widget, index): active = widget.get_active() if active: # Primero cerramos todos los teclados que no estemos usando i = 0 for button in self.RoutesButtons[3]: if not i == index: button.set_active(False) i += 1 # Segundo buscamos el cliente y el puerto del teclado seleccionado client_iter = self.TreeStores[7].get_iter(index) client_id = self.TreeStores[7].get_value(client_iter, 0) client_name = self.TreeStores[7].get_value(client_iter, 1) port_iter = self.TreeStores[7].iter_children(client_iter) port_id = self.TreeStores[7].get_value(port_iter, 0) port_name = self.TreeStores[7].get_value(port_iter, 1) self.keyboard_selected = [client_id, client_name, port_id, port_name] # Tercero buscamos los sintetizadores conectados al teclado iter = self.TreeStores[6].get_iter_first() i = 0 self.lock_synths = True while iter: c_client_id = self.TreeStores[6].get_value(iter, 0) c_client_name = self.TreeStores[6].get_value(iter, 1) iter_children = self.TreeStores[6].iter_children(iter) c_port_id = self.TreeStores[6].get_value(iter_children, 0) connected = False for connection in connections: if client_id == connection[0] and port_id == connection[2] and c_client_id == connection[4] and c_port_id == connection[6]: self.RoutesButtons[2][i].set_active(True) connected = True if not connected: self.RoutesButtons[2][i].set_active(False) iter = self.TreeStores[6].iter_next(iter) i += 1 self.lock_synths = False def __connect_synth(self, widget, index): pass active = widget.get_active() if not self.lock_synths: if active: # Desactivamos los clientes no seleccionados # Si no está seleccionado múltiples sintetizadores if not self.multiple_synth.get_active(): i = 0 for button in self.RoutesButtons[2]: if not i == index: button.set_active(False) i += 1 # Buscamos el cliente y el puerto del sintetizador # Y lo conectamos al teclado client_iter = self.TreeStores[6].get_iter(index) port_iter = self.TreeStores[6].iter_children(client_iter) port_id = self.TreeStores[6].get_value(port_iter, 0) jack_control_ifa.ConnectPortsByID(self.keyboard_selected[2], port_id) else: # Si se desselecciona el cliente desconectamos el sintetizador client_iter = self.TreeStores[6].get_iter(index) port_iter = self.TreeStores[6].iter_children(client_iter) port_id = self.TreeStores[6].get_value(port_iter, 0) jack_control_ifa.DisconnectPortsByID(self.keyboard_selected[2], port_id) win = MyWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() win.hide_buttons() Gtk.main()