/* * Copyright (C) 1998-2018 Paul Davis * Copyright (C) 2005-2006 Taybin Rutkin * Copyright (C) 2009 David Robillard * Copyright (C) 2015-2019 Robin Gareus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once #include #include #include "pbd/signals.h" #include "midi++/libmidi_visibility.h" #include "midi++/types.h" namespace MIDI { class Port; class Parser; typedef PBD::Signal ZeroByteSignal; typedef PBD::Signal BankSignal; typedef PBD::Signal TimestampedSignal; typedef PBD::Signal OneByteSignal; typedef PBD::Signal TwoByteSignal; typedef PBD::Signal PitchBendSignal; typedef PBD::Signal RPNSignal; typedef PBD::Signal RPNValueSignal; typedef PBD::Signal Signal; typedef PBD::Signal AnySignal; class LIBMIDIPP_API Parser { public: Parser (); ~Parser (); /* sets the time that will be reported for any MTC or MIDI Clock message the next time ::scanner() parses such a message. It should therefore be set before every byte passed into ::scanner(). */ samplecnt_t get_timestamp() const { return _timestamp; } void set_timestamp (const samplecnt_t timestamp) { _timestamp = timestamp; } /* signals that anyone can connect to */ BankSignal bank_change; TwoByteSignal note_on; TwoByteSignal note_off; TwoByteSignal poly_pressure; OneByteSignal pressure; OneByteSignal program_change; PitchBendSignal pitchbend; TwoByteSignal controller; BankSignal channel_bank_change[16]; TwoByteSignal channel_note_on[16]; TwoByteSignal channel_note_off[16]; TwoByteSignal channel_poly_pressure[16]; OneByteSignal channel_pressure[16]; OneByteSignal channel_program_change[16]; PitchBendSignal channel_pitchbend[16]; TwoByteSignal channel_controller[16]; ZeroByteSignal channel_active_preparse[16]; ZeroByteSignal channel_active_postparse[16]; RPNValueSignal channel_rpn[16]; RPNValueSignal channel_nrpn[16]; RPNSignal channel_rpn_change[16]; RPNSignal channel_nrpn_change[16]; OneByteSignal mtc_quarter_frame; /* see below for more useful signals */ Signal mtc; Signal raw_preparse; Signal raw_postparse; AnySignal any; Signal sysex; Signal mmc; AnySignal position; Signal song; ZeroByteSignal all_notes_off; ZeroByteSignal tune; ZeroByteSignal active_sense; ZeroByteSignal reset; ZeroByteSignal eox; TimestampedSignal timing; TimestampedSignal tick; /* rarely seen in the wild */ TimestampedSignal start; TimestampedSignal stop; TimestampedSignal contineu; /* note spelling */ /* This should really be protected, but then derivatives of Port can't access it. */ void scanner (byte c); size_t *message_counts() { return message_counter; } const char *midi_event_type_name (MIDI::eventType); void trace (bool onoff, std::ostream *o, const std::string &prefix = ""); bool tracing() { return trace_stream != 0; } void set_offline (bool); bool offline() const { return _offline; } PBD::Signal OfflineStatusChanged; PBD::Signal edit; void set_mmc_forwarding (bool yn) { _mmc_forward = yn; } /* MTC */ MTC_FPS mtc_fps() const { return _mtc_fps; } MTC_Status mtc_running() const { return _mtc_running; } const byte *mtc_current() const { return _mtc_time; } bool mtc_locked() const { return _mtc_locked; } PBD::Signal mtc_qtr; PBD::Signal mtc_time; PBD::Signal mtc_status; PBD::Signal mtc_skipped; void set_mtc_forwarding (bool yn) { _mtc_forward = yn; } void reset_mtc_state (); private: /* tracing */ std::ostream *trace_stream; std::string trace_prefix; void trace_event (Parser &p, byte *msg, size_t len, samplecnt_t); PBD::ScopedConnection trace_connection; size_t message_counter[256]; enum ParseState { NEEDSTATUS, NEEDONEBYTE, NEEDTWOBYTES, VARIABLELENGTH }; ParseState state; unsigned char *msgbuf; int msglen; int msgindex; MIDI::eventType msgtype; channel_t channel; bool _offline; bool runnable; bool was_runnable; bool _mmc_forward; bool _mtc_forward; int expected_mtc_quarter_frame_code; byte _mtc_time[5]; byte _qtr_mtc_time[5]; unsigned long consecutive_qtr_frame_cnt; MTC_FPS _mtc_fps; MTC_Status _mtc_running; bool _mtc_locked; byte last_qtr_frame; samplecnt_t _timestamp; ParseState pre_variable_state; MIDI::eventType pre_variable_msgtype; byte last_status_byte; void channel_msg (byte); void realtime_msg (byte); void system_msg (byte); void signal (byte *msg, size_t msglen); bool possible_mmc (byte *msg, size_t msglen); bool possible_mtc (byte *msg, size_t msglen); void process_mtc_quarter_frame (byte *msg); }; } // namespace MIDI