Browse Source

Load internal JACK clients and port connections from configuration list file

Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
pull/276/head
Timo Wischer 8 years ago
parent
commit
8facc4a559
9 changed files with 220 additions and 1 deletions
  1. +11
    -0
      common/JackControlAPI.cpp
  2. +4
    -0
      common/JackControlAPI.h
  3. +148
    -0
      common/JackLoader.cpp
  4. +27
    -0
      common/JackLoader.h
  5. +7
    -0
      common/JackServer.cpp
  6. +1
    -0
      common/JackServer.h
  7. +5
    -0
      common/Jackdmp.cpp
  8. +15
    -0
      common/jack/control.h
  9. +2
    -1
      common/wscript

+ 11
- 0
common/JackControlAPI.cpp View File

@@ -1347,6 +1347,17 @@ SERVER_EXPORT bool jackctl_server_load_internal(
}
}

SERVER_EXPORT bool jackctl_server_load_conf_file(
jackctl_server * const server_ptr,
const char* const file)
{
if (!server_ptr || !file || !server_ptr->engine) {
return false;
}

return (server_ptr->engine->InternalLoadFromConfFile(file) >= 0);
}

SERVER_EXPORT bool jackctl_server_unload_internal(
jackctl_server * server_ptr,
jackctl_internal * internal)


+ 4
- 0
common/JackControlAPI.h View File

@@ -232,6 +232,10 @@ SERVER_EXPORT bool jackctl_server_load_internal(
jackctl_server * server,
jackctl_internal * internal);

SERVER_EXPORT bool jackctl_server_load_conf_file(
jackctl_server * const server_ptr,
const char* const file);

SERVER_EXPORT bool jackctl_server_unload_internal(
jackctl_server * server,
jackctl_internal * internal);


+ 148
- 0
common/JackLoader.cpp View File

@@ -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());
}

}

+ 27
- 0
common/JackLoader.h View File

@@ -0,0 +1,27 @@
#ifndef JACKLOADER_H
#define JACKLOADER_H

#include <string>
#include <sstream>
#include "JackServer.h"


namespace Jack
{

class JackLoader
{
public:
JackLoader(JackServer* const server);
int Load(const std::string file);

private:
void LoadClient(std::istringstream& iss, const int linenr);
void ConnectPorts(std::istringstream& iss, const int linenr);

JackServer* const fServer;
};

} // end of namespace

#endif // JACKLOADER_H

+ 7
- 0
common/JackServer.cpp View File

@@ -33,6 +33,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackInternalClient.h"
#include "JackError.h"
#include "JackMessageBuffer.h"
#include "JackLoader.h"

const char * jack_get_self_connect_mode_description(char mode);

@@ -225,6 +226,12 @@ int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const
}
}

int JackServer::InternalLoadFromConfFile(const char* const file)
{
JackLoader loader(this);
return loader.Load(file);
}

//---------------------------
// From request thread : API
//---------------------------


+ 1
- 0
common/JackServer.h View File

@@ -86,6 +86,7 @@ class SERVER_EXPORT JackServer
// Internals clients
int InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status);
int InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status);
int InternalLoadFromConfFile(const char* const file);
// Transport management
int ReleaseTimebase(int refnum);


+ 5
- 0
common/Jackdmp.cpp View File

@@ -606,6 +606,11 @@ int main(int argc, char** argv)
}
}

if (!jackctl_server_load_conf_file(server_ctl, "/etc/jackd.conf")) {
fprintf(stderr, "Configuration file %s can not be loaded\n", "TODO");
goto stop_server;
}

notify_server_start(server_name);
notify_sent = true;
return_value = 0;


+ 15
- 0
common/jack/control.h View File

@@ -242,6 +242,21 @@ jackctl_server_load_internal(
jackctl_server_t * server,
jackctl_internal_t * internal);

/**
* Call this function to load one internal client.
* (can be used when the server is running)
*
* @param server server object handle
* @param file the configuration file
* which contains the clients and connections
* which should be loaded
*
* @return success status: true - success, false - fail
*/
bool jackctl_server_load_conf_file(
jackctl_server * const server_ptr,
const char* const file);

/**
* Call this function to unload one internal client.
* (can be used when the server is running)


+ 2
- 1
common/wscript View File

@@ -244,7 +244,8 @@ def build(bld):
'JackMidiReceiveQueue.cpp',
'JackMidiSendQueue.cpp',
'JackMidiUtil.cpp',
'JackMidiWriteQueue.cpp'
'JackMidiWriteQueue.cpp',
'JackLoader.cpp'
]

if bld.env['IS_LINUX']:


Loading…
Cancel
Save