Lescasse Consulting
 Home    Company    News    Prices    Download    Buy    Forums   
Read Me
Buy
Forums
Resume
AntiSpam 1.2
wBackup 1.11
NetAccess 2.0
Visual APL 1.0 
APL+Win 8.0 
APL+Win Products 
APL+Win Objects™ 
APL+Win Training 
APL+Web Services
APL+Web Component 
APL+ History
Dyalog.Net Tutorial
Conferences 
Powerpoint
White Papers
Web Hosting
References
Links
 
APL+Win Objects™ 6.0

TADO5
TADO5 Tutorial
TAPLDraw5
TAPLEdit5
TAPLSession5
TAbale5
TAboutBox5
TAccess5
TAgent5
TBlatMail5
TButton5
TCDO5
TCRC5
TCancelButton5
TCheck5
TCheckGroup5
TChildForm5
TChooseColor5
TChooseFont5
TClipBoard5
TClock5
TCodeStats5
TColors5
TCombo5
TComboDrive5
TComboFilter5
TComboList5
TComboTree5
TCommandBar5
TCommandButton5
TControlClass5
TCueCard5
TDHTML5
TDHTMLEditor5
TDateTime5
TDateTimeFr5
TDates5
TDemoHandlers5
TDisplay5
TDOS5
TDualSelect5
TEdit5
TEditAmount5
TEditDir5
TEditEnter5
TEditFile5
TEditGrid5
TEditList5
TEditListview5
TEditMenu5
TEditNum5
TEditSelect5
TEditSpin5
TEmail5
TError5
TExampleForm5
TExcel5
TExcel5 Tutorial
TFindReplace5
TFOne5
TFTP5
TFTP5 Tutorial
TFileCompare5
TFileMenu5
TFileMenuDef5
TFlatButton5
TForm5
TFormClass5
TFormEditor5
TFrame5
TGetDir5
TGif5
TGifForm5
TGifWb5
TGoMenu5
TGraphX5
TGrid5
TGridDisplay5
TGridPrint5
TGUID5
THLine5
THTML5
THTML5 Tutorial
THTTP5
THelp5
THelpMenu5
TImagelist5
TInfo5
TIniFile5
TInstall5
TInternet5
TJpg5
TJpgWb5
TLabel5
TList5
TListview5
TLock5
TLogs5
TMAPI5
TMath5
TMDIForm5
TMSOutlook5
TMaskEdit5
TMedia5
TMenu5
TMessage5
TModalCall5
TMsgBox5
TNavigator5
TNetwork5
TNonVisualClass5
TODBC5
TOKButton5
TObject5
TOpenFile5
TOption5
TOptionGroup5
TOutlook5
TOutlookMail5
TOWCSpread5
TPDF5
TPFKeys5
TPage5
TPassword5
TPicture5
TPing5
TPopupMenu5
TPowerpoint5
TPowerpoint5 Tutorial
TPrinter5
TProgress5
TProgressDlg5
TQuestion5
TRegistry5
TRegistryKey5
TResource5
TRichEdit5
TSPX5
TSQLDMO5
TScheduler5
TScroll5
TSelector5
TSpinner5
TSplitter5
TStatus5
TStopWatch5
TTest5
TTestError5
TTextFile5
TTimer5
TTip5
TTipForm5
TTLI5
TToolBar5
TToolbox5
TToolsMenu5
TTrackbar5
TTranslate5
TTree5
TVLine5
TViewMenu5
TWebBrowser5
TWebServer5
TWebSite5
TWebSiteNet5
TWinMenu5
TWord5
TYesNo5
    Visits:  4503 (18 on line) Last Update: Apr 23, 2003  
    Play MIDI Files with APL+Win    Printer Friendly  

Download a few MIDI files and the APL+Win utilities presented in this article.
  

Preliminary notes
In order to play MIDI files on your computer you need a sound card.
If you are Dyalog APL/W user you may use ŚNA to play MIDI file in a
much similar manner as we do in this article with function PlayMidiWait2.


The APL+Win RAD development system contains high level functions (such as ŒWI) to quickly and easily develop your application interface.

But APL+Win also lets you use all of the 16bit and 32bit Windows API.

Let's use the 32 bit Windows API to write small functions allowing us to play MIDI files from APL+Win.

The 32 bit Windows API contains several functions which could let you play MIDI files. One of them is called mciSendString and is found in WINMM.DLL in the Windows 95/98 System directory (look for WINMM16.DLL under Windows 3.1).

The Windows SDK documentation tells us that mciSendString accepts 4 arguments:

  • the command string to be sent to the MCI (Media Control Interface) device (called a sequencer for MIDI files)
  • a buffer for return information
  • the size of this buffer
  • a handle to a window to call back if "notify" was specified in the command string

Since we will not use the "notify" keyword in our command strings the fourth argument will always be 0 for us.

We will choose the second argument to always be a vector of 256 null characters (ŒTCNUL). The third will therefore always be integer scalar 256.

The first argument is more interesting: it should contain the command strings we need to send to the MCI sequencer device in order to play our MIDI file.

Let's assume our MIDI file is called \APLWIN\RES\MID\BABYBUMB.MID.

The Windows SDK documentation tells us that the set of mciSendString commands required to play the file are:

  • open \APLWIN\RES\MID\BABYBUMB.MID type sequencer alias song
  • play song wait
  • close song

So we can use the APL+Win ŚWCALL system function to access the mciSendString Windows API function to play the MIDI file, in the following way:

   ’ PlayMidiWait A;B;C
[1]  B„(256˝ŚTCNUL)256 0
[2]  C„ŚWCALL'mciSendString'('open ',A,' type sequencer alias song'),B
[3]  C„ŚWCALL'mciSendString' 'play song wait',B
[4]  C„ŚWCALL'mciSendString' 'close song',B
   ’

The PlayMidiWait function argument is the MIDI file name to play. Example:

      PlayMidiWait'\aplwin\res\mid\babybumb.mid'

Alternatively, APL+Win offers a ŒNA (Name Association) system function which also lets you access the Windows API. Using ŒNA, our PlayMidiWait function would read:

   ’ PlayMidiWait2 A;B;C;mciSendString
[1]  B„(256˝Śtcnul) 256 0
[2]  C„'DLL I4„WINMM.mciSendStringA(*C1,*C1„,I4,I4)'Śna'mciSendString'
[3]  A„mciSendString(›'open ',A,' type sequencer alias song',Śtcnul),B
[4]  A„mciSendString(›'play song wait',Śtcnul) , B
[5]  A„mciSendString(›'close song',Śtcnul) , B
   ’

This function works as well to play any MIDI file:

      PlayMidiWait2'\aplwin\res\mid\fugue.mid'

Note that the mciSendString Windows API function returns 0 if it succeeded or an error code in case it failed. You might want to check the meaning of this integer error code with the mciGetErrorString Windows API function. This will be explained in detail in the April 97 issue of the APL+Win Training Program.

The above examples work fine, but have one drawback. These PlayMidiWait programs wait until the MIDI file is entirely played to terminate.

It would be nicer to return immediately and not block the user.

So we would like to remove the wait keyword in the play song wait command string.

However if we do so, the program will start playing the MIDI file and will immediately execute the next statement (close song) which closes the MCI device and therefore stops the MIDI playback. That's not exactly what we want!

Therefore we should remove the close song command string lines in our programs. But the Windows SDK documentation indicates that we MUST be sure to close the device we have opened.

How do we solve this problem then?

We can simply use a high level APL+Win object called a Timer. A Timer is an object which allows you to schedule regular callbacks to APL.

The mciSendString function accepts other command strings than the 3 ones we have already seen. One of them is quite interesting: the status ... mode command. This command returns "playing" as long as the MCI (sequencer) device is still playing.

We will therefore be able to tell the APL system to regularly check if the device is still playing and as soon as it has finished playing, we will disable our timer and automatically run the close song command.

Here is a more general PlayMidi function which does not wait until the MIDI file is finished playing:

   ’ PlayMidi A;B
[1]  B„(256˝Śtcnul) 256 0
[2]  :select A
[3]  :case 'StillPlaying?'
[4]  A„†1‡Śwcall'mciSendString' 'status song mode',B
[5]  :if ~'playing'­(^\A¬Śtcnul)/A
[6]      A„Śwcall'mciSendString' 'close song',B
[7]      'timer'Świ'enabled'0
[8]  :end
[9]  :else
[10] 'timer'Świ'Delete'
[11] A„Śwcall'mciSendString'('open ',A,' type sequencer alias song'),B
[12] A„Śwcall'mciSendString' 'play song',B
[13] A„'timer'Świ'New' 'Timer'('onTimer' 'PlayMidi''StillPlaying?''')
[14] :end
   ’  

The function uses a :select Control Structure to check the argument. If the argument is a MIDI file name (i.e. if it is not character string 'StillPlaying?') lines 10 to 13 are executed.

On line 10 an object called timer is destroyed in case it already existed.

Line 11 opens the MIDI file on the MCI sequencer and aliases it with the word 'song'.

Line 12 starts playing song (alias our MIDI file) and does not wait.

Immediately, on line 13 a Timer object called timer is created, using a default 1000 milliseconds interval. Whenever the onTimer event happens (i.e. every 1000 milliseconds) the following APL expression will be automatically executed by the APL+Win system:

PlayMidi'StillPlaying?'

Thus PlayMidi will run again, this time executing lines 4 to 8. On line 4 we check if the MIDI file is still playing by querying its status mode with the mciSendString 'status song mode' command.

On line 5 we check if the status result is keyword 'playing'.

If it is not the case, this means the sequencer has now finished playing the MIDI file and we can safely close the MCI sequencer device (line 6) and disable our timer (line 7)

 This entire Web site has been dynamically generated by APL+Win Objects™ 6.0
 For all questions contact:  info@lescasse.com
 Copyright © 2003-2005 Lescasse Consulting. All rights reserved.