amstream: Implement AMAudioStream::EndOfStream().
[wine.git] / dlls / amstream / audiostream.c
blobb46694569586049c6d0d677ac848519ef35b6857
1 /*
2 * Primary audio stream
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
21 #define COBJMACROS
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}";
30 struct audio_stream
32 IAMMediaStream IAMMediaStream_iface;
33 IAudioMediaStream IAudioMediaStream_iface;
34 IMemInputPin IMemInputPin_iface;
35 IPin IPin_iface;
36 LONG ref;
38 IMultiMediaStream* parent;
39 MSPID purpose_id;
40 STREAM_TYPE stream_type;
41 CRITICAL_SECTION cs;
42 IMediaStreamFilter *filter;
44 IPin *peer;
45 IMemAllocator *allocator;
46 AM_MEDIA_TYPE mt;
47 WAVEFORMATEX format;
48 FILTER_STATE state;
49 BOOL eos;
52 typedef struct {
53 IAudioStreamSample IAudioStreamSample_iface;
54 LONG ref;
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);
75 *ret_iface = iface;
76 return S_OK;
79 *ret_iface = NULL;
81 ERR("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ret_iface);
82 return E_NOINTERFACE;
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);
92 return 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);
102 if (!ref)
103 HeapFree(GetProcessHeap(), 0, This);
105 return ref;
108 /*** IStreamSample methods ***/
109 static HRESULT WINAPI IAudioStreamSampleImpl_GetMediaStream(IAudioStreamSample *iface, IMediaStream **media_stream)
111 FIXME("(%p)->(%p): stub\n", iface, media_stream);
113 return E_NOTIMPL;
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);
121 return E_NOTIMPL;
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);
129 return E_NOTIMPL;
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);
137 return E_NOTIMPL;
140 static HRESULT WINAPI IAudioStreamSampleImpl_CompletionStatus(IAudioStreamSample *iface, DWORD flags, DWORD milliseconds)
142 FIXME("(%p)->(%x,%u): stub\n", iface, flags, milliseconds);
144 return E_NOTIMPL;
147 /*** IAudioStreamSample methods ***/
148 static HRESULT WINAPI IAudioStreamSampleImpl_GetAudioData(IAudioStreamSample *iface, IAudioData **audio_data)
150 FIXME("(%p)->(%p): stub\n", iface, audio_data);
152 return E_NOTIMPL;
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));
178 if (!object)
179 return E_OUTOFMEMORY;
181 object->IAudioStreamSample_iface.lpVtbl = &AudioStreamSample_Vtbl;
182 object->ref = 1;
183 object->parent = parent;
184 object->audio_data = audio_data;
186 *audio_stream_sample = &object->IAudioStreamSample_iface;
188 return S_OK;
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);
209 *ret_iface = iface;
210 return S_OK;
212 else if (IsEqualGUID(riid, &IID_IAudioMediaStream))
214 IAMMediaStream_AddRef(iface);
215 *ret_iface = &This->IAudioMediaStream_iface;
216 return S_OK;
218 else if (IsEqualGUID(riid, &IID_IPin))
220 IAMMediaStream_AddRef(iface);
221 *ret_iface = &This->IPin_iface;
222 return S_OK;
224 else if (IsEqualGUID(riid, &IID_IMemInputPin))
226 IAMMediaStream_AddRef(iface);
227 *ret_iface = &This->IMemInputPin_iface;
228 return S_OK;
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);
242 return 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);
252 if (!ref)
254 DeleteCriticalSection(&This->cs);
255 HeapFree(GetProcessHeap(), 0, This);
258 return ref;
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)
270 return E_POINTER;
272 IMultiMediaStream_AddRef(This->parent);
273 *multi_media_stream = This->parent;
275 return S_OK;
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);
285 if (purpose_id)
286 *purpose_id = This->purpose_id;
287 if (type)
288 *type = This->stream_type;
290 return S_OK;
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);
300 return S_FALSE;
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);
310 return S_FALSE;
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);
320 return S_FALSE;
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);
329 return S_FALSE;
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);
340 return S_FALSE;
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)
352 stream->eos = FALSE;
354 stream->state = state;
356 LeaveCriticalSection(&stream->cs);
358 return S_OK;
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);
368 return S_FALSE;
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;
379 return S_OK;
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);
388 return S_FALSE;
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)
446 return E_POINTER;
448 IMultiMediaStream_AddRef(This->parent);
449 *multi_media_stream = This->parent;
451 return S_OK;
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);
461 if (purpose_id)
462 *purpose_id = This->purpose_id;
463 if (type)
464 *type = This->stream_type;
466 return S_OK;
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);
476 return S_FALSE;
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);
486 return S_FALSE;
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);
496 return S_FALSE;
499 static HRESULT WINAPI audio_IAudioMediaStream_SendEndOfStream(IAudioMediaStream *iface,
500 DWORD flags)
502 struct audio_stream *This = impl_from_IAudioMediaStream(iface);
504 FIXME("(%p/%p)->(%x) stub!\n", iface, This, flags);
506 return S_FALSE;
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);
516 if (!format)
517 return E_POINTER;
519 EnterCriticalSection(&stream->cs);
521 if (!stream->peer)
523 LeaveCriticalSection(&stream->cs);
524 return MS_E_NOSTREAM;
527 *format = *(WAVEFORMATEX *)stream->mt.pbFormat;
529 LeaveCriticalSection(&stream->cs);
531 return S_OK;
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);
540 if (!format)
541 return E_POINTER;
543 if (format->wFormatTag != WAVE_FORMAT_PCM)
544 return E_INVALIDARG;
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);
552 return E_INVALIDARG;
555 stream->format = *format;
557 LeaveCriticalSection(&stream->cs);
559 return S_OK;
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);
569 if (!audio_data)
570 return E_POINTER;
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;
594 LONG refcount;
595 unsigned int index;
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);
612 *out = iface;
613 return S_OK;
616 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
617 *out = NULL;
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);
626 return 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);
634 if (!refcount)
635 heap_free(enum_media_types);
636 return refcount;
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);
645 if (!ret_count)
646 return E_POINTER;
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;
655 *ret_count = 1;
656 return count == 1 ? S_OK : S_FALSE;
659 *ret_count = 0;
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;
670 return S_OK;
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;
680 return S_OK;
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;
698 return S_OK;
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);
738 return E_UNEXPECTED;
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);
744 PIN_DIRECTION dir;
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)
754 return E_INVALIDARG;
756 EnterCriticalSection(&stream->cs);
758 if (stream->peer)
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);
775 return E_INVALIDARG;
778 CopyMediaType(&stream->mt, mt);
779 IPin_AddRef(stream->peer = peer);
781 LeaveCriticalSection(&stream->cs);
783 return S_OK;
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);
794 if (!stream->peer)
796 LeaveCriticalSection(&stream->cs);
797 return S_FALSE;
800 IPin_Release(stream->peer);
801 stream->peer = NULL;
802 FreeMediaType(&stream->mt);
803 memset(&stream->mt, 0, sizeof(AM_MEDIA_TYPE));
805 LeaveCriticalSection(&stream->cs);
807 return S_OK;
810 static HRESULT WINAPI audio_sink_ConnectedTo(IPin *iface, IPin **peer)
812 struct audio_stream *stream = impl_from_IPin(iface);
813 HRESULT hr;
815 TRACE("stream %p, peer %p.\n", stream, peer);
817 EnterCriticalSection(&stream->cs);
819 if (stream->peer)
821 IPin_AddRef(*peer = stream->peer);
822 hr = S_OK;
824 else
826 *peer = NULL;
827 hr = VFW_E_NOT_CONNECTED;
830 LeaveCriticalSection(&stream->cs);
832 return hr;
835 static HRESULT WINAPI audio_sink_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
837 struct audio_stream *stream = impl_from_IPin(iface);
838 HRESULT hr;
840 TRACE("stream %p, mt %p.\n", stream, mt);
842 EnterCriticalSection(&stream->cs);
844 if (stream->peer)
846 CopyMediaType(mt, &stream->mt);
847 hr = S_OK;
849 else
851 memset(mt, 0, sizeof(AM_MEDIA_TYPE));
852 hr = VFW_E_NOT_CONNECTED;
855 LeaveCriticalSection(&stream->cs);
857 return hr;
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);
870 return S_OK;
873 static HRESULT WINAPI audio_sink_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
875 TRACE("iface %p, dir %p.\n", iface, dir);
876 *dir = PINDIR_INPUT;
877 return S_OK;
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);
889 return S_OK;
892 static HRESULT WINAPI audio_sink_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
894 TRACE("iface %p, mt %p.\n", iface, mt);
895 return S_OK;
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)
905 return E_POINTER;
907 if (!(object = heap_alloc(sizeof(*object))))
908 return E_OUTOFMEMORY;
910 object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
911 object->refcount = 1;
912 object->index = 0;
914 *enum_media_types = &object->IEnumMediaTypes_iface;
915 return S_OK;
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);
921 return E_NOTIMPL;
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);
932 if (stream->eos)
934 LeaveCriticalSection(&stream->cs);
935 return E_FAIL;
938 stream->eos = TRUE;
940 LeaveCriticalSection(&stream->cs);
942 return S_OK;
945 static HRESULT WINAPI audio_sink_BeginFlush(IPin *iface)
947 FIXME("iface %p, stub!\n", iface);
948 return E_NOTIMPL;
951 static HRESULT WINAPI audio_sink_EndFlush(IPin *iface)
953 FIXME("iface %p, stub!\n", iface);
954 return E_NOTIMPL;
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);
961 return E_NOTIMPL;
964 static const IPinVtbl audio_sink_vtbl =
966 audio_sink_QueryInterface,
967 audio_sink_AddRef,
968 audio_sink_Release,
969 audio_sink_Connect,
970 audio_sink_ReceiveConnection,
971 audio_sink_Disconnect,
972 audio_sink_ConnectedTo,
973 audio_sink_ConnectionMediaType,
974 audio_sink_QueryPinInfo,
975 audio_sink_QueryDirection,
976 audio_sink_QueryId,
977 audio_sink_QueryAccept,
978 audio_sink_EnumMediaTypes,
979 audio_sink_QueryInternalConnections,
980 audio_sink_EndOfStream,
981 audio_sink_BeginFlush,
982 audio_sink_EndFlush,
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);
1018 return S_OK;
1021 *allocator = NULL;
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);
1031 if (!allocator)
1032 return E_POINTER;
1034 if (allocator)
1035 IMemAllocator_AddRef(allocator);
1036 if (stream->allocator)
1037 IMemAllocator_Release(stream->allocator);
1038 stream->allocator = allocator;
1040 return S_OK;
1043 static HRESULT WINAPI audio_meminput_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
1045 TRACE("iface %p, props %p.\n", iface, props);
1046 return E_NOTIMPL;
1049 static HRESULT WINAPI audio_meminput_Receive(IMemInputPin *iface, IMediaSample *sample)
1051 FIXME("iface %p, sample %p, stub!\n", iface, sample);
1052 return E_NOTIMPL;
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);
1059 return E_NOTIMPL;
1062 static HRESULT WINAPI audio_meminput_ReceiveCanBlock(IMemInputPin *iface)
1064 TRACE("iface %p.\n", iface);
1065 return S_OK;
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);
1088 if (stream_object)
1089 FIXME("Specifying a stream object is not yet supported.\n");
1091 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1092 if (!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;
1099 object->ref = 1;
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;
1108 return S_OK;