ReactOS 0.4.17-dev-966-gf06eace
audiorecord.c
Go to the documentation of this file.
1/*
2 * Audio capture filter
3 *
4 * Copyright 2015 Damjan Jovanovic
5 * Copyright 2023 Zeb Figura for CodeWeavers
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include "qcap_private.h"
23
25
27{
30
33 IAMStreamConfig IAMStreamConfig_iface;
35
36 unsigned int id;
37 HWAVEIN device;
40
41 /* FIXME: It would be nice to avoid duplicating this variable with strmbase.
42 * However, synchronization is tricky; we need access to be protected by a
43 * separate lock. */
44 FILTER_STATE state;
45 CONDITION_VARIABLE state_cv;
47
50};
51
53{
55}
56
58{
60
61 if (IsEqualGUID(iid, &IID_IAMBufferNegotiation))
62 *out = &filter->IAMBufferNegotiation_iface;
63 else if (IsEqualGUID(iid, &IID_IAMStreamConfig))
64 *out = &filter->IAMStreamConfig_iface;
65 else if (IsEqualGUID(iid, &IID_IKsPropertySet))
66 *out = &filter->IKsPropertySet_iface;
67 else
68 return E_NOINTERFACE;
69
70 IUnknown_AddRef((IUnknown *)*out);
71 return S_OK;
72}
73
75{
76 if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Audio))
77 return S_FALSE;
78
79 if (!IsEqualGUID(&mt->formattype, &FORMAT_WaveFormatEx))
80 return S_FALSE;
81
82 return S_OK;
83}
84
85static const struct
86{
87 unsigned int rate;
88 unsigned int depth;
89 unsigned int channels;
90}
92{
93 {44100, 16, 2},
94 {44100, 16, 1},
95 {32000, 16, 2},
96 {32000, 16, 1},
97 {22050, 16, 2},
98 {22050, 16, 1},
99 {11025, 16, 2},
100 {11025, 16, 1},
101 { 8000, 16, 2},
102 { 8000, 16, 1},
103 {44100, 8, 2},
104 {44100, 8, 1},
105 {22050, 8, 2},
106 {22050, 8, 1},
107 {11025, 8, 2},
108 {11025, 8, 1},
109 { 8000, 8, 2},
110 { 8000, 8, 1},
111 {48000, 16, 2},
112 {48000, 16, 1},
113 {96000, 16, 2},
114 {96000, 16, 1},
116
118{
120
121 if (index >= 1 + ARRAY_SIZE(audio_formats))
122 return VFW_S_NO_MORE_ITEMS;
123
124 if (!index)
125 return CopyMediaType(mt, &filter->format);
126 --index;
127
128 if (!(format = CoTaskMemAlloc(sizeof(*format))))
129 return E_OUTOFMEMORY;
130
131 memset(format, 0, sizeof(WAVEFORMATEX));
132 format->wFormatTag = WAVE_FORMAT_PCM;
133 format->nChannels = audio_formats[index].channels;
134 format->nSamplesPerSec = audio_formats[index].rate;
135 format->wBitsPerSample = audio_formats[index].depth;
136 format->nBlockAlign = audio_formats[index].channels * audio_formats[index].depth / 8;
137 format->nAvgBytesPerSec = format->nBlockAlign * format->nSamplesPerSec;
138
139 memset(mt, 0, sizeof(AM_MEDIA_TYPE));
140 mt->majortype = MEDIATYPE_Audio;
141 mt->subtype = MEDIASUBTYPE_PCM;
142 mt->bFixedSizeSamples = TRUE;
143 mt->lSampleSize = format->nBlockAlign;
144 mt->formattype = FORMAT_WaveFormatEx;
145 mt->cbFormat = sizeof(WAVEFORMATEX);
146 mt->pbFormat = (BYTE *)format;
147
148 return S_OK;
149}
150
152 unsigned int index, AM_MEDIA_TYPE *mt)
153{
155
156 return fill_media_type(filter, index, mt);
157}
158
161{
162 struct audio_record *filter = impl_from_strmbase_filter(iface->pin.filter);
163 const WAVEFORMATEX *format = (void *)filter->source.pin.mt.pbFormat;
164 ALLOCATOR_PROPERTIES ret_props;
166 HRESULT hr;
167
168 props->cBuffers = (filter->props.cBuffers == -1) ? 4 : filter->props.cBuffers;
169 /* This is the algorithm that native uses. The alignment to an even number
170 * doesn't make much sense, and may be a bug. */
171 if (filter->props.cbBuffer == -1)
172 props->cbBuffer = (format->nAvgBytesPerSec / 2) & ~1;
173 else
174 props->cbBuffer = filter->props.cbBuffer & ~1;
175 if (filter->props.cbAlign == -1 || filter->props.cbAlign == 0)
176 props->cbAlign = 1;
177 else
178 props->cbAlign = filter->props.cbAlign;
179 props->cbPrefix = (filter->props.cbPrefix == -1) ? 0 : filter->props.cbPrefix;
180
181 if (FAILED(hr = IMemAllocator_SetProperties(allocator, props, &ret_props)))
182 return hr;
183
184 if ((ret = waveInOpen(&filter->device, filter->id, format,
186 {
187 ERR("Failed to open device %u, error %u.\n", filter->id, ret);
188 return E_FAIL;
189 }
190
191 return S_OK;
192}
193
195{
196 struct audio_record *filter = impl_from_strmbase_filter(iface->pin.filter);
197
198 waveInClose(filter->device);
199}
200
201static const struct strmbase_source_ops source_ops =
202{
203 .base.pin_get_media_type = audio_record_source_get_media_type,
204 .base.pin_query_accept = audio_record_source_query_accept,
205 .base.pin_query_interface = audio_record_source_query_interface,
206 .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
207 .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
208 .pfnDecideBufferSize = audio_record_source_DecideBufferSize,
209 .source_disconnect = audio_record_source_disconnect,
210};
211
212static struct audio_record *impl_from_IAMStreamConfig(IAMStreamConfig *iface)
213{
215}
216
217static HRESULT WINAPI stream_config_QueryInterface(IAMStreamConfig *iface, REFIID iid, void **out)
218{
220 return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out);
221}
222
223static ULONG WINAPI stream_config_AddRef(IAMStreamConfig *iface)
224{
226 return IPin_AddRef(&filter->source.pin.IPin_iface);
227}
228
229static ULONG WINAPI stream_config_Release(IAMStreamConfig *iface)
230{
232 return IPin_Release(&filter->source.pin.IPin_iface);
233}
234
235static HRESULT WINAPI stream_config_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *mt)
236{
238 HRESULT hr;
239
240 TRACE("iface %p, mt %p.\n", iface, mt);
242
243 if (!mt)
244 return E_POINTER;
245
247
248 if ((hr = CopyMediaType(&filter->format, mt)))
249 {
251 return hr;
252 }
253
255
256 return S_OK;
257}
258
259static HRESULT WINAPI stream_config_GetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE **ret_mt)
260{
262 AM_MEDIA_TYPE *mt;
263 HRESULT hr;
264
265 TRACE("iface %p, mt %p.\n", iface, ret_mt);
266
267 if (!(mt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))))
268 return E_OUTOFMEMORY;
269
271
272 if ((hr = CopyMediaType(mt, &filter->format)))
273 {
275 CoTaskMemFree(mt);
276 return hr;
277 }
278
280
281 *ret_mt = mt;
282 return S_OK;
283}
284
286 int *count, int *size)
287{
289
290 TRACE("filter %p, count %p, size %p.\n", filter, count, size);
291
293 *size = sizeof(AUDIO_STREAM_CONFIG_CAPS);
294 return S_OK;
295}
296
297static HRESULT WINAPI stream_config_GetStreamCaps(IAMStreamConfig *iface,
298 int index, AM_MEDIA_TYPE **ret_mt, BYTE *caps)
299{
301 AUDIO_STREAM_CONFIG_CAPS *audio_caps = (void *)caps;
302 AM_MEDIA_TYPE *mt;
303 HRESULT hr;
304
305 TRACE("filter %p, index %d, ret_mt %p, caps %p.\n", filter, index, ret_mt, caps);
306
307 if (index >= 1 + ARRAY_SIZE(audio_formats))
308 return S_FALSE;
309
310 if (!(mt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))))
311 return E_OUTOFMEMORY;
312
313 if ((hr = fill_media_type(filter, index, mt)) != S_OK)
314 {
315 CoTaskMemFree(mt);
316 return hr;
317 }
318
319 *ret_mt = mt;
320
321 audio_caps->guid = MEDIATYPE_Audio;
322 audio_caps->MinimumChannels = 1;
323 audio_caps->MaximumChannels = 2;
324 audio_caps->ChannelsGranularity = 1;
325 audio_caps->MinimumBitsPerSample = 8;
326 audio_caps->MaximumBitsPerSample = 16;
327 audio_caps->BitsPerSampleGranularity = 8;
328 audio_caps->MinimumSampleFrequency = 11025;
329 audio_caps->MaximumSampleFrequency = 44100;
330 audio_caps->SampleFrequencyGranularity = 11025;
331
332 return S_OK;
333}
334
335static const IAMStreamConfigVtbl stream_config_vtbl =
336{
344};
345
347{
349}
350
352{
354 return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out);
355}
356
358{
360 return IPin_AddRef(&filter->source.pin.IPin_iface);
361}
362
364{
366 return IPin_Release(&filter->source.pin.IPin_iface);
367}
368
371{
373
374 TRACE("filter %p, props %p.\n", filter, props);
375 TRACE("Requested %ld buffers, size %ld, alignment %ld, prefix %ld.\n",
376 props->cBuffers, props->cbBuffer, props->cbAlign, props->cbPrefix);
377
378 EnterCriticalSection(&filter->state_cs);
379 filter->props = *props;
380 LeaveCriticalSection(&filter->state_cs);
381
382 return S_OK;
383}
384
387{
388 FIXME("iface %p, props %p, stub!\n", iface, props);
389 return E_NOTIMPL;
390}
391
392static const IAMBufferNegotiationVtbl buffer_negotiation_vtbl =
393{
399};
400
402{
404}
405
407{
409 return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out);
410}
411
413{
415 return IPin_AddRef(&filter->source.pin.IPin_iface);
416}
417
419{
421 return IPin_Release(&filter->source.pin.IPin_iface);
422}
423
425 void *instance, DWORD instance_size, void *data, DWORD size)
426{
427 FIXME("iface %p, set %s, id %lu, instance %p, instance_size %lu, data %p, size %lu, stub!\n",
428 iface, debugstr_guid(set), id, instance, instance_size, data, size);
429 return E_NOTIMPL;
430}
431
433 void *instance, DWORD instance_size, void *data, DWORD size, DWORD *ret_size)
434{
436
437 TRACE("filter %p, set %s, id %lu, instance %p, instance_size %lu, data %p, size %lu, ret_size %p.\n",
438 filter, debugstr_guid(set), id, instance, instance_size, data, size, ret_size);
439
440 if (!IsEqualGUID(set, &AMPROPSETID_Pin))
441 {
442 FIXME("Unknown set %s, returning E_PROP_SET_UNSUPPORTED.\n", debugstr_guid(set));
444 }
445
446 if (id != AMPROPERTY_PIN_CATEGORY)
447 {
448 FIXME("Unknown id %lu, returning E_PROP_ID_UNSUPPORTED.\n", id);
450 }
451
452 if (instance || instance_size)
453 FIXME("Unexpected instance data %p, size %lu.\n", instance, instance_size);
454
455 *ret_size = sizeof(GUID);
456
457 if (size < sizeof(GUID))
458 return E_UNEXPECTED;
459
460 *(GUID *)data = PIN_CATEGORY_CAPTURE;
461 return S_OK;
462}
463
465 const GUID *set, DWORD id, DWORD *support)
466{
467 FIXME("iface %p, set %s, id %lu, support %p, stub!\n", iface, debugstr_guid(set), id, support);
468 return E_NOTIMPL;
469}
470
471static const IKsPropertySetVtbl property_set_vtbl =
472{
479};
480
482{
484}
485
486static struct strmbase_pin *audio_record_get_pin(struct strmbase_filter *iface, unsigned int index)
487{
489
490 if (!index)
491 return &filter->source.pin;
492 return NULL;
493}
494
495static void audio_record_destroy(struct strmbase_filter *iface)
496{
498
499 filter->state_cs.DebugInfo->Spare[0] = 0;
500 DeleteCriticalSection(&filter->state_cs);
501 CloseHandle(filter->event);
502 FreeMediaType(&filter->format);
505 free(filter);
506}
507
509{
511
513 *out = &filter->IPersistPropertyBag_iface;
514 else
515 return E_NOINTERFACE;
516
517 IUnknown_AddRef((IUnknown *)*out);
518 return S_OK;
519}
520
522{
523 struct audio_record *filter = arg;
524 const WAVEFORMATEX *format = (void *)filter->source.pin.mt.pbFormat;
525 bool started = false;
527
528 /* FIXME: We should probably queue several buffers instead of just one. */
529
530 EnterCriticalSection(&filter->state_cs);
531
532 for (;;)
533 {
535 WAVEHDR header = {0};
536 HRESULT hr;
537 BYTE *data;
538
539 while (filter->state == State_Paused)
540 SleepConditionVariableCS(&filter->state_cv, &filter->state_cs, INFINITE);
541
542 if (filter->state == State_Stopped)
543 break;
544
545 if (FAILED(hr = IMemAllocator_GetBuffer(filter->source.pAllocator, &sample, NULL, NULL, 0)))
546 {
547 ERR("Failed to get sample, hr %#lx.\n", hr);
548 break;
549 }
550
551 IMediaSample_GetPointer(sample, &data);
552
553 header.lpData = (void *)data;
554 header.dwBufferLength = IMediaSample_GetSize(sample);
555 if ((ret = waveInPrepareHeader(filter->device, &header, sizeof(header))) != MMSYSERR_NOERROR)
556 ERR("Failed to prepare header, error %u.\n", ret);
557
558 if ((ret = waveInAddBuffer(filter->device, &header, sizeof(header))) != MMSYSERR_NOERROR)
559 ERR("Failed to add buffer, error %u.\n", ret);
560
561 if (!started)
562 {
563 if ((ret = waveInStart(filter->device)) != MMSYSERR_NOERROR)
564 ERR("Failed to start, error %u.\n", ret);
565 started = true;
566 }
567
568 while (!(header.dwFlags & WHDR_DONE) && filter->state == State_Running)
569 {
570 LeaveCriticalSection(&filter->state_cs);
571
572 if ((ret = WaitForSingleObject(filter->event, INFINITE)))
573 ERR("Failed to wait, error %u.\n", ret);
574
575 EnterCriticalSection(&filter->state_cs);
576 }
577
578 if (filter->state != State_Running)
579 {
580 TRACE("State is %#x; resetting.\n", filter->state);
581 if ((ret = waveInReset(filter->device)) != MMSYSERR_NOERROR)
582 ERR("Failed to reset, error %u.\n", ret);
583 }
584
585 if ((ret = waveInUnprepareHeader(filter->device, &header, sizeof(header))) != MMSYSERR_NOERROR)
586 ERR("Failed to unprepare header, error %u.\n", ret);
587
588 IMediaSample_SetActualDataLength(sample, header.dwBytesRecorded);
589
590 if (filter->state == State_Running)
591 {
592 REFERENCE_TIME start_pts, end_pts;
593 MMTIME time;
594
595 time.wType = TIME_BYTES;
596 if ((ret = waveInGetPosition(filter->device, &time, sizeof(time))) != MMSYSERR_NOERROR)
597 ERR("Failed to get position, error %u.\n", ret);
598 if (time.wType != TIME_BYTES)
599 ERR("Got unexpected type %#x.\n", time.wType);
600 end_pts = MulDiv(time.u.cb, 10000000, format->nAvgBytesPerSec);
601 start_pts = MulDiv(time.u.cb - header.dwBytesRecorded, 10000000, format->nAvgBytesPerSec);
602 IMediaSample_SetTime(sample, &start_pts, &end_pts);
603
604 TRACE("Sending buffer %p.\n", sample);
605 if (FAILED(hr = IMemInputPin_Receive(filter->source.pMemInputPin, sample)))
606 {
607 ERR("IMemInputPin::Receive() returned %#lx.\n", hr);
608 IMediaSample_Release(sample);
609 break;
610 }
611 }
612
613 IMediaSample_Release(sample);
614 }
615
616 LeaveCriticalSection(&filter->state_cs);
617
618 if (started && (ret = waveInStop(filter->device)) != MMSYSERR_NOERROR)
619 ERR("Failed to stop, error %u.\n", ret);
620
621 return 0;
622}
623
625{
627 HRESULT hr;
628
629 if (!filter->source.pin.peer)
630 return S_OK;
631
632 if (FAILED(hr = IMemAllocator_Commit(filter->source.pAllocator)))
633 ERR("Failed to commit allocator, hr %#lx.\n", hr);
634
635 EnterCriticalSection(&filter->state_cs);
636 filter->state = State_Paused;
637 LeaveCriticalSection(&filter->state_cs);
638
639 filter->thread = CreateThread(NULL, 0, stream_thread, filter, 0, NULL);
640
641 return S_OK;
642}
643
645{
647
648 if (!filter->source.pin.peer)
649 return S_OK;
650
651 EnterCriticalSection(&filter->state_cs);
652 filter->state = State_Running;
653 LeaveCriticalSection(&filter->state_cs);
654 WakeConditionVariable(&filter->state_cv);
655 return S_OK;
656}
657
659{
661
662 if (!filter->source.pin.peer)
663 return S_OK;
664
665 EnterCriticalSection(&filter->state_cs);
666 filter->state = State_Paused;
667 LeaveCriticalSection(&filter->state_cs);
668 SetEvent(filter->event);
669 return S_OK;
670}
671
673{
675 HRESULT hr;
676
677 if (!filter->source.pin.peer)
678 return S_OK;
679
680 EnterCriticalSection(&filter->state_cs);
681 filter->state = State_Stopped;
682 LeaveCriticalSection(&filter->state_cs);
683 WakeConditionVariable(&filter->state_cv);
684 SetEvent(filter->event);
685
687 CloseHandle(filter->thread);
688 filter->thread = NULL;
689
690 hr = IMemAllocator_Decommit(filter->source.pAllocator);
691 if (hr != S_OK && hr != VFW_E_NOT_COMMITTED)
692 ERR("Failed to decommit allocator, hr %#lx.\n", hr);
693
694 return S_OK;
695}
696
698{
700
701 if (filter->filter.state == State_Paused)
702 return VFW_S_CANT_CUE;
703 return S_OK;
704}
705
706static const struct strmbase_filter_ops filter_ops =
707{
708 .filter_get_pin = audio_record_get_pin,
709 .filter_destroy = audio_record_destroy,
710 .filter_query_interface = audio_record_query_interface,
711 .filter_init_stream = audio_record_init_stream,
712 .filter_start_stream = audio_record_start_stream,
713 .filter_stop_stream = audio_record_stop_stream,
714 .filter_cleanup_stream = audio_record_cleanup_stream,
715 .filter_wait_state = audio_record_wait_state,
716};
717
719{
721
722 return IUnknown_QueryInterface(filter->filter.outer_unk, riid, ppv);
723}
724
726{
728
729 return IUnknown_AddRef(filter->filter.outer_unk);
730}
731
733{
735
736 return IUnknown_Release(filter->filter.outer_unk);
737}
738
740{
742 TRACE("(%p/%p)->(%p)\n", iface, This, pClassID);
743 return IBaseFilter_GetClassID(&This->filter.IBaseFilter_iface, pClassID);
744}
745
747{
749 FIXME("(%p/%p)->(): stub\n", iface, This);
750 return E_NOTIMPL;
751}
752
754{
756 VARIANT var;
757 HRESULT hr;
758
759 TRACE("filter %p, bag %p, error_log %p.\n", filter, bag, error_log);
760
761 V_VT(&var) = VT_I4;
762 if (FAILED(hr = IPropertyBag_Read(bag, L"WaveInID", &var, error_log)))
763 return hr;
764
766 filter->id = V_I4(&var);
768
769 return hr;
770}
771
773 BOOL fClearDirty, BOOL fSaveAllProperties)
774{
776 FIXME("(%p/%p)->(%p, %u, %u): stub\n", iface, This, pPropBag, fClearDirty, fSaveAllProperties);
777 return E_NOTIMPL;
778}
779
780static const IPersistPropertyBagVtbl PersistPropertyBagVtbl =
781{
787 PPB_Load,
789};
790
792{
793 struct audio_record *object;
794 HRESULT hr;
795
796 if (!(object = calloc(1, sizeof(*object))))
797 return E_OUTOFMEMORY;
798
799 if (!(object->event = CreateEventW(NULL, FALSE, FALSE, NULL)))
800 {
801 free(object);
802 return E_OUTOFMEMORY;
803 }
804
805 if ((hr = fill_media_type(object, 1, &object->format)))
806 {
807 CloseHandle(object->event);
808 free(object);
809 return hr;
810 }
811
812 object->props.cBuffers = -1;
813 object->props.cbBuffer = -1;
814 object->props.cbAlign = -1;
815 object->props.cbPrefix = -1;
816
817 object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
818 strmbase_filter_init(&object->filter, outer, &CLSID_AudioRecord, &filter_ops);
819
820 strmbase_source_init(&object->source, &object->filter, L"Capture", &source_ops);
821 object->IAMBufferNegotiation_iface.lpVtbl = &buffer_negotiation_vtbl;
822 object->IAMStreamConfig_iface.lpVtbl = &stream_config_vtbl;
823 object->IKsPropertySet_iface.lpVtbl = &property_set_vtbl;
824
825 object->state = State_Stopped;
828 object->state_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_record.state_cs");
829
830 TRACE("Created audio recorder %p.\n", object);
831 *out = &object->filter.IUnknown_inner;
832 return S_OK;
833}
static struct audio_record * impl_from_strmbase_filter(struct strmbase_filter *filter)
Definition: audiorecord.c:52
static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag *iface)
Definition: audiorecord.c:746
static HRESULT audio_record_init_stream(struct strmbase_filter *iface)
Definition: audiorecord.c:624
static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_source *iface, IMemAllocator *allocator, ALLOCATOR_PROPERTIES *props)
Definition: audiorecord.c:159
static ULONG WINAPI property_set_AddRef(IKsPropertySet *iface)
Definition: audiorecord.c:412
static HRESULT fill_media_type(struct audio_record *filter, unsigned int index, AM_MEDIA_TYPE *mt)
Definition: audiorecord.c:117
static HRESULT WINAPI stream_config_GetNumberOfCapabilities(IAMStreamConfig *iface, int *count, int *size)
Definition: audiorecord.c:285
static HRESULT WINAPI property_set_Get(IKsPropertySet *iface, const GUID *set, DWORD id, void *instance, DWORD instance_size, void *data, DWORD size, DWORD *ret_size)
Definition: audiorecord.c:432
static HRESULT WINAPI property_set_QueryInterface(IKsPropertySet *iface, REFIID iid, void **out)
Definition: audiorecord.c:406
static struct audio_record * impl_from_IAMStreamConfig(IAMStreamConfig *iface)
Definition: audiorecord.c:212
static ULONG WINAPI stream_config_AddRef(IAMStreamConfig *iface)
Definition: audiorecord.c:223
static struct audio_record * impl_from_IPersistPropertyBag(IPersistPropertyBag *iface)
Definition: audiorecord.c:481
static HRESULT WINAPI PPB_GetClassID(IPersistPropertyBag *iface, CLSID *pClassID)
Definition: audiorecord.c:739
static HRESULT WINAPI property_set_Set(IKsPropertySet *iface, const GUID *set, DWORD id, void *instance, DWORD instance_size, void *data, DWORD size)
Definition: audiorecord.c:424
static ULONG WINAPI buffer_negotiation_AddRef(IAMBufferNegotiation *iface)
Definition: audiorecord.c:357
static HRESULT audio_record_wait_state(struct strmbase_filter *iface, DWORD timeout)
Definition: audiorecord.c:697
static const IAMStreamConfigVtbl stream_config_vtbl
Definition: audiorecord.c:335
static HRESULT audio_record_start_stream(struct strmbase_filter *iface, REFERENCE_TIME time)
Definition: audiorecord.c:644
static HRESULT WINAPI property_set_QuerySupported(IKsPropertySet *iface, const GUID *set, DWORD id, DWORD *support)
Definition: audiorecord.c:464
static HRESULT audio_record_cleanup_stream(struct strmbase_filter *iface)
Definition: audiorecord.c:672
unsigned int depth
Definition: audiorecord.c:88
static const IKsPropertySetVtbl property_set_vtbl
Definition: audiorecord.c:471
static ULONG WINAPI stream_config_Release(IAMStreamConfig *iface)
Definition: audiorecord.c:229
static void audio_record_destroy(struct strmbase_filter *iface)
Definition: audiorecord.c:495
static HRESULT audio_record_source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
Definition: audiorecord.c:57
HRESULT audio_record_create(IUnknown *outer, IUnknown **out)
Definition: audiorecord.c:791
static ULONG WINAPI PPB_AddRef(IPersistPropertyBag *iface)
Definition: audiorecord.c:725
static ULONG WINAPI property_set_Release(IKsPropertySet *iface)
Definition: audiorecord.c:418
static ULONG WINAPI PPB_Release(IPersistPropertyBag *iface)
Definition: audiorecord.c:732
static const IAMBufferNegotiationVtbl buffer_negotiation_vtbl
Definition: audiorecord.c:392
static HRESULT WINAPI buffer_negotiation_GetAllocatorProperties(IAMBufferNegotiation *iface, ALLOCATOR_PROPERTIES *props)
Definition: audiorecord.c:385
static const struct strmbase_source_ops source_ops
Definition: audiorecord.c:201
static struct strmbase_pin * audio_record_get_pin(struct strmbase_filter *iface, unsigned int index)
Definition: audiorecord.c:486
static HRESULT WINAPI PPB_Load(IPersistPropertyBag *iface, IPropertyBag *bag, IErrorLog *error_log)
Definition: audiorecord.c:753
unsigned int channels
Definition: audiorecord.c:89
static struct audio_record * impl_from_IAMBufferNegotiation(IAMBufferNegotiation *iface)
Definition: audiorecord.c:346
static HRESULT audio_record_query_interface(struct strmbase_filter *iface, REFIID iid, void **out)
Definition: audiorecord.c:508
static const struct @327 audio_formats[]
static const struct strmbase_filter_ops filter_ops
Definition: audiorecord.c:706
static HRESULT audio_record_source_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt)
Definition: audiorecord.c:151
static HRESULT WINAPI stream_config_GetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE **ret_mt)
Definition: audiorecord.c:259
static HRESULT WINAPI PPB_Save(IPersistPropertyBag *iface, IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
Definition: audiorecord.c:772
static HRESULT WINAPI stream_config_GetStreamCaps(IAMStreamConfig *iface, int index, AM_MEDIA_TYPE **ret_mt, BYTE *caps)
Definition: audiorecord.c:297
static DWORD WINAPI stream_thread(void *arg)
Definition: audiorecord.c:521
static HRESULT WINAPI stream_config_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *mt)
Definition: audiorecord.c:235
static HRESULT audio_record_stop_stream(struct strmbase_filter *iface)
Definition: audiorecord.c:658
static void audio_record_source_disconnect(struct strmbase_source *iface)
Definition: audiorecord.c:194
static HRESULT WINAPI PPB_QueryInterface(IPersistPropertyBag *iface, REFIID riid, LPVOID *ppv)
Definition: audiorecord.c:718
static HRESULT WINAPI stream_config_QueryInterface(IAMStreamConfig *iface, REFIID iid, void **out)
Definition: audiorecord.c:217
static const IPersistPropertyBagVtbl PersistPropertyBagVtbl
Definition: audiorecord.c:780
static ULONG WINAPI buffer_negotiation_Release(IAMBufferNegotiation *iface)
Definition: audiorecord.c:363
static HRESULT WINAPI buffer_negotiation_QueryInterface(IAMBufferNegotiation *iface, REFIID iid, void **out)
Definition: audiorecord.c:351
static HRESULT audio_record_source_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt)
Definition: audiorecord.c:74
static struct audio_record * impl_from_IKsPropertySet(IKsPropertySet *iface)
Definition: audiorecord.c:401
static HRESULT WINAPI buffer_negotiation_SuggestAllocatorProperties(IAMBufferNegotiation *iface, const ALLOCATOR_PROPERTIES *props)
Definition: audiorecord.c:369
unsigned int rate
Definition: audiorecord.c:87
@ AMPROPERTY_PIN_CATEGORY
Definition: axextend.idl:1160
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WAVE_FORMAT_PCM
Definition: constants.h:425
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: _set.h:50
const GUID IID_IKsPropertySet
Definition: controlnode.cpp:13
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static HINSTANCE instance
Definition: main.c:35
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
#define CloseHandle
Definition: compat.h:739
@ VT_I4
Definition: compat.h:2298
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD Timeout)
Definition: sync.c:59
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:22
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
Definition: sync.c:107
VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:98
LONGLONG REFERENCE_TIME
Definition: dmusicks.h:9
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_guid
Definition: kernel32.h:35
if(dx< 0)
Definition: linetemp.h:194
__u16 time
Definition: mkdosfs.c:8
#define TIME_BYTES
Definition: mmsystem.h:30
UINT MMRESULT
Definition: mmsystem.h:964
#define CALLBACK_EVENT
Definition: mmsystem.h:152
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define WHDR_DONE
Definition: mmsystem.h:193
const char * var
Definition: shader.c:5879
static void ULONG ULONG * ret_size
Definition: time.c:40
static IUnknown * outer
Definition: compobj.c:82
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
#define V_VT(A)
Definition: oleauto.h:211
#define V_I4(A)
Definition: oleauto.h:247
const GUID IID_IPersistPropertyBag
Definition: proxy.cpp:11
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define calloc
Definition: rosglue.h:14
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *pDest, const AM_MEDIA_TYPE *pSrc)
Definition: mediatype.c:150
void WINAPI FreeMediaType(AM_MEDIA_TYPE *pMediaType)
Definition: mediatype.c:165
HRESULT WINAPI BaseOutputPinImpl_DecideAllocator(struct strmbase_source *pin, IMemInputPin *peer, IMemAllocator **allocator)
Definition: pin.c:680
void strmbase_source_init(struct strmbase_source *pin, struct strmbase_filter *filter, const WCHAR *name, const struct strmbase_source_ops *func_table)
Definition: pin.c:765
void strmbase_dump_media_type(const AM_MEDIA_TYPE *mt)
Definition: mediatype.c:58
void strmbase_filter_cleanup(struct strmbase_filter *filter)
Definition: filter.c:540
void strmbase_source_cleanup(struct strmbase_source *pin)
Definition: pin.c:778
void strmbase_filter_init(struct strmbase_filter *filter, IUnknown *outer, const CLSID *clsid, const struct strmbase_filter_ops *func_table)
Definition: filter.c:517
HRESULT WINAPI BaseOutputPinImpl_AttemptConnection(struct strmbase_source *pin, IPin *peer, const AM_MEDIA_TYPE *mt)
Definition: pin.c:710
CRITICAL_SECTION state_cs
Definition: audiorecord.c:46
HWAVEIN device
Definition: audiorecord.c:37
unsigned int id
Definition: audiorecord.c:36
FILTER_STATE state
Definition: audiorecord.c:44
AM_MEDIA_TYPE format
Definition: audiorecord.c:48
IAMStreamConfig IAMStreamConfig_iface
Definition: audiorecord.c:33
CONDITION_VARIABLE state_cv
Definition: audiorecord.c:45
IPersistPropertyBag IPersistPropertyBag_iface
Definition: audiorecord.c:29
HANDLE thread
Definition: audiorecord.c:39
HANDLE event
Definition: audiorecord.c:38
IKsPropertySet IKsPropertySet_iface
Definition: audiorecord.c:34
IAMBufferNegotiation IAMBufferNegotiation_iface
Definition: audiorecord.c:32
ALLOCATOR_PROPERTIES props
Definition: audiorecord.c:49
Definition: filter.c:165
IBaseFilter * filter
Definition: filtergraph.c:75
FILTER_STATE state
Definition: filter.c:177
Definition: wave.c:25
struct strmbase_filter * filter
Definition: strmbase.h:58
struct strmbase_pin pin
Definition: strmbase.h:79
Definition: dhcpd.h:248
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define E_PROP_ID_UNSUPPORTED
Definition: vfwmsgs.h:173
#define E_PROP_SET_UNSUPPORTED
Definition: vfwmsgs.h:176
#define VFW_E_NOT_COMMITTED
Definition: vfwmsgs.h:56
#define VFW_S_CANT_CUE
Definition: vfwmsgs.h:33
#define VFW_S_NO_MORE_ITEMS
Definition: vfwmsgs.h:19
static const WCHAR props[]
Definition: wbemdisp.c:288
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define E_NOINTERFACE
Definition: winerror.h:3479
#define E_UNEXPECTED
Definition: winerror.h:3528
#define E_POINTER
Definition: winerror.h:3480
UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, LPMMTIME lpTime, UINT uSize)
Definition: winmm.c:2779
UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2717
UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2653
UINT WINAPI waveInStop(HWAVEIN hWaveIn)
Definition: winmm.c:2764
UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2684
UINT WINAPI waveInReset(HWAVEIN hWaveIn)
Definition: winmm.c:2734
MMRESULT WINAPI waveInOpen(HWAVEIN *lphWaveIn, UINT uDeviceID, LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags)
Definition: winmm.c:2623
UINT WINAPI waveInClose(HWAVEIN hWaveIn)
Definition: winmm.c:2634
UINT WINAPI waveInStart(HWAVEIN hWaveIn)
Definition: winmm.c:2749
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1156
unsigned char BYTE
Definition: xxhash.c:193