Jack2
1.9.10
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #include "JackLibClient.h" 00021 #include "JackTime.h" 00022 #include "JackLibGlobals.h" 00023 #include "JackGlobals.h" 00024 #include "JackPlatformPlug.h" 00025 #include "JackTools.h" 00026 00027 namespace Jack 00028 { 00029 00030 // Used for external C API (JackAPI.cpp) 00031 JackGraphManager* GetGraphManager() 00032 { 00033 if (JackLibGlobals::fGlobals) { 00034 return JackLibGlobals::fGlobals->fGraphManager; 00035 } else { 00036 return NULL; 00037 } 00038 } 00039 00040 JackEngineControl* GetEngineControl() 00041 { 00042 if (JackLibGlobals::fGlobals) { 00043 return JackLibGlobals::fGlobals->fEngineControl; 00044 } else { 00045 return NULL; 00046 } 00047 } 00048 00049 JackSynchro* GetSynchroTable() 00050 { 00051 return (JackLibGlobals::fGlobals ? JackLibGlobals::fGlobals->fSynchroTable : 0); 00052 } 00053 00054 //------------------- 00055 // Client management 00056 //------------------- 00057 00058 /* 00059 ShutDown is called: 00060 - from the RT thread when Execute method fails 00061 - possibly from a "closed" notification channel 00062 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown)) 00063 */ 00064 00065 void JackLibClient::ShutDown(jack_status_t code, const char* message) 00066 { 00067 jack_log("JackLibClient::ShutDown"); 00068 JackGlobals::fServerRunning = false; 00069 JackClient::ShutDown(code, message); 00070 } 00071 00072 JackLibClient::JackLibClient(JackSynchro* table): JackClient(table) 00073 { 00074 jack_log("JackLibClient::JackLibClient table = %x", table); 00075 fChannel = new JackClientChannel(); 00076 } 00077 00078 JackLibClient::~JackLibClient() 00079 { 00080 jack_log("JackLibClient::~JackLibClient"); 00081 delete fChannel; 00082 } 00083 00084 int JackLibClient::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) 00085 { 00086 int shared_engine, shared_client, shared_graph, result; 00087 bool res; 00088 jack_log("JackLibClient::Open name = %s", name); 00089 00090 if (strlen(name) >= JACK_CLIENT_NAME_SIZE) { 00091 jack_error("\"%s\" is too long to be used as a JACK client name.\n" 00092 "Please use %lu characters or less", 00093 name, 00094 JACK_CLIENT_NAME_SIZE - 1); 00095 return -1; 00096 } 00097 00098 strncpy(fServerName, server_name, sizeof(fServerName)); 00099 00100 // Open server/client channel 00101 char name_res[JACK_CLIENT_NAME_SIZE + 1]; 00102 if (fChannel->Open(server_name, name, uuid, name_res, this, options, status) < 0) { 00103 jack_error("Cannot connect to the server"); 00104 goto error; 00105 } 00106 00107 // Start receiving notifications 00108 if (fChannel->Start() < 0) { 00109 jack_error("Cannot start channel"); 00110 goto error; 00111 } 00112 00113 // Require new client 00114 fChannel->ClientOpen(name_res, JackTools::GetPID(), uuid, &shared_engine, &shared_client, &shared_graph, &result); 00115 if (result < 0) { 00116 jack_error("Cannot open %s client", name_res); 00117 goto error; 00118 } 00119 00120 try { 00121 // Map shared memory segments 00122 JackLibGlobals::fGlobals->fEngineControl.SetShmIndex(shared_engine, fServerName); 00123 JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName); 00124 fClientControl.SetShmIndex(shared_client, fServerName); 00125 JackGlobals::fVerbose = GetEngineControl()->fVerbose; 00126 } catch (...) { 00127 jack_error("Map shared memory segments exception"); 00128 goto error; 00129 } 00130 00131 SetupDriverSync(false); 00132 00133 // Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process 00134 assert(JackGlobals::fSynchroMutex); 00135 JackGlobals::fSynchroMutex->Lock(); 00136 res = fSynchroTable[GetClientControl()->fRefNum].Connect(name_res, fServerName); 00137 JackGlobals::fSynchroMutex->Unlock(); 00138 if (!res) { 00139 jack_error("Cannot ConnectSemaphore %s client", name_res); 00140 goto error; 00141 } 00142 00143 JackGlobals::fClientTable[GetClientControl()->fRefNum] = this; 00144 SetClockSource(GetEngineControl()->fClockSource); 00145 jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum); 00146 return 0; 00147 00148 error: 00149 fChannel->Stop(); 00150 fChannel->Close(); 00151 return -1; 00152 } 00153 00154 // Notifications received from the server 00155 // TODO this should be done once for all clients in the process, when a shared notification channel 00156 // will be shared by all clients... 00157 int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) 00158 { 00159 int res = 0; 00160 assert(JackGlobals::fSynchroMutex); 00161 JackGlobals::fSynchroMutex->Lock(); 00162 00163 // Done all time 00164 switch (notify) { 00165 00166 case kAddClient: 00167 jack_log("JackClient::AddClient name = %s, ref = %ld ", name, refnum); 00168 // the synchro must be usable in I/O mode when several clients live in the same process 00169 res = fSynchroTable[refnum].Connect(name, fServerName) ? 0 : -1; 00170 break; 00171 00172 case kRemoveClient: 00173 jack_log("JackClient::RemoveClient name = %s, ref = %ld ", name, refnum); 00174 if (GetClientControl() && strcmp(GetClientControl()->fName, name) != 0) { 00175 res = fSynchroTable[refnum].Disconnect() ? 0 : -1; 00176 } 00177 break; 00178 } 00179 00180 JackGlobals::fSynchroMutex->Unlock(); 00181 return res; 00182 } 00183 00184 JackGraphManager* JackLibClient::GetGraphManager() const 00185 { 00186 assert(JackLibGlobals::fGlobals->fGraphManager); 00187 return JackLibGlobals::fGlobals->fGraphManager; 00188 } 00189 00190 JackEngineControl* JackLibClient::GetEngineControl() const 00191 { 00192 assert(JackLibGlobals::fGlobals->fEngineControl); 00193 return JackLibGlobals::fGlobals->fEngineControl; 00194 } 00195 00196 JackClientControl* JackLibClient::GetClientControl() const 00197 { 00198 return fClientControl; 00199 } 00200 00201 } // end of namespace 00202 00203 00204