The branch, dharma has been updated
       via  c89d9189223fb0b7fc3ecc0925c29b41cd911ed7 (commit)
       via  6e374f8700babf72c39faa28774c9d98c0b53c1d (commit)
      from  218c32754f92ad00af0e3ef861b7bc11050aa3cf (commit)

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

commit c89d9189223fb0b7fc3ecc0925c29b41cd911ed7
Author: amet <[email protected]>
Date:   Wed Jan 26 14:55:49 2011 +0400

    [script.trakt] -v 0.1.1
    - excluded all videos starting with http://
    - fixed url encoding of special chars when searching for tvdb id's
    - added year to IMDB id query

diff --git a/script.trakt/addon.xml b/script.trakt/addon.xml
index 83184c1..c34d328 100644
--- a/script.trakt/addon.xml
+++ b/script.trakt/addon.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon id="script.trakt"
        name="trakt"
-       version="0.1.0"
+       version="0.1.1"
        provider-name="rudf0rd">
   <requires>
     <import addon="xbmc.python" version="1.0"/>
@@ -9,8 +9,10 @@
   <extension point="xbmc.python.script"
              library="default.py" />
   <extension point="xbmc.addon.metadata">
-    <summary lang="en">trakt</summary>
+    <summary lang="en">trakt helps keep a record of what TV shows and movies 
you are watching. Based on your favorites, trakt recommends additional shows 
and movies you'll enjoy!</summary>
     <description lang="en">
+               The XMBC plugin for trakt automatically fills your library and 
updates it with what you've been watching in XBMC. For best results, make sure 
you are in library mode.
+               
                Installation instructions: 
                After installing this plugin, sign up for an account at 
http://trakt.tv.  Then.. 
                
@@ -18,7 +20,7 @@
                2. Enter in username and password that you have set up on the 
trakt website and any other configuration you would like 
                3. Navigate to Home > Programs and activate trakt* (location of 
trakt activation is skin dependent and may be in other places labeled Addons, 
Scripts, etc.) 
                
-               Note: if you do not configure trakt to autostart, you will need 
to repeat step 5 any time you would like to submit tv shows
+               Note: if you do not configure trakt to autostart, you will need 
to repeat step 3 any time you would like to submit tv shows
     </description>
     <platform>all</platform>
   </extension>
diff --git a/script.trakt/changelog.txt b/script.trakt/changelog.txt
index 80e8245..7fb0d7f 100644
--- a/script.trakt/changelog.txt
+++ b/script.trakt/changelog.txt
@@ -1,3 +1,8 @@
+Version 0.1.1
+       - excluded all videos starting with http://
+       - fixed url encoding of special chars when searching for tvdb id's
+       - added year to IMDB id query
+       
 Version 0.1.0
        - added Spanish translation thanks to MaDDoGo!
        - removed check for year since the year is missing if you start a tv 
show/movie in certain manners (ex: android xbmc remote)
diff --git a/script.trakt/default.py b/script.trakt/default.py
index e64c657..c3d339c 100644
--- a/script.trakt/default.py
+++ b/script.trakt/default.py
@@ -12,7 +12,7 @@ import re
 __scriptname__ = "trakt"
 __author__ = "Sean Rudford"
 __url__ = "http://trakt.tv/";
-__version__ = "0.1.0"
+__version__ = "0.1.1"
 __XBMC_Revision__ = ""
 
 def addPadding(number):
@@ -59,8 +59,11 @@ def CheckAndSubmit(Manual=False):
         if ((xbmc.getInfoLabel("VideoPlayer.mpaa") == "XXX")):
             Debug('Video is with XXX mpaa rating', False)
             bRatingExcluded = True
+        currentPath = xbmc.Player().getPlayingFile()
+        if (currentPath.find("http://";) > -1):
+            Debug("Video is playing via web source.  Excluded.", False)
+            bPathExcluded = True
         if ((__settings__.getSetting( "ExcludePath" ) != "") and 
(__settings__.getSetting( "ExcludePathOption" ) == 'true')):
-            currentPath = xbmc.Player().getPlayingFile()
             if (currentPath.find(__settings__.getSetting( "ExcludePath" )) > 
-1):
                 Debug('Video is located in excluded path', False)
                 bPathExcluded = True
@@ -208,6 +211,7 @@ if ((bStartup and bAutoStart) or bRun):
         if (xbmc.abortRequested):
             break
             
-        time.sleep(sleepTime)
+        # time.sleep(sleepTime)
+        time.sleep(10)
 
 Debug( 'Exiting...', False)
diff --git a/script.trakt/resources/lib/utilities.py 
b/script.trakt/resources/lib/utilities.py
index b14f854..8ad5c71 100644
--- a/script.trakt/resources/lib/utilities.py
+++ b/script.trakt/resources/lib/utilities.py
@@ -1,260 +1,272 @@
-import sys
-import os
-import xbmc
-import xbmcaddon
-import re
-import string
-import urllib
-import urllib2
-from urllib2 import URLError
-
-# disgracefully stolen from xbmc subtitles
-try:
-  # Python 2.6 +
-  from hashlib import sha as sha
-except ImportError:
-  # Python 2.5 and earlier
-  import sha
-
-__settings__ = xbmcaddon.Addon(id='script.trakt')
-__language__ = __settings__.getLocalizedString
-__version__ = "0.1.0"
-__cwd__ = __settings__.getAddonInfo('path')
-
-#Path handling
-LANGUAGE_RESOURCE_PATH = xbmc.translatePath( os.path.join( __cwd__, 
'resources', 'language' ) )
-CONFIG_PATH = xbmc.translatePath( os.path.join( __cwd__, 'resources', 
'settings.cfg' ) )
-AUTOEXEC_PATH = xbmc.translatePath( 'special://home/userdata/autoexec.py' )
-AUTOEXEC_FOLDER_PATH = xbmc.translatePath( 'special://home/userdata/' )
-VERSION_PATH = xbmc.translatePath( os.path.join( __cwd__, 'resources', 
'version.cfg' ) )
-
-#Consts
-AUTOEXEC_SCRIPT = '\nimport 
time;time.sleep(5);xbmc.executebuiltin("XBMC.RunScript(special://home/addons/script.trakt/default.py,-startup)")\n'
-
-def SendUpdate(info, progress, sType, status):
-    Debug("Creating data to send", False)
-    
-    bUsername = __settings__.getSetting( "Username" )
-    bPassword = sha.new(__settings__.getSetting( "Password" )).hexdigest()
-    bNotify = __settings__.getSetting( "NotifyOnSubmit" )
-    
-    
-    if (bUsername == '' or bPassword == ''):
-        Debug("Username or password not set", False)
-        notification("Trakt", __language__(45051).encode( "utf-8", "ignore" ), 
5000, __settings__.getAddonInfo("icon"))
-        return False
-    
-    Debug(info, False)
-    
-    if (sType == "TVShow"):
-        ID = getID(sType, 
unicode(xbmc.getInfoLabel("VideoPlayer.TvShowTitle"), 'utf-8'))
-    elif (sType == "Movie"):
-        ID = getID(sType, 
urllib.quote(xbmc.getInfoLabel("VideoPlayer.Title"))) 
-    
-    Debug("IMDB/tvdb id: "+ID);
-    
-    # split on type and create data packet for each type
-    if (sType == "Movie"):
-        Debug("Parsing Movie", False)
-        
-        # format: title, year
-        title, year = info.split(",")
-        
-        # check to make sure the data is there
-        # otherwise return
-        if(title == ''):
-            return
-        
-        # set alert text
-        submitAlert = __language__(45052).encode( "utf-8", "ignore" )
-        submitAlert = submitAlert.replace('%MOVIENAME%', title)
-        submitAlert = submitAlert.replace('%YEAR%', year)
-        
-        toSend = urllib.urlencode({ "type": sType,
-                                    "status": status,
-                                    "title": title, 
-                                    "year": year,
-                                    "imdbid": ID,
-                                    "progress": progress,
-                                    "plugin_version": __version__,
-                                    "media_center": 'xbmc',
-                                    "media_center_version": xbmc.getInfoLabel( 
"system.buildversion" ),
-                                    "media_center_date": xbmc.getInfoLabel( 
"system.builddate" ),
-                                    "duration": 
xbmc.getInfoLabel("VideoPlayer.Duration"),
-                                    "username": bUsername, 
-                                    "password": bPassword})
-    elif (sType == "TVShow"):
-        Debug("Parsing TVShow", False)
-        
-        # format: title, year, season, episode
-        title, year, season, episode = info.split(",")
-        
-        # check to make sure the data is there
-        # otherwise return
-        if(title == '' or season == '' or episode == ''):
-            return
-        
-        # set alert text
-        submitAlert = __language__(45053).encode( "utf-8", "ignore" )
-        submitAlert = submitAlert.replace('%TVSHOW%', title)
-        submitAlert = submitAlert.replace('%SEASON%', season)
-        submitAlert = submitAlert.replace('%EPISODE%', episode)
-        
-        toSend = urllib.urlencode({ "type": sType,
-                                    "status": status,
-                                    "title": title, 
-                                    "year": year, 
-                                    "season": season, 
-                                    "episode": episode,
-                                    "tvdbid": ID,
-                                    "progress": progress,
-                                    "plugin_version": __version__,
-                                    "media_center": 'xbmc',
-                                    "media_center_version": xbmc.getInfoLabel( 
"system.buildversion" ),
-                                    "media_center_date": xbmc.getInfoLabel( 
"system.builddate" ),
-                                    "duration": 
xbmc.getInfoLabel("VideoPlayer.Duration"),
-                                    "username": bUsername, 
-                                    "password": bPassword})
-        
-    Debug("Data: "+toSend, False)
-    
-    # send
-    transmit(toSend)
-    # and notify if wanted
-    if (bNotify == "true" and status == "watched"):
-        notification("Trakt", submitAlert, 3000, 
__settings__.getAddonInfo("icon"))
-    
-def transmit(status):
-    bNotify = __settings__.getSetting( "NotifyOnSubmit" )
-
-    req = urllib2.Request("http://api.trakt.tv/post";,
-            status,
-            headers = { "Accept": "*/*",   
-                        "User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; 
Windows NT)", 
-                      })
-
-    try:
-        f = urllib2.urlopen(req)
-        response = f.read()
-        Debug("Return packet: "+response)
-        
-    except URLError, e:
-        if e.code == 401:
-            Debug("Bad username or password", False)
-            if (bNotify == "true"):
-                notification("Trakt: Bad Authentication!", "Check your login 
information", 5000, __settings__.getAddonInfo("icon"))
-                
-    except:
-        # do nothing 'cept spit out error (catch all)
-        if (bNotify == "true"):
-            notification("Trakt", "Error sending status.  API may not be 
reachable", 10000, __settings__.getAddonInfo("icon"))
-
-
-def Debug(message, Verbose=True):
-    message = "TRAKT: " + message
-    bVerbose = __settings__.getSetting( "debug" )
-    if (bVerbose == 'true'):
-        bVerbose = True
-    else:
-        bVerbose = False
-    
-    if (bVerbose and Verbose):
-        # repr() is used, got wierd issues with unicode otherwise, since we 
send mixed string types (eg: unicode and ascii) 
-        print repr(message)
-    elif (not Verbose):
-        # repr() is used, got wierd issues with unicode otherwise, since we 
send mixed string types (eg: unicode and ascii) 
-        print repr(message)
-
-def CalcPercentageRemaining(currenttime, duration):
-    try:
-        iCurrentMinutes = (int(currenttime.split(':')[0]) * 60) + 
int(currenttime.split(':')[1])
-    except:
-        iCurrentMinutes = int(0)
-        
-    try:
-        iDurationMinutes = (int(duration.split(':')[0]) * 60) + 
int(duration.split(':')[1])
-    except:
-        iDurationMinutes = int(0)
-
-    try:
-        Debug( 'Percentage of progress: ' + str(float(iCurrentMinutes) / 
float(iDurationMinutes)), True)
-        return float(iCurrentMinutes) / float(iDurationMinutes) 
-    except:
-        Debug( 'Percentage of progress: null', True)
-        return float(0.0)
-
-def SetAutoStart(bState = True):
-    Debug( '::AutoStart::' + str(bState), True)
-    if (os.path.exists(AUTOEXEC_PATH)):
-        Debug( 'Found Autoexec.py file, checking we''re there', True)
-        bFound = False
-        autoexecfile = file(AUTOEXEC_PATH, 'r')
-        filecontents = autoexecfile.readlines()
-        autoexecfile.close()
-        for line in filecontents:
-            if line.find('trakt') > 0:
-                Debug( 'Found our script, no need to do anything', True)
-                bFound = True
-        if (not bFound):
-            Debug( 'Appending our script to the autoexec.py script', True)
-            autoexecfile = file(AUTOEXEC_PATH, 'w')
-            filecontents.append(AUTOEXEC_SCRIPT)
-            autoexecfile.writelines(filecontents)            
-            autoexecfile.close()
-        if (bFound and not bState):
-            #remove line
-            Debug( 'Removing our script from the autoexec.py script', True)
-            autoexecfile = file(AUTOEXEC_PATH, 'w')
-            for line in filecontents:
-                if not line.find('trakt') > 0:
-                    autoexecfile.write(line)
-            autoexecfile.close()            
-    else:
-        if (os.path.exists(AUTOEXEC_FOLDER_PATH)):
-            Debug( 'File Autoexec.py is missing, creating file with autostart 
script', True)
-            autoexecfile = file(AUTOEXEC_PATH, 'w')
-            autoexecfile.write (AUTOEXEC_SCRIPT.strip())
-            autoexecfile.close()
-        else:
-            Debug( 'Scripts folder is missing, creating folder and autoexec.py 
file with autostart script', True)
-            os.makedirs(AUTOEXEC_FOLDER_PATH)
-            autoexecfile = file(AUTOEXEC_PATH, 'w')
-            autoexecfile.write (AUTOEXEC_SCRIPT.strip())
-            autoexecfile.close()
-    Debug( '::AutoStart::'  , True)
-
-def notification( header="", message="", sleep=5000, 
icon=__settings__.getAddonInfo( "icon" ) ):
-    """ Will display a notification dialog with the specified header and 
message,
-        in addition you can set the length of time it displays in milliseconds 
and a icon image. 
-    """
-    xbmc.executebuiltin( "XBMC.Notification(%s,%s,%i,%s)" % ( header, message, 
sleep, icon ) )
-    
-def getID(sType, title):
-    Debug("Title sent to getID: "+title, False)
-    video_id = ""
-    if (sType == "TVShow"):
-        # get tvdb id
-        try:
-            query = "select c12 from tvshow where lower(c00) = lower('" + 
title + "') limit 1"
-            res = xbmc.executehttpapi("queryvideodatabase(" + query + ")")
-            tvid = re.findall('[\d.]*\d+',res) # find it
-
-            if len(tvid[0].strip()) >= 1:
-                video_id = tvid[0].strip();
-        except:        
-            video_id = ""
-    else:
-        try:
-            query = "select movie.c09 from movie where lower(movie.c00) = 
lower('" + title + "') limit 1"
-            Debug(query)
-            res = xbmc.executehttpapi("queryvideodatabase(" + query + ")")
-            Debug(res)
-            movieid = re.findall('<field>(.*?)</field>',res) # find it
-
-            if len(str(movieid[0])) >= 1:
-                Debug("Final answer (for id!) --> "+str(movieid[0]))
-                video_id = str(movieid[0])
-        except:
-            video_id = ""
-    
+import sys

+import os

+import xbmc

+import xbmcaddon

+import re

+import string

+import urllib

+import urllib2

+from urllib2 import URLError

+

+# disgracefully stolen from xbmc subtitles

+try:

+  # Python 2.6 +

+  from hashlib import sha as sha

+except ImportError:

+  # Python 2.5 and earlier

+  import sha

+

+__settings__ = xbmcaddon.Addon(id='script.trakt')

+__language__ = __settings__.getLocalizedString

+__version__ = "0.1.1"

+__cwd__ = __settings__.getAddonInfo('path')

+

+#Path handling

+LANGUAGE_RESOURCE_PATH = xbmc.translatePath( os.path.join( __cwd__, 
'resources', 'language' ) )

+CONFIG_PATH = xbmc.translatePath( os.path.join( __cwd__, 'resources', 
'settings.cfg' ) )

+AUTOEXEC_PATH = xbmc.translatePath( 'special://home/userdata/autoexec.py' )

+AUTOEXEC_FOLDER_PATH = xbmc.translatePath( 'special://home/userdata/' )

+VERSION_PATH = xbmc.translatePath( os.path.join( __cwd__, 'resources', 
'version.cfg' ) )

+

+#Consts

+AUTOEXEC_SCRIPT = '\nimport 
time;time.sleep(5);xbmc.executebuiltin("XBMC.RunScript(special://home/addons/script.trakt/default.py,-startup)")\n'

+

+def SendUpdate(info, progress, sType, status):

+    Debug("Creating data to send", False)

+    

+    bUsername = __settings__.getSetting( "Username" )

+    bPassword = sha.new(__settings__.getSetting( "Password" )).hexdigest()

+    bNotify = __settings__.getSetting( "NotifyOnSubmit" )

+    

+    

+    if (bUsername == '' or bPassword == ''):

+        Debug("Username or password not set", False)

+        notification("Trakt", __language__(45051).encode( "utf-8", "ignore" ), 
5000, __settings__.getAddonInfo("icon"))

+        return False

+    

+    Debug(info, False)

+    

+    

+    

+    # split on type and create data packet for each type

+    if (sType == "Movie"):

+        Debug("Parsing Movie", False)

+        

+        # format: title, year

+        title, year = info.split(",")

+        if (year == ''):

+            year_for_id = False

+        else:

+            year_for_id = year

+        ID = getID(sType, xbmc.getInfoLabel("VideoPlayer.Title"), year_for_id)

+        Debug("IMDB: "+ID);

+        

+        # check to make sure the data is there

+        # otherwise return

+        if(title == ''):

+            return

+        

+        # set alert text

+        submitAlert = __language__(45052).encode( "utf-8", "ignore" )

+        submitAlert = submitAlert.replace('%MOVIENAME%', title)

+        submitAlert = submitAlert.replace('%YEAR%', year)

+        

+        toSend = urllib.urlencode({ "type": sType,

+                                    "status": status,

+                                    "title": title, 

+                                    "year": year,

+                                    "imdbid": ID,

+                                    "progress": progress,

+                                    "plugin_version": __version__,

+                                    "media_center": 'xbmc',

+                                    "media_center_version": xbmc.getInfoLabel( 
"system.buildversion" ),

+                                    "media_center_date": xbmc.getInfoLabel( 
"system.builddate" ),

+                                    "duration": 
xbmc.getInfoLabel("VideoPlayer.Duration"),

+                                    "username": bUsername, 

+                                    "password": bPassword})

+    elif (sType == "TVShow"):

+        Debug("Parsing TVShow", False)

+        

+        # format: title, year, season, episode

+        title, year, season, episode = info.split(",")

+        if (year == ''):

+            year_for_id = False

+        else:

+            year_for_id = year

+        ID = getID(sType, xbmc.getInfoLabel("VideoPlayer.TvShowTitle"), 
year_for_id) 

+        Debug("TVDB id: "+ID);

+        

+        # check to make sure the data is there

+        # otherwise return

+        if(title == '' or season == '' or episode == ''):

+            return

+        

+        # set alert text

+        submitAlert = __language__(45053).encode( "utf-8", "ignore" )

+        submitAlert = submitAlert.replace('%TVSHOW%', title)

+        submitAlert = submitAlert.replace('%SEASON%', season)

+        submitAlert = submitAlert.replace('%EPISODE%', episode)

+        

+        toSend = urllib.urlencode({ "type": sType,

+                                    "status": status,

+                                    "title": title, 

+                                    "year": year, 

+                                    "season": season, 

+                                    "episode": episode,

+                                    "tvdbid": ID,

+                                    "progress": progress,

+                                    "plugin_version": __version__,

+                                    "media_center": 'xbmc',

+                                    "media_center_version": xbmc.getInfoLabel( 
"system.buildversion" ),

+                                    "media_center_date": xbmc.getInfoLabel( 
"system.builddate" ),

+                                    "duration": 
xbmc.getInfoLabel("VideoPlayer.Duration"),

+                                    "username": bUsername, 

+                                    "password": bPassword})

+        

+    Debug("Data: "+toSend, False)

+    

+    # send

+    #transmit(toSend)

+    # and notify if wanted

+    if (bNotify and status == "watched"):

+        notification("Trakt", submitAlert, 3000, 
__settings__.getAddonInfo("icon"))

+    

+def transmit(status):

+    bNotify = __settings__.getSetting( "NotifyOnSubmit" )

+

+    req = urllib2.Request("http://api.trakt.tv/post";,

+            status,

+            headers = { "Accept": "*/*",   

+                        "User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; 
Windows NT)", 

+                      })

+

+    try:

+        f = urllib2.urlopen(req)

+        response = f.read()

+        Debug("Return packet: "+response)

+        

+    except URLError, e:

+        if e.code == 401:

+            Debug("Bad username or password", False)

+            if (bNotify):

+                notification("Trakt: Bad Authentication!", "Check your login 
information", 5000, __settings__.getAddonInfo("icon"))

+                

+    except:

+        # do nothing 'cept spit out error (catch all)

+        if (bNotify):

+            notification("Trakt", "Error sending status.  API may not be 
reachable", 10000, __settings__.getAddonInfo("icon"))

+

+

+def Debug(message, Verbose=True):

+    message = "TRAKT: " + message

+    bVerbose = __settings__.getSetting( "debug" )

+    if (bVerbose == 'true'):

+        bVerbose = True

+    else:

+        bVerbose = False

+    

+    if (bVerbose and Verbose):

+        # repr() is used, got wierd issues with unicode otherwise, since we 
send mixed string types (eg: unicode and ascii) 

+        print repr(message)

+    elif (not Verbose):

+        # repr() is used, got wierd issues with unicode otherwise, since we 
send mixed string types (eg: unicode and ascii) 

+        print repr(message)

+

+def CalcPercentageRemaining(currenttime, duration):

+    try:

+        iCurrentMinutes = (int(currenttime.split(':')[0]) * 60) + 
int(currenttime.split(':')[1])

+    except:

+        iCurrentMinutes = int(0)

+        

+    try:

+        iDurationMinutes = (int(duration.split(':')[0]) * 60) + 
int(duration.split(':')[1])

+    except:

+        iDurationMinutes = int(0)

+

+    try:

+        Debug( 'Percentage of progress: ' + str(float(iCurrentMinutes) / 
float(iDurationMinutes)), True)

+        return float(iCurrentMinutes) / float(iDurationMinutes) 

+    except:

+        Debug( 'Percentage of progress: null', True)

+        return float(0.0)

+

+def SetAutoStart(bState = True):

+    Debug( '::AutoStart::' + str(bState), True)

+    if (os.path.exists(AUTOEXEC_PATH)):

+        Debug( 'Found Autoexec.py file, checking we''re there', True)

+        bFound = False

+        autoexecfile = file(AUTOEXEC_PATH, 'r')

+        filecontents = autoexecfile.readlines()

+        autoexecfile.close()

+        for line in filecontents:

+            if line.find('trakt') > 0:

+                Debug( 'Found our script, no need to do anything', True)

+                bFound = True

+        if (not bFound):

+            Debug( 'Appending our script to the autoexec.py script', True)

+            autoexecfile = file(AUTOEXEC_PATH, 'w')

+            filecontents.append(AUTOEXEC_SCRIPT)

+            autoexecfile.writelines(filecontents)            

+            autoexecfile.close()

+        if (bFound and not bState):

+            #remove line

+            Debug( 'Removing our script from the autoexec.py script', True)

+            autoexecfile = file(AUTOEXEC_PATH, 'w')

+            for line in filecontents:

+                if not line.find('trakt') > 0:

+                    autoexecfile.write(line)

+            autoexecfile.close()            

+    else:

+        if (os.path.exists(AUTOEXEC_FOLDER_PATH)):

+            Debug( 'File Autoexec.py is missing, creating file with autostart 
script', True)

+            autoexecfile = file(AUTOEXEC_PATH, 'w')

+            autoexecfile.write (AUTOEXEC_SCRIPT.strip())

+            autoexecfile.close()

+        else:

+            Debug( 'Scripts folder is missing, creating folder and autoexec.py 
file with autostart script', True)

+            os.makedirs(AUTOEXEC_FOLDER_PATH)

+            autoexecfile = file(AUTOEXEC_PATH, 'w')

+            autoexecfile.write (AUTOEXEC_SCRIPT.strip())

+            autoexecfile.close()

+    Debug( '::AutoStart::'  , True)

+

+def notification( header="", message="", sleep=5000, 
icon=__settings__.getAddonInfo( "icon" ) ):

+    """ Will display a notification dialog with the specified header and 
message,

+        in addition you can set the length of time it displays in milliseconds 
and a icon image. 

+    """

+    xbmc.executebuiltin( "XBMC.Notification(%s,%s,%i,%s)" % ( header, message, 
sleep, icon ) )

+    

+def getID(sType, title, year=False):

+    Debug("Title sent to getID: "+title, False)

+    video_id = ""

+    if (sType == "TVShow"):

+        # get tvdb id

+        try:

+            # year isn't used here because i'm still trying to figure out how 
to reconcile air date vs tv show first air date

+            query = "select c12 from tvshow where lower(c00) = lower('" + 
title + "') limit 1"

+            Debug(query)

+            res = xbmc.executehttpapi("queryvideodatabase(" + query + ")")

+            tvid = re.findall('[\d.]*\d+',res) # find it

+

+            if len(tvid[0].strip()) >= 1:

+                video_id = tvid[0].strip();

+        except:        

+            video_id = ""

+    else:

+        try:

+            if(year):

+                query = "select movie.c09 from movie where movie.c07 = '" + 
year + "' and lower(movie.c00) = lower('" + title + "') limit 1"

+            else:

+                query = "select movie.c09 from movie where lower(movie.c00) = 
lower('" + title + "') limit 1"

+            Debug(query)

+            res = xbmc.executehttpapi("queryvideodatabase(" + query + ")")

+            Debug(res)

+            movieid = re.findall('<field>(.*?)</field>',res) # find it

+

+            if len(str(movieid[0])) >= 1:

+                video_id = str(movieid[0])

+        except:

+            video_id = ""

+            

+    Debug("Final answer (for id!) --> "+video_id)

     return video_id
\ No newline at end of file

http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/scripts;a=commit;h=6e374f8700babf72c39faa28774c9d98c0b53c1d

commit 6e374f8700babf72c39faa28774c9d98c0b53c1d
Author: amet <[email protected]>
Date:   Wed Jan 26 14:52:28 2011 +0400

    [script.mythbox] - 1.0.2
    -----------------------------
      New
        - Issue 148 - Dutch translations (tnx Fred van Zwieten)
    
      Fixed
        - Issue 145 - Fixed unicode error in Live TV window
        - Issue 147 - Changes to the recording schedule do not take effect 
immediately
        - Issue 149 - Help text on Settings screen gets truncated based on the 
translation
        - Added support for ScheduleType.NOT_RECORDING
        - TVRage grabber more resilient to incomplete season and episode 
information
        - Google image search now works for programs with unicode chars in the 
title

diff --git a/script.mythbox/FAQ b/script.mythbox/FAQ
index dc2ee87..66ae653 100644
--- a/script.mythbox/FAQ
+++ b/script.mythbox/FAQ
@@ -14,11 +14,10 @@ Q9. Where is the source code?
 Q10. When are you going to add feature <insert your feature here> to MythBox?

 Q11. What sort of MythTV setup do you use with MythBox?

 Q12. When I play a recorded program, I get nothing but a green screen.

-Q13. (Windows Only) Import errors when running scipt

-Q14. How do I fix a 'MySQL connection error 1043 bad handshake' error? 

-Q15. How do I fix a 'Connect to MySQL failed: Found EOF after Auth' error?

-Q16. What is the difference between XBMC's built-in myth:// protocol support 
and MythBox? 

-Q17. What is the plan to support the new Confluence skin released with XBMC 
9.11?

+Q13. How do I fix a 'MySQL connection error 1043 bad handshake' error? 

+Q14. How do I fix a 'Connect to MySQL failed: Found EOF after Auth' error?

+Q15. What is the difference between XBMC's built-in myth:// protocol support 
and MythBox? 

+Q16. What is the plan to support the new Confluence skin released with XBMC 
9.11?

 

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

 Q1. What should I do if I run into problems or something doesn't work?

@@ -161,14 +160,8 @@ Q12. When I play a recorded program, I get nothing but a 
green screen.
      2. Go to Utilites/Setup->Setup->TV Settings->Recording Profiles->Software 
Encoders->Live TV

      3. Set the codec to MPEG4 instead of RTjpeg.

 

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

-Q13. (Windows Only) Import errors when running scipt

-

-     Old versions of WinZip don't uncompress tar.gz files correctly. 

-     Upgrade to the latest version of WinZip and try again.

-

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

-Q14. How do I fix a 'MySQL connection error 1043 bad handshake' error?

+Q13. How do I fix a 'MySQL connection error 1043 bad handshake' error?

 

      Your MySQL database server is set to authenticate using the old MySQL 4.0 
style 

      instead of the newer style used since MySQL 4.1+. This is pretty easy to 
fix 

@@ -177,13 +170,13 @@ Q14. How do I fix a 'MySQL connection error 1043 bad 
handshake' error?
      reset it making sure you select MySQL 4.1+ for 'Password hashing'.

      

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

-Q15. How do I fix a 'Connect to MySQL failed: Found EOF after Auth' error?

+Q14. How do I fix a 'Connect to MySQL failed: Found EOF after Auth' error?

 

      1. Edit /etc/mysql/my.cnf and change old_passwords=1 to old_passwords=0

      2. Reset the password for the MythTV database (see Q14) and restart 
MythBox

 

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

-Q16. What is the difference between XBMC's myth:// protocol support and 
MythBox?     

+Q15. What is the difference between XBMC's myth:// protocol support and 
MythBox?     

      

      Feature                  MythBox        XBMC + myth://

      ==========================================================

@@ -201,7 +194,7 @@ Q16. What is the difference between XBMC's myth:// protocol 
support and MythBox?
      Network streaming        Live TV only   Yes

 

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

-Q17. What is the plan to support the new Confluence skin released in XBMC 9.11?

+Q16. What is the plan to support the new Confluence skin released in XBMC 9.11?

      

      While I've been able to cobble together the current look & feel of the

      MythBox user interface based on the PM3.HD skin, I am by no means 
aesthetically 

diff --git a/script.mythbox/addon.xml b/script.mythbox/addon.xml
index b719cd7..20381c6 100644
--- a/script.mythbox/addon.xml
+++ b/script.mythbox/addon.xml
@@ -2,7 +2,7 @@
 <addon 

     id="script.mythbox" 

     name="MythBox" 

-    version="1.0.1" 

+    version="1.0.2" 

     provider-name="[email protected]">

     <requires>

         <import addon="xbmc.python" version="1.0" />

diff --git a/script.mythbox/changelog.txt b/script.mythbox/changelog.txt
index 737d3aa..193e01c 100644
--- a/script.mythbox/changelog.txt
+++ b/script.mythbox/changelog.txt
@@ -1,3 +1,16 @@
+1/25/2011 - MythBox 1.0.2
+-----------------------------
+  New
+    - Issue 148 - Dutch translations (tnx Fred van Zwieten)
+    
+  Fixed
+    - Issue 145 - Fixed unicode error in Live TV window 
+    - Issue 147 - Changes to the recording schedule do not take effect 
immediately
+    - Issue 149 - Help text on Settings screen gets truncated based on the 
translation
+    - Added support for ScheduleType.NOT_RECORDING
+    - TVRage grabber more resilient to incomplete season and episode 
information
+    - Google image search now works for programs with unicode chars in the 
title
+    
 1/13/2011 - MythBox 1.0.1
 -----------------------------
   New
diff --git a/script.mythbox/default.py b/script.mythbox/default.py
index 060b6ae..6454c3c 100644
--- a/script.mythbox/default.py
+++ b/script.mythbox/default.py
@@ -1,7 +1,7 @@
 #
 #  MythBox for XBMC
 #
-#  Copyright (C) 2010 [email protected] 
+#  Copyright (C) 2011 [email protected] 
 #  http://mythbox.googlecode.com
 #
 #  This program is free software; you can redistribute it and/or
@@ -32,12 +32,13 @@ if __name__ == '__main__':
     #import rpdb2 
     #rpdb2.start_embedded_debugger('xxx')
 
-    import os, sys
-    sys.path.append(os.path.join(os.getcwd(), 'resources', 'src'))
+    import os, sys, xbmcaddon
+    scriptDir = xbmcaddon.Addon('script.mythbox').getAddonInfo('path')
+    sys.path.append(os.path.join(scriptDir, 'resources', 'src'))
 
     import xbmcgui
     import xbmc
-    splash = xbmcgui.WindowXML('mythbox_splash.xml', os.getcwd())
+    splash = xbmcgui.WindowXML('mythbox_splash.xml', scriptDir)
     splash.show()
     
     from mythbox.bootstrapper import BootStrapper
diff --git a/script.mythbox/resources/language/English/strings.xml 
b/script.mythbox/resources/language/English/strings.xml
index 2cd1a7f..5cdd201 100644
--- a/script.mythbox/resources/language/English/strings.xml
+++ b/script.mythbox/resources/language/English/strings.xml
@@ -135,6 +135,7 @@ To submit translations for your native language
   <string id="110">Recording Schedules</string>
   
   <!-- enums.ScheduleType -->
+  <string id="170">Not Recording</string>
   <string id="111">Once</string>

   <string id="112">Daily</string>

   <string id="113">Channel</string>

diff --git a/script.mythbox/resources/skins/Default/720p/mythbox_settings.xml 
b/script.mythbox/resources/skins/Default/720p/mythbox_settings.xml
index aa0fff4..0166a86 100644
--- a/script.mythbox/resources/skins/Default/720p/mythbox_settings.xml
+++ b/script.mythbox/resources/skins/Default/720p/mythbox_settings.xml
@@ -584,9 +584,9 @@
             <animation effect="fade" time="200">VisibleChange</animation>
            </control>
       
-           <control type="button">
+           <control type="label">
                <description>mythtv recording dirs help1</description>
-               <posx>300</posx>
+               <posx>310</posx>
                <posy>580</posy>
                <height>50</height>
                <width>900</width>
@@ -598,11 +598,12 @@
                        <visible>Control.HasFocus(205)</visible>
                        <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
            </control>
            
-           <control type="button">
+           <control type="label">
                <description>mythtv recording dirs help2</description>
-               <posx>300</posx>
+               <posx>310</posx>
                <posy>610</posy>
                <height>50</height>
                <width>900</width>
@@ -614,29 +615,12 @@
                        <visible>Control.HasFocus(205)</visible>
                        <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
            </control>
-
-        <!--
-           <control type="button">
-               <description>empty help</description>
-               <posx>300</posx>
-               <posy>580</posy>
-               <height>50</height>
-               <width>900</width>
-               <align>left</align>
-               <aligny>center</aligny>
-               <font>font12</font>
-               <textcolor>ffffffff</textcolor>
-               <label>SCRIPT418</label>
-                       <visible>Control.HasFocus(209)</visible>
-                       <texturenofocus>-</texturenofocus>
-            <animation effect="fade" time="200">VisibleChange</animation>
-           </control>
-        -->
          
-        <control type="button">
+        <control type="label">
             <description>aggressive caching help1</description>
-            <posx>300</posx>
+            <posx>310</posx>
             <posy>580</posy>
             <height>50</height>
             <width>900</width>
@@ -648,11 +632,12 @@
             <visible>Control.HasFocus(207)</visible>
             <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
         </control>
         
-        <control type="button">
+        <control type="label">
             <description>aggressive caching help2</description>
-            <posx>300</posx>
+            <posx>310</posx>
             <posy>610</posy>
             <height>50</height>
             <width>900</width>
@@ -664,6 +649,7 @@
             <visible>Control.HasFocus(207)</visible>
             <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
         </control>
 
            <control type="button">
@@ -714,9 +700,9 @@
             <animation effect="fade" time="200">VisibleChange</animation>
            </control>
 
-        <control type="button">
+        <control type="label">
             <description>lirc hack help1</description>
-            <posx>300</posx>
+            <posx>310</posx>
             <posy>580</posy>
             <height>50</height>
             <width>900</width>
@@ -728,11 +714,12 @@
             <visible>Control.HasFocus(501)</visible>
             <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
         </control>
 
-        <control type="button">
+        <control type="label">
             <description>lirc hack help2</description>
-            <posx>300</posx>
+            <posx>310</posx>
             <posy>610</posy>
             <height>50</height>
             <width>900</width>
@@ -744,11 +731,12 @@
             <visible>Control.HasFocus(501)</visible>
             <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
         </control>
 
-        <control type="button">
+        <control type="label">
             <description>twitter help</description>
-            <posx>300</posx>
+            <posx>310</posx>
             <posy>580</posy>
             <height>50</height>
             <width>900</width>
@@ -760,6 +748,7 @@
             <visible>Control.HasFocus(503)</visible>
             <texturenofocus>-</texturenofocus>
             <animation effect="fade" time="200">VisibleChange</animation>
+            <scroll>true</scroll>
         </control>
 
     </control>
diff --git a/script.mythbox/resources/src/mythbox/fanart.py 
b/script.mythbox/resources/src/mythbox/fanart.py
index a0a958d..62f27ae 100644
--- a/script.mythbox/resources/src/mythbox/fanart.py
+++ b/script.mythbox/resources/src/mythbox/fanart.py
@@ -493,7 +493,7 @@ class GoogleImageSearchProvider(BaseFanartProvider):
     def getPosters(self, program):
         posters = []
         try:
-            url_values = urllib.urlencode({'v':'1.0', 'safe':'on', 
'imgar':'t', 'q':program.title()})
+            url_values = urllib.urlencode({'v':'1.0', 'safe':'on', 
'imgar':'t', 'q':program.title()}, doseq=True)
             searchUrl = 
'http://ajax.googleapis.com/ajax/services/search/images?' + url_values
             req = urllib2.Request(searchUrl, 
headers={'Referer':'http://mythbox.googlecode.com'})
             resp = urllib2.urlopen(req)
@@ -510,7 +510,7 @@ class GoogleImageSearchProvider(BaseFanartProvider):
                 #log.debug('%d googleresult = %s' % (i, 
result['unescapedUrl']))
                 posters.append(result['unescapedUrl'])
         except Exception, e:
-            log.error('GOOGLE fanart search:  %s %s' % 
(safe_str(program.title()), str(e)))
+            log.exception('GOOGLE fanart search:  %s %s' % 
(safe_str(program.title()), str(e)))
         return posters
         
 
@@ -531,7 +531,7 @@ class TvRageProvider(NoOpFanartProvider):
         if program.title() in self.memcache.keys():
             return self.memcache[program.title()]
         
-        fname = os.path.join(self.cacheDir, safe_str(program.title()))
+        fname = os.path.join(self.cacheDir, 
safe_str(program.title().replace('/','_')))
         if not os.path.exists(fname):
             return None
         f = open(fname, 'rb')
@@ -544,7 +544,7 @@ class TvRageProvider(NoOpFanartProvider):
     
     def save(self, program, show):
         '''Save tvrage.api.Show to memory/disk cache'''
-        f = open(os.path.join(self.cacheDir, safe_str(program.title())), 'wb')
+        f = open(os.path.join(self.cacheDir, 
safe_str(program.title().replace('/','_'))), 'wb')
         try:
             self.memcache[program.title()] = show
             pickle.dump(show, f)
@@ -579,7 +579,18 @@ class TvRageProvider(NoOpFanartProvider):
         except tvrage.api.ShowNotFound:
             log.debug('TVRage: Show not found - %s' % 
safe_str(program.title()))
             return None, None
-                    
+        except KeyError, ke:
+            # TVRage throws KeyError on last line of constructor for incomplete
+            # datasets
+            log.warn('TVRage: KeyError %s - %s' % (safe_str(ke), 
safe_str(program.title())))
+            return None, None
+        except TypeError, te:
+            #  File "tvrage/api.py", line 145, in __init__
+            #    for season in eplist:
+            #TypeError: iteration over non-sequence
+            log.warn('TVRage: TypeError %s - %s' % (safe_str(te), 
safe_str(program.title())))
+            return None, None
+        
     def indexEpisodes(self, show):
         '''Throw all episodes into a map for fast lookup and attach to show 
object so the index is persisted'''
         show.seasonsAndEpisodes = {}  # key = original air date, value = 
(season, episode)
diff --git a/script.mythbox/resources/src/mythbox/mythtv/conn.py 
b/script.mythbox/resources/src/mythbox/mythtv/conn.py
index 449ef73..bd4ad05 100644
--- a/script.mythbox/resources/src/mythbox/mythtv/conn.py
+++ b/script.mythbox/resources/src/mythbox/mythtv/conn.py
@@ -1,6 +1,6 @@
 #
 #  MythBox for XBMC - http://mythbox.googlecode.com
-#  Copyright (C) 2010 [email protected]
+#  Copyright (C) 2011 [email protected]
 # 
 #  This program is free software; you can redistribute it and/or
 #  modify it under the terms of the GNU General Public License
@@ -994,10 +994,11 @@ class Connection(object):
         the backend.
         
         @type schedule: Schedule
+        @return Saved schedule with newly generated scheduleId (if new)
         """
-        new = schedule.getScheduleId() is None
-        self.db().saveSchedule(schedule)
-        self.rescheduleNotify(schedule)
+        savedSchedule = self.db().saveSchedule(schedule)
+        self.rescheduleNotify(savedSchedule)
+        return savedSchedule
 
     @inject_db
     def deleteSchedule(self, schedule):
@@ -1017,11 +1018,11 @@ class Connection(object):
         by the backend.
         """
         log.debug('rescheduleNotify(schedule= %s)' % safe_str(schedule))
-        scheduleId = 0
+        scheduleId = -1
         if schedule:
             scheduleId = schedule.getScheduleId()
             if scheduleId is None:
-                scheduleId = 0
+                scheduleId = -1
         reply = self._sendRequest(self.cmdSock, ['RESCHEDULE_RECORDINGS %s' % 
scheduleId])
         if int(reply[0]) < 0:
             raise ServerException, 'Reschedule notify failed: %s' % reply
@@ -1160,14 +1161,14 @@ class Connection(object):
             try:
                 new = socket.recv(left)
             except Exception, e:
-               if str(e) == "(9, 'Bad file descriptor')" or str(e) == "(10054, 
'Connection reset by peer')":
-                       print('Lost connection resetting')
-                       try:
-                               self.close()
-                       except Exception, e:
-                               print('noclose')
-                       self.db_init()
-                       return b
+                if str(e) == "(9, 'Bad file descriptor')" or str(e) == 
"(10054, 'Connection reset by peer')":
+                    log.warn('Lost connection resetting')
+                    try:
+                        self.close()
+                    except Exception, e:
+                        log.exception('noclose')
+                    self.db_init()
+                    return b
                 raise e
             if new == '':
                 break # eof
diff --git a/script.mythbox/resources/src/mythbox/mythtv/db.py 
b/script.mythbox/resources/src/mythbox/mythtv/db.py
index 71a4914..b3c1b92 100644
--- a/script.mythbox/resources/src/mythbox/mythtv/db.py
+++ b/script.mythbox/resources/src/mythbox/mythtv/db.py
@@ -34,7 +34,7 @@ import string
 from decorator import decorator
 from mythbox import pool
 from mythbox.pool import PoolableFactory
-from mythbox.util import timed, threadlocals
+from mythbox.util import timed, threadlocals, safe_str
         
 log = logging.getLogger('mythbox.core')
 ilog = logging.getLogger('mythbox.inject')
@@ -720,7 +720,6 @@ class MythDatabase(object):
         return self.cursor.rowcount
     
     @timed
-    @inject_cursor
     def saveSchedule(self, schedule):
         """
         Method to save a schedule to the database. If schedule.getScheduleId() 
is None 
@@ -731,7 +730,7 @@ class MythDatabase(object):
         have been made so that the backend will apply the changes.
 
         @param schedule: Schedule
-        @return: 0 on success
+        @return: saved schedule w/ populated scheduleId (if a new schedule)
         """
         s = schedule
         
@@ -826,11 +825,26 @@ class MythDatabase(object):
                 int(not s.isEnabled()), 
                 int(s.parentid()))
 
-        log.debug("sql = %s"%sql)
+        log.debug("sql = %s" % safe_str(sql))
         args = (s.title(), s.subtitle(), s.description())
-        self.cursor.execute(sql, args)
-        log.debug('Row count = %s' % self.cursor.rowcount)
- 
+
+        c = self.conn.cursor(*cursorArgs)       
+        try:
+            c.execute(sql, args)
+        finally:
+            c.close()
+
+        if s.getScheduleId() is None:
+            c2 = self.conn.cursor(*cursorArgs)
+            try:
+                c2.execute("select max(recordid) from record")
+                scheduleId = c2.fetchall()[0][0]
+                s.setScheduleId(scheduleId)
+                log.debug('New scheduleId = %s' % scheduleId)
+            finally:
+                c.close()
+        return s
+    
         # INSERT INTO `record` (
         # `recordid`,       241,  
         # `type`,           5, 
diff --git a/script.mythbox/resources/src/mythbox/mythtv/domain.py 
b/script.mythbox/resources/src/mythbox/mythtv/domain.py
index 68022b7..828b2d8 100644
--- a/script.mythbox/resources/src/mythbox/mythtv/domain.py
+++ b/script.mythbox/resources/src/mythbox/mythtv/domain.py
@@ -255,9 +255,17 @@ class Program(object):
         self.translator = translator
 
     def __eq__(self, rhs):
+        #
+        # NOTE: 
+        #   Replaced use of channelId with channelNumber
+        #   since channelId is tied to a tuner and comparing
+        #   a TVProgram to a RecordedProgram would result in
+        #   failures if > 1 tuner has the same channel 
+        #   (different channelId but same channelNumber)
+        #
         return \
             isinstance(rhs, Program) and \
-            self.getChannelId() == rhs.getChannelId() and \
+            self.getChannelNumber() == rhs.getChannelNumber() and \
             self.starttime() == rhs.starttime()
 
     def getChannelId(self):
diff --git a/script.mythbox/resources/src/mythbox/mythtv/enums.py 
b/script.mythbox/resources/src/mythbox/mythtv/enums.py
index 8a27bac..82984e1 100644
--- a/script.mythbox/resources/src/mythbox/mythtv/enums.py
+++ b/script.mythbox/resources/src/mythbox/mythtv/enums.py
@@ -78,41 +78,45 @@ class RecordingStatus(object):
 
 
 class ScheduleType(object):
-    
-    ONCE        = 1
-    DAILY       = 2
-    CHANNEL     = 3
-    ALWAYS      = 4
-    WEEKLY      = 5
-    FIND_ONE    = 6
-    OVERRIDE    = 7
-    DONT_RECORD = 8
-    FIND_DAILY  = 9
-    FIND_WEEKLY = 10
+    '''See recordingtypes.cpp'''
+    
+    NOT_RECORDING = 0
+    ONCE          = 1
+    DAILY         = 2
+    CHANNEL       = 3
+    ALWAYS        = 4
+    WEEKLY        = 5
+    FIND_ONE      = 6
+    OVERRIDE      = 7
+    DONT_RECORD   = 8
+    FIND_DAILY    = 9
+    FIND_WEEKLY   = 10
     
     translations = odict([
-        (ONCE       ,111),
-        (DAILY      ,112),
-        (WEEKLY     ,115),
-        (FIND_ONE   ,116),
-        (FIND_DAILY ,119),
-        (FIND_WEEKLY,120),
-        (CHANNEL    ,113),
-        (ALWAYS     ,114),
-        (OVERRIDE   ,117),
-        (DONT_RECORD,118)])
+        (ONCE         ,111),
+        (DAILY        ,112),
+        (WEEKLY       ,115),
+        (FIND_ONE     ,116),
+        (FIND_DAILY   ,119),
+        (FIND_WEEKLY  ,120),
+        (CHANNEL      ,113),
+        (ALWAYS       ,114),
+        (OVERRIDE     ,117),
+        (DONT_RECORD  ,118),
+        (NOT_RECORDING,170)])
     
     long_translations = odict([
-        (ONCE       ,135),
-        (DAILY      ,136),
-        (WEEKLY     ,139),
-        (FIND_ONE   ,140),
-        (FIND_DAILY ,143),
-        (FIND_WEEKLY,144),
-        (CHANNEL    ,137),
-        (ALWAYS     ,138),
-        (OVERRIDE   ,141),
-        (DONT_RECORD,142)])
+        (ONCE         ,135),
+        (DAILY        ,136),
+        (WEEKLY       ,139),
+        (FIND_ONE     ,140),
+        (FIND_DAILY   ,143),
+        (FIND_WEEKLY  ,144),
+        (CHANNEL      ,137),
+        (ALWAYS       ,138),
+        (OVERRIDE     ,141),
+        (DONT_RECORD  ,142),
+        (NOT_RECORDING,170)])
     
 
 class EpisodeFilter(object):
diff --git a/script.mythbox/resources/src/mythbox/platform.py 
b/script.mythbox/resources/src/mythbox/platform.py
index 13ea19e..10c75eb 100644
--- a/script.mythbox/resources/src/mythbox/platform.py
+++ b/script.mythbox/resources/src/mythbox/platform.py
@@ -75,10 +75,15 @@ class Platform(object):
             'mysql-connector-python',
             'python-twitter',
             'twisted',
-            'zope.interface']
+            'zope.interface',
+            'mockito',
+            'unittest2',
+            'unittest']
         
         for lib in libs:
             sys.path.append(os.path.join(self.getScriptDir(), 'resources', 
'lib', lib))
+        
+        sys.path.append(os.path.join(self.getScriptDir(), 'resources', 'test'))
             
         for i, path in enumerate(sys.path):    
             log.debug('syspath[%d] = %s' % (i, path))
diff --git a/script.mythbox/resources/src/mythbox/ui/livetv.py 
b/script.mythbox/resources/src/mythbox/ui/livetv.py
index acfbcc2..7bb7010 100644
--- a/script.mythbox/resources/src/mythbox/ui/livetv.py
+++ b/script.mythbox/resources/src/mythbox/ui/livetv.py
@@ -1,6 +1,6 @@
 #
 #  MythBox for XBMC - http://mythbox.googlecode.com
-#  Copyright (C) 2010 [email protected]
+#  Copyright (C) 2011 [email protected]
 # 
 #  This program is free software; you can redistribute it and/or
 #  modify it under the terms of the GNU General Public License
@@ -30,7 +30,7 @@ from mythbox.mythtv.domain import Channel
 from mythbox.mythtv.conn import ServerException
 from mythbox.ui.player import MythPlayer, NoOpCommercialSkipper
 from mythbox.ui.toolkit import Action, BaseWindow, window_busy
-from mythbox.util import catchall, catchall_ui, run_async, lirc_hack, 
ui_locked, coalesce, ui_locked2
+from mythbox.util import safe_str,catchall, catchall_ui, run_async, lirc_hack, 
ui_locked, coalesce, ui_locked2
 from odict import odict
 
 log = logging.getLogger('mythbox.ui')
@@ -84,7 +84,7 @@ class MythLiveTvBrain(BaseLiveTvBrain):
             #del livePlayer # induce GC so on* callbacks unregistered
             return self.tuner
         except ServerException, se:
-            xbmcgui.Dialog().ok(self.translator.get(m.INFO), str(se))
+            xbmcgui.Dialog().ok(self.translator.get(m.INFO), safe_str(se))
 
 
 class MythLiveTvPlayer(xbmc.Player):
@@ -326,7 +326,7 @@ class LiveTvWindow(BaseWindow):
             self.lastSelected = self.channelsListBox.getSelectedPosition()
             channel = 
self.listItem2Channel(self.channelsListBox.getSelectedItem())
             if channel.currentProgram and channel.needsPoster:
-                log.debug("Adding channel %s to front of q" % channel)
+                log.debug('Adding channel %s to front of q' % 
channel.getChannelNumber())
                 self.workq.append(channel)
 
     def listIndex2Channel(self, i):
@@ -348,7 +348,7 @@ class LiveTvWindow(BaseWindow):
             brain.watchLiveTV(channel)
         except Exception, e:
             log.error(e)
-            xbmcgui.Dialog().ok(self.translator.get(m.ERROR), '', str(e))
+            xbmcgui.Dialog().ok(self.translator.get(m.ERROR), '', safe_str(e))
 
     @inject_db
     def loadChannels(self):
@@ -410,7 +410,7 @@ class LiveTvWindow(BaseWindow):
                         channel.needsPoster = True
                         self.setListItemProperty(listItem, 'poster', 
'loading.gif')
                 else:
-                    self.setListItemProperty(listItem, 'title', 'No Data')
+                    self.setListItemProperty(listItem, 'title', 
self.translator.get(m.NO_DATA))
                     
                 listItems.append(listItem)
                 self.listItemsByChannel[channel] = listItem
@@ -437,7 +437,7 @@ class LiveTvWindow(BaseWindow):
                     self.lookupPoster(listItem, channel)
                     channel.needsPoster = False
             except:
-                log.exception('channel = %s' % channel)
+                log.exception('channel = %s' % safe_str(channel))
 
     def lookupPoster(self, listItem, channel):
         posterPath = self.fanArt.getRandomPoster(channel.currentProgram)
diff --git a/script.mythbox/resources/src/mythbox/ui/schedules.py 
b/script.mythbox/resources/src/mythbox/ui/schedules.py
index a29576c..2c2b28a 100644
--- a/script.mythbox/resources/src/mythbox/ui/schedules.py
+++ b/script.mythbox/resources/src/mythbox/ui/schedules.py
@@ -223,8 +223,11 @@ class ScheduleDialog(BaseDialog):
         log.debug('onClick %s ' % controlId)
         source = self.getControl(controlId)
         s = self.schedule
-        
-        if controlId == 201: 
self._chooseFromList(ScheduleType.long_translations, t(m.RECORD_WHEN), 
'scheduleType', s.setScheduleType)
+ 
+        # NOTE: Don't let user select ScheduleType.NOT_RECORDING -- remove 
from translation list
+        scheduleTypeMinusNotRecording = 
odict.odict(ScheduleType.long_translations)
+        del scheduleTypeMinusNotRecording[ScheduleType.NOT_RECORDING]        
+        if controlId == 201: 
self._chooseFromList(scheduleTypeMinusNotRecording, t(m.RECORD_WHEN), 
'scheduleType', s.setScheduleType)
         
         elif controlId == 202:
             priority = self._enterNumber(t(m.RECORDING_PRIORITY), 
s.getPriority(), -99, 99)
diff --git a/script.mythbox/resources/src/mythbox/ui/tvguide.py 
b/script.mythbox/resources/src/mythbox/ui/tvguide.py
index 863e999..29cce96 100644
--- a/script.mythbox/resources/src/mythbox/ui/tvguide.py
+++ b/script.mythbox/resources/src/mythbox/ui/tvguide.py
@@ -362,6 +362,7 @@ class TvGuideWindow(ui.BaseWindow):
                 createScheduleDialog.doModal()
                 
                 if createScheduleDialog.shouldRefresh:
+                    self.cacheUpcoming()
                     log.debug('schedule saved')
         return actionConsumed
 

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

Summary of changes:
 script.mythbox/FAQ                                 |   23 +-
 script.mythbox/addon.xml                           |    2 +-
 script.mythbox/changelog.txt                       |   13 +
 script.mythbox/default.py                          |    9 +-
 .../resources/language/Dutch/strings.xml           |  402 +++++++++++++++
 .../resources/language/English/strings.xml         |    1 +
 .../skins/Default/720p/mythbox_settings.xml        |   53 +--
 script.mythbox/resources/src/mythbox/fanart.py     |   21 +-
 script.mythbox/resources/src/mythbox/log.py        |   46 ++
 .../resources/src/mythbox/mythtv/conn.py           |   29 +-
 script.mythbox/resources/src/mythbox/mythtv/db.py  |   28 +-
 .../resources/src/mythbox/mythtv/domain.py         |   10 +-
 .../resources/src/mythbox/mythtv/enums.py          |   64 ++--
 script.mythbox/resources/src/mythbox/platform.py   |    7 +-
 script.mythbox/resources/src/mythbox/ui/livetv.py  |   14 +-
 .../resources/src/mythbox/ui/schedules.py          |    7 +-
 script.mythbox/resources/src/mythbox/ui/tvguide.py |    1 +
 script.trakt/addon.xml                             |    8 +-
 script.trakt/changelog.txt                         |    5 +
 script.trakt/default.py                            |   10 +-
 script.trakt/resources/lib/utilities.py            |  530 ++++++++++----------
 21 files changed, 899 insertions(+), 384 deletions(-)
 create mode 100644 script.mythbox/resources/language/Dutch/strings.xml
 create mode 100644 script.mythbox/resources/src/mythbox/log.py


hooks/post-receive
-- 
Scripts

------------------------------------------------------------------------------
Special Offer-- Download ArcSight Logger for FREE (a $49 USD value)!
Finally, a world-class log management solution at an even better price-free!
Download using promo code Free_Logger_4_Dev2Dev. Offer expires 
February 28th, so secure your free ArcSight Logger TODAY! 
http://p.sf.net/sfu/arcsight-sfd2d
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons

Reply via email to