Jack2 1.9.6

JackDebugClient.cpp

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