Embed plugin inside script
#1
With my Add-on:XSqueeze (wiki), 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!!


Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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
Reply
#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())

Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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.
Reply
#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!)
Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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...
Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#7
You can instance xbmc.Addon for any id...
Reply
#8
...and then call get_settings() from that instance =)
Reply
#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!!)
Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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??
Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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.
Reply
#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,isFolder=True)
        return is_ok
Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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?
Reply
#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...
Addons I wrote &/or maintain:
OzWeather (Australian BOM weather) | Check Previous Episode | Playback Resumer | Unpause Jumpback | XSqueezeDisplay | (Legacy - XSqueeze & XZen)
Sorry, no help w/out a *full debug log*.
Reply
#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/
Reply

Logout Mark Read Team Forum Stats Members Help
Embed plugin inside script0