[RELEASE] xbmcswift2 - plugin framework
#16
(2013-01-07, 18:17)void0 Wrote: BTW, I need to cache login objects, do you know how it is possible?

Can you elaborate a bit more?
Reply
#17
Is it possible to save an object, say for 30 min? When plugin is fired up, I would like to check if object already exists in the cache and use it if it does, if not create new one and save to cache.
Reply
#18
(2013-01-14, 15:59)void0 Wrote: Is it possible to save an object, say for 30 min? When plugin is fired up, I would like to check if object already exists in the cache and use it if it does, if not create new one and save to cache.

Code:
login_storage = plugin.get_storage('login_stuff', TTL=30)

# login_storage acts like a dict, so simply check for existence of keys
if 'username' not in login_stuff.keys():
    login_storage['username'] = get_user_name()

Reply
#19
I still don't understand how to use it.
Code:
import login
from xbmcswift2 import Plugin

plugin = Plugin()
conn = login.ConnManager(plugin)

@plugin.route('/')
def list_content():
    client = conn.get_client()
    for item in client.get_files():
        yield item

I would like to save conn in cache and have an access to all the methods from that object
Reply
#20
This is great. Trying my hand at my first plugin, and this greatly simplifies it. Thanks!

Should the @plugin.cache mentioned in the docs work with the version installed via pip? Version 1.1.1 near as I can tell, that's what it puts in the template addon.xml.

When I try to use it I get "AttributeError: 'Plugin' object has no attribute 'cache'" (example usage is near the end of my code block). Currently I'm only testing in the CLI.

Also, in the case of an error/missing url/etc what is the proper way with xbmcswift2 to return a "do nothing"? For example in the play_live() below. Again only testing in CLI right now, and the result of play_live() leaves me in a view with a single ".." entry to return to root. Maybe it wouldn't behave that way actually running in XBMC.

Code:
import simplejson as json
from xbmcswift2 import Plugin
from xbmcswift2 import xbmc, xbmcgui

plugin = Plugin()

@plugin.route('/')
def index():
    items = [
    {'label': 'Live', 'path': plugin.url_for('play_live'), 'is_playable': True},
    {'label': 'Archives', 'path': plugin.url_for('list_archives')}
    ]
    return items

@plugin.route('/live')
def play_live():
    live_url = get_live_url()
    if live_url == 'NONE':
    plugin.notify('No active live stream', 'Unavailable', 2000)
    return
    else:
    return plugin.set_resolved_url(live_url)

@plugin.cached_route('/archive/', TTL=60*2)
def list_archives():
    archives = parse_archives()

    videos = [{
    'label': archives[event]['title'],
    'path': plugin.url_for('play_archive', event=str(event)),
        'is_playable': True,
    } for event in archives ]

    return videos

@plugin.route('/play/<event>')
def play_archive(event):
    #Present select dialog here for bitrate
    bitrates = [500,1000,2000]
    dialog = xbmgui.Dialog()
    rate = dialog.select('Choose a bitrate',bitrates)

    return plugin.set_resolved_url(archive_url)

def get_live_url():
    #Present select dialog here for bitrate
    return 'NONE'

@plugin.cache(TTL=60*2)
def parse_archives():
    archives = { x : { 'title': 'Archive '+ str(x), } for x in [1,2,3,4,5] }
    return archives


if __name__ == '__main__':
    plugin.run()
Reply
#21
(2013-01-14, 19:38)void0 Wrote: I still don't understand how to use it.
Code:
import login
from xbmcswift2 import Plugin

plugin = Plugin()
conn = login.ConnManager(plugin)

@plugin.route('/')
def list_content():
    client = conn.get_client()
    for item in client.get_files():
        yield item

I would like to save conn in cache and have an access to all the methods from that object

Why do you pass plugin to login.ConnManager()?

If conn can be pickled this code should be work:

PHP Code:
import login
from xbmcswift2 import Plugin

plugin 
Plugin()
storage plugin.get_storage('storage'TTL=30)

if 
'conn' in storage:
    
conn storage['conn']
else:
    
conn login.ConnManager()
    
storage['conn'] = conn
    storage
.sync()


@
plugin.route('/')
def list_content():
    
client conn.get_client()
    for 
item in client.get_files():
        yield 
item 
My GitHub. My Add-ons:
Image
Reply
#22
(2013-01-14, 19:38)void0 Wrote: I still don't understand how to use it.

I would like to save conn in cache and have an access to all the methods from that object

I'd have to see your full addon source to understand what you are doing. It makes sense to cache specific values, such as usernames/passwords/cookies. It doesn't necessarily make sense to cache an entire python object when a new instance can be created easily. Instead you should cache the values that matter to the instance, typically what you pass to your class's __init__ method.
Reply
#23
(2013-01-15, 06:51)fatcatfan Wrote: This is great. Trying my hand at my first plugin, and this greatly simplifies it. Thanks!

Should the @plugin.cache mentioned in the docs work with the version installed via pip? Version 1.1.1 near as I can tell, that's what it puts in the template addon.xml.

When I try to use it I get "AttributeError: 'Plugin' object has no attribute 'cache'" (example usage is near the end of my code block). Currently I'm only testing in the CLI.

Also, in the case of an error/missing url/etc what is the proper way with xbmcswift2 to return a "do nothing"? For example in the play_live() below. Again only testing in CLI right now, and the result of play_live() leaves me in a view with a single ".." entry to return to root. Maybe it wouldn't behave that way actually running in XBMC.

1. The docs need to be updated! The method call is actually plugin.cached() not plugin.cache().
2. For a missing url simply return None. A recent commit in the develop version fixes the behavior where you see a blank listing with only the ".." entry. In the future, the addon will remain on the current listing if the new one fails.
3. The CLI mode doesn't always behave exactly as XBMC would. If you see weird behavior in the future, verify it in XBMC. Please report any CLI bugs that you find however Wink
Reply
#24
I just started using this library today and I have a quick question. If I want to perform an action (not play a movie, but make a JSON call, for example) and then return to the previous menu, how do I do that?

Right now I'm doing my JSON call, then calling:
Code:
plugin.finish(succeeded=False)

But this returns to the current path, and re-loads it (which is expensive in my case). I'd like to 1) not reload and 2) go to the parent ("..") menu level, if possible.

Thanks so much. This library is amazing.
Reply
#25
Does this framework support non video (ie music and image) plugins? A guick glance seems to imply no?
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
#26
(2013-02-08, 05:20)SorryGoFish Wrote: I just started using this library today and I have a quick question. If I want to perform an action (not play a movie, but make a JSON call, for example) and then return to the previous menu, how do I do that?

Right now I'm doing my JSON call, then calling:
Code:
plugin.finish(succeeded=False)

But this returns to the current path, and re-loads it (which is expensive in my case). I'd like to 1) not reload and 2) go to the parent ("..") menu level, if possible.

Thanks so much. This library is amazing.

Does the JSON call get kicked off from a context menu item or from clicking on a directory item? You rarely want to do succeeded=False, that indicates to XBMC that an error occurred.
(2013-02-08, 06:02)bossanova808 Wrote: Does this framework support non video (ie music and image) plugins? A guick glance seems to imply no?

It does support music and image plugins. Most of the functionality in xbmcswift2 isn't video specific, sometimes the terminology/documentation just makes it seem that way. Check out some addons by sphere, he's done a bunch that are music/image and use xbmcswift2.

https://github.com/dersphere/plugin.audio.shoutcast
https://github.com/dersphere/plugin.audio.radio_de
https://github.com/dersphere/plugin.imag...er_network

Reply
#27
(2013-02-08, 06:06)jbel Wrote:
(2013-02-08, 05:20)SorryGoFish Wrote: I just started using this library today and I have a quick question. If I want to perform an action (not play a movie, but make a JSON call, for example) and then return to the previous menu, how do I do that?

Right now I'm doing my JSON call, then calling:
Code:
plugin.finish(succeeded=False)

But this returns to the current path, and re-loads it (which is expensive in my case). I'd like to 1) not reload and 2) go to the parent ("..") menu level, if possible.

Thanks so much. This library is amazing.

Does the JSON call get kicked off from a context menu item or from clicking on a directory item? You rarely want to do succeeded=False, that indicates to XBMC that an error occurred.

Short answer: It gets called from clicking a directory item.

More detail: I'm probably not using your framework exactly right. I've only spent a few hours with it.

Here's the item:
Code:
{'label' : trailer["title"],
     'path'  : plugin.url_for('set_trailer',
                              filter_by = filter_by,
                              url = trailer['resolutions'][resolution],
                              movie_id = movie_id,
                              source = trailer['source'])}
And here's the function called:
Code:
@plugin.route('/movies/<filter_by>/<movie_id>/set_trailer/<url>/<source>')
def set_trailer(filter_by, movie_id, url, source):
    if source == "apple.com":
        url = '%s|User-Agent=QuickTime' % url

    result = send_request('VideoLibrary.SetMovieDetails', {'movieid' : int(movie_id), 'trailer' : url})
    return None

After reading some of your comments in this thread I changed it to "return None" but basically I'd just like for the item to be a terminal action, not a directory, and not a "playable" entry. Does that make sense? Thanks so much for your help.

Edit: By the way, I discovered the caching functionality, so returning to the current directory is no problem. Right now it works the way I want it to, but as you say, it sends an error to XBMC because the function asserts succeeded=False.
Reply
#28
I think one possible solution for you is to use update_listing=True. You'll have to return plugin.finish(items, update_listing=True) instead of just lists of dicts from your view.
Code:
@plugin.route('/')
def parent():
    items = [{
        'path': plugin.url_for('show_items, url=item.url, ...),
        ...
    } for item in get_items()]
    return items

@plugin.route('/items/<url>')
def show_item(url):
    items = [{
        'path': plugin.url_for('set_item, url=item.url, ...),
    } for item in get_items(url)]
    return plugin.finish(items, update_listing=True)

@plugin.route('/items/<url>/set')
def set_item(url):
    set_the_item(url)
    parent_items = parent()  # call the parent view directly and get its items
    return plugin.finish(parent_items, update_listing=True)

When the user clicks on the terminal item, set_item is called and you do whatever setting stuff you need to do. Then we are displaying the parent item views results in set_item. Since we pass update_listing=True to plugin.finish(), those views won't go on the history stack. So the user appears to go back to the parent view. If you had a larger stack of parents, the '..' item should correctly.
Reply
#29
That worked perfectly. Thanks a lot. Edit maybe not.

It works on the first click, then, if I (for whatever reason) click the same entry again, it goes into an infinite loop.

The incoming URL stays at "set_item"' route, so it loops. But this appears to only happen on the second click...
Reply
#30
(2013-02-08, 21:01)SorryGoFish Wrote: That worked perfectly. Thanks a lot. Edit maybe not.

It works on the first click, then, if I (for whatever reason) click the same entry again, it goes into an infinite loop. It almost seems like "set_item" is hijacking "parent"s route...

Can you pastebin your code?
Reply

Logout Mark Read Team Forum Stats Members Help
[RELEASE] xbmcswift2 - plugin framework2