Registering a new Aspect from a Plugin failing

Discussion in 'Plugin Development' started by McGoober, November 20, 2012.

  1. McGoober
    • Team MediaPortal

    McGoober Retired Team Member

    Joined:
    August 13, 2006
    Messages:
    122
    Likes Received:
    103
    Gender:
    Male
    Occupation:
    Staff Software Developement Engineer
    Location:
    Cambridge, UK
    Ratings:
    +105 / 0
    Home Country:
    United Kingdom United Kingdom
    Sanity check here... I must be missing something.

    Ok, so I have a plugin which needs to register a new aspect so I can store extra data about media items. So I create the new aspect and go to register it. However when I do (I'm doing this from IPluginStateTracker.Activated()) I get an exception in the core.

    Code (Text):
    1. System.NullReferenceException: Object reference not set to an instance of an object.
    2.   at MediaPortal.Backend.Services.MediaLibrary.MediaLibrary.AddMediaItemAspectStorage(MediaItemAspectMetadata miam) in E:\users\jason leonard\work\mediaportal-2\MediaPortal\Source\Core\MediaPortal.Backend\Services\MediaLibrary\MediaLibrary.cs:line 956
    3.   at MediaPortal.Backend.Services.MediaManagement.MediaItemAspectTypeRegistration.RegisterLocallyKnownMediaItemAspectType(MediaItemAspectMetadata miam) in E:\users\jason leonard\work\mediaportal-2\MediaPortal\Source\Core\MediaPortal.Backend\Services\MediaManagement\MediaItemAspectTypeRegistration.cs:line 51
    4.   at MediaPortal.Extensions.MediaServer.MediaServerPlugin.Activated(PluginRuntime pluginRuntime)
    5.   at MediaPortal.Common.Services.PluginManager.PluginManager.TryActivate(PluginRuntime plugin) in E:\users\jason leonard\work\mediaportal-2\MediaPortal\Source\Core\MediaPortal.Common\Services\PluginManager\PluginManager.cs:line 930
    6.  
    Apparently the MediaLibrary service hasn't been started yet, and therefore fails to register the aspect.
    So the question is.. when do I get a call from the IPluginStateTracker that I can use to register the aspect?


     
  2. Google AdSense Guest Advertisement



    to hide all adverts.
  3. chefkoch
    • Team MediaPortal

    chefkoch Retired Team Member

    Joined:
    October 5, 2004
    Messages:
    3,130
    Likes Received:
    1,456
    Gender:
    Male
    Location:
    Dresden / Munich / Maastricht
    Ratings:
    +1,773 / 1
    Home Country:
    Germany Germany
    Not sure as I did not developed a plugin on my own. Might it be needed to do the registration within the plugin.xml declaration?
     
  4. McGoober
    • Team MediaPortal

    McGoober Retired Team Member

    Joined:
    August 13, 2006
    Messages:
    122
    Likes Received:
    103
    Gender:
    Male
    Occupation:
    Staff Software Developement Engineer
    Location:
    Cambridge, UK
    Ratings:
    +105 / 0
    Home Country:
    United Kingdom United Kingdom
    Yeah, I was wondering if something like that was needed...
    Here is my metadata extractor element...
    Code (Text):
    1. <Register Location="/Media/MetadataExtractors">
    Does anyone know the magic incarnation for the Location field I would need for this?
     
  5. chefkoch
    • Team MediaPortal

    chefkoch Retired Team Member

    Joined:
    October 5, 2004
    Messages:
    3,130
    Likes Received:
    1,456
    Gender:
    Male
    Location:
    Dresden / Munich / Maastricht
    Ratings:
    +1,773 / 1
    Home Country:
    Germany Germany
  6. McGoober
    • Team MediaPortal

    McGoober Retired Team Member

    Joined:
    August 13, 2006
    Messages:
    122
    Likes Received:
    103
    Gender:
    Male
    Occupation:
    Staff Software Developement Engineer
    Location:
    Cambridge, UK
    Ratings:
    +105 / 0
    Home Country:
    United Kingdom United Kingdom
    I've found another way of doing it, but doesn't seem like the right thing to do.
    I've registered for events from the IMessageBroker, and I watch for the state "Running". This solves the problem but creates a race condition between the UPNP device starting and my aspect/resourcemodule registering.
     
  7. MJGraf
    • Team MediaPortal

    MJGraf Retired Team Member

    Joined:
    January 13, 2006
    Messages:
    2,475
    Likes Received:
    796
    Ratings:
    +1,372 / 1
    Hi Leonard,
    well, that's a good point - just had a look into the code:

    At startup, the ApplicationLauncher calls

    PluginManager.Startup - this is where IPluginStateTracker.Activated is called for all plugins set to autoactivate --> NRE
    ApplicationCore.StartCoreServices
    BackupExtensions.StartupBackendServices - this is where the MediaLibrary is instantiated --> too late...
    ApplicationCore.RegisterDefaultMediaItemAspectTypes

    And behind the last line is a comment that says: to be done after backed services are running

    That looks like a conceptual bug to me, but in the end this is really a question for @morpheus_xx or @Albert. I don't know whether PluginManager.Startup should be called after the backend services are running? To me that would make sense because as a plugin author I would assume that the backend services are running when my plugin reaches the active state, but I don't know whether there's another dependency I'm not aware of...

    Good luck and keep up your great work!
    Michael
     
    • Like Like x 3
  8. MJGraf
    • Team MediaPortal

    MJGraf Retired Team Member

    Joined:
    January 13, 2006
    Messages:
    2,475
    Likes Received:
    796
    Ratings:
    +1,372 / 1
    oh well, that's not going to be easy...

    I should have known that anything in MP2 is a plugin - such as the database. So if you startup the PluginManager after you try to startup the BackendServices this gives you a "There is no database present in the system" exception. Not a good idea...

    My first thought was to implement something like a "SystemRunning"-method in IPluginStateTracker so that you don't have to listen to system messages just for registering MIAs. But then again I'm not sure if there's a problem with the ApplicationLauncher.

    After
    ApplicationCore.RegisterDefaultMediaItemAspectTypes(); // To be done after backend services are running

    it continues with:
    mediaAccessor.Initialize();
    systemStateService.SwitchSystemState(SystemState.Running, true);
    BackendExtension.ActivateImporterWorker(); // To be done after default media item aspect types are present and when the system is running (other plugins might also install media item aspect types)

    So I suppose that plugins should have a possibility to register MIAs before the ImportWorker is started. Since my understanding of messages in MP2 is that they are decoupled from the main thread, I'm also not sure if your implementation now, Leonard, is guaranteed to work. If your plugin takes more time to register the MIAs, they may get registered after the main thread activated the ImportWorker.

    Conclusion for me is that we would indeed need something like IPluginStateTracker.SystemRunning(), but we would have to make sure that it is called before ApplicationLauncher activates the ImportWorker. Since this is deep down in the core of MP2, I'll leave that to the Pros now ;)

    cheers,
    Michael
     
    Last edited: November 24, 2012
    • Like Like x 2
  9. McGoober
    • Team MediaPortal

    McGoober Retired Team Member

    Joined:
    August 13, 2006
    Messages:
    122
    Likes Received:
    103
    Gender:
    Male
    Occupation:
    Staff Software Developement Engineer
    Location:
    Cambridge, UK
    Ratings:
    +105 / 0
    Home Country:
    United Kingdom United Kingdom
    See, now I'm a bit torn between having a callback to perform registration in or adding registration items into the plugin.xml...

    Do we do...
    Code (Text):
    1.  
    2. public class MediaServerPlugin : IPluginStateTracker
    3. {
    4.     public void SystemRunning()
    5.     {
    6.       ServiceRegistration.Get<IMediaItemAspectTypeRegistration>()
    7.         .RegisterLocallyKnownMediaItemAspectType(DlnaAspect.Metadata);
    8.     }
    9. }
    10.  
    or....
    Code (Text):
    1.  
    2. <Register Location="/Database/Aspects">
    3.    <Instance
    4.         Id="DlnaAspect"
    5.         ClassName="MediaPortal.Extensions.MediaServer.Aspects.DlnaAspect"/>
    6. </Register>
    7.  
    My concern is that all registrations for my plugin must happen before the UPNP subsystem is brought up. I haven't as yet drilled down to the call that happens in but according to the log it's after the database subsystem is active. If I was to register everything in the plugin.xml then it's up to the core team to decide when registration of the different parts actually occurs, and not me. This would mean that if a core init change were to happen I would (should) be decoupled from the changes.
    Make sense?
     
  10. MJGraf
    • Team MediaPortal

    MJGraf Retired Team Member

    Joined:
    January 13, 2006
    Messages:
    2,475
    Likes Received:
    796
    Ratings:
    +1,372 / 1
    Makes absolute sense!

    But to be honest, I still didn't understand the difference between registering something via plugin.xml an registering the same thing with a call within Plugin.Activated. Let's take registering a service:

    Morpheus registers his FanArtService in FanArtServicePlugin.Activated with a call to ServiceRegistration.Set<IFanArtService>(new FanArtService());
    There's nothing in plugin.xml regarding the service.

    On the other hand, the SeriesTVDbMatcher and the MovieTheMovieDbMatcher in the OnlineLibraries are registered only via plugin.xml.

    The reason for the first example may be that after registering the service, he adds the respective service implementation to the Backend UPNP device and wants to make sure that this happens after the service is registered with the service registration. On the other hand, the reason for the second example could be as easy as there is no PluginStateTracker for the OnlineLibraries - hence to Activated method.

    As to your question re startup order:

    ApplicationLauncher first activates the plugins and thereby starts all services provided by plugins.
    Then it starts ApplicationCore.StartCoreServices();
    Then we start BackendExtension.StartupBackendServices();
    And after that the DefaultMediaItemAspectTypes are registered.

    The UPNP subsytem is the UPNPBackendServer, which is contained in MediaPortal.Backend.Services.BackendServer. This is therefore started as "BackendService", which is according to the above before the Default MIAs are registered. I'm therefore not sure whether it would be necessary at all to register your aspect before the UPNPBackendServer ist running. The default MIAs are registered after that as well...

    And to be honest, I'm also not sure whether it is necessary to register your aspect before the ImportWorker starts. At least there should be as message informing all interested services that the registered MIAs have changed. But I'm quite sure that this doesn't work (yet), because there seems to be a bug with the message. Maybe @morpheus_xx can check this:

    In the ContentDirectoryMessaging class (which is called by MediaLibrary.AddMediaItemAspectStorage) I found:
    public static void SendPlaylistsChangedMessage()
    {
    SystemMessage msg = new SystemMessage(MessageType.PlaylistsChanged);
    ServiceRegistration.Get<IMessageBroker>().Send(CHANNEL, msg);
    }
    public static void SendMIATypesChangedMessage()
    {
    SystemMessage msg = new SystemMessage(MessageType.PlaylistsChanged);
    ServiceRegistration.Get<IMessageBroker>().Send(CHANNEL, msg);
    }

    In my understanding this is a copy and paste bug - in the second method this should be:
    SystemMessage msg = new SystemMessage(MessageType.MIATypesChanged);

    At least UPnPContentDirectoryServiceImpl checks for this message and it looks like it never received one... :D
    In the ImportWorker, however, I couldn't find anything listening to that message.

    This whole thing indeed brings me to the conclusion that it may be much easier for plugin programmers if they did not have to take care about all this when they register new MIAs - therefore at first glance I would prefer the plugin.xml solution. But this again requires the PluginRuntime to be extended for automatically registering MIAs - and I have no clue how to do that...

    Michael
     
    • Like Like x 3
  11. morpheus_xx
    • Team MediaPortal

    morpheus_xx Lead Dev MP2

    Joined:
    March 24, 2007
    Messages:
    10,920
    Likes Received:
    4,704
    Ratings:
    +6,742 / 11
    Home Country:
    Germany Germany
    Show System Specs
    Good finding, fixed this in dev branch!

    The registration issue itself needs more work ;)
     
    • Like Like x 1
Loading...

Users Viewing Thread (Users: 0, Guests: 0)

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice
  • About The Project

    The vision of the MediaPortal project is to create a free open source media centre application, which supports all advanced media centre functions, and is accessible to all Windows users.

    In reaching this goal we are working every day to make sure our software is one of the best.

             

  • Support MediaPortal!

    The team works very hard to make sure the community is running the best HTPC-software. We give away MediaPortal for free but hosting and software is not for us.

    Care to support our work with a few bucks? We'd really appreciate it!