def start(self): assert not self._process env = os.environ.copy() env['PYTHONPATH'] = os.pathsep.join( filter(None, [ os.path.join(__file__, *[os.pardir] * 3), env.get('PYTHONPATH') ])) self._process = subprocess.Popen( [sys.executable, '-u', '-m', 'video_downloader.downloader'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, universal_newlines=True, start_new_session=True) fcntl.fcntl(self._process.stdout, fcntl.F_SETFL, os.O_NONBLOCK) fcntl.fcntl(self._process.stderr, fcntl.F_SETFL, os.O_NONBLOCK) self._process.stdout_remainder = self._process.stderr_remainder = '' GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT_IDLE, self._process.stdout.fileno(), GLib.IOCondition.IN, self._on_process_stdout) GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT_IDLE, self._process.stderr.fileno(), GLib.IOCondition.IN, self._on_process_stderr, self._process)
def start(self): assert not self._process env = os.environ.copy() env['PYTHONPATH'] = os.pathsep.join( filter(None, [ os.path.join(__file__, *[os.pardir] * 3), env.get('PYTHONPATH') ])) # Start child process in its own process group to shield it from # signals by terminals (e.g. SIGINT) and to identify remaning children. # youtube-dl doesn't kill ffmpeg and other subprocesses on error. self._process = subprocess.Popen( [sys.executable, '-u', '-m', 'video_downloader.downloader'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, universal_newlines=True, preexec_fn=os.setpgrp) fcntl.fcntl(self._process.stdout, fcntl.F_SETFL, os.O_NONBLOCK) fcntl.fcntl(self._process.stderr, fcntl.F_SETFL, os.O_NONBLOCK) self._process.stdout_remainder = self._process.stderr_remainder = '' GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT_IDLE, self._process.stdout.fileno(), GLib.IOCondition.IN, self._on_process_stdout) GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT_IDLE, self._process.stderr.fileno(), GLib.IOCondition.IN, self._on_process_stderr, self._process)
def _fd_output_future(fd, log_fn): """Return a future for all output on fd. :param fd: A Python file object to collect output from and close. The caller should not touch it in any way after calling this function. """ output_chunks = [] # A list of strings to avoid an O(N^2) behavior # A string holding output data for logging # Needs to be stored as a one-item array because strings # are immutable and it would otherwise be overwritten by # input_handler below linebuf = [''] future = Future() def input_handler(unused_fd, condition, unused_data): finished = True if (condition & (GLib.IOCondition.ERR | GLib.IOCondition.NVAL)) != 0: log.error("Unexpected input handler state %s" % condition) else: assert (condition & (GLib.IOCondition.IN | GLib.IOCondition.HUP)) != 0 # Note that HUP and IN can happen at the same time, so don’t # explicitly test for HUP. try: chunk = fd.read() except IOError as e: log.error("Error reading subprocess output: %s" % e) else: if len(chunk) > 0: output_chunks.append(chunk.decode('utf-8')) # Log the input at the requested level lines = (linebuf[0] + chunk.decode('utf-8')).split('\n') for line in lines[:-1]: try: msg = line.encode(errors='backslashreplace') except UnicodeError: # Line contains non-ASCII content that # cannot be escaped. Log it as base64. msg = line.encode(encoding='base64') log_fn(msg) linebuf[0] = lines[-1]; # Continue until there's no more data to be had finished = False if finished: fd.close() future.set_result("".join(output_chunks)) return False return True fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) condition = (GLib.IOCondition.IN | GLib.IOCondition.ERR | GLib.IOCondition.HUP | GLib.IOCondition.NVAL) GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT, fd.fileno(), condition, input_handler, None) return future
def add_writer(self, fd, callback, *args): def doit(_1, _2, _3, _4): # not sure what the args are callback(*args) return \ True # keep watching #end doit #begin add_writer fileno = _fd_fileno(fd) self._add_source \ ( attr = "_writer_sources", key = fileno, source_nr = GLib.unix_fd_add_full ( 0, fileno, GLib.IOCondition.OUT | GLib.IOCondition.PRI, doit, None, None ) ) self = None # avoid circular references
def Inhibit(_, what, who, why, mode): if not hasattr(mockobject, "inhibitors"): mockobject.inhibitors = [] fd_r, fd_w = os.pipe() inhibitor = (what, who, why, mode, 1000, 123456) mockobject.inhibitors.append(inhibitor) def inhibitor_dropped(fd, cond): # pylint: disable=unused-argument os.close(fd) mockobject.inhibitors.remove(inhibitor) return False GLib.unix_fd_add_full(GLib.PRIORITY_HIGH, fd_r, GLib.IO_HUP, inhibitor_dropped) GLib.idle_add(os.close, fd_w) return fd_w
def __init__(self, mainloop, fd, read, write, desc): self._mainloop = mainloop self.description = desc condition = GLib.IOCondition(0) if read: condition |= GLib.IOCondition.IN | GLib.IOCondition.HUP if write: condition |= GLib.IOCondition.OUT self._doread = read self._dowrite = write self._handle = GLib.unix_fd_add_full(0, fd, condition, self._call, None, None)
def __init__(self, mainloop, fd, read, write, desc): self._mainloop = mainloop self.description = desc condition = GLib.IOCondition(0) if read: condition |= GLib.IOCondition.IN | GLib.IOCondition.HUP if write: condition |= GLib.IOCondition.OUT self._doread = read self._dowrite = write self._handle = GLib.unix_fd_add_full( 0, fd, condition, self._call, None, None)
def start(self): assert not self._process env = os.environ.copy() env['PYTHONPATH'] = os.pathsep.join( filter(None, [ os.path.join(__file__, *[os.pardir] * 3), env.get('PYTHONPATH') ])) # Start child process in its own process group to shield it from # signals by terminals (e.g. SIGINT) and to identify remaning children. # youtube-dl doesn't kill ffmpeg and other subprocesses on error. self._process = subprocess.Popen( [sys.executable, '-u', '-m', 'video_downloader.downloader'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, universal_newlines=True, preexec_fn=os.setpgrp) # WARNING: O_NONBLOCK can break mult ibyte decoding and line splitting # under rare circumstances. # E.g. when the buffer only includes the first byte of a multi byte # UTF-8 character, TextIOWrapper would normally block until all bytes # of the character are read. This does not work with O_NONBLOCK, and it # raises UnicodeDecodeError instead. # E.g. when the buffer only includes `b'\r'`, TextIOWrapper would # normally block to read the next byte and check if it's `b'\n'`. # This does not work with O_NONBLOCK, and it gets transformed to `'\n'` # directly. The line ending `b'\r\n'` will be transformed to `'\n\n'`. fcntl.fcntl(self._process.stdout, fcntl.F_SETFL, os.O_NONBLOCK) fcntl.fcntl(self._process.stderr, fcntl.F_SETFL, os.O_NONBLOCK) self._process.stdout_remainder = self._process.stderr_remainder = b'' GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT_IDLE, self._process.stdout.fileno(), GLib.IOCondition.IN, self._on_process_stdout, self._process) GLib.unix_fd_add_full(GLib.PRIORITY_DEFAULT_IDLE, self._process.stderr.fileno(), GLib.IOCondition.IN, self._on_process_stderr, self._process)
def __init__(self, app, patch): self.app = app self.patch = patch # 0 : patched channels # 1 : all channels self.view_type = 0 self.percent_level = Gio.Application.get_default().settings.get_boolean('percent') Gtk.Window.__init__(self, title="Open Lighting Console", application=app) self.set_default_size(1400, 1200) self.set_name('olc') self.header = Gtk.HeaderBar(title="Open Lighting Console") self.header.set_subtitle("Fonctionne avec ola") self.header.props.show_close_button = True box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) #Gtk.StyleContext.add_class(box.get_style_context(), "linked") button = Gtk.Button() icon = Gio.ThemedIcon(name="view-grid-symbolic") image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON) button.connect("clicked", self.button_clicked_cb) button.add(image) box.add(button) button = Gtk.Button() icon = Gio.ThemedIcon(name="open-menu-symbolic") image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON) button.add(image) box.add(button) self.header.pack_end(box) self.set_titlebar(self.header) self.paned = Gtk.Paned(orientation=Gtk.Orientation.VERTICAL) self.paned.set_position(950) #self.paned.set_wide_handle(True) self.scrolled = Gtk.ScrolledWindow() self.scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.flowbox = Gtk.FlowBox() self.flowbox.set_valign(Gtk.Align.START) self.flowbox.set_max_children_per_line(20) self.flowbox.set_homogeneous(True) self.flowbox.set_selection_mode(Gtk.SelectionMode.MULTIPLE) self.flowbox.set_filter_func(self.filter_func, None) # Fonction de filtrage self.keystring = "" self.last_chan_selected = "" self.channels = [] for i in range(512): self.channels.append(ChannelWidget(i+1, 0, 0)) self.flowbox.add(self.channels[i]) self.scrolled.add(self.flowbox) self.paned.add1(self.scrolled) # Gtk.Statusbar to display keyboard's keys self.statusbar = Gtk.Statusbar() self.context_id = self.statusbar.get_context_id("keypress") self.grid = Gtk.Grid() label = Gtk.Label("Saisie clavier : ") self.grid.add(label) self.grid.attach_next_to(self.statusbar, label, Gtk.PositionType.RIGHT, 1, 1) self.paned.add2(self.grid) self.paned2 = Gtk.Paned(orientation=Gtk.Orientation.HORIZONTAL) self.paned2.set_position(950) self.paned2.add1(self.paned) self.app = Gio.Application.get_default() self.seq = self.app.sequence # Sequential part of the window position = self.seq.position t_total = self.seq.cues[position].total_time t_in = self.seq.cues[position].time_in t_out = self.seq.cues[position].time_out t_wait = self.seq.cues[position].wait channel_time = self.seq.cues[position].channel_time # Crossfade widget self.sequential = SequentialWidget(t_total, t_in, t_out, t_wait, channel_time) # Model : Step, Memory, Text, Wait, Time Out, Time In, Channel Time self.cues_liststore1 = Gtk.ListStore(str, str, str, str, str, str, str, str) self.cues_liststore2 = Gtk.ListStore(str, str, str, str, str, str, str) for i in range(self.app.sequence.last): if self.seq.cues[i].wait.is_integer(): wait = str(int(self.seq.cues[i].wait)) if wait == "0": wait = "" else: wait = str(self.seq.cues[i].wait) if self.seq.cues[i].time_out.is_integer(): t_out = str(int(self.seq.cues[i].time_out)) else: t_out = str(self.seq.cues[i].time_out) if self.seq.cues[i].time_in.is_integer(): t_in = str(int(self.seq.cues[i].time_in)) else: t_in = str(self.seq.cues[i].time_in) channel_time = str(len(self.seq.cues[i].channel_time)) if channel_time == "0": channel_time = "" bg = "#232729" self.cues_liststore1.append([str(i), str(self.seq.cues[i].memory), self.seq.cues[i].text, wait, t_out, t_in, channel_time, bg]) self.cues_liststore2.append([str(i), str(self.seq.cues[i].memory), self.seq.cues[i].text, wait, t_out, t_in, channel_time]) # Filter for the first part of the cue list self.step_filter1 = self.cues_liststore1.filter_new() self.step_filter1.set_visible_func(self.step_filter_func1) # List self.treeview1 = Gtk.TreeView(model=self.step_filter1) self.treeview1.set_enable_search(False) sel = self.treeview1.get_selection() sel.set_mode(Gtk.SelectionMode.NONE) for i, column_title in enumerate(["Pas", "Mémoire", "Texte", "Wait", "Out", "In", "Channel Time"]): renderer = Gtk.CellRendererText() # Change background color one column out of two if i % 2 == 0: renderer.set_property("background-rgba", Gdk.RGBA(alpha=0.03)) column = Gtk.TreeViewColumn(column_title, renderer, text=i, background=7) if i == 2: column.set_min_width(600) column.set_resizable(True) self.treeview1.append_column(column) # Filter self.step_filter2 = self.cues_liststore2.filter_new() self.step_filter2.set_visible_func(self.step_filter_func2) # List self.treeview2 = Gtk.TreeView(model=self.step_filter2) self.treeview2.set_enable_search(False) sel = self.treeview2.get_selection() sel.set_mode(Gtk.SelectionMode.NONE) for i, column_title in enumerate(["Pas", "Mémoire", "Texte", "Wait", "Out", "In", "Channel Time"]): renderer = Gtk.CellRendererText() # Change background color one column out of two if i % 2 == 0: renderer.set_property("background-rgba", Gdk.RGBA(alpha=0.03)) column = Gtk.TreeViewColumn(column_title, renderer, text=i) if i == 2: column.set_min_width(600) column.set_resizable(True) self.treeview2.append_column(column) # Put Cues List in a scrolled window self.scrollable2 = Gtk.ScrolledWindow() self.scrollable2.set_vexpand(True) self.scrollable2.set_hexpand(True) self.scrollable2.add(self.treeview2) # Put Cues lists and sequential in a grid self.seq_grid = Gtk.Grid() self.seq_grid.set_row_homogeneous(False) self.seq_grid.attach(self.treeview1, 0, 0, 1, 1) self.seq_grid.attach_next_to(self.sequential, self.treeview1, Gtk.PositionType.BOTTOM, 1, 1) self.seq_grid.attach_next_to(self.scrollable2, self.sequential, Gtk.PositionType.BOTTOM, 1, 1) # Sequential in a Tab self.notebook = Gtk.Notebook() self.notebook.append_page(self.seq_grid, Gtk.Label('Main Playback')) self.paned2.add2(self.notebook) self.add(self.paned2) # Select first Cue self.cues_liststore1[0][7] = "#997004" # Open MIDI input port #self.inport = mido.open_input('UC-33 USB MIDI Controller:UC-33 USB MIDI Controller MIDI 24:1') try: self.inport = mido.open_input('UC-33 USB MIDI Controller:UC-33 USB MIDI Controller MIDI 24:0') except: self.inport = mido.open_input() # Scan MIDI every 100ms self.timeout_id = GObject.timeout_add(100, self.on_timeout, None) # Scan Ola messages - 27 = IN(1) + HUP(16) + PRI(2) + ERR(8) GLib.unix_fd_add_full(0, self.app.sock.fileno(), GLib.IOCondition(27), self.app.on_fd_read, None) # TODO: Add Enttec wing playback support with Gio.SocketService (et Gio.SocketListener.add_address) """ service = Gio.SocketService() service.connect('incoming', self.incoming_connection_cb) #service.add_address(Gio.InetSocketAddress(Gio.SocketFamily(2), 3330), Gio.SocketType(2), Gio.SocketProtocal(17), None) address = Gio.InetAddress.new_any(2) #address = Gio.InetAddress.new_from_string('127.0.0.1') #inetsock = Gio.InetSocketAddress.new(address, 3330) inetsock = Gio.InetSocketAddress.new_from_string('127.0.0.1', 3330) service.add_address(inetsock, Gio.SocketType.DATAGRAM, Gio.SocketProtocol.UDP) """ """ socket = Gio.Socket.new(Gio.SocketFamily.IPV4, Gio.SocketType.DATAGRAM, Gio.SocketProtocol.UDP) address = Gio.InetAddress.new_any(Gio.SocketFamily.IPV4) inetsock = Gio.InetSocketAddress.new(address, 3330) ret = socket.connect(inetsock) print(ret) fd = socket.get_fd() print(fd) ch = GLib.IOChannel.unix_new(fd) print(ch) GLib.io_add_watch(ch, 0, GLib.IOCondition.IN, self.incoming_connection_cb) """ import socket address = ('', 3330) self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind(address) self.fd = self.sock.fileno() #ch = GLib.IOChannel.unix_new(fd) #GLib.io_add_watch(ch, 0, GLib.IOCondition.IN, self.incoming_connection_cb) GLib.unix_fd_add_full(0, self.fd, GLib.IOCondition.IN, self.incoming_connection_cb, None) self.connect('key_press_event', self.on_key_press_event) self.set_icon_name('olc')