The Plugin runs on the core. The Player runs on each participating media director.
The Plugin's job, is to interface with the Media Plugin, and provide a specific stream type to the Media Plugin, a stream in this case, is mainly a media handler object specifying what type of media this is, where it is going to, and any information needed by the Player to be able to play the resulting media.
The Plugin's job is divided into several main functions:
* Register - to map the relationship between the plugins, and the players they ultimately take care of. This is cross referenced against the DeviceTemplate_MediaType table, and the Devices mapped into entertainment areas to determine whether an entertainment area has a player capable of playing a media stream specified by the Media Plugin.
* CreateStream - this function literally creates a subclass of MediaStream to handle your custom media type. The whole thing here is to determine which players in an entertainment area can take care of a device, fill out the MediaDevice entries for them, and include that in a custom MediaStream subclass, that is ultimately passed back to the Media Plugin.
* StartMedia - This function literally takes the information passed in from the Media Plugin, as it has processed the information it got back from CreateMediaStream to find destinations etc, to find all of the media player devices that match, and to send them a CMD_Play_Media for the target media. If a bookmarked position is passed in, here, it is also handled here as well, as well as if there are special considerations, such as starting media on "chapter boundaries" etc.
* StopMedia - This does the inverse of the StopMedia function, and sends a CMD_Stop_Media() to the resulting players, so that the media can be stopped as needed.
There is also the custom MediaStream subclass, which specifies any changes to MediaStream that need to happen, the most important being does it ContainsVideo, ContainsAudio, etc...so that the media plugin can only turn on the video pipes if it needs to, etc. The various Set Now Playing bits are also defined in the media stream subclass, as well.
The Player, on the other hand, runs on the media director, and literally provides the one to one mapping of commands that directly affect that player's operation. Play, Stop, Fast Forward, Rewind, Move up, Move Down, Left, Right, etc... Each of these commands get forwarded to the media plugin, which forwards them to the player's media plugin, which forwards them to the appropriate media player device, automatically (this is what the Register() method ultimately sets the stage for), so that we don't have to make a play button for each and every single media player type on the planet.
The only other aspect not mentioned here is streaming to multiple destinations. To LinuxMCE, streaming to multiple destination is simply passing a given URL, and a list of destination player devices, to the media plugin, which the media player plugin ultimately converts into a CMD_Start_Streaming command, at which point it is up to the plugin to determine how best to coordinate the effort between the different target devices, and send the appropriate playback commands to the players to accomplish the desired tasks.
One thing that DCE device skeletons provide, is an implementation stub for each and every single function. You can see the output of these on the console, as you run your device. Watch the output of these, as you do commands, to see the sequence of commands and what happens. The DCE Router log is also helpful in this regard.
The architecture is like this, in order to provide an exceptionally flexible method of sending media to different target devices. the Media Plugin simply deals with media types, and destination, and it asks each registered plugin for a media type to handle its requisite player devices independently. This allows for playback of a type of media on a wide range of heterogeneous devices, all at the same time, and to be able to arbitrarily move between these different devices.