2 Copyright (C) 2004-2008 Grame
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.
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.
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.
20 #include "JackDebugClient.h"
21 #include "JackEngineControl.h"
22 #include "JackException.h"
23 #include "JackError.h"
37 JackDebugClient::JackDebugClient(JackClient
* client
)
39 fTotalPortNumber
= 1; // The total number of port opened and maybe closed. Historical view.
40 fOpenPortNumber
= 0; // The current number of opened port.
48 JackDebugClient::~JackDebugClient()
50 fTotalPortNumber
--; // fTotalPortNumber start at 1
51 *fStream
<< endl
<< endl
<< "----------------------------------- JackDebugClient summary ------------------------------- " << endl
<< endl
;
52 *fStream
<< "Client flags ( 1:yes / 0:no ) :" << endl
;
53 *fStream
<< setw(5) << "- Client call activated : " << fIsActivated
<< endl
;
54 *fStream
<< setw(5) << "- Client call deactivated : " << fIsDeactivated
<< endl
;
55 *fStream
<< setw(5) << "- Client call closed : " << fIsClosed
<< endl
;
56 *fStream
<< setw(5) << "- Total number of instantiated port : " << fTotalPortNumber
<< endl
;
57 *fStream
<< setw(5) << "- Number of port remaining open when exiting client : " << fOpenPortNumber
<< endl
;
58 if (fOpenPortNumber
!= 0)
59 *fStream
<< "!!! WARNING !!! Some ports have not been unregistered ! Incorrect exiting !" << endl
;
60 if (fIsDeactivated
!= fIsActivated
)
61 *fStream
<< "!!! ERROR !!! Client seem to not perform symetric activation-deactivation ! (not the same number of activate and deactivate)" << endl
;
63 *fStream
<< "!!! ERROR !!! Client have not been closed with jack_client_close() !" << endl
;
65 *fStream
<< endl
<< endl
<< "---------------------------- JackDebugClient detailed port summary ------------------------ " << endl
<< endl
;
66 //for (int i = 0; i < fTotalPortNumber ; i++) {
67 for (int i
= 1; i
<= fTotalPortNumber
; i
++) {
68 *fStream
<< endl
<< "Port index (internal debug test value) : " << i
<< endl
;
69 *fStream
<< setw(5) << "- Name : " << fPortList
[i
].name
<< endl
;
70 *fStream
<< setw(5) << "- idport : " << fPortList
[i
].idport
<< endl
;
71 *fStream
<< setw(5) << "- IsConnected : " << fPortList
[i
].IsConnected
<< endl
;
72 *fStream
<< setw(5) << "- IsUnregistered : " << fPortList
[i
].IsUnregistered
<< endl
;
73 if (fPortList
[i
].IsUnregistered
== 0)
74 *fStream
<< "!!! WARNING !!! Port have not been unregistered ! Incorrect exiting !" << endl
;
76 *fStream
<< "delete object JackDebugClient : end of tracing" << endl
;
81 int JackDebugClient::Open(const char* server_name
, const char* name
, int uuid
, jack_options_t options
, jack_status_t
* status
)
83 int res
= fClient
->Open(server_name
, name
, uuid
, options
, status
);
88 /* Get the current time. */
89 curtime
= time (NULL
);
90 /* Convert it to local time representation. */
91 loctime
= localtime (&curtime
);
92 strftime (buffer
, 256, "%I-%M", loctime
);
93 snprintf(provstr
, sizeof(provstr
), "JackClientDebug-%s-%s.log", name
, buffer
);
94 fStream
= new ofstream(provstr
, ios_base::ate
);
95 if (fStream
->is_open()) {
97 *fStream
<< "Trying to open client with name '" << name
<< "' with bad result (client not opened)." << res
<< endl
;
99 *fStream
<< "Open client with name '" << name
<< "'." << endl
;
102 jack_log("JackDebugClient::Open : cannot open log file");
104 strcpy(fClientName
, name
);
108 int JackDebugClient::Close()
110 *fStream
<< "Client '" << fClientName
<< "' was closed" << endl
;
111 int res
= fClient
->Close();
116 void JackDebugClient::CheckClient(const char* function_name
) const
119 *fStream
<< "CheckClient : " << function_name
<< ", calling thread : " << GetCurrentThread() << endl
;
121 *fStream
<< "CheckClient : " << function_name
<< ", calling thread : " << pthread_self() << endl
;
125 *fStream
<< "!!! ERROR !!! : Accessing a client '" << fClientName
<< "' already closed " << "from " << function_name
<< endl
;
126 *fStream
<< "This is likely to cause crash !'" << endl
;
133 jack_native_thread_t
JackDebugClient::GetThreadID()
135 CheckClient("GetThreadID");
136 return fClient
->GetThreadID();
139 JackGraphManager
* JackDebugClient::GetGraphManager() const
141 CheckClient("GetGraphManager");
142 return fClient
->GetGraphManager();
144 JackEngineControl
* JackDebugClient::GetEngineControl() const
146 CheckClient("GetEngineControl");
147 return fClient
->GetEngineControl();
150 \brief Notification received from the server.
153 int JackDebugClient::ClientNotify(int refnum
, const char* name
, int notify
, int sync
, const char* message
, int value1
, int value2
)
155 CheckClient("ClientNotify");
156 return fClient
->ClientNotify( refnum
, name
, notify
, sync
, message
, value1
, value2
);
159 int JackDebugClient::Activate()
161 CheckClient("Activate");
162 int res
= fClient
->Activate();
165 *fStream
<< "Client '" << fClientName
<< "' call activate a new time (it already call 'activate' previously)." << endl
;
166 *fStream
<< "Client '" << fClientName
<< "' Activated" << endl
;
168 *fStream
<< "Client '" << fClientName
<< "' try to activate but server return " << res
<< " ." << endl
;
172 int JackDebugClient::Deactivate()
174 CheckClient("Deactivate");
175 int res
= fClient
->Deactivate();
177 if (fIsActivated
== 0)
178 *fStream
<< "Client '" << fClientName
<< "' deactivate while it hasn't been previoulsy activated !" << endl
;
179 *fStream
<< "Client '" << fClientName
<< "' Deactivated" << endl
;
181 *fStream
<< "Client '" << fClientName
<< "' try to deactivate but server return " << res
<< " ." << endl
;
189 int JackDebugClient::PortRegister(const char* port_name
, const char* port_type
, unsigned long flags
, unsigned long buffer_size
)
191 CheckClient("PortRegister");
192 int res
= fClient
->PortRegister(port_name
, port_type
, flags
, buffer_size
);
194 *fStream
<< "Client '" << fClientName
<< "' try port register ('" << port_name
<< "') and server return error " << res
<< " ." << endl
;
196 if (fTotalPortNumber
< MAX_PORT_HISTORY
) {
197 fPortList
[fTotalPortNumber
].idport
= res
;
198 strcpy(fPortList
[fTotalPortNumber
].name
, port_name
);
199 fPortList
[fTotalPortNumber
].IsConnected
= 0;
200 fPortList
[fTotalPortNumber
].IsUnregistered
= 0;
202 *fStream
<< "!!! WARNING !!! History is full : no more port history will be recorded." << endl
;
206 *fStream
<< "Client '" << fClientName
<< "' port register with portname '" << port_name
<< " port " << res
<< "' ." << endl
;
211 int JackDebugClient::PortUnRegister(jack_port_id_t port_index
)
213 CheckClient("PortUnRegister");
214 int res
= fClient
->PortUnRegister(port_index
);
217 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
218 if (fPortList
[i
].idport
== port_index
) { // We found the last record
219 if (fPortList
[i
].IsUnregistered
!= 0)
220 *fStream
<< "!!! ERROR !!! : '" << fClientName
<< "' id deregistering port '" << fPortList
[i
].name
<< "' that have already been unregistered !" << endl
;
221 fPortList
[i
].IsUnregistered
++;
225 if (i
== 0) // Port is not found
226 *fStream
<< "JackClientDebug : PortUnregister : port " << port_index
<< " was not previously registered !" << endl
;
228 *fStream
<< "Client '" << fClientName
<< "' try to do PortUnregister and server return " << res
<< endl
;
229 *fStream
<< "Client '" << fClientName
<< "' unregister port '" << port_index
<< "'." << endl
;
233 int JackDebugClient::PortConnect(const char* src
, const char* dst
)
235 CheckClient("PortConnect");
237 *fStream
<< "!!! ERROR !!! Trying to connect a port ( " << src
<< " to " << dst
<< ") while the client has not been activated !" << endl
;
239 int res
= fClient
->PortConnect( src
, dst
);
240 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
241 if (strcmp(fPortList
[i
].name
, src
) == 0) { // We found the last record in sources
242 if (fPortList
[i
].IsUnregistered
!= 0)
243 *fStream
<< "!!! ERROR !!! Connecting port " << src
<< " previoulsy unregistered !" << endl
;
244 fPortList
[i
].IsConnected
++;
245 *fStream
<< "Connecting port " << src
<< " to " << dst
<< ". ";
247 } else if (strcmp(fPortList
[i
].name
, dst
) == 0 ) { // We found the record in dest
248 if (fPortList
[i
].IsUnregistered
!= 0)
249 *fStream
<< "!!! ERROR !!! Connecting port " << dst
<< " previoulsy unregistered !" << endl
;
250 fPortList
[i
].IsConnected
++;
251 *fStream
<< "Connecting port " << src
<< " to " << dst
<< ". ";
255 if (i
== 0) // Port is not found
256 *fStream
<< "JackClientDebug : PortConnect : port was not found in debug database !" << endl
;
258 *fStream
<< "Client '" << fClientName
<< "' try to do PortConnect but server return " << res
<< " ." << endl
;
259 //*fStream << "Client Port Connect done with names" << endl;
263 int JackDebugClient::PortDisconnect(const char* src
, const char* dst
)
265 CheckClient("PortDisconnect");
267 *fStream
<< "!!! ERROR !!! Trying to disconnect a port ( " << src
<< " to " << dst
<< ") while the client has not been activated !" << endl
;
268 int res
= fClient
->PortDisconnect( src
, dst
);
270 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
271 if (strcmp(fPortList
[i
].name
, src
) == 0) { // We found the record in sources
272 if (fPortList
[i
].IsUnregistered
!= 0)
273 *fStream
<< "!!! ERROR !!! : Disconnecting port " << src
<< " previoulsy unregistered !" << endl
;
274 fPortList
[i
].IsConnected
--;
275 *fStream
<< "disconnecting port " << src
<< ". ";
277 } else if (strcmp(fPortList
[i
].name
, dst
) == 0 ) { // We found the record in dest
278 if (fPortList
[i
].IsUnregistered
!= 0)
279 *fStream
<< "!!! ERROR !!! : Disonnecting port " << dst
<< " previoulsy unregistered !" << endl
;
280 fPortList
[i
].IsConnected
--;
281 *fStream
<< "disconnecting port " << dst
<< ". ";
285 if (i
== 0) // Port is not found
286 *fStream
<< "JackClientDebug : PortDisConnect : port was not found in debug database !" << endl
;
288 *fStream
<< "Client '" << fClientName
<< "' try to do PortDisconnect but server return " << res
<< " ." << endl
;
289 //*fStream << "Client Port Disconnect done." << endl;
293 int JackDebugClient::PortDisconnect(jack_port_id_t src
)
295 CheckClient("PortDisconnect");
297 *fStream
<< "!!! ERROR !!! : Trying to disconnect port " << src
<< " while that client has not been activated !" << endl
;
298 int res
= fClient
->PortDisconnect(src
);
300 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
301 if (fPortList
[i
].idport
== src
) { // We found the record in sources
302 if (fPortList
[i
].IsUnregistered
!= 0)
303 *fStream
<< "!!! ERROR !!! : Disconnecting port " << src
<< " previoulsy unregistered !" << endl
;
304 fPortList
[i
].IsConnected
--;
305 *fStream
<< "Disconnecting port " << src
<< ". " << endl
;
309 if (i
== 0) // Port is not found
310 *fStream
<< "JackClientDebug : PortDisconnect : port was not found in debug database !" << endl
;
312 *fStream
<< "Client '" << fClientName
<< "' try to do PortDisconnect but server return " << res
<< " ." << endl
;
313 //*fStream << "Client Port Disconnect with ID done." << endl;
317 int JackDebugClient::PortIsMine(jack_port_id_t port_index
)
319 CheckClient("PortIsMine");
320 *fStream
<< "JackClientDebug : PortIsMine port_index " << port_index
<< endl
;
321 return fClient
->PortIsMine(port_index
);
324 int JackDebugClient::PortRename(jack_port_id_t port_index
, const char* name
)
326 CheckClient("PortRename");
327 *fStream
<< "JackClientDebug : PortRename port_index " << port_index
<< "name" << name
<< endl
;
328 return fClient
->PortRename(port_index
, name
);
331 //--------------------
332 // Context management
333 //--------------------
335 int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size
)
337 CheckClient("SetBufferSize");
338 *fStream
<< "JackClientDebug : SetBufferSize buffer_size " << buffer_size
<< endl
;
339 return fClient
->SetBufferSize(buffer_size
);
342 int JackDebugClient::SetFreeWheel(int onoff
)
344 CheckClient("SetFreeWheel");
345 if (onoff
&& fFreewheel
)
346 *fStream
<< "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl
;
347 if (!onoff
&& !fFreewheel
)
348 *fStream
<< "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl
;
349 fFreewheel
= onoff
? true : false;
350 return fClient
->SetFreeWheel(onoff
);
353 int JackDebugClient::ComputeTotalLatencies()
355 CheckClient("ComputeTotalLatencies");
356 return fClient
->ComputeTotalLatencies();
361 - from the RT thread when Execute method fails
362 - possibly from a "closed" notification channel
363 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown))
366 void JackDebugClient::ShutDown()
368 CheckClient("ShutDown");
372 //---------------------
373 // Transport management
374 //---------------------
376 int JackDebugClient::ReleaseTimebase()
378 CheckClient("ReleaseTimebase");
379 return fClient
->ReleaseTimebase();
382 int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback
, void* arg
)
384 CheckClient("SetSyncCallback");
385 return fClient
->SetSyncCallback(sync_callback
, arg
);
388 int JackDebugClient::SetSyncTimeout(jack_time_t timeout
)
390 CheckClient("SetSyncTimeout");
391 *fStream
<< "JackClientDebug : SetSyncTimeout timeout " << timeout
<< endl
;
392 return fClient
->SetSyncTimeout(timeout
);
395 int JackDebugClient::SetTimebaseCallback(int conditional
, JackTimebaseCallback timebase_callback
, void* arg
)
397 CheckClient("SetTimebaseCallback");
398 return fClient
->SetTimebaseCallback( conditional
, timebase_callback
, arg
);
401 void JackDebugClient::TransportLocate(jack_nframes_t frame
)
403 CheckClient("TransportLocate");
404 *fStream
<< "JackClientDebug : TransportLocate frame " << frame
<< endl
;
405 fClient
->TransportLocate(frame
);
408 jack_transport_state_t
JackDebugClient::TransportQuery(jack_position_t
* pos
)
410 CheckClient("TransportQuery");
411 return fClient
->TransportQuery(pos
);
414 jack_nframes_t
JackDebugClient::GetCurrentTransportFrame()
416 CheckClient("GetCurrentTransportFrame");
417 return fClient
->GetCurrentTransportFrame();
420 int JackDebugClient::TransportReposition(jack_position_t
* pos
)
422 CheckClient("TransportReposition");
423 return fClient
->TransportReposition(pos
);
426 void JackDebugClient::TransportStart()
428 CheckClient("TransportStart");
429 fClient
->TransportStart();
432 void JackDebugClient::TransportStop()
434 CheckClient("TransportStop");
435 fClient
->TransportStop();
438 //---------------------
439 // Callback management
440 //---------------------
442 void JackDebugClient::OnShutdown(JackShutdownCallback callback
, void *arg
)
444 CheckClient("OnShutdown");
445 fClient
->OnShutdown(callback
, arg
);
448 void JackDebugClient::OnInfoShutdown(JackInfoShutdownCallback callback
, void *arg
)
450 CheckClient("OnInfoShutdown");
451 fClient
->OnInfoShutdown(callback
, arg
);
454 int JackDebugClient::TimeCallback(jack_nframes_t nframes
, void *arg
)
456 JackDebugClient
* client
= (JackDebugClient
*)arg
;
457 jack_time_t t1
= GetMicroSeconds();
458 int res
= client
->fProcessTimeCallback(nframes
, client
->fProcessTimeCallbackArg
);
460 jack_time_t t2
= GetMicroSeconds();
461 long delta
= long((t2
- t1
) - client
->GetEngineControl()->fPeriodUsecs
);
462 if (delta
> 0 && !client
->fFreewheel
) {
463 *client
->fStream
<< "!!! ERROR !!! : Process overload of " << delta
<< " us" << endl
;
469 int JackDebugClient::SetProcessCallback(JackProcessCallback callback
, void *arg
)
471 CheckClient("SetProcessCallback");
473 fProcessTimeCallback
= callback
;
474 fProcessTimeCallbackArg
= arg
;
476 if (callback
== NULL
) {
477 // Clear the callback...
478 return fClient
->SetProcessCallback(callback
, arg
);
480 // Setup the measuring version...
481 return fClient
->SetProcessCallback(TimeCallback
, this);
485 int JackDebugClient::SetXRunCallback(JackXRunCallback callback
, void *arg
)
487 CheckClient("SetXRunCallback");
488 return fClient
->SetXRunCallback(callback
, arg
);
491 int JackDebugClient::SetInitCallback(JackThreadInitCallback callback
, void *arg
)
493 CheckClient("SetInitCallback");
494 return fClient
->SetInitCallback(callback
, arg
);
497 int JackDebugClient::SetGraphOrderCallback(JackGraphOrderCallback callback
, void *arg
)
499 CheckClient("SetGraphOrderCallback");
500 return fClient
->SetGraphOrderCallback(callback
, arg
);
503 int JackDebugClient::SetBufferSizeCallback(JackBufferSizeCallback callback
, void *arg
)
505 CheckClient("SetBufferSizeCallback");
506 return fClient
->SetBufferSizeCallback(callback
, arg
);
509 int JackDebugClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback
, void* arg
)
511 CheckClient("SetClientRegistrationCallback");
512 return fClient
->SetClientRegistrationCallback(callback
, arg
);
515 int JackDebugClient::SetFreewheelCallback(JackFreewheelCallback callback
, void *arg
)
517 CheckClient("SetFreewheelCallback");
518 return fClient
->SetFreewheelCallback(callback
, arg
);
521 int JackDebugClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback
, void *arg
)
523 CheckClient("SetPortRegistrationCallback");
524 return fClient
->SetPortRegistrationCallback(callback
, arg
);
527 int JackDebugClient::SetPortConnectCallback(JackPortConnectCallback callback
, void *arg
)
529 CheckClient("SetPortConnectCallback");
530 return fClient
->SetPortConnectCallback(callback
, arg
);
533 int JackDebugClient::SetPortRenameCallback(JackPortRenameCallback callback
, void *arg
)
535 CheckClient("SetPortRenameCallback");
536 return fClient
->SetPortRenameCallback(callback
, arg
);
539 int JackDebugClient::SetSessionCallback(JackSessionCallback callback
, void *arg
)
541 CheckClient("SetSessionCallback");
542 return fClient
->SetSessionCallback(callback
, arg
);
545 int JackDebugClient::SetLatencyCallback(JackLatencyCallback callback
, void *arg
)
547 CheckClient("SetLatencyCallback");
548 return fClient
->SetLatencyCallback(callback
, arg
);
551 int JackDebugClient::SetProcessThread(JackThreadCallback fun
, void *arg
)
553 CheckClient("SetProcessThread");
554 return fClient
->SetProcessThread(fun
, arg
);
557 jack_session_command_t
* JackDebugClient::SessionNotify(const char* target
, jack_session_event_type_t type
, const char* path
)
559 CheckClient("SessionNotify");
560 *fStream
<< "JackClientDebug : SessionNotify target " << target
<< "type " << type
<< "path " << path
<< endl
;
561 return fClient
->SessionNotify(target
, type
, path
);
564 int JackDebugClient::SessionReply(jack_session_event_t
* ev
)
566 CheckClient("SessionReply");
567 return fClient
->SessionReply(ev
);
570 char* JackDebugClient::GetUUIDForClientName(const char* client_name
)
572 CheckClient("GetUUIDForClientName");
573 *fStream
<< "JackClientDebug : GetUUIDForClientName client_name " << client_name
<< endl
;
574 return fClient
->GetUUIDForClientName(client_name
);
577 char* JackDebugClient::GetClientNameByUUID(const char* uuid
)
579 CheckClient("GetClientNameByUUID");
580 *fStream
<< "JackClientDebug : GetClientNameByUUID uuid " << uuid
<< endl
;
581 return fClient
->GetClientNameByUUID(uuid
);
584 int JackDebugClient::ReserveClientName(const char* client_name
, const char* uuid
)
586 CheckClient("ReserveClientName");
587 *fStream
<< "JackClientDebug : ReserveClientName client_name " << client_name
<< "uuid " << uuid
<< endl
;
588 return fClient
->ReserveClientName(client_name
, uuid
);
591 int JackDebugClient::ClientHasSessionCallback(const char* client_name
)
593 CheckClient("ClientHasSessionCallback");
594 *fStream
<< "JackClientDebug : ClientHasSessionCallback client_name " << client_name
<< endl
;
595 return fClient
->ClientHasSessionCallback(client_name
);
598 JackClientControl
* JackDebugClient::GetClientControl() const
600 CheckClient("GetClientControl");
601 return fClient
->GetClientControl();
605 char* JackDebugClient::GetInternalClientName(int ref
)
607 CheckClient("GetInternalClientName");
608 return fClient
->GetInternalClientName(ref
);
611 int JackDebugClient::InternalClientHandle(const char* client_name
, jack_status_t
* status
)
613 CheckClient("InternalClientHandle");
614 return fClient
->InternalClientHandle(client_name
, status
);
617 int JackDebugClient::InternalClientLoad(const char* client_name
, jack_options_t options
, jack_status_t
* status
, jack_varargs_t
* va
)
619 CheckClient("InternalClientLoad");
620 return fClient
->InternalClientLoad(client_name
, options
, status
, va
);
623 void JackDebugClient::InternalClientUnload(int ref
, jack_status_t
* status
)
625 CheckClient("InternalClientUnload");
626 fClient
->InternalClientUnload(ref
, status
);
629 } // end of namespace