2 * Simple (MOD player) - Instrument routines
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/sched.h>
24 #include <linux/slab.h>
25 #include <sound/core.h>
26 #include <sound/ainstr_simple.h>
27 #include <sound/initval.h>
28 #include <asm/uaccess.h>
30 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
31 MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
32 MODULE_LICENSE("GPL");
34 static unsigned int snd_seq_simple_size(unsigned int size
, unsigned int format
)
36 unsigned int result
= size
;
38 if (format
& SIMPLE_WAVE_16BIT
)
40 if (format
& SIMPLE_WAVE_STEREO
)
45 static void snd_seq_simple_instr_free(snd_simple_ops_t
*ops
,
46 simple_instrument_t
*ip
,
49 if (ops
->remove_sample
)
50 ops
->remove_sample(ops
->private_data
, ip
, atomic
);
53 static int snd_seq_simple_put(void *private_data
, snd_seq_kinstr_t
*instr
,
54 char __user
*instr_data
, long len
,
57 snd_simple_ops_t
*ops
= (snd_simple_ops_t
*)private_data
;
58 simple_instrument_t
*ip
;
59 simple_xinstrument_t ix
;
61 unsigned int real_size
;
63 if (cmd
!= SNDRV_SEQ_INSTR_PUT_CMD_CREATE
)
65 gfp_mask
= atomic
? GFP_ATOMIC
: GFP_KERNEL
;
66 /* copy instrument data */
67 if (len
< (long)sizeof(ix
))
69 if (copy_from_user(&ix
, instr_data
, sizeof(ix
)))
71 if (ix
.stype
!= SIMPLE_STRU_INSTR
)
73 instr_data
+= sizeof(ix
);
75 ip
= (simple_instrument_t
*)KINSTR_DATA(instr
);
76 ip
->share_id
[0] = le32_to_cpu(ix
.share_id
[0]);
77 ip
->share_id
[1] = le32_to_cpu(ix
.share_id
[1]);
78 ip
->share_id
[2] = le32_to_cpu(ix
.share_id
[2]);
79 ip
->share_id
[3] = le32_to_cpu(ix
.share_id
[3]);
80 ip
->format
= le32_to_cpu(ix
.format
);
81 ip
->size
= le32_to_cpu(ix
.size
);
82 ip
->start
= le32_to_cpu(ix
.start
);
83 ip
->loop_start
= le32_to_cpu(ix
.loop_start
);
84 ip
->loop_end
= le32_to_cpu(ix
.loop_end
);
85 ip
->loop_repeat
= le16_to_cpu(ix
.loop_repeat
);
86 ip
->effect1
= ix
.effect1
;
87 ip
->effect1_depth
= ix
.effect1_depth
;
88 ip
->effect2
= ix
.effect2
;
89 ip
->effect2_depth
= ix
.effect2_depth
;
90 real_size
= snd_seq_simple_size(ip
->size
, ip
->format
);
91 if (len
< (long)real_size
)
93 if (ops
->put_sample
) {
94 err
= ops
->put_sample(ops
->private_data
, ip
,
95 instr_data
, real_size
, atomic
);
102 static int snd_seq_simple_get(void *private_data
, snd_seq_kinstr_t
*instr
,
103 char __user
*instr_data
, long len
,
106 snd_simple_ops_t
*ops
= (snd_simple_ops_t
*)private_data
;
107 simple_instrument_t
*ip
;
108 simple_xinstrument_t ix
;
110 unsigned int real_size
;
112 if (cmd
!= SNDRV_SEQ_INSTR_GET_CMD_FULL
)
114 if (len
< (long)sizeof(ix
))
116 memset(&ix
, 0, sizeof(ix
));
117 ip
= (simple_instrument_t
*)KINSTR_DATA(instr
);
118 ix
.stype
= SIMPLE_STRU_INSTR
;
119 ix
.share_id
[0] = cpu_to_le32(ip
->share_id
[0]);
120 ix
.share_id
[1] = cpu_to_le32(ip
->share_id
[1]);
121 ix
.share_id
[2] = cpu_to_le32(ip
->share_id
[2]);
122 ix
.share_id
[3] = cpu_to_le32(ip
->share_id
[3]);
123 ix
.format
= cpu_to_le32(ip
->format
);
124 ix
.size
= cpu_to_le32(ip
->size
);
125 ix
.start
= cpu_to_le32(ip
->start
);
126 ix
.loop_start
= cpu_to_le32(ip
->loop_start
);
127 ix
.loop_end
= cpu_to_le32(ip
->loop_end
);
128 ix
.loop_repeat
= cpu_to_le32(ip
->loop_repeat
);
129 ix
.effect1
= cpu_to_le16(ip
->effect1
);
130 ix
.effect1_depth
= cpu_to_le16(ip
->effect1_depth
);
131 ix
.effect2
= ip
->effect2
;
132 ix
.effect2_depth
= ip
->effect2_depth
;
133 if (copy_to_user(instr_data
, &ix
, sizeof(ix
)))
135 instr_data
+= sizeof(ix
);
137 real_size
= snd_seq_simple_size(ip
->size
, ip
->format
);
138 if (len
< (long)real_size
)
140 if (ops
->get_sample
) {
141 err
= ops
->get_sample(ops
->private_data
, ip
,
142 instr_data
, real_size
, atomic
);
149 static int snd_seq_simple_get_size(void *private_data
, snd_seq_kinstr_t
*instr
,
152 simple_instrument_t
*ip
;
154 ip
= (simple_instrument_t
*)KINSTR_DATA(instr
);
155 *size
= sizeof(simple_xinstrument_t
) + snd_seq_simple_size(ip
->size
, ip
->format
);
159 static int snd_seq_simple_remove(void *private_data
,
160 snd_seq_kinstr_t
*instr
,
163 snd_simple_ops_t
*ops
= (snd_simple_ops_t
*)private_data
;
164 simple_instrument_t
*ip
;
166 ip
= (simple_instrument_t
*)KINSTR_DATA(instr
);
167 snd_seq_simple_instr_free(ops
, ip
, atomic
);
171 static void snd_seq_simple_notify(void *private_data
,
172 snd_seq_kinstr_t
*instr
,
175 snd_simple_ops_t
*ops
= (snd_simple_ops_t
*)private_data
;
178 ops
->notify(ops
->private_data
, instr
, what
);
181 int snd_seq_simple_init(snd_simple_ops_t
*ops
,
183 snd_seq_kinstr_ops_t
*next
)
185 memset(ops
, 0, sizeof(*ops
));
186 ops
->private_data
= private_data
;
187 ops
->kops
.private_data
= ops
;
188 ops
->kops
.add_len
= sizeof(simple_instrument_t
);
189 ops
->kops
.instr_type
= SNDRV_SEQ_INSTR_ID_SIMPLE
;
190 ops
->kops
.put
= snd_seq_simple_put
;
191 ops
->kops
.get
= snd_seq_simple_get
;
192 ops
->kops
.get_size
= snd_seq_simple_get_size
;
193 ops
->kops
.remove
= snd_seq_simple_remove
;
194 ops
->kops
.notify
= snd_seq_simple_notify
;
195 ops
->kops
.next
= next
;
203 static int __init
alsa_ainstr_simple_init(void)
208 static void __exit
alsa_ainstr_simple_exit(void)
212 module_init(alsa_ainstr_simple_init
)
213 module_exit(alsa_ainstr_simple_exit
)
215 EXPORT_SYMBOL(snd_seq_simple_init
);