Help request with onPlayBackStopped

  Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Post Reply
SniperCharlie Offline
Junior Member
Posts: 23
Joined: Mar 2008
Reputation: 0
Post: #1
I'm very new to python (4 days and lotsa googling), and am nearing completion on my first plugin for the audio service Hypem.

I'm building a directory of 20 items, all of which get queued when one is selected. I'm having trouble registering onPlayBackStopped, or other player state commands such as onPlayBackEnded.

The commands for that shouldn't be too hard, but I can't get the onPlayBackStopped to work. I started by testing with some logging commands.

Code:
player = XBMCPlayer()

class XBMCPlayer( xbmc.Player ):
    def _init_( self, *args ):
        pass
    
    def onPlayBackStopped( self ):
        xbmc.log( "Playback Stopped" )

I assume the onPlayBackStopped is not being called because the player being called isn't the one specified for this class.

Here's the code specifying my directory listing for items:

Code:
def addLink(name,url,iconimage):
    #xbmcplugin.setContent(handle=int(sys.argv[1]), content="audio" )
    ok=True
    liz=xbmcgui.ListItem(label=name,thumbnailImage=iconimage, path=url)
    liz.setProperty("mimetype", 'audio/mpeg')
    liz.setInfo('Music', {"title": name })
    liz.setProperty('IsPlayable','true')
    ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=False)
    return ok

Is there a way to pass a specific player name to the items being played in this list? (Assuming that is the issue.)

And here is my code calling the addir just for completion sake.

Code:
def INDEX(url,page):
    feedurl = url + str(page) + apikey
    page=int(page)+1
    req = urllib2.Request(feedurl)
    req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3')
    response = urllib2.urlopen(req)
    raw_json=response.read()
    response.close()
    parsed_json=json.loads(raw_json)
    del parsed_json['version']
    print 'Parsed_Json_output'
    decoded_json =_decode_dict(parsed_json)
    print 'decoded_json_output'
    playlist = sortedDictValues1(decoded_json)
    print 'Sorted_playlist_output'
    #xbmcplugin.setContent(handle=int(sys.argv[1]), content="audio" )
    for x in playlist:
        artist = str(x['artist'])
        title = str(x['title'])
        puburl = x['stream_pub']
        thumb = x['thumb_url_large']
        name = artist + ' - ' + title
        addLink(name,puburl,thumb)
    def mainmenu():
        addDir('Main Menu...',url,None,'',int(page))
    def nextmenu():
        nextmenu = addDir('Next Page...',url,1,'',int(page))
    if len(playlist) < 1:
        CATEGORIES()
    elif len(playlist) < 19:
        mainmenu()
    else:
        nextmenu()
        mainmenu()

I've seen a number of other users having issues with getting the status of the player - most end up writing a set of nested loops with sleep(x) commands. I tried some of them as well, and my directories just never populated. If anyone could provide any help I would much appreciate it!
find quote
jmarshall Online
Team-XBMC Developer
Posts: 25,694
Joined: Oct 2003
Reputation: 169
Post: #2
Your script isn't running once the player starts up, thus you never get any of the calls is my guess.

What is it you're trying to do?

Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


[Image: badge.gif]
find quote
SniperCharlie Offline
Junior Member
Posts: 23
Joined: Mar 2008
Reputation: 0
Post: #3
Here is my code in its entirety:

Code:
import xbmc, xbmcgui, xbmcplugin
import urllib, urllib2

try: import json
except ImportError:
    import simplejson as json

def decode(data):
    items = data.items()
    items = _decode_dict(items)
    return [value for key, value in items]
    
def sortedDictValues1(parsed_json):
    items = parsed_json.items()
    items.sort(key = lambda x:int(x[0]))
    return [value for key, value in items]

def _decode_list(data):
    rv = []
    for item in data:
        if isinstance(item, unicode):
            item = item.encode('utf-8')
        elif isinstance(item, list):
            item = _decode_list(item)
        elif isinstance(item, dict):
            item = _decode_dict(item)
        rv.append(item)
    return rv
    
def _decode_dict(data):
    rv = {}
    for key, value in data.iteritems():
        if isinstance(key, unicode):
           key = key.encode('utf-8')
        if isinstance(value, unicode):
           value = value.encode('utf-8')
        elif isinstance(value, list):
           value = _decode_list(value)
        elif isinstance(value, dict):
           value = _decode_dict(value)
        rv[key] = value
    return rv

#def urlredirect(url):
#    redirect = urllib2.urlopen(url).geturl()
#    return redirect

apikey = '/data.js?key=redacted'
username = 'redacted'

def CATEGORIES():
    addDir('Most Popular','http://api.hypem.com/playlist/popular/3day/json/',1,'',1)
    addDir('Most Recent','http://api.hypem.com/playlist/time/today/json/',1,'',1)
    addDir('My Loved Tracks','http://api.hypem.com/playlist/loved/' + username + '/json/',1,'',1)
    addDir('My Loved Tracks (Shuffled)', 'http://api.hypem.com/playlist/loved_shuffle/' + username + '/json/',1,'',1)
    addDir('My Feed','http://api.hypem.com/playlist/subscriptions/' + username + '/json/',1,'',1)


    
def INDEX(url,page):
    feedurl = url + str(page) + apikey
    page=int(page)+1
    req = urllib2.Request(feedurl)
    req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3')
    response = urllib2.urlopen(req)
    raw_json=response.read()
    response.close()
    parsed_json=json.loads(raw_json)
    del parsed_json['version']
    print 'Parsed_Json_output'
    decoded_json =_decode_dict(parsed_json)
    print 'decoded_json_output'
    playlist = sortedDictValues1(decoded_json)
    print 'Sorted_playlist_output'
    #xbmcplugin.setContent(handle=int(sys.argv[1]), content="audio" )
    for x in playlist:
        artist = str(x['artist'])
        title = str(x['title'])
        puburl = x['stream_pub']
        thumb = x['thumb_url_large']
        name = artist + ' - ' + title
        addLink(name,puburl,thumb)
    def mainmenu():
        addDir('Main Menu...',url,None,'',int(page))
    def nextmenu():
        nextmenu = addDir('Next Page...',url,1,'',int(page))
    if len(playlist) < 1:
        CATEGORIES()
    elif len(playlist) < 19:
        mainmenu()
    else:
        nextmenu()
        mainmenu()
        
    #autoplay the next page of items
#player = 'PAPlayer'
# class XBMCPlayer( xbmc.Player ):
#     def _init_( self, *args ):
#         pass
#     
#     def onPlayBackStopped( self ):
#         xbmc.log( "Playback Stopped" )
#         
# player = XBMCPlayer()

#class XBMCPlayer(xbmc.Player):
#    def __init__(self):
#        xbmc.Player.__init__(self)
#        print "#XBMCPlayer#"
#    
#    def onPlayBackEnded(self):
#        if (AUDIO == 1):
#            if len(playlist)<19:
#                CATEGORIES()
#            else:
#                nextmenu()
#                xbmc.Player().play(firstitem)
#    
#    def onPlayBackStopped(self):
#        if (AUDIO == 1):
#            CATEGORIES()
#
#    VIDEO = 0
#
#    while(1):
#        if xbmc.Player().isPlaying():
#            if xbmc.Player().isPlayingVideo():
#                VIDEO = 1
#            else:
#                VIDEO = 0
#        xbmc.sleep(1000)
    
def VIDEOLINKS(url,name):
        req = urllib2.Request(url)
        req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3')
        response = urllib2.urlopen(req)
        link=response.read()
        response.close()
        match=re.compile('').findall(link)
        for url in match:
            addLink(name,url,'')

def get_params():
        param=[]
        paramstring=sys.argv[2]
        if len(paramstring)>=2:
                params=sys.argv[2]
                cleanedparams=params.replace('?','')
                if (params[len(params)-1]=='/'):
                        params=params[0:len(params)-2]
                pairsofparams=cleanedparams.split('&')
                param={}
                for i in range(len(pairsofparams)):
                        splitparams={}
                        splitparams=pairsofparams[i].split('=')
                        if (len(splitparams))==2:
                                param[splitparams[0]]=splitparams[1]
                                
        return param

def addLink(name,url,iconimage):
    #xbmcplugin.setContent(handle=int(sys.argv[1]), content="audio" )
    ok=True
    liz=xbmcgui.ListItem(label=name,thumbnailImage=iconimage, path=url)
    liz.setProperty("mimetype", 'audio/mpeg')
    liz.setInfo('Music', {"title": name })
    liz.setProperty('IsPlayable','true')
    ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz,isFolder=False)
    return ok
        
def addDir(name,url,mode,iconimage,page):
    #xbmcplugin.setContent(handle=int(sys.argv[1]), content="audio" )
    u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&page="+str(page)
    ok=True
    liz=xbmcgui.ListItem(name,iconImage="DefaultFolder.png",thumbnailImage=iconimage)
    liz.setInfo( "Music", { "Title": name })
    liz.setProperty('IsPlayable','true')
    ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
    return ok

params=get_params()
url=None
name=None
mode=None
page=None

try:
    page=int(params["page"])
except:
    pass

try:
    url=urllib.unquote_plus(params["url"])
except:
    pass
try:
    name=urllib.unquote_plus(params["name"])
except:
    pass
try:
    mode=int(params["mode"])
except:
    pass

print "Mode: "+str(mode)
print "URL: "+str(url)
print "Name: "+str(name)
print "Page: "+str(page)

if mode==None or url==None or len(url)<1:
        print ""
        CATEGORIES()
      
elif mode==1:
        print ""+url
        INDEX(url,page)
        
elif mode==2:
        print ""+url
        VIDEOLINKS(url,name)
        
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)

What I am trying to do is when the list of ~20 items gets to the end, to load the next page with the nextmenu() , and then play the first item loaded from addDir, for a semi-seamless transition to the next 20 items - to allow play to continue somewhat forever.

I need the onPlayBackEnded to know the end of the playlist has been reached, and the onPlayBackStopped to differentiate between a user stop, and an end of the playlist.

Thanks for your assistance!
(This post was last modified: 2012-02-28 01:58 by SniperCharlie.)
find quote
SniperCharlie Offline
Junior Member
Posts: 23
Joined: Mar 2008
Reputation: 0
Post: #4
Any ideas? I'm thinking the addDir function is not specifying a player. In the logs I can see PAPlayer is the one doing the functionality.

Can I get the playbackended/stopped events from the JSON API?

I've looked, but can't find any documentation on the Pre-Eden/Eden JSON API. Any guidance would be much appreciated!
find quote
SniperCharlie Offline
Junior Member
Posts: 23
Joined: Mar 2008
Reputation: 0
Post: #5
Any ideas? The scrape from the website only returns 20 items - and I don't want to limit how much I cue by say craping 5x and cueing 100 items. I'd prefer to get to the end of the 20 items, and cute another 20.

Is it possible to detect where in the playlist the currently playing track is - since onPlayBackStopped doesn't seem to work for me on Eden?

Thanks!
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 16
Post: #6
Like jmarshall said, you need to keep your script alive while the player is off doing it's thing. You want something like:

MyPlayer.play(myurl, mylistitem)
while Myplayer.isPlaying():
xbmc.sleep(250)

That will keep your script alive while xbmc's player logic takes over. If your script is still alive when playback stops or is ended, xbmc will execute whatever is defined in the appropriate method of your player.

Think of it like this. Your python script isn't actually playing the content. By subclassing xbmc.Player() you're just telling that you'd like these methods to be called at the appropriate times. It's more like registering callbacks than actually subclassing the player
find quote