UnixSeqMidiDriver.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2004-2005  The Pentagram Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 /*
00020   Unix MIDI sequencer
00021   Adapted from ScummVM's backends/midi/seq.cpp
00022 */
00023 
00024 #include "pent_include.h"
00025 #include "UnixSeqMidiDriver.h"
00026 
00027 #ifdef USE_UNIX_SEQ_MIDI
00028 
00029 #include <fcntl.h>
00030 #include <unistd.h>
00031 #include <cerrno>
00032 
00033 const MidiDriver::MidiDriverDesc UnixSeqMidiDriver::desc =
00034                 MidiDriver::MidiDriverDesc ("UnixSeqDevice", createInstance);
00035 
00036 #define SEQ_MIDIPUTC 5
00037 #define SEQ_DEVICE "/dev/sequencer"
00038 
00039 UnixSeqMidiDriver::UnixSeqMidiDriver()
00040         : isOpen(false), device(0), deviceNum(0)
00041 {
00042         // see if the config file specifies an alternate midi device
00043         devname = getConfigSetting("unixseqdevice", SEQ_DEVICE);
00044 }
00045 
00046 int UnixSeqMidiDriver::open()
00047 {
00048         if (isOpen) return 1;
00049         isOpen = true;
00050         device = 0;
00051 
00052         pout << "UnixSeqDevice: opening device: " << devname << std::endl;
00053 
00054         device = ::open(devname.c_str(), O_RDWR, 0);
00055         if (device < 0) {
00056                 perr << "UnixSeqDevice: failed: " << strerror(errno);
00057                 perr << std::endl;
00058                 return device;
00059         }
00060 
00061         return 0;
00062 }
00063 
00064 void UnixSeqMidiDriver::close()
00065 {
00066 	::close(device);
00067         isOpen = false;
00068 }
00069 
00070 void UnixSeqMidiDriver::send(uint32 b) {
00071         unsigned char buf[256];
00072         int position = 0;
00073 
00074         switch (b & 0xF0) {
00075         case 0x80:
00076         case 0x90:
00077         case 0xA0:
00078         case 0xB0:
00079         case 0xE0:
00080                 buf[position++] = SEQ_MIDIPUTC;
00081                 buf[position++] = (unsigned char)b;
00082                 buf[position++] = deviceNum;
00083                 buf[position++] = 0;
00084                 buf[position++] = SEQ_MIDIPUTC;
00085                 buf[position++] = (unsigned char)((b >> 8) & 0x7F);
00086                 buf[position++] = deviceNum;
00087                 buf[position++] = 0;
00088                 buf[position++] = SEQ_MIDIPUTC;
00089                 buf[position++] = (unsigned char)((b >> 16) & 0x7F);
00090                 buf[position++] = deviceNum;
00091                 buf[position++] = 0;
00092                 break;
00093         case 0xC0:
00094         case 0xD0:
00095                 buf[position++] = SEQ_MIDIPUTC;
00096                 buf[position++] = (unsigned char)b;
00097                 buf[position++] = deviceNum;
00098                 buf[position++] = 0;
00099                 buf[position++] = SEQ_MIDIPUTC;
00100                 buf[position++] = (unsigned char)((b >> 8) & 0x7F);
00101                 buf[position++] = deviceNum;
00102                 buf[position++] = 0;
00103                 break;
00104         default:
00105                 perr << "UnixSeqMidiDriver: Unknown Command: "
00106                          << std::hex << (int)b << std::dec << std::endl;
00107                 break;
00108         }
00109 
00110         ::write(device, buf, position);
00111 }
00112 
00113 void UnixSeqMidiDriver::send_sysex(uint8 status,const uint8 *msg,uint16 length)
00114 {
00115         if (length > 511) {
00116                 perr << "UnixSeqMidiDriver: "
00117                          << "Cannot send SysEx block - data too large" << std::endl;
00118                 return;
00119         }
00120 
00121         unsigned char buf [2048];
00122         int position = 0;
00123         const uint8 *chr = msg;
00124 
00125         buf[position++] = SEQ_MIDIPUTC;
00126         buf[position++] = status;
00127         buf[position++] = deviceNum;
00128         buf[position++] = 0;
00129 
00130         for (; length; --length) {
00131                 buf[position++] = SEQ_MIDIPUTC;
00132                 buf[position++] = *chr++;
00133                 buf[position++] = deviceNum;
00134                 buf[position++] = 0;
00135         }
00136 
00137         ::write (device, buf, position);
00138 }
00139 
00140 #endif

Generated on Fri Jul 27 22:27:50 2007 for pentagram by  doxygen 1.4.7