diff options
Diffstat (limited to 'portmidi/pm_common/pminternal.h')
| -rwxr-xr-x | portmidi/pm_common/pminternal.h | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/portmidi/pm_common/pminternal.h b/portmidi/pm_common/pminternal.h new file mode 100755 index 0000000..8b3d8f5 --- /dev/null +++ b/portmidi/pm_common/pminternal.h | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /** @file pminternal.h header for PortMidi 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 | /** @cond INTERNAL - add INTERNAL to Doxygen ENABLED_SECTIONS to include */ | ||
| 21 | |||
| 22 | #ifdef __cplusplus | ||
| 23 | extern "C" { | ||
| 24 | #endif | ||
| 25 | |||
| 26 | extern int pm_initialized; /* see note in portmidi.c */ | ||
| 27 | extern PmDeviceID pm_default_input_device_id; | ||
| 28 | extern PmDeviceID pm_default_output_device_id; | ||
| 29 | |||
| 30 | /* these are defined in system-specific file */ | ||
| 31 | void *pm_alloc(size_t s); | ||
| 32 | void pm_free(void *ptr); | ||
| 33 | |||
| 34 | /* if a host error (an error reported by the host MIDI API that is not | ||
| 35 | * mapped to a PortMidi error code) occurs in a synchronous operation | ||
| 36 | * (i.e., not in a callback from another thread) set these: */ | ||
| 37 | extern int pm_hosterror; /* boolean */ | ||
| 38 | extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN]; | ||
| 39 | |||
| 40 | struct pm_internal_struct; | ||
| 41 | |||
| 42 | /* these do not use PmInternal because it is not defined yet... */ | ||
| 43 | typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi, | ||
| 44 | PmEvent *buffer); | ||
| 45 | typedef PmError (*pm_begin_sysex_fn)(struct pm_internal_struct *midi, | ||
| 46 | PmTimestamp timestamp); | ||
| 47 | typedef PmError (*pm_end_sysex_fn)(struct pm_internal_struct *midi, | ||
| 48 | PmTimestamp timestamp); | ||
| 49 | typedef PmError (*pm_write_byte_fn)(struct pm_internal_struct *midi, | ||
| 50 | unsigned char byte, PmTimestamp timestamp); | ||
| 51 | typedef PmError (*pm_write_realtime_fn)(struct pm_internal_struct *midi, | ||
| 52 | PmEvent *buffer); | ||
| 53 | typedef PmError (*pm_write_flush_fn)(struct pm_internal_struct *midi, | ||
| 54 | PmTimestamp timestamp); | ||
| 55 | typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi); | ||
| 56 | /* pm_open_fn should clean up all memory and close the device if any part | ||
| 57 | of the open fails */ | ||
| 58 | typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi, | ||
| 59 | void *driverInfo); | ||
| 60 | typedef PmError (*pm_create_fn)(int is_input, const char *name, | ||
| 61 | void *driverInfo); | ||
| 62 | typedef PmError (*pm_delete_fn)(PmDeviceID id); | ||
| 63 | typedef PmError (*pm_abort_fn)(struct pm_internal_struct *midi); | ||
| 64 | /* pm_close_fn should clean up all memory and close the device if any | ||
| 65 | part of the close fails. */ | ||
| 66 | typedef PmError (*pm_close_fn)(struct pm_internal_struct *midi); | ||
| 67 | typedef PmError (*pm_poll_fn)(struct pm_internal_struct *midi); | ||
| 68 | typedef unsigned int (*pm_check_host_error_fn)(struct pm_internal_struct *midi); | ||
| 69 | |||
| 70 | typedef struct { | ||
| 71 | pm_write_short_fn write_short; /* output short MIDI msg */ | ||
| 72 | pm_begin_sysex_fn begin_sysex; /* prepare to send a sysex message */ | ||
| 73 | pm_end_sysex_fn end_sysex; /* marks end of sysex message */ | ||
| 74 | pm_write_byte_fn write_byte; /* accumulate one more sysex byte */ | ||
| 75 | pm_write_realtime_fn write_realtime; /* send real-time msg within sysex */ | ||
| 76 | pm_write_flush_fn write_flush; /* send any accumulated but unsent data */ | ||
| 77 | pm_synchronize_fn synchronize; /* synchronize PM time to stream time */ | ||
| 78 | pm_open_fn open; /* open MIDI device */ | ||
| 79 | pm_abort_fn abort; /* abort */ | ||
| 80 | pm_close_fn close; /* close device */ | ||
| 81 | pm_poll_fn poll; /* read pending midi events into portmidi buffer */ | ||
| 82 | pm_check_host_error_fn check_host_error; /* true when device has had host */ | ||
| 83 | /* error; sets pm_hosterror and writes message to pm_hosterror_text */ | ||
| 84 | } pm_fns_node, *pm_fns_type; | ||
| 85 | |||
| 86 | |||
| 87 | /* when open fails, the dictionary gets this set of functions: */ | ||
| 88 | extern pm_fns_node pm_none_dictionary; | ||
| 89 | |||
| 90 | typedef struct { | ||
| 91 | PmDeviceInfo pub; /* some portmidi state also saved in here (for automatic | ||
| 92 | device closing -- see PmDeviceInfo struct) */ | ||
| 93 | int deleted; /* is this is a deleted virtual device? */ | ||
| 94 | void *descriptor; /* ID number passed to win32 multimedia API open, | ||
| 95 | * coreMIDI endpoint, etc., representing the device */ | ||
| 96 | struct pm_internal_struct *pm_internal; /* points to PmInternal device */ | ||
| 97 | /* when the device is open, allows automatic device closing */ | ||
| 98 | pm_fns_type dictionary; | ||
| 99 | } descriptor_node, *descriptor_type; | ||
| 100 | |||
| 101 | extern int pm_descriptor_max; | ||
| 102 | extern descriptor_type pm_descriptors; | ||
| 103 | extern int pm_descriptor_len; | ||
| 104 | |||
| 105 | typedef uint32_t (*time_get_proc_type)(void *time_info); | ||
| 106 | |||
| 107 | typedef struct pm_internal_struct { | ||
| 108 | int device_id; /* which device is open (index to pm_descriptors) */ | ||
| 109 | short is_input; /* MIDI IN (true) or MIDI OUT (false) */ | ||
| 110 | short is_removed; /* MIDI device was removed */ | ||
| 111 | PmTimeProcPtr time_proc; /* where to get the time */ | ||
| 112 | void *time_info; /* pass this to get_time() */ | ||
| 113 | int32_t buffer_len; /* how big is the buffer or queue? */ | ||
| 114 | PmQueue *queue; | ||
| 115 | |||
| 116 | int32_t latency; /* time delay in ms between timestamps and actual output */ | ||
| 117 | /* set to zero to get immediate, simple blocking output */ | ||
| 118 | /* if latency is zero, timestamps will be ignored; */ | ||
| 119 | /* if midi input device, this field ignored */ | ||
| 120 | |||
| 121 | int sysex_in_progress; /* when sysex status is seen, this flag becomes | ||
| 122 | * true until EOX is seen. When true, new data is appended to the | ||
| 123 | * stream of outgoing bytes. When overflow occurs, sysex data is | ||
| 124 | * dropped (until an EOX or non-real-timei status byte is seen) so | ||
| 125 | * that, if the overflow condition is cleared, we don't start | ||
| 126 | * sending data from the middle of a sysex message. If a sysex | ||
| 127 | * message is filtered, sysex_in_progress is false, causing the | ||
| 128 | * message to be dropped. */ | ||
| 129 | PmMessage message; /* buffer for 4 bytes of sysex data */ | ||
| 130 | int message_count; /* how many bytes in sysex_message so far */ | ||
| 131 | int short_message_count; /* how many bytes are expected in short message */ | ||
| 132 | unsigned char running_status; /* running status byte or zero if none */ | ||
| 133 | int32_t filters; /* flags that filter incoming message classes */ | ||
| 134 | int32_t channel_mask; /* filter incoming messages based on channel */ | ||
| 135 | PmTimestamp last_msg_time; /* timestamp of last message */ | ||
| 136 | PmTimestamp sync_time; /* time of last synchronization */ | ||
| 137 | PmTimestamp now; /* set by PmWrite to current time */ | ||
| 138 | int first_message; /* initially true, used to run first synchronization */ | ||
| 139 | pm_fns_type dictionary; /* implementation functions */ | ||
| 140 | void *api_info; /* system-dependent state */ | ||
| 141 | /* the following are used to expedite sysex data */ | ||
| 142 | /* on windows, in debug mode, based on some profiling, these optimizations | ||
| 143 | * cut the time to process sysex bytes from about 7.5 to 0.26 usec/byte, | ||
| 144 | * but this does not count time in the driver, so I don't know if it is | ||
| 145 | * important | ||
| 146 | */ | ||
| 147 | unsigned char *fill_base; /* addr of ptr to sysex data */ | ||
| 148 | uint32_t *fill_offset_ptr; /* offset of next sysex byte */ | ||
| 149 | uint32_t fill_length; /* how many sysex bytes to write */ | ||
| 150 | } PmInternal; | ||
| 151 | |||
| 152 | /* what is the length of this short message? */ | ||
| 153 | int pm_midi_length(PmMessage msg); | ||
| 154 | |||
| 155 | /* defined by system specific implementation, e.g. pmwinmm, used by PortMidi */ | ||
| 156 | void pm_init(void); | ||
| 157 | void pm_term(void); | ||
| 158 | |||
| 159 | /* defined by portMidi, used by pmwinmm */ | ||
| 160 | PmError none_write_short(PmInternal *midi, PmEvent *buffer); | ||
| 161 | PmError none_write_byte(PmInternal *midi, unsigned char byte, | ||
| 162 | PmTimestamp timestamp); | ||
| 163 | PmTimestamp none_synchronize(PmInternal *midi); | ||
| 164 | |||
| 165 | PmError pm_fail_fn(PmInternal *midi); | ||
| 166 | PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp); | ||
| 167 | PmError pm_success_fn(PmInternal *midi); | ||
| 168 | PmError pm_add_interf(char *interf, pm_create_fn create_fn, | ||
| 169 | pm_delete_fn delete_fn); | ||
| 170 | PmError pm_add_device(char *interf, const char *name, int is_input, | ||
| 171 | int is_virtual, void *descriptor, pm_fns_type dictionary); | ||
| 172 | void pm_undo_add_device(int id); | ||
| 173 | uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len, | ||
| 174 | PmTimestamp timestamp); | ||
| 175 | void pm_read_short(PmInternal *midi, PmEvent *event); | ||
| 176 | |||
| 177 | #define none_write_flush pm_fail_timestamp_fn | ||
| 178 | #define none_sysex pm_fail_timestamp_fn | ||
| 179 | #define none_poll pm_fail_fn | ||
| 180 | #define success_poll pm_success_fn | ||
| 181 | |||
| 182 | #define MIDI_REALTIME_MASK 0xf8 | ||
| 183 | #define is_real_time(msg) \ | ||
| 184 | ((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK) | ||
| 185 | |||
| 186 | #ifdef __cplusplus | ||
| 187 | } | ||
| 188 | #endif | ||
| 189 | |||
| 190 | /** @endcond */ | ||
