XBMC Community Forum
script.module.urlresolver development - Printable Version

+- XBMC Community Forum (http://forum.xbmc.org)
+-- Forum: Development (/forumdisplay.php?fid=32)
+--- Forum: Python Add-on Development (/forumdisplay.php?fid=26)
+--- Thread: script.module.urlresolver development (/showthread.php?tid=105707)

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31


- DragonWin - 2011-09-05 19:39

Hey,

I have 3 items I'm not satisfied with in the favorite code, and I hope for some input on it.

1) Passing addon.url to ContextMenu
The only way I have found to get hold of the addon.url is to initialize ContextMenu with it as an arg.

Code:
addon = Addon('plugin.video.solarmovie', sys.argv)
cm = ContextMenu(addon.url)

2) Getting hold of the addon's ContextMenu object
In order to utilize the existing code to generate the "Delete favorite" menu, the addon needs to pass the cm object in order to generate the menu.

Code:
addon.show_favorites(cm)

3) A way to make a dict to a string and the other way around
As I need to hide data from xbmc when it's sent to the mode showfavoties, I had to base64 encode it, how ever only strings can be base64 encoded. I could not find an existing function that could do this without it "molested" the data by adding other stuff to it. So I created 2 new functions in Addon.

I would really like to utilize existing functions as not to clutter the code.
Code:
def dict_to_string(self, dictionary):
        '''
        This is a convinient way to convert a dictionary to a string. It can
        only be 2 layers deep e.g.
        
        { 'mylist' : ('foo', 'bar', 'chimera'), 'mydict' : { 'key1' : 'key1value',
         'key2' : 'key2value' }, 'myurl' : 'http://xmbx.org' }

        Args:
            dictionary (dict): Each value in the dict can contain one of the
            following: bol, Nontype, str, dict, list, tuple, int. Note that the
            dict in dict, list in dict, tuple in dict's contents must be
            one of the above types, also any int values will have become
            str values, and you need to set it again after using string_to_dict.
            
            See :meth:`string_to_dict` for infomation.
            
        Returns:
            A string in the format &key=value, how ever it's not url safe.
        
        '''
        dictstring = ''
        for key in dictionary:
            string = key
            m = re.match(r'([\d|\w|\s]+)', string)
            if m:
                if type(dictionary[key]) == tuple:
                    tuplestring = '&%s=%s' % (key,'__tuple__/')
                    for value in dictionary[key]:
                        tuplestring = tuplestring + '__%s' % (value)
                    dictstring = dictstring + tuplestring
                elif type(dictionary[key]) == list:
                    liststring = '&%s=%s' % (key,'__list__/')
                    for value in dictionary[key]:
                        liststring = liststring + '__%s' % (value)
                    dictstring = dictstring + liststring
                elif type(dictionary[key]) == dict:
                    dictstring = '&%s=%s' % (key, '__dict__/')
                    for middlekey in dictionary[key]:
                        dictstring = dictstring + '___%s__%s' % \
                        (middlekey, dictionary[key][middlekey])
                    dictstring = dictstring + dictstring
                else:
                    dictstring = dictstring + '&%s=__str__/%s' % \
                    (key, dictionary[key])
        return dictstring
    
    

        
        
    def string_to_dict(self, dictstring):
        '''
        This function rebuilts a dict that was previously turned into a string
        using dict_to_string. Remember as it was turned into a string the
        values and keys are all str now.
        
        Args:
            dictstring (str): A string priveously generated by dict_to_string.
            
            See :meth:`dict_to_string` for further infomation.
        
        Returns:
            A rebuilt dictionary
        '''
        restoreddict = {}
        splitter=re.split('&', dictstring)
        for string in splitter:
            if re.match('.+?__str__/', string):
                key, value = re.split('=__str__/', string)
                restoreddict[key] = value
            elif re.match('.+?__tuple__/', string):
                key, values = re.split('=__tuple__/', string)
                splits = re.split('__', values)
                splits.pop(0)
                tmptuple = tuple(splits)
                restoreddict[key] = tmptuple
            elif re.match('.+?__list__/', string):
                key, values = re.split('=__list__/', string)
                splits = re.split('__', values)
                splits.pop(0)
                restoreddict[key] = splits
            elif re.match('.+?__dict__/', string):
                tmpdict = {}
                key, values = re.split('=__dict__/', string)
                entrypairs = re.split('___', values)
                for pair in entrypairs:
                    if pair:
                        pairkey, pairvalue = re.split('__', pair)
                        tmpdict[pairkey] = pairvalue
                restoreddict[key] = tmpdict
        return restoreddict

Other than that it's looking pretty good now, I'll see if I can quickly make a new video of how it all fits together now that it's a class by itself.


- t0mm0 - 2011-09-05 21:15

DragonWin Wrote:Hey,

I have 3 items I'm not satisfied with in the favorite code, and I hope for some input on it.

1) Passing addon.url to ContextMenu
The only way I have found to get hold of the addon.url is to initialize ContextMenu with it as an arg.

Code:
addon = Addon('plugin.video.solarmovie', sys.argv)
cm = ContextMenu(addon.url)
seems ok to me for the moment, maybe even just pass addon as a whole?
DragonWin Wrote:2) Getting hold of the addon's ContextMenu object
In order to utilize the existing code to generate the "Delete favorite" menu, the addon needs to pass the cm object in order to generate the menu.

Code:
addon.show_favorites(cm)
hmmmm, that's where putting the favourites and context menu stuff together falls down a bit isn't it. might have some more thoughts on looking at the code.
DragonWin Wrote:3) A way to make a dict to a string and the other way around
As I need to hide data from xbmc when it's sent to the mode showfavoties, I had to base64 encode it, how ever only strings can be base64 encoded. I could not find an existing function that could do this without it "molested" the data by adding other stuff to it. So I created 2 new functions in Addon.

I would really like to utilize existing functions as not to clutter the code.
yeah, need to lose that stuff Wink

to serialise objects you can use existing stuff like pickle or json for example. but depending on what you actually need to pass around you might be better off just adding the variables needed to create the object again to the query string? or you could use your previous pickle code to save the object to disk and just send a hash so you can retrieve it again?

t0mm0


- DragonWin - 2011-09-05 21:41

t0mm0 Wrote:seems ok to me for the moment, maybe even just pass addon as a whole?

I'll change that in the next commit to my branch.

t0mm0 Wrote:hmmmm, that's where putting the favourites and context menu stuff together falls down a bit isn't it. might have some more thoughts on looking at the code.

I have just committed the branch to Github here: Favorite Branch

t0mm0 Wrote:yeah, need to lose that stuff Wink

to serialise objects you can use existing stuff like pickle or json for example. but depending on what you actually need to pass around you might be better off just adding the variables needed to create the object again to the query string? or you could use your previous pickle code to save the object to disk and just send a hash so you can retrieve it again?

t0mm0
I'll take another look at pickle on how I can serialize data so it does not clash. I'll rather try and reuse pickle as it's already imported instead of importing yet another class.

I can't add it to the original query string as that would create clashes with the original string, as some part of the key's are the same. Id' rather not change the key names during the process as it makes it harder to keep track of the data passed around.

The problem is the save data call comes from the context menu when the user clicks the menu, so I don't control when it should be used, as the menu is unique to each item shown. This would create a lot of disk IO (relative of cause), but the XBMC best practice says that disk IO should be kept to a minimum to take into account those who runs if from ssd / flash drives.

[EDIT]
Changed the init function to accept the addon object instead of addon.url

Found pickle.dumps and pickle.loads to encode to a string instead of to a file. I originally did not consider pickle, because when I print the pickled data, I saw line breaks in the pickled data

Still need to find a way around passing the cm module to addon. The parts to concentrate on is show_favorites (line 856 where the cm.add_favorite is used and line 860 and 865 where it's passed to add_item and add_direcotry)
[/EDIT]


- k1m0s - 2011-09-09 04:19

Hey t0mm0, Could you tell me if there is a way to add a direct url to an avi file using your test.py as a base? Im making a simple addon without a host page. I manually add megaupl urls to the list.
When I add:
Code:
addon.add_video_item('http://www...com...avi',
                         {'title': 'Whatever'}, 'http://www...com...png')
I get an unable to resolve url error. Plays no prob in vlc, so addresses are good. I assume it automatically checks for a compatible resorse like megaul or 2gbhost and fails without finding one of those addresses. Thanks for any help Smile


- t0mm0 - 2011-09-09 22:47

k1m0s Wrote:Hey t0mm0, Could you tell me if there is a way to add a direct url to an avi file using your test.py as a base? Im making a simple addon without a host page. I manually add megaupl urls to the list.
When I add:
Code:
addon.add_video_item('http://www...com...avi',
                         {'title': 'Whatever'}, 'http://www...com...png')
I get an unable to resolve url error. Plays no prob in vlc, so addresses are good. I assume it automatically checks for a compatible resorse like megaul or 2gbhost and fails without finding one of those addresses. Thanks for any help Smile

yes, see the docs for add_video_item()
Quote:resolved (bool): If False (default), play will be sent as a query to the addon when the item is played. If False, play will be treated as a URL to the media item.

this part of the code is currently undergoing some changes though so be prepared for it to break!

but if it is a megaupload url wouldn't you be better off using urlresolver rather than direct links?

on a good note i have another couple of weeks off work so you should see another spike in commits - maybe we can get a release done at last Wink

and DragonWin and Eldorado - i'm not ignoring your code i'll get to it in the next few days (busy over the weekend but will start working on this stuff seriously again after that!)

t0mm0


- k1m0s - 2011-09-10 05:27

t0mm0 Wrote:yes, see the docs for add_video_item()


this part of the code is currently undergoing some changes though so be prepared for it to break!

but if it is a megaupload url wouldn't you be better off using urlresolver rather than direct links?

on a good note i have another couple of weeks off work so you should see another spike in commits - maybe we can get a release done at last Wink

and DragonWin and Eldorado - i'm not ignoring your code i'll get to it in the next few days (busy over the weekend but will start working on this stuff seriously again after that!)

t0mm0


Kickass t0mm0 thx, the ones in question are furk, and furk seems to be stable at keeping a direct url to their video files


- DragonWin - 2011-09-12 16:19

No problem t0mm0, this is after all an open source project, and not a work we are paid to do Wink

I have not had much time to redo the code that requires the cm to be passed to the mode = showfavorite, the only thing I can see right on the top of my head is to put it in the addon itself, as by design the cm.addcontext etc is build to be used by the addon code, and not the t0mm0.addon module.

Hence why I have not made a pull request yet Wink

I hope I get a chance to look at it further soon.


- DragonWin - 2011-09-12 17:42

I really hate to add more "code required in the addon" but the only way I can see right now is to change the showfavorites to some thing like this, where addon.show_favorites returns False if no favorites are found, and returns a list of dicts that can be used to generate the directories / play items.

Code:
elif mode == 'showfavorites':
    favorites = addon.show_favorites()
    if favorites:
        cm.add_favorite('Delete favorite',{ 'mode' : 'deletefavorite'},
                        'deletefavorite', addon.queries['favtype'] )
        for data in favorites:
            if data['callback'] == 'play':
                addon.add_item(data['url'], { 'title' : data['title']},
                              item_type=data['item_type'], cm=cm)
            else:
                addon.add_directory(data['queries'], data['title'], cm=cm)



- anarchintosh - 2011-09-13 14:23

hi guys, it's really neat you all actually followed through on devving this! was worried it'd become another cold turkey.

i messed around with making a reCaptcha module https://github.com/anarchintosh/script.module.recaptcha
basically what is needed is an actual patch to XBMC itself to have a 'captcha keyboard view'* as part of xbmcgui.

Because the current method of using a folder image as the captcha image is a horrible hack that many hate.

I suppose it's important because many popular cyberlockers use reCaptcha these days (fileserve/sonic, wupload, hotfile etc)

*ie. a keyboard with a little space for a captcha image above the text box.


- t0mm0 - 2011-09-14 16:06

anarchintosh Wrote:hi guys, it's really neat you all actually followed through on devving this! was worried it'd become another cold turkey.

i messed around with making a reCaptcha module https://github.com/anarchintosh/script.module.recaptcha
basically what is needed is an actual patch to XBMC itself to have a 'captcha keyboard view'* as part of xbmcgui.

Because the current method of using a folder image as the captcha image is a horrible hack that many hate.

I suppose it's important because many popular cyberlockers use reCaptcha these days (fileserve/sonic, wupload, hotfile etc)

*ie. a keyboard with a little space for a captcha image above the text box.

cool, thanks anarchintosh! i guess it might be useful to make it more generic at some point so it would work for any captcha not just recaptcha.