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