Questions on writing my first plugin (2 Viewers)

huha

Extension Developer
January 3, 2008
890
556
Home Country
Germany Germany
Update: The language files are not working for the summer release

I started to write my first plugin and got excited about MP2.

As I had no idea about xaml or MP2 before, I am documenting some steps in learning which may be helpful for others, too.

The following steps describe some basic examples for MP2 and give simple code examples.
The plugin has no real meaning besides demonstrating and testing basic functions in MP2

Before you continue you should have understood the function of the "Hallo World Plugin".
Don´t get frustrated if you did not understand the WIKI MP2 documentation. Many things became more clear after i was going through the following steps.


**************************************************************
Step1: (Closed, source code attached)
**************************************************************
-the plugin MyTestPlugin has a dependency on the Configuration Manager Plugin in plugin.xml

-example for a push navigation button from the MyTestPlugin to the HelloWorldplugin in workflow\MyTestPlugin.xml

-example for a push navigation button from the HelloWorldplugin to the MyTestPlugin in workflow\MyTestPlugin.xml

-example for a function button FunctionButton in workflow\MyTestPlugin.xml

-example for generating a "push" workflow transition (from the MyTestPlugin to the HelloWorldplugin) in the model code triggered by the Push button

-example for generating a "pop" workflow transition (from the MyTestPlugin to the previous screen) in the model code triggered by the Pop button

-example for a button "Press me" toggling a label in the skin

-example for tracing the workflow states using the IWorkFlowModel functions

-example for logging

-cleanup on naming convention


**************************************************************
Step2: (closed, source attached)
**************************************************************
- cleanup on naming convention

- adding config settings to the plugin (string, integer, bool) in the configuration folder. Loadsettings example in the model MyTestPlugin.cs.

- example for messaging when a configuration setting did change(send in the configuration if a string changes its value and receive in the model MyTestPlugin.cs)

- assigning keys/ IR commands to functions in the skin MyTestPlugin.xaml
pressing F1 button (or whatever you configured for MyButton_Key in the configuration) will call the function ChangeHelloWorldString.

- assigning keys/ IR commands to functions in the model MyTestPlugin.cs (Pause key) using the IInputManager which will call the function MyFunctionButton in the model MyTestPlugin.cs


**************************************************************
Step3: (closed, source attached)
**************************************************************
- adding another child skin (MyTestPluginScreen2.xaml and its model MyTestPluginScreen2.cs)

- transition from parent to child and revers (new workflow in workflow\MyTestPlugin.xml)

- listview menu processing (MyTestPluginScreen2.xaml and its model MyTestPluginScreen2.cs)
(The defaultstyle refers to a key "Name" !) the number of listview menu items is determined by the integer in the configuration settings.

- creating an information dialog and watch its closing in the model MyTestPlugin.cs

- creating a dialog menu in the model MyTestPlugin.cs with a derived skin SimpleDialogMenu.xaml

- creating a input textbox dialog which can use the virtual keyboard in the model MyTestPlugin.cs with a skin SimpleDialogTextBoxInput.xaml


**************************************************************
Step4: (closed, source attached)
**************************************************************
- Important: You need to change to the MP2 Easter Build version (only working for default skin)
- Important: You need to have MPExtended to be installed (not working for TV4Home!)

- the Screen2 now implements a gui dialog where the user is asked to select a tv group. Then all channels of the selected Tv group will be displayed in the listitem on screen2. For this the SlimTvInterface was used with its implemented functions from Morpheus. Just register the global _tvHandler in the constructor and use the _tvhandler functions to get an IList of all groups

_tvHandler.ChannelAndGroupInfo.GetChannelGroups(out mygroups)
SimpleMenuDialogScreen2() implements a menu dialog, where the user can select the tv group derived from the dialog in Step3.

-The channel names are obtained in a similar way in InitListItems(). They are displayed as listitems in the skin.
In a similar way schedules and programs can be handled. Look at the SlimTvInterfaces from morpheus_xx

- As there was no definition for TV database settings in SlimTvInterfaces i have created an own class derived from the SlimTvMPExtended class to connect to the Tvserver and read/write data base settings. That´s why step4 needs MPExtended only.
In MyTestPluginMPExtendedProvider.cs the functions

GetConnectedServers(out List<ServerName> serverNames)
ReadSetting(int serverId, string tagName, string defaultValue, out Setting setting)
WriteSetting(int serverId, string tagName, string value)

have been defined in addition to reusing the functions for connecting to the Tvserver from the original code of morpheus_xx. This may become void in the future if morpheus_xx implements the settings in SlimTvInterfaces. As MPExtended supports multiple tv servers the function GetConnectedServers lists all defined and connected tv servers.

-The testplugin uses this class in the main screen and reads a tvserver database setting within the function OnPageLoad and displays the setting "postRecordInterval" whenever the main screen is entered.
The menu dialog is used to select different numbers and write back this setting with the selected value to the tv server database in the function MenuItemSelected(ListItem myitem).

**************************************************************
Step5: (closed, source attached)
**************************************************************
Step 5 gives an example for a process plugin, which will open a dialog box if the workflow changes. It consists of the derived classes
BaseMessageControlledModel, IPluginStateTracker
In contrast to a workflowmodel it will be activated at the beginning and is ideal for implementing a process plugin. This plugin just listens for new messages and opens a dialog box if a new message has been received. Trace the log file to see the actual states from the PluginStateTracker. Check the plugin.xml file to see how the plugin is registered.


I have posted the updated code in the zip file.

Update 6/17/2012:
- updated all the source code and removed a few minor bugs
- removed dependency on TV plugin, as it caused an issue for other skins
 

Attachments

  • Step1.jpg
    Step1.jpg
    141 KB
  • Step2.jpg
    Step2.jpg
    155.6 KB
  • Step3.jpg
    Step3.jpg
    252.6 KB
  • Step4.JPG
    Step4.JPG
    68 KB
  • MP2 MyTestPlugin.zip
    6.2 MB
Last edited:

morpheus_xx

Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    I've checked your plugin. The text is not updated after button click, because you are missing a Property.

    If you add
    Code:
      public AbstractProperty FunctionButtonLabelProperty
        {
            get { return _functionButtonProperty; }
        }
    to code it works.

    Background is the databinding: FunctionButtonLabel exposes the string, the skin engine's databinding always tries to attach to FunctionButtonLabelProperty, so that it is able to react on property change events.

    If you want to make debugging easier, add this commands to the project "post build actions":
    Code:
    xcopy /Y "$(ProjectDir)plugin.xml" "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\"
    mkdir "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\Language"
    robocopy "$(ProjectDir)Language" "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\Language" /MIR /NP
    mkdir "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\Skin"
    robocopy "$(ProjectDir)Skin" "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\Skin" /MIR /NP
    xcopy /Y "$(TargetDir)$(ProjectName).dll"  "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\"
    , add the project to the MP2-Client solution.This way the required plugin files are copied to MP2-Client plugins on build.

    Then you can debug directly inside VS2010.
     

    huha

    Extension Developer
    January 3, 2008
    890
    556
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #3
    morpheus_xx,
    thanks a lot for your help. I defined a property FunctionButtonProperty instead of FunctionButtonLabelProperty.
    I will try your script code. I think I got now a first understanding of the workflowtransitions.
     

    huha

    Extension Developer
    January 3, 2008
    890
    556
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #4
    I found another bug in my example. I did not derive the class from IWorkflowModel, IDisposable
    and i did not specify the workflowmodel in plugin.xml, so the IWorkflowModel implementation did not work.

    I have updated in the first post the plugin with all issues corrected.
     

    huha

    Extension Developer
    January 3, 2008
    890
    556
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #5
    I made some more progress on my first plugin and have documented the steps in my first posting. I got the config settings working and an example for messaging. The later one gave me some headache on transferring a string from a static function to the skin.

    I will be out the next 2 weeks and continue afterwards.

    If someone knows how to attach keys or IR commands to buttons please post.
     

    Albert

    MP2 Developer
  • Premium Supporter
  • February 18, 2008
    1,297
    1,130
    45
    Freiburg im Breisgau, Germany
    Home Country
    Germany Germany
    If someone knows how to attach keys or IR commands to buttons please post.

    Internally, IR commands are mapped to keys before they are sent through the system.
    To map commands to actions, there are several ways:
    • You can add a key mapping for a screen. To do that, there are two ways:
      • Use the KeyBinding XAML element. That control adds an "invisible" key handler which simply executes a command when the configured key is pressed.
      • Use the KeyBindingControl XAML element.
    • You can add a global key mapping using the SkinEngine's input manager. In method SkinEnginePlugin.RegisterGlobalKeyBindings(), you can see how such global key bindings are used. Please note that global key bindings must be unregistered when your plugin is unloaded, as any other resource which is aquired by a plugin.
     

    huha

    Extension Developer
    January 3, 2008
    890
    556
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #7
    Albert, thanks for your help here! I got it. I updated Step2 in the first post. I am also making progress on step 3.
    I am starting to understand slowly what great new opportunities MP2 will give for the plugins and skins.
     

    Quarter

    MP Donator
  • Premium Supporter
  • June 21, 2010
    722
    138
    Queenstown
    Home Country
    New Zealand New Zealand
    Its going to be a very long time (if ever) before I understand mp2 enough to start writing a plugin. I think I will have to stick to mp1. Maybe someone can create a plugin builder to handle all the xmal files. C# I can handle. :(
     

    huha

    Extension Developer
    January 3, 2008
    890
    556
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #9
    After having spent hours without success on the listitem I need to ask for help again:

    I have defined a skin MyTestPluginScreen2.xaml with a listitem in a dockpanel:

    <ListView Name="TestListView" DockPanel.Dock="Center" Height="300" Width="600" ItemsSource="{Binding MyListViewItems}" SelectionChanged="{CommandStencil FocusedItemChanged}"/>

    In the corresponding model MyTestPluginScreen2.cs i have defined:


    private ItemsList _testlist = null;

    public ItemsList MyListViewItems
    {
    get { return _testlist; }
    }




    public void InitListItems()
    {
    //load settings
    MyTestPluginSettings settings = ServiceRegistration.Get<ISettingsManager>().Load<MyTestPluginSettings>();

    //define all items for ListView in skin and use MySetting_Int for number of items to create
    _testlist = new ItemsList();
    for (int i = 0; i < settings.MySetting_Int; i++)
    {
    ListItem myitem = new ListItem();
    string myitemstring = LocalizationHelper.Translate(ITEM_RESOURCE, i);
    myitem.SetLabel("Item",myitemstring);
    mylogger.Debug("Adding item="+myitemstring);
    //this command will be executed after selection
    myitem.Command = new MethodDelegateCommand(() => SelectedItemChanged(i));
    _testlist.Add(myitem);
    }

    //update skin
    MyListViewItems.FireChange();
    }


    I believe i do not have to define any properties, as this is done in the ListItem class.
    I see in the log files that list items are created, but no list item is shown on the screen and i have no idea why.

    I have included the complete code Step3 in a zip file
     

    Attachments

    • Step3.zip
      1.1 MB

    Albert

    MP2 Developer
  • Premium Supporter
  • February 18, 2008
    1,297
    1,130
    45
    Freiburg im Breisgau, Germany
    Home Country
    Germany Germany
    I think the problem is that you don't define a Style attribute on your ListView, so the default style is used. The default ListView style (DefaultListViewStyle) uses the DefaultItemDataTemplate for presenting the items, which uses the Name label as presentation string. That label is not set by your initialization code...
     

    Users who are viewing this thread

    Top Bottom