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.

407 lines
9.8KB

  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. #ifdef KEYBOARD_SUPPORT
  25. #include <FL/Fl.h>
  26. #endif
  27. static const int MIDI_SCANBUFSIZE=256;
  28. static const int MIDI_KEYOFFSET=0;
  29. static const unsigned char STATUS_START = 0x80;
  30. static const unsigned char STATUS_NOTE_OFF = 0x80;
  31. static const unsigned char STATUS_NOTE_ON = 0x90;
  32. static const unsigned char STATUS_AFTERTOUCH = 0xa0;
  33. static const unsigned char STATUS_CONTROL_CHANGE = 0xb0;
  34. static const unsigned char STATUS_PROG_CHANGE = 0xc0;
  35. static const unsigned char STATUS_CHANNEL_PRESSURE = 0xd0;
  36. static const unsigned char STATUS_PITCH_WHEEL = 0xe0;
  37. static const unsigned char STATUS_END = 0xf0;
  38. static const unsigned char SYSEX_START = 0xf0;
  39. static const unsigned char SYSEX_TERMINATOR = 0xf7;
  40. static const unsigned char MIDI_CLOCK = 0xf8;
  41. static const unsigned char ACTIVE_SENSE = 0xfe;
  42. static int NKEYS = 30;
  43. static char KEYMAP[30]={'z','s','x','d','c','v','g','b','h','n','j','m','q',
  44. '2','w','3','e','r','5','t','6','y','7','u','i','9',
  45. 'o','0','p','['};
  46. MidiDevice *MidiDevice::m_Singleton;
  47. string MidiDevice::m_DeviceName;
  48. MidiDevice::MidiDevice() :
  49. m_Poly(1)
  50. {
  51. Open();
  52. #ifdef KEYBOARD_SUPPORT
  53. m_Oct=4;
  54. m_CurrentVoice=0;
  55. for (int n=0; n<256; n++)
  56. {
  57. m_KeyVoice[n]=' ';
  58. }
  59. #endif
  60. }
  61. MidiDevice::~MidiDevice()
  62. {
  63. Close();
  64. }
  65. void MidiDevice::Close()
  66. {
  67. pthread_mutex_lock(m_Mutex);
  68. pthread_cancel(m_MidiReader);
  69. pthread_mutex_unlock(m_Mutex);
  70. pthread_mutex_destroy(m_Mutex);
  71. close(m_MidiFd);
  72. close(m_MidiWrFd);
  73. cerr<<"Closed midi device"<<endl;
  74. }
  75. void MidiDevice::Open()
  76. {
  77. //if (!SpiralInfo::WANTMIDI) return;
  78. m_MidiFd = open(m_DeviceName.c_str(),O_RDONLY|O_SYNC);
  79. if (!m_MidiFd)
  80. {
  81. cerr<<"Couldn't open midi for reading ["<<m_DeviceName<<"]"<<endl;
  82. return;
  83. }
  84. m_MidiWrFd = open(m_DeviceName.c_str(),O_WRONLY);
  85. if (!m_MidiWrFd)
  86. {
  87. cerr<<"Couldn't open midi for writing ["<<m_DeviceName<<"]"<<endl;
  88. return;
  89. }
  90. cerr<<"Opened midi device ["<<m_DeviceName<<"]"<<endl;
  91. m_Mutex = new pthread_mutex_t;
  92. pthread_mutex_init(m_Mutex, NULL);
  93. int ret=pthread_create(&m_MidiReader,NULL,(void*(*)(void*))MidiDevice::MidiReaderCallback,(void*)this);
  94. }
  95. // returns the next event off the list, or an
  96. // empty event if the list is exhausted
  97. MidiEvent MidiDevice::GetEvent(int Device)
  98. {
  99. if (Device<0 || Device>15)
  100. {
  101. cerr<<"GetEvent: Invalid Midi device "<<Device<<endl;
  102. return MidiEvent(MidiEvent::NONE,0,0);
  103. }
  104. #ifdef KEYBOARD_SUPPORT
  105. CheckKeyboard();
  106. #endif
  107. pthread_mutex_lock(m_Mutex);
  108. if (m_EventVec[Device].size()==0)
  109. {
  110. pthread_mutex_unlock(m_Mutex);
  111. return MidiEvent(MidiEvent::NONE,0,0);
  112. }
  113. MidiEvent event(m_EventVec[Device].front());
  114. m_EventVec[Device].pop();
  115. pthread_mutex_unlock(m_Mutex);
  116. return event;
  117. }
  118. void MidiDevice::SendEvent(int Device,const MidiEvent &Event)
  119. {
  120. if (Device<0 || Device>15)
  121. {
  122. cerr<<"SendEvent: Invalid Midi device "<<Device<<endl;
  123. }
  124. char message[3];
  125. message[1]=Event.GetNote()+MIDI_KEYOFFSET;
  126. message[2]=(char)Event.GetVolume();
  127. if (Event.GetType()==MidiEvent::ON)
  128. {
  129. message[0]=STATUS_NOTE_ON+Device;
  130. write(m_MidiWrFd,message,3);
  131. //cerr<<"sending "<<message<<endl;
  132. }
  133. if (Event.GetType()==MidiEvent::OFF)
  134. {
  135. message[0]=STATUS_NOTE_OFF+Device;
  136. write(m_MidiWrFd,message,3);
  137. //cerr<<"sending "<<message<<endl;
  138. }
  139. }
  140. /////////////////////////////////////////////////////////////////////////////////
  141. // Reader thread functions
  142. // little helper to strip out the realtime and unused messages
  143. void MidiDevice::ReadByte(unsigned char *c)
  144. {
  145. *c=MIDI_CLOCK;
  146. do read(m_MidiFd,c,1);
  147. while (*c>=STATUS_END);
  148. }
  149. // collect events deals with the byte level messages, and sorts
  150. // and filters them into distinct messages we can handle easily
  151. void MidiDevice::CollectEvents()
  152. {
  153. unsigned char buf[1];
  154. int count,n,nn;
  155. bool MessageSent;
  156. unsigned char data[3],last=0;
  157. // constantly scan for relevent input,
  158. // and write it to the pipe
  159. // filters out unhandled messages, and attempts to build
  160. // coherent messages to send to the midi handler
  161. bool InSysex=false;
  162. for(;;)
  163. {
  164. ReadByte(buf);
  165. if (*buf>=STATUS_START) // we've got a status byte
  166. {
  167. if (*buf==SYSEX_TERMINATOR) InSysex=false;
  168. // find out if it's an opcode
  169. if(*buf>=STATUS_START && *buf<=STATUS_END)
  170. {
  171. InSysex=false;
  172. last=data[0]=*buf;
  173. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  174. {
  175. ReadByte(&data[1]); //one byte
  176. data[2]=0;
  177. }
  178. else // get the next two bytes
  179. {
  180. ReadByte(&data[1]);
  181. ReadByte(&data[2]);
  182. }
  183. AddEvent(data);
  184. }
  185. else // its a sysex or other message like active sense
  186. {
  187. if (*buf==SYSEX_START) InSysex=true;
  188. cerr<<"Unhandled midi message: "; printf("%x\n",(int)*buf);
  189. }
  190. }
  191. else // more data (running status)
  192. {
  193. if (!InSysex)
  194. {
  195. data[0]=last;
  196. data[1]=*buf;
  197. if (data[0]>=STATUS_PROG_CHANGE && data[0]<STATUS_PITCH_WHEEL)
  198. {
  199. data[2]=0; //one byte
  200. }
  201. else // get the next byte
  202. {
  203. ReadByte(&data[2]);
  204. }
  205. AddEvent(data);
  206. }
  207. }
  208. }
  209. }
  210. // addevent converts the midi bytecode into midi message objects and
  211. // stacks them onto the event list to be picked up by the app
  212. void MidiDevice::AddEvent(unsigned char* midi)
  213. {
  214. MidiEvent::type MessageType=MidiEvent::NONE;
  215. int Volume=0,Note=0,EventDevice=0;
  216. // note off
  217. if (midi[0] >= STATUS_NOTE_OFF && midi[0] < STATUS_NOTE_ON)
  218. {
  219. MessageType=MidiEvent::OFF;
  220. Note=midi[1]-MIDI_KEYOFFSET;
  221. EventDevice=midi[0]-STATUS_NOTE_OFF;
  222. }
  223. // note on
  224. else if (midi[0] >= STATUS_NOTE_ON && midi[0] < STATUS_AFTERTOUCH)
  225. {
  226. Volume = midi[2];
  227. // cope with Roland equipment, where note on's
  228. // with zero velocity are sent as note offs.
  229. if (Volume) MessageType=MidiEvent::ON;
  230. else MessageType=MidiEvent::OFF;
  231. Note=midi[1]-MIDI_KEYOFFSET;
  232. EventDevice=midi[0]-STATUS_NOTE_ON;
  233. }
  234. // aftertouch
  235. else if (midi[0] >= STATUS_AFTERTOUCH && midi[0] < STATUS_CONTROL_CHANGE)
  236. {
  237. MessageType=MidiEvent::AFTERTOUCH;
  238. Note=midi[1]-MIDI_KEYOFFSET;
  239. Volume=midi[2];
  240. EventDevice=midi[0]-STATUS_AFTERTOUCH;
  241. }
  242. // parameter
  243. else if (midi[0] >= STATUS_CONTROL_CHANGE && midi[0] < STATUS_PROG_CHANGE)
  244. {
  245. MessageType=MidiEvent::PARAMETER;
  246. Note=midi[1];
  247. Volume=midi[2];
  248. EventDevice=midi[0]-STATUS_CONTROL_CHANGE;
  249. }
  250. // channel pressure
  251. else if (midi[0] >= STATUS_CHANNEL_PRESSURE && midi[0] < STATUS_PITCH_WHEEL)
  252. {
  253. MessageType=MidiEvent::CHANNELPRESSURE;
  254. Volume=midi[1];
  255. EventDevice=midi[0]-STATUS_CHANNEL_PRESSURE;
  256. }
  257. // note pitchbend
  258. else if (midi[0] >= STATUS_PITCH_WHEEL && midi[0] < STATUS_END)
  259. {
  260. MessageType=MidiEvent::PITCHBEND;
  261. // should probably take the first byte into account too?
  262. Volume=midi[2];
  263. EventDevice=midi[0]-STATUS_PITCH_WHEEL;
  264. }
  265. if (EventDevice<0 || EventDevice>15)
  266. {
  267. cerr<<"Error - Midi device "<<EventDevice<<" ??"<<endl;
  268. return;
  269. }
  270. pthread_mutex_lock(m_Mutex);
  271. m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
  272. pthread_mutex_unlock(m_Mutex);
  273. }
  274. ///////////////////////////////////////////////////////////////////////////////
  275. // Parse the keyboard to generate midi messages
  276. #ifdef KEYBOARD_SUPPORT
  277. void MidiDevice::CheckKeyboard()
  278. {
  279. Fl::check();
  280. MidiEvent::type MessageType=MidiEvent::NONE;
  281. int Volume=0,Note=0,EventDevice=0;
  282. if (Fl::event_key(FL_F+1)) m_Oct=0;
  283. if (Fl::event_key(FL_F+2)) m_Oct=1;
  284. if (Fl::event_key(FL_F+3)) m_Oct=2;
  285. if (Fl::event_key(FL_F+4)) m_Oct=3;
  286. if (Fl::event_key(FL_F+5)) m_Oct=4;
  287. if (Fl::event_key(FL_F+6)) m_Oct=5;
  288. if (Fl::event_key(FL_F+7)) m_Oct=6;
  289. if (Fl::event_key(FL_F+8)) m_Oct=7;
  290. if (Fl::event_key(FL_F+9)) m_Oct=8;
  291. if (Fl::event_key(FL_F+10)) m_Oct=9;
  292. if (Fl::event_key(FL_F+11)) m_Oct=10;
  293. int note=0;
  294. char KeyChar=0;
  295. bool KeyPressed=false;
  296. for (int key=0; key<NKEYS; key++)
  297. {
  298. KeyChar=KEYMAP[key];
  299. // check if a key's been pressed
  300. if (Fl::event_key(KeyChar))
  301. {
  302. KeyPressed=true;
  303. // check it was pressed last time
  304. bool Found=false;
  305. for (int n=0; n<m_Poly; n++)
  306. {
  307. if (m_KeyVoice[n]==KeyChar)
  308. {
  309. Found=true;
  310. }
  311. }
  312. if (!Found)
  313. {
  314. Volume = 127;
  315. MessageType=MidiEvent::ON;
  316. Note=(m_Oct*12)+note;
  317. // Move to the next voice
  318. m_CurrentVoice++;
  319. if (m_CurrentVoice>=m_Poly)
  320. {
  321. m_CurrentVoice=0;
  322. }
  323. // this should be the current voice we are using
  324. m_KeyVoice[m_CurrentVoice]=KeyChar;
  325. }
  326. }
  327. else // it's not pressed down
  328. {
  329. //see if the note was pressed down last time
  330. for (int n=0; n<m_Poly; n++)
  331. {
  332. if (m_KeyVoice[n]==KeyChar)
  333. {
  334. MessageType=MidiEvent::OFF;
  335. Note=(m_Oct*12)+note;
  336. m_KeyVoice[n]=' ';
  337. }
  338. }
  339. }
  340. note++;
  341. }
  342. if (MessageType!=MidiEvent::NONE)
  343. {
  344. pthread_mutex_lock(m_Mutex);
  345. m_EventVec[EventDevice].push(MidiEvent(MessageType,Note,Volume));
  346. pthread_mutex_unlock(m_Mutex);
  347. }
  348. }
  349. #endif