示例#1
0
int WinMIDIDevice::Open(MidiCallback callback, void *userdata)
{
	MMRESULT err;

	Callback = callback;
	CallbackData = userdata;
	if (MidiOut == nullptr)
	{
		err = midiStreamOpen(&MidiOut, &DeviceID, 1, (DWORD_PTR)CallbackFunc, (DWORD_PTR)this, CALLBACK_FUNCTION);

		if (err == MMSYSERR_NOERROR)
		{
			if (IgnoreMIDIVolume(DeviceID))
			{
				VolumeWorks = false;
			}
			else
			{
				// Set master volume to full, if the device allows it on this interface.
				VolumeWorks = (MMSYSERR_NOERROR == midiOutGetVolume((HMIDIOUT)MidiOut, &SavedVolume));
				if (VolumeWorks)
				{
					VolumeWorks &= (MMSYSERR_NOERROR == midiOutSetVolume((HMIDIOUT)MidiOut, 0xffffffff));
				}
			}
		}
		else
		{
			return 1;
		}
	}
	return 0;
}
示例#2
0
/* midi_win32_get_mixer_volume:
 */
int midi_win32_get_mixer_volume(void)
{
   DWORD vol;
   
   if (!midi_device)
      return -1;

   if (midiOutGetVolume(midi_device, &vol) != MMSYSERR_NOERROR)
      return -1;

   vol &= 0xffff;
   return vol / (0xffff / 255);
}
示例#3
0
ArchMidi* archMidiOutCreate(int device)
{
    Properties* pProperties = propGetGlobalProperties();
    char* propName = device == 0 ? pProperties->sound.MidiOut.name : pProperties->sound.MidiOut.name;
    ArchMidi* archMidi = (ArchMidi*)calloc(1, sizeof(ArchMidi));

    if (device != 0) {
        return archMidi;
    }

    if (midi.out.current[device] == NULL) {
        int i;
        for (i = 0; i < midi.out.count; i++) {
            if (strcmp(midi.out.dev[i].idString, propName) == 0) {
                if (midiOutOpen((HMIDIOUT*)&midi.out.dev[i].handle, midi.out.dev[i].id, 0, 0 ,0) == MMSYSERR_NOERROR) {
                    midi.out.current[device] = &midi.out.dev[i];
                }
                break;
            }
        }
        if (midi.out.current[device] == NULL && midi.out.count > 0) {
            if (midiOutOpen((HMIDIOUT*)&midi.out.dev[0].handle, midi.out.dev[0].id, 0, 0 ,0) == MMSYSERR_NOERROR) {
                midi.out.current[device] = &midi.out.dev[0];
            }
            strcpy(propName, midi.out.dev[0].idString);
        }

        if (midi.out.current[device] != NULL) {
            midiOutGetVolume((HMIDIOUT)midi.out.current[device]->handle, &midi.out.current[device]->origVolume);
        }
        archMidiEnable(midi.enabled);

        // Clear history
        memset(midi.out.history.data, 0, sizeof(midi.out.history.data));
    }

    if (midi.out.current[device] != NULL) {
        midi.out.current[device]->refCount++;
    }

    archMidi->devInfo = midi.out.current[device];

    return archMidi;
}
示例#4
0
static void test_midiOut_device(UINT udev, HWND hwnd)
{
    HMIDIOUT hm;
    MMRESULT rc;
    MIDIOUTCAPSA capsA;
    DWORD ovolume;
    UINT  udevid;
    MIDIHDR mhdr;

    rc = midiOutGetDevCapsA(udev, &capsA, sizeof(capsA));
    ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (!rc) {
        trace("* %s: manufacturer=%d, product=%d, tech=%d, support=%X: %d voices, %d notes\n",
              capsA.szPname, capsA.wMid, capsA.wPid, capsA.wTechnology, capsA.dwSupport, capsA.wVoices, capsA.wNotes);
        ok(!((MIDIMAPPER==udev) ^ (MOD_MAPPER==capsA.wTechnology)), "technology %d on device %d\n", capsA.wTechnology, udev);
        if (MOD_MIDIPORT == capsA.wTechnology) {
            ok(capsA.wVoices == 0 && capsA.wNotes == 0, "external device with notes or voices\n");
            ok(capsA.wChannelMask == 0xFFFF, "external device channel mask %x\n", capsA.wChannelMask);
            ok(!(capsA.dwSupport & (MIDICAPS_VOLUME|MIDICAPS_LRVOLUME|MIDICAPS_CACHE)), "external device support=%X\n", capsA.dwSupport);
        }
    }

    if (hwnd)
        rc = midiOutOpen(&hm, udev, (DWORD_PTR)hwnd, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW);
    else
        rc = midiOutOpen(&hm, udev, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION);
    if (rc == MMSYSERR_NOTSUPPORTED)
    {
        skip( "MIDI out not supported\n" );
        return;
    }
    ok(!rc, "midiOutOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (rc) return;

    test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0);

    rc = midiOutGetVolume(hm, &ovolume);
    ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume rc=%s\n", mmsys_error(rc));
    /* The native mapper responds with FFFFFFFF initially,
     * real devices with the volume GUI SW-synth settings. */
    if (!rc) trace("Current volume %x on device %d\n", ovolume, udev);

    /* The W95 ESFM Synthesis device reports NOTENABLED although
     * GetVolume by handle works and music plays. */
    rc = midiOutGetVolume(UlongToHandle(udev), &ovolume);
    ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_NOTENABLED) : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume(dev=%d) rc=%s\n", udev, mmsys_error(rc));

    rc = midiOutGetVolume(hm, NULL);
    ok(rc==MMSYSERR_INVALPARAM, "midiOutGetVolume NULL rc=%s\n", mmsys_error(rc));

    /* Tests with midiOutSetvolume show that the midi mapper forwards
     * the value to the real device, but Get initially always reports
     * FFFFFFFF.  Therefore, a Get+SetVolume pair with the mapper is
     * not adequate to restore the value prior to tests.
     */
    if (winetest_interactive && (capsA.dwSupport & MIDICAPS_VOLUME)) {
        DWORD volume2 = (ovolume < 0x80000000) ? 0xC000C000 : 0x40004000;
        rc = midiOutSetVolume(hm, volume2);
        ok(!rc, "midiOutSetVolume rc=%s\n", mmsys_error(rc));
        if (!rc) {
            DWORD volume3;
            rc = midiOutGetVolume(hm, &volume3);
            ok(!rc, "midiOutGetVolume new rc=%s\n", mmsys_error(rc));
            if (!rc) trace("New volume %x on device %d\n", volume3, udev);
            todo_wine ok(volume2==volume3, "volume Set %x = Get %x\n", volume2, volume3);

            rc = midiOutSetVolume(hm, ovolume);
            ok(!rc, "midiOutSetVolume restore rc=%s\n", mmsys_error(rc));
        }
    }
    rc = midiOutGetDevCapsA((UINT_PTR)hm, &capsA, sizeof(capsA));
    ok(!rc, "midiOutGetDevCaps(dev=%d) by handle rc=%s\n", udev, mmsys_error(rc));
    rc = midiInGetDevCapsA((UINT_PTR)hm, (LPMIDIINCAPSA)&capsA, sizeof(DWORD));
    ok(rc==MMSYSERR_BADDEVICEID, "midiInGetDevCaps(dev=%d) by out handle rc=%s\n", udev, mmsys_error(rc));

    {   DWORD e = 0x006F4893; /* velocity, note (#69 would be 440Hz) channel */
        trace("ShortMsg type %x\n", LOBYTE(LOWORD(e)));
        rc = midiOutShortMsg(hm, e);
        ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc));
        if (!rc) Sleep(400); /* Hear note */
    }

    memset(&mhdr, 0, sizeof(mhdr));
    mhdr.dwFlags = 0;
    mhdr.dwUser   = 0x56FA552C;
    mhdr.dwOffset = 0xDEADBEEF;
    mhdr.dwBufferLength = 70000; /* > 64KB! */
    mhdr.lpData = HeapAlloc(GetProcessHeap(), 0 , mhdr.dwBufferLength);
    ok(mhdr.lpData!=NULL, "No %d bytes of memory!\n", mhdr.dwBufferLength);
    if (mhdr.lpData) {
        rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr));
        ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc));
        test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER);

        rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1);
        ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc));
        rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc));
        rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc));
        rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
        trace("MIDIHDR flags=%x when unsent\n", mhdr.dwFlags);

        HeapFree(GetProcessHeap(), 0, mhdr.lpData);
    }
    ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser);
    ok(mhdr.dwOffset==0xDEADBEEF, "MIDIHDR.dwOffset changed to %x\n", mhdr.dwOffset);

    rc = midiOutGetID(hm, &udevid);
    ok(!rc, "midiOutGetID rc=%s\n", mmsys_error(rc));
    if(!rc) ok(udevid==udev, "midiOutGetID gives %d, expect %d\n", udevid, udev);

    rc = midiOutReset(hm); /* Quiet everything */
    ok(!rc, "midiOutReset rc=%s\n", mmsys_error(rc));

    rc = midiOutClose(hm);
    ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc));
    test_notification(hwnd, "midiOutClose", MOM_CLOSE, 0);
    test_notification(hwnd, "midiOut over", 0, WHATEVER);
}
void MIDISong2::Play (bool looping)
{
	MIDIOUTCAPS caps;
	DWORD tid;

	m_Status = STATE_Stopped;
	m_Looping = looping;

	// Find out if this an FM synth or not for EMIDI
	DesignationMask = 0xFF0F;
	if (MMSYSERR_NOERROR == midiOutGetDevCaps (mididevice, &caps, sizeof(caps)))
	{
		if (caps.wTechnology == MOD_FMSYNTH)
		{
			DesignationMask = 0x00F0;
		}
		else if (caps.wTechnology == MOD_MIDIPORT)
		{
			DesignationMask = 0x0001;
		}
	}

	if (MMSYSERR_NOERROR != midiOutOpen (&MidiOut, mididevice, 0, 0, CALLBACK_NULL))
	{
		Printf (PRINT_BOLD, "Could not open MIDI out device\n");
		return;
	}

	// Try two different methods for setting the stream to full volume.
	// Unfortunately, this isn't as reliable as it once was, which is a pity.
	// The real volume selection is done by setting the volume controller for
	// each channel. Because every General MIDI-compliant device must support
	// this controller, it is the most reliable means of setting the volume.

	VolumeWorks = (MMSYSERR_NOERROR == midiOutGetVolume (MidiOut, &SavedVolume));
	if (VolumeWorks)
	{
		VolumeWorks &= (MMSYSERR_NOERROR == midiOutSetVolume (MidiOut, 0xffffffff));
	}
	else
	{
		// Send the standard SysEx message for full master volume
		BYTE volmess[] = { 0xf0, 0x7f, 0x7f, 0x04, 0x01, 0x7f, 0x7f, 0xf7 };
		MIDIHDR hdr = { (LPSTR)volmess, sizeof(volmess), };

		if (MMSYSERR_NOERROR == midiOutPrepareHeader (MidiOut, &hdr, sizeof(hdr)))
		{
			midiOutLongMsg (MidiOut, &hdr, sizeof(hdr));
			while (MIDIERR_STILLPLAYING == midiOutUnprepareHeader (MidiOut, &hdr, sizeof(hdr)))
			{
				Sleep (10);
			}
		}
	}

	snd_midivolume.Callback();	// set volume to current music's properties
	PlayerThread = CreateThread (NULL, 0, PlayerProc, this, 0, &tid);
	if (PlayerThread == NULL)
	{
		if (VolumeWorks)
		{
			midiOutSetVolume (MidiOut, SavedVolume);
		}
		midiOutClose (MidiOut);
		MidiOut = NULL;
	}

	m_Status = STATE_Playing;
}