1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS Kernel Streaming
4c2c66affSColin Finck * FILE: lib/drivers/sound/mmixer/midi.c
5c2c66affSColin Finck * PURPOSE: Midi Support Functions
6c2c66affSColin Finck * PROGRAMMER: Johannes Anderwald
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck #include "precomp.h"
10c2c66affSColin Finck
11*60b0afc3SSerge Gautherie // #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck
14c2c66affSColin Finck MIXER_STATUS
MMixerGetPinDataFlowAndCommunication(IN PMIXER_CONTEXT MixerContext,IN HANDLE hDevice,IN ULONG PinId,OUT PKSPIN_DATAFLOW DataFlow,OUT PKSPIN_COMMUNICATION Communication)15c2c66affSColin Finck MMixerGetPinDataFlowAndCommunication(
16c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
17c2c66affSColin Finck IN HANDLE hDevice,
18c2c66affSColin Finck IN ULONG PinId,
19c2c66affSColin Finck OUT PKSPIN_DATAFLOW DataFlow,
20c2c66affSColin Finck OUT PKSPIN_COMMUNICATION Communication)
21c2c66affSColin Finck {
22c2c66affSColin Finck KSP_PIN Pin;
23c2c66affSColin Finck ULONG BytesReturned;
24c2c66affSColin Finck MIXER_STATUS Status;
25c2c66affSColin Finck
26c2c66affSColin Finck /* setup request */
27c2c66affSColin Finck Pin.PinId = PinId;
28c2c66affSColin Finck Pin.Reserved = 0;
29c2c66affSColin Finck Pin.Property.Flags = KSPROPERTY_TYPE_GET;
30c2c66affSColin Finck Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW;
31c2c66affSColin Finck Pin.Property.Set = KSPROPSETID_Pin;
32c2c66affSColin Finck
33c2c66affSColin Finck /* get pin dataflow */
34c2c66affSColin Finck Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
35c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
36c2c66affSColin Finck {
37c2c66affSColin Finck /* failed to retrieve dataflow */
38c2c66affSColin Finck return Status;
39c2c66affSColin Finck }
40c2c66affSColin Finck
41c2c66affSColin Finck /* setup communication request */
42c2c66affSColin Finck Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
43c2c66affSColin Finck
44c2c66affSColin Finck /* get pin communication */
45c2c66affSColin Finck Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
46c2c66affSColin Finck
47c2c66affSColin Finck return Status;
48c2c66affSColin Finck }
49c2c66affSColin Finck
50c2c66affSColin Finck MIXER_STATUS
MMixerAddMidiPin(IN PMIXER_CONTEXT MixerContext,IN PMIXER_LIST MixerList,IN ULONG DeviceId,IN ULONG PinId,IN ULONG bInput,IN LPWSTR DeviceName)51c2c66affSColin Finck MMixerAddMidiPin(
52c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
53c2c66affSColin Finck IN PMIXER_LIST MixerList,
54c2c66affSColin Finck IN ULONG DeviceId,
55c2c66affSColin Finck IN ULONG PinId,
56c2c66affSColin Finck IN ULONG bInput,
57c2c66affSColin Finck IN LPWSTR DeviceName)
58c2c66affSColin Finck {
59c2c66affSColin Finck LPMIDI_INFO MidiInfo;
60c2c66affSColin Finck
61c2c66affSColin Finck /* allocate midi info */
62c2c66affSColin Finck MidiInfo = MixerContext->Alloc(sizeof(MIDI_INFO));
63c2c66affSColin Finck
64c2c66affSColin Finck if (!MidiInfo)
65c2c66affSColin Finck {
66c2c66affSColin Finck /* no memory */
67c2c66affSColin Finck return MM_STATUS_NO_MEMORY;
68c2c66affSColin Finck }
69c2c66affSColin Finck
70c2c66affSColin Finck /* initialize midi info */
71c2c66affSColin Finck MidiInfo->DeviceId = DeviceId;
72c2c66affSColin Finck MidiInfo->PinId = PinId;
73c2c66affSColin Finck
74c2c66affSColin Finck /* sanity check */
752bbc94c6SThomas Faber ASSERT(!DeviceName || (wcslen(DeviceName) < MAXPNAMELEN));
76c2c66affSColin Finck
77c2c66affSColin Finck /* copy device name */
78c2c66affSColin Finck if (bInput && DeviceName)
79c2c66affSColin Finck {
80c2c66affSColin Finck wcscpy(MidiInfo->u.InCaps.szPname, DeviceName);
81c2c66affSColin Finck }
82c2c66affSColin Finck else if (!bInput && DeviceName)
83c2c66affSColin Finck {
84c2c66affSColin Finck wcscpy(MidiInfo->u.OutCaps.szPname, DeviceName);
85c2c66affSColin Finck }
86c2c66affSColin Finck
87c2c66affSColin Finck /* FIXME determine manufacturer / product id */
88c2c66affSColin Finck if (bInput)
89c2c66affSColin Finck {
90c2c66affSColin Finck MidiInfo->u.InCaps.dwSupport = 0;
91c2c66affSColin Finck MidiInfo->u.InCaps.wMid = MM_MICROSOFT;
92c2c66affSColin Finck MidiInfo->u.InCaps.wPid = MM_PID_UNMAPPED;
93c2c66affSColin Finck MidiInfo->u.InCaps.vDriverVersion = 1;
94c2c66affSColin Finck }
95c2c66affSColin Finck else
96c2c66affSColin Finck {
97c2c66affSColin Finck MidiInfo->u.OutCaps.dwSupport = 0;
98c2c66affSColin Finck MidiInfo->u.OutCaps.wMid = MM_MICROSOFT;
99c2c66affSColin Finck MidiInfo->u.OutCaps.wPid = MM_PID_UNMAPPED;
100c2c66affSColin Finck MidiInfo->u.OutCaps.vDriverVersion = 1;
101c2c66affSColin Finck }
102c2c66affSColin Finck
103c2c66affSColin Finck if (bInput)
104c2c66affSColin Finck {
105c2c66affSColin Finck /* insert into list */
106c2c66affSColin Finck InsertTailList(&MixerList->MidiInList, &MidiInfo->Entry);
107c2c66affSColin Finck MixerList->MidiInListCount++;
108c2c66affSColin Finck }
109c2c66affSColin Finck else
110c2c66affSColin Finck {
111c2c66affSColin Finck /* insert into list */
112c2c66affSColin Finck InsertTailList(&MixerList->MidiOutList, &MidiInfo->Entry);
113c2c66affSColin Finck MixerList->MidiOutListCount++;
114c2c66affSColin Finck }
115c2c66affSColin Finck
116c2c66affSColin Finck return MM_STATUS_SUCCESS;
117c2c66affSColin Finck }
118c2c66affSColin Finck
119c2c66affSColin Finck VOID
MMixerCheckFilterPinMidiSupport(IN PMIXER_CONTEXT MixerContext,IN PMIXER_LIST MixerList,IN LPMIXER_DATA MixerData,IN ULONG PinId,IN PKSMULTIPLE_ITEM MultipleItem,IN LPWSTR szPname)120c2c66affSColin Finck MMixerCheckFilterPinMidiSupport(
121c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
122c2c66affSColin Finck IN PMIXER_LIST MixerList,
123c2c66affSColin Finck IN LPMIXER_DATA MixerData,
124c2c66affSColin Finck IN ULONG PinId,
125c2c66affSColin Finck IN PKSMULTIPLE_ITEM MultipleItem,
126c2c66affSColin Finck IN LPWSTR szPname)
127c2c66affSColin Finck {
128c2c66affSColin Finck ULONG Index;
129c2c66affSColin Finck PKSDATARANGE DataRange;
130c2c66affSColin Finck KSPIN_COMMUNICATION Communication;
131c2c66affSColin Finck KSPIN_DATAFLOW DataFlow;
132c2c66affSColin Finck
133c2c66affSColin Finck /* get first datarange */
134c2c66affSColin Finck DataRange = (PKSDATARANGE)(MultipleItem + 1);
135c2c66affSColin Finck
136c2c66affSColin Finck /* alignment assert */
137c2c66affSColin Finck ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
138c2c66affSColin Finck
139c2c66affSColin Finck /* iterate through all data ranges */
140c2c66affSColin Finck for(Index = 0; Index < MultipleItem->Count; Index++)
141c2c66affSColin Finck {
142c2c66affSColin Finck if (IsEqualGUIDAligned(&DataRange->MajorFormat, &KSDATAFORMAT_TYPE_MUSIC) &&
143c2c66affSColin Finck IsEqualGUIDAligned(&DataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_MIDI) &&
144c2c66affSColin Finck IsEqualGUIDAligned(&DataRange->Specifier, &KSDATAFORMAT_SPECIFIER_NONE))
145c2c66affSColin Finck {
146c2c66affSColin Finck /* pin supports midi datarange */
147c2c66affSColin Finck if (MMixerGetPinDataFlowAndCommunication(MixerContext, MixerData->hDevice, PinId, &DataFlow, &Communication) == MM_STATUS_SUCCESS)
148c2c66affSColin Finck {
149c2c66affSColin Finck if (DataFlow == KSPIN_DATAFLOW_IN && Communication == KSPIN_COMMUNICATION_SINK)
150c2c66affSColin Finck {
151c2c66affSColin Finck MMixerAddMidiPin(MixerContext, MixerList, MixerData->DeviceId, PinId, FALSE, szPname);
152c2c66affSColin Finck }
153c2c66affSColin Finck else if (DataFlow == KSPIN_DATAFLOW_OUT && Communication == KSPIN_COMMUNICATION_SOURCE)
154c2c66affSColin Finck {
155c2c66affSColin Finck MMixerAddMidiPin(MixerContext, MixerList, MixerData->DeviceId, PinId, TRUE, szPname);
156c2c66affSColin Finck }
157c2c66affSColin Finck }
158c2c66affSColin Finck }
159c2c66affSColin Finck
160c2c66affSColin Finck /* move to next datarange */
161c2c66affSColin Finck DataRange = (PKSDATARANGE)((ULONG_PTR)DataRange + DataRange->FormatSize);
162c2c66affSColin Finck
163c2c66affSColin Finck /* alignment assert */
164c2c66affSColin Finck ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
165c2c66affSColin Finck
166c2c66affSColin Finck /* data ranges are 64-bit aligned */
167c2c66affSColin Finck DataRange = (PVOID)(((ULONG_PTR)DataRange + 0x7) & ~0x7);
168c2c66affSColin Finck }
169c2c66affSColin Finck }
170c2c66affSColin Finck
171c2c66affSColin Finck VOID
MMixerInitializeMidiForFilter(IN PMIXER_CONTEXT MixerContext,IN PMIXER_LIST MixerList,IN LPMIXER_DATA MixerData,IN PTOPOLOGY Topology)172c2c66affSColin Finck MMixerInitializeMidiForFilter(
173c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
174c2c66affSColin Finck IN PMIXER_LIST MixerList,
175c2c66affSColin Finck IN LPMIXER_DATA MixerData,
176c2c66affSColin Finck IN PTOPOLOGY Topology)
177c2c66affSColin Finck {
178c2c66affSColin Finck ULONG PinCount, Index;
179c2c66affSColin Finck MIXER_STATUS Status;
180c2c66affSColin Finck PKSMULTIPLE_ITEM MultipleItem;
181c2c66affSColin Finck WCHAR szPname[MAXPNAMELEN];
182c2c66affSColin Finck
183c2c66affSColin Finck /* get filter pin count */
184c2c66affSColin Finck MMixerGetTopologyPinCount(Topology, &PinCount);
185c2c66affSColin Finck
186c2c66affSColin Finck /* get mixer name */
187c2c66affSColin Finck if (MMixerGetDeviceName(MixerContext, szPname, MixerData->hDeviceInterfaceKey) != MM_STATUS_SUCCESS)
188c2c66affSColin Finck {
189c2c66affSColin Finck /* clear name */
190c2c66affSColin Finck szPname[0] = 0;
191c2c66affSColin Finck }
192c2c66affSColin Finck
193c2c66affSColin Finck /* iterate all pins and check for KSDATARANGE_MUSIC support */
194c2c66affSColin Finck for(Index = 0; Index < PinCount; Index++)
195c2c66affSColin Finck {
196c2c66affSColin Finck /* get audio pin data ranges */
197c2c66affSColin Finck Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Index, &MultipleItem);
198c2c66affSColin Finck
199c2c66affSColin Finck /* check for success */
200c2c66affSColin Finck if (Status == MM_STATUS_SUCCESS)
201c2c66affSColin Finck {
202c2c66affSColin Finck /* check if there is support KSDATARANGE_MUSIC */
203c2c66affSColin Finck MMixerCheckFilterPinMidiSupport(MixerContext, MixerList, MixerData, Index, MultipleItem, szPname);
204c2c66affSColin Finck }
205c2c66affSColin Finck }
206c2c66affSColin Finck }
207c2c66affSColin Finck
208c2c66affSColin Finck MIXER_STATUS
MMixerOpenMidiPin(IN PMIXER_CONTEXT MixerContext,IN PMIXER_LIST MixerList,IN ULONG DeviceId,IN ULONG PinId,IN ACCESS_MASK DesiredAccess,IN PIN_CREATE_CALLBACK CreateCallback,IN PVOID Context,OUT PHANDLE PinHandle)209c2c66affSColin Finck MMixerOpenMidiPin(
210c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
211c2c66affSColin Finck IN PMIXER_LIST MixerList,
212c2c66affSColin Finck IN ULONG DeviceId,
213c2c66affSColin Finck IN ULONG PinId,
214c2c66affSColin Finck IN ACCESS_MASK DesiredAccess,
215c2c66affSColin Finck IN PIN_CREATE_CALLBACK CreateCallback,
216c2c66affSColin Finck IN PVOID Context,
217c2c66affSColin Finck OUT PHANDLE PinHandle)
218c2c66affSColin Finck {
219c2c66affSColin Finck PKSPIN_CONNECT PinConnect;
220c2c66affSColin Finck PKSDATAFORMAT DataFormat;
221c2c66affSColin Finck LPMIXER_DATA MixerData;
222c2c66affSColin Finck NTSTATUS Status;
223c2c66affSColin Finck MIXER_STATUS MixerStatus;
224c2c66affSColin Finck
225c2c66affSColin Finck MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId);
226c2c66affSColin Finck if (!MixerData)
227c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
228c2c66affSColin Finck
229c2c66affSColin Finck /* allocate pin connect */
230c2c66affSColin Finck PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT));
231c2c66affSColin Finck if (!PinConnect)
232c2c66affSColin Finck {
233c2c66affSColin Finck /* no memory */
234c2c66affSColin Finck return MM_STATUS_NO_MEMORY;
235c2c66affSColin Finck }
236c2c66affSColin Finck
237c2c66affSColin Finck /* initialize pin connect struct */
238c2c66affSColin Finck MMixerInitializePinConnect(PinConnect, PinId);
239c2c66affSColin Finck
240c2c66affSColin Finck /* get offset to dataformat */
241c2c66affSColin Finck DataFormat = (PKSDATAFORMAT) (PinConnect + 1);
242c2c66affSColin Finck
243c2c66affSColin Finck /* initialize data format */
244c2c66affSColin Finck RtlMoveMemory(&DataFormat->MajorFormat, &KSDATAFORMAT_TYPE_MUSIC, sizeof(GUID));
245c2c66affSColin Finck RtlMoveMemory(&DataFormat->SubFormat, &KSDATAFORMAT_SUBTYPE_MIDI, sizeof(GUID));
246c2c66affSColin Finck RtlMoveMemory(&DataFormat->Specifier, &KSDATAFORMAT_SPECIFIER_NONE, sizeof(GUID));
247c2c66affSColin Finck
248c2c66affSColin Finck if (CreateCallback)
249c2c66affSColin Finck {
250c2c66affSColin Finck /* let the callback handle the creation */
251c2c66affSColin Finck MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
252c2c66affSColin Finck }
253c2c66affSColin Finck else
254c2c66affSColin Finck {
255c2c66affSColin Finck /* now create the pin */
256c2c66affSColin Finck Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
257c2c66affSColin Finck
258c2c66affSColin Finck /* normalize status */
259c2c66affSColin Finck if (Status == STATUS_SUCCESS)
260c2c66affSColin Finck MixerStatus = MM_STATUS_SUCCESS;
261c2c66affSColin Finck else
262c2c66affSColin Finck MixerStatus = MM_STATUS_UNSUCCESSFUL;
263c2c66affSColin Finck }
264c2c66affSColin Finck
265c2c66affSColin Finck /* free create info */
266c2c66affSColin Finck MixerContext->Free(PinConnect);
267c2c66affSColin Finck
268c2c66affSColin Finck /* done */
269c2c66affSColin Finck return MixerStatus;
270c2c66affSColin Finck }
271c2c66affSColin Finck
272c2c66affSColin Finck MIXER_STATUS
MMixerGetMidiInfoByIndexAndType(IN PMIXER_LIST MixerList,IN ULONG DeviceIndex,IN ULONG bMidiInputType,OUT LPMIDI_INFO * OutMidiInfo)273c2c66affSColin Finck MMixerGetMidiInfoByIndexAndType(
274c2c66affSColin Finck IN PMIXER_LIST MixerList,
275c2c66affSColin Finck IN ULONG DeviceIndex,
276c2c66affSColin Finck IN ULONG bMidiInputType,
277c2c66affSColin Finck OUT LPMIDI_INFO *OutMidiInfo)
278c2c66affSColin Finck {
279c2c66affSColin Finck ULONG Index = 0;
280c2c66affSColin Finck PLIST_ENTRY Entry, ListHead;
281c2c66affSColin Finck LPMIDI_INFO MidiInfo;
282c2c66affSColin Finck
283c2c66affSColin Finck if (bMidiInputType)
284c2c66affSColin Finck ListHead = &MixerList->MidiInList;
285c2c66affSColin Finck else
286c2c66affSColin Finck ListHead = &MixerList->MidiOutList;
287c2c66affSColin Finck
288c2c66affSColin Finck /* get first entry */
289c2c66affSColin Finck Entry = ListHead->Flink;
290c2c66affSColin Finck
291c2c66affSColin Finck while(Entry != ListHead)
292c2c66affSColin Finck {
293c2c66affSColin Finck MidiInfo = (LPMIDI_INFO)CONTAINING_RECORD(Entry, MIDI_INFO, Entry);
294c2c66affSColin Finck
295c2c66affSColin Finck if (Index == DeviceIndex)
296c2c66affSColin Finck {
297c2c66affSColin Finck *OutMidiInfo = MidiInfo;
298c2c66affSColin Finck return MM_STATUS_SUCCESS;
299c2c66affSColin Finck }
300c2c66affSColin Finck Index++;
301c2c66affSColin Finck Entry = Entry->Flink;
302c2c66affSColin Finck }
303c2c66affSColin Finck
304c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
305c2c66affSColin Finck }
306c2c66affSColin Finck
307c2c66affSColin Finck MIXER_STATUS
MMixerMidiOutCapabilities(IN PMIXER_CONTEXT MixerContext,IN ULONG DeviceIndex,OUT LPMIDIOUTCAPSW Caps)308c2c66affSColin Finck MMixerMidiOutCapabilities(
309c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
310c2c66affSColin Finck IN ULONG DeviceIndex,
311c2c66affSColin Finck OUT LPMIDIOUTCAPSW Caps)
312c2c66affSColin Finck {
313c2c66affSColin Finck PMIXER_LIST MixerList;
314c2c66affSColin Finck MIXER_STATUS Status;
315c2c66affSColin Finck LPMIDI_INFO MidiInfo;
316c2c66affSColin Finck
317c2c66affSColin Finck /* verify mixer context */
318c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
319c2c66affSColin Finck
320c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
321c2c66affSColin Finck {
322c2c66affSColin Finck /* invalid context passed */
323c2c66affSColin Finck return Status;
324c2c66affSColin Finck }
325c2c66affSColin Finck
326c2c66affSColin Finck /* grab mixer list */
327c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
328c2c66affSColin Finck
329c2c66affSColin Finck /* find destination midi */
330c2c66affSColin Finck Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceIndex, FALSE, &MidiInfo);
331c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
332c2c66affSColin Finck {
333c2c66affSColin Finck /* failed to find midi info */
334c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
335c2c66affSColin Finck }
336c2c66affSColin Finck
337c2c66affSColin Finck /* copy capabilities */
338c2c66affSColin Finck MixerContext->Copy(Caps, &MidiInfo->u.OutCaps, sizeof(MIDIOUTCAPSW));
339c2c66affSColin Finck
340c2c66affSColin Finck return MM_STATUS_SUCCESS;
341c2c66affSColin Finck }
342c2c66affSColin Finck
343c2c66affSColin Finck MIXER_STATUS
MMixerMidiInCapabilities(IN PMIXER_CONTEXT MixerContext,IN ULONG DeviceIndex,OUT LPMIDIINCAPSW Caps)344c2c66affSColin Finck MMixerMidiInCapabilities(
345c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
346c2c66affSColin Finck IN ULONG DeviceIndex,
347c2c66affSColin Finck OUT LPMIDIINCAPSW Caps)
348c2c66affSColin Finck {
349c2c66affSColin Finck PMIXER_LIST MixerList;
350c2c66affSColin Finck MIXER_STATUS Status;
351c2c66affSColin Finck LPMIDI_INFO MidiInfo;
352c2c66affSColin Finck
353c2c66affSColin Finck /* verify mixer context */
354c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
355c2c66affSColin Finck
356c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
357c2c66affSColin Finck {
358c2c66affSColin Finck /* invalid context passed */
359c2c66affSColin Finck return Status;
360c2c66affSColin Finck }
361c2c66affSColin Finck
362c2c66affSColin Finck /* grab mixer list */
363c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
364c2c66affSColin Finck
365c2c66affSColin Finck /* find destination midi */
366c2c66affSColin Finck Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceIndex, TRUE, &MidiInfo);
367c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
368c2c66affSColin Finck {
369c2c66affSColin Finck /* failed to find midi info */
370c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
371c2c66affSColin Finck }
372c2c66affSColin Finck
373c2c66affSColin Finck /* copy capabilities */
374c2c66affSColin Finck MixerContext->Copy(Caps, &MidiInfo->u.InCaps, sizeof(MIDIINCAPSW));
375c2c66affSColin Finck
376c2c66affSColin Finck return MM_STATUS_SUCCESS;
377c2c66affSColin Finck }
378c2c66affSColin Finck
379c2c66affSColin Finck MIXER_STATUS
MMixerGetMidiDevicePath(IN PMIXER_CONTEXT MixerContext,IN ULONG bMidiIn,IN ULONG DeviceId,OUT LPWSTR * DevicePath)380c2c66affSColin Finck MMixerGetMidiDevicePath(
381c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
382c2c66affSColin Finck IN ULONG bMidiIn,
383c2c66affSColin Finck IN ULONG DeviceId,
384c2c66affSColin Finck OUT LPWSTR * DevicePath)
385c2c66affSColin Finck {
386c2c66affSColin Finck PMIXER_LIST MixerList;
387c2c66affSColin Finck LPMIXER_DATA MixerData;
388c2c66affSColin Finck LPMIDI_INFO MidiInfo;
3899e066abeSTimo Kreuzer SIZE_T Length;
390c2c66affSColin Finck MIXER_STATUS Status;
391c2c66affSColin Finck
392c2c66affSColin Finck /* verify mixer context */
393c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
394c2c66affSColin Finck
395c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
396c2c66affSColin Finck {
397c2c66affSColin Finck /* invalid context passed */
398c2c66affSColin Finck return Status;
399c2c66affSColin Finck }
400c2c66affSColin Finck
401c2c66affSColin Finck /* grab mixer list */
402c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
403c2c66affSColin Finck
404c2c66affSColin Finck /* find destination midi */
405c2c66affSColin Finck Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceId, bMidiIn, &MidiInfo);
406c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
407c2c66affSColin Finck {
408c2c66affSColin Finck /* failed to find midi info */
409c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
410c2c66affSColin Finck }
411c2c66affSColin Finck
412c2c66affSColin Finck /* get associated device id */
413c2c66affSColin Finck MixerData = MMixerGetDataByDeviceId(MixerList, MidiInfo->DeviceId);
414c2c66affSColin Finck if (!MixerData)
415c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
416c2c66affSColin Finck
417c2c66affSColin Finck /* calculate length */
418c2c66affSColin Finck Length = wcslen(MixerData->DeviceName)+1;
419c2c66affSColin Finck
420c2c66affSColin Finck /* allocate destination buffer */
421c2c66affSColin Finck *DevicePath = MixerContext->Alloc(Length * sizeof(WCHAR));
422c2c66affSColin Finck
423c2c66affSColin Finck if (!*DevicePath)
424c2c66affSColin Finck {
425c2c66affSColin Finck /* no memory */
426c2c66affSColin Finck return MM_STATUS_NO_MEMORY;
427c2c66affSColin Finck }
428c2c66affSColin Finck
429c2c66affSColin Finck /* copy device path */
430c2c66affSColin Finck MixerContext->Copy(*DevicePath, MixerData->DeviceName, Length * sizeof(WCHAR));
431c2c66affSColin Finck
432c2c66affSColin Finck /* done */
433c2c66affSColin Finck return MM_STATUS_SUCCESS;
434c2c66affSColin Finck }
435c2c66affSColin Finck
436c2c66affSColin Finck MIXER_STATUS
MMixerSetMidiStatus(IN PMIXER_CONTEXT MixerContext,IN HANDLE PinHandle,IN KSSTATE State)437c2c66affSColin Finck MMixerSetMidiStatus(
438c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
439c2c66affSColin Finck IN HANDLE PinHandle,
440c2c66affSColin Finck IN KSSTATE State)
441c2c66affSColin Finck {
442c2c66affSColin Finck KSPROPERTY Property;
443c2c66affSColin Finck ULONG Length;
444c2c66affSColin Finck
445c2c66affSColin Finck /* setup property request */
446c2c66affSColin Finck Property.Set = KSPROPSETID_Connection;
447c2c66affSColin Finck Property.Id = KSPROPERTY_CONNECTION_STATE;
448c2c66affSColin Finck Property.Flags = KSPROPERTY_TYPE_SET;
449c2c66affSColin Finck
450c2c66affSColin Finck return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length);
451c2c66affSColin Finck }
452c2c66affSColin Finck
453c2c66affSColin Finck MIXER_STATUS
MMixerOpenMidi(IN PMIXER_CONTEXT MixerContext,IN ULONG DeviceIndex,IN ULONG bMidiIn,IN PIN_CREATE_CALLBACK CreateCallback,IN PVOID Context,OUT PHANDLE PinHandle)454c2c66affSColin Finck MMixerOpenMidi(
455c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
456c2c66affSColin Finck IN ULONG DeviceIndex,
457c2c66affSColin Finck IN ULONG bMidiIn,
458c2c66affSColin Finck IN PIN_CREATE_CALLBACK CreateCallback,
459c2c66affSColin Finck IN PVOID Context,
460c2c66affSColin Finck OUT PHANDLE PinHandle)
461c2c66affSColin Finck {
462c2c66affSColin Finck PMIXER_LIST MixerList;
463c2c66affSColin Finck MIXER_STATUS Status;
464c2c66affSColin Finck LPMIDI_INFO MidiInfo;
465c2c66affSColin Finck ACCESS_MASK DesiredAccess = 0;
466c2c66affSColin Finck
467c2c66affSColin Finck /* verify mixer context */
468c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
469c2c66affSColin Finck
470c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
471c2c66affSColin Finck {
472c2c66affSColin Finck /* invalid context passed */
473c2c66affSColin Finck return Status;
474c2c66affSColin Finck }
475c2c66affSColin Finck
476c2c66affSColin Finck /* grab mixer list */
477c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
478c2c66affSColin Finck
479c2c66affSColin Finck /* find destination midi */
480c2c66affSColin Finck Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceIndex, bMidiIn, &MidiInfo);
481c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
482c2c66affSColin Finck {
483c2c66affSColin Finck /* failed to find midi info */
484c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
485c2c66affSColin Finck }
486c2c66affSColin Finck
487c2c66affSColin Finck /* get desired access */
488c2c66affSColin Finck if (bMidiIn)
489c2c66affSColin Finck {
490c2c66affSColin Finck DesiredAccess |= GENERIC_READ;
491c2c66affSColin Finck }
492c2c66affSColin Finck else
493c2c66affSColin Finck {
494c2c66affSColin Finck DesiredAccess |= GENERIC_WRITE;
495c2c66affSColin Finck }
496c2c66affSColin Finck
497c2c66affSColin Finck /* now try open the pin */
498c2c66affSColin Finck return MMixerOpenMidiPin(MixerContext, MixerList, MidiInfo->DeviceId, MidiInfo->PinId, DesiredAccess, CreateCallback, Context, PinHandle);
499c2c66affSColin Finck }
500c2c66affSColin Finck
501c2c66affSColin Finck ULONG
MMixerGetMidiInCount(IN PMIXER_CONTEXT MixerContext)502c2c66affSColin Finck MMixerGetMidiInCount(
503c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext)
504c2c66affSColin Finck {
505c2c66affSColin Finck PMIXER_LIST MixerList;
506c2c66affSColin Finck MIXER_STATUS Status;
507c2c66affSColin Finck
508c2c66affSColin Finck /* verify mixer context */
509c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
510c2c66affSColin Finck
511c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
512c2c66affSColin Finck {
513c2c66affSColin Finck /* invalid context passed */
514c2c66affSColin Finck return Status;
515c2c66affSColin Finck }
516c2c66affSColin Finck
517c2c66affSColin Finck /* grab mixer list */
518c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
519c2c66affSColin Finck
520c2c66affSColin Finck return MixerList->MidiInListCount;
521c2c66affSColin Finck }
522c2c66affSColin Finck
523c2c66affSColin Finck ULONG
MMixerGetMidiOutCount(IN PMIXER_CONTEXT MixerContext)524c2c66affSColin Finck MMixerGetMidiOutCount(
525c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext)
526c2c66affSColin Finck {
527c2c66affSColin Finck PMIXER_LIST MixerList;
528c2c66affSColin Finck MIXER_STATUS Status;
529c2c66affSColin Finck
530c2c66affSColin Finck /* verify mixer context */
531c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
532c2c66affSColin Finck
533c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
534c2c66affSColin Finck {
535c2c66affSColin Finck /* invalid context passed */
536c2c66affSColin Finck return Status;
537c2c66affSColin Finck }
538c2c66affSColin Finck
539c2c66affSColin Finck /* grab mixer list */
540c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
541c2c66affSColin Finck
542c2c66affSColin Finck return MixerList->MidiOutListCount;
543c2c66affSColin Finck }
544