1/*
2 *  ALSA sequencer Timer
3 *  Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
4 *
5 *
6 *   This program is free software; you can redistribute it and/or modify
7 *   it under the terms of the GNU General Public License as published by
8 *   the Free Software Foundation; either version 2 of the License, or
9 *   (at your option) any later version.
10 *
11 *   This program is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *   GNU General Public License for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with this program; if not, write to the Free Software
18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 *
20 */
21#ifndef __SND_SEQ_TIMER_H
22#define __SND_SEQ_TIMER_H
23
24#include <sound/timer.h>
25#include <sound/seq_kernel.h>
26
27struct snd_seq_timer_tick {
28	snd_seq_tick_time_t	cur_tick;	/* current tick */
29	unsigned long		resolution;	/* time per tick in nsec */
30	unsigned long		fraction;	/* current time per tick in nsec */
31};
32
33struct snd_seq_timer {
34	/* ... tempo / offset / running state */
35
36	unsigned int		running:1,	/* running state of queue */
37				initialized:1;	/* timer is initialized */
38
39	unsigned int		tempo;		/* current tempo, us/tick */
40	int			ppq;		/* time resolution, ticks/quarter */
41
42	snd_seq_real_time_t	cur_time;	/* current time */
43	struct snd_seq_timer_tick	tick;	/* current tick */
44	int tick_updated;
45
46	int			type;		/* timer type */
47	struct snd_timer_id	alsa_id;	/* ALSA's timer ID */
48	struct snd_timer_instance	*timeri;	/* timer instance */
49	unsigned int		ticks;
50	unsigned long		preferred_resolution; /* timer resolution, ticks/sec */
51
52	unsigned int skew;
53	unsigned int skew_base;
54
55	struct timeval 		last_update;	 /* time of last clock update, used for interpolation */
56
57	spinlock_t lock;
58};
59
60
61/* create new timer (constructor) */
62struct snd_seq_timer *snd_seq_timer_new(void);
63
64/* delete timer (destructor) */
65void snd_seq_timer_delete(struct snd_seq_timer **tmr);
66
67/* */
68static inline void snd_seq_timer_update_tick(struct snd_seq_timer_tick *tick,
69					     unsigned long resolution)
70{
71	if (tick->resolution > 0) {
72		tick->fraction += resolution;
73		tick->cur_tick += (unsigned int)(tick->fraction / tick->resolution);
74		tick->fraction %= tick->resolution;
75	}
76}
77
78
79/* compare timestamp between events */
80/* return 1 if a >= b; otherwise return 0 */
81static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b)
82{
83	/* compare ticks */
84	return (*a >= *b);
85}
86
87static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b)
88{
89	/* compare real time */
90	if (a->tv_sec > b->tv_sec)
91		return 1;
92	if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec))
93		return 1;
94	return 0;
95}
96
97
98static inline void snd_seq_sanity_real_time(snd_seq_real_time_t *tm)
99{
100	while (tm->tv_nsec >= 1000000000) {
101		/* roll-over */
102		tm->tv_nsec -= 1000000000;
103                tm->tv_sec++;
104        }
105}
106
107
108/* increment timestamp */
109static inline void snd_seq_inc_real_time(snd_seq_real_time_t *tm, snd_seq_real_time_t *inc)
110{
111	tm->tv_sec  += inc->tv_sec;
112	tm->tv_nsec += inc->tv_nsec;
113	snd_seq_sanity_real_time(tm);
114}
115
116static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long nsec)
117{
118	tm->tv_nsec  += nsec;
119	snd_seq_sanity_real_time(tm);
120}
121
122/* called by timer isr */
123struct snd_seq_queue;
124int snd_seq_timer_open(struct snd_seq_queue *q);
125int snd_seq_timer_close(struct snd_seq_queue *q);
126int snd_seq_timer_midi_open(struct snd_seq_queue *q);
127int snd_seq_timer_midi_close(struct snd_seq_queue *q);
128void snd_seq_timer_defaults(struct snd_seq_timer *tmr);
129void snd_seq_timer_reset(struct snd_seq_timer *tmr);
130int snd_seq_timer_stop(struct snd_seq_timer *tmr);
131int snd_seq_timer_start(struct snd_seq_timer *tmr);
132int snd_seq_timer_continue(struct snd_seq_timer *tmr);
133int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo);
134int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq);
135int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
136int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
137int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
138snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr);
139snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
140
141extern int seq_default_timer_class;
142extern int seq_default_timer_sclass;
143extern int seq_default_timer_card;
144extern int seq_default_timer_device;
145extern int seq_default_timer_subdevice;
146extern int seq_default_timer_resolution;
147
148#endif
149