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.

1510 lines
48KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. Copyright (C) 2004-2006 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackClient.h"
  17. #include "JackError.h"
  18. #include "JackGraphManager.h"
  19. #include "JackEngineControl.h"
  20. #include "JackClientControl.h"
  21. #include "JackGlobals.h"
  22. #include "JackTime.h"
  23. #include "JackExports.h"
  24. #include "JackAPI.h"
  25. #ifdef __APPLE__
  26. #include "JackMachThread.h"
  27. #elif WIN32
  28. #include "JackWinThread.h"
  29. #else
  30. #include "JackPosixThread.h"
  31. #endif
  32. #include <math.h>
  33. #ifdef __CLIENTDEBUG__
  34. #include "JackLibGlobals.h"
  35. #endif
  36. using namespace Jack;
  37. #ifdef __cplusplus
  38. extern "C"
  39. {
  40. #endif
  41. EXPORT int jack_client_name_size (void);
  42. EXPORT char* jack_get_client_name (jack_client_t *client);
  43. EXPORT int jack_internal_client_new (const char *client_name,
  44. const char *load_name,
  45. const char *load_init);
  46. EXPORT void jack_internal_client_close (const char *client_name);
  47. EXPORT int jack_is_realtime (jack_client_t *client);
  48. EXPORT void jack_on_shutdown (jack_client_t *client,
  49. void (*function)(void *arg), void *arg);
  50. EXPORT int jack_set_process_callback (jack_client_t *client,
  51. JackProcessCallback process_callback,
  52. void *arg);
  53. EXPORT int jack_set_thread_init_callback (jack_client_t *client,
  54. JackThreadInitCallback thread_init_callback,
  55. void *arg);
  56. EXPORT int jack_set_freewheel_callback (jack_client_t *client,
  57. JackFreewheelCallback freewheel_callback,
  58. void *arg);
  59. EXPORT int jack_set_freewheel(jack_client_t* client, int onoff);
  60. EXPORT int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes);
  61. EXPORT int jack_set_buffer_size_callback (jack_client_t *client,
  62. JackBufferSizeCallback bufsize_callback,
  63. void *arg);
  64. EXPORT int jack_set_sample_rate_callback (jack_client_t *client,
  65. JackSampleRateCallback srate_callback,
  66. void *arg);
  67. EXPORT int jack_set_client_registration_callback (jack_client_t *,
  68. JackClientRegistrationCallback
  69. registration_callback, void *arg);
  70. EXPORT int jack_set_port_registration_callback (jack_client_t *,
  71. JackPortRegistrationCallback
  72. registration_callback, void *arg);
  73. EXPORT int jack_set_graph_order_callback (jack_client_t *,
  74. JackGraphOrderCallback graph_callback,
  75. void *);
  76. EXPORT int jack_set_xrun_callback (jack_client_t *,
  77. JackXRunCallback xrun_callback, void *arg);
  78. EXPORT int jack_activate (jack_client_t *client);
  79. EXPORT int jack_deactivate (jack_client_t *client);
  80. EXPORT jack_port_t * jack_port_register (jack_client_t *client,
  81. const char *port_name,
  82. const char *port_type,
  83. unsigned long flags,
  84. unsigned long buffer_size);
  85. EXPORT int jack_port_unregister (jack_client_t *, jack_port_t *);
  86. EXPORT void * jack_port_get_buffer (jack_port_t *, jack_nframes_t);
  87. EXPORT const char * jack_port_name (const jack_port_t *port);
  88. EXPORT const char * jack_port_short_name (const jack_port_t *port);
  89. EXPORT int jack_port_flags (const jack_port_t *port);
  90. EXPORT const char * jack_port_type (const jack_port_t *port);
  91. EXPORT int jack_port_is_mine (const jack_client_t *, const jack_port_t *port);
  92. EXPORT int jack_port_connected (const jack_port_t *port);
  93. EXPORT int jack_port_connected_to (const jack_port_t *port,
  94. const char *port_name);
  95. EXPORT const char ** jack_port_get_connections (const jack_port_t *port);
  96. EXPORT const char ** jack_port_get_all_connections (const jack_client_t *client,
  97. const jack_port_t *port);
  98. EXPORT int jack_port_tie (jack_port_t *src, jack_port_t *dst);
  99. EXPORT int jack_port_untie (jack_port_t *port);
  100. EXPORT int jack_port_lock (jack_client_t *, jack_port_t *);
  101. EXPORT int jack_port_unlock (jack_client_t *, jack_port_t *);
  102. EXPORT jack_nframes_t jack_port_get_latency (jack_port_t *port);
  103. EXPORT jack_nframes_t jack_port_get_total_latency (jack_client_t *,
  104. jack_port_t *port);
  105. EXPORT void jack_port_set_latency (jack_port_t *, jack_nframes_t);
  106. EXPORT int jack_recompute_total_latencies (jack_client_t*);
  107. EXPORT int jack_port_set_name (jack_port_t *port, const char *port_name);
  108. EXPORT int jack_port_set_alias (jack_port_t *port, const char *alias);
  109. EXPORT int jack_port_unset_alias (jack_port_t *port, const char *alias);
  110. EXPORT int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]);
  111. EXPORT int jack_port_request_monitor (jack_port_t *port, int onoff);
  112. EXPORT int jack_port_request_monitor_by_name (jack_client_t *client,
  113. const char *port_name, int onoff);
  114. EXPORT int jack_port_ensure_monitor (jack_port_t *port, int onoff);
  115. EXPORT int jack_port_monitoring_input (jack_port_t *port);
  116. EXPORT int jack_connect (jack_client_t *,
  117. const char *source_port,
  118. const char *destination_port);
  119. EXPORT int jack_disconnect (jack_client_t *,
  120. const char *source_port,
  121. const char *destination_port);
  122. EXPORT int jack_port_disconnect (jack_client_t *, jack_port_t *);
  123. EXPORT int jack_port_name_size(void);
  124. EXPORT int jack_port_type_size(void);
  125. EXPORT jack_nframes_t jack_get_sample_rate (jack_client_t *);
  126. EXPORT jack_nframes_t jack_get_buffer_size (jack_client_t *);
  127. EXPORT const char ** jack_get_ports (jack_client_t *,
  128. const char *port_name_pattern,
  129. const char *type_name_pattern,
  130. unsigned long flags);
  131. EXPORT jack_port_t * jack_port_by_name (jack_client_t *, const char *port_name);
  132. EXPORT jack_port_t * jack_port_by_id (jack_client_t *client,
  133. jack_port_id_t port_id);
  134. EXPORT int jack_engine_takeover_timebase (jack_client_t *);
  135. EXPORT jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *);
  136. EXPORT jack_time_t jack_get_time(const jack_client_t *client);
  137. EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t time);
  138. EXPORT jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t frames);
  139. EXPORT jack_nframes_t jack_frame_time (const jack_client_t *);
  140. EXPORT jack_nframes_t jack_last_frame_time (const jack_client_t *client);
  141. EXPORT float jack_cpu_load (jack_client_t *client);
  142. EXPORT pthread_t jack_client_thread_id (jack_client_t *);
  143. EXPORT void jack_set_error_function (void (*func)(const char *));
  144. EXPORT float jack_get_max_delayed_usecs (jack_client_t *client);
  145. EXPORT float jack_get_xrun_delayed_usecs (jack_client_t *client);
  146. EXPORT void jack_reset_max_delayed_usecs (jack_client_t *client);
  147. EXPORT int jack_release_timebase (jack_client_t *client);
  148. EXPORT int jack_set_sync_callback (jack_client_t *client,
  149. JackSyncCallback sync_callback,
  150. void *arg);
  151. EXPORT int jack_set_sync_timeout (jack_client_t *client,
  152. jack_time_t timeout);
  153. EXPORT int jack_set_timebase_callback (jack_client_t *client,
  154. int conditional,
  155. JackTimebaseCallback timebase_callback,
  156. void *arg);
  157. EXPORT int jack_transport_locate (jack_client_t *client,
  158. jack_nframes_t frame);
  159. EXPORT jack_transport_state_t jack_transport_query (const jack_client_t *client,
  160. jack_position_t *pos);
  161. EXPORT jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client);
  162. EXPORT int jack_transport_reposition (jack_client_t *client,
  163. jack_position_t *pos);
  164. EXPORT void jack_transport_start (jack_client_t *client);
  165. EXPORT void jack_transport_stop (jack_client_t *client);
  166. EXPORT void jack_get_transport_info (jack_client_t *client,
  167. jack_transport_info_t *tinfo);
  168. EXPORT void jack_set_transport_info (jack_client_t *client,
  169. jack_transport_info_t *tinfo);
  170. EXPORT int jack_acquire_real_time_scheduling (pthread_t thread, int priority);
  171. EXPORT int jack_client_create_thread (jack_client_t* client,
  172. pthread_t *thread,
  173. int priority,
  174. int realtime, // boolean
  175. void *(*start_routine)(void*),
  176. void *arg);
  177. EXPORT int jack_drop_real_time_scheduling (pthread_t thread);
  178. EXPORT char * jack_get_internal_client_name (jack_client_t *client,
  179. jack_intclient_t intclient);
  180. EXPORT jack_intclient_t jack_internal_client_handle (jack_client_t *client,
  181. const char *client_name,
  182. jack_status_t *status);
  183. EXPORT jack_intclient_t jack_internal_client_load (jack_client_t *client,
  184. const char *client_name,
  185. jack_options_t options,
  186. jack_status_t *status, ...);
  187. EXPORT jack_status_t jack_internal_client_unload (jack_client_t *client,
  188. jack_intclient_t intclient);
  189. #ifdef __cplusplus
  190. }
  191. #endif
  192. #ifdef WIN32
  193. /* missing on Windows : see http://bugs.mysql.com/bug.php?id=15936 */
  194. inline double rint(double nr)
  195. {
  196. double f = floor(nr);
  197. double c = ceil(nr);
  198. return (((c -nr) >= (nr - f)) ? f : c);
  199. }
  200. #endif
  201. static inline bool CheckPort(jack_port_id_t port_index)
  202. {
  203. return (port_index < PORT_NUM);
  204. }
  205. static inline bool CheckBufferSize(jack_nframes_t buffer_size)
  206. {
  207. return (buffer_size <= BUFFER_SIZE_MAX);
  208. }
  209. static inline void WaitGraphChange()
  210. {
  211. if (GetGraphManager()->IsPendingChange()) {
  212. JackLog("WaitGraphChange...\n");
  213. JackSleep(GetEngineControl()->fPeriodUsecs * 2);
  214. }
  215. }
  216. static void default_jack_error_callback(const char *desc)
  217. {
  218. fprintf(stderr, "%s\n", desc);
  219. }
  220. void (*jack_error_callback)(const char *desc) = &default_jack_error_callback;
  221. EXPORT void jack_set_error_function (void (*func)(const char *))
  222. {
  223. jack_error_callback = func;
  224. }
  225. EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames)
  226. {
  227. #ifdef __CLIENTDEBUG__
  228. JackLibGlobals::CheckContext();
  229. #endif
  230. jack_port_id_t myport = (jack_port_id_t)port;
  231. if (!CheckPort(myport)) {
  232. jack_error("jack_port_get_buffer called with an incorrect port %ld", myport);
  233. return NULL;
  234. } else {
  235. return GetGraphManager()->GetBuffer(myport, frames);
  236. }
  237. }
  238. EXPORT const char* jack_port_name(const jack_port_t* port)
  239. {
  240. #ifdef __CLIENTDEBUG__
  241. JackLibGlobals::CheckContext();
  242. #endif
  243. jack_port_id_t myport = (jack_port_id_t)port;
  244. if (!CheckPort(myport)) {
  245. jack_error("jack_port_name called with an incorrect port %ld", myport);
  246. return NULL;
  247. } else {
  248. return GetGraphManager()->GetPort(myport)->GetName();
  249. }
  250. }
  251. EXPORT const char* jack_port_short_name(const jack_port_t* port)
  252. {
  253. #ifdef __CLIENTDEBUG__
  254. JackLibGlobals::CheckContext();
  255. #endif
  256. jack_port_id_t myport = (jack_port_id_t)port;
  257. if (!CheckPort(myport)) {
  258. jack_error("jack_port_short_name called with an incorrect port %ld", myport);
  259. return NULL;
  260. } else {
  261. return GetGraphManager()->GetPort(myport)->GetShortName();
  262. }
  263. }
  264. EXPORT int jack_port_flags(const jack_port_t* port)
  265. {
  266. #ifdef __CLIENTDEBUG__
  267. JackLibGlobals::CheckContext();
  268. #endif
  269. jack_port_id_t myport = (jack_port_id_t)port;
  270. if (!CheckPort(myport)) {
  271. jack_error("jack_port_flags called with an incorrect port %ld", myport);
  272. return -1;
  273. } else {
  274. return GetGraphManager()->GetPort(myport)->Flags();
  275. }
  276. }
  277. EXPORT const char* jack_port_type(const jack_port_t* port)
  278. {
  279. #ifdef __CLIENTDEBUG__
  280. JackLibGlobals::CheckContext();
  281. #endif
  282. jack_port_id_t myport = (jack_port_id_t)port;
  283. if (!CheckPort(myport)) {
  284. jack_error("jack_port_flags called an incorrect port %ld", myport);
  285. return NULL;
  286. } else {
  287. return GetGraphManager()->GetPort(myport)->Type();
  288. }
  289. }
  290. EXPORT int jack_port_connected(const jack_port_t* port)
  291. {
  292. #ifdef __CLIENTDEBUG__
  293. JackLibGlobals::CheckContext();
  294. #endif
  295. jack_port_id_t myport = (jack_port_id_t)port;
  296. if (!CheckPort(myport)) {
  297. jack_error("jack_port_connected called with an incorrect port %ld", myport);
  298. return -1;
  299. } else {
  300. WaitGraphChange();
  301. return GetGraphManager()->GetConnectionsNum(myport);
  302. }
  303. }
  304. EXPORT int jack_port_connected_to(const jack_port_t* port, const char* portname)
  305. {
  306. #ifdef __CLIENTDEBUG__
  307. JackLibGlobals::CheckContext();
  308. #endif
  309. jack_port_id_t myport = (jack_port_id_t)port;
  310. if (!CheckPort(myport)) {
  311. jack_error("jack_port_connected_to called with an incorrect port %ld", myport);
  312. return -1;
  313. } else if (portname == NULL) {
  314. jack_error("jack_port_connected_to called with a NULL port name");
  315. return -1;
  316. } else {
  317. WaitGraphChange();
  318. return GetGraphManager()->ConnectedTo(myport, portname);
  319. }
  320. }
  321. EXPORT int jack_port_tie(jack_port_t* src, jack_port_t* dst)
  322. {
  323. #ifdef __CLIENTDEBUG__
  324. JackLibGlobals::CheckContext();
  325. #endif
  326. jack_port_id_t mysrc = (jack_port_id_t)src;
  327. if (!CheckPort(mysrc)) {
  328. jack_error("jack_port_tie called with a NULL src port");
  329. return -1;
  330. }
  331. jack_port_id_t mydst = (jack_port_id_t)dst;
  332. if (!CheckPort(mydst)) {
  333. jack_error("jack_port_tie called with a NULL dst port");
  334. return -1;
  335. }
  336. if (GetGraphManager()->GetPort(mysrc)->GetRefNum() != GetGraphManager()->GetPort(mydst)->GetRefNum()) {
  337. jack_error("jack_port_tie called with ports not belonging to the same client");
  338. return -1;
  339. }
  340. return GetGraphManager()->GetPort(mydst)->Tie(mysrc);
  341. }
  342. EXPORT int jack_port_untie(jack_port_t* port)
  343. {
  344. #ifdef __CLIENTDEBUG__
  345. JackLibGlobals::CheckContext();
  346. #endif
  347. jack_port_id_t myport = (jack_port_id_t)port;
  348. if (!CheckPort(myport)) {
  349. jack_error("jack_port_untie called with an incorrect port %ld", myport);
  350. return -1;
  351. } else {
  352. return GetGraphManager()->GetPort(myport)->UnTie();
  353. }
  354. }
  355. EXPORT jack_nframes_t jack_port_get_latency(jack_port_t* port)
  356. {
  357. #ifdef __CLIENTDEBUG__
  358. JackLibGlobals::CheckContext();
  359. #endif
  360. jack_port_id_t myport = (jack_port_id_t)port;
  361. if (!CheckPort(myport)) {
  362. jack_error("jack_port_get_latency called with an incorrect port %ld", myport);
  363. return 0;
  364. } else {
  365. WaitGraphChange();
  366. return GetGraphManager()->GetPort(myport)->GetLatency();
  367. }
  368. }
  369. EXPORT void jack_port_set_latency(jack_port_t* port, jack_nframes_t frames)
  370. {
  371. #ifdef __CLIENTDEBUG__
  372. JackLibGlobals::CheckContext();
  373. #endif
  374. jack_port_id_t myport = (jack_port_id_t)port;
  375. if (!CheckPort(myport)) {
  376. jack_error("jack_port_set_latency called with an incorrect port %ld", myport);
  377. } else {
  378. GetGraphManager()->GetPort(myport)->SetLatency(frames);
  379. }
  380. }
  381. EXPORT int jack_recompute_total_latencies(jack_client_t* ext_client)
  382. {
  383. // The latency computation is done each time jack_port_get_total_latency is called
  384. return 0;
  385. }
  386. EXPORT int jack_port_set_name(jack_port_t* port, const char* name)
  387. {
  388. #ifdef __CLIENTDEBUG__
  389. JackLibGlobals::CheckContext();
  390. #endif
  391. jack_port_id_t myport = (jack_port_id_t)port;
  392. if (!CheckPort(myport)) {
  393. jack_error("jack_port_set_name called with an incorrect port %ld", myport);
  394. return -1;
  395. } else if (name == NULL) {
  396. jack_error("jack_port_set_name called with a NULL port name");
  397. return -1;
  398. } else {
  399. return GetGraphManager()->GetPort(myport)->SetName(name);
  400. }
  401. }
  402. EXPORT int jack_port_set_alias(jack_port_t* port, const char* name)
  403. {
  404. #ifdef __CLIENTDEBUG__
  405. JackLibGlobals::CheckContext();
  406. #endif
  407. jack_port_id_t myport = (jack_port_id_t)port;
  408. if (!CheckPort(myport)) {
  409. jack_error("jack_port_set_alias called with an incorrect port %ld", myport);
  410. return -1;
  411. } else if (name == NULL) {
  412. jack_error("jack_port_set_alias called with a NULL port name");
  413. return -1;
  414. } else {
  415. return GetGraphManager()->GetPort(myport)->SetAlias(name);
  416. }
  417. }
  418. EXPORT int jack_port_unset_alias(jack_port_t* port, const char* name)
  419. {
  420. #ifdef __CLIENTDEBUG__
  421. JackLibGlobals::CheckContext();
  422. #endif
  423. jack_port_id_t myport = (jack_port_id_t)port;
  424. if (!CheckPort(myport)) {
  425. jack_error("jack_port_unset_alias called with an incorrect port %ld", myport);
  426. return -1;
  427. } else if (name == NULL) {
  428. jack_error("jack_port_unset_alias called with a NULL port name");
  429. return -1;
  430. } else {
  431. return GetGraphManager()->GetPort(myport)->UnsetAlias(name);
  432. }
  433. }
  434. EXPORT int jack_port_get_aliases(const jack_port_t* port, char* const aliases[2])
  435. {
  436. #ifdef __CLIENTDEBUG__
  437. JackLibGlobals::CheckContext();
  438. #endif
  439. jack_port_id_t myport = (jack_port_id_t)port;
  440. if (!CheckPort(myport)) {
  441. jack_error("jack_port_get_aliases called with an incorrect port %ld", myport);
  442. return -1;
  443. } else {
  444. return GetGraphManager()->GetPort(myport)->GetAliases(aliases);
  445. }
  446. }
  447. EXPORT int jack_port_request_monitor(jack_port_t* port, int onoff)
  448. {
  449. #ifdef __CLIENTDEBUG__
  450. JackLibGlobals::CheckContext();
  451. #endif
  452. jack_port_id_t myport = (jack_port_id_t)port;
  453. if (!CheckPort(myport)) {
  454. jack_error("jack_port_request_monitor called with an incorrect port %ld", myport);
  455. return -1;
  456. } else {
  457. return GetGraphManager()->RequestMonitor(myport, onoff);
  458. }
  459. }
  460. EXPORT int jack_port_request_monitor_by_name(jack_client_t* ext_client, const char* port_name, int onoff)
  461. {
  462. #ifdef __CLIENTDEBUG__
  463. JackLibGlobals::CheckContext();
  464. #endif
  465. JackClient* client = (JackClient*)ext_client;
  466. if (client == NULL) {
  467. jack_error("jack_port_request_monitor_by_name called with a NULL client");
  468. return -1;
  469. } else {
  470. jack_port_id_t myport = GetGraphManager()->GetPort(port_name);
  471. if (!CheckPort(myport)) {
  472. jack_error("jack_port_request_monitor_by_name called with an incorrect port %s", port_name);
  473. return -1;
  474. } else {
  475. return GetGraphManager()->RequestMonitor(myport, onoff);
  476. }
  477. }
  478. }
  479. EXPORT int jack_port_ensure_monitor(jack_port_t* port, int onoff)
  480. {
  481. #ifdef __CLIENTDEBUG__
  482. JackLibGlobals::CheckContext();
  483. #endif
  484. jack_port_id_t myport = (jack_port_id_t)port;
  485. if (!CheckPort(myport)) {
  486. jack_error("jack_port_ensure_monitor called with an incorrect port %ld", myport);
  487. return -1;
  488. } else {
  489. return GetGraphManager()->GetPort(myport)->EnsureMonitor(onoff);
  490. }
  491. }
  492. EXPORT int jack_port_monitoring_input(jack_port_t* port)
  493. {
  494. #ifdef __CLIENTDEBUG__
  495. JackLibGlobals::CheckContext();
  496. #endif
  497. jack_port_id_t myport = (jack_port_id_t)port;
  498. if (!CheckPort(myport)) {
  499. jack_error("jack_port_monitoring_input called with an incorrect port %ld", myport);
  500. return -1;
  501. } else {
  502. return GetGraphManager()->GetPort(myport)->MonitoringInput();
  503. }
  504. }
  505. EXPORT int jack_is_realtime(jack_client_t* ext_client)
  506. {
  507. #ifdef __CLIENTDEBUG__
  508. JackLibGlobals::CheckContext();
  509. #endif
  510. JackClient* client = (JackClient*)ext_client;
  511. if (client == NULL) {
  512. jack_error("jack_is_realtime called with a NULL client");
  513. return -1;
  514. } else {
  515. return GetEngineControl()->fRealTime;
  516. }
  517. }
  518. EXPORT void jack_on_shutdown(jack_client_t* ext_client, void (*function)(void* arg), void* arg)
  519. {
  520. #ifdef __CLIENTDEBUG__
  521. JackLibGlobals::CheckContext();
  522. #endif
  523. JackClient* client = (JackClient*)ext_client;
  524. if (client == NULL) {
  525. jack_error("jack_on_shutdown called with a NULL client");
  526. } else {
  527. client->OnShutdown(function, arg);
  528. }
  529. }
  530. EXPORT int jack_set_process_callback(jack_client_t* ext_client, JackProcessCallback callback, void* arg)
  531. {
  532. #ifdef __CLIENTDEBUG__
  533. JackLibGlobals::CheckContext();
  534. #endif
  535. JackClient* client = (JackClient*)ext_client;
  536. if (client == NULL) {
  537. jack_error("jack_set_process_callback called with a NULL client");
  538. return -1;
  539. } else {
  540. return client->SetProcessCallback(callback, arg);
  541. }
  542. }
  543. EXPORT int jack_set_freewheel_callback(jack_client_t* ext_client, JackFreewheelCallback freewheel_callback, void* arg)
  544. {
  545. #ifdef __CLIENTDEBUG__
  546. JackLibGlobals::CheckContext();
  547. #endif
  548. JackClient* client = (JackClient*)ext_client;
  549. if (client == NULL) {
  550. jack_error("jack_set_freewheel_callback called with a NULL client");
  551. return -1;
  552. } else {
  553. return client->SetFreewheelCallback(freewheel_callback, arg);
  554. }
  555. }
  556. EXPORT int jack_set_freewheel(jack_client_t* ext_client, int onoff)
  557. {
  558. #ifdef __CLIENTDEBUG__
  559. JackLibGlobals::CheckContext();
  560. #endif
  561. JackClient* client = (JackClient*)ext_client;
  562. if (client == NULL) {
  563. jack_error("jack_set_freewheel called with a NULL client");
  564. return -1;
  565. } else {
  566. return client->SetFreeWheel(onoff);
  567. }
  568. }
  569. EXPORT int jack_set_buffer_size(jack_client_t* ext_client, jack_nframes_t buffer_size)
  570. {
  571. #ifdef __CLIENTDEBUG__
  572. JackLibGlobals::CheckContext();
  573. #endif
  574. JackClient* client = (JackClient*)ext_client;
  575. if (client == NULL) {
  576. jack_error("jack_set_buffer_size called with a NULL client");
  577. return -1;
  578. } else if (!CheckBufferSize(buffer_size)) {
  579. return -1;
  580. } else {
  581. return client->SetBufferSize(buffer_size);
  582. }
  583. }
  584. EXPORT int jack_set_buffer_size_callback(jack_client_t* ext_client, JackBufferSizeCallback bufsize_callback, void* arg)
  585. {
  586. #ifdef __CLIENTDEBUG__
  587. JackLibGlobals::CheckContext();
  588. #endif
  589. JackClient* client = (JackClient*)ext_client;
  590. if (client == NULL) {
  591. jack_error("jack_set_buffer_size_callback called with a NULL client");
  592. return -1;
  593. } else {
  594. return client->SetBufferSizeCallback(bufsize_callback, arg);
  595. }
  596. }
  597. EXPORT int jack_set_sample_rate_callback(jack_client_t* ext_client, JackSampleRateCallback srate_callback, void* arg)
  598. {
  599. #ifdef __CLIENTDEBUG__
  600. JackLibGlobals::CheckContext();
  601. #endif
  602. JackClient* client = (JackClient*)ext_client;
  603. if (client == NULL) {
  604. jack_error("jack_set_sample_rate_callback called with a NULL client");
  605. return -1;
  606. } else {
  607. jack_error("jack_set_sample_rate_callback: deprecated");
  608. return 0;
  609. }
  610. }
  611. EXPORT int jack_set_client_registration_callback(jack_client_t* ext_client, JackClientRegistrationCallback registration_callback, void* arg)
  612. {
  613. #ifdef __CLIENTDEBUG__
  614. JackLibGlobals::CheckContext();
  615. #endif
  616. JackClient* client = (JackClient*)ext_client;
  617. if (client == NULL) {
  618. jack_error("jack_set_client_registration_callback called with a NULL client");
  619. return -1;
  620. } else {
  621. return client->SetClientRegistrationCallback(registration_callback, arg);
  622. }
  623. }
  624. EXPORT int jack_set_port_registration_callback(jack_client_t* ext_client, JackPortRegistrationCallback registration_callback, void* arg)
  625. {
  626. #ifdef __CLIENTDEBUG__
  627. JackLibGlobals::CheckContext();
  628. #endif
  629. JackClient* client = (JackClient*)ext_client;
  630. if (client == NULL) {
  631. jack_error("jack_set_port_registration_callback called with a NULL client");
  632. return -1;
  633. } else {
  634. return client->SetPortRegistrationCallback(registration_callback, arg);
  635. }
  636. }
  637. EXPORT int jack_set_graph_order_callback(jack_client_t* ext_client, JackGraphOrderCallback graph_callback, void* arg)
  638. {
  639. #ifdef __CLIENTDEBUG__
  640. JackLibGlobals::CheckContext();
  641. #endif
  642. JackClient* client = (JackClient*)ext_client;
  643. JackLog("jack_set_graph_order_callback ext_client %x client %x \n", ext_client, client);
  644. if (client == NULL) {
  645. jack_error("jack_set_graph_order_callback called with a NULL client");
  646. return -1;
  647. } else {
  648. return client->SetGraphOrderCallback(graph_callback, arg);
  649. }
  650. }
  651. EXPORT int jack_set_xrun_callback(jack_client_t* ext_client, JackXRunCallback xrun_callback, void* arg)
  652. {
  653. #ifdef __CLIENTDEBUG__
  654. JackLibGlobals::CheckContext();
  655. #endif
  656. JackClient* client = (JackClient*)ext_client;
  657. if (client == NULL) {
  658. jack_error("jack_set_xrun_callback called with a NULL client");
  659. return -1;
  660. } else {
  661. return client->SetXRunCallback(xrun_callback, arg);
  662. }
  663. }
  664. EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg)
  665. {
  666. #ifdef __CLIENTDEBUG__
  667. JackLibGlobals::CheckContext();
  668. #endif
  669. JackClient* client = (JackClient*)ext_client;
  670. JackLog("jack_set_thread_init_callback ext_client %x client %x \n", ext_client, client);
  671. if (client == NULL) {
  672. jack_error("jack_set_thread_init_callback called with a NULL client");
  673. return -1;
  674. } else {
  675. return client->SetInitCallback(init_callback, arg);
  676. }
  677. }
  678. EXPORT int jack_activate(jack_client_t* ext_client)
  679. {
  680. #ifdef __CLIENTDEBUG__
  681. JackLibGlobals::CheckContext();
  682. #endif
  683. JackClient* client = (JackClient*)ext_client;
  684. if (client == NULL) {
  685. jack_error("jack_activate called with a NULL client");
  686. return -1;
  687. } else {
  688. return client->Activate();
  689. }
  690. }
  691. EXPORT int jack_deactivate(jack_client_t* ext_client)
  692. {
  693. #ifdef __CLIENTDEBUG__
  694. JackLibGlobals::CheckContext();
  695. #endif
  696. JackClient* client = (JackClient*)ext_client;
  697. if (client == NULL) {
  698. jack_error("jack_deactivate called with a NULL client");
  699. return -1;
  700. } else {
  701. return client->Deactivate();
  702. }
  703. }
  704. EXPORT jack_port_t* jack_port_register(jack_client_t* ext_client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
  705. {
  706. #ifdef __CLIENTDEBUG__
  707. JackLibGlobals::CheckContext();
  708. #endif
  709. JackClient* client = (JackClient*)ext_client;
  710. if (client == NULL) {
  711. jack_error("jack_port_register called with a NULL client");
  712. return NULL;
  713. } else if ((port_name == NULL) || (port_type == NULL)) {
  714. jack_error("jack_port_register called with a NULL port name or a NULL port_type");
  715. return NULL;
  716. } else {
  717. return (jack_port_t *)client->PortRegister(port_name, port_type, flags, buffer_size);
  718. }
  719. }
  720. EXPORT int jack_port_unregister(jack_client_t* ext_client, jack_port_t* port)
  721. {
  722. #ifdef __CLIENTDEBUG__
  723. JackLibGlobals::CheckContext();
  724. #endif
  725. JackClient* client = (JackClient*)ext_client;
  726. if (client == NULL) {
  727. jack_error("jack_port_unregister called with a NULL client");
  728. return -1;
  729. }
  730. jack_port_id_t myport = (jack_port_id_t)port;
  731. if (!CheckPort(myport)) {
  732. jack_error("jack_port_unregister called with an incorrect port %ld", myport);
  733. return -1;
  734. }
  735. return client->PortUnRegister(myport);
  736. }
  737. EXPORT int jack_port_is_mine(const jack_client_t* ext_client, const jack_port_t* port)
  738. {
  739. #ifdef __CLIENTDEBUG__
  740. JackLibGlobals::CheckContext();
  741. #endif
  742. JackClient* client = (JackClient*)ext_client;
  743. if (client == NULL) {
  744. jack_error("jack_port_is_mine called with a NULL client");
  745. return -1;
  746. }
  747. jack_port_id_t myport = (jack_port_id_t)port;
  748. if (!CheckPort(myport)) {
  749. jack_error("jack_port_is_mine called with an incorrect port %ld", myport);
  750. return -1;
  751. }
  752. return client->PortIsMine(myport);
  753. }
  754. EXPORT const char** jack_port_get_connections(const jack_port_t* port)
  755. {
  756. #ifdef __CLIENTDEBUG__
  757. JackLibGlobals::CheckContext();
  758. #endif
  759. jack_port_id_t myport = (jack_port_id_t)port;
  760. if (!CheckPort(myport)) {
  761. jack_error("jack_port_get_connections called with an incorrect port %ld", myport);
  762. return NULL;
  763. } else {
  764. WaitGraphChange();
  765. return GetGraphManager()->GetConnections(myport);
  766. }
  767. }
  768. // Calling client does not need to "own" the port
  769. EXPORT const char** jack_port_get_all_connections(const jack_client_t* ext_client, const jack_port_t* port)
  770. {
  771. #ifdef __CLIENTDEBUG__
  772. JackLibGlobals::CheckContext();
  773. #endif
  774. JackClient* client = (JackClient*)ext_client;
  775. if (client == NULL) {
  776. jack_error("jack_port_get_all_connections called with a NULL client");
  777. return NULL;
  778. }
  779. jack_port_id_t myport = (jack_port_id_t)port;
  780. if (!CheckPort(myport)) {
  781. jack_error("jack_port_get_all_connections called with an incorrect port %ld", myport);
  782. return NULL;
  783. } else {
  784. WaitGraphChange();
  785. return GetGraphManager()->GetConnections(myport);
  786. }
  787. }
  788. // Does not use the client parameter
  789. EXPORT int jack_port_lock(jack_client_t* ext_client, jack_port_t* port)
  790. {
  791. #ifdef __CLIENTDEBUG__
  792. JackLibGlobals::CheckContext();
  793. #endif
  794. JackClient* client = (JackClient*)ext_client;
  795. if (client == NULL) {
  796. jack_error("jack_port_lock called with a NULL client");
  797. return -1;
  798. }
  799. jack_port_id_t myport = (jack_port_id_t)port;
  800. if (!CheckPort(myport)) {
  801. jack_error("jack_port_lock called with an incorrect port %ld", myport);
  802. return -1;
  803. } else {
  804. return (myport && client->PortIsMine(myport)) ? GetGraphManager()->GetPort(myport)->Lock() : -1;
  805. }
  806. }
  807. // Does not use the client parameter
  808. EXPORT int jack_port_unlock(jack_client_t* ext_client, jack_port_t* port)
  809. {
  810. #ifdef __CLIENTDEBUG__
  811. JackLibGlobals::CheckContext();
  812. #endif
  813. JackClient* client = (JackClient*)ext_client;
  814. if (client == NULL) {
  815. jack_error("jack_port_unlock called with a NULL client");
  816. return -1;
  817. }
  818. jack_port_id_t myport = (jack_port_id_t)port;
  819. if (!CheckPort(myport)) {
  820. jack_error("jack_port_unlock called with an incorrect port %ld", myport);
  821. return -1;
  822. } else {
  823. return (myport && client->PortIsMine(myport)) ? GetGraphManager()->GetPort(myport)->Unlock() : -1;
  824. }
  825. }
  826. EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t* ext_client, jack_port_t* port)
  827. {
  828. #ifdef __CLIENTDEBUG__
  829. JackLibGlobals::CheckContext();
  830. #endif
  831. JackClient* client = (JackClient*)ext_client;
  832. if (client == NULL) {
  833. jack_error("jack_port_get_total_latency called with a NULL client");
  834. return 0;
  835. }
  836. jack_port_id_t myport = (jack_port_id_t)port;
  837. if (!CheckPort(myport)) {
  838. jack_error("jack_port_get_total_latency called with an incorrect port %ld", myport);
  839. return 0;
  840. } else {
  841. // The latency computation is done each time
  842. WaitGraphChange();
  843. return GetGraphManager()->GetTotalLatency(myport);
  844. }
  845. }
  846. EXPORT int jack_connect(jack_client_t* ext_client, const char* src, const char* dst)
  847. {
  848. #ifdef __CLIENTDEBUG__
  849. JackLibGlobals::CheckContext();
  850. #endif
  851. JackClient* client = (JackClient*)ext_client;
  852. if (client == NULL) {
  853. jack_error("jack_connect called with a NULL client");
  854. return -1;
  855. } else if ((src == NULL) || (dst == NULL)) {
  856. jack_error("jack_connect called with a NULL port name");
  857. return -1;
  858. } else {
  859. return client->PortConnect(src, dst);
  860. }
  861. }
  862. EXPORT int jack_disconnect(jack_client_t* ext_client, const char* src, const char* dst)
  863. {
  864. #ifdef __CLIENTDEBUG__
  865. JackLibGlobals::CheckContext();
  866. #endif
  867. JackClient* client = (JackClient*)ext_client;
  868. if (client == NULL) {
  869. jack_error("jack_disconnect called with a NULL client");
  870. return -1;
  871. } else if ((src == NULL) || (dst == NULL)) {
  872. jack_error("jack_connect called with a NULL port name");
  873. return -1;
  874. } else {
  875. return client->PortDisconnect(src, dst);
  876. }
  877. }
  878. EXPORT int jack_port_connect(jack_client_t* ext_client, jack_port_t* src, jack_port_t* dst)
  879. {
  880. #ifdef __CLIENTDEBUG__
  881. JackLibGlobals::CheckContext();
  882. #endif
  883. JackClient* client = (JackClient*)ext_client;
  884. if (client == NULL) {
  885. jack_error("jack_port_connect called with a NULL client");
  886. return -1;
  887. }
  888. jack_port_id_t mysrc = (jack_port_id_t)src;
  889. if (!CheckPort(mysrc)) {
  890. jack_error("jack_port_connect called with a NULL src port");
  891. return -1;
  892. }
  893. jack_port_id_t mydst = (jack_port_id_t)dst;
  894. if (!CheckPort(mydst)) {
  895. jack_error("jack_port_connect called with a NULL dst port");
  896. return -1;
  897. }
  898. return client->PortConnect(mysrc, mydst);
  899. }
  900. EXPORT int jack_port_disconnect(jack_client_t* ext_client, jack_port_t* src)
  901. {
  902. #ifdef __CLIENTDEBUG__
  903. JackLibGlobals::CheckContext();
  904. #endif
  905. JackClient* client = (JackClient*)ext_client;
  906. if (client == NULL) {
  907. jack_error("jack_port_disconnect called with a NULL client");
  908. return -1;
  909. }
  910. jack_port_id_t myport = (jack_port_id_t)src;
  911. if (!CheckPort(myport)) {
  912. jack_error("jack_port_disconnect called with an incorrect port %ld", myport);
  913. return -1;
  914. }
  915. return client->PortDisconnect(myport);
  916. }
  917. EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t* ext_client)
  918. {
  919. #ifdef __CLIENTDEBUG__
  920. JackLibGlobals::CheckContext();
  921. #endif
  922. JackClient* client = (JackClient*)ext_client;
  923. if (client == NULL) {
  924. jack_error("jack_get_sample_rate called with a NULL client");
  925. return 0;
  926. } else {
  927. return GetEngineControl()->fSampleRate;
  928. }
  929. }
  930. EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t* ext_client)
  931. {
  932. #ifdef __CLIENTDEBUG__
  933. JackLibGlobals::CheckContext();
  934. #endif
  935. JackClient* client = (JackClient*)ext_client;
  936. if (client == NULL) {
  937. jack_error("jack_get_buffer_size called with a NULL client");
  938. return 0;
  939. } else {
  940. return GetEngineControl()->fBufferSize;
  941. }
  942. }
  943. EXPORT const char** jack_get_ports(jack_client_t* ext_client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
  944. {
  945. #ifdef __CLIENTDEBUG__
  946. JackLibGlobals::CheckContext();
  947. #endif
  948. JackClient* client = (JackClient*)ext_client;
  949. if (client == NULL) {
  950. jack_error("jack_get_ports called with a NULL client");
  951. return NULL;
  952. }
  953. return GetGraphManager()->GetPorts(port_name_pattern, type_name_pattern, flags);
  954. }
  955. EXPORT jack_port_t* jack_port_by_name(jack_client_t* ext_client, const char* portname)
  956. {
  957. #ifdef __CLIENTDEBUG__
  958. JackLibGlobals::CheckContext();
  959. #endif
  960. JackClient* client = (JackClient*)ext_client;
  961. if (client == NULL) {
  962. jack_error("jack_get_ports called with a NULL client");
  963. return 0;
  964. }
  965. if (portname == NULL) {
  966. jack_error("jack_port_by_name called with a NULL port name");
  967. return NULL;
  968. } else {
  969. int res = GetGraphManager()->GetPort(portname); // returns a port index at least > 1
  970. return (res == NO_PORT) ? NULL : (jack_port_t*)res;
  971. }
  972. }
  973. EXPORT jack_port_t* jack_port_by_id(jack_client_t* ext_client, jack_port_id_t id)
  974. {
  975. #ifdef __CLIENTDEBUG__
  976. JackLibGlobals::CheckContext();
  977. #endif
  978. /* jack_port_t* type is actually the port index */
  979. return (jack_port_t*)id;
  980. }
  981. EXPORT int jack_engine_takeover_timebase(jack_client_t* ext_client)
  982. {
  983. #ifdef __CLIENTDEBUG__
  984. JackLibGlobals::CheckContext();
  985. #endif
  986. JackClient* client = (JackClient*)ext_client;
  987. if (client == NULL) {
  988. jack_error("jack_engine_takeover_timebase called with a NULL client");
  989. return -1;
  990. } else {
  991. jack_error("jack_engine_takeover_timebase: deprecated\n");
  992. return 0;
  993. }
  994. }
  995. EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t* ext_client)
  996. {
  997. #ifdef __CLIENTDEBUG__
  998. JackLibGlobals::CheckContext();
  999. #endif
  1000. JackTimer timer;
  1001. GetEngineControl()->ReadFrameTime(&timer);
  1002. return (jack_nframes_t) floor((((float)GetEngineControl()->fSampleRate) / 1000000.0f) * (GetMicroSeconds() - timer.fCurrentCallback));
  1003. }
  1004. EXPORT jack_time_t jack_get_time(jack_client_t *client)
  1005. {
  1006. return GetMicroSeconds();
  1007. }
  1008. EXPORT jack_time_t jack_frames_to_time(const jack_client_t* ext_client, jack_nframes_t frames)
  1009. {
  1010. #ifdef __CLIENTDEBUG__
  1011. JackLibGlobals::CheckContext();
  1012. #endif
  1013. JackClient* client = (JackClient*)ext_client;
  1014. if (client == NULL) {
  1015. jack_error("jack_frames_to_time called with a NULL client");
  1016. return 0;
  1017. } else {
  1018. JackTimer timer;
  1019. GetEngineControl()->ReadFrameTime(&timer);
  1020. if (timer.fInitialized) {
  1021. return timer.fCurrentWakeup +
  1022. (long) rint(((double) ((frames - timer.fFrames)) *
  1023. ((jack_time_t)(timer.fNextWakeUp - timer.fCurrentWakeup))) / GetEngineControl()->fBufferSize);
  1024. } else {
  1025. return 0;
  1026. }
  1027. }
  1028. }
  1029. EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t* ext_client, jack_time_t time)
  1030. {
  1031. #ifdef __CLIENTDEBUG__
  1032. JackLibGlobals::CheckContext();
  1033. #endif
  1034. JackClient* client = (JackClient*)ext_client;
  1035. if (client == NULL) {
  1036. jack_error("jack_time_to_frames called with a NULL client");
  1037. return 0;
  1038. } else {
  1039. JackTimer timer;
  1040. GetEngineControl()->ReadFrameTime(&timer);
  1041. if (timer.fInitialized) {
  1042. return timer.fFrames +
  1043. (long) rint(((double) ((time - timer.fCurrentWakeup)) /
  1044. ((jack_time_t)(timer.fNextWakeUp - timer.fCurrentWakeup))) * GetEngineControl()->fBufferSize);
  1045. } else {
  1046. return 0;
  1047. }
  1048. }
  1049. }
  1050. EXPORT jack_nframes_t jack_frame_time(const jack_client_t* ext_client)
  1051. {
  1052. return jack_time_to_frames(ext_client, GetMicroSeconds());
  1053. }
  1054. EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t* ext_client)
  1055. {
  1056. #ifdef __CLIENTDEBUG__
  1057. JackLibGlobals::CheckContext();
  1058. #endif
  1059. JackTimer timer;
  1060. GetEngineControl()->ReadFrameTime(&timer);
  1061. return timer.fFrames;
  1062. }
  1063. EXPORT float jack_cpu_load(jack_client_t* ext_client)
  1064. {
  1065. #ifdef __CLIENTDEBUG__
  1066. JackLibGlobals::CheckContext();
  1067. #endif
  1068. JackClient* client = (JackClient*)ext_client;
  1069. if (client == NULL) {
  1070. jack_error("jack_cpu_load called with a NULL client");
  1071. return 0.0f;
  1072. } else {
  1073. return GetEngineControl()->fCPULoad;
  1074. }
  1075. }
  1076. EXPORT pthread_t jack_client_thread_id(jack_client_t* ext_client)
  1077. {
  1078. #ifdef __CLIENTDEBUG__
  1079. JackLibGlobals::CheckContext();
  1080. #endif
  1081. JackClient* client = (JackClient*)ext_client;
  1082. if (client == NULL) {
  1083. jack_error("jack_client_thread_id called with a NULL client");
  1084. return (pthread_t)NULL;
  1085. } else {
  1086. return client->GetThreadID();
  1087. }
  1088. }
  1089. EXPORT char* jack_get_client_name (jack_client_t* ext_client)
  1090. {
  1091. #ifdef __CLIENTDEBUG__
  1092. JackLibGlobals::CheckContext();
  1093. #endif
  1094. JackClient* client = (JackClient*)ext_client;
  1095. if (client == NULL) {
  1096. jack_error("jack_get_client_name called with a NULL client");
  1097. return NULL;
  1098. } else {
  1099. return client->GetClientControl()->fName;
  1100. }
  1101. }
  1102. EXPORT int jack_client_name_size(void)
  1103. {
  1104. return JACK_CLIENT_NAME_SIZE;
  1105. }
  1106. EXPORT int jack_port_name_size(void)
  1107. {
  1108. return JACK_PORT_NAME_SIZE;
  1109. }
  1110. // transport.h
  1111. EXPORT int jack_release_timebase(jack_client_t* ext_client)
  1112. {
  1113. #ifdef __CLIENTDEBUG__
  1114. JackLibGlobals::CheckContext();
  1115. #endif
  1116. JackClient* client = (JackClient*)ext_client;
  1117. if (client == NULL) {
  1118. jack_error("jack_release_timebase called with a NULL client");
  1119. return -1;
  1120. } else {
  1121. return client->ReleaseTimebase();
  1122. }
  1123. }
  1124. EXPORT int jack_set_sync_callback(jack_client_t* ext_client, JackSyncCallback sync_callback, void *arg)
  1125. {
  1126. #ifdef __CLIENTDEBUG__
  1127. JackLibGlobals::CheckContext();
  1128. #endif
  1129. JackClient* client = (JackClient*)ext_client;
  1130. if (client == NULL) {
  1131. jack_error("jack_set_sync_callback called with a NULL client");
  1132. return -1;
  1133. } else {
  1134. return client->SetSyncCallback(sync_callback, arg);
  1135. }
  1136. }
  1137. EXPORT int jack_set_sync_timeout(jack_client_t* ext_client, jack_time_t timeout)
  1138. {
  1139. #ifdef __CLIENTDEBUG__
  1140. JackLibGlobals::CheckContext();
  1141. #endif
  1142. JackClient* client = (JackClient*)ext_client;
  1143. if (client == NULL) {
  1144. jack_error("jack_set_sync_timeout called with a NULL client");
  1145. return -1;
  1146. } else {
  1147. return client->SetSyncTimeout(timeout);
  1148. }
  1149. }
  1150. EXPORT int jack_set_timebase_callback(jack_client_t* ext_client, int conditional, JackTimebaseCallback timebase_callback, void* arg)
  1151. {
  1152. #ifdef __CLIENTDEBUG__
  1153. JackLibGlobals::CheckContext();
  1154. #endif
  1155. JackClient* client = (JackClient*)ext_client;
  1156. if (client == NULL) {
  1157. jack_error("jack_set_timebase_callback called with a NULL client");
  1158. return -1;
  1159. } else {
  1160. return client->SetTimebaseCallback(conditional, timebase_callback, arg);
  1161. }
  1162. }
  1163. EXPORT int jack_transport_locate(jack_client_t* ext_client, jack_nframes_t frame)
  1164. {
  1165. #ifdef __CLIENTDEBUG__
  1166. JackLibGlobals::CheckContext();
  1167. #endif
  1168. JackClient* client = (JackClient*)ext_client;
  1169. if (client == NULL) {
  1170. jack_error("jack_transport_locate called with a NULL client");
  1171. return -1;
  1172. } else {
  1173. return client->TransportLocate(frame);
  1174. }
  1175. }
  1176. EXPORT jack_transport_state_t jack_transport_query(const jack_client_t* ext_client, jack_position_t* pos)
  1177. {
  1178. #ifdef __CLIENTDEBUG__
  1179. JackLibGlobals::CheckContext();
  1180. #endif
  1181. JackClient* client = (JackClient*)ext_client;
  1182. if (client == NULL) {
  1183. jack_error("jack_transport_query called with a NULL client");
  1184. return JackTransportStopped;
  1185. } else {
  1186. return client->TransportQuery(pos);
  1187. }
  1188. }
  1189. EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t* ext_client)
  1190. {
  1191. #ifdef __CLIENTDEBUG__
  1192. JackLibGlobals::CheckContext();
  1193. #endif
  1194. JackClient* client = (JackClient*)ext_client;
  1195. if (client == NULL) {
  1196. jack_error("jack_get_current_transport_frame called with a NULL client");
  1197. return 0;
  1198. } else {
  1199. return client->GetCurrentTransportFrame();
  1200. }
  1201. }
  1202. EXPORT int jack_transport_reposition(jack_client_t* ext_client, jack_position_t* pos)
  1203. {
  1204. #ifdef __CLIENTDEBUG__
  1205. JackLibGlobals::CheckContext();
  1206. #endif
  1207. JackClient* client = (JackClient*)ext_client;
  1208. if (client == NULL) {
  1209. jack_error("jack_transport_reposition called with a NULL client");
  1210. return -1;
  1211. } else {
  1212. return client->TransportReposition(pos);
  1213. }
  1214. }
  1215. EXPORT void jack_transport_start(jack_client_t* ext_client)
  1216. {
  1217. #ifdef __CLIENTDEBUG__
  1218. JackLibGlobals::CheckContext();
  1219. #endif
  1220. JackClient* client = (JackClient*)ext_client;
  1221. if (client == NULL) {
  1222. jack_error("jack_transport_start called with a NULL client");
  1223. } else {
  1224. client->TransportStart();
  1225. }
  1226. }
  1227. EXPORT void jack_transport_stop(jack_client_t* ext_client)
  1228. {
  1229. #ifdef __CLIENTDEBUG__
  1230. JackLibGlobals::CheckContext();
  1231. #endif
  1232. JackClient* client = (JackClient*)ext_client;
  1233. if (client == NULL) {
  1234. jack_error("jack_transport_stop called with a NULL client");
  1235. } else {
  1236. client->TransportStop();
  1237. }
  1238. }
  1239. // deprecated
  1240. EXPORT void jack_get_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
  1241. {
  1242. jack_error("jack_get_transport_info: deprecated");
  1243. if (tinfo)
  1244. memset(tinfo, 0, sizeof(jack_transport_info_t));
  1245. }
  1246. EXPORT void jack_set_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
  1247. {
  1248. jack_error("jack_set_transport_info: deprecated");
  1249. if (tinfo)
  1250. memset(tinfo, 0, sizeof(jack_transport_info_t));
  1251. }
  1252. // statistics.h
  1253. EXPORT float jack_get_max_delayed_usecs(jack_client_t* ext_client)
  1254. {
  1255. #ifdef __CLIENTDEBUG__
  1256. JackLibGlobals::CheckContext();
  1257. #endif
  1258. JackLog("jack_get_max_delayed_usecs: not yet implemented\n");
  1259. return 0.f;
  1260. }
  1261. EXPORT float jack_get_xrun_delayed_usecs(jack_client_t* ext_client)
  1262. {
  1263. #ifdef __CLIENTDEBUG__
  1264. JackLibGlobals::CheckContext();
  1265. #endif
  1266. JackLog("jack_get_xrun_delayed_usecs: not yet implemented\n");
  1267. return 0.f;
  1268. }
  1269. EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client)
  1270. {
  1271. #ifdef __CLIENTDEBUG__
  1272. JackLibGlobals::CheckContext();
  1273. #endif
  1274. JackLog("jack_reset_max_delayed_usecs: not yet implemented\n");
  1275. }
  1276. // thread.h
  1277. EXPORT int jack_acquire_real_time_scheduling(pthread_t thread, int priority)
  1278. {
  1279. #ifdef __APPLE__
  1280. return JackMachThread::AcquireRealTimeImp(thread, GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
  1281. #elif WIN32
  1282. return JackWinThread::AcquireRealTimeImp(thread, priority);
  1283. #else
  1284. return JackPosixThread::AcquireRealTimeImp(thread, priority);
  1285. #endif
  1286. }
  1287. EXPORT int jack_client_create_thread(jack_client_t* client,
  1288. pthread_t *thread,
  1289. int priority,
  1290. int realtime, /* boolean */
  1291. void *(*start_routine)(void*),
  1292. void *arg)
  1293. {
  1294. #ifdef __APPLE__
  1295. return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg);
  1296. #elif WIN32
  1297. return JackWinThread::StartImp(thread, priority, realtime, (ThreadCallback)start_routine, arg);
  1298. #else
  1299. return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg);
  1300. #endif
  1301. }
  1302. EXPORT int jack_drop_real_time_scheduling(pthread_t thread)
  1303. {
  1304. #ifdef __APPLE__
  1305. return JackMachThread::DropRealTimeImp(thread);
  1306. #elif WIN32
  1307. return JackWinThread::DropRealTimeImp(thread);
  1308. #else
  1309. return JackPosixThread::DropRealTimeImp(thread);
  1310. #endif
  1311. }
  1312. // intclient.h
  1313. EXPORT char* jack_get_internal_client_name(jack_client_t* ext_client, jack_intclient_t intclient)
  1314. {
  1315. #ifdef __CLIENTDEBUG__
  1316. JackLibGlobals::CheckContext();
  1317. #endif
  1318. JackClient* client = (JackClient*)ext_client;
  1319. if (client == NULL) {
  1320. jack_error("jack_get_internal_client_name called with a NULL client");
  1321. return NULL;
  1322. } else if (intclient < 0 || intclient >= CLIENT_NUM) {
  1323. jack_error("jack_get_internal_client_name: incorrect client");
  1324. return NULL;
  1325. } else {
  1326. return client->GetInternalClientName(intclient);
  1327. }
  1328. }
  1329. EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t* ext_client, const char* client_name, jack_status_t* status)
  1330. {
  1331. #ifdef __CLIENTDEBUG__
  1332. JackLibGlobals::CheckContext();
  1333. #endif
  1334. JackClient* client = (JackClient*)ext_client;
  1335. if (client == NULL) {
  1336. jack_error("jack_internal_client_handle called with a NULL client");
  1337. return 0;
  1338. } else {
  1339. jack_status_t my_status;
  1340. if (status == NULL) /* no status from caller? */
  1341. status = &my_status; /* use local status word */
  1342. *status = (jack_status_t)0;
  1343. return client->InternalClientHandle(client_name, status);
  1344. }
  1345. }
  1346. EXPORT jack_intclient_t jack_internal_client_load(jack_client_t* ext_client, const char* client_name, jack_options_t options, jack_status_t* status, ...)
  1347. {
  1348. #ifdef __CLIENTDEBUG__
  1349. JackLibGlobals::CheckContext();
  1350. #endif
  1351. JackClient* client = (JackClient*)ext_client;
  1352. if (client == NULL) {
  1353. jack_error("jack_internal_client_load called with a NULL client");
  1354. return 0;
  1355. } else {
  1356. va_list ap;
  1357. jack_varargs_t va;
  1358. jack_status_t my_status;
  1359. if (status == NULL) /* no status from caller? */
  1360. status = &my_status; /* use local status word */
  1361. *status = (jack_status_t)0;
  1362. /* validate parameters */
  1363. if ((options & ~JackLoadOptions)) {
  1364. int my_status1 = *status | (JackFailure | JackInvalidOption);
  1365. *status = (jack_status_t)my_status1;
  1366. return 0;
  1367. }
  1368. /* parse variable arguments */
  1369. va_start(ap, status);
  1370. jack_varargs_parse(options, ap, &va);
  1371. va_end(ap);
  1372. return client->InternalClientLoad(client_name, options, status, &va);
  1373. }
  1374. }
  1375. EXPORT jack_status_t jack_internal_client_unload(jack_client_t* ext_client, jack_intclient_t intclient)
  1376. {
  1377. #ifdef __CLIENTDEBUG__
  1378. JackLibGlobals::CheckContext();
  1379. #endif
  1380. JackClient* client = (JackClient*)ext_client;
  1381. if (client == NULL) {
  1382. jack_error("jack_internal_client_unload called with a NULL client");
  1383. return (jack_status_t)(JackNoSuchClient | JackFailure);
  1384. } else if (intclient < 0 || intclient >= CLIENT_NUM) {
  1385. jack_error("jack_internal_client_unload: incorrect client");
  1386. return (jack_status_t)(JackNoSuchClient | JackFailure);
  1387. } else {
  1388. jack_status_t my_status;
  1389. client->InternalClientUnload(intclient, &my_status);
  1390. return my_status;
  1391. }
  1392. }