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.

538 lines
14KB

  1. /*
  2. JACK transport engine -- runs in the server 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 General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. 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 General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include <config.h>
  18. #include <errno.h>
  19. #include <assert.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <jack/internal.h>
  23. #include <jack/engine.h>
  24. #include <jack/messagebuffer.h>
  25. #include "transengine.h"
  26. /********************** internal functions **********************/
  27. /* initiate polling a new slow-sync client
  28. *
  29. * precondition: caller holds the graph lock. */
  30. static inline void
  31. jack_sync_poll_new (jack_engine_t *engine, jack_client_internal_t *client)
  32. {
  33. /* force sync_cb callback to run in its first cycle */
  34. engine->control->sync_time_left = engine->control->sync_timeout;
  35. client->control->sync_new = 1;
  36. if (!client->control->sync_poll) {
  37. client->control->sync_poll = 1;
  38. engine->control->sync_remain++;
  39. }
  40. // JOQ: I don't like doing this here...
  41. if (engine->control->transport_state == JackTransportRolling) {
  42. engine->control->transport_state = JackTransportStarting;
  43. VERBOSE (engine, "force transport state to Starting");
  44. }
  45. VERBOSE (engine, "polling sync client %" PRIu32,
  46. client->control->id);
  47. }
  48. /* stop polling a specific slow-sync client
  49. *
  50. * precondition: caller holds the graph lock. */
  51. static inline void
  52. jack_sync_poll_deactivate (jack_engine_t *engine,
  53. jack_client_internal_t *client)
  54. {
  55. if (client->control->sync_poll) {
  56. client->control->sync_poll = 0;
  57. client->control->sync_new = 0;
  58. engine->control->sync_remain--;
  59. VERBOSE (engine, "sync poll interrupted for client %"
  60. PRIu32, client->control->id);
  61. }
  62. client->control->active_slowsync = 0;
  63. engine->control->sync_clients--;
  64. assert(engine->control->sync_clients >= 0);
  65. }
  66. /* stop polling all the slow-sync clients
  67. *
  68. * precondition: caller holds the graph lock. */
  69. static void
  70. jack_sync_poll_stop (jack_engine_t *engine)
  71. {
  72. JSList *node;
  73. long poll_count = 0; /* count sync_poll clients */
  74. for (node = engine->clients; node; node = jack_slist_next (node)) {
  75. jack_client_internal_t *client =
  76. (jack_client_internal_t *) node->data;
  77. if (client->control->active_slowsync &&
  78. client->control->sync_poll) {
  79. client->control->sync_poll = 0;
  80. poll_count++;
  81. }
  82. }
  83. //JOQ: check invariant for debugging...
  84. assert (poll_count == engine->control->sync_remain);
  85. VERBOSE (engine,
  86. "sync poll halted with %" PRIu32
  87. " clients and %8.6f secs remaining",
  88. engine->control->sync_remain,
  89. (double) (engine->control->sync_time_left / 1000000.0));
  90. engine->control->sync_remain = 0;
  91. engine->control->sync_time_left = 0;
  92. }
  93. /* start polling all the slow-sync clients
  94. *
  95. * precondition: caller holds the graph lock. */
  96. static void
  97. jack_sync_poll_start (jack_engine_t *engine)
  98. {
  99. JSList *node;
  100. long sync_count = 0; /* count slow-sync clients */
  101. for (node = engine->clients; node; node = jack_slist_next (node)) {
  102. jack_client_internal_t *client =
  103. (jack_client_internal_t *) node->data;
  104. if (client->control->active_slowsync) {
  105. client->control->sync_poll = 1;
  106. sync_count++;
  107. }
  108. }
  109. //JOQ: check invariant for debugging...
  110. assert (sync_count == engine->control->sync_clients);
  111. engine->control->sync_remain = sync_count;
  112. engine->control->sync_time_left = engine->control->sync_timeout;
  113. VERBOSE (engine, "transport Starting, sync poll of %" PRIu32
  114. " clients for %8.6f secs", engine->control->sync_remain,
  115. (double) (engine->control->sync_time_left / 1000000.0));
  116. }
  117. /* check for sync timeout */
  118. static inline int
  119. jack_sync_timeout (jack_engine_t *engine)
  120. {
  121. jack_control_t *ectl = engine->control;
  122. jack_time_t buf_usecs =
  123. ((ectl->buffer_size * (jack_time_t) 1000000) /
  124. ectl->current_time.frame_rate);
  125. /* compare carefully, jack_time_t is unsigned */
  126. if (ectl->sync_time_left > buf_usecs) {
  127. ectl->sync_time_left -= buf_usecs;
  128. return FALSE;
  129. }
  130. /* timed out */
  131. VERBOSE (engine, "transport sync timeout");
  132. ectl->sync_time_left = 0;
  133. return TRUE;
  134. }
  135. /**************** subroutines used by engine.c ****************/
  136. /* driver callback */
  137. int
  138. jack_set_sample_rate (jack_engine_t *engine, jack_nframes_t nframes)
  139. {
  140. jack_control_t *ectl = engine->control;
  141. ectl->current_time.frame_rate = nframes;
  142. ectl->pending_time.frame_rate = nframes;
  143. return 0;
  144. }
  145. /* on ResetTimeBaseClient request */
  146. int
  147. jack_timebase_reset (jack_engine_t *engine, jack_client_id_t client_id)
  148. {
  149. int ret;
  150. struct _jack_client_internal *client;
  151. jack_control_t *ectl = engine->control;
  152. jack_lock_graph (engine);
  153. client = jack_client_internal_by_id (engine, client_id);
  154. if (client && (client == engine->timebase_client)) {
  155. client->control->is_timebase = 0;
  156. client->control->timebase_new = 0;
  157. engine->timebase_client = NULL;
  158. ectl->pending_time.valid = 0;
  159. VERBOSE (engine, "%s resigned as timebase master",
  160. client->control->name);
  161. ret = 0;
  162. } else
  163. ret = EINVAL;
  164. jack_unlock_graph (engine);
  165. return ret;
  166. }
  167. /* on SetTimeBaseClient request */
  168. int
  169. jack_timebase_set (jack_engine_t *engine,
  170. jack_client_id_t client_id, int conditional)
  171. {
  172. int ret = 0;
  173. struct _jack_client_internal *client;
  174. jack_lock_graph (engine);
  175. client = jack_client_internal_by_id (engine, client_id);
  176. if (client == NULL) {
  177. VERBOSE (engine, " %" PRIu32 " no longer exists", client_id);
  178. jack_unlock_graph (engine);
  179. return EINVAL;
  180. }
  181. if (conditional && engine->timebase_client) {
  182. /* see if timebase master is someone else */
  183. if (client != engine->timebase_client) {
  184. VERBOSE (engine, "conditional timebase for %s failed",
  185. client->control->name);
  186. VERBOSE (engine, " %s is already the master",
  187. engine->timebase_client->control->name);
  188. ret = EBUSY;
  189. } else
  190. VERBOSE (engine, " %s was already timebase master:",
  191. client->control->name);
  192. } else {
  193. if (engine->timebase_client) {
  194. engine->timebase_client->control->is_timebase = 0;
  195. engine->timebase_client->control->timebase_new = 0;
  196. }
  197. engine->timebase_client = client;
  198. client->control->is_timebase = 1;
  199. if (client->control->active)
  200. client->control->timebase_new = 1;
  201. VERBOSE (engine, "new timebase master: %s",
  202. client->control->name);
  203. }
  204. jack_unlock_graph (engine);
  205. return ret;
  206. }
  207. /* for client activation
  208. *
  209. * precondition: caller holds the graph lock. */
  210. void
  211. jack_transport_activate (jack_engine_t *engine, jack_client_internal_t *client)
  212. {
  213. if (client->control->is_slowsync) {
  214. assert(!client->control->active_slowsync);
  215. client->control->active_slowsync = 1;
  216. engine->control->sync_clients++;
  217. jack_sync_poll_new (engine, client);
  218. }
  219. if (client->control->is_timebase) {
  220. client->control->timebase_new = 1;
  221. }
  222. }
  223. /* for engine initialization */
  224. void
  225. jack_transport_init (jack_engine_t *engine)
  226. {
  227. jack_control_t *ectl = engine->control;
  228. engine->timebase_client = NULL;
  229. ectl->transport_state = JackTransportStopped;
  230. ectl->transport_cmd = TransportCommandStop;
  231. ectl->previous_cmd = TransportCommandStop;
  232. memset (&ectl->current_time, 0, sizeof(ectl->current_time));
  233. memset (&ectl->pending_time, 0, sizeof(ectl->pending_time));
  234. memset (&ectl->request_time, 0, sizeof(ectl->request_time));
  235. ectl->prev_request = 0;
  236. ectl->seq_number = 1; /* can't start at 0 */
  237. ectl->new_pos = 0;
  238. ectl->pending_pos = 0;
  239. ectl->pending_frame = 0;
  240. ectl->sync_clients = 0;
  241. ectl->sync_remain = 0;
  242. ectl->sync_timeout = 2000000; /* 2 second default */
  243. ectl->sync_time_left = 0;
  244. }
  245. /* when any client exits the graph (either dead or not active)
  246. *
  247. * precondition: caller holds the graph lock */
  248. void
  249. jack_transport_client_exit (jack_engine_t *engine,
  250. jack_client_internal_t *client)
  251. {
  252. if (client == engine->timebase_client) {
  253. if (client->control->dead) {
  254. engine->timebase_client->control->is_timebase = 0;
  255. engine->timebase_client->control->timebase_new = 0;
  256. engine->timebase_client = NULL;
  257. VERBOSE (engine, "timebase master exit");
  258. }
  259. engine->control->current_time.valid = 0;
  260. engine->control->pending_time.valid = 0;
  261. }
  262. if (client->control->is_slowsync) {
  263. if (client->control->active_slowsync)
  264. jack_sync_poll_deactivate (engine, client);
  265. if (client->control->dead)
  266. client->control->is_slowsync = 0;
  267. }
  268. }
  269. /* when a new client is being created */
  270. void
  271. jack_transport_client_new (jack_client_internal_t *client)
  272. {
  273. client->control->is_timebase = 0;
  274. client->control->timebase_new = 0;
  275. client->control->is_slowsync = 0;
  276. client->control->active_slowsync = 0;
  277. client->control->sync_poll = 0;
  278. client->control->sync_new = 0;
  279. client->control->sync_cb_cbset = FALSE;
  280. client->control->timebase_cb_cbset = FALSE;
  281. #if 0
  282. if (client->control->type != ClientExternal) {
  283. client->sync_cb = NULL;
  284. client->sync_arg = NULL;
  285. client->timebase_cb = NULL;
  286. client->timebase_arg = NULL;
  287. }
  288. #endif
  289. }
  290. /* on ResetSyncClient request */
  291. int
  292. jack_transport_client_reset_sync (jack_engine_t *engine,
  293. jack_client_id_t client_id)
  294. {
  295. int ret;
  296. jack_client_internal_t *client;
  297. jack_lock_graph (engine);
  298. client = jack_client_internal_by_id (engine, client_id);
  299. if (client && (client->control->is_slowsync)) {
  300. if (client->control->active_slowsync)
  301. jack_sync_poll_deactivate (engine, client);
  302. client->control->is_slowsync = 0;
  303. ret = 0;
  304. } else
  305. ret = EINVAL;
  306. jack_unlock_graph (engine);
  307. return ret;
  308. }
  309. /* on SetSyncClient request */
  310. int
  311. jack_transport_client_set_sync (jack_engine_t *engine,
  312. jack_client_id_t client_id)
  313. {
  314. int ret;
  315. jack_client_internal_t *client;
  316. DEBUG ("set sync client");
  317. /* The process cycle runs with this lock. */
  318. jack_lock_graph (engine);
  319. DEBUG ("got write lock");
  320. client = jack_client_internal_by_id (engine, client_id);
  321. DEBUG ("client was %p");
  322. if (client) {
  323. if (!client->control->is_slowsync) {
  324. client->control->is_slowsync = 1;
  325. if (client->control->active) {
  326. client->control->active_slowsync = 1;
  327. engine->control->sync_clients++;
  328. }
  329. }
  330. /* force poll of the new slow-sync client, if active */
  331. if (client->control->active_slowsync) {
  332. DEBUG ("sync poll new");
  333. jack_sync_poll_new (engine, client);
  334. }
  335. ret = 0;
  336. } else
  337. ret = EINVAL;
  338. DEBUG ("unlocking write lock for set_sync");
  339. jack_unlock_graph (engine);
  340. return ret;
  341. }
  342. /* at process cycle end, set transport parameters for the next cycle
  343. *
  344. * precondition: caller holds the graph lock.
  345. */
  346. void
  347. jack_transport_cycle_end (jack_engine_t *engine)
  348. {
  349. jack_control_t *ectl = engine->control;
  350. transport_command_t cmd; /* latest transport command */
  351. /* Promote pending_time to current_time. Maintain the usecs,
  352. * frame_rate and frame values, clients may not set them. */
  353. ectl->pending_time.usecs = ectl->current_time.usecs;
  354. ectl->pending_time.frame_rate = ectl->current_time.frame_rate;
  355. ectl->pending_time.frame = ectl->pending_frame;
  356. ectl->current_time = ectl->pending_time;
  357. ectl->new_pos = ectl->pending_pos;
  358. /* check sync results from previous cycle */
  359. if (ectl->transport_state == JackTransportStarting) {
  360. if ((ectl->sync_remain == 0) ||
  361. (jack_sync_timeout(engine))) {
  362. ectl->transport_state = JackTransportRolling;
  363. VERBOSE (engine, "transport Rolling, %8.6f sec"
  364. " left for poll",
  365. (double) (ectl->sync_time_left / 1000000.0));
  366. }
  367. }
  368. /* Handle any new transport command from the last cycle. */
  369. cmd = ectl->transport_cmd;
  370. if (cmd != ectl->previous_cmd) {
  371. ectl->previous_cmd = cmd;
  372. VERBOSE (engine, "transport command: %s",
  373. (cmd == TransportCommandStart? "START": "STOP"));
  374. } else
  375. cmd = TransportCommandNone;
  376. /* state transition switch */
  377. switch (ectl->transport_state) {
  378. case JackTransportStopped:
  379. if (cmd == TransportCommandStart) {
  380. if (ectl->sync_clients) {
  381. ectl->transport_state = JackTransportStarting;
  382. jack_sync_poll_start(engine);
  383. } else {
  384. ectl->transport_state = JackTransportRolling;
  385. VERBOSE (engine, "transport Rolling");
  386. }
  387. }
  388. break;
  389. case JackTransportStarting:
  390. if (cmd == TransportCommandStop) {
  391. ectl->transport_state = JackTransportStopped;
  392. VERBOSE (engine, "transport Stopped");
  393. if (ectl->sync_remain)
  394. jack_sync_poll_stop(engine);
  395. } else if (ectl->new_pos) {
  396. if (ectl->sync_clients) {
  397. ectl->transport_state = JackTransportStarting;
  398. jack_sync_poll_start(engine);
  399. } else {
  400. ectl->transport_state = JackTransportRolling;
  401. VERBOSE (engine, "transport Rolling");
  402. }
  403. }
  404. break;
  405. case JackTransportRolling:
  406. if (cmd == TransportCommandStop) {
  407. ectl->transport_state = JackTransportStopped;
  408. VERBOSE (engine, "transport Stopped");
  409. if (ectl->sync_remain)
  410. jack_sync_poll_stop(engine);
  411. } else if (ectl->new_pos) {
  412. if (ectl->sync_clients) {
  413. ectl->transport_state = JackTransportStarting;
  414. jack_sync_poll_start(engine);
  415. }
  416. }
  417. break;
  418. default:
  419. jack_error ("invalid JACK transport state: %d",
  420. ectl->transport_state);
  421. }
  422. /* Update timebase, if needed. */
  423. if (ectl->transport_state == JackTransportRolling) {
  424. ectl->pending_time.frame =
  425. ectl->current_time.frame + ectl->buffer_size;
  426. }
  427. /* See if an asynchronous position request arrived during the
  428. * last cycle. The request_time could change during the
  429. * guarded copy. If so, we use the newest request. */
  430. ectl->pending_pos = 0;
  431. if (ectl->request_time.unique_1 != ectl->prev_request) {
  432. jack_transport_copy_position(&ectl->request_time,
  433. &ectl->pending_time);
  434. VERBOSE (engine, "new transport position: %" PRIu32
  435. ", id=0x%" PRIx64, ectl->pending_time.frame,
  436. ectl->pending_time.unique_1);
  437. ectl->prev_request = ectl->pending_time.unique_1;
  438. ectl->pending_pos = 1;
  439. }
  440. /* clients can't set pending frame number, so save it here */
  441. ectl->pending_frame = ectl->pending_time.frame;
  442. }
  443. /* driver callback at start of cycle */
  444. void
  445. jack_transport_cycle_start (jack_engine_t *engine, jack_time_t time)
  446. {
  447. engine->control->current_time.usecs = time;
  448. }
  449. /* on SetSyncTimeout request */
  450. int
  451. jack_transport_set_sync_timeout (jack_engine_t *engine,
  452. jack_time_t usecs)
  453. {
  454. engine->control->sync_timeout = usecs;
  455. VERBOSE (engine, "new sync timeout: %8.6f secs",
  456. (double) (usecs / 1000000.0));
  457. return 0;
  458. }