OSDN Git Service

作業部屋#50802 画面キャプチャができなくなっていた問題を暫定対応(F12キー固定で対応中)
[dtxmaniaxg-verk/dtxmaniaxg-verk-git.git] / SlimDXc_Jun2010(VC++2008) / source / directsound / CaptureBuffer.cpp
1 #include "stdafx.h"
2 /*
3 * Copyright (c) 2007-2010 SlimDX Group
4
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:
11
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14
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
21 * THE SOFTWARE.
22 */
23 #include <windows.h>
24 #include <dsound.h>
25
26 #include "../stack_array.h"
27 #include "../ComObject.h"
28 #include "../Utilities.h"
29 #include "../DataStream.h"
30
31 #include "../multimedia/WaveFormat.h"
32 #include "../multimedia/WaveFormatExtensible.h"
33
34 #include "DirectSoundException.h"
35
36 #include "CaptureBuffer.h"
37
38 using namespace System;
39 using namespace System::Reflection;
40 using namespace SlimDX::Multimedia;
41
42 namespace SlimDX
43 {
44 namespace DirectSound
45 {
46         CaptureBuffer::CaptureBuffer( DirectSoundCapture^ capture, CaptureBufferDescription description )
47         {
48                 DSCBUFFERDESC value = description.ToUnmanaged();
49                 IDirectSoundCaptureBuffer* buffer;
50
51                 HRESULT hr = capture->InternalPointer->CreateCaptureBuffer( &value, &buffer, NULL );
52
53                 delete[] value.lpDSCFXDesc;
54                 delete[] value.lpwfxFormat;
55
56                 if( RECORD_DSOUND( hr ).IsFailure )
57                         throw gcnew DirectSoundException( Result::Last );
58
59                 IDirectSoundCaptureBuffer8* dsCapture;
60                 hr = buffer->QueryInterface( IID_IDirectSoundCaptureBuffer8, reinterpret_cast<void**>( &dsCapture ) );
61
62                 if( RECORD_DSOUND( hr ).IsFailure )
63                         throw gcnew DirectSoundException( Result::Last );
64
65                 Construct( dsCapture );
66         }
67         
68         Result CaptureBuffer::Start( bool looping )
69         {
70                 HRESULT hr = InternalPointer->Start( looping ? DSCBSTART_LOOPING : 0 );
71                 return RECORD_DSOUND( hr );
72         }
73
74         Result CaptureBuffer::Stop()
75         {
76                 HRESULT hr = InternalPointer->Stop();
77                 return RECORD_DSOUND( hr );
78         }
79
80         DataStream^ CaptureBuffer::Lock( int offset, int sizeBytes, bool lockEntireBuffer, [Out] DataStream^% secondPart )
81         {
82                 void* buffer1;
83                 void* buffer2;
84                 DWORD size1, size2;
85
86                 secondPart = nullptr;
87
88                 HRESULT hr = InternalPointer->Lock( offset, sizeBytes, &buffer1, &size1, &buffer2, &size2, lockEntireBuffer ? DSCBLOCK_ENTIREBUFFER : 0 );
89                 if( RECORD_DSOUND( hr ).IsFailure )
90                         return nullptr;
91
92                 DataStream^ stream1 = gcnew DataStream( buffer1, size1, true, false, false );
93                 if( buffer2 != NULL )
94                         secondPart = gcnew DataStream( buffer2, size2, true, false, false );
95
96                 return stream1;
97         }
98
99         Result CaptureBuffer::Unlock( DataStream^ firstPart, DataStream^ secondPart )
100         {
101                 void* buffer2 = NULL;
102                 int size2 = 0;
103
104                 if( secondPart != nullptr )
105                 {
106                         buffer2 = secondPart->RawPointer;
107                         size2 = static_cast<int>( secondPart->Length );
108                 }
109
110                 HRESULT hr = InternalPointer->Unlock( firstPart->RawPointer, static_cast<int>( firstPart->Length ), buffer2, size2 );
111                 return RECORD_DSOUND( hr );
112         }
113
114         generic<typename T>
115         Result CaptureBuffer::Read( array<T>^ data, int bufferOffset, bool lockEntireBuffer )
116         {
117                 return InternalRead( data, 0, 0, bufferOffset, lockEntireBuffer );
118         }
119
120         generic<typename T>
121         Result CaptureBuffer::Read( array<T>^ data, int startIndex, int count, int bufferOffset )
122         {
123                 return InternalRead( data, startIndex, count, bufferOffset, false );
124         }
125
126         generic<typename T>
127         Result CaptureBuffer::InternalRead( array<T>^ data, int startIndex, int count, int bufferOffset, bool lockEntireBuffer )
128         {
129                 Utilities::CheckArrayBounds( data, startIndex, count );
130                 int bytes = static_cast<int>(sizeof(T) * count);
131
132                 DataStream^ stream2;
133                 DataStream^ stream1 = Lock( bufferOffset, bytes, lockEntireBuffer, stream2 );
134
135                 if( stream1 == nullptr )
136                         return Result::Last;
137
138                 int count1 = static_cast<int>( stream1->Length ) / sizeof(T);
139                 stream1->ReadRange( data, startIndex, count1 );
140
141                 if( stream2 != nullptr && count > count1 )
142                         stream2->ReadRange( data, count1 + startIndex, count - count1 );
143
144                 return Unlock( stream1, stream2 );
145         }
146
147         Result CaptureBuffer::SetNotificationPositions( array<NotificationPosition>^ positions )
148         {
149                 IDirectSoundNotify *pointer;
150                 HRESULT hr = InternalPointer->QueryInterface( IID_IDirectSoundNotify, reinterpret_cast<void**>( &pointer ) );
151
152                 if( FAILED( hr ) )
153                         return RECORD_DSOUND( hr );
154
155                 stack_array<DSBPOSITIONNOTIFY> notifies = stackalloc( DSBPOSITIONNOTIFY, positions->Length );
156                 for( int i = 0; i < positions->Length; i++ )
157                 {
158                         notifies[i].dwOffset = positions[i].Offset;
159                         notifies[i].hEventNotify = positions[i].Event->SafeWaitHandle->DangerousGetHandle().ToPointer();
160                 }
161
162                 hr = pointer->SetNotificationPositions( positions->Length, &notifies[0] );
163                 pointer->Release();
164
165                 return RECORD_DSOUND( hr );
166         }
167
168         WaveFormat^ CaptureBuffer::Format::get()
169         {
170                 WaveFormat^ result;
171                 WAVEFORMATEX* format;
172                 DWORD size;
173
174                 HRESULT hr = InternalPointer->GetFormat( NULL, 0, &size );
175                 if( RECORD_DSOUND( hr ).IsFailure )
176                         return nullptr;
177
178                 // Manual Allocation: handled properly in the try/finally clause below
179                 format = reinterpret_cast<WAVEFORMATEX*>( new char[size] );
180
181                 try
182                 {
183                         hr = InternalPointer->GetFormat( format, size, NULL );
184
185                         if( RECORD_DSOUND( hr ).IsFailure )
186                                 return nullptr;
187
188                         if( format->wFormatTag == WAVE_FORMAT_EXTENSIBLE )
189                                 result = WaveFormatExtensible::FromBase( format );
190                         else 
191                                 result = WaveFormat::FromUnmanaged( *format );
192
193                         return result;
194                 }
195                 finally
196                 {
197                         delete[] format;
198                 }
199         }
200
201         array<CaptureEffectResult>^ CaptureBuffer::GetEffectStatus( int effectCount )
202         {
203                 stack_array<DWORD> results = stackalloc( DWORD, effectCount );
204
205                 HRESULT hr = InternalPointer->GetFXStatus( effectCount, &results[0] );
206                 if( RECORD_DSOUND( hr ).IsFailure )
207                         return nullptr;
208
209                 array<CaptureEffectResult>^ output = gcnew array<CaptureEffectResult>( effectCount );
210
211                 for( int i = 0; i < effectCount; i++ )
212                         output[i] = static_cast<CaptureEffectResult>( results[i] );
213
214                 return output;
215         }
216
217         generic<typename T>
218         T CaptureBuffer::GetEffect( int index )
219         {
220                 GUID guid = Utilities::GetNativeGuidForType( T::typeid );
221                 void *resultPointer;
222
223                 HRESULT hr = InternalPointer->GetObjectInPath( GUID_All_Objects, index, guid, &resultPointer );
224                 if( RECORD_DSOUND( hr ).IsFailure )
225                         return T();
226
227                 MethodInfo^ method = T::typeid->GetMethod( "FromPointer", BindingFlags::Public | BindingFlags::Static );
228                 return safe_cast<T>( method->Invoke( nullptr, gcnew array<Object^> { IntPtr( resultPointer ) } ) );
229         }
230
231         bool CaptureBuffer::WaveMapped::get()
232         {
233                 DSCBCAPS caps;
234                 caps.dwSize = sizeof( DSCBCAPS );
235                 HRESULT hr = InternalPointer->GetCaps( &caps );
236
237                 if( RECORD_DSOUND( hr ).IsFailure )
238                         return false;
239
240                 return caps.dwFlags == DSCBCAPS_WAVEMAPPED;
241         }
242
243         int CaptureBuffer::SizeInBytes::get()
244         {
245                 DSCBCAPS caps;
246                 caps.dwSize = sizeof( DSCBCAPS );
247                 HRESULT hr = InternalPointer->GetCaps( &caps );
248
249                 if( RECORD_DSOUND( hr ).IsFailure )
250                         return 0;
251
252                 return caps.dwBufferBytes;
253         }
254
255         bool CaptureBuffer::Capturing::get()
256         {
257                 DWORD status;
258                 HRESULT hr = InternalPointer->GetStatus( &status );
259                 
260                 if( RECORD_DSOUND( hr ).IsFailure )
261                         return false;
262
263                 return ( status & DSCBSTATUS_CAPTURING ) != 0;
264         }
265
266         bool CaptureBuffer::Looping::get()
267         {
268                 DWORD status;
269                 HRESULT hr = InternalPointer->GetStatus( &status );
270                 
271                 if( RECORD_DSOUND( hr ).IsFailure )
272                         return false;
273
274                 return ( status & DSCBSTATUS_LOOPING ) != 0;
275         }
276
277         int CaptureBuffer::CurrentCapturePosition::get()
278         {
279                 DWORD capturePosition;
280                 HRESULT hr = InternalPointer->GetCurrentPosition( &capturePosition, NULL );
281                 
282                 if( RECORD_DSOUND( hr ).IsFailure )
283                         return 0;
284
285                 return capturePosition;
286         }
287
288         int CaptureBuffer::CurrentReadPosition::get()
289         {
290                 DWORD readPosition;
291                 HRESULT hr = InternalPointer->GetCurrentPosition( NULL, &readPosition );
292                 
293                 if( RECORD_DSOUND( hr ).IsFailure )
294                         return 0;
295
296                 return readPosition;
297         }
298 }
299 }