Wave Function CALLBACK HandleEvent

oknbs
Posts: 31
Joined: Wed Mar 19, 2008 8:52 am

Wave Function CALLBACK HandleEvent

Post by oknbs »

Dear Harbour User

I want to make a simple Voice Recoder by using WaveInOpen and WaveOutOpen Function.
I set CALLBACK to WINDOW (the Function is as follows) and I tried to receive MM_WIN_OPEN, MM_WIN_DATA of HandleEvent.
But I don't know what to set the Class Name of CreateWindow.
I really need your help.
Or Are there any Voice Recoder Sample File made by Harbour?

Code: Select all


#define MM_WIM_OPEN         958      /* waveform input */
#define MM_WIM_CLOSE        959
#define MM_WIM_DATA         960


CLASS TWave FROM TControl
  
   DATA hWaveIn

   METHOD New() CONSTRUCTOR
   METHOD WaveInStart( oWnd )
   ...
   METHOD HandleEvent( nMsg, nWParam, nLParam )
   ...
ENDCLASS


METHOE New() CLASS TWave
   
   ::Create( "????" )  => ? Class Name
   //

Return Self


METHOD WaveInStart( oWnd ) CLASS TWave

   LOCAL hWaveIn

   if WaveInOpen( &hWaveIn, oWnd:hWnd ) >= 0
      ::hWaveIn := hWaveIn
      //
   endif

Return NIL  


METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TWave

   do case
      case nMsg == MM_WIN_OPEN
           //
      case nMsg == MM_WIN_DATA
           //
      otherwise
           //
   endcase

Return NIL



HB_FUNC( WAVEINOPEN )
{
   HWAVEIN       hWaveIn;
   WAVEFORMATEX  waveformat;
   int           nResult;

   waveformat.wFormatTag      = WAVE_FORMAT_PCM;                                            
   waveformat.nChannels       = 1 ;                                                         
   waveformat.nSamplesPerSec  = 11025;                                                     
   waveformat.wBitsPerSample  = 8;                                                           
   waveformat.nBlockAlign     = waveformat.nChannels*waveformat.wBitsPerSample/8;            
   waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec*waveformat.nBlockAlign;            
   waveformat.cbSize          = 0;                                                           

   nResult = WaveInOpen( &hWaveIn, WAVE_MAPPER, (WAVEFORMATEX)&waveformat, (DWORD) hb_parnl(2), 0, CALLBACK_WINDOW );

   hb_stornl( ( LONG ) hWaveIn, 1 );
   hb_retni( nResult );
}

User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

There is no need to provide a classname for it when calling ::Create()

FiveWin will automatically provide "TWave" :-)

Just call ::Create()
regards, saludos

Antonio Linares
www.fivetechsoft.com
oknbs
Posts: 31
Joined: Wed Mar 19, 2008 8:52 am

Post by oknbs »

Thank you for your answer.

::Create() => Cannot create window or control Error!

Code: Select all


METHOD New( oWnd ) CLASS TWave

   DEFAULT oWnd := GetWndDefault()

   ::nId       = ::GetNewId()
   ::oWnd      = oWnd
   ::nStyle    = nOR( WS_CHILD, WS_VISIBLE )

   ::Register()

   if !Empty( oWnd:hWnd )
      ::Create()
      oWnd:AddControl( Self )
   else
      oWnd:DefControl( Self )
   endif

   ::aBuffer[1] := HB_WaveInitBuffer()
   ::aBuffer[2] := HB_WaveInitBuffer()

RETURN Self

oknbs.
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Oknbs,

Maybe "TWave" is an already used class in Windows. Then please try it this way:

::Create( "TMyWave" )
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

BTW, you are missing this important code in your class header:

CLASSDATA lRegistered AS LOGICAL

that code is a must for user defined control classes.
regards, saludos

Antonio Linares
www.fivetechsoft.com
oknbs
Posts: 31
Joined: Wed Mar 19, 2008 8:52 am

Post by oknbs »

Thank you for your answer Antonio.

I added "CLASSDATA lRegistered AS LOGICAL" and the problem go away.

Tahnk you.

oknbs.
oknbs
Posts: 31
Joined: Wed Mar 19, 2008 8:52 am

Post by oknbs »

Dear Antonio.

There wasn't any error after I add the "CLASSDATA lRegistered AS LOGICAL" Code.
But the HandleEvent did not run.

Attached is my source code.

Code: Select all


#include "Fivewin.ch"

#define MM_WOM_OPEN         955      /* waveform output */
#define MM_WOM_CLOSE        956
#define MM_WOM_DONE         957

#define MM_WIM_OPEN         958      /* waveform input */
#define MM_WIM_CLOSE        959
#define MM_WIM_DATA         960

STATIC oWave

Function Main()

   LOCAL oWnd

   DEFINE WINDOW oWnd FROM 3, 6 TO 20, 70 ;
      TITLE "Voice Recoder Test"

   SetKey( VK_F2, { || StartWave( oWnd ), RecordWave( oWnd ) } )

   ACTIVATE WINDOW oWnd ;
      VALID App_Exit()

Return NIL

//---------------------------------------------------------------------------//

Function StartWave( oWnd )

   oWave := TSipWave():New( oWnd )

Return NIL

//---------------------------------------------------------------------------//

Function RecordWave( oWnd )

   oWave:WaveInStart( oWnd )

Return NIL

//---------------------------------------------------------------------------//

Function App_Exit()

   LOCAL lResult := .F.

   if MsgYesNo( "Are you sure?", "Do you want to exit?" )
      lResult := .T.
      if oWave != NIL
         oWave:WaveInStop()
         oWave:WaveInClose()
         oWave:End()
      endif
   endif

Return lResult

//---------------------------------------------------------------------------//

CLASS TSipWave FROM TControl

      DATA hWaveIn
      DATA hWaveOut

      DATA aBuffer     AS ARRAY INIT Array(2)
      DATA aWaveHdr    AS ARRAY INIT Array(2)

      CLASSDATA lRegistered AS LOGICAL

      METHOD New( oWnd ) CONSTRUCTOR

      METHOD WaveInStart( oWnd )
      METHOD WaveInStop()            INLINE HB_WaveInStop( ::hWaveIn )
      METHOD WaveInClose()           INLINE HB_WaveInClose( ::hWaveIn )

      METHOD End()  INLINE  ::Destory()
      METHOD Destory()

      METHOD HandleEvent( nMsg, nWParam, nLParam )

ENDCLASS

//---------------------------------------------------------------------------//

METHOD New( oWnd ) CLASS TSipWave

   DEFAULT oWnd := GetWndDefault()

   ::nId       = ::GetNewId()
   ::oWnd      = oWnd
   ::nStyle    = nOR( WS_CHILD, WS_VISIBLE )

   ::Register()

   if !Empty( oWnd:hWnd )
      ::Create()
      oWnd:AddControl( Self )
   else
      oWnd:DefControl( Self )
   endif

   ::aBuffer[1] := HB_WaveInitBuffer()
   ::aBuffer[2] := HB_WaveInitBuffer()

RETURN Self

//---------------------------------------------------------------------------//

METHOD WaveInStart( oWnd ) CLASS TSipWave

   LOCAL hWaveIn

   if HB_WaveInOpen( @hWaveIn, oWnd:hWnd ) >= 0
      ::hWaveIn := hWaveIn

      ::aWaveHdr[1] := HB_InitWaveHdr( ::aBuffer[1] )
      ::aWaveHdr[2] := HB_InitWavehdr( ::aBuffer[2] )

      if HB_WaveInPrepareHeader( ::hWaveIn, ::aWaveHdr[1] ) < 0
         MsgAlert( "WaveInPrepareHeader Error" )
      endif

      if HB_WaveInPrepareHeader( ::hWaveIn, ::aWaveHdr[2] ) < 0
         MsgAlert( "WaveInPrepareHeader Error" )
      endif

      if HB_WaveInAddBuffer( ::hWaveIn, ::aWaveHdr[1] ) < 0
         MsgAlert( "WaveInAddBuffer Error" )
      endif

      if HB_WaveInAddBuffer( ::hWaveIn, ::aWaveHdr[2] ) < 0
         MsgAlert( "WaveInAddBuffer Error" )
      endif

      if HB_WaveInStart( ::hWaveIn ) >= 0
         // To do
      endif
   endif

Return NIL

//---------------------------------------------------------------------------//

METHOD Destory() CLASS TSipWave

   HB_WaveFreeBuffer( ::aBuffer[1] )
   HB_WaveFreeBuffer( ::aBuffer[2] )

Return NIL

//---------------------------------------------------------------------------//

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TSipWave

   do case
      case nMsg == MM_WIM_OPEN
           Msginfo( "MM_WIM_OPEN" )
      case nMsg == MM_WIM_DATA
           MsgInfo( "MM_WIM_DATA" )
      case nMsg == MM_WIM_CLOSE
           MsgInfo( "MM_WIM_CLOSE" )
   endcase

Return Super:HandleEvent( nMsg, nWParam, nLParam )


//---------------------------------------------------------------------------//

#pragma BEGINDUMP

#include "hbapi.h"
#include "hbapiitm.h"
#include "hbdefs.h"

#include <windows.h>
#include <mmsystem.h>

#define  BUFFER_SIZE     5000

HB_FUNC( HB_WAVEINITBUFFER )
{
   PBYTE pBuffer;

   pBuffer = hb_xgrab( BUFFER_SIZE );
   hb_retptr( pBuffer );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEFREEBUFFER )               // BYTE pBuffer
{
    hb_xfree( hb_parptr( 1 ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_INITWAVEHDR )                    // BYTE pBuffer
{
   PWAVEHDR pWavehdr;

   pWavehdr = hb_xgrab( sizeof( WAVEHDR ) );

   pWavehdr->lpData          = (LPSTR) hb_parptr(1);
   pWavehdr->dwBufferLength  = BUFFER_SIZE;
   pWavehdr->dwUser          = 0;
   pWavehdr->dwFlags         = 0;

   hb_retptr( pWavehdr );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINOPEN )       // hWaveIn, pWavehdr, hWnd
{
   HWAVEIN  hWaveIn ;
   WAVEFORMATEX   waveformat;

   int nResult;

   waveformat.wFormatTag      = WAVE_FORMAT_PCM;
   waveformat.nChannels       = 1;
   waveformat.nBlockAlign     = 1;
   waveformat.wBitsPerSample  = 8;
   waveformat.nSamplesPerSec  = 11025;
   waveformat.nAvgBytesPerSec = 11025;
   waveformat.cbSize          = 0;

   nResult = waveInOpen( &hWaveIn, WAVE_MAPPER, (LPWAVEFORMATEX)&waveformat, (DWORD)hb_parnl(2), 0, CALLBACK_WINDOW );

   hb_stornl( (LONG)hWaveIn, 1 );
   hb_retni( nResult );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINPREPAREHEADER )     // hWaveIn, pWavehdr
{
   hb_retni( waveInPrepareHeader( (HWAVEIN) hb_parnl(1), hb_parptr(2), sizeof( WAVEHDR ) ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINUNPREPAREHEADER )  // hWaveIn, pWavehdr
{
   hb_retni( waveInUnprepareHeader( (HWAVEIN) hb_parnl(1), hb_parptr(2), sizeof( WAVEHDR ) ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINADDBUFFER )       // hWaveIn, pWavehdr
{
   hb_retni( waveInAddBuffer( (HWAVEIN) hb_parnl(1), hb_parptr(2), sizeof( WAVEHDR ) ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINSTART )          // hWaveIn
{
   hb_retni( waveInStart( (HWAVEIN) hb_parnl(1) ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINRESET )         // hWaveIn
{
   hb_retni( waveInReset( (HWAVEIN) hb_parnl(1) ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINSTOP )          // hWaveIn
{
   hb_retni( waveInStop( (HWAVEIN) hb_parnl(1) ) );
}

//---------------------------------------------------------------------------//

HB_FUNC( HB_WAVEINCLOSE )         // hWaveIn
{
   hb_retni( waveInClose( (HWAVEIN) hb_parnl(1) ) );
}

//---------------------------------------------------------------------------//

#pragma ENDDUMP

oknbs.
User avatar
Patrick Mast
Posts: 244
Joined: Sat Mar 03, 2007 8:42 pm

Post by Patrick Mast »

Antonio Linares wrote:BTW, you are missing this important code in your class header:

CLASSDATA lRegistered AS LOGICAL

that code is a must for user defined control classes.
[Learning mode]
What is "CLASSDATA lRegistered AS LOGICAL" doing for the class? Why exactly is it needed?
[/Learning mode]

;-)

Patrick
User avatar
Carles
Posts: 937
Joined: Fri Feb 10, 2006 2:34 pm
Location: Barcelona
Contact:

Post by Carles »

Patrick,
> CLASSDATA lRegistered AS LOGICAL

It is needed for new control Classes that are not Windows estandard. Windows API requires to "register" a control class name. It has to be registered only once. That DATA controls that. Estandard Window classes are already "registered" by Windows itself.
C.
Salutacions, saludos, regards

"...programar es fácil, hacer programas es difícil..."

https://modharbour.app
https://modharbour.app/compass
https://forum.modharbour.app
User avatar
Patrick Mast
Posts: 244
Joined: Sat Mar 03, 2007 8:42 pm

Post by Patrick Mast »

Carles wrote:
> CLASSDATA lRegistered AS LOGICAL
It is needed for new control Classes that are not Windows estandard. Windows API requires to "register" a control class name. It has to be registered only once. That DATA controls that. Estandard Window classes are already "registered" by Windows itself.
C.
Ok, thanks. Now, WHY does Windows API requires a class to be "registered". If we don't do it, what's going to happen?

Patrick
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Patrick,

It will not be "found".

Is similar as when we do CLASS TTest() ... ENDCLASS in Harbour. If we don't do that and we call TTest() then an object TTest is not created :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Oknbs,

Please place some traces using MsgBeep(), MsgInfo() and LogFile() to check in which parts of your code the execution is going trough.

You can also use OutputDebugString() to check traces on an external dbwin32 utility
Last edited by Antonio Linares on Mon Aug 18, 2008 11:10 am, edited 1 time in total.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

Hello Antonio,
> You can also use OutputDebugString() to check traces on an external dbwin utility
Could you please explain how to use an external dbwin utility and which one.

Thanks in advance
Otto
User avatar
Carles
Posts: 937
Joined: Fri Feb 10, 2006 2:34 pm
Location: Barcelona
Contact:

Post by Carles »

Otto,

Code: Select all

#include 'fivewin.ch'

FUNCTION Main()

   Dbg( Time() )

   MsgInfo( 'Output to DBWin32.exe' )

RETU nil

FUNCTION Dbg( xVal, cTitle )

   DEFAULT cTitle := 'FWH Debug'

   OutputDebugString( cTitle + ' => ' + cValToChar( xVal ) )

RETURN NIL


DLL32 FUNCTION OutputDebugString( cOutStr AS LPSTR ) As VOID PASCAL ;
  FROM "OutputDebugStringA" lib "kernel32.dll"

*#pragma BEGINDUMP
*
*#include <windows.h>
*#include "hbapi.h"
*
*HB_FUNC( OUTPUTDEBUGSTRINGC )
*{
* OutPutDebugStringA( hb_parc( 1 ) );
*}
*
*#pragma ENDDUMP
*
*FUNCTION OutPutDebugString( xVal )
*
*    OutPutDebugStringC( cValToChar( xVal ))
*
*RETURN NIL
You need execute also DBwin32.exe

C.
Salutacions, saludos, regards

"...programar es fácil, hacer programas es difícil..."

https://modharbour.app
https://modharbour.app/compass
https://forum.modharbour.app
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

regards, saludos

Antonio Linares
www.fivetechsoft.com
Post Reply