• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "OISConfig.h"
2 #ifdef OIS_LIRC_SUPPORT
3 /*
4 The zlib/libpng License
5 
6 Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
7 
8 This software is provided 'as-is', without any express or implied warranty. In no event will
9 the authors be held liable for any damages arising from the use of this software.
10 
11 Permission is granted to anyone to use this software for any purpose, including commercial
12 applications, and to alter it and redistribute it freely, subject to the following
13 restrictions:
14 
15     1. The origin of this software must not be misrepresented; you must not claim that
16 		you wrote the original software. If you use this software in a product,
17 		an acknowledgment in the product documentation would be appreciated but is
18 		not required.
19 
20     2. Altered source versions must be plainly marked as such, and must not be
21 		misrepresented as being the original software.
22 
23     3. This notice may not be removed or altered from any source distribution.
24 
25  # ------------------------#
26  # Original License follows:
27  # ------------------------#
28 
29  * PortAudio Portable Real-Time Audio Library
30  * Latest version at: http://www.audiomulch.com/portaudio/
31  * <platform> Implementation
32  * Copyright (c) 1999-2000 <author(s)>
33  *
34  * Permission is hereby granted, free of charge, to any person obtaining
35  * a copy of this software and associated documentation files
36  * (the "Software"), to deal in the Software without restriction,
37  * including without limitation the rights to use, copy, modify, merge,
38  * publish, distribute, sublicense, and/or sell copies of the Software,
39  * and to permit persons to whom the Software is furnished to do so,
40  * subject to the following conditions:
41  *
42  * The above copyright notice and this permission notice shall be
43  * included in all copies or substantial portions of the Software.
44  *
45  * Any person wishing to distribute modifications to the Software is
46  * requested to send the modifications to the original developer so that
47  * they can be incorporated into the canonical version.
48  *
49  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
53  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
54  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
55  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56  */
57 #ifndef OIS_LIRCRingBuffer_H
58 #define OIS_LIRCRingBuffer_H
59 
60 #include "OISPrereqs.h"
61 
62 namespace OIS
63 {
64 	struct LIRCEvent
65 	{
66 		//! high bit (0x80000000) will be on if button pushed, else it was released
67 		unsigned int button;
68 	};
69 
70 	/// <summary>
71 	/// Ring Buffer (fifo) used to store 16bit pcm data
72 	/// </summary>
73 	class LIRCRingBuffer
74 	{
75 	private:
76 		//! Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init
77 		int bufferSize;
78 		//! Used for wrapping indices with extra bit to distinguish full/empty.
79 		int bigMask;
80 		// Used for fitting indices to buffer.
81 		int smallMask;
82 
83 		// Buffer holding the actual event buffers
84 		LIRCEvent *buffer;
85 
86 		//! Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex.
87 		volatile int writeIndex;
88 
89 		//! Index of next readable byte. Set by RingBuffer_AdvanceReadIndex.
90 		volatile int readIndex;
91 
92 	public:
LIRCRingBuffer(unsigned int numEntries)93 		LIRCRingBuffer( unsigned int numEntries )
94 		{
95 			numEntries = RoundUpToNextPowerOf2( numEntries );
96 
97 			//2 bytes per short
98 			bufferSize = (int)numEntries;
99 			buffer = new LIRCEvent[numEntries];
100 
101 			Flush();
102 
103 			bigMask = (int)(numEntries*2)-1;
104 			smallMask = (int)(numEntries)-1;
105 		}
106 
~LIRCRingBuffer()107 		~LIRCRingBuffer()
108 		{
109 			delete buffer;
110 		}
111 
RoundUpToNextPowerOf2(unsigned int n)112 		unsigned int RoundUpToNextPowerOf2( unsigned int n )
113 		{
114 			int numBits = 0;
115 			if( ((n-1) & n) == 0)
116 			return n; //Already Power of two.
117 
118 			while( n > 0 )
119 			{
120 				n= n>>1;
121 				numBits++;
122 			}
123 			return (unsigned int)(1<<numBits);
124 		}
125 
126 
GetReadAvailable()127 		int GetReadAvailable( )
128 		{
129 			return ( (writeIndex - readIndex) & bigMask );
130 		}
131 
132 
GetWriteAvailable()133 		int GetWriteAvailable( )
134 		{
135 			return ( bufferSize - GetReadAvailable());
136 		}
137 
138 
Write(LIRCEvent * data,int numEntries)139 		int Write( LIRCEvent *data, int numEntries )
140 		{
141 			int size1 = 0, size2 = 0, numWritten;
142 			int data1Ptr = 0, data2Ptr = 0;
143 
144 			numWritten = GetWriteRegions( numEntries, data1Ptr, size1, data2Ptr, size2 );
145 
146 			if( size2 > 0 )
147 			{
148 				//copy to two parts
149 				memcpy( &buffer[data1Ptr], data, sizeof(LIRCEvent) * size1 );
150 				//Array.Copy( data, offsetPtr, buffer, data1Ptr, size1 );
151 				memcpy( &buffer[data2Ptr], &data[size1], sizeof(LIRCEvent) * size2 );
152 				//Array.Copy( data, offsetPtr + size1, buffer, data2Ptr, size2 );
153 			}
154 			else
155 			{	//Copy all continous
156 				memcpy( &buffer[data1Ptr], data, sizeof(LIRCEvent) * size1 );
157 				//Array.Copy( data, offsetPtr, buffer, data1Ptr, size1 );
158 			}
159 			AdvanceWriteIndex( numWritten );
160 			return numWritten;
161 		}
162 
163 
164 		/// <summary>
165 		/// Reads requested number of entries into sent array.
166 		/// Returns number written
167 		/// </summary>
Read(LIRCEvent * data,int numEntries)168 		int Read( LIRCEvent *data, int numEntries )
169 		{
170 			int size1 = 0, size2 = 0, numRead, data1Ptr = 0, data2Ptr = 0;
171 
172 			numRead = GetReadRegions( numEntries, data1Ptr, size1, data2Ptr, size2 );
173 
174 			if( size2 > 0 )
175 			{
176 				memcpy( data, &buffer[data1Ptr], sizeof(LIRCEvent) * size1 );
177 				//Array.Copy( buffer, data1Ptr, data, 0, size1 );
178 				memcpy( &data[size1], &buffer[data2Ptr], sizeof(LIRCEvent) * size2 );
179 				//Array.Copy( buffer, data2Ptr, data, size1, size2 );
180 			}
181 			else
182 				memcpy( data, &buffer[data1Ptr], sizeof(LIRCEvent) * size1 );
183 				//Array.Copy( buffer, data1Ptr, data, 0, size1 );
184 
185 			AdvanceReadIndex( numRead );
186 			return numRead;
187 		}
188 
189 	private:
190 
GetWriteRegions(int numEntries,int & dataPtr1,int & sizePtr1,int & dataPtr2,int & sizePtr2)191 		int GetWriteRegions( int numEntries, int &dataPtr1, int &sizePtr1,
192 							 int &dataPtr2, int &sizePtr2 )
193 		{
194 			int   index;
195 			int   available = GetWriteAvailable();
196 			if( numEntries > available )
197 				numEntries = available;
198 
199 			//Check to see if write is not contiguous.
200 			index = writeIndex & smallMask;
201 			if( (index + numEntries) > bufferSize )
202 			{
203 				//Write data in two blocks that wrap the buffer.
204 				int   firstHalf = bufferSize - index;
205 				dataPtr1 = index;//&buffer[index];
206 				sizePtr1 = firstHalf;
207 				dataPtr2 = 0;//&buffer[0];
208 				sizePtr2 = numEntries - firstHalf;
209 			}
210 			else
211 			{
212 				dataPtr1 = index;//&buffer[index];
213 				sizePtr1 = numEntries;
214 				dataPtr2 = 0;
215 				sizePtr2 = 0;
216 			}
217 			return numEntries;
218 		}
219 
220 
GetReadRegions(int numEntries,int & dataPtr1,int & sizePtr1,int & dataPtr2,int & sizePtr2)221 		int GetReadRegions( int numEntries, int &dataPtr1, int &sizePtr1, int &dataPtr2, int &sizePtr2 )
222 		{
223 			int   index;
224 			int   available = GetReadAvailable( );
225 			if( numEntries > available )
226 				numEntries = available;
227 
228 			// Check to see if read is not contiguous
229 			index = readIndex & smallMask;
230 			if( (index + numEntries) > bufferSize )
231 			{
232 				// Write data in two blocks that wrap the buffer
233 				int firstHalf = bufferSize - index;
234 				dataPtr1 = index;//&buffer[index];
235 				sizePtr1 = firstHalf;
236 				dataPtr2 = 0;//&buffer[0];
237 				sizePtr2 = numEntries - firstHalf;
238 			}
239 			else
240 			{
241 				dataPtr1 = index;//&buffer[index];
242 				sizePtr1 = numEntries;
243 				dataPtr2 = 0;
244 				sizePtr2 = 0;
245 			}
246 			return numEntries;
247 		}
248 
249 
AdvanceWriteIndex(int numEntries)250 		int AdvanceWriteIndex( int numEntries )
251 		{
252 			 return writeIndex = (writeIndex + numEntries) & bigMask;
253 		}
254 
255 
AdvanceReadIndex(int numEntries)256 		int AdvanceReadIndex( int numEntries )
257 		{
258 			return readIndex = (readIndex + numEntries) & bigMask;
259 		}
260 
261 
Flush()262 		void Flush( )
263 		{
264 			writeIndex = readIndex = 0;
265 		}
266 	};
267 }
268 #endif //#define OIS_LIRCRingBuffer_H
269 #endif
270