FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

SOUND

Play .wav sound files


I'm not really sure what I did, but I got playing .WAV files in FBII to work:

(I would be grateful for some feedback on the need for the strange use of a pseudo FSSpec (see '#specPtr& in 'FN PlayWaveUsingQuickTime(wFname$, srcWD%)' below. The FBII manual says just use a standard FSSpec [as in DIM myFSSpec.70], not a pointer to an FSSpec.... {whine, whine, bitch, moan.....})

Anyone who can use the code is welcome to it....
CLEAR LOCAL
LOCAL FN myFSMakeFSSpec(vRefNum, dirID&, filename$, specAddr&)
  'Call as follows:
  ' OSErr = FN myFSMakeFSSpec(vRefNum, dirID&, filename$, @spec)
  'where spec is a 70-byte (or longer) record
  DIM filenameAddr&, OSErr

  filenameAddr& = @filename$
  `     clr.w   -(sp)
  `     move.w  ^vRefNum,-(sp)
  `     move.l  ^dirID&,-(sp)
  `     move.l  ^filenameAddr&,-(sp)
  `     move.l  ^specAddr&,-(sp)
  `     move.w  #$0001,d0
  `     dc.w    $AA52
  `     move.w  (sp)+,^OSErr
END FN = OSErr

CLEAR LOCAL
LOCAL FN PlayWaveUsingQuickTime(wFname$, srcWD%)
  DIM fsVRefNum,fsParID&,fsName$;64
  DIM srcSpec.70
  DIM movie.24
  DIM OSErr%, MovieRef%, isOK%, movieptr&, specPtr&
  DIM resID,resName$,newMovieFlags%,dataRefChg%
  DIM okToGo%, anErr%

  resID = 0
  resName$ = ""
  newMovieFlags% = 0
  dataRefChg% = 0

  movieptr&   = @movie
  specPtr&    = @fsVRefNum

  anErr% = FN myFSMakeFSSpec(srcWD%, 0, wFname$, specPtr&)
  LONG IF anErr% = _noErr
    okToGo% = okToGo% + 1
  END IF

  anErr% = FN ENTERMOVIES
  LONG IF anErr% = _noErr
    okToGo% = okToGo% + 1
  END IF

  anErr% = FN OPENMOVIEFILE(#specPtr&,MovieRef%,_fsRdPerm)
  LONG IF anErr% = _noErr
    okToGo% = okToGo% + 1
  END IF

  anErr% = FN
NEWMOVIEFROMFILE(movieptr&,MovieRef%,resID,resName$,newMovieFlags%,dataRefCh
g%)
  LONG IF anErr% = _noErr
    okToGo% = okToGo% + 1
  END IF

  anErr% = FN CLOSEMOVIEFILE(MovieRef%)
  LONG IF anErr% = _noErr
    okToGo% = okToGo% + 1
  END IF

  LONG IF okToGo% = 5
    CALL STARTMOVIE(movieptr&)
    WHILE FN ISMOVIEDONE(movieptr&) = _false
      CALL MOVIESTASK(movieptr&, 0)
    WEND
    CALL DISPOSEMOVIE(movieptr&)
  END IF

END FN
Michael Evans

There are a number Toolbox functions/procedures in FB which have the following characteristics for one or more of their parameters:

1. The Toolbox routine (internally) "wants" the parameter to be an address to a data structure;

2. FB lets you specify a variable (rather than an address) in that parameter; FB then passes the variable's address to the Toolbox routine, to satisfy the Toolbox's need for an address.

Strangely, there's a subset of such routines which FB has chosen to implement with this additional bizarre restriction: 3. The variable that you specify _must_ be a short integer variable--even if the data structure "inside" the variable is supposed to be many bytes in length(!)

This is why you often get the (completely misleading) error message, "Must be a long integer variable." This message is in error: it really should say, "Must be a _short_ integer variable," because that is what FB is expecting you to put there. I don't know why they've never fixed this message.

There are two ways to handle this situation. Let's say a certain Toolbox call falls into this category and it wants the address to a 10-byte structure. Your first impulse is to pass a variable declared like this:
DIM myRec.10
But, in this hypothetical case, the variable must be a short integer, so the compiler complains when you pass "myRec". So one possible solution is to declare it like this instead:
DIM myRec;10
In this case, "myRec" is actually and literally a 2-byte short-integer variable, but it's followed by 8 bytes of "free" space into which you can put whatever you want. This makes the compiler happy; FB passes the address of "myRec" to the Toolbox routine; the Toolbox routine doesn't know from short integers; it just looks at the address as the beginning of a 10-byte buffer.

The other solution is to use the "#" syntax. The "#" syntax can _only_ be used in Toolbox parameters that satisfy conditions "1" and "2" above (with or without "3"). When FB sees the "#", it stops looking for a variable in that position, and instead looks for (any) long-integer expression. It evaluates the expression, and sends the result to the Toolbox routine. The Toolbox routine then uses that value as the "address" that it wants.

So to recap: For those parameters that satisfy conditions "1" and "2", the Toolbox routine receives either:

* The address of an FB variable (when you specify that variable as the parameter); or:

* An arbitrary long-integer value (when you specify a long-integer expression preceded by "#")

In our example situation, you could do any of the following:
DIM myRec;10
CALL SOMETOOLBOX(myRec)  'Happy to have a short integer var
or:
DIM myRec.10
myRecPtr& = @myRec
CALL SOMETOOLBOX(#myRecPtr&)  'Any long int expression OK
or even:
DIM myRec.10
CALL SOMETOOLBOX(#@myRec)  '@myRec is a long int expression
Rick