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.

441 lines
13KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2007,2008,2010 Nedko Arnaudov
  4. Copyright (C) 2007-2008 Juuso Alasuutari
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #if defined(HAVE_CONFIG_H)
  17. #include "config.h"
  18. #endif
  19. #include <stdint.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <assert.h>
  23. #include <dbus/dbus.h>
  24. #include "jackdbus.h"
  25. #include "controller_internal.h"
  26. #include "xml.h"
  27. #define JACK_DBUS_IFACE_NAME "org.jackaudio.JackControl"
  28. void
  29. jack_controller_control_send_signal_server_started()
  30. {
  31. jack_dbus_send_signal(
  32. JACK_CONTROLLER_OBJECT_PATH,
  33. JACK_DBUS_IFACE_NAME,
  34. "ServerStarted",
  35. DBUS_TYPE_INVALID);
  36. }
  37. void
  38. jack_controller_control_send_signal_server_stopped()
  39. {
  40. jack_dbus_send_signal(
  41. JACK_CONTROLLER_OBJECT_PATH,
  42. JACK_DBUS_IFACE_NAME,
  43. "ServerStopped",
  44. DBUS_TYPE_INVALID);
  45. }
  46. #define controller_ptr ((struct jack_controller *)call->context)
  47. /*
  48. * Check if the supplied method name exists in org.jackaudio.JackControl,
  49. * if it does execute it and return true. Otherwise return false.
  50. */
  51. static
  52. bool
  53. jack_control_run_method(
  54. struct jack_dbus_method_call * call,
  55. const struct jack_dbus_interface_method_descriptor * methods)
  56. {
  57. int ret;
  58. int type;
  59. message_arg_t arg;
  60. /* use empty reply if not overridden in the code that follows */
  61. type = DBUS_TYPE_INVALID;
  62. if (strcmp (call->method_name, "Exit") == 0)
  63. {
  64. g_exit_command = TRUE;
  65. }
  66. else if (strcmp (call->method_name, "IsStarted") == 0)
  67. {
  68. type = DBUS_TYPE_BOOLEAN;
  69. arg.boolean = (dbus_bool_t) (controller_ptr->started ? TRUE : FALSE);
  70. }
  71. else if (strcmp (call->method_name, "StartServer") == 0)
  72. {
  73. if (controller_ptr->started)
  74. {
  75. jack_info("Ignoring JACK server start request because server is already started.");
  76. }
  77. else
  78. {
  79. if (!jack_controller_start_server(controller_ptr, call))
  80. {
  81. /* the reply is set by the failed function */
  82. assert(call->reply != NULL);
  83. return true;
  84. }
  85. jack_controller_control_send_signal_server_started();
  86. }
  87. }
  88. else if (strcmp (call->method_name, "StopServer") == 0)
  89. {
  90. if (!controller_ptr->started)
  91. {
  92. jack_info("Ignoring JACK server stop request because server is already stopped.");
  93. }
  94. else
  95. {
  96. if (!jack_controller_stop_server(controller_ptr, call))
  97. {
  98. /* the reply is set by the failed function */
  99. assert(call->reply != NULL);
  100. return true;
  101. }
  102. jack_controller_control_send_signal_server_stopped();
  103. }
  104. }
  105. else if (strcmp (call->method_name, "SwitchMaster") == 0)
  106. {
  107. if (!controller_ptr->started)
  108. {
  109. goto not_started;
  110. }
  111. else
  112. {
  113. if (!jack_controller_switch_master(controller_ptr, call))
  114. {
  115. /* the reply is set by the failed function */
  116. assert(call->reply != NULL);
  117. return true;
  118. }
  119. }
  120. }
  121. else if (strcmp (call->method_name, "GetLoad") == 0)
  122. {
  123. if (!controller_ptr->started)
  124. {
  125. goto not_started;
  126. }
  127. type = DBUS_TYPE_DOUBLE;
  128. arg.doubl = jack_cpu_load(controller_ptr->client);
  129. }
  130. else if (strcmp (call->method_name, "GetXruns") == 0)
  131. {
  132. type = DBUS_TYPE_UINT32;
  133. arg.uint32 = controller_ptr->xruns;
  134. }
  135. else if (strcmp (call->method_name, "GetSampleRate") == 0)
  136. {
  137. if (!controller_ptr->started)
  138. {
  139. goto not_started;
  140. }
  141. type = DBUS_TYPE_UINT32;
  142. arg.uint32 = jack_get_sample_rate(controller_ptr->client);
  143. }
  144. else if (strcmp (call->method_name, "GetLatency") == 0)
  145. {
  146. if (!controller_ptr->started)
  147. {
  148. goto not_started;
  149. }
  150. type = DBUS_TYPE_DOUBLE;
  151. arg.doubl = ((float)jack_get_buffer_size(controller_ptr->client) / (float)jack_get_sample_rate(controller_ptr->client)) * 1000.0f;
  152. }
  153. else if (strcmp (call->method_name, "GetBufferSize") == 0)
  154. {
  155. if (!controller_ptr->started)
  156. {
  157. goto not_started;
  158. }
  159. type = DBUS_TYPE_UINT32;
  160. arg.uint32 = jack_get_buffer_size(controller_ptr->client);
  161. }
  162. else if (strcmp (call->method_name, "SetBufferSize") == 0)
  163. {
  164. dbus_uint32_t buffer_size;
  165. if (!controller_ptr->started)
  166. {
  167. goto not_started;
  168. }
  169. if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT32, &buffer_size, DBUS_TYPE_INVALID))
  170. {
  171. /* jack_dbus_get_method_args() has set reply for us */
  172. goto exit;
  173. }
  174. ret = jack_set_buffer_size(controller_ptr->client, buffer_size);
  175. if (ret != 0)
  176. {
  177. jack_dbus_error(
  178. call,
  179. JACK_DBUS_ERROR_GENERIC,
  180. "jack_set_buffer_size(%u) failed with error %d", (unsigned int)buffer_size, ret);
  181. goto exit;
  182. }
  183. }
  184. else if (strcmp (call->method_name, "IsRealtime") == 0)
  185. {
  186. type = DBUS_TYPE_BOOLEAN;
  187. arg.boolean = jack_is_realtime(controller_ptr->client) ? TRUE : FALSE;
  188. }
  189. else if (strcmp (call->method_name, "ResetXruns") == 0)
  190. {
  191. controller_ptr->xruns = 0;
  192. }
  193. else if (strcmp (call->method_name, "LoadInternal") == 0)
  194. {
  195. const char *internal_name;
  196. if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_INVALID))
  197. {
  198. /* The method call had invalid arguments meaning that
  199. * get_method_args() has constructed an error for us.
  200. */
  201. goto exit;
  202. }
  203. if (!jack_controller_load_internal(controller_ptr, internal_name)) {
  204. jack_dbus_error(
  205. call,
  206. JACK_DBUS_ERROR_GENERIC,
  207. "jack_controller_load_internal failed for internal (%s)", internal_name);
  208. }
  209. }
  210. else if (strcmp (call->method_name, "AddSlaveDriver") == 0)
  211. {
  212. const char *driver_name;
  213. if (controller_ptr->started)
  214. {
  215. goto fail_started;
  216. }
  217. if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID))
  218. {
  219. /* The method call had invalid arguments meaning that
  220. * get_method_args() has constructed an error for us.
  221. */
  222. goto exit;
  223. }
  224. if (!jack_controller_add_slave_driver(controller_ptr, driver_name))
  225. {
  226. jack_dbus_error(
  227. call,
  228. JACK_DBUS_ERROR_GENERIC,
  229. "jack_controller_add_slave_driver failed for driver (%s)", driver_name);
  230. }
  231. else
  232. {
  233. jack_controller_pending_save(controller_ptr);
  234. }
  235. }
  236. else if (strcmp (call->method_name, "RemoveSlaveDriver") == 0)
  237. {
  238. const char *driver_name;
  239. if (controller_ptr->started)
  240. {
  241. goto fail_started;
  242. }
  243. if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID))
  244. {
  245. /* The method call had invalid arguments meaning that
  246. * get_method_args() has constructed an error for us.
  247. */
  248. goto exit;
  249. }
  250. if (!jack_controller_remove_slave_driver(controller_ptr, driver_name))
  251. {
  252. jack_dbus_error(
  253. call,
  254. JACK_DBUS_ERROR_GENERIC,
  255. "jack_controller_remove_slave_driver failed for driver (%s)", driver_name);
  256. }
  257. else
  258. {
  259. jack_controller_pending_save(controller_ptr);
  260. }
  261. }
  262. else if (strcmp (call->method_name, "UnloadInternal") == 0)
  263. {
  264. const char *internal_name;
  265. if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_INVALID))
  266. {
  267. /* The method call had invalid arguments meaning that
  268. * get_method_args() has constructed an error for us.
  269. */
  270. goto exit;
  271. }
  272. if (!jack_controller_unload_internal(controller_ptr, internal_name)) {
  273. jack_dbus_error(
  274. call,
  275. JACK_DBUS_ERROR_GENERIC,
  276. "jack_controller_unload_internal failed for internal (%s)", internal_name);
  277. }
  278. }
  279. else
  280. {
  281. return false;
  282. }
  283. jack_dbus_construct_method_return_single(call, type, arg);
  284. goto exit;
  285. not_started:
  286. jack_dbus_only_error(
  287. call,
  288. JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
  289. "Can't execute method '%s' with stopped JACK server",
  290. call->method_name);
  291. goto exit;
  292. fail_started:
  293. jack_dbus_only_error(
  294. call,
  295. JACK_DBUS_ERROR_SERVER_RUNNING,
  296. "Can't execute method '%s' with started JACK server",
  297. call->method_name);
  298. goto exit;
  299. exit:
  300. return true;
  301. }
  302. #undef controller_ptr
  303. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsStarted)
  304. JACK_DBUS_METHOD_ARGUMENT("started", "b", true)
  305. JACK_DBUS_METHOD_ARGUMENTS_END
  306. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StartServer)
  307. JACK_DBUS_METHOD_ARGUMENTS_END
  308. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StopServer)
  309. JACK_DBUS_METHOD_ARGUMENTS_END
  310. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SwitchMaster)
  311. JACK_DBUS_METHOD_ARGUMENTS_END
  312. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLoad)
  313. JACK_DBUS_METHOD_ARGUMENT("load", "d", true)
  314. JACK_DBUS_METHOD_ARGUMENTS_END
  315. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetXruns)
  316. JACK_DBUS_METHOD_ARGUMENT("xruns_count", "u", true)
  317. JACK_DBUS_METHOD_ARGUMENTS_END
  318. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSampleRate)
  319. JACK_DBUS_METHOD_ARGUMENT("sample_rate", "u", true)
  320. JACK_DBUS_METHOD_ARGUMENTS_END
  321. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLatency)
  322. JACK_DBUS_METHOD_ARGUMENT("latency_ms", "d", true)
  323. JACK_DBUS_METHOD_ARGUMENTS_END
  324. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetBufferSize)
  325. JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", true)
  326. JACK_DBUS_METHOD_ARGUMENTS_END
  327. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetBufferSize)
  328. JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", false)
  329. JACK_DBUS_METHOD_ARGUMENTS_END
  330. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsRealtime)
  331. JACK_DBUS_METHOD_ARGUMENT("realtime", "b", true)
  332. JACK_DBUS_METHOD_ARGUMENTS_END
  333. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ResetXruns)
  334. JACK_DBUS_METHOD_ARGUMENTS_END
  335. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(LoadInternal)
  336. JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
  337. JACK_DBUS_METHOD_ARGUMENTS_END
  338. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(UnloadInternal)
  339. JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
  340. JACK_DBUS_METHOD_ARGUMENTS_END
  341. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(AddSlaveDriver)
  342. JACK_DBUS_METHOD_ARGUMENT("driver_name", "s", false)
  343. JACK_DBUS_METHOD_ARGUMENTS_END
  344. JACK_DBUS_METHOD_ARGUMENTS_BEGIN(RemoveSlaveDriver)
  345. JACK_DBUS_METHOD_ARGUMENT("driver_name", "s", false)
  346. JACK_DBUS_METHOD_ARGUMENTS_END
  347. JACK_DBUS_METHODS_BEGIN
  348. JACK_DBUS_METHOD_DESCRIBE(IsStarted, NULL)
  349. JACK_DBUS_METHOD_DESCRIBE(StartServer, NULL)
  350. JACK_DBUS_METHOD_DESCRIBE(StopServer, NULL)
  351. JACK_DBUS_METHOD_DESCRIBE(SwitchMaster, NULL)
  352. JACK_DBUS_METHOD_DESCRIBE(GetLoad, NULL)
  353. JACK_DBUS_METHOD_DESCRIBE(GetXruns, NULL)
  354. JACK_DBUS_METHOD_DESCRIBE(GetSampleRate, NULL)
  355. JACK_DBUS_METHOD_DESCRIBE(GetLatency, NULL)
  356. JACK_DBUS_METHOD_DESCRIBE(GetBufferSize, NULL)
  357. JACK_DBUS_METHOD_DESCRIBE(SetBufferSize, NULL)
  358. JACK_DBUS_METHOD_DESCRIBE(IsRealtime, NULL)
  359. JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL)
  360. JACK_DBUS_METHOD_DESCRIBE(LoadInternal, NULL)
  361. JACK_DBUS_METHOD_DESCRIBE(UnloadInternal, NULL)
  362. JACK_DBUS_METHOD_DESCRIBE(AddSlaveDriver, NULL)
  363. JACK_DBUS_METHOD_DESCRIBE(RemoveSlaveDriver, NULL)
  364. JACK_DBUS_METHODS_END
  365. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ServerStarted)
  366. JACK_DBUS_SIGNAL_ARGUMENTS_END
  367. JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ServerStopped)
  368. JACK_DBUS_SIGNAL_ARGUMENTS_END
  369. JACK_DBUS_SIGNALS_BEGIN
  370. JACK_DBUS_SIGNAL_DESCRIBE(ServerStarted)
  371. JACK_DBUS_SIGNAL_DESCRIBE(ServerStopped)
  372. JACK_DBUS_SIGNALS_END
  373. JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_control, JACK_DBUS_IFACE_NAME)
  374. JACK_DBUS_IFACE_HANDLER(jack_control_run_method)
  375. JACK_DBUS_IFACE_EXPOSE_METHODS
  376. JACK_DBUS_IFACE_EXPOSE_SIGNALS
  377. JACK_DBUS_IFACE_END