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.

377 lines
9.4KB

  1. /* -*- mode: c; c-file-style: "linux"; -*- */
  2. /*
  3. Copyright (C) 2003 Robert Ham <rah@bash.sh>
  4. Copyright (C) 2001 Paul Davis
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (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
  12. GNU 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. $Id$
  17. */
  18. #include <math.h>
  19. #include <stdio.h>
  20. #include <memory.h>
  21. #include <unistd.h>
  22. #include <stdlib.h>
  23. #include <errno.h>
  24. #include <stdarg.h>
  25. #include <sys/mman.h>
  26. #include <jack/types.h>
  27. #include <jack/internal.h>
  28. #include <jack/engine.h>
  29. #include <sysdeps/time.h>
  30. #include "dummy_driver.h"
  31. #undef DEBUG_WAKEUP
  32. static jack_nframes_t
  33. dummy_driver_wait (dummy_driver_t *driver, int extra_fd, int *status,
  34. float *delayed_usecs)
  35. {
  36. jack_time_t starting_time = jack_get_microseconds();
  37. jack_time_t processing_time = (driver->last_wait_ust?
  38. starting_time - driver->last_wait_ust:
  39. 0);
  40. /* wait until time for next cycle */
  41. if (driver->wait_time > processing_time)
  42. usleep (driver->wait_time - processing_time);
  43. driver->last_wait_ust = jack_get_microseconds ();
  44. driver->engine->transport_cycle_start (driver->engine,
  45. driver->last_wait_ust);
  46. /* this driver doesn't work so well if we report a delay */
  47. *delayed_usecs = 0; /* lie about it */
  48. *status = 0;
  49. return driver->period_size;
  50. }
  51. static inline int
  52. dummy_driver_run_cycle (dummy_driver_t *driver)
  53. {
  54. jack_engine_t *engine = driver->engine;
  55. int wait_status;
  56. float delayed_usecs;
  57. jack_nframes_t nframes = dummy_driver_wait (driver, -1, &wait_status,
  58. &delayed_usecs);
  59. if (nframes == 0) {
  60. /* we detected an xrun and restarted: notify
  61. * clients about the delay. */
  62. engine->delay (engine, delayed_usecs);
  63. return 0;
  64. }
  65. if (wait_status == 0)
  66. return engine->run_cycle (engine, nframes, delayed_usecs);
  67. if (wait_status < 0)
  68. return -1;
  69. else
  70. return 0;
  71. }
  72. static int
  73. dummy_driver_null_cycle (dummy_driver_t* driver, jack_nframes_t nframes)
  74. {
  75. return 0;
  76. }
  77. static int
  78. dummy_driver_bufsize (dummy_driver_t* driver, jack_nframes_t nframes)
  79. {
  80. /* This is a somewhat arbitrary size restriction. The dummy
  81. * driver doesn't work well with smaller buffer sizes,
  82. * apparantly due to usleep() inaccuracy under Linux 2.4. If
  83. * you can get it working with smaller buffers, lower the
  84. * limit. (JOQ) */
  85. if (nframes < 128)
  86. return EINVAL;
  87. driver->period_size = nframes;
  88. driver->period_usecs = driver->wait_time =
  89. (jack_time_t) floor ((((float) nframes) / driver->sample_rate)
  90. * 1000000.0f);
  91. /* tell the engine to change its buffer size */
  92. driver->engine->set_buffer_size (driver->engine, nframes);
  93. return 0;
  94. }
  95. static int
  96. dummy_driver_write (dummy_driver_t* driver, jack_nframes_t nframes)
  97. {
  98. return 0;
  99. }
  100. static int
  101. dummy_driver_attach (dummy_driver_t *driver)
  102. {
  103. jack_port_t * port;
  104. char buf[32];
  105. unsigned int chn;
  106. int port_flags;
  107. driver->engine->set_buffer_size (driver->engine, driver->period_size);
  108. driver->engine->set_sample_rate (driver->engine, driver->sample_rate);
  109. port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
  110. for (chn = 0; chn < driver->capture_channels; chn++)
  111. {
  112. snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);
  113. port = jack_port_register (driver->client, buf,
  114. JACK_DEFAULT_AUDIO_TYPE,
  115. port_flags, 0);
  116. if (!port)
  117. {
  118. jack_error ("DUMMY: cannot register port for %s", buf);
  119. break;
  120. }
  121. driver->capture_ports =
  122. jack_slist_append (driver->capture_ports, port);
  123. }
  124. port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
  125. for (chn = 0; chn < driver->playback_channels; chn++)
  126. {
  127. snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);
  128. port = jack_port_register (driver->client, buf,
  129. JACK_DEFAULT_AUDIO_TYPE,
  130. port_flags, 0);
  131. if (!port)
  132. {
  133. jack_error ("DUMMY: cannot register port for %s", buf);
  134. break;
  135. }
  136. driver->playback_ports =
  137. jack_slist_append (driver->playback_ports, port);
  138. }
  139. jack_activate (driver->client);
  140. return 0;
  141. }
  142. static int
  143. dummy_driver_detach (dummy_driver_t *driver)
  144. {
  145. JSList * node;
  146. if (driver->engine == 0)
  147. return 0;
  148. for (node = driver->capture_ports; node; node = jack_slist_next (node))
  149. jack_port_unregister (driver->client,
  150. ((jack_port_t *) node->data));
  151. jack_slist_free (driver->capture_ports);
  152. driver->capture_ports = NULL;
  153. for (node = driver->playback_ports; node; node = jack_slist_next (node))
  154. jack_port_unregister (driver->client,
  155. ((jack_port_t *) node->data));
  156. jack_slist_free (driver->playback_ports);
  157. driver->playback_ports = NULL;
  158. return 0;
  159. }
  160. static void
  161. dummy_driver_delete (dummy_driver_t *driver)
  162. {
  163. jack_driver_nt_finish ((jack_driver_nt_t *) driver);
  164. free (driver);
  165. }
  166. static jack_driver_t *
  167. dummy_driver_new (jack_client_t * client,
  168. char *name,
  169. unsigned int capture_ports,
  170. unsigned int playback_ports,
  171. jack_nframes_t sample_rate,
  172. jack_nframes_t period_size,
  173. unsigned long wait_time)
  174. {
  175. dummy_driver_t * driver;
  176. printf ("creating dummy driver ... %s|%" PRIu32 "|%" PRIu32
  177. "|%lu|%u|%u\n", name, sample_rate, period_size, wait_time,
  178. capture_ports, playback_ports);
  179. driver = (dummy_driver_t *) calloc (1, sizeof (dummy_driver_t));
  180. jack_driver_nt_init ((jack_driver_nt_t *) driver);
  181. driver->write = (JackDriverReadFunction) dummy_driver_write;
  182. driver->null_cycle = (JackDriverNullCycleFunction) dummy_driver_null_cycle;
  183. driver->nt_attach = (JackDriverNTAttachFunction) dummy_driver_attach;
  184. driver->nt_detach = (JackDriverNTDetachFunction) dummy_driver_detach;
  185. driver->nt_bufsize = (JackDriverNTBufSizeFunction) dummy_driver_bufsize;
  186. driver->nt_run_cycle = (JackDriverNTRunCycleFunction) dummy_driver_run_cycle;
  187. driver->period_usecs =
  188. (jack_time_t) floor ((((float) period_size) / sample_rate)
  189. * 1000000.0f);
  190. driver->sample_rate = sample_rate;
  191. driver->period_size = period_size;
  192. driver->wait_time = wait_time;
  193. driver->last_wait_ust = 0;
  194. driver->capture_channels = capture_ports;
  195. driver->capture_ports = NULL;
  196. driver->playback_channels = playback_ports;
  197. driver->playback_ports = NULL;
  198. driver->client = client;
  199. driver->engine = NULL;
  200. return (jack_driver_t *) driver;
  201. }
  202. /* DRIVER "PLUGIN" INTERFACE */
  203. jack_driver_desc_t *
  204. driver_get_descriptor ()
  205. {
  206. jack_driver_desc_t * desc;
  207. jack_driver_param_desc_t * params;
  208. unsigned int i;
  209. desc = calloc (1, sizeof (jack_driver_desc_t));
  210. strcpy (desc->name, "dummy");
  211. desc->nparams = 5;
  212. params = calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
  213. i = 0;
  214. strcpy (params[i].name, "capture");
  215. params[i].character = 'C';
  216. params[i].type = JackDriverParamUInt;
  217. params[i].value.ui = 2U;
  218. strcpy (params[i].short_desc, "Number of capture ports");
  219. strcpy (params[i].long_desc, params[i].short_desc);
  220. i++;
  221. strcpy (params[i].name, "playback");
  222. params[i].character = 'P';
  223. params[i].type = JackDriverParamUInt;
  224. params[1].value.ui = 2U;
  225. strcpy (params[i].short_desc, "Number of playback ports");
  226. strcpy (params[i].long_desc, params[i].short_desc);
  227. i++;
  228. strcpy (params[i].name, "rate");
  229. params[i].character = 'r';
  230. params[i].type = JackDriverParamUInt;
  231. params[i].value.ui = 48000U;
  232. strcpy (params[i].short_desc, "Sample rate");
  233. strcpy (params[i].long_desc, params[i].short_desc);
  234. i++;
  235. strcpy (params[i].name, "period");
  236. params[i].character = 'p';
  237. params[i].type = JackDriverParamUInt;
  238. params[i].value.ui = 1024U;
  239. strcpy (params[i].short_desc, "Frames per period");
  240. strcpy (params[i].long_desc, params[i].short_desc);
  241. i++;
  242. strcpy (params[i].name, "wait");
  243. params[i].character = 'w';
  244. params[i].type = JackDriverParamUInt;
  245. params[i].value.ui = 21333U;
  246. strcpy (params[i].short_desc,
  247. "Number of usecs to wait between engine processes");
  248. strcpy (params[i].long_desc, params[i].short_desc);
  249. desc->params = params;
  250. return desc;
  251. }
  252. const char driver_client_name[] = "dummy_pcm";
  253. jack_driver_t *
  254. driver_initialize (jack_client_t *client, const JSList * params)
  255. {
  256. jack_nframes_t sample_rate = 48000;
  257. jack_nframes_t period_size = 1024;
  258. unsigned int capture_ports = 2;
  259. unsigned int playback_ports = 2;
  260. int wait_time_set = 0;
  261. unsigned long wait_time = 0;
  262. const JSList * node;
  263. const jack_driver_param_t * param;
  264. for (node = params; node; node = jack_slist_next (node)) {
  265. param = (const jack_driver_param_t *) node->data;
  266. switch (param->character) {
  267. case 'C':
  268. capture_ports = param->value.ui;
  269. break;
  270. case 'P':
  271. playback_ports = param->value.ui;
  272. break;
  273. case 'r':
  274. sample_rate = param->value.ui;
  275. break;
  276. case 'p':
  277. period_size = param->value.ui;
  278. break;
  279. case 'w':
  280. wait_time = param->value.ui;
  281. wait_time_set = 1;
  282. break;
  283. }
  284. }
  285. if (!wait_time_set)
  286. wait_time = (((float)period_size) / ((float)sample_rate)) * 1000000.0;
  287. return dummy_driver_new (client, "dummy_pcm", capture_ports,
  288. playback_ports, sample_rate, period_size,
  289. wait_time);
  290. }
  291. void
  292. driver_finish (jack_driver_t *driver)
  293. {
  294. dummy_driver_delete ((dummy_driver_t *) driver);
  295. }