예제 #1
0
def logToFile( strMessage, strSpecificFileName = "" ):
    "add a message to the current debug log file"
    import filetools
    import pathtools
    global global_strAltools_LogToFile;
    global global_mutex_LogToFile;
    global global_timeLogToFile_lastLog;
    timeNow = time.time();
    rDurationSec = timeNow - global_timeLogToFile_lastLog;
    global_timeLogToFile_lastLog = timeNow;
    while( global_mutex_LogToFile.testandset() == False ):
        time.sleep( 0.02 );
    if( global_strAltools_LogToFile == None ):
        try:
            os.makedirs( pathtools.getCachePath() );
        except:
            pass
        global_strAltools_LogToFile = pathtools.getCachePath() + filetools.getFilenameFromTime() + ".log";
        print( "altools.logToFile: logging to '%s'" % global_strAltools_LogToFile );
        
    if( strSpecificFileName == '' ):
        strFileName = global_strAltools_LogToFile;
    else:
        strFileName = pathtools.getCachePath() + strSpecificFileName + '_' + getNaoqiStartupTimeStamp() + ".log";
#    print( "logToFile: logging to %s" % strFileName );
    try:
        file = open( strFileName, "at" );
        file.write( "%s (%5.2fs): %s\n" % ( getHumanTimeStamp(), rDurationSec, strMessage ) );
    finally:
        if( file ):
            file.close();
    global_mutex_LogToFile.unlock();
예제 #2
0
def logToFile(strMessage, strSpecificFileName=""):
    "add a message to the current debug log file"
    global global_strAltools_LogToFile
    global global_mutex_LogToFile
    global global_timeLogToFile_lastLog
    timeNow = time.time()
    rDurationSec = timeNow - global_timeLogToFile_lastLog
    global_timeLogToFile_lastLog = timeNow
    while (global_mutex_LogToFile.testandset() == False):
        time.sleep(0.02)
    if (global_strAltools_LogToFile == None):
        try:
            os.makedirs(pathtools.getCachePath())
        except:
            pass  # often the cases!
        global_strAltools_LogToFile = pathtools.getCachePath(
        ) + getFilenameFromTime() + ".log"
        print("altools.logToFile: logging to '%s'" %
              global_strAltools_LogToFile)

    if (strSpecificFileName == ''):
        strFileName = global_strAltools_LogToFile
    else:
        strFileName = pathtools.getCachePath(
        ) + strSpecificFileName + '_' + naoqitools.getNaoqiStartupTimeStamp(
        ) + ".log"
#    print( "logToFile: logging to %s" % strFileName );
    try:
        file = open(strFileName, "at")
        file.write("%s (%5.2fs): %s\n" %
                   (debug.getHumanTimeStamp(), rDurationSec, strMessage))
    finally:
        if (file):
            file.close()
    global_mutex_LogToFile.unlock()
예제 #3
0
 def log( self, strMessage ):
     timeNow = time.time();
     rDurationSec = timeNow - self.logLastTime;
     self.logLastTime = timeNow;
     strTimeStamp = debug.getHumanTimeStamp();
     print( "INF: %s: Xarloader: %s" % ( strTimeStamp,  str( strMessage ) ) );
     while( self.logMutex.testandset() == False ):
         print( "INF: XarLoader: log: locked" );
         time.sleep( 0.02 );
     
     strFilename = pathtools.getCachePath() + "XarLoader.log";
     try:
         os.makedirs( pathtools.getCachePath() );
     except BaseException, err:
         print( "WRN: normal error: err: " + str( err ) );
예제 #4
0
def sayAndCacheAndLight( strTextToSay, bJustPrepare = False, bStoreToNonVolatilePath = False, nEyesColor = 0, nUseLang = -1 ):
    "say a cached text with light animation"
    "nEyesColor: 0: white, 1: blue, 2: green; 3: red"
    "nUseLang: if different of -1: speak with a specific languages (useful, when text are already generated: doesn't need to swap languages for nothing!"
    "return the length of the text in seconds, or None if impossible"
    print( "sayAndCacheAndLight( '%s', bJustPrepare: %s, bStoreToNonVolatilePath: %s, nEyesColor: %s, nUseLang: %s )" % ( strTextToSay, str( bJustPrepare ), str( bStoreToNonVolatilePath ), str( nEyesColor ), str( nUseLang ) ) );
    if( not config.bPrecomputeText ):
        print( "sayAndCacheAndLight: disabled by configuration: bPrecomputeText is false" );
        if( bJustPrepare ):
            return None; # do nothing
        tts = naoqitools.myGetProxy( "ALTextToSpeech" );
        tts.say( strTextToSay );
        return None;

    rLength = sayAndCache( strTextToSay, bJustPrepare = True, bStoreToNonVolatilePath = bStoreToNonVolatilePath, nUseLang = nUseLang, bCalledFromSayAndCacheFromLight = True ); # we store it to disk, only if we must do it

    # this two lines are done too in sayAndCache...
    strTextToSay = assumeTextHasDefaultSettings( strTextToSay, nUseLang );
    szFilename = sayAndCache_getFilename( strTextToSay, nUseLang );

    szPathVolatile = pathtools.getVolatilePath();
    rSampleLenSec = 0.05;
#    szPathFilenamePeak = szPathVolatile + szFilename + ("_%5.3f.egy" % rSampleLenSec);
    szPathFilenamePeak = szFilename + ("_%5.3f.egy" % rSampleLenSec);
    szPathFilenamePeakCache = pathtools.getCachePath() + "generatedvoices" + pathtools.getDirectorySeparator() + szPathFilenamePeak;
    szPathFilenamePeak = szPathVolatile + szPathFilenamePeak;
    anLedsColorSequency = [];
    aBufFile = "";
    bFileGenerated = False;
    if( not filetools.isFileExists( szPathFilenamePeak ) ):
        if( filetools.isFileExists( szPathFilenamePeakCache ) ):
            copyFile( szPathFilenamePeakCache, szPathFilenamePeak );
    if( not filetools.isFileExists( szPathFilenamePeak ) ):
        # generate peak file
        timeBegin = time.time();
        print( "sayAndCacheAndLight: generating peak light - begin\n" );
        szPathFilename = szPathVolatile + szFilename + ".raw";
        anLedsColorSequency = [];
        try:
            une = naoqitools.myGetProxy( 'UsageNoiseExtractor' );
            anLedsColorSequency = une.analyseSpeakSound( szPathFilename, int( rSampleLenSec * 1000 ), False );
        except BaseException, err:
            print( "ERR: sayAndCacheAndLight( '%s' ): err: %s" % ( strTextToSay, str( err ) ) );
            print( "ERR: sayAndCacheAndLight => trying old cpp version" );
            anLedsColorSequency = analyseSpeakSound( szPathFilename, rSampleLenSec * 1000 );
        print( "sayAndCacheAndLight: analyseSpeakSound - end - time: %fs\n" % float( time.time() - timeBegin ) );        
#        print( "anLedsColorSequency: %d samples: %s\n" % ( len( anLedsColorSequency ), str( anLedsColorSequency ) ) );
        
        print( "Writing file with %d peak samples (time: %d)\n" % ( len( anLedsColorSequency ), int( time.time() ) ) );
        #         struct.pack_into( "f"*len( anLedsColorSequency ), aBufFile, anLedsColorSequency[:] );
        for peakValue in anLedsColorSequency:
            aBufFile += struct.pack( "f", peakValue );
        try:
            file = open( szPathFilenamePeak, "wb" );
            file.write( aBufFile );
        except RuntimeError, err:
            print( "ERR: sayAndCacheAndLight( '%s' ): err: %s" % ( strTextToSay, str( err ) ) );
예제 #5
0
 def saveToDisk( self ):
     try:
         timer = altools.TimeMethod();    
     except:
         pass
     print( "INF: KmlManager.saveToDisk: begining..." );
     file = open( pathtools.getCachePath() + "KmlManager.dat", "wb" );
     dictTofile( file, self.aListPos );
     file.close();
     print( "INF: KmlManager.saveToDisk: end" );
예제 #6
0
 def loadFromDisk( self ):
     print( "INF: KmlManager.loadFromDisk: begin" );
     try:
         file = open( pathtools.getCachePath() + "KmlManager.dat", "rb" );        
         if( file ):
             self.aListPos = fileToDict( file );
             print( "INF: KmlManager.loadFromDisk: position known: %d" %  len( self.aListPos ) );
             file.close();
     except BaseException, err:
         print( "INF: KmlManager.loadFromDisk: no previous data found ? (err:%s)" % ( err ) );        
         self.aListPos = {}; # reset it
         return;
예제 #7
0
 def __getVarPath_Inner__(self):
     import pathtools  # module already unloaded when called from __del__
     return pathtools.getCachePath(
     ) + "mem" + pathtools.getDirectorySeparator()
예제 #8
0
 def getVarPath():
     return pathtools.getCachePath(
     ) + 'mem' + pathtools.getDirectorySeparator()
예제 #9
0
  szFilename = sayAndCache_getFilename( strTextToSay, nUseLang, strUseVoice );
  
  szPathVolatile = pathtools.getVolatilePath() + "generatedvoices" + pathtools.getDirectorySeparator();
  try:
    os.mkdir( szPathVolatile );
  except BaseException, err:
    pass
  
  
#  if( not szFilename.isalnum() ): # the underscore is not an alphanumeric, but is valid there
#    debug.debug( "WRN: sayAndCache: some chars are not alphanumeric in filename '%s'" % szFilename );
  szPathFilename = szPathVolatile + szFilename + ".raw";
  bGenerate = not filetools.isFileExists( szPathFilename );
  
  if( bGenerate ):
    szAlternatePathFilename = pathtools.getCachePath() + "generatedvoices" + pathtools.getDirectorySeparator() + szFilename + ".raw"; # look in a non volatile path
    
    if( filetools.isFileExists( szAlternatePathFilename ) ):
      debug.debug( "sayAndCache: get static precomputed text for '%s'" % ( strTextToSay ) );
      filetools.copyFile( szAlternatePathFilename, szPathFilename );
      bGenerate = not filetools.isFileExists( szPathFilename );  #update this variable
    # if alternate
  # if bGenerate
  
  if( bGenerate ):
    # generate it!
    debug.debug( "sayAndCache: generating '%s' to file '%s'" % ( strTextToSay, szPathFilename ) );
    sayAndCache_InformProcess();
    timeBegin = time.time();
    tts = naoqitools.myGetProxy( "ALTextToSpeech" );
    
예제 #10
0
def sayAndCacheAndLight(strTextToSay,
                        bJustPrepare=False,
                        bStoreToNonVolatilePath=False,
                        nEyesColor=0,
                        nUseLang=-1):
    "say a cached text with light animation"
    "nEyesColor: 0: white, 1: blue, 2: green; 3: red"
    "nUseLang: if different of -1: speak with a specific languages (useful, when text are already generated: doesn't need to swap languages for nothing!"
    "return the length of the text in seconds, or None if impossible"
    print(
        "sayAndCacheAndLight( '%s', bJustPrepare: %s, bStoreToNonVolatilePath: %s, nEyesColor: %s, nUseLang: %s )"
        % (strTextToSay, str(bJustPrepare), str(bStoreToNonVolatilePath),
           str(nEyesColor), str(nUseLang)))
    if (not config.bPrecomputeText):
        print(
            "sayAndCacheAndLight: disabled by configuration: bPrecomputeText is false"
        )
        if (bJustPrepare):
            return None
            # do nothing
        tts = naoqitools.myGetProxy("ALTextToSpeech")
        tts.say(strTextToSay)
        return None

    rLength = sayAndCache(strTextToSay,
                          bJustPrepare=True,
                          bStoreToNonVolatilePath=bStoreToNonVolatilePath,
                          nUseLang=nUseLang,
                          bCalledFromSayAndCacheFromLight=True)
    # we store it to disk, only if we must do it

    # this two lines are done too in sayAndCache...
    strTextToSay = assumeTextHasDefaultSettings(strTextToSay, nUseLang)
    szFilename = sayAndCache_getFilename(strTextToSay, nUseLang)

    szPathVolatile = pathtools.getVolatilePath()
    rSampleLenSec = 0.05
    #    szPathFilenamePeak = szPathVolatile + szFilename + ("_%5.3f.egy" % rSampleLenSec);
    szPathFilenamePeak = szFilename + ("_%5.3f.egy" % rSampleLenSec)
    szPathFilenamePeakCache = pathtools.getCachePath(
    ) + "generatedvoices" + pathtools.getDirectorySeparator(
    ) + szPathFilenamePeak
    szPathFilenamePeak = szPathVolatile + szPathFilenamePeak
    anLedsColorSequency = []
    aBufFile = ""
    bFileGenerated = False
    if (not filetools.isFileExists(szPathFilenamePeak)):
        if (filetools.isFileExists(szPathFilenamePeakCache)):
            copyFile(szPathFilenamePeakCache, szPathFilenamePeak)
    if (not filetools.isFileExists(szPathFilenamePeak)):
        # generate peak file
        timeBegin = time.time()
        print("sayAndCacheAndLight: generating peak light - begin\n")
        szPathFilename = szPathVolatile + szFilename + ".raw"
        anLedsColorSequency = []
        try:
            une = naoqitools.myGetProxy('UsageNoiseExtractor')
            anLedsColorSequency = une.analyseSpeakSound(
                szPathFilename, int(rSampleLenSec * 1000), False)
        except BaseException, err:
            print("ERR: sayAndCacheAndLight( '%s' ): err: %s" %
                  (strTextToSay, str(err)))
            print("ERR: sayAndCacheAndLight => trying old cpp version")
            anLedsColorSequency = analyseSpeakSound(szPathFilename,
                                                    rSampleLenSec * 1000)
        print("sayAndCacheAndLight: analyseSpeakSound - end - time: %fs\n" %
              float(time.time() - timeBegin))
        #        print( "anLedsColorSequency: %d samples: %s\n" % ( len( anLedsColorSequency ), str( anLedsColorSequency ) ) );

        print("Writing file with %d peak samples (time: %d)\n" %
              (len(anLedsColorSequency), int(time.time())))
        #         struct.pack_into( "f"*len( anLedsColorSequency ), aBufFile, anLedsColorSequency[:] );
        for peakValue in anLedsColorSequency:
            aBufFile += struct.pack("f", peakValue)
        try:
            file = open(szPathFilenamePeak, "wb")
            file.write(aBufFile)
        except RuntimeError, err:
            print("ERR: sayAndCacheAndLight( '%s' ): err: %s" %
                  (strTextToSay, str(err)))
예제 #11
0
def sayAndCache(strTextToSay,
                bJustPrepare=False,
                bStoreToNonVolatilePath=False,
                bDirectPlay=False,
                nUseLang=-1,
                bWaitEnd=True,
                bCalledFromSayAndCacheFromLight=False):
    "generate a text in a file, then read it, next time it will be directly played from that file"
    "bJustPrepare: render the text to a file, but don't play it now"
    "bStoreToNonVolatilePath: copy the generated file to a non volatile path (/usr/generatedvoices)"
    "nUseLang: if different of -1: speak with a specific languages (useful, when text are already generated: doesn't need to swap languages for nothing!"
    "return the length of the text in seconds, or None if impossible"
    print(
        "sayAndCache( '%s', bJustPrepare: %s, bStoreToNonVolatilePath: %s, bDirectPlay: %s, nUseLang: %d, bWaitEnd: %s, bCalledFromSayAndCacheFromLight: %s )"
        % (strTextToSay, str(bJustPrepare), str(bStoreToNonVolatilePath),
           str(bDirectPlay), nUseLang, str(bWaitEnd),
           str(bCalledFromSayAndCacheFromLight)))
    if (not config.bPrecomputeText):
        print(
            "sayAndCache: disabled by configuration: bPrecomputeText is false")
        if (bJustPrepare):
            return None
            # do nothing
        tts = naoqitools.myGetProxy("ALTextToSpeech")
        tts.say(strTextToSay)
        return None
    print(
        "sayAndCache: FORCING DIRECT_PLAY CAR SINON C'EST BUGGE DANS LA VERSION COURANTE!"
    )
    bDirectPlay = True

    if (config.bRemoveDirectPlay):
        print(
            "WRN: DISABLING DIRECT_PLAY SETTINGS for testing/temporary purpose"
        )
        bDirectPlay = False

    strTextToSay = assumeTextHasDefaultSettings(strTextToSay, nUseLang)
    szFilename = sayAndCache_getFilename(strTextToSay, nUseLang)

    szPathVolatile = pathtools.getVolatilePath()

    #  if( not szFilename.isalnum() ): # the underscore is not an alphanumeric, but is valid there
    #    debug( "WRN: sayAndCache: some chars are not alphanumeric in filename '%s'" % szFilename );
    szPathFilename = szPathVolatile + szFilename + ".raw"
    bGenerate = not filetools.isFileExists(szPathFilename)

    if (bGenerate):
        szAlternatePathFilename = pathtools.getCachePath(
        ) + "generatedvoices" + pathtools.getDirectorySeparator(
        ) + szFilename + ".raw"
        # look in a non volatile path

        if (filetools.isFileExists(szAlternatePathFilename)):
            debug("sayAndCache: get static precomputed text for '%s'" %
                  (strTextToSay))
            copyFile(szAlternatePathFilename, szPathFilename)
            bGenerate = not filetools.isFileExists(szPathFilename)
            #update this variable
        # if alternate
    # if bGenerate

    if (bGenerate):
        # generate it!
        debug("sayAndCache: generating '%s' to file '%s'" %
              (strTextToSay, szPathFilename))
        sayAndCache_InformProcess()
        timeBegin = time.time()
        tts = naoqitools.myGetProxy("ALTextToSpeech")

        if (nUseLang != -1):
            # change the language to the wanted one
            setSpeakLanguage(nUseLang)
        if (len(strTextToSay) > 150
                and (not bJustPrepare or bCalledFromSayAndCacheFromLight)):
            # if it's a long text, we had a blabla to tell the user we will wait (if it's a just prepare from inner, we don't use it)
            sayAndCache_InformPrepare()

        print("TTS TO FILE 1 - BEGIN")
        tts.sayToFile(strTextToSay, szPathFilename)
        print("TTS TO FILE 1 - END")
        sayAndCache_InformProcess_end()

        debug("sayAndCache: generating text to file - end (tts) - time: %fs" %
              (time.time() - timeBegin))
        timeBegin = time.time()

        removeBlankFromFile(szPathFilename)
        debug(
            "sayAndCache: generating text to file - end (post-process1) - time: %fs"
            % (time.time() - timeBegin))
        timeBegin = time.time()

        if (bStoreToNonVolatilePath):
            try:
                os.makedirs(pathtools.getCachePath() + "generatedvoices" +
                            pathtools.getDirectorySeparator())
            except:
                pass
            szAlternatePathFilename = pathtools.getCachePath(
            ) + "generatedvoices" + pathtools.getDirectorySeparator(
            ) + szFilename + ".raw"
            # a non volatile path
            copyFile(szPathFilename, szAlternatePathFilename)

        time.sleep(0.1)
        # pour laisser la synthese souffler un peu (dans les scripts je mettais 300ms)
        debug(
            "sayAndCache: generating text to file - end (post-process2) - time: %fs"
            % (time.time() - timeBegin))

    statinfo = os.stat(szPathFilename)
    rLength = statinfo.st_size / float(22050 * 1 * 2)
    # sizefile => secondes

    if (not bJustPrepare):
        #    debug( "speech::sayAndCache: launching sound now!" );
        if (bWaitEnd):
            analyseSound_pause(True)
        if (bDirectPlay):
            nLang = nUseLang
            if (nLang == -1):
                nLang = getSpeakLanguage()
            nFreq = 22050
            if (nLang == constants.LANG_CH or nLang == constants.LANG_KO):
                nFreq = 17000
                # parce que c'est beau, (ca fait a peu pres du speed a 72%) # todo: ca désynchronise les yeux qui se lisent trop vite ! argh !
            mySystemCall("aplay -c1 -r%d -fS16_LE -q %s" %
                         (nFreq, szPathFilename),
                         bWaitEnd=bWaitEnd)
        else:
            leds = naoqitools.myGetProxy("ALLeds", True)
            leds.post.fadeRGB("RightFootLeds", 0xFF0000, 0.7)
            # right in red (skip)
            audioProxy = naoqitools.myGetProxy("ALAudioPlayer", True)
            # read it in background and check if someone press the right feet a long times => skip text playing

            id = audioProxy.post.playFile(szPathFilename)
            if (not bWaitEnd):
                # attention: no unpause of analyse dans ce cas la!
                return rLength
            nbrFramesBumpersPushed = 0
            nbrFramesBumpersPushedMinToSkip = 2
            strTemplateKeyName = "Device/SubDeviceList/%sFoot/Bumper/%s/Sensor/Value"
            stm = naoqitools.myGetProxy("ALMemory")
            while (audioProxy.isRunning(id)):
                time.sleep(0.1)
                # time for user to release precedent push
                listRightFeetBumpers = stm.getListData([
                    strTemplateKeyName % ("R", "Left"),
                    strTemplateKeyName % ("R", "Right")
                ])
                if (listRightFeetBumpers[0] > 0.0
                        or listRightFeetBumpers[1] > 0.0):
                    nbrFramesBumpersPushed += 1
                    if (nbrFramesBumpersPushed >=
                            nbrFramesBumpersPushedMinToSkip):
                        print(
                            "sayAndCache: skipping current text reading because users press on right bumpers"
                        )
                        audioProxy.stop(id)
            leds.post.fadeRGB("RightFootLeds", 0x000000, 0.2)
            # turn off it
            # while - end
        #if( bDirectPlay ) - end
        analyseSound_resume(True)
    # if( not bJustPrepare ) - end
    print("sayAndCache: End !!!")
    return rLength
예제 #12
0
    szFilename = sayAndCache_getFilename(strTextToSay, nUseLang, strUseVoice)

    szPathVolatile = pathtools.getVolatilePath(
    ) + "generatedvoices" + pathtools.getDirectorySeparator()
    try:
        os.mkdir(szPathVolatile)
    except BaseException, err:
        pass

#  if( not szFilename.isalnum() ): # the underscore is not an alphanumeric, but is valid there
#    debug.debug( "WRN: sayAndCache: some chars are not alphanumeric in filename '%s'" % szFilename );
    szPathFilename = szPathVolatile + szFilename + ".raw"
    bGenerate = not filetools.isFileExists(szPathFilename)

    if (bGenerate):
        szAlternatePathFilename = pathtools.getCachePath(
        ) + "generatedvoices" + pathtools.getDirectorySeparator(
        ) + szFilename + ".raw"
        # look in a non volatile path

        if (filetools.isFileExists(szAlternatePathFilename)):
            debug.debug("sayAndCache: get static precomputed text for '%s'" %
                        (strTextToSay))
            filetools.copyFile(szAlternatePathFilename, szPathFilename)
            bGenerate = not filetools.isFileExists(szPathFilename)
            #update this variable
        # if alternate
    # if bGenerate

    if (bGenerate):
        # generate it!
        debug.debug("sayAndCache: generating '%s' to file '%s'" %
 def __getVarPath_Inner__( self ):
     import pathtools # module already unloaded when called from __del__
     return pathtools.getCachePath() + "mem" + pathtools.getDirectorySeparator();
 def getVarPath():
     return pathtools.getCachePath() + 'mem' + pathtools.getDirectorySeparator();
예제 #15
0
def sayAndCache( strTextToSay, bJustPrepare = False, bStoreToNonVolatilePath = False, bDirectPlay = False, nUseLang = -1, bWaitEnd = True, bCalledFromSayAndCacheFromLight = False ):
  "generate a text in a file, then read it, next time it will be directly played from that file"
  "bJustPrepare: render the text to a file, but don't play it now"
  "bStoreToNonVolatilePath: copy the generated file to a non volatile path (/usr/generatedvoices)"
  "nUseLang: if different of -1: speak with a specific languages (useful, when text are already generated: doesn't need to swap languages for nothing!"
  "return the length of the text in seconds, or None if impossible"
  print( "sayAndCache( '%s', bJustPrepare: %s, bStoreToNonVolatilePath: %s, bDirectPlay: %s, nUseLang: %d, bWaitEnd: %s, bCalledFromSayAndCacheFromLight: %s )" % ( strTextToSay, str( bJustPrepare ), str( bStoreToNonVolatilePath ), str( bDirectPlay ), nUseLang, str( bWaitEnd ), str( bCalledFromSayAndCacheFromLight ) ) );
  if( not config.bPrecomputeText ):
      print( "sayAndCache: disabled by configuration: bPrecomputeText is false" );
      if( bJustPrepare ):
          return None; # do nothing
      tts = naoqitools.myGetProxy( "ALTextToSpeech" );
      tts.say( strTextToSay );
      return None;
  print( "sayAndCache: FORCING DIRECT_PLAY CAR SINON C'EST BUGGE DANS LA VERSION COURANTE!");  
  bDirectPlay = True;
  
  if( config.bRemoveDirectPlay ):
    print( "WRN: DISABLING DIRECT_PLAY SETTINGS for testing/temporary purpose" );
    bDirectPlay = False;  
  
  strTextToSay = assumeTextHasDefaultSettings( strTextToSay, nUseLang );
  szFilename = sayAndCache_getFilename( strTextToSay, nUseLang );
  
  szPathVolatile = pathtools.getVolatilePath();
  
#  if( not szFilename.isalnum() ): # the underscore is not an alphanumeric, but is valid there
#    debug( "WRN: sayAndCache: some chars are not alphanumeric in filename '%s'" % szFilename );
  szPathFilename = szPathVolatile + szFilename + ".raw";
  bGenerate = not filetools.isFileExists( szPathFilename );
  
  if( bGenerate ):
    szAlternatePathFilename = pathtools.getCachePath() + "generatedvoices" + pathtools.getDirectorySeparator() + szFilename + ".raw"; # look in a non volatile path
    
    if( filetools.isFileExists( szAlternatePathFilename ) ):
      debug( "sayAndCache: get static precomputed text for '%s'" % ( strTextToSay ) );
      copyFile( szAlternatePathFilename, szPathFilename );
      bGenerate = not filetools.isFileExists( szPathFilename );  #update this variable
    # if alternate
  # if bGenerate
  
  if( bGenerate ):
    # generate it!
    debug( "sayAndCache: generating '%s' to file '%s'" % ( strTextToSay, szPathFilename ) );
    sayAndCache_InformProcess();
    timeBegin = time.time();
    tts = naoqitools.myGetProxy( "ALTextToSpeech" );
    
    if( nUseLang != -1 ):
        # change the language to the wanted one
        setSpeakLanguage( nUseLang );
    if( len( strTextToSay ) > 150 and ( not bJustPrepare or bCalledFromSayAndCacheFromLight ) ):
        # if it's a long text, we had a blabla to tell the user we will wait (if it's a just prepare from inner, we don't use it)
        sayAndCache_InformPrepare();
    
    print( "TTS TO FILE 1 - BEGIN" );
    tts.sayToFile( strTextToSay, szPathFilename );
    print( "TTS TO FILE 1 - END" );
    sayAndCache_InformProcess_end();
    
    debug( "sayAndCache: generating text to file - end (tts) - time: %fs" % ( time.time() - timeBegin ) );    
    timeBegin = time.time();
    
    removeBlankFromFile( szPathFilename );
    debug( "sayAndCache: generating text to file - end (post-process1) - time: %fs" % ( time.time() - timeBegin ) );
    timeBegin = time.time();

    if( bStoreToNonVolatilePath ):
      try:
        os.makedirs( pathtools.getCachePath() + "generatedvoices" + pathtools.getDirectorySeparator());
      except:
        pass
      szAlternatePathFilename = pathtools.getCachePath() + "generatedvoices" + pathtools.getDirectorySeparator() + szFilename + ".raw"; # a non volatile path
      copyFile( szPathFilename, szAlternatePathFilename );

    time.sleep( 0.1 ); # pour laisser la synthese souffler un peu (dans les scripts je mettais 300ms)
    debug( "sayAndCache: generating text to file - end (post-process2) - time: %fs" % ( time.time() - timeBegin ) );
    
  statinfo = os.stat( szPathFilename );
  rLength = statinfo.st_size / float(22050*1*2); # sizefile => secondes
    
  if( not bJustPrepare ):
#    debug( "speech::sayAndCache: launching sound now!" );
    if( bWaitEnd ):
        analyseSound_pause( True );
    if( bDirectPlay ):
        nLang = nUseLang;
        if( nLang == -1 ):
            nLang = getSpeakLanguage();
        nFreq = 22050;
        if( nLang == constants.LANG_CH or nLang == constants.LANG_KO ):
            nFreq = 17000; # parce que c'est beau, (ca fait a peu pres du speed a 72%) # todo: ca désynchronise les yeux qui se lisent trop vite ! argh !
        mySystemCall( "aplay -c1 -r%d -fS16_LE -q %s" % ( nFreq, szPathFilename ), bWaitEnd = bWaitEnd );
    else:
        leds = naoqitools.myGetProxy( "ALLeds", True );
        leds.post.fadeRGB( "RightFootLeds", 0xFF0000, 0.7 ); # right in red (skip)
        audioProxy = naoqitools.myGetProxy( "ALAudioPlayer", True );
        # read it in background and check if someone press the right feet a long times => skip text playing
        
        id = audioProxy.post.playFile(szPathFilename);
        if( not bWaitEnd ):
            # attention: no unpause of analyse dans ce cas la!
            return rLength;
        nbrFramesBumpersPushed = 0;
        nbrFramesBumpersPushedMinToSkip = 2;
        strTemplateKeyName = "Device/SubDeviceList/%sFoot/Bumper/%s/Sensor/Value";
        stm = naoqitools.myGetProxy( "ALMemory" );
        while( audioProxy.isRunning( id ) ):
            time.sleep( 0.1 ); # time for user to release precedent push
            listRightFeetBumpers = stm.getListData( [strTemplateKeyName % ( "R", "Left" ), strTemplateKeyName % ( "R", "Right" )] );
            if( listRightFeetBumpers[0] > 0.0 or listRightFeetBumpers[1] > 0.0 ):
                nbrFramesBumpersPushed += 1;
                if( nbrFramesBumpersPushed >= nbrFramesBumpersPushedMinToSkip ):
                    print( "sayAndCache: skipping current text reading because users press on right bumpers" );
                    audioProxy.stop( id );
        leds.post.fadeRGB( "RightFootLeds", 0x000000, 0.2 ); # turn off it
        # while - end
    #if( bDirectPlay ) - end
    analyseSound_resume( True );
  # if( not bJustPrepare ) - end
  print( "sayAndCache: End !!!");
  return rLength;