Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
seq_timer.c
Go to the documentation of this file.
1 /*
2  * ALSA sequencer Timer
3  * Copyright (c) 1998-1999 by Frank van de Pol <[email protected]>
4  * Jaroslav Kysela <[email protected]>
5  *
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22 
23 #include <sound/core.h>
24 #include <linux/slab.h>
25 #include "seq_timer.h"
26 #include "seq_queue.h"
27 #include "seq_info.h"
28 
29 /* allowed sequencer timer frequencies, in Hz */
30 #define MIN_FREQUENCY 10
31 #define MAX_FREQUENCY 6250
32 #define DEFAULT_FREQUENCY 1000
33 
34 #define SKEW_BASE 0x10000 /* 16bit shift */
35 
36 static void snd_seq_timer_set_tick_resolution(struct snd_seq_timer *tmr)
37 {
38  if (tmr->tempo < 1000000)
39  tmr->tick.resolution = (tmr->tempo * 1000) / tmr->ppq;
40  else {
41  /* might overflow.. */
42  unsigned int s;
43  s = tmr->tempo % tmr->ppq;
44  s = (s * 1000) / tmr->ppq;
45  tmr->tick.resolution = (tmr->tempo / tmr->ppq) * 1000;
46  tmr->tick.resolution += s;
47  }
48  if (tmr->tick.resolution <= 0)
49  tmr->tick.resolution = 1;
50  snd_seq_timer_update_tick(&tmr->tick, 0);
51 }
52 
53 /* create new timer (constructor) */
55 {
56  struct snd_seq_timer *tmr;
57 
58  tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
59  if (tmr == NULL) {
60  snd_printd("malloc failed for snd_seq_timer_new() \n");
61  return NULL;
62  }
63  spin_lock_init(&tmr->lock);
64 
65  /* reset setup to defaults */
67 
68  /* reset time */
70 
71  return tmr;
72 }
73 
74 /* delete timer (destructor) */
76 {
77  struct snd_seq_timer *t = *tmr;
78  *tmr = NULL;
79 
80  if (t == NULL) {
81  snd_printd("oops: snd_seq_timer_delete() called with NULL timer\n");
82  return;
83  }
84  t->running = 0;
85 
86  /* reset time */
89 
90  kfree(t);
91 }
92 
94 {
95  /* setup defaults */
96  tmr->ppq = 96; /* 96 PPQ */
97  tmr->tempo = 500000; /* 120 BPM */
98  snd_seq_timer_set_tick_resolution(tmr);
99  tmr->running = 0;
100 
101  tmr->type = SNDRV_SEQ_TIMER_ALSA;
102  tmr->alsa_id.dev_class = seq_default_timer_class;
103  tmr->alsa_id.dev_sclass = seq_default_timer_sclass;
104  tmr->alsa_id.card = seq_default_timer_card;
105  tmr->alsa_id.device = seq_default_timer_device;
106  tmr->alsa_id.subdevice = seq_default_timer_subdevice;
108 
109  tmr->skew = tmr->skew_base = SKEW_BASE;
110 }
111 
113 {
114  unsigned long flags;
115 
116  spin_lock_irqsave(&tmr->lock, flags);
117 
118  /* reset time & songposition */
119  tmr->cur_time.tv_sec = 0;
120  tmr->cur_time.tv_nsec = 0;
121 
122  tmr->tick.cur_tick = 0;
123  tmr->tick.fraction = 0;
124 
125  spin_unlock_irqrestore(&tmr->lock, flags);
126 }
127 
128 
129 /* called by timer interrupt routine. the period time since previous invocation is passed */
130 static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
131  unsigned long resolution,
132  unsigned long ticks)
133 {
134  unsigned long flags;
135  struct snd_seq_queue *q = timeri->callback_data;
136  struct snd_seq_timer *tmr;
137 
138  if (q == NULL)
139  return;
140  tmr = q->timer;
141  if (tmr == NULL)
142  return;
143  if (!tmr->running)
144  return;
145 
146  resolution *= ticks;
147  if (tmr->skew != tmr->skew_base) {
148  /* FIXME: assuming skew_base = 0x10000 */
149  resolution = (resolution >> 16) * tmr->skew +
150  (((resolution & 0xffff) * tmr->skew) >> 16);
151  }
152 
153  spin_lock_irqsave(&tmr->lock, flags);
154 
155  /* update timer */
156  snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
157 
158  /* calculate current tick */
159  snd_seq_timer_update_tick(&tmr->tick, resolution);
160 
161  /* register actual time of this timer update */
163 
164  spin_unlock_irqrestore(&tmr->lock, flags);
165 
166  /* check queues and dispatch events */
167  snd_seq_check_queue(q, 1, 0);
168 }
169 
170 /* set current tempo */
172 {
173  unsigned long flags;
174 
175  if (snd_BUG_ON(!tmr))
176  return -EINVAL;
177  if (tempo <= 0)
178  return -EINVAL;
179  spin_lock_irqsave(&tmr->lock, flags);
180  if ((unsigned int)tempo != tmr->tempo) {
181  tmr->tempo = tempo;
182  snd_seq_timer_set_tick_resolution(tmr);
183  }
184  spin_unlock_irqrestore(&tmr->lock, flags);
185  return 0;
186 }
187 
188 /* set current ppq */
190 {
191  unsigned long flags;
192 
193  if (snd_BUG_ON(!tmr))
194  return -EINVAL;
195  if (ppq <= 0)
196  return -EINVAL;
197  spin_lock_irqsave(&tmr->lock, flags);
198  if (tmr->running && (ppq != tmr->ppq)) {
199  /* refuse to change ppq on running timers */
200  /* because it will upset the song position (ticks) */
201  spin_unlock_irqrestore(&tmr->lock, flags);
202  snd_printd("seq: cannot change ppq of a running timer\n");
203  return -EBUSY;
204  }
205 
206  tmr->ppq = ppq;
207  snd_seq_timer_set_tick_resolution(tmr);
208  spin_unlock_irqrestore(&tmr->lock, flags);
209  return 0;
210 }
211 
212 /* set current tick position */
214  snd_seq_tick_time_t position)
215 {
216  unsigned long flags;
217 
218  if (snd_BUG_ON(!tmr))
219  return -EINVAL;
220 
221  spin_lock_irqsave(&tmr->lock, flags);
222  tmr->tick.cur_tick = position;
223  tmr->tick.fraction = 0;
224  spin_unlock_irqrestore(&tmr->lock, flags);
225  return 0;
226 }
227 
228 /* set current real-time position */
230  snd_seq_real_time_t position)
231 {
232  unsigned long flags;
233 
234  if (snd_BUG_ON(!tmr))
235  return -EINVAL;
236 
237  snd_seq_sanity_real_time(&position);
238  spin_lock_irqsave(&tmr->lock, flags);
239  tmr->cur_time = position;
240  spin_unlock_irqrestore(&tmr->lock, flags);
241  return 0;
242 }
243 
244 /* set timer skew */
245 int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew,
246  unsigned int base)
247 {
248  unsigned long flags;
249 
250  if (snd_BUG_ON(!tmr))
251  return -EINVAL;
252 
253  /* FIXME */
254  if (base != SKEW_BASE) {
255  snd_printd("invalid skew base 0x%x\n", base);
256  return -EINVAL;
257  }
258  spin_lock_irqsave(&tmr->lock, flags);
259  tmr->skew = skew;
260  spin_unlock_irqrestore(&tmr->lock, flags);
261  return 0;
262 }
263 
265 {
266  struct snd_timer_instance *t;
267  struct snd_seq_timer *tmr;
268  char str[32];
269  int err;
270 
271  tmr = q->timer;
272  if (snd_BUG_ON(!tmr))
273  return -EINVAL;
274  if (tmr->timeri)
275  return -EBUSY;
276  sprintf(str, "sequencer queue %i", q->queue);
277  if (tmr->type != SNDRV_SEQ_TIMER_ALSA) /* standard ALSA timer */
278  return -EINVAL;
279  if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
280  tmr->alsa_id.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER;
281  err = snd_timer_open(&t, str, &tmr->alsa_id, q->queue);
282  if (err < 0 && tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE) {
283  if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_GLOBAL ||
284  tmr->alsa_id.device != SNDRV_TIMER_GLOBAL_SYSTEM) {
285  struct snd_timer_id tid;
286  memset(&tid, 0, sizeof(tid));
289  tid.card = -1;
291  err = snd_timer_open(&t, str, &tid, q->queue);
292  }
293  if (err < 0) {
294  snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
295  return err;
296  }
297  }
298  t->callback = snd_seq_timer_interrupt;
299  t->callback_data = q;
301  tmr->timeri = t;
302  return 0;
303 }
304 
306 {
307  struct snd_seq_timer *tmr;
308 
309  tmr = q->timer;
310  if (snd_BUG_ON(!tmr))
311  return -EINVAL;
312  if (tmr->timeri) {
313  snd_timer_stop(tmr->timeri);
314  snd_timer_close(tmr->timeri);
315  tmr->timeri = NULL;
316  }
317  return 0;
318 }
319 
321 {
322  if (! tmr->timeri)
323  return -EINVAL;
324  if (!tmr->running)
325  return 0;
326  tmr->running = 0;
327  snd_timer_pause(tmr->timeri);
328  return 0;
329 }
330 
331 static int initialize_timer(struct snd_seq_timer *tmr)
332 {
333  struct snd_timer *t;
334  unsigned long freq;
335 
336  t = tmr->timeri->timer;
337  if (snd_BUG_ON(!t))
338  return -EINVAL;
339 
340  freq = tmr->preferred_resolution;
341  if (!freq)
342  freq = DEFAULT_FREQUENCY;
343  else if (freq < MIN_FREQUENCY)
344  freq = MIN_FREQUENCY;
345  else if (freq > MAX_FREQUENCY)
346  freq = MAX_FREQUENCY;
347 
348  tmr->ticks = 1;
349  if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
350  unsigned long r = t->hw.resolution;
351  if (! r && t->hw.c_resolution)
352  r = t->hw.c_resolution(t);
353  if (r) {
354  tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
355  if (! tmr->ticks)
356  tmr->ticks = 1;
357  }
358  }
359  tmr->initialized = 1;
360  return 0;
361 }
362 
364 {
365  if (! tmr->timeri)
366  return -EINVAL;
367  if (tmr->running)
368  snd_seq_timer_stop(tmr);
369  snd_seq_timer_reset(tmr);
370  if (initialize_timer(tmr) < 0)
371  return -EINVAL;
372  snd_timer_start(tmr->timeri, tmr->ticks);
373  tmr->running = 1;
375  return 0;
376 }
377 
379 {
380  if (! tmr->timeri)
381  return -EINVAL;
382  if (tmr->running)
383  return -EBUSY;
384  if (! tmr->initialized) {
385  snd_seq_timer_reset(tmr);
386  if (initialize_timer(tmr) < 0)
387  return -EINVAL;
388  }
389  snd_timer_start(tmr->timeri, tmr->ticks);
390  tmr->running = 1;
392  return 0;
393 }
394 
395 /* return current 'real' time. use timeofday() to get better granularity. */
397 {
398  snd_seq_real_time_t cur_time;
399 
400  cur_time = tmr->cur_time;
401  if (tmr->running) {
402  struct timeval tm;
403  int usec;
404  do_gettimeofday(&tm);
405  usec = (int)(tm.tv_usec - tmr->last_update.tv_usec);
406  if (usec < 0) {
407  cur_time.tv_nsec += (1000000 + usec) * 1000;
408  cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec - 1;
409  } else {
410  cur_time.tv_nsec += usec * 1000;
411  cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec;
412  }
413  snd_seq_sanity_real_time(&cur_time);
414  }
415 
416  return cur_time;
417 }
418 
419 /* TODO: use interpolation on tick queue (will only be useful for very
420  high PPQ values) */
422 {
423  return tmr->tick.cur_tick;
424 }
425 
426 
427 #ifdef CONFIG_PROC_FS
428 /* exported to seq_info.c */
430  struct snd_info_buffer *buffer)
431 {
432  int idx;
433  struct snd_seq_queue *q;
434  struct snd_seq_timer *tmr;
435  struct snd_timer_instance *ti;
436  unsigned long resolution;
437 
438  for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
439  q = queueptr(idx);
440  if (q == NULL)
441  continue;
442  if ((tmr = q->timer) == NULL ||
443  (ti = tmr->timeri) == NULL) {
444  queuefree(q);
445  continue;
446  }
447  snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
448  resolution = snd_timer_resolution(ti) * tmr->ticks;
449  snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
450  snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base);
451  queuefree(q);
452  }
453 }
454 #endif /* CONFIG_PROC_FS */
455