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.

1144 lines
39KB

  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. #ifdef __APPLE__
  25. #include "JackMachThread.h"
  26. #elif WIN32
  27. #include "JackWinThread.h"
  28. #else
  29. #include "JackPosixThread.h"
  30. #endif
  31. #include <math.h>
  32. using namespace Jack;
  33. #ifdef __cplusplus
  34. extern "C"
  35. {
  36. #endif
  37. EXPORT int jack_client_name_size (void);
  38. EXPORT char* jack_get_client_name (jack_client_t *client);
  39. EXPORT int jack_internal_client_new (const char *client_name,
  40. const char *load_name,
  41. const char *load_init);
  42. EXPORT jack_client_t* my_jack_internal_client_new(const char* client_name);
  43. EXPORT void jack_internal_client_close (const char *client_name);
  44. EXPORT void my_jack_internal_client_close (jack_client_t* client);
  45. EXPORT int jack_is_realtime (jack_client_t *client);
  46. EXPORT void jack_on_shutdown (jack_client_t *client,
  47. void (*function)(void *arg), void *arg);
  48. EXPORT int jack_set_process_callback (jack_client_t *client,
  49. JackProcessCallback process_callback,
  50. void *arg);
  51. EXPORT int jack_set_thread_init_callback (jack_client_t *client,
  52. JackThreadInitCallback thread_init_callback,
  53. void *arg);
  54. EXPORT int jack_set_freewheel_callback (jack_client_t *client,
  55. JackFreewheelCallback freewheel_callback,
  56. void *arg);
  57. EXPORT int jack_set_freewheel(jack_client_t* client, int onoff);
  58. EXPORT int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes);
  59. EXPORT int jack_set_buffer_size_callback (jack_client_t *client,
  60. JackBufferSizeCallback bufsize_callback,
  61. void *arg);
  62. EXPORT int jack_set_sample_rate_callback (jack_client_t *client,
  63. JackSampleRateCallback srate_callback,
  64. void *arg);
  65. EXPORT int jack_set_port_registration_callback (jack_client_t *,
  66. JackPortRegistrationCallback
  67. registration_callback, void *arg);
  68. EXPORT int jack_set_graph_order_callback (jack_client_t *,
  69. JackGraphOrderCallback graph_callback,
  70. void *);
  71. EXPORT int jack_set_xrun_callback (jack_client_t *,
  72. JackXRunCallback xrun_callback, void *arg);
  73. EXPORT int jack_activate (jack_client_t *client);
  74. EXPORT int jack_deactivate (jack_client_t *client);
  75. EXPORT jack_port_t * jack_port_register (jack_client_t *client,
  76. const char *port_name,
  77. const char *port_type,
  78. unsigned long flags,
  79. unsigned long buffer_size);
  80. EXPORT int jack_port_unregister (jack_client_t *, jack_port_t *);
  81. EXPORT void * jack_port_get_buffer (jack_port_t *, jack_nframes_t);
  82. EXPORT const char * jack_port_name (const jack_port_t *port);
  83. EXPORT const char * jack_port_short_name (const jack_port_t *port);
  84. EXPORT int jack_port_flags (const jack_port_t *port);
  85. EXPORT const char * jack_port_type (const jack_port_t *port);
  86. EXPORT int jack_port_is_mine (const jack_client_t *, const jack_port_t *port);
  87. EXPORT int jack_port_connected (const jack_port_t *port);
  88. EXPORT int jack_port_connected_to (const jack_port_t *port,
  89. const char *port_name);
  90. EXPORT const char ** jack_port_get_connections (const jack_port_t *port);
  91. EXPORT const char ** jack_port_get_all_connections (const jack_client_t *client,
  92. const jack_port_t *port);
  93. EXPORT int jack_port_tie (jack_port_t *src, jack_port_t *dst);
  94. EXPORT int jack_port_untie (jack_port_t *port);
  95. EXPORT int jack_port_lock (jack_client_t *, jack_port_t *);
  96. EXPORT int jack_port_unlock (jack_client_t *, jack_port_t *);
  97. EXPORT jack_nframes_t jack_port_get_latency (jack_port_t *port);
  98. EXPORT jack_nframes_t jack_port_get_total_latency (jack_client_t *,
  99. jack_port_t *port);
  100. EXPORT void jack_port_set_latency (jack_port_t *, jack_nframes_t);
  101. EXPORT int jack_recompute_total_latencies (jack_client_t*);
  102. EXPORT int jack_port_set_name (jack_port_t *port, const char *port_name);
  103. EXPORT int jack_port_request_monitor (jack_port_t *port, int onoff);
  104. EXPORT int jack_port_request_monitor_by_name (jack_client_t *client,
  105. const char *port_name, int onoff);
  106. EXPORT int jack_port_ensure_monitor (jack_port_t *port, int onoff);
  107. EXPORT int jack_port_monitoring_input (jack_port_t *port);
  108. EXPORT int jack_connect (jack_client_t *,
  109. const char *source_port,
  110. const char *destination_port);
  111. EXPORT int jack_disconnect (jack_client_t *,
  112. const char *source_port,
  113. const char *destination_port);
  114. EXPORT int jack_port_disconnect (jack_client_t *, jack_port_t *);
  115. EXPORT int jack_port_name_size(void);
  116. EXPORT int jack_port_type_size(void);
  117. EXPORT jack_nframes_t jack_get_sample_rate (jack_client_t *);
  118. EXPORT jack_nframes_t jack_get_buffer_size (jack_client_t *);
  119. EXPORT const char ** jack_get_ports (jack_client_t *,
  120. const char *port_name_pattern,
  121. const char *type_name_pattern,
  122. unsigned long flags);
  123. EXPORT jack_port_t * jack_port_by_name (jack_client_t *, const char *port_name);
  124. EXPORT jack_port_t * jack_port_by_id (jack_client_t *client,
  125. jack_port_id_t port_id);
  126. EXPORT int jack_engine_takeover_timebase (jack_client_t *);
  127. EXPORT jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *);
  128. EXPORT jack_nframes_t jack_frame_time (const jack_client_t *);
  129. EXPORT jack_nframes_t jack_last_frame_time (const jack_client_t *client);
  130. EXPORT float jack_cpu_load (jack_client_t *client);
  131. EXPORT pthread_t jack_client_thread_id (jack_client_t *);
  132. EXPORT void jack_set_error_function (void (*func)(const char *));
  133. EXPORT float jack_get_max_delayed_usecs (jack_client_t *client);
  134. EXPORT float jack_get_xrun_delayed_usecs (jack_client_t *client);
  135. EXPORT void jack_reset_max_delayed_usecs (jack_client_t *client);
  136. EXPORT int jack_release_timebase (jack_client_t *client);
  137. EXPORT int jack_set_sync_callback (jack_client_t *client,
  138. JackSyncCallback sync_callback,
  139. void *arg);
  140. EXPORT int jack_set_sync_timeout (jack_client_t *client,
  141. jack_time_t timeout);
  142. EXPORT int jack_set_timebase_callback (jack_client_t *client,
  143. int conditional,
  144. JackTimebaseCallback timebase_callback,
  145. void *arg);
  146. EXPORT int jack_transport_locate (jack_client_t *client,
  147. jack_nframes_t frame);
  148. EXPORT jack_transport_state_t jack_transport_query (const jack_client_t *client,
  149. jack_position_t *pos);
  150. EXPORT jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client);
  151. EXPORT int jack_transport_reposition (jack_client_t *client,
  152. jack_position_t *pos);
  153. EXPORT void jack_transport_start (jack_client_t *client);
  154. EXPORT void jack_transport_stop (jack_client_t *client);
  155. EXPORT void jack_get_transport_info (jack_client_t *client,
  156. jack_transport_info_t *tinfo);
  157. EXPORT void jack_set_transport_info (jack_client_t *client,
  158. jack_transport_info_t *tinfo);
  159. EXPORT int jack_acquire_real_time_scheduling (pthread_t thread, int priority);
  160. EXPORT int jack_client_create_thread (jack_client_t* client,
  161. pthread_t *thread,
  162. int priority,
  163. int realtime, // boolean
  164. void *(*start_routine)(void*),
  165. void *arg);
  166. EXPORT int jack_drop_real_time_scheduling (pthread_t thread);
  167. EXPORT char * jack_get_internal_client_name (jack_client_t *client,
  168. jack_intclient_t intclient);
  169. EXPORT jack_intclient_t jack_internal_client_handle (jack_client_t *client,
  170. const char *client_name,
  171. jack_status_t *status);
  172. EXPORT jack_intclient_t jack_internal_client_load (jack_client_t *client,
  173. const char *client_name,
  174. jack_options_t options,
  175. jack_status_t *status, ...);
  176. EXPORT jack_status_t jack_internal_client_unload (jack_client_t *client,
  177. jack_intclient_t intclient);
  178. #ifdef __cplusplus
  179. }
  180. #endif
  181. #ifdef WIN32
  182. /* missing on Windows : see http://bugs.mysql.com/bug.php?id=15936 */
  183. inline double rint(double nr)
  184. {
  185. double f = floor(nr);
  186. double c = ceil(nr);
  187. return (((c -nr) >= (nr - f)) ? f : c);
  188. }
  189. #endif
  190. static inline bool CheckPort(jack_port_id_t port_index)
  191. {
  192. return (port_index < PORT_NUM);
  193. }
  194. static inline bool CheckBufferSize(jack_nframes_t buffer_size)
  195. {
  196. return (buffer_size <= BUFFER_SIZE_MAX);
  197. }
  198. static inline void WaitGraphChange()
  199. {
  200. if (GetGraphManager()->IsPendingChange()) {
  201. JackLog("WaitGraphChange...\n");
  202. JackSleep(GetEngineControl()->fPeriodUsecs * 2);
  203. }
  204. }
  205. static void default_jack_error_callback(const char *desc)
  206. {
  207. fprintf(stderr, "%s\n", desc);
  208. }
  209. void (*jack_error_callback)(const char *desc) = &default_jack_error_callback;
  210. EXPORT void jack_set_error_function (void (*func)(const char *))
  211. {
  212. jack_error_callback = func;
  213. }
  214. EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames)
  215. {
  216. jack_port_id_t myport = (jack_port_id_t)port;
  217. if (!CheckPort(myport)) {
  218. jack_error("jack_port_get_buffer called with an incorrect port %ld", myport);
  219. return NULL;
  220. } else {
  221. return GetGraphManager()->GetBuffer(myport, frames);
  222. }
  223. }
  224. EXPORT const char* jack_port_name(const jack_port_t* port)
  225. {
  226. jack_port_id_t myport = (jack_port_id_t)port;
  227. if (!CheckPort(myport)) {
  228. jack_error("jack_port_name called with an incorrect port %ld", myport);
  229. return NULL;
  230. } else {
  231. return GetGraphManager()->GetPort(myport)->GetName();
  232. }
  233. }
  234. EXPORT const char* jack_port_short_name(const jack_port_t* port)
  235. {
  236. jack_port_id_t myport = (jack_port_id_t)port;
  237. if (!CheckPort(myport)) {
  238. jack_error("jack_port_short_name called with an incorrect port %ld", myport);
  239. return NULL;
  240. } else {
  241. return GetGraphManager()->GetPort(myport)->GetShortName();
  242. }
  243. }
  244. EXPORT int jack_port_flags(const jack_port_t* port)
  245. {
  246. jack_port_id_t myport = (jack_port_id_t)port;
  247. if (!CheckPort(myport)) {
  248. jack_error("jack_port_flags called with an incorrect port %ld", myport);
  249. return -1;
  250. } else {
  251. return GetGraphManager()->GetPort(myport)->Flags();
  252. }
  253. }
  254. EXPORT const char* jack_port_type(const jack_port_t* port)
  255. {
  256. jack_port_id_t myport = (jack_port_id_t)port;
  257. if (!CheckPort(myport)) {
  258. jack_error("jack_port_flags called an incorrect port %ld", myport);
  259. return NULL;
  260. } else {
  261. return GetGraphManager()->GetPort(myport)->Type();
  262. }
  263. }
  264. EXPORT int jack_port_connected(const jack_port_t* port)
  265. {
  266. jack_port_id_t myport = (jack_port_id_t)port;
  267. if (!CheckPort(myport)) {
  268. jack_error("jack_port_connected called with an incorrect port %ld", myport);
  269. return -1;
  270. } else {
  271. WaitGraphChange();
  272. return GetGraphManager()->GetConnectionsNum(myport);
  273. }
  274. }
  275. EXPORT int jack_port_connected_to(const jack_port_t* port, const char* portname)
  276. {
  277. jack_port_id_t myport = (jack_port_id_t)port;
  278. if (!CheckPort(myport)) {
  279. jack_error("jack_port_connected_to called with an incorrect port %ld", myport);
  280. return -1;
  281. } else if (portname == NULL) {
  282. jack_error("jack_port_connected_to called with a NULL port name");
  283. return -1;
  284. } else {
  285. WaitGraphChange();
  286. return GetGraphManager()->ConnectedTo(myport, portname);
  287. }
  288. }
  289. EXPORT int jack_port_tie(jack_port_t* src, jack_port_t* dst)
  290. {
  291. jack_port_id_t mysrc = (jack_port_id_t)src;
  292. if (!CheckPort(mysrc)) {
  293. jack_error("jack_port_tie called with a NULL src port");
  294. return -1;
  295. }
  296. jack_port_id_t mydst = (jack_port_id_t)dst;
  297. if (!CheckPort(mydst)) {
  298. jack_error("jack_port_tie called with a NULL dst port");
  299. return -1;
  300. }
  301. if (GetGraphManager()->GetPort(mysrc)->GetRefNum() != GetGraphManager()->GetPort(mydst)->GetRefNum()) {
  302. jack_error("jack_port_tie called with ports not belonging to the same client");
  303. return -1;
  304. }
  305. return GetGraphManager()->GetPort(mydst)->Tie(mysrc);
  306. }
  307. EXPORT int jack_port_untie(jack_port_t* port)
  308. {
  309. jack_port_id_t myport = (jack_port_id_t)port;
  310. if (!CheckPort(myport)) {
  311. jack_error("jack_port_untie called with an incorrect port %ld", myport);
  312. return -1;
  313. } else {
  314. return GetGraphManager()->GetPort(myport)->UnTie();
  315. }
  316. }
  317. EXPORT jack_nframes_t jack_port_get_latency(jack_port_t* port)
  318. {
  319. jack_port_id_t myport = (jack_port_id_t)port;
  320. if (!CheckPort(myport)) {
  321. jack_error("jack_port_get_latency called with an incorrect port %ld", myport);
  322. return 0;
  323. } else {
  324. WaitGraphChange();
  325. return GetGraphManager()->GetPort(myport)->GetLatency();
  326. }
  327. }
  328. EXPORT void jack_port_set_latency(jack_port_t* port, jack_nframes_t frames)
  329. {
  330. jack_port_id_t myport = (jack_port_id_t)port;
  331. if (!CheckPort(myport)) {
  332. jack_error("jack_port_set_latency called with an incorrect port %ld", myport);
  333. } else {
  334. GetGraphManager()->GetPort(myport)->SetLatency(frames);
  335. }
  336. }
  337. EXPORT int jack_recompute_total_latencies(jack_client_t* ext_client)
  338. {
  339. // The latency computation is done each time jack_port_get_total_latency is called
  340. return 0;
  341. }
  342. EXPORT int jack_port_set_name(jack_port_t* port, const char* name)
  343. {
  344. jack_port_id_t myport = (jack_port_id_t)port;
  345. if (!CheckPort(myport)) {
  346. jack_error("jack_port_set_name called with an incorrect port %ld", myport);
  347. return -1;
  348. } else if (name == NULL) {
  349. jack_error("jack_port_set_name called with a NULL port name");
  350. return -1;
  351. } else {
  352. return GetGraphManager()->GetPort(myport)->SetName(name);
  353. }
  354. }
  355. EXPORT int jack_port_request_monitor(jack_port_t* port, int onoff)
  356. {
  357. jack_port_id_t myport = (jack_port_id_t)port;
  358. if (!CheckPort(myport)) {
  359. jack_error("jack_port_request_monitor called with an incorrect port %ld", myport);
  360. return -1;
  361. } else {
  362. return GetGraphManager()->RequestMonitor(myport, onoff);
  363. }
  364. }
  365. EXPORT int jack_port_request_monitor_by_name(jack_client_t* ext_client, const char* port_name, int onoff)
  366. {
  367. JackClient* client = (JackClient*)ext_client;
  368. if (client == NULL) {
  369. jack_error("jack_port_request_monitor_by_name called with a NULL client");
  370. return -1;
  371. } else {
  372. jack_port_id_t myport = GetGraphManager()->GetPort(port_name);
  373. if (!CheckPort(myport)) {
  374. jack_error("jack_port_request_monitor_by_name called with an incorrect port %s", port_name);
  375. return -1;
  376. } else {
  377. return GetGraphManager()->RequestMonitor(myport, onoff);
  378. }
  379. }
  380. }
  381. EXPORT int jack_port_ensure_monitor(jack_port_t* port, int onoff)
  382. {
  383. jack_port_id_t myport = (jack_port_id_t)port;
  384. if (!CheckPort(myport)) {
  385. jack_error("jack_port_ensure_monitor called with an incorrect port %ld", myport);
  386. return -1;
  387. } else {
  388. return GetGraphManager()->GetPort(myport)->EnsureMonitor(onoff);
  389. }
  390. }
  391. EXPORT int jack_port_monitoring_input(jack_port_t* port)
  392. {
  393. jack_port_id_t myport = (jack_port_id_t)port;
  394. if (!CheckPort(myport)) {
  395. jack_error("jack_port_monitoring_input called with an incorrect port %ld", myport);
  396. return -1;
  397. } else {
  398. return GetGraphManager()->GetPort(myport)->MonitoringInput();
  399. }
  400. }
  401. EXPORT int jack_is_realtime(jack_client_t* ext_client)
  402. {
  403. JackClient* client = (JackClient*)ext_client;
  404. if (client == NULL) {
  405. jack_error("jack_is_realtime called with a NULL client");
  406. return -1;
  407. } else {
  408. return GetEngineControl()->fRealTime;
  409. }
  410. }
  411. EXPORT void jack_on_shutdown(jack_client_t* ext_client, void (*function)(void* arg), void* arg)
  412. {
  413. JackClient* client = (JackClient*)ext_client;
  414. if (client == NULL) {
  415. jack_error("jack_on_shutdown called with a NULL client");
  416. } else {
  417. client->OnShutdown(function, arg);
  418. }
  419. }
  420. EXPORT int jack_set_process_callback(jack_client_t* ext_client, JackProcessCallback callback, void* arg)
  421. {
  422. JackClient* client = (JackClient*)ext_client;
  423. if (client == NULL) {
  424. jack_error("jack_set_process_callback called with a NULL client");
  425. return -1;
  426. } else {
  427. return client->SetProcessCallback(callback, arg);
  428. }
  429. }
  430. EXPORT int jack_set_freewheel_callback(jack_client_t* ext_client, JackFreewheelCallback freewheel_callback, void* arg)
  431. {
  432. JackClient* client = (JackClient*)ext_client;
  433. if (client == NULL) {
  434. jack_error("jack_set_freewheel_callback called with a NULL client");
  435. return -1;
  436. } else {
  437. return client->SetFreewheelCallback(freewheel_callback, arg);
  438. }
  439. }
  440. EXPORT int jack_set_freewheel(jack_client_t* ext_client, int onoff)
  441. {
  442. JackClient* client = (JackClient*)ext_client;
  443. if (client == NULL) {
  444. jack_error("jack_set_freewheel called with a NULL client");
  445. return -1;
  446. } else {
  447. return client->SetFreeWheel(onoff);
  448. }
  449. }
  450. EXPORT int jack_set_buffer_size(jack_client_t* ext_client, jack_nframes_t buffer_size)
  451. {
  452. JackClient* client = (JackClient*)ext_client;
  453. if (client == NULL) {
  454. jack_error("jack_set_buffer_size called with a NULL client");
  455. return -1;
  456. } else if (!CheckBufferSize(buffer_size)) {
  457. return -1;
  458. } else {
  459. return client->SetBufferSize(buffer_size);
  460. }
  461. }
  462. EXPORT int jack_set_buffer_size_callback(jack_client_t* ext_client, JackBufferSizeCallback bufsize_callback, void* arg)
  463. {
  464. JackClient* client = (JackClient*)ext_client;
  465. if (client == NULL) {
  466. jack_error("jack_set_buffer_size_callback called with a NULL client");
  467. return -1;
  468. } else {
  469. return client->SetBufferSizeCallback(bufsize_callback, arg);
  470. }
  471. }
  472. EXPORT int jack_set_sample_rate_callback(jack_client_t* ext_client, JackSampleRateCallback srate_callback, void* arg)
  473. {
  474. JackClient* client = (JackClient*)ext_client;
  475. JackLog("jack_set_sample_rate_callback ext_client %x client %x \n", ext_client, client);
  476. if (client == NULL) {
  477. jack_error("jack_set_sample_rate_callback called with a NULL client");
  478. return -1;
  479. } else {
  480. JackLog("jack_set_sample_rate_callback: deprecated\n");
  481. return -1;
  482. }
  483. }
  484. EXPORT int jack_set_port_registration_callback(jack_client_t* ext_client, JackPortRegistrationCallback registration_callback, void* arg)
  485. {
  486. JackClient* client = (JackClient*)ext_client;
  487. if (client == NULL) {
  488. jack_error("jack_set_port_registration_callback called with a NULL client");
  489. return -1;
  490. } else {
  491. return client->SetPortRegistrationCallback(registration_callback, arg);
  492. }
  493. }
  494. EXPORT int jack_set_graph_order_callback(jack_client_t* ext_client, JackGraphOrderCallback graph_callback, void* arg)
  495. {
  496. JackClient* client = (JackClient*)ext_client;
  497. JackLog("jack_set_graph_order_callback ext_client %x client %x \n", ext_client, client);
  498. if (client == NULL) {
  499. jack_error("jack_set_graph_order_callback called with a NULL client");
  500. return -1;
  501. } else {
  502. return client->SetGraphOrderCallback(graph_callback, arg);
  503. }
  504. }
  505. EXPORT int jack_set_xrun_callback(jack_client_t* ext_client, JackXRunCallback xrun_callback, void* arg)
  506. {
  507. JackClient* client = (JackClient*)ext_client;
  508. if (client == NULL) {
  509. jack_error("jack_set_xrun_callback called with a NULL client");
  510. return -1;
  511. } else {
  512. return client->SetXRunCallback(xrun_callback, arg);
  513. }
  514. }
  515. EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg)
  516. {
  517. JackClient* client = (JackClient*)ext_client;
  518. JackLog("jack_set_thread_init_callback ext_client %x client %x \n", ext_client, client);
  519. if (client == NULL) {
  520. jack_error("jack_set_thread_init_callback called with a NULL client");
  521. return -1;
  522. } else {
  523. return client->SetInitCallback(init_callback, arg);
  524. }
  525. }
  526. EXPORT int jack_activate(jack_client_t* ext_client)
  527. {
  528. JackClient* client = (JackClient*)ext_client;
  529. if (client == NULL) {
  530. jack_error("jack_activate called with a NULL client");
  531. return -1;
  532. } else {
  533. return client->Activate();
  534. }
  535. }
  536. EXPORT int jack_deactivate(jack_client_t* ext_client)
  537. {
  538. JackClient* client = (JackClient*)ext_client;
  539. if (client == NULL) {
  540. jack_error("jack_deactivate called with a NULL client");
  541. return -1;
  542. } else {
  543. return client->Deactivate();
  544. }
  545. }
  546. 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)
  547. {
  548. JackClient* client = (JackClient*)ext_client;
  549. if (client == NULL) {
  550. jack_error("jack_port_register called with a NULL client");
  551. return NULL;
  552. } else if ((port_name == NULL) || (port_type == NULL)) {
  553. jack_error("jack_port_register called with a NULL port name or a NULL port_type");
  554. return NULL;
  555. } else {
  556. return (jack_port_t *)client->PortRegister(port_name, port_type, flags, buffer_size);
  557. }
  558. }
  559. EXPORT int jack_port_unregister(jack_client_t* ext_client, jack_port_t* port)
  560. {
  561. JackClient* client = (JackClient*)ext_client;
  562. if (client == NULL) {
  563. jack_error("jack_port_unregister called with a NULL client");
  564. return -1;
  565. }
  566. jack_port_id_t myport = (jack_port_id_t)port;
  567. if (!CheckPort(myport)) {
  568. jack_error("jack_port_unregister called with an incorrect port %ld", myport);
  569. return -1;
  570. }
  571. return client->PortUnRegister(myport);
  572. }
  573. EXPORT int jack_port_is_mine(const jack_client_t* ext_client, const jack_port_t* port)
  574. {
  575. JackClient* client = (JackClient*)ext_client;
  576. if (client == NULL) {
  577. jack_error("jack_port_is_mine called with a NULL client");
  578. return -1;
  579. }
  580. jack_port_id_t myport = (jack_port_id_t)port;
  581. if (!CheckPort(myport)) {
  582. jack_error("jack_port_is_mine called with an incorrect port %ld", myport);
  583. return -1;
  584. }
  585. return client->PortIsMine(myport);
  586. }
  587. EXPORT const char** jack_port_get_connections(const jack_port_t* port)
  588. {
  589. jack_port_id_t myport = (jack_port_id_t)port;
  590. if (!CheckPort(myport)) {
  591. jack_error("jack_port_get_connections called with an incorrect port %ld", myport);
  592. return NULL;
  593. } else {
  594. WaitGraphChange();
  595. return GetGraphManager()->GetConnections(myport);
  596. }
  597. }
  598. // Calling client does not need to "own" the port
  599. EXPORT const char** jack_port_get_all_connections(const jack_client_t* ext_client, const jack_port_t* port)
  600. {
  601. JackClient* client = (JackClient*)ext_client;
  602. if (client == NULL) {
  603. jack_error("jack_port_get_all_connections called with a NULL client");
  604. return NULL;
  605. }
  606. jack_port_id_t myport = (jack_port_id_t)port;
  607. if (!CheckPort(myport)) {
  608. jack_error("jack_port_get_all_connections called with an incorrect port %ld", myport);
  609. return NULL;
  610. } else {
  611. WaitGraphChange();
  612. return GetGraphManager()->GetConnections(myport);
  613. }
  614. }
  615. // Does not use the client parameter
  616. EXPORT int jack_port_lock(jack_client_t* ext_client, jack_port_t* port)
  617. {
  618. JackClient* client = (JackClient*)ext_client;
  619. if (client == NULL) {
  620. jack_error("jack_port_lock called with a NULL client");
  621. return -1;
  622. }
  623. jack_port_id_t myport = (jack_port_id_t)port;
  624. if (!CheckPort(myport)) {
  625. jack_error("jack_port_lock called with an incorrect port %ld", myport);
  626. return -1;
  627. } else {
  628. return (myport && client->PortIsMine(myport)) ? GetGraphManager()->GetPort(myport)->Lock() : -1;
  629. }
  630. }
  631. // Does not use the client parameter
  632. EXPORT int jack_port_unlock(jack_client_t* ext_client, jack_port_t* port)
  633. {
  634. JackClient* client = (JackClient*)ext_client;
  635. if (client == NULL) {
  636. jack_error("jack_port_unlock called with a NULL client");
  637. return -1;
  638. }
  639. jack_port_id_t myport = (jack_port_id_t)port;
  640. if (!CheckPort(myport)) {
  641. jack_error("jack_port_unlock called with an incorrect port %ld", myport);
  642. return -1;
  643. } else {
  644. return (myport && client->PortIsMine(myport)) ? GetGraphManager()->GetPort(myport)->Unlock() : -1;
  645. }
  646. }
  647. EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t* ext_client, jack_port_t* port)
  648. {
  649. JackClient* client = (JackClient*)ext_client;
  650. if (client == NULL) {
  651. jack_error("jack_port_get_total_latency called with a NULL client");
  652. return 0;
  653. }
  654. jack_port_id_t myport = (jack_port_id_t)port;
  655. if (!CheckPort(myport)) {
  656. jack_error("jack_port_get_total_latency called with an incorrect port %ld", myport);
  657. return 0;
  658. } else {
  659. // The latency computation is done each time
  660. WaitGraphChange();
  661. return GetGraphManager()->GetTotalLatency(myport);
  662. }
  663. }
  664. EXPORT int jack_connect(jack_client_t* ext_client, const char* src, const char* dst)
  665. {
  666. JackClient* client = (JackClient*)ext_client;
  667. if (client == NULL) {
  668. jack_error("jack_connect called with a NULL client");
  669. return -1;
  670. } else if ((src == NULL) || (dst == NULL)) {
  671. jack_error("jack_connect called with a NULL port name");
  672. return -1;
  673. } else {
  674. return client->PortConnect(src, dst);
  675. }
  676. }
  677. EXPORT int jack_disconnect(jack_client_t* ext_client, const char* src, const char* dst)
  678. {
  679. JackClient* client = (JackClient*)ext_client;
  680. if (client == NULL) {
  681. jack_error("jack_disconnect called with a NULL client");
  682. return -1;
  683. } else if ((src == NULL) || (dst == NULL)) {
  684. jack_error("jack_connect called with a NULL port name");
  685. return -1;
  686. } else {
  687. return client->PortDisconnect(src, dst);
  688. }
  689. }
  690. EXPORT int jack_port_connect(jack_client_t* ext_client, jack_port_t* src, jack_port_t* dst)
  691. {
  692. JackClient* client = (JackClient*)ext_client;
  693. if (client == NULL) {
  694. jack_error("jack_port_connect called with a NULL client");
  695. return -1;
  696. }
  697. jack_port_id_t mysrc = (jack_port_id_t)src;
  698. if (!CheckPort(mysrc)) {
  699. jack_error("jack_port_connect called with a NULL src port");
  700. return -1;
  701. }
  702. jack_port_id_t mydst = (jack_port_id_t)dst;
  703. if (!CheckPort(mydst)) {
  704. jack_error("jack_port_connect called with a NULL dst port");
  705. return -1;
  706. }
  707. return client->PortConnect(mysrc, mydst);
  708. }
  709. EXPORT int jack_port_disconnect(jack_client_t* ext_client, jack_port_t* src)
  710. {
  711. JackClient* client = (JackClient*)ext_client;
  712. if (client == NULL) {
  713. jack_error("jack_port_disconnect called with a NULL client");
  714. return -1;
  715. }
  716. jack_port_id_t myport = (jack_port_id_t)src;
  717. if (!CheckPort(myport)) {
  718. jack_error("jack_port_disconnect called with an incorrect port %ld", myport);
  719. return -1;
  720. }
  721. return client->PortDisconnect(myport);
  722. }
  723. EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t* ext_client)
  724. {
  725. JackClient* client = (JackClient*)ext_client;
  726. if (client == NULL) {
  727. jack_error("jack_get_sample_rate called with a NULL client");
  728. return 0;
  729. } else {
  730. return GetEngineControl()->fSampleRate;
  731. }
  732. }
  733. EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t* ext_client)
  734. {
  735. JackClient* client = (JackClient*)ext_client;
  736. if (client == NULL) {
  737. jack_error("jack_get_buffer_size called with a NULL client");
  738. return 0;
  739. } else {
  740. return GetEngineControl()->fBufferSize;
  741. }
  742. }
  743. EXPORT const char** jack_get_ports(jack_client_t* ext_client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
  744. {
  745. JackClient* client = (JackClient*)ext_client;
  746. if (client == NULL) {
  747. jack_error("jack_get_ports called with a NULL client");
  748. return NULL;
  749. }
  750. return GetGraphManager()->GetPorts(port_name_pattern, type_name_pattern, flags);
  751. }
  752. EXPORT jack_port_t* jack_port_by_name(jack_client_t* ext_client, const char* portname)
  753. {
  754. JackClient* client = (JackClient*)ext_client;
  755. if (client == NULL) {
  756. jack_error("jack_get_ports called with a NULL client");
  757. return 0;
  758. }
  759. if (portname == NULL) {
  760. jack_error("jack_port_by_name called with a NULL port name");
  761. return NULL;
  762. } else {
  763. int res = GetGraphManager()->GetPort(portname); // returns a port index at least > 1
  764. return (res == NO_PORT) ? NULL : (jack_port_t*)res;
  765. }
  766. }
  767. EXPORT jack_port_t* jack_port_by_id(const jack_client_t* ext_client, jack_port_id_t id)
  768. {
  769. /* jack_port_t* type is actually the port index */
  770. return (jack_port_t*)id;
  771. }
  772. EXPORT int jack_engine_takeover_timebase(jack_client_t* ext_client)
  773. {
  774. JackClient* client = (JackClient*)ext_client;
  775. if (client == NULL) {
  776. jack_error("jack_engine_takeover_timebase called with a NULL client");
  777. return -1;
  778. } else {
  779. jack_error("jack_engine_takeover_timebase : not yet implemented\n");
  780. return 0;
  781. }
  782. }
  783. EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t* ext_client)
  784. {
  785. JackTimer timer;
  786. GetEngineControl()->ReadFrameTime(&timer);
  787. return (jack_nframes_t) floor((((float)GetEngineControl()->fSampleRate) / 1000000.0f) * (GetMicroSeconds() - timer.fCurrentCallback));
  788. }
  789. EXPORT jack_nframes_t jack_frame_time(const jack_client_t* ext_client)
  790. {
  791. JackClient* client = (JackClient*)ext_client;
  792. if (client == NULL) {
  793. jack_error("jack_frame_time called with a NULL client");
  794. return 0;
  795. } else {
  796. JackTimer timer;
  797. GetEngineControl()->ReadFrameTime(&timer);
  798. if (timer.fInitialized) {
  799. return timer.fFrames +
  800. (long) rint(((double) ((jack_time_t)(GetMicroSeconds() - timer.fCurrentWakeup)) /
  801. ((jack_time_t)(timer.fNextWakeUp - timer.fCurrentWakeup))) * GetEngineControl()->fBufferSize);
  802. } else {
  803. return 0;
  804. }
  805. }
  806. }
  807. EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t* ext_client)
  808. {
  809. JackTimer timer;
  810. GetEngineControl()->ReadFrameTime(&timer);
  811. return timer.fFrames;
  812. }
  813. EXPORT float jack_cpu_load(jack_client_t* ext_client)
  814. {
  815. JackClient* client = (JackClient*)ext_client;
  816. if (client == NULL) {
  817. jack_error("jack_cpu_load called with a NULL client");
  818. return 0.0f;
  819. } else {
  820. return GetEngineControl()->fCPULoad;
  821. }
  822. }
  823. EXPORT pthread_t jack_client_thread_id(jack_client_t* ext_client)
  824. {
  825. JackClient* client = (JackClient*)ext_client;
  826. if (client == NULL) {
  827. jack_error("jack_client_thread_id called with a NULL client");
  828. return (pthread_t)NULL;
  829. } else {
  830. return client->GetThreadID();
  831. }
  832. }
  833. EXPORT char* jack_get_client_name (jack_client_t* ext_client)
  834. {
  835. JackClient* client = (JackClient*)ext_client;
  836. if (client == NULL) {
  837. jack_error("jack_get_client_name called with a NULL client");
  838. return NULL;
  839. } else {
  840. return client->GetClientControl()->fName;
  841. }
  842. }
  843. EXPORT int jack_client_name_size(void)
  844. {
  845. return JACK_CLIENT_NAME_SIZE;
  846. }
  847. EXPORT int jack_port_name_size(void)
  848. {
  849. return JACK_PORT_NAME_SIZE;
  850. }
  851. // transport.h
  852. EXPORT int jack_release_timebase(jack_client_t* ext_client)
  853. {
  854. JackClient* client = (JackClient*)ext_client;
  855. if (client == NULL) {
  856. jack_error("jack_release_timebase called with a NULL client");
  857. return -1;
  858. } else {
  859. return client->ReleaseTimebase();
  860. }
  861. }
  862. EXPORT int jack_set_sync_callback(jack_client_t* ext_client, JackSyncCallback sync_callback, void *arg)
  863. {
  864. JackClient* client = (JackClient*)ext_client;
  865. if (client == NULL) {
  866. jack_error("jack_set_sync_callback called with a NULL client");
  867. return -1;
  868. } else {
  869. return client->SetSyncCallback(sync_callback, arg);
  870. }
  871. }
  872. EXPORT int jack_set_sync_timeout(jack_client_t* ext_client, jack_time_t timeout)
  873. {
  874. JackClient* client = (JackClient*)ext_client;
  875. if (client == NULL) {
  876. jack_error("jack_set_sync_timeout called with a NULL client");
  877. return -1;
  878. } else {
  879. return client->SetSyncTimeout(timeout);
  880. }
  881. }
  882. EXPORT int jack_set_timebase_callback(jack_client_t* ext_client, int conditional, JackTimebaseCallback timebase_callback, void* arg)
  883. {
  884. JackClient* client = (JackClient*)ext_client;
  885. if (client == NULL) {
  886. jack_error("jack_set_timebase_callback called with a NULL client");
  887. return -1;
  888. } else {
  889. return client->SetTimebaseCallback(conditional, timebase_callback, arg);
  890. }
  891. }
  892. EXPORT int jack_transport_locate(jack_client_t* ext_client, jack_nframes_t frame)
  893. {
  894. JackClient* client = (JackClient*)ext_client;
  895. if (client == NULL) {
  896. jack_error("jack_transport_locate called with a NULL client");
  897. return -1;
  898. } else {
  899. return client->TransportLocate(frame);
  900. }
  901. }
  902. EXPORT jack_transport_state_t jack_transport_query(const jack_client_t* ext_client, jack_position_t* pos)
  903. {
  904. JackClient* client = (JackClient*)ext_client;
  905. if (client == NULL) {
  906. jack_error("jack_transport_query called with a NULL client");
  907. return JackTransportStopped;
  908. } else {
  909. return client->TransportQuery(pos);
  910. }
  911. }
  912. EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t* ext_client)
  913. {
  914. JackClient* client = (JackClient*)ext_client;
  915. if (client == NULL) {
  916. jack_error("jack_get_current_transport_frame called with a NULL client");
  917. return 0;
  918. } else {
  919. return client->GetCurrentTransportFrame();
  920. }
  921. }
  922. EXPORT int jack_transport_reposition(jack_client_t* ext_client, jack_position_t* pos)
  923. {
  924. JackClient* client = (JackClient*)ext_client;
  925. if (client == NULL) {
  926. jack_error("jack_transport_reposition called with a NULL client");
  927. return -1;
  928. } else {
  929. return client->TransportReposition(pos);
  930. }
  931. }
  932. EXPORT void jack_transport_start(jack_client_t* ext_client)
  933. {
  934. JackClient* client = (JackClient*)ext_client;
  935. if (client == NULL) {
  936. jack_error("jack_transport_start called with a NULL client");
  937. } else {
  938. client->TransportStart();
  939. }
  940. }
  941. EXPORT void jack_transport_stop(jack_client_t* ext_client)
  942. {
  943. JackClient* client = (JackClient*)ext_client;
  944. if (client == NULL) {
  945. jack_error("jack_transport_stop called with a NULL client");
  946. } else {
  947. client->TransportStop();
  948. }
  949. }
  950. // deprecated
  951. EXPORT void jack_get_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
  952. {
  953. JackLog("jack_get_transport_info : deprecated");
  954. if (tinfo)
  955. memset(tinfo, 0, sizeof(jack_transport_info_t));
  956. }
  957. EXPORT void jack_set_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
  958. {
  959. JackLog("jack_set_transport_info : deprecated");
  960. if (tinfo)
  961. memset(tinfo, 0, sizeof(jack_transport_info_t));
  962. }
  963. // statistics.h
  964. EXPORT float jack_get_max_delayed_usecs(jack_client_t* ext_client)
  965. {
  966. JackLog("jack_get_max_delayed_usecs: not yet implemented\n");
  967. return 0.f;
  968. }
  969. EXPORT float jack_get_xrun_delayed_usecs(jack_client_t* ext_client)
  970. {
  971. JackLog("jack_get_xrun_delayed_usecs: not yet implemented\n");
  972. return 0.f;
  973. }
  974. EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client)
  975. {
  976. JackLog("jack_reset_max_delayed_usecs: not yet implemented\n");
  977. }
  978. // thread.h
  979. EXPORT int jack_acquire_real_time_scheduling(pthread_t thread, int priority)
  980. {
  981. #ifdef __APPLE__
  982. return JackMachThread::AcquireRealTimeImp(thread, 0, 500 * 1000, 500 * 1000);
  983. #elif WIN32
  984. return JackWinThread::AcquireRealTimeImp(thread, priority);
  985. #else
  986. return JackPosixThread::AcquireRealTimeImp(thread, priority);
  987. #endif
  988. }
  989. EXPORT int jack_client_create_thread(jack_client_t* client,
  990. pthread_t *thread,
  991. int priority,
  992. int realtime, /* boolean */
  993. void *(*start_routine)(void*),
  994. void *arg)
  995. {
  996. #ifdef __APPLE__
  997. return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg);
  998. #elif WIN32
  999. return JackWinThread::StartImp(thread, priority, realtime, start_routine, arg);
  1000. #else
  1001. return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg);
  1002. #endif
  1003. }
  1004. EXPORT int jack_drop_real_time_scheduling(pthread_t thread)
  1005. {
  1006. #ifdef __APPLE__
  1007. return JackMachThread::DropRealTimeImp(thread);
  1008. #elif WIN32
  1009. return JackWinThread::DropRealTimeImp(thread);
  1010. #else
  1011. return JackPosixThread::DropRealTimeImp(thread);
  1012. #endif
  1013. }
  1014. // intclient.h
  1015. EXPORT char* jack_get_internal_client_name(jack_client_t* ext_client, jack_intclient_t intclient)
  1016. {
  1017. JackLog("jack_get_internal_client_name: not yet implemented\n");
  1018. return "";
  1019. }
  1020. EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t* ext_client, const char* client_name, jack_status_t* status)
  1021. {
  1022. JackLog("jack_internal_client_handle: not yet implemented\n");
  1023. return 0;
  1024. }
  1025. 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, ...)
  1026. {
  1027. JackLog("jack_internal_client_load: not yet implemented\n");
  1028. return 0;
  1029. }
  1030. EXPORT jack_status_t jack_internal_client_unload(jack_client_t* ext_client, jack_intclient_t intclient)
  1031. {
  1032. JackLog("jack_internal_client_unload: not yet implemented\n");
  1033. return JackFailure;
  1034. }