I am using Delphi 10.2.
I want a small music program of mine to be able to play MIDI files. I want to use MCI (Media Control Interface), as it should be simpler to code than the more low-level MIDI API. I found the following code, which functions OK as long as I choose a given MIDI file only once.
I have a TFileListBox
on my Form, and I can choose and play as many MIDI files as I want as long as they are not repeated. As soon as I chose one of the MIDI files for a second time, it will stop playing.
It might be a problem that I don't call mciSendCommand()
with MCI_CLOSE
, but if I try to do this then I get an error like:
Could not convert variant of type (NULL) into type (Int64)
Function TForm1.PlayMidiFile(FileName: string): Word;
// http://www.delphigroups.info/2/3e/176031.html
// You need to add the MMSYSTEM unit in your USES clause.
var
wDeviceID: Integer;
dwReturn : Word;
mciOpen : TMCI_Open_Parms;
mciPlay : TMCI_Play_Parms;
mciStat : TMCI_Status_Parms;
mciSeq : TMCI_Seq_Set_Parms;
begin
// Open the device by specifying the device and filename.
// MCI will attempt to choose the MIDI mapper as the output port.
mciOpen.lpstrDeviceType := 'sequencer';
mciOpen.lpstrElementName := PChar(FileName);
dwReturn := mciSendCommand($0, MCI_OPEN, MCI_OPEN_TYPE or MCI_OPEN_ELEMENT, LongInt(@mciOpen));
if dwReturn <> 0 then
Result := dwReturn
else begin
// The device opened successfully; get the device ID.
wDeviceID := mciOpen.wDeviceID;
// Check if the output port is the MIDI mapper.
mciStat.dwItem := MCI_SEQ_STATUS_PORT;
dwReturn := mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, LongInt(@mciStat));
if dwReturn <> 0 then begin
{ close if not succeeding }
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
Result := dwReturn;
end else begin
// Begin playback. The window procedure function for the parent
// window will be notified with an MM_MCINOTIFY message when
// playback is complete. At this time, the window procedure closes
// the device.
mciPlay.dwCallback := Application.Handle;
dwReturn := mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, LongInt(@mciPlay));
if dwReturn <> 0 then begin
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
Result := dwReturn;
end;
end;
end;
end;