You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

501 lines
12KB

  1. /*
  2. * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "Midi.h"
  19. #include "NoteTable.h"
  20. #include "unistd.h"
  21. #include "sys/types.h"
  22. #include "signal.h"
  23. #include "pthread.h"
  24. static const int MIDI_SCANBUFSIZE=256;
  25. static const int MIDI_KEYOFFSET=0;
  26. static const unsigned char STATUS_START = 0x80;
  27. static const unsigned char STATUS_NOTE_OFF = 0x80;
  28. static const unsigned char STATUS_NOTE_ON = 0x90;
  29. static const unsigned char STATUS_AFTERTOUCH = 0xa0;
  30. static const unsigned char STATUS_CONTROL_CHANGE = 0xb0;
  31. static const unsigned char STATUS_PROG_CHANGE = 0xc0;
  32. static const unsigned char STATUS_CHANNEL_PRESSURE = 0xd0;
  33. static const unsigned char STATUS_PITCH_WHEEL = 0xe0;
  34. static const unsigned char STATUS_END = 0xf0;
  35. static const unsigned char SYSEX_START = 0xf0;
  36. static const unsigned char SYSEX_TERMINATOR = 0xf7;
  37. static const unsigned char MIDI_CLOCK = 0xf8;
  38. static const unsigned char ACTIVE_SENSE = 0xfe;
  39. static int NKEYS = 30;
  40. MidiDevice *MidiDevice::m_Singleton;
  41. string MidiDevice::m_DeviceName;
  42. #if __APPLE__
  43. #define read AppleRead
  44. #endif
  45. MidiDevice::MidiDevice() :
  46. m_Poly(1)
  47. {
  48. #ifdef ALSA_MIDI
  49. seq_handle=AlsaOpen();
  50. #else
  51. Open();
  52. #endif
  53. #ifdef KEYBOARD_SUPPORT
  54. m_Oct=4;
  55. m_CurrentVoice=0;
  56. for (int n=0; n<256; n++)
  57. {
  58. m_KeyVoice[n]=' ';
  59. }
  60. #endif
  61. }
  62. MidiDevice::~MidiDevice()
  63. {
  64. #ifdef ALSA_MIDI
  65. snd_seq_close (seq_handle);
  66. #else
  67. Close();
  68. #endif
  69. }
  70. void MidiDevice::Close()
  71. {
  72. #if __APPLE__
  73. AppleClose();
  74. #else
  75. pthread_mutex_lock(m_Mutex);
  76. pthread_cancel(m_MidiReader);
  77. pthread_mutex_unlock(m_Mutex);
  78. pthread_mutex_destroy(m_Mutex);
  79. close(m_MidiFd);
  80. close(m_MidiWrFd);
  81. cerr<<"Closed midi device"<<endl;
  82. #endif // !__APPLE__
  83. }
  84. void MidiDevice::Open()
  85. {
  86. #if __APPLE__
  87. AppleOpen();
  88. #else
  89. //if (!SpiralInfo::WANTMIDI) return;
  90. m_MidiFd = open(m_DeviceName.c_str(),O_RDONLY|O_SYNC);
  91. if (!m_MidiFd)
  92. {
  93. cerr<<"Couldn't open midi for reading ["<<m_DeviceName<<"]"<<endl;
  94. return;
  95. }
  96. m_MidiWrFd = open(m_DeviceName.c_str(),O_WRONLY);
  97. if (!m_MidiWrFd)
  98. {
  99. cerr<<"Couldn't open midi for writing ["<<m_DeviceName<<"]"<<endl;
  100. return;
  101. }
  102. cerr<<"Opened midi device ["<<m_DeviceName<<"]"<<endl;
  103. #endif // !__APPLE__
  104. m_Mutex = new pthread_mutex_t;
  105. pthread_mutex_init(m_Mutex, NULL);
  106. int ret=pthread_create(&m_MidiReader,NULL,(void*(*)(void*))MidiDevice::MidiReaderCallback,(void*)this);
  107. }
  108. // returns the next event off the list, or an
  109. // empty event if the list is exhausted
  110. MidiEvent MidiDevice::GetEvent(int Device)
  111. {
  112. if (Device<0 || Device>15)
  113. {
  114. cerr<<"GetEvent: Invalid Midi device "<<Device<<endl;
  115. return MidiEvent(MidiEvent::NONE,0,0);
  116. }
  117. #ifdef ALSA_MIDI
  118. AlsaCallback();
  119. if (m_EventVec[Device].size()==0)
  120. {
  121. return MidiEvent(MidiEvent::NONE,0,0);
  122. }
  123. MidiEvent event(m_EventVec[Device].front());
  124. m_EventVec[Device].pop();
  125. #else
  126. pthread_mutex_lock(m_Mutex);
  127. if (m_EventVec[Device].size()==0)
  128. {
  129. pthread_mutex_unlock(m_Mutex);
  130. return MidiEvent(MidiEvent::NONE,0,0);
  131. }
  132. MidiEvent event(m_EventVec[Device].front());
  133. m_EventVec[Device].pop();
  134. pthread_mutex_unlock(m_Mutex);
  135. #endif
  136. return event;
  137. }
  138. void MidiDevice::SendEvent(int Device,const MidiEvent &Event)
  139. {
  140. #ifndef ALSA_MIDI
  141. if (Device<0 || Device>15)
  142. {
  143. cerr<<"SendEvent: Invalid Midi device "<<Device<<endl;
  144. }
  145. char message[3];
  146. message[1]=Event.GetNote()+MIDI_KEYOFFSET;
  147. message[2]=(char)Event.GetVolume();
  148. if (Event.GetType()==MidiEvent::ON)
  149. {
  150. message[0]=STATUS_NOTE_ON+Device;
  151. write(m_MidiWrFd,message,3);
  152. //cerr<<"sending "<<message<<endl;
  153. }
  154. if (Event.GetType()==MidiEvent::OFF)
  155. {
  156. message[0]=STATUS_NOTE_OFF+Device;
  157. write(m_MidiWrFd,message,3);
  158. //cerr<<"sending "<<message<<endl;
  159. }
  160. #endif
  161. }
  162. /////////////////////////////////////////////////////////////////////////////////
  163. // Reader thread functions
  164. // little helper to strip out the realtime and unused messages
  165. void MidiDevice::ReadByte(unsigned char *c)
  166. {
  167. *c=MIDI_CLOCK;
  168. do read(m_MidiFd,c,1);
  169. while (*c>=STATUS_END);
  170. }
  171. // collect events deals with the byte level messages, and sorts
  172. // and filters them into distinct messages we can handle easily
  173. void MidiDevice::CollectEvents()
  174. {
  175. unsigned char buf[1];
  176. int count,n,nn;
  177. bool MessageSent;
  178. unsigned char data[3],last=0;
  179. // constantly scan for relevent input,
  180. // and write it to the pipe
  181. // filters out unhandled messages, and attempts to build
  182. // coherent messages to send to the midi handler
  183. bool InSysex=false;
  184. for(;;)
  185. {
  186. ReadByte(buf);
  187. if (*buf>=STATUS_START) // we've got a status byte
  188. {
  189. if (*buf==SYSEX_TERMINATOR) InSysex=false;
  190. // find out if it's an opcode
  191. if(*buf>=STATUS_START && *buf<=STATUS_END)
  192. {
  193. InSysex=false;
  194. last=data[0]=*buf;
  195. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  196. {
  197. ReadByte(&data[1]); //one byte
  198. data[2]=0;
  199. }
  200. else // get the next two bytes
  201. {
  202. ReadByte(&data[1]);
  203. ReadByte(&data[2]);
  204. }
  205. AddEvent(data);
  206. }
  207. else // its a sysex or other message like active sense
  208. {
  209. if (*buf==SYSEX_START) InSysex=true;
  210. cerr<<"Unhandled midi message: "; printf("%x\n",(int)*buf);
  211. }
  212. }
  213. else // more data (running status)
  214. {
  215. if (!InSysex)
  216. {
  217. data[0]=last;
  218. data[1]=*buf;
  219. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  220. {
  221. data[2]=0; //one byte
  222. }
  223. else // get the next byte
  224. {
  225. ReadByte(&data[2]);
  226. }
  227. AddEvent(data);
  228. }
  229. }
  230. }
  231. }
  232. // addevent converts the midi bytecode into midi message objects and
  233. // stacks them onto the event list to be picked up by the app
  234. void MidiDevice::AddEvent(unsigned char* midi)
  235. {
  236. MidiEvent::type MessageType=MidiEvent::NONE;
  237. int Volume=0,Note=0,EventDevice=0;
  238. // note off
  239. if (midi[0] >= STATUS_NOTE_OFF && midi[0] < STATUS_NOTE_ON)
  240. {
  241. MessageType=MidiEvent::OFF;
  242. Note=midi[1]-MIDI_KEYOFFSET;
  243. EventDevice=midi[0]-STATUS_NOTE_OFF;
  244. }
  245. // note on
  246. else if (midi[0] >= STATUS_NOTE_ON && midi[0] < STATUS_AFTERTOUCH)
  247. {
  248. Volume = midi[2];
  249. // cope with Roland equipment, where note on's
  250. // with zero velocity are sent as note offs.
  251. if (Volume) MessageType=MidiEvent::ON;
  252. else MessageType=MidiEvent::OFF;
  253. Note=midi[1]-MIDI_KEYOFFSET;
  254. EventDevice=midi[0]-STATUS_NOTE_ON;
  255. }
  256. // aftertouch
  257. else if (midi[0] >= STATUS_AFTERTOUCH && midi[0] < STATUS_CONTROL_CHANGE)
  258. {
  259. MessageType=MidiEvent::AFTERTOUCH;
  260. Note=midi[1]-MIDI_KEYOFFSET;
  261. Volume=midi[2];
  262. EventDevice=midi[0]-STATUS_AFTERTOUCH;
  263. }
  264. // parameter
  265. else if (midi[0] >= STATUS_CONTROL_CHANGE && midi[0] < STATUS_PROG_CHANGE)
  266. {
  267. MessageType=MidiEvent::PARAMETER;
  268. Note=midi[1];
  269. Volume=midi[2];
  270. EventDevice=midi[0]-STATUS_CONTROL_CHANGE;
  271. }
  272. // channel pressure
  273. else if (midi[0] >= STATUS_CHANNEL_PRESSURE && midi[0] < STATUS_PITCH_WHEEL)
  274. {
  275. MessageType=MidiEvent::CHANNELPRESSURE;
  276. Volume=midi[1];
  277. EventDevice=midi[0]-STATUS_CHANNEL_PRESSURE;
  278. }
  279. // note pitchbend
  280. else if (midi[0] >= STATUS_PITCH_WHEEL && midi[0] < STATUS_END)
  281. {
  282. MessageType=MidiEvent::PITCHBEND;
  283. // should probably take the first byte into account too?
  284. Volume=midi[2];
  285. EventDevice=midi[0]-STATUS_PITCH_WHEEL;
  286. }
  287. if (EventDevice<0 || EventDevice>15)
  288. {
  289. cerr<<"Error - Midi device "<<EventDevice<<" ??"<<endl;
  290. return;
  291. }
  292. pthread_mutex_lock(m_Mutex);
  293. m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
  294. pthread_mutex_unlock(m_Mutex);
  295. }
  296. ///////////////////////////////////////////////////////////////////////////////
  297. #ifdef ALSA_MIDI
  298. // code taken and modified from jack_miniFMsynth
  299. int MidiDevice::AlsaCallback()
  300. {
  301. snd_seq_event_t *ev;
  302. int l1;
  303. MidiEvent::type MessageType=MidiEvent::NONE;
  304. int Volume=0,Note=0,EventDevice=0;
  305. do {
  306. snd_seq_event_input(seq_handle, &ev);
  307. if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0))
  308. {
  309. ev->type = SND_SEQ_EVENT_NOTEOFF;
  310. }
  311. switch (ev->type) {
  312. case SND_SEQ_EVENT_PITCHBEND:
  313. MessageType=MidiEvent::CHANNELPRESSURE;
  314. Volume = (char)((ev->data.control.value / 8192.0)*256);
  315. break;
  316. case SND_SEQ_EVENT_CONTROLLER:
  317. MessageType=MidiEvent::PARAMETER;
  318. Note = ev->data.control.param;
  319. Volume = ev->data.control.value;
  320. break;
  321. case SND_SEQ_EVENT_NOTEON:
  322. MessageType=MidiEvent::ON;
  323. EventDevice = ev->data.control.channel;
  324. Note = ev->data.note.note;
  325. Volume = ev->data.note.velocity;
  326. break;
  327. case SND_SEQ_EVENT_NOTEOFF:
  328. MessageType=MidiEvent::ON;
  329. EventDevice = ev->data.control.channel;
  330. Note = ev->data.note.note;
  331. break;
  332. }
  333. m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
  334. snd_seq_free_event(ev);
  335. } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
  336. return (0);
  337. }
  338. snd_seq_t *MidiDevice::AlsaOpen()
  339. {
  340. snd_seq_t *seq_handle;
  341. int client_id, port_id;
  342. if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
  343. fprintf(stderr, "Error opening ALSA sequencer.\n");
  344. exit(1);
  345. }
  346. snd_seq_set_client_name(seq_handle, "spiralmodular");
  347. client_id = snd_seq_client_id(seq_handle);
  348. if ((port_id = snd_seq_create_simple_port(seq_handle, "spiralmodular",
  349. SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
  350. SND_SEQ_PORT_TYPE_APPLICATION) < 0)) {
  351. fprintf(stderr, "Error creating sequencer port.\n");
  352. }
  353. return(seq_handle);
  354. }
  355. #endif
  356. #if __APPLE__
  357. void MidiDevice::AppleOpen()
  358. {
  359. m_ReadFillIndex = m_ReadReadIndex = 0;
  360. OSStatus err = 0;
  361. mMIDISource = NULL;
  362. mMIDIClient = NULL;
  363. mMIDIDestination = NULL;
  364. err = MIDIClientCreate(CFSTR("org.pawpal.ssm"), NULL, NULL, &mMIDIClient);
  365. if (err) printf("MIDIClientCreate failed returned %d\n", err);
  366. if (!err) {
  367. err = MIDISourceCreate(mMIDIClient, CFSTR("SpiralSynth"), &mMIDISource);
  368. if (err) printf("MIDIInputPortCreate failed returned %d\n", err);
  369. }
  370. if (!err) {
  371. err = MIDIDestinationCreate(mMIDIClient, CFSTR("SpiralSynth"), sMIDIRead, this, &mMIDIDestination);
  372. MIDIObjectSetIntegerProperty(mMIDIDestination, kMIDIPropertyUniqueID, 'SSmP');
  373. }
  374. }
  375. void MidiDevice::AppleClose()
  376. {
  377. if (mMIDIDestination)
  378. MIDIEndpointDispose(mMIDIDestination);
  379. if (mMIDISource)
  380. MIDIEndpointDispose(mMIDISource);
  381. mMIDISource = NULL;
  382. if (mMIDIClient)
  383. MIDIClientDispose(mMIDIClient);
  384. mMIDIClient = NULL;
  385. }
  386. int MidiDevice::AppleWrite(int dummy, unsigned char *outbuffer, int maxlen)
  387. {
  388. return 0;
  389. }
  390. int MidiDevice::AppleRead(int dummy, unsigned char *outbuffer, int maxlen)
  391. {
  392. if (!mMIDIClient)
  393. return -1;
  394. int len = 0;
  395. do {
  396. while (m_ReadReadIndex == m_ReadFillIndex)
  397. usleep(1000); // 1ms
  398. int readl = m_ReadFillIndex - m_ReadReadIndex;
  399. if (readl < 0)
  400. readl += midi_ReadSize; // wrapped
  401. while (len < maxlen && readl-- > 0) {
  402. int r = m_ReadReadIndex;
  403. outbuffer[len++] = m_ReadBuffer[r];
  404. r++;
  405. m_ReadReadIndex = r % midi_ReadSize;
  406. }
  407. } while (len < maxlen);
  408. return len;
  409. }
  410. void MidiDevice::sMIDIRead(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
  411. {
  412. MidiDevice & t = *((MidiDevice*)readProcRefCon);
  413. const MIDIPacket *packet = &pktlist->packet[0];
  414. for (int i = 0; i < (int)pktlist->numPackets; i++) {
  415. const MIDIPacket & p = *packet;
  416. for (int b = 0; b < p.length; b++) {
  417. // printf("%02x ", p.data[b]);
  418. int d = t.m_ReadFillIndex;
  419. t.m_ReadBuffer[d] = p.data[b];
  420. d++;
  421. t.m_ReadFillIndex = d % midi_ReadSize;
  422. }
  423. // printf("\n");
  424. packet = MIDIPacketNext(packet);
  425. }
  426. }
  427. #endif