|
|
|
@@ -0,0 +1,148 @@ |
|
|
|
#include <fstream> |
|
|
|
#include "JackLoader.h" |
|
|
|
#include "JackLockedEngine.h" |
|
|
|
|
|
|
|
|
|
|
|
namespace Jack |
|
|
|
{ |
|
|
|
|
|
|
|
JackLoader::JackLoader(JackServer* const server) : |
|
|
|
fServer(server) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
int JackLoader::Load(const std::string file) |
|
|
|
{ |
|
|
|
std::ifstream infile(file); |
|
|
|
|
|
|
|
if (!infile.is_open()) { |
|
|
|
jack_error("JACK configuration file %s does not exist or cannot be opened for reading.", file.c_str()); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::string line; |
|
|
|
int linenr = -1; |
|
|
|
while (std::getline(infile, line)) |
|
|
|
{ |
|
|
|
linenr++; |
|
|
|
|
|
|
|
std::istringstream iss(line); |
|
|
|
|
|
|
|
std::string command; |
|
|
|
if ( !(iss >> command) ) { |
|
|
|
/* ignoring empty line or line only filled with spaces */ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
/* convert command to lower case to accept any case of the letters in the command */ |
|
|
|
std::transform(command.begin(), command.end(), command.begin(), ::tolower); |
|
|
|
|
|
|
|
if ( (command.compare("c") == 0) || (command.compare("connect") == 0) ) { |
|
|
|
ConnectPorts(iss, linenr); |
|
|
|
} else if ( (command.compare("l") == 0) || (command.compare("load") == 0) ) { |
|
|
|
LoadClient(iss, linenr); |
|
|
|
} else if (command.front() == '#') { |
|
|
|
/* ignoring commented lines. |
|
|
|
* The # can be followed by non spaces. |
|
|
|
* Therefore only compare the first letter of the command. |
|
|
|
*/ |
|
|
|
} else { |
|
|
|
jack_error("JACK configuration file %s line %u contains unkown command '%s'. Ignoring the line!", file.c_str(), linenr, line.c_str()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void JackLoader::LoadClient(std::istringstream& iss, const int linenr) |
|
|
|
{ |
|
|
|
std::string client_name; |
|
|
|
if ( !(iss >> client_name) ) { |
|
|
|
jack_error("Cannot read client name from configuration file line %u '%s'. Ignoring the line!", linenr, iss.str().c_str()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
std::string lib_name; |
|
|
|
if ( !(iss >> lib_name) ) { |
|
|
|
jack_error("Cannot read client library name from configuration file line %u '%s'. Ignoring the line!", linenr, iss.str().c_str()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* get the rest of the line */ |
|
|
|
std::string parameters; |
|
|
|
if ( std::getline(iss, parameters) ) { |
|
|
|
/* remove the leading spaces */ |
|
|
|
const std::size_t start = parameters.find_first_not_of(" \t"); |
|
|
|
if (start == std::string::npos) { |
|
|
|
/* Parameters containing only spaces. |
|
|
|
* Use empty parameter string. |
|
|
|
*/ |
|
|
|
parameters = ""; |
|
|
|
} else { |
|
|
|
parameters = parameters.substr(start); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* jackctl_server_load_internal() can not be used |
|
|
|
* because it calls jack_internal_initialize() |
|
|
|
* instead of jack_initialize() |
|
|
|
*/ |
|
|
|
int status = 0; |
|
|
|
int refnum = 0; |
|
|
|
if (fServer->InternalClientLoad1(client_name.c_str(), lib_name.c_str(), parameters.c_str(), (JackLoadName|JackUseExactName|JackLoadInit), &refnum, -1, &status) < 0) { |
|
|
|
/* Due to the JackUseExactName option JackNameNotUnique will always handled as a failure. |
|
|
|
* See JackEngine::ClientCheck(). |
|
|
|
*/ |
|
|
|
if (status & JackNameNotUnique) { |
|
|
|
jack_error("Internal client name `%s' not unique", client_name.c_str()); |
|
|
|
} |
|
|
|
/* An error message for JackVersionError will already |
|
|
|
* be printed by JackInternalClient::Open(). |
|
|
|
* Therefore no need to handle it here. |
|
|
|
*/ |
|
|
|
|
|
|
|
jack_error("Cannot load client %s from configuration file line %u. Ignoring the line!", client_name.c_str(), linenr); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* status has not to be checked for JackFailure |
|
|
|
* because JackServer::InternalClientLoad1() will return a value < 0 |
|
|
|
* and this is handled by the previouse if-clause. |
|
|
|
*/ |
|
|
|
|
|
|
|
jack_info("Internal client %s successfully loaded", client_name.c_str()); |
|
|
|
} |
|
|
|
|
|
|
|
void JackLoader::ConnectPorts(std::istringstream& iss, const int linenr) |
|
|
|
{ |
|
|
|
std::string src_port; |
|
|
|
if ( !(iss >> src_port) ) { |
|
|
|
jack_error("Cannot read first port from configuration file line %u '%s'. Ignoring the line!", linenr, iss.str().c_str()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
std::string dst_port; |
|
|
|
if ( !(iss >> dst_port) ) { |
|
|
|
jack_error("Cannot read second port from configuration file line %u '%s'. Ignoring the line!", linenr, iss.str().c_str()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* use the client reference of the source port */ |
|
|
|
const jack_port_id_t src_port_index = fServer->GetGraphManager()->GetPort(src_port.c_str()); |
|
|
|
if (src_port_index >= NO_PORT) { |
|
|
|
jack_error("Source port %s does not exist! Ignoring configuration file line %u '%s'.", src_port.c_str(), linenr, iss.str().c_str()); |
|
|
|
return; |
|
|
|
} |
|
|
|
const int src_refnum = fServer->GetGraphManager()->GetOutputRefNum(src_port_index); |
|
|
|
|
|
|
|
if (fServer->GetEngine()->PortConnect(src_refnum, src_port.c_str(), dst_port.c_str()) < 0) { |
|
|
|
jack_error("Cannot connect ports of configuration file line %u '%s'.Possibly the destination port does not exist. Ignoring the line!", linenr, iss.str().c_str()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
jack_info("Ports connected: %s -> %s", src_port.c_str(), dst_port.c_str()); |
|
|
|
} |
|
|
|
|
|
|
|
} |