4 * Copyright 2012 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "amstream_private.h"
23 #include "wine/debug.h"
24 #include "wine/strmbase.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(amstream
);
28 static const WCHAR sink_id
[] = L
"I{A35FF56B-9FDA-11D0-8FDF-00C04FD9189D}";
32 IAMMediaStream IAMMediaStream_iface
;
33 IAudioMediaStream IAudioMediaStream_iface
;
34 IMemInputPin IMemInputPin_iface
;
38 IMultiMediaStream
* parent
;
40 STREAM_TYPE stream_type
;
42 IMediaStreamFilter
*filter
;
45 IMemAllocator
*allocator
;
53 IAudioStreamSample IAudioStreamSample_iface
;
55 struct audio_stream
*parent
;
56 IAudioData
*audio_data
;
57 } IAudioStreamSampleImpl
;
59 static inline IAudioStreamSampleImpl
*impl_from_IAudioStreamSample(IAudioStreamSample
*iface
)
61 return CONTAINING_RECORD(iface
, IAudioStreamSampleImpl
, IAudioStreamSample_iface
);
64 /*** IUnknown methods ***/
65 static HRESULT WINAPI
IAudioStreamSampleImpl_QueryInterface(IAudioStreamSample
*iface
,
66 REFIID riid
, void **ret_iface
)
68 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(riid
), ret_iface
);
70 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
71 IsEqualGUID(riid
, &IID_IStreamSample
) ||
72 IsEqualGUID(riid
, &IID_IAudioStreamSample
))
74 IAudioStreamSample_AddRef(iface
);
81 ERR("(%p)->(%s,%p),not found\n", iface
, debugstr_guid(riid
), ret_iface
);
85 static ULONG WINAPI
IAudioStreamSampleImpl_AddRef(IAudioStreamSample
*iface
)
87 IAudioStreamSampleImpl
*This
= impl_from_IAudioStreamSample(iface
);
88 ULONG ref
= InterlockedIncrement(&This
->ref
);
90 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
95 static ULONG WINAPI
IAudioStreamSampleImpl_Release(IAudioStreamSample
*iface
)
97 IAudioStreamSampleImpl
*This
= impl_from_IAudioStreamSample(iface
);
98 ULONG ref
= InterlockedDecrement(&This
->ref
);
100 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
103 HeapFree(GetProcessHeap(), 0, This
);
108 /*** IStreamSample methods ***/
109 static HRESULT WINAPI
IAudioStreamSampleImpl_GetMediaStream(IAudioStreamSample
*iface
, IMediaStream
**media_stream
)
111 FIXME("(%p)->(%p): stub\n", iface
, media_stream
);
116 static HRESULT WINAPI
IAudioStreamSampleImpl_GetSampleTimes(IAudioStreamSample
*iface
, STREAM_TIME
*start_time
,
117 STREAM_TIME
*end_time
, STREAM_TIME
*current_time
)
119 FIXME("(%p)->(%p,%p,%p): stub\n", iface
, start_time
, end_time
, current_time
);
124 static HRESULT WINAPI
IAudioStreamSampleImpl_SetSampleTimes(IAudioStreamSample
*iface
, const STREAM_TIME
*start_time
,
125 const STREAM_TIME
*end_time
)
127 FIXME("(%p)->(%p,%p): stub\n", iface
, start_time
, end_time
);
132 static HRESULT WINAPI
IAudioStreamSampleImpl_Update(IAudioStreamSample
*iface
, DWORD flags
, HANDLE event
,
133 PAPCFUNC func_APC
, DWORD APC_data
)
135 FIXME("(%p)->(%x,%p,%p,%u): stub\n", iface
, flags
, event
, func_APC
, APC_data
);
140 static HRESULT WINAPI
IAudioStreamSampleImpl_CompletionStatus(IAudioStreamSample
*iface
, DWORD flags
, DWORD milliseconds
)
142 FIXME("(%p)->(%x,%u): stub\n", iface
, flags
, milliseconds
);
147 /*** IAudioStreamSample methods ***/
148 static HRESULT WINAPI
IAudioStreamSampleImpl_GetAudioData(IAudioStreamSample
*iface
, IAudioData
**audio_data
)
150 FIXME("(%p)->(%p): stub\n", iface
, audio_data
);
155 static const struct IAudioStreamSampleVtbl AudioStreamSample_Vtbl
=
157 /*** IUnknown methods ***/
158 IAudioStreamSampleImpl_QueryInterface
,
159 IAudioStreamSampleImpl_AddRef
,
160 IAudioStreamSampleImpl_Release
,
161 /*** IStreamSample methods ***/
162 IAudioStreamSampleImpl_GetMediaStream
,
163 IAudioStreamSampleImpl_GetSampleTimes
,
164 IAudioStreamSampleImpl_SetSampleTimes
,
165 IAudioStreamSampleImpl_Update
,
166 IAudioStreamSampleImpl_CompletionStatus
,
167 /*** IAudioStreamSample methods ***/
168 IAudioStreamSampleImpl_GetAudioData
171 static HRESULT
audiostreamsample_create(struct audio_stream
*parent
, IAudioData
*audio_data
, IAudioStreamSample
**audio_stream_sample
)
173 IAudioStreamSampleImpl
*object
;
175 TRACE("(%p)\n", audio_stream_sample
);
177 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAudioStreamSampleImpl
));
179 return E_OUTOFMEMORY
;
181 object
->IAudioStreamSample_iface
.lpVtbl
= &AudioStreamSample_Vtbl
;
183 object
->parent
= parent
;
184 object
->audio_data
= audio_data
;
186 *audio_stream_sample
= &object
->IAudioStreamSample_iface
;
191 static inline struct audio_stream
*impl_from_IAMMediaStream(IAMMediaStream
*iface
)
193 return CONTAINING_RECORD(iface
, struct audio_stream
, IAMMediaStream_iface
);
196 /*** IUnknown methods ***/
197 static HRESULT WINAPI
audio_IAMMediaStream_QueryInterface(IAMMediaStream
*iface
,
198 REFIID riid
, void **ret_iface
)
200 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
202 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
204 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
205 IsEqualGUID(riid
, &IID_IMediaStream
) ||
206 IsEqualGUID(riid
, &IID_IAMMediaStream
))
208 IAMMediaStream_AddRef(iface
);
212 else if (IsEqualGUID(riid
, &IID_IAudioMediaStream
))
214 IAMMediaStream_AddRef(iface
);
215 *ret_iface
= &This
->IAudioMediaStream_iface
;
218 else if (IsEqualGUID(riid
, &IID_IPin
))
220 IAMMediaStream_AddRef(iface
);
221 *ret_iface
= &This
->IPin_iface
;
224 else if (IsEqualGUID(riid
, &IID_IMemInputPin
))
226 IAMMediaStream_AddRef(iface
);
227 *ret_iface
= &This
->IMemInputPin_iface
;
231 ERR("(%p)->(%s,%p),not found\n", This
, debugstr_guid(riid
), ret_iface
);
232 return E_NOINTERFACE
;
235 static ULONG WINAPI
audio_IAMMediaStream_AddRef(IAMMediaStream
*iface
)
237 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
238 ULONG ref
= InterlockedIncrement(&This
->ref
);
240 TRACE("(%p/%p)->(): new ref = %u\n", iface
, This
, ref
);
245 static ULONG WINAPI
audio_IAMMediaStream_Release(IAMMediaStream
*iface
)
247 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
248 ULONG ref
= InterlockedDecrement(&This
->ref
);
250 TRACE("(%p/%p)->(): new ref = %u\n", iface
, This
, ref
);
254 DeleteCriticalSection(&This
->cs
);
255 HeapFree(GetProcessHeap(), 0, This
);
261 /*** IMediaStream methods ***/
262 static HRESULT WINAPI
audio_IAMMediaStream_GetMultiMediaStream(IAMMediaStream
*iface
,
263 IMultiMediaStream
** multi_media_stream
)
265 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
267 TRACE("(%p/%p)->(%p)\n", This
, iface
, multi_media_stream
);
269 if (!multi_media_stream
)
272 IMultiMediaStream_AddRef(This
->parent
);
273 *multi_media_stream
= This
->parent
;
278 static HRESULT WINAPI
audio_IAMMediaStream_GetInformation(IAMMediaStream
*iface
,
279 MSPID
*purpose_id
, STREAM_TYPE
*type
)
281 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
283 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, purpose_id
, type
);
286 *purpose_id
= This
->purpose_id
;
288 *type
= This
->stream_type
;
293 static HRESULT WINAPI
audio_IAMMediaStream_SetSameFormat(IAMMediaStream
*iface
,
294 IMediaStream
*pStreamThatHasDesiredFormat
, DWORD flags
)
296 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
298 FIXME("(%p/%p)->(%p,%x) stub!\n", This
, iface
, pStreamThatHasDesiredFormat
, flags
);
303 static HRESULT WINAPI
audio_IAMMediaStream_AllocateSample(IAMMediaStream
*iface
,
304 DWORD flags
, IStreamSample
**sample
)
306 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
308 FIXME("(%p/%p)->(%x,%p) stub!\n", This
, iface
, flags
, sample
);
313 static HRESULT WINAPI
audio_IAMMediaStream_CreateSharedSample(IAMMediaStream
*iface
,
314 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
316 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
318 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", This
, iface
, existing_sample
, flags
, sample
);
323 static HRESULT WINAPI
audio_IAMMediaStream_SendEndOfStream(IAMMediaStream
*iface
, DWORD flags
)
325 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
327 FIXME("(%p/%p)->(%x) stub!\n", This
, iface
, flags
);
332 /*** IAMMediaStream methods ***/
333 static HRESULT WINAPI
audio_IAMMediaStream_Initialize(IAMMediaStream
*iface
, IUnknown
*source_object
, DWORD flags
,
334 REFMSPID purpose_id
, const STREAM_TYPE stream_type
)
336 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
338 FIXME("(%p/%p)->(%p,%x,%p,%u) stub!\n", This
, iface
, source_object
, flags
, purpose_id
, stream_type
);
343 static HRESULT WINAPI
audio_IAMMediaStream_SetState(IAMMediaStream
*iface
, FILTER_STATE state
)
345 struct audio_stream
*stream
= impl_from_IAMMediaStream(iface
);
347 TRACE("stream %p, state %u.\n", stream
, state
);
349 EnterCriticalSection(&stream
->cs
);
351 if (stream
->state
== State_Stopped
)
354 stream
->state
= state
;
356 LeaveCriticalSection(&stream
->cs
);
361 static HRESULT WINAPI
audio_IAMMediaStream_JoinAMMultiMediaStream(IAMMediaStream
*iface
,
362 IAMMultiMediaStream
*am_multi_media_stream
)
364 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
366 FIXME("(%p/%p)->(%p) stub!\n", This
, iface
, am_multi_media_stream
);
371 static HRESULT WINAPI
audio_IAMMediaStream_JoinFilter(IAMMediaStream
*iface
, IMediaStreamFilter
*filter
)
373 struct audio_stream
*stream
= impl_from_IAMMediaStream(iface
);
375 TRACE("stream %p, filter %p.\n", stream
, filter
);
377 stream
->filter
= filter
;
382 static HRESULT WINAPI
audio_IAMMediaStream_JoinFilterGraph(IAMMediaStream
*iface
, IFilterGraph
*filtergraph
)
384 struct audio_stream
*This
= impl_from_IAMMediaStream(iface
);
386 FIXME("(%p/%p)->(%p) stub!\n", This
, iface
, filtergraph
);
391 static const struct IAMMediaStreamVtbl audio_IAMMediaStream_vtbl
=
393 audio_IAMMediaStream_QueryInterface
,
394 audio_IAMMediaStream_AddRef
,
395 audio_IAMMediaStream_Release
,
396 audio_IAMMediaStream_GetMultiMediaStream
,
397 audio_IAMMediaStream_GetInformation
,
398 audio_IAMMediaStream_SetSameFormat
,
399 audio_IAMMediaStream_AllocateSample
,
400 audio_IAMMediaStream_CreateSharedSample
,
401 audio_IAMMediaStream_SendEndOfStream
,
402 audio_IAMMediaStream_Initialize
,
403 audio_IAMMediaStream_SetState
,
404 audio_IAMMediaStream_JoinAMMultiMediaStream
,
405 audio_IAMMediaStream_JoinFilter
,
406 audio_IAMMediaStream_JoinFilterGraph
,
409 static inline struct audio_stream
*impl_from_IAudioMediaStream(IAudioMediaStream
*iface
)
411 return CONTAINING_RECORD(iface
, struct audio_stream
, IAudioMediaStream_iface
);
414 /*** IUnknown methods ***/
415 static HRESULT WINAPI
audio_IAudioMediaStream_QueryInterface(IAudioMediaStream
*iface
,
416 REFIID riid
, void **ret_iface
)
418 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
419 TRACE("(%p/%p)->(%s,%p)\n", iface
, This
, debugstr_guid(riid
), ret_iface
);
420 return IAMMediaStream_QueryInterface(&This
->IAMMediaStream_iface
, riid
, ret_iface
);
423 static ULONG WINAPI
audio_IAudioMediaStream_AddRef(IAudioMediaStream
*iface
)
425 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
426 TRACE("(%p/%p)\n", iface
, This
);
427 return IAMMediaStream_AddRef(&This
->IAMMediaStream_iface
);
430 static ULONG WINAPI
audio_IAudioMediaStream_Release(IAudioMediaStream
*iface
)
432 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
433 TRACE("(%p/%p)\n", iface
, This
);
434 return IAMMediaStream_Release(&This
->IAMMediaStream_iface
);
437 /*** IMediaStream methods ***/
438 static HRESULT WINAPI
audio_IAudioMediaStream_GetMultiMediaStream(IAudioMediaStream
*iface
,
439 IMultiMediaStream
**multi_media_stream
)
441 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
443 TRACE("(%p/%p)->(%p)\n", iface
, This
, multi_media_stream
);
445 if (!multi_media_stream
)
448 IMultiMediaStream_AddRef(This
->parent
);
449 *multi_media_stream
= This
->parent
;
454 static HRESULT WINAPI
audio_IAudioMediaStream_GetInformation(IAudioMediaStream
*iface
,
455 MSPID
*purpose_id
, STREAM_TYPE
*type
)
457 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
459 TRACE("(%p/%p)->(%p,%p)\n", iface
, This
, purpose_id
, type
);
462 *purpose_id
= This
->purpose_id
;
464 *type
= This
->stream_type
;
469 static HRESULT WINAPI
audio_IAudioMediaStream_SetSameFormat(IAudioMediaStream
*iface
,
470 IMediaStream
*stream_format
, DWORD flags
)
472 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
474 FIXME("(%p/%p)->(%p,%x) stub!\n", iface
, This
, stream_format
, flags
);
479 static HRESULT WINAPI
audio_IAudioMediaStream_AllocateSample(IAudioMediaStream
*iface
,
480 DWORD flags
, IStreamSample
**sample
)
482 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
484 FIXME("(%p/%p)->(%x,%p) stub!\n", iface
, This
, flags
, sample
);
489 static HRESULT WINAPI
audio_IAudioMediaStream_CreateSharedSample(IAudioMediaStream
*iface
,
490 IStreamSample
*existing_sample
, DWORD flags
, IStreamSample
**sample
)
492 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
494 FIXME("(%p/%p)->(%p,%x,%p) stub!\n", iface
, This
, existing_sample
, flags
, sample
);
499 static HRESULT WINAPI
audio_IAudioMediaStream_SendEndOfStream(IAudioMediaStream
*iface
,
502 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
504 FIXME("(%p/%p)->(%x) stub!\n", iface
, This
, flags
);
509 /*** IAudioMediaStream methods ***/
510 static HRESULT WINAPI
audio_IAudioMediaStream_GetFormat(IAudioMediaStream
*iface
, WAVEFORMATEX
*format
)
512 struct audio_stream
*stream
= impl_from_IAudioMediaStream(iface
);
514 TRACE("stream %p, format %p.\n", stream
, format
);
519 EnterCriticalSection(&stream
->cs
);
523 LeaveCriticalSection(&stream
->cs
);
524 return MS_E_NOSTREAM
;
527 *format
= *(WAVEFORMATEX
*)stream
->mt
.pbFormat
;
529 LeaveCriticalSection(&stream
->cs
);
534 static HRESULT WINAPI
audio_IAudioMediaStream_SetFormat(IAudioMediaStream
*iface
, const WAVEFORMATEX
*format
)
536 struct audio_stream
*stream
= impl_from_IAudioMediaStream(iface
);
538 TRACE("stream %p, format %p.\n", stream
, format
);
543 if (format
->wFormatTag
!= WAVE_FORMAT_PCM
)
546 EnterCriticalSection(&stream
->cs
);
548 if ((stream
->peer
&& memcmp(format
, stream
->mt
.pbFormat
, sizeof(WAVEFORMATEX
)))
549 || (stream
->format
.wFormatTag
&& memcmp(format
, &stream
->format
, sizeof(WAVEFORMATEX
))))
551 LeaveCriticalSection(&stream
->cs
);
555 stream
->format
= *format
;
557 LeaveCriticalSection(&stream
->cs
);
562 static HRESULT WINAPI
audio_IAudioMediaStream_CreateSample(IAudioMediaStream
*iface
, IAudioData
*audio_data
,
563 DWORD flags
, IAudioStreamSample
**sample
)
565 struct audio_stream
*This
= impl_from_IAudioMediaStream(iface
);
567 TRACE("(%p/%p)->(%p,%u,%p)\n", iface
, This
, audio_data
, flags
, sample
);
572 return audiostreamsample_create(This
, audio_data
, sample
);
575 static const struct IAudioMediaStreamVtbl audio_IAudioMediaStream_vtbl
=
577 audio_IAudioMediaStream_QueryInterface
,
578 audio_IAudioMediaStream_AddRef
,
579 audio_IAudioMediaStream_Release
,
580 audio_IAudioMediaStream_GetMultiMediaStream
,
581 audio_IAudioMediaStream_GetInformation
,
582 audio_IAudioMediaStream_SetSameFormat
,
583 audio_IAudioMediaStream_AllocateSample
,
584 audio_IAudioMediaStream_CreateSharedSample
,
585 audio_IAudioMediaStream_SendEndOfStream
,
586 audio_IAudioMediaStream_GetFormat
,
587 audio_IAudioMediaStream_SetFormat
,
588 audio_IAudioMediaStream_CreateSample
,
591 struct enum_media_types
593 IEnumMediaTypes IEnumMediaTypes_iface
;
598 static const IEnumMediaTypesVtbl enum_media_types_vtbl
;
600 static struct enum_media_types
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
602 return CONTAINING_RECORD(iface
, struct enum_media_types
, IEnumMediaTypes_iface
);
605 static HRESULT WINAPI
enum_media_types_QueryInterface(IEnumMediaTypes
*iface
, REFIID iid
, void **out
)
607 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
609 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumMediaTypes
))
611 IEnumMediaTypes_AddRef(iface
);
616 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
618 return E_NOINTERFACE
;
621 static ULONG WINAPI
enum_media_types_AddRef(IEnumMediaTypes
*iface
)
623 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
624 ULONG refcount
= InterlockedIncrement(&enum_media_types
->refcount
);
625 TRACE("%p increasing refcount to %u.\n", enum_media_types
, refcount
);
629 static ULONG WINAPI
enum_media_types_Release(IEnumMediaTypes
*iface
)
631 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
632 ULONG refcount
= InterlockedDecrement(&enum_media_types
->refcount
);
633 TRACE("%p decreasing refcount to %u.\n", enum_media_types
, refcount
);
635 heap_free(enum_media_types
);
639 static HRESULT WINAPI
enum_media_types_Next(IEnumMediaTypes
*iface
, ULONG count
, AM_MEDIA_TYPE
**mts
, ULONG
*ret_count
)
641 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
643 TRACE("iface %p, count %u, mts %p, ret_count %p.\n", iface
, count
, mts
, ret_count
);
648 if (count
&& !enum_media_types
->index
)
650 mts
[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
651 memset(mts
[0], 0, sizeof(AM_MEDIA_TYPE
));
652 mts
[0]->majortype
= MEDIATYPE_Audio
;
653 mts
[0]->subtype
= MEDIASUBTYPE_PCM
;
654 ++enum_media_types
->index
;
656 return count
== 1 ? S_OK
: S_FALSE
;
660 return count
? S_FALSE
: S_OK
;
663 static HRESULT WINAPI
enum_media_types_Skip(IEnumMediaTypes
*iface
, ULONG count
)
665 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
667 TRACE("iface %p, count %u.\n", iface
, count
);
669 enum_media_types
->index
+= count
;
673 static HRESULT WINAPI
enum_media_types_Reset(IEnumMediaTypes
*iface
)
675 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
677 TRACE("iface %p.\n", iface
);
679 enum_media_types
->index
= 0;
683 static HRESULT WINAPI
enum_media_types_Clone(IEnumMediaTypes
*iface
, IEnumMediaTypes
**out
)
685 struct enum_media_types
*enum_media_types
= impl_from_IEnumMediaTypes(iface
);
686 struct enum_media_types
*object
;
688 TRACE("iface %p, out %p.\n", iface
, out
);
690 if (!(object
= heap_alloc(sizeof(*object
))))
691 return E_OUTOFMEMORY
;
693 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
694 object
->refcount
= 1;
695 object
->index
= enum_media_types
->index
;
697 *out
= &object
->IEnumMediaTypes_iface
;
701 static const IEnumMediaTypesVtbl enum_media_types_vtbl
=
703 enum_media_types_QueryInterface
,
704 enum_media_types_AddRef
,
705 enum_media_types_Release
,
706 enum_media_types_Next
,
707 enum_media_types_Skip
,
708 enum_media_types_Reset
,
709 enum_media_types_Clone
,
712 static inline struct audio_stream
*impl_from_IPin(IPin
*iface
)
714 return CONTAINING_RECORD(iface
, struct audio_stream
, IPin_iface
);
717 static HRESULT WINAPI
audio_sink_QueryInterface(IPin
*iface
, REFIID iid
, void **out
)
719 struct audio_stream
*stream
= impl_from_IPin(iface
);
720 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
723 static ULONG WINAPI
audio_sink_AddRef(IPin
*iface
)
725 struct audio_stream
*stream
= impl_from_IPin(iface
);
726 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
729 static ULONG WINAPI
audio_sink_Release(IPin
*iface
)
731 struct audio_stream
*stream
= impl_from_IPin(iface
);
732 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
735 static HRESULT WINAPI
audio_sink_Connect(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
737 WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface
, peer
, mt
);
741 static HRESULT WINAPI
audio_sink_ReceiveConnection(IPin
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
743 struct audio_stream
*stream
= impl_from_IPin(iface
);
746 TRACE("stream %p, peer %p, mt %p.\n", stream
, peer
, mt
);
748 if (!IsEqualGUID(&mt
->majortype
, &MEDIATYPE_Audio
)
749 || !IsEqualGUID(&mt
->formattype
, &FORMAT_WaveFormatEx
)
750 || mt
->cbFormat
< sizeof(WAVEFORMATEX
))
751 return VFW_E_TYPE_NOT_ACCEPTED
;
753 if (((const WAVEFORMATEX
*)mt
->pbFormat
)->wFormatTag
!= WAVE_FORMAT_PCM
)
756 EnterCriticalSection(&stream
->cs
);
760 LeaveCriticalSection(&stream
->cs
);
761 return VFW_E_ALREADY_CONNECTED
;
764 IPin_QueryDirection(peer
, &dir
);
765 if (dir
!= PINDIR_OUTPUT
)
767 WARN("Rejecting connection from input pin.\n");
768 LeaveCriticalSection(&stream
->cs
);
769 return VFW_E_INVALID_DIRECTION
;
772 if (stream
->format
.wFormatTag
&& memcmp(mt
->pbFormat
, &stream
->format
, sizeof(WAVEFORMATEX
)))
774 LeaveCriticalSection(&stream
->cs
);
778 CopyMediaType(&stream
->mt
, mt
);
779 IPin_AddRef(stream
->peer
= peer
);
781 LeaveCriticalSection(&stream
->cs
);
786 static HRESULT WINAPI
audio_sink_Disconnect(IPin
*iface
)
788 struct audio_stream
*stream
= impl_from_IPin(iface
);
790 TRACE("stream %p.\n", stream
);
792 EnterCriticalSection(&stream
->cs
);
796 LeaveCriticalSection(&stream
->cs
);
800 IPin_Release(stream
->peer
);
802 FreeMediaType(&stream
->mt
);
803 memset(&stream
->mt
, 0, sizeof(AM_MEDIA_TYPE
));
805 LeaveCriticalSection(&stream
->cs
);
810 static HRESULT WINAPI
audio_sink_ConnectedTo(IPin
*iface
, IPin
**peer
)
812 struct audio_stream
*stream
= impl_from_IPin(iface
);
815 TRACE("stream %p, peer %p.\n", stream
, peer
);
817 EnterCriticalSection(&stream
->cs
);
821 IPin_AddRef(*peer
= stream
->peer
);
827 hr
= VFW_E_NOT_CONNECTED
;
830 LeaveCriticalSection(&stream
->cs
);
835 static HRESULT WINAPI
audio_sink_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mt
)
837 struct audio_stream
*stream
= impl_from_IPin(iface
);
840 TRACE("stream %p, mt %p.\n", stream
, mt
);
842 EnterCriticalSection(&stream
->cs
);
846 CopyMediaType(mt
, &stream
->mt
);
851 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
852 hr
= VFW_E_NOT_CONNECTED
;
855 LeaveCriticalSection(&stream
->cs
);
860 static HRESULT WINAPI
audio_sink_QueryPinInfo(IPin
*iface
, PIN_INFO
*info
)
862 struct audio_stream
*stream
= impl_from_IPin(iface
);
864 TRACE("stream %p, info %p.\n", stream
, info
);
866 IBaseFilter_AddRef(info
->pFilter
= (IBaseFilter
*)stream
->filter
);
867 info
->dir
= PINDIR_INPUT
;
868 wcscpy(info
->achName
, sink_id
);
873 static HRESULT WINAPI
audio_sink_QueryDirection(IPin
*iface
, PIN_DIRECTION
*dir
)
875 TRACE("iface %p, dir %p.\n", iface
, dir
);
880 static HRESULT WINAPI
audio_sink_QueryId(IPin
*iface
, WCHAR
**id
)
882 TRACE("iface %p, id %p.\n", iface
, id
);
884 if (!(*id
= CoTaskMemAlloc(sizeof(sink_id
))))
885 return E_OUTOFMEMORY
;
887 wcscpy(*id
, sink_id
);
892 static HRESULT WINAPI
audio_sink_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*mt
)
894 TRACE("iface %p, mt %p.\n", iface
, mt
);
898 static HRESULT WINAPI
audio_sink_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**enum_media_types
)
900 struct enum_media_types
*object
;
902 TRACE("iface %p, enum_media_types %p.\n", iface
, enum_media_types
);
904 if (!enum_media_types
)
907 if (!(object
= heap_alloc(sizeof(*object
))))
908 return E_OUTOFMEMORY
;
910 object
->IEnumMediaTypes_iface
.lpVtbl
= &enum_media_types_vtbl
;
911 object
->refcount
= 1;
914 *enum_media_types
= &object
->IEnumMediaTypes_iface
;
918 static HRESULT WINAPI
audio_sink_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*count
)
920 TRACE("iface %p, pins %p, count %p.\n", iface
, pins
, count
);
924 static HRESULT WINAPI
audio_sink_EndOfStream(IPin
*iface
)
926 struct audio_stream
*stream
= impl_from_IPin(iface
);
928 TRACE("stream %p.\n", stream
);
930 EnterCriticalSection(&stream
->cs
);
934 LeaveCriticalSection(&stream
->cs
);
940 LeaveCriticalSection(&stream
->cs
);
945 static HRESULT WINAPI
audio_sink_BeginFlush(IPin
*iface
)
947 FIXME("iface %p, stub!\n", iface
);
951 static HRESULT WINAPI
audio_sink_EndFlush(IPin
*iface
)
953 FIXME("iface %p, stub!\n", iface
);
957 static HRESULT WINAPI
audio_sink_NewSegment(IPin
*iface
, REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
959 FIXME("iface %p, start %s, stop %s, rate %0.16e, stub!\n",
960 iface
, wine_dbgstr_longlong(start
), wine_dbgstr_longlong(stop
), rate
);
964 static const IPinVtbl audio_sink_vtbl
=
966 audio_sink_QueryInterface
,
970 audio_sink_ReceiveConnection
,
971 audio_sink_Disconnect
,
972 audio_sink_ConnectedTo
,
973 audio_sink_ConnectionMediaType
,
974 audio_sink_QueryPinInfo
,
975 audio_sink_QueryDirection
,
977 audio_sink_QueryAccept
,
978 audio_sink_EnumMediaTypes
,
979 audio_sink_QueryInternalConnections
,
980 audio_sink_EndOfStream
,
981 audio_sink_BeginFlush
,
983 audio_sink_NewSegment
,
986 static inline struct audio_stream
*impl_from_IMemInputPin(IMemInputPin
*iface
)
988 return CONTAINING_RECORD(iface
, struct audio_stream
, IMemInputPin_iface
);
991 static HRESULT WINAPI
audio_meminput_QueryInterface(IMemInputPin
*iface
, REFIID iid
, void **out
)
993 struct audio_stream
*stream
= impl_from_IMemInputPin(iface
);
994 return IAMMediaStream_QueryInterface(&stream
->IAMMediaStream_iface
, iid
, out
);
997 static ULONG WINAPI
audio_meminput_AddRef(IMemInputPin
*iface
)
999 struct audio_stream
*stream
= impl_from_IMemInputPin(iface
);
1000 return IAMMediaStream_AddRef(&stream
->IAMMediaStream_iface
);
1003 static ULONG WINAPI
audio_meminput_Release(IMemInputPin
*iface
)
1005 struct audio_stream
*stream
= impl_from_IMemInputPin(iface
);
1006 return IAMMediaStream_Release(&stream
->IAMMediaStream_iface
);
1009 static HRESULT WINAPI
audio_meminput_GetAllocator(IMemInputPin
*iface
, IMemAllocator
**allocator
)
1011 struct audio_stream
*stream
= impl_from_IMemInputPin(iface
);
1013 TRACE("stream %p, allocator %p.\n", stream
, allocator
);
1015 if (stream
->allocator
)
1017 IMemAllocator_AddRef(*allocator
= stream
->allocator
);
1022 return VFW_E_NO_ALLOCATOR
;
1025 static HRESULT WINAPI
audio_meminput_NotifyAllocator(IMemInputPin
*iface
, IMemAllocator
*allocator
, BOOL readonly
)
1027 struct audio_stream
*stream
= impl_from_IMemInputPin(iface
);
1029 TRACE("stream %p, allocator %p, readonly %d.\n", stream
, allocator
, readonly
);
1035 IMemAllocator_AddRef(allocator
);
1036 if (stream
->allocator
)
1037 IMemAllocator_Release(stream
->allocator
);
1038 stream
->allocator
= allocator
;
1043 static HRESULT WINAPI
audio_meminput_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
1045 TRACE("iface %p, props %p.\n", iface
, props
);
1049 static HRESULT WINAPI
audio_meminput_Receive(IMemInputPin
*iface
, IMediaSample
*sample
)
1051 FIXME("iface %p, sample %p, stub!\n", iface
, sample
);
1055 static HRESULT WINAPI
audio_meminput_ReceiveMultiple(IMemInputPin
*iface
,
1056 IMediaSample
**samples
, LONG count
, LONG
*processed
)
1058 FIXME("iface %p, samples %p, count %u, processed %p, stub!\n", iface
, samples
, count
, processed
);
1062 static HRESULT WINAPI
audio_meminput_ReceiveCanBlock(IMemInputPin
*iface
)
1064 TRACE("iface %p.\n", iface
);
1068 static const IMemInputPinVtbl audio_meminput_vtbl
=
1070 audio_meminput_QueryInterface
,
1071 audio_meminput_AddRef
,
1072 audio_meminput_Release
,
1073 audio_meminput_GetAllocator
,
1074 audio_meminput_NotifyAllocator
,
1075 audio_meminput_GetAllocatorRequirements
,
1076 audio_meminput_Receive
,
1077 audio_meminput_ReceiveMultiple
,
1078 audio_meminput_ReceiveCanBlock
,
1081 HRESULT
audio_stream_create(IMultiMediaStream
*parent
, const MSPID
*purpose_id
,
1082 IUnknown
*stream_object
, STREAM_TYPE stream_type
, IAMMediaStream
**media_stream
)
1084 struct audio_stream
*object
;
1086 TRACE("(%p,%s,%p,%p)\n", parent
, debugstr_guid(purpose_id
), stream_object
, media_stream
);
1089 FIXME("Specifying a stream object is not yet supported.\n");
1091 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1093 return E_OUTOFMEMORY
;
1095 object
->IAMMediaStream_iface
.lpVtbl
= &audio_IAMMediaStream_vtbl
;
1096 object
->IAudioMediaStream_iface
.lpVtbl
= &audio_IAudioMediaStream_vtbl
;
1097 object
->IMemInputPin_iface
.lpVtbl
= &audio_meminput_vtbl
;
1098 object
->IPin_iface
.lpVtbl
= &audio_sink_vtbl
;
1101 InitializeCriticalSection(&object
->cs
);
1102 object
->parent
= parent
;
1103 object
->purpose_id
= *purpose_id
;
1104 object
->stream_type
= stream_type
;
1106 *media_stream
= &object
->IAMMediaStream_iface
;