00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "midiout.h"
00027 #include <unistd.h>
00028 #include <fcntl.h>
00029 #include <stdio.h>
00030 #include "sndcard.h"
00031 #include <errno.h>
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include <sys/param.h>
00035 #include "midispec.h"
00036 #include "alsaout.h"
00037
00038 #ifdef HAVE_CONFIG_H
00039 #include <config.h>
00040 #endif
00041
00042 #include <sys/ioctl.h>
00043
00044 SEQ_USE_EXTBUF();
00045
00046 MidiOut::MidiOut(int d)
00047 {
00048 seqfd = -1;
00049 devicetype=KMID_EXTERNAL_MIDI;
00050 device= d;
00051 volumepercentage=100;
00052 map=new MidiMapper(NULL);
00053 if (map==NULL) { printfdebug("ERROR : midiOut : Map is NULL\n"); return; };
00054 _ok=1;
00055 }
00056
00057 MidiOut::~MidiOut()
00058 {
00059 delete map;
00060 closeDev();
00061 }
00062
00063 void MidiOut::openDev (int sqfd)
00064 {
00065 #ifdef HAVE_OSS_SUPPORT
00066 _ok=1;
00067 seqfd=sqfd;
00068 if (seqfd==-1)
00069 {
00070 printfdebug("ERROR: Could not open /dev/sequencer\n");
00071 _ok=0;
00072 return;
00073 }
00074 #endif
00075 }
00076
00077 void MidiOut::closeDev (void)
00078 {
00079 if (!ok()) return;
00080
00081 SEQ_STOP_TIMER();
00082 SEQ_DUMPBUF();
00083 seqfd=-1;
00084 }
00085
00086 void MidiOut::initDev (void)
00087 {
00088 #ifdef HAVE_OSS_SUPPORT
00089 int chn;
00090 if (!ok()) return;
00091 uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7};
00092 sysex(gm_reset, sizeof(gm_reset));
00093 for (chn=0;chn<16;chn++)
00094 {
00095 chnmute[chn]=0;
00096 chnPatchChange(chn,0);
00097 chnPressure(chn,127);
00098 chnPitchBender(chn, 0x00, 0x40);
00099 chnController(chn, CTL_MAIN_VOLUME,110*volumepercentage);
00100 chnController(chn, CTL_EXT_EFF_DEPTH, 0);
00101 chnController(chn, CTL_CHORUS_DEPTH, 0);
00102 chnController(chn, 0x4a, 127);
00103 }
00104 #endif
00105 }
00106
00107 void MidiOut::setMidiMapper(MidiMapper *_map)
00108 {
00109 delete map;
00110 map=_map;
00111 }
00112
00113 void MidiOut::noteOn (uchar chn, uchar note, uchar vel)
00114 {
00115 if (vel==0)
00116 {
00117 noteOff(chn,note,vel);
00118 }
00119 else
00120 {
00121 SEQ_MIDIOUT(device, MIDI_NOTEON + map->channel(chn));
00122 SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note));
00123 SEQ_MIDIOUT(device, vel);
00124 }
00125 #ifdef MIDIOUTDEBUG
00126 printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
00127 #endif
00128 }
00129
00130 void MidiOut::noteOff (uchar chn, uchar note, uchar vel)
00131 {
00132 SEQ_MIDIOUT(device, MIDI_NOTEOFF + map->channel(chn));
00133 SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note));
00134 SEQ_MIDIOUT(device, vel);
00135 #ifdef MIDIOUTDEBUG
00136 printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
00137 #endif
00138 }
00139
00140 void MidiOut::keyPressure (uchar chn, uchar note, uchar vel)
00141 {
00142 SEQ_MIDIOUT(device, MIDI_KEY_PRESSURE + map->channel(chn));
00143 SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note));
00144 SEQ_MIDIOUT(device, vel);
00145 }
00146
00147 void MidiOut::chnPatchChange (uchar chn, uchar patch)
00148 {
00149 #ifdef MIDIOUTDEBUG
00150 printfdebug("PATCHCHANGE [%d->%d] %d -> %d\n",
00151 chn,map->channel(chn),patch,map->patch(chn,patch));
00152 #endif
00153 SEQ_MIDIOUT(device, MIDI_PGM_CHANGE + map->channel(chn));
00154 SEQ_MIDIOUT(device, map->patch(chn,patch));
00155 chnpatch[chn]=patch;
00156 }
00157
00158 void MidiOut::chnPressure (uchar chn, uchar vel)
00159 {
00160 SEQ_MIDIOUT(device, MIDI_CHN_PRESSURE + map->channel(chn));
00161 SEQ_MIDIOUT(device, vel);
00162
00163 chnpressure[chn]=vel;
00164 }
00165
00166 void MidiOut::chnPitchBender(uchar chn,uchar lsb, uchar msb)
00167 {
00168 SEQ_MIDIOUT(device, MIDI_PITCH_BEND + map->channel(chn));
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 map->pitchBender(chn,lsb,msb);
00181 SEQ_MIDIOUT(device, lsb);
00182 SEQ_MIDIOUT(device, msb);
00183 chnbender[chn]=(msb << 8) | (lsb & 0xFF);
00184 }
00185
00186 void MidiOut::chnController (uchar chn, uchar ctl, uchar v)
00187 {
00188 SEQ_MIDIOUT(device, MIDI_CTL_CHANGE + map->channel(chn));
00189 #ifdef AT_HOME
00190 if (ctl==11) ctl=7;
00191 #endif
00192 map->controller(chn,ctl,v);
00193 if ((ctl==11)||(ctl==7))
00194 {
00195 v=(v*volumepercentage)/100;
00196 if (v>127) v=127;
00197 }
00198
00199 SEQ_MIDIOUT(device, ctl);
00200 SEQ_MIDIOUT(device, v);
00201
00202 chncontroller[chn][ctl]=v;
00203 }
00204
00205 void MidiOut::sysex(uchar *data, ulong size)
00206 {
00207 ulong i=0;
00208 SEQ_MIDIOUT(device, MIDI_SYSTEM_PREFIX);
00209 while (i<size)
00210 {
00211 SEQ_MIDIOUT(device, *data);
00212 data++;
00213 i++;
00214 }
00215 #ifdef MIDIOUTDEBUG
00216 printfdebug("sysex\n");
00217 #endif
00218 }
00219
00220 void MidiOut::allNotesOff (void)
00221 {
00222 for (int i=0; i<16; i++)
00223 {
00224 chnController(i, 0x78, 0);
00225 chnController(i, 0x79, 0);
00226 };
00227 sync(1);
00228 }
00229
00230 void MidiOut::channelSilence (uchar chn)
00231 {
00232 uchar i;
00233 for ( i=0; i<127; i++)
00234 {
00235 noteOff(chn,i,0);
00236 };
00237 sync();
00238 }
00239
00240 void MidiOut::channelMute(uchar chn, int a)
00241 {
00242 if (a==1)
00243 {
00244 chnmute[chn]=a;
00245 channelSilence(chn);
00246 }
00247 else if (a==0)
00248 {
00249 chnmute[chn]=a;
00250 }
00251
00252 }
00253
00254 void MidiOut::seqbuf_dump (void)
00255 {
00256 #ifdef HAVE_OSS_SUPPORT
00257 if (_seqbufptr && seqfd!=-1 && seqfd!=0)
00258 if (write (seqfd, _seqbuf, _seqbufptr) == -1)
00259 {
00260 printfdebug("Error writing to /dev/sequencer in MidiOut::seq_buf_dump\n");
00261 perror ("write /dev/sequencer in seqBufDump\n");
00262 exit (-1);
00263 }
00264 _seqbufptr = 0;
00265 #endif
00266 }
00267
00268 void MidiOut::seqbuf_clean(void)
00269 {
00270 #ifdef HAVE_OSS_SUPPORT
00271 _seqbufptr=0;
00272 #endif
00273 }
00274
00275 const char *MidiOut::midiMapFilename(void)
00276 {
00277 return (map!=NULL) ? map->filename() : "";
00278 }
00279
00280 const char * MidiOut::deviceName(void) const
00281 {
00282 switch (deviceType())
00283 {
00284 case (KMID_EXTERNAL_MIDI) : return "External Midi";
00285 case (KMID_SYNTH) : return "Synth";
00286 case (KMID_FM) : return "FM";
00287 case (KMID_GUS) : return "GUS";
00288 case (KMID_AWE) : return "AWE";
00289 case (KMID_ALSA) : return reinterpret_cast<const AlsaOut *>(this)->deviceName();
00290 }
00291 return "Unknown";
00292 }
00293
00294 void MidiOut::sync(int i)
00295 {
00296 if (deviceType()==KMID_ALSA) {
00297 reinterpret_cast<AlsaOut *>(this)->sync(i);
00298 return;
00299 }
00300 SEQ_DUMPBUF();
00301 }