#!/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()