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.

513 lines
13KB

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