Peran Perangkat untuk Aplikasi Multimedia Windows Warisan

Catatan

MMDevice API mendukung peran perangkat. Namun, antarmuka pengguna di Windows Vista tidak menerapkan dukungan untuk fitur ini. Dukungan antarmuka pengguna untuk peran perangkat mungkin diimplementasikan dalam versi Windows yang akan datang. Untuk informasi selengkapnya, lihat Peran Perangkat di Windows Vista.

 

Fungsi windows multimedia waveOutXxx dan waveInXxx warisan tidak menyediakan cara bagi aplikasi untuk memilih perangkat titik akhir audio yang telah ditetapkan pengguna ke peran perangkat tertentu. Namun, di Windows Vista, API audio inti dapat digunakan bersama dengan aplikasi multimedia Windows untuk mengaktifkan pemilihan perangkat berdasarkan peran perangkat. Misalnya, dengan bantuan MMDevice API, aplikasi waveOutXxx dapat mengidentifikasi perangkat titik akhir audio yang ditetapkan ke peran, mengidentifikasi perangkat output bentuk gelombang yang sesuai, dan memanggil fungsi waveOutOpen untuk membuka instans perangkat. Untuk informasi selengkapnya tentang waveOutXxx dan waveInXxx, lihat dokumentasi Windows SDK.

Contoh kode berikut menunjukkan cara mendapatkan ID perangkat bentuk gelombang untuk perangkat titik akhir penyajian yang ditetapkan ke peran perangkat tertentu:

//-----------------------------------------------------------
// This function gets the waveOut ID of the audio endpoint
// device that is currently assigned to the specified device
// role. The caller can use the waveOut ID to open the
// waveOut device that corresponds to the endpoint device.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

HRESULT GetWaveOutId(ERole role, int *pWaveOutId)
{
    HRESULT hr;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    WCHAR *pstrEndpointIdKey = NULL;
    WCHAR *pstrEndpointId = NULL;

    if (pWaveOutId == NULL)
    {
        return E_POINTER;
    }

    // Create an audio endpoint device enumerator.
    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                          NULL, CLSCTX_INPROC_SERVER,
                          __uuidof(IMMDeviceEnumerator),
                          (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    // Get the audio endpoint device that the user has
    // assigned to the specified device role.
    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, role,
                                              &pDevice);
    EXIT_ON_ERROR(hr)

    // Get the endpoint ID string of the audio endpoint device.
    hr = pDevice->GetId(&pstrEndpointIdKey);
    EXIT_ON_ERROR(hr)

    // Get the size of the endpoint ID string.
    size_t  cbEndpointIdKey;

    hr = StringCbLength(pstrEndpointIdKey,
                        STRSAFE_MAX_CCH * sizeof(WCHAR),
                        &cbEndpointIdKey);
    EXIT_ON_ERROR(hr)

    // Include terminating null in string size.
    cbEndpointIdKey += sizeof(WCHAR);

    // Allocate a buffer for a second string of the same size.
    pstrEndpointId = (WCHAR*)CoTaskMemAlloc(cbEndpointIdKey);
    if (pstrEndpointId == NULL)
    {
        EXIT_ON_ERROR(hr = E_OUTOFMEMORY)
    }

    // Each for-loop iteration below compares the endpoint ID
    // string of the audio endpoint device to the endpoint ID
    // string of an enumerated waveOut device. If the strings
    // match, then we've found the waveOut device that is
    // assigned to the specified device role.
    int waveOutId;
    int cWaveOutDevices = waveOutGetNumDevs();

    for (waveOutId = 0; waveOutId < cWaveOutDevices; waveOutId++)
    {
        MMRESULT mmr;
        size_t cbEndpointId;

        // Get the size (including the terminating null) of
        // the endpoint ID string of the waveOut device.
        mmr = waveOutMessage((HWAVEOUT)IntToPtr(waveOutId),
                             DRV_QUERYFUNCTIONINSTANCEIDSIZE,
                             (DWORD_PTR)&cbEndpointId, NULL);
        if (mmr != MMSYSERR_NOERROR ||
            cbEndpointIdKey != cbEndpointId)  // do sizes match?
        {
            continue;  // not a matching device
        }

        // Get the endpoint ID string for this waveOut device.
        mmr = waveOutMessage((HWAVEOUT)IntToPtr(waveOutId),
                             DRV_QUERYFUNCTIONINSTANCEID,
                             (DWORD_PTR)pstrEndpointId,
                             cbEndpointId);
        if (mmr != MMSYSERR_NOERROR)
        {
            continue;
        }

        // Check whether the endpoint ID string of this waveOut
        // device matches that of the audio endpoint device.
        if (lstrcmpi(pstrEndpointId, pstrEndpointIdKey) == 0)
        {
            *pWaveOutId = waveOutId;  // found match
            hr = S_OK;
            break;
        }
    }

    if (waveOutId == cWaveOutDevices)
    {
        // We reached the end of the for-loop above without
        // finding a waveOut device with a matching endpoint
        // ID string. This behavior is quite unexpected.
        hr = E_UNEXPECTED;
    }

Exit:
    SAFE_RELEASE(pEnumerator);
    SAFE_RELEASE(pDevice);
    CoTaskMemFree(pstrEndpointIdKey);  // NULL pointer okay
    CoTaskMemFree(pstrEndpointId);
    return hr;
}

Dalam contoh kode sebelumnya, fungsi GetWaveOutId menerima peran perangkat (eConsole, eMultimedia, atau eCommunications) sebagai parameter input. Parameter kedua adalah penunjuk di mana fungsi menulis ID perangkat bentuk gelombang untuk perangkat output bentuk gelombang yang ditetapkan ke peran yang ditentukan. Aplikasi kemudian dapat memanggil waveOutOpen dengan ID ini untuk membuka perangkat.

Perulangan utama dalam contoh kode sebelumnya berisi dua panggilan ke fungsi waveOutMessage . Panggilan pertama mengirim pesan DRV_QUERYFUNCTIONINSTANCEIDSIZE untuk mengambil ukuran, dalam byte, dari string ID titik akhir perangkat bentuk gelombang yang diidentifikasi oleh parameter waveOutId . (String ID titik akhir mengidentifikasi perangkat titik akhir audio yang mendasar abstraksi perangkat bentuk gelombang.) Ukuran yang dilaporkan oleh panggilan ini mencakup spasi untuk karakter null yang mengakhiri di akhir string. Program ini dapat menggunakan informasi ukuran untuk mengalokasikan buffer yang cukup besar untuk berisi seluruh string ID titik akhir.

Panggilan kedua ke waveOutMessage mengirimkan pesan DRV_QUERYFUNCTIONINSTANCEID untuk mengambil string ID perangkat dari perangkat output bentuk gelombang. Contoh kode membandingkan string ini dengan string ID perangkat dari perangkat titik akhir audio dengan peran perangkat yang ditentukan. Jika string cocok, maka fungsi menulis ID perangkat bentuk gelombang ke lokasi yang ditujukkan oleh parameter pWaveOutId. Pemanggil dapat menggunakan ID ini untuk membuka perangkat output bentuk gelombang yang memiliki peran perangkat yang ditentukan.

Windows Vista mendukung pesan DRV_QUERYFUNCTIONINSTANCEIDSIZE dan DRV_QUERYFUNCTIONINSTANCEID. Mereka tidak didukung di versi Windows sebelumnya, termasuk Windows Server 2003, Windows XP, dan Windows 2000.

Fungsi dalam contoh kode sebelumnya mendapatkan ID perangkat bentuk gelombang untuk perangkat penyajian, tetapi, dengan beberapa modifikasi, dapat disesuaikan untuk mendapatkan ID perangkat bentuk gelombang untuk perangkat tangkapan. Aplikasi kemudian dapat memanggil waveInOpen dengan ID ini untuk membuka perangkat. Untuk mengubah contoh kode sebelumnya untuk mendapatkan ID perangkat bentuk gelombang untuk perangkat titik akhir pengambilan audio yang ditetapkan ke peran tertentu, lakukan hal berikut:

  • Ganti semua panggilan fungsi waveOutXxx dalam contoh sebelumnya dengan panggilan fungsi waveInXxx yang sesuai.
  • Ubah jenis handel HWAVEOUT ke HWAVEIN.
  • Ganti konstanta enumerasi ERole eRender dengan eCapture.

Di Windows Vista, fungsi waveOutOpen dan waveInOpen selalu menetapkan aliran audio yang mereka buat ke sesi default—sesi khusus proses yang diidentifikasi oleh nilai GUID sesi GUID_NULL.

Interoperabilitas dengan API Audio Warisan