3 * Copyright (c) 2007-2010 SlimDX Group
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "../stack_array.h"
27 #include "../ComObject.h"
28 #include "../Utilities.h"
29 #include "../DataStream.h"
31 #include "../multimedia/WaveFormat.h"
32 #include "../multimedia/WaveFormatExtensible.h"
34 #include "DirectSoundException.h"
36 #include "CaptureBuffer.h"
38 using namespace System;
39 using namespace System::Reflection;
40 using namespace SlimDX::Multimedia;
46 CaptureBuffer::CaptureBuffer( DirectSoundCapture^ capture, CaptureBufferDescription description )
48 DSCBUFFERDESC value = description.ToUnmanaged();
49 IDirectSoundCaptureBuffer* buffer;
51 HRESULT hr = capture->InternalPointer->CreateCaptureBuffer( &value, &buffer, NULL );
53 delete[] value.lpDSCFXDesc;
54 delete[] value.lpwfxFormat;
56 if( RECORD_DSOUND( hr ).IsFailure )
57 throw gcnew DirectSoundException( Result::Last );
59 IDirectSoundCaptureBuffer8* dsCapture;
60 hr = buffer->QueryInterface( IID_IDirectSoundCaptureBuffer8, reinterpret_cast<void**>( &dsCapture ) );
62 if( RECORD_DSOUND( hr ).IsFailure )
63 throw gcnew DirectSoundException( Result::Last );
65 Construct( dsCapture );
68 Result CaptureBuffer::Start( bool looping )
70 HRESULT hr = InternalPointer->Start( looping ? DSCBSTART_LOOPING : 0 );
71 return RECORD_DSOUND( hr );
74 Result CaptureBuffer::Stop()
76 HRESULT hr = InternalPointer->Stop();
77 return RECORD_DSOUND( hr );
80 DataStream^ CaptureBuffer::Lock( int offset, int sizeBytes, bool lockEntireBuffer, [Out] DataStream^% secondPart )
88 HRESULT hr = InternalPointer->Lock( offset, sizeBytes, &buffer1, &size1, &buffer2, &size2, lockEntireBuffer ? DSCBLOCK_ENTIREBUFFER : 0 );
89 if( RECORD_DSOUND( hr ).IsFailure )
92 DataStream^ stream1 = gcnew DataStream( buffer1, size1, true, false, false );
94 secondPart = gcnew DataStream( buffer2, size2, true, false, false );
99 Result CaptureBuffer::Unlock( DataStream^ firstPart, DataStream^ secondPart )
101 void* buffer2 = NULL;
104 if( secondPart != nullptr )
106 buffer2 = secondPart->RawPointer;
107 size2 = static_cast<int>( secondPart->Length );
110 HRESULT hr = InternalPointer->Unlock( firstPart->RawPointer, static_cast<int>( firstPart->Length ), buffer2, size2 );
111 return RECORD_DSOUND( hr );
115 Result CaptureBuffer::Read( array<T>^ data, int bufferOffset, bool lockEntireBuffer )
117 return InternalRead( data, 0, 0, bufferOffset, lockEntireBuffer );
121 Result CaptureBuffer::Read( array<T>^ data, int startIndex, int count, int bufferOffset )
123 return InternalRead( data, startIndex, count, bufferOffset, false );
127 Result CaptureBuffer::InternalRead( array<T>^ data, int startIndex, int count, int bufferOffset, bool lockEntireBuffer )
129 Utilities::CheckArrayBounds( data, startIndex, count );
130 int bytes = static_cast<int>(sizeof(T) * count);
133 DataStream^ stream1 = Lock( bufferOffset, bytes, lockEntireBuffer, stream2 );
135 if( stream1 == nullptr )
138 int count1 = static_cast<int>( stream1->Length ) / sizeof(T);
139 stream1->ReadRange( data, startIndex, count1 );
141 if( stream2 != nullptr && count > count1 )
142 stream2->ReadRange( data, count1 + startIndex, count - count1 );
144 return Unlock( stream1, stream2 );
147 Result CaptureBuffer::SetNotificationPositions( array<NotificationPosition>^ positions )
149 IDirectSoundNotify *pointer;
150 HRESULT hr = InternalPointer->QueryInterface( IID_IDirectSoundNotify, reinterpret_cast<void**>( &pointer ) );
153 return RECORD_DSOUND( hr );
155 stack_array<DSBPOSITIONNOTIFY> notifies = stackalloc( DSBPOSITIONNOTIFY, positions->Length );
156 for( int i = 0; i < positions->Length; i++ )
158 notifies[i].dwOffset = positions[i].Offset;
159 notifies[i].hEventNotify = positions[i].Event->SafeWaitHandle->DangerousGetHandle().ToPointer();
162 hr = pointer->SetNotificationPositions( positions->Length, ¬ifies[0] );
165 return RECORD_DSOUND( hr );
168 WaveFormat^ CaptureBuffer::Format::get()
171 WAVEFORMATEX* format;
174 HRESULT hr = InternalPointer->GetFormat( NULL, 0, &size );
175 if( RECORD_DSOUND( hr ).IsFailure )
178 // Manual Allocation: handled properly in the try/finally clause below
179 format = reinterpret_cast<WAVEFORMATEX*>( new char[size] );
183 hr = InternalPointer->GetFormat( format, size, NULL );
185 if( RECORD_DSOUND( hr ).IsFailure )
188 if( format->wFormatTag == WAVE_FORMAT_EXTENSIBLE )
189 result = WaveFormatExtensible::FromBase( format );
191 result = WaveFormat::FromUnmanaged( *format );
201 array<CaptureEffectResult>^ CaptureBuffer::GetEffectStatus( int effectCount )
203 stack_array<DWORD> results = stackalloc( DWORD, effectCount );
205 HRESULT hr = InternalPointer->GetFXStatus( effectCount, &results[0] );
206 if( RECORD_DSOUND( hr ).IsFailure )
209 array<CaptureEffectResult>^ output = gcnew array<CaptureEffectResult>( effectCount );
211 for( int i = 0; i < effectCount; i++ )
212 output[i] = static_cast<CaptureEffectResult>( results[i] );
218 T CaptureBuffer::GetEffect( int index )
220 GUID guid = Utilities::GetNativeGuidForType( T::typeid );
223 HRESULT hr = InternalPointer->GetObjectInPath( GUID_All_Objects, index, guid, &resultPointer );
224 if( RECORD_DSOUND( hr ).IsFailure )
227 MethodInfo^ method = T::typeid->GetMethod( "FromPointer", BindingFlags::Public | BindingFlags::Static );
228 return safe_cast<T>( method->Invoke( nullptr, gcnew array<Object^> { IntPtr( resultPointer ) } ) );
231 bool CaptureBuffer::WaveMapped::get()
234 caps.dwSize = sizeof( DSCBCAPS );
235 HRESULT hr = InternalPointer->GetCaps( &caps );
237 if( RECORD_DSOUND( hr ).IsFailure )
240 return caps.dwFlags == DSCBCAPS_WAVEMAPPED;
243 int CaptureBuffer::SizeInBytes::get()
246 caps.dwSize = sizeof( DSCBCAPS );
247 HRESULT hr = InternalPointer->GetCaps( &caps );
249 if( RECORD_DSOUND( hr ).IsFailure )
252 return caps.dwBufferBytes;
255 bool CaptureBuffer::Capturing::get()
258 HRESULT hr = InternalPointer->GetStatus( &status );
260 if( RECORD_DSOUND( hr ).IsFailure )
263 return ( status & DSCBSTATUS_CAPTURING ) != 0;
266 bool CaptureBuffer::Looping::get()
269 HRESULT hr = InternalPointer->GetStatus( &status );
271 if( RECORD_DSOUND( hr ).IsFailure )
274 return ( status & DSCBSTATUS_LOOPING ) != 0;
277 int CaptureBuffer::CurrentCapturePosition::get()
279 DWORD capturePosition;
280 HRESULT hr = InternalPointer->GetCurrentPosition( &capturePosition, NULL );
282 if( RECORD_DSOUND( hr ).IsFailure )
285 return capturePosition;
288 int CaptureBuffer::CurrentReadPosition::get()
291 HRESULT hr = InternalPointer->GetCurrentPosition( NULL, &readPosition );
293 if( RECORD_DSOUND( hr ).IsFailure )