1 /* 2 * Copyright (C) 1998-2018 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com> 4 * Copyright (C) 2009 David Robillard <d@drobilla.net> 5 * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 */ 21 22 #ifndef __midi_parse_h__ 23 #define __midi_parse_h__ 24 25 #include <string> 26 #include <iostream> 27 28 #include "pbd/signals.h" 29 30 #include "midi++/libmidi_visibility.h" 31 #include "midi++/types.h" 32 33 namespace MIDI { 34 35 class Port; 36 class Parser; 37 38 typedef PBD::Signal1<void,Parser&> ZeroByteSignal; 39 typedef PBD::Signal2<void,Parser&,unsigned short> BankSignal; 40 typedef PBD::Signal2<void,Parser&,samplecnt_t> TimestampedSignal; 41 typedef PBD::Signal2<void,Parser&, byte> OneByteSignal; 42 typedef PBD::Signal2<void,Parser &, EventTwoBytes *> TwoByteSignal; 43 typedef PBD::Signal2<void,Parser &, pitchbend_t> PitchBendSignal; 44 typedef PBD::Signal3<void,Parser &, uint16_t, int> RPNSignal; 45 typedef PBD::Signal3<void,Parser &, uint16_t, float> RPNValueSignal; 46 typedef PBD::Signal3<void,Parser &, byte *, size_t> Signal; 47 typedef PBD::Signal4<void,Parser &, byte *, size_t, samplecnt_t> AnySignal; 48 49 class LIBMIDIPP_API Parser { 50 public: 51 Parser (); 52 ~Parser (); 53 54 /* sets the time that will be reported for any MTC or MIDI Clock 55 message the next time ::scanner() parses such a message. It should 56 therefore be set before every byte passed into ::scanner(). 57 */ 58 get_timestamp()59 samplecnt_t get_timestamp() const { return _timestamp; } set_timestamp(const samplecnt_t timestamp)60 void set_timestamp (const samplecnt_t timestamp) { _timestamp = timestamp; } 61 62 /* signals that anyone can connect to */ 63 64 BankSignal bank_change; 65 TwoByteSignal note_on; 66 TwoByteSignal note_off; 67 TwoByteSignal poly_pressure; 68 OneByteSignal pressure; 69 OneByteSignal program_change; 70 PitchBendSignal pitchbend; 71 TwoByteSignal controller; 72 73 BankSignal channel_bank_change[16]; 74 TwoByteSignal channel_note_on[16]; 75 TwoByteSignal channel_note_off[16]; 76 TwoByteSignal channel_poly_pressure[16]; 77 OneByteSignal channel_pressure[16]; 78 OneByteSignal channel_program_change[16]; 79 PitchBendSignal channel_pitchbend[16]; 80 TwoByteSignal channel_controller[16]; 81 ZeroByteSignal channel_active_preparse[16]; 82 ZeroByteSignal channel_active_postparse[16]; 83 RPNValueSignal channel_rpn[16]; 84 RPNValueSignal channel_nrpn[16]; 85 RPNSignal channel_rpn_change[16]; 86 RPNSignal channel_nrpn_change[16]; 87 88 OneByteSignal mtc_quarter_frame; /* see below for more useful signals */ 89 Signal mtc; 90 Signal raw_preparse; 91 Signal raw_postparse; 92 AnySignal any; 93 Signal sysex; 94 Signal mmc; 95 AnySignal position; 96 Signal song; 97 98 ZeroByteSignal all_notes_off; 99 ZeroByteSignal tune; 100 ZeroByteSignal active_sense; 101 ZeroByteSignal reset; 102 ZeroByteSignal eox; 103 104 TimestampedSignal timing; 105 TimestampedSignal start; 106 TimestampedSignal stop; 107 TimestampedSignal contineu; /* note spelling */ 108 109 /* This should really be protected, but then derivatives of Port 110 can't access it. 111 */ 112 113 void scanner (byte c); 114 message_counts()115 size_t *message_counts() { return message_counter; } 116 const char *midi_event_type_name (MIDI::eventType); 117 void trace (bool onoff, std::ostream *o, const std::string &prefix = ""); tracing()118 bool tracing() { return trace_stream != 0; } 119 120 void set_offline (bool); offline()121 bool offline() const { return _offline; } 122 PBD::Signal0<void> OfflineStatusChanged; 123 124 PBD::Signal2<int,byte *, size_t> edit; 125 set_mmc_forwarding(bool yn)126 void set_mmc_forwarding (bool yn) { 127 _mmc_forward = yn; 128 } 129 130 /* MTC */ 131 mtc_fps()132 MTC_FPS mtc_fps() const { return _mtc_fps; } mtc_running()133 MTC_Status mtc_running() const { return _mtc_running; } mtc_current()134 const byte *mtc_current() const { return _mtc_time; } mtc_locked()135 bool mtc_locked() const { return _mtc_locked; } 136 137 PBD::Signal3<void, Parser &, int, samplecnt_t> mtc_qtr; 138 PBD::Signal3<void, const byte *, bool, samplecnt_t> mtc_time; 139 PBD::Signal1<void, MTC_Status> mtc_status; 140 PBD::Signal0<bool> mtc_skipped; 141 set_mtc_forwarding(bool yn)142 void set_mtc_forwarding (bool yn) { 143 _mtc_forward = yn; 144 } 145 146 void reset_mtc_state (); 147 148 private: 149 /* tracing */ 150 151 std::ostream *trace_stream; 152 std::string trace_prefix; 153 void trace_event (Parser &p, byte *msg, size_t len, samplecnt_t); 154 PBD::ScopedConnection trace_connection; 155 156 size_t message_counter[256]; 157 158 enum ParseState { 159 NEEDSTATUS, 160 NEEDONEBYTE, 161 NEEDTWOBYTES, 162 VARIABLELENGTH 163 }; 164 ParseState state; 165 unsigned char *msgbuf; 166 int msglen; 167 int msgindex; 168 MIDI::eventType msgtype; 169 channel_t channel; 170 bool _offline; 171 bool runnable; 172 bool was_runnable; 173 bool _mmc_forward; 174 bool _mtc_forward; 175 int expected_mtc_quarter_frame_code; 176 byte _mtc_time[5]; 177 byte _qtr_mtc_time[5]; 178 unsigned long consecutive_qtr_frame_cnt; 179 MTC_FPS _mtc_fps; 180 MTC_Status _mtc_running; 181 bool _mtc_locked; 182 byte last_qtr_frame; 183 184 samplecnt_t _timestamp; 185 186 ParseState pre_variable_state; 187 MIDI::eventType pre_variable_msgtype; 188 byte last_status_byte; 189 190 void channel_msg (byte); 191 void realtime_msg (byte); 192 void system_msg (byte); 193 void signal (byte *msg, size_t msglen); 194 bool possible_mmc (byte *msg, size_t msglen); 195 bool possible_mtc (byte *msg, size_t msglen); 196 void process_mtc_quarter_frame (byte *msg); 197 }; 198 199 } // namespace MIDI 200 201 #endif // __midi_parse_h__ 202 203