Decoder plug-ins must implement and export the functions defined in decode_plug.h.
There are two interface revision levels.
For developing new plug-ins the revision 2 interface is recommended.
Before including any PM123 include file the macro DECODER_PLUGIN_LEVEL
must be defined
if you want to use anything higher than level 0. Example:
#define DECODE_PLUGIN_LEVEL 2
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 )
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_PARAMS2 *params )
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.
In the level 2 interface the data source always passed as an URL. The URL parameter uses the following syntax:
file:///D:/Music/my favorite song.mp3
file://server/share/path/song.mp3 UNC path
http://... (as you would expect)
cdda:///H:/track02
The status interface has to be thread safe.
ULONG DLLENTRY decoder_status( void *w )
ULONG DLLENTRY decoder_length( void *w )
(ULONG)-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).
The info interface functions must be independent of the current decoder status. They should always be functionnaly and give consistent results in any conditions. The functions must be thread safe.
ULONG DLLENTRY decoder_fileinfo( const char *url, int* what, DECODER_INFO2 *info )
If a decoder knows that some information, that is not explicitely requested, is not available for the current URL or it knows it's content during processing of the request, it should always set the corresponding bit in *what and return the information if applicable. This avoids redundant calls to decoder_fileinfo.
Bit in *what on input Bit in *what on return Corresponding info available Corresponding fields in DECODER_INFO2 reset reset don't care ignored set reset don't care not allowed! don't care set no unmodified don't care set yes filled with valid content
ULONG DLLENTRY decoder_saveinfo( char* url, const META_INFO* info, int haveinfo )
It is called if it is necessary to change the meta information for the specified file and the decoder supports this feature. Exporting this function is optional. A decoder may override the meta editor by exporting decoder_editmeta.
ULONG DLLENTRY decoder_cdinfo( const char *drive, DECODER_CDINFO *info )
This function is unused by PM123 since version 1.40 but it might still be invoked by visual plug-ins.
You need not to export this function unless decoder_support
returns the DECODER_TRACK flag.
ULONG DLLENTRY decoder_support( const char** fileext, const char** filetype )
decode_saveinfo
.This is used by PM123 to suggest to the user what he can play with the decoder. Furthermore PM123 will normally not query the decoder about files or other objects that are not supported.
The function is called again after a successful call to plugin_configure. This allows to modify the supported file types through the configuration.
The following functions are used to improove the GUI of PM123 with plug-in specific content.
All functions in this section are optional.
ULONG DLLENTRY decoder_editmeta( HWND owner, const char* url )
If decoder_editmeta
is not implemented, the edit tag entry is disabled.
const DECODER_WIZZARD* DLLENTRY decoder_getwizzard( )
DECODER_WIZZARD
structures (linked list).DECODER_WIZZARD
objects set the link pointer to NULL
.
The returned storage must be valid until the next call to decoder_getwizzard
or the plug-in gets unloaded.
If the function is not implemented or returns NULL
the context menu is not extended with entries specific to this plug-in.
The field prompt
is the menu text. It should not contain information about the accelerator key,
because this is generated automatically.
The fields accel_key
[2
] and accel_opt
[2
] can be used to extend the accelerator table of PM123.
They correspond to the fields key
and fs
of the ACCEL
structure.
The first set of entries is used for the PM123 main window and the playlist windows.
The second set is for the Playlist Manager to append to the currently selected playlist.
You should set accel_key
to 0
if you do not want an accelerator key
for your plug-in's wizzard dialog.
Be careful with the choice of the accelerator keys because there may be clashes.
Using Alt and Shift-Alt as meta keys is recommended.
When the menu entry is selected the corresponding wizzard function is called by PM123.
ULONG (DLLENTRYP wizzard)( HWND owner, const char* title, void (DLLENTRYP callback)( void* param, const char* url ), void* param );
The decoder must use this interface to pass the decoded samples to the output stage. The samples must be passed as 16 bit signed integers.
The function entry points for these callbacks are passed in DECODER_PARAMS2
at the DECODER_SETUP call.
The interface functions have to be called by the decoder in a separate thread.
The level 2 interface allocates the buffers by the consumer. This causes less double buffering and allows dynamic buffer sizes.
You must call output_request_buffer
and output_commit_buffer
alternatingly to pass the samples to the next plug-in. Anything else is an error.
int (DLLENTRYP output_request_buffer)( void* a, const FORMAT_INFO2* format, short** buf )
DECODER_PARAMS2
.
FORMAT_INFO2
in format.h for more details.
The data at *format
need not to be valid after this call returned.
If you get a smaller buffer as you need to pass your data you should call output_request_buffer
and output_commit_buffer
again untill all your data is consumed.
There is no guaranteed minimum size of the buffer. You should not expect this to get very small buffers quite often.
void (DLLENTRYP output_commit_buffer)( void* a, int len, double posmarker )
DECODER_PARAMS2
.
The length must not be higher than the the return value from the previous output_request_buffer
call.
But it might be less than the requested length.
This causes no significant performance impact as long as you do not always pass very few samples.
void (DLLENTRYP output_event)( void* a, DECEVENTTYPE event, void* param )
DECODER_PARAMS2
.
The decoder plug-in MUST call the above function on the following conditions:
DECEVENT_PLAYSTOP
when the stream has finished decoding and the last sample has been passed to output_commit_buffer
.
DECEVENT_PLAYERROR
when a playback error occured so that PM123 should know to stop immediately.
DECEVENT_SEEKSTOP
when a DECODER_JUMPTO
operation is completed (ie.: when no buffers from before the seek is sent to the output plugin anymore).
DECEVENT_CHANGTECH
is sent whenever you want PM123 to change the display of the current technical information of stream (like bitrate).
param must point to a TECH_INFO
structure.
DECEVENT_METADATA
is sent whenever streaming metadata is updated.
param must point to a META_INFO
structure.
void DLLENTRY decoder_event( void* w, OUTEVENTTYPE event );
decoder_init
OUTEVENT_LOW_WATER
- the ouput plug-in detected that it will run out of data soon.OUTEVENT_HIGH_WATER
- the ouput plug-in detected a clear condition.
The events may be used to speed up the data source e.g. by manipulating the decoder thread's priority.
If you get OUTEVENT_HIGH_WATER
you sholud return to normal behaviour.
The event handler may be called from any thread in any context. It might be called when the decoder is in stopped state if the end of the stream has been reached recently. This should be ignored.
You will usually get a OUTEVENT_LOW_WATER
call immiediately after the decoding started
or after a seek command because the buffers are not yet filled.
See level 2 initialization interface. This part of the interface has not been changed.
ULONG DLLENTRY decoder_command( void *w, ULONG msg, DECODER_PARAMS *params )
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:
Streaming metadata currently is for SHOUTcast (and icecast is using the same method), so it is a string with the following format:
Only StreamingTitle is used by PM123.StreamingTitle='blah blah';StreamingURL='more useless information';
See level 2 status interface. This part of the interface has not been changed.
The info interface functions must be independent of the current decoder status. They should always be functionnaly and give consistent results in any conditions. The functions must be thread-safe.
ULONG DLLENTRY decoder_fileinfo( const char *url, DECODER_INFO *info )
ULONG DLLENTRY decoder_saveinfo( char* url, const DECODER_INFO* info )
It is called if it is necessary to change the meta information for
the specified file and the decoder supports this feature.
Exporting this function is optional. See decoder_support
.
ULONG DLLENTRY decoder_trackinfo( const char *drive, int track, DECODER_INFO *info )
ULONG DLLENTRY decoder_cdinfo( char *drive, DECODER_CDINFO *info )
This function is unused by PM123 since version 1.40 but it might still be invoked by visual plug-ins.
You need not to export the CD related functions unless decoder_support
returns the DECODER_TRACK flag.
ULONG DLLENTRY decoder_support( char *fileext[], int *size )
decode_saveinfo
.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".
See level 2 GUI enhancement interface. This part of the interface is new with PM123 1.40, but since all of the functions are optional it is compatible anyway.
The decoder must use this interface to pass the decoded samples to the output stage.
The function entry points for these callbacks are passed in DECODER_PARAMS
at the DECODER_SETUP call.
The interface functions have to be called by the decoder in a separate thread.
int (DLLENTRYPP output_play_samples)( void* a, const FORMAT_INFO* format, const char* buf, int len, int posmarker )
DECODER_PARAMS
.
FORMAT_INFO
in format.h for more details.
The data at *format
need not to be valid after this call returned.
The decoder should pass the decoded samples to this function. The decoder shold pass a bunch of samples at once unless the end of the data is reached to keep the performance reasonable.