include: Add ID3D12VideoDecoderHeap in d3d12video.idl.
[wine.git] / dlls / dmime / graph.c
blobd8f6bb8870159130c11f39e868564d28a88c8b3a
1 /* IDirectMusicGraph
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "dmime_private.h"
21 #include "dmobject.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
25 struct tool_entry
27 struct list entry;
28 IDirectMusicTool *tool;
29 DWORD delivery;
32 struct graph
34 IDirectMusicGraph IDirectMusicGraph_iface;
35 struct dmobject dmobj;
36 LONG ref;
38 struct list tools;
41 static inline struct graph *impl_from_IDirectMusicGraph(IDirectMusicGraph *iface)
43 return CONTAINING_RECORD(iface, struct graph, IDirectMusicGraph_iface);
46 static inline struct graph *impl_from_IPersistStream(IPersistStream *iface)
48 return CONTAINING_RECORD(iface, struct graph, dmobj.IPersistStream_iface);
51 static HRESULT WINAPI graph_QueryInterface(IDirectMusicGraph *iface, REFIID riid, void **ret_iface)
53 struct graph *This = impl_from_IDirectMusicGraph(iface);
55 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ret_iface);
57 *ret_iface = NULL;
59 if (IsEqualIID(riid, &IID_IUnknown) ||
60 IsEqualIID(riid, &IID_IDirectMusicGraph))
62 *ret_iface = &This->IDirectMusicGraph_iface;
64 else if (IsEqualIID(riid, &IID_IDirectMusicObject))
65 *ret_iface = &This->dmobj.IDirectMusicObject_iface;
66 else if (IsEqualIID(riid, &IID_IPersistStream))
67 *ret_iface = &This->dmobj.IPersistStream_iface;
69 if (*ret_iface)
71 IDirectMusicGraph_AddRef(iface);
72 return S_OK;
75 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ret_iface);
76 return E_NOINTERFACE;
79 static ULONG WINAPI graph_AddRef(IDirectMusicGraph *iface)
81 struct graph *This = impl_from_IDirectMusicGraph(iface);
82 ULONG ref = InterlockedIncrement(&This->ref);
84 TRACE("(%p): %ld\n", This, ref);
86 return ref;
89 static ULONG WINAPI graph_Release(IDirectMusicGraph *iface)
91 struct graph *This = impl_from_IDirectMusicGraph(iface);
92 ULONG ref = InterlockedDecrement(&This->ref);
94 TRACE("(%p): %ld\n", This, ref);
96 if (!ref)
98 struct tool_entry *entry, *next;
100 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->tools, struct tool_entry, entry)
102 list_remove(&entry->entry);
103 IDirectMusicTool_Release(entry->tool);
104 free(entry);
107 free(This);
110 return ref;
113 static HRESULT WINAPI graph_StampPMsg(IDirectMusicGraph *iface, DMUS_PMSG *msg)
115 const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME;
116 struct graph *This = impl_from_IDirectMusicGraph(iface);
117 struct tool_entry *entry, *next, *first;
119 TRACE("(%p, %p)\n", This, msg);
121 if (!msg) return E_POINTER;
123 first = LIST_ENTRY(This->tools.next, struct tool_entry, entry);
124 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->tools, struct tool_entry, entry)
125 if (entry->tool == msg->pTool) break;
126 if (&entry->entry == &This->tools) next = first;
128 if (msg->pTool)
130 IDirectMusicTool_Release(msg->pTool);
131 msg->pTool = NULL;
134 if (&next->entry == &This->tools) return DMUS_S_LAST_TOOL;
136 if (!msg->pGraph)
138 msg->pGraph = iface;
139 IDirectMusicGraph_AddRef(msg->pGraph);
142 msg->pTool = next->tool;
143 IDirectMusicTool_AddRef(msg->pTool);
145 msg->dwFlags &= ~delivery_flags;
146 msg->dwFlags |= next->delivery;
148 return S_OK;
151 static HRESULT WINAPI graph_InsertTool(IDirectMusicGraph *iface, IDirectMusicTool *tool,
152 DWORD *channels, DWORD channel_count, LONG index)
154 struct graph *This = impl_from_IDirectMusicGraph(iface);
155 struct tool_entry *entry, *next;
156 HRESULT hr;
158 TRACE("(%p, %p, %p, %ld, %li)\n", This, tool, channels, channel_count, index);
160 if (!tool) return E_POINTER;
162 LIST_FOR_EACH_ENTRY(next, &This->tools, struct tool_entry, entry)
164 if (next->tool == tool) return DMUS_E_ALREADY_EXISTS;
165 if (index-- <= 0) break;
168 if (!(entry = calloc(1, sizeof(*entry)))) return E_OUTOFMEMORY;
169 entry->tool = tool;
170 IDirectMusicTool_AddRef(tool);
171 IDirectMusicTool_Init(tool, iface);
172 if (FAILED(hr = IDirectMusicTool_GetMsgDeliveryType(tool, &entry->delivery)))
174 WARN("Failed to get delivery type from tool %p, hr %#lx\n", tool, hr);
175 entry->delivery = DMUS_PMSGF_TOOL_IMMEDIATE;
177 list_add_before(&next->entry, &entry->entry);
179 return S_OK;
182 static HRESULT WINAPI graph_GetTool(IDirectMusicGraph *iface, DWORD index, IDirectMusicTool **ret_tool)
184 struct graph *This = impl_from_IDirectMusicGraph(iface);
185 struct tool_entry *entry;
187 TRACE("(%p, %ld, %p)\n", This, index, ret_tool);
189 if (!ret_tool) return E_POINTER;
191 LIST_FOR_EACH_ENTRY(entry, &This->tools, struct tool_entry, entry)
193 if (!index--)
195 *ret_tool = entry->tool;
196 IDirectMusicTool_AddRef(entry->tool);
197 return S_OK;
201 return DMUS_E_NOT_FOUND;
204 static HRESULT WINAPI graph_RemoveTool(IDirectMusicGraph *iface, IDirectMusicTool *tool)
206 struct graph *This = impl_from_IDirectMusicGraph(iface);
207 struct tool_entry *entry;
209 TRACE("(%p, %p)\n", This, tool);
211 if (!tool) return E_POINTER;
213 LIST_FOR_EACH_ENTRY(entry, &This->tools, struct tool_entry, entry)
215 if (entry->tool == tool)
217 list_remove(&entry->entry);
218 IDirectMusicTool_Release(entry->tool);
219 free(entry);
220 return S_OK;
224 return DMUS_E_NOT_FOUND;
227 static const IDirectMusicGraphVtbl graph_vtbl =
229 graph_QueryInterface,
230 graph_AddRef,
231 graph_Release,
232 graph_StampPMsg,
233 graph_InsertTool,
234 graph_GetTool,
235 graph_RemoveTool,
238 static HRESULT WINAPI graph_IDirectMusicObject_ParseDescriptor(IDirectMusicObject *iface,
239 IStream *stream, DMUS_OBJECTDESC *desc)
241 struct chunk_entry riff = {0};
242 HRESULT hr;
244 TRACE("(%p, %p, %p)\n", iface, stream, desc);
246 if (!stream)
247 return E_POINTER;
248 if (!desc || desc->dwSize != sizeof(*desc))
249 return E_INVALIDARG;
251 if ((hr = stream_get_chunk(stream, &riff)) != S_OK)
252 return hr;
253 if (riff.id != FOURCC_RIFF || riff.type != DMUS_FOURCC_TOOLGRAPH_FORM) {
254 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff));
255 stream_skip_chunk(stream, &riff);
256 return DMUS_E_CHUNKNOTFOUND;
259 hr = dmobj_parsedescriptor(stream, &riff, desc,
260 DMUS_OBJ_OBJECT|DMUS_OBJ_NAME|DMUS_OBJ_CATEGORY|DMUS_OBJ_VERSION);
261 if (FAILED(hr))
262 return hr;
264 desc->guidClass = CLSID_DirectMusicGraph;
265 desc->dwValidData |= DMUS_OBJ_CLASS;
267 dump_DMUS_OBJECTDESC(desc);
268 return S_OK;
271 static const IDirectMusicObjectVtbl dmobject_vtbl = {
272 dmobj_IDirectMusicObject_QueryInterface,
273 dmobj_IDirectMusicObject_AddRef,
274 dmobj_IDirectMusicObject_Release,
275 dmobj_IDirectMusicObject_GetDescriptor,
276 dmobj_IDirectMusicObject_SetDescriptor,
277 graph_IDirectMusicObject_ParseDescriptor
280 static HRESULT WINAPI graph_IPersistStream_Load(IPersistStream *iface, IStream *stream)
282 struct graph *This = impl_from_IPersistStream(iface);
284 FIXME("(%p, %p): Loading not implemented yet\n", This, stream);
286 return IDirectMusicObject_ParseDescriptor(&This->dmobj.IDirectMusicObject_iface, stream,
287 &This->dmobj.desc);
290 static const IPersistStreamVtbl persiststream_vtbl = {
291 dmobj_IPersistStream_QueryInterface,
292 dmobj_IPersistStream_AddRef,
293 dmobj_IPersistStream_Release,
294 dmobj_IPersistStream_GetClassID,
295 unimpl_IPersistStream_IsDirty,
296 graph_IPersistStream_Load,
297 unimpl_IPersistStream_Save,
298 unimpl_IPersistStream_GetSizeMax
301 /* for ClassFactory */
302 HRESULT create_dmgraph(REFIID riid, void **ret_iface)
304 struct graph *obj;
305 HRESULT hr;
307 *ret_iface = NULL;
308 if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
309 obj->IDirectMusicGraph_iface.lpVtbl = &graph_vtbl;
310 obj->ref = 1;
311 dmobject_init(&obj->dmobj, &CLSID_DirectMusicGraph, (IUnknown *)&obj->IDirectMusicGraph_iface);
312 obj->dmobj.IDirectMusicObject_iface.lpVtbl = &dmobject_vtbl;
313 obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
314 list_init(&obj->tools);
316 hr = IDirectMusicGraph_QueryInterface(&obj->IDirectMusicGraph_iface, riid, ret_iface);
317 IDirectMusicGraph_Release(&obj->IDirectMusicGraph_iface);
319 return hr;