Recuperación de las funcionalidades de representación compatibles con un dispositivo
Windows dispositivos portátiles que admiten la categoría funcional de información de representación (WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION) devolverá información de representación cuando se consulte. La información de representación describe los requisitos y las restricciones impuestas a las aplicaciones que intentan escribir contenido en un dispositivo.
La función auxiliar ListRenderingCapabilityInformation, la función auxiliar SupportsFunctionalCategory y la función auxiliar ReadProfileInformationProperties del módulo DeviceCapabilities.cpp muestran la recuperación de funcionalidades de representación para un dispositivo seleccionado.
La aplicación puede recuperar las funcionalidades de representación compatibles con un dispositivo mediante las interfaces descritas en la tabla siguiente.
Interfaz | Descripción |
---|---|
IPortableDeviceContent (Interfaz) | Proporciona acceso a la interfaz IPortableDeviceProperties. |
IPortableDeviceProperties (interfaz) | Proporciona acceso a los métodos específicos de la propiedad. |
IPortableDeviceKeyCollection (Interfaz) | Se usa para almacenar las claves de propiedad para el perfil especificado. |
IPortableDeviceValues (Interfaz) | Se usa para almacenar los valores de propiedad para el perfil especificado. |
IPortableDeviceCapabilities (Interfaz) | Se usa para almacenar los valores de propiedad para el perfil especificado. |
IPortableDevicePropVariantCollection (Interfaz) | Se usa para almacenar los valores de propiedad para el perfil especificado. |
IPortableDeviceValuesCollection (Interfaz) | Se usa para almacenar los valores de propiedad para el perfil especificado. |
Una de las primeras tareas realizadas por la aplicación de ejemplo es determinar si el dispositivo seleccionado es capaz de enumerar las funcionalidades de representación. La función auxiliar SupportsFunctionalCategory determina si este es el caso llamando a la función auxiliar ListRenderingCapabilityInformation y pasando WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION como segundo argumento.
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pRenderingInfoObjects;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CAtlStringW strRenderingInfoObjectID;
if (SupportsFunctionalCategory(pDevice, WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION) == FALSE)
{
printf("This device does not support device rendering information to display\n");
return;
}
Si el dispositivo es capaz de enumerar las funcionalidades de representación, el siguiente paso implica recuperar un objeto IPortableDeviceCapabilities e invocar el método GetFunctionalObjects para recuperar un identificador de objeto para el objeto de información de representación.
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pRenderingInfoObjects;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CAtlStringW strRenderingInfoObjectID;
hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get the functional object identifier for the rendering information object
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetFunctionalObjects(WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION, &pRenderingInfoObjects);
if (FAILED(hr))
{
printf("! Failed to get functional objects, hr = 0x%lx\n", hr);
}
}
El siguiente paso consiste en almacenar el identificador de objeto de información de representación que se acaba de recuperar en una variable de cadena (strRenderingInfoObjectID) y, a continuación, llamar a la función auxiliar ReadProfileInformationProperties. (La variable strRenderingInfoObjectID se pasa como segundo argumento a la función auxiliar).
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pRenderingInfoObjects;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CAtlStringW strRenderingInfoObjectID;
if (SUCCEEDED(hr))
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pRenderingInfoObjects->GetAt(0, &pv);
if ((SUCCEEDED(hr)) &&
(pv.vt== VT_LPWSTR) )
{
strRenderingInfoObjectID = pv.pwszVal;
}
else
{
printf("! Failed to get first rendering object's identifier, hr = 0x%lx\n", hr);
}
PropVariantClear(&pv);
}
if (SUCCEEDED(hr))
{
hr = ReadProfileInformationProperties(pDevice,
strRenderingInfoObjectID,
&pRenderingInfoProfiles);
// Error output statements are performed by the helper function, so they
// are omitted here.
}
Una de las primeras tareas realizadas por la función auxiliar es recuperar un objeto IPortableDeviceContent , que usará para acceder a los métodos específicos del contenido.
HRESULT hr = S_OK;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDeviceValues> pObjectProperties;
if (SUCCEEDED(hr))
{
hr = pDevice->Content(&pContent);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
}
}
A continuación, la función auxiliar recupera un objeto IPortableDeviceProperties , que se usará para tener acceso a los métodos específicos de la propiedad.
HRESULT hr = S_OK;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDeviceValues> pObjectProperties;
if (SUCCEEDED(hr))
{
hr = pContent->Properties(&pProperties);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr);
}
}
El siguiente paso consiste en crear un objeto IPortableDeviceKeyCollection en el que se almacenan las claves de propiedad de la información de representación. Una vez creado el objeto, se invoca el método IPortableDeviceKeyCollection::Add para agregar las claves necesarias. (Es necesario agregar estas claves para que los perfiles de representación correspondientes se puedan recuperar en los pasos posteriores).
HRESULT hr = S_OK;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDeviceValues> pObjectProperties;
hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection,
NULL,
CLSCTX_INPROC_SERVER,
IID_IPortableDeviceKeyCollection,
(VOID**) &pPropertiesToRead);
if (SUCCEEDED(hr))
{
// Populate the IPortableDeviceKeyCollection with the keys we wish to read.
// NOTE: We are not handling any special error cases here so we can proceed with
// adding as many of the target properties as we can.
if (pPropertiesToRead != NULL)
{
HRESULT hrTemp = S_OK;
hrTemp = pPropertiesToRead->Add(WPD_RENDERING_INFORMATION_PROFILES);
if (FAILED(hrTemp))
{
printf("! Failed to add WPD_RENDERING_INFORMATION_PROFILES to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp);
}
}
}
El siguiente paso consiste en recuperar los valores de propiedad del controlador de dispositivo llamando al método IPortableDeviceProperties::GetValues .
HRESULT hr = S_OK;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDeviceValues> pObjectProperties;
if (SUCCEEDED(hr))
{
hr = pProperties->GetValues(wszFunctionalObjectID, // The object whose properties we are reading
pPropertiesToRead, // The properties we want to read
&pObjectProperties); // Driver supplied property values for the specified object
if (FAILED(hr))
{
printf("! Failed to get all properties for object '%ws', hr= 0x%lx\n", wszFunctionalObjectID, hr);
}
}
El siguiente paso recupera el perfil de información de representación y lo almacena en el argumento ppRenderingInfoProfiles.
HRESULT hr = S_OK;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDeviceValues> pObjectProperties;
if (SUCCEEDED(hr))
{
hr = pObjectProperties->GetIPortableDeviceValuesCollectionValue(WPD_RENDERING_INFORMATION_PROFILES,
&pRenderingInfoProfiles);
if (FAILED(hr))
{
printf("! Failed to get WPD_RENDERING_INFORMATION_PROFILES from rendering information, hr= 0x%lx\n", hr);
}
}
// QueryInterface the interface into the out-going parameters.
if (SUCCEEDED(hr))
{
hr = pRenderingInfoProfiles->QueryInterface(IID_PPV_ARGS(ppRenderingInfoProfiles));
if (FAILED(hr))
{
printf("! Failed to QueryInterface for IPortableDeviceValuesCollection (Rendering information profiles), hr= 0x%lx\n", hr);
}
}
Una vez que la función auxiliar lee las propiedades de WPD_RENDERING_INFORMATION_PROFILES, se muestran los perfiles de representación. Estos perfiles se muestran mediante la función auxiliar DisplayRenderingProfile.
void DisplayRenderingProfile(
IPortableDeviceValues* pProfile)
{
HRESULT hr = S_OK;
if (pProfile == NULL)
{
return;
}
if (SUCCEEDED(hr))
{
DWORD dwTotalBitrate = 0;
DWORD dwChannelCount = 0;
DWORD dwAudioFormatCode = 0;
GUID guidFormat = WPD_OBJECT_FORMAT_UNSPECIFIED;
// Display WPD_MEDIA_TOTAL_BITRATE
hr = pProfile->GetUnsignedIntegerValue(WPD_MEDIA_TOTAL_BITRATE, &dwTotalBitrate);
if (SUCCEEDED(hr))
{
printf("Total Bitrate: %d\n", dwTotalBitrate);
}
// If we fail to read the total bitrate as a single value, then it must be
// a valid value set. (i.e. returning IPortableDeviceValues as the value which
// contains properties describing the valid values for this property.)
if (hr == DISP_E_TYPEMISMATCH)
{
CComPtr<IPortableDeviceValues> pExpectedValues;
hr = pProfile->GetIPortableDeviceValuesValue(WPD_MEDIA_TOTAL_BITRATE, &pExpectedValues);
if (SUCCEEDED(hr))
{
printf("Total Bitrate: ");
DisplayExpectedValues(pExpectedValues);
}
}
// If we are still a failure here, report the error
if (FAILED(hr))
{
printf("! Failed to get WPD_MEDIA_TOTAL_BITRATE from rendering profile, hr = 0x%lx\n",hr);
}
// Display WPD_AUDIO_CHANNEL_COUNT
hr = pProfile->GetUnsignedIntegerValue(WPD_AUDIO_CHANNEL_COUNT, &dwChannelCount);
if (SUCCEEDED(hr))
{
printf("Channel Count: %d\n", dwChannelCount);
}
else
{
printf("! Failed to get WPD_AUDIO_CHANNEL_COUNT from rendering profile, hr = 0x%lx\n",hr);
}
// Display WPD_AUDIO_FORMAT_CODE
hr = pProfile->GetUnsignedIntegerValue(WPD_AUDIO_FORMAT_CODE, &dwAudioFormatCode);
if (SUCCEEDED(hr))
{
printf("Audio Format Code: %d\n", dwAudioFormatCode);
}
else
{
printf("! Failed to get WPD_AUDIO_FORMAT_CODE from rendering profile, hr = 0x%lx\n",hr);
}
// Display WPD_OBJECT_FORMAT
hr = pProfile->GetGuidValue(WPD_OBJECT_FORMAT, &guidFormat);
if (SUCCEEDED(hr))
{
printf("Object Format: %ws\n", (LPWSTR)CComBSTR(guidFormat));
}
else
{
printf("! Failed to get WPD_OBJECT_FORMAT from rendering profile, hr = 0x%lx\n",hr);
}
}
}
Tenga en cuenta que, dado que los perfiles de representación son estáticos, la aplicación puede elegir leer los perfiles y almacenarlos localmente (en lugar de acceder al dispositivo cada vez que se necesitan los datos).