audio_sndio.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* $OpenBSD: audio_sndio.c,v 1.2 2009/06/20 14:56:18 martynas Exp $ */
  2. /*
  3. * Copyright (c) 2009 Martynas Venckus <martynas@openbsd.org>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "global.h"
  21. #include "gettext.h"
  22. #include "audio.h"
  23. #include <sndio.h>
  24. static audio_pcmfunc_t *audio_pcm;
  25. static struct sio_hdl *hdl;
  26. static int sio_started;
  27. static int
  28. init(struct audio_init *init)
  29. {
  30. hdl = sio_open((char *)init->path, SIO_PLAY, 0);
  31. if (hdl == NULL) {
  32. audio_error = ":";
  33. return (-1);
  34. }
  35. return (0);
  36. }
  37. static int
  38. config(struct audio_config *config)
  39. {
  40. struct sio_par par;
  41. unsigned int bitdepth;
  42. bitdepth = config->precision & ~7;
  43. if (bitdepth == 0) {
  44. bitdepth = 16;
  45. } else if (bitdepth > 32) {
  46. bitdepth = 32;
  47. }
  48. sio_initpar(&par);
  49. par.bits = bitdepth;
  50. par.le = SIO_LE_NATIVE;
  51. par.pchan = config->channels;
  52. par.rate = config->speed;
  53. par.sig = (par.bits == 8) ? 0 : 1;
  54. if (sio_started) {
  55. sio_stop(hdl);
  56. sio_started = 0;
  57. }
  58. if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par) ||
  59. !sio_start(hdl)) {
  60. audio_error = ":sio_setpar";
  61. sio_close(hdl);
  62. return (-1);
  63. }
  64. sio_started = 1;
  65. switch(par.bits) {
  66. case 8:
  67. audio_pcm = audio_pcm_u8;
  68. break;
  69. case 16:
  70. audio_pcm = par.le ? audio_pcm_s16le : audio_pcm_s16be;
  71. break;
  72. case 24:
  73. audio_pcm = par.le ? audio_pcm_s32le : audio_pcm_s32be;
  74. break;
  75. case 32:
  76. audio_pcm = par.le ? audio_pcm_s32le : audio_pcm_s32be;
  77. break;
  78. default:
  79. audio_error = _("no supported audio format available");
  80. sio_close(hdl);
  81. return (-1);
  82. }
  83. config->channels = par.pchan;
  84. config->precision = par.bits;
  85. config->speed = par.rate;
  86. return (0);
  87. }
  88. static int
  89. play(struct audio_play *play)
  90. {
  91. unsigned char data[MAX_NSAMPLES * 4 * 2];
  92. unsigned int len;
  93. int count;
  94. len = audio_pcm(data, play->nsamples, play->samples[0],
  95. play->samples[1], play->mode, play->stats);
  96. count = (int)sio_write(hdl, data, len);
  97. if (count == 0 && sio_eof(hdl))
  98. return (-1);
  99. return (count);
  100. }
  101. static int
  102. stop(struct audio_stop *stop)
  103. {
  104. return (0);
  105. }
  106. static int
  107. finish(struct audio_finish *finish)
  108. {
  109. sio_close(hdl);
  110. return (0);
  111. }
  112. int
  113. audio_sndio(union audio_control *control)
  114. {
  115. audio_error = 0;
  116. switch (control->command) {
  117. case AUDIO_COMMAND_INIT:
  118. return (init(&control->init));
  119. case AUDIO_COMMAND_CONFIG:
  120. return (config(&control->config));
  121. case AUDIO_COMMAND_PLAY:
  122. return (play(&control->play));
  123. case AUDIO_COMMAND_STOP:
  124. return (stop(&control->stop));
  125. case AUDIO_COMMAND_FINISH:
  126. return (finish(&control->finish));
  127. }
  128. return (0);
  129. }