Jack2  1.9.13
JackLibClient.cpp
1 /*
2 Copyright (C) 2004-2008 Grame
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 "JackLibClient.h"
21 #include "JackTime.h"
22 #include "JackLibGlobals.h"
23 #include "JackGlobals.h"
24 #include "JackPlatformPlug.h"
25 #include "JackTools.h"
26 
27 namespace Jack
28 {
29 
30 // Used for external C API (JackAPI.cpp)
31 JackGraphManager* GetGraphManager()
32 {
33  if (JackLibGlobals::fGlobals) {
34  return JackLibGlobals::fGlobals->fGraphManager;
35  } else {
36  return NULL;
37  }
38 }
39 
40 JackEngineControl* GetEngineControl()
41 {
42  if (JackLibGlobals::fGlobals) {
43  return JackLibGlobals::fGlobals->fEngineControl;
44  } else {
45  return NULL;
46  }
47 }
48 
49 JackSynchro* GetSynchroTable()
50 {
51  return (JackLibGlobals::fGlobals ? JackLibGlobals::fGlobals->fSynchroTable : 0);
52 }
53 
54 // Used for client-side Metadata API (JackLibAPI.cpp)
55 JackMetadata* GetMetadata()
56 {
57  if (JackLibGlobals::fGlobals) {
58  return JackLibGlobals::fGlobals->fMetadata;
59  } else {
60  return NULL;
61  }
62 }
63 
64 //-------------------
65 // Client management
66 //-------------------
67 
68 /*
69 ShutDown is called:
70 - from the RT thread when Execute method fails
71 - possibly from a "closed" notification channel
72 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown))
73 */
74 
75 void JackLibClient::ShutDown(jack_status_t code, const char* message)
76 {
77  jack_log("JackLibClient::ShutDown");
78  JackGlobals::fServerRunning = false;
79  JackClient::ShutDown(code, message);
80 }
81 
83 {
84  jack_log("JackLibClient::JackLibClient table = %x", table);
86 }
87 
88 JackLibClient::~JackLibClient()
89 {
90  jack_log("JackLibClient::~JackLibClient");
91  delete fChannel;
92 }
93 
94 int JackLibClient::Open(const char* server_name, const char* name, jack_uuid_t uuid, jack_options_t options, jack_status_t* status)
95 {
96  int shared_engine, shared_client, shared_graph, result;
97  bool res;
98  jack_log("JackLibClient::Open name = %s", name);
99 
100  if (strlen(name) >= JACK_CLIENT_NAME_SIZE) {
101  jack_error("\"%s\" is too long to be used as a JACK client name.\n"
102  "Please use %lu characters or less",
103  name,
104  JACK_CLIENT_NAME_SIZE - 1);
105  return -1;
106  }
107 
108  strncpy(fServerName, server_name, sizeof(fServerName));
109 
110  // Open server/client channel
111  char name_res[JACK_CLIENT_NAME_SIZE+1];
112  if (fChannel->Open(server_name, name, uuid, name_res, this, options, status) < 0) {
113  jack_error("Cannot connect to the server");
114  goto error;
115  }
116 
117  // Start receiving notifications
118  if (fChannel->Start() < 0) {
119  jack_error("Cannot start channel");
120  goto error;
121  }
122 
123  // Require new client
124  fChannel->ClientOpen(name_res, JackTools::GetPID(), uuid, &shared_engine, &shared_client, &shared_graph, &result);
125  if (result < 0) {
126  jack_error("Cannot open %s client", name_res);
127  goto error;
128  }
129 
130  try {
131  // Map shared memory segments
132  JackLibGlobals::fGlobals->fEngineControl.SetShmIndex(shared_engine, fServerName);
133  JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName);
134  fClientControl.SetShmIndex(shared_client, fServerName);
135  JackGlobals::fVerbose = GetEngineControl()->fVerbose;
136  } catch (...) {
137  jack_error("Map shared memory segments exception");
138  goto error;
139  }
140 
141  SetupDriverSync(false);
142 
143  // Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process
144  assert(JackGlobals::fSynchroMutex);
145  JackGlobals::fSynchroMutex->Lock();
146  res = fSynchroTable[GetClientControl()->fRefNum].Connect(name_res, fServerName);
147  JackGlobals::fSynchroMutex->Unlock();
148  if (!res) {
149  jack_error("Cannot ConnectSemaphore %s client", name_res);
150  goto error;
151  }
152 
153  JackGlobals::fClientTable[GetClientControl()->fRefNum] = this;
154  SetClockSource(GetEngineControl()->fClockSource);
155  jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum);
156  return 0;
157 
158 error:
159  fChannel->Stop();
160  fChannel->Close();
161  return -1;
162 }
163 
164 // Notifications received from the server
165 // TODO this should be done once for all clients in the process, when a shared notification channel
166 // will be shared by all clients...
167 int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
168 {
169  int res = 0;
170  assert(JackGlobals::fSynchroMutex);
171  JackGlobals::fSynchroMutex->Lock();
172 
173  // Done all time
174  switch (notify) {
175 
176  case kAddClient:
177  jack_log("JackClient::AddClient name = %s, ref = %ld ", name, refnum);
178  // the synchro must be usable in I/O mode when several clients live in the same process
179  res = fSynchroTable[refnum].Connect(name, fServerName) ? 0 : -1;
180  break;
181 
182  case kRemoveClient:
183  jack_log("JackClient::RemoveClient name = %s, ref = %ld ", name, refnum);
184  if (GetClientControl() && strcmp(GetClientControl()->fName, name) != 0) {
185  res = fSynchroTable[refnum].Disconnect() ? 0 : -1;
186  }
187  break;
188  }
189 
190  JackGlobals::fSynchroMutex->Unlock();
191  return res;
192 }
193 
194 JackGraphManager* JackLibClient::GetGraphManager() const
195 {
196  assert(JackLibGlobals::fGlobals->fGraphManager);
197  return JackLibGlobals::fGlobals->fGraphManager;
198 }
199 
200 JackEngineControl* JackLibClient::GetEngineControl() const
201 {
202  assert(JackLibGlobals::fGlobals->fEngineControl);
203  return JackLibGlobals::fGlobals->fEngineControl;
204 }
205 
206 JackClientControl* JackLibClient::GetClientControl() const
207 {
208  return fClientControl;
209 }
210 
211 } // end of namespace
212 
213 
214 
Inter process synchronization using POSIX semaphore.
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
Graph manager: contains the connection manager and the port array.
void SetupDriverSync(bool freewheel)
Definition: JackClient.cpp:140
JackClientChannel using sockets.
JackLibClient(JackSynchro *table)
int ClientNotifyImp(int refnum, const char *name, int notify, int sync, const char *message, int value1, int value2)
Notification received from the server.
detail::JackClientChannelInterface * fChannel
Definition: JackClient.h:97
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
The base class for clients: share part of the implementation for JackInternalClient and JackLibClient...
Definition: JackClient.h:48