FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Wave Function CALLBACK HandleEvent
Posts: 31
Joined: Wed Mar 19, 2008 08:52 AM

Wave Function CALLBACK HandleEvent

Posted: Wed Aug 13, 2008 06:05 PM
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?

#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 );
}
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Wave Function CALLBACK HandleEvent

Posted: Wed Aug 13, 2008 08:19 PM

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
Posts: 31
Joined: Wed Mar 19, 2008 08:52 AM

Wave Function CALLBACK HandleEvent

Posted: Thu Aug 14, 2008 01:16 AM
Thank you for your answer.

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

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.
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Wave Function CALLBACK HandleEvent

Posted: Thu Aug 14, 2008 07:25 AM

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
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Wave Function CALLBACK HandleEvent

Posted: Thu Aug 14, 2008 07:27 AM

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
Posts: 31
Joined: Wed Mar 19, 2008 08:52 AM

Wave Function CALLBACK HandleEvent

Posted: Thu Aug 14, 2008 09:41 AM

Thank you for your answer Antonio.

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

Tahnk you.

oknbs.

Posts: 31
Joined: Wed Mar 19, 2008 08:52 AM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 03:02 AM
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.

#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.
Posts: 246
Joined: Sat Mar 03, 2007 08:42 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 08:24 AM
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
Posts: 1283
Joined: Fri Feb 10, 2006 02:34 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 09:23 AM
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..."

UT Page -> https://carles9000.github.io/
Forum UT -> https://discord.gg/bq8a9yGMWh
HIX -> https://github.com/carles9000/hix
Posts: 246
Joined: Sat Mar 03, 2007 08:42 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 09:29 AM
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
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 10:08 AM

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
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 10:12 AM

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

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 6984
Joined: Fri Oct 07, 2005 07:07 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 10:15 AM

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

Posts: 1283
Joined: Fri Feb 10, 2006 02:34 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 10:41 AM
Otto,

#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..."

UT Page -> https://carles9000.github.io/
Forum UT -> https://discord.gg/bq8a9yGMWh
HIX -> https://github.com/carles9000/hix
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Wave Function CALLBACK HandleEvent

Posted: Mon Aug 18, 2008 10:55 AM
regards, saludos

Antonio Linares
www.fivetechsoft.com