1/* 2 * Routines for Gravis UltraSound soundcards - Sample support 3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 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 22#include <sound/driver.h> 23#include <linux/time.h> 24#include <sound/core.h> 25#include <sound/gus.h> 26 27/* 28 * 29 */ 30 31static void select_instrument(struct snd_gus_card * gus, struct snd_gus_voice * v) 32{ 33 struct snd_seq_kinstr *instr; 34 35 instr = snd_seq_instr_find(gus->gf1.ilist, &v->instr, 0, 1); 36 if (instr != NULL) { 37 if (instr->ops) { 38 if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE)) 39 snd_gf1_simple_init(v); 40 } 41 snd_seq_instr_free_use(gus->gf1.ilist, instr); 42 } 43} 44 45/* 46 * 47 */ 48 49static void event_sample(struct snd_seq_event *ev, struct snd_gus_port *p, 50 struct snd_gus_voice *v) 51{ 52 if (v->sample_ops && v->sample_ops->sample_stop) 53 v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY); 54 v->instr.std = ev->data.sample.param.sample.std; 55 if (v->instr.std & 0xff000000) { /* private instrument */ 56 v->instr.std &= 0x00ffffff; 57 v->instr.std |= (unsigned int)ev->source.client << 24; 58 } 59 v->instr.bank = ev->data.sample.param.sample.bank; 60 v->instr.prg = ev->data.sample.param.sample.prg; 61 select_instrument(p->gus, v); 62} 63 64static void event_cluster(struct snd_seq_event *ev, struct snd_gus_port *p, 65 struct snd_gus_voice *v) 66{ 67 if (v->sample_ops && v->sample_ops->sample_stop) 68 v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY); 69 v->instr.cluster = ev->data.sample.param.cluster.cluster; 70 select_instrument(p->gus, v); 71} 72 73static void event_start(struct snd_seq_event *ev, struct snd_gus_port *p, 74 struct snd_gus_voice *v) 75{ 76 if (v->sample_ops && v->sample_ops->sample_start) 77 v->sample_ops->sample_start(p->gus, v, ev->data.sample.param.position); 78} 79 80static void event_stop(struct snd_seq_event *ev, struct snd_gus_port *p, 81 struct snd_gus_voice *v) 82{ 83 if (v->sample_ops && v->sample_ops->sample_stop) 84 v->sample_ops->sample_stop(p->gus, v, ev->data.sample.param.stop_mode); 85} 86 87static void event_freq(struct snd_seq_event *ev, struct snd_gus_port *p, 88 struct snd_gus_voice *v) 89{ 90 if (v->sample_ops && v->sample_ops->sample_freq) 91 v->sample_ops->sample_freq(p->gus, v, ev->data.sample.param.frequency); 92} 93 94static void event_volume(struct snd_seq_event *ev, struct snd_gus_port *p, 95 struct snd_gus_voice *v) 96{ 97 if (v->sample_ops && v->sample_ops->sample_volume) 98 v->sample_ops->sample_volume(p->gus, v, &ev->data.sample.param.volume); 99} 100 101static void event_loop(struct snd_seq_event *ev, struct snd_gus_port *p, 102 struct snd_gus_voice *v) 103{ 104 if (v->sample_ops && v->sample_ops->sample_loop) 105 v->sample_ops->sample_loop(p->gus, v, &ev->data.sample.param.loop); 106} 107 108static void event_position(struct snd_seq_event *ev, struct snd_gus_port *p, 109 struct snd_gus_voice *v) 110{ 111 if (v->sample_ops && v->sample_ops->sample_pos) 112 v->sample_ops->sample_pos(p->gus, v, ev->data.sample.param.position); 113} 114 115static void event_private1(struct snd_seq_event *ev, struct snd_gus_port *p, 116 struct snd_gus_voice *v) 117{ 118 if (v->sample_ops && v->sample_ops->sample_private1) 119 v->sample_ops->sample_private1(p->gus, v, (unsigned char *)&ev->data.sample.param.raw8); 120} 121 122typedef void (gus_sample_event_handler_t)(struct snd_seq_event *ev, 123 struct snd_gus_port *p, 124 struct snd_gus_voice *v); 125static gus_sample_event_handler_t *gus_sample_event_handlers[9] = { 126 event_sample, 127 event_cluster, 128 event_start, 129 event_stop, 130 event_freq, 131 event_volume, 132 event_loop, 133 event_position, 134 event_private1 135}; 136 137void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p) 138{ 139 int idx, voice; 140 struct snd_gus_card *gus = p->gus; 141 struct snd_gus_voice *v; 142 unsigned long flags; 143 144 idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE; 145 if (idx < 0 || idx > 8) 146 return; 147 for (voice = 0; voice < 32; voice++) { 148 v = &gus->gf1.voices[voice]; 149 if (v->use && v->client == ev->source.client && 150 v->port == ev->source.port && 151 v->index == ev->data.sample.channel) { 152 spin_lock_irqsave(&gus->event_lock, flags); 153 gus_sample_event_handlers[idx](ev, p, v); 154 spin_unlock_irqrestore(&gus->event_lock, flags); 155 return; 156 } 157 } 158} 159