[ANN] Tool for calling C functions from Clean 1.3 is available

Antonio Eduardo Costa Pereira costa@ufu.br
Fri, 12 Feb 1999 09:51:11 -0200


Clean Support wrote:
> 
> Version 1.0 of htoclean, a tool that makes it easier to call functions written
> in C from Clean 1.3 or 1.3.1, is now available from:
> 
>     http://www.cs.kun.nl/~clean/download.html#HtoClean
> 
> or:
> 
>     ftp://ftp.cs.kun.nl/pub/Clean/supported/H_to_Clean10/
> 
> The archives contain the tool, documentation, examples and source code.

Dear members of Clean Support.

I have written a rather large program to generate music and accords. The
program was designed by Dr. Luciano Lima, and it is described in his
thesis and papers. It basically "learns" rules of composition from
examples,
and generates a midi file. Not long ago, I added a module to play the
music which the program generates. This module, written in C, plays the
music most of the time. In a few occasions, however, it freezes the
sound
equipament. This always happens when a music ends, and I want to play
the next one. It is easy to see what is happening. The MIDI interface
 is supposed to return a notification when the music ends. 
In Prolog, there is a predicate
to hook the main Window to a native process. The hooking enables the
event
handles predicate to catch the notification, and turns off the
instruments,
which become ready for the next music. In Clean, I don't know how to
catch the notification, and turn off the instruments. I wrote a very
simple version of the program for you to examine. This simple version
uses MCI and Sound Blaster, instead of a MIDI interface. I tryed to make
it as small as possible to ease your analysis. Remember, it works most
of the time. It fails only in a few occasions, and only when a music
ends and you want to play it again.

// File midPlay.icl ================================================
module midPlay; 

import StdEnv, StdDebug, intrface; 
import deltaEventIO, deltaDialog; 
import deltaIOState; 

NOSOUND :== 100000; 

:: *State = {snd::!Int}; 

// playMid returns MCIDEVICEID soundID, which can be used
// to turn off Sound Blaster.
playMid :: !Int !Int-> !Int; 
playMid _  _ 
= code 
    {    
            ccall mid "II-I" 
         
    }; 

// closeMid takes the soundID and turns off the sound Blaster.
closeMid :: !Int -> !Int; 
closeMid _ 
= code 
    {    
            ccall  closemm "I-I" 
         
    }; 

// A simple dialog to test the system. It contains
// a quit button, a Play button, and a Stop button.
// If I use the button to stop the music, I can restart
// it with the Play button. However, if I let the music
// reach the end, the Play button may fail to restart it.
// With professional music instruments, the whole system
// may freeze. I guess that this is caused by failure in
// catching the end of music notification and closing
// soundID.
Start world 
#    initState= {snd= NOSOUND}     
;    (state, world)= StartIO [DialogSystem[DLG]] initState [] world 
= state.snd; 

DLG= 
  CommandDialog 0 "Midi" [] exit_id 
    [    DialogButton exit_id Left "Bye" Able Quit 
    ,    DialogButton play_id (Below exit_id) "Play" Able Playit 
    ,    DialogButton stop_id (RightTo play_id) "Stop" Able Stopit] 
where 
{    [exit_id, play_id, stop_id:_]= [1..] }; 

Quit info s=:{snd} io 
#    i= closeMid snd 
= ({s&snd=i}, QuitIO io); 

Playit info s=:{snd} io 
#    (_, os)= WinInitOs 
// ;    (cstr, os1)= WinMakeCString "partitura.mid" os
;    (cstr, os1)= WinMakeCString "d:\\scher\\scheh1.mid" os 
;    i= playMid cstr snd 
= ({s& snd= i}, io); 

Stopit info s=:{snd} io 
#    i= closeMid snd 
= ({s&snd= i}, io);


// File sound.c =================================================
// This file can be compiled with Visual C, or with lcc.
// In any case, a sound.o is generated.
#include "windows.h"
#include "mmsystem.h"

#define NOSOUND 100000

int mid(LPSTR path, MCIDEVICEID soundID)
{   
    MCI_OPEN_PARMS mciOpen;
    MCI_PLAY_PARMS mciPlay;
    MCIERROR rtrn; 

    if (soundID != NOSOUND)
      {rtrn= mciSendCommand(soundID,MCI_CLOSE,(DWORD)0, (DWORD)NULL);}


    mciOpen.wDeviceID= (MCIDEVICEID)NULL;
    mciOpen.lpstrDeviceType="sequencer";
    mciOpen.lpstrElementName=path;

    if((rtrn=mciSendCommand((MCIDEVICEID)NULL,MCI_OPEN,MCI_OPEN_TYPE | 
               MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOpen)) != 0L)
                return(NOSOUND);
 

    soundID=mciOpen.wDeviceID;
    
    if((rtrn=mciSendCommand(soundID,MCI_PLAY, 0
/*MCI_NOTIFY*/,(DWORD)(LPVOID)&mciPlay)) != 0L) {
         mciSendCommand(soundID,MCI_CLOSE,(DWORD)0, (DWORD)NULL);
         
                return(NOSOUND);
       
                   }

        return(soundID);
}
 
int closemm(int soundID)
{ if (soundID != NOSOUND) mciSendCommand(soundID,MCI_CLOSE,(DWORD)0,
(DWORD)NULL);
  return NOSOUND;
}

// File winlib =======================

c:\Windows\System\winmm.dll
mciSendCommandA@16


Both winlib and sound.o must be added to the link options.
Since I don't have an email for the time being, you can use
my adviser's email to contact me. The address is costa@ufu.br.
Thank you for helping.

Wes