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.

556 lines
15KB

  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. seq_handle=AlsaOpen(t);
  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. snd_seq_event_t ev;
  111. snd_seq_ev_clear (&ev);
  112. snd_seq_ev_set_direct (&ev);
  113. snd_seq_ev_set_subs (&ev);
  114. snd_seq_ev_set_source (&ev, 0);
  115. switch (Event.GetType())
  116. {
  117. case MidiEvent::ON:
  118. ev.type = SND_SEQ_EVENT_NOTEON;
  119. break;
  120. case MidiEvent::OFF:
  121. ev.type = SND_SEQ_EVENT_NOTEOFF;
  122. break;
  123. default:
  124. break;
  125. }
  126. ev.data.note.velocity = (char)Event.GetVolume()*127;
  127. ev.data.control.channel = Device;
  128. ev.data.note.note=Event.GetNote();
  129. int ret=snd_seq_event_output(seq_handle, &ev);
  130. snd_seq_drain_output(seq_handle);
  131. #else
  132. if (Device<0 || Device>15)
  133. {
  134. cerr<<"SendEvent: Invalid Midi device "<<Device<<endl;
  135. }
  136. char message[3];
  137. message[1]=Event.GetNote()+MIDI_KEYOFFSET;
  138. message[2]=(char)Event.GetVolume();
  139. if (Event.GetType()==MidiEvent::ON)
  140. {
  141. message[0]=STATUS_NOTE_ON+Device;
  142. write(m_MidiWrFd,message,3);
  143. //cerr<<"sending "<<message<<endl;
  144. }
  145. if (Event.GetType()==MidiEvent::OFF)
  146. {
  147. message[0]=STATUS_NOTE_OFF+Device;
  148. write(m_MidiWrFd,message,3);
  149. //cerr<<"sending "<<message<<endl;
  150. }
  151. #endif
  152. }
  153. //////////////////////////////////////////// Oss Code Only ////////////////////////////////////////
  154. #ifdef USE_OSS_MIDI
  155. bool MidiDevice::OssOpen() {
  156. //if (!SpiralInfo::WANTMIDI) return;
  157. m_MidiFd = open (m_DeviceName.c_str(), O_RDONLY | O_SYNC);
  158. if (!m_MidiFd) {
  159. cerr << "Couldn't open midi for reading [" << m_DeviceName << "]" << endl;
  160. return false;
  161. }
  162. m_MidiWrFd = open (m_DeviceName.c_str(), O_WRONLY);
  163. if (!m_MidiWrFd) {
  164. cerr << "Couldn't open midi for writing [" << m_DeviceName << "]" << endl;
  165. return false;
  166. }
  167. cerr << "Opened midi device [" << m_DeviceName << "]" << endl;
  168. return true;
  169. }
  170. void MidiDevice::OssClose() {
  171. close(m_MidiFd);
  172. close(m_MidiWrFd);
  173. cerr<<"Closed midi device"<<endl;
  174. }
  175. // little helper to strip out the realtime and unused messages
  176. void MidiDevice::OssReadByte(unsigned char *c)
  177. {
  178. *c=ACTIVE_SENSE;
  179. do read(m_MidiFd,c,1);
  180. while (*c>=STATUS_END && *c!=MIDI_CLOCK);
  181. }
  182. // collect events deals with the byte level messages, and sorts
  183. // and filters them into distinct messages we can handle easily
  184. void MidiDevice::OssCollectEvents()
  185. {
  186. unsigned char buf[1];
  187. int count,n,nn;
  188. bool MessageSent;
  189. unsigned char data[3],last=0;
  190. // constantly scan for relevent input,
  191. // and write it to the pipe
  192. // filters out unhandled messages, and attempts to build
  193. // coherent messages to send to the midi handler
  194. bool InSysex=false;
  195. for(;;)
  196. {
  197. OssReadByte(buf);
  198. if (*buf==MIDI_CLOCK)
  199. {
  200. m_ClockCount++;
  201. if (m_ClockCount==6)
  202. {
  203. m_Clock=-m_Clock;
  204. m_ClockCount=0;
  205. }
  206. }
  207. else
  208. if (*buf>=STATUS_START) // we've got a status byte
  209. {
  210. if (*buf==SYSEX_TERMINATOR) InSysex=false;
  211. // find out if it's an opcode
  212. if(*buf>=STATUS_START && *buf<=STATUS_END)
  213. {
  214. InSysex=false;
  215. last=data[0]=*buf;
  216. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  217. {
  218. OssReadByte(&data[1]); //one byte
  219. data[2]=0;
  220. }
  221. else // get the next two bytes
  222. {
  223. OssReadByte(&data[1]);
  224. OssReadByte(&data[2]);
  225. }
  226. OssAddEvent(data);
  227. }
  228. else // its a sysex or other message like active sense
  229. {
  230. if (*buf==SYSEX_START) InSysex=true;
  231. cerr<<"Unhandled midi message: "; printf("%x\n",(int)*buf);
  232. }
  233. }
  234. else // more data (running status)
  235. {
  236. if (!InSysex)
  237. {
  238. data[0]=last;
  239. data[1]=*buf;
  240. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  241. {
  242. data[2]=0; //one byte
  243. }
  244. else // get the next byte
  245. {
  246. OssReadByte(&data[2]);
  247. }
  248. OssAddEvent(data);
  249. }
  250. }
  251. }
  252. }
  253. // addevent converts the midi bytecode into midi message objects and
  254. // stacks them onto the event list to be picked up by the app
  255. void MidiDevice::OssAddEvent(unsigned char* midi)
  256. {
  257. MidiEvent::type MessageType=MidiEvent::NONE;
  258. int Volume=0,Note=0,EventDevice=0;
  259. // note off
  260. if (midi[0] >= STATUS_NOTE_OFF && midi[0] < STATUS_NOTE_ON)
  261. {
  262. MessageType=MidiEvent::OFF;
  263. Note=midi[1]-MIDI_KEYOFFSET;
  264. EventDevice=midi[0]-STATUS_NOTE_OFF;
  265. }
  266. // note on
  267. else if (midi[0] >= STATUS_NOTE_ON && midi[0] < STATUS_AFTERTOUCH)
  268. {
  269. Volume = midi[2];
  270. // cope with Roland equipment, where note on's
  271. // with zero velocity are sent as note offs.
  272. if (Volume) MessageType=MidiEvent::ON;
  273. else MessageType=MidiEvent::OFF;
  274. Note=midi[1]-MIDI_KEYOFFSET;
  275. EventDevice=midi[0]-STATUS_NOTE_ON;
  276. }
  277. // aftertouch
  278. else if (midi[0] >= STATUS_AFTERTOUCH && midi[0] < STATUS_CONTROL_CHANGE)
  279. {
  280. MessageType=MidiEvent::AFTERTOUCH;
  281. Note=midi[1]-MIDI_KEYOFFSET;
  282. Volume=midi[2];
  283. EventDevice=midi[0]-STATUS_AFTERTOUCH;
  284. }
  285. // parameter
  286. else if (midi[0] >= STATUS_CONTROL_CHANGE && midi[0] < STATUS_PROG_CHANGE)
  287. {
  288. MessageType=MidiEvent::PARAMETER;
  289. Note=midi[1];
  290. Volume=midi[2];
  291. EventDevice=midi[0]-STATUS_CONTROL_CHANGE;
  292. }
  293. // channel pressure
  294. else if (midi[0] >= STATUS_CHANNEL_PRESSURE && midi[0] < STATUS_PITCH_WHEEL)
  295. {
  296. MessageType=MidiEvent::CHANNELPRESSURE;
  297. Volume=midi[1];
  298. EventDevice=midi[0]-STATUS_CHANNEL_PRESSURE;
  299. }
  300. // note pitchbend
  301. else if (midi[0] >= STATUS_PITCH_WHEEL && midi[0] < STATUS_END)
  302. {
  303. MessageType=MidiEvent::PITCHBEND;
  304. // should probably take the first byte into account too?
  305. Volume=midi[2];
  306. EventDevice=midi[0]-STATUS_PITCH_WHEEL;
  307. }
  308. if (EventDevice<0 || EventDevice>15)
  309. {
  310. cerr<<"Error - Midi device "<<EventDevice<<" ??"<<endl;
  311. return;
  312. }
  313. pthread_mutex_lock(m_Mutex);
  314. m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
  315. pthread_mutex_unlock(m_Mutex);
  316. }
  317. #endif
  318. //////////////////////////////////////////// Alsa Code Only ////////////////////////////////////////
  319. #ifdef USE_ALSA_MIDI
  320. // code taken and modified from jack_miniFMsynth
  321. void MidiDevice::AlsaClose () {
  322. snd_seq_close (seq_handle);
  323. }
  324. void MidiDevice::AlsaCollectEvents () {
  325. int seq_nfds, l1;
  326. struct pollfd *pfds;
  327. seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
  328. // Andy Preston
  329. // pfds = (struct pollfd *)alloca (sizeof(struct pollfd) * seq_nfds);
  330. pfds = new struct pollfd[seq_nfds];
  331. snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
  332. for (;;) {
  333. if (poll (pfds, seq_nfds, 1000) > 0) {
  334. for (l1 = 0; l1 < seq_nfds; l1++) {
  335. if (pfds[l1].revents > 0) {
  336. snd_seq_event_t *ev;
  337. // this line looks suspect to me (Andy Preston)
  338. // int l1;
  339. MidiEvent::type MessageType=MidiEvent::NONE;
  340. int Volume=0, Note=0, EventDevice=0;
  341. do {
  342. snd_seq_event_input (seq_handle, &ev);
  343. if ((ev->type == SND_SEQ_EVENT_NOTEON) && (ev->data.note.velocity == 0)) {
  344. ev->type = SND_SEQ_EVENT_NOTEOFF;
  345. }
  346. switch (ev->type) {
  347. case SND_SEQ_EVENT_PITCHBEND:
  348. // Andy Preston
  349. MessageType=MidiEvent::PITCHBEND;
  350. Volume = (char)((ev->data.control.value / 8192.0)*256);
  351. break;
  352. case SND_SEQ_EVENT_CONTROLLER:
  353. MessageType=MidiEvent::PARAMETER;
  354. Note = ev->data.control.param;
  355. Volume = ev->data.control.value;
  356. break;
  357. case SND_SEQ_EVENT_NOTEON:
  358. MessageType=MidiEvent::ON;
  359. EventDevice = ev->data.control.channel;
  360. Note = ev->data.note.note;
  361. Volume = ev->data.note.velocity;
  362. break;
  363. case SND_SEQ_EVENT_NOTEOFF:
  364. MessageType=MidiEvent::ON;
  365. EventDevice = ev->data.control.channel;
  366. Note = ev->data.note.note;
  367. break;
  368. }
  369. pthread_mutex_lock (m_Mutex);
  370. m_EventVec[EventDevice].push (MidiEvent (MessageType, Note, Volume));
  371. pthread_mutex_unlock (m_Mutex);
  372. snd_seq_free_event (ev);
  373. } while (snd_seq_event_input_pending(seq_handle, 0) > 0);
  374. }
  375. }
  376. }
  377. }
  378. delete [] pfds;
  379. }
  380. snd_seq_t *MidiDevice::AlsaOpen(Type t)
  381. {
  382. snd_seq_t *seq_handle;
  383. int client_id, port_id;
  384. if (t==WRITE)
  385. {
  386. if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) {
  387. fprintf(stderr, "Error opening ALSA sequencer.\n");
  388. exit(1);
  389. }
  390. snd_seq_set_client_name(seq_handle, m_AppName.c_str());
  391. client_id = snd_seq_client_id(seq_handle);
  392. if ((port_id = snd_seq_create_simple_port(seq_handle, m_AppName.c_str(),
  393. SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
  394. SND_SEQ_PORT_TYPE_APPLICATION) < 0)) {
  395. fprintf(stderr, "Error creating sequencer port.\n");
  396. }
  397. }
  398. else
  399. {
  400. if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
  401. fprintf(stderr, "Error opening ALSA sequencer.\n");
  402. exit(1);
  403. }
  404. snd_seq_set_client_name(seq_handle, m_AppName.c_str());
  405. client_id = snd_seq_client_id(seq_handle);
  406. if ((port_id = snd_seq_create_simple_port(seq_handle, m_AppName.c_str(),
  407. SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
  408. SND_SEQ_PORT_TYPE_APPLICATION) < 0)) {
  409. fprintf(stderr, "Error creating sequencer port.\n");
  410. }
  411. }
  412. return(seq_handle);
  413. }
  414. #endif
  415. //////////////////////////////////////////// Apple Code Only /////////////////////////////////////////
  416. #if __APPLE__
  417. void MidiDevice::AppleOpen()
  418. {
  419. m_ReadFillIndex = m_ReadReadIndex = 0;
  420. OSStatus err = 0;
  421. mMIDISource = NULL;
  422. mMIDIClient = NULL;
  423. mMIDIDestination = NULL;
  424. err = MIDIClientCreate(CFSTR("org.pawpal.ssm"), NULL, NULL, &mMIDIClient);
  425. if (err) printf("MIDIClientCreate failed returned %d\n", err);
  426. if (!err) {
  427. err = MIDISourceCreate(mMIDIClient, CFSTR("SpiralSynth"), &mMIDISource);
  428. if (err) printf("MIDIInputPortCreate failed returned %d\n", err);
  429. }
  430. if (!err) {
  431. err = MIDIDestinationCreate(mMIDIClient, CFSTR("SpiralSynth"), sMIDIRead, this, &mMIDIDestination);
  432. MIDIObjectSetIntegerProperty(mMIDIDestination, kMIDIPropertyUniqueID, 'SSmP');
  433. }
  434. }
  435. void MidiDevice::AppleClose()
  436. {
  437. if (mMIDIDestination)
  438. MIDIEndpointDispose(mMIDIDestination);
  439. if (mMIDISource)
  440. MIDIEndpointDispose(mMIDISource);
  441. mMIDISource = NULL;
  442. if (mMIDIClient)
  443. MIDIClientDispose(mMIDIClient);
  444. mMIDIClient = NULL;
  445. }
  446. int MidiDevice::AppleWrite(int dummy, unsigned char *outbuffer, int maxlen)
  447. {
  448. return 0;
  449. }
  450. int MidiDevice::AppleRead(int dummy, unsigned char *outbuffer, int maxlen)
  451. {
  452. if (!mMIDIClient)
  453. return -1;
  454. int len = 0;
  455. do {
  456. while (m_ReadReadIndex == m_ReadFillIndex)
  457. usleep(1000); // 1ms
  458. int readl = m_ReadFillIndex - m_ReadReadIndex;
  459. if (readl < 0)
  460. readl += midi_ReadSize; // wrapped
  461. while (len < maxlen && readl-- > 0) {
  462. int r = m_ReadReadIndex;
  463. outbuffer[len++] = m_ReadBuffer[r];
  464. r++;
  465. m_ReadReadIndex = r % midi_ReadSize;
  466. }
  467. } while (len < maxlen);
  468. return len;
  469. }
  470. void MidiDevice::sMIDIRead(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
  471. {
  472. MidiDevice & t = *((MidiDevice*)readProcRefCon);
  473. const MIDIPacket *packet = &pktlist->packet[0];
  474. for (int i = 0; i < (int)pktlist->numPackets; i++) {
  475. const MIDIPacket & p = *packet;
  476. for (int b = 0; b < p.length; b++) {
  477. // printf("%02x ", p.data[b]);
  478. int d = t.m_ReadFillIndex;
  479. t.m_ReadBuffer[d] = p.data[b];
  480. d++;
  481. t.m_ReadFillIndex = d % midi_ReadSize;
  482. }
  483. // printf("\n");
  484. packet = MIDIPacketNext(packet);
  485. }
  486. }
  487. #endif