Jack2 1.9.6
|
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 "JackDebugClient.h" 00021 #include "JackEngineControl.h" 00022 #include "JackException.h" 00023 #include "JackError.h" 00024 #include "JackTime.h" 00025 #include <iostream> 00026 #include <iomanip> 00027 #include <sstream> 00028 #include <fstream> 00029 #include <string> 00030 #include <time.h> 00031 00032 using namespace std; 00033 00034 namespace Jack 00035 { 00036 00037 JackDebugClient::JackDebugClient(JackClient * client) 00038 { 00039 fTotalPortNumber = 1; // The total number of port opened and maybe closed. Historical view. 00040 fOpenPortNumber = 0; // The current number of opened port. 00041 fIsActivated = 0; 00042 fIsDeactivated = 0; 00043 fIsClosed = 0; 00044 fClient = client; 00045 fFreewheel = false; 00046 } 00047 00048 JackDebugClient::~JackDebugClient() 00049 { 00050 fTotalPortNumber--; // fTotalPortNumber start at 1 00051 *fStream << endl << endl << "----------------------------------- JackDebugClient summary ------------------------------- " << endl << endl; 00052 *fStream << "Client flags ( 1:yes / 0:no ) :" << endl; 00053 *fStream << setw(5) << "- Client call activated : " << fIsActivated << endl; 00054 *fStream << setw(5) << "- Client call deactivated : " << fIsDeactivated << endl; 00055 *fStream << setw(5) << "- Client call closed : " << fIsClosed << endl; 00056 *fStream << setw(5) << "- Total number of instantiated port : " << fTotalPortNumber << endl; 00057 *fStream << setw(5) << "- Number of port remaining open when exiting client : " << fOpenPortNumber << endl; 00058 if (fOpenPortNumber != 0) 00059 *fStream << "!!! WARNING !!! Some ports have not been unregistered ! Incorrect exiting !" << endl; 00060 if (fIsDeactivated != fIsActivated) 00061 *fStream << "!!! ERROR !!! Client seem to not perform symetric activation-deactivation ! (not the same number of activate and deactivate)" << endl; 00062 if (fIsClosed == 0) 00063 *fStream << "!!! ERROR !!! Client have not been closed with jack_client_close() !" << endl; 00064 00065 *fStream << endl << endl << "---------------------------- JackDebugClient detailed port summary ------------------------ " << endl << endl; 00066 //for (int i = 0; i < fTotalPortNumber ; i++) { 00067 for (int i = 1; i <= fTotalPortNumber ; i++) { 00068 *fStream << endl << "Port index (internal debug test value) : " << i << endl; 00069 *fStream << setw(5) << "- Name : " << fPortList[i].name << endl; 00070 *fStream << setw(5) << "- idport : " << fPortList[i].idport << endl; 00071 *fStream << setw(5) << "- IsConnected : " << fPortList[i].IsConnected << endl; 00072 *fStream << setw(5) << "- IsUnregistered : " << fPortList[i].IsUnregistered << endl; 00073 if (fPortList[i].IsUnregistered == 0) 00074 *fStream << "!!! WARNING !!! Port have not been unregistered ! Incorrect exiting !" << endl; 00075 } 00076 *fStream << "delete object JackDebugClient : end of tracing" << endl; 00077 delete fStream; 00078 delete fClient; 00079 } 00080 00081 int JackDebugClient::Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status) 00082 { 00083 int res = fClient->Open(server_name, name, options, status); 00084 char provstr[256]; 00085 char buffer[256]; 00086 time_t curtime; 00087 struct tm *loctime; 00088 /* Get the current time. */ 00089 curtime = time (NULL); 00090 /* Convert it to local time representation. */ 00091 loctime = localtime (&curtime); 00092 strftime (buffer, 256, "%I-%M", loctime); 00093 sprintf(provstr, "JackClientDebug-%s-%s.log", name, buffer); 00094 fStream = new ofstream(provstr, ios_base::ate); 00095 if (fStream->is_open()) { 00096 if (res == -1) { 00097 *fStream << "Trying to open client with name '" << name << "' with bad result (client not opened)." << res << endl; 00098 } else { 00099 *fStream << "Open client with name '" << name << "'." << endl; 00100 } 00101 } else { 00102 jack_log("JackDebugClient::Open : cannot open log file"); 00103 } 00104 strcpy(fClientName, name); 00105 return res; 00106 } 00107 00108 int JackDebugClient::Close() 00109 { 00110 *fStream << "Client '" << fClientName << "' was closed" << endl; 00111 int res = fClient->Close(); 00112 fIsClosed++; 00113 return res; 00114 } 00115 00116 void JackDebugClient::CheckClient(const char* function_name) const 00117 { 00118 *fStream << "CheckClient : " << function_name << ", calling thread : " << pthread_self() << endl; 00119 00120 if (fIsClosed > 0) { 00121 *fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed " << "from " << function_name << endl; 00122 *fStream << "This is likely to cause crash !'" << endl; 00123 #ifdef __APPLE__ 00124 // Debugger(); 00125 #endif 00126 } 00127 } 00128 00129 pthread_t JackDebugClient::GetThreadID() 00130 { 00131 CheckClient("GetThreadID"); 00132 return fClient->GetThreadID(); 00133 } 00134 00135 JackGraphManager* JackDebugClient::GetGraphManager() const 00136 { 00137 CheckClient("GetGraphManager"); 00138 return fClient->GetGraphManager(); 00139 } 00140 JackEngineControl* JackDebugClient::GetEngineControl() const 00141 { 00142 CheckClient("GetEngineControl"); 00143 return fClient->GetEngineControl(); 00144 } 00149 int JackDebugClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) 00150 { 00151 CheckClient("ClientNotify"); 00152 return fClient->ClientNotify( refnum, name, notify, sync, message, value1, value2); 00153 } 00154 00155 int JackDebugClient::Activate() 00156 { 00157 CheckClient("Activate"); 00158 int res = fClient->Activate(); 00159 fIsActivated++; 00160 if (fIsDeactivated) 00161 *fStream << "Client '" << fClientName << "' call activate a new time (it already call 'activate' previously)." << endl; 00162 *fStream << "Client '" << fClientName << "' Activated" << endl; 00163 if (res != 0) 00164 *fStream << "Client '" << fClientName << "' try to activate but server return " << res << " ." << endl; 00165 return res; 00166 } 00167 00168 int JackDebugClient::Deactivate() 00169 { 00170 CheckClient("Deactivate"); 00171 int res = fClient->Deactivate(); 00172 fIsDeactivated++; 00173 if (fIsActivated == 0) 00174 *fStream << "Client '" << fClientName << "' deactivate while it hasn't been previoulsy activated !" << endl; 00175 *fStream << "Client '" << fClientName << "' Deactivated" << endl; 00176 if (res != 0) 00177 *fStream << "Client '" << fClientName << "' try to deactivate but server return " << res << " ." << endl; 00178 return res; 00179 } 00180 00181 //----------------- 00182 // Port management 00183 //----------------- 00184 00185 int JackDebugClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size) 00186 { 00187 CheckClient("PortRegister"); 00188 int res = fClient->PortRegister(port_name, port_type, flags, buffer_size); 00189 if (res <= 0) { 00190 *fStream << "Client '" << fClientName << "' try port register ('" << port_name << "') and server return error " << res << " ." << endl; 00191 } else { 00192 if (fTotalPortNumber < MAX_PORT_HISTORY) { 00193 fPortList[fTotalPortNumber].idport = res; 00194 strcpy(fPortList[fTotalPortNumber].name, port_name); 00195 fPortList[fTotalPortNumber].IsConnected = 0; 00196 fPortList[fTotalPortNumber].IsUnregistered = 0; 00197 } else { 00198 *fStream << "!!! WARNING !!! History is full : no more port history will be recorded." << endl; 00199 } 00200 fTotalPortNumber++; 00201 fOpenPortNumber++; 00202 *fStream << "Client '" << fClientName << "' port register with portname '" << port_name << " port " << res << "' ." << endl; 00203 } 00204 return res; 00205 } 00206 00207 int JackDebugClient::PortUnRegister(jack_port_id_t port_index) 00208 { 00209 CheckClient("PortUnRegister"); 00210 int res = fClient->PortUnRegister(port_index); 00211 fOpenPortNumber--; 00212 int i; 00213 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history 00214 if (fPortList[i].idport == port_index) { // We found the last record 00215 if (fPortList[i].IsUnregistered != 0) 00216 *fStream << "!!! ERROR !!! : '" << fClientName << "' id deregistering port '" << fPortList[i].name << "' that have already been unregistered !" << endl; 00217 fPortList[i].IsUnregistered++; 00218 break; 00219 } 00220 } 00221 if (i == 0) // Port is not found 00222 *fStream << "JackClientDebug : PortUnregister : port " << port_index << " was not previously registered !" << endl; 00223 if (res != 0) 00224 *fStream << "Client '" << fClientName << "' try to do PortUnregister and server return " << res << endl; 00225 *fStream << "Client '" << fClientName << "' unregister port '" << port_index << "'." << endl; 00226 return res; 00227 } 00228 00229 int JackDebugClient::PortConnect(const char* src, const char* dst) 00230 { 00231 CheckClient("PortConnect"); 00232 if (!fIsActivated) 00233 *fStream << "!!! ERROR !!! Trying to connect a port ( " << src << " to " << dst << ") while the client has not been activated !" << endl; 00234 int i; 00235 int res = fClient->PortConnect( src, dst); 00236 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history 00237 if (strcmp(fPortList[i].name, src) == 0) { // We found the last record in sources 00238 if (fPortList[i].IsUnregistered != 0) 00239 *fStream << "!!! ERROR !!! Connecting port " << src << " previoulsy unregistered !" << endl; 00240 fPortList[i].IsConnected++; 00241 *fStream << "Connecting port " << src << " to " << dst << ". "; 00242 break; 00243 } else if (strcmp(fPortList[i].name, dst) == 0 ) { // We found the record in dest 00244 if (fPortList[i].IsUnregistered != 0) 00245 *fStream << "!!! ERROR !!! Connecting port " << dst << " previoulsy unregistered !" << endl; 00246 fPortList[i].IsConnected++; 00247 *fStream << "Connecting port " << src << " to " << dst << ". "; 00248 break; 00249 } 00250 } 00251 if (i == 0) // Port is not found 00252 *fStream << "JackClientDebug : PortConnect : port was not found in debug database !" << endl; 00253 if (res != 0) 00254 *fStream << "Client '" << fClientName << "' try to do PortConnect but server return " << res << " ." << endl; 00255 //*fStream << "Client Port Connect done with names" << endl; 00256 return res; 00257 } 00258 00259 int JackDebugClient::PortDisconnect(const char* src, const char* dst) 00260 { 00261 CheckClient("PortDisconnect"); 00262 if (!fIsActivated) 00263 *fStream << "!!! ERROR !!! Trying to disconnect a port ( " << src << " to " << dst << ") while the client has not been activated !" << endl; 00264 int res = fClient->PortDisconnect( src, dst); 00265 int i; 00266 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history 00267 if (strcmp(fPortList[i].name, src) == 0) { // We found the record in sources 00268 if (fPortList[i].IsUnregistered != 0) 00269 *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl; 00270 fPortList[i].IsConnected--; 00271 *fStream << "disconnecting port " << src << ". "; 00272 break; 00273 } else if (strcmp(fPortList[i].name, dst) == 0 ) { // We found the record in dest 00274 if (fPortList[i].IsUnregistered != 0) 00275 *fStream << "!!! ERROR !!! : Disonnecting port " << dst << " previoulsy unregistered !" << endl; 00276 fPortList[i].IsConnected--; 00277 *fStream << "disconnecting port " << dst << ". "; 00278 break; 00279 } 00280 } 00281 if (i == 0) // Port is not found 00282 *fStream << "JackClientDebug : PortDisConnect : port was not found in debug database !" << endl; 00283 if (res != 0) 00284 *fStream << "Client '" << fClientName << "' try to do PortDisconnect but server return " << res << " ." << endl; 00285 //*fStream << "Client Port Disconnect done." << endl; 00286 return res; 00287 } 00288 00289 int JackDebugClient::PortDisconnect(jack_port_id_t src) 00290 { 00291 CheckClient("PortDisconnect"); 00292 if (!fIsActivated) 00293 *fStream << "!!! ERROR !!! : Trying to disconnect port " << src << " while that client has not been activated !" << endl; 00294 int res = fClient->PortDisconnect(src); 00295 int i; 00296 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history 00297 if (fPortList[i].idport == src) { // We found the record in sources 00298 if (fPortList[i].IsUnregistered != 0) 00299 *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl; 00300 fPortList[i].IsConnected--; 00301 *fStream << "Disconnecting port " << src << ". " << endl; 00302 break; 00303 } 00304 } 00305 if (i == 0) // Port is not found 00306 *fStream << "JackClientDebug : PortDisconnect : port was not found in debug database !" << endl; 00307 if (res != 0) 00308 *fStream << "Client '" << fClientName << "' try to do PortDisconnect but server return " << res << " ." << endl; 00309 //*fStream << "Client Port Disconnect with ID done." << endl; 00310 return res; 00311 } 00312 00313 int JackDebugClient::PortIsMine(jack_port_id_t port_index) 00314 { 00315 CheckClient("PortIsMine"); 00316 return fClient->PortIsMine(port_index); 00317 } 00318 00319 //-------------------- 00320 // Context management 00321 //-------------------- 00322 00323 int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size) 00324 { 00325 CheckClient("SetBufferSize"); 00326 return fClient->SetBufferSize(buffer_size); 00327 } 00328 00329 int JackDebugClient::SetFreeWheel(int onoff) 00330 { 00331 CheckClient("SetFreeWheel"); 00332 if (onoff && fFreewheel) 00333 *fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl; 00334 if (!onoff && !fFreewheel) 00335 *fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl; 00336 fFreewheel = onoff; 00337 return fClient->SetFreeWheel(onoff); 00338 } 00339 00340 /* 00341 ShutDown is called: 00342 - from the RT thread when Execute method fails 00343 - possibly from a "closed" notification channel 00344 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown)) 00345 */ 00346 00347 void JackDebugClient::ShutDown() 00348 { 00349 fClient->ShutDown(); 00350 } 00351 00352 //--------------------- 00353 // Transport management 00354 //--------------------- 00355 00356 int JackDebugClient::ReleaseTimebase() 00357 { 00358 CheckClient("ReleaseTimebase"); 00359 return fClient->ReleaseTimebase(); 00360 } 00361 00362 int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg) 00363 { 00364 CheckClient("SetSyncCallback"); 00365 return fClient->SetSyncCallback(sync_callback, arg); 00366 } 00367 00368 int JackDebugClient::SetSyncTimeout(jack_time_t timeout) 00369 { 00370 CheckClient("SetSyncTimeout"); 00371 return fClient->SetSyncTimeout(timeout); 00372 } 00373 00374 int JackDebugClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg) 00375 { 00376 CheckClient("SetTimebaseCallback"); 00377 return fClient->SetTimebaseCallback( conditional, timebase_callback, arg); 00378 } 00379 00380 void JackDebugClient::TransportLocate(jack_nframes_t frame) 00381 { 00382 CheckClient("TransportLocate"); 00383 fClient->TransportLocate(frame); 00384 } 00385 00386 jack_transport_state_t JackDebugClient::TransportQuery(jack_position_t* pos) 00387 { 00388 CheckClient("TransportQuery"); 00389 return fClient->TransportQuery(pos); 00390 } 00391 00392 jack_nframes_t JackDebugClient::GetCurrentTransportFrame() 00393 { 00394 CheckClient("GetCurrentTransportFrame"); 00395 return fClient->GetCurrentTransportFrame(); 00396 } 00397 00398 int JackDebugClient::TransportReposition(jack_position_t* pos) 00399 { 00400 CheckClient("TransportReposition"); 00401 return fClient->TransportReposition(pos); 00402 } 00403 00404 void JackDebugClient::TransportStart() 00405 { 00406 CheckClient("TransportStart"); 00407 fClient->TransportStart(); 00408 } 00409 00410 void JackDebugClient::TransportStop() 00411 { 00412 CheckClient("TransportStop"); 00413 fClient->TransportStop(); 00414 } 00415 00416 //--------------------- 00417 // Callback management 00418 //--------------------- 00419 00420 void JackDebugClient::OnShutdown(JackShutdownCallback callback, void *arg) 00421 { 00422 CheckClient("OnShutdown"); 00423 fClient->OnShutdown(callback, arg); 00424 } 00425 00426 void JackDebugClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg) 00427 { 00428 CheckClient("OnInfoShutdown"); 00429 fClient->OnInfoShutdown(callback, arg); 00430 } 00431 00432 int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg) 00433 { 00434 JackDebugClient* client = (JackDebugClient*)arg; 00435 jack_time_t t1 = GetMicroSeconds(); 00436 int res = client->fProcessTimeCallback(nframes, client->fProcessTimeCallbackArg); 00437 if (res == 0) { 00438 jack_time_t t2 = GetMicroSeconds(); 00439 long delta = long((t2 - t1) - client->GetEngineControl()->fPeriodUsecs); 00440 if (delta > 0 && !client->fFreewheel) 00441 *client->fStream << "!!! ERROR !!! : Process overload of " << delta << " us" << endl; 00442 } 00443 return res; 00444 } 00445 00446 int JackDebugClient::SetProcessCallback(JackProcessCallback callback, void *arg) 00447 { 00448 CheckClient("SetProcessCallback"); 00449 fProcessTimeCallback = callback; 00450 fProcessTimeCallbackArg = arg; 00451 return fClient->SetProcessCallback(TimeCallback, this); 00452 } 00453 00454 int JackDebugClient::SetXRunCallback(JackXRunCallback callback, void *arg) 00455 { 00456 CheckClient("SetXRunCallback"); 00457 return fClient->SetXRunCallback(callback, arg); 00458 } 00459 00460 int JackDebugClient::SetInitCallback(JackThreadInitCallback callback, void *arg) 00461 { 00462 CheckClient("SetInitCallback"); 00463 return fClient->SetInitCallback(callback, arg); 00464 } 00465 00466 int JackDebugClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg) 00467 { 00468 CheckClient("SetGraphOrderCallback"); 00469 return fClient->SetGraphOrderCallback(callback, arg); 00470 } 00471 00472 int JackDebugClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg) 00473 { 00474 CheckClient("SetBufferSizeCallback"); 00475 return fClient->SetBufferSizeCallback(callback, arg); 00476 } 00477 00478 int JackDebugClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback, void* arg) 00479 { 00480 CheckClient("SetClientRegistrationCallback"); 00481 return fClient->SetClientRegistrationCallback(callback, arg); 00482 } 00483 00484 int JackDebugClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg) 00485 { 00486 CheckClient("SetFreewheelCallback"); 00487 return fClient->SetFreewheelCallback(callback, arg); 00488 } 00489 00490 int JackDebugClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg) 00491 { 00492 CheckClient("SetPortRegistrationCallback"); 00493 return fClient->SetPortRegistrationCallback(callback, arg); 00494 } 00495 00496 int JackDebugClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg) 00497 { 00498 CheckClient("SetPortConnectCallback"); 00499 return fClient->SetPortConnectCallback(callback, arg); 00500 } 00501 00502 int JackDebugClient::SetPortRenameCallback(JackPortRenameCallback callback, void *arg) 00503 { 00504 CheckClient("SetPortRenameCallback"); 00505 return fClient->SetPortRenameCallback(callback, arg); 00506 } 00507 00508 JackClientControl* JackDebugClient::GetClientControl() const 00509 { 00510 CheckClient("GetClientControl"); 00511 return fClient->GetClientControl(); 00512 } 00513 00514 // Internal clients 00515 char* JackDebugClient::GetInternalClientName(int ref) 00516 { 00517 CheckClient("GetInternalClientName"); 00518 return fClient->GetInternalClientName(ref); 00519 } 00520 00521 int JackDebugClient::InternalClientHandle(const char* client_name, jack_status_t* status) 00522 { 00523 CheckClient("InternalClientHandle"); 00524 return fClient->InternalClientHandle(client_name, status); 00525 } 00526 00527 int JackDebugClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va) 00528 { 00529 CheckClient("InternalClientLoad"); 00530 return fClient->InternalClientLoad(client_name, options, status, va); 00531 } 00532 00533 void JackDebugClient::InternalClientUnload(int ref, jack_status_t* status) 00534 { 00535 CheckClient("InternalClientUnload"); 00536 fClient->InternalClientUnload(ref, status); 00537 } 00538 00539 } // end of namespace 00540