How does one discover [non-Apple] Audio Units with Audio Component Services? - macos

In OS X, I am trying to find an example of how to discover all the Audio Units installed on an end-users system and get back that information for display and use.
I know that Audio Component is involved with that task, but I am completely baffled how to go about doing it. All the examples I come across are based around finding a 'known' Apple AU with AudioComponentFindNext, and I cannot find an example for discovering anything else.
Can anyone point me to an example?
Thanks

You can set up a AudioComponentDescription struct using 0 as a wildcard for type, subtype, and manufacturer. Pass that to AudioComponentFindNext:
AudioComponentDescription acd = { 0 };
AudioComponent comp = nullptr;
while((comp = AudioComponentFindNext(comp, &acd)) {
// Found an AU
}
Here is some relevant documentation from the header:
#function AudioComponentFindNext
#abstract Finds an audio component.
#discussion This function is used to find an audio component that is the closest match
to the provided values.
#param inComponent
If NULL, then the search starts from the beginning until an audio
component is found that matches the description provided by inDesc.
If non-NULL, then the search starts (continues) from the previously
found audio component specified by inComponent, and will return the next
found audio component.
#param inDesc
The type, subtype and manufacturer fields are used to specify the audio
component to search for. A value of 0 (zero) for any of these fields is
a wildcard, so the first match found is returned.
#result An audio component that matches the search parameters, or NULL if none found.

Simply use the provided AVAudioUnitComponentManager components function to get audio units.
It will return an array of audio units that match the AudioComponentDescription you pass.
Command click AudioComponentDescription and kAudioUnitType_MusicDevice to see the various values you can use.
// Exemple to get instruments audio units
var match = AudioComponentDescription()
match.componentType = kAudioUnitType_MusicDevice
let audioUnitComponents = AVAudioUnitComponentManager.shared().components(matching: match)

Related

optional vertexbufferobjects in directx11

I have some models (geometries) which have some vertexinformation. For example position, normal, color, texcoord each of this information has its own vertexbuffer. But some of these models have texture coordinates some not...
To manage these differences I wrote a vertexshader which is checking, if the flag inside the constantbuffer "hasTextureCoordinates" is == 1. And if so it uses the texcoord parameter or not.
But Directx does not realy like this workaround and prints out:
D3D11 INFO: ID3D11DeviceContext::Draw: Element [3] in the current Input Layout's declaration references input slot 3, but there is no Buffer bound to this slot. This is OK, as reads from an empty slot are defined to return 0. It is also possible the developer knows the data will not be used anyway. This is only a problem if the developer actually intended to bind an input Buffer here. [ EXECUTION INFO #348: DEVICE_DRAW_VERTEX_BUFFER_NOT_SET]
I'm not sure if every hardware handles this correctly, also it's not nice to see inside the output this "warnings" every frame...
I know i could write two shaders, one with and one without texcoods, but the problem is that this is not the only maybe missing parameter... some has color other not, some has color and texturecoordinates and so on. And to write a shader for each combination of vertexbuffer inputs is extremly redundant. this is extremly bad, because if we change one shader, we have to change all other too. There is also the possibility of put parts of the shader to different files and include them, but it's confusing.
Is there a way to say directx that the specific vertexbuffer is optional?
Or does someone knows a better solution for this problem?
You can suppress this specific message programmatically. As it's an INFO rather than an ERROR or CORRUPTION message, it's safe to ignore.
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
ComPtr<ID3D11Debug> d3dDebug;
if ( SUCCEEDED( device.As(&d3dDebug) ) )
{
ComPtr<ID3D11InfoQueue> d3dInfoQueue;
if ( SUCCEEDED( d3dDebug.As(&d3dInfoQueue) ) )
{
#ifdef _DEBUG
d3dInfoQueue->SetBreakOnSeverity( D3D11_MESSAGE_SEVERITY_CORRUPTION, true );
d3dInfoQueue->SetBreakOnSeverity( D3D11_MESSAGE_SEVERITY_ERROR, true );
#endif
D3D11_MESSAGE_ID hide[] =
{
D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_NOT_SET, // <--- Your message here!
// Add more message IDs here as needed
};
D3D11_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumIDs = _countof(hide);
filter.DenyList.pIDList = hide;
d3dInfoQueue->AddStorageFilterEntries( &filter );
}
}
In addition to suppressing 'noise' messages, in debug builds this also causes the debug layer to generate a break-point if you do hit a ERROR or CORRUPTION message as those really need to be fixed.
See Direct3D SDK Debug Layer Tricks
Note I'm using ComPtr here to simplify the QueryInterface chain, and I assume you are keeping your device as a ComPtr<ID3D11Device> device as I do in in Anatomy of Direct3D 11 Create Device
I also assume you are using VS 2013 or later so that D3D11_INFO_QUEUE_FILTER filter = {}; is sufficient to zero-fill the structure.

What's the difference between event's Unique-ID and Channel-Call-UUID?

Freeswitch events contain two variables (Unique-ID and Channel-Call-UUID) that seem to always be set to the exact same value: the leg's unique identifier.
I don't see the purpose of this and while Unique-ID has a one-line documentation on FS's wiki ("uuid of this channel's call leg"), Channel-Call-UUID doesn't.
Even worse: I came accross two examples where their values were different:
[...]
Channel-Call-UUID: c9bbde8b-379b-45d4-b193-3f761a44f3e2
Unique-ID: 81273088-c31f-4469-85a6-c878e42210e5
[...]
[...]
Channel-Call-UUID: ada7f3de-2374-4144-9b1d-eade29df0779
Unique-ID: f3ebca6c-d9cd-4f89-ae12-748e6c479dda
[...]
I need to be able to clearly identify a leg in my code, so I'd like to know
which one is the most accurate and
what's the purpose of the other one
"Unique-ID" identifies the leg of the current channel (this value seems to always be identical to "Caller-Unique-ID", documented as "This channel's uuid").
"Channel-Call-UUID" is an ID that can be used to identify answered/bridged channels. It seems to be derived from the "Unique-ID" of the channel's creator.
The value of "Channel-Call-UUID" of the b-leg (the callee) differs from its "Unique-ID", but it is identical to the value of the "Other-Leg-Unique-ID" header.
The source code (src/switch_channel.c) supports my previous claims:
if ((v = switch_channel_get_variable(channel, "call_uuid"))) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", v);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", switch_core_session_get_uuid(channel->session));
}

Find DeviceInterface (SP_DEVICE_INTERFACE_DATA) for DeviceInfo (SP_DEVINFO_DATA)

I am trying to communicate with a USB printer using c-function CreateFile and therefore i need the device path. I know that i can get the device path by SetupDiEnumDeviceInterfaces and SetupDiGetDeviceInterfaceDetail, but for SetupDiEnumDeviceInterfaces i need to give an InterfaceClassGuid as third parameter which I don't know.
My current approach is:
OpenPrinter with the "user friendly" name of the Printer
GetPrinterDataEx with "PnpData" and "DeviceInstanceId" as parameters 2 and 3 which gives me the DeviceInstanceId
ClosePrinter
SetupDiCreateDeviceInfoList (with NULL-parameters)
SetupDiOpenDeviceInfo with the DeviceInstanceId obtained in step 2. Now I have the DeviceInfo of the printer
CM_Get_Parent with the DevInst of the printer (obtained in step 5).
CM_Get_Device_ID of the parent (obtained in step 6)
SetupDiOpenDeviceInfo with the device id obtained in step 7. Now I have the DeviceInfo of the USB-Interface (but not the interface itself) and am almost at the end.
The only missing thing is to get the device interface (SP_DEVICE_INTERFACE_DATA) when I have the SP_DEVINFO_DATA. The other way would be easy: Having the SP_DEVICE_INTERFACE_DATA, I could call SetupDiGetDeviceInterfaceDetail, so basically I am looking for the opposite function of SetupDiGetDeviceInterfaceDetail.
If it would be possible to enumerate ALL interfaces without having to know the InterfaceClassGuid, I could iterate through the list of interfaces and look for the one that is pointing to my device, but unfortunately, this is not possible.
The following articles were very helpful on my way:
Figuring which printer name corresponds to which device ID AND
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/51449be7-a4fa-476b-8cd2-b8933bfa3294/enumerate-multifunction-printer-in-vc?forum=wdk
Am I missing something?
It's been awhile, so I imagine you already found the answer. I'll answer it anyway for someone who may find this question later. I believe the answer is to call SetupDiEnumDeviceInterfaces passing in your SP_DEVINFO_DATA as the second parameter. From the documentation:
A pointer to an SP_DEVINFO_DATA
structure that specifies a device information element in
DeviceInfoSet.
This parameter is optional and can be NULL. If this parameter is
specified, SetupDiEnumDeviceInterfaces constrains the enumeration to
the interfaces that are supported by the specified device. If this
parameter is NULL, repeated calls to SetupDiEnumDeviceInterfaces
return information about the interfaces that are associated with all
the device information elements in DeviceInfoSet. This pointer is
typically returned by SetupDiEnumDeviceInfo.

examining audio file alternative to spotlight

i'm looking for an efficient alternative to grabbing audio file attributes in case spotlight is turned off.
Spotlight's MDItem attributes: kMDItemDurationSeconds, kMDItemAudioEncodingApplication, kMDItemAudioBitRate, kMDItemAudioSampleRate,kMDItemAudioChannelCount, kMDItemCodecs, are possible.
however QTKit's movieAttributes (if the file can be a QTMovie type), are not as complete, only QTMovieDurationAttribute fills my spec.
should i use Audio Format Services : OSStatus AudioFormatGetProperty, or is there something else, perhaps more light-weight that will suffice in the absence of MDItem information ?
i don't need to modify or play any files, i only need to know the property values.
thanks.
Get attributes from the audio track's media, not the movie. Here is an example of how to get duration in seconds.
for (QTTrack* track in [movie tracks])
{
QTMedia* trackMedia = [track media];
if ([trackMedia hasCharacteristic:QTMediaCharacteristicAudio])
{
QTTime mediaDuration = [(NSValue*)[trackMedia attributeForKey:QTMediaDurationAttribute] QTTimeValue];
long long mediaDurationScaleValue = mediaDuration.timeScale;
long long mediaDurationTimeValue = mediaDuration.timeValue;
result = (double)mediaDurationTimeValue / (double)mediaDurationScaleValue;
break;
}
}
[trackMedia mediaAttributes] will give you other available attributes of the audio.
If you are not afraid of using the Terminal, mdls is probably the tool for you:
mdls /path/toYour/file

IOServiceMatching on AppleUSBCDCACMData IOClass: Anomaly?

I am trying to extract a list of all AppleUSBCDCACMData IOClass devices in my mac using the following code snippet (just some small scale modifications in apple sample code). The device is a usb modem which creates some 7 /dev/cu.usbmodemx device nodes.
error = IOMasterPort(MACH_PORT_NULL, &masterPort);
if(error){
return ;
}
else{
matchingDict = IOServiceMatching("AppleUSBCDCACMData");
IOServiceGetMatchingServices(masterPort,matchingDict,&modem_iterator);
while(usbDevice = IOIteratorNext(modem_iterator))
{
}
My observation is, the iterator returned by IOServiceGetMatchingServices is empty (ie nothing to iterate on). But if i pass "AppleUSBCDCACMControl" as the parameter to IOServiceMatching, i get a iterator of a list of 7 elements - which is in conformance with the IORegistryExplorer view. See a screenshot of IORegistryExplorer here, http://tumblr.deepak.dk/post/1666218968/ioregistryexplorer
It appears that it is not possible to query IORegistry with arbitrary IOClass name strings? Since i faced the same issues with some non-standard proprietary IOClasses as well.
This can be reproduced using any USB modem (3g/HSDPA) which loads AppleUSBCDC driver.
What am i doing wrong?
IOService objects can only be matched once registerService() has been called for them. AppleUSBCDCACMControl does this, but AppleUSBCDCACMData does not.

Resources