예제 #1
0
파일: winmm.c 프로젝트: lucianolorenti/wine
/**************************************************************************
 * 				midiOutGetDevCapsA	[WINMM.@]
 */
UINT WINAPI midiOutGetDevCapsA(UINT_PTR uDeviceID, LPMIDIOUTCAPSA lpCaps,
			       UINT uSize)
{
    MIDIOUTCAPSW	mocW;
    UINT		ret;

    if (lpCaps == NULL)        return MMSYSERR_INVALPARAM;

    ret = midiOutGetDevCapsW(uDeviceID, &mocW, sizeof(mocW));

    if (ret == MMSYSERR_NOERROR) {
	MIDIOUTCAPSA mocA;
	mocA.wMid		= mocW.wMid;
	mocA.wPid		= mocW.wPid;
	mocA.vDriverVersion	= mocW.vDriverVersion;
	WideCharToMultiByte( CP_ACP, 0, mocW.szPname, -1, mocA.szPname,
                             sizeof(mocA.szPname), NULL, NULL );
	mocA.wTechnology        = mocW.wTechnology;
	mocA.wVoices		= mocW.wVoices;
	mocA.wNotes		= mocW.wNotes;
	mocA.wChannelMask	= mocW.wChannelMask;
	mocA.dwSupport	        = mocW.dwSupport;
	memcpy(lpCaps, &mocA, min(uSize, sizeof(mocA)));
    }
    return ret;
}
예제 #2
0
/**************************************************************************
 * 				MIDIMAP_drvOpen			[internal]
 */
static LRESULT MIDIMAP_drvOpen(LPSTR str)
{
    MIDIOUTCAPSW	moc;
    unsigned		dev, i;

    if (midiOutPorts)
	return 0;

    numMidiOutPorts = midiOutGetNumDevs();
    midiOutPorts = HeapAlloc(GetProcessHeap(), 0,
			     numMidiOutPorts * sizeof(MIDIOUTPORT));
    for (dev = 0; dev < numMidiOutPorts; dev++)
    {
	if (midiOutGetDevCapsW(dev, &moc, sizeof(moc)) == 0L)
	{
	    strcpyW(midiOutPorts[dev].name, moc.szPname);
	    midiOutPorts[dev].loaded = 0;
	    midiOutPorts[dev].hMidi = 0;
	    midiOutPorts[dev].uDevID = dev;
	    midiOutPorts[dev].lpbPatch = NULL;
	    for (i = 0; i < 16; i++)
		midiOutPorts[dev].aChn[i] = i;
	}
	else
	{
	    midiOutPorts[dev].loaded = -1;
	}
    }

    return 1;
}
예제 #3
0
/**********************************************************************
 * DEVENUM_CreateSpecialCategories (INTERNAL)
 *
 * Creates the keys in the registry for the dynamic categories
 */
static HRESULT DEVENUM_CreateSpecialCategories(void)
{
    HRESULT res;
    WCHAR szDSoundNameFormat[MAX_PATH + 1];
    WCHAR szDSoundName[MAX_PATH + 1];
    DWORD iDefaultDevice = -1;
    UINT numDevs;
    IFilterMapper2 * pMapper = NULL;
    REGFILTER2 rf2;
    REGFILTERPINS2 rfp2;
    WCHAR path[MAX_PATH];
    HKEY basekey;

    if (DEVENUM_populate_handle)
        return S_OK;
    DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE, DEVENUM_populate_handle_nameW);
    if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
        /* Webcams can take some time to scan if the driver is badly written and it enables them,
         * so have a 10 s timeout here
         */
        if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT)
            WARN("Waiting for object timed out\n");
        TRACE("No need to rescan\n");
        return S_OK;
    }
    TRACE("Scanning for devices\n");

    /* Since devices can change between session, for example because you just plugged in a webcam
     * or switched from pulseaudio to alsa, delete all old devices first
     */
    if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioRendererCategory, &basekey, path, MAX_PATH)))
        RegDeleteTreeW(basekey, path);
    if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioInputDeviceCategory, &basekey, path, MAX_PATH)))
        RegDeleteTreeW(basekey, path);
    if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoInputDeviceCategory, &basekey, path, MAX_PATH)))
        RegDeleteTreeW(basekey, path);
    if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey, path, MAX_PATH)))
        RegDeleteTreeW(basekey, path);

    rf2.dwVersion = 2;
    rf2.dwMerit = MERIT_PREFERRED;
    rf2.u.s1.cPins2 = 1;
    rf2.u.s1.rgPins2 = &rfp2;
    rfp2.cInstances = 1;
    rfp2.nMediums = 0;
    rfp2.lpMedium = NULL;
    rfp2.clsPinCategory = &IID_NULL;

    if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat, sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1))
    {
        ERR("Couldn't get string resource (GetLastError() is %d)\n", GetLastError());
        return HRESULT_FROM_WIN32(GetLastError());
    }

    res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
                           &IID_IFilterMapper2, (void **) &pMapper);
    /*
     * Fill in info for devices
     */
    if (SUCCEEDED(res))
    {
        UINT i;
        WAVEOUTCAPSW wocaps;
	WAVEINCAPSW wicaps;
        MIDIOUTCAPSW mocaps;
        REGPINTYPES * pTypes;

	numDevs = waveOutGetNumDevs();

        res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
        if (FAILED(res)) /* can't register any devices in this category */
            numDevs = 0;

	rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
	for (i = 0; i < numDevs; i++)
	{
	    if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW))
	        == MMSYSERR_NOERROR)
	    {
                IMoniker * pMoniker = NULL;

                rfp2.nMediaTypes = 1;
                pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
                if (!pTypes)
                {
                    IFilterMapper2_Release(pMapper);
                    return E_OUTOFMEMORY;
                }
                /* FIXME: Native devenum seems to register a lot more types for
                 * DSound than we do. Not sure what purpose they serve */
                pTypes[0].clsMajorType = &MEDIATYPE_Audio;
                pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;

                rfp2.lpMediaType = pTypes;

                res = IFilterMapper2_RegisterFilter(pMapper,
		                              &CLSID_AudioRender,
					      wocaps.szPname,
					      &pMoniker,
					      &CLSID_AudioRendererCategory,
					      wocaps.szPname,
					      &rf2);

                /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */

                if (pMoniker)
                {
                    IMoniker_Release(pMoniker);
                    pMoniker = NULL;
                }

		wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname);
	        res = IFilterMapper2_RegisterFilter(pMapper,
		                              &CLSID_DSoundRender,
					      szDSoundName,
					      &pMoniker,
					      &CLSID_AudioRendererCategory,
					      szDSoundName,
					      &rf2);

                /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */

		if (pMoniker)
		    IMoniker_Release(pMoniker);

		if (i == iDefaultDevice)
		{
		    FIXME("Default device\n");
		}

                CoTaskMemFree(pTypes);
	    }
	}

        numDevs = waveInGetNumDevs();

        res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory);
        if (FAILED(res)) /* can't register any devices in this category */
            numDevs = 0;

	rfp2.dwFlags = REG_PINFLAG_B_OUTPUT;
        for (i = 0; i < numDevs; i++)
        {
            if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW))
                == MMSYSERR_NOERROR)
            {
                IMoniker * pMoniker = NULL;

                rfp2.nMediaTypes = 1;
                pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
                if (!pTypes)
                {
                    IFilterMapper2_Release(pMapper);
                    return E_OUTOFMEMORY;
                }

                /* FIXME: Not sure if these are correct */
                pTypes[0].clsMajorType = &MEDIATYPE_Audio;
                pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;

                rfp2.lpMediaType = pTypes;

	        res = IFilterMapper2_RegisterFilter(pMapper,
		                              &CLSID_AudioRecord,
					      wicaps.szPname,
					      &pMoniker,
					      &CLSID_AudioInputDeviceCategory,
					      wicaps.szPname,
					      &rf2);

                /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */

		if (pMoniker)
		    IMoniker_Release(pMoniker);

                CoTaskMemFree(pTypes);
	    }
	}

	numDevs = midiOutGetNumDevs();

        res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory);
        if (FAILED(res)) /* can't register any devices in this category */
            numDevs = 0;

	rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
	for (i = 0; i < numDevs; i++)
	{
	    if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW))
	        == MMSYSERR_NOERROR)
	    {
                IMoniker * pMoniker = NULL;

                rfp2.nMediaTypes = 1;
                pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
                if (!pTypes)
                {
                    IFilterMapper2_Release(pMapper);
                    return E_OUTOFMEMORY;
                }

                /* FIXME: Not sure if these are correct */
                pTypes[0].clsMajorType = &MEDIATYPE_Midi;
                pTypes[0].clsMinorType = &MEDIASUBTYPE_None;

                rfp2.lpMediaType = pTypes;

                res = IFilterMapper2_RegisterFilter(pMapper,
		                              &CLSID_AVIMIDIRender,
					      mocaps.szPname,
					      &pMoniker,
					      &CLSID_MidiRendererCategory,
					      mocaps.szPname,
					      &rf2);

                /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
		/* Native version sets MidiOutId */

		if (pMoniker)
		    IMoniker_Release(pMoniker);

		if (i == iDefaultDevice)
		{
		    FIXME("Default device\n");
		}

                CoTaskMemFree(pTypes);
	    }
	}
        res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
        if (SUCCEEDED(res))
            for (i = 0; i < 10; i++)
            {
                WCHAR szDeviceName[32], szDeviceVersion[32], szDevicePath[10];

                if (capGetDriverDescriptionW ((WORD) i,
                                              szDeviceName, sizeof(szDeviceName)/sizeof(WCHAR),
                                              szDeviceVersion, sizeof(szDeviceVersion)/sizeof(WCHAR)))
                {
                    IMoniker * pMoniker = NULL;
                    IPropertyBag * pPropBag = NULL;
                    WCHAR dprintf[] = { 'v','i','d','e','o','%','d',0 };
                    snprintfW(szDevicePath, sizeof(szDevicePath)/sizeof(WCHAR), dprintf, i);
                    /* The above code prevents 1 device with a different ID overwriting another */

                    rfp2.nMediaTypes = 1;
                    pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
                    if (!pTypes) {
                        IFilterMapper2_Release(pMapper);
                        return E_OUTOFMEMORY;
                    }

                    pTypes[0].clsMajorType = &MEDIATYPE_Video;
                    pTypes[0].clsMinorType = &MEDIASUBTYPE_None;

                    rfp2.lpMediaType = pTypes;

                    res = IFilterMapper2_RegisterFilter(pMapper,
                                                        &CLSID_VfwCapture,
                                                        szDeviceName,
                                                        &pMoniker,
                                                        &CLSID_VideoInputDeviceCategory,
                                                        szDevicePath,
                                                        &rf2);

                    if (pMoniker) {
                       OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 };
                       VARIANT var;
                       V_VT(&var) = VT_I4;
                       V_UNION(&var, ulVal) = i;
                       res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag);
                       if (SUCCEEDED(res))
                          res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var);
                       IMoniker_Release(pMoniker);
                    }

                    if (i == iDefaultDevice) FIXME("Default device\n");
                    CoTaskMemFree(pTypes);
                }
            }
    }

    if (pMapper)
        IFilterMapper2_Release(pMapper);
    SetEvent(DEVENUM_populate_handle);
    return res;
}
예제 #4
0
파일: dmusic.c 프로젝트: Dimillian/wine
static void create_system_ports_list(IDirectMusic8Impl* object)
{
    port_info * port;
    const WCHAR emulated[] = {' ','[','E','m','u','l','a','t','e','d',']',0};
    ULONG nb_ports;
    ULONG nb_midi_out;
    ULONG nb_midi_in;
    MIDIOUTCAPSW caps_out;
    MIDIINCAPSW caps_in;
    IDirectMusicSynth8* synth;
    HRESULT hr;
    ULONG i;

    TRACE("(%p)\n", object);

    /* NOTE:
       - it seems some native versions get the rest of devices through dmusic32.EnumLegacyDevices...*sigh*...which is undocumented
       - should we enum wave devices ? Native does not seem to
    */

    nb_midi_out = midiOutGetNumDevs();
    nb_midi_in = midiInGetNumDevs();
    nb_ports = 1 /* midi mapper */ + nb_midi_out + nb_midi_in + 1 /* synth port */;

    port = object->system_ports = HeapAlloc(GetProcessHeap(), 0, nb_ports * sizeof(port_info));
    if (!object->system_ports)
        return;

    /* Fill common port caps for all winmm ports */
    for (i = 0; i < (nb_ports - 1 /* synth port*/); i++)
    {
        object->system_ports[i].caps.dwSize = sizeof(DMUS_PORTCAPS);
        object->system_ports[i].caps.dwType = DMUS_PORT_WINMM_DRIVER;
        object->system_ports[i].caps.dwMemorySize = 0;
        object->system_ports[i].caps.dwMaxChannelGroups = 1;
        object->system_ports[i].caps.dwMaxVoices = 0;
        object->system_ports[i].caps.dwMaxAudioChannels = 0;
        object->system_ports[i].caps.dwEffectFlags = DMUS_EFFECT_NONE;
        /* Fake port GUID */
        object->system_ports[i].caps.guidPort = IID_IUnknown;
        object->system_ports[i].caps.guidPort.Data1 = i + 1;
    }

    /* Fill midi mapper port info */
    port->device = MIDI_MAPPER;
    port->create = DMUSIC_CreateMidiOutPortImpl;
    midiOutGetDevCapsW(MIDI_MAPPER, &caps_out, sizeof(caps_out));
    strcpyW(port->caps.wszDescription, caps_out.szPname);
    strcatW(port->caps.wszDescription, emulated);
    port->caps.dwFlags = DMUS_PC_SHAREABLE;
    port->caps.dwClass = DMUS_PC_OUTPUTCLASS;
    port++;

    /* Fill midi out port info */
    for (i = 0; i < nb_midi_out; i++)
    {
        port->device = i;
        port->create = DMUSIC_CreateMidiOutPortImpl;
        midiOutGetDevCapsW(i, &caps_out, sizeof(caps_out));
        strcpyW(port->caps.wszDescription, caps_out.szPname);
        strcatW(port->caps.wszDescription, emulated);
        port->caps.dwFlags = DMUS_PC_SHAREABLE | DMUS_PC_EXTERNAL;
        port->caps.dwClass = DMUS_PC_OUTPUTCLASS;
        port++;
    }

    /* Fill midi in port info */
    for (i = 0; i < nb_midi_in; i++)
    {
        port->device = i;
        port->create = DMUSIC_CreateMidiInPortImpl;
        midiInGetDevCapsW(i, &caps_in, sizeof(caps_in));
        strcpyW(port->caps.wszDescription, caps_in.szPname);
        strcatW(port->caps.wszDescription, emulated);
        port->caps.dwFlags = DMUS_PC_EXTERNAL;
        port->caps.dwClass = DMUS_PC_INPUTCLASS;
        port++;
    }

    /* Fill synth port info */
    port->create = DMUSIC_CreateSynthPortImpl;
    hr = CoCreateInstance(&CLSID_DirectMusicSynth, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicSynth8, (void**)&synth);
    if (SUCCEEDED(hr))
    {
        port->caps.dwSize = sizeof(port->caps);
        hr = IDirectMusicSynth8_GetPortCaps(synth, &port->caps);
        IDirectMusicSynth8_Release(synth);
    }
    if (FAILED(hr))
        nb_ports--;

    object->nb_system_ports = nb_ports;
}