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.

595 lines
16KB

  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 "unistd.h"
  20. #include "sys/types.h"
  21. #include "signal.h"
  22. #include "pthread.h"
  23. static const int MIDI_SCANBUFSIZE=256;
  24. static const int MIDI_KEYOFFSET=0;
  25. static const unsigned char STATUS_START = 0x80;
  26. static const unsigned char STATUS_NOTE_OFF = 0x80;
  27. static const unsigned char STATUS_NOTE_ON = 0x90;
  28. static const unsigned char STATUS_AFTERTOUCH = 0xa0;
  29. static const unsigned char STATUS_CONTROL_CHANGE = 0xb0;
  30. static const unsigned char STATUS_PROG_CHANGE = 0xc0;
  31. static const unsigned char STATUS_CHANNEL_PRESSURE = 0xd0;
  32. static const unsigned char STATUS_PITCH_WHEEL = 0xe0;
  33. static const unsigned char STATUS_END = 0xf0;
  34. static const unsigned char SYSEX_START = 0xf0;
  35. static const unsigned char SYSEX_TERMINATOR = 0xf7;
  36. static const unsigned char MIDI_CLOCK = 0xf8;
  37. static const unsigned char ACTIVE_SENSE = 0xfe;
  38. static int NKEYS = 30;
  39. MidiDevice *MidiDevice::m_Singleton;
  40. string MidiDevice::m_AppName;
  41. #if __APPLE__
  42. #define read AppleRead
  43. #endif
  44. #ifdef USE_OSS_MIDI
  45. string MidiDevice::m_DeviceName;
  46. #endif
  47. void MidiDevice::Init(const string &name, Type t)
  48. {
  49. if (!m_Singleton)
  50. {
  51. m_AppName=name;
  52. m_Singleton=new MidiDevice(t);
  53. }
  54. }
  55. MidiDevice::MidiDevice(Type t) :
  56. m_Poly (1),
  57. m_Clock (1.0f),
  58. m_ClockCount (0)
  59. {
  60. #if __APPLE__
  61. AppleOpen();
  62. #endif
  63. #ifdef USE_ALSA_MIDI
  64. AlsaOpen();
  65. #endif
  66. #ifdef USE_OSS_MIDI
  67. if (!OssOpen()) return;
  68. #endif
  69. m_Mutex = new pthread_mutex_t;
  70. pthread_mutex_init (m_Mutex, NULL);
  71. pthread_create (&m_MidiReader, NULL, (void*(*)(void*))MidiDevice::MidiReaderCallback, (void*)this);
  72. }
  73. MidiDevice::~MidiDevice() {
  74. pthread_mutex_lock (m_Mutex);
  75. pthread_cancel (m_MidiReader);
  76. pthread_mutex_unlock (m_Mutex);
  77. pthread_mutex_destroy (m_Mutex);
  78. #if __APPLE__
  79. AppleClose();
  80. #endif
  81. #ifdef USE_ALSA_MIDI
  82. AlsaClose();
  83. #endif
  84. #ifdef USE_OSS_MIDI
  85. OssClose();
  86. #endif
  87. }
  88. // returns the next event off the list, or an
  89. // empty event if the list is exhausted
  90. MidiEvent MidiDevice::GetEvent(int Device)
  91. {
  92. if (Device<0 || Device>15)
  93. {
  94. cerr<<"GetEvent: Invalid Midi device "<<Device<<endl;
  95. return MidiEvent(MidiEvent::NONE,0,0);
  96. }
  97. pthread_mutex_lock(m_Mutex);
  98. if (m_EventVec[Device].size()==0)
  99. {
  100. pthread_mutex_unlock(m_Mutex);
  101. return MidiEvent(MidiEvent::NONE,0,0);
  102. }
  103. MidiEvent event(m_EventVec[Device].front());
  104. m_EventVec[Device].pop();
  105. pthread_mutex_unlock(m_Mutex);
  106. return event;
  107. }
  108. void MidiDevice::SendEvent (int Device, const MidiEvent &Event) {
  109. #ifdef USE_ALSA_MIDI
  110. AlsaSendEvent (Device, Event);
  111. #else
  112. if (Device<0 || Device>15)
  113. {
  114. cerr<<"SendEvent: Invalid Midi device "<<Device<<endl;
  115. }
  116. char message[3];
  117. message[1]=Event.GetNote()+MIDI_KEYOFFSET;
  118. message[2]=(char)Event.GetVolume();
  119. if (Event.GetType()==MidiEvent::ON)
  120. {
  121. message[0]=STATUS_NOTE_ON+Device;
  122. write(m_MidiWrFd,message,3);
  123. //cerr<<"sending "<<message<<endl;
  124. }
  125. if (Event.GetType()==MidiEvent::OFF)
  126. {
  127. message[0]=STATUS_NOTE_OFF+Device;
  128. write(m_MidiWrFd,message,3);
  129. //cerr<<"sending "<<message<<endl;
  130. }
  131. #endif
  132. }
  133. //////////////////////////////////////////// Oss Code Only ////////////////////////////////////////
  134. #ifdef USE_OSS_MIDI
  135. bool MidiDevice::OssOpen() {
  136. //if (!SpiralInfo::WANTMIDI) return;
  137. m_MidiFd = open (m_DeviceName.c_str(), O_RDONLY | O_SYNC);
  138. if (!m_MidiFd) {
  139. cerr << "Couldn't open midi for reading [" << m_DeviceName << "]" << endl;
  140. return false;
  141. }
  142. m_MidiWrFd = open (m_DeviceName.c_str(), O_WRONLY);
  143. if (!m_MidiWrFd) {
  144. cerr << "Couldn't open midi for writing [" << m_DeviceName << "]" << endl;
  145. return false;
  146. }
  147. cerr << "Opened midi device [" << m_DeviceName << "]" << endl;
  148. return true;
  149. }
  150. void MidiDevice::OssClose() {
  151. close(m_MidiFd);
  152. close(m_MidiWrFd);
  153. cerr<<"Closed midi device"<<endl;
  154. }
  155. // little helper to strip out the realtime and unused messages
  156. void MidiDevice::OssReadByte(unsigned char *c)
  157. {
  158. *c=ACTIVE_SENSE;
  159. do read(m_MidiFd,c,1);
  160. while (*c>=STATUS_END && *c!=MIDI_CLOCK);
  161. }
  162. // collect events deals with the byte level messages, and sorts
  163. // and filters them into distinct messages we can handle easily
  164. void MidiDevice::OssCollectEvents()
  165. {
  166. unsigned char buf[1];
  167. int count,n,nn;
  168. bool MessageSent;
  169. unsigned char data[3],last=0;
  170. // constantly scan for relevent input,
  171. // and write it to the pipe
  172. // filters out unhandled messages, and attempts to build
  173. // coherent messages to send to the midi handler
  174. bool InSysex=false;
  175. for(;;)
  176. {
  177. OssReadByte(buf);
  178. if (*buf==MIDI_CLOCK)
  179. {
  180. m_ClockCount++;
  181. if (m_ClockCount==6)
  182. {
  183. m_Clock=-m_Clock;
  184. m_ClockCount=0;
  185. }
  186. }
  187. else
  188. if (*buf>=STATUS_START) // we've got a status byte
  189. {
  190. if (*buf==SYSEX_TERMINATOR) InSysex=false;
  191. // find out if it's an opcode
  192. if(*buf>=STATUS_START && *buf<=STATUS_END)
  193. {
  194. InSysex=false;
  195. last=data[0]=*buf;
  196. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  197. {
  198. OssReadByte(&data[1]); //one byte
  199. data[2]=0;
  200. }
  201. else // get the next two bytes
  202. {
  203. OssReadByte(&data[1]);
  204. OssReadByte(&data[2]);
  205. }
  206. OssAddEvent(data);
  207. }
  208. else // its a sysex or other message like active sense
  209. {
  210. if (*buf==SYSEX_START) InSysex=true;
  211. cerr<<"Unhandled midi message: "; printf("%x\n",(int)*buf);
  212. }
  213. }
  214. else // more data (running status)
  215. {
  216. if (!InSysex)
  217. {
  218. data[0]=last;
  219. data[1]=*buf;
  220. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  221. {
  222. data[2]=0; //one byte
  223. }
  224. else // get the next byte
  225. {
  226. OssReadByte(&data[2]);
  227. }
  228. OssAddEvent(data);
  229. }
  230. }
  231. }
  232. }
  233. // addevent converts the midi bytecode into midi message objects and
  234. // stacks them onto the event list to be picked up by the app
  235. void MidiDevice::OssAddEvent(unsigned char* midi)
  236. {
  237. MidiEvent::type MessageType=MidiEvent::NONE;
  238. int Volume=0,Note=0,EventDevice=0;
  239. // note off
  240. if (midi[0] >= STATUS_NOTE_OFF && midi[0] < STATUS_NOTE_ON)
  241. {
  242. MessageType=MidiEvent::OFF;
  243. Note=midi[1]-MIDI_KEYOFFSET;
  244. EventDevice=midi[0]-STATUS_NOTE_OFF;
  245. }
  246. // note on
  247. else if (midi[0] >= STATUS_NOTE_ON && midi[0] < STATUS_AFTERTOUCH)
  248. {
  249. Volume = midi[2];
  250. // cope with Roland equipment, where note on's
  251. // with zero velocity are sent as note offs.
  252. if (Volume) MessageType=MidiEvent::ON;
  253. else MessageType=MidiEvent::OFF;
  254. Note=midi[1]-MIDI_KEYOFFSET;
  255. EventDevice=midi[0]-STATUS_NOTE_ON;
  256. }
  257. // aftertouch
  258. else if (midi[0] >= STATUS_AFTERTOUCH && midi[0] < STATUS_CONTROL_CHANGE)
  259. {
  260. MessageType=MidiEvent::AFTERTOUCH;
  261. Note=midi[1]-MIDI_KEYOFFSET;
  262. Volume=midi[2];
  263. EventDevice=midi[0]-STATUS_AFTERTOUCH;
  264. }
  265. // parameter
  266. else if (midi[0] >= STATUS_CONTROL_CHANGE && midi[0] < STATUS_PROG_CHANGE)
  267. {
  268. MessageType=MidiEvent::PARAMETER;
  269. Note=midi[1];
  270. Volume=midi[2];
  271. EventDevice=midi[0]-STATUS_CONTROL_CHANGE;
  272. }
  273. // channel pressure
  274. else if (midi[0] >= STATUS_CHANNEL_PRESSURE && midi[0] < STATUS_PITCH_WHEEL)
  275. {
  276. MessageType=MidiEvent::CHANNELPRESSURE;
  277. Volume=midi[1];
  278. EventDevice=midi[0]-STATUS_CHANNEL_PRESSURE;
  279. }
  280. // note pitchbend
  281. else if (midi[0] >= STATUS_PITCH_WHEEL && midi[0] < STATUS_END)
  282. {
  283. MessageType=MidiEvent::PITCHBEND;
  284. // should probably take the first byte into account too?
  285. Volume=midi[2];
  286. EventDevice=midi[0]-STATUS_PITCH_WHEEL;
  287. }
  288. if (EventDevice<0 || EventDevice>15)
  289. {
  290. cerr<<"Error - Midi device "<<EventDevice<<" ??"<<endl;
  291. return;
  292. }
  293. pthread_mutex_lock(m_Mutex);
  294. m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
  295. pthread_mutex_unlock(m_Mutex);
  296. }
  297. #endif
  298. //////////////////////////////////////////// Alsa Code Only ////////////////////////////////////////
  299. #ifdef USE_ALSA_MIDI
  300. // code taken and modified from jack_miniFMsynth
  301. void MidiDevice::AlsaClose () {
  302. //Alsa requires two handles - one for read and one for write,
  303. //so we make sure too close both here
  304. snd_seq_close (seq_rhandle);
  305. snd_seq_close (seq_whandle);
  306. }
  307. void MidiDevice::AlsaCollectEvents () {
  308. //As Alsa only supports a read or write, we use the read handle here to poll our input
  309. //for MIDI events
  310. int seq_nfds, l1;
  311. struct pollfd *pfds;
  312. //get descriptors count to find out how many events are
  313. //waiting to be processed
  314. seq_nfds = snd_seq_poll_descriptors_count(seq_rhandle, POLLIN);
  315. //poll the descriptors to be proccessed and loop through them
  316. pfds = new struct pollfd[seq_nfds];
  317. snd_seq_poll_descriptors(seq_rhandle, pfds, seq_nfds, POLLIN);
  318. for (;;) {
  319. if (poll (pfds, seq_nfds, 1000) > 0) {
  320. for (l1 = 0; l1 < seq_nfds; l1++) {
  321. if (pfds[l1].revents > 0) {
  322. snd_seq_event_t *ev;
  323. // this line looks suspect to me (Andy Preston)
  324. // int l1;
  325. MidiEvent::type MessageType=MidiEvent::NONE;
  326. int Volume=0, Note=0, EventDevice=0;
  327. do {
  328. snd_seq_event_input (seq_rhandle, &ev);
  329. if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0)) {
  330. ev->type = SND_SEQ_EVENT_NOTEOFF;
  331. }
  332. switch (ev->type) {
  333. case SND_SEQ_EVENT_PITCHBEND:
  334. // Andy Preston
  335. MessageType=MidiEvent::PITCHBEND;
  336. Volume = (char)((ev->data.control.value / 8192.0)*256);
  337. break;
  338. case SND_SEQ_EVENT_CONTROLLER:
  339. MessageType=MidiEvent::PARAMETER;
  340. Note = ev->data.control.param;
  341. Volume = ev->data.control.value;
  342. break;
  343. case SND_SEQ_EVENT_NOTEON:
  344. MessageType=MidiEvent::ON;
  345. EventDevice = ev->data.control.channel;
  346. Note = ev->data.note.note;
  347. Volume = ev->data.note.velocity;
  348. break;
  349. case SND_SEQ_EVENT_NOTEOFF:
  350. MessageType=MidiEvent::ON;
  351. EventDevice = ev->data.control.channel;
  352. Note = ev->data.note.note;
  353. break;
  354. }
  355. pthread_mutex_lock (m_Mutex);
  356. m_EventVec[EventDevice].push (MidiEvent (MessageType, Note, Volume));
  357. pthread_mutex_unlock (m_Mutex);
  358. snd_seq_free_event (ev);
  359. } while (snd_seq_event_input_pending(seq_rhandle, 0) > 0);
  360. }
  361. }
  362. }
  363. }
  364. delete [] pfds;
  365. }
  366. void MidiDevice::AlsaSendEvent (int Device, const MidiEvent &Event) {
  367. //As Alsa only supports a read or write, we use the write handle here to send
  368. //our MIDI events
  369. snd_seq_event_t ev;
  370. snd_seq_ev_clear (&ev);
  371. snd_seq_ev_set_direct (&ev);
  372. snd_seq_ev_set_subs (&ev);
  373. snd_seq_ev_set_source (&ev, 0);
  374. switch (Event.GetType())
  375. {
  376. case MidiEvent::ON:
  377. ev.type = SND_SEQ_EVENT_NOTEON;
  378. break;
  379. case MidiEvent::OFF:
  380. ev.type = SND_SEQ_EVENT_NOTEOFF;
  381. break;
  382. /* case MidiEvent::PARAMETER:
  383. ev.type = SND_SEQ_EVENT_CONTROLLER;
  384. ev.data.control.param = Event.GetNote();
  385. ev.data.control.value =
  386. break;
  387. case MidiEvent::PITCHBEND:
  388. ev.type = SND_SEQ_EVENT_PITCHBEND;
  389. ev.data.control.param = Event.GetNote();
  390. ev.data.control.value =
  391. break;*/
  392. default:
  393. break;
  394. }
  395. ev.data.note.velocity = (char)Event.GetVolume()*127;
  396. ev.data.control.channel = Device;
  397. ev.data.note.note=Event.GetNote();
  398. snd_seq_event_output(seq_whandle, &ev);
  399. snd_seq_drain_output(seq_whandle);
  400. }
  401. void MidiDevice::AlsaOpen()
  402. {
  403. int client_id, port_id;
  404. //Alsa apears to require two handles, one for read and one for write
  405. //so we try to open one first for input and then one for output
  406. //open input handle
  407. if (snd_seq_open(&seq_rhandle, "default", SND_SEQ_OPEN_INPUT, 0) < 0)
  408. {
  409. fprintf(stderr, "Error opening ALSA input sequencer.\n");
  410. exit(1);
  411. }
  412. //setup our input name as seen by other apps, and get corresponding client id
  413. snd_seq_set_client_name(seq_rhandle, m_AppName.c_str());
  414. client_id = snd_seq_client_id(seq_rhandle);
  415. //try and create our actual input port capable of being written to by MIDI outputs
  416. if ((port_id = snd_seq_create_simple_port(seq_rhandle, m_AppName.c_str(),
  417. SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
  418. SND_SEQ_PORT_TYPE_APPLICATION) < 0))
  419. {
  420. fprintf(stderr, "Error creating input sequencer port.\n");
  421. }
  422. //open output handle
  423. if (snd_seq_open(&seq_whandle, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0)
  424. {
  425. fprintf(stderr, "Error opening ALSA ouput sequencer.\n");
  426. exit(1);
  427. }
  428. //setup our output name as seen by other apps, and get corresponding client id
  429. snd_seq_set_client_name(seq_whandle, m_AppName.c_str());
  430. client_id = snd_seq_client_id(seq_whandle);
  431. //try and create our actual output port capable of being read from by MIDI inputs
  432. if ((port_id = snd_seq_create_simple_port(seq_whandle, m_AppName.c_str(),
  433. SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
  434. SND_SEQ_PORT_TYPE_APPLICATION) < 0))
  435. {
  436. fprintf(stderr, "Error creating output sequencer port.\n");
  437. }
  438. }
  439. #endif
  440. //////////////////////////////////////////// Apple Code Only /////////////////////////////////////////
  441. #if __APPLE__
  442. void MidiDevice::AppleOpen()
  443. {
  444. m_ReadFillIndex = m_ReadReadIndex = 0;
  445. OSStatus err = 0;
  446. mMIDISource = NULL;
  447. mMIDIClient = NULL;
  448. mMIDIDestination = NULL;
  449. err = MIDIClientCreate(CFSTR("org.pawpal.ssm"), NULL, NULL, &mMIDIClient);
  450. if (err) printf("MIDIClientCreate failed returned %d\n", err);
  451. if (!err) {
  452. err = MIDISourceCreate(mMIDIClient, CFSTR("SpiralSynth"), &mMIDISource);
  453. if (err) printf("MIDIInputPortCreate failed returned %d\n", err);
  454. }
  455. if (!err) {
  456. err = MIDIDestinationCreate(mMIDIClient, CFSTR("SpiralSynth"), sMIDIRead, this, &mMIDIDestination);
  457. MIDIObjectSetIntegerProperty(mMIDIDestination, kMIDIPropertyUniqueID, 'SSmP');
  458. }
  459. }
  460. void MidiDevice::AppleClose()
  461. {
  462. if (mMIDIDestination)
  463. MIDIEndpointDispose(mMIDIDestination);
  464. if (mMIDISource)
  465. MIDIEndpointDispose(mMIDISource);
  466. mMIDISource = NULL;
  467. if (mMIDIClient)
  468. MIDIClientDispose(mMIDIClient);
  469. mMIDIClient = NULL;
  470. }
  471. int MidiDevice::AppleWrite(int dummy, unsigned char *outbuffer, int maxlen)
  472. {
  473. return 0;
  474. }
  475. int MidiDevice::AppleRead(int dummy, unsigned char *outbuffer, int maxlen)
  476. {
  477. if (!mMIDIClient)
  478. return -1;
  479. int len = 0;
  480. do {
  481. while (m_ReadReadIndex == m_ReadFillIndex)
  482. usleep(1000); // 1ms
  483. int readl = m_ReadFillIndex - m_ReadReadIndex;
  484. if (readl < 0)
  485. readl += midi_ReadSize; // wrapped
  486. while (len < maxlen && readl-- > 0) {
  487. int r = m_ReadReadIndex;
  488. outbuffer[len++] = m_ReadBuffer[r];
  489. r++;
  490. m_ReadReadIndex = r % midi_ReadSize;
  491. }
  492. } while (len < maxlen);
  493. return len;
  494. }
  495. void MidiDevice::sMIDIRead(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
  496. {
  497. MidiDevice & t = *((MidiDevice*)readProcRefCon);
  498. const MIDIPacket *packet = &pktlist->packet[0];
  499. for (int i = 0; i < (int)pktlist->numPackets; i++) {
  500. const MIDIPacket & p = *packet;
  501. for (int b = 0; b < p.length; b++) {
  502. // printf("%02x ", p.data[b]);
  503. int d = t.m_ReadFillIndex;
  504. t.m_ReadBuffer[d] = p.data[b];
  505. d++;
  506. t.m_ReadFillIndex = d % midi_ReadSize;
  507. }
  508. // printf("\n");
  509. packet = MIDIPacketNext(packet);
  510. }
  511. }
  512. #endif