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(snd_gus_card_t
* gus
, snd_gus_voice_t
* v
)
33 snd_seq_kinstr_t
*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(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
58 if (v
->sample_ops
&& v
->sample_ops
->sample_stop
)
59 v
->sample_ops
->sample_stop(p
->gus
, v
, SAMPLE_STOP_IMMEDIATELY
);
60 v
->instr
.std
= ev
->data
.sample
.param
.sample
.std
;
61 if (v
->instr
.std
& 0xff000000) { /* private instrument */
62 v
->instr
.std
&= 0x00ffffff;
63 v
->instr
.std
|= (unsigned int)ev
->source
.client
<< 24;
65 v
->instr
.bank
= ev
->data
.sample
.param
.sample
.bank
;
66 v
->instr
.prg
= ev
->data
.sample
.param
.sample
.prg
;
67 select_instrument(p
->gus
, v
);
70 static void event_cluster(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
72 if (v
->sample_ops
&& v
->sample_ops
->sample_stop
)
73 v
->sample_ops
->sample_stop(p
->gus
, v
, SAMPLE_STOP_IMMEDIATELY
);
74 v
->instr
.cluster
= ev
->data
.sample
.param
.cluster
.cluster
;
75 select_instrument(p
->gus
, v
);
78 static void event_start(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
80 if (v
->sample_ops
&& v
->sample_ops
->sample_start
)
81 v
->sample_ops
->sample_start(p
->gus
, v
, ev
->data
.sample
.param
.position
);
84 static void event_stop(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
86 if (v
->sample_ops
&& v
->sample_ops
->sample_stop
)
87 v
->sample_ops
->sample_stop(p
->gus
, v
, ev
->data
.sample
.param
.stop_mode
);
90 static void event_freq(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
92 if (v
->sample_ops
&& v
->sample_ops
->sample_freq
)
93 v
->sample_ops
->sample_freq(p
->gus
, v
, ev
->data
.sample
.param
.frequency
);
96 static void event_volume(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
98 if (v
->sample_ops
&& v
->sample_ops
->sample_volume
)
99 v
->sample_ops
->sample_volume(p
->gus
, v
, &ev
->data
.sample
.param
.volume
);
102 static void event_loop(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
104 if (v
->sample_ops
&& v
->sample_ops
->sample_loop
)
105 v
->sample_ops
->sample_loop(p
->gus
, v
, &ev
->data
.sample
.param
.loop
);
108 static void event_position(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
110 if (v
->sample_ops
&& v
->sample_ops
->sample_pos
)
111 v
->sample_ops
->sample_pos(p
->gus
, v
, ev
->data
.sample
.param
.position
);
114 static void event_private1(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
)
116 if (v
->sample_ops
&& v
->sample_ops
->sample_private1
)
117 v
->sample_ops
->sample_private1(p
->gus
, v
, (unsigned char *)&ev
->data
.sample
.param
.raw8
);
120 typedef void (gus_sample_event_handler_t
)(snd_seq_event_t
*ev
, snd_gus_port_t
*p
, snd_gus_voice_t
*v
);
122 static gus_sample_event_handler_t
*gus_sample_event_handlers
[9] = {
134 void snd_gus_sample_event(snd_seq_event_t
*ev
, snd_gus_port_t
*p
)
137 snd_gus_card_t
*gus
= p
->gus
;
141 idx
= ev
->type
- SNDRV_SEQ_EVENT_SAMPLE
;
142 if (idx
< 0 || idx
> 8)
144 for (voice
= 0; voice
< 32; voice
++) {
145 v
= &gus
->gf1
.voices
[voice
];
146 if (v
->use
&& v
->client
== ev
->source
.client
&&
147 v
->port
== ev
->source
.port
&&
148 v
->index
== ev
->data
.sample
.channel
) {
149 spin_lock_irqsave(&gus
->event_lock
, flags
);
150 gus_sample_event_handlers
[idx
](ev
, p
, v
);
151 spin_unlock_irqrestore(&gus
->event_lock
, flags
);