remove reference "const int32_t&" -> const int32_t"
[ardour.git] / libs / ardour / ardour / event_ring_buffer.h
1 /*
2     Copyright (C) 2006-2014 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifndef __ardour_event_ring_buffer_h__
21 #define __ardour_event_ring_buffer_h__
22
23 #include <algorithm>
24 #include <iostream>
25
26 #include "pbd/ringbufferNPT.h"
27
28 #include "evoral/EventSink.hpp"
29 #include "evoral/types.hpp"
30
31 namespace ARDOUR {
32
33 /** A RingBuffer of events (generic time-stamped binary "blobs").
34  *
35  * This packs a timestamp, size, and size bytes of data flat into the buffer.
36  * Useful for MIDI events, OSC messages, etc.
37  *
38  * Note: the uint8_t template argument to RingBufferNPT<> indicates "byte
39  * oriented data", not anything particular linked to MIDI or any other
40  * possible interpretation of uint8_t.
41  */
42 template<typename Time>
43 class EventRingBuffer : public PBD::RingBufferNPT<uint8_t>
44                       , public Evoral::EventSink<Time> {
45 public:
46
47         /** @param capacity Ringbuffer capacity in bytes.
48          */
49         EventRingBuffer(size_t capacity) : PBD::RingBufferNPT<uint8_t>(capacity)
50         {}
51
52         inline size_t capacity() const { return bufsize(); }
53
54         /** Peek at the ringbuffer (read w/o advancing read pointer).
55          * @return how much has been peeked (wraps around if read exceeds
56          * the end of the buffer):
57          * <pre>
58          * |===========--------------R=============================|
59          *            read-pointer---^
60          * </pre>
61          */
62         inline bool peek (uint8_t*, size_t size);
63
64         inline uint32_t write(Time  time, Evoral::EventType  type, uint32_t  size, const uint8_t* buf);
65         inline bool     read (Time* time, Evoral::EventType* type, uint32_t* size,       uint8_t* buf);
66 };
67
68 template<typename Time>
69 inline bool
70 EventRingBuffer<Time>::peek (uint8_t* buf, size_t size)
71 {
72         PBD::RingBufferNPT<uint8_t>::rw_vector vec;
73
74         get_read_vector (&vec);
75
76         if (vec.len[0] + vec.len[1] < size) {
77                 return false;
78         }
79
80         if (vec.len[0] > 0) {
81                 memcpy (buf, vec.buf[0], std::min (vec.len[0], size));
82         }
83
84         if (vec.len[0] < size) {
85                 if (vec.len[1]) {
86                         memcpy (buf + vec.len[0], vec.buf[1], size - vec.len[0]);
87                 }
88         }
89
90         return true;
91 }
92
93 template<typename Time>
94 inline bool
95 EventRingBuffer<Time>::read(Time* time, Evoral::EventType* type, uint32_t* size, uint8_t* buf)
96 {
97         if (PBD::RingBufferNPT<uint8_t>::read ((uint8_t*)time, sizeof (Time)) != sizeof (Time)) {
98                 return false;
99         }
100
101         if (PBD::RingBufferNPT<uint8_t>::read ((uint8_t*)type, sizeof(Evoral::EventType)) != sizeof (Evoral::EventType)) {
102                 return false;
103         }
104
105         if (PBD::RingBufferNPT<uint8_t>::read ((uint8_t*)size, sizeof(uint32_t)) != sizeof (uint32_t)) {
106                 return false;
107         }
108
109         if (PBD::RingBufferNPT<uint8_t>::read (buf, *size) != *size) {
110                 return false;
111         }
112
113         return true;
114 }
115
116 template<typename Time>
117 inline uint32_t
118 EventRingBuffer<Time>::write(Time time, Evoral::EventType type, uint32_t size, const uint8_t* buf)
119 {
120         if (!buf || write_space() < (sizeof(Time) + sizeof(Evoral::EventType) + sizeof(uint32_t) + size)) {
121                 return 0;
122         } else {
123                 PBD::RingBufferNPT<uint8_t>::write ((uint8_t*)&time, sizeof(Time));
124                 PBD::RingBufferNPT<uint8_t>::write ((uint8_t*)&type, sizeof(Evoral::EventType));
125                 PBD::RingBufferNPT<uint8_t>::write ((uint8_t*)&size, sizeof(uint32_t));
126                 PBD::RingBufferNPT<uint8_t>::write (buf, size);
127                 return size;
128         }
129 }
130
131 } // namespace ARDOUR
132
133 #endif // __ardour_event_ring_buffer_h__