2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/midi.c
5 * PURPOSE: Midi Support Functions
6 * PROGRAMMER: Johannes Anderwald
15 MMixerGetPinDataFlowAndCommunication(
16 IN PMIXER_CONTEXT MixerContext
,
19 OUT PKSPIN_DATAFLOW DataFlow
,
20 OUT PKSPIN_COMMUNICATION Communication
)
29 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
30 Pin
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
31 Pin
.Property
.Set
= KSPROPSETID_Pin
;
33 /* get pin dataflow */
34 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)DataFlow
, sizeof(KSPIN_DATAFLOW
), &BytesReturned
);
35 if (Status
!= MM_STATUS_SUCCESS
)
37 /* failed to retrieve dataflow */
41 /* setup communication request */
42 Pin
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
44 /* get pin communication */
45 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (PVOID
)Communication
, sizeof(KSPIN_COMMUNICATION
), &BytesReturned
);
52 IN PMIXER_CONTEXT MixerContext
,
53 IN PMIXER_LIST MixerList
,
61 /* allocate midi info */
62 MidiInfo
= MixerContext
->Alloc(sizeof(MIDI_INFO
));
67 return MM_STATUS_NO_MEMORY
;
70 /* initialize midi info */
71 MidiInfo
->DeviceId
= DeviceId
;
72 MidiInfo
->PinId
= PinId
;
75 ASSERT(!DeviceName
|| (wcslen(DeviceName
) + 1 < MAXPNAMELEN
));
77 /* copy device name */
78 if (bInput
&& DeviceName
)
80 wcscpy(MidiInfo
->u
.InCaps
.szPname
, DeviceName
);
82 else if (!bInput
&& DeviceName
)
84 wcscpy(MidiInfo
->u
.OutCaps
.szPname
, DeviceName
);
87 /* FIXME determine manufacturer / product id */
90 MidiInfo
->u
.InCaps
.dwSupport
= 0;
91 MidiInfo
->u
.InCaps
.wMid
= MM_MICROSOFT
;
92 MidiInfo
->u
.InCaps
.wPid
= MM_PID_UNMAPPED
;
93 MidiInfo
->u
.InCaps
.vDriverVersion
= 1;
97 MidiInfo
->u
.OutCaps
.dwSupport
= 0;
98 MidiInfo
->u
.OutCaps
.wMid
= MM_MICROSOFT
;
99 MidiInfo
->u
.OutCaps
.wPid
= MM_PID_UNMAPPED
;
100 MidiInfo
->u
.OutCaps
.vDriverVersion
= 1;
105 /* insert into list */
106 InsertTailList(&MixerList
->MidiInList
, &MidiInfo
->Entry
);
107 MixerList
->MidiInListCount
++;
111 /* insert into list */
112 InsertTailList(&MixerList
->MidiOutList
, &MidiInfo
->Entry
);
113 MixerList
->MidiOutListCount
++;
116 return MM_STATUS_SUCCESS
;
120 MMixerCheckFilterPinMidiSupport(
121 IN PMIXER_CONTEXT MixerContext
,
122 IN PMIXER_LIST MixerList
,
123 IN LPMIXER_DATA MixerData
,
125 IN PKSMULTIPLE_ITEM MultipleItem
,
129 PKSDATARANGE DataRange
;
130 KSPIN_COMMUNICATION Communication
;
131 KSPIN_DATAFLOW DataFlow
;
133 /* get first datarange */
134 DataRange
= (PKSDATARANGE
)(MultipleItem
+ 1);
136 /* alignment assert */
137 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
139 /* iterate through all data ranges */
140 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
142 if (IsEqualGUIDAligned(&DataRange
->MajorFormat
, &KSDATAFORMAT_TYPE_MUSIC
) &&
143 IsEqualGUIDAligned(&DataRange
->SubFormat
, &KSDATAFORMAT_SUBTYPE_MIDI
) &&
144 IsEqualGUIDAligned(&DataRange
->Specifier
, &KSDATAFORMAT_SPECIFIER_NONE
))
146 /* pin supports midi datarange */
147 if (MMixerGetPinDataFlowAndCommunication(MixerContext
, MixerData
->hDevice
, PinId
, &DataFlow
, &Communication
) == MM_STATUS_SUCCESS
)
149 if (DataFlow
== KSPIN_DATAFLOW_IN
&& Communication
== KSPIN_COMMUNICATION_SINK
)
151 MMixerAddMidiPin(MixerContext
, MixerList
, MixerData
->DeviceId
, PinId
, FALSE
, szPname
);
153 else if (DataFlow
== KSPIN_DATAFLOW_OUT
&& Communication
== KSPIN_COMMUNICATION_SOURCE
)
155 MMixerAddMidiPin(MixerContext
, MixerList
, MixerData
->DeviceId
, PinId
, TRUE
, szPname
);
160 /* move to next datarange */
161 DataRange
= (PKSDATARANGE
)((ULONG_PTR
)DataRange
+ DataRange
->FormatSize
);
163 /* alignment assert */
164 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
166 /* data ranges are 64-bit aligned */
167 DataRange
= (PVOID
)(((ULONG_PTR
)DataRange
+ 0x7) & ~0x7);
172 MMixerInitializeMidiForFilter(
173 IN PMIXER_CONTEXT MixerContext
,
174 IN PMIXER_LIST MixerList
,
175 IN LPMIXER_DATA MixerData
,
176 IN PTOPOLOGY Topology
)
178 ULONG PinCount
, Index
;
180 PKSMULTIPLE_ITEM MultipleItem
;
181 WCHAR szPname
[MAXPNAMELEN
];
183 /* get filter pin count */
184 MMixerGetTopologyPinCount(Topology
, &PinCount
);
187 if (MMixerGetDeviceName(MixerContext
, szPname
, MixerData
->hDeviceInterfaceKey
) != MM_STATUS_SUCCESS
)
193 /* iterate all pins and check for KSDATARANGE_MUSIC support */
194 for(Index
= 0; Index
< PinCount
; Index
++)
196 /* get audio pin data ranges */
197 Status
= MMixerGetAudioPinDataRanges(MixerContext
, MixerData
->hDevice
, Index
, &MultipleItem
);
199 /* check for success */
200 if (Status
== MM_STATUS_SUCCESS
)
202 /* check if there is support KSDATARANGE_MUSIC */
203 MMixerCheckFilterPinMidiSupport(MixerContext
, MixerList
, MixerData
, Index
, MultipleItem
, szPname
);
210 IN PMIXER_CONTEXT MixerContext
,
211 IN PMIXER_LIST MixerList
,
214 IN ACCESS_MASK DesiredAccess
,
215 IN PIN_CREATE_CALLBACK CreateCallback
,
217 OUT PHANDLE PinHandle
)
219 PKSPIN_CONNECT PinConnect
;
220 PKSDATAFORMAT DataFormat
;
221 LPMIXER_DATA MixerData
;
223 MIXER_STATUS MixerStatus
;
225 MixerData
= MMixerGetDataByDeviceId(MixerList
, DeviceId
);
227 return MM_STATUS_INVALID_PARAMETER
;
229 /* allocate pin connect */
230 PinConnect
= MMixerAllocatePinConnect(MixerContext
, sizeof(KSDATAFORMAT
));
234 return MM_STATUS_NO_MEMORY
;
237 /* initialize pin connect struct */
238 MMixerInitializePinConnect(PinConnect
, PinId
);
240 /* get offset to dataformat */
241 DataFormat
= (PKSDATAFORMAT
) (PinConnect
+ 1);
243 /* initialize data format */
244 RtlMoveMemory(&DataFormat
->MajorFormat
, &KSDATAFORMAT_TYPE_MUSIC
, sizeof(GUID
));
245 RtlMoveMemory(&DataFormat
->SubFormat
, &KSDATAFORMAT_SUBTYPE_MIDI
, sizeof(GUID
));
246 RtlMoveMemory(&DataFormat
->Specifier
, &KSDATAFORMAT_SPECIFIER_NONE
, sizeof(GUID
));
250 /* let the callback handle the creation */
251 MixerStatus
= CreateCallback(Context
, DeviceId
, PinId
, MixerData
->hDevice
, PinConnect
, DesiredAccess
, PinHandle
);
255 /* now create the pin */
256 Status
= KsCreatePin(MixerData
->hDevice
, PinConnect
, DesiredAccess
, PinHandle
);
258 /* normalize status */
259 if (Status
== STATUS_SUCCESS
)
260 MixerStatus
= MM_STATUS_SUCCESS
;
262 MixerStatus
= MM_STATUS_UNSUCCESSFUL
;
265 /* free create info */
266 MixerContext
->Free(PinConnect
);
273 MMixerGetMidiInfoByIndexAndType(
274 IN PMIXER_LIST MixerList
,
275 IN ULONG DeviceIndex
,
276 IN ULONG bMidiInputType
,
277 OUT LPMIDI_INFO
*OutMidiInfo
)
280 PLIST_ENTRY Entry
, ListHead
;
281 LPMIDI_INFO MidiInfo
;
284 ListHead
= &MixerList
->MidiInList
;
286 ListHead
= &MixerList
->MidiOutList
;
288 /* get first entry */
289 Entry
= ListHead
->Flink
;
291 while(Entry
!= ListHead
)
293 MidiInfo
= (LPMIDI_INFO
)CONTAINING_RECORD(Entry
, MIDI_INFO
, Entry
);
295 if (Index
== DeviceIndex
)
297 *OutMidiInfo
= MidiInfo
;
298 return MM_STATUS_SUCCESS
;
301 Entry
= Entry
->Flink
;
304 return MM_STATUS_INVALID_PARAMETER
;
308 MMixerMidiOutCapabilities(
309 IN PMIXER_CONTEXT MixerContext
,
310 IN ULONG DeviceIndex
,
311 OUT LPMIDIOUTCAPSW Caps
)
313 PMIXER_LIST MixerList
;
315 LPMIDI_INFO MidiInfo
;
317 /* verify mixer context */
318 Status
= MMixerVerifyContext(MixerContext
);
320 if (Status
!= MM_STATUS_SUCCESS
)
322 /* invalid context passed */
326 /* grab mixer list */
327 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
329 /* find destination midi */
330 Status
= MMixerGetMidiInfoByIndexAndType(MixerList
, DeviceIndex
, FALSE
, &MidiInfo
);
331 if (Status
!= MM_STATUS_SUCCESS
)
333 /* failed to find midi info */
334 return MM_STATUS_UNSUCCESSFUL
;
337 /* copy capabilities */
338 MixerContext
->Copy(Caps
, &MidiInfo
->u
.OutCaps
, sizeof(MIDIOUTCAPSW
));
340 return MM_STATUS_SUCCESS
;
344 MMixerMidiInCapabilities(
345 IN PMIXER_CONTEXT MixerContext
,
346 IN ULONG DeviceIndex
,
347 OUT LPMIDIINCAPSW Caps
)
349 PMIXER_LIST MixerList
;
351 LPMIDI_INFO MidiInfo
;
353 /* verify mixer context */
354 Status
= MMixerVerifyContext(MixerContext
);
356 if (Status
!= MM_STATUS_SUCCESS
)
358 /* invalid context passed */
362 /* grab mixer list */
363 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
365 /* find destination midi */
366 Status
= MMixerGetMidiInfoByIndexAndType(MixerList
, DeviceIndex
, TRUE
, &MidiInfo
);
367 if (Status
!= MM_STATUS_SUCCESS
)
369 /* failed to find midi info */
370 return MM_STATUS_UNSUCCESSFUL
;
373 /* copy capabilities */
374 MixerContext
->Copy(Caps
, &MidiInfo
->u
.InCaps
, sizeof(MIDIINCAPSW
));
376 return MM_STATUS_SUCCESS
;
380 MMixerGetMidiDevicePath(
381 IN PMIXER_CONTEXT MixerContext
,
384 OUT LPWSTR
* DevicePath
)
386 PMIXER_LIST MixerList
;
387 LPMIXER_DATA MixerData
;
388 LPMIDI_INFO MidiInfo
;
392 /* verify mixer context */
393 Status
= MMixerVerifyContext(MixerContext
);
395 if (Status
!= MM_STATUS_SUCCESS
)
397 /* invalid context passed */
401 /* grab mixer list */
402 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
404 /* find destination midi */
405 Status
= MMixerGetMidiInfoByIndexAndType(MixerList
, DeviceId
, bMidiIn
, &MidiInfo
);
406 if (Status
!= MM_STATUS_SUCCESS
)
408 /* failed to find midi info */
409 return MM_STATUS_INVALID_PARAMETER
;
412 /* get associated device id */
413 MixerData
= MMixerGetDataByDeviceId(MixerList
, MidiInfo
->DeviceId
);
415 return MM_STATUS_INVALID_PARAMETER
;
417 /* calculate length */
418 Length
= wcslen(MixerData
->DeviceName
)+1;
420 /* allocate destination buffer */
421 *DevicePath
= MixerContext
->Alloc(Length
* sizeof(WCHAR
));
426 return MM_STATUS_NO_MEMORY
;
429 /* copy device path */
430 MixerContext
->Copy(*DevicePath
, MixerData
->DeviceName
, Length
* sizeof(WCHAR
));
433 return MM_STATUS_SUCCESS
;
438 IN PMIXER_CONTEXT MixerContext
,
445 /* setup property request */
446 Property
.Set
= KSPROPSETID_Connection
;
447 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
448 Property
.Flags
= KSPROPERTY_TYPE_SET
;
450 return MixerContext
->Control(PinHandle
, IOCTL_KS_PROPERTY
, &Property
, sizeof(KSPROPERTY
), &State
, sizeof(KSSTATE
), &Length
);
455 IN PMIXER_CONTEXT MixerContext
,
456 IN ULONG DeviceIndex
,
458 IN PIN_CREATE_CALLBACK CreateCallback
,
460 OUT PHANDLE PinHandle
)
462 PMIXER_LIST MixerList
;
464 LPMIDI_INFO MidiInfo
;
465 ACCESS_MASK DesiredAccess
= 0;
467 /* verify mixer context */
468 Status
= MMixerVerifyContext(MixerContext
);
470 if (Status
!= MM_STATUS_SUCCESS
)
472 /* invalid context passed */
476 /* grab mixer list */
477 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
479 /* find destination midi */
480 Status
= MMixerGetMidiInfoByIndexAndType(MixerList
, DeviceIndex
, bMidiIn
, &MidiInfo
);
481 if (Status
!= MM_STATUS_SUCCESS
)
483 /* failed to find midi info */
484 return MM_STATUS_INVALID_PARAMETER
;
487 /* get desired access */
490 DesiredAccess
|= GENERIC_READ
;
494 DesiredAccess
|= GENERIC_WRITE
;
497 /* now try open the pin */
498 return MMixerOpenMidiPin(MixerContext
, MixerList
, MidiInfo
->DeviceId
, MidiInfo
->PinId
, DesiredAccess
, CreateCallback
, Context
, PinHandle
);
502 MMixerGetMidiInCount(
503 IN PMIXER_CONTEXT MixerContext
)
505 PMIXER_LIST MixerList
;
508 /* verify mixer context */
509 Status
= MMixerVerifyContext(MixerContext
);
511 if (Status
!= MM_STATUS_SUCCESS
)
513 /* invalid context passed */
517 /* grab mixer list */
518 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
520 return MixerList
->MidiInListCount
;
524 MMixerGetMidiOutCount(
525 IN PMIXER_CONTEXT MixerContext
)
527 PMIXER_LIST MixerList
;
530 /* verify mixer context */
531 Status
= MMixerVerifyContext(MixerContext
);
533 if (Status
!= MM_STATUS_SUCCESS
)
535 /* invalid context passed */
539 /* grab mixer list */
540 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
542 return MixerList
->MidiOutListCount
;