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.

279 lines
6.8KB

  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 ), ("client_name", 33*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. JackSessionSave = 1
  78. JackSessionQuit = 2
  79. class Port( object ):
  80. def __init__( self, client, name ):
  81. self.client = client
  82. self.name = name
  83. self.portname = name.split(':')[1]
  84. self.port_p = port_by_name( self.client, name )
  85. def get_connections( self ):
  86. conns = port_get_all_connections( self.client, self.port_p )
  87. if not conns:
  88. return []
  89. i=0
  90. retval = []
  91. while conns[i]:
  92. retval.append( conns[i] )
  93. i+=1
  94. jack_free(conns)
  95. return retval
  96. def connect( self, other ):
  97. connect( self.client, self.name, other )
  98. def disconnect( self, other ):
  99. disconnect( self.client, self.name, other )
  100. def is_input( self ):
  101. return (port_flags( self.port_p ) & JackPortIsInput) != 0
  102. def is_output( self ):
  103. return (port_flags( self.port_p ) & JackPortIsOutput) != 0
  104. def is_audio( self ):
  105. return (port_type( self.port_p ) == JACK_DEFAULT_AUDIO_TYPE)
  106. def is_midi( self ):
  107. return (port_type( self.port_p ) == JACK_DEFAULT_MIDI_TYPE)
  108. class Client( object ):
  109. def __init__( self, client, name ):
  110. self.client = client
  111. self.name = name
  112. self.ports = []
  113. self.commandline = None
  114. def get_commandline( self ):
  115. if self.commandline:
  116. return self.commandline
  117. else:
  118. return ""
  119. def add_port( self, portname ):
  120. self.ports.append( Port( self.client, portname ) )
  121. def rename( self, newname ):
  122. rename_client( self.client, self.name, self.newname )
  123. self.ports = []
  124. ports = get_ports( self.client, self.newname+":.*", None, 0 )
  125. i=0
  126. while(ports[i]):
  127. self.add_port( ports[i] )
  128. i+=1
  129. jack_free( ports )
  130. class JackGraph( object ):
  131. def __init__( self, client, ports, uuids=[] ):
  132. self.client = client
  133. self.clients = {}
  134. self.uuid_to_name = {}
  135. self.name_to_uuid = {}
  136. for uid in uuids:
  137. name = get_client_name_by_uuid( self.client, uid )
  138. if name:
  139. self.uuid_to_name[uid] = name
  140. self.name_to_uuid[name] = uid
  141. jack_free( name )
  142. i=0
  143. while(ports[i]):
  144. port_split = ports[i].split(':')
  145. if not self.clients.has_key(port_split[0]):
  146. self.clients[port_split[0]] = Client( client, port_split[0] )
  147. self.clients[port_split[0]].add_port( ports[i] )
  148. i+=1
  149. def get_client( self, name ):
  150. return self.clients[name]
  151. def get_client_by_uuid( self, uuid ):
  152. return self.clients[self.uuid_to_name[uuid]]
  153. def check_client_name( self, client ):
  154. if not client.name in self.clients.keys():
  155. return
  156. cname_split = client.name.split('-')
  157. if len(cname_split) == 0:
  158. cname_prefix = cname_split[0]
  159. else:
  160. cname_prefix = string.join( name_split[:-1], '-' )
  161. num = 1
  162. while ("%s-%d"%(cname_prefix,num)) in self.clients.keys():
  163. num+=1
  164. # XXX: this might still fail due to race.
  165. # also needs to lock
  166. client.rename( "%s-%d"%(cname_prefix,num ) )
  167. class NotifyReply(object):
  168. def __init__( self, uuid, clientname, commandline ):
  169. self.uuid = uuid
  170. self.clientname = clientname
  171. self.commandline = commandline
  172. class JackClient(object):
  173. def __init__( self, name ):
  174. self.client = client_new( name )
  175. self.reg_cb = PortRegistrationCallback( self.port_registration_cb )
  176. set_port_registration_callback( self.client, self.reg_cb, None )
  177. self.port_queue = Queue()
  178. activate( self.client )
  179. def close( self ):
  180. client_close( self.client )
  181. def get_graph( self ):
  182. ports = get_ports( self.client, None, None, 0 )
  183. retval = JackGraph( self.client, ports )
  184. jack_free( ports )
  185. return retval
  186. def rename_client( self, old, new ):
  187. if rename_client( self.client, old, new ):
  188. raise Exception
  189. def port_registration_cb( self, port_id, reg, arg ):
  190. port_p = port_by_id( self.client, port_id )
  191. self.port_queue.put( (port_p,reg) )
  192. def session_save( self, path ):
  193. commands = session_notify( self.client, JackSessionSave, path )
  194. i=0
  195. retval = []
  196. while( commands[i].uuid[0] != 0 ):
  197. retval.append( NotifyReply( commands[i].uuid, commands[i].clientname, commands[i].commandline ) )
  198. jack_free( commands )