Jack2  1.9.12
JackInternalSessionLoader.cpp
1 /*
2 Copyright (C) 2017 Timo Wischer
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13 
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 
18 */
19 
20 #include <fstream>
21 #include "JackInternalSessionLoader.h"
22 #include "JackLockedEngine.h"
23 
24 
25 namespace Jack
26 {
27 
28 JackInternalSessionLoader::JackInternalSessionLoader(JackServer* const server) :
29  fServer(server)
30 {
31 }
32 
33 int JackInternalSessionLoader::Load(const char* file)
34 {
35  std::ifstream infile(file);
36 
37  if (!infile.is_open()) {
38  jack_error("JACK internal session file %s does not exist or cannot be opened for reading.", file);
39  return -1;
40  }
41 
42  std::string line;
43  int linenr = -1;
44  while (std::getline(infile, line))
45  {
46  linenr++;
47 
48  std::istringstream iss(line);
49 
50  std::string command;
51  if ( !(iss >> command) ) {
52  /* ignoring empty line or line only filled with spaces */
53  continue;
54  }
55 
56  /* convert command to lower case to accept any case of the letters in the command */
57  std::transform(command.begin(), command.end(), command.begin(), ::tolower);
58 
59  if ( (command.compare("c") == 0) || (command.compare("con") == 0) ) {
60  ConnectPorts(iss, linenr);
61  } else if ( (command.compare("l") == 0) || (command.compare("load") == 0) ) {
62  LoadClient(iss, linenr);
63 #if 0
64  /* NOTE: c++11 only */
65  } else if (command.front() == '#') {
66 #else
67  } else if (command[0] == '#') {
68 #endif
69  /* ignoring commented lines.
70  * The # can be followed by non spaces.
71  * Therefore only compare the first letter of the command.
72  */
73  } else {
74  jack_error("JACK internal session file %s line %u contains unkown command '%s'. Ignoring the line!", file, linenr, line.c_str());
75  }
76  }
77 
78  return 0;
79 }
80 
81 void JackInternalSessionLoader::LoadClient(std::istringstream& iss, const int linenr)
82 {
83  std::string client_name;
84  if ( !(iss >> client_name) ) {
85  jack_error("Cannot read client name from internal session file line %u '%s'. Ignoring the line!", linenr, iss.str().c_str());
86  return;
87  }
88 
89  std::string lib_name;
90  if ( !(iss >> lib_name) ) {
91  jack_error("Cannot read client library name from internal session file line %u '%s'. Ignoring the line!", linenr, iss.str().c_str());
92  return;
93  }
94 
95  /* get the rest of the line */
96  std::string parameters;
97  if ( std::getline(iss, parameters) ) {
98  /* remove the leading spaces */
99  const std::size_t start = parameters.find_first_not_of(" \t");
100  if (start == std::string::npos) {
101  /* Parameters containing only spaces.
102  * Use empty parameter string.
103  */
104  parameters = "";
105  } else {
106  parameters = parameters.substr(start);
107  }
108  }
109 
110 
111  /* jackctl_server_load_internal() can not be used
112  * because it calls jack_internal_initialize()
113  * instead of jack_initialize()
114  */
115  int status = 0;
116  int refnum = 0;
117  if (fServer->InternalClientLoad1(client_name.c_str(), lib_name.c_str(), parameters.c_str(), (JackLoadName|JackUseExactName|JackLoadInit), &refnum, -1, &status) < 0) {
118  /* Due to the JackUseExactName option JackNameNotUnique will always handled as a failure.
119  * See JackEngine::ClientCheck().
120  */
121  if (status & JackNameNotUnique) {
122  jack_error("Internal client name `%s' not unique", client_name.c_str());
123  }
124  /* An error message for JackVersionError will already
125  * be printed by JackInternalClient::Open().
126  * Therefore no need to handle it here.
127  */
128 
129  jack_error("Cannot load client %s from internal session file line %u. Ignoring the line!", client_name.c_str(), linenr);
130  return;
131  }
132 
133  /* status has not to be checked for JackFailure
134  * because JackServer::InternalClientLoad1() will return a value < 0
135  * and this is handled by the previouse if-clause.
136  */
137 
138  jack_info("Internal client %s successfully loaded", client_name.c_str());
139 }
140 
141 void JackInternalSessionLoader::ConnectPorts(std::istringstream& iss, const int linenr)
142 {
143  std::string src_port;
144  if ( !(iss >> src_port) ) {
145  jack_error("Cannot read first port from internal session file line %u '%s'. Ignoring the line!",
146  linenr, iss.str().c_str());
147  return;
148  }
149 
150  std::string dst_port;
151  if ( !(iss >> dst_port) ) {
152  jack_error("Cannot read second port from internal session file line %u '%s'. Ignoring the line!",
153  linenr, iss.str().c_str());
154  return;
155  }
156 
157  /* use the client reference of the source port */
158  const jack_port_id_t src_port_index = fServer->GetGraphManager()->GetPort(src_port.c_str());
159  if (src_port_index >= NO_PORT) {
160  jack_error("Source port %s does not exist! Ignoring internal session file line %u '%s'.",
161  src_port.c_str(), linenr, iss.str().c_str());
162  return;
163  }
164  const int src_refnum = fServer->GetGraphManager()->GetOutputRefNum(src_port_index);
165 
166  if (fServer->GetEngine()->PortConnect(src_refnum, src_port.c_str(), dst_port.c_str()) < 0) {
167  jack_error("Cannot connect ports of internal session file line %u '%s'.\n"
168  "Possibly the destination port does not exist. Ignoring the line!",
169  linenr, iss.str().c_str());
170  return;
171  }
172 
173  jack_info("Ports connected: %s -> %s", src_port.c_str(), dst_port.c_str());
174 }
175 
176 }
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
jack_info
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:100