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.

500 lines
15KB

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