jack2 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.

415 lines
15KB

  1. #!/usr/bin/python3
  2. from __future__ import print_function
  3. import dbus
  4. import sys
  5. name_base = 'org.jackaudio'
  6. control_interface_name = name_base + '.JackControl'
  7. configure_interface_name = name_base + '.Configure'
  8. service_name = name_base + '.service'
  9. control_iface = None
  10. configure_iface = None
  11. def bool_convert(str_value):
  12. if str_value == "0" or str_value.lower() in ["false", "off", "no", "(null)"]:
  13. return False
  14. return bool(str_value)
  15. def dbus_type_to_python_type(dbus_value):
  16. t = type(dbus_value)
  17. if t == dbus.Boolean:
  18. return bool(dbus_value)
  19. if t == dbus.Int32 or t == dbus.UInt32:
  20. return int(dbus_value)
  21. return dbus_value
  22. def python_type_to_jackdbus_type(value, type_char):
  23. type_char = str(type_char)
  24. if type_char == "b":
  25. return bool_convert(value)
  26. elif type_char == "y":
  27. return dbus.Byte(ord(value))
  28. elif type_char == "i":
  29. return dbus.Int32(value)
  30. elif type_char == "u":
  31. return dbus.UInt32(value)
  32. return value
  33. def dbus_typesig_to_type_string(type_char):
  34. type_char = str(type_char)
  35. if type_char == 'i':
  36. return "sint"
  37. if type_char == 'u':
  38. return "uint"
  39. if type_char == 'y':
  40. return "char"
  41. if type_char == 's':
  42. return "str"
  43. if type_char == 'b':
  44. return "bool"
  45. print('err: unknown dbus typesig "%s"' % type_char)
  46. return None # throw exception here?
  47. def get_parameters(iface, path):
  48. params = iface.GetParametersInfo(path)
  49. # print params
  50. for param in params:
  51. typestr = dbus_typesig_to_type_string(param[0])
  52. name = param[1]
  53. # print name
  54. descr = param[2]
  55. # print descr
  56. isset, default, value = iface.GetParameterValue(path + [name])
  57. # print typestr
  58. if bool(isset):
  59. isset = "set"
  60. else:
  61. isset = "notset"
  62. value = dbus_type_to_python_type(value)
  63. default = dbus_type_to_python_type(default)
  64. print("%20s: %s (%s:%s:%s:%s)" % (name, descr, typestr, isset, default, value))
  65. def print_help():
  66. help_output = (
  67. "Usage: jack_control [command] [command] ...\n"
  68. "Commands:\n"
  69. " shell - execute commands from stdin until End Of File (Ctrl+D in terminal)\n"
  70. " exit - exit jack dbus service (stops jack server if currently running)\n"
  71. " help - print this help text\n"
  72. " status - check whether jack server is started, "
  73. "return value is 0 if running and 1 otherwise\n"
  74. " start - start jack server if not currently started\n"
  75. " stop - stop jack server if currently started\n"
  76. " sm - switch master to currently selected driver\n"
  77. " dl - get list of available drivers\n"
  78. " dg - get currently selected driver\n"
  79. " ds <driver> - select driver\n"
  80. " dp - get parameters of currently selected driver\n"
  81. " dpd <param> - get long description for driver parameter\n"
  82. " dps <param> <value> - set driver parameter\n"
  83. " dpr <param> - reset driver parameter to its default value\n"
  84. " asd <driver> - add slave driver\n"
  85. " rsd <driver> - remove slave driver\n"
  86. " il - get list of available internals\n"
  87. " ip <name> - get parameters of given internal\n"
  88. " ipd <name> <param> - get long description for internal parameter\n"
  89. " ips <name> <param> <value> - set internal parameter\n"
  90. " ipr <name> <param> - reset internal parameter to its default value\n"
  91. " iload <name> - load internal\n"
  92. " iunload <name> - unload internal\n"
  93. " ep - get engine parameters\n"
  94. " epd <param> - get long description for engine parameter\n"
  95. " eps <param> <value> - set engine parameter\n"
  96. " epr <param> - reset engine parameter to its default value\n"
  97. )
  98. print(help_output)
  99. def maybe_print_param_constraint(iface, param):
  100. is_range, is_strict, is_fake, values = iface.GetParameterConstraint(param)
  101. if is_range:
  102. print()
  103. print(("allowed range: %s to %s (inclusive)" % (values[0][0], values[1][0])))
  104. elif len(values):
  105. print()
  106. if is_strict:
  107. print("allowed values:")
  108. else:
  109. print("suggested values:")
  110. max_len = 0
  111. for value in values:
  112. if len(str(value[0])) > max_len:
  113. max_len = len(str(value[0]))
  114. for value in values:
  115. print(("%*s'%s' - %s" % (1 + max_len - len(str(value[0])), "", str(value[0]), str(value[1]))))
  116. def parse_argv(argv):
  117. global control_iface, configure_iface
  118. # check arguments
  119. index = 0
  120. while index < len(argv):
  121. arg = argv[index]
  122. index += 1
  123. try:
  124. if arg == 'exit':
  125. print("--- exit")
  126. control_iface.Exit()
  127. elif arg == 'status':
  128. print("--- status")
  129. if control_iface.IsStarted():
  130. return (0, "started")
  131. else:
  132. return (1, "stoped")
  133. elif arg == 'start':
  134. print("--- start")
  135. control_iface.StartServer()
  136. elif arg == 'stop':
  137. print("--- stop")
  138. control_iface.StopServer()
  139. elif arg == 'sm':
  140. print("--- switch master driver")
  141. control_iface.SwitchMaster()
  142. elif arg == 'ism':
  143. if control_iface.IsManuallyActivated():
  144. print("Manually activated")
  145. else:
  146. print("Automatically activated")
  147. elif arg == 'dl':
  148. print("--- drivers list")
  149. is_range, is_strict, is_fake_values, values = configure_iface.GetParameterConstraint(
  150. ['engine', 'driver']
  151. )
  152. for value in values:
  153. print(value[1])
  154. elif arg == 'dg':
  155. print("--- get selected driver")
  156. isset, default, value = configure_iface.GetParameterValue(['engine', 'driver'])
  157. print(value)
  158. elif arg == 'ds':
  159. if index >= len(argv):
  160. return (1, "driver select command requires driver name argument")
  161. arg = argv[index]
  162. index += 1
  163. print("--- driver select \"%s\"" % arg)
  164. configure_iface.SetParameterValue(['engine', 'driver'], dbus.String(arg))
  165. elif arg == 'dp':
  166. print("--- get driver parameters (type:isset:default:value)")
  167. get_parameters(configure_iface, ['driver'])
  168. elif arg == 'dpd':
  169. if index >= len(argv):
  170. return (1, "get driver parameter long description command requires parameter name argument")
  171. param = argv[index]
  172. index += 1
  173. print("--- get driver parameter description (%s)" % param)
  174. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['driver', param])
  175. print(long_descr)
  176. maybe_print_param_constraint(configure_iface, ['driver', param])
  177. elif arg == 'dps':
  178. if index + 1 >= len(argv):
  179. return (1, "driver parameter set command requires parameter name and value arguments")
  180. param = argv[index]
  181. index += 1
  182. value = argv[index]
  183. index += 1
  184. print("--- driver param set \"%s\" -> \"%s\"" % (param, value))
  185. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['driver', param])
  186. configure_iface.SetParameterValue(['driver', param], python_type_to_jackdbus_type(value, type_char))
  187. elif arg == 'dpr':
  188. if index >= len(argv):
  189. return (1, "driver parameter reset command requires parameter name argument")
  190. param = argv[index]
  191. index += 1
  192. print("--- driver param reset \"%s\"" % param)
  193. configure_iface.ResetParameterValue(['driver', param])
  194. elif arg == 'ep':
  195. print("--- get engine parameters (type:isset:default:value)")
  196. get_parameters(configure_iface, ['engine'])
  197. elif arg == 'epd':
  198. if index >= len(argv):
  199. return (1, "get engine parameter long description command requires parameter name argument")
  200. param_name = argv[index]
  201. index += 1
  202. print("--- get engine parameter description (%s)" % param_name)
  203. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['engine', param_name])
  204. print(long_descr)
  205. maybe_print_param_constraint(configure_iface, ['engine', param_name])
  206. elif arg == 'eps':
  207. if index + 1 >= len(argv):
  208. return (1, "engine parameter set command requires parameter name and value arguments")
  209. param = argv[index]
  210. index += 1
  211. value = argv[index]
  212. index += 1
  213. print("--- engine param set \"%s\" -> \"%s\"" % (param, value))
  214. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['engine', param])
  215. configure_iface.SetParameterValue(['engine', param], python_type_to_jackdbus_type(value, type_char))
  216. elif arg == 'epr':
  217. if index >= len(argv):
  218. return (1, "engine parameter reset command requires parameter name")
  219. param = argv[index]
  220. index += 1
  221. print("--- engine param reset \"%s\"" % param)
  222. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['engine', param])
  223. configure_iface.ResetParameterValue(['engine', param])
  224. elif arg == 'il':
  225. print("--- internals list")
  226. is_leaf, internals = configure_iface.ReadContainer(['internals'])
  227. for internal in internals:
  228. print(internal)
  229. elif arg == 'ip':
  230. print("--- get internal parameters (type:isset:default:value)")
  231. if index >= len(argv):
  232. return (1, "internal parameters command requires internal name argument")
  233. internal_name = argv[index]
  234. index += 1
  235. get_parameters(configure_iface, ['internals', internal_name])
  236. elif arg == 'ipd':
  237. if index + 1 >= len(argv):
  238. return (
  239. 1,
  240. "get internal parameter long description command requires internal and parameter name arguments"
  241. )
  242. name = argv[index]
  243. index += 1
  244. param = argv[index]
  245. index += 1
  246. print("--- get internal parameter description (%s)" % param)
  247. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(['internals', name, param])
  248. print(long_descr)
  249. elif arg == 'ips':
  250. if index + 2 >= len(argv):
  251. return (1, "internal parameter set command requires internal, parameter name and value arguments")
  252. internal_name = argv[index]
  253. index += 1
  254. param = argv[index]
  255. index += 1
  256. value = argv[index]
  257. index += 1
  258. print("--- internal param set \"%s\" -> \"%s\"" % (param, value))
  259. type_char, name, short_descr, long_descr = configure_iface.GetParameterInfo(
  260. ['internals', internal_name, param]
  261. )
  262. configure_iface.SetParameterValue(
  263. ['internals', internal_name, param],
  264. python_type_to_jackdbus_type(value, type_char),
  265. )
  266. elif arg == 'ipr':
  267. if index + 1 >= len(argv):
  268. return (1, "reset internal parameter command requires internal and parameter name arguments")
  269. internal_name = argv[index]
  270. index += 1
  271. param = argv[index]
  272. index += 1
  273. print("--- internal param reset \"%s\"" % param)
  274. configure_iface.ResetParameterValue(['internals', internal_name, param])
  275. elif arg == 'iload':
  276. print("--- load internal")
  277. if index >= len(argv):
  278. return (1, "load internal command requires internal name argument")
  279. name = argv[index]
  280. index += 1
  281. control_iface.LoadInternal(name)
  282. elif arg == 'iunload':
  283. print("--- unload internal")
  284. if index >= len(argv):
  285. return (1, "unload internal command requires internal name argument")
  286. name = argv[index]
  287. index += 1
  288. control_iface.UnloadInternal(name)
  289. elif arg == 'asd':
  290. print("--- add slave driver")
  291. if index >= len(argv):
  292. return (1, "add slave driver command requires driver name argument")
  293. name = argv[index]
  294. index += 1
  295. control_iface.AddSlaveDriver(name)
  296. elif arg == 'rsd':
  297. print("--- remove slave driver")
  298. if index >= len(argv):
  299. return (1, "remove slave driver command requires driver name argument")
  300. name = argv[index]
  301. index += 1
  302. control_iface.RemoveSlaveDriver(name)
  303. elif arg == 'help':
  304. print_help()
  305. else:
  306. return (0, "Unknown command '%s'" % arg)
  307. except dbus.DBusException as e:
  308. return (1, "DBus exception: %s" % str(e))
  309. return (0, "")
  310. def shell():
  311. from click.parser import split_arg_string
  312. from sys import stdin
  313. while True:
  314. try:
  315. cmd = stdin.readline()
  316. if (cmd == ''):
  317. break
  318. s, t = parse_argv(split_arg_string(cmd))
  319. print("%i: %s" % (s, t), flush=True)
  320. except Exception:
  321. break
  322. def main():
  323. global control_iface, configure_iface
  324. if len(sys.argv) == 1 or sys.argv[1] in ["-h", "--help"]:
  325. print_help()
  326. return 0
  327. bus = dbus.SessionBus()
  328. controller = bus.get_object(service_name, "/org/jackaudio/Controller")
  329. control_iface = dbus.Interface(controller, control_interface_name)
  330. configure_iface = dbus.Interface(controller, configure_interface_name)
  331. # check arguments
  332. if sys.argv[1] == "shell":
  333. shell()
  334. else:
  335. s, t = parse_argv(sys.argv[1:])
  336. if (t):
  337. print(t)
  338. return s
  339. if __name__ == '__main__':
  340. sys.exit(main())