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.

1646 lines
53KB

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