Add a string parameter to server ==> client notification, add a new InfoShutdown...
[jack2.git] / common / JackDebugClient.cpp
bloba2a61d8d95b2d4025501a59626240998fb149aef
1 /*
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 "JackError.h"
23 #include "JackTime.h"
24 #include <iostream>
25 #include <iomanip>
26 #include <sstream>
27 #include <fstream>
28 #include <string>
29 #include <time.h>
31 using namespace std;
33 namespace Jack
36 JackDebugClient::JackDebugClient(JackClient * client)
38 fTotalPortNumber = 1; // The total number of port opened and maybe closed. Historical view.
39 fOpenPortNumber = 0; // The current number of opened port.
40 fIsActivated = 0;
41 fIsDeactivated = 0;
42 fIsClosed = 0;
43 fClient = client;
44 fFreewheel = false;
47 JackDebugClient::~JackDebugClient()
49 fTotalPortNumber--; // fTotalPortNumber start at 1
50 *fStream << endl << endl << "----------------------------------- JackDebugClient summary ------------------------------- " << endl << endl;
51 *fStream << "Client flags ( 1:yes / 0:no ) :" << endl;
52 *fStream << setw(5) << "- Client call activated : " << fIsActivated << endl;
53 *fStream << setw(5) << "- Client call deactivated : " << fIsDeactivated << endl;
54 *fStream << setw(5) << "- Client call closed : " << fIsClosed << endl;
55 *fStream << setw(5) << "- Total number of instantiated port : " << fTotalPortNumber << endl;
56 *fStream << setw(5) << "- Number of port remaining open when exiting client : " << fOpenPortNumber << endl;
57 if (fOpenPortNumber != 0)
58 *fStream << "!!! WARNING !!! Some ports have not been unregistrated ! Incorrect exiting !" << endl;
59 if (fIsDeactivated != fIsActivated)
60 *fStream << "!!! ERROR !!! Client seem do not perform symetric activation-deactivation ! (not the same number of activate and deactivate)" << endl;
61 if (fIsClosed == 0)
62 *fStream << "!!! ERROR !!! Client have not been closed with jack_client_close() !" << endl;
64 *fStream << endl << endl << "---------------------------- JackDebugClient detailed port summary ------------------------ " << endl << endl;
65 //for (int i = 0; i < fTotalPortNumber ; i++) {
66 for (int i = 1; i <= fTotalPortNumber ; i++) {
67 *fStream << endl << "Port index (internal debug test value) : " << i << endl;
68 *fStream << setw(5) << "- Name : " << fPortList[i].name << endl;
69 *fStream << setw(5) << "- idport : " << fPortList[i].idport << endl;
70 *fStream << setw(5) << "- IsConnected : " << fPortList[i].IsConnected << endl;
71 *fStream << setw(5) << "- IsUnregistrated : " << fPortList[i].IsUnregistrated << endl;
72 if (fPortList[i].IsUnregistrated == 0)
73 *fStream << "!!! WARNING !!! Port have not been unregistrated ! Incorrect exiting !" << endl;
75 *fStream << "delete object JackDebugClient : end of tracing" << endl;
76 delete fStream;
77 delete fClient;
80 int JackDebugClient::Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status)
82 int res = fClient->Open(server_name, name, options, status);
83 char provstr[256];
84 char buffer[256];
85 time_t curtime;
86 struct tm *loctime;
87 /* Get the current time. */
88 curtime = time (NULL);
89 /* Convert it to local time representation. */
90 loctime = localtime (&curtime);
91 strftime (buffer, 256, "%I-%M", loctime);
92 sprintf(provstr, "JackClientDebug-%s-%s.log", name, buffer);
93 fStream = new ofstream(provstr, ios_base::ate);
94 if (fStream->is_open()) {
95 if (res == -1) {
96 *fStream << "Trying to open client with name '" << name << "' with bad result (client not opened)." << res << endl;
97 } else {
98 *fStream << "Open client with name '" << name << "'." << endl;
100 } else {
101 jack_log("JackDebugClient::Open : cannot open log file");
103 strcpy(fClientName, name);
104 return res;
107 int JackDebugClient::Close()
109 fIsClosed++;
110 *fStream << "Client '" << fClientName << "' was closed" << endl;
111 return fClient->Close();
114 void JackDebugClient::CheckClient() const
116 if (fIsClosed > 0) {
117 *fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed !" << endl;
118 *fStream << "This is likely to cause crash !'" << endl;
122 pthread_t JackDebugClient::GetThreadID()
124 CheckClient();
125 return fClient->GetThreadID();
128 JackGraphManager* JackDebugClient::GetGraphManager() const
130 CheckClient();
131 return fClient->GetGraphManager();
133 JackEngineControl* JackDebugClient::GetEngineControl() const
135 CheckClient();
136 return fClient->GetEngineControl();
139 \brief Notification received from the server.
142 int JackDebugClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
144 CheckClient();
145 return fClient->ClientNotify( refnum, name, notify, sync, message, value1, value2);
148 int JackDebugClient::Activate()
150 CheckClient();
151 int res = fClient->Activate();
152 fIsActivated++;
153 if (fIsDeactivated)
154 *fStream << "Client '" << fClientName << "' call activate a new time (it already call 'activate' previously)." << endl;
155 *fStream << "Client '" << fClientName << "' Activated" << endl;
156 if (res != 0)
157 *fStream << "Client '" << fClientName << "' try to activate but server return " << res << " ." << endl;
158 return res;
161 int JackDebugClient::Deactivate()
163 CheckClient();
164 int res = fClient->Deactivate();
165 fIsDeactivated++;
166 if (fIsActivated == 0)
167 *fStream << "Client '" << fClientName << "' deactivate while it hasn't been previoulsy activated !" << endl;
168 *fStream << "Client '" << fClientName << "' Deactivated" << endl;
169 if (res != 0)
170 *fStream << "Client '" << fClientName << "' try to deactivate but server return " << res << " ." << endl;
171 return res;
174 //-----------------
175 // Port management
176 //-----------------
178 int JackDebugClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
180 CheckClient();
181 int res = fClient->PortRegister(port_name, port_type, flags, buffer_size);
182 if (res <= 0) {
183 *fStream << "Client '" << fClientName << "' try port register ('" << port_name << "') and server return error " << res << " ." << endl;
184 } else {
185 if (fTotalPortNumber < MAX_PORT_HISTORY) {
186 fPortList[fTotalPortNumber].idport = res;
187 strcpy(fPortList[fTotalPortNumber].name, port_name);
188 fPortList[fTotalPortNumber].IsConnected = 0;
189 fPortList[fTotalPortNumber].IsUnregistrated = 0;
190 } else {
191 *fStream << "!!! WARNING !!! History is full : no more port history will be recorded." << endl;
193 fTotalPortNumber++;
194 fOpenPortNumber++;
195 *fStream << "Client '" << fClientName << "' port register with portname '" << port_name << " port " << res << "' ." << endl;
197 return res;
200 int JackDebugClient::PortUnRegister(jack_port_id_t port_index)
202 CheckClient();
203 int res = fClient->PortUnRegister(port_index);
204 fOpenPortNumber--;
205 int i;
206 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
207 if (fPortList[i].idport == port_index) { // We found the last record
208 if (fPortList[i].IsUnregistrated != 0)
209 *fStream << "!!! ERROR !!! : '" << fClientName << "' id deregistering port '" << fPortList[i].name << "' that have already been unregistered !" << endl;
210 fPortList[i].IsUnregistrated++;
211 break;
214 if (i == 0) // Port is not found
215 *fStream << "JackClientDebug : PortUnregister : port " << port_index << " was not previously registered !" << endl;
216 if (res != 0)
217 *fStream << "Client '" << fClientName << "' try to do PortUnregister and server return " << res << " )." << endl;
218 *fStream << "Client '" << fClientName << "' unregister port '" << port_index << "'." << endl;
219 return res;
222 int JackDebugClient::PortConnect(const char* src, const char* dst)
224 CheckClient();
225 if (!fIsActivated)
226 *fStream << "!!! ERROR !!! Trying to connect a port ( " << src << " to " << dst << ") while the client has not been activated !" << endl;
227 int i;
228 int res = fClient->PortConnect( src, dst);
229 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
230 if (strcmp(fPortList[i].name, src) == 0) { // We found the last record in sources
231 if (fPortList[i].IsUnregistrated != 0)
232 *fStream << "!!! ERROR !!! Connecting port " << src << " previoulsy unregistered !" << endl;
233 fPortList[i].IsConnected++;
234 *fStream << "Connecting port " << src << " to " << dst << ". ";
235 break;
236 } else if (strcmp(fPortList[i].name, dst) == 0 ) { // We found the record in dest
237 if (fPortList[i].IsUnregistrated != 0)
238 *fStream << "!!! ERROR !!! Connecting port " << dst << " previoulsy unregistered !" << endl;
239 fPortList[i].IsConnected++;
240 *fStream << "Connecting port " << src << " to " << dst << ". ";
241 break;
244 if (i == 0) // Port is not found
245 *fStream << "JackClientDebug : PortConnect : port was not found in debug database !" << endl;
246 if (res != 0)
247 *fStream << "Client '" << fClientName << "' try to do PortConnect but server return " << res << " ." << endl;
248 //*fStream << "Client Port Connect done with names" << endl;
249 return res;
252 int JackDebugClient::PortDisconnect(const char* src, const char* dst)
254 CheckClient();
255 if (!fIsActivated)
256 *fStream << "!!! ERROR !!! Trying to disconnect a port ( " << src << " to " << dst << ") while the client has not been activated !" << endl;
257 int res = fClient->PortDisconnect( src, dst);
258 int i;
259 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
260 if (strcmp(fPortList[i].name, src) == 0) { // We found the record in sources
261 if (fPortList[i].IsUnregistrated != 0)
262 *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl;
263 fPortList[i].IsConnected--;
264 *fStream << "disconnecting port " << src << ". ";
265 break;
266 } else if (strcmp(fPortList[i].name, dst) == 0 ) { // We found the record in dest
267 if (fPortList[i].IsUnregistrated != 0)
268 *fStream << "!!! ERROR !!! : Disonnecting port " << dst << " previoulsy unregistered !" << endl;
269 fPortList[i].IsConnected--;
270 *fStream << "disconnecting port " << dst << ". ";
271 break;
274 if (i == 0) // Port is not found
275 *fStream << "JackClientDebug : PortDisConnect : port was not found in debug database !" << endl;
276 if (res != 0)
277 *fStream << "Client '" << fClientName << "' try to do PortDisconnect but server return " << res << " ." << endl;
278 //*fStream << "Client Port Disconnect done." << endl;
279 return res;
282 int JackDebugClient::PortDisconnect(jack_port_id_t src)
284 CheckClient();
285 if (!fIsActivated)
286 *fStream << "!!! ERROR !!! : Trying to disconnect port " << src << " while that client has not been activated !" << endl;
287 int res = fClient->PortDisconnect(src);
288 int i;
289 for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
290 if (fPortList[i].idport == src) { // We found the record in sources
291 if (fPortList[i].IsUnregistrated != 0)
292 *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl;
293 fPortList[i].IsConnected--;
294 *fStream << "Disconnecting port " << src << ". " << endl;
295 break;
298 if (i == 0) // Port is not found
299 *fStream << "JackClientDebug : PortDisconnect : port was not found in debug database !" << endl;
300 if (res != 0)
301 *fStream << "Client '" << fClientName << "' try to do PortDisconnect but server return " << res << " ." << endl;
302 //*fStream << "Client Port Disconnect with ID done." << endl;
303 return res;
306 int JackDebugClient::PortIsMine(jack_port_id_t port_index)
308 CheckClient();
309 return fClient->PortIsMine(port_index);
312 //--------------------
313 // Context management
314 //--------------------
316 int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size)
318 CheckClient();
319 return fClient->SetBufferSize(buffer_size);
322 int JackDebugClient::SetFreeWheel(int onoff)
324 CheckClient();
325 if (onoff && fFreewheel)
326 *fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl;
327 if (!onoff && !fFreewheel)
328 *fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl;
329 fFreewheel = onoff;
330 return fClient->SetFreeWheel(onoff);
334 ShutDown is called:
335 - from the RT thread when Execute method fails
336 - possibly from a "closed" notification channel
337 (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown))
340 void JackDebugClient::ShutDown()
342 fClient->ShutDown();
345 //---------------------
346 // Transport management
347 //---------------------
349 int JackDebugClient::ReleaseTimebase()
351 CheckClient();
352 return fClient->ReleaseTimebase();
355 int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
357 CheckClient();
358 return fClient->SetSyncCallback(sync_callback, arg);
361 int JackDebugClient::SetSyncTimeout(jack_time_t timeout)
363 CheckClient();
364 return fClient->SetSyncTimeout(timeout);
367 int JackDebugClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
369 CheckClient();
370 return fClient->SetTimebaseCallback( conditional, timebase_callback, arg);
373 void JackDebugClient::TransportLocate(jack_nframes_t frame)
375 CheckClient();
376 fClient->TransportLocate(frame);
379 jack_transport_state_t JackDebugClient::TransportQuery(jack_position_t* pos)
381 CheckClient();
382 return fClient->TransportQuery(pos);
385 jack_nframes_t JackDebugClient::GetCurrentTransportFrame()
387 CheckClient();
388 return fClient->GetCurrentTransportFrame();
391 int JackDebugClient::TransportReposition(jack_position_t* pos)
393 CheckClient();
394 return fClient->TransportReposition(pos);
397 void JackDebugClient::TransportStart()
399 CheckClient();
400 fClient->TransportStart();
403 void JackDebugClient::TransportStop()
405 CheckClient();
406 fClient->TransportStop();
409 //---------------------
410 // Callback management
411 //---------------------
413 void JackDebugClient::OnShutdown(JackShutdownCallback callback, void *arg)
415 CheckClient();
416 fClient->OnShutdown(callback, arg);
419 void JackDebugClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg)
421 CheckClient();
422 fClient->OnInfoShutdown(callback, arg);
425 int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg)
427 JackDebugClient* client = (JackDebugClient*)arg;
428 jack_time_t t1 = GetMicroSeconds();
429 int res = client->fProcessTimeCallback(nframes, client->fProcessTimeCallbackArg);
430 jack_time_t t2 = GetMicroSeconds();
431 long delta = long((t2 - t1) - client->GetEngineControl()->fPeriodUsecs);
432 if (delta > 0 && !client->fFreewheel)
433 *client->fStream << "!!! ERROR !!! : Process overload of " << delta << " us" << endl;
434 return res;
437 int JackDebugClient::SetProcessCallback(JackProcessCallback callback, void *arg)
439 CheckClient();
440 fProcessTimeCallback = callback;
441 fProcessTimeCallbackArg = arg;
442 return fClient->SetProcessCallback(TimeCallback, this);
445 int JackDebugClient::SetXRunCallback(JackXRunCallback callback, void *arg)
447 CheckClient();
448 return fClient->SetXRunCallback(callback, arg);
451 int JackDebugClient::SetInitCallback(JackThreadInitCallback callback, void *arg)
453 CheckClient();
454 return fClient->SetInitCallback(callback, arg);
457 int JackDebugClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
459 CheckClient();
460 return fClient->SetGraphOrderCallback(callback, arg);
463 int JackDebugClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
465 CheckClient();
466 return fClient->SetBufferSizeCallback(callback, arg);
469 int JackDebugClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback, void* arg)
471 CheckClient();
472 return fClient->SetClientRegistrationCallback(callback, arg);
475 int JackDebugClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
477 CheckClient();
478 return fClient->SetFreewheelCallback(callback, arg);
481 int JackDebugClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg)
483 CheckClient();
484 return fClient->SetPortRegistrationCallback(callback, arg);
487 int JackDebugClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg)
489 CheckClient();
490 return fClient->SetPortConnectCallback(callback, arg);
493 int JackDebugClient::SetPortRenameCallback(JackPortRenameCallback callback, void *arg)
495 CheckClient();
496 return fClient->SetPortRenameCallback(callback, arg);
499 JackClientControl* JackDebugClient::GetClientControl() const
501 CheckClient();
502 return fClient->GetClientControl();
505 // Internal clients
506 char* JackDebugClient::GetInternalClientName(int ref)
508 CheckClient();
509 return fClient->GetInternalClientName(ref);
512 int JackDebugClient::InternalClientHandle(const char* client_name, jack_status_t* status)
514 CheckClient();
515 return fClient->InternalClientHandle(client_name, status);
518 int JackDebugClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va)
520 CheckClient();
521 return fClient->InternalClientLoad(client_name, options, status, va);
524 void JackDebugClient::InternalClientUnload(int ref, jack_status_t* status)
526 CheckClient();
527 fClient->InternalClientUnload(ref, status);
530 } // end of namespace