jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

550 lines
19KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackDebugClient.h"
  16. #include "JackEngineControl.h"
  17. #include "JackError.h"
  18. #include "JackTime.h"
  19. #include <iostream>
  20. #include <iomanip>
  21. #include <sstream>
  22. #include <fstream>
  23. #include <string>
  24. #include <time.h>
  25. using namespace std;
  26. namespace Jack
  27. {
  28. JackDebugClient::JackDebugClient(JackClient * client)
  29. {
  30. fTotalPortNumber = 1; // The total number of port opened and maybe closed. Historical view.
  31. fOpenPortNumber = 0; // The current number of opened port.
  32. fIsActivated = 0;
  33. fIsDeactivated = 0;
  34. fIsClosed = 0;
  35. fClient = client;
  36. }
  37. JackDebugClient::~JackDebugClient()
  38. {
  39. fTotalPortNumber--; // fTotalPortNumber start at 1
  40. *fStream << endl << endl << "----------------------------------- JackDebugClient summary ------------------------------- " << endl << endl;
  41. *fStream << "Client flags ( 1:yes / 0:no ) :" << endl;
  42. *fStream << setw(5) << "- Client call activated : " << fIsActivated << endl;
  43. *fStream << setw(5) << "- Client call deactivated : " << fIsDeactivated << endl;
  44. *fStream << setw(5) << "- Client call closed : " << fIsClosed << endl;
  45. *fStream << setw(5) << "- Total number of instantiated port : " << fTotalPortNumber << endl;
  46. *fStream << setw(5) << "- Number of port remaining open when exiting client : " << fOpenPortNumber << endl;
  47. if (fOpenPortNumber != 0)
  48. *fStream << "!!! WARNING !!! Some ports have not been unregistrated ! Incorrect exiting !" << endl;
  49. if (fIsDeactivated != fIsActivated)
  50. *fStream << "!!! ERROR !!! Client seem do not perform symetric activation-deactivation ! (not the same number of activate and deactivate)" << endl;
  51. if (fIsClosed == 0)
  52. *fStream << "!!! ERROR !!! Client have not been closed with jack_client_close() !" << endl;
  53. *fStream << endl << endl << "---------------------------- JackDebugClient detailed port summary ------------------------ " << endl << endl;
  54. //for (int i = 0; i < fTotalPortNumber ; i++) {
  55. for (int i = 1; i <= fTotalPortNumber ; i++) {
  56. *fStream << endl << "Port index (internal debug test value) : " << i << endl;
  57. *fStream << setw(5) << "- Name : " << fPortList[i].name << endl;
  58. *fStream << setw(5) << "- idport : " << fPortList[i].idport << endl;
  59. *fStream << setw(5) << "- IsConnected : " << fPortList[i].IsConnected << endl;
  60. *fStream << setw(5) << "- IsUnregistrated : " << fPortList[i].IsUnregistrated << endl;
  61. if (fPortList[i].IsUnregistrated == 0)
  62. *fStream << "!!! WARNING !!! Port have not been unregistrated ! Incorrect exiting !" << endl;
  63. }
  64. *fStream << "delete object JackDebugClient : end of tracing" << endl;
  65. delete fStream;
  66. delete fClient;
  67. }
  68. int JackDebugClient::Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status)
  69. {
  70. int res = fClient->Open(server_name, name, options, status);
  71. char provstr[256];
  72. char buffer[256];
  73. time_t curtime;
  74. struct tm *loctime;
  75. /* Get the current time. */
  76. curtime = time (NULL);
  77. /* Convert it to local time representation. */
  78. loctime = localtime (&curtime);
  79. strftime (buffer, 256, "%I-%M", loctime);
  80. sprintf(provstr, "JackClientDebug-%s-%s.log", name, buffer);
  81. fStream = new ofstream(provstr, ios_base::ate);
  82. if (fStream->is_open()) {
  83. if (res == -1) {
  84. *fStream << "Trying to open client with name '" << name << "' with bad result (client not opened)." << res << endl;
  85. } else {
  86. *fStream << "Open client with name '" << name << "'." << endl;
  87. }
  88. } else {
  89. JackLog("JackDebugClient::Open : cannot open log file\n");
  90. }
  91. strcpy(fClientName, name);
  92. return res;
  93. }
  94. int JackDebugClient::Close()
  95. {
  96. fIsClosed++;
  97. *fStream << "Client '" << fClientName << "' was closed" << endl;
  98. return fClient->Close();
  99. }
  100. void JackDebugClient::CheckClient() const
  101. {
  102. if (fIsClosed > 0) {
  103. *fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed !" << endl;
  104. *fStream << "This is likely to cause crash !'" << endl;
  105. }
  106. }
  107. pthread_t JackDebugClient::GetThreadID()
  108. {
  109. CheckClient();
  110. return fClient->GetThreadID();
  111. }
  112. JackGraphManager* JackDebugClient::GetGraphManager() const
  113. {
  114. CheckClient();
  115. return fClient->GetGraphManager();
  116. }
  117. JackEngineControl* JackDebugClient::GetEngineControl() const
  118. {
  119. CheckClient();
  120. return fClient->GetEngineControl();
  121. }
  122. /*!
  123. \brief Notification received from the server.
  124. */
  125. int JackDebugClient::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
  126. {
  127. CheckClient();
  128. return fClient->ClientNotify( refnum, name, notify, sync, value1, value2);
  129. }
  130. int JackDebugClient::Activate()
  131. {
  132. CheckClient();
  133. int res = fClient->Activate();
  134. fIsActivated++;
  135. if (fIsDeactivated)
  136. *fStream << "Client '" << fClientName << "' call activate a new time (it already call 'activate' previously)." << endl;
  137. *fStream << "Client '" << fClientName << "' Activated" << endl;
  138. if (res != 0)
  139. *fStream << "Client '" << fClientName << "' try to activate but server return " << res << " ." << endl;
  140. return res;
  141. }
  142. int JackDebugClient::Deactivate()
  143. {
  144. CheckClient();
  145. int res = fClient->Deactivate();
  146. fIsDeactivated++;
  147. if (fIsActivated == 0)
  148. *fStream << "Client '" << fClientName << "' deactivate while it hasn't been previoulsy activated !" << endl;
  149. *fStream << "Client '" << fClientName << "' Deactivated" << endl;
  150. if (res != 0)
  151. *fStream << "Client '" << fClientName << "' try to deactivate but server return " << res << " ." << endl;
  152. return res;
  153. }
  154. //-----------------
  155. // Port management
  156. //-----------------
  157. int JackDebugClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
  158. {
  159. CheckClient();
  160. int res = fClient->PortRegister(port_name, port_type, flags, buffer_size);
  161. if (res <= 0) {
  162. *fStream << "Client '" << fClientName << "' try port register ('" << port_name << "') and server return error " << res << " ." << endl;
  163. } else {
  164. if (fTotalPortNumber < MAX_PORT_HISTORY) {
  165. fPortList[fTotalPortNumber].idport = res;
  166. strcpy(fPortList[fTotalPortNumber].name, port_name);
  167. fPortList[fTotalPortNumber].IsConnected = 0;
  168. fPortList[fTotalPortNumber].IsUnregistrated = 0;
  169. } else {
  170. *fStream << "!!! WARNING !!! History is full : no more port history will be recorded." << endl;
  171. }
  172. fTotalPortNumber++;
  173. fOpenPortNumber++;
  174. *fStream << "Client '" << fClientName << "' port register with portname '" << port_name << " port " << res << "' ." << endl;
  175. }
  176. return res;
  177. }
  178. int JackDebugClient::PortUnRegister(jack_port_id_t port_index)
  179. {
  180. CheckClient();
  181. int res = fClient->PortUnRegister(port_index);
  182. fOpenPortNumber--;
  183. int i;
  184. for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
  185. if (fPortList[i].idport == port_index) { // We found the last record
  186. if (fPortList[i].IsUnregistrated != 0)
  187. *fStream << "!!! ERROR !!! : '" << fClientName << "' id deregistering port '" << fPortList[i].name << "' that have already been unregistered !" << endl;
  188. fPortList[i].IsUnregistrated++;
  189. break;
  190. }
  191. }
  192. if (i == 0) // Port is not found
  193. *fStream << "JackClientDebug : PortUnregister : port " << port_index << " was not previously registered !" << endl;
  194. if (res != 0)
  195. *fStream << "Client '" << fClientName << "' try to do PortUnregister and server return " << res << " )." << endl;
  196. *fStream << "Client '" << fClientName << "' unregister port '" << port_index << "'." << endl;
  197. return res;
  198. }
  199. int JackDebugClient::PortConnect(const char* src, const char* dst)
  200. {
  201. CheckClient();
  202. if (!fIsActivated)
  203. *fStream << "!!! ERROR !!! Trying to connect a port ( " << src << " to " << dst << ") while the client has not been activated !" << endl;
  204. int i;
  205. int res = fClient->PortConnect( src, dst);
  206. for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
  207. if (strcmp(fPortList[i].name, src) == 0) { // We found the last record in sources
  208. if (fPortList[i].IsUnregistrated != 0)
  209. *fStream << "!!! ERROR !!! Connecting port " << src << " previoulsy unregistered !" << endl;
  210. fPortList[i].IsConnected++;
  211. *fStream << "Connecting port " << src << " to " << dst << ". ";
  212. break;
  213. } else if (strcmp(fPortList[i].name, dst) == 0 ) { // We found the record in dest
  214. if (fPortList[i].IsUnregistrated != 0)
  215. *fStream << "!!! ERROR !!! Connecting port " << dst << " previoulsy unregistered !" << endl;
  216. fPortList[i].IsConnected++;
  217. *fStream << "Connecting port " << src << " to " << dst << ". ";
  218. break;
  219. }
  220. }
  221. if (i == 0) // Port is not found
  222. *fStream << "JackClientDebug : PortConnect : port was not found in debug database !" << endl;
  223. if (res != 0)
  224. *fStream << "Client '" << fClientName << "' try to do PortConnect but server return " << res << " ." << endl;
  225. //*fStream << "Client Port Connect done with names" << endl;
  226. return res;
  227. }
  228. int JackDebugClient::PortDisconnect(const char* src, const char* dst)
  229. {
  230. CheckClient();
  231. if (!fIsActivated)
  232. *fStream << "!!! ERROR !!! Trying to disconnect a port ( " << src << " to " << dst << ") while the client has not been activated !" << endl;
  233. int res = fClient->PortDisconnect( src, dst);
  234. int i;
  235. for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
  236. if (strcmp(fPortList[i].name, src) == 0) { // We found the record in sources
  237. if (fPortList[i].IsUnregistrated != 0)
  238. *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl;
  239. fPortList[i].IsConnected--;
  240. *fStream << "disconnecting port " << src << ". ";
  241. break;
  242. } else if (strcmp(fPortList[i].name, dst) == 0 ) { // We found the record in dest
  243. if (fPortList[i].IsUnregistrated != 0)
  244. *fStream << "!!! ERROR !!! : Disonnecting port " << dst << " previoulsy unregistered !" << endl;
  245. fPortList[i].IsConnected--;
  246. *fStream << "disconnecting port " << dst << ". ";
  247. break;
  248. }
  249. }
  250. if (i == 0) // Port is not found
  251. *fStream << "JackClientDebug : PortDisConnect : port was not found in debug database !" << endl;
  252. if (res != 0)
  253. *fStream << "Client '" << fClientName << "' try to do PortDisconnect but server return " << res << " ." << endl;
  254. //*fStream << "Client Port Disconnect done." << endl;
  255. return res;
  256. }
  257. int JackDebugClient::PortConnect(jack_port_id_t src, jack_port_id_t dst)
  258. {
  259. CheckClient();
  260. if (!fIsActivated)
  261. *fStream << "!!! ERROR !!! : Trying to connect port " << src << " to " << dst << " while the client has not been activated !" << endl;
  262. int res = fClient->PortConnect(src, dst);
  263. int i;
  264. for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
  265. if (fPortList[i].idport == src) { // We found the record in sources
  266. if (fPortList[i].IsUnregistrated != 0)
  267. *fStream << "!!! ERROR !!! : Connecting port " << src << " previoulsy unregistered !" << endl;
  268. fPortList[i].IsConnected++;
  269. *fStream << "Connecting port " << src << ". ";
  270. break;
  271. } else if (fPortList[i].idport == dst) { // We found the record in dest
  272. if (fPortList[i].IsUnregistrated != 0)
  273. *fStream << "!!! ERROR !!! : Connecting port " << dst << " previoulsy unregistered !" << endl;
  274. fPortList[i].IsConnected++;
  275. *fStream << "Connecting port " << dst << ". ";
  276. break;
  277. }
  278. }
  279. if (i == 0) // Port is not found
  280. *fStream << "JackClientDebug : PortConnect : port was not found in debug database !" << endl;
  281. if (res == -1)
  282. *fStream << "Client '" << fClientName << "' try to do Portconnect but server return " << res << " ." << endl;
  283. //*fStream << "Client Port Connect with ID done." << endl;
  284. return res;
  285. }
  286. int JackDebugClient::PortDisconnect(jack_port_id_t src)
  287. {
  288. CheckClient();
  289. if (!fIsActivated)
  290. *fStream << "!!! ERROR !!! : Trying to disconnect port " << src << " while that client has not been activated !" << endl;
  291. int res = fClient->PortDisconnect(src);
  292. int i;
  293. for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history
  294. if (fPortList[i].idport == src) { // We found the record in sources
  295. if (fPortList[i].IsUnregistrated != 0)
  296. *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl;
  297. fPortList[i].IsConnected--;
  298. *fStream << "Disconnecting port " << src << ". " << endl;
  299. break;
  300. }
  301. }
  302. if (i == 0) // Port is not found
  303. *fStream << "JackClientDebug : PortDisconnect : port was not found in debug database !" << endl;
  304. if (res != 0)
  305. *fStream << "Client '" << fClientName << "' try to do PortDisconnect but server return " << res << " ." << endl;
  306. //*fStream << "Client Port Disconnect with ID done." << endl;
  307. return res;
  308. }
  309. int JackDebugClient::PortIsMine(jack_port_id_t port_index)
  310. {
  311. CheckClient();
  312. return fClient->PortIsMine(port_index);
  313. }
  314. //--------------------
  315. // Context management
  316. //--------------------
  317. int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size)
  318. {
  319. CheckClient();
  320. return fClient->SetBufferSize(buffer_size);
  321. }
  322. int JackDebugClient::SetFreeWheel(int onoff)
  323. {
  324. CheckClient();
  325. return fClient->SetFreeWheel(onoff);
  326. }
  327. /*
  328. ShutDown is called:
  329. - from the RT thread when Execute method fails
  330. - possibly from a "closed" notification channel
  331. (Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown))
  332. */
  333. void JackDebugClient::ShutDown()
  334. {
  335. fClient->ShutDown();
  336. }
  337. //---------------------
  338. // Transport management
  339. //---------------------
  340. int JackDebugClient::ReleaseTimebase()
  341. {
  342. CheckClient();
  343. return fClient->ReleaseTimebase();
  344. }
  345. int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
  346. {
  347. CheckClient();
  348. return fClient->SetSyncCallback(sync_callback, arg);
  349. }
  350. int JackDebugClient::SetSyncTimeout(jack_time_t timeout)
  351. {
  352. CheckClient();
  353. return fClient->SetSyncTimeout(timeout);
  354. }
  355. int JackDebugClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
  356. {
  357. CheckClient();
  358. return fClient->SetTimebaseCallback( conditional, timebase_callback, arg);
  359. }
  360. int JackDebugClient::TransportLocate(jack_nframes_t frame)
  361. {
  362. CheckClient();
  363. return fClient->TransportLocate(frame);
  364. }
  365. jack_transport_state_t JackDebugClient::TransportQuery(jack_position_t* pos)
  366. {
  367. CheckClient();
  368. return fClient->TransportQuery(pos);
  369. }
  370. jack_nframes_t JackDebugClient::GetCurrentTransportFrame()
  371. {
  372. CheckClient();
  373. return fClient->GetCurrentTransportFrame();
  374. }
  375. int JackDebugClient::TransportReposition(jack_position_t* pos)
  376. {
  377. CheckClient();
  378. return fClient->TransportReposition(pos);
  379. }
  380. void JackDebugClient::TransportStart()
  381. {
  382. CheckClient();
  383. fClient->TransportStart();
  384. }
  385. void JackDebugClient::TransportStop()
  386. {
  387. CheckClient();
  388. fClient->TransportStop();
  389. }
  390. //---------------------
  391. // Callback management
  392. //---------------------
  393. void JackDebugClient::OnShutdown(JackShutdownCallback callback, void *arg)
  394. {
  395. CheckClient();
  396. fClient->OnShutdown(callback, arg);
  397. }
  398. int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg)
  399. {
  400. JackDebugClient* client = (JackDebugClient*)arg;
  401. jack_time_t t1 = GetMicroSeconds();
  402. int res = client->fProcessTimeCallback(nframes, client->fProcessTimeCallbackArg);
  403. jack_time_t t2 = GetMicroSeconds();
  404. long delta = long((t2 - t1) - client->GetEngineControl()->fPeriodUsecs);
  405. if (delta > 0)
  406. *client->fStream << "!!! ERROR !!! : Process overload of " << delta << " us" << endl;
  407. return res;
  408. }
  409. int JackDebugClient::SetProcessCallback(JackProcessCallback callback, void *arg)
  410. {
  411. CheckClient();
  412. fProcessTimeCallback = callback;
  413. fProcessTimeCallbackArg = arg;
  414. return fClient->SetProcessCallback(TimeCallback, this);
  415. }
  416. int JackDebugClient::SetXRunCallback(JackXRunCallback callback, void *arg)
  417. {
  418. CheckClient();
  419. return fClient->SetXRunCallback(callback, arg);
  420. }
  421. int JackDebugClient::SetInitCallback(JackThreadInitCallback callback, void *arg)
  422. {
  423. CheckClient();
  424. return fClient->SetInitCallback(callback, arg);
  425. }
  426. int JackDebugClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
  427. {
  428. CheckClient();
  429. return fClient->SetGraphOrderCallback(callback, arg);
  430. }
  431. int JackDebugClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
  432. {
  433. CheckClient();
  434. return fClient->SetBufferSizeCallback(callback, arg);
  435. }
  436. int JackDebugClient::SetClientRegistrationCallback(JackClientRegistrationCallback callback, void* arg)
  437. {
  438. CheckClient();
  439. return fClient->SetClientRegistrationCallback(callback, arg);
  440. }
  441. int JackDebugClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
  442. {
  443. CheckClient();
  444. return fClient->SetFreewheelCallback(callback, arg);
  445. }
  446. int JackDebugClient::SetPortRegistrationCallback(JackPortRegistrationCallback callback, void *arg)
  447. {
  448. CheckClient();
  449. return fClient->SetPortRegistrationCallback(callback, arg);
  450. }
  451. int JackDebugClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg)
  452. {
  453. CheckClient();
  454. return fClient->SetPortConnectCallback(callback, arg);
  455. }
  456. JackClientControl* JackDebugClient::GetClientControl() const
  457. {
  458. CheckClient();
  459. return fClient->GetClientControl();
  460. }
  461. // Internal clients
  462. char* JackDebugClient::GetInternalClientName(int ref)
  463. {
  464. CheckClient();
  465. return fClient->GetInternalClientName(ref);
  466. }
  467. int JackDebugClient::InternalClientHandle(const char* client_name, jack_status_t* status)
  468. {
  469. CheckClient();
  470. return fClient->InternalClientHandle(client_name, status);
  471. }
  472. int JackDebugClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va)
  473. {
  474. CheckClient();
  475. return fClient->InternalClientLoad(client_name, options, status, va);
  476. }
  477. void JackDebugClient::InternalClientUnload(int ref, jack_status_t* status)
  478. {
  479. CheckClient();
  480. fClient->InternalClientUnload(ref, status);
  481. }
  482. jack_nframes_t JackDebugClient::Wait(int status)
  483. {
  484. CheckClient();
  485. return fClient->Wait(status);
  486. }
  487. } // end of namespace