summaryrefslogtreecommitdiff
path: root/common/JackInternalSessionLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/JackInternalSessionLoader.cpp')
-rw-r--r--common/JackInternalSessionLoader.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/common/JackInternalSessionLoader.cpp b/common/JackInternalSessionLoader.cpp
new file mode 100644
index 00000000..5a438e72
--- /dev/null
+++ b/common/JackInternalSessionLoader.cpp
@@ -0,0 +1,176 @@
+/*
+Copyright (C) 2017 Timo Wischer
+
+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
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <fstream>
+#include "JackInternalSessionLoader.h"
+#include "JackLockedEngine.h"
+
+
+namespace Jack
+{
+
+JackInternalSessionLoader::JackInternalSessionLoader(JackServer* const server) :
+ fServer(server)
+{
+}
+
+int JackInternalSessionLoader::Load(const char* file)
+{
+ std::ifstream infile(file);
+
+ if (!infile.is_open()) {
+ jack_error("JACK internal session file %s does not exist or cannot be opened for reading.", file);
+ 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("con") == 0) ) {
+ ConnectPorts(iss, linenr);
+ } else if ( (command.compare("l") == 0) || (command.compare("load") == 0) ) {
+ LoadClient(iss, linenr);
+#if 0
+ /* NOTE: c++11 only */
+ } else if (command.front() == '#') {
+#else
+ } else if (command[0] == '#') {
+#endif
+ /* ignoring commented lines.
+ * The # can be followed by non spaces.
+ * Therefore only compare the first letter of the command.
+ */
+ } else {
+ jack_error("JACK internal session file %s line %u contains unkown command '%s'. Ignoring the line!", file, linenr, line.c_str());
+ }
+ }
+
+ return 0;
+}
+
+void JackInternalSessionLoader::LoadClient(std::istringstream& iss, const int linenr)
+{
+ std::string client_name;
+ if ( !(iss >> client_name) ) {
+ jack_error("Cannot read client name from internal session 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 internal session 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 internal session 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 JackInternalSessionLoader::ConnectPorts(std::istringstream& iss, const int linenr)
+{
+ std::string src_port;
+ if ( !(iss >> src_port) ) {
+ jack_error("Cannot read first port from internal session 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 internal session 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 internal session 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 internal session file line %u '%s'.\n"
+ "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());
+}
+
+}