2 * Routines for Gravis UltraSound soundcards - Sample support
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
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.
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.
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
22 #include <sound/driver.h>
23 #include <linux/time.h>
24 #include <sound/core.h>
25 #include <sound/gus.h>
31 static void select_instrument(struct snd_gus_card
* gus
, struct snd_gus_voice
* v
)
33 struct snd_seq_kinstr
*instr
;
36 printk("select instrument: cluster = %li, std = 0x%x, bank = %i, prg = %i\n",
42 instr
= snd_seq_instr_find(gus
->gf1
.ilist
, &v
->instr
, 0, 1);
45 if (!strcmp(instr
->ops
->instr_type
, SNDRV_SEQ_INSTR_ID_SIMPLE
))
46 snd_gf1_simple_init(v
);
48 snd_seq_instr_free_use(gus
->gf1
.ilist
, instr
);
56 static void event_sample(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
57 struct snd_gus_voice
*v
)
59 if (v
->sample_ops
&& v
->sample_ops
->sample_stop
)
60 v
->sample_ops
->sample_stop(p
->gus
, v
, SAMPLE_STOP_IMMEDIATELY
);
61 v
->instr
.std
= ev
->data
.sample
.param
.sample
.std
;
62 if (v
->instr
.std
& 0xff000000) { /* private instrument */
63 v
->instr
.std
&= 0x00ffffff;
64 v
->instr
.std
|= (unsigned int)ev
->source
.client
<< 24;
66 v
->instr
.bank
= ev
->data
.sample
.param
.sample
.bank
;
67 v
->instr
.prg
= ev
->data
.sample
.param
.sample
.prg
;
68 select_instrument(p
->gus
, v
);
71 static void event_cluster(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
72 struct snd_gus_voice
*v
)
74 if (v
->sample_ops
&& v
->sample_ops
->sample_stop
)
75 v
->sample_ops
->sample_stop(p
->gus
, v
, SAMPLE_STOP_IMMEDIATELY
);
76 v
->instr
.cluster
= ev
->data
.sample
.param
.cluster
.cluster
;
77 select_instrument(p
->gus
, v
);
80 static void event_start(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
81 struct snd_gus_voice
*v
)
83 if (v
->sample_ops
&& v
->sample_ops
->sample_start
)
84 v
->sample_ops
->sample_start(p
->gus
, v
, ev
->data
.sample
.param
.position
);
87 static void event_stop(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
88 struct snd_gus_voice
*v
)
90 if (v
->sample_ops
&& v
->sample_ops
->sample_stop
)
91 v
->sample_ops
->sample_stop(p
->gus
, v
, ev
->data
.sample
.param
.stop_mode
);
94 static void event_freq(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
95 struct snd_gus_voice
*v
)
97 if (v
->sample_ops
&& v
->sample_ops
->sample_freq
)
98 v
->sample_ops
->sample_freq(p
->gus
, v
, ev
->data
.sample
.param
.frequency
);
101 static void event_volume(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
102 struct snd_gus_voice
*v
)
104 if (v
->sample_ops
&& v
->sample_ops
->sample_volume
)
105 v
->sample_ops
->sample_volume(p
->gus
, v
, &ev
->data
.sample
.param
.volume
);
108 static void event_loop(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
109 struct snd_gus_voice
*v
)
111 if (v
->sample_ops
&& v
->sample_ops
->sample_loop
)
112 v
->sample_ops
->sample_loop(p
->gus
, v
, &ev
->data
.sample
.param
.loop
);
115 static void event_position(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
116 struct snd_gus_voice
*v
)
118 if (v
->sample_ops
&& v
->sample_ops
->sample_pos
)
119 v
->sample_ops
->sample_pos(p
->gus
, v
, ev
->data
.sample
.param
.position
);
122 static void event_private1(struct snd_seq_event
*ev
, struct snd_gus_port
*p
,
123 struct snd_gus_voice
*v
)
125 if (v
->sample_ops
&& v
->sample_ops
->sample_private1
)
126 v
->sample_ops
->sample_private1(p
->gus
, v
, (unsigned char *)&ev
->data
.sample
.param
.raw8
);
129 typedef void (gus_sample_event_handler_t
)(struct snd_seq_event
*ev
,
130 struct snd_gus_port
*p
,
131 struct snd_gus_voice
*v
);
132 static gus_sample_event_handler_t
*gus_sample_event_handlers
[9] = {
144 void snd_gus_sample_event(struct snd_seq_event
*ev
, struct snd_gus_port
*p
)
147 struct snd_gus_card
*gus
= p
->gus
;
148 struct snd_gus_voice
*v
;
151 idx
= ev
->type
- SNDRV_SEQ_EVENT_SAMPLE
;
152 if (idx
< 0 || idx
> 8)
154 for (voice
= 0; voice
< 32; voice
++) {
155 v
= &gus
->gf1
.voices
[voice
];
156 if (v
->use
&& v
->client
== ev
->source
.client
&&
157 v
->port
== ev
->source
.port
&&
158 v
->index
== ev
->data
.sample
.channel
) {
159 spin_lock_irqsave(&gus
->event_lock
, flags
);
160 gus_sample_event_handlers
[idx
](ev
, p
, v
);
161 spin_unlock_irqrestore(&gus
->event_lock
, flags
);