Embed plugin inside script

  Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Post Reply
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #1
With my Add-on:XSqueeze, I have a need to embed a plugin.

Well, put better, I want to embed a plugin (for choosing music for playback inside XSqueeze), so that I can use the simple XBMC plugin structure and thus get views, lists etc. 'for free' without implementing all this stuff in a WindowXML which seems like a lot more work...

Is it possible to put a plugin inside a script at all? I.e. instantiate one directly in the script...such that one has access to the script AND plugin code at once, if you see what I mean.

Obviously one can call the plugin like any other, but then I have no access to the script's scope/classes, and would like if possible to reduce code duplication as I have a need for a lot of the stuff in the main addon when I call the script.

Hopefully this is clear enough & makes sense...basically, I need an easy way of building lists (of names with pictures) and getting the selections, which then trigger actions on an external server program...this seems pretty easy to do in a plugin as the list stuff is all taken care of...or is there a really easy way to do such a list with WindowXML I am missing - my early experiements have not been successful, I can get items to show, but only the focussed item at any one time, and one doesn't get the standard views etc.

Advice very much appreciated!!
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 16
Post: #2
I think it's pretty much assumed that if you're creating your own window that you want full control. With using the plugin methods, you're giving up 99% of the control of the look and feel to the skin.

You can only pass strings between instances of scripts or plugins. If you can't do it any other way, you can pickle the object in one instance, pass the resulting string to the next instance and unpickle it there.

That being said, if you could clarify exactly what you need to do that you can't do from an addon, maybe we can find a way around it
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #3
Well, it's not so much not being able to do what I want, just that it's much more bang for buck for this particular purpose using a plugin. This is a separate bit to the main addon that simply supplies lists (e.g). New Music, Albums, Artists, etc, then as you go into the list actual album names or whatever) - the user chooses something and a messages is sent to the external to XBMC server to start playback...

So basically the easy-listing with all the skin views you get for free via a plugin is what I need, but I ideally want to hang on to my server connection class, player class, etc., to reduce code duplication.

Is there an easy way in an addon to get that plugin like structure going on, is the question, really? I have tried manually creating a list but this involves a WindowXML, skin file etc. etc, which seems more work than just doing it in a plugin structure.





If I pickle the objects and pass them from the addon to the plugin, then they are in full scope at the plugin side?? I guess that would work, but I presume pickling is the sort of thing that is a bit platform specific and may create issues (like, e.g. POpen())
(This post was last modified: 2012-05-08 05:52 by bossanova808.)
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 16
Post: #4
pickle is cross platform and generally pretty gremlin free. Obviously the object that comes out the other side isn't the same so setting it to a new value won't affect the original, but it'll give you a pretty decent approximation. The only thing is you have to make sure any name spaces used by the original are already imported before you unpickle on the other side.

I admit I'm still no clear about what exactly you're doing (don't have a squeezebox) so this may or may not apply, but hopefully it'll give you an idea at least. An addon can include a service that runs without the actual addon having been launched. I use this for a "subscription" service that periodically creates new .strm files when new content is posted to a website. Here's the addon.xml for a combined service and traditional addon: https://github.com/bstrdsmkr/1Channel/bl.../addon.xml

If that's not what you're after, and you want to preserve a bunch of framework code, you can include it in a script module and require that from both addons.
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #5
I've read up a bit on pickle and it doesn't seem like passing a network connection in a pickled object will work (the connection to squeezeserver is basically via telnet of all things!!) - certainly in Python3+ they seem to be against it even if it might currently work.

>> If that's not what you're after, and you want to preserve a bunch of framework code, you can include it in a script module and require that from both addons.

Yeah that seems like the more sensible option really. It's not a lot of code and it's probably best to do it that way.

(I don't think a service helps me here but thanks for tha idea too!)
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #6
Yeah after some thinking that should work, I just need to ifgure out how to get the settings of the script from within the plugin so they don't have to configure twice...
find quote
spiff Offline
Retired Developer
Posts: 12,386
Joined: Nov 2003
Post: #7
You can instance xbmc.Addon for any id...
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 16
Post: #8
...and then call get_settings() from that instance =)
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #9
Yeah for future searchers this is what you do:

Code:
refToXSqueeze = xbmcaddon.Addon(id='script.xsqueeze')
SERVERIP = refToXSqueeze.getSetting('autoserverip')

(and thanks for the help!!)
(This post was last modified: 2012-05-08 12:48 by bossanova808.)
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #10
Ok - another question - I am trying to pass arguments to the plugin called from my addon. This is to force it always to start in 'mode 0' at the root menu.

To do this I am using this code:

Code:
chooser = "RunScript(plugin.program.xsqueezechooser,mode=0)"
xbmc.executebuiltin(chooser)

..however, this breaks the 'magic' bit where I get the int handle to the plugin...

thisPlugin = int(sys.argv[1])

...makes sens because the arguments have changed I guess, but I can no longer find a way to get this magic handle in the plugin (and there seems to be no other way to force the plugin to always start at the root node)

Any ideas??
(This post was last modified: 2012-05-09 04:35 by bossanova808.)
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 16
Post: #11
Try using RunPlugin('plugin://script.video.something/?mode=0') first

Failing that, how are you calling addItem()? Make sure you're creating it as a folder if the items you're adding aren't the end of the chain.
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #12
Ok running it that way gives me an invalid handle error - the sys.argv dump shows:

Code:
chooser="RunPlugin(plugin://plugin.program.xsqueezechooser/?mode=0)"
      xbmc.executebuiltin(chooser)


13:06:17 T:6828  NOTICE: Called as: ['plugin://plugin.program.xsqueezechooser/', '-1', '?mode=0']

..I guess the -1 is the handle?

addItem is being called:

Code:
#dummy nodes for root menu for modes

def buildRootListing():

  addNode("New Music","",1,"")
  addNode("Albums","",2,"")


def addNode(name, url, mode, iconimage, album="", artist=""):

        u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name) +"&album="+urllib.quote_plus(album) +"&artist="+urllib.quote_plus(artist)

        is_ok=True

        listItem=xbmcgui.ListItem(name, iconImage="DefaultFolder.png", thumbnailImage=iconimage)
        listItem.setInfo( type="Video", infoLabels={ "Title": name } )

        is_ok=xbmcplugin.addDirectoryItem(thisPlugin,url=u,listitem=listItem,isFold​er=True)
        return is_ok
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 16
Post: #13
Yeah, -1 is the handle. That usually happens when the current directory is not created as a directory. Xbmc expects everything currently displayed to be playable, not build a new list.

How is xbmc.executebuiltin(chooser) being called? Is it from a context menu?
find quote
bossanova808 Offline
Donor
Posts: 2,082
Joined: Sep 2009
Reputation: 27
Location: Melbourne, Australia
Post: #14
it's bound to an action in my windowXML:

Code:
#chooser
    elif action == ACTION_CODES['ACTION_SHOW_INFO']:
      Logger.log("### Starting Chooser...")
      ####chooser = "RunAddon(plugin.program.xsqueezechooser,mode=0)"
      chooser="RunPlugin(plugin://plugin.program.xsqueezechooser/?mode=0)"
      xbmc.executebuiltin(chooser)

...and yeah I want it to start at root precisely because it's remembering where it was (actually jsut a dummy message that says 'album queued' - and this retriggers the adding of the album...I really need to be able to force it back to the root...
(This post was last modified: 2012-05-09 05:51 by bossanova808.)
find quote
Nuka1195 Offline
Skilled Python Coder
Posts: 3,910
Joined: Dec 2004
Reputation: 18
Post: #15
Activatewindow() which runaddon() should call should work. I see you have it commented out. Did you try it? A -1 handle just means invalid. runplugin is used when you're calling back to your plugin to do a task. Activatewindow or runaddon is when you want a new listing.

For python coding questions first see http://mirrors.xbmc.org/docs/python-docs/
find quote
Post Reply