-template<typename T>
-inline void
-MidiRingBufferBase<T>::write(size_t size, const T* src)
-{
- const size_t priv_write_ptr = g_atomic_int_get(&_write_ptr);
-
- if (priv_write_ptr + size <= _size) {
- memcpy(&_buf[priv_write_ptr], src, size);
- g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size);
- } else {
- const size_t this_size = _size - priv_write_ptr;
- assert(this_size < size);
- assert(priv_write_ptr + this_size <= _size);
- memcpy(&_buf[priv_write_ptr], src, this_size);
- memcpy(&_buf[0], src+this_size, size - this_size);
- g_atomic_int_set(&_write_ptr, size - this_size);
- }
-}
-
-
-/* ******************************************************************** */
-
-
-/** A MIDI RingBuffer.
- *
- * This is timestamps and MIDI packed sequentially into a single buffer, similarly
- * to LV2 MIDI. The buffer looks like this:
- *
- * [timestamp][size][size bytes of raw MIDI][timestamp][size][etc..]
- */
-class MidiRingBuffer : public MidiRingBufferBase<Byte> {
-public:
- /** @param size Size in bytes.
- */
- MidiRingBuffer(size_t size)
- : MidiRingBufferBase<Byte>(size), _channel_mask(0x0000FFFF)
- {}
-
- size_t write(double time, size_t size, const Byte* buf);
- bool read(double* time, size_t* size, Byte* buf);
-
- bool read_prefix(double* time, size_t* size);
- bool read_contents(size_t size, Byte* buf);
-
- size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0);
-
- /** Set the channel filtering mode.
- * @param mask If mode is FilterChannels, each bit represents a midi channel:
- * bit 0 = channel 0, bit 1 = channel 1 etc. the read and write methods will only
- * process events whose channel bit is 1.
- * If mode is ForceChannel, mask is simply a channel number which all events will
- * be forced to while reading.
- */
- void set_channel_mode(ChannelMode mode, uint16_t mask) {
- g_atomic_int_set(&_channel_mask, ((uint16_t)mode << 16) | mask);
- }
-
- ChannelMode get_channel_mode() const {
- return static_cast<ChannelMode>((g_atomic_int_get(&_channel_mask) & 0xFFFF0000) >> 16);
- }
-
- uint16_t get_channel_mask() const {
- return static_cast<ChannelMode>((g_atomic_int_get(&_channel_mask) & 0x0000FFFF));
- }
-
-protected:
- inline bool is_channel_event(Byte event_type_byte) {
- // mask out channel information
- event_type_byte &= 0xF0;
- // midi channel events range from 0x80 to 0xE0
- return (0x80 <= event_type_byte) && (event_type_byte <= 0xE0);
- }
-
-private:
- volatile uint32_t _channel_mask; // 16 bits mode, 16 bits mask
-};
-
-
-inline bool
-MidiRingBuffer::read(double* time, size_t* size, Byte* buf)
-{
- bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)time);
-
- if (success) {
- success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)size);
- }
- if (success) {
- success = MidiRingBufferBase<Byte>::full_read(*size, buf);
- }
-
- return success;
-}
-
-
-/** Read the time and size of an event. This call MUST be immediately proceeded
- * by a call to read_contents (or the read pointer will be garabage).
- */
-inline bool
-MidiRingBuffer::read_prefix(double* time, size_t* size)
-{
- bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)time);
- if (success) {
- success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)size);
- }
-
- return success;
-}
-
-
-/** Read the contenst of an event. This call MUST be immediately preceeded
- * by a call to read_prefix (or the returned even will be garabage).