jack1 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.

547 lines
14KB

  1. /*
  2. JACK transport client interface -- runs in the client process.
  3. Copyright (C) 2001-2003 Paul Davis
  4. Copyright (C) 2003 Jack O'Quin
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License
  7. as published by the Free Software Foundation; either version 2.1
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this program; if not, write to the Free
  15. Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  16. 02111-1307, USA.
  17. */
  18. #include <config.h>
  19. #include <errno.h>
  20. #include <math.h>
  21. #include <stdio.h>
  22. #include <jack/uuid.h>
  23. #include "atomicity.h"
  24. #include "internal.h"
  25. #include "local.h"
  26. /********************* Internal functions *********************/
  27. /* generate a unique non-zero ID, different for each call */
  28. jack_unique_t
  29. jack_generate_unique_id (jack_control_t *ectl)
  30. {
  31. /* The jack_unique_t is an opaque type. */
  32. return exchange_and_add(&ectl->seq_number, 1);
  33. }
  34. static inline void
  35. jack_read_frame_time (const jack_client_t *client, jack_frame_timer_t *copy)
  36. {
  37. int tries = 0;
  38. long timeout = 1000;
  39. do {
  40. /* throttle the busy wait if we don't get
  41. the answer very quickly.
  42. XXX This is disgusting. on a UP
  43. system, it needs to sleep
  44. if the first try didn't work. on an SMP
  45. system, it should wait for half of
  46. the context switch time before
  47. sleeping.
  48. */
  49. if (tries > 10) {
  50. usleep (20);
  51. tries = 0;
  52. /* debug code to avoid system hangs... */
  53. if (--timeout == 0) {
  54. jack_error ("hung in loop copying position A");
  55. abort();
  56. }
  57. }
  58. *copy = client->engine->frame_timer;
  59. tries++;
  60. } while (copy->guard1 != copy->guard2);
  61. }
  62. /* copy a JACK transport position structure (thread-safe) */
  63. void
  64. jack_transport_copy_position (jack_position_t *from, jack_position_t *to)
  65. {
  66. int tries = 0;
  67. long timeout = 1000;
  68. do {
  69. /* throttle the busy wait if we don't get the answer
  70. * very quickly. See comment above about this
  71. * design.
  72. */
  73. if (tries > 10) {
  74. usleep (20);
  75. tries = 0;
  76. /* debug code to avoid system hangs... */
  77. if (--timeout == 0) {
  78. jack_error ("hung in loop copying position B");
  79. abort();
  80. }
  81. }
  82. *to = *from;
  83. tries++;
  84. } while (to->unique_1 != to->unique_2);
  85. }
  86. static inline int
  87. jack_transport_request_new_pos (jack_client_t *client, jack_position_t *pos)
  88. {
  89. jack_control_t *ectl = client->engine;
  90. /* distinguish this request from all others */
  91. pos->unique_1 = pos->unique_2 = jack_generate_unique_id(ectl);
  92. /* clients may not set these fields */
  93. pos->usecs = ectl->current_time.usecs;
  94. pos->frame_rate = ectl->current_time.frame_rate;
  95. /* carefully copy requested postion into shared memory */
  96. jack_transport_copy_position (pos, &ectl->request_time);
  97. return 0;
  98. }
  99. /******************** Callback invocations ********************/
  100. void
  101. jack_call_sync_client (jack_client_t *client)
  102. {
  103. jack_client_control_t *control = client->control;
  104. jack_control_t *ectl = client->engine;
  105. /* Make sure still active and slow-sync; active_slowsync is
  106. * set in a critical section; sync_cb is not. */
  107. if ((ectl->new_pos || control->sync_poll || control->sync_new) &&
  108. control->active_slowsync) {
  109. if (client->sync_cb (ectl->transport_state,
  110. &ectl->current_time,
  111. client->sync_arg)) {
  112. if (control->sync_poll) {
  113. control->sync_poll = 0;
  114. ectl->sync_remain--;
  115. }
  116. }
  117. control->sync_new = 0;
  118. }
  119. }
  120. void
  121. jack_call_timebase_master (jack_client_t *client)
  122. {
  123. jack_client_control_t *control = client->control;
  124. jack_control_t *ectl = client->engine;
  125. int new_pos = (int) ectl->pending_pos;
  126. /* Make sure this is still the master; is_timebase is set in a
  127. * critical section; timebase_cb is not. */
  128. if (control->is_timebase) {
  129. if (control->timebase_new) { /* first callback? */
  130. control->timebase_new = 0;
  131. new_pos = 1;
  132. }
  133. if ((ectl->transport_state == JackTransportRolling) ||
  134. new_pos) {
  135. client->timebase_cb (ectl->transport_state,
  136. ectl->buffer_size,
  137. &ectl->pending_time,
  138. new_pos,
  139. client->timebase_arg);
  140. }
  141. } else {
  142. /* another master took over, so resign */
  143. client->timebase_cb = NULL;
  144. client->timebase_arg = NULL;
  145. control->timebase_cb_cbset = FALSE;
  146. }
  147. }
  148. /************************* API functions *************************/
  149. jack_nframes_t
  150. jack_get_current_transport_frame (const jack_client_t *client)
  151. {
  152. jack_position_t position;
  153. float usecs;
  154. jack_nframes_t elapsed;
  155. jack_transport_state_t tstate;
  156. /* get the current transport position information.
  157. this is thread-safe and atomic with respect
  158. to the structure contents.
  159. */
  160. tstate = jack_transport_query (client, &position);
  161. if (tstate != JackTransportRolling) {
  162. return position.frame;
  163. }
  164. /* compute the elapsed usecs then audio frames since
  165. the transport info was last updated
  166. */
  167. usecs = jack_get_microseconds() - position.usecs;
  168. elapsed = (jack_nframes_t) floor ((((float) position.frame_rate)
  169. / 1000000.0f) * usecs);
  170. /* return the estimated transport frame position
  171. */
  172. return position.frame + elapsed;
  173. }
  174. jack_nframes_t
  175. jack_frames_since_cycle_start (const jack_client_t *client)
  176. {
  177. float usecs;
  178. jack_control_t *ectl = client->engine;
  179. usecs = jack_get_microseconds() - ectl->current_time.usecs;
  180. return (jack_nframes_t) floor ((((float) ectl->current_time.frame_rate)
  181. / 1000000.0f) * usecs);
  182. }
  183. int
  184. jack_get_cycle_times (const jack_client_t *client,
  185. jack_nframes_t *current_frames,
  186. jack_time_t *current_usecs,
  187. jack_time_t *next_usecs,
  188. float *period_usecs)
  189. {
  190. jack_frame_timer_t time;
  191. jack_read_frame_time (client, &time);
  192. if (time.initialized) {
  193. *current_frames = time.frames;
  194. *current_usecs = time.current_wakeup;
  195. *next_usecs = time.next_wakeup;
  196. *period_usecs = time.period_usecs;
  197. return 0;
  198. }
  199. return 1;
  200. }
  201. jack_time_t
  202. jack_get_time()
  203. {
  204. return jack_get_microseconds();
  205. }
  206. jack_nframes_t
  207. jack_time_to_frames(const jack_client_t *client, jack_time_t usecs)
  208. {
  209. jack_frame_timer_t time;
  210. jack_control_t *ectl = client->engine;
  211. jack_read_frame_time (client, &time);
  212. if (time.initialized) {
  213. /*
  214. Make sure we have signed differences. It would make a lot of sense
  215. to use the standard signed intNN_t types everywhere instead of e.g.
  216. jack_nframes_t and jack_time_t. This would at least ensure that the
  217. types used below are the correct ones. There is no way to get a type
  218. that would be 'a signed version of jack_time_t' for example - the
  219. types below are inherently fragile and there is no automatic way to
  220. check they are the correct ones. The only way is to check manually
  221. against jack/types.h. FA - 16/02/2012
  222. */
  223. int64_t du = usecs - time.current_wakeup;
  224. int64_t dp = time.next_wakeup - time.current_wakeup;
  225. return time.frames + (int32_t) floor (((double) du / (double) dp
  226. * ectl->buffer_size) + 0.5);
  227. }
  228. return 0;
  229. }
  230. jack_nframes_t
  231. jack_frame_time (const jack_client_t *client)
  232. {
  233. jack_time_t now = jack_get_microseconds();
  234. return jack_time_to_frames(client, now);
  235. }
  236. jack_nframes_t
  237. jack_last_frame_time (const jack_client_t *client)
  238. {
  239. return client->engine->frame_timer.frames;
  240. }
  241. jack_time_t
  242. jack_frames_to_time(const jack_client_t *client, jack_nframes_t frames)
  243. {
  244. jack_frame_timer_t time;
  245. jack_control_t *ectl = client->engine;
  246. jack_read_frame_time (client, &time);
  247. if (time.initialized) {
  248. /*
  249. Make sure we have signed differences. It would make a lot of sense
  250. to use the standard signed intNN_t types everywhere instead of e.g.
  251. jack_nframes_t and jack_time_t. This would at least ensure that the
  252. types used below are the correct ones. There is no way to get a type
  253. that would be 'a signed version of jack_time_t' for example - the
  254. types below are inherently fragile and there is no automatic way to
  255. check they are the correct ones. The only way is to check manually
  256. against jack/types.h. FA - 16/02/2012
  257. */
  258. int32_t df = frames - time.frames;
  259. int64_t dp = time.next_wakeup - time.current_wakeup;
  260. return time.current_wakeup + (int64_t) floor (((double) df * (double) dp
  261. / ectl->buffer_size) + 0.5);
  262. }
  263. return 0;
  264. }
  265. jack_nframes_t
  266. jack_get_sample_rate (jack_client_t *client)
  267. {
  268. return client->engine->current_time.frame_rate;
  269. }
  270. int
  271. jack_set_sample_rate_callback (jack_client_t *client,
  272. JackSampleRateCallback callback, void *arg)
  273. {
  274. if (client->control->active) {
  275. jack_error ("You cannot set callbacks on an active client.");
  276. return -1;
  277. }
  278. client->srate_arg = arg;
  279. client->srate = callback;
  280. client->control->srate_cbset = (callback != NULL);
  281. /* Now invoke it */
  282. callback (client->engine->current_time.frame_rate, arg);
  283. return 0;
  284. }
  285. int
  286. jack_release_timebase (jack_client_t *client)
  287. {
  288. int rc;
  289. jack_request_t req;
  290. jack_client_control_t *ctl = client->control;
  291. VALGRIND_MEMSET (&req, 0, sizeof (req));
  292. req.type = ResetTimeBaseClient;
  293. jack_uuid_copy (&req.x.client_id, ctl->uuid);
  294. rc = jack_client_deliver_request (client, &req);
  295. if (rc == 0) {
  296. client->timebase_cb = NULL;
  297. client->timebase_arg = NULL;
  298. ctl->timebase_cb_cbset = 0;
  299. }
  300. return rc;
  301. }
  302. int
  303. jack_set_sync_callback (jack_client_t *client,
  304. JackSyncCallback sync_callback, void *arg)
  305. {
  306. jack_client_control_t *ctl = client->control;
  307. jack_request_t req;
  308. int rc;
  309. VALGRIND_MEMSET (&req, 0, sizeof (req));
  310. if (sync_callback)
  311. req.type = SetSyncClient;
  312. else
  313. req.type = ResetSyncClient;
  314. jack_uuid_copy (&req.x.client_id, ctl->uuid);
  315. rc = jack_client_deliver_request (client, &req);
  316. if (rc == 0) {
  317. client->sync_cb = sync_callback;
  318. client->sync_arg = arg;
  319. ctl->sync_cb_cbset = TRUE;
  320. }
  321. return rc;
  322. }
  323. int
  324. jack_set_sync_timeout (jack_client_t *client, jack_time_t usecs)
  325. {
  326. jack_request_t req;
  327. VALGRIND_MEMSET (&req, 0, sizeof (req));
  328. req.type = SetSyncTimeout;
  329. req.x.timeout = usecs;
  330. return jack_client_deliver_request (client, &req);
  331. }
  332. int
  333. jack_set_timebase_callback (jack_client_t *client, int conditional,
  334. JackTimebaseCallback timebase_cb, void *arg)
  335. {
  336. int rc;
  337. jack_request_t req;
  338. jack_client_control_t *ctl = client->control;
  339. VALGRIND_MEMSET (&req, 0, sizeof (req));
  340. req.type = SetTimeBaseClient;
  341. jack_uuid_copy (&req.x.timebase.client_id, ctl->uuid);
  342. req.x.timebase.conditional = conditional;
  343. rc = jack_client_deliver_request (client, &req);
  344. if (rc == 0) {
  345. client->timebase_arg = arg;
  346. client->timebase_cb = timebase_cb;
  347. ctl->timebase_cb_cbset = TRUE;
  348. }
  349. return rc;
  350. }
  351. int
  352. jack_transport_locate (jack_client_t *client, jack_nframes_t frame)
  353. {
  354. jack_position_t pos;
  355. pos.frame = frame;
  356. pos.valid = 0;
  357. return jack_transport_request_new_pos (client, &pos);
  358. }
  359. jack_transport_state_t
  360. jack_transport_query (const jack_client_t *client, jack_position_t *pos)
  361. {
  362. jack_control_t *ectl = client->engine;
  363. if (pos) {
  364. /* the guarded copy makes this function work in any
  365. * thread
  366. */
  367. jack_transport_copy_position (&ectl->current_time, pos);
  368. }
  369. return ectl->transport_state;
  370. }
  371. int
  372. jack_transport_reposition (jack_client_t *client, const jack_position_t *pos)
  373. {
  374. /* copy the input, to avoid modifying its contents */
  375. jack_position_t tmp = *pos;
  376. /* validate input */
  377. if (tmp.valid & ~JACK_POSITION_MASK) /* unknown field present? */
  378. return EINVAL;
  379. return jack_transport_request_new_pos (client, &tmp);
  380. }
  381. void
  382. jack_transport_start (jack_client_t *client)
  383. {
  384. client->engine->transport_cmd = TransportCommandStart;
  385. }
  386. void
  387. jack_transport_stop (jack_client_t *client)
  388. {
  389. client->engine->transport_cmd = TransportCommandStop;
  390. }
  391. #ifdef OLD_TRANSPORT
  392. /************* Compatibility with old transport API. *************/
  393. int
  394. jack_engine_takeover_timebase (jack_client_t *client)
  395. {
  396. jack_error ("jack_engine_takeover_timebase() is no longer supported.");
  397. return ENOSYS;
  398. }
  399. void
  400. jack_get_transport_info (jack_client_t *client,
  401. jack_transport_info_t *info)
  402. {
  403. jack_control_t *ectl = client->engine;
  404. static int first_time = 1;
  405. if (first_time)
  406. jack_error ("jack_get_transport_info() is deprecated.");
  407. first_time = 0;
  408. /* check that this is the process thread */
  409. if (!pthread_equal(client->thread_id, pthread_self())) {
  410. jack_error("Invalid thread for jack_get_transport_info().");
  411. abort(); /* kill this client */
  412. }
  413. info->usecs = ectl->current_time.usecs;
  414. info->frame_rate = ectl->current_time.frame_rate;
  415. info->transport_state = ectl->transport_state;
  416. info->frame = ectl->current_time.frame;
  417. info->valid = (ectl->current_time.valid |
  418. JackTransportState | JackTransportPosition);
  419. if (info->valid & JackTransportBBT) {
  420. info->bar = ectl->current_time.bar;
  421. info->beat = ectl->current_time.beat;
  422. info->tick = ectl->current_time.tick;
  423. info->bar_start_tick = ectl->current_time.bar_start_tick;
  424. info->beats_per_bar = ectl->current_time.beats_per_bar;
  425. info->beat_type = ectl->current_time.beat_type;
  426. info->ticks_per_beat = ectl->current_time.ticks_per_beat;
  427. info->beats_per_minute = ectl->current_time.beats_per_minute;
  428. }
  429. }
  430. void
  431. jack_set_transport_info (jack_client_t *client,
  432. jack_transport_info_t *info)
  433. {
  434. static int first_time = 1;
  435. if (first_time)
  436. jack_error ("jack_set_transport_info() no longer supported.");
  437. first_time = 0;
  438. }
  439. #endif /* OLD_TRANSPORT */