source: GPL/branches/uniaud32-next/lib32/soundmidi.c@ 655

Last change on this file since 655 was 655, checked in by Paul Smedley, 5 years ago

Code cleanups from AlexT

File size: 12.4 KB
Line 
1/* $Id: soundmidi.c,v 1.1.1.1 2003/07/02 13:57:02 eleph Exp $ */
2/*
3 * MMPM/2 to OSS interface translation layer
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21 * USA.
22 *
23 */
24
25#include <sound/core.h>
26#include <sound/control.h>
27#include <sound/info.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/minors.h>
31#include <sound/asequencer.h>
32#include <sound/seqmid.h>
33#include <sound/seq_kernel.h>
34#include <linux/file.h>
35#include <linux/soundcard.h>
36
37#define LINUX
38#include <ossidc32.h>
39#include <stacktoflat.h>
40#include <stdlib.h>
41#include "soundoss.h"
42
43int midi_port = 0;
44
45//******************************************************************************
46//******************************************************************************
47OSSRET OSS32_MidiOpen(ULONG deviceid, ULONG streamtype, OSSSTREAMID *pStreamId)
48{
49 midihandle *pHandle;
50 int ret, i;
51 struct snd_seq_port_subscribe subs;
52 struct snd_seq_client_info clientinfo;
53 struct snd_seq_port_info portinfo;
54
55 *pStreamId = 0;
56
57 if(alsa_fops == NULL) {
58 DebugInt3();
59 return OSSERR_NO_DEVICE_AVAILABLE;
60 }
61
62 pHandle = kmalloc(sizeof(midihandle), GFP_KERNEL);
63 if(pHandle == NULL) {
64 DebugInt3();
65 return OSSERR_OUT_OF_MEMORY;
66 }
67 memset(pHandle, 0, sizeof(midihandle));
68
69 //set operation to non-blocking
70 pHandle->file.f_flags = O_NONBLOCK;
71
72 //setup pointers in file structure (used internally by ALSA)
73 pHandle->file.f_dentry = &pHandle->d_entry;
74 pHandle->file.f_dentry->d_inode = &pHandle->inode;
75
76 switch(streamtype) {
77 case OSS32_STREAM_MPU401_MIDIOUT:
78 dprintf(("OSS32_STREAM_MPU401_MIDIOUT"));
79 pHandle->file.f_mode = FMODE_WRITE;
80 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_RAWMIDI);
81 pHandle->inode.i_rdev |= (CONFIG_SND_MAJOR << 8);
82 break;
83 case OSS32_STREAM_MPU401_MIDIIN:
84 dprintf(("OSS32_STREAM_MPU401_MIDIIN"));
85 pHandle->file.f_mode = FMODE_READ;
86 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_RAWMIDI);
87 pHandle->inode.i_rdev |= (CONFIG_SND_MAJOR << 8);
88 break;
89 case OSS32_STREAM_FM_MIDIOUT:
90 dprintf(("OSS32_STREAM_FM_MIDIOUT"));
91 pHandle->file.f_mode = FMODE_WRITE;
92 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_SEQUENCER);
93 break;
94 case OSS32_STREAM_WAVETABLE_MIDIOUT:
95 dprintf(("OSS32_STREAM_WAVETABLE_MIDIOUT: TODO"));
96 pHandle->file.f_mode = FMODE_WRITE;
97 pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_SEQUENCER);
98 kfree(pHandle);
99 return OSSERR_INVALID_PARAMETER;
100 break;
101 default:
102 DebugInt3();
103 kfree(pHandle);
104 return OSSERR_INVALID_PARAMETER;
105 }
106#if 1
107
108 ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
109 if(ret) {
110 rprintf(("Midi Open %d failed with error %d", streamtype, ret));
111 kfree(pHandle);
112 return UNIXToOSSError(ret);
113 }
114 pHandle->magic = MAGIC_MIDI_ALSA32;
115 *pStreamId = (ULONG)pHandle;
116
117 pHandle->state |= MIDISTATE_OPENED;
118 dprintf(("Opened MIDI %x\n",(ULONG)pHandle));
119 if(streamtype == OSS32_STREAM_FM_MIDIOUT)
120 {
121 //get the client id
122 ret = pHandle->file.f_op->unlocked_ioctl(&pHandle->file, SNDRV_SEQ_IOCTL_CLIENT_ID, (ULONG)&pHandle->clientid);
123 if(ret) {
124 rprintf(("Get client id failed with error %d", ret));
125 kfree(pHandle);
126 return UNIXToOSSError(ret);
127 }
128
129 //find the FM device
130 for(i=64;i<64+((deviceid+1)<<3);i++)
131 {
132 memset(&clientinfo, 0, sizeof(clientinfo));
133 clientinfo.client = i;
134 clientinfo.type = KERNEL_CLIENT;
135 ret = pHandle->file.f_op->unlocked_ioctl(&pHandle->file, SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, (ULONG)&clientinfo);
136 if(ret) {
137 continue;
138 }
139 if(!strcmp(clientinfo.name, "OPL3 FM synth")) {
140 //found the FM synth device
141 break;
142 }
143 }
144 if(i == 64+((deviceid+1)<<3)) {
145 rprintf(("Couldn't find OPL3 device"));
146 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
147 kfree(pHandle);
148 *pStreamId = 0;
149 return OSSERR_NO_DEVICE_AVAILABLE;
150 }
151 pHandle->destclient = i;
152 pHandle->destport = 0;
153
154 //create client port
155 memset(&portinfo, 0, sizeof(portinfo));
156 strcpy(portinfo.name, "Unamed port");
157 portinfo.addr.client = pHandle->clientid;
158 portinfo.flags = SNDRV_SEQ_PORT_TYPE_APPLICATION;
159 ret = pHandle->file.f_op->unlocked_ioctl(&pHandle->file, SNDRV_SEQ_IOCTL_CREATE_PORT, (ULONG)&portinfo);
160 if(ret) {
161 rprintf(("subscribe error %d", ret));
162 kfree(pHandle);
163 return UNIXToOSSError(ret);
164 }
165 pHandle->clientport = portinfo.addr.port;
166 pHandle->state |= MIDISTATE_PORTCREATED;
167
168 //subscribe to FM device port
169 memset(&subs, 0, sizeof(subs));
170 subs.dest.client = pHandle->destclient;
171 subs.dest.port = pHandle->destport;
172 subs.sender.client = pHandle->clientid;
173 subs.sender.port = pHandle->clientport;
174 ret = pHandle->file.f_op->unlocked_ioctl(&pHandle->file, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, (ULONG)&subs);
175 if(ret) {
176 rprintf(("subscribe error %d", ret));
177 kfree(pHandle);
178 return UNIXToOSSError(ret);
179 }
180 pHandle->state |= MIDISTATE_SUBSCRIBED;
181
182#if 0
183 //Load FM instruments (only done once)
184 OSS32_FMMidiLoadInstruments((ULONG)pHandle);
185#endif
186
187 }//if FM
188#endif
189 return OSSERR_SUCCESS;
190}
191//******************************************************************************
192//******************************************************************************
193OSSRET OSS32_MidiClose(OSSSTREAMID streamid)
194{
195 midihandle *pHandle = (midihandle *)streamid;
196 int ret;
197
198 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
199 DebugInt3();
200 return OSSERR_INVALID_STREAMID;
201 }
202 dprintf(("Closing MIDI %x\n",(ULONG)streamid));
203
204 //set operation to non-blocking
205 pHandle->file.f_flags = O_NONBLOCK;
206 //unsubscribe
207 if(pHandle->state & MIDISTATE_SUBSCRIBED) {
208 struct snd_seq_port_subscribe subs;
209 memset(&subs, 0, sizeof(subs));
210 subs.dest.client = pHandle->destclient;
211 subs.dest.port = pHandle->destport;
212 subs.sender.client = pHandle->clientid;
213 subs.sender.port = pHandle->clientport;
214 ret = pHandle->file.f_op->unlocked_ioctl(&pHandle->file, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, (ULONG)&subs);
215 if(ret) {
216 rprintf(("unsubscribe error %d", ret));
217 DebugInt3();
218 }
219 }
220
221 //delete port
222 if(pHandle->state & MIDISTATE_SUBSCRIBED) {
223 struct snd_seq_port_info portinfo;
224
225 memset(&portinfo, 0, sizeof(portinfo));
226 strcpy(portinfo.name, "Unamed port");
227 portinfo.addr.client = pHandle->clientid;
228 portinfo.addr.port = pHandle->clientport;
229 ret = pHandle->file.f_op->unlocked_ioctl(&pHandle->file, SNDRV_SEQ_IOCTL_DELETE_PORT, (ULONG)&portinfo);
230 if(ret) {
231 dprintf(("delete port error %d", ret));
232 DebugInt3();
233 }
234 }
235 //and release device
236 ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
237 kfree(pHandle); //free handle data
238
239 if(ret) {
240 DebugInt3();
241 return UNIXToOSSError(ret);
242 }
243
244 return OSSERR_SUCCESS;
245}
246//******************************************************************************
247//******************************************************************************
248OSSRET OSS32_MidiWrite(OSSSTREAMID streamid, ULONG midiByte)
249{
250 dprintf(("MIDI write %x\n",(ULONG)streamid));
251 return OSSERR_INVALID_STREAMID;
252}
253//******************************************************************************
254//******************************************************************************
255OSSRET OSS32_MidiRead(OSSSTREAMID streamid, char *buffer, ULONG bufsize, ULONG *pTransferred)
256{
257 midihandle *pHandle = (midihandle *)streamid;
258 int ret;
259
260 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
261 DebugInt3();
262 return OSSERR_INVALID_STREAMID;
263 }
264 //set operation to non-blocking
265 pHandle->file.f_flags = O_NONBLOCK;
266 //and release device
267 ret = pHandle->file.f_op->read(&pHandle->file,(char*)buffer, bufsize, &pHandle->file.f_pos);
268 kfree(pHandle); //free handle data
269 if (ret > 0)
270 {
271 dprintf(("MIDI read %i bytes from %x. first byte is: %x\n",ret, (ULONG)streamid, (char*)buffer[0]));
272 *pTransferred = ret;
273 return OSSERR_SUCCESS;
274 }
275 return UNIXToOSSError(ret);
276}
277//******************************************************************************
278//******************************************************************************
279OSSRET OSS32_MidiQueryCaps(OSSSTREAMID streamid, POSS32_MIDICAPS pCaps)
280{
281 dprintf(("MIDI query caps %x\n",(ULONG)streamid));
282 return OSSERR_INVALID_STREAMID;
283}
284//******************************************************************************
285//******************************************************************************
286OSSRET OSS32_MidiCommand(OSSSTREAMID streamid, ULONG Cmd, BYTE channel, BYTE param1, BYTE param2)
287{
288 midihandle *pHandle = (midihandle *)streamid;
289 //int ret;
290 LONG transferred;
291 struct snd_seq_event fmevent;
292
293 if(pHandle == NULL || pHandle->magic != MAGIC_MIDI_ALSA32) {
294 DebugInt3();
295 return OSSERR_INVALID_STREAMID;
296 }
297 dprintf(("MIDI command %x\n",(ULONG)streamid));
298
299 //set operation to non-blocking
300 pHandle->file.f_flags = O_NONBLOCK;
301
302 memset(&fmevent, 0, sizeof(fmevent));
303 switch(Cmd) {
304 case IDC32_MIDI_NOTEON:
305 snd_seq_ev_set_noteon((&fmevent), channel, param1, param2);
306 break;
307 case IDC32_MIDI_NOTEOFF:
308 snd_seq_ev_set_noteoff((&fmevent), channel, param1, param2);
309 break;
310 case IDC32_MIDI_KEY_PRESSURE:
311 snd_seq_ev_set_keypress((&fmevent), channel, param1, param2);
312 break;
313 case IDC32_MIDI_CONTROL_CHANGE:
314 snd_seq_ev_set_controller((&fmevent), channel, param1, param2);
315 break;
316 case IDC32_MIDI_PROGRAM_CHANGE:
317 snd_seq_ev_set_pgmchange((&fmevent), channel, param1);
318 break;
319 case IDC32_MIDI_CHANNEL_PRESSURE:
320 snd_seq_ev_set_chanpress((&fmevent), channel, param1);
321 break;
322 case IDC32_MIDI_PITCH_BEND:
323 snd_seq_ev_set_pitchbend((&fmevent), channel, param1);
324 break;
325 }
326 fmevent.tag = 0;
327 fmevent.queue = SNDRV_SEQ_QUEUE_DIRECT;
328 fmevent.source.client = pHandle->clientid;
329 fmevent.source.port = pHandle->clientport;
330 fmevent.dest.client = pHandle->destclient;
331 fmevent.dest.port = pHandle->destport;
332
333 transferred = pHandle->file.f_op->write(&pHandle->file, (char *)&fmevent, sizeof(fmevent), &pHandle->file.f_pos);
334
335 if(transferred < 0) {
336 rprintf(("OSS32_MidiNoteOn failed!!"));
337 DebugInt3();
338 return UNIXToOSSError(transferred);
339 }
340 return OSSERR_SUCCESS;
341}
342//******************************************************************************
343//******************************************************************************
344
Note: See TracBrowser for help on using the repository browser.