seq_oss_timer.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /*
  2. * OSS compatible sequencer driver
  3. *
  4. * Timer control routines
  5. *
  6. * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include "seq_oss_timer.h"
  23. #include "seq_oss_event.h"
  24. #include <sound/seq_oss_legacy.h>
  25. #include <linux/slab.h>
  26. /*
  27. */
  28. #define MIN_OSS_TEMPO 8
  29. #define MAX_OSS_TEMPO 360
  30. #define MIN_OSS_TIMEBASE 1
  31. #define MAX_OSS_TIMEBASE 1000
  32. /*
  33. */
  34. static void calc_alsa_tempo(struct seq_oss_timer *timer);
  35. static int send_timer_event(struct seq_oss_devinfo *dp, int type, int value);
  36. /*
  37. * create and register a new timer.
  38. * if queue is not started yet, start it.
  39. */
  40. struct seq_oss_timer *
  41. snd_seq_oss_timer_new(struct seq_oss_devinfo *dp)
  42. {
  43. struct seq_oss_timer *rec;
  44. rec = kzalloc(sizeof(*rec), GFP_KERNEL);
  45. if (rec == NULL)
  46. return NULL;
  47. rec->dp = dp;
  48. rec->cur_tick = 0;
  49. rec->realtime = 0;
  50. rec->running = 0;
  51. rec->oss_tempo = 60;
  52. rec->oss_timebase = 100;
  53. calc_alsa_tempo(rec);
  54. return rec;
  55. }
  56. /*
  57. * delete timer.
  58. * if no more timer exists, stop the queue.
  59. */
  60. void
  61. snd_seq_oss_timer_delete(struct seq_oss_timer *rec)
  62. {
  63. if (rec) {
  64. snd_seq_oss_timer_stop(rec);
  65. kfree(rec);
  66. }
  67. }
  68. /*
  69. * process one timing event
  70. * return 1 : event proceseed -- skip this event
  71. * 0 : not a timer event -- enqueue this event
  72. */
  73. int
  74. snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev)
  75. {
  76. abstime_t parm = ev->t.time;
  77. if (ev->t.code == EV_TIMING) {
  78. switch (ev->t.cmd) {
  79. case TMR_WAIT_REL:
  80. parm += rec->cur_tick;
  81. rec->realtime = 0;
  82. /* continue to next */
  83. case TMR_WAIT_ABS:
  84. if (parm == 0) {
  85. rec->realtime = 1;
  86. } else if (parm >= rec->cur_tick) {
  87. rec->realtime = 0;
  88. rec->cur_tick = parm;
  89. }
  90. return 1; /* skip this event */
  91. case TMR_START:
  92. snd_seq_oss_timer_start(rec);
  93. return 1;
  94. }
  95. } else if (ev->s.code == SEQ_WAIT) {
  96. /* time = from 1 to 3 bytes */
  97. parm = (ev->echo >> 8) & 0xffffff;
  98. if (parm > rec->cur_tick) {
  99. /* set next event time */
  100. rec->cur_tick = parm;
  101. rec->realtime = 0;
  102. }
  103. return 1;
  104. }
  105. return 0;
  106. }
  107. /*
  108. * convert tempo units
  109. */
  110. static void
  111. calc_alsa_tempo(struct seq_oss_timer *timer)
  112. {
  113. timer->tempo = (60 * 1000000) / timer->oss_tempo;
  114. timer->ppq = timer->oss_timebase;
  115. }
  116. /*
  117. * dispatch a timer event
  118. */
  119. static int
  120. send_timer_event(struct seq_oss_devinfo *dp, int type, int value)
  121. {
  122. struct snd_seq_event ev;
  123. memset(&ev, 0, sizeof(ev));
  124. ev.type = type;
  125. ev.source.client = dp->cseq;
  126. ev.source.port = 0;
  127. ev.dest.client = SNDRV_SEQ_CLIENT_SYSTEM;
  128. ev.dest.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
  129. ev.queue = dp->queue;
  130. ev.data.queue.queue = dp->queue;
  131. ev.data.queue.param.value = value;
  132. return snd_seq_kernel_client_dispatch(dp->cseq, &ev, 1, 0);
  133. }
  134. /*
  135. * set queue tempo and start queue
  136. */
  137. int
  138. snd_seq_oss_timer_start(struct seq_oss_timer *timer)
  139. {
  140. struct seq_oss_devinfo *dp = timer->dp;
  141. struct snd_seq_queue_tempo tmprec;
  142. if (timer->running)
  143. snd_seq_oss_timer_stop(timer);
  144. memset(&tmprec, 0, sizeof(tmprec));
  145. tmprec.queue = dp->queue;
  146. tmprec.ppq = timer->ppq;
  147. tmprec.tempo = timer->tempo;
  148. snd_seq_set_queue_tempo(dp->cseq, &tmprec);
  149. send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
  150. timer->running = 1;
  151. timer->cur_tick = 0;
  152. return 0;
  153. }
  154. /*
  155. * stop queue
  156. */
  157. int
  158. snd_seq_oss_timer_stop(struct seq_oss_timer *timer)
  159. {
  160. if (! timer->running)
  161. return 0;
  162. send_timer_event(timer->dp, SNDRV_SEQ_EVENT_STOP, 0);
  163. timer->running = 0;
  164. return 0;
  165. }
  166. /*
  167. * continue queue
  168. */
  169. int
  170. snd_seq_oss_timer_continue(struct seq_oss_timer *timer)
  171. {
  172. if (timer->running)
  173. return 0;
  174. send_timer_event(timer->dp, SNDRV_SEQ_EVENT_CONTINUE, 0);
  175. timer->running = 1;
  176. return 0;
  177. }
  178. /*
  179. * change queue tempo
  180. */
  181. int
  182. snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value)
  183. {
  184. if (value < MIN_OSS_TEMPO)
  185. value = MIN_OSS_TEMPO;
  186. else if (value > MAX_OSS_TEMPO)
  187. value = MAX_OSS_TEMPO;
  188. timer->oss_tempo = value;
  189. calc_alsa_tempo(timer);
  190. if (timer->running)
  191. send_timer_event(timer->dp, SNDRV_SEQ_EVENT_TEMPO, timer->tempo);
  192. return 0;
  193. }
  194. /*
  195. * ioctls
  196. */
  197. int
  198. snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg)
  199. {
  200. int value;
  201. if (cmd == SNDCTL_SEQ_CTRLRATE) {
  202. /* if *arg == 0, just return the current rate */
  203. if (get_user(value, arg))
  204. return -EFAULT;
  205. if (value)
  206. return -EINVAL;
  207. value = ((timer->oss_tempo * timer->oss_timebase) + 30) / 60;
  208. return put_user(value, arg) ? -EFAULT : 0;
  209. }
  210. if (timer->dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
  211. return 0;
  212. switch (cmd) {
  213. case SNDCTL_TMR_START:
  214. return snd_seq_oss_timer_start(timer);
  215. case SNDCTL_TMR_STOP:
  216. return snd_seq_oss_timer_stop(timer);
  217. case SNDCTL_TMR_CONTINUE:
  218. return snd_seq_oss_timer_continue(timer);
  219. case SNDCTL_TMR_TEMPO:
  220. if (get_user(value, arg))
  221. return -EFAULT;
  222. return snd_seq_oss_timer_tempo(timer, value);
  223. case SNDCTL_TMR_TIMEBASE:
  224. if (get_user(value, arg))
  225. return -EFAULT;
  226. if (value < MIN_OSS_TIMEBASE)
  227. value = MIN_OSS_TIMEBASE;
  228. else if (value > MAX_OSS_TIMEBASE)
  229. value = MAX_OSS_TIMEBASE;
  230. timer->oss_timebase = value;
  231. calc_alsa_tempo(timer);
  232. return 0;
  233. case SNDCTL_TMR_METRONOME:
  234. case SNDCTL_TMR_SELECT:
  235. case SNDCTL_TMR_SOURCE:
  236. /* not supported */
  237. return 0;
  238. }
  239. return 0;
  240. }