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
)
38 : JackClient(client
->fSynchroTable
)
40 fTotalPortNumber
= 1; // The total number of port opened and maybe closed. Historical view.
41 fOpenPortNumber
= 0; // The current number of opened port.
49 JackDebugClient::~JackDebugClient()
51 fTotalPortNumber
--; // fTotalPortNumber start at 1
52 *fStream
<< endl
<< endl
<< "----------------------------------- JackDebugClient summary ------------------------------- " << endl
<< endl
;
53 *fStream
<< "Client flags ( 1:yes / 0:no ) :" << endl
;
54 *fStream
<< setw(5) << "- Client call activated : " << fIsActivated
<< endl
;
55 *fStream
<< setw(5) << "- Client call deactivated : " << fIsDeactivated
<< endl
;
56 *fStream
<< setw(5) << "- Client call closed : " << fIsClosed
<< endl
;
57 *fStream
<< setw(5) << "- Total number of instantiated port : " << fTotalPortNumber
<< endl
;
58 *fStream
<< setw(5) << "- Number of port remaining open when exiting client : " << fOpenPortNumber
<< endl
;
59 if (fOpenPortNumber
!= 0)
60 *fStream
<< "!!! WARNING !!! Some ports have not been unregistered ! Incorrect exiting !" << endl
;
61 if (fIsDeactivated
!= fIsActivated
)
62 *fStream
<< "!!! ERROR !!! Client seem to not perform symmetric activation-deactivation ! (not the same number of activate and deactivate)" << endl
;
64 *fStream
<< "!!! ERROR !!! Client have not been closed with jack_client_close() !" << endl
;
66 *fStream
<< endl
<< endl
<< "---------------------------- JackDebugClient detailed port summary ------------------------ " << endl
<< endl
;
67 //for (int i = 0; i < fTotalPortNumber ; i++) {
68 for (int i
= 1; i
<= fTotalPortNumber
; i
++) {
69 *fStream
<< endl
<< "Port index (internal debug test value) : " << i
<< endl
;
70 *fStream
<< setw(5) << "- Name : " << fPortList
[i
].name
<< endl
;
71 *fStream
<< setw(5) << "- idport : " << fPortList
[i
].idport
<< endl
;
72 *fStream
<< setw(5) << "- IsConnected : " << fPortList
[i
].IsConnected
<< endl
;
73 *fStream
<< setw(5) << "- IsUnregistered : " << fPortList
[i
].IsUnregistered
<< endl
;
74 if (fPortList
[i
].IsUnregistered
== 0)
75 *fStream
<< "!!! WARNING !!! Port have not been unregistered ! Incorrect exiting !" << endl
;
77 *fStream
<< "delete object JackDebugClient : end of tracing" << endl
;
82 int JackDebugClient::Open(const char* server_name
, const char* name
, jack_uuid_t uuid
, jack_options_t options
, jack_status_t
* status
)
84 int res
= fClient
->Open(server_name
, name
, uuid
, options
, status
);
89 /* Get the current time. */
90 curtime
= time (NULL
);
91 /* Convert it to local time representation. */
92 loctime
= localtime (&curtime
);
93 strftime (buffer
, 256, "%I-%M", loctime
);
94 snprintf(provstr
, sizeof(provstr
), "JackClientDebug-%s-%s.log", name
, buffer
);
95 fStream
= new ofstream(provstr
, ios_base::ate
);
96 if (fStream
->is_open()) {
98 *fStream
<< "Trying to open client with name '" << name
<< "' with bad result (client not opened)." << res
<< endl
;
100 *fStream
<< "Open client with name '" << name
<< "'." << endl
;
103 jack_log("JackDebugClient::Open : cannot open log file");
105 strcpy(fClientName
, name
);
109 int JackDebugClient::Close()
111 *fStream
<< "Client '" << fClientName
<< "' was closed" << endl
;
112 int res
= fClient
->Close();
117 void JackDebugClient::CheckClient(const char* function_name
) const
120 *fStream
<< "CheckClient : " << function_name
<< ", calling thread : " << GetCurrentThread() << endl
;
122 *fStream
<< "CheckClient : " << function_name
<< ", calling thread : " << pthread_self() << endl
;
126 *fStream
<< "!!! ERROR !!! : Accessing a client '" << fClientName
<< "' already closed " << "from " << function_name
<< endl
;
127 *fStream
<< "This is likely to cause crash !'" << endl
;
134 jack_native_thread_t
JackDebugClient::GetThreadID()
136 CheckClient("GetThreadID");
137 return fClient
->GetThreadID();
140 JackGraphManager
* JackDebugClient::GetGraphManager() const
142 CheckClient("GetGraphManager");
143 return fClient
->GetGraphManager();
145 JackEngineControl
* JackDebugClient::GetEngineControl() const
147 CheckClient("GetEngineControl");
148 return fClient
->GetEngineControl();
151 \brief Notification received from the server.
154 int JackDebugClient::ClientNotify(int refnum
, const char* name
, int notify
, int sync
, const char* message
, int value1
, int value2
)
156 CheckClient("ClientNotify");
157 return fClient
->ClientNotify( refnum
, name
, notify
, sync
, message
, value1
, value2
);
160 int JackDebugClient::Activate()
162 CheckClient("Activate");
163 int res
= fClient
->Activate();
166 *fStream
<< "Client '" << fClientName
<< "' call activate a new time (it already call 'activate' previously)." << endl
;
167 *fStream
<< "Client '" << fClientName
<< "' Activated" << endl
;
169 *fStream
<< "Client '" << fClientName
<< "' try to activate but server return " << res
<< " ." << endl
;
173 int JackDebugClient::Deactivate()
175 CheckClient("Deactivate");
176 int res
= fClient
->Deactivate();
178 if (fIsActivated
== 0)
179 *fStream
<< "Client '" << fClientName
<< "' deactivate while it hasn't been previoulsy activated !" << endl
;
180 *fStream
<< "Client '" << fClientName
<< "' Deactivated" << endl
;
182 *fStream
<< "Client '" << fClientName
<< "' try to deactivate but server return " << res
<< " ." << endl
;
190 int JackDebugClient::PortRegister(const char* port_name
, const char* port_type
, unsigned long flags
, unsigned long buffer_size
)
192 CheckClient("PortRegister");
193 int res
= fClient
->PortRegister(port_name
, port_type
, flags
, buffer_size
);
195 *fStream
<< "Client '" << fClientName
<< "' try port register ('" << port_name
<< "') and server return error " << res
<< " ." << endl
;
197 if (fTotalPortNumber
< MAX_PORT_HISTORY
) {
198 fPortList
[fTotalPortNumber
].idport
= res
;
199 strcpy(fPortList
[fTotalPortNumber
].name
, port_name
);
200 fPortList
[fTotalPortNumber
].IsConnected
= 0;
201 fPortList
[fTotalPortNumber
].IsUnregistered
= 0;
203 *fStream
<< "!!! WARNING !!! History is full : no more port history will be recorded." << endl
;
207 *fStream
<< "Client '" << fClientName
<< "' port register with portname '" << port_name
<< " port " << res
<< "' ." << endl
;
212 int JackDebugClient::PortUnRegister(jack_port_id_t port_index
)
214 CheckClient("PortUnRegister");
215 int res
= fClient
->PortUnRegister(port_index
);
218 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
219 if (fPortList
[i
].idport
== port_index
) { // We found the last record
220 if (fPortList
[i
].IsUnregistered
!= 0)
221 *fStream
<< "!!! ERROR !!! : '" << fClientName
<< "' id deregistering port '" << fPortList
[i
].name
<< "' that have already been unregistered !" << endl
;
222 fPortList
[i
].IsUnregistered
++;
226 if (i
== 0) // Port is not found
227 *fStream
<< "JackClientDebug : PortUnregister : port " << port_index
<< " was not previously registered !" << endl
;
229 *fStream
<< "Client '" << fClientName
<< "' try to do PortUnregister and server return " << res
<< endl
;
230 *fStream
<< "Client '" << fClientName
<< "' unregister port '" << port_index
<< "'." << endl
;
234 int JackDebugClient::PortConnect(const char* src
, const char* dst
)
236 CheckClient("PortConnect");
238 *fStream
<< "!!! ERROR !!! Trying to connect a port ( " << src
<< " to " << dst
<< ") while the client has not been activated !" << endl
;
240 int res
= fClient
->PortConnect( src
, dst
);
241 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
242 if (strcmp(fPortList
[i
].name
, src
) == 0) { // We found the last record in sources
243 if (fPortList
[i
].IsUnregistered
!= 0)
244 *fStream
<< "!!! ERROR !!! Connecting port " << src
<< " previoulsy unregistered !" << endl
;
245 fPortList
[i
].IsConnected
++;
246 *fStream
<< "Connecting port " << src
<< " to " << dst
<< ". ";
248 } else if (strcmp(fPortList
[i
].name
, dst
) == 0 ) { // We found the record in dest
249 if (fPortList
[i
].IsUnregistered
!= 0)
250 *fStream
<< "!!! ERROR !!! Connecting port " << dst
<< " previoulsy unregistered !" << endl
;
251 fPortList
[i
].IsConnected
++;
252 *fStream
<< "Connecting port " << src
<< " to " << dst
<< ". ";
256 if (i
== 0) // Port is not found
257 *fStream
<< "JackClientDebug : PortConnect : port was not found in debug database !" << endl
;
259 *fStream
<< "Client '" << fClientName
<< "' try to do PortConnect but server return " << res
<< " ." << endl
;
260 //*fStream << "Client Port Connect done with names" << endl;
264 int JackDebugClient::PortDisconnect(const char* src
, const char* dst
)
266 CheckClient("PortDisconnect");
268 *fStream
<< "!!! ERROR !!! Trying to disconnect a port ( " << src
<< " to " << dst
<< ") while the client has not been activated !" << endl
;
269 int res
= fClient
->PortDisconnect( src
, dst
);
271 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
272 if (strcmp(fPortList
[i
].name
, src
) == 0) { // We found the record in sources
273 if (fPortList
[i
].IsUnregistered
!= 0)
274 *fStream
<< "!!! ERROR !!! : Disconnecting port " << src
<< " previoulsy unregistered !" << endl
;
275 fPortList
[i
].IsConnected
--;
276 *fStream
<< "disconnecting port " << src
<< ". ";
278 } else if (strcmp(fPortList
[i
].name
, dst
) == 0 ) { // We found the record in dest
279 if (fPortList
[i
].IsUnregistered
!= 0)
280 *fStream
<< "!!! ERROR !!! : Disonnecting port " << dst
<< " previoulsy unregistered !" << endl
;
281 fPortList
[i
].IsConnected
--;
282 *fStream
<< "disconnecting port " << dst
<< ". ";
286 if (i
== 0) // Port is not found
287 *fStream
<< "JackClientDebug : PortDisConnect : port was not found in debug database !" << endl
;
289 *fStream
<< "Client '" << fClientName
<< "' try to do PortDisconnect but server return " << res
<< " ." << endl
;
290 //*fStream << "Client Port Disconnect done." << endl;
294 int JackDebugClient::PortDisconnect(jack_port_id_t src
)
296 CheckClient("PortDisconnect");
298 *fStream
<< "!!! ERROR !!! : Trying to disconnect port " << src
<< " while that client has not been activated !" << endl
;
299 int res
= fClient
->PortDisconnect(src
);
301 for (i
= (fTotalPortNumber
- 1); i
>= 0; i
--) { // We search the record into the history
302 if (fPortList
[i
].idport
== src
) { // We found the record in sources
303 if (fPortList
[i
].IsUnregistered
!= 0)
304 *fStream
<< "!!! ERROR !!! : Disconnecting port " << src
<< " previoulsy unregistered !" << endl
;
305 fPortList
[i
].IsConnected
--;
306 *fStream
<< "Disconnecting port " << src
<< ". " << endl
;
310 if (i
== 0) // Port is not found
311 *fStream
<< "JackClientDebug : PortDisconnect : port was not found in debug database !" << endl
;
313 *fStream
<< "Client '" << fClientName
<< "' try to do PortDisconnect but server return " << res
<< " ." << endl
;
314 //*fStream << "Client Port Disconnect with ID done." << endl;
318 int JackDebugClient::PortIsMine(jack_port_id_t port_index
)
320 CheckClient("PortIsMine");
321 *fStream
<< "JackClientDebug : PortIsMine port_index " << port_index
<< endl
;
322 return fClient
->PortIsMine(port_index
);
325 int JackDebugClient::PortRename(jack_port_id_t port_index
, const char* name
)
327 CheckClient("PortRename");
328 *fStream
<< "JackClientDebug : PortRename port_index " << port_index
<< "name" << name
<< endl
;
329 return fClient
->PortRename(port_index
, name
);
332 //--------------------
333 // Context management
334 //--------------------
336 int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size
)
338 CheckClient("SetBufferSize");
339 *fStream
<< "JackClientDebug : SetBufferSize buffer_size " << buffer_size
<< endl
;
340 return fClient
->SetBufferSize(buffer_size
);
343 int JackDebugClient::SetFreeWheel(int onoff
)
345 CheckClient("SetFreeWheel");
346 if (onoff
&& fFreewheel
)
347 *fStream
<< "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl
;
348 if (!onoff
&& !fFreewheel
)
349 *fStream
<< "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl
;
350 fFreewheel
= onoff
? true : false;
351 return fClient
->SetFreeWheel(onoff
);
354 int JackDebugClient::ComputeTotalLatencies()
356 CheckClient("ComputeTotalLatencies");
357 return fClient
->ComputeTotalLatencies();
362 - from the RT thread when Execute method fails
363 - possibly from a "closed" notification channel
364 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown))
367 void JackDebugClient::ShutDown(jack_status_t code
, const char* message
)
369 CheckClient("ShutDown");
370 fClient
->ShutDown(code
, message
);
373 //---------------------
374 // Transport management
375 //---------------------
377 int JackDebugClient::ReleaseTimebase()
379 CheckClient("ReleaseTimebase");
380 return fClient
->ReleaseTimebase();
383 int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback
, void* arg
)
385 CheckClient("SetSyncCallback");
386 return fClient
->SetSyncCallback(sync_callback
, arg
);
389 int JackDebugClient::SetSyncTimeout(jack_time_t timeout
)
391 CheckClient("SetSyncTimeout");
392 *fStream
<< "JackClientDebug : SetSyncTimeout timeout " << timeout
<< endl
;
393 return fClient
->SetSyncTimeout(timeout
);
396 int JackDebugClient::SetTimebaseCallback(int conditional
, JackTimebaseCallback timebase_callback
, void* arg
)
398 CheckClient("SetTimebaseCallback");
399 return fClient
->SetTimebaseCallback( conditional
, timebase_callback
, arg
);
402 void JackDebugClient::TransportLocate(jack_nframes_t frame
)
404 CheckClient("TransportLocate");
405 *fStream
<< "JackClientDebug : TransportLocate frame " << frame
<< endl
;
406 fClient
->TransportLocate(frame
);
409 jack_transport_state_t
JackDebugClient::TransportQuery(jack_position_t
* pos
)
411 CheckClient("TransportQuery");
412 return fClient
->TransportQuery(pos
);
415 jack_nframes_t
JackDebugClient::GetCurrentTransportFrame()
417 CheckClient("GetCurrentTransportFrame");
418 return fClient
->GetCurrentTransportFrame();
421 int JackDebugClient::TransportReposition(const jack_position_t
* pos
)
423 CheckClient("TransportReposition");
424 return fClient
->TransportReposition(pos
);
427 void JackDebugClient::TransportStart()
429 CheckClient("TransportStart");
430 fClient
->TransportStart();
433 void JackDebugClient::TransportStop()
435 CheckClient("TransportStop");
436 fClient
->TransportStop();
439 //---------------------
440 // Callback management
441 //---------------------
443 void JackDebugClient::OnShutdown(JackShutdownCallback callback
, void *arg
)
445 CheckClient("OnShutdown");
446 fClient
->OnShutdown(callback
, arg
);
449 void JackDebugClient::OnInfoShutdown(JackInfoShutdownCallback callback
, void *arg
)
451 CheckClient("OnInfoShutdown");
452 fClient
->OnInfoShutdown(callback
, arg
);
455 int JackDebugClient::TimeCallback(jack_nframes_t nframes
, void *arg
)
457 JackDebugClient
* client
= (JackDebugClient
*)arg
;
458 jack_time_t t1
= GetMicroSeconds();
459 int res
= client
->fProcessTimeCallback(nframes
, client
->fProcessTimeCallbackArg
);
461 jack_time_t t2
= GetMicroSeconds();
462 long delta
= long((t2
- t1
) - client
->GetEngineControl()->fPeriodUsecs
);
463 if (delta
> 0 && !client
->fFreewheel
) {
464 *client
->fStream
<< "!!! ERROR !!! : Process overload of " << delta
<< " us" << endl
;
470 int JackDebugClient::SetProcessCallback(JackProcessCallback callback
, void *arg
)
472 CheckClient("SetProcessCallback");
474 fProcessTimeCallback
= callback
;
475 fProcessTimeCallbackArg
= arg
;
477 if (callback
== NULL
) {
478 // Clear the callback...
479 return fClient
->SetProcessCallback(callback
, arg
);
481 // Setup the measuring version...
482 return fClient
->SetProcessCallback(TimeCallback
, this);
486 int JackDebugClient::SetXRunCallback(JackXRunCallback callback
, void *arg
)
488 CheckClient("SetXRunCallback");
489 return fClient
->SetXRunCallback(callback
, arg
);
492 int JackDebugClient::SetInitCallback(JackThreadInitCallback callback
, void *arg
)
494 CheckClient("SetInitCallback");
495 return fClient
->SetInitCallback(callback
, arg
);
498 int JackDebugClient::SetGraphOrderCallback(JackGraphOrderCallback callback
, void *arg
)
500 CheckClient("SetGraphOrderCallback");
501 return fClient
->SetGraphOrderCallback(callback
, arg
);
504 int JackDebugClient::SetBufferSizeCallback(JackBufferSizeCallback callback
, void *arg
)
506 CheckClient("SetBufferSizeCallback");
507 return fClient
->SetBufferSizeCallback(callback
, arg
);
510 int JackDebugClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback
, void* arg
)
512 CheckClient("SetClientRegistrationCallback");
513 return fClient
->SetClientRegistrationCallback(callback
, arg
);
516 int JackDebugClient::SetFreewheelCallback(JackFreewheelCallback callback
, void *arg
)
518 CheckClient("SetFreewheelCallback");
519 return fClient
->SetFreewheelCallback(callback
, arg
);
522 int JackDebugClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback
, void *arg
)
524 CheckClient("SetPortRegistrationCallback");
525 return fClient
->SetPortRegistrationCallback(callback
, arg
);
528 int JackDebugClient::SetPortConnectCallback(JackPortConnectCallback callback
, void *arg
)
530 CheckClient("SetPortConnectCallback");
531 return fClient
->SetPortConnectCallback(callback
, arg
);
534 int JackDebugClient::SetPortRenameCallback(JackPortRenameCallback callback
, void *arg
)
536 CheckClient("SetPortRenameCallback");
537 return fClient
->SetPortRenameCallback(callback
, arg
);
540 int JackDebugClient::SetSessionCallback(JackSessionCallback callback
, void *arg
)
542 CheckClient("SetSessionCallback");
543 return fClient
->SetSessionCallback(callback
, arg
);
546 int JackDebugClient::SetLatencyCallback(JackLatencyCallback callback
, void *arg
)
548 CheckClient("SetLatencyCallback");
549 return fClient
->SetLatencyCallback(callback
, arg
);
552 int JackDebugClient::SetProcessThread(JackThreadCallback fun
, void *arg
)
554 CheckClient("SetProcessThread");
555 return fClient
->SetProcessThread(fun
, arg
);
558 jack_session_command_t
* JackDebugClient::SessionNotify(const char* target
, jack_session_event_type_t type
, const char* path
)
560 CheckClient("SessionNotify");
561 *fStream
<< "JackClientDebug : SessionNotify target " << target
<< "type " << type
<< "path " << path
<< endl
;
562 return fClient
->SessionNotify(target
, type
, path
);
565 int JackDebugClient::SessionReply(jack_session_event_t
* ev
)
567 CheckClient("SessionReply");
568 return fClient
->SessionReply(ev
);
571 char* JackDebugClient::GetUUIDForClientName(const char* client_name
)
573 CheckClient("GetUUIDForClientName");
574 *fStream
<< "JackClientDebug : GetUUIDForClientName client_name " << client_name
<< endl
;
575 return fClient
->GetUUIDForClientName(client_name
);
578 char* JackDebugClient::GetClientNameByUUID(const char* uuid
)
580 CheckClient("GetClientNameByUUID");
581 *fStream
<< "JackClientDebug : GetClientNameByUUID uuid " << uuid
<< endl
;
582 return fClient
->GetClientNameByUUID(uuid
);
585 int JackDebugClient::ReserveClientName(const char* client_name
, const char* uuid
)
587 CheckClient("ReserveClientName");
588 *fStream
<< "JackClientDebug : ReserveClientName client_name " << client_name
<< "uuid " << uuid
<< endl
;
589 return fClient
->ReserveClientName(client_name
, uuid
);
592 int JackDebugClient::ClientHasSessionCallback(const char* client_name
)
594 CheckClient("ClientHasSessionCallback");
595 *fStream
<< "JackClientDebug : ClientHasSessionCallback client_name " << client_name
<< endl
;
596 return fClient
->ClientHasSessionCallback(client_name
);
599 JackClientControl
* JackDebugClient::GetClientControl() const
601 CheckClient("GetClientControl");
602 return fClient
->GetClientControl();
606 char* JackDebugClient::GetInternalClientName(int ref
)
608 CheckClient("GetInternalClientName");
609 return fClient
->GetInternalClientName(ref
);
612 int JackDebugClient::InternalClientHandle(const char* client_name
, jack_status_t
* status
)
614 CheckClient("InternalClientHandle");
615 return fClient
->InternalClientHandle(client_name
, status
);
618 int JackDebugClient::InternalClientLoad(const char* client_name
, jack_options_t options
, jack_status_t
* status
, jack_varargs_t
* va
)
620 CheckClient("InternalClientLoad");
621 return fClient
->InternalClientLoad(client_name
, options
, status
, va
);
624 void JackDebugClient::InternalClientUnload(int ref
, jack_status_t
* status
)
626 CheckClient("InternalClientUnload");
627 fClient
->InternalClientUnload(ref
, status
);
630 } // end of namespace