# PM123 Decoder Plug-ins

Decoder plug-ins must implement and export the functions defined in decoder_plug.h.

         int  DLLENTRY decoder_init  ( void **w )
         BOOL DLLENTRY decoder_uninit( void *w  )

- w : Allocate any chunk of memory necessary for the decoder's function. This pointer will be passed to the other functions.
- return value : PLUGIN_FAILED (-1) means the decoder was not initialized successfully.

Init function is called when PM123 needs the specified decoder to play the stream demanded by the user. So only one decoder plug-in is active at any given time. It should initialize the necessary semaphores and threads. decoder_uninit is called when another decoder than yours is needed, and should destroy the decoder's thread, semaphores, other opened handles and free allocated memory for w.

         ULONG DLLENTRY decoder_command( void *w, ULONG msg, DECODER_PARAMS *params )

- msg: one of the following:
  - DECODER_PLAY start playing the given filename, URL or others.
  - DECODER_STOP stop playing.
  - DECODER_FFWD engage in ffwd mode (ie.: play faster or skip when playing).
  - DECODER_REW engage rewind mode.
  - DECODER_JUMPTO jump and start decoding at the given time position.
  - DECODER_SETUP setup various parameters such as the output plugin functions, hwnd where to send messages and an optional play semaphore.
  - DECODER_SAVEDATA tells the decoder to start saving the stream to HD.
- params: structure that contains the parameters needed by the preceding commands.
- return value:
  PLUGIN_OK (0) -> ok.
  PLUGIN_UNSUPPORTED (1) -> command unsupported.
  DECODER_PLAY and DECODER_STOP can return also PLUGIN_GO_ALREADY (101) and PLUGIN_GO_FAILED (102).

There is a lot of commands to implement for this function. Parameters needed for each of the are described in the definition of the structure in the decoder_plug.h file. The decoder necessarily should support following commands: DECODER_SETUP, DECODER_PLAY, DECODER_STOP and DECODER_JUMPTO.

The decoder plug-in MUST WinPostMsg() the following messages to hwnd:

- WM_PLAYSTOP when the stream has finished decoding.
- WM_PLAYERROR when a playback error occured so that PM123 should know to stop immediately.
- WM_SEEKSTOP when a JUMPTO operation is completed (ie.: when no buffers from before the seek is sent to the output plugin anymore).
- WM_CHANGEBR is sent whenever you want PM123 to change the display of the current bitrate. mp1 = current bitrate in kbit/s.
- WM_METADATA is sent whenever streaming metadata is updated and contains the pointer to the streaming metadata in mp1. This pointer should be the same one that is passed with DECODER_SETUP because it is garanteed to be available to PM123 without memory leaking.

Streaming metadata currently is for SHOUTcast (and icecast is using the same method), so it is a string with the following format:

         StreamingTitle='blah blah';StreamingURL='more useless information';

Only StreamingTitle is used by PM123.

         ULONG DLLENTRY decoder_status( void *w )

- return value - One of the following:
  DECODER_STOPPED
  DECODER_PLAYING
  DECODER_STARTING
  DECODER_PAUSED

         ULONG DLLENTRY decoder_length( void *w )

- return value - number of milliseconds the stream lasts (you can report -1 if unknown).

The call to this function must be valid even if DECODER_STARTING or DECODER_STOPPED is reported (when the stream plays too fast for example).

         ULONG DLLENTRY decoder_fileinfo ( char *filename, DECODER_INFO *info )
         ULONG DLLENTRY decoder_trackinfo( char *drive, int track, DECODER_INFO *info )

- filename : full path or URL to the desired stream.
- drive : ie.: "X:"
- track : CD tracks start from 1.
- info : this structure must be filled with the required information.
- return value:
  PLUGIN_OK (0) = everything's perfect, structure is set.
  PLUGIN_NO_READ (100) = error reading file (too small?).
  PLUGIN_NO_PLAY (200) = decoder can't play that.
  other values = errno.

decoder_fileinfo and decoder_trackinfo (for CD decoders) must be independant from the current status of the decoder. It should always be functionnaly and give consistent results in any conditions.

         ULONG DLLENTRY decoder_cdinfo( char *drive, DECODER_CDINFO *info )

- drive: ...
- info: required info on the number of tracks available from the decoder.
- return value:
  PLUGIN_OK (0) = everything's perfect, structure is set.
  PLUGIN_NO_READ (100) = error reading required info.
  other values = errno.

This is used by PM123 before calling decoder_trackinfo.

        ULONG DLLENTRY decoder_saveinfo( char* filename, DECODER_INFO* info );

- return value:
  PLUGIN_OK (0) = everything's perfect, meta info is saved to filename.
  other values = errno.

It is called if it is necessary to change the meta information for the specified file and the decoder supports this feature. See decoder_support.

        ULONG DLLENTRY decoder_support( char *fileext[], int *size )

- fileext: fill this array with all the wildcard expression matching filenames this decoder can play (each element is a 8 bytes char array).
- size: number of wildcard expressions returned (if this value is not big enough, ie.: 0, return the appropriate size without filling fileext).
- return value: return what kind of stream can the decoder play:
  DECODER_FILENAME
  DECODER_URL
  DECODER_TRACK
  DECODER_OTHER
  and what features are supported by the decoder:
  DECODER_METAINFO

This is used by PM123 to suggest to the user what he can play with the decoder and what features are supported. Extentions can be for example "*.MOD".