sapi: Add SpMMAudioOut stub.
[wine.git] / dlls / sapi / mmaudio.c
blob684476f5c568ee499858033e731eca95307e8145
1 /*
2 * Speech API (SAPI) winmm audio implementation.
4 * Copyright 2023 Shaun Ren for CodeWeavers
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 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
29 #include "sapiddk.h"
30 #include "sperror.h"
32 #include "wine/debug.h"
34 #include "sapi_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(sapi);
38 enum flow_type { FLOW_IN, FLOW_OUT };
40 struct mmaudio
42 ISpEventSource ISpEventSource_iface;
43 ISpEventSink ISpEventSink_iface;
44 ISpObjectWithToken ISpObjectWithToken_iface;
45 ISpMMSysAudio ISpMMSysAudio_iface;
46 LONG ref;
48 enum flow_type flow;
49 ISpObjectToken *token;
52 static inline struct mmaudio *impl_from_ISpEventSource(ISpEventSource *iface)
54 return CONTAINING_RECORD(iface, struct mmaudio, ISpEventSource_iface);
57 static inline struct mmaudio *impl_from_ISpEventSink(ISpEventSink *iface)
59 return CONTAINING_RECORD(iface, struct mmaudio, ISpEventSink_iface);
62 static inline struct mmaudio *impl_from_ISpObjectWithToken(ISpObjectWithToken *iface)
64 return CONTAINING_RECORD(iface, struct mmaudio, ISpObjectWithToken_iface);
67 static inline struct mmaudio *impl_from_ISpMMSysAudio(ISpMMSysAudio *iface)
69 return CONTAINING_RECORD(iface, struct mmaudio, ISpMMSysAudio_iface);
72 static HRESULT WINAPI event_source_QueryInterface(ISpEventSource *iface, REFIID iid, void **obj)
74 struct mmaudio *This = impl_from_ISpEventSource(iface);
76 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(iid), obj);
78 return ISpMMSysAudio_QueryInterface(&This->ISpMMSysAudio_iface, iid, obj);
81 static ULONG WINAPI event_source_AddRef(ISpEventSource *iface)
83 struct mmaudio *This = impl_from_ISpEventSource(iface);
85 TRACE("(%p).\n", iface);
87 return ISpMMSysAudio_AddRef(&This->ISpMMSysAudio_iface);
90 static ULONG WINAPI event_source_Release(ISpEventSource *iface)
92 struct mmaudio *This = impl_from_ISpEventSource(iface);
94 TRACE("(%p).\n", iface);
96 return ISpMMSysAudio_Release(&This->ISpMMSysAudio_iface);
99 static HRESULT WINAPI event_source_SetNotifySink(ISpEventSource *iface, ISpNotifySink *sink)
101 FIXME("(%p, %p): stub.\n", iface, sink);
103 return E_NOTIMPL;
106 static HRESULT WINAPI event_source_SetNotifyWindowMessage(ISpEventSource *iface, HWND hwnd,
107 UINT msg, WPARAM wparam, LPARAM lparam)
109 FIXME("(%p, %p, %u, %Ix, %Ix): stub.\n", iface, hwnd, msg, wparam, lparam);
111 return E_NOTIMPL;
114 static HRESULT WINAPI event_source_SetNotifyCallbackFunction(ISpEventSource *iface, SPNOTIFYCALLBACK *callback,
115 WPARAM wparam, LPARAM lparam)
117 FIXME("(%p, %p, %Ix, %Ix): stub.\n", iface, callback, wparam, lparam);
119 return E_NOTIMPL;
122 static HRESULT WINAPI event_source_SetNotifyCallbackInterface(ISpEventSource *iface, ISpNotifyCallback *callback,
123 WPARAM wparam, LPARAM lparam)
125 FIXME("(%p, %p, %Ix, %Ix): stub.\n", iface, callback, wparam, lparam);
127 return E_NOTIMPL;
130 static HRESULT WINAPI event_source_SetNotifyWin32Event(ISpEventSource *iface)
132 FIXME("(%p): stub.\n", iface);
134 return E_NOTIMPL;
137 static HRESULT WINAPI event_source_WaitForNotifyEvent(ISpEventSource *iface, DWORD milliseconds)
139 FIXME("(%p, %ld): stub.\n", iface, milliseconds);
141 return E_NOTIMPL;
144 static HANDLE WINAPI event_source_GetNotifyEventHandle(ISpEventSource *iface)
146 FIXME("(%p): stub.\n", iface);
148 return NULL;
151 static HRESULT WINAPI event_source_SetInterest(ISpEventSource *iface, ULONGLONG event, ULONGLONG queued)
153 FIXME("(%p, %s, %s): stub.\n", iface, wine_dbgstr_longlong(event), wine_dbgstr_longlong(queued));
155 return E_NOTIMPL;
158 static HRESULT WINAPI event_source_GetEvents(ISpEventSource *iface, ULONG count, SPEVENT *array, ULONG *fetched)
160 FIXME("(%p, %lu, %p, %p): stub.\n", iface, count, array, fetched);
162 return E_NOTIMPL;
165 static HRESULT WINAPI event_source_GetInfo(ISpEventSource *iface, SPEVENTSOURCEINFO *info)
167 FIXME("(%p, %p): stub.\n", iface, info);
169 return E_NOTIMPL;
172 static const ISpEventSourceVtbl event_source_vtbl =
174 event_source_QueryInterface,
175 event_source_AddRef,
176 event_source_Release,
177 event_source_SetNotifySink,
178 event_source_SetNotifyWindowMessage,
179 event_source_SetNotifyCallbackFunction,
180 event_source_SetNotifyCallbackInterface,
181 event_source_SetNotifyWin32Event,
182 event_source_WaitForNotifyEvent,
183 event_source_GetNotifyEventHandle,
184 event_source_SetInterest,
185 event_source_GetEvents,
186 event_source_GetInfo
189 static HRESULT WINAPI event_sink_QueryInterface(ISpEventSink *iface, REFIID iid, void **obj)
191 struct mmaudio *This = impl_from_ISpEventSink(iface);
193 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(iid), obj);
195 return ISpMMSysAudio_QueryInterface(&This->ISpMMSysAudio_iface, iid, obj);
198 static ULONG WINAPI event_sink_AddRef(ISpEventSink *iface)
200 struct mmaudio *This = impl_from_ISpEventSink(iface);
202 TRACE("(%p).\n", iface);
204 return ISpMMSysAudio_AddRef(&This->ISpMMSysAudio_iface);
207 static ULONG WINAPI event_sink_Release(ISpEventSink *iface)
209 struct mmaudio *This = impl_from_ISpEventSink(iface);
211 TRACE("(%p).\n", iface);
213 return ISpMMSysAudio_Release(&This->ISpMMSysAudio_iface);
216 static HRESULT WINAPI event_sink_AddEvents(ISpEventSink *iface, const SPEVENT *events, ULONG count)
218 FIXME("(%p, %p, %lu).\n", iface, events, count);
220 return E_NOTIMPL;
223 static HRESULT WINAPI event_sink_GetEventInterest(ISpEventSink *iface, ULONGLONG *interest)
225 FIXME("(%p, %p).\n", iface, interest);
227 return E_NOTIMPL;
230 static const ISpEventSinkVtbl event_sink_vtbl =
232 event_sink_QueryInterface,
233 event_sink_AddRef,
234 event_sink_Release,
235 event_sink_AddEvents,
236 event_sink_GetEventInterest
239 static HRESULT WINAPI objwithtoken_QueryInterface(ISpObjectWithToken *iface, REFIID iid, void **obj)
241 struct mmaudio *This = impl_from_ISpObjectWithToken(iface);
243 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(iid), obj);
245 return ISpMMSysAudio_QueryInterface(&This->ISpMMSysAudio_iface, iid, obj);
248 static ULONG WINAPI objwithtoken_AddRef(ISpObjectWithToken *iface)
250 struct mmaudio *This = impl_from_ISpObjectWithToken(iface);
252 TRACE("(%p).\n", iface);
254 return ISpMMSysAudio_AddRef(&This->ISpMMSysAudio_iface);
257 static ULONG WINAPI objwithtoken_Release(ISpObjectWithToken *iface)
259 struct mmaudio *This = impl_from_ISpObjectWithToken(iface);
261 TRACE("(%p).\n", iface);
263 return ISpMMSysAudio_Release(&This->ISpMMSysAudio_iface);
266 static HRESULT WINAPI objwithtoken_SetObjectToken(ISpObjectWithToken *iface, ISpObjectToken *token)
268 struct mmaudio *This = impl_from_ISpObjectWithToken(iface);
270 FIXME("(%p, %p): semi-stub.\n", iface, token);
272 if (!token)
273 return E_INVALIDARG;
274 if (This->token)
275 return SPERR_ALREADY_INITIALIZED;
277 This->token = token;
278 return S_OK;
281 static HRESULT WINAPI objwithtoken_GetObjectToken(ISpObjectWithToken *iface, ISpObjectToken **token)
283 struct mmaudio *This = impl_from_ISpObjectWithToken(iface);
285 TRACE("(%p, %p).\n", iface, token);
287 if (!token)
288 return E_POINTER;
290 *token = This->token;
291 if (*token)
293 ISpObjectToken_AddRef(*token);
294 return S_OK;
296 else
297 return S_FALSE;
300 static const ISpObjectWithTokenVtbl objwithtoken_vtbl =
302 objwithtoken_QueryInterface,
303 objwithtoken_AddRef,
304 objwithtoken_Release,
305 objwithtoken_SetObjectToken,
306 objwithtoken_GetObjectToken
309 static HRESULT WINAPI mmsysaudio_QueryInterface(ISpMMSysAudio *iface, REFIID iid, void **obj)
311 struct mmaudio *This = impl_from_ISpMMSysAudio(iface);
313 TRACE("(%p, %s, %p).\n", iface, debugstr_guid(iid), obj);
315 if (IsEqualIID(iid, &IID_IUnknown) ||
316 IsEqualIID(iid, &IID_ISequentialStream) ||
317 IsEqualIID(iid, &IID_IStream) ||
318 IsEqualIID(iid, &IID_ISpStreamFormat) ||
319 IsEqualIID(iid, &IID_ISpAudio) ||
320 IsEqualIID(iid, &IID_ISpMMSysAudio))
321 *obj = &This->ISpMMSysAudio_iface;
322 else if (IsEqualIID(iid, &IID_ISpEventSource))
323 *obj = &This->ISpEventSource_iface;
324 else if (IsEqualIID(iid, &IID_ISpEventSink))
325 *obj = &This->ISpEventSink_iface;
326 else if (IsEqualIID(iid, &IID_ISpObjectWithToken))
327 *obj = &This->ISpObjectWithToken_iface;
328 else
330 *obj = NULL;
331 FIXME("interface %s not implemented.\n", debugstr_guid(iid));
332 return E_NOINTERFACE;
335 IUnknown_AddRef((IUnknown *)*obj);
336 return S_OK;
339 static ULONG WINAPI mmsysaudio_AddRef(ISpMMSysAudio *iface)
341 struct mmaudio *This = impl_from_ISpMMSysAudio(iface);
342 ULONG ref = InterlockedIncrement(&This->ref);
344 TRACE("(%p): ref=%lu\n", iface, ref);
346 return ref;
349 static ULONG WINAPI mmsysaudio_Release(ISpMMSysAudio *iface)
351 struct mmaudio *This = impl_from_ISpMMSysAudio(iface);
352 ULONG ref = InterlockedDecrement(&This->ref);
354 TRACE("(%p): ref=%lu\n", iface, ref);
356 if (!ref)
358 if (This->token) ISpObjectToken_Release(This->token);
360 heap_free(This);
363 return ref;
366 static HRESULT WINAPI mmsysaudio_Read(ISpMMSysAudio *iface, void *pv, ULONG cb, ULONG *cb_read)
368 FIXME("(%p, %p, %lu, %p): stub.\n", iface, pv, cb, cb_read);
370 return E_NOTIMPL;
373 static HRESULT WINAPI mmsysaudio_Write(ISpMMSysAudio *iface, const void *pv, ULONG cb, ULONG *cb_written)
375 FIXME("(%p, %p, %lu, %p): stub.\n", iface, pv, cb, cb_written);
377 return E_NOTIMPL;
380 static HRESULT WINAPI mmsysaudio_Seek(ISpMMSysAudio *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
382 FIXME("(%p, %s, %lu, %p): stub.\n", iface, wine_dbgstr_longlong(move.QuadPart), origin, new_pos);
384 return E_NOTIMPL;
387 static HRESULT WINAPI mmsysaudio_SetSize(ISpMMSysAudio *iface, ULARGE_INTEGER new_size)
389 FIXME("(%p, %s): stub.\n", iface, wine_dbgstr_longlong(new_size.QuadPart));
391 return E_NOTIMPL;
394 static HRESULT WINAPI mmsysaudio_CopyTo(ISpMMSysAudio *iface, IStream *stream, ULARGE_INTEGER cb,
395 ULARGE_INTEGER *cb_read, ULARGE_INTEGER *cb_written)
397 FIXME("(%p, %p, %s, %p, %p): stub.\n", iface, stream, wine_dbgstr_longlong(cb.QuadPart), cb_read, cb_written);
399 return E_NOTIMPL;
402 static HRESULT WINAPI mmsysaudio_Commit(ISpMMSysAudio *iface, DWORD flags)
404 FIXME("(%p, %#lx): stub.\n", iface, flags);
406 return E_NOTIMPL;
409 static HRESULT WINAPI mmsysaudio_Revert(ISpMMSysAudio *iface)
411 FIXME("(%p).\n", iface);
413 return E_NOTIMPL;
416 static HRESULT WINAPI mmsysaudio_LockRegion(ISpMMSysAudio *iface, ULARGE_INTEGER offset, ULARGE_INTEGER cb,
417 DWORD lock_type)
419 FIXME("(%p, %s, %s, %#lx): stub.\n", iface, wine_dbgstr_longlong(offset.QuadPart),
420 wine_dbgstr_longlong(cb.QuadPart), lock_type);
422 return E_NOTIMPL;
425 static HRESULT WINAPI mmsysaudio_UnlockRegion(ISpMMSysAudio *iface, ULARGE_INTEGER offset, ULARGE_INTEGER cb,
426 DWORD lock_type)
428 FIXME("(%p, %s, %s, %#lx): stub.\n", iface, wine_dbgstr_longlong(offset.QuadPart),
429 wine_dbgstr_longlong(cb.QuadPart), lock_type);
431 return E_NOTIMPL;
434 static HRESULT WINAPI mmsysaudio_Stat(ISpMMSysAudio *iface, STATSTG *statstg, DWORD flags)
436 FIXME("(%p, %p, %#lx): stub.\n", iface, statstg, flags);
438 return E_NOTIMPL;
441 static HRESULT WINAPI mmsysaudio_Clone(ISpMMSysAudio *iface, IStream **stream)
443 FIXME("(%p, %p): stub.\n", iface, stream);
445 return E_NOTIMPL;
448 static HRESULT WINAPI mmsysaudio_GetFormat(ISpMMSysAudio *iface, GUID *format, WAVEFORMATEX **wfx)
450 FIXME("(%p, %p, %p): stub.\n", iface, format, wfx);
452 return E_NOTIMPL;
455 static HRESULT WINAPI mmsysaudio_SetState(ISpMMSysAudio *iface, SPAUDIOSTATE state, ULONGLONG reserved)
457 FIXME("(%p, %u, %s): stub.\n", iface, state, wine_dbgstr_longlong(reserved));
459 return E_NOTIMPL;
462 static HRESULT WINAPI mmsysaudio_SetFormat(ISpMMSysAudio *iface, const GUID *guid, const WAVEFORMATEX *wfx)
464 FIXME("(%p, %s, %p): stub.\n", iface, debugstr_guid(guid), wfx);
466 return E_NOTIMPL;
469 static HRESULT WINAPI mmsysaudio_GetStatus(ISpMMSysAudio *iface, SPAUDIOSTATUS *status)
471 FIXME("(%p, %p): stub.\n", iface, status);
473 return E_NOTIMPL;
476 static HRESULT WINAPI mmsysaudio_SetBufferInfo(ISpMMSysAudio *iface, const SPAUDIOBUFFERINFO *info)
478 FIXME("(%p, %p): stub.\n", iface, info);
480 return E_NOTIMPL;
483 static HRESULT WINAPI mmsysaudio_GetBufferInfo(ISpMMSysAudio *iface, SPAUDIOBUFFERINFO *info)
485 FIXME("(%p, %p): stub.\n", iface, info);
487 return E_NOTIMPL;
490 static HRESULT WINAPI mmsysaudio_GetDefaultFormat(ISpMMSysAudio *iface, GUID *guid, WAVEFORMATEX **wfx)
492 FIXME("(%p, %p, %p): stub.\n", iface, guid, wfx);
494 return E_NOTIMPL;
497 static HANDLE WINAPI mmsysaudio_EventHandle(ISpMMSysAudio *iface)
499 FIXME("(%p): stub.\n", iface);
501 return NULL;
504 static HRESULT WINAPI mmsysaudio_GetVolumeLevel(ISpMMSysAudio *iface, ULONG *level)
506 FIXME("(%p, %p): stub.\n", iface, level);
508 return E_NOTIMPL;
511 static HRESULT WINAPI mmsysaudio_SetVolumeLevel(ISpMMSysAudio *iface, ULONG level)
513 FIXME("(%p, %lu): stub.\n", iface, level);
515 return E_NOTIMPL;
518 static HRESULT WINAPI mmsysaudio_GetBufferNotifySize(ISpMMSysAudio *iface, ULONG *size)
520 FIXME("(%p, %p): stub.\n", iface, size);
522 return E_NOTIMPL;
525 static HRESULT WINAPI mmsysaudio_SetBufferNotifySize(ISpMMSysAudio *iface, ULONG size)
527 FIXME("(%p, %lu): stub.\n", iface, size);
529 return E_NOTIMPL;
532 static HRESULT WINAPI mmsysaudio_GetDeviceId(ISpMMSysAudio *iface, UINT *id)
534 FIXME("(%p, %p): stub.\n", iface, id);
536 return E_NOTIMPL;
539 static HRESULT WINAPI mmsysaudio_SetDeviceId(ISpMMSysAudio *iface, UINT id)
541 FIXME("(%p, %u): stub.\n", iface, id);
543 return E_NOTIMPL;
546 static HRESULT WINAPI mmsysaudio_GetMMHandle(ISpMMSysAudio *iface, void **handle)
548 FIXME("(%p, %p): stub.\n", iface, handle);
550 return E_NOTIMPL;
553 static HRESULT WINAPI mmsysaudio_GetLineId(ISpMMSysAudio *iface, UINT *id)
555 FIXME("(%p, %p): stub.\n", iface, id);
557 return E_NOTIMPL;
560 static HRESULT WINAPI mmsysaudio_SetLineId(ISpMMSysAudio *iface, UINT id)
562 FIXME("(%p, %u): stub.\n", iface, id);
564 return E_NOTIMPL;
567 static const ISpMMSysAudioVtbl mmsysaudio_vtbl =
569 mmsysaudio_QueryInterface,
570 mmsysaudio_AddRef,
571 mmsysaudio_Release,
572 mmsysaudio_Read,
573 mmsysaudio_Write,
574 mmsysaudio_Seek,
575 mmsysaudio_SetSize,
576 mmsysaudio_CopyTo,
577 mmsysaudio_Commit,
578 mmsysaudio_Revert,
579 mmsysaudio_LockRegion,
580 mmsysaudio_UnlockRegion,
581 mmsysaudio_Stat,
582 mmsysaudio_Clone,
583 mmsysaudio_GetFormat,
584 mmsysaudio_SetState,
585 mmsysaudio_SetFormat,
586 mmsysaudio_GetStatus,
587 mmsysaudio_SetBufferInfo,
588 mmsysaudio_GetBufferInfo,
589 mmsysaudio_GetDefaultFormat,
590 mmsysaudio_EventHandle,
591 mmsysaudio_GetVolumeLevel,
592 mmsysaudio_SetVolumeLevel,
593 mmsysaudio_GetBufferNotifySize,
594 mmsysaudio_SetBufferNotifySize,
595 mmsysaudio_GetDeviceId,
596 mmsysaudio_SetDeviceId,
597 mmsysaudio_GetMMHandle,
598 mmsysaudio_GetLineId,
599 mmsysaudio_SetLineId
602 static HRESULT mmaudio_create(IUnknown *outer, REFIID iid, void **obj, enum flow_type flow)
604 struct mmaudio *This;
605 HRESULT hr;
607 if (flow != FLOW_OUT)
609 FIXME("flow %d not implemented.\n", flow);
610 return E_NOTIMPL;
613 if (!(This = heap_alloc_zero(sizeof(*This))))
614 return E_OUTOFMEMORY;
615 This->ISpEventSource_iface.lpVtbl = &event_source_vtbl;
616 This->ISpEventSink_iface.lpVtbl = &event_sink_vtbl;
617 This->ISpObjectWithToken_iface.lpVtbl = &objwithtoken_vtbl;
618 This->ISpMMSysAudio_iface.lpVtbl = &mmsysaudio_vtbl;
619 This->ref = 1;
621 This->flow = flow;
622 This->token = NULL;
624 hr = ISpMMSysAudio_QueryInterface(&This->ISpMMSysAudio_iface, iid, obj);
626 ISpMMSysAudio_Release(&This->ISpMMSysAudio_iface);
627 return hr;
630 HRESULT mmaudio_out_create(IUnknown *outer, REFIID iid, void **obj)
632 return mmaudio_create(outer, iid, obj, FLOW_OUT);