jack1 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
6.3KB

  1. from ctypes import *
  2. import string
  3. class jack_client_t(Structure):
  4. pass
  5. class jack_port_t(Structure):
  6. pass
  7. client_p = POINTER(jack_client_t)
  8. port_p = POINTER(jack_port_t)
  9. libjack = cdll.LoadLibrary( "libjack.so" )
  10. client_new = libjack.jack_client_new
  11. client_new.argtypes = [ c_char_p ]
  12. client_new.restype = client_p
  13. client_close = libjack.jack_client_close
  14. client_close.argtypes = [ client_p ]
  15. client_close.restype = None
  16. activate = libjack.jack_activate
  17. activate.argtypes = [ client_p ]
  18. activate.restype = None
  19. deactivate = libjack.jack_deactivate
  20. deactivate.argtypes = [ client_p ]
  21. deactivate.restype = None
  22. get_ports = libjack.jack_get_ports
  23. get_ports.argtypes = [ client_p, c_char_p, c_char_p, c_ulong ]
  24. get_ports.restype = POINTER( c_char_p )
  25. port_by_name = libjack.jack_port_by_name
  26. port_by_name.argtypes = [ client_p, c_char_p ]
  27. port_by_name.restype = port_p
  28. port_get_all_connections = libjack.jack_port_get_all_connections
  29. port_get_all_connections.argtypes = [ client_p, port_p ]
  30. port_get_all_connections.restype = POINTER( c_char_p )
  31. jack_free = libjack.jack_free
  32. jack_free.argtypes = [ c_void_p ]
  33. jack_free.restype = None
  34. rename_client = libjack.jack_rename_client
  35. rename_client.argtypes = [ client_p, c_char_p, c_char_p ]
  36. rename_client.restype = c_int
  37. class jack_session_command_t( Structure ):
  38. _fields_ = [ ("uuid", 16*c_char ), ("command", 256*c_char ) ]
  39. session_notify = libjack.jack_session_notify
  40. session_notify.argtypes = [ client_p, c_uint, c_char_p ]
  41. session_notify.restype = POINTER( jack_session_command_t )
  42. get_client_name_by_uuid = libjack.jack_get_client_name_by_uuid
  43. get_client_name_by_uuid.argtypes = [ client_p, c_char_p ]
  44. get_client_name_by_uuid.restype = c_char_p
  45. get_cookie_by_uuid = libjack.jack_get_cookie_by_uuid
  46. get_cookie_by_uuid.argtypes = [ client_p, c_char_p, c_char_p ]
  47. get_cookie_by_uuid.restype = c_char_p
  48. connect = libjack.jack_connect
  49. connect.argtypes = [ client_p, c_char_p, c_char_p ]
  50. connect.restype = c_int
  51. disconnect = libjack.jack_disconnect
  52. disconnect.argtypes = [ client_p, c_char_p, c_char_p ]
  53. disconnect.restype = c_int
  54. PortRegistrationCallback = CFUNCTYPE( None, c_uint, c_int, c_void_p )
  55. set_port_registration_callback = libjack.jack_set_port_registration_callback
  56. set_port_registration_callback.argtypes = [ client_p, PortRegistrationCallback, c_void_p ]
  57. set_port_registration_callback.restype = c_int
  58. port_by_id = libjack.jack_port_by_id
  59. port_by_id.argtypes = [ client_p, c_uint ]
  60. port_by_id.restype = port_p
  61. port_name = libjack.jack_port_name
  62. port_name.argtypes = [ port_p ]
  63. port_name.restype = c_char_p
  64. port_type = libjack.jack_port_type
  65. port_type.argtypes = [ port_p ]
  66. port_type.restype = c_char_p
  67. port_flags = libjack.jack_port_flags
  68. port_flags.argtypes = [ port_p ]
  69. port_flags.restype = c_int
  70. JACK_DEFAULT_AUDIO_TYPE="32 bit float mono audio"
  71. JACK_DEFAULT_MIDI_TYPE="8 bit raw midi"
  72. JackPortIsInput = 0x1
  73. JackPortIsOutput = 0x2
  74. JackPortIsPhysical = 0x4
  75. JackPortCanMonitor = 0x8
  76. JackPortIsTerminal = 0x10
  77. class Port( object ):
  78. def __init__( self, client, name ):
  79. self.client = client
  80. self.name = name
  81. self.portname = name.split(':')[1]
  82. self.port_p = port_by_name( self.client, name )
  83. def get_connections( self ):
  84. conns = port_get_all_connections( self.client, self.port_p )
  85. if not conns:
  86. return []
  87. i=0
  88. retval = []
  89. while conns[i]:
  90. retval.append( conns[i] )
  91. i+=1
  92. jack_free(conns)
  93. return retval
  94. def connect( self, other ):
  95. connect( self.client, self.name, other )
  96. def disconnect( self, other ):
  97. disconnect( self.client, self.name, other )
  98. def is_input( self ):
  99. return (port_flags( self.port_p ) & JackPortIsInput) != 0
  100. def is_output( self ):
  101. return (port_flags( self.port_p ) & JackPortIsOutput) != 0
  102. def is_audio( self ):
  103. return (port_type( self.port_p ) == JACK_DEFAULT_AUDIO_TYPE)
  104. def is_midi( self ):
  105. return (port_type( self.port_p ) == JACK_DEFAULT_MIDI_TYPE)
  106. class Client( object ):
  107. def __init__( self, client, name ):
  108. self.client = client
  109. self.name = name
  110. self.ports = []
  111. self.commandline = None
  112. def get_commandline( self ):
  113. if self.commandline:
  114. return self.commandline
  115. else:
  116. return ""
  117. def add_port( self, portname ):
  118. self.ports.append( Port( self.client, portname ) )
  119. def rename( self, newname ):
  120. rename_client( self.client, self.name, self.newname )
  121. self.ports = []
  122. ports = get_ports( self.client, self.newname+":.*", None, 0 )
  123. i=0
  124. while(ports[i]):
  125. self.add_port( ports[i] )
  126. i+=1
  127. jack_free( ports )
  128. class JackGraph( object ):
  129. def __init__( self, client, ports, uuids=[] ):
  130. self.client = client
  131. self.clients = {}
  132. self.uuid_to_name = {}
  133. self.name_to_uuid = {}
  134. for uid in uuids:
  135. name = get_client_name_by_uuid( self.client, uid )
  136. if name:
  137. self.uuid_to_name[uid] = name
  138. self.name_to_uuid[name] = uid
  139. jack_free( name )
  140. i=0
  141. while(ports[i]):
  142. port_split = ports[i].split(':')
  143. if not self.clients.has_key(port_split[0]):
  144. self.clients[port_split[0]] = Client( client, port_split[0] )
  145. self.clients[port_split[0]].add_port( ports[i] )
  146. i+=1
  147. def get_client( self, name ):
  148. return self.clients[name]
  149. def get_client_by_uuid( self, uuid ):
  150. return self.clients[self.uuid_to_name[uuid]]
  151. def check_client_name( self, client ):
  152. if not client.name in self.clients.keys():
  153. return
  154. cname_split = client.name.split('-')
  155. if len(cname_split) == 0:
  156. cname_prefix = cname_split[0]
  157. else:
  158. cname_prefix = string.join( name_split[:-1], '-' )
  159. num = 1
  160. while ("%s-%d"%(cname_prefix,num)) in self.clients.keys():
  161. num+=1
  162. # XXX: this might still fail due to race.
  163. # also needs to lock
  164. client.rename( "%s-%d"%(cname_prefix,num ) )
  165. class JackClient(object):
  166. def __init__( self, name ):
  167. self.client = client_new( name )
  168. self.reg_cb = PortRegistrationCallback( self.port_registration_cb )
  169. set_port_registration_callback( self.client, self.reg_cb, None )
  170. self.port_queue = Queue()
  171. activate( self.client )
  172. def close( self ):
  173. client_close( self.client )
  174. def get_graph( self ):
  175. ports = get_ports( self.client, None, None, 0 )
  176. retval = JackGraph( self.client, ports )
  177. jack_free( ports )
  178. return retval
  179. def rename_client( self, old, new ):
  180. if rename_client( self.client, old, new ):
  181. raise Exception
  182. def port_registration_cb( self, port_id, reg, arg ):
  183. port_p = port_by_id( self.client, port_id )
  184. self.port_queue.put( (port_p,reg) )