Wave Function CALLBACK HandleEvent

Wave Function CALLBACK HandleEvent

Postby oknbs » Wed Aug 13, 2008 6: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?

Code: Select all  Expand view  RUN

#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 );
}

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

Postby Antonio Linares » Wed Aug 13, 2008 8: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
User avatar
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby oknbs » Thu Aug 14, 2008 1:16 am

Thank you for your answer.

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

Code: Select all  Expand view  RUN

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.
oknbs
 
Posts: 31
Joined: Wed Mar 19, 2008 8:52 am

Postby Antonio Linares » Thu Aug 14, 2008 7: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
User avatar
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby Antonio Linares » Thu Aug 14, 2008 7: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
User avatar
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby oknbs » Thu Aug 14, 2008 9:41 am

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

Postby oknbs » Mon Aug 18, 2008 3: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.

Code: Select all  Expand view  RUN

#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.
oknbs
 
Posts: 31
Joined: Wed Mar 19, 2008 8:52 am

Postby Patrick Mast » Mon Aug 18, 2008 8: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
User avatar
Patrick Mast
 
Posts: 246
Joined: Sat Mar 03, 2007 8:42 pm

Postby Carles » Mon Aug 18, 2008 9: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
Skype -> https://join.skype.com/cnzQg3Kr1dnk
User avatar
Carles
 
Posts: 1139
Joined: Fri Feb 10, 2006 2:34 pm
Location: Barcelona

Postby Patrick Mast » Mon Aug 18, 2008 9: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
User avatar
Patrick Mast
 
Posts: 246
Joined: Sat Mar 03, 2007 8:42 pm

Postby Antonio Linares » 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
User avatar
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby Antonio Linares » 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
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
Antonio Linares
Site Admin
 
Posts: 42122
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby Otto » 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
User avatar
Otto
 
Posts: 6345
Joined: Fri Oct 07, 2005 7:07 pm

Postby Carles » Mon Aug 18, 2008 10:41 am

Otto,

Code: Select all  Expand view  RUN
#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
Skype -> https://join.skype.com/cnzQg3Kr1dnk
User avatar
Carles
 
Posts: 1139
Joined: Fri Feb 10, 2006 2:34 pm
Location: Barcelona

Postby Antonio Linares » Mon Aug 18, 2008 10:55 am

regards, saludos

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

Next

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 50 guests