Changeset 2493

Show
Ignore:
Timestamp:
11/11/08 12:01:48 (8 weeks ago)
Author:
bzr
Message:

Merged appData branch:
* new: The NVDA application now includes a manifest, which means that it no longer runs in compatibility mode in Windows Vista.
* new: The configuration file and speech dictionaries are now saved in the user's application data directory if NVDA was installed using the installer. This is necessary for Windows Vista and also allows multiple users to have individual NVDA configurations.

Location:
trunk
Files:
1 removed
10 modified
1 copied

Legend:

Unmodified
Added
Removed
  • trunk

    • Property bzr:revision-info
      •  

        old new  
        1 timestamp: 2008-11-11 13:00:33.200999975 +1100 
        2 committer: James Teh <jamie@jantrid.net> 
         1timestamp: 2008-11-11 22:55:36.428999901 +1100 
         2committer: Michael Curran <mick@kulgan.net> 
        33properties:  
        44        branch-nick: main 
        5         rebase-of: jamie@jantrid.net-20081111020033-bkc6t5rofs9rod6x 
    • Property bzr:ancestry:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
      •  

        old new  
        1313jamie@jantrid.net-20081104100702-aqivw5dfzmygyo17 
        1414jamie@jantrid.net-20081109113343-zabfejnnivsxf2gd 
         15jamie@jantrid.net-20081111050702-md0ib7fbd6r5scsh 
    • Property bzr:revision-id:v3-list-QlpoOTFBWSZTWbrL2vUAAB1VgAAQABCAQDrrnqAgAFCgaaGRkxBoTIJ6mmaNRwhndFAoNhZjh_YY4a01fOg1ulgNNC2UrzPdXXEnDpX8XckU4UJC6y9r1A..
      •  

        old new  
        2622622290 peter.v@datagate.sk-20081110173809-ursuetu2mfiec6t3 
        2632632291 jamie@jantrid.net-20081111020033-pzhx3l8q2rvmerlv 
         2642292 mick@kulgan.net-20081111115536-4010omrj0yzvubsn 
    • Property bzr:file-ids
      •  

        old new  
         1installer/nvda.nsi      519@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:installer%2Fnvda.nsi 
         2source/api.py   46@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fapi.py 
         3source/builtin.dic      1848@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fspeechdicts%2Fdefault.dic 
         4source/config/__init__.py       46@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fconfig%2F__init__.py 
         5source/core.py  49@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fcore.py 
         6source/nvda.pyw 475@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fnvda.pyw 
         7source/setup.py 46@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2Fsetup.py 
         8source/speechDictHandler.py     1848@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FspeechDictHandler.py 
        19source/synthDriverHandler.py    97@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FsynthDriverHandler.py 
        2 source/synthDrivers/audiologic.py       audiologic.py-20080701031200-sjkq3p9snm96sxhq-2 
        3 source/synthDrivers/display.py  1310@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FsynthDrivers%2Fdisplay.py 
        4 source/synthDrivers/espeak.py   612@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FsynthDrivers%2Fespeak.py 
        5 source/synthDrivers/sapi4.py    sapi4.py-20081105062308-fz5mgli5iso5vcdq-2 
        6 source/synthDrivers/sapi5.py    94@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:source%2FsynthDrivers%2Fsapi5.py 
         10user_docs/whats%20new.txt       559@dbe06fc7-9119-0410-a01d-9dbf589ecbba:trunk:user_docs%2Fwhats%20new.txt 
    • Property bzr:text-parents
      •  

        old new  
         1installer/nvda.nsi      mick@kulgan.net-20081111011336-vyjr4ckpgw1id60v 
         2source/api.py   jamie@jantrid.net-20081111000130-ogbjmubm7hbp2w8b 
         3source/builtin.dic      jamie@jantrid.net-20081111020432-cq91do2ohrbdnn3k 
         4source/config/__init__.py       jamie@jantrid.net-20081111050702-md0ib7fbd6r5scsh 
         5source/core.py  jamie@jantrid.net-20081111024153-2s812gqcfug4e3ms 
         6source/nvda.pyw mick@kulgan.net-20081110092815-eua72ap9o5gxht9o 
         7source/setup.py jamie@jantrid.net-20081111024453-ht5z2l2ny3s4vt44 
         8source/speechDictHandler.py     jamie@jantrid.net-20081111024153-2s812gqcfug4e3ms 
         9source/synthDriverHandler.py    jamie@jantrid.net-20081111021520-lfmlgtkovxoech8e 
         10user_docs/whats%20new.txt       jamie@jantrid.net-20081111044917-m1lxw7wa76jwlkoa 
  • trunk/installer/nvda.nsi

    r2293 r2493  
    1515!define NVDATempDir "_nvda_temp_" 
    1616!define NVDASourceDir "..\source\dist" 
    17 !define NVDAConfig "nvda.ini" 
    1817!define SNDLogo "nvda_logo.wav" 
    1918 
     
    313312 
    314313; Uninstall functions 
    315 var PreserveConfig 
    316314Function un.onInit 
    317315;!insertmacro MUI_UNGETLANGUAGE 
     
    348346;end uninstall, after uninstall from all logged paths has been performed 
    349347!insertmacro UNINSTALL.LOG_END_UNINSTALL 
    350  
    351 ; Warn about configuration file 
    352 IfFileExists "$INSTDIR\${NVDAConfig}" +1 +2 
    353 MessageBox MB_ICONQUESTION|MB_YESNO|MB_DefButton2 $(msg_NVDAConfigFound) IDYES +1 IDNO PreserveConfiguration 
    354 goto Continue 
    355 PreserveConfiguration: 
    356 CopyFiles /SILENT "$INSTDIR\${NVDAConfig}" "$PLUGINSDIR\${NVDAConfig}" 
    357 strcpy $preserveConfig "1" 
    358 Continue: 
    359348!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder 
    360349Delete "$SMPROGRAMS\$StartMenuFolder\*.*" 
     
    364353DeleteRegKey ${INSTDIR_REG_ROOT} "SOFTWARE\${PRODUCT}" 
    365354DeleteRegKey ${INSTDIR_REG_ROOT} ${INSTDIR_REG_KEY} 
    366 StrCmp $PreserveConfig 1 +1 NoPreserveConfig 
    367 CreateDirectory $INSTDIR 
    368 CopyFiles /SILENT "$PLUGINSDIR\${NVDAConfig}" "$INSTDIR\${NVDAConfig}" 
    369 goto End 
    370 NoPreserveConfig: 
    371 Delete $INSTDIR\${NVDAConfig} 
    372355Rmdir $INSTDIR 
    373 Goto End 
    374  
    375 End: 
    376356SectionEnd 
    377357 
  • trunk/source/api.py

    r2466 r2493  
    328328        return text + " ".join(chunk for child in obj.children for chunk in (child.name, child.value) if chunk and isinstance(chunk, basestring) and not chunk.isspace()) 
    329329 
    330 def validateFile(name): 
    331         """Replaces invalid characters in a given string to make a windows compatible filename. 
    332 @returns: A string holding altered name. 
    333 @rtype: string 
    334 @param name: text to makea file name of 
    335 @type text: string 
    336 """ 
     330def filterFileName(name): 
     331        """Replaces invalid characters in a given string to make a windows compatible file name. 
     332        @param name: The file name to filter. 
     333        @type name: str 
     334        @returns: The filtered file name. 
     335        @rtype: str 
     336        """ 
    337337        invalidChars=':?*\|<>/"' 
    338338        for c in invalidChars: 
  • trunk/source/config/__init__.py

    r2482 r2493  
    33 
    44import globalVars 
    5 #: The name of the configuration file. 
    6 #: @type: str 
    7 configFileName = globalVars.appArgs.configFileName 
    8  
     5import _winreg 
    96import os 
    107from cStringIO import StringIO 
     
    135132#: @type: ConfigObj 
    136133conf = None 
    137 mtime = 0 
    138134 
    139135def load(): 
     
    141137        It also takes note of the file's modification time so that L{save} won't lose any changes made to the file while NVDA is running.  
    142138        """ 
    143         global conf, mtime 
    144         # If the config file exists, store its mtime. 
    145         if os.path.isfile(configFileName): 
    146                 mtime = os.path.getmtime(configFileName) 
     139        global conf 
     140        configFileName=os.path.join(globalVars.appArgs.configPath,"nvda.ini") 
    147141        conf = ConfigObj(configFileName, configspec = confspec, indent_type = "\t", encoding="UTF-8") 
    148142        # Python converts \r\n to \n when reading files in Windows, so ConfigObj can't determine the true line ending. 
     
    164158                return False 
    165159 
    166 def save(force = False): 
    167         """Saves the configuration to the config file. However it does not if the file's modification time has changed and L{force} is not true. 
    168         @param force: if true then the modification time of the file will be ignored. 
    169         @type force: boolean 
     160def save(): 
     161        """Saves the configuration to the config file. 
    170162        """ 
    171         global conf, mtime 
    172         # If the file has changed since it was read, don't save over the top of it. 
    173         if not force and os.path.isfile(configFileName) and os.path.getmtime(configFileName) != mtime: 
    174                 return 
     163        global conf 
     164        if not os.path.isdir(globalVars.appArgs.configPath): 
     165                try: 
     166                        os.makedirs(globalVars.appArgs.configPath) 
     167                except OSError, e: 
     168                        log.warning("Could not create configuration directory") 
     169                        log.debugWarning("", exc_info=True) 
     170                        raise e 
    175171        try: 
    176172                # Copy default settings and formatting. 
     
    182178                log.debugWarning("", exc_info=True) 
    183179                raise e 
    184         mtime = os.path.getmtime(configFileName) 
    185180 
    186181def saveOnExit(): 
     
    194189                except: 
    195190                        pass 
     191 
     192def isInstalledCopy(): 
     193        """Checks to see if this running copy of NVDA is installed on the system""" 
     194        try: 
     195                k=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NVDA") 
     196                try: 
     197                        instDir=_winreg.QueryValueEx(k,"UninstallDirectory")[0] 
     198                except: 
     199                        instDir="" 
     200                _winreg.CloseKey(k) 
     201                return os.path.normpath(os.getcwd())==os.path.normpath(instDir) 
     202        except: 
     203                return False 
     204 
     205def getUserDefaultConfigPath(): 
     206        if isInstalledCopy(): 
     207                return os.path.expandvars("$appdata\\nvda") 
     208        else: 
     209                return ".\\" 
  • trunk/source/core.py

    r2436 r2493  
    4949""" 
    5050        log.debug("Core starting") 
     51        log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) 
    5152        log.debug("loading config") 
    5253        import config 
  • trunk/source/nvda.pyw

    r2298 r2493  
    1818import win32con 
    1919import globalVars 
     20import config 
    2021import logHandler 
    2122from logHandler import log 
     
    6465parser.add_option('-f','--log-file',dest='logFileName',default=logFileName,help="The file where log messages should be written to") 
    6566parser.add_option('-l','--log-level',type="int",dest='logLevel',default=0,help="The lowest level of message logged (debug 10, info 20, warning 30, error 40, critical 50), default is warning")  
    66 parser.add_option('-c','--config-file',dest='configFileName',default="./nvda.ini",help="The file where all settings are stored") 
     67parser.add_option('-c','--config-path',dest='configPath',default=config.getUserDefaultConfigPath(),help="The path where all settings for NVDA are stored") 
    6768parser.add_option('-m','--minimal',action="store_true",dest='minimal',default=False,help="No sounds, no interface, no start message etc") 
    6869(globalVars.appArgs,extraArgs)=parser.parse_args() 
  • trunk/source/setup.py

    r2455 r2493  
    1414from py2exe import build_exe 
    1515import wx 
     16 
     17RT_MANIFEST = 24 #resource number for manifest 
     18 
     19NVDAManifestText=""" 
     20<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
     21<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
     22<assemblyIdentity 
     23    version="6.0.0.0" 
     24    processorArchitecture="x86" 
     25    name="%(name)s" 
     26    type="win32" 
     27/> 
     28<description>%(description)s</description> 
     29<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
     30<security> 
     31<requestedPrivileges> 
     32<requestedExecutionLevel 
     33level="AsInvoker" 
     34uiAccess="false" /> 
     35</requestedPrivileges> 
     36</security> 
     37</trustInfo> 
     38</assembly> 
     39"""%vars() 
    1640 
    1741# py2exe insists on excluding certain dlls that don't seem to exist on many systems, so hackishly force them to be included. 
     
    6488                "script":"nvda.pyw", 
    6589                "icon_resources":[(1,"images/nvda.ico")], 
     90                "other_resources":[(RT_MANIFEST,1,NVDAManifestText)], 
    6691        }], 
    6792        options = {"py2exe": { 
     
    7499        zipfile = None, 
    75100        data_files=[ 
    76                 (".",glob("*.dll")), 
     101                (".",glob("*.dll")+["builtin.dic"]), 
    77102                ("documentation", ['../copying.txt', '../contributors.txt']), 
    78103                ("comInterfaces", glob("comInterfaces/*.pyc")), 
     
    82107                ("waves", glob("waves/*.wav")), 
    83108                ("images", glob("images/*.ico")), 
    84                 ("speechdicts", glob("speechdicts/*.dic")), 
    85109                ("louis/tables",glob("louis/tables/*")) 
    86110        ] + getLocaleDataFiles()+getRecursiveDataFiles('documentation','../user_docs')+getRecursiveDataFiles('synthDrivers','synthDrivers')+getRecursiveDataFiles('brailleDisplayDrivers','brailleDisplayDrivers'), 
  • trunk/source/speechDictHandler.py

    r2351 r2493  
    1212import synthDriverHandler 
    1313import api 
     14import config 
    1415 
    1516dictionaries = {} 
    16 dictTypes = ("temp", "voice", "default") # ordered by their priority E.G. voice specific speech dictionary is processed before the default 
    17 speechDictsPath="speechdicts" 
     17dictTypes = ("temp", "voice", "default", "builtin") # ordered by their priority E.G. voice specific speech dictionary is processed before the default 
     18speechDictsPath=os.path.join(globalVars.appArgs.configPath, "speechdicts") 
    1819 
    1920class SpeechDictEntry: 
     
    6768                if not fileName: 
    6869                        fileName=getattr(self,'fileName',None) 
    69                 if fileName: 
    70                         file = codecs.open(fileName,"w","utf_8_sig",errors="replace") 
    71                         for entry in self: 
    72                                 if entry.comment: 
    73                                         file.write("#%s\r\n"%entry.comment) 
    74                                 file.write("%s\t%s\t%s\t%s\r\n"%(entry.pattern,entry.replacement,int(entry.caseSensitive),int(entry.regexp))) 
    75                         file.close() 
     70                if not fileName: 
     71                        return 
     72                dirName=os.path.dirname(fileName) 
     73                if not os.path.isdir(dirName): 
     74                        os.makedirs(dirName) 
     75                file = codecs.open(fileName,"w","utf_8_sig",errors="replace") 
     76                for entry in self: 
     77                        if entry.comment: 
     78                                file.write("#%s\r\n"%entry.comment) 
     79                        file.write("%s\t%s\t%s\t%s\r\n"%(entry.pattern,entry.replacement,int(entry.caseSensitive),int(entry.regexp))) 
     80                file.close() 
    7681 
    7782        def sub(self, text): 
     
    8792        return text 
    8893 
    89 def getFileName(type): 
    90         if type is "default": 
    91                 return "%s/default.dic"%speechDictsPath 
    92         elif type is "voice": 
    93                 s=synthDriverHandler.getSynth() 
    94                 return "%s/%s-%s.dic"%(speechDictsPath,api.validateFile(s.name),validateFile(s.getVoiceName(s.voice))) 
    95         return None 
    96  
    9794def initialize(): 
    9895        for type in dictTypes: 
    9996                dictionaries[type]=SpeechDict() 
    100         dictionaries["default"].load(getFileName("default")) 
    101  
     97        dictionaries["default"].load(os.path.join(speechDictsPath, "default.dic")) 
     98        dictionaries["builtin"].load("builtin.dic") 
  • trunk/source/synthDriverHandler.py

    r2492 r2493  
    1919 
    2020def changeVoice(synth, voice): 
    21         voiceName=synth.getVoiceInfoByID(voice).name 
    22         voiceName=voiceName.replace('\\','_') 
    23         fileName="%s/%s-%s.dic"%(speechDictHandler.speechDictsPath,synth.name,voiceName) 
     21        import api 
     22        voiceName = synth.getVoiceInfoByID(voice).name 
     23        synth.voice = voice 
     24        fileName=r"%s\%s-%s.dic"%(speechDictHandler.speechDictsPath,synth.name,api.filterFileName(voiceName)) 
    2425        speechDictHandler.dictionaries["voice"].load(fileName) 
    25         synth.voice = voice 
    2626 
    2727def getSynthList(): 
     
    6262                                except LookupError: 
    6363                                        log.warning("No such voice: %s" % voice) 
     64                                        # Update the configuration with the correct voice. 
     65                                        config.conf["speech"][name]["voice"]=newSynth.voice 
     66                                        # We need to call changeVoice here so voice dictionaries can be managed 
     67                                        changeVoice(newSynth,newSynth.voice) 
    6468                        if newSynth.hasVariant: 
    6569                                newSynth.variant=config.conf["speech"][name]["variant"] 
     
    7579                        if newSynth.hasVoice: 
    7680                                config.conf["speech"][name]["voice"]=newSynth.voice 
    77                                 #We need to call changeVoice here so voice dictionries can be managed 
     81                                #We need to call changeVoice here so voice dictionaries can be managed 
    7882                                changeVoice(newSynth,newSynth.voice) 
    7983                        if newSynth.hasVariant: 
  • trunk/user_docs/whats new.txt

    r2482 r2493  
    4949* fix: The eSpeak synthesizer driver no longer stops speaking completely after a single error. 
    5050* fix: Fix the issue whereby updated voice parameters (rate, pitch, etc.) were not saved when the voice was changed from the synthesizer settings ring. 
     51* new: The NVDA application now includes a manifest, which means that it no longer runs in compatibility mode in Windows Vista. 
     52* new: The configuration file and speech dictionaries are now saved in the user's application data directory if NVDA was installed using the installer. This is necessary for Windows Vista and also allows multiple users to have individual NVDA configurations. 
    5153 
    5254