more changes to try to improve MTC handling even in slightly pathological cases
[ardour.git] / libs / midi++2 / midi++ / parser.h
1 /*
2     Copyright (C) 1998 Paul Barton-Davis
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef  __midi_parse_h__
21 #define  __midi_parse_h__
22
23 #include <string>
24 #include <iostream>
25
26 #include <sigc++/sigc++.h>
27
28 #include "midi++/types.h"
29
30 namespace MIDI {
31
32 class Port;
33 class Parser;
34
35 typedef sigc::signal<void, Parser &, byte>                 OneByteSignal;
36 typedef sigc::signal<void, Parser &, EventTwoBytes *>      TwoByteSignal;
37 typedef sigc::signal<void, Parser &, pitchbend_t>          PitchBendSignal;
38 typedef sigc::signal<void, Parser &, byte *, size_t> Signal;
39
40 class Parser : public sigc::trackable {
41  public:
42         Parser (Port &p);
43         ~Parser ();
44         
45         /* signals that anyone can connect to */
46         
47         OneByteSignal         bank_change;
48         TwoByteSignal         note_on;
49         TwoByteSignal         note_off;
50         TwoByteSignal         poly_pressure;
51         OneByteSignal         pressure;
52         OneByteSignal         program_change;
53         PitchBendSignal       pitchbend;
54         TwoByteSignal         controller;
55
56         OneByteSignal         channel_bank_change[16];
57         TwoByteSignal         channel_note_on[16];
58         TwoByteSignal         channel_note_off[16];
59         TwoByteSignal         channel_poly_pressure[16];
60         OneByteSignal         channel_pressure[16];
61         OneByteSignal         channel_program_change[16];
62         PitchBendSignal       channel_pitchbend[16];
63         TwoByteSignal         channel_controller[16];
64         sigc::signal<void, Parser &>          channel_active_preparse[16];
65         sigc::signal<void, Parser &>          channel_active_postparse[16];
66
67         OneByteSignal         mtc_quarter_frame;
68
69         Signal                raw_preparse;
70         Signal                raw_postparse;
71         Signal                any;
72         Signal                sysex;
73         Signal                mmc;
74         Signal                position;
75         Signal                song;
76
77         Signal                           mtc;
78         sigc::signal<void,Parser&,int>   mtc_qtr;
79
80         sigc::signal<void, Parser &>                     all_notes_off;
81         sigc::signal<void, Parser &>                     tune;
82         sigc::signal<void, Parser &, nframes_t>          timing;
83         sigc::signal<void, Parser &, nframes_t>          start;
84         sigc::signal<void, Parser &, nframes_t>          stop;
85         sigc::signal<void, Parser &, nframes_t>          contineu;  /* note spelling */
86         sigc::signal<void, Parser &>          active_sense;
87         sigc::signal<void, Parser &>          reset;
88         sigc::signal<void, Parser &>          eox;
89
90         /* This should really be protected, but then derivatives of Port
91            can't access it.
92         */
93
94         void scanner (byte c);
95
96         size_t *message_counts() { return message_counter; }
97         const char *midi_event_type_name (MIDI::eventType);
98         void trace (bool onoff, std::ostream *o, const std::string &prefix = "");
99         bool tracing() { return trace_stream != 0; }
100         Port &port() { return _port; }
101
102         void set_offline (bool);
103         bool offline() const { return _offline; }
104         sigc::signal<void> OfflineStatusChanged;
105
106         sigc::signal<int, byte *, size_t> edit;
107
108         void set_mmc_forwarding (bool yn) {
109                 _mmc_forward = yn;
110         }
111
112         /* MTC */
113
114         enum MTC_Status {
115                 MTC_Stopped = 0,
116                 MTC_Forward,
117                 MTC_Backward
118         };
119
120         MTC_FPS mtc_fps() const { return _mtc_fps; }
121         MTC_Status  mtc_running() const { return _mtc_running; }
122         const byte *mtc_current() const { return _mtc_time; }
123         bool        mtc_locked() const  { return _mtc_locked; }
124         
125         nframes_t get_midi_clock_timestamp() const { return _midi_clock_timestamp; }
126         void set_midi_clock_timestamp(const nframes_t timestamp) { _midi_clock_timestamp = timestamp; } 
127
128         sigc::signal<void,MTC_Status> mtc_status;
129         sigc::signal<bool>            mtc_skipped;
130         sigc::signal<void,const byte*,bool> mtc_time;
131
132         void set_mtc_forwarding (bool yn) {
133                 _mtc_forward = yn;
134         }
135
136         void reset_mtc_state ();
137         
138   private:
139         Port &_port;
140         /* tracing */
141
142         std::ostream *trace_stream;
143         std::string trace_prefix;
144         void trace_event (Parser &p, byte *msg, size_t len);
145         sigc::connection trace_connection;
146
147         size_t message_counter[256];
148
149         enum ParseState { 
150                 NEEDSTATUS,
151                 NEEDONEBYTE,
152                 NEEDTWOBYTES,
153                 VARIABLELENGTH
154         };
155         ParseState state;
156         unsigned char *msgbuf;
157         int msglen;
158         int msgindex;
159         MIDI::eventType msgtype;
160         channel_t channel;
161         bool _offline;
162         bool runnable;
163         bool was_runnable;
164         bool _mmc_forward;
165         bool _mtc_forward;
166         int   expected_mtc_quarter_frame_code;
167         byte _mtc_time[5];
168         byte _qtr_mtc_time[5];
169         unsigned long consecutive_qtr_frame_cnt;
170         MTC_FPS _mtc_fps;
171         MTC_Status _mtc_running;
172         bool       _mtc_locked;
173         byte last_qtr_frame;
174         
175         nframes_t _midi_clock_timestamp;
176
177         ParseState pre_variable_state;
178         MIDI::eventType pre_variable_msgtype;
179         byte last_status_byte;
180
181         void channel_msg (byte);
182         void realtime_msg (byte);
183         void system_msg (byte);
184         void signal (byte *msg, size_t msglen);
185         bool possible_mmc (byte *msg, size_t msglen);
186         bool possible_mtc (byte *msg, size_t msglen);
187         void process_mtc_quarter_frame (byte *msg);
188 };
189
190 } // namespace MIDI
191
192 #endif   // __midi_parse_h__
193