#!/usr/bin/env python import gtk import gtk.glade import gobject import subprocess import os import pickle gladefile=""" True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 6 GtkNetSource False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 2 4 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0.10999999940395355 <b>Status:</b>Deactivated True 50 True 2 1 2 8 True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-preferences True 0 1 2 GTK_FILL True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0.05000000074505806 Start/Stop GTK_FILL GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 True GTK_WIN_POS_CENTER_ON_PARENT True GDK_WINDOW_TYPE_HINT_DIALOG True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 3 8 9 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 GTK_SHADOW_NONE True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0.75 32 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 10 3 3 7 5 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 periods 2 3 2 3 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 bytes/period 2 3 1 2 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 1 0 500 1 10 10 True True 1 2 2 3 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Latency: 2 3 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0.019999999552965164 2 2 1024 2 10 10 True True 1 2 1 2 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Celt float 16bit 1 3 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Compress to: 1 2 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Type: True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Link</b> True label_item 12 12 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 GTK_SHADOW_NONE True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0.89999997615814209 0.89999997615814209 6 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 3 4 5 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Reply Port: 2 3 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Port: 1 2 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK host.jack.net 1 4 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Hostname: True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 3002 0 65535 1 10 10 True True 3 4 1 2 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 3001 0 65535 1 10 10 True True 3 4 2 3 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Default 0 True True portcustom 1 2 1 2 GTK_FILL True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Custom: 0 True True 2 3 1 2 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Default 0 True True replycustom 1 2 2 3 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Custom: 0 True True 2 3 2 3 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Connection</b> True label_item 3 1 2 12 10 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 GTK_SHADOW_NONE True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 10 4 2 7 5 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 0 100 1 10 10 True True 1 2 2 3 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 0 100 1 10 10 True True 1 2 3 4 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Midi OUT: 3 4 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 0 100 1 10 10 True True 1 2 1 2 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 0 100 1 10 10 True True 1 2 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Midi IN: 2 3 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Audio OUT: 1 2 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 Audio IN: True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Channels</b> True label_item 1 3 12 12 1 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK GTK_BUTTONBOX_END True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-cancel True 0 True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-ok True 0 1 False GTK_PACK_END """ class LinkType(int): pass configfilename = os.environ['HOME'] + '/.gtknetsource' confkeys = ['audioin', 'audioout', 'midiin', 'midiout', 'quality', 'latency', 'port', 'replyport', 'hostname', 'linktype', 'portdefault', 'replydefault' ] config = { 'audioin': 2, 'audioout': 2, 'midiin': 1, 'midiout': 1, 'quality': 32, 'latency': 2, 'port': 3000, 'replyport': 3001, 'hostname': "localhost", 'linktype': LinkType(0), 'portdefault': True, 'replydefault': True } class NetSource: def __init__( self ): self.reset() def reset( self ): self.connected = False self.xruns = 0 self.latency = 0 self.netsource_child = 0 self.netsource_watch = 0 self.want_connect = False self.packets_seen = False; def child_output( self, src, cond ): s = src.readline() s = s.strip() if s=="Connected :-)": self.connected = True self.packets_seen = True if s=="Not Connected": self.connected = False self.latency = 0 if "at frame" in s: self.xruns = int(s.split()[-1]) if "current latency" in s: self.latency = int(s.split()[-1]) self.packets_seen = True if self.connected: info = "Status: Connected xruns: %d latency: %d LOCKED" % (self.xruns, config['latency'] ) elif self.packets_seen and self.latency != 0: info = "Status: Trying to Lock latency: %d want: %d" % (self.latency, config['latency'] ) elif self.packets_seen: info = "Status: Connection Lost" else: info = "Status: Connecting" w = xml.get_widget( "info" ) w.set_markup( info ) return True def connect_handler( self ): self.want_connect = True if( self.netsource_watch==0 ): cmd = 'jack_netsource ' cmd += '-h "%s" ' % ( config['hostname'] ) cmd += '-P %d ' % ( config['audioout'] ) cmd += '-C %d ' % ( config['audioin'] ) cmd += '-o %d ' % ( config['midiout'] ) cmd += '-i %d ' % ( config['midiin'] ) cmd += '-l %d ' % ( config['latency'] ) if not config['portdefault']: cmd += '-p %d ' % ( config['port'] ) if not config['replydefault']: cmd += '-r %d ' % ( config['replyport'] ) if config['linktype'] == 0: cmd += '-c %d ' % ( config['quality'] ) if config['linktype'] == 2: cmd += '-b 16 ' info = xml.get_widget( "info" ) info.set_markup( "Status: Starting..." ); self.netsource_child = subprocess.Popen(cmd, shell=True, bufsize=1, stdout=subprocess.PIPE, close_fds=True ) self.netsource_watch = gobject.io_add_watch( self.netsource_child.stdout, gobject.IO_IN, self.child_output ) def disconnect_handler( self ): self.want_connect = False if( self.netsource_watch != 0 ): gobject.source_remove( self.netsource_watch ) self.netsource_watch = 0 os.kill( self.netsource_child.pid, 15 ) self.netsource_child.wait() info = xml.get_widget( "info" ) info.set_markup( "Status: Deactivated" ); def prefs_handler( widget ): config_dialog = xml.get_widget( "configdialog" ) config_dialog.show() def config_ok( widget ): for i in confkeys: w = xml.get_widget( i ) if type(config[i]) == int: config[i] = w.get_value() if type(config[i]) == float: config[i] = w.get_value() if type(config[i]) == str: config[i] = w.get_text() if type(config[i]) == LinkType: config[i] = LinkType( w.get_active() ) if type(config[i]) == bool: config[i] = bool( w.get_active() ) configfile = file( configfilename, "w" ) pickle.dump( config, configfile ) config_dialog = xml.get_widget( "configdialog" ) config_dialog.hide() def set_dialog_to_config(): for i in confkeys: w = xml.get_widget( i ) if type(config[i]) == int: w.set_value( config[i] ) if type(config[i]) == float: w.set_value( config[i] ) if type(config[i]) == str: w.set_text( config[i] ) if type(config[i]) == LinkType: w.set_active( config[i] ) if type(config[i]) == bool: w.set_active( config[i] ) if( not config[i] ): for k in w.get_group(): k.set_active(True) def config_cancel( widget ): set_dialog_to_config() config_dialog = xml.get_widget( "configdialog" ) config_dialog.hide() def close_window( widget ): netsource.disconnect_handler() gtk.main_quit() def start_handler( widget ): label = xml.get_widget( "start_label" ) if netsource.want_connect: label.set_text( "Start" ) netsource.disconnect_handler() else: label.set_text( "Stop" ) netsource.connect_handler() netsource = NetSource() #xml = gtk.glade.XML( "gtknetsource.glade" ) xml = gtk.glade.xml_new_from_buffer( gladefile, len(gladefile) ) xml.signal_autoconnect( { 'close_window': close_window, 'start': start_handler, 'prefs': prefs_handler, 'config_ok': config_ok, 'config_cancel': config_cancel } ) try: configfile = file( configfilename ) config = pickle.load( configfile ) except: configfile = file( configfilename, "w" ) pickle.dump( config, configfile ) set_dialog_to_config() gtk.main()