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.

324 lines
7.8KB

  1. /*
  2. Copyright (C) 2003 Robert Ham <rah@bash.sh>
  3. Copyright (C) 2001 Paul Davis
  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. $Id$
  16. */
  17. #include <stdio.h>
  18. #include <memory.h>
  19. #include <unistd.h>
  20. #include <stdlib.h>
  21. #include <errno.h>
  22. #include <stdarg.h>
  23. #include <getopt.h>
  24. #include <jack/types.h>
  25. #include <jack/internal.h>
  26. #include <jack/engine.h>
  27. #include <jack/time.h>
  28. #include "dummy_driver.h"
  29. #undef DEBUG_WAKEUP
  30. static int
  31. dummy_driver_audio_start (dummy_driver_t *driver)
  32. {
  33. return 0;
  34. }
  35. static int
  36. dummy_driver_audio_stop (dummy_driver_t *driver)
  37. {
  38. return 0;
  39. }
  40. static jack_nframes_t
  41. dummy_driver_wait (dummy_driver_t *driver, int extra_fd, int *status, float *delayed_usecs)
  42. {
  43. usleep (driver->wait_time);
  44. driver->last_wait_ust = jack_get_microseconds ();
  45. *status = 0;
  46. *delayed_usecs = 0.0;
  47. return driver->period_size;
  48. }
  49. static int
  50. dummy_driver_null_cycle (dummy_driver_t* driver, jack_nframes_t nframes)
  51. {
  52. return 0;
  53. }
  54. static int
  55. dummy_driver_read (dummy_driver_t *driver, jack_nframes_t nframes)
  56. {
  57. return 0;
  58. }
  59. static int
  60. dummy_driver_write (dummy_driver_t* driver, jack_nframes_t nframes)
  61. {
  62. return 0;
  63. }
  64. static int
  65. dummy_driver_attach (dummy_driver_t *driver, jack_engine_t *engine)
  66. {
  67. jack_port_t * port;
  68. char buf[32];
  69. unsigned int chn;
  70. int port_flags;
  71. driver->engine = engine;
  72. driver->engine->set_buffer_size (engine, driver->period_size);
  73. driver->engine->set_sample_rate (engine, driver->sample_rate);
  74. port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
  75. for (chn = 0; chn < driver->capture_channels; chn++)
  76. {
  77. snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);
  78. port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
  79. if (!port)
  80. {
  81. jack_error ("DUMMY: cannot register port for %s", buf);
  82. break;
  83. }
  84. driver->capture_ports = jack_slist_append (driver->capture_ports, port);
  85. }
  86. port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
  87. for (chn = 0; chn < driver->playback_channels; chn++)
  88. {
  89. snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);
  90. port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
  91. if (!port)
  92. {
  93. jack_error ("DUMMY: cannot register port for %s", buf);
  94. break;
  95. }
  96. driver->playback_ports = jack_slist_append (driver->playback_ports, port);
  97. }
  98. jack_activate (driver->client);
  99. return 0;
  100. }
  101. static void
  102. dummy_driver_detach (dummy_driver_t *driver, jack_engine_t *engine)
  103. {
  104. JSList * node;
  105. if (driver->engine == 0)
  106. return;
  107. for (node = driver->capture_ports; node; node = jack_slist_next (node))
  108. jack_port_unregister (driver->client, ((jack_port_t *) node->data));
  109. jack_slist_free (driver->capture_ports);
  110. driver->capture_ports = NULL;
  111. for (node = driver->playback_ports; node; node = jack_slist_next (node))
  112. jack_port_unregister (driver->client, ((jack_port_t *) node->data));
  113. jack_slist_free (driver->playback_ports);
  114. driver->playback_ports = NULL;
  115. driver->engine = NULL;
  116. }
  117. static void
  118. dummy_driver_delete (dummy_driver_t *driver)
  119. {
  120. free (driver);
  121. }
  122. static jack_driver_t *
  123. dummy_driver_new (jack_client_t * client,
  124. char *name,
  125. unsigned int capture_ports,
  126. unsigned int playback_ports,
  127. jack_nframes_t sample_rate,
  128. jack_nframes_t period_size,
  129. unsigned long wait_time)
  130. {
  131. dummy_driver_t * driver;
  132. printf ("creating dummy driver ... %s|%lu|%lu|%lu|%u|%u\n",
  133. name, sample_rate, period_size, wait_time,
  134. capture_ports, playback_ports);
  135. driver = (dummy_driver_t *) calloc (1, sizeof (dummy_driver_t));
  136. jack_driver_init ((jack_driver_t *) driver);
  137. driver->attach = (JackDriverAttachFunction) dummy_driver_attach;
  138. driver->detach = (JackDriverDetachFunction) dummy_driver_detach;
  139. driver->wait = (JackDriverWaitFunction) dummy_driver_wait;
  140. driver->read = (JackDriverReadFunction) dummy_driver_read;
  141. driver->write = (JackDriverReadFunction) dummy_driver_write;
  142. driver->null_cycle = (JackDriverNullCycleFunction) dummy_driver_null_cycle;
  143. driver->start = (JackDriverStartFunction) dummy_driver_audio_start;
  144. driver->stop = (JackDriverStopFunction) dummy_driver_audio_stop;
  145. driver->period_usecs = (((float)period_size) / ((float)sample_rate)) / 1000000.0;
  146. driver->sample_rate = sample_rate;
  147. driver->period_size = period_size;
  148. driver->wait_time = wait_time;
  149. driver->capture_channels = capture_ports;
  150. driver->capture_ports = NULL;
  151. driver->playback_channels = playback_ports;
  152. driver->playback_ports = NULL;
  153. driver->client = client;
  154. driver->engine = NULL;
  155. return (jack_driver_t *) driver;
  156. }
  157. static void
  158. dummy_usage ()
  159. {
  160. fprintf (stderr, "\n"
  161. "dummy driver arguments:\n"
  162. " -h,--help \tprint this message\n"
  163. " -r,--rate <n> \tsample rate (default: 48000)\n"
  164. " -p,--period <n> \tframes per period (default: 1024)\n"
  165. " -C,--capture <n> \tnumber of capture ports (default: 2)\n"
  166. " -P,--playback <n> \tnumber of playback ports (default: 2)\n"
  167. " -w,--wait <usecs> \tnumber of usecs to wait between engine processes (default: 21333)\n"
  168. "\n");
  169. }
  170. static void
  171. dummy_error (char *type, char *value)
  172. {
  173. fprintf (stderr, "dummy driver: unknown %s: `%s'\n", type, value);
  174. dummy_usage();
  175. }
  176. /* DRIVER "PLUGIN" INTERFACE */
  177. const char driver_client_name[] = "dummy_pcm";
  178. jack_driver_t *
  179. driver_initialize (jack_client_t *client, int argc, char **argv)
  180. {
  181. jack_nframes_t sample_rate = 48000;
  182. jack_nframes_t period_size = 1024;
  183. unsigned int capture_ports = 2;
  184. unsigned int playback_ports = 2;
  185. int wait_time_set = 0;
  186. unsigned long wait_time;
  187. int opt;
  188. char optstring[2]; /* string made from opt char */
  189. struct option long_options[] =
  190. {
  191. { "help", no_argument, NULL, 'h' },
  192. { "rate", required_argument, NULL, 'r' },
  193. { "period", required_argument, NULL, 'p' },
  194. { "capture", required_argument, NULL, 'C' },
  195. { "playback", required_argument, NULL, 'P' },
  196. { "wait", required_argument, NULL, 'w' },
  197. { 0, 0, 0, 0 }
  198. };
  199. /*
  200. * Setting optind back to zero is a hack to reinitialize a new
  201. * getopts() loop. See declaration in <getopt.h>.
  202. */
  203. optind = 0;
  204. opterr = 0;
  205. while ((opt = getopt_long(argc, argv, "C::P::p:r:w:h",
  206. long_options, NULL))
  207. != EOF) {
  208. switch (opt) {
  209. case 'C':
  210. capture_ports = atoi (optarg);
  211. break;
  212. case 'P':
  213. playback_ports = atoi (optarg);
  214. break;
  215. case 'p':
  216. period_size = atoi(optarg);
  217. break;
  218. case 'r':
  219. sample_rate = atoi(optarg);
  220. break;
  221. case 'w':
  222. wait_time = strtoul(optarg, NULL, 10);
  223. wait_time_set = 1;
  224. break;
  225. case 'h':
  226. dummy_usage();
  227. return NULL;
  228. /* the rest is error handling: */
  229. case 1: /* not an option */
  230. dummy_error("parameter", optarg);
  231. return NULL;
  232. default: /* unrecognized option */
  233. optstring[0] = (char) optopt;
  234. optstring[1] = '\0';
  235. dummy_error("option", optstring);
  236. return NULL;
  237. }
  238. }
  239. if (!wait_time_set)
  240. wait_time = (((float)period_size) / ((float)sample_rate)) * 1000000.0;
  241. return dummy_driver_new (client, "dummy_pcm", capture_ports, playback_ports,
  242. sample_rate, period_size, wait_time);
  243. }
  244. void
  245. driver_finish (jack_driver_t *driver)
  246. {
  247. dummy_driver_delete ((dummy_driver_t *) driver);
  248. }