Link to home
Start Free TrialLog in
Avatar of Stuart Landreth
Stuart LandrethFlag for United Kingdom of Great Britain and Northern Ireland

asked on

callback messages

I am programming using an MPEG2 card and am having trouble getting callbacks from it.

The first method I tried using the CallBack function kept crashing my program when it was compiled and running outside of the VB environment.

The SDK suggestst that with VB you use a CallBack *message* rather than a *function*
The C+ code is

        VCCCALL mpgCallBack ( HWND hwnd);

which i have translated to VB as

       Declare Sub mpgCallback Lib "4reelaps.dll" (ByVal hwnd As Long)
 
in my init code, I am trying to route the messages to a window called frmMessageWindow

      Call mpgCallback(frmMessageWindow.hwnd)



but how do I go about writing the procedure to receive the messages?
from the SDK, I know it returns 3 integers: Card, Channel and Message.

For your reference, the SDK for the card i am using is is available here
http://www.visualcircuits.com/downloads/download.php?id=110
Avatar of foodlebardle
foodlebardle

OK so the function call
Call mpgCallback(frmMessageWindow.hwnd)
tells the mpeg driver that you want the messages sent to the window 'frmMessageWindow'?

Is there a VB equivalent of OnMessage(WM_MPEG_FOO) that you could add to the 'message map'?
Also if you don't know the exact messages sent, you could use spy++ to detect them.
ASKER CERTIFIED SOLUTION
Avatar of jacobhoover
jacobhoover

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Could you post the code that originally crashed with the mpgCallbackFunction?
Hmm,
  one may guess that the function may be prototyped incorectly if it's immediately crashing.  It would be nice to know what the typedef of VCCCALL is defined as.  The PDF they provide alludes to the idea that they "may" of included some samples... Have you looked to see if there are any VB samples to see if the function is prototyped correctly?
  Another possibility is the DLL is posting messages to the window before the message loop is fully initalized.  One could check this by putting the "Call mpgCallback(frmMessageWindow.hwnd)" in a location where it's after the form has loaded and is visible..
 
  Either way, once you get this running, you would want to impliment the subclassing to easily handle the custom user messages this dll will be posting to you.

Jake
Avatar of Stuart Landreth

ASKER

Further details - as per the e-mail I sent to their technical support
----------------------------------------------------------------------------------------

When I run my program from VB, it works fine.
When I compile and run my program, it crashes as soon as it starts.
"VidiZone has encountered a problems and needs to close. We are sorry for the inconvenience"
MonName: msvbvm60.dll
ModVer 6.0.96.90 Offset: 0002453c
 
I know this is related to the callback function.
 
This is my callback code which is in a module
 
 
Public Sub CallBack(ByVal CardNum As Long, ByVal ChanNum As Long, ByVal Message As Long)

    On Error Resume Next
    ' Prevent program crash through error
 
    Select Case Message
   
        Case MPG_FILE_PLAY_COMPLETE
            bReadyForNextTrack(ChanNum + 1) = True
            ' Flag that channel is ready for the next track
        Case MPG_FILE_READ_START
            bRefreshNeeded = True
            ' Flag to update track listings
   End Select
End Sub

As you can see the code is not really doing anything to cause a crash other than changing some boolean values.
I have tried without the "on error" line and to no avail.
 
If it helps, this is the code i'm using to initialise the card.
 
Sub InitMPEG()
    If mpgOpenDriver = DRIVER_NOT_FOUND Then
        MsgBox "Driver not found."
        Exit Sub
    End If
   
    Call mpgCallbackFunction(AddressOf CallBack)
End Sub
With reference to samples:

Yes there is a VB sample demonstrating *some* of the functions described in the SDK. It works fine in the IDE, but on compilation it crashes when a file is opened (i.e. when the first callback is received)
If this holds any clues, this is the declares.bas from the samples file
which i am also using in my project
--------------------------------------------------------------------------------------

Option Explicit

'This module will hold only the declares for the functionality
'contained in 4reelaps.dll

Declare Function mpgOpenDriver Lib "4reelaps.dll" () As Long
'opens connection to the kernel mode driver.
'Must be called before any other function

Declare Sub mpgCloseDriver Lib "4reelaps.dll" ()
'closes connection to the kernel mode driver.
'Must be called upon program completion, assuming mpgOpenDriver worked.

Declare Function mpgLoad Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
                                        ByVal filename As String) As Long
'Opens an MPEG for playing on a channel.  Will interupt anything currently playing.

Declare Sub mpgClose Lib "reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'stops playback and closes the file handle of the file loaded.
'Can also close superfile

Declare Sub mpgPlay Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'starts or resumes playback on a channel

Declare Sub mpgPlayAll Lib "4reelaps.dll" ()
'plays ALL channels already loaded with a file.

Declare Sub mpgStop Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'stops the selected channels.

Declare Sub mpgStopAll Lib "4reelaps.dll" ()
'stops ALL channels already playing.

Declare Sub mpgStatus Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByRef mStatus As mpgStatusStruct)
'obtains status data from a channel.  (Note use of user-defined data type.)

Declare Sub mpgDiagnostic Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByRef mDiag As mpgDiagStruct)
'obtains diagnostic information from channel  (Note use of user-defined data type.)

Declare Sub mpgCards Lib "4reelaps.dll" (ByRef NumCards As Long)
'get number of cards installed

Declare Sub mpgSeek Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal Position As Long)
'seek to a certain position on a file

Declare Sub mpgAutoRepeat Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'sets repeat on

Declare Sub mpgNoRepeat Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'sets repeat off

Declare Sub mpgMute Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'sets mute on

Declare Sub mpgUnMute Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'sets mute off

Declare Sub mpgBlack Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'sets channel to show Black screen

Declare Sub mpgSetAVSync Lib "4reelaps.dll" (ByVal Enable As Boolean)
'set AV synchronization

Declare Sub mpgGetAVSync Lib "4reelaps.dll" (ByRef Enable As Boolean)
'get AV synchronization

Declare Sub mpgCallbackFunction Lib "4reelaps.dll" (ByVal ptrFunction As Any)
'declare callback function

Declare Sub mpgSetInitOnOpen Lib "4reelaps.dll" (ByVal Val As Long)
'set init. on open

Declare Sub mpgSetAuxSkip Lib "4reelaps.dll" (ByVal Val As Long)
'set aux skip(?)

Declare Sub mpgLoadNext Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal filename As String)
'loads another file for playing

'On screen display routines:

Declare Sub osdLoadBMP Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal GIFFileName As String, ByVal xPos As Long, ByVal yPos As Long, _
            ByVal Mix As Long, ByVal xColor As Long)
'loads a GIF file

Declare Sub osdShow Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'shows an already loaded GIF file

Declare Sub osdHide Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long)
'hides an already shown GIF file

Declare Sub osdSetXYMix Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal xPos As Long, ByVal yPos As Long, ByVal Mix As Long)
'Changes the position and mix values for a GIF

Declare Sub mpgSuppressHost Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal Value As Long)
'stops MPEG data from being sent to decoder chip from host memory.
'0- don't supress data flow
'1-supress data flow

Declare Sub mpgSuppressChip Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal Value As Long)
'stops MPEG data from being sent to host memory from hard drive.
'0- don't supress data flow
'1-supress data flow


Declare Sub mpgSetStickyFrame Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal Val As Long)
'set a frame number to stop playback on, continues with the next mgpPlay

Declare Sub mpgSetCurrentFrame Lib "4reelaps.dll" (ByVal CardNum As Long, ByVal ChanNum As Long, _
            ByVal Val As Long)
'sets the current frame number for a channel

'structure for variable to send to status routine
Public Type mpgStatusStruct
    FilesSize       As Long     'size of loaded MPEG file
    FilePosition    As Long     'current MPEG file read position
    System          As Long     'Is this a system file(audio and video)
    HSize           As Long     'Horizontal size of mpeg file
    VSize           As Long     'vertical size
    PicRate         As Long     'picture rate code of file
    BitRate         As Long     'bitrate of file, divided by 400
    TimeCode        As Long     'last time code decoded
    RunTime         As Long     'how long MPEG file has been running
    Frame           As Long     'current frame being decoded
    DataUnderFlows  As Long     'stat-number of times decoder underflowed
    DiskUnderFlows  As Long     'stat-number of data from disk ran out
End Type

'structure for variable to send to diagnostic routine
Public Type mpgDiagStruct
    DMACount                As Long 'number of started DMA transfers to this channel
    InterurptCount          As Long 'number of completed DMA interrupt transfers
    NumberOfSyncs           As Long 'number of times the channel has had to adjust a/v sync
    LastSyncCorrection      As Long 'amount of last sync correction
    VideoDataOnChip         As Long 'on chip video data quantity
    AudioDataOnChip         As Long 'on-chip audi data quantity
    SizeVideoBufferOnChip   As Long 'on chip video buffer size
    SizeAudioBufferOnChip   As Long 'on-chp audio buffer size
    MPEGDataInMemory        As Long 'memory MPEG data quantity
    SizeMPEGBufferInMemory  As Long 'memory video buffer size
    AudioFrequency          As Long
    AudioBitrate            As Long
    FileType                As Long
    reserved3               As Long
    reserved4               As Long
    reserved5               As Long
    reserved6               As Long
    reserved7               As Long
End Type

Public Const MPG_FILE_READ_COMPLETE = &H1 'message sent to callback routine
Public Const MPG_FILE_PLAY_COMPLETE = &H2 'message sent to callback routine
Public Const MPG_FILE_READ_START = &H5 'message sent to callback routine
Public Const MPG_FILE_FRAME_STICK = &H8 'message sent to callback routine

Public Const CHANNELS_PER_CARD = 4
Public Const SYNC_GROUPS = 10

Public Const HIDE_READ_ONLY_OPTION = &H4
Public Const VERIFY_FILE_EXISTS = &H1000

Public Const TIMER_INTERVAL = 50 'number of milliseconds

Public Const APP_NAME = "4ReelTimePro"

'return values
Public Const NO_ERROR = 0
Public Const DRIVER_NOT_FOUND = 1
Public Const FILE_NOT_FOUND = 3

Public Card()          As clsCard 'array of card objects, each of which has a number of channels

Everything in there looks good - sorry, I can't help you there.

I would recommend trying out the subclassing solution jacobhoover mentioned.

Best regards,
Maxim
Another option would be to generate the symbolic debug info for the application and attempt to debug it further with the visual c++ debugger, but judging from the error message you received you do not have that available.  Either way, using callback messages in the message loop of a window would be more stable, but also more time sensitive.  The main reason that the use of a callback function is so risky in VB6 is because it is NOT thread safe, and the even of a callback is actually a second thread jumping into your address space, specifically at the address of the function you passed to it.  However, using the message based system, the foreign thread is just posting a message to your window which is threadsafe.  The only issue is the time involved, as a message que is a FIFO buffer of sorts and if the window is flooded with other messages or is busy processing a current message it can't respond to any other messages.  One could argue the use of "DoEvents" in VB6, but that is a slimy hack at best to cover for language faults and poor programming.

Jake