| @@ -82,4 +82,6 @@ | |||||
| #define EMPTY 0xFFFD | #define EMPTY 0xFFFD | ||||
| #define FREE 0xFFFC | #define FREE 0xFFFC | ||||
| #define JACK_DEFAULT_SELF_CONNECT_MODE JackSelfConnectIgnoreAll | |||||
| #endif | #endif | ||||
| @@ -47,6 +47,13 @@ | |||||
| using namespace Jack; | using namespace Jack; | ||||
| #define SELF_CONNECT_MODE_ALLOW_CHAR ' ' | |||||
| #define SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR 'E' | |||||
| #define SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR 'e' | |||||
| #define SELF_CONNECT_MODE_FAIL_ALL_CHAR 'A' | |||||
| #define SELF_CONNECT_MODE_IGNORE_ALL_CHAR 'a' | |||||
| #define SELF_CONNECT_MODES_COUNT 5 | |||||
| struct jackctl_server | struct jackctl_server | ||||
| { | { | ||||
| JSList * drivers; | JSList * drivers; | ||||
| @@ -94,6 +101,12 @@ struct jackctl_server | |||||
| /* bool, synchronous or asynchronous engine mode */ | /* bool, synchronous or asynchronous engine mode */ | ||||
| union jackctl_parameter_value sync; | union jackctl_parameter_value sync; | ||||
| union jackctl_parameter_value default_sync; | union jackctl_parameter_value default_sync; | ||||
| /* char enum, self connect mode mode */ | |||||
| union jackctl_parameter_value self_connect_mode; | |||||
| union jackctl_parameter_value default_self_connect_mode; | |||||
| jack_driver_param_value_enum_t self_connect_mode_possible_values[SELF_CONNECT_MODES_COUNT]; | |||||
| jack_driver_param_constraint_desc_t self_connect_mode_constraint; | |||||
| }; | }; | ||||
| struct jackctl_driver | struct jackctl_driver | ||||
| @@ -869,6 +882,40 @@ SERVER_EXPORT jackctl_server_t * jackctl_server_create( | |||||
| goto fail_free_parameters; | goto fail_free_parameters; | ||||
| } | } | ||||
| server_ptr->self_connect_mode_constraint.flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; | |||||
| server_ptr->self_connect_mode_constraint.constraint.enumeration.count = SELF_CONNECT_MODES_COUNT; | |||||
| server_ptr->self_connect_mode_constraint.constraint.enumeration.possible_values_array = server_ptr->self_connect_mode_possible_values; | |||||
| server_ptr->self_connect_mode_possible_values[0].value.c = SELF_CONNECT_MODE_ALLOW_CHAR; | |||||
| strcpy(server_ptr->self_connect_mode_possible_values[0].short_desc, "Don't restrict self connect requests"); | |||||
| server_ptr->self_connect_mode_possible_values[1].value.c = SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR ; | |||||
| strcpy(server_ptr->self_connect_mode_possible_values[1].short_desc, "Fail self connect requests to external ports only"); | |||||
| server_ptr->self_connect_mode_possible_values[2].value.c = SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR; | |||||
| strcpy(server_ptr->self_connect_mode_possible_values[2].short_desc, "Ignore self connect requests to external ports only"); | |||||
| server_ptr->self_connect_mode_possible_values[3].value.c = SELF_CONNECT_MODE_FAIL_ALL_CHAR; | |||||
| strcpy(server_ptr->self_connect_mode_possible_values[3].short_desc, "Fail all self connect requests"); | |||||
| server_ptr->self_connect_mode_possible_values[4].value.c = SELF_CONNECT_MODE_IGNORE_ALL_CHAR; | |||||
| strcpy(server_ptr->self_connect_mode_possible_values[4].short_desc, "Ignore all self connect requests"); | |||||
| value.c = SELF_CONNECT_MODE_ALLOW_CHAR; | |||||
| if (jackctl_add_parameter( | |||||
| &server_ptr->parameters, | |||||
| "self-connect-mode", | |||||
| "Self connect mode.", | |||||
| "Whether JACK clients are allowed to connect their own ports", | |||||
| JackParamChar, | |||||
| &server_ptr->self_connect_mode, | |||||
| &server_ptr->default_self_connect_mode, | |||||
| value, | |||||
| &server_ptr->self_connect_mode_constraint) == NULL) | |||||
| { | |||||
| goto fail_free_parameters; | |||||
| } | |||||
| JackServerGlobals::on_device_acquire = on_device_acquire; | JackServerGlobals::on_device_acquire = on_device_acquire; | ||||
| JackServerGlobals::on_device_release = on_device_release; | JackServerGlobals::on_device_release = on_device_release; | ||||
| @@ -953,6 +1000,7 @@ jackctl_server_open( | |||||
| jackctl_server *server_ptr, | jackctl_server *server_ptr, | ||||
| jackctl_driver *driver_ptr) | jackctl_driver *driver_ptr) | ||||
| { | { | ||||
| JackSelfConnectMode self_connect_mode; | |||||
| JSList * paramlist = NULL; | JSList * paramlist = NULL; | ||||
| try { | try { | ||||
| @@ -986,6 +1034,27 @@ jackctl_server_open( | |||||
| server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | ||||
| } | } | ||||
| switch (server_ptr->self_connect_mode.c) | |||||
| { | |||||
| case SELF_CONNECT_MODE_ALLOW_CHAR: | |||||
| self_connect_mode = JackSelfConnectAllow; | |||||
| break; | |||||
| case SELF_CONNECT_MODE_FAIL_EXTERNAL_ONLY_CHAR: | |||||
| self_connect_mode = JackSelfConnectFailExternalOnly; | |||||
| break; | |||||
| case SELF_CONNECT_MODE_IGNORE_EXTERNAL_ONLY_CHAR: | |||||
| self_connect_mode = JackSelfConnectIgnoreExternalOnly; | |||||
| break; | |||||
| case SELF_CONNECT_MODE_FAIL_ALL_CHAR: | |||||
| self_connect_mode = JackSelfConnectFailAll; | |||||
| break; | |||||
| case SELF_CONNECT_MODE_IGNORE_ALL_CHAR: | |||||
| self_connect_mode = JackSelfConnectIgnoreAll; | |||||
| break; | |||||
| default: | |||||
| self_connect_mode = JACK_DEFAULT_SELF_CONNECT_MODE; | |||||
| } | |||||
| /* check port max value before allocating server */ | /* check port max value before allocating server */ | ||||
| if (server_ptr->port_max.ui > PORT_NUM_MAX) { | if (server_ptr->port_max.ui > PORT_NUM_MAX) { | ||||
| jack_error("Jack server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | jack_error("Jack server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | ||||
| @@ -1002,6 +1071,7 @@ jackctl_server_open( | |||||
| server_ptr->port_max.ui, | server_ptr->port_max.ui, | ||||
| server_ptr->verbose.b, | server_ptr->verbose.b, | ||||
| (jack_timer_type_t)server_ptr->clock_source.ui, | (jack_timer_type_t)server_ptr->clock_source.ui, | ||||
| self_connect_mode, | |||||
| server_ptr->name.str); | server_ptr->name.str); | ||||
| if (server_ptr->engine == NULL) | if (server_ptr->engine == NULL) | ||||
| { | { | ||||
| @@ -38,13 +38,15 @@ namespace Jack | |||||
| JackEngine::JackEngine(JackGraphManager* manager, | JackEngine::JackEngine(JackGraphManager* manager, | ||||
| JackSynchro* table, | JackSynchro* table, | ||||
| JackEngineControl* control) | |||||
| JackEngineControl* control, | |||||
| JackSelfConnectMode self_connect_mode) | |||||
| : JackLockAble(control->fServerName), | : JackLockAble(control->fServerName), | ||||
| fSignal(control->fServerName) | fSignal(control->fServerName) | ||||
| { | { | ||||
| fGraphManager = manager; | fGraphManager = manager; | ||||
| fSynchroTable = table; | fSynchroTable = table; | ||||
| fEngineControl = control; | fEngineControl = control; | ||||
| fSelfConnectMode = self_connect_mode; | |||||
| for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
| fClientTable[i] = NULL; | fClientTable[i] = NULL; | ||||
| } | } | ||||
| @@ -803,10 +805,10 @@ int JackEngine::ClientDeactivate(int refnum) | |||||
| // First disconnect all ports | // First disconnect all ports | ||||
| for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { | for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { | ||||
| PortDisconnect(refnum, input_ports[i], ALL_PORTS); | |||||
| PortDisconnect(-1, input_ports[i], ALL_PORTS); | |||||
| } | } | ||||
| for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { | for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { | ||||
| PortDisconnect(refnum, output_ports[i], ALL_PORTS); | |||||
| PortDisconnect(-1, output_ports[i], ALL_PORTS); | |||||
| } | } | ||||
| // Then issue port registration notification | // Then issue port registration notification | ||||
| @@ -874,7 +876,7 @@ int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) | |||||
| assert(client); | assert(client); | ||||
| // Disconnect port ==> notification is sent | // Disconnect port ==> notification is sent | ||||
| PortDisconnect(refnum, port_index, ALL_PORTS); | |||||
| PortDisconnect(-1, port_index, ALL_PORTS); | |||||
| if (fGraphManager->ReleasePort(refnum, port_index) == 0) { | if (fGraphManager->ReleasePort(refnum, port_index) == 0) { | ||||
| if (client->GetClientControl()->fActive) { | if (client->GetClientControl()->fActive) { | ||||
| @@ -886,6 +888,72 @@ int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) | |||||
| } | } | ||||
| } | } | ||||
| // this check is to prevent apps to self connect to other apps | |||||
| // TODO: make this work with multiple clients per app | |||||
| int JackEngine::CheckPortsConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) | |||||
| { | |||||
| JackPort* src_port = fGraphManager->GetPort(src); | |||||
| JackPort* dst_port = fGraphManager->GetPort(dst); | |||||
| jack_log("CheckPortsConnect(caller = %d, src = %d, dst = %d)", refnum, src_port->GetRefNum(), dst_port->GetRefNum()); | |||||
| int src_self = src_port->GetRefNum() == refnum ? 1 : 0; | |||||
| int dst_self = dst_port->GetRefNum() == refnum ? 1 : 0; | |||||
| jack_log("src_self is %s", src_self ? "true" : "false"); | |||||
| jack_log("dst_self is %s", dst_self ? "true" : "false"); | |||||
| // 0 means client is connecting other client ports (i.e. control app patchbay functionality) | |||||
| // 1 means client is connecting its own port to port of other client (i.e. self hooking into system app) | |||||
| // 2 means client is connecting its own ports (i.e. for app internal functionality) | |||||
| // TODO: Make this check an engine option and more tweakable (return error or success) | |||||
| // MAYBE: make the engine option changable on the fly and expose it through client or control API | |||||
| switch (fSelfConnectMode) | |||||
| { | |||||
| case JackSelfConnectFailExternalOnly: | |||||
| if (src_self + dst_self == 1) | |||||
| { | |||||
| jack_info("rejecting port self connect request to external port (%s -> %s)", src_port->GetName(), dst_port->GetName()); | |||||
| return -1; | |||||
| } | |||||
| return 1; | |||||
| case JackSelfConnectIgnoreExternalOnly: | |||||
| if (src_self + dst_self == 1) | |||||
| { | |||||
| jack_info("ignoring port self connect request to external port (%s -> %s)", src_port->GetName(), dst_port->GetName()); | |||||
| return 0; | |||||
| } | |||||
| return 1; | |||||
| case JackSelfConnectFailAll: | |||||
| if (src_self + dst_self != 0) | |||||
| { | |||||
| jack_info("rejecting port self connect request (%s -> %s)", src_port->GetName(), dst_port->GetName()); | |||||
| return -1; | |||||
| } | |||||
| return 1; | |||||
| case JackSelfConnectIgnoreAll: | |||||
| if (src_self + dst_self != 0) | |||||
| { | |||||
| jack_info("ignoring port self connect request (%s -> %s)", src_port->GetName(), dst_port->GetName()); | |||||
| return 0; | |||||
| } | |||||
| return 1; | |||||
| case JackSelfConnectAllow: // fix warning | |||||
| return 1; | |||||
| } | |||||
| return 1; | |||||
| } | |||||
| int JackEngine::PortConnect(int refnum, const char* src, const char* dst) | int JackEngine::PortConnect(int refnum, const char* src, const char* dst) | ||||
| { | { | ||||
| jack_log("JackEngine::PortConnect src = %s dst = %s", src, dst); | jack_log("JackEngine::PortConnect src = %s dst = %s", src, dst); | ||||
| @@ -926,7 +994,12 @@ int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| int res = fGraphManager->Connect(src, dst); | |||||
| int res = CheckPortsConnect(refnum, src, dst); | |||||
| if (res != 1) { | |||||
| return res; | |||||
| } | |||||
| res = fGraphManager->Connect(src, dst); | |||||
| if (res == 0) { | if (res == 0) { | ||||
| NotifyPortConnect(src, dst, true); | NotifyPortConnect(src, dst, true); | ||||
| } | } | ||||
| @@ -969,15 +1042,21 @@ int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t ds | |||||
| } | } | ||||
| return res; | return res; | ||||
| } else if (fGraphManager->CheckPorts(src, dst) < 0) { | |||||
| return -1; | |||||
| } else if (fGraphManager->Disconnect(src, dst) == 0) { | |||||
| // Notifications | |||||
| NotifyPortConnect(src, dst, false); | |||||
| return 0; | |||||
| } else { | |||||
| } | |||||
| if (fGraphManager->CheckPorts(src, dst) < 0) { | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| int res = CheckPortsConnect(refnum, src, dst); | |||||
| if (res != 1) { | |||||
| return res; | |||||
| } | |||||
| res = fGraphManager->Disconnect(src, dst); | |||||
| if (res == 0) | |||||
| NotifyPortConnect(src, dst, false); | |||||
| return res; | |||||
| } | } | ||||
| int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | ||||
| @@ -49,6 +49,7 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
| JackGraphManager* fGraphManager; | JackGraphManager* fGraphManager; | ||||
| JackEngineControl* fEngineControl; | JackEngineControl* fEngineControl; | ||||
| JackSelfConnectMode fSelfConnectMode; | |||||
| JackClientInterface* fClientTable[CLIENT_NUM]; | JackClientInterface* fClientTable[CLIENT_NUM]; | ||||
| JackSynchro* fSynchroTable; | JackSynchro* fSynchroTable; | ||||
| JackServerNotifyChannel fChannel; /*! To communicate between the RT thread and server */ | JackServerNotifyChannel fChannel; /*! To communicate between the RT thread and server */ | ||||
| @@ -94,9 +95,11 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
| return (refnum >= 0 && refnum < CLIENT_NUM && fClientTable[refnum] != NULL); | return (refnum >= 0 && refnum < CLIENT_NUM && fClientTable[refnum] != NULL); | ||||
| } | } | ||||
| int CheckPortsConnect(int refnum, jack_port_id_t src, jack_port_id_t dst); | |||||
| public: | public: | ||||
| JackEngine(JackGraphManager* manager, JackSynchro* table, JackEngineControl* controler); | |||||
| JackEngine(JackGraphManager* manager, JackSynchro* table, JackEngineControl* controler, JackSelfConnectMode self_connect_mode); | |||||
| ~JackEngine(); | ~JackEngine(); | ||||
| int Open(); | int Open(); | ||||
| @@ -83,8 +83,8 @@ class SERVER_EXPORT JackLockedEngine | |||||
| public: | public: | ||||
| JackLockedEngine(JackGraphManager* manager, JackSynchro* table, JackEngineControl* controler): | |||||
| fEngine(manager, table, controler) | |||||
| JackLockedEngine(JackGraphManager* manager, JackSynchro* table, JackEngineControl* controler, JackSelfConnectMode self_connect_mode): | |||||
| fEngine(manager, table, controler, self_connect_mode) | |||||
| {} | {} | ||||
| ~JackLockedEngine() | ~JackLockedEngine() | ||||
| {} | {} | ||||
| @@ -40,8 +40,7 @@ namespace Jack | |||||
| //---------------- | //---------------- | ||||
| // Server control | // Server control | ||||
| //---------------- | //---------------- | ||||
| JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, const char* server_name) | |||||
| JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, JackSelfConnectMode self_connect_mode, const char* server_name) | |||||
| { | { | ||||
| if (rt) { | if (rt) { | ||||
| jack_info("JACK server starting in realtime mode with priority %ld", priority); | jack_info("JACK server starting in realtime mode with priority %ld", priority); | ||||
| @@ -51,7 +50,7 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio | |||||
| fGraphManager = JackGraphManager::Allocate(port_max); | fGraphManager = JackGraphManager::Allocate(port_max); | ||||
| fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); | fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); | ||||
| fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); | |||||
| fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl, self_connect_mode); | |||||
| // A distinction is made between the threaded freewheel driver and the | // A distinction is made between the threaded freewheel driver and the | ||||
| // regular freewheel driver because the freewheel driver needs to run in | // regular freewheel driver because the freewheel driver needs to run in | ||||
| @@ -64,7 +64,7 @@ class SERVER_EXPORT JackServer | |||||
| public: | public: | ||||
| JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, const char* server_name); | |||||
| JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, JackSelfConnectMode self_connect_mode, const char* server_name); | |||||
| ~JackServer(); | ~JackServer(); | ||||
| // Server control | // Server control | ||||
| @@ -47,10 +47,11 @@ int JackServerGlobals::Start(const char* server_name, | |||||
| int priority, | int priority, | ||||
| int port_max, | int port_max, | ||||
| int verbose, | int verbose, | ||||
| jack_timer_type_t clock) | |||||
| jack_timer_type_t clock, | |||||
| JackSelfConnectMode self_connect_mode) | |||||
| { | { | ||||
| jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose); | jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose); | ||||
| new JackServer(sync, temporary, time_out_ms, rt, priority, port_max, verbose, clock, server_name); // Will setup fInstance and fUserCount globals | |||||
| new JackServer(sync, temporary, time_out_ms, rt, priority, port_max, verbose, clock, self_connect_mode, server_name); // Will setup fInstance and fUserCount globals | |||||
| int res = fInstance->Open(driver_desc, driver_params); | int res = fInstance->Open(driver_desc, driver_params); | ||||
| return (res < 0) ? res : fInstance->Start(); | return (res < 0) ? res : fInstance->Start(); | ||||
| } | } | ||||
| @@ -336,7 +337,7 @@ bool JackServerGlobals::Init() | |||||
| free(argv[i]); | free(argv[i]); | ||||
| } | } | ||||
| int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source); | |||||
| int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source, JACK_DEFAULT_SELF_CONNECT_MODE); | |||||
| if (res < 0) { | if (res < 0) { | ||||
| jack_error("Cannot start server... exit"); | jack_error("Cannot start server... exit"); | ||||
| Delete(); | Delete(); | ||||
| @@ -60,7 +60,8 @@ struct SERVER_EXPORT JackServerGlobals | |||||
| int priority, | int priority, | ||||
| int port_max, | int port_max, | ||||
| int verbose, | int verbose, | ||||
| jack_timer_type_t clock); | |||||
| jack_timer_type_t clock, | |||||
| JackSelfConnectMode self_connect_mode); | |||||
| static void Stop(); | static void Stop(); | ||||
| static void Delete(); | static void Delete(); | ||||
| }; | }; | ||||
| @@ -50,4 +50,14 @@ typedef enum { | |||||
| Finished, | Finished, | ||||
| } jack_client_state_t; | } jack_client_state_t; | ||||
| enum JackSelfConnectMode | |||||
| { | |||||
| JackSelfConnectAllow, | |||||
| JackSelfConnectFailExternalOnly, | |||||
| JackSelfConnectIgnoreExternalOnly, | |||||
| JackSelfConnectFailAll, | |||||
| JackSelfConnectIgnoreAll, | |||||
| }; | |||||
| #endif | #endif | ||||
| @@ -203,8 +203,8 @@ int main(int argc, char** argv) | |||||
| jackctl_driver_t * master_driver_ctl; | jackctl_driver_t * master_driver_ctl; | ||||
| jackctl_driver_t * loopback_driver_ctl = NULL; | jackctl_driver_t * loopback_driver_ctl = NULL; | ||||
| int replace_registry = 0; | int replace_registry = 0; | ||||
| const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:" | const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:" | ||||
| "a:" | |||||
| #ifdef __linux__ | #ifdef __linux__ | ||||
| "c:" | "c:" | ||||
| #endif | #endif | ||||
| @@ -234,6 +234,7 @@ int main(int argc, char** argv) | |||||
| { "version", 0, 0, 'V' }, | { "version", 0, 0, 'V' }, | ||||
| { "silent", 0, 0, 's' }, | { "silent", 0, 0, 's' }, | ||||
| { "sync", 0, 0, 'S' }, | { "sync", 0, 0, 'S' }, | ||||
| { "autoconnect", 1, 0, 'a' }, | |||||
| { 0, 0, 0, 0 } | { 0, 0, 0, 0 } | ||||
| }; | }; | ||||
| @@ -296,6 +297,26 @@ int main(int argc, char** argv) | |||||
| break; | break; | ||||
| #endif | #endif | ||||
| case 'a': | |||||
| param = jackctl_get_parameter(server_parameters, "self-connect-mode"); | |||||
| if (param != NULL) { | |||||
| bool value_valid = false; | |||||
| for (uint32_t k=0; k<jackctl_parameter_get_enum_constraints_count( param ); k++ ) { | |||||
| value = jackctl_parameter_get_enum_constraint_value( param, k ); | |||||
| if( value.c == optarg[0] ) | |||||
| value_valid = true; | |||||
| } | |||||
| if( value_valid ) { | |||||
| value.c = optarg[0]; | |||||
| jackctl_parameter_set_value(param, &value); | |||||
| } else { | |||||
| usage(stdout); | |||||
| goto destroy_server; | |||||
| } | |||||
| } | |||||
| break; | |||||
| case 'd': | case 'd': | ||||
| master_driver_name = optarg; | master_driver_name = optarg; | ||||
| break; | break; | ||||