diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index 319afea..542ee2a 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -120,6 +120,7 @@ struct jackctl_parameter struct jackctl_driver * driver_ptr; char id; jack_driver_param_t * driver_parameter_ptr; + jack_driver_param_constraint_desc_t * constraint_ptr; }; static @@ -132,7 +133,8 @@ jackctl_add_parameter( jackctl_param_type_t type, union jackctl_parameter_value * value_ptr, union jackctl_parameter_value * default_value_ptr, - union jackctl_parameter_value value) + union jackctl_parameter_value value, + jack_driver_param_constraint_desc_t * constraint_ptr = NULL) { struct jackctl_parameter * parameter_ptr; @@ -167,6 +169,7 @@ jackctl_add_parameter( parameter_ptr->driver_ptr = NULL; parameter_ptr->driver_parameter_ptr = NULL; parameter_ptr->id = 0; + parameter_ptr->constraint_ptr = constraint_ptr; *parameters_list_ptr_ptr = jack_slist_append(*parameters_list_ptr_ptr, parameter_ptr); @@ -251,7 +254,8 @@ jackctl_add_driver_parameters( jackctl_type, NULL, NULL, - jackctl_value); + jackctl_value, + descriptor_ptr->constraint); if (parameter_ptr == NULL) { @@ -909,6 +913,88 @@ EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *pa return parameter_ptr->long_description; } +EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr) +{ + return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0; +} + +EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr) +{ + return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0; +} + +EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr) +{ + if (!jackctl_parameter_has_enum_constraint(parameter_ptr)) + { + return 0; + } + + return parameter_ptr->constraint_ptr->constraint.enumeration.count; +} + +EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index) +{ + jack_driver_param_value_t * value_ptr; + union jackctl_parameter_value jackctl_value; + + value_ptr = ¶meter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value; + + switch (parameter_ptr->type) + { + case JackParamInt: + jackctl_value.i = value_ptr->i; + break; + case JackParamUInt: + jackctl_value.ui = value_ptr->ui; + break; + case JackParamChar: + jackctl_value.c = value_ptr->c; + break; + case JackParamString: + strcpy(jackctl_value.str, value_ptr->str); + break; + default: + jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type); + assert(0); + } + + return jackctl_value; +} + +EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index) +{ + return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc; +} + +EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr) +{ + switch (parameter_ptr->type) + { + case JackParamInt: + min_ptr->i = parameter_ptr->constraint_ptr->constraint.range.min.i; + max_ptr->i = parameter_ptr->constraint_ptr->constraint.range.max.i; + return; + case JackParamUInt: + min_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.min.ui; + max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui; + return; + default: + jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr->type); + assert(0); + } +} + +EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr) +{ + return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0; +} + +EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr) +{ + return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0; +} + EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr) { return parameter_ptr->type; diff --git a/common/JackControlAPI.h b/common/JackControlAPI.h index 032e0e9..7fc7324 100644 --- a/common/JackControlAPI.h +++ b/common/JackControlAPI.h @@ -164,6 +164,42 @@ EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value( jackctl_parameter *parameter_ptr); +EXPORT bool +jackctl_parameter_has_range_constraint( + jackctl_parameter_t * parameter_ptr); + +EXPORT bool +jackctl_parameter_has_enum_constraint( + jackctl_parameter_t * parameter_ptr); + +EXPORT uint32_t +jackctl_parameter_get_enum_constraints_count( + jackctl_parameter_t * parameter_ptr); + +EXPORT union jackctl_parameter_value +jackctl_parameter_get_enum_constraint_value( + jackctl_parameter_t * parameter_ptr, + uint32_t index); + +EXPORT const char * +jackctl_parameter_get_enum_constraint_description( + jackctl_parameter_t * parameter_ptr, + uint32_t index); + +EXPORT void +jackctl_parameter_get_range_constraint( + jackctl_parameter_t * parameter_ptr, + union jackctl_parameter_value * min_ptr, + union jackctl_parameter_value * max_ptr); + +EXPORT bool +jackctl_parameter_constraint_is_strict( + jackctl_parameter_t * parameter_ptr); + +EXPORT bool +jackctl_parameter_constraint_is_fake_value( + jackctl_parameter_t * parameter_ptr); + EXPORT const JSList * jackctl_server_get_internals_list( jackctl_server *server_ptr); diff --git a/common/driver_interface.h b/common/driver_interface.h index d1444e4..779d138 100644 --- a/common/driver_interface.h +++ b/common/driver_interface.h @@ -1,5 +1,6 @@ /* Copyright (C) 2003 Bob Ham + Copyright (C) 2008 Nedko Arnaudov This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -36,6 +37,10 @@ extern "C" #define JACK_DRIVER_PARAM_DESC 255 #define JACK_PATH_MAX 511 +#define JACK_CONSTRAINT_FLAG_RANGE ((uint32_t)1) /**< if set, constraint is a range (min-max) */ +#define JACK_CONSTRAINT_FLAG_STRICT ((uint32_t)2) /**< if set, constraint is strict, i.e. supplying non-matching value will not work */ +#define JACK_CONSTRAINT_FLAG_FAKE_VALUE ((uint32_t)2) /**< if set, values have no user meaningful meaning */ + /** Driver parameter types */ typedef enum { @@ -55,6 +60,26 @@ extern "C" char str[JACK_DRIVER_PARAM_STRING_MAX + 1]; } jack_driver_param_value_t; + typedef struct { + jack_driver_param_value_t value; + char short_desc[64]; /**< A short (~30 chars) description for the user */ + } jack_driver_param_value_enum_t; + + typedef struct { + uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ + + union { + struct { + jack_driver_param_value_t min; + jack_driver_param_value_t max; + } range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */ + + struct { + uint32_t count; + jack_driver_param_value_enum_t * possible_values_array; + } enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */ + } constraint; + } jack_driver_param_constraint_desc_t; /** A driver parameter descriptor */ typedef struct { @@ -62,6 +87,7 @@ extern "C" char character; /**< The parameter's character (for getopt, etc) */ jack_driver_param_type_t type; /**< The parameter's type */ jack_driver_param_value_t value; /**< The parameter's (default) value */ + jack_driver_param_constraint_desc_t * constraint; /**< Pointer to parameter constraint descriptor. NULL if there is no constraint */ char short_desc[64]; /**< A short (~30 chars) description for the user */ char long_desc[1024]; /**< A longer description for the user */ } diff --git a/common/jack/control.h b/common/jack/control.h index 96cf3e1..63f061a 100644 --- a/common/jack/control.h +++ b/common/jack/control.h @@ -312,6 +312,103 @@ jackctl_parameter_get_default_value( jackctl_parameter_t * parameter); /** + * Call this function check whether parameter has range constraint. + * + * @param parameter object handle of parameter to check + * + * @return whether parameter has range constraint. + */ +bool +jackctl_parameter_has_range_constraint( + jackctl_parameter_t * parameter_ptr); + +/** + * Call this function check whether parameter has enumeration constraint. + * + * @param parameter object handle of parameter to check + * + * @return whether parameter has enumeration constraint. + */ +bool +jackctl_parameter_has_enum_constraint( + jackctl_parameter_t * parameter_ptr); + +/** + * Call this function get how many enumeration values parameter has. + * + * @param parameter object handle of parameter + * + * @return number of enumeration values + */ +uint32_t +jackctl_parameter_get_enum_constraints_count( + jackctl_parameter_t * parameter_ptr); + +/** + * Call this function to get parameter enumeration value. + * + * @param parameter object handle of parameter + * @param index index of parameter enumeration value + * + * @return enumeration value. + */ +union jackctl_parameter_value +jackctl_parameter_get_enum_constraint_value( + jackctl_parameter_t * parameter_ptr, + uint32_t index); + +/** + * Call this function to get parameter enumeration value description. + * + * @param parameter object handle of parameter + * @param index index of parameter enumeration value + * + * @return enumeration value description. + */ +const char * +jackctl_parameter_get_enum_constraint_description( + jackctl_parameter_t * parameter_ptr, + uint32_t index); + +/** + * Call this function to get parameter range. + * + * @param parameter object handle of parameter + * @param min_ptr pointer to variable receiving parameter minimum value + * @param max_ptr pointer to variable receiving parameter maximum value + */ +void +jackctl_parameter_get_range_constraint( + jackctl_parameter_t * parameter_ptr, + union jackctl_parameter_value * min_ptr, + union jackctl_parameter_value * max_ptr); + +/** + * Call this function to check whether parameter constraint is strict, + * i.e. whether supplying non-matching value will not work for sure. + * + * @param parameter parameter object handle to check + * + * @return whether parameter constraint is strict. + */ +bool +jackctl_parameter_constraint_is_strict( + jackctl_parameter_t * parameter_ptr); + +/** + * Call this function to check whether parameter has fake values, + * i.e. values have no user meaningful meaning and only value + * description is meaningful to user. + * + * @param parameter parameter object handle to check + * + * @return whether parameter constraint is strict. + */ +bool +jackctl_parameter_constraint_is_fake_value( + jackctl_parameter_t * parameter_ptr); + +/** * Call this function to get list of available internal clients. List node data * pointers is a internal client object handle (::jackctl_internal_t). * diff --git a/dbus/controller_iface_configure.c b/dbus/controller_iface_configure.c index 804b19b..7927c49 100644 --- a/dbus/controller_iface_configure.c +++ b/dbus/controller_iface_configure.c @@ -409,6 +409,211 @@ fail: jack_error ("Ran out of memory trying to construct method return"); } +static +void +jack_controller_get_parameter_constraint( + struct jack_dbus_method_call * call, + jackctl_parameter_t * parameter) +{ + uint32_t index; + uint32_t count; + union jackctl_parameter_value min; + union jackctl_parameter_value max; + union jackctl_parameter_value jackctl_value; + DBusMessageIter iter, array_iter, struct_iter; + const char * descr; + jackctl_param_type_t type; + message_arg_t value; + bool is_range; + + type = jackctl_parameter_get_type(parameter); + + call->reply = dbus_message_new_method_return(call->message); + if (!call->reply) + { + goto fail; + } + + dbus_message_iter_init_append(call->reply, &iter); + + is_range = jackctl_parameter_has_range_constraint(parameter); + value.boolean = is_range; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) + { + goto fail_unref; + } + + value.boolean = jackctl_parameter_constraint_is_strict(parameter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) + { + goto fail_unref; + } + + value.boolean = jackctl_parameter_constraint_is_fake_value(parameter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) + { + goto fail_unref; + } + + /* Open the array. */ + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(vs)", &array_iter)) + { + goto fail_unref; + } + + if (is_range) + { + jack_info("parameter with range constraint"); + + jackctl_parameter_get_range_constraint(parameter, &min, &max); + + /* Open the struct. */ + if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) + { + goto fail_close_unref; + } + + jack_controller_jack_to_dbus_variant(type, &min, &value); + + if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value)) + { + goto fail_close2_unref; + } + + descr = "min"; + + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &descr)) + { + goto fail_close2_unref; + } + + /* Close the struct. */ + if (!dbus_message_iter_close_container(&array_iter, &struct_iter)) + { + goto fail_close_unref; + } + + /* Open the struct. */ + if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) + { + goto fail_close_unref; + } + + jack_controller_jack_to_dbus_variant(type, &max, &value); + + if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value)) + { + goto fail_close2_unref; + } + + descr = "max"; + + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &descr)) + { + goto fail_close2_unref; + } + + /* Close the struct. */ + if (!dbus_message_iter_close_container(&array_iter, &struct_iter)) + { + goto fail_close_unref; + } + } + else + { + count = jackctl_parameter_get_enum_constraints_count(parameter); + + /* Append enum values to the array. */ + for (index = 0 ; index < count ; index++) + { + jackctl_value = jackctl_parameter_get_enum_constraint_value(parameter, index); + descr = jackctl_parameter_get_enum_constraint_description(parameter, index); + + jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); + + /* Open the struct. */ + if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) + { + goto fail_close_unref; + } + + if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value)) + { + goto fail_close2_unref; + } + + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &descr)) + { + goto fail_close2_unref; + } + + /* Close the struct. */ + if (!dbus_message_iter_close_container(&array_iter, &struct_iter)) + { + goto fail_close_unref; + } + } + } + + /* Close the array. */ + if (!dbus_message_iter_close_container(&iter, &array_iter)) + { + goto fail_unref; + } + + return; + +fail_close2_unref: + dbus_message_iter_close_container(&array_iter, &struct_iter); + +fail_close_unref: + dbus_message_iter_close_container(&iter, &array_iter); + +fail_unref: + dbus_message_unref(call->reply); + call->reply = NULL; + +fail: + jack_error ("Ran out of memory trying to construct method return"); +} + +static +void +jack_controller_dbus_get_driver_parameter_constraint( + struct jack_dbus_method_call * call) +{ + const char * parameter_name; + jackctl_parameter_t * parameter; + + if (controller_ptr->driver == NULL) + { + jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, "No driver selected"); + return; + } + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter_name, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + jack_controller_get_parameter_constraint(call, parameter); +} + /* * Execute GetDriverParametersInfo method call. */ @@ -649,6 +854,39 @@ jack_controller_dbus_get_engine_parameter_info( } /* + * Execute GetEngineParameterConstraint method call. + */ +static +void +jack_controller_dbus_get_engine_parameter_constraint( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + jackctl_parameter_t *parameter; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, + "Unknown engine parameter \"%s\"", + parameter); + return; + } + + jack_controller_get_parameter_constraint(call, parameter); +} + +/* * Execute GetDriverParameterValue method call. */ static @@ -856,6 +1094,53 @@ jack_controller_dbus_get_internal_parameter_info( } /* + * Execute GetInternalParameterConstraint method call. + */ +static +void +jack_controller_dbus_get_internal_parameter_constraint( + struct jack_dbus_method_call *call) +{ + const char *internal_name; + const char *parameter_name; + jackctl_parameter_t *parameter; + jackctl_internal_t * internal; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + return; + } + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_INTERNAL, + "Unknown internal \"%s\"", + internal_name); + return; + } + + parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter_name, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + jack_controller_get_parameter_constraint(call, parameter); +} + +/* * Execute GetInternalParameterValue method call. */ static void @@ -1022,6 +1307,14 @@ JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterInfo) JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) JACK_DBUS_METHOD_ARGUMENTS_END +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterConstraint) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("is_range", "b", true) + JACK_DBUS_METHOD_ARGUMENT("is_strict", "b", true) + JACK_DBUS_METHOD_ARGUMENT("is_fake_value", "b", true) + JACK_DBUS_METHOD_ARGUMENT("values", "a(vs)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterValue) JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) @@ -1043,6 +1336,14 @@ JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterInfo) JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) JACK_DBUS_METHOD_ARGUMENTS_END +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterConstraint) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("is_range", "b", true) + JACK_DBUS_METHOD_ARGUMENT("is_strict", "b", true) + JACK_DBUS_METHOD_ARGUMENT("is_fake_value", "b", true) + JACK_DBUS_METHOD_ARGUMENT("values", "a(vs)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterValue) JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) @@ -1070,6 +1371,15 @@ JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetInternalParameterInfo) JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) JACK_DBUS_METHOD_ARGUMENTS_END +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetInternalParameterConstraint) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("is_range", "b", true) + JACK_DBUS_METHOD_ARGUMENT("is_strict", "b", true) + JACK_DBUS_METHOD_ARGUMENT("is_fake_value", "b", true) + JACK_DBUS_METHOD_ARGUMENT("values", "a(vs)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetInternalParameterValue) JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) @@ -1090,15 +1400,18 @@ JACK_DBUS_METHODS_BEGIN JACK_DBUS_METHOD_DESCRIBE(SelectDriver, jack_controller_dbus_select_driver) JACK_DBUS_METHOD_DESCRIBE(GetDriverParametersInfo, jack_controller_dbus_get_driver_parameters_info) JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterInfo, jack_controller_dbus_get_driver_parameter_info) + JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterConstraint, jack_controller_dbus_get_driver_parameter_constraint) JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterValue, jack_controller_dbus_get_driver_parameter_value) JACK_DBUS_METHOD_DESCRIBE(SetDriverParameterValue, jack_controller_dbus_set_driver_parameter_value) JACK_DBUS_METHOD_DESCRIBE(GetEngineParametersInfo, jack_controller_dbus_get_engine_parameters_info) + JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterConstraint, jack_controller_dbus_get_engine_parameter_constraint) JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterInfo, jack_controller_dbus_get_engine_parameter_info) JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterValue, jack_controller_dbus_get_engine_parameter_value) JACK_DBUS_METHOD_DESCRIBE(SetEngineParameterValue, jack_controller_dbus_set_engine_parameter_value) JACK_DBUS_METHOD_DESCRIBE(GetAvailableInternals, jack_controller_dbus_get_available_internals) JACK_DBUS_METHOD_DESCRIBE(GetInternalParametersInfo, jack_controller_dbus_get_internal_parameters_info) JACK_DBUS_METHOD_DESCRIBE(GetInternalParameterInfo, jack_controller_dbus_get_internal_parameter_info) + JACK_DBUS_METHOD_DESCRIBE(GetInternalParameterConstraint, jack_controller_dbus_get_internal_parameter_constraint) JACK_DBUS_METHOD_DESCRIBE(GetInternalParameterValue, jack_controller_dbus_get_internal_parameter_value) JACK_DBUS_METHOD_DESCRIBE(SetInternalParameterValue, jack_controller_dbus_set_internal_parameter_value) JACK_DBUS_METHODS_END diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 2a615be..785cd95 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -2413,6 +2413,186 @@ extern "C" { #endif +static +void +fill_device( + jack_driver_param_constraint_desc_t ** constraint_ptr_ptr, + uint32_t * array_size_ptr, + const char * device_id, + const char * device_description) +{ + jack_driver_param_value_enum_t * possible_value_ptr; + + //jack_info("%6s - %s", device_id, device_description); + + if (*constraint_ptr_ptr == NULL) + { + *constraint_ptr_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); + *array_size_ptr = 0; + } + + if ((*constraint_ptr_ptr)->constraint.enumeration.count == *array_size_ptr) + { + *array_size_ptr += 10; + (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array = + (jack_driver_param_value_enum_t *)realloc( + (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array, + sizeof(jack_driver_param_value_enum_t) * *array_size_ptr); + } + + possible_value_ptr = (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array + (*constraint_ptr_ptr)->constraint.enumeration.count; + (*constraint_ptr_ptr)->constraint.enumeration.count++; + strcpy(possible_value_ptr->value.str, device_id); + strcpy(possible_value_ptr->short_desc, device_description); +} + +static +jack_driver_param_constraint_desc_t * +enum_alsa_devices() +{ + snd_ctl_t * handle; + snd_ctl_card_info_t * info; + snd_pcm_info_t * pcminfo_capture; + snd_pcm_info_t * pcminfo_playback; + int card_no = -1; + char card_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; + char device_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; + char description[64]; + int device_no; + bool has_capture; + bool has_playback; + jack_driver_param_constraint_desc_t * constraint_ptr; + uint32_t array_size; + + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo_capture); + snd_pcm_info_alloca(&pcminfo_playback); + + constraint_ptr = NULL; + + while(snd_card_next(&card_no) >= 0 && card_no >= 0) + { + sprintf(card_id, "hw:%d", card_no); + + if (snd_ctl_open(&handle, card_id, 0) >= 0 && + snd_ctl_card_info(handle, info) >= 0) + { + fill_device(&constraint_ptr, &array_size, card_id, snd_ctl_card_info_get_name(info)); + + device_no = -1; + + while (snd_ctl_pcm_next_device(handle, &device_no) >= 0 && device_no != -1) + { + sprintf(device_id, "%s,%d", card_id, device_no); + + snd_pcm_info_set_device(pcminfo_capture, device_no); + snd_pcm_info_set_subdevice(pcminfo_capture, 0); + snd_pcm_info_set_stream(pcminfo_capture, SND_PCM_STREAM_CAPTURE); + has_capture = snd_ctl_pcm_info(handle, pcminfo_capture) >= 0; + + snd_pcm_info_set_device(pcminfo_playback, device_no); + snd_pcm_info_set_subdevice(pcminfo_playback, 0); + snd_pcm_info_set_stream(pcminfo_playback, SND_PCM_STREAM_PLAYBACK); + has_playback = snd_ctl_pcm_info(handle, pcminfo_playback) >= 0; + + if (has_capture && has_playback) + { + snprintf(description, sizeof(description),"%s (duplex)", snd_pcm_info_get_name(pcminfo_capture)); + } + else if (has_capture) + { + snprintf(description, sizeof(description),"%s (capture)", snd_pcm_info_get_name(pcminfo_capture)); + } + else if (has_playback) + { + snprintf(description, sizeof(description),"%s (playback)", snd_pcm_info_get_name(pcminfo_playback)); + } + else + { + continue; + } + + fill_device(&constraint_ptr, &array_size, device_id, description); + } + + snd_ctl_close(handle); + } + } + + return constraint_ptr; +} + +static +jack_driver_param_constraint_desc_t * +get_midi_driver_constraint() +{ + jack_driver_param_constraint_desc_t * constraint_ptr; + jack_driver_param_value_enum_t * possible_value_ptr; + + //jack_info("%6s - %s", device_id, device_description); + + constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); + constraint_ptr->flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; + + constraint_ptr->constraint.enumeration.possible_values_array = (jack_driver_param_value_enum_t *)malloc(3 * sizeof(jack_driver_param_value_enum_t)); + constraint_ptr->constraint.enumeration.count = 3; + + possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; + + strcpy(possible_value_ptr->value.str, "none"); + strcpy(possible_value_ptr->short_desc, "no MIDI driver"); + + possible_value_ptr++; + + strcpy(possible_value_ptr->value.str, "seq"); + strcpy(possible_value_ptr->short_desc, "ALSA Sequencer driver"); + + possible_value_ptr++; + + strcpy(possible_value_ptr->value.str, "raw"); + strcpy(possible_value_ptr->short_desc, "ALSA RawMIDI driver"); + + return constraint_ptr; +} + +static +jack_driver_param_constraint_desc_t * +get_dither_constraint() +{ + jack_driver_param_constraint_desc_t * constraint_ptr; + jack_driver_param_value_enum_t * possible_value_ptr; + + //jack_info("%6s - %s", device_id, device_description); + + constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); + constraint_ptr->flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; + + constraint_ptr->constraint.enumeration.possible_values_array = (jack_driver_param_value_enum_t *)malloc(4 * sizeof(jack_driver_param_value_enum_t)); + constraint_ptr->constraint.enumeration.count = 4; + + possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; + + possible_value_ptr->value.c = 'n'; + strcpy(possible_value_ptr->short_desc, "none"); + + possible_value_ptr++; + + possible_value_ptr->value.c = 'r'; + strcpy(possible_value_ptr->short_desc, "rectangular"); + + possible_value_ptr++; + + possible_value_ptr->value.c = 's'; + strcpy(possible_value_ptr->short_desc, "shaped"); + + possible_value_ptr++; + + possible_value_ptr->value.c = 't'; + strcpy(possible_value_ptr->short_desc, "triangular"); + + return constraint_ptr; +} + static int dither_opt (char c, DitherAlgorithm* dither) { @@ -2480,6 +2660,7 @@ extern "C" strcpy (params[i].value.str, "hw:0"); strcpy (params[i].short_desc, "ALSA device name"); strcpy (params[i].long_desc, params[i].short_desc); + params[i].constraint = enum_alsa_devices(); i++; strcpy (params[i].name, "rate"); @@ -2558,6 +2739,7 @@ extern "C" " r - rectangular\n" " s - shaped\n" " t - triangular"); + params[i].constraint = get_dither_constraint(); i++; strcpy (params[i].name, "inchannels"); @@ -2612,6 +2794,7 @@ extern "C" " none - no MIDI driver\n" " seq - ALSA Sequencer driver\n" " raw - ALSA RawMIDI driver\n"); + params[i].constraint = get_midi_driver_constraint(); desc->params = params; return desc;