@database "thx-play"
@master "Dixie:home/kyz/dev/mine/e/main/PlayTHX/src/thx-play.doc"

@Node Main "thx-play.doc"
    @{" --overview-- " Link "--overview--"}
    @{" thxFree() " Link "thxFree()"}
    @{" thxGetNumSongs() " Link "thxGetNumSongs()"}
    @{" thxGetSyncByte() " Link "thxGetSyncByte()"}
    @{" thxGetVolume() " Link "thxGetVolume()"}
    @{" thxInit() " Link "thxInit()"}
    @{" thxNoteFX() " Link "thxNoteFX()"}
    @{" thxPause() " Link "thxPause()"}
    @{" thxPlay() " Link "thxPlay()"}
    @{" thxPlayNote() " Link "thxPlayNote()"}
    @{" thxSetSong() " Link "thxSetSong()"}
    @{" thxSetVolume() " Link "thxSetVolume()"}
    @{" thxSignalEnd() " Link "thxSignalEnd()"}
    @{" thxSongEnded() " Link "thxSongEnded()"}
    @{" thxStop() " Link "thxStop()"}
    @{" thxStopNote() " Link "thxStopNote()"}
    @{" thxWind() " Link "thxWind()"}
@EndNode

@Node "--overview--" "thx-play.m/--overview--"

@{b}   PURPOSE@{ub}
       To provide an interface to the THX2 player.

@{b}   OVERVIEW@{ub}
       THX2  is  a  'chip' music tracker by Martin Wodok (Dexter/Abyss). It
       comes with a rather cumbersome binary replayer, so you may play THX2
       songs  in  your  own  programs.  This  module  provides  an easy and
       powerful  interface  to  the  THX2 player, providing a wide range of
       functions.

        - Basic controls:     Init, Free, Play, Stop, Pause, Wind
        - Volume controls:    GetVolume, SetVolume
        - MultiSong controls: GetNumSongs, SetSong
        - Sound FX controls:  PlayNote, StopNote, NoteFX
        - Misc controls:      SignalEnd, SongEnded, SyncByte


       You  need  to read a THX song in from disk or INCBIN it, this is not
       one  of  the functions in thx-play.m. You should load it into PUBLIC
       memory,  it does not have to be CHIP memory. The module 'tools/file'
       is handy for loading files from disk.

       The  music  play  is,  as  you  would  expect, interrupt-driven, and
       asynchronous. This interface automatically provides fallback support
       for a VSYNC interrupt driven replayer if it cannot grab a CIA timer.

       The  interface  is  68000  compatible,  an optimised version for the
       68020 or better is also included as thx-play_020.m

@{b}   EXAMPLE@{ub}
       More thorough examples are included with the distribution.

       MODULE 'tools/thx-play','tools/file'
       PROC main()
         DEF mod
         IF mod:=loadfile(arg, 0, MEMF_PUBLIC)
           IF thxInit(mod)=0
             @{"thxPlay()" Link "thxPlay()"}
             REPEAT; WaitTOF(); UNTIL CtrlC() OR @{"thxSongEnded()" Link "thxSongEnded()"}
             @{"thxStop()" Link "thxStop()"}

             @{"thxFree()" Link "thxFree()"}
           ENDIF
           freefile(mod)
         ENDIF
       ENDPROC


@EndNode

@Node "thxFree()" "thx-play.m/thxFree"

@{b}   NAME@{ub}
       thxFree -- free resources held by player.

@{b}   SYNOPSIS@{ub}
       void thxFree()

@{b}   FUNCTION@{ub}
       Stops any THX module playing and frees resources used by the player.
       You can call this whether @{"thxInit()" Link "thxInit()"} suceeded or not.

@{b}   SEE ALSO@{ub}
       @{"thxInit()" Link "thxInit()"}

@EndNode

@Node "thxGetNumSongs()" "thx-play.m/thxGetNumSongs"

@{b}   NAME@{ub}
       thxGetNumSongs -- get number of subsongs.

@{b}   SYNOPSIS@{ub}
       songs = thxGetNumSongs()

@{b}   FUNCTION@{ub}
       Returns  the  number  of subsongs in the module, if any. You can use
       the  @{"thxSetSong()" Link "thxSetSong()"}  function  to  play one of the subsongs, if that's
       possible.

@{b}   RESULT@{ub}
       songs - 0 if there are no subsongs (only the main song), otherwise
               returns the number of subsongs.

@{b}   SEE ALSO@{ub}
       @{"thxSetSong()" Link "thxSetSong()"}

@EndNode

@Node "thxGetSyncByte()" "thx-play.m/thxGetSyncByte"

@{b}   NAME@{ub}
       thxGetSyncByte -- get sync byte value.

@{b}   SYNOPSIS@{ub}
       value = thxGetSyncByte()

@{b}   FUNCTION@{ub}
       Gets the current setting of the 'external timing' byte, which can be
       set  to any byte value at any moment in time during play of the song
       BY  the  song  itself,  using  the  8  command  in the tracker. This
       function  is  here to allow you to mark specific events in the music
       with   the   8   command  and  a  value,  then  wait  until  calling
       thxSyncByte()  returns that value. The returned value doesn't change
       until another 8 command in the song changes it.

@{b}   NOTE@{ub}
       Be  very  careful  not  to  busy-wait on a new value if there is the
       possibility the song is paused or not playing.

@{b}   RESULT@{ub}
       value - current value of the sync byte.

@EndNode

@Node "thxGetVolume()" "thx-play.m/thxGetVolume"

@{b}   NAME@{ub}
       thxGetVolume -- get master volume.

@{b}   SYNOPSIS@{ub}
       volume = thxGetVolume()

@{b}   FUNCTION@{ub}
       Returns the current master volume value. Does not stop play.

@{b}   RESULT@{ub}
       volume - current volume setting from 0 (silent) to 64 (loudest)

@{b}   SEE ALSO@{ub}
       @{"thxSetVolume()" Link "thxSetVolume()"}

@EndNode

@Node "thxInit()" "thx-play.m/thxInit"

@{b}   NAME@{ub}
       thxInit -- initialise player and module.

@{b}   SYNOPSIS@{ub}
       error = thxInit(moduleptr)

@{b}   FUNCTION@{ub}
       Initialises  the  player (if needed) and initializes the module. You
       may  also  call  thxInit(NIL)  to  initialise the player but not the
       module.  Does not start to play the module until you call @{"thxPlay()" Link "thxPlay()"}.
       You  must  call  this each time you want to play a different module.
       The allocations made for the player are made only the first time you
       call  thxInit(), no matter how many modules you want. If allocations
       fail, they will be automatically freed.

@{b}   INPUTS@{ub}
       module - pointer to a THX module or NIL

@{b}   RESULT@{ub}
       error - 0 means all went OK, any other value means something FAILED.

@{b}   SEE ALSO@{ub}
       @{"thxFree()" Link "thxFree()"}, @{"thxPlay()" Link "thxPlay()"}

@EndNode

@Node "thxNoteFX()" "thx-play.m/thxNoteFX"

@{b}   NAME@{ub}
       thxNoteFX -- perform FX command on user-specified note.

@{b}   SYNOPSIS@{ub}
       void thxNoteFX(command, parameter)

@{b}   FUNCTION@{ub}
       Performs  an effect command on the user-specified note. You can call
       this  at  any  time,  even before you play the note, if you want the
       note  to  start  off  with an initial effect. See THX Sound System's
       documentation for the full list of commands and their parameters.

@{b}   INPUTS@{ub}
       command   - the effect command, eg $C is the Set Volume command.
       parameter - the parameter to the command, eg $40 is full volume.

@{b}   NOTE@{ub}
       No validation of the command or its parameter is done. Beware feeding 
wrong
       or  out of range values. Range for command is $0 to $F, parameter is $
00 to
       $FF.

@{b}   SEE ALSO@{ub}
       @{"thxPlayNote()" Link "thxPlayNote()"}

@EndNode

@Node "thxPause()" "thx-play.m/thxPause"

@{b}   NAME@{ub}
       thxPause -- pause play of a song.

@{b}   SYNOPSIS@{ub}
       void thxPause()

@{b}   FUNCTION@{ub}
       Pauses the playing module. Call @{"thxPlay()" Link "thxPlay()"} to continue play again.

@{b}   SEE ALSO@{ub}
       @{"thxPlay()" Link "thxPlay()"}

@EndNode

@Node "thxPlay()" "thx-play.m/thxPlay"

@{b}   NAME@{ub}
       thxPlay -- start playing the song.

@{b}   SYNOPSIS@{ub}
       void thxPlay()

@{b}   FUNCTION@{ub}
       Starts  playing  the module. If the module has just been initialised
       or  stopped,  or  the  subsong has just been changed, then play will
       start  at  the  beginning  of  the  song/subsong. Otherwise, it will
       continue from where it was paused.

@{b}   SEE ALSO@{ub}
       @{"thxStop()" Link "thxStop()"}, @{"thxPause()" Link "thxPause()"}

@EndNode

@Node "thxPlayNote()" "thx-play.m/thxPlayNote"

@{b}   NAME@{ub}
       thxPlayNote -- start playing a user-specified note.

@{b}   SYNOPSIS@{ub}
       void thxPlayNote(instrument, note, channel)

@{b}   FUNCTION@{ub}
       Plays  one of the instruments in the THX module at a particular note
       on  a particular channel. It is up to you to ensure that the channel
       you  play  the  note  on is empty and so will not interfere with the
       note  being  played.  This function is to allow you to play your own
       notes  during  THX  play,  for  example  as  part of a game as sound
       effects.  The  note  played is subject to the same conditions as the
       song itself, such as the global volume control. In addition, you can
       apply  'FX'  commands to the note. In effect, what is happening when
       you  call  thxPlayNote()  is  that  the  'track data' for the chosen
       channel being played is overwritten (not the module itself, just the
       data  output). It is overwritten on the first line by your specified
       instrument  with  note  and  FX,  then  on  consecutive lines by the
       'blank'  note and instrument. This 'overwriting' stops only when you
       call @{"thxStopNote()" Link "thxStopNote()"}, or stop the module naturaly.

@{b}   INPUTS@{ub}
       instrument - an instrument from the song, from 1-63. You should know
                    which instrument you want to play!
       note       - The halfnote (pitch) at which the instrument is to be
                    played, from 1 (C-1) to 60 (B-5).
       channel    - The channel on which the note is played, from 0 to 3.

@{b}   EXAMPLE@{ub}
       thxPlayNote(12, 8, 2) is equivalent to this in THX Sound System's
       tracker view:

       ---00000 | ---00000 | G-112000 | ---00000
       ---00000 | ---00000 | ---00000 | ---00000
       ---00000 | ---00000 | ---00000 | ---00000
       [...]

@{b}   SEE ALSO@{ub}
       @{"thxStopNote()" Link "thxStopNote()"}, @{"thxNoteFX()" Link "thxNoteFX()"}

@EndNode

@Node "thxSetSong()" "thx-play.m/thxSetSong"

@{b}   NAME@{ub}
       thxSetSong -- set song to be played.

@{b}   SYNOPSIS@{ub}
       thxSetSong(song)

@{b}   FUNCTION@{ub}
       Sets  which  song  to play, if a module contains more than one song.
       Most  modules  only  contain  one  song,  but  some  modules contain
       sub-songs  as  well  as  the  main one. You can use this function to
       specify  which  one  should be played. If you call this function and
       there is already a song playing, it will be stopped first.

@{b}   INPUTS@{ub}
       song - 0 to set the main song to be played, any other number will
              change to that subsong, if it exists. Otherwise, no change
              will be made (other than the stoppage).

@{b}   NOTE@{ub}
       It is up to you to start playing the module again.

@{b}   SEE ALSO@{ub}
       @{"thxGetNumSongs()" Link "thxGetNumSongs()"}

@EndNode

@Node "thxSetVolume()" "thx-play.m/thxSetVolume"

@{b}   NAME@{ub}
       thxSetVolume -- set master volume.

@{b}   SYNOPSIS@{ub}
       void thxSetVolume(volume)

@{b}   FUNCTION@{ub}
       Sets the master volume. Does not stop play.

@{b}   INPUTS@{ub}
       volume - from 0 (silent) to 64 (loudest)

@{b}   NOTE@{ub}
       This  function  can take up to two frames to take an audible effect.
       If the song is paused, will not take effect until unpaused.

@{b}   SEE ALSO@{ub}
       @{"thxGetVolume()" Link "thxGetVolume()"}

@EndNode

@Node "thxSignalEnd()" "thx-play.m/thxSignalEnd"

@{b}   NAME@{ub}
       thxSignalEnd -- Signal() when song ends.

@{b}   SYNOPSIS@{ub}
       void thxSignalEnd(signals)

@{b}   FUNCTION@{ub}
       Asks  THX  to send the signals you specify back to you when the song
       ends.  If songend occurs and the signal is sent, it will not be sent
       again  unless  you  call thxSignalEnd() again to reload the trigger.
       The signal will also be cancelled if you call @{"thxStop()" Link "thxStop()"} directly, or
       indirectly  through  @{"thxSetSong()" Link "thxSetSong()"}  or  @{"thxFree()" Link "thxFree()"}.  You may call this
       function  at  any  time, even when the player is not initialised, or
       while  a  song  is  playing. The task you call it from is stored, so
       don't  call  it  from asynchronous threads that may disappear before
       songend is reached.

@{b}   NOTE@{ub}
       The detection of songend is crap (sorry Dexter :^)

@{b}   INPUTS@{ub}
       signals - a 32bit set of signals, to be sent back to calling task
                 when songend occurs.

@{b}   EXAMPLE@{ub}
       thxSignalEnd(SIGBREAKF_CTRL_C)  will send you a CTRL-C when the song
       ends.

@{b}   SEE ALSO@{ub}
       @{"thxSongEnded()" Link "thxSongEnded()"}, exec.library/Signal()

@EndNode

@Node "thxSongEnded()" "thx-play.m/thxSongEnded"

@{b}   NAME@{ub}
       thxSongEnded -- detect if song has ended.

@{b}   SYNOPSIS@{ub}
       ended = thxSongEnded()

@{b}   FUNCTION@{ub}
       Returns  nonzero  value if the player has detected the end of a song
       and is now looping.

@{b}   NOTE@{ub}
       The detection of songend is crap (sorry Dexter :^)

@{b}   RESULT@{ub}
       value - nonzero if song is now looping, zero otherwise.

@{b}   SEE ALSO@{ub}
       @{"thxSignalEnd()" Link "thxSignalEnd()"}

@EndNode

@Node "thxStop()" "thx-play.m/thxStop"

@{b}   NAME@{ub}
       thxStop -- stop playing a song/module.

@{b}   SYNOPSIS@{ub}
       void thxStop()

@{b}   FUNCTION@{ub}
       Stops  the  module.  Can  be restarted from the beginning again with
       @{"thxPlay()" Link "thxPlay()"}.  If  you  call this, you can free the memory used by your
       thx module without calling @{"thxFree()" Link "thxFree()"} which has the unpleasant effect
       of  requiring  to  recalculate all the filters if you call @{"thxInit()" Link "thxInit()"}
       again.

@{b}   SEE ALSO@{ub}
       @{"thxPlay()" Link "thxPlay()"}, @{"thxFree()" Link "thxFree()"}

@EndNode

@Node "thxStopNote()" "thx-play.m/thxStopNote"

@{b}   NAME@{ub}
       thxStopNote -- stop playing user-specified note.

@{b}   SYNOPSIS@{ub}
       void thxStopNote()

@{b}   FUNCTION@{ub}
       Stops  anything you started with @{"thxPlayNote()" Link "thxPlayNote()"}. Please be aware that
       notes  which  don't  fade  away  on  their own will first need to be
       silenced with thxNoteFX($C, $00), or such

@{b}   SEE ALSO@{ub}
       @{"thxPlayNote()" Link "thxPlayNote()"}

@EndNode

@Node "thxWind()" "thx-play.m/thxWind"

@{b}   NAME@{ub}
       thxWind -- wind the song forward or back.

@{b}   SYNOPSIS@{ub}
       void thxWind(direction)

@{b}   FUNCTION@{ub}
       Advances forward or backwards through the song by a specified number
       of  positions. Please use the value 1 to skip forward and -1 to skip
       back, for future compatibility.

@{b}   INPUTS@{ub}
       direction - if positive, winds on to the next position.
                   if negative, winds back to the previous position,
                   if 0, ignored.

@{b}   NOTE@{ub}
       Be  wary  of  stepping  beyond  the  end  of  a song. Also note this
       function only takes effect only once a frame.

@EndNode

