The branch, frodo has been updated
       via  55abb002a61774f1275c221824bcebc035e796b6 (commit)
      from  d1bd74a30055bea2de5437bf59ca6159c05cba9f (commit)

- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/scripts;a=commit;h=55abb002a61774f1275c221824bcebc035e796b6

commit 55abb002a61774f1275c221824bcebc035e796b6
Author: Martijn Kaijser <[email protected]>
Date:   Sat Jul 26 12:28:55 2014 +0200

    [script.module.xbmcutil] 2.1.0

diff --git a/script.module.xbmcutil/addon.xml b/script.module.xbmcutil/addon.xml
index 98ff9b3..714c30d 100644
--- a/script.module.xbmcutil/addon.xml
+++ b/script.module.xbmcutil/addon.xml
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="script.module.xbmcutil" name="XBMC Utility Pack" 
provider-name="willforde" version="2.0.4">
+<addon id="script.module.xbmcutil" name="XBMC Utility Pack" 
provider-name="willforde" version="2.1.0">
        <requires>
                <import addon="xbmc.python" version="2.1.0"/>
-               <import addon="script.module.parsedom" version="2.5.1"/>
                <import addon="script.module.simple.downloader" 
version="1.9.4"/>
        </requires>
        <extension library="lib" point="xbmc.python.module"/>
diff --git a/script.module.xbmcutil/changelog.txt 
b/script.module.xbmcutil/changelog.txt
index d17ebd3..9064ded 100644
--- a/script.module.xbmcutil/changelog.txt
+++ b/script.module.xbmcutil/changelog.txt
@@ -1,3 +1,17 @@
+[B]Version 2.1.0[/B] 2014-06-30
+- Update Strings to strings.po
+- Added UnitTests
+- Added stripEnity to urlopeners
+- Added with steatment support to urlhandler
+- Added cleanup method that runs ones every 28 Days to cleanup stail url cache
+- Added a option to enable debug output when testing addons
+- Added unittest cases for all methods and fuctions
+- Removed unnecessary cache validation checks
+- Reworked debug messages and methods
+- Reworked the vimeo url scraper
+- Fix bug with youtube video id parser
+- And a lot more small improvements
+
 [B]Version 2.0.4[/B]
 - Changed the Video Context menu to not replace items
 - Fixed bug with XBMC unexpectedly returning unicode instead of a string
diff --git a/script.module.xbmcutil/lib/fastjson.py 
b/script.module.xbmcutil/lib/fastjson.py
index f613150..3dad9c1 100644
--- a/script.module.xbmcutil/lib/fastjson.py
+++ b/script.module.xbmcutil/lib/fastjson.py
@@ -1,9 +1,3 @@
 import sys
-_log = sys.modules["__main__"].xbmcutil.plugin.log
-
-if sys.version_info >=  (2, 7):
-       _log("Importing Built in Json Library", 0)
-       from json import *
-else:
-       _log("Importing Older Simplejson Library", 0)
-       from simplejson import *
\ No newline at end of file
+if sys.version_info >=  (2, 7):        from json import *
+else: from simplejson import *
\ No newline at end of file
diff --git a/script.module.xbmcutil/lib/xbmcutil/__init__.py 
b/script.module.xbmcutil/lib/xbmcutil/__init__.py
index ee5e7b0..8d21595 100644
--- a/script.module.xbmcutil/lib/xbmcutil/__init__.py
+++ b/script.module.xbmcutil/lib/xbmcutil/__init__.py
@@ -19,6 +19,15 @@
        along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
+# Manually Remove reference to the below objects to fix XBMC Bug
+def cleanup():
+       del Addon.getLocalizedString
+       del Addon.openSettings
+       del Addon.getSetting
+       del Addon.setSetting
+       del Addon._addonData
+       del Addon._scriptData
+
 # Funtion for Checking the subAction Params
 def sysCheck():
        # Fetch SubAction Param
@@ -40,7 +49,7 @@ def sysCheck():
        elif subAction == u"opensettings":
                # Open Settings Dialog
                plugin.openSettings()
-               plugin.refreshContainer()
+               plugin.executebuiltin("Container.Refresh")
        
        elif subAction == u"search":
                # Call storageDB and exacute saved searches
@@ -48,344 +57,180 @@ def sysCheck():
                storageDB.SavedSearches()
 
 class Addon(object):
-       _addonObj = __import__("xbmcaddon").Addon
-       _addonName = None
+       # Create Addon Object to the System Script Module
+       import xbmcaddon
+       _scriptData = xbmcaddon.Addon("script.module.xbmcutil")
+       _addonData = xbmcaddon.Addon()
+       getLocalizedString = _addonData.getLocalizedString
+       openSettings = _addonData.openSettings
+       getSetting = _addonData.getSetting
+       setSetting = _addonData.setSetting
        _profile = None
        
-       def setAddonIDs(self, localID, globalID):
-               """ Initiate Local and Global Objects """
-               self._addonData = self._addonObj(localID)
-               self._scriptData = self._addonObj(globalID)
-               self._addonID = localID
-               
-               # Shortcuts
-               self.openSettings = self._addonData.openSettings
-               self.setSetting = self._addonData.setSetting
-               self.getuni = self.getLocalizedString
+       def getAddonInfo(self, id):
+               """ # List of possible ids.
+                       author, changelog, description, disclaimer,
+                       fanart, icon, id, name, path, profile,
+                       stars, summary, type, version
+               """
+               # Call parent method and convert response to unicode
+               return self._addonData.getAddonInfo(id).decode("utf8")
        
-       def getLocalizedString(self, id):
+       def getuni(self, id):
                """ Return localized unicode string for selected id """
-               if   id >= 30000 and id <= 30899: return 
self._addonData.getLocalizedString(id)
-               elif id >= 32900 and id <= 32999: return 
self._scriptData.getLocalizedString(id)
+               if   id >= 30000 and id <= 30899: return 
self.getLocalizedString(id)
+               elif id >= 32800 and id <= 32999: return 
self._scriptData.getLocalizedString(id)
                else: return self.xbmc.getLocalizedString(id)
        
        def getstr(self, id):
-               """ Return localized string for selected id """
-               return self.getLocalizedString(id).encode("utf8")
+               """ Return localized unicode string for selected id """
+               if   id >= 30000 and id <= 30899: return 
self.getLocalizedString(id).encode("utf8")
+               elif id >= 32800 and id <= 32999: return 
self._scriptData.getLocalizedString(id).encode("utf8")
+               else: return self.xbmc.getLocalizedString(id).encode("utf8")
        
-       def getAddonSetting(self, id, key):
-               """ Return setting for selected addon """
-               try: addonData = self._addonObj(id)
-               except: return u""
-               else: return addonData.getSetting(key)
+       def getLocalPath(self):
+               return self.getAddonInfo("path")
        
-       def getQuality(self):
-               """ Return unicode for quality setting """
-               return self._addonData.getSetting("quality")
+       def getGlobalPath(self):
+               return self._scriptData.getAddonInfo("path").decode("utf8")
        
-       def getSetting(self, id):
-               """ Return unicode for setting """
-               return self._addonData.getSetting(id)
+       def getAddonSetting(self, id, key):
+               """ Return setting for selected addon """
+               return self.xbmcaddon.Addon(id).getSetting(key)
        
        def getSettingInt(self, id):
                """ Return Integer for settings """
-               return int(self._addonData.getSetting(id))
+               return int(self.getSetting(id))
        
        def getSettingBool(self, id):
                """ Return boolean for setting """
-               return self._addonData.getSetting(id) == u"true"
+               return self.getSetting(id) == u"true"
+       
+       def getIcon(self):
+               """ Return unicode path to addon icon """
+               return self.translatePath(self.getAddonInfo("icon"))
        
        def translatePath(self, path):
                """ Return translated special paths as unicode """
                return self.xbmc.translatePath(path).decode("utf8")
        
-       def getId(self):
-               """ Return addon id """
-               return self._addonID.decode("utf8")
-       
-       def getAuthor(self):
-               """ Return author for current addon """
-               return self._addonData.getAddonInfo("author").decode("utf8")
-       
-       def getChangelog(self):
-               """ Return path to changelog for addon """
-               return self._addonData.getAddonInfo("changelog").decode("utf8")
-       
-       def getDescription(self):
-               """ Return full description for addon """
-               return 
self._addonData.getAddonInfo("description").decode("utf8")
-       
-       def getDisclaimer(self):
-               """ Return the disclamimer for current addon if any """
-               return self._addonData.getAddonInfo("disclaimer").decode("utf8")
-       
-       def getName(self):
-               """ Return name of current addon """
-               if self._addonName: return self._addonName
-               else:
-                       self._addonName = 
self._addonData.getAddonInfo("name").decode("utf8")
-                       return self._addonName
-       
-       def getStars(self):
-               """ Return Start rating for addon """
-               return self._addonData.getAddonInfo("stars").decode("utf8")
-       
-       def getSummary(self):
-               """ Return description summary for addon """
-               return self._addonData.getAddonInfo("summary").decode("utf8")
-       
-       def getType(self):
-               """ Return type of addon """
-               return self._addonData.getAddonInfo("type").decode("utf8")
-       
-       def getVersion(self):
-               """ Return current addon version """
-               return self._addonData.getAddonInfo("version").decode("utf8")
-       
-       def getTempPath(self):
-               """ Return unicode path to temp folder """
-               return self.translatePath("special://home/temp/")
-       
        def getProfile(self):
                """ Returns full unicode path to the addons saved data location 
"""
                if self._profile: return self._profile
                else:
-                       self._profile = 
self.translatePath(self._addonData.getAddonInfo("profile"))
-                       if not self.os.path.exists(self._profile): 
self.os.makedirs(self._profile)
-                       return self._profile
-       
-       def getLibPath(self):
-               """ Returns full unicode path to the plugin library location """
-               return self.os.path.join(self._addonData.getAddonInfo("path"), 
"resources", "lib").decode("utf8")
-       
-       def getIcon(self):
-               """ Return unicode path to addon icon """
-               return self.translatePath(self._addonData.getAddonInfo("icon"))
-       
-       def getFanartImage(self):
-               """ Return unicode path of addon fanart """
-               return 
self.translatePath(self._addonData.getAddonInfo("fanart"))
-       
-       def getImageLocation(self, local=True):
-               """ Return unicode path to local or globale image location """
-               return self.os.path.join(self.getPath(local), "resources", 
"media", "%s")
-       
-       def getPath(self, local=True):
-               """ Returns full unicode path to the plugin location """
-               if local: return 
self._addonData.getAddonInfo("path").decode("utf8")
-               else: return 
self._scriptData.getAddonInfo("path").decode("utf8")
+                       self._profile = _profile = 
self.translatePath(self.getAddonInfo("profile"))
+                       if not self.os.path.exists(_profile): 
self.os.makedirs(_profile)
+                       return _profile
 
 class Dialog(object):
-       import xbmcgui
-       xbmcgui.INPUT_ALPHANUM = 0
-       xbmcgui.INPUT_NUMERIC = 1
-       xbmcgui.INPUT_DATE = 2
-       xbmcgui.INPUT_TIME = 3
-       xbmcgui.INPUT_IPADDRESS = 4
-       xbmcgui.INPUT_PASSWORD = 5
-       xbmcgui.PASSWORD_VERIFY = 1
-       xbmcgui.ALPHANUM_HIDE_INPUT = 2
-       
-       def dialogYesNo(self, heading, line1, line2="", line3="", nolabel="", 
yeslabel=""):
-               """
-                       Returns True if 'Yes' was pressed, else False.
-                       
-                       heading         : string or unicode - dialog heading.
-                       line1           : string or unicode - line #1 text.
-                       line2           : [opt] string or unicode - line #2 
text.
-                       line3           : [opt] string or unicode - line #3 
text.
-                       nolabel         : [opt] label to put on the no button.
-                       yeslabel        : [opt] label to put on the yes button.
-               """
-               dialogbox = self.xbmcgui.Dialog()
-               return dialogbox.yesno(heading, line1, line2, line3, nolabel, 
yeslabel)
-       
-       def dialogOK(self, heading, line1, line2="", line3=""):
-               """
-                       Returns True if 'Ok' was pressed, else False.
-                       
-                       heading         : string or unicode - dialog heading.
-                       line1           : string or unicode - line #1 text.
-                       line2           : [opt] string or unicode - line #2 
text.
-                       line3           : [opt] string or unicode - line #3 
text.
-               """
-               dialogbox = self.xbmcgui.Dialog()
-               return dialogbox.ok(heading, line1, line2, line3)
-       
        def dialogSelect(self, heading, list, autoclose=0):
-               """
-                       Returns the position of the highlighted item as an 
integer.
-                       
-                       heading         : string or unicode - dialog heading.
-                       list            : string list - list of items.
-                       autoclose       : [opt] integer - milliseconds to 
autoclose dialog. (default=do not autoclose)
-               """
+               """ Returns the position of the highlighted item as an integer. 
"""
                dialogbox = self.xbmcgui.Dialog()
                return dialogbox.select(heading, list, autoclose)
        
        def dialogNumeric(self, type, heading, default=""):
-               """
-                       Returns the entered data as a unicode string
-                       
-                       type            : integer - the type of numeric dialog.
-                       heading         : string or unicode - dialog heading.
-                       default         : [opt] string - default value.
-                       
-                       Types:
-                       - 0 : ShowAndGetNumber (default format: #)
-                       - 1 : ShowAndGetDate (default format: DD/MM/YYYY)
-                       - 2 : ShowAndGetTime (default format: HH:MM)
-                       - 3 : ShowAndGetIPAddress (default format: #.#.#.#)
-               """
+               """ Returns the entered data as a unicode string """
                dialogbox = self.xbmcgui.Dialog()
                return dialogbox.numeric(type, heading, default).decode("utf8")
        
-       def dialogInput(self, heading, default="", type=0, option=0, 
autoclose=0):
-               """
-                       Returns the entered data as a unicode string
-                       
-                       heading         : string - dialog heading.
-                       default         : [opt] string - default value. 
(default=empty string)
-                       type            : [opt] integer - the type of keyboard 
dialog. (default=xbmcgui.INPUT_ALPHANUM)
-                       option          : [opt] integer - option for the 
dialog. (see Options below)
-                       autoclose       : [opt] integer - milliseconds to 
autoclose dialog. (default=do not autoclose)
-                       
-                       Types:
-                       0 - xbmcgui.INPUT_ALPHANUM (standard keyboard)
-                       1 - xbmcgui.INPUT_NUMERIC (format: #)
-                       2 - xbmcgui.INPUT_DATE (format: DD/MM/YYYY)
-                       3 - xbmcgui.INPUT_TIME (format: HH:MM)
-                       4 - xbmcgui.INPUT_IPADDRESS (format: #.#.#.#)
-                       5 - xbmcgui.INPUT_PASSWORD (return md5 hash of input, 
input is masked)
-               """
-               if type == 0: return self.keyBoard(default, heading, option==2)
-               elif type >= 1 and type <= 4: return self.dialogNumeric(type-1, 
heading, default)
-               elif type == 5:
-                       ret = self.keyBoard(default, heading, True)
-                       if ret:
-                               from hashlib import md5
-                               hash = md5(ret).hexdigest().decode("utf8")
-                               if option == 1: return default == hash
-                               else: return hash
-                       else: return None
-               else: raise ValueError("dialogInput argument type is out of 
bounds")
-       
-       def dialogBrowse(self, type, heading, shares, mask="", useThumbs=False, 
treatAsFolder=False, default="", enableMultiple=False):
-               """
-                       Returns filename and/or path as a unicode string to the 
location of the highlighted item
-                       
-                       type           : integer - the type of browse dialog.
-                       heading        : string or unicode - dialog heading.
-                       shares         : string or unicode - from sources.xml. 
(i.e. 'myprograms')
-                       mask           : [opt] string or unicode - '|' 
separated file mask. (i.e. '.jpg|.png')
-                       useThumbs      : [opt] boolean - if True autoswitch to 
Thumb view if files exist.
-                       treatAsFolder  : [opt] boolean - if True playlists and 
archives act as folders.
-                       default        : [opt] string - default path or file.
-               """
-               dialogbox = self.xbmcgui.Dialog()
-               return dialogbox.browse(type, heading, shares, mask, useThumbs, 
treatAsFolder, default, enableMultiple)
-       
        def browseMultiple(self, type, heading, shares, mask="", 
useThumbs=False, treatAsFolder=False, default=""):
                """ Returns tuple of marked filenames as a unicode string """
-               return tuple([filename.decode("utf8") for filename in 
self.dialogBrowse(type, heading, shares, mask, useThumbs, treatAsFolder, 
default, True)])
+               dialogbox = self.xbmcgui.Dialog()
+               return tuple([filename.decode("utf8") for filename in 
dialogbox.browse(type, heading, shares, mask, useThumbs, treatAsFolder, 
default, True)])
        
        def browseSingle(self, type, heading, shares, mask="", useThumbs=False, 
treatAsFolder=False, default=""):
                """ Returns filename and/or path as a unicode string to the 
location of the highlighted item """
-               return self.dialogBrowse(type, heading, shares, mask, 
useThumbs, treatAsFolder, default, False).decode("utf8")
+               dialogbox = self.xbmcgui.Dialog()
+               return dialogbox.browse(type, heading, shares, mask, useThumbs, 
treatAsFolder, default, False).decode("utf8")
        
        def keyBoard(self, default="", heading="", hidden=False):
-               """
-                       Return User input as a unicode string
-                       
-                       default : default text entry.
-                       heading : keyboard heading.
-                       hidden  : True for hidden text entry.
-               """
+               """ Return User input as a unicode string """
                kb = self.xbmc.Keyboard(default, heading, hidden)
                kb.doModal()
                if kb.isConfirmed() and kb.getText(): return 
kb.getText().decode("utf8")
                else: return None
        
-       def dialogSearch(self, urlString=""):
-               # Open KeyBoard Dialog
-               ret = self.keyBoard("", self.getstr(16017), False)
-               
-               # Check if User Entered Any Data
+       def dialogSearch(self, urlString=None):
+               """ Open KeyBoard Dialog and return input with urlString """
+               ret = self.keyBoard("", self.getstr(16017), False) # 16017 = 
Enter Search String
                if ret and urlString: return urlString % ret
                elif ret: return ret
-               else: raise plugin.URLError(0, "User Cannceled The Search 
KeyBoard Dialog")
+               else:
+                       self.debug("User Cannceled The Search KeyBoard Dialog")
+                       raise plugin.URLError(None)
        
-       def setNotification(self, heading, message, icon="error", time=5000, 
sound=True):
-               """
-                       heading : string - dialog heading.
-                       message : string - dialog message.
-                       icon    : [opt] string - icon to use.
-                       time    : [opt] integer - time in milliseconds (default 
5000)
-                       sound   : [opt] bool - play notification sound (default 
True)
-               """
-               
-               # Check if Errors are Suppressed
-               if icon == "error":
-                       if self._suppressErrors == True: return
-                       else: self._suppressErrors = True
-               
-               # Fetch Localized String if Needed
+       def sendNotification(self, heading, message, icon="info", time=5000, 
sound=True):
+               """ Send a notification to xbmc to be displayed """
                if isinstance(heading, int): heading = self.getstr(heading)
                if isinstance(message, int): message = self.getstr(message)
                
-               # Send Error Messisg to Display
-               #box = self.dialogBox
-               #box.notification(heading, message, icon, time, sound)
-               
                # Send Error Message to Display
                exeString = "xbmc.Notification(%s,%s,%i)" % (heading, message, 
time)
                self.executebuiltin(exeString)
 
 # Class For Fetching plugin Information
 class Info(Addon, Dialog):
-       import xbmcplugin, xbmc, urllib, sys, os
+       import xbmcplugin, xbmcgui, xbmc, urllib, sys, os
        _suppressErrors = False
        _traceback = None
        _xbmcvfs = None
+       _devmode = True
+       
+       # Fetch system elements
+       handleZero = sys.argv[0]
+       handleOne = int(sys.argv[1])
+       handleTwo = sys.argv[2]
+       addonID = handleZero[9:-1]
+       xbmc.log("#### %s ####" % addonID, 2)
        
        class Error(Exception):
-               exceptionName = 32909 # UnexpectedError
-               def __init__(self, errorCode=0, errorMsg=""):
-                       if errorMsg: plugin.setDebugMsg(self.exceptionName, 
errorMsg)
-                       self.errorCode = errorCode
+               exceptionName = 32851 # UnexpectedError
+               def __init__(self, errorMsg="", debugMsg=""):
                        self.errorMsg = errorMsg
-               
-               def __str__(self): return self.errorMsg
-               def __int__(self): return self.errorCode
-
-       class ScraperError(Error):  exceptionName = 32915 # ScraperError
-       class URLError(Error):      exceptionName = 32916 # URLError
-       class CacheError(Error):    exceptionName = 32917 # CacheError
-       class ParserError(Error):   exceptionName = 32918 # ParserError
-       class YoutubeAPI(Error):    exceptionName = 32919 # YoutubeAPI
-       class videoResolver(Error): exceptionName = 32920 # videoResolver
+                       self.debugMsg = debugMsg
+       
+       class URLError(Error):      exceptionName = 32807 # URLError
+       class ScraperError(Error):  exceptionName = 32824 # ScraperError
+       class CacheError(Error):    exceptionName = 32808 # CacheError
+       class ParserError(Error):   exceptionName = 32821 # ParserError
+       class YoutubeAPI(Error):    exceptionName = 32822 # YoutubeError
+       class videoResolver(Error): exceptionName = 32823 # ResolverError
        
        def error_handler(cls, function):
                # Wrapper for Scraper Function
                def wrapper(*arguments, **keywords):
                        try: response = function(*arguments, **keywords)
+                       except (UnicodeEncodeError, UnicodeDecodeError) as e:
+                               cls.sendNotification(32852, e.reason, 
icon="error") # 32852 = Unicode Error
+                               cls.severe("A Severe Unicode Encode/Decode 
Error was raise, unable to continue", traceback=True)
+                               cls._suppressErrors = True
+                       
+                       except ImportError as e:
+                               cls.sendNotification(32851, e.message, 
icon="error") # 32852 = Unexpected Error
+                               cls.severe("An unexpected python exception was 
raised, unable to continue", traceback=True)
+                               cls._suppressErrors = True
+                       
                        except cls.Error as e:
-                               if e.errorCode: 
cls.setNotification(e.exceptionName, e.errorCode, icon="error")
-                               cls.printTraceback()
-                               return False
-                       except (UnicodeEncodeError, UnicodeDecodeError):
-                               cls.setNotification(32909, 32921, icon="error")
-                               cls.printTraceback()
-                               return False
+                               exceptionName = cls.getstr(e.exceptionName)
+                               if e.debugMsg: cls.severe("%s:%s" % 
(exceptionName, e.debugMsg))
+                               if e.errorMsg:
+                                       cls.sendNotification(exceptionName, 
e.errorMsg, icon="error")
+                                       cls.severe("%s:%s" % (exceptionName, 
e.errorMsg))
+                                       cls._suppressErrors = True
+                               
+                               # print TraceBack to xbmc log
+                               cls.severe("Unrecoverable Error", 
traceback=True)
+                       
                        except:
-                               cls.setNotification(32909, 32974, icon="error")
-                               cls.printTraceback()
-                               return False
+                               cls.sendNotification(32851, 32853, icon="error")
+                               cls.severe("A Severe Unhandled Error was raise, 
unable to continue", traceback=True)
+                               cls._suppressErrors = True
+                       
                        else:
                                if response: return response
                                else:
-                                       cls.setNotification(cls.getName(), 
33077, icon="error")
-                                       return False
+                                       
cls.sendNotification(cls.getAddonInfo("name"), 33077, icon="error")
+                                       cls.debug("No Video information was 
found")
                
                # Return Wrapper
                return wrapper
@@ -394,41 +239,37 @@ class Info(Addon, Dialog):
        def xbmcvfs(self):
                if self._xbmcvfs: return self._xbmcvfs
                else:
-                       self._xbmcvfs = __import__("xbmcvfs")
-                       return self._xbmcvfs
+                       self._xbmcvfs = xbmcvfs = __import__("xbmcvfs")
+                       return xbmcvfs
        
        @property
        def traceback(self):
                if self._traceback: return self._traceback
                else:
-                       self._traceback = __import__("traceback")
-                       return self._traceback
+                       self._traceback = traceback = __import__("traceback")
+                       return traceback
        
        def __init__(self):
-               # Fetch system elements
-               self.handleZero = self.sys.argv[0]
-               self.handleOne = int(self.sys.argv[1])
-               self.handleTwo = self.sys.argv[2]
-               
-               # Create Plugin Handle Three
-               if self.handleTwo: self.handleThree = "%s%s&" % 
(self.handleZero, self.handleTwo.replace("refresh","_"))
-               else: self.handleThree = "%s?" % 
self.handleZero.replace("refresh","_")
-               
-               # Fetch Dict of Params
-               if self.handleTwo: self._Params = 
self.get_params(self.handleTwo)
-               else: self._Params = {}
+               # Check for Quary handle
+               if self.handleTwo:
+                       # Fetch Dict of Params
+                       self._Params = self.parse_qs(self.handleTwo)
+                       # Fetch list of actions
+                       self.actions = 
self._Params.get("action",u"Initialize").split(".")
+                       # Create Plugin Handle No Three
+                       self.handleThree = "%s%s&" % (self.handleZero, 
self.handleTwo.replace("refresh","_"))
+                       # Log values for debug
+                       self.debug(self.handleTwo)
+               else:
+                       # Create empty params
+                       self._Params = {}
+                       # Create Initialize action
+                       self.actions = [u"Initialize"]
+                       # Create Plugin Handle Three
+                       self.handleThree = "%s?" % self.handleZero
                
                # Initiate Local and Global xbmcAddon Objects
-               self.setAddonIDs(self.handleZero[9:-1], 
"script.module.xbmcutil")
-               
-               # Fetch list of actions
-               self.actions = self.get("action",u"Initialize").split(".")
-               
-               # Set addon library path
-               self.sys.path.append(self.getLibPath())
-               
-               # Display Current ID in XBMC Log
-               self.log("### %s ###" % self._addonID)
+               
self.sys.path.append(self.os.path.join(self.getAddonInfo("path"), u"resources", 
u"lib"))
        
        def getSelectedViewID(self, content):
                """ Returns selected View Mode setting if available """
@@ -440,8 +281,7 @@ class Info(Addon, Dialog):
                        contentViewMode = self.getSettingInt(content)
                        if contentViewMode == 0: return None
                        elif contentViewMode == 3:
-                               customView = self.getSetting("%scustom" % 
content)
-                               try: return int(customView)
+                               try: return int(self.getSetting("%scustom" % 
content))
                                except: return None
                        else:
                                # Create Table to Sky IDs
@@ -449,15 +289,12 @@ class Info(Addon, Dialog):
                                                         'skin.aeonmq5':        
        {'files': {1:59, 2:56},         'episodes': {1:59, 2:64}},
                                                         'skin.aeon.nox':       
        {'files': {1:52, 2:500},        'episodes': {1:518, 2:500}},
                                                         'skin.amber':          
        {'files': {1:None, 2:53},       'episodes': {1:52, 2:53}},
-                                                       #'skin.back-row':       
        {'files': {1:None, 2:None},     'episodes': {1:None, 2:None}},
                                                         'skin.bello':          
        {'files': {1:50, 2:56},         'episodes': {1:50, 2:561}},
                                                         'skin.carmichael':     
        {'files': {1:50, 2:51},         'episodes': {1:50, 2:56}},
                                                         'skin.confluence':     
        {'files': {1:51, 2:500},        'episodes': {1:51, 2:500}},
-                                                       #'skin.diffuse':        
        {'files': {1:None, 2:None},     'episodes': {1:None, 2:None}},
                                                         'skin.droid':          
        {'files': {1:50, 2:55},         'episodes': {1:50, 2:51}},
                                                         'skin.hybrid':         
        {'files': {1:50, 2:500},        'episodes': {1:50, 2:500}},
                                                         'skin.metropolis':     
        {'files': {1:503, 2:None},      'episodes': {1:55, 2:59}},
-                                                       #'skin.nbox':           
        {'files': {1:None, 2:None},     'episodes': {1:None, 2:None}},
                                                         'skin.pm3-hd':         
        {'files': {1:550, 2:53},        'episodes': {1:550, 2:53}},
                                                         'skin.quartz':         
        {'files': {1:52, 2:None},       'episodes': {1:52, 2:None}},
                                                         'skin.re-touched':     
        {'files': {1:50, 2:500},        'episodes': {1:550, 2:500}},
@@ -469,92 +306,52 @@ class Info(Addon, Dialog):
                                                         'skin.xtv-saf':        
        {'files': {1:50, 2:58},         'episodes': {1:50, 2:58}}}
                                
                                # Fetch IDs for current skin
-                               skinID = self.xbmc.getSkinDir()
-                               if skinID in viewModes: return 
viewModes[skinID][content][contentViewMode]
-                               else: return None
+                               try: return 
viewModes[self.xbmc.getSkinDir()][content][contentViewMode]
+                               except: return None
        
-       def log(self, msg, level=2):
-               """
-                       msg             : string - text to output.
-                       level   : [opt] integer - log level to ouput at. 
(default=LOGNOTICE)
-                       
-                       Text is written to the log for the following conditions.
-                       0 - LOGDEBUG
-                       1 - LOGINFO
-                       2 - LOGNOTICE
-                       3 - LOGWARNING
-                       4 - LOGERROR
-                       5 - LOGSEVERE
-                       6 - LOGFATAL
-                       7 - LOGNONE
-               """
-               # Convert Unicode to UTF-8 if needed
-               if isinstance(msg, unicode):
-                       msg = msg.encode("utf8")
-               
-               # Send message to xbmc log
+       def debug(self, msg): self.log(msg, 0)
+       def info(self, msg): self.log(msg, 1)
+       def notice(self, msg): self.log(msg, 2)
+       def warning(self, msg): self.log(msg, 3)
+       def error(self, msg, traceback=False): self.log(msg, 4, traceback)
+       def severe(self, msg, traceback=False): self.log(msg, 5, traceback)
+       def fatal(self, msg, traceback=False): self.log(msg, 6, traceback)
+       def log(self, msg, level=2, traceback=False):
+               if level < 2 and self._devmode is True: level = 7
+               if isinstance(msg, unicode): msg = msg.encode("utf8")
+               if traceback is True: msg = "%s\n%s" % (msg, 
self.traceback.format_exc())
                self.xbmc.log(msg, level)
        
-       def setDebugMsg(self, exceptionName="", errorMsg=""):
-               """ Recives a *list of mesages to print """
-               if isinstance(exceptionName, int): exceptionName = 
self.getstr(exceptionName)
-               if isinstance(errorMsg, int): errorMsg = self.getstr(errorMsg)
-               self.log("%s: %s" % (exceptionName, errorMsg), 0)
-       
-       def printTraceback(self):
-               """ Print Exception Traceback to log """
-               self.log(self.traceback.format_exc(), 6)
-       
        def executebuiltin(self, function):
-               """ Exacute XBMC Builtin Fuction """
-               
-               # Convert Unicode to UTF-8 if needed
-               if isinstance(function, unicode):
-                       function = function.encode("utf8")
-               
-               # Execute Builtin Function
-               self.xbmc.executebuiltin(function)
-       
-       def executePlugin(self, pluginUrl):
-               """ Execute XBMC plugin """
-               self.executebuiltin(u"XBMC.RunPlugin(%s)" % pluginUrl)
-       
-       def executeAddon(self, addonID):
-               """ Execute XBMC Addon """
-               self.executebuiltin(u"XBMC.RunAddon(%s)" % addonID)
-       
-       def refreshContainer(self):
-               """ Refresh XBMC Container Listing """
-               self.xbmc.executebuiltin("Container.Refresh")
-       
-       def setviewMode(self, viewMode):
-               """ Sets XBMC View Mode, Identified by View Mode ID """
-               self.xbmc.executebuiltin("Container.SetViewMode(%d)" % viewMode)
+               """ Exacute XBMC Builtin Function """
+               if isinstance(function, unicode): 
self.xbmc.executebuiltin(function.encode("utf8"))
+               else: self.xbmc.executebuiltin(function)
        
        def urlencode(self, query):
                # Create Sortcuts
                quote_plus = self.urllib.quote_plus
-               isinstancex = isinstance
-               unicodex = unicode
-               strx = str
+               isinstancel = isinstance
+               unicodel = unicode
+               strl = str
                
                # Parse dict and return urlEncoded string of key and values 
separated by &
-               return "&".join([quote_plus(strx(key)) + "=" + 
quote_plus(value.encode("utf8")) if isinstancex(value, unicodex) else 
quote_plus(strx(key)) + "=" + quote_plus(strx(value)) for key, value in 
query.iteritems()])
+               return "&".join([strl(key) + "=" + 
quote_plus(value.encode("utf8")) if isinstancel(value, unicodel) else strl(key) 
+ "=" + quote_plus(strl(value)) for key, value in query.iteritems()])
        
-       def get_params(self, params):
+       def parse_qs(self, params, asList=False):
                # Convert Unicode to UTF-8 if needed
                if isinstance(params, unicode):
                        params = params.encode("utf8")
                
                # Convert urlEncoded String into a dict and unquote
-               worker = {}
+               qDict = {}
                unquoter = self.urllib.unquote_plus
-               for part in params[params[:1].find("?")+1:].split("&"):
-                       part = unquoter(part)
+               for part in params[params.find("?")+1:].split("&"):
                        try: key, value = part.split("=",1)
-                       except: continue
-                       else: worker[key] = value.decode("utf8")
-               return worker
+                       except: pass
+                       else:
+                               if not asList: qDict[key.lower()] = 
unquoter(value).decode("utf8")
+                               else: qDict[key.lower()] = 
[unquoter(segment).decode("utf8") for segment in value.split(",")]
+               return qDict
        
        def update(self, dicts):
                self._Params.update(dicts)
@@ -574,20 +371,25 @@ class Info(Addon, Dialog):
        def __len__(self):
                return len(self._Params)
        
-       def get(self, key, failobj=None):
+       def get(self, key, default=None):
                if key in self._Params: return self._Params[key]
-               else: return failobj
-       
-       def popitem(self, key):
-               value = self._Params[key]
-               del self._Params[key]
-               return value
+               else: return default
        
        def setdefault(self, key, failobj=None):
                if key in self._Params: return self._Params[key]
                else:
                        self._Params[key] = failobj
                        return failobj
+       
+       def pop(self, key, default=None):
+               if key in self._Params:
+                       value = self._Params[key]
+                       del self._Params[key]
+                       return value
+               elif default:
+                       return default
+               else:
+                       raise KeyError
 
 # Set plugin ID
 plugin = Info()
\ No newline at end of file
diff --git a/script.module.xbmcutil/lib/xbmcutil/listitem.py 
b/script.module.xbmcutil/lib/xbmcutil/listitem.py
index fe2b3b2..2756a94 100644
--- a/script.module.xbmcutil/lib/xbmcutil/listitem.py
+++ b/script.module.xbmcutil/lib/xbmcutil/listitem.py
@@ -22,58 +22,10 @@
 # Import Python System Modules
 import os
 import time
-import urllib
 import functools
 
 # Import Custom Modules
-from xbmcutil import plugin
-
-class Playlist(plugin.xbmc.PlayList):
-       """ Wrapper for XBMC Playlist """
-       def __init__(self, playlistType):
-               """ Retrieve a reference from a valid xbmc playlist
-               
-                       0 : xbmc.PLAYLIST_MUSIC
-                       1 : xbmc.PLAYLIST_VIDEO
-               """
-               
-               # Initiate Overriding, in obj Classs Method
-               super(Playlist, self).__init__()
-               self.clear()
-       
-       def add_iter(self, listitems):
-               """ Accepts a iterable of (url, listitem, isfolder) """
-               for url, listitem, isfolder in listitems:
-                       if isfolder is False: self.add(url, listitem)
-
-class DialogProgress(plugin.xbmcgui.DialogProgress):
-       def __init__(self, heading, line1, line2="", line3=""):
-               # Initiate Overriding, in obj Classs Method
-               self.subClass = super(DialogProgress, self)
-               self.subClass.__init__()
-               
-               # Create Progress Dialog
-               self.lines = [line1,line2,line3]
-               self.create(heading, line1, line2, line3)
-               self.update(0)
-       
-       def updateLine1(self, line):
-               self.lines[0] = line
-       
-       def updateLine2(self, line):
-               self.lines[1] = line
-       
-       def updateLine3(self, line):
-               self.lines[2] = line
-       
-       def update(self, percent, line1=None, line2=None, line3=None):
-               # Add updated line if available
-               if line1 != None: self.lines[0] = line1
-               if line2 != None: self.lines[1] = line2
-               if line3 != None: self.lines[2] = line3
-               
-               # Initeate Overriding, in obj Classs Method
-               self.subClass.update(int(percent), *self.lines)
+from xbmcutil import plugin, cleanup
 
 class ListItem(plugin.xbmcgui.ListItem):
        """
@@ -84,20 +36,19 @@ class ListItem(plugin.xbmcgui.ListItem):
        _strptime = time.strptime
        _strftime = time.strftime
        _handleZero = _plugin.handleZero
-       _handelThree = _plugin.handleThree
        _selfObject = _plugin.xbmcgui.ListItem
        _urlencode = _plugin.urlencode
-       _addonName = _plugin.getName()
-       _fanartImage = _plugin.getFanartImage()
-       _imageGlobal = _plugin.getImageLocation(local=False)
-       _imageLocal = _plugin.getImageLocation(local=True)
-       _stringDownload = _plugin.getuni(33003)
-       _strRelated = _plugin.getuni(32966)
-       _staticMenu = ([(_plugin.getuni(20159), "XBMC.Action(Info)"),
-                                       (_plugin.getuni(13347), 
"XBMC.Action(Queue)"),
-                                       (_plugin.getuni(184), 
"XBMC.Container.Update(%srefresh=true)" % _handelThree)],
-                                  [(_plugin.getuni(1045), 
"XBMC.RunPlugin(%s?action=system.opensettings)" % _handleZero),
-                                       (_plugin.getuni(184), 
"XBMC.Container.Update(%srefresh=true)" % _handelThree)])
+       _addonName = _plugin.getAddonInfo("name")
+       _fanartImage = _plugin.translatePath(_plugin.getAddonInfo("fanart"))
+       _imageGlobal = os.path.join(_plugin.getGlobalPath(), "resources", 
"media", "%s")
+       _imageLocal = os.path.join(_plugin.getLocalPath(), "resources", 
"media", "%s")
+       _strRelated = _plugin.getuni(32904) # 32904 = Related Videos
+       _folderMenu = [("$LOCALIZE[1045]", 
"XBMC.RunPlugin(%s?action=system.opensettings)" % _handleZero), # 1045 = Add-on 
Settings
+                                  ("$LOCALIZE[184]", 
"XBMC.Container.Update(%srefresh=true)" % _plugin.handleThree)] # 184 = Refresh
+       _videoMenu =  [("$LOCALIZE[20159]", "XBMC.Action(Info)"), # 20159 = 
Video Information
+                                  ("$LOCALIZE[13347]", "XBMC.Action(Queue)"), 
# 13347 = Queue Item
+                                  ("$LOCALIZE[13350]", 
"XBMC.ActivateWindow(videoplaylist)"), # 13350 = Now Playing...
+                                  ("$LOCALIZE[184]", 
"XBMC.Container.Update(%srefresh=true)" % _plugin.handleThree)] # 184 = Refresh
        
        def __init__(self):
                """ Initialize XBMC ListItem Object """
@@ -107,20 +58,16 @@ class ListItem(plugin.xbmcgui.ListItem):
                
                # Set class wide variables
                self.infoLabels = {"studio":self._addonName}
-               self.contextMenu = []
                self.urlParams = {}
                self.streamInfo = {}
-               self.isFolder = True
-               self.isIconSet = False
-               self.isFanartSet = False
-               self.isPlayableSet = False
+               self.contextMenu = []
+               
+               # Pre Define Vars
+               self.icon = None
+               self.fanartImg = None
        
        def setLabel(self, label):
-               """ Sets the listitem's label
-                       
-                       label: string or unicode - text string
-               """
-               self.urlParams["title"] = label.encode("ascii", "ignore")
+               """ Sets the listitem's label """
                self.infoLabels["title"] = label
                self._selfObject.setLabel(self, label)
        
@@ -128,20 +75,19 @@ class ListItem(plugin.xbmcgui.ListItem):
                """ Returns the listitem label as a unicode string"""
                return self._selfObject.getLabel(self).decode("utf8")
        
-       def setIconImage(self, icon=None):
-               """ Sets ListItem's Icon Image
-                       
-                       icon: string - 
(DefaultFolder.png/DefaultVideo.png/DefaultVideoPlaylists.png)
-               """
-               if icon is None: icon = 
("DefaultVideo.png","DefaultFolder.png")[self.isFolder]
-               self._selfObject.setIconImage(self, icon)
-               self.isIconSet = True
+       def setIconImage(self, icon):
+               """ Sets ListItem's Icon Image """
+               self.icon = icon
+       
+       def setFanartImage(self, fanart):
+               """ Sets ListItem's Fanart Image """
+               self.fanartImg = fanart
        
        def setThumbnailImage(self, image, local=0):
                """ Sets ListItem's Thumbnail Image
                        
                        image: string - Path to thumbnail image, (local or 
remote)
-                       local: integer - (0/1/2) - Changes image path to point 
to (Remote/Local/Global) Filesystem
+                       local: integer - (0/1/2) - Changes image path to point 
to (Remote/Local/Global)
                """
                if   local is 0: self._selfObject.setThumbnailImage(self, image)
                elif local is 1: self._selfObject.setThumbnailImage(self, 
self._imageLocal % image)
@@ -162,20 +108,17 @@ class ListItem(plugin.xbmcgui.ListItem):
                if key and value: self.streamInfo[key] = value
                if kwargs: self.streamInfo.update(kwargs)
        
-       def getInfoItem(self, key, fbObject=None):
-               """ Return specifiyed Key form infolabels """
-               if key in self.infoLabels: return self.infoLabels[key]
-               else: return fbObject
-       
-       def getParamItem(self, key, fbObject=None):
-               """ Return specifiyed key from urlparams """
-               if key in self.urlParams: return self.urlParams[key]
-               else: return fbObject
-       
-       def getStreamItem(self, key, fbObject=None):
-               """ Return specifiyed key from streamInfo """
-               if key in self.streamInfo: return self.streamInfo[key]
-               else: return fbObject
+       def setDateInfo(self, date, dateFormat):
+               """ Sets Date Info Label
+                       
+                       date: string - Date of list item
+                       dateFormat: string - Format of date string for strptime 
conversion
+               """
+               convertedDate = self._strptime(date, dateFormat)
+               self.infoLabels["date"] = self._strftime("%d.%m.%Y", 
convertedDate)
+               self.infoLabels["aired"] = self._strftime("%Y-%m-%d", 
convertedDate)
+               self.infoLabels["year"] = self._strftime("%Y", convertedDate)
+               self.infoLabels["dateadded"] = self._strftime("%Y-%m-%d 
%H-%M-%S", convertedDate)
        
        def setDurationInfo(self, duration):
                """ Sets Date duration Label """
@@ -198,30 +141,9 @@ class ListItem(plugin.xbmcgui.ListItem):
                # Set Duration
                self.streamInfo["duration"] = duration
        
-       def setResumePoint(self, startPoint, totalTime=None):
-               """ Set Resume Pont for xbmc to start playing video """
-               self.setProperty("TotalTime", totalTime or 
str(self.streamInfo.get("duration","1")))
-               self.setProperty("ResumeTime", startPoint)
-       
-       def setDateInfo(self, date, dateFormat):
-               """ Sets Date Info Label
-                       
-                       date: string - Date of list item
-                       dateFormat: string - Format of date string for strptime 
conversion
-               """
-               convertedDate = self._strptime(date, dateFormat)
-               self.infoLabels["date"] = self._strftime("%d.%m.%Y", 
convertedDate)
-               self.infoLabels["aired"] = self._strftime("%Y-%m-%d", 
convertedDate)
-               self.infoLabels["year"] = self._strftime("%Y", convertedDate)
-       
-       def setFanartImage(self, fanart=None):
-               """ Sets ListItem's Fanart Image
-                       
-                       fanart: string - Path to fanart image, if not set 
defaults to fanart of addon
-               """
-               if fanart is None: fanart = self._fanartImage
-               self.setProperty("Fanart_Image", fanart)
-               self.isFanartSet = True
+       def setAudioInfo(self, codec="aac", language="en", channels=2):
+               """ Set Default Audio Info """
+               self.addStreamInfo("audio", {"codec":codec, 
"language":language, "channels":channels})
        
        def setQualityIcon(self, HD=False):
                """ Enable Listitem's HD|SD Overlay Iron """
@@ -234,9 +156,10 @@ class ListItem(plugin.xbmcgui.ListItem):
                        self.streamInfo["width"] = 768
                        self.streamInfo["height"] = 576
        
-       def setAudioInfo(self, codec="aac", language="en", channels=2):
-               """ Set Default Audio Info """
-               self.addStreamInfo("audio", {"codec":codec, 
"language":language, "channels":channels})
+       def setResumePoint(self, startPoint, totalTime=None):
+               """ Set Resume Pont for xbmc to start playing video """
+               self.setProperty("totaltime", totalTime or 
str(self.streamInfo.get("duration","1")))
+               self.setProperty("resumetime", startPoint)
        
        def addRelatedContext(self, **params):
                """ Adds a context menu item to link to related videos """
@@ -254,140 +177,155 @@ class ListItem(plugin.xbmcgui.ListItem):
                if params: command += "(%s?%s)" % (self._handleZero, 
self._urlencode(params))
                self.contextMenu.append((label, command))
        
-       def setIsPlayable(self, isPlayable=False):
-               """ Sets the listitem's playable flag """
-               self.isPlayableSet = True
-               self.isFolder = not isPlayable
-               self.setProperty("IsPlayable", str(isPlayable).lower())
-               self.setProperty(("Folder","Video")[isPlayable], "true")
-       
        def setIdentifier(self, identifier):
                """ Sets Unique Identifier for Watched Flags """
                self.urlParams["identifier"] = identifier
        
-       def getPath(self):
-               """ Returns urlParams as a string """
-               return self._handleZero + "?" + self._urlencode(self.urlParams)
-       
-       def finalize(function):
-               """ Wrapper for get Listitem to finalize creation of listitem 
for XBMC
+       def getListitemTuple(self, isPlayable=False):
+               """ Returns a tuple of listitem properties, (path, listitem, 
isFolder) """
+               infoLabels = self.infoLabels
+               urlParams = self.urlParams
+               
+               # Set XBMC InfoLabels and StreamInfo
+               self.setInfo("video", infoLabels)
+               if self.streamInfo: self.addStreamInfo("video", self.streamInfo)
+               
+               # Set Listitem Fanart Image
+               if self.fanartImg: self.setProperty("fanart_image", 
self.fanartImg)
+               else: self.setProperty("fanart_image", self._fanartImage)
+               
+               if isPlayable is True:
+                       # Change XBMC Propertys to mark as Playable
+                       self.setProperty("isplayable","true")
+                       self.setProperty("video","true")
+                       
+                       # Add title to urlParams for the Download title
+                       urlParams["title"] = 
infoLabels["title"].encode("ascii","ignore")
+                       
+                       # If not a live video then add Download option in 
context menu
+                       path = "%s?%s" % (self._handleZero, 
self._urlencode(urlParams))
+                       if not "live" in urlParams: 
self.contextMenu.append(("$LOCALIZE[33003]", "XBMC.RunPlugin(%s&download=true)" 
% path))
+                       
+                       # Set XBMC icon image
+                       if self.icon: self._selfObject.setIconImage(self, 
self.icon)
+                       else: self._selfObject.setIconImage(self, 
"DefaultVideo.png")
                        
-                       isPlayable: boolean - (True/False) - Lets XBMC know if 
listitem is a playable source - Default=False
-                       infoType: string - (video/music/pictures) - Lets XBMC 
know the type of content been listed - Default="video"
-               """
-               def wrapped(self, isPlayable=False, infoType="video"):
-                       # If markers are not set, set sections
-                       if not self.isPlayableSet: 
self.setIsPlayable(isPlayable)
-                       if not self.isFanartSet: self.setFanartImage()
-                       if not self.isIconSet: self.setIconImage()
-                       # Set info, steam into and path where available
-                       if self.infoLabels: self.setInfo(infoType, 
self.infoLabels)
-                       if self.streamInfo: self.addStreamInfo(infoType, 
self.streamInfo)
-                       self.path = self.getPath()
                        # Add context menu items
-                       if not self.isFolder and not "live" in self.urlParams: 
self.addContextMenuItem(self._stringDownload, 
"XBMC.RunPlugin(%s&download=true)" % (self.path))
-                       self.addContextMenuItems(self.contextMenu + 
self._staticMenu[self.isFolder], replaceItems=not isPlayable)
-                       # Call Decorated Function ad return it response
-                       return function(self)
-               return wrapped
-       
-       @finalize
-       def getListitemTuple(self):
-               """ Returns a tuple of listitem properties, (path, _listitem, 
isFolder) """
-               return self.path, self, self.isFolder
-       
-       @finalize
-       def getListitem(self):
-               """ Returns the wrapped xbmcgui.ListItem """
-               return self
+                       self.addContextMenuItems(self.contextMenu + 
self._videoMenu, replaceItems=False)
+                       
+                       # Return Tuple of url, listitem, isFolder
+                       return (path, self, False)
+               
+               else:
+                       # Change XBMC Propertys to mark as Folder
+                       self.setProperty("isplayable","false")
+                       self.setProperty("video","true")
+                       
+                       # Set XBMC icon image
+                       if self.icon: self._selfObject.setIconImage(self, 
self.icon)
+                       else: self._selfObject.setIconImage(self, 
"DefaultFolder.png")
+                       
+                       # Add context menu items
+                       self.addContextMenuItems(self.contextMenu + 
self._folderMenu, replaceItems=True)
+                       
+                       # Return Tuple of url, listitem, isFolder
+                       return ("%s?%s" % (self._handleZero, 
self._urlencode(urlParams)), self, True)
        
        @classmethod
-       def add_item(cls, label=None, label2=None, icon=None, thumbnail=None, 
url={}, info={}, isPlayable=False, infoType="video"):
+       def add_item(cls, label=None, icon=None, thumbnail=None, url={}, 
info={}, isPlayable=False):
                """ A Listitem constructor for creating a XBMC listitem object
                        
                        label: string - Title of listitem
-                       label2: string - Secondary lable of listitem
                        icon: string - Image for listitem icon
                        thumbnail: list/tuple - (image/0) Thumbnail Image for 
listitem / Image location identifier
                        url: dict - Dictionary containing url params to control 
addon
                        info: dict - Dictionary containing information about 
video 
                        isPlayable: boolean - (True/False) - Lets XBMC know if 
listitem is a playable source - Default=False
-                       infoType: string - (video/music/pictures) - Lets XBMC 
know the type of content been listed - Default="video"
                """
                listitem = cls()
                if label: listitem.setLabel(label)
-               if label2: listitem.setLabel2(label2)
-               if icon: listitem.setIconImage(icon)
+               if icon: listitem.icon = icon
                if thumbnail: listitem.setThumbnailImage(*thumbnail)
                if url: listitem.urlParams.update(url)
                if info: listitem.infoLabels.update(info)
-               return listitem.getListitemTuple(isPlayable, infoType)
+               return listitem.getListitemTuple(isPlayable)
        
        @classmethod
-       def add_next_page(cls, url={}, infoType="video"):
+       def add_next_page(cls, url={}):
                """ A Listitem constructor for Next Page Item
                        
                        url: dict - Dictionary containing url params to control 
addon
-                       infoType: string - (video/music/pictures) - Lets XBMC 
know the type of content been listed - Default="video"
                """
-               nextCount = int(cls._plugin.get("NextPageCount",1)) + 1
+               nextCount = int(cls._plugin.get("nextpagecount",1)) + 1
                if not "action" in url and "action" in cls._plugin: 
url["action"] = cls._plugin["action"]
-               url["NextPageCount"] = nextCount
+               url["nextpagecount"] = nextCount
                url["updatelisting"] = "true"
-               label = u"%s %i" % (cls._plugin.getuni(33078), nextCount)
-               return cls.add_item(label, thumbnail=(u"next.png", 2), url=url, 
infoType=infoType)
+               label = u"%s %i" % (cls._plugin.getuni(33078), nextCount) # 
33078 = Next Page
+               listitem = cls()
+               listitem.setLabel(label)
+               listitem.setThumbnailImage(u"next.png", 2)
+               listitem.urlParams.update(url)
+               return listitem.getListitemTuple(False)
        
        @classmethod
-       def add_search(cls, forwarding, url, label=u"-Search"):
+       def add_search(cls, forwarding, url, label=None):
                """ A Listitem constructor to add Saved Search Support to addon
                        
                        forwarding: string - Addon Action to farward on to
                        url: string - Base url to combine with search term
                        label: string - Lable of Listitem
                """
-               return cls.add_item(label, thumbnail=(u"search.png", 2), 
url={"action":"system.search", "forwarding":forwarding, "url":url})
+               listitem = cls()
+               if label: listitem.setLabel(label)
+               else: listitem.setLabel(u"-%s" % cls._plugin.getuni(137)) # 137 
= Search
+               listitem.setThumbnailImage(u"search.png", 2)
+               listitem.urlParams.update({"action":"system.search", 
"forwarding":forwarding, "url":url})
+               return listitem.getListitemTuple(False)
        
        @classmethod
-       def add_youtube_channel(cls, channelID, label=None, hasPlaylist=False):
+       def add_youtube_channel(cls, channelID, label=None, hasPlaylist=False, 
hasHD=None):
                """ A Listitem constructor to add a youtube channel to addon
                        
                        channelID: string - Youtube channel ID to add
                        label: string - Title of listitem - default (-Youtube 
Channel)
                        hasPlaylist: boolean - True/False if channel ID 
contains any playlists - default (False) - (soon to be obsolete)
                """
-               if label is None: label = u"-" + cls._plugin.getuni(32963)
-               return cls.add_item(label, thumbnail=(u"youtube.png", 2), 
url={"action":"system.videohosts.YTChannelUploads", "url":channelID, 
"hasPlaylists":unicode(hasPlaylist).lower()})
+               listitem = cls()
+               if label: listitem.setLabel(label)
+               else: listitem.setLabel(u"-" + cls._plugin.getuni(32901)) # 
32901 = Youtube Channel
+               listitem.setThumbnailImage(u"youtube.png", 2)
+               
listitem.urlParams.update({"action":"system.videohosts.YTChannelUploads", 
"url":channelID, "hasplaylists":str(hasPlaylist).lower(), 
"hashd":str(hasHD).lower()})
+               return listitem.getListitemTuple(False)
        
        @classmethod
-       def add_youtube_playlist(cls, playlistID, label=None):
+       def add_youtube_playlist(cls, playlistID, label=None, hasHD=None):
                """ A Listitem constructor to add a youtube playlist to addon 
                        
                        playlistID: string - Youtube playlist ID to add
                        label: string - Title of listitem - default (-Youtube 
Playlist)
                """
-               if label is None: label = u"-" + cls._plugin.getuni(32964)
-               return cls.add_item(label, icon="DefaultVideoPlaylists.png", 
thumbnail=(u"youtubeplaylist.png", 2), 
url={"action":"system.videohosts.YTPlaylistVideos", "url":playlistID})
+               listitem = cls()
+               if label: listitem.setLabel(label)
+               else: listitem.setLabel(u"-" + cls._plugin.getuni(32902)) # 
32902 = Youtube Playlist
+               listitem.icon = "DefaultVideoPlaylists.png"
+               listitem.setThumbnailImage(u"youtubeplaylist.png", 2)
+               
listitem.urlParams.update({"action":"system.videohosts.YTPlaylistVideos", 
"url":playlistID, "hashd":str(hasHD).lower()})
+               return listitem.getListitemTuple(False)
        
        @classmethod
-       def add_youtube_playlists(cls, channelID, label=None):
+       def add_youtube_playlists(cls, channelID, label=None, hasHD=None):
                """ A Listitem constructor to add a youtube playlist to addon 
                        
                        channelID: string - Youtube channel ID to list 
playlists from
                        label: string - Title of listitem - default (-Youtube 
Playlist)
                """
-               if label is None: label = u"-" + cls._plugin.getuni(32965)
-               return cls.add_item(label, icon="DefaultVideoPlaylists.png", 
thumbnail=(u"youtubeplaylist.png", 2), 
url={"action":"system.videohosts.YTChannelPlaylists", "url":channelID})
-       
-       @classmethod
-       def add_vimeo_user(cls, channelID, label=None):
-               """ A Listitem constructor to add a youtube channel to addon
-                       
-                       channelID: string - Youtube channel ID to add
-                       label: string - Title of listitem - default (-Youtube 
Channel)
-                       hasPlaylist: boolean - True/False if channel ID 
contains any playlists - default (False) - (soon to be obsolete)
-               """
-               if label is None: label = u"-" + cls._plugin.getuni(32967)
-               return cls.add_item(label, thumbnail=(u"vimeo.png", 2), 
url={"action":"system.videohosts.VUserVideos", "url":channelID})
+               listitem = cls()
+               if label: listitem.setLabel(label)
+               else: listitem.setLabel(u"-" + cls._plugin.getuni(32903)) # 
32903 = Youtube Playlists
+               listitem.icon = "DefaultVideoPlaylists.png"
+               listitem.setThumbnailImage(u"youtubeplaylist.png", 2)
+               
listitem.urlParams.update({"action":"system.videohosts.YTChannelPlaylists", 
"url":channelID, "hashd":str(hasHD).lower()})
+               return listitem.getListitemTuple(False)
 
 class VirtualFS(object):
        """ Wrapper for XBMC Virtual Directory Listings """
@@ -413,30 +351,33 @@ class VirtualFS(object):
                        self.cacheToDisc = True
                
                # Start Scraper Script
+               self.extraItems = []
                self.add_item = self.item_add(self._listitem.add_item)
                self.add_next_page = self.item_add(self._listitem.add_next_page)
                self.add_search = self.item_add(self._listitem.add_search)
                self.add_youtube_channel = 
self.item_add(self._listitem.add_youtube_channel)
                self.add_youtube_playlist = 
self.item_add(self._listitem.add_youtube_playlist)
                self.add_youtube_playlists = 
self.item_add(self._listitem.add_youtube_playlists)
-               self.add_vimeo_user = 
self.item_add(self._listitem.add_vimeo_user)
                
-               # If a directory listings exists then add to XBMC and Finalize
-               #start = time.time()
+               # Add Listitems to xbmc
                listitems = self.scraper()
-               #self._plugin.log("Elapsed Time: %s" % (time.time() - start))
-               if listitems and listitems is not True: 
self.add_dir_items(listitems)
+               extraItems = self.extraItems
+               if isinstance(listitems, list): extraItems.extend(listitems)
+               if extraItems: self.add_dir_items(extraItems)
+               
+               # Finalize the script
                self.finalize(bool(listitems), self.updateListing, 
self.cacheToDisc)
+               self.cleanup()
        
        def item_add(self, function):
                # Wrap Listitem classmethods to redirect the output to 
add_dir_item
                @functools.wraps(function)
-               def wrapped(*args, **kwargs): self.add_dir_item(function(*args, 
**kwargs))
+               def wrapped(*args, **kwargs): 
self.extraItems.append(function(*args, **kwargs))
                return wrapped
        
        def add_dir_item(self, listitem):
                """ Add Directory List Item to XBMC """
-               self._plugin.xbmcplugin.addDirectoryItem(self._handleOne, 
*listitem)
+               self.extraItems.append(listitem)
        
        def add_dir_items(self, listitems):
                """ Add Directory List Items to XBMC """
@@ -454,19 +395,36 @@ class VirtualFS(object):
        
        def finalize(self, succeeded=True, updateListing=False, 
cacheToDisc=False):
                """ Make the end of directory listings """
-               if succeeded and self.viewID: 
self._plugin.setviewMode(self.viewID)
+               if succeeded and self.viewID: 
self._plugin.executebuiltin("Container.SetViewMode(%d)" % self.viewID)
                self._plugin.xbmcplugin.setPluginFanart(self._handleOne, 
self._listitem._fanartImage)
                self._plugin.xbmcplugin.endOfDirectory(self._handleOne, 
succeeded, updateListing, cacheToDisc)
+       
+       def scraper_speed_check(self):
+               try:
+                       start = time.time()
+                       return self.scraper()
+               finally:
+                       self._plugin.info("Elapsed Time: %s" % (time.time() - 
start))
+       
+       def cleanup(self):
+               currentTime = time.time()
+               try: lastTime = float(plugin.getSetting("lastcleanup")) + 
2419200
+               except ValueError: lastTime = 0
+               if lastTime < currentTime:
+                       plugin.debug("Initiating Cache Cleanup")
+                       import urlhandler
+                       try: urlhandler.CachedResponse.cleanup(604800)
+                       except: plugin.error("Cache Cleanup Failed")
+                       else: plugin.setSetting("lastcleanup", str(currentTime))
 
 class PlayMedia(object):
        """ Class to handle the resolving and playing of video url """
        _plugin = plugin
-       _videoData = _plugin._Params
-       _quotePlus = urllib.quote_plus
+       _quotePlus = _plugin.urllib.quote_plus
        def __init__(self):
                # Fetch Common Vars
-               downloadRequested = self._videoData.get("download") == u"true"
-               vaildFilename = self.validate_filename(self._videoData["title"])
+               downloadRequested = self._plugin.get("download") == u"true"
+               vaildFilename = self.validate_filename(self._plugin["title"])
                downloadPath = self._plugin.getSetting("downloadpath")
                
                # Check if Video has already been downlaoded
@@ -474,7 +432,7 @@ class PlayMedia(object):
                else: downloads = None
                
                # Select witch Video Resolver to use
-               if downloads: self._videoData["url"] = downloads
+               if downloads: self._plugin["url"] = downloads
                elif self.video_resolver() is not True: return None
                self.process_video(downloadRequested, downloadPath, 
vaildFilename)
                
@@ -509,10 +467,10 @@ class PlayMedia(object):
                        # Resolve Video Url using Plugin Resolver
                        resolvedData = self.resolve()
                        if resolvedData and isinstance(resolvedData, dict):
-                               self._videoData.update(resolvedData)
+                               self._plugin.update(resolvedData)
                                return True
                        elif resolvedData:
-                               self._videoData["url"] = resolvedData
+                               self._plugin["url"] = resolvedData
                                return True
                else:
                        # Resolve Video Url using Video Hosts sources
@@ -521,22 +479,27 @@ class PlayMedia(object):
                        elif subaction == u"source":
                                resolvedData = 
self._plugin.error_handler(self.sources)()
                                if resolvedData and isinstance(resolvedData, 
dict):
-                                       self._videoData.update(resolvedData)
+                                       self._plugin.update(resolvedData)
                                        return True
                                elif resolvedData:
-                                       self._videoData["url"] = resolvedData
+                                       self._plugin["url"] = resolvedData
                                        return True
        
-       def sources(self, url=None, urls=None):
+       def sources(self, url=None, urls=None, sourcetype=None):
                # Import Video Resolver
                import videoResolver
-               if url is None: url = self._videoData["url"]
+               if url is None: url = self._plugin["url"]
                
                # Call Specified Source Decoder if Set
-               if "sourcetype" in self._videoData:
+               sourcetype = self._plugin.get("sourcetype", sourcetype)
+               if sourcetype and hasattr(videoResolver, sourcetype.lower()):
                        # Fetch Specified Class
-                       classObject = getattr(videoResolver, 
self._videoData["sourcetype"].lower())()
+                       classObject = getattr(videoResolver, 
sourcetype.lower())()
                        return classObject.decode(url)
+               elif sourcetype:
+                       # Use urlresolver to fetch video url 
+                       import urlresolver
+                       return {"url": urlresolver.HostedMediaFile(url, 
sourcetype.replace(u"_",u".").lower()).resolve()}
                else:
                        # Parse WebPage and Find Video Sources
                        sources = videoResolver.VideoParser()
@@ -550,15 +513,25 @@ class PlayMedia(object):
                                except self._plugin.videoResolver: pass
                                except self._plugin.URLError: pass
                        
+                       # Failed to find a playable video using my own parser, 
Not trying urlResolver
+                       try: import urlresolver
+                       except ImportError: pass
+                       else:
+                               for url in sources.sourceUrls:
+                                       urlObj = 
urlresolver.HostedMediaFile(url)
+                                       if urlObj:
+                                               mediaUrl = urlObj.resolve()
+                                               if mediaUrl: return 
{"url":mediaUrl}
+                       
                        # Unable to Resolve Video Source
-                       raise self._plugin.videoResolver(33077, "Was unable to 
Find Video Url for: %s" % repr(sources.get()))
+                       raise 
self._plugin.videoResolver(self._plugin.getstr(33077), "Was unable to Find 
Video Url for: %s" % repr(sources.get()))
        
        def process_video(self, downloadRequested, downloadPath, vaildFilename):
                # Fetch Video Url / List and Create Listitem
                listitemObj = self._plugin.xbmcgui.ListItem
-               videoTitle = self._videoData["title"].encode("utf8")
+               videoTitle = self._plugin["title"].encode("utf8")
                vaildFilename = vaildFilename.encode("utf8")
-               videoUrl = self._videoData["url"]
+               videoUrl = self._plugin["url"]
                
                # Add Each url to a Playlist
                isIterable = hasattr(videoUrl, "__iter__")
@@ -583,8 +556,8 @@ class PlayMedia(object):
                                                listitem.setLabel(videoTitle % 
count)
                                        
                                        # Add Content Type and urlpath to 
listitem
-                                       if "type" in self._videoData: 
listitem.setMimeType(self._videoData["type"])
-                                       url = self.add_header_pips(url, 
self._videoData.get("useragent"), self._videoData.get("referer"))
+                                       if "type" in self._plugin: 
listitem.setMimeType(self._plugin["type"])
+                                       url = self.add_header_pips(url, 
self._plugin.get("useragent"), self._plugin.get("referer"))
                                        listitem.setPath(url)
                                        prepappend((url, listitem, False))
                        
@@ -593,8 +566,10 @@ class PlayMedia(object):
                                downloader.add_batch_job(prepList)
                        else:
                                # Create Playlist and add items
-                               playlist = Playlist(1)
-                               playlist.add_iter(prepList)
+                               playlist = self._plugin.xbmc.PlayList(1)
+                               playlist.clear()
+                               for url, listitem, isfolder in prepList:
+                                       if isfolder is False: playlist.add(url, 
listitem)
                                
                                # Resolve to first element of playlist
                                self.set_resolved_url(prepList[0][1])
@@ -611,11 +586,11 @@ class PlayMedia(object):
                                downloader.add_job(videoUrl, vaildFilename, 
videoTitle)
                        else:
                                # Add Content Type and Header Pips if any
-                               if "item" in self._videoData: listitem = 
self._videoData["item"]
+                               if "item" in self._plugin: listitem = 
self._plugin["item"]
                                else: listitem = listitemObj()
                                
-                               if "type" in self._videoData: 
listitem.setMimeType(self._videoData["type"])
-                               listitem.setPath(self.add_header_pips(videoUrl, 
self._videoData.get("useragent"), self._videoData.get("referer")))
+                               if "type" in self._plugin: 
listitem.setMimeType(self._plugin["type"])
+                               listitem.setPath(self.add_header_pips(videoUrl, 
self._plugin.get("useragent"), self._plugin.get("referer")))
                                self.set_resolved_url(listitem)
        
        def add_header_pips(self, url, useragent, referer):
@@ -663,7 +638,7 @@ class DownloadMGR(object):
        
        def get_download_path(self):
                """ Asks for Download Path """
-               downloadPath = self._plugin.browseSingle(3, 
self._plugin.getuni(32933), u"video", u"", False, False, "")
+               downloadPath = self._plugin.browseSingle(3, 
self._plugin.getuni(33010), u"video", u"", False, False, "") # 33010 = Set 
Download Directory
                if downloadPath: self._plugin.setSetting("downloadpath", 
downloadPath)
                return downloadPath
        
@@ -676,7 +651,7 @@ class DownloadMGR(object):
        
        def add_job(self, url, filename, title=None):
                # Check if url is a Plugin instead of a video Url
-               if url.startswith("plugin:"): return 
self._plugin.executePlugin(url)
+               if url.startswith("plugin:"): return 
self._plugin.executebuiltin("XBMC.RunPlugin(%s)" % url)
                elif not self.params["download_path"]: return None
                else:
                        # Guess Full Filename
diff --git a/script.module.xbmcutil/lib/xbmcutil/storageDB.py 
b/script.module.xbmcutil/lib/xbmcutil/storageDB.py
index f8f3312..20a126c 100644
--- a/script.module.xbmcutil/lib/xbmcutil/storageDB.py
+++ b/script.module.xbmcutil/lib/xbmcutil/storageDB.py
@@ -93,7 +93,7 @@ class Metadata(dictStorage):
        def __init__(self):
                # Check if UserData Exists
                from xbmcutil import plugin
-               systemMetaData = os.path.join(plugin.getPath(), u"resources", 
u"metadata.json")
+               systemMetaData = os.path.join(plugin.getLocalPath(), 
u"resources", u"metadata.json")
                userMetaData = os.path.join(plugin.getProfile(), 
u"metadata.json")
                if os.path.isfile(systemMetaData) and not 
os.path.isfile(userMetaData):
                        import shutil
@@ -118,7 +118,7 @@ class SavedSearches(listitem.VirtualFS):
                                
                # Call Search Dialog if Required
                if "remove" in plugin and plugin["remove"] in self.searches:
-                       self.searches.remove(plugin.popitem("remove"))
+                       self.searches.remove(plugin.pop("remove"))
                        self.searches.sync()
                elif "search" in plugin:
                        self.search_dialog(plugin["url"])
@@ -131,7 +131,7 @@ class SavedSearches(listitem.VirtualFS):
                params["search"] = "true"
                params["updatelisting"] = "true"
                params["cachetodisc"] = "true"
-               self.add_item(label=u"-Search", url=params, isPlayable=False)
+               self.add_item(label=u"-%s" % plugin.getuni(137), url=params, 
isPlayable=False) # 137 = Search
                
                # Set Content Properties
                self.set_sort_methods(self.sort_method_video_title)
@@ -145,11 +145,8 @@ class SavedSearches(listitem.VirtualFS):
                        self.searches.close()
        
        def search_dialog(self, urlString):
-               # Call Search Dialog
-               searchTerm = plugin.dialogSearch()
-               
                # Add searchTerm to database
-               self.searches.add(searchTerm)
+               self.searches.add(plugin.dialogSearch())
                self.searches.sync()
        
        def list_searches(self):
@@ -163,7 +160,7 @@ class SavedSearches(listitem.VirtualFS):
                baseAction = plugin["forwarding"]
                
                # Create Context Menu item Params
-               strRemove = plugin.getuni(1210)
+               strRemove = plugin.getuni(1210) # 1210 = Remove
                params = plugin._Params.copy()
                params["updatelisting"] = "true"
                
diff --git a/script.module.xbmcutil/lib/xbmcutil/urlhandler.py 
b/script.module.xbmcutil/lib/xbmcutil/urlhandler.py
index 8affb42..b24058b 100644
--- a/script.module.xbmcutil/lib/xbmcutil/urlhandler.py
+++ b/script.module.xbmcutil/lib/xbmcutil/urlhandler.py
@@ -29,17 +29,17 @@ from hashlib import md5
 
 #################################################################
 
-def urlopen(url, maxAge=None, data=None, headers={}, userAgent=1):
+def urlopen(url, maxAge=None, data=None, headers={}, userAgent=1, 
stripEntity=False):
        ''' Makes Request and Return Response Object '''
        handle = HttpHandler()
-       handle.add_response_handler(userAgent)
+       handle.add_response_handler(userAgent, stripEntity=stripEntity)
        if maxAge is not None: handle.add_cache_handler(maxAge)
        return handle.open(url, data, headers)
 
-def urlread(url, maxAge=None, data=None, headers={}, userAgent=1):
+def urlread(url, maxAge=None, data=None, headers={}, userAgent=1, 
stripEntity=True):
        ''' Makes Request and Return Response Data '''
        handle = HttpHandler()
-       handle.add_response_handler(userAgent, stripEntity=True)
+       handle.add_response_handler(userAgent, stripEntity=stripEntity)
        if maxAge is not None: handle.add_cache_handler(maxAge)
        resp = handle.open(url, data, headers)
        data = resp.read()
@@ -62,12 +62,6 @@ def urlretrieve(url, filename):
 
 #################################################################
 
-def parse_qs(url):
-       # Strip url down to Query String
-       if u"#" in url: url = url[:url.find(u"#")]
-       if u"?" in url: url = url[url.find(u"?")+1:]
-       return dict(part.split(u"=",1) for part in url.split(u"&"))
-
 def strip_tags(html):
        # Strips out html code and return plan text
        sub_start = html.find(u"<")
@@ -78,28 +72,19 @@ def strip_tags(html):
                sub_end = html.find(u">")
        return html
 
-def search(urlString=u""):
-       # Open KeyBoard Dialog
-       ret = plugin.keyBoard("", plugin.getstr(16017), False)
-       
-       # Check if User Entered Any Data
-       if ret and urlString: return urlString % ret
-       elif ret: return ret
-       else: raise plugin.URLError(0, "User Cannceled The Search KeyBoard 
Dialog")
-
 def redirect(url, data=None, headers={}):
        # Convert url to ascii if needed
        if isinstance(url, unicode): url = url.encode("ascii")
        
        # Log for Debuging
-       plugin.log(url + " - Redirected To:", 0)
+       plugin.debug(url + " - Redirected To:")
        
        # Split url into Components
        splitUrl = urlparse.urlsplit(url)
        
        # Create Connection Object, HTTP or HTTPS
-       if splitUrl[0] == "http": conn = httplib.HTTPConnection(splitUrl[1])
-       elif splitUrl[0] == "https": conn = httplib.HTTPSConnection(splitUrl[1])
+       if splitUrl[0] == "http": conn = httplib.HTTPConnection(splitUrl[1], 
timeout=10)
+       elif splitUrl[0] == "https": conn = 
httplib.HTTPSConnection(splitUrl[1], timeout=10)
        
        # Set Request Mothods
        if data is not None:
@@ -111,23 +96,28 @@ def redirect(url, data=None, headers={}):
        
        # Make Request to Server
        try: conn.request(method, urlparse.urlunsplit(splitUrl), data, headers)
-       except: raise plugin.URLError(32910, "Failed to Make Request for 
Redirected Url")
+       except httplib.HTTPException as e: raise plugin.URLError(str(e), 
"Failed to Make Request for Redirected Url")
        
        # Fetch Headers from Server
        try:
                resp = conn.getresponse()
-               plugin.log("%s - %s" % (resp.status, resp.reason), 0)
+               plugin.debug("%s - %s" % (resp.status, resp.reason))
                headers = dict(resp.getheaders())
                conn.close()
-       except: raise plugin.URLError(32910, "Failed to Read Server Response")
+       except httplib.HTTPException as e: raise plugin.URLError(str(e), 
"Failed to Read Redirected Server Response")
        
        # Fetch Redirect Location
        if "location" in headers: url = headers["location"]
        elif "uri" in headers: url = headers["uri"]
        else: url = ""
-       plugin.log(url, 0)
+       plugin.debug(url)
        return url.decode("ascii")
 
+class withaddinfourl(urllib2.addinfourl):
+       # Methods to add support for with statement
+       def __enter__(self): return self
+       def __exit__(self, *exc_info): self.close()
+
 #################################################################
 
 class HttpHandler:
@@ -142,9 +132,9 @@ class HttpHandler:
                ''' Adds Response Handler to Urllib to Handle Compression and 
unescaping '''
                self.handleList.append(ResponseHandler(userAgent, compressed, 
stripEntity))
        
-       def add_cache_handler(self, maxAge=0, cacheLocal=u"urlcache", 
asUrl=None):
+       def add_cache_handler(self, maxAge=0, asUrl=None):
                ''' Adds Cache Handler to Urllib to Handle Caching of Source '''
-               self.handleList.append(CacheHandler(maxAge, cacheLocal, asUrl))
+               self.handleList.append(CacheHandler(maxAge, asUrl))
        
        def add_authorization(self, username, password):
                ''' Adds Basic Authentication to Requst '''
@@ -162,13 +152,13 @@ class HttpHandler:
                # Make Url Connection, Save Cookie If Set and Return Response
                opener = urllib2.build_opener(*self.handleList)
                try: return opener.open(request, timeout=timeout)
-               except socket.timeout: raise plugin.URLError(32904, "Server 
Request Timed Out")
-               except urllib2.URLError: raise plugin.URLError(32909, "An 
Unexpected UrlError Occurred")
+               except socket.timeout as e: raise plugin.URLError(str(e))
+               except urllib2.URLError as e: raise plugin.URLError(str(e))
 
 class ErrorHandler(urllib2.HTTPDefaultErrorHandler):
        ''' Default Error Handler for Reporting The Error Code to XBMC '''
        def http_error_default(self, req, fp, code, msg, hdrs):
-               raise plugin.URLError(msg, "HTTPError %s:%s" % (code, msg))
+               raise plugin.URLError("HTTPError %s:%s" % (code, msg))
 
 class Authorization(urllib2.BaseHandler):
        def __init__(self, username, password):
@@ -222,11 +212,11 @@ class HTTPCookieProcessor(urllib2.BaseHandler):
                loginPage = self.loginPage
                if loginPage and (headers.get("location") == loginPage or 
headers.get("uri") == loginPage):
                        # Check if Logon has already happend within current 
session
-                       if self.logonAtempted is True: raise 
plugin.URLError(32914, "Logon Already Atempted, Stopping infinite loop")
+                       if self.logonAtempted is True: raise 
plugin.URLError(plugin.getstr(32806), "Logon Already Atempted, Stopping 
infinite loop")
                        else: self.logonAtempted = True
                        
                        # Login to site and create session cookie
-                       plugin.log("Sending Login Data")
+                       plugin.debug("Sending Login Data")
                        urllogin(**self.loginData)
                        
                        # Resend Request for Data with new session cookie
@@ -270,7 +260,7 @@ class ResponseHandler(urllib2.BaseHandler):
                if self.userAgent and not request.has_header("User-Agent"): 
request.add_header("User-Agent", self.userAgent)
                if self.compressed: request.add_header("Accept-Encoding", 
"gzip, deflate")
                request.add_header("Accept-Language", "en-gb,en-us,en")
-               plugin.log(request.get_full_url())
+               plugin.notice(request.get_full_url())
                return request
        
        def handle_response(self, response):
@@ -286,8 +276,8 @@ class ResponseHandler(urllib2.BaseHandler):
                        elif contentEncoding and "deflate" in contentEncoding: 
data = zlib.decompress(response.read())
                        else: data = response.read()
                
-               except zlib.error:
-                       raise plugin.URLError(32912, "Failed to Decompress 
Response Body")
+               except zlib.error as e:
+                       raise plugin.URLError(plugin.getstr(32804), str(e))
                
                else:
                        # Convert content to unicode and back to utf-8 to fix 
any issues
@@ -298,13 +288,13 @@ class ResponseHandler(urllib2.BaseHandler):
                                        if charset: contentCharset = charset[0]
                        
                                # Attempt to decode Response to unicode
-                               if not contentCharset: contentCharset = 
"utf-8"; plugin.log("Response encoding not specified, defaulting to UTF-8", 0)
+                               if not contentCharset: contentCharset = 
"utf-8"; plugin.debug("Response encoding not specified, defaulting to UTF-8")
                                try: data = unicode(data, 
contentCharset.lower())
                                except:
                                        # Attempt to decode using iso-8859-1 
(latin-1)
-                                       plugin.log("Specified encoding failed, 
reverting to iso-8859-1 (latin-1)", 0)
+                                       plugin.debug("Specified encoding 
failed, reverting to iso-8859-1 (latin-1)")
                                        try: data = unicode(data, "iso-8859-1")
-                                       except: raise plugin.URLError(32913, 
"Unable to Decode response to unicode")
+                                       except UnicodeDecodeError as e: raise 
plugin.URLError(plugin.getstr(32805), str(e))
                                
                                # Unescape the content if requested
                                if self.stripEntity: data = 
self.unescape(data).encode("utf-8")
@@ -315,7 +305,7 @@ class ResponseHandler(urllib2.BaseHandler):
                        response.close()
                
                # Return Data Wraped in an addinfourl Object
-               addInfo = urllib2.addinfourl(StringIO.StringIO(data), headers, 
response.url, response.code)
+               addInfo = withaddinfourl(StringIO.StringIO(data), headers, 
response.url, response.code)
                addInfo.msg = response.msg
                return addInfo
        
@@ -337,12 +327,11 @@ class ResponseHandler(urllib2.BaseHandler):
                                except KeyError: return text
                
                # Return Clean string using accepted encoding
-               try: return re.sub("&#?\w+;", fixup, text)
-               except: raise plugin.URLError(32913, "HTML Entity Decoding 
Failed")
+               return re.sub("&#?\w+;", fixup, text)
        
        def http_response(self, request, response):
                ''' Returns a Decompress Version of the response '''
-               plugin.log("%s - %s" % (response.code, response.msg), 0)
+               plugin.debug("%s - %s" % (response.code, response.msg))
                if response.code is not 200 or response.info().get("X-Cache") 
== "HIT": return response
                else: return self.handle_response(response)
        
@@ -352,10 +341,9 @@ class ResponseHandler(urllib2.BaseHandler):
 
 class CacheHandler(urllib2.BaseHandler):
        '''Stores responses in a persistant on-disk cache'''
-       def __init__(self, maxAge=0, cacheLocal=u"urlcache", asUrl=None):
+       def __init__(self, maxAge=0, asUrl=None):
                global time
                import time
-               self.cacheLocal = cacheLocal
                self.maxAge = maxAge
                self.redirect = False
                self.url = asUrl
@@ -378,37 +366,50 @@ class CacheHandler(urllib2.BaseHandler):
                        
                        # Create Cache Path
                        urlHash = md5(url).hexdigest()
-                       plugin.log("UrlHash = " + urlHash, 0)
-                       self.CachePath = os.path.join(plugin.getProfile(), 
self.cacheLocal, urlHash + u".%s")
-               
-               # Check Status of Cache
-               if CachedResponse.exists(self.CachePath):
-                       # If Refresh Param Exists Then Reset 
-                       if "refresh" in plugin: 
CachedResponse.reset(self.CachePath, (0,0))
+                       plugin.debug("UrlHash = %s" % urlHash)
+                       self.CachePath = CachePath = 
os.path.join(plugin.getProfile(), "urlcache", urlHash + u".%s")
                        
-                       # Check if Cache is Valid
-                       if self.maxAge == -1 or 
CachedResponse.isValid(self.CachePath, self.maxAge):
-                               plugin.log("Cached")
-                               # Return Cached Response
-                               return CachedResponse(self.CachePath)
-                       else:
-                               plugin.log("Cache Not Valid")
+                       # Check Status of Cache
+                       if CachedResponse.exists(CachePath):
+                               # If Refresh Param Exists Then Reset 
+                               if "refresh" in plugin: 
CachedResponse.reset(CachePath, (0,0))
+                               maxAge = self.maxAge
+                               
+                               # Check if Cache is Valid and return Cached 
Response if valid
+                               if not maxAge == 0:
+                                       if maxAge == -1 or 
CachedResponse.isValid(CachePath, maxAge):
+                                               plugin.notice("Cached")
+                                               try: return 
CachedResponse(CachePath)
+                                               except plugin.CacheError as e:
+                                                       
CachedResponse.remove(self.CachePath)
+                                                       plugin.error(e.debugMsg)
+                                                       return None
+                                       else:
+                                               plugin.notice("Cache Not Valid")
+                               
                                # Set If-Modified-Since & If-None-Match Headers
-                               cacheHeaders = 
CachedResponse.loadHeaders(self.CachePath)
+                               cacheHeaders = 
CachedResponse.loadHeaders(CachePath)
                                if "Last-Modified" in cacheHeaders:
                                        # Add If-Modified-Since Date to Request 
Headers
                                        request.add_header("If-Modified-Since", 
cacheHeaders["Last-Modified"])
                                if "ETag" in cacheHeaders:
                                        # Add If-None-Match Etag to Request 
Headers
                                        request.add_header("If-None-Match", 
cacheHeaders["ETag"])
+                       else:
+                               plugin.debug("Cache Not Found")
        
        def http_response(self, request, response):
                ''' Store Server Response into Cache '''
                # Save response to cache and return it if status is 200 else 
return response untouched
                self.redirect = False
                if response.code is 200 and not response.info().get("X-Cache") 
== "HIT":
-                       CachedResponse.store_in_cache(self.CachePath, response)
-                       return CachedResponse(self.CachePath)
+                       try:
+                               CachedResponse.store_in_cache(self.CachePath, 
response)
+                               return CachedResponse(self.CachePath)
+                       except plugin.CacheError as e:
+                               CachedResponse.remove(self.CachePath)
+                               plugin.error(e.debugMsg)
+                               return response
                elif response.code in (301,302,303,307):
                        self.redirect = True
                        return response
@@ -436,6 +437,18 @@ class CachedResponse(StringIO.StringIO):
        To determine wheter a response is cached or coming directly from
        the network, check the x-cache header rather than the object type.
        '''
+       @staticmethod
+       def cleanup(maxAge):
+               # Loop each file within urlcache folder
+               cachePath = os.path.join(plugin.getProfile(), "urlcache")
+               for urlFile in os.listdir(cachePath):
+                       # Check if file is a Body file then proceed
+                       if urlFile.endswith(".body"):
+                               # Fetch urlHash and check if Cache is Stale, 
then remove
+                               fullPath = os.path.join(cachePath, 
urlFile.replace(".body", ".%s"))
+                               if not CachedResponse.isValid(fullPath, maxAge):
+                                       # If file is not valid then Remove
+                                       CachedResponse.remove(fullPath)
        
        @staticmethod
        def exists(cachePath):
@@ -445,19 +458,20 @@ class CachedResponse(StringIO.StringIO):
        @staticmethod
        def isValid(cachePath, maxAge):
                ''' Returns True if Cache is Valid, Else Return False '''
-               return maxAge and time.time() - os.stat(cachePath % 
u"body").st_mtime < maxAge and time.time() - os.stat(cachePath % 
u"headers").st_mtime < maxAge
+               return time.time() - os.stat(cachePath % u"body").st_mtime < 
maxAge and time.time() - os.stat(cachePath % u"headers").st_mtime < maxAge
        
        @staticmethod
        def loadHeaders(cachePath):
                ''' Returns Only the headers to chack If-Modified-Since & 
If-None-Match '''
-               try: return 
httplib.HTTPMessage(StringIO.StringIO(CachedResponse.readFile(cachePath % 
u"headers")))
-               except: raise plugin.CacheError(32911, "Loading of Cache 
Headers Failed")
+               return 
httplib.HTTPMessage(StringIO.StringIO(CachedResponse.readFile(cachePath % 
u"headers")))
        
        @staticmethod
        def readFile(filename):
                ''' Return content of file and auto close file '''
-               with open(filename, "rb") as fileObject:
-                       return fileObject.read()
+               try:
+                       with open(filename, "rb") as fileObject: return 
fileObject.read()
+               except (IOError, OSError) as e:
+                       raise plugin.CacheError(plugin.getstr(32803), str(e))
        
        @staticmethod
        def reset(cachePath, times=None):
@@ -468,6 +482,7 @@ class CachedResponse(StringIO.StringIO):
        @staticmethod
        def remove(cachePath):
                ''' Remove Cache Items '''
+               plugin.debug("Removing Cache item: %s" % cachePath[:-3])
                # Remove Headers
                try: os.remove(cachePath % u"headers")
                except: pass
@@ -488,13 +503,13 @@ class CachedResponse(StringIO.StringIO):
                headers["X-Cache"] = "HIT"
                headers["X-Location"] = response.url
                try: outputFile.write(str(headers))
-               except: raise plugin.CacheError(32911, "Failed to Save Headers 
to Cache")
+               except (IOError, OSError) as e: raise 
plugin.CacheError(plugin.getstr(32803), str(e))
                finally: outputFile.close()
                
                # Save Response to Cache
                outputFile = open(cachePath % u"body", "wb")
                try: outputFile.write(response.read())
-               except: raise plugin.CacheError(32911, "Failed to Save Body to 
Cache")
+               except (IOError, OSError) as e: raise 
plugin.CacheError(plugin.getstr(32803), str(e))
                finally: outputFile.close()
                
                # Close Response Connection
@@ -502,8 +517,7 @@ class CachedResponse(StringIO.StringIO):
        
        def __init__(self, cachePath):
                # Read in Both Body and Header Responses
-               try: StringIO.StringIO.__init__(self, self.readFile(cachePath % 
u"body"))
-               except: raise plugin.CacheError(32911, "Loading of Cache Body 
Failed")
+               StringIO.StringIO.__init__(self, self.readFile(cachePath % 
u"body"))
                self.headers = self.loadHeaders(cachePath)
                
                # Set Response Codes
@@ -518,3 +532,7 @@ class CachedResponse(StringIO.StringIO):
        def geturl(self):
                ''' Returns original Url '''
                return self.url
+       
+       # Methods to add support for with statement
+       def __enter__(self): return self
+       def __exit__(self, *exc_info): self.close()
diff --git a/script.module.xbmcutil/lib/xbmcutil/videoResolver.py 
b/script.module.xbmcutil/lib/xbmcutil/videoResolver.py
index 382b1c3..4b68e68 100644
--- a/script.module.xbmcutil/lib/xbmcutil/videoResolver.py
+++ b/script.module.xbmcutil/lib/xbmcutil/videoResolver.py
@@ -48,15 +48,15 @@ class MainParser(HTMLParser.HTMLParser):
                elif tag == u"embed": self.handle_embed(dict(attrs))
        
        def handle_iframe(self, attrs):
-               if u"src" in attrs and attrs[u"src"][:4] == u"http":
+               if u"src" in attrs:# and attrs[u"src"][:4] == u"http":
                        self.sourceUrls.add(attrs[u"src"])
        
        def handle_param(self, attrs):
-               if u"name" in attrs and u"value" in attrs and attrs[u"name"] == 
u"movie" and attrs[u"value"][:4] == u"http":
+               if u"name" in attrs and u"value" in attrs and attrs[u"name"] == 
u"movie":# and attrs[u"value"][:4] == u"http":
                        self.sourceUrls.add(attrs[u"value"])
        
        def handle_embed(self, attrs):
-               if u"src" in attrs and attrs[u"src"][:4] == u"http":
+               if u"src" in attrs:# and attrs[u"src"][:4] == u"http":
                        self.sourceUrls.add(attrs[u"src"])
 
 class RegexParser:
@@ -87,15 +87,15 @@ class RegexParser:
                for attrs in re.findall('<embed(.*?)[/]*>', self.html, 
re.DOTALL | re.IGNORECASE): self.handle_embed(self.dict(attrs))
        
        def handle_iframe(self, attrs):
-               if u"src" in attrs and attrs[u"src"][:4] == u"http":
+               if u"src" in attrs:# and attrs[u"src"][:4] == u"http":
                        self.sourceUrls.add(attrs[u"src"])
        
        def handle_param(self, attrs):
-               if u"name" in attrs and u"value" in attrs and attrs[u"name"] == 
u"movie" and attrs[u"value"][:4] == u"http":
+               if u"name" in attrs and u"value" in attrs and attrs[u"name"] == 
u"movie":# and attrs[u"value"][:4] == u"http":
                        self.sourceUrls.add(attrs[u"value"])
        
        def handle_embed(self, attrs):
-               if u"src" in attrs and attrs[u"src"][:4] == u"http":
+               if u"src" in attrs:# and attrs[u"src"][:4] == u"http":
                        self.sourceUrls.add(attrs[u"src"])
 
 class SoupParser:
@@ -145,7 +145,7 @@ class VideoParser:
        [{'domain':'videobb.com', 'vodepid':'ZaibwUjYLlxJ', 
'function':videobb_com, 'isplaylist':False, 'priority':71}, 
{'domain':'www.youtube.com', 'vodepid':'st40Gps08KI', 'function':youtube_com, 
'isplaylist':False, 'priority':100}]
        '''
        
-       def parse(self, arg, maxAge=86400):
+       def parse(self, arg, maxAge=57600):
                '''
                Takes in a url to a online resource or the HTML to that online 
resource and
                Passes it into the Custom Parsers to Find Embeded Sources
@@ -159,18 +159,14 @@ class VideoParser:
                        htmlSource = arg
                
                # Feed the HTML into the HTMLParser and acquire the source urls
-               sourceUrls = self.htmlparser(htmlSource)
-               if not sourceUrls: raise plugin.ParserError(32973, "No Video 
Sources ware found")
+               sourceUrls = list(self.htmlparser(htmlSource))
+               if not sourceUrls: raise 
plugin.ParserError(plugin.getstr(32827), "No Video Sources ware found")
                else: self.setUrls(sourceUrls)
        
        def setUrls(self, sourceUrls):
                # Process Available Sources
-               plugin.log("Source url's: " + str(sourceUrls))
-               parsedUrls = self.processUrls(sourceUrls)
-               
-               # Check for Supported Sources
-               if not parsedUrls: raise plugin.ParserError(32970, "No 
Supported Video Sources ware found")
-               else: self.parsedUrls = parsedUrls
+               plugin.debug("Source url's: " + str(sourceUrls))
+               self.parsedUrls = self.processUrls(sourceUrls)
        
        def htmlparser(self, htmlSource):
                '''
@@ -183,36 +179,45 @@ class VideoParser:
                        customParser = MainParser()
                        customParser.parse(htmlSource)
                        return customParser.sourceUrls
-               except: plugin.log("HTML Parser Failed: Falling Back to Regex", 
0)
+               except: plugin.debug("HTML Parser Failed: Falling Back to 
Regex")
                
                try:
                        # Try Parse HTML Using Regex
                        customParser = RegexParser()
                        customParser.parse(htmlSource)
                        return customParser.sourceUrls
-               except: plugin.log("Regex Parser Failed: Falling Beautiful 
Soup", 0)
+               except: plugin.debug("Regex Parser Failed: Falling Beautiful 
Soup")
                
                try:
                        # Try Parse HTML Using Beautiful Soup
                        customParser = SoupParser()
                        customParser.parse(htmlSource)
                        return customParser.sourceUrls
-               except: plugin.log("Beautiful Soup Parser Failed: All Out Total 
Failure", 0)
+               except: plugin.debug("Beautiful Soup Parser Failed: All Out 
Total Failure")
                
                # Raise ParserError when all three parsers have failded
-               raise plugin.ParserError(32972, "HTML Parsing Failed")
+               raise plugin.ParserError(plugin.getstr(32826), "HTML Parsing 
Failed")
        
        def processUrls(self, sourceUrls):
                '''
                Take in a list of Embeded Source Urls and Create a list 
Containing
                information about the Sources found and the required Decoder.
                ''' 
+               blockList = ("platform.twitter.com", "google.com", 
"megavideo.com", "myspace.com")
                
                # Filter Video Sources
                parsedUrls = []
+               self.sourceUrls = []
+               appendUrl = self.sourceUrls.append
                for url in sourceUrls:
-                       filtered = self.process(urlparse.urlsplit(url))
-                       if filtered: parsedUrls.append(filtered)
+                       urlParts = urlparse.urlsplit(url)
+                       if urlParts[1] in blockList:
+                               plugin.debug("Ignoring domain %s" % urlParts[1])
+                               continue
+                       else:
+                               appendUrl(url)
+                               filtered = self.process(urlParts)
+                               if filtered: parsedUrls.append(filtered)
                
                # Return list of processed Urls
                return parsedUrls
@@ -229,7 +234,7 @@ class VideoParser:
                                return pluginObject().strip(*urlObject)
                
                # Log The UnSupported Video Source for Future Identification
-               plugin.log(u"Video Source UnSupported\nDomain = %s\nurl    = 
%s" % (urlObject[1], urlObject.geturl()), 0)
+               plugin.debug(u"Video Source UnSupported\nDomain = %s\nurl    = 
%s" % (urlObject[1], urlObject.geturl()))
        
        def get(self, sort=True):
                '''
@@ -251,63 +256,26 @@ def check_arg(pluginName):
                def wrapper(self, oarg):
                        arg = oarg
                        if arg[:4] == u"http": arg = 
self.strip(*urlparse.urlsplit(arg), returnID=True)
-                       if not arg: raise plugin.videoResolver(32918, u"Unable 
to Strip out videoID ==> %s ==> %s" % (pluginName, oarg))
+                       if not arg: raise 
plugin.videoResolver(plugin.getstr(32821), u"Unable to Strip out videoID ==> %s 
==> %s" % (pluginName, oarg))
                        else:
                                # Call Function and return response
-                               plugin.setDebugMsg("VideoResolver", u"Select 
Source ==> %s ==> %s" % (pluginName, arg))
+                               plugin.debug("VideoResolver, Select Source ==> 
%s ==> %s" % (pluginName, arg))
                                return function(self, arg)
                return wrapper
        return decorator
 
-def parse_qs(query):
-       '''
-       Takes in a Query Stirng and Converts to a Dictionary with Lower Case 
Keys
-       '''
-       qDict = {}
-       for key,value in urlparse.parse_qsl(query):
-               if key in qDict: qDict[key.lower()].append(value)
-               else: qDict[key.lower()] = [value]
-       return qDict
-
-def jsUnpack(sJavascript):
-       aSplit = sJavascript.split(";',")
-       p = str(aSplit[0])
-       aSplit = aSplit[1].split(",")
-       a = int(aSplit[0])
-       c = int(aSplit[1])
-       k = aSplit[2].split(".")[0].replace("'", '').split('|')
-       e = ''
-       d = ''
-       sUnpacked = str(__unpack(p, a, c, k, e, d))
-       return sUnpacked.replace('\\', '')
-
-def __unpack(p, a, c, k, e, d):
-       while (c > 1):
-               c = c -1
-               if (k[c]):
-                       p = re.sub('\\b' + str(__itoa(c, a)) +'\\b', k[c], p)
-       return p
-
-def __itoa(num, radix):
-       result = ""
-       while num > 0:
-               result = "0123456789abcdefghijklmnopqrstuvwxyz"[num % radix] + 
result
-               num /= radix
-       return result
-
 
#######################################################################################
 
 class youtube_com(object):
        '''
-       Takes a video id from a Youtube video page url, or takes a complete url 
-       to a Youtube swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
+       Takes a full youtube url or video ID and returns the url to the actual
+       video resource. Raises video Resolver Error if no resource is found.
        
        >>> youtube_com.decode('http://www.youtube.com/v/c64Aia4XE1Y')
-       
'http://o-o.preferred.dub06s01.v22.lscache8.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Csource%2Calgorithm%2Cburst%2Cfactor%2Ccp&fexp=909513%2C914051%2C910102%2C913601%2C914102%2C902516&algorithm=throttle-factor&itag=34&ip=93.0.0.0&burst=40&sver=3&signature=CB2444C0FE8F08F9C8A5187CD8A7ECB9300F7D08.84A27889772123BA3F53BA5F1D2B6390E9EFF14E&source=youtube&expire=1327129325&key=yt1&ipbits=8&factor=1.25&cp=U0hRTFFNV19HT0NOMV9JR0FEOk5FVGY5blpiSjQx&id=73ae0089ae171356'
+       
'http://o-o.preferred.dub06s01.v22.lscache8.c.youtube.com/videoplayback?sparams=id%2Cexpi...'
        
        >>> youtube_com.decode('c64Aia4XE1Y')
-       
'http://o-o.preferred.dub06s01.v22.lscache8.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Csource%2Calgorithm%2Cburst%2Cfactor%2Ccp&fexp=909513%2C914051%2C910102%2C913601%2C914102%2C902516&algorithm=throttle-factor&itag=34&ip=93.0.0.0&burst=40&sver=3&signature=CB2444C0FE8F08F9C8A5187CD8A7ECB9300F7D08.84A27889772123BA3F53BA5F1D2B6390E9EFF14E&source=youtube&expire=1327129325&key=yt1&ipbits=8&factor=1.25&cp=U0hRTFFNV19HT0NOMV9JR0FEOk5FVGY5blpiSjQx&id=73ae0089ae171356'
+       
'http://o-o.preferred.dub06s01.v22.lscache8.c.youtube.com/videoplayback?sparams=id%2Cexpi...'
        '''
        __metaclass__ = Plugin
        def __init__(self, priority=100):
@@ -316,20 +284,28 @@ class youtube_com(object):
                self.priority = priority
        
        def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               if path.lower() is u"/embed/videoseries":
-                       playlistID = parse_qs(query)[u"list"][0]
+               if path.lower().startswith(u"/embed/videoseries"):
+                       playlistID = plugin.parse_qs(query)["list"]
+                       if returnID: return playlistID
+                       else: return {"domain":netloc, "vodepid":playlistID, 
"function":self.decode_playlist, "priority":self.priority-1}
+               elif path.lower().startswith("/playlist"):
+                       playlistID = plugin.parse_qs(query)["list"]
                        if returnID: return playlistID
-                       else: return {"domain":netloc, "vodepid":playlistID, 
"function":self.decode_playlist, "isplaylist":True, "priority":self.priority-1}
+                       else: return {"domain":netloc, "vodepid":playlistID, 
"function":self.decode_playlist, "priority":self.priority-1}
+               elif path.lower().startswith(u"/embed/") and "list" in query:
+                       playlistID = plugin.parse_qs(query)["list"]
+                       if returnID: return playlistID
+                       else: return {"domain":netloc, "vodepid":playlistID, 
"function":self.decode_playlist, "priority":self.priority-1}
                elif path.lower().startswith(u"/embed/") or 
path.lower().startswith(u"/v/"):
-                       videoID = path[path.rfind(u"/")+1:]
+                       videoID = path[path.rfind(u"/")+1:].split("&")[0]
                        if returnID: return videoID
-                       else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
+                       else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "priority":self.priority}
                elif path.lower().startswith(u"/watch"):
-                       videoID = parse_qs(query)[u"v"][0]
+                       videoID = plugin.parse_qs(query)["v"]
                        if returnID: return videoID
-                       else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
+                       else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "priority":self.priority}
                else: 
-                       plugin.log("Unable to Strip out video id from youtube 
source url")
+                       plugin.notice("Unable to Strip out video id from 
youtube.com source url")
                        return None
        
        @check_arg(u"Youtube")
@@ -347,64 +323,11 @@ class youtube_com(object):
                # Fetch list of urls and listiems
                markForDownload = plugin.get("download",u"false") == u"true"
                return [{"url":url + "&download=true", "item":listitem} if 
markForDownload else {"url":url, "item":listitem} for url, listitem, isfolder 
in Gdata.VideoGenerator()]
-       
-       def checker(self, testcard=u"c64Aia4XE1Y"):
-               plugin.log("Checking Youtube Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
 
 class youtu_be(youtube_com): pass
 
 
#######################################################################################
 
-class vimeo_com(object):
-       '''
-       Takes a video id from a Vimeo video page url, or takes a complete url 
-       to a Vimeo swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
-       
-       >>> 
vimeo_com.decode('http://player.vimeo.com/video/34242816?title=0&byline=0&portrait=0')
-       
'http://av.vimeo.com/68932/441/78039067.mp4?token=1327120954_425c5e7baa06f349386b5479f9cb6d0e'
-       
-       >>> vimeo_com.decode('34242816')
-       
'http://av.vimeo.com/68932/441/78039067.mp4?token=1327120954_425c5e7baa06f349386b5479f9cb6d0e'
-       '''
-       __metaclass__ = Plugin
-       def __init__(self, priority=97):
-               self.priority = priority
-       
-       def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.rfind(u"/")+1:]
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
-       
-       @check_arg(u"Vimeo")
-       def decode(self, arg):
-               # Fetch Video Processer Object and Return Decoded Url
-               if plugin.get("download",u"false") == u"true": return 
{"url":u"plugin://plugin.video.vimeo/?action=download&videoid=%s" % arg}
-               else: return 
{"url":u"plugin://plugin.video.vimeo/?action=play_video&videoid=%s" % arg}
-       
-       def checker(self, testcard=u"34242816"):
-               plugin.log("Checking Vimeo Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
 class dailymotion_com(object):
        '''
        Takes a video id from a DailyMotion video page url, or takes a complete 
url 
@@ -422,23 +345,30 @@ class dailymotion_com(object):
                self.priority = priority
        
        def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.rfind(u"/")+1:].split(u"_",1)[0]
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
+               if "video/" in path.lower():
+                       videoID = path[path.rfind(u"/")+1:].split(u"_",1)[0]
+                       if returnID: return videoID
+                       else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "priority":self.priority}
+               else:
+                       plugin.notice("Unable to Strip out video id from 
dailymotion.com source url")
+                       return None
        
        @check_arg(u"DailyMotion")
        def decode(self, arg):
                # Fetch Redirected Url
                url = u"http://www.dailymotion.com/embed/video/%s"; % arg
-               sourceCode = urlhandler.urlread(url)
+               handle = urlhandler.HttpHandler()
+               handle.add_response_handler()
+               with handle.open(url) as resp:
+                       sourceCode = resp.read().decode("utf-8")
                
                # Fetch list of Urls
                sourceCode = re.findall('var info = (\{.+?\}),', sourceCode)[0]
                Sources = dict([[part for part in match if part] for match in 
re.findall('"(stream_h264_url)":"(\S+?)",|"(stream_h264_ld_url)":"(\S+?)",|"(stream_h264_hq_url)":"(\S+?)",|"(stream_h264_hd_url)":"(\S+?)",|"(stream_h264_hd1080_url)":"(\S+?)",',
 sourceCode)])
-               if not Sources: raise plugin.videoResolver(33077, "Unable to 
Find Video Url")
+               if not Sources: raise 
plugin.videoResolver(plugin.getstr(33077), "Unable to Find Video Url")
                
                # Fetch Video Quality
-               Quality = plugin.getQuality()
+               Quality = plugin.getSetting("quality")
                if  Quality == u"1080p": Quality = 5
                elif Quality == u"720p": Quality = 4
                else: Quality = 3
@@ -450,18 +380,6 @@ class dailymotion_com(object):
                
                # Fallback to any quality if unable to find format
                return {"url":Sources[Sources.keys()[0]]}
-       
-       def checker(self, testcard=u"x162i8b"):
-               plugin.log("Checking DailyMotion Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
 
 
#######################################################################################
 
@@ -471,36 +389,45 @@ class blip_tv(object):
        to a BlipTV swf and returns the url to the actual video resource.
        Raises videoResolver Error if no match is found.
        
-       >>> blip_tv.decode('http://blip.tv/play/AYOW3REC.html')
-       
'http://blip.tv/file/get/Linuxjournal-GetFirefoxMenuButtonInLinux474.m4v'
+       >>> blip_tv.decode('http://blip.tv/play/AYKvk2QC.html')
+       'http://blip.tv/file/get/8bitredcat-....m4v'
        
-       >>> blip_tv.decode('AYOW3REC'|'6663725')
-       
'http://blip.tv/file/get/Linuxjournal-GetFirefoxMenuButtonInLinux474.m4v'
+       >>> blip_tv.decode('AYKvk2QC'|'4966784')
+       'http://blip.tv/file/get/8bitredcat-....m4v'
        '''
        __metaclass__ = Plugin
        def __init__(self, priority=95):
                self.priority = priority
        
        def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.rfind(u"/")+1:].split(u".")[0]
+               if "api.swf" in path.lower(): videoID = fragment
+               elif "play/" in path.lower(): videoID = 
path[path.rfind(u"/")+1:].split(u".")[0]
+               elif str.isdigit(path.rsplit("-", 1)[-1]): videoID = 
path.rsplit("-", 1)[-1]
+               else: 
+                       plugin.notice("Unable to Strip out video id from 
blip.tv source url")
+                       return None
+               
+               # Return Ether Video id or dict of objects
                if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
+               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "priority":self.priority}
        
        @check_arg(u"BlipTV")
        def decode(self, arg):
                # Check if arg is the embeded ID or VideoID
-               if arg.isdigit():
-                       # Fetch Redirected Url
+               if arg.isdigit(): url = "http://blip.tv/rss/flash/%s"; % arg
+               else:
+                       # Fetch Redirected Url with the numeric id
                        url = u"http://blip.tv/play/%s"; % arg
                        reUrl = urlhandler.redirect(url)
                        
                        # Filter out VideoCode
-                       try: arg = re.findall('flash%2F(.+?)&', reUrl)[0]
-                       except: raise plugin.videoResolver(33077, "Unable to 
filter out Video Code")
+                       try: url = 
plugin.parse_qs(reUrl[reUrl.find("?")+1:])["file"]
+                       except (ValueError, KeyError) as e: raise 
plugin.videoResolver(plugin.getstr(33077), str(e))
                
                # Fetch XMLSource
-               url = u"http://blip.tv/rss/flash/%s"; % arg
-               sourceObj = urlhandler.urlopen(url)
+               handle = urlhandler.HttpHandler()
+               handle.add_response_handler()
+               sourceObj = handle.open(url)
                import xml.etree.ElementTree as ElementTree
                media = u"http://search.yahoo.com/mrss/";
                tree = ElementTree.parse(sourceObj)
@@ -508,30 +435,20 @@ class blip_tv(object):
                
                # Fetch list of Media Content Found
                filtered = ((int(node.get(u"height",0)), node.attrib) for node 
in tree.getiterator(u"{%s}content" % media) if not node.get(u"type") == 
u"text/plain")
+               filtered = sorted(filtered, key=lambda x: x[0], reverse=True)
+               filtered = sorted(filtered, key=lambda x: x[1]["isDefault"] == 
"true", reverse=True)
                
                # Fetch Video Quality and return video
-               quality = int(plugin.getQuality().replace(u"p",u""))
-               qualitySorted = sorted(filtered, key=lambda x: x[0], 
reverse=True)
-               for content in qualitySorted:
-                       if content[0] <= quality:
-                               videoInfo = content[1]
-                               return {"url":videoInfo[u"url"], 
"type":videoInfo[u"type"]}
+               try: quality = 
int(plugin.getSetting("quality").replace(u"p",u""))
+               except ValueError: quality = 720
+               
+               for res, content in filtered:
+                       if res <= quality:
+                               return {"url":content[u"url"], 
"type":content[u"type"]}
                
                # Fallback to hightest available quality
-               videoInfo = qualitySorted[0][1]
+               videoInfo = filtered[0][1]
                return {"url":videoInfo[u"url"], "type":videoInfo[u"type"]}
-       
-       def checker(self, testcard=u"AYOW3REC"):
-               plugin.log("Checking BlipTV Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
 
 
#######################################################################################
 
@@ -541,10 +458,10 @@ class veehd_com(object):
        to a veehd swf and returns the url to the actual video resource.
        Raises videoResolver Error if no match is found.
        
-       >>> 
veehd_com.decode('http://veehd.com/embed?v=4700076&w=720&h=406&t=2&s=6000&p=divx')
+       >>> 
veehd_com.decode('http://veehd.com/embed?v=4686958&w=720&h=405&t=1&s=0&p=flash')
        
'http://v33.veehd.com/dl/92c8e1b53f19f27697e16d186c28f17b/1327678479/5000.4686958.mp4&b=390'
        
-       >>> veehd_com.decode('4700076')
+       >>> veehd_com.decode('4686958')
        
'http://v33.veehd.com/dl/92c8e1b53f19f27697e16d186c28f17b/1327678479/5000.4686958.mp4&b=390'
        '''
        __metaclass__ = Plugin
@@ -552,14 +469,15 @@ class veehd_com(object):
                self.priority = priority
        
        def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               if path.lower().startswith(u"/embed"): videoID = 
parse_qs(query)[u"v"][0]
+               if path.lower().startswith(u"/embed"): videoID = 
plugin.parse_qs(query)[u"v"]
                elif path.lower().startswith(u"/video/"): videoID = 
path.strip(u"/video/").split(u"_")[0]
                else: 
-                       plugin.log("Unable to Strip out video id from veehd.com 
source url")
+                       plugin.notice("Unable to Strip out video id from 
veehd.com source url")
                        return None
                
+               # Return Ether Video id or dict of objects
                if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
+               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "priority":self.priority}
        
        @check_arg(u"Veehd")
        def decode(self, arg):
@@ -567,375 +485,77 @@ class veehd_com(object):
                url = u"http://veehd.com/video/%s"; % arg
                handle = urlhandler.HttpHandler()
                handle.add_response_handler()
-               htmlSource = handle.open(url).read().decode("utf8")
+               with handle.open(url) as resp:
+                       htmlSource = resp.read().decode("utf-8")
                
                # Fetch Video Info Page Url and Download HTML Page
-               try: url = u"http://veehd.com"; + 
re.findall('load_stream\(\)\{\s+\$\("#playeriframe"\).attr\(\{src : 
"(/vpi.+?)"\}\);\s+\}',htmlSource)[0]
-               except: raise plugin.videoResolver(33077, "Was unable to Find 
Veehd Video Info Page Url")
-               else: htmlSource = handle.open(url).read().decode("utf8")
-               
-               # Search for Video Url Using Params Method
-               try: return 
{"url":re.findall('<param\s+name="src"\svalue="(http://\S+?)">',htmlSource)[0]}
-               except: plugin.setDebugMsg("VideoResolver", "Video Url Search 
using params Failed")
-               
-               # search for Video Url Using Embed Method
-               try: return 
{"url":re.findall('<embed\s+type="video/divx"\s+src="(http://\S+?)"',htmlSource)[0]}
-               except: plugin.setDebugMsg("VideoResolver", "Video Url Search 
using embed Failed")
+               try: url = [u"http://veehd.com%s"; % url for url in 
re.findall('attr\(\{src\s:\s"(/vpi\S+?)"\}\)',htmlSource) if u"do=d" in url][0]
+               except IndexError as e: raise 
plugin.videoResolver(plugin.getstr(33077), str(e))
+               else:
+                       with handle.open(url) as resp:
+                               htmlSource = resp.read().decode("utf-8")
                
-               # Search for Video Url Javascript Method
-               import urllib
-               try: return 
{"url":urllib.unquote_plus(re.findall('"url":"(\S+?)"',htmlSource)[0].encode("ascii"))}
-               except: raise plugin.videoResolver(33077, "Was unable to Find 
Veehd Video Url or Decode It")
-       
-       def checker(self, testcard=u"4700076"):
-               plugin.log("Checking Veehd Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
+               # Search for Video Url
+               try: return 
{"url":re.findall('<a\sstyle="color\:#31A0FF;"\shref="(http://.+?)">', 
htmlSource)[0]}
+               except IndexError as e: raise 
plugin.videoResolver(plugin.getstr(33077), "Was unable to Find Veehd Video Url 
or Decode It")
 
 
#######################################################################################
 
-class www_4shared_com(object):
+class vimeo_com(object):
        '''
-       Takes a video id from a 4shared video page url, or takes a complete url 
-       to a 4shared swf and returns the url to the actual video resource.
+       Takes a video id from a vimeo video page url, or takes a complete url 
+       to a vimeo swf and returns the url to the actual video resource.
        Raises videoResolver Error if no match is found.
        
-       >>> 
4shared_com.decode('http://www.4shared.com/embed/488295743/e62f15bd')
-       
'http://dc171.4shared.com/img/260186666/598f38a8/dlink__2Fdownload_2FsRLkhHko_3Ftsid_3D20120126-030811-665332a8/preview.flv?file=http://dc171.4shared.com/img/260186666/598f38a8/dlink__2Fdownload_2FsRLkhHko_3Ftsid_3D20120126-030811-665332a8/preview.flv&start=0'
+       >>> vimeo_com.decode('http://player.vimeo.com/video/6368439')
+       
'http://av.vimeo.com/30750/741/12016117.mp4?token2=1403188386_b1960dae0fb3a6eafedc717134285fbe&aksessionid=5281d14cce9e052f&ns=4'
        
-       >>> 4shared_com.decode('488295743/e62f15bd')
-       
'http://dc171.4shared.com/img/260186666/598f38a8/dlink__2Fdownload_2FsRLkhHko_3Ftsid_3D20120126-030811-665332a8/preview.flv?file=http://dc171.4shared.com/img/260186666/598f38a8/dlink__2Fdownload_2FsRLkhHko_3Ftsid_3D20120126-030811-665332a8/preview.flv&start=0'
+       >>> vimeo_com.decode('6368439')
+       
'http://av.vimeo.com/30750/741/12016117.mp4?token2=1403188386_b1960dae0fb3a6eafedc717134285fbe&aksessionid=5281d14cce9e052f&ns=4'
        '''
        __metaclass__ = Plugin
-       def __init__(self, priority=72):
+       def __init__(self, priority=94):
                self.priority = priority
        
        def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path.strip(u"/embed/")
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
-       
-       @check_arg(u"4Shared")
-       def decode(self, arg):
-               # Fetch Redirected Url
-               url = u"http://www.4shared.com/embed/%s"; % arg
-               reUrl = urlhandler.redirect(url)
-               
-               # Parse Url String and Create Dict
-               urlDict = parse_qs(urlparse.urlsplit(reUrl)[3])
+               """ 
+                       http://www.vimeo.com/moogaloop.swf?clip_id=45517759
+                       http://player.vimeo.com/video/6368439
+                       http://vimeo.com/6368439 
+               """
+               if "/video/" in path.lower(): videoID = path[path.rfind("/")+1:]
+               elif "/moogaloop.swf" in path: videoID = 
plugin.parse_qs(query)[u"clip_id"]
+               elif path[1:].isdigit(): videoID = path[1:]
+               else: 
+                       plugin.notice("Unable to Strip out video id from 
veehd.com source url")
+                       return None
                
-               # Check if the Required Keys Exist
-               if u"file" in urlDict and u"streamer" in urlDict: return 
{"url":u"%s?file=%s&start=0" % (urlDict[u"streamer"][0], urlDict[u"file"][0])}
-               else: raise plugin.videoResolver(33077, "Required Key Not Found 
in Redirected Url")
-       
-       def checker(self, testcard=u"488295743/e62f15bd"):
-               plugin.log("Checking 4Shared Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
-class uploadc_com(object):
-       '''
-       Takes a video id from a uploadc video page url, or takes a complete url 
-       to a uploadc swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
-       
-       >>> uploadc_com.decode('http://www.uploadc.com/embed-mcc8uenje34i.html')
-       
'http://www1.uploadc.com:182/d/rqgabh5gvsulzrqm3ln6pcvoamzh5zsdbpurbtaty6adou55pzhyjqt3/Zegapain+-+Episode+25.mkv'
-       
-       >>> uploadc_com.decode('mcc8uenje34i')
-       
'http://www1.uploadc.com:182/d/rqgabh5gvsulzrqm3ln6pcvoamzh5zsdbpurbtaty6adou55pzhyjqt3/Zegapain+-+Episode+25.mkv'
-       '''
-       __metaclass__ = Plugin
-       def __init__(self, priority=71):
-               self.priority = priority
-       
-       def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.find(u"embed-")+6:path.rfind(u".")]
+               # Return Ether Video id or dict of objects
                if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
+               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "priority":self.priority}
        
-       @check_arg(u"UploadC")
-       def decode(self, arg):
-               # Create Url String and Fetch HTML Page
-               url = u"http://www.uploadc.com/embed-%s.html"; % arg
-               sourceObj = urlhandler.urlopen(url)
-               htmlSource = sourceObj.read()
-               sourceObj.close()
-               
-               # Fetch JavaScript Code and Unpack
-               try: jsCode = jsUnpack(re.findall("<script 
type='text/javascript'>eval\((.+?)\)\s+</script>", htmlSource)[0])
-               except: raise plugin.videoResolver(33077, "Was unable to Find 
JavaScript and Unpack It")
-               
-               # Fetch Video ID From JavaScript Code
-               import urllib
-               try: return {"url":re.findall('<param 
name="src"0="(http://\S+?)"/>', jsCode)[0], "referer":url.encode("ascii")}
-               except: raise plugin.videoResolver(33077, "Video Url Was Not 
Found in JavaScript Code")
-       
-       def checker(self, testcard=u"mcc8uenje34i"):
-               plugin.log("Checking Uploadc Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
-class putlocker_com(object):
-       '''
-       Takes a video id from a PutLocker video page url, or takes a complete 
url 
-       to a PutLocker swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
-       
-       >>> putlocker_com.decode('http://www.putlocker.com/embed/21NRHEZN4Z17')
-       
'http://media-b30.putlocker.com/download/69/imbtcd1_arc_56c02.flv/daac7e476510246bb24ca320e6468969/4f1a63dc'
-       
-       >>> putlocker_com.decode('21NRHEZN4Z17')
-       
'http://media-b30.putlocker.com/download/69/imbtcd1_arc_56c02.flv/daac7e476510246bb24ca320e6468969/4f1a63dc'
-       '''
-       __metaclass__ = Plugin
-       def __init__(self, priority=70):
-               self.priority = priority
-       
-       def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.rfind(u"/")+1:]
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
-       
-       @check_arg(u"PutLocker")
+       @check_arg(u"Veehd")
        def decode(self, arg):
-               # Construct Embedded Url and Fetch Server Response
-               url = u"http://www.putlocker.com/embed/%s"; % arg
+               # Create Url String and Download HTML Page
+               url = u"http://player.vimeo.com/video/%s"; % arg
                handle = urlhandler.HttpHandler()
                handle.add_response_handler()
-               response = handle.open(url).read()
-               
-               # Fetch Cookie and Hash Values
-               try: hash = 
"fuck_you=%s&confirm=Close+Ad+and+Watch+as+Free+User" % (re.findall('<input 
type="hidden" value="(\S+?)" name="fuck_you">', response)[0])
-               except: raise plugin.videoResolver(33077, "Failed to Read Hash 
Value used for validating the Cookie")
-               
-               # Validate Cookie with the Hash Value
-               response = handle.open(url, hash, 
{"Referer":url.encode("ascii")}).read()
-               
-               # Construct Embedded Url and Fetch Video Info
-               try: url = "http://www.putlocker.com/get_file.php?stream=%s"; % 
(re.findall('/get_file.php\?stream=(\S+)', response)[0])
-               except: raise plugin.videoResolver(33077, "Failed to Validate 
Cookie and Fetch Embed Code")
-               
-               # Connect to Server to Download Video Source Data
-               response = handle.open(url)
-               
-               # Fetch and Return Video Url
-               import xml.etree.ElementTree as ElementTree
-               media = u"http://search.yahoo.com/mrss/";
-               tree = ElementTree.parse(response)
-               response.close()
-               
-               # Loop each media content element and find video url
-               for node in tree.getiterator(u"{%s}content" % media):
-                       url = node.get(u"url")
-                       type = node.get(u"type")
-                       if url is not None and type[:5] == u"video":
-                               return {"url":url, "type":type}
+               with handle.open(url) as resp:
+                       htmlSource = resp.read()
                
-               # Raise Error if unable to return any video url
-               raise plugin.videoResolver(33077, "Failed to Read Video Url")
-       
-       def checker(self, testcard=u"21NRHEZN4Z17"):
-               plugin.log("Checking PutLocker Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
-class kqed_org(object):
-       '''
-       Takes a video id from a kqed.org video page url, or takes a complete 
url 
-       to a kqed.org swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
-       
-       >>> kqed_org.decode('http://www.kqed.org/quest/television/embed/502')
-       'http://www.kqed.org/.stream/anon/quest/116b_exoplanets_e.flv'
-       
-       >>> kqed_org.decode('502')
-       'http://www.kqed.org/.stream/anon/quest/116b_exoplanets_e.flv'
-       '''
-       __metaclass__ = Plugin
-       def __init__(self, priority=51):
-               self.priority = priority
-       
-       def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.rfind(u"/")+1:]
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
-       
-       @check_arg(u"kqed.org")
-       def decode(self, arg):
-               # Create Url String and Fetch HTML Page
-               url = u"http://www.kqed.org/quest/television/embed/%s"; % arg
-               htmlSource = urlhandler.urlread(url)
-               
-               # Fetch the Video Url And Return It
-               try: return {"url":re.findall("source=(http\S+?)&", 
htmlSource)[0]}
-               except: raise plugin.videoResolver(33077, "Was unable to Find 
kqed.org Video Url")
-       
-       def checker(self, testcard=u"502"):
-               plugin.log("Checking kqed Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
-class stagevu_com(object):
-       '''
-       WARNING: Very Slow to Start Video Source
-       Takes a video id from a StageView video page url, or takes a complete 
url 
-       to a StageView swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
-       
-       >>> 
stagevu_com.decode('http://stagevu.com/embed?width=720&height=405&background=000&uid=srpfmbeqxlwe')
-       'http://n47.stagevu.com/v/e848f783c2a9046f44cb93e32ae5d878/43289.avi'
-       
-       >>> stagevu_com.decode('srpfmbeqxlwe')
-       'http://n47.stagevu.com/v/e848f783c2a9046f44cb93e32ae5d878/43289.avi'
-       '''
-       __metaclass__ = Plugin
-       def __init__(self, priority=20):
-               self.priority = priority
-       
-       def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = parse_qs(query)[u"uid"][0]
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
-       
-       @check_arg(u"StageView")
-       def decode(self, arg):
-               # Create Url String and Fetch HTML Page
-               url = u"http://stagevu.com/embed?uid=%s"; % arg
-               htmlSource = urlhandler.urlread(url)
+               # Fetch Video Info Page Url and Download HTML Page
+               try: jsonData = re.findall('"h264":({.+?}),"hls"', 
htmlSource)[0]
+               except IndexError as e: raise 
plugin.videoResolver(plugin.getstr(33077), str(e))
                
-               # Search for Video Url and Return
-               try: return {"url":re.findall("url\[\d+]\ = '(http://\S+?)';", 
htmlSource)[0]}
-               except: raise plugin.videoResolver(33077, "Was unable to Find 
StageView Video Url")
-       
-       def checker(self, testcard=u"srpfmbeqxlwe"):
-               plugin.log("Checking StageView Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
-class rutube_ru(object):
-       '''
-       Warning: Video Stream Failes when a 3rd of the way into the Video
-       Takes a video id from a rutube.ru video page url, or takes a complete 
url 
-       to a rutube.ru swf and returns the url to the actual video resource.
-       Raises videoResolver Error if no match is found.
-       
-       >>> 
rutube_ru.decode('http://video.rutube.ru/65110c1ab97f073835033d2b4a9c3bd2')
-       'http://bl.rutube.ru/65110c1ab97f073835033d2b4a9c3bd2.m3u8'
-       
-       >>> rutube_ru.decode('65110c1ab97f073835033d2b4a9c3bd2')
-       'http://bl.rutube.ru/65110c1ab97f073835033d2b4a9c3bd2.m3u8'
-       '''
-       #__metaclass__ = Plugin
-       def __init__(self, priority=-1):
-               self.priority = priority
-       
-       def strip(self, scheme, netloc, path, query, fragment, returnID=False):
-               videoID = path[path.rfind(u"/")+1:]
-               if returnID: return videoID
-               else: return {"domain":netloc, "vodepid":videoID, 
"function":self.decode, "isplaylist":False, "priority":self.priority}
-       
-       @check_arg(u"rutube.ru")
-       def decode(self, arg):
-               # Fetch Video Information
-               url = u"http://rutube.ru/api/play/options/%s/?format=json"; % arg
-               sourceObj = urlhandler.urlopen(url)
+               # Convert String to json Object
+               import fastjson as json
+               try: urlData = sorted([(value["height"], value["url"]) for 
value in json.loads(jsonData).values()], key=lambda x: x[0], reverse=True)
+               except (ValueError, KeyError) as e: raise 
plugin.videoResolver(plugin.getstr(33077), str(e))
                
-               # Load Json Object
-               from fastjson import load
-               jsonObject = load(sourceObj)
-               sourceObj.close()
+               # Fetch Video Quality and return video
+               try: quality = 
int(plugin.getSetting("quality").replace(u"p",u""))
+               except ValueError: quality = 720
                
-               # Return Video Url
-               return {"url":jsonObject[u"video_balancer"][u"m3u8"]}
-       
-       def checker(self, testcard=u"65110c1ab97f073835033d2b4a9c3bd2"):
-               plugin.log("Checking RuTube.ru Decoder", 0)
-               try: 
-                       videoUrl = self.decode(testcard)
-                       plugin.log("#########################################", 
0)
-                       plugin.log(u"PASS: Successfully Decoded %s" % testcard, 
0)
-                       plugin.log( videoUrl)
-                       return videoUrl
-               except:
-                       plugin.log("#######################################", 0)
-                       plugin.log(u"FAILED: Unable to Devode %s" % testcard, 0)
-
-#######################################################################################
-
-'''
-       Dummy Class to Stop Shutdown Sources from Been Identified as 
UnSupported,
-       Google Video has been Shut Down and is no longer available.
-       Megavideo has been Shut Down and is no longer available.
-       Myspace has Totally Changed and is no longer serving videos
-'''
-
-class google_com(object):
-       __metaclass__ = Plugin
-       def strip(self, *args, **kwargs):
-               plugin.log("google.com: Google Video has been Shut Down and is 
no longer available.")
-               return None
-
-class megavideo_com(object):
-       __metaclass__ = Plugin
-       def strip(self, *args, **kwargs):
-               plugin.log("megavideo.com: Megavideo has been Shut Down and is 
no longer available.")
-               return None
-
-class myspace_com(object):
-       __metaclass__ = Plugin
-       def strip(self, *args, **kwargs):
-               plugin.log("myspace.com: Myspace has Totally Changed and is no 
longer serving videos.")
-               return None
+               for res, url in urlData:
+                       if res <= quality:
+                               return {"url":url}
\ No newline at end of file
diff --git a/script.module.xbmcutil/lib/xbmcutil/videohostsAPI.py 
b/script.module.xbmcutil/lib/xbmcutil/videohostsAPI.py
index f3f8e50..758dbf9 100644
--- a/script.module.xbmcutil/lib/xbmcutil/videohostsAPI.py
+++ b/script.module.xbmcutil/lib/xbmcutil/videohostsAPI.py
@@ -28,10 +28,10 @@ from fastjson import load
 
 class YTChannelUploads(listitem.VirtualFS):
        @plugin.error_handler
-       def scraper(self, contentID=None):
+       def scraper(self):
                # Create Url Source
                urlString = 
u"http://gdata.youtube.com/feeds/api/users/%s/uploads";
-               contentID = plugin.get("url", contentID)
+               contentID = plugin["url"]
                url = urlString % contentID
                
                # Initialize Gdata API
@@ -42,10 +42,10 @@ class YTChannelUploads(listitem.VirtualFS):
                videoItems = Gdata.VideoGenerator()
                
                # Add Next Page and/or Playlist
-               if plugin.get("hasPlaylists",u"false") == u"true": 
self.add_youtube_playlists(contentID, label=u"Playlists")
+               if plugin.get("hasplaylists",u"false") == u"true": 
self.add_youtube_playlists(contentID, label=plugin.getuni(136), 
hasHD=plugin.get("hashd","none"))
                
                # Add Next Page
-               if Gdata.processed: 
self.add_next_page({"action":plugin["action"], "url":contentID, 
"processed":Gdata.processed})
+               if Gdata.processed: 
self.add_next_page({"action":plugin["action"], "url":contentID, 
"processed":Gdata.processed, "hashd":plugin.get("hashd","none")})
                
                # Set SortMethods and Content
                self.set_sort_methods(self.sort_method_date, 
self.sort_method_video_runtime, self.sort_method_program_count, 
self.sort_method_video_rating, self.sort_method_genre, self.sort_method_studio, 
self.sort_method_video_title)
@@ -56,10 +56,10 @@ class YTChannelUploads(listitem.VirtualFS):
 
 class YTChannelPlaylists(listitem.VirtualFS):
        @plugin.error_handler
-       def scraper(self, contentID=None):
+       def scraper(self):
                # Create Url Source
                urlString = 
u"http://gdata.youtube.com/feeds/api/users/%s/playlists";
-               contentID = plugin.get("url", contentID)
+               contentID = plugin["url"]
                url = urlString % contentID
                
                # Initialize Gdata API
@@ -70,7 +70,7 @@ class YTChannelPlaylists(listitem.VirtualFS):
                videoItems = Gdata.PlaylistGenerator(loop=True)
                
                # Add Next Page
-               if Gdata.processed: 
self.add_next_page({"action":plugin["action"], "url":contentID, 
"processed":Gdata.processed})
+               if Gdata.processed: 
self.add_next_page({"action":plugin["action"], "url":contentID, 
"processed":Gdata.processed, "hashd":plugin.get("hashd","none")})
                
                # Set SortMethods and Content
                self.set_sort_methods(self.sort_method_video_title, 
self.sort_method_date)
@@ -81,10 +81,10 @@ class YTChannelPlaylists(listitem.VirtualFS):
 
 class YTPlaylistVideos(listitem.VirtualFS):
        @plugin.error_handler
-       def scraper(self, contentID=None):
+       def scraper(self):
                # Create Url Source
                urlString = u"http://gdata.youtube.com/feeds/api/playlists/%s";
-               contentID = plugin.get("url", contentID)
+               contentID = plugin["url"]
                url = urlString % contentID
                
                # Initialize Gdata API
@@ -95,8 +95,8 @@ class YTPlaylistVideos(listitem.VirtualFS):
                videoItems = Gdata.VideoGenerator()
                
                # Add Next Page
-               if Gdata.processed: 
self.add_next_page({"action":plugin["action"], "url":contentID, 
"processed":Gdata.processed})
-
+               if Gdata.processed: 
self.add_next_page({"action":plugin["action"], "url":contentID, 
"processed":Gdata.processed, "hashd":plugin.get("hashd","none")})
+               
                # Set Content Properties
                self.set_sort_methods(self.sort_method_date, 
self.sort_method_video_runtime, self.sort_method_program_count, 
self.sort_method_video_rating, self.sort_method_genre, self.sort_method_studio, 
self.sort_method_video_title)
                self.set_content("episodes")
@@ -106,10 +106,10 @@ class YTPlaylistVideos(listitem.VirtualFS):
 
 class YTRelatedVideos(listitem.VirtualFS):
        @plugin.error_handler
-       def scraper(self, contentID=None):
+       def scraper(self):
                # Create Url Source
                urlString = 
u"http://gdata.youtube.com/feeds/api/videos/%s/related";
-               contentID = plugin.get("url", contentID)
+               contentID = plugin["url"]
                url = urlString % contentID
                
                # Initialize Gdata API
@@ -133,11 +133,21 @@ class YoutubeAPI:
                # Fetch Filter String Based of Filter Mode
                if filterMode == "video": self.filterString = 
u"openSearch:totalResults,entry(yt:statistics,gd:rating,media:group(yt:videoid,media:title,yt:aspectRatio,yt:duration,media:credit,media:category,media:description,yt:uploaded))"
                elif filterMode == "playlists": self.filterString = 
u"openSearch:totalResults,entry(yt:playlistId,yt:countHint,title,summary,published,media:group(media:thumbnail))"
+               
+               # Fetch Youtube Video Quality Setting
+               try: setting = 
int(plugin.getAddonSetting("plugin.video.youtube", "hd_videos"))
+               except: self.isHD = None
+               else:
+                       # Set HD Flag based of Youtube Setting
+                       hashd = plugin.get("hashd", "none")
+                       if setting == 1 or hashd == "false": self.isHD = False
+                       elif (setting == 0 or setting >= 2) and hashd == 
u"true": self.isHD = True
+                       else: self.isHD = None
        
        def ProcessUrl(self):
                # Fetch SourceCode
                url = 
u"%s?v=2&max-results=%i&start-index=%i&alt=json&fields=%s" % (self.baseUrl, 
self.maxResults, self.processed+1, self.filterString)
-               sourceObj = urlhandler.urlopen(url, 28800)
+               sourceObj = urlhandler.urlopen(url, 14400) # TTL = 4 Hours
                
                # Fetch List of Entries
                feed = load(sourceObj)[u"feed"]
@@ -155,10 +165,12 @@ class YoutubeAPI:
                # Setup Converter and Optimizations
                results = []
                localInt = int
+               isHD = self.isHD
                localFloat = float
                imagePath = u"http://img.youtube.com/vi/%s/0.jpg";
                localListItem = listitem.ListItem
                addItem = results.append
+               hashd = plugin.get("hashd","none")
                
                while 1:
                        # Loop Entries
@@ -200,10 +212,14 @@ class YoutubeAPI:
                                if u"yt$aspectRatio" in mediaGroup and 
mediaGroup[u"yt$aspectRatio"][u"$t"] == u"widescreen": 
item.setStreamDict("aspect", 1.78)
                                
                                # Add Context item to link to related videos
-                               
item.addRelatedContext(action="system.videohosts.YTRelatedVideos", url=videoID)
+                               
item.addRelatedContext(action="system.videohosts.YTRelatedVideos", url=videoID, 
hashd=hashd)
+                               
+                               # Set Quality and Audio Overlays
+                               item.setQualityIcon(isHD)
+                               item.setAudioInfo()
                                
                                # Add InfoLabels and Data to Processed List
-                               addItem(item.getListitemTuple(isPlayable=True))
+                               addItem(item.getListitemTuple(True))
                        
                        # Fetch Next Set of Pages if Available
                        if (loop == True) and (self.processed): 
self.ProcessUrl()
@@ -215,6 +231,7 @@ class YoutubeAPI:
        def PlaylistGenerator(self, loop=False):
                results = []
                addItem = results.append
+               hashd = plugin.get("hashd", "none")
                while True:
                        # Loop Entries
                        for node in self.entries:
@@ -224,6 +241,7 @@ class YoutubeAPI:
                                
                                # Fetch Video ID
                                item.setParamDict("url", 
node[u"yt$playlistId"][u"$t"])
+                               item.setParamDict("hashd", hashd)
                                
                                # Fetch Title and Video Cound for combining 
Title
                                item.setLabel(u"%s (%s)" % 
(node[u"title"][u"$t"], node[u"yt$countHint"][u"$t"]))
@@ -238,7 +256,7 @@ class YoutubeAPI:
                                if u"published" in node: 
item.setDateInfo(node[u"published"][u"$t"].split(u"T")[0], "%Y-%m-%d")
                                
                                # Add InfoLabels and Data to Processed List
-                               addItem(item.getListitemTuple())
+                               addItem(item.getListitemTuple(False))
                        
                        # Fetch Next Set of Pages if Available
                        if (loop == True) and (self.processed): 
self.ProcessUrl()
@@ -246,112 +264,3 @@ class YoutubeAPI:
                
                # Return List of Listitems
                return results
-
-############################## VimeoAPI ##############################
-
-class VUserVideos(listitem.VirtualFS):
-       @plugin.error_handler
-       def scraper(self, contentID=None):
-               # Create Url Source
-               urlString = u"http://vimeo.com/api/v2/%s/videos.json";
-               contentID = plugin.get("url", contentID)
-               url = urlString % contentID
-               
-               # Fetch User Info
-               pagelimit = int(plugin.get("pagelimit", 0))
-               if pagelimit == 0:
-                       info = VimeoAPI.user_info(contentID)
-                       pagelimit = (info[u"total_videos_uploaded"] -1) / 20 + 1
-               
-               # Initialize Vimeo API
-               Vimeo = VimeoAPI(url, int(plugin.get("currentpage",1)), 
pagelimit)
-               Vimeo.ProcessUrl()
-               
-               # Fetch Video Results
-               videoItems = Vimeo.VideoGenerator()
-               
-               # Add Next Page
-               #if Vimeo.currentPage: self.add_next_page({"url":contentID, 
"pagelimit":Vimeo.pageLimit, "currentpage":Vimeo.currentPage})
-               
-               # Set Content Properties
-               self.set_sort_methods(self.sort_method_date, 
self.sort_method_video_runtime, self.sort_method_genre, 
self.sort_method_video_title)
-               self.set_content("episodes")
-               
-               # Return List of Video Listitems
-               return videoItems
-
-class VimeoAPI:
-       @classmethod
-       def user_info(self, userID):
-               # Create Url String
-               url = u"http://vimeo.com/api/v2/%s/info.json"; % userID
-               sourceObj = urlhandler.urlopen(url, 604800)
-               
-               # Fetch User Info
-               info = load(sourceObj)
-               sourceObj.close()
-               return info
-       
-       def __init__(self, baseUrl, currentPage=1, pageLimit=3):
-               # Set Global Vars
-               self.baseUrl = baseUrl
-               self.currentPage = currentPage
-               
-               # Restrict Page Limit to 3, Only 3 Pages allowed for Simple API
-               if pageLimit > 3: self.pageLimit = 3
-               else: self.pageLimit = pageLimit
-       
-       def ProcessUrl(self):
-               # Fetch SourceCode
-               sourceObj = urlhandler.urlopen(u"%s?page=%i" % (self.baseUrl, 
self.currentPage), 28800)
-               
-               # Fetch List of Entries
-               self.entries = load(sourceObj)
-               sourceObj.close()
-               
-               # Increment Page Counter
-               if self.currentPage >= self.pageLimit: self.currentPage = 0
-               else: self.currentPage += 1
-       
-       def VideoGenerator(self, loop=False):
-               # Setup Converter and Optimizations
-               results = []
-               localListItem = listitem.ListItem
-               addItem = results.append
-               
-               while 1:
-                       # Loop Entries
-                       for node in self.entries:
-                               # Create listitem object
-                               item = localListItem()
-                               
-                               # Fetch Title
-                               item.setLabel(node[u"title"])
-                               
-                               # Fetch Video ID and Set Actions
-                               item.setParamDict(action="system.source", 
sourcetype="vimeo_com", url=node[u"id"])
-                               
-                               # Fetch Plot Description
-                               item.setInfoDict(plot=node[u"description"], 
genre=node[u"tags"].replace(u'"',u'').split(u",")[0])
-                               
-                               # Fetch Duration and Convert to String
-                               item.setDurationInfo(node[u"duration"])
-                               
-                               # Fetch Date of Video
-                               item.setDateInfo(node[u"upload_date"].split(u" 
")[0], "%Y-%m-%d")
-                               
-                               # Add Thumbnail Image
-                               item.setThumbnailImage(node[u"thumbnail_large"])
-                               
-                               # Add Quality Overlay
-                               item.setStreamDict(codec="h264", 
width=node[u"width"], height=node[u"height"])
-                               
-                               # Add InfoLabels and Data to Processed List
-                               addItem(item.getListitemTuple(isPlayable=True))
-                       
-                       # Fetch Next Set of Pages if Available
-                       if (loop == True) and (self.currentPage): 
self.ProcessUrl()
-                       else: break
-               
-               # Return List of Listitems
-               return results

-----------------------------------------------------------------------

Summary of changes:
 script.module.xbmcutil/addon.xml                   |    3 +-
 script.module.xbmcutil/changelog.txt               |   14 +
 script.module.xbmcutil/lib/fastjson.py             |   10 +-
 script.module.xbmcutil/lib/xbmcutil/__init__.py    |  542 +++++-----------
 script.module.xbmcutil/lib/xbmcutil/listitem.py    |  431 ++++++-------
 script.module.xbmcutil/lib/xbmcutil/storageDB.py   |   13 +-
 script.module.xbmcutil/lib/xbmcutil/urlhandler.py  |  160 +++--
 .../lib/xbmcutil/videoResolver.py                  |  674 +++++---------------
 .../lib/xbmcutil/videohostsAPI.py                  |  161 +----
 .../resources/language/English/strings.po          |  151 +++++
 .../resources/language/English/strings.xml         |   40 --
 11 files changed, 819 insertions(+), 1380 deletions(-)
 create mode 100644 script.module.xbmcutil/resources/language/English/strings.po
 delete mode 100644 
script.module.xbmcutil/resources/language/English/strings.xml


hooks/post-receive
-- 
Scripts

------------------------------------------------------------------------------
Want fast and easy access to all the code in your enterprise? Index and
search up to 200,000 lines of code with a free copy of Black Duck
Code Sight - the same software that powers the world's largest code
search on Ohloh, the Black Duck Open Hub! Try it now.
http://p.sf.net/sfu/bds
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons

Reply via email to