1 /* 2 * Copyright (c) 2003 Matthijs Hollemans 3 * Copyright (c) 2003 Jerome Leveque 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <unistd.h> 27 28 #include "PortDrivers.h" 29 30 //------------------------------------------------------------------------------ 31 32 MidiPortConsumer::MidiPortConsumer(int fd_, const char* name = NULL) 33 : BMidiLocalConsumer(name) 34 { 35 fd = fd_; 36 } 37 38 //------------------------------------------------------------------------------ 39 40 void MidiPortConsumer::Data( 41 uchar* data, size_t length, bool atomic, bigtime_t time) 42 { 43 snooze_until(time - Latency(), B_SYSTEM_TIMEBASE); 44 45 if (write(fd, data, length) == -1) 46 { 47 perror("Error sending data to driver"); 48 } 49 } 50 51 //------------------------------------------------------------------------------ 52 53 MidiPortProducer::MidiPortProducer(int fd_, const char *name = NULL) 54 : BMidiLocalProducer(name) 55 { 56 fd = fd_; 57 keepRunning = true; 58 59 thread_id thread = spawn_thread( 60 SpawnThread, "MidiDriversProducer", B_URGENT_PRIORITY, this); 61 62 resume_thread(thread); 63 } 64 65 //------------------------------------------------------------------------------ 66 67 MidiPortProducer::~MidiPortProducer() 68 { 69 keepRunning = false; 70 } 71 72 //------------------------------------------------------------------------------ 73 74 int32 MidiPortProducer::SpawnThread(void* data) 75 { 76 return ((MidiPortProducer*) data)->GetData(); 77 } 78 79 //------------------------------------------------------------------------------ 80 81 int32 MidiPortProducer::GetData() 82 { 83 uchar data[3]; 84 85 while (keepRunning) 86 { 87 if (read(fd, data, 1) != 1) 88 { 89 perror("Error reading data from driver"); 90 return B_ERROR; 91 } 92 93 switch (data[0] & 0xF0) 94 { 95 case B_NOTE_OFF: 96 read(fd, data + 1, 2); 97 SprayNoteOff(data[0] & 0x0F, data[1], data[2]); 98 break; 99 100 case B_NOTE_ON: 101 read(fd, data + 1, 2); 102 SprayNoteOn(data[0] & 0x0F, data[1], data[2]); 103 break; 104 105 case B_KEY_PRESSURE: 106 read(fd, data + 1, 2); 107 SprayKeyPressure(data[0] & 0x0F, data[1], data[2]); 108 break; 109 110 case B_CONTROL_CHANGE: 111 read(fd, data + 1, 2); 112 SprayControlChange(data[0] & 0x0F, data[1], data[2]); 113 break; 114 115 case B_PROGRAM_CHANGE: 116 read(fd, data + 1, 1); 117 SprayProgramChange(data[0] & 0x0F, data[1]); 118 break; 119 120 case B_CHANNEL_PRESSURE: 121 read(fd, data + 1, 1); 122 SprayChannelPressure(data[0] & 0x0F, data[1]); 123 break; 124 125 case B_PITCH_BEND: 126 read(fd, data + 1, 2); 127 SprayPitchBend(data[0] & 0x0F, data[1], data[2]); 128 break; 129 } 130 131 switch (data[0]) 132 { 133 case B_SYS_EX_START: 134 { 135 size_t msg_size = 4096; 136 uchar* msg = (uchar*) malloc(msg_size); 137 size_t count = 0; 138 139 while (read(fd, msg + count, 1) == 1) 140 { 141 // Realtime events may interleave System Exclusives. Any 142 // non-realtime status byte (not just 0xF7) ends a sysex. 143 144 if (msg[count] >= 0xF8) 145 { 146 SpraySystemRealTime(msg[count]); 147 } 148 else if (msg[count] >= 0xF0) 149 { 150 SpraySystemExclusive(msg, count - 1); 151 break; 152 } 153 else // a normal data byte 154 { 155 ++count; 156 if (count == msg_size) 157 { 158 msg_size *= 2; 159 msg = (uchar*) realloc(msg, msg_size); 160 } 161 } 162 } 163 164 free(msg); 165 break; 166 } 167 168 case B_TUNE_REQUEST: 169 case B_SYS_EX_END: 170 SpraySystemCommon(data[0], 0, 0); 171 break; 172 173 case B_MIDI_TIME_CODE: 174 case B_SONG_SELECT: 175 case B_CABLE_MESSAGE: 176 read(fd, data + 1, 1); 177 SpraySystemCommon(data[0], data[1], 0); 178 break; 179 180 case B_SONG_POSITION: 181 read(fd, data + 1, 2); 182 SpraySystemCommon(data[0], data[1], data[2]); 183 break; 184 185 case B_TIMING_CLOCK: 186 case B_START: 187 case B_CONTINUE: 188 case B_STOP: 189 case B_ACTIVE_SENSING: 190 case B_SYSTEM_RESET: 191 SpraySystemRealTime(data[0]); 192 break; 193 } 194 } 195 196 return B_OK; 197 } 198 199 //------------------------------------------------------------------------------ 200