f7c62705b70b6c64582c51af3d0df407323a573d
[ardour.git] / libs / backends / wavesaudio / portmidi / src / pm_common / pminternal.h
1 /* pminternal.h -- header for interface implementations */\r
2 \r
3 /* this file is included by files that implement library internals */\r
4 /* Here is a guide to implementers:\r
5      provide an initialization function similar to pm_winmm_init()\r
6      add your initialization function to pm_init()\r
7      Note that your init function should never require not-standard\r
8          libraries or fail in any way. If the interface is not available,\r
9          simply do not call pm_add_device. This means that non-standard\r
10          libraries should try to do dynamic linking at runtime using a DLL\r
11          and return without error if the DLL cannot be found or if there\r
12          is any other failure.\r
13      implement functions as indicated in pm_fns_type to open, read, write,\r
14          close, etc.\r
15      call pm_add_device() for each input and output device, passing it a\r
16          pm_fns_type structure.\r
17      assumptions about pm_fns_type functions are given below.\r
18  */\r
19 \r
20 #ifdef __cplusplus\r
21 extern "C" {\r
22 #endif\r
23 \r
24 extern int pm_initialized; /* see note in portmidi.c */\r
25 \r
26 /* these are defined in system-specific file */\r
27 void *pm_alloc(size_t s);\r
28 void pm_free(void *ptr);\r
29 \r
30 /* if an error occurs while opening or closing a midi stream, set these: */\r
31 extern int pm_hosterror;\r
32 extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN];\r
33  \r
34 struct pm_internal_struct;\r
35 \r
36 /* these do not use PmInternal because it is not defined yet... */\r
37 typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi, \r
38                                      PmEvent *buffer);\r
39 typedef PmError (*pm_begin_sysex_fn)(struct pm_internal_struct *midi,\r
40                                      PmTimestamp timestamp);\r
41 typedef PmError (*pm_end_sysex_fn)(struct pm_internal_struct *midi,\r
42                                    PmTimestamp timestamp);\r
43 typedef PmError (*pm_write_byte_fn)(struct pm_internal_struct *midi,\r
44                                     unsigned char byte, PmTimestamp timestamp);\r
45 typedef PmError (*pm_write_realtime_fn)(struct pm_internal_struct *midi,\r
46                                         PmEvent *buffer);\r
47 typedef PmError (*pm_write_flush_fn)(struct pm_internal_struct *midi,\r
48                                      PmTimestamp timestamp);\r
49 typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi);\r
50 /* pm_open_fn should clean up all memory and close the device if any part\r
51    of the open fails */\r
52 typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi,\r
53                               void *driverInfo);\r
54 typedef PmError (*pm_abort_fn)(struct pm_internal_struct *midi);\r
55 /* pm_close_fn should clean up all memory and close the device if any\r
56    part of the close fails. */\r
57 typedef PmError (*pm_close_fn)(struct pm_internal_struct *midi);\r
58 typedef PmError (*pm_poll_fn)(struct pm_internal_struct *midi);\r
59 typedef void (*pm_host_error_fn)(struct pm_internal_struct *midi, char * msg,\r
60                                  unsigned int len);\r
61 typedef unsigned int (*pm_has_host_error_fn)(struct pm_internal_struct *midi);\r
62 \r
63 typedef struct {\r
64     pm_write_short_fn write_short; /* output short MIDI msg */\r
65     pm_begin_sysex_fn begin_sysex; /* prepare to send a sysex message */\r
66     pm_end_sysex_fn end_sysex; /* marks end of sysex message */\r
67     pm_write_byte_fn write_byte; /* accumulate one more sysex byte */\r
68     pm_write_realtime_fn write_realtime; /* send real-time message within sysex */\r
69     pm_write_flush_fn write_flush; /* send any accumulated but unsent data */\r
70     pm_synchronize_fn synchronize; /* synchronize portmidi time to stream time */\r
71     pm_open_fn open;   /* open MIDI device */\r
72     pm_abort_fn abort; /* abort */\r
73     pm_close_fn close; /* close device */\r
74     pm_poll_fn poll;   /* read pending midi events into portmidi buffer */\r
75     pm_has_host_error_fn has_host_error; /* true when device has had host \r
76                                             error message */\r
77     pm_host_error_fn host_error; /* provide text readable host error message\r
78                                     for device (clears and resets) */\r
79 } pm_fns_node, *pm_fns_type;\r
80 \r
81 \r
82 /* when open fails, the dictionary gets this set of functions: */\r
83 extern pm_fns_node pm_none_dictionary;\r
84 \r
85 typedef struct {\r
86     PmDeviceInfo pub; /* some portmidi state also saved in here (for autmatic\r
87                          device closing (see PmDeviceInfo struct) */\r
88     void *descriptor; /* ID number passed to win32 multimedia API open */\r
89     void *internalDescriptor; /* points to PmInternal device, allows automatic \r
90                                  device closing */\r
91     pm_fns_type dictionary;\r
92 } descriptor_node, *descriptor_type;\r
93 \r
94 extern int pm_descriptor_max;\r
95 extern descriptor_type descriptors;\r
96 extern int pm_descriptor_index;\r
97 \r
98 typedef uint32_t (*time_get_proc_type)(void *time_info);\r
99 \r
100 typedef struct pm_internal_struct {\r
101     int device_id; /* which device is open (index to descriptors) */\r
102     short write_flag; /* MIDI_IN, or MIDI_OUT */\r
103     \r
104     PmTimeProcPtr time_proc; /* where to get the time */\r
105     void *time_info; /* pass this to get_time() */\r
106     int32_t buffer_len; /* how big is the buffer or queue? */\r
107     PmQueue *queue;\r
108 \r
109     int32_t latency; /* time delay in ms between timestamps and actual output */\r
110                   /* set to zero to get immediate, simple blocking output */\r
111                   /* if latency is zero, timestamps will be ignored; */\r
112                   /* if midi input device, this field ignored */\r
113     \r
114     int sysex_in_progress; /* when sysex status is seen, this flag becomes\r
115         * true until EOX is seen. When true, new data is appended to the\r
116         * stream of outgoing bytes. When overflow occurs, sysex data is \r
117         * dropped (until an EOX or non-real-timei status byte is seen) so\r
118         * that, if the overflow condition is cleared, we don't start \r
119         * sending data from the middle of a sysex message. If a sysex\r
120         * message is filtered, sysex_in_progress is false, causing the\r
121         * message to be dropped. */\r
122     PmMessage sysex_message; /* buffer for 4 bytes of sysex data */\r
123     int sysex_message_count; /* how many bytes in sysex_message so far */\r
124 \r
125     int32_t filters; /* flags that filter incoming message classes */\r
126     int32_t channel_mask; /* filter incoming messages based on channel */\r
127     PmTimestamp last_msg_time; /* timestamp of last message */\r
128     PmTimestamp sync_time; /* time of last synchronization */\r
129     PmTimestamp now; /* set by PmWrite to current time */\r
130     int first_message; /* initially true, used to run first synchronization */\r
131     pm_fns_type dictionary; /* implementation functions */\r
132     void *descriptor; /* system-dependent state */\r
133     /* the following are used to expedite sysex data */\r
134     /* on windows, in debug mode, based on some profiling, these optimizations\r
135      * cut the time to process sysex bytes from about 7.5 to 0.26 usec/byte,\r
136      * but this does not count time in the driver, so I don't know if it is\r
137      * important\r
138      */\r
139     unsigned char *fill_base; /* addr of ptr to sysex data */\r
140     uint32_t *fill_offset_ptr; /* offset of next sysex byte */\r
141     int32_t fill_length; /* how many sysex bytes to write */\r
142 } PmInternal;\r
143 \r
144 \r
145 /* defined by system specific implementation, e.g. pmwinmm, used by PortMidi */\r
146 void pm_init(void); \r
147 void pm_term(void); \r
148 \r
149 /* defined by portMidi, used by pmwinmm */\r
150 PmError none_write_short(PmInternal *midi, PmEvent *buffer);\r
151 PmError none_write_byte(PmInternal *midi, unsigned char byte, \r
152                         PmTimestamp timestamp);\r
153 PmTimestamp none_synchronize(PmInternal *midi);\r
154 \r
155 PmError pm_fail_fn(PmInternal *midi);\r
156 PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp);\r
157 PmError pm_success_fn(PmInternal *midi);\r
158 PmError pm_add_device(char *interf, char *name, int input, void *descriptor,\r
159                       pm_fns_type dictionary);\r
160 uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len,\r
161                            PmTimestamp timestamp);\r
162 void pm_read_short(PmInternal *midi, PmEvent *event);\r
163 \r
164 #define none_write_flush pm_fail_timestamp_fn\r
165 #define none_sysex pm_fail_timestamp_fn\r
166 #define none_poll pm_fail_fn\r
167 #define success_poll pm_success_fn\r
168 \r
169 #define MIDI_REALTIME_MASK 0xf8\r
170 #define is_real_time(msg) \\r
171     ((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK)\r
172 \r
173 int pm_find_default_device(char *pattern, int is_input);\r
174 \r
175 #ifdef __cplusplus\r
176 }\r
177 #endif\r
178 \r