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.

1031 lines
30KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2007,2008,2011 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 <assert.h>
  22. #include <dbus/dbus.h>
  23. #include "jackdbus.h"
  24. #include "controller_internal.h"
  25. #include "xml.h"
  26. unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] =
  27. {
  28. [JackParamInt] = DBUS_TYPE_INT32,
  29. [JackParamUInt] = DBUS_TYPE_UINT32,
  30. [JackParamChar] = DBUS_TYPE_BYTE,
  31. [JackParamString] = DBUS_TYPE_STRING,
  32. [JackParamBool] = DBUS_TYPE_BOOLEAN,
  33. };
  34. const char *jack_controller_dbus_type_signatures[JACK_PARAM_MAX] =
  35. {
  36. [JackParamInt] = DBUS_TYPE_INT32_AS_STRING,
  37. [JackParamUInt] = DBUS_TYPE_UINT32_AS_STRING,
  38. [JackParamChar] = DBUS_TYPE_BYTE_AS_STRING,
  39. [JackParamString] = DBUS_TYPE_STRING_AS_STRING,
  40. [JackParamBool] = DBUS_TYPE_BOOLEAN_AS_STRING,
  41. };
  42. #define PARAM_TYPE_JACK_TO_DBUS(_) jack_controller_dbus_types[_]
  43. #define PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(_) jack_controller_dbus_type_signatures[_]
  44. static
  45. bool
  46. jack_controller_jack_to_dbus_variant(
  47. jackctl_param_type_t type,
  48. const union jackctl_parameter_value *value_ptr,
  49. message_arg_t *dbusv_ptr)
  50. {
  51. switch (type)
  52. {
  53. case JackParamInt:
  54. dbusv_ptr->int32 = (dbus_int32_t)value_ptr->i;
  55. return true;
  56. case JackParamUInt:
  57. dbusv_ptr->uint32 = (dbus_uint32_t)value_ptr->ui;
  58. return true;
  59. case JackParamChar:
  60. dbusv_ptr->byte = value_ptr->c;
  61. return true;
  62. case JackParamString:
  63. dbusv_ptr->string = value_ptr->str;
  64. return true;
  65. case JackParamBool:
  66. dbusv_ptr->boolean = (dbus_bool_t)value_ptr->b;
  67. return true;
  68. }
  69. jack_error("Unknown JACK parameter type %i", (int)type);
  70. assert(0);
  71. return false;
  72. }
  73. static
  74. bool
  75. jack_controller_dbus_to_jack_variant(
  76. int type,
  77. const message_arg_t *dbusv_ptr,
  78. union jackctl_parameter_value *value_ptr)
  79. {
  80. size_t len;
  81. switch (type)
  82. {
  83. case DBUS_TYPE_INT32:
  84. value_ptr->i = dbusv_ptr->int32;
  85. return true;
  86. case DBUS_TYPE_UINT32:
  87. value_ptr->ui = dbusv_ptr->uint32;
  88. return true;
  89. case DBUS_TYPE_BYTE:
  90. value_ptr->c = dbusv_ptr->byte;
  91. return true;
  92. case DBUS_TYPE_STRING:
  93. len = strlen(dbusv_ptr->string);
  94. if (len > JACK_PARAM_STRING_MAX)
  95. {
  96. jack_error("Parameter string value is too long (%u)", (unsigned int)len);
  97. return false;
  98. }
  99. memcpy(value_ptr->str, dbusv_ptr->string, len + 1);
  100. return true;
  101. case DBUS_TYPE_BOOLEAN:
  102. value_ptr->b = dbusv_ptr->boolean;
  103. return true;
  104. }
  105. jack_error("Unknown D-Bus parameter type %i", (int)type);
  106. return false;
  107. }
  108. /*
  109. * Construct a return message for a Get[Driver|Engine]ParameterValue method call.
  110. *
  111. * The operation can only fail due to lack of memory, in which case
  112. * there's no sense in trying to construct an error return. Instead,
  113. * call->reply will be set to NULL and handled in send_method_return().
  114. */
  115. static void
  116. jack_dbus_construct_method_return_parameter(
  117. struct jack_dbus_method_call * call,
  118. dbus_bool_t is_set,
  119. int type,
  120. const char *signature,
  121. message_arg_t default_value,
  122. message_arg_t value)
  123. {
  124. DBusMessageIter iter;
  125. /* Create a new method return message. */
  126. call->reply = dbus_message_new_method_return (call->message);
  127. if (!call->reply)
  128. {
  129. goto fail;
  130. }
  131. dbus_message_iter_init_append (call->reply, &iter);
  132. /* Append the is_set argument. */
  133. if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, (const void *) &is_set))
  134. {
  135. goto fail_unref;
  136. }
  137. /* Append the 'default' and 'value' arguments. */
  138. if (!jack_dbus_message_append_variant(&iter, type, signature, &default_value))
  139. {
  140. goto fail_unref;
  141. }
  142. if (!jack_dbus_message_append_variant(&iter, type, signature, &value))
  143. {
  144. goto fail_unref;
  145. }
  146. return;
  147. fail_unref:
  148. dbus_message_unref (call->reply);
  149. call->reply = NULL;
  150. fail:
  151. jack_error ("Ran out of memory trying to construct method return");
  152. }
  153. static
  154. bool
  155. jack_controller_dbus_get_parameter_address_ex(
  156. struct jack_dbus_method_call * call,
  157. DBusMessageIter * iter_ptr,
  158. const char ** address_array)
  159. {
  160. const char * signature;
  161. DBusMessageIter array_iter;
  162. int type;
  163. int index;
  164. if (!dbus_message_iter_init(call->message, iter_ptr))
  165. {
  166. jack_dbus_error(
  167. call,
  168. JACK_DBUS_ERROR_INVALID_ARGS,
  169. "Invalid arguments to method '%s'. No input arguments found.",
  170. call->method_name);
  171. return false;
  172. }
  173. signature = dbus_message_iter_get_signature(iter_ptr);
  174. if (signature == NULL)
  175. {
  176. jack_error("dbus_message_iter_get_signature() failed");
  177. return false;
  178. }
  179. if (strcmp(signature, "as") != 0)
  180. {
  181. jack_dbus_error(
  182. call,
  183. JACK_DBUS_ERROR_INVALID_ARGS,
  184. "Invalid arguments to method '%s'. Input arguments signature '%s', must begin with 'as'.",
  185. call->method_name,
  186. signature);
  187. return false;
  188. }
  189. dbus_message_iter_recurse(iter_ptr, &array_iter);
  190. index = 0;
  191. while ((type = dbus_message_iter_get_arg_type(&array_iter)) != DBUS_TYPE_INVALID)
  192. {
  193. if (index == PARAM_ADDRESS_SIZE)
  194. {
  195. jack_dbus_error(
  196. call,
  197. JACK_DBUS_ERROR_INVALID_ARGS,
  198. "Invalid arguments to method '%s'. Parameter address array must contain not more than %u elements.",
  199. (unsigned int)PARAM_ADDRESS_SIZE,
  200. call->method_name);
  201. return false;
  202. }
  203. ;
  204. if (type != DBUS_TYPE_STRING)
  205. {
  206. jack_dbus_error(
  207. call,
  208. JACK_DBUS_ERROR_FATAL,
  209. "Internal error when parsing parameter address of method '%s'. Address array element type '%c' is not string type.",
  210. call->method_name,
  211. type);
  212. return false;
  213. }
  214. dbus_message_iter_get_basic(&array_iter, address_array + index);
  215. //jack_info("address component: '%s'", address_array[index]);
  216. dbus_message_iter_next(&array_iter);
  217. index++;
  218. }
  219. while (index < PARAM_ADDRESS_SIZE)
  220. {
  221. address_array[index] = NULL;
  222. index++;
  223. }
  224. return true;
  225. }
  226. static
  227. bool
  228. jack_controller_dbus_get_parameter_address(
  229. struct jack_dbus_method_call * call,
  230. const char ** address_array)
  231. {
  232. DBusMessageIter iter;
  233. bool ret;
  234. ret = jack_controller_dbus_get_parameter_address_ex(call, &iter, address_array);
  235. if (ret && dbus_message_iter_has_next(&iter))
  236. {
  237. jack_dbus_error(
  238. call,
  239. JACK_DBUS_ERROR_INVALID_ARGS,
  240. "Invalid arguments to method '%s'. Input arguments signature must be 'as'.",
  241. call->method_name);
  242. return false;
  243. }
  244. return ret;
  245. }
  246. #define controller_ptr ((struct jack_controller *)call->context)
  247. static bool append_node_name(void * context, const char * name)
  248. {
  249. return dbus_message_iter_append_basic(context, DBUS_TYPE_STRING, &name);
  250. }
  251. static
  252. void
  253. jack_controller_dbus_read_container(
  254. struct jack_dbus_method_call * call)
  255. {
  256. const char * address[PARAM_ADDRESS_SIZE];
  257. dbus_bool_t leaf;
  258. DBusMessageIter iter;
  259. DBusMessageIter array_iter;
  260. //jack_info("jack_controller_dbus_read_container() called");
  261. if (!jack_controller_dbus_get_parameter_address(call, address))
  262. {
  263. /* The method call had invalid arguments meaning that
  264. * jack_controller_dbus_get_parameter_address() has
  265. * constructed an error for us. */
  266. return;
  267. }
  268. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  269. /* Create a new method return message. */
  270. call->reply = dbus_message_new_method_return(call->message);
  271. if (!call->reply)
  272. {
  273. goto oom;
  274. }
  275. dbus_message_iter_init_append(call->reply, &iter);
  276. if (!jack_params_check_address(controller_ptr->params, address, false))
  277. {
  278. jack_dbus_error(
  279. call,
  280. JACK_DBUS_ERROR_INVALID_ARGS,
  281. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  282. address[0],
  283. address[1],
  284. address[2],
  285. call->method_name);
  286. return;
  287. }
  288. leaf = jack_params_is_leaf_container(controller_ptr->params, address);
  289. if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
  290. {
  291. goto oom_unref;
  292. }
  293. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter))
  294. {
  295. goto oom_unref;
  296. }
  297. if (!jack_params_iterate_container(controller_ptr->params, address, append_node_name, &array_iter))
  298. {
  299. goto oom_close_unref;
  300. }
  301. dbus_message_iter_close_container(&iter, &array_iter);
  302. return;
  303. oom_close_unref:
  304. dbus_message_iter_close_container(&iter, &array_iter);
  305. oom_unref:
  306. dbus_message_unref(call->reply);
  307. call->reply = NULL;
  308. oom:
  309. jack_error ("Ran out of memory trying to construct method return");
  310. }
  311. static bool append_parameter(void * context, const struct jack_parameter * param_ptr)
  312. {
  313. DBusMessageIter struct_iter;
  314. unsigned char type;
  315. /* Open the struct. */
  316. if (!dbus_message_iter_open_container(context, DBUS_TYPE_STRUCT, NULL, &struct_iter))
  317. {
  318. goto fail;
  319. }
  320. /* Append parameter type. */
  321. type = PARAM_TYPE_JACK_TO_DBUS(param_ptr->type);
  322. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BYTE, &type))
  323. {
  324. goto fail_close;
  325. }
  326. /* Append parameter name. */
  327. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &param_ptr->name))
  328. {
  329. goto fail_close;
  330. }
  331. /* Append parameter short description. */
  332. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &param_ptr->short_decr))
  333. {
  334. goto fail_close;
  335. }
  336. /* Append parameter long description. */
  337. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &param_ptr->long_descr))
  338. {
  339. goto fail_close;
  340. }
  341. /* Close the struct. */
  342. if (!dbus_message_iter_close_container(context, &struct_iter))
  343. {
  344. goto fail;
  345. }
  346. return true;
  347. fail_close:
  348. dbus_message_iter_close_container(context, &struct_iter);
  349. fail:
  350. return false;
  351. }
  352. static
  353. void
  354. jack_controller_dbus_get_parameters_info(
  355. struct jack_dbus_method_call * call)
  356. {
  357. const char * address[PARAM_ADDRESS_SIZE];
  358. DBusMessageIter iter, array_iter;
  359. //jack_info("jack_controller_dbus_get_parameters_info() called");
  360. if (!jack_controller_dbus_get_parameter_address(call, address))
  361. {
  362. /* The method call had invalid arguments meaning that
  363. * jack_controller_dbus_get_parameter_address() has
  364. * constructed an error for us. */
  365. return;
  366. }
  367. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  368. if (!jack_params_check_address(controller_ptr->params, address, true))
  369. {
  370. jack_dbus_error(
  371. call,
  372. JACK_DBUS_ERROR_INVALID_ARGS,
  373. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  374. address[0],
  375. address[1],
  376. address[2],
  377. call->method_name);
  378. return;
  379. }
  380. call->reply = dbus_message_new_method_return (call->message);
  381. if (!call->reply)
  382. {
  383. goto fail;
  384. }
  385. dbus_message_iter_init_append (call->reply, &iter);
  386. /* Open the array. */
  387. if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter))
  388. {
  389. goto fail_unref;
  390. }
  391. if (!jack_params_iterate_params(controller_ptr->params, address, append_parameter, &array_iter))
  392. {
  393. goto fail_close_unref;
  394. }
  395. /* Close the array. */
  396. if (!dbus_message_iter_close_container (&iter, &array_iter))
  397. {
  398. goto fail_unref;
  399. }
  400. return;
  401. fail_close_unref:
  402. dbus_message_iter_close_container (&iter, &array_iter);
  403. fail_unref:
  404. dbus_message_unref (call->reply);
  405. call->reply = NULL;
  406. fail:
  407. jack_error ("Ran out of memory trying to construct method return");
  408. }
  409. static
  410. void
  411. jack_controller_dbus_get_parameter_info(
  412. struct jack_dbus_method_call * call)
  413. {
  414. const char * address[PARAM_ADDRESS_SIZE];
  415. const struct jack_parameter * param_ptr;
  416. DBusMessageIter iter;
  417. //jack_info("jack_controller_dbus_get_parameter_info() called");
  418. if (!jack_controller_dbus_get_parameter_address(call, address))
  419. {
  420. /* The method call had invalid arguments meaning that
  421. * jack_controller_dbus_get_parameter_address() has
  422. * constructed an error for us. */
  423. return;
  424. }
  425. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  426. param_ptr = jack_params_get_parameter(controller_ptr->params, address);
  427. if (param_ptr == NULL)
  428. {
  429. jack_dbus_error(
  430. call,
  431. JACK_DBUS_ERROR_INVALID_ARGS,
  432. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  433. address[0],
  434. address[1],
  435. address[2],
  436. call->method_name);
  437. return;
  438. }
  439. call->reply = dbus_message_new_method_return(call->message);
  440. if (!call->reply)
  441. {
  442. goto fail;
  443. }
  444. dbus_message_iter_init_append(call->reply, &iter);
  445. if (!append_parameter(&iter, param_ptr))
  446. {
  447. goto fail_unref;
  448. }
  449. return;
  450. fail_unref:
  451. dbus_message_unref(call->reply);
  452. call->reply = NULL;
  453. fail:
  454. jack_error("Ran out of memory trying to construct method return");
  455. }
  456. static
  457. void
  458. jack_controller_dbus_get_parameter_constraint(
  459. struct jack_dbus_method_call * call)
  460. {
  461. const char * address[PARAM_ADDRESS_SIZE];
  462. const struct jack_parameter * param_ptr;
  463. uint32_t index;
  464. DBusMessageIter iter, array_iter, struct_iter;
  465. const char * descr;
  466. message_arg_t value;
  467. //jack_info("jack_controller_dbus_get_parameter_constraint() called");
  468. if (!jack_controller_dbus_get_parameter_address(call, address))
  469. {
  470. /* The method call had invalid arguments meaning that
  471. * jack_controller_dbus_get_parameter_address() has
  472. * constructed an error for us. */
  473. return;
  474. }
  475. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  476. param_ptr = jack_params_get_parameter(controller_ptr->params, address);
  477. if (param_ptr == NULL)
  478. {
  479. jack_dbus_error(
  480. call,
  481. JACK_DBUS_ERROR_INVALID_ARGS,
  482. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  483. address[0],
  484. address[1],
  485. address[2],
  486. call->method_name);
  487. return;
  488. }
  489. call->reply = dbus_message_new_method_return(call->message);
  490. if (!call->reply)
  491. {
  492. goto fail;
  493. }
  494. dbus_message_iter_init_append(call->reply, &iter);
  495. if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0)
  496. {
  497. value.boolean = param_ptr->constraint_range;
  498. }
  499. else
  500. {
  501. value.boolean = false;
  502. }
  503. if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
  504. {
  505. goto fail_unref;
  506. }
  507. if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0)
  508. {
  509. value.boolean = (param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
  510. }
  511. if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
  512. {
  513. goto fail_unref;
  514. }
  515. if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0)
  516. {
  517. value.boolean = (param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
  518. }
  519. if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
  520. {
  521. goto fail_unref;
  522. }
  523. /* Open the array. */
  524. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(vs)", &array_iter))
  525. {
  526. goto fail_unref;
  527. }
  528. if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) == 0)
  529. {
  530. goto close;
  531. }
  532. if (param_ptr->constraint_range)
  533. {
  534. /* Open the struct. */
  535. if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
  536. {
  537. goto fail_close_unref;
  538. }
  539. jack_controller_jack_to_dbus_variant(param_ptr->type, &param_ptr->constraint.range.min, &value);
  540. if (!jack_dbus_message_append_variant(
  541. &struct_iter,
  542. PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
  543. PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
  544. &value))
  545. {
  546. goto fail_close2_unref;
  547. }
  548. descr = "min";
  549. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &descr))
  550. {
  551. goto fail_close2_unref;
  552. }
  553. /* Close the struct. */
  554. if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
  555. {
  556. goto fail_close_unref;
  557. }
  558. /* Open the struct. */
  559. if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
  560. {
  561. goto fail_close_unref;
  562. }
  563. jack_controller_jack_to_dbus_variant(param_ptr->type, &param_ptr->constraint.range.max, &value);
  564. if (!jack_dbus_message_append_variant(
  565. &struct_iter,
  566. PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
  567. PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
  568. &value))
  569. {
  570. goto fail_close2_unref;
  571. }
  572. descr = "max";
  573. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &descr))
  574. {
  575. goto fail_close2_unref;
  576. }
  577. /* Close the struct. */
  578. if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
  579. {
  580. goto fail_close_unref;
  581. }
  582. }
  583. else
  584. {
  585. /* Append enum values to the array. */
  586. for (index = 0 ; index < param_ptr->constraint.enumeration.count ; index++)
  587. {
  588. descr = param_ptr->constraint.enumeration.possible_values_array[index].short_desc;
  589. jack_controller_jack_to_dbus_variant(param_ptr->type, &param_ptr->constraint.enumeration.possible_values_array[index].value, &value);
  590. /* Open the struct. */
  591. if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
  592. {
  593. goto fail_close_unref;
  594. }
  595. if (!jack_dbus_message_append_variant(
  596. &struct_iter,
  597. PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
  598. PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
  599. &value))
  600. {
  601. goto fail_close2_unref;
  602. }
  603. if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &descr))
  604. {
  605. goto fail_close2_unref;
  606. }
  607. /* Close the struct. */
  608. if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
  609. {
  610. goto fail_close_unref;
  611. }
  612. }
  613. }
  614. close:
  615. /* Close the array. */
  616. if (!dbus_message_iter_close_container(&iter, &array_iter))
  617. {
  618. goto fail_unref;
  619. }
  620. return;
  621. fail_close2_unref:
  622. dbus_message_iter_close_container(&array_iter, &struct_iter);
  623. fail_close_unref:
  624. dbus_message_iter_close_container(&iter, &array_iter);
  625. fail_unref:
  626. dbus_message_unref(call->reply);
  627. call->reply = NULL;
  628. fail:
  629. jack_error ("Ran out of memory trying to construct method return");
  630. }
  631. static void
  632. jack_controller_dbus_get_parameter_value(
  633. struct jack_dbus_method_call * call)
  634. {
  635. const char * address[PARAM_ADDRESS_SIZE];
  636. const struct jack_parameter * param_ptr;
  637. union jackctl_parameter_value jackctl_value;
  638. union jackctl_parameter_value jackctl_default_value;
  639. message_arg_t value;
  640. message_arg_t default_value;
  641. //jack_info("jack_controller_dbus_get_parameter_value() called");
  642. if (!jack_controller_dbus_get_parameter_address(call, address))
  643. {
  644. /* The method call had invalid arguments meaning that
  645. * jack_controller_dbus_get_parameter_address() has
  646. * constructed an error for us. */
  647. return;
  648. }
  649. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  650. param_ptr = jack_params_get_parameter(controller_ptr->params, address);
  651. if (param_ptr == NULL)
  652. {
  653. jack_dbus_error(
  654. call,
  655. JACK_DBUS_ERROR_INVALID_ARGS,
  656. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  657. address[0],
  658. address[1],
  659. address[2],
  660. call->method_name);
  661. return;
  662. }
  663. jackctl_default_value = param_ptr->vtable.get_default_value(param_ptr->obj);
  664. jackctl_value = param_ptr->vtable.get_value(param_ptr->obj);
  665. jack_controller_jack_to_dbus_variant(param_ptr->type, &jackctl_value, &value);
  666. jack_controller_jack_to_dbus_variant(param_ptr->type, &jackctl_default_value, &default_value);
  667. /* Construct the reply. */
  668. jack_dbus_construct_method_return_parameter(
  669. call,
  670. (dbus_bool_t)(param_ptr->vtable.is_set(param_ptr->obj) ? TRUE : FALSE),
  671. PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
  672. PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
  673. default_value,
  674. value);
  675. }
  676. static
  677. void
  678. jack_controller_dbus_set_parameter_value(
  679. struct jack_dbus_method_call * call)
  680. {
  681. const char * address[PARAM_ADDRESS_SIZE];
  682. const struct jack_parameter * param_ptr;
  683. DBusMessageIter iter;
  684. DBusMessageIter variant_iter;
  685. message_arg_t arg;
  686. int arg_type;
  687. union jackctl_parameter_value value;
  688. //jack_info("jack_controller_dbus_set_parameter_value() called");
  689. if (!jack_controller_dbus_get_parameter_address_ex(call, &iter, address))
  690. {
  691. /* The method call had invalid arguments meaning that
  692. * jack_controller_dbus_get_parameter_address() has
  693. * constructed an error for us. */
  694. return;
  695. }
  696. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  697. param_ptr = jack_params_get_parameter(controller_ptr->params, address);
  698. if (param_ptr == NULL)
  699. {
  700. jack_dbus_error(
  701. call,
  702. JACK_DBUS_ERROR_INVALID_ARGS,
  703. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  704. address[0],
  705. address[1],
  706. address[2],
  707. call->method_name);
  708. return;
  709. }
  710. dbus_message_iter_next(&iter);
  711. if (dbus_message_iter_has_next(&iter))
  712. {
  713. jack_dbus_error(
  714. call,
  715. JACK_DBUS_ERROR_INVALID_ARGS,
  716. "Invalid arguments to method '%s'. Too many arguments.",
  717. call->method_name);
  718. return;
  719. }
  720. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
  721. {
  722. jack_dbus_error(
  723. call,
  724. JACK_DBUS_ERROR_INVALID_ARGS,
  725. "Invalid arguments to method '%s'. Value to set must be variant.",
  726. call->method_name);
  727. return;
  728. }
  729. dbus_message_iter_recurse (&iter, &variant_iter);
  730. dbus_message_iter_get_basic(&variant_iter, &arg);
  731. arg_type = dbus_message_iter_get_arg_type(&variant_iter);
  732. //jack_info("argument of type '%c'", arg_type);
  733. if (PARAM_TYPE_JACK_TO_DBUS(param_ptr->type) != arg_type)
  734. {
  735. jack_dbus_error(
  736. call,
  737. JACK_DBUS_ERROR_INVALID_ARGS,
  738. "Parameter value type mismatch: was expecting '%c', got '%c'",
  739. (char)PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
  740. (char)arg_type);
  741. return;
  742. }
  743. if (!jack_controller_dbus_to_jack_variant(
  744. arg_type,
  745. &arg,
  746. &value))
  747. {
  748. jack_dbus_error(
  749. call,
  750. JACK_DBUS_ERROR_INVALID_ARGS,
  751. "Cannot convert parameter value");
  752. return;
  753. }
  754. param_ptr->vtable.set_value(param_ptr->obj, &value);
  755. jack_controller_pending_save(controller_ptr);
  756. jack_dbus_construct_method_return_empty(call);
  757. }
  758. static
  759. void
  760. jack_controller_dbus_reset_parameter_value(
  761. struct jack_dbus_method_call * call)
  762. {
  763. const char * address[PARAM_ADDRESS_SIZE];
  764. const struct jack_parameter * param_ptr;
  765. //jack_info("jack_controller_dbus_reset_parameter_value() called");
  766. if (!jack_controller_dbus_get_parameter_address(call, address))
  767. {
  768. /* The method call had invalid arguments meaning that
  769. * jack_controller_dbus_get_parameter_address() has
  770. * constructed an error for us. */
  771. return;
  772. }
  773. //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
  774. param_ptr = jack_params_get_parameter(controller_ptr->params, address);
  775. if (param_ptr == NULL)
  776. {
  777. jack_dbus_error(
  778. call,
  779. JACK_DBUS_ERROR_INVALID_ARGS,
  780. "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
  781. address[0],
  782. address[1],
  783. address[2],
  784. call->method_name);
  785. return;
  786. }
  787. param_ptr->vtable.reset(param_ptr->obj);
  788. jack_controller_pending_save(controller_ptr);
  789. jack_dbus_construct_method_return_empty(call);
  790. }
  791. #undef controller_ptr
  792. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(ReadContainer, "Get names of child parameters or containers")
  793. JACK_DBUS_METHOD_ARGUMENT_IN("parent", "as", "Address of parent container")
  794. JACK_DBUS_METHOD_ARGUMENT_OUT("leaf", "b", "Whether children are parameters (true) or containers (false)")
  795. JACK_DBUS_METHOD_ARGUMENT_OUT("children", "as", "Array of child names")
  796. JACK_DBUS_METHOD_ARGUMENTS_END
  797. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(GetParametersInfo, "Retrieve info about parameters")
  798. JACK_DBUS_METHOD_ARGUMENT_IN("parent", "as", "Address of parameters parent")
  799. JACK_DBUS_METHOD_ARGUMENT_OUT("parameter_info_array", "a(ysss)", "Array of parameter info structs. Each info struct contains: type char, name, short and long description")
  800. JACK_DBUS_METHOD_ARGUMENTS_END
  801. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(GetParameterInfo, "Retrieve info about parameter")
  802. JACK_DBUS_METHOD_ARGUMENT_IN("parameter", "as", "Address of parameter")
  803. JACK_DBUS_METHOD_ARGUMENT_OUT("parameter_info", "(ysss)", "Parameter info struct that contains: type char, name, short and long description")
  804. JACK_DBUS_METHOD_ARGUMENTS_END
  805. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(GetParameterConstraint, "Get constraint of parameter")
  806. JACK_DBUS_METHOD_ARGUMENT_IN("parameter", "as", "Address of parameter")
  807. JACK_DBUS_METHOD_ARGUMENT_OUT("is_range", "b", "Whether constrinat is a range. If so, values parameter will contain two values, min and max")
  808. JACK_DBUS_METHOD_ARGUMENT_OUT("is_strict", "b", "Whether enum constraint is strict. I.e. value not listed in values array will not work")
  809. JACK_DBUS_METHOD_ARGUMENT_OUT("is_fake_value", "b", "Whether enum values are fake. I.e. have no user meaningful meaning")
  810. JACK_DBUS_METHOD_ARGUMENT_OUT("values", "a(vs)", "Values. If there is no constraint, this array will be empty. For range constraint there will be two values, min and max. For enum constraint there will be 2 or more values.")
  811. JACK_DBUS_METHOD_ARGUMENTS_END
  812. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(GetParameterValue, "Get value of parameter")
  813. JACK_DBUS_METHOD_ARGUMENT_IN("parameter", "as", "Address of parameter")
  814. JACK_DBUS_METHOD_ARGUMENT_OUT("is_set", "b", "Whether parameter is set or its default value is used")
  815. JACK_DBUS_METHOD_ARGUMENT_OUT("default", "v", "Default value of parameter")
  816. JACK_DBUS_METHOD_ARGUMENT_OUT("value", "v", "Actual value of parameter")
  817. JACK_DBUS_METHOD_ARGUMENTS_END
  818. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(SetParameterValue, "Set value of parameter")
  819. JACK_DBUS_METHOD_ARGUMENT_IN("parameter", "as", "Address of parameter")
  820. JACK_DBUS_METHOD_ARGUMENT_IN("value", "v", "New value for parameter")
  821. JACK_DBUS_METHOD_ARGUMENTS_END
  822. JACK_DBUS_METHOD_ARGUMENTS_BEGIN_EX(ResetParameterValue, "Reset parameter to default value")
  823. JACK_DBUS_METHOD_ARGUMENT_IN("parameter", "as", "Address of parameter")
  824. JACK_DBUS_METHOD_ARGUMENTS_END
  825. JACK_DBUS_METHODS_BEGIN
  826. JACK_DBUS_METHOD_DESCRIBE(ReadContainer, jack_controller_dbus_read_container)
  827. JACK_DBUS_METHOD_DESCRIBE(GetParametersInfo, jack_controller_dbus_get_parameters_info)
  828. JACK_DBUS_METHOD_DESCRIBE(GetParameterInfo, jack_controller_dbus_get_parameter_info)
  829. JACK_DBUS_METHOD_DESCRIBE(GetParameterConstraint, jack_controller_dbus_get_parameter_constraint)
  830. JACK_DBUS_METHOD_DESCRIBE(GetParameterValue, jack_controller_dbus_get_parameter_value)
  831. JACK_DBUS_METHOD_DESCRIBE(SetParameterValue, jack_controller_dbus_set_parameter_value)
  832. JACK_DBUS_METHOD_DESCRIBE(ResetParameterValue, jack_controller_dbus_reset_parameter_value)
  833. JACK_DBUS_METHODS_END
  834. /*
  835. * Parameter addresses:
  836. *
  837. * "engine"
  838. * "engine", "driver"
  839. * "engine", "realtime"
  840. * "engine", ...more engine parameters
  841. *
  842. * "driver", "device"
  843. * "driver", ...more driver parameters
  844. *
  845. * "drivers", "alsa", "device"
  846. * "drivers", "alsa", ...more alsa driver parameters
  847. *
  848. * "drivers", ...more drivers
  849. *
  850. * "internals", "netmanager", "multicast_ip"
  851. * "internals", "netmanager", ...more netmanager parameters
  852. *
  853. * "internals", ...more internals
  854. *
  855. */
  856. JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_configure, "org.jackaudio.Configure")
  857. JACK_DBUS_IFACE_EXPOSE_METHODS
  858. JACK_DBUS_IFACE_END