示例#1
0
    def process_compressed_data(self):
        self.unzipped_input += self.decompressor.decompress(self.data)
        self.data = ""
        while self.hasNextObj():
            reqObject = self.read_next_object_from_unzipped()
            if reqObject != None:
                self.logger.debug("Packet with class: {0}".format(reqObject['class']))
                self.logger.debug("packet with content:\n{0}".format(pprint.pformat(reqObject, width=40)))

                # first handle speech stuff

                if 'refId' in reqObject:
                    # if the following holds, this packet is an answer to a request by a plugin
                    if reqObject['refId'] == self.plugin_lastAceId and self.current_running_plugin != None:
                        if self.current_running_plugin.waitForResponse != None:
                            # just forward the object to the
                            # don't change it's refId, further requests must reference last FinishSpeech
                            self.logger.info("Forwarding object to plugin")
                            self.plugin_lastAceId = None
                            self.current_running_plugin.response = reqObject if reqObject['class'] != "StartRequest" else reqObject['properties']['utterance']
                            self.current_running_plugin.waitForResponse.set()
                            continue

                if ObjectIsCommand(reqObject, StartSpeechRequest) or ObjectIsCommand(reqObject, StartSpeechDictation):
                    self.logger.info("New start of speech received")
                    startSpeech = None
                    if ObjectIsCommand(reqObject, StartSpeechDictation):
                        dictation = True
                        startSpeech = StartSpeechDictation(reqObject)
                    else:
                        dictation = False
                        startSpeech = StartSpeechRequest(reqObject)

                    decoder = speex.Decoder()
                    encoder = flac.Encoder()
                    speexUsed = False
                    if startSpeech.codec == StartSpeech.CodecSpeex_WB_Quality8Value:
                        decoder.initialize(mode=speex.SPEEX_MODEID_WB)
                        encoder.initialize(16000, 1, 16)
                        speexUsed = True
                    elif startSpeech.codec == StartSpeech.CodecSpeex_NB_Quality7Value:
                        decoder.initialize(mode=speex.SPEEX_MODEID_NB)
                        encoder.initialize(16000, 1, 16)
                        speexUsed = True
                    elif startSpeech.codec == StartSpeech.CodecPCM_Mono_16Bit_8000HzValue:
                        encoder.initialize(8000, 1, 16)
                    elif startSpeech.codec == StartSpeech.CodecPCM_Mono_16Bit_11025HzValue:
                        encoder.initialize(11025, 1, 16)
                    elif startSpeech.coded == StartSpeech.CodecPCM_Mono_16Bit_16000HzValue:
                        encoder.initialize(16000, 1, 16)
                    elif startSpeech.coded == StartSpeech.CodecPCM_Mono_16Bit_22050HzValue:
                        encoder.initialize(22050, 1, 16)
                    elif startSpeech.coded == StartSpeech.CodecPCM_Mono_16Bit_32000HzValue:
                        encoder.initialize(32000, 1, 16)
                    # we probably need resampling for sample rates other than 16kHz...

                    self.speech[startSpeech.aceId] = (decoder if speexUsed else None, encoder, dictation)

                elif ObjectIsCommand(reqObject, SpeechPacket):
                    self.logger.info("Decoding speech packet")
                    speechPacket = SpeechPacket(reqObject)
                    (decoder, encoder, dictation) = self.speech[speechPacket.refId]
                    if decoder:
                        pcm = decoder.decode(speechPacket.packets)
                    else:
                        pcm = SpeechPacket.data # <- probably data... if pcm
                    encoder.encode(pcm)

                elif reqObject['class'] == 'StartCorrectedSpeechRequest':

                    self.process_recognized_speech({u'hypotheses': [{'confidence': 1.0, 'utterance': reqObject['properties']['utterance'].lower()}]}, reqObject['aceId'], False)

                elif ObjectIsCommand(reqObject, FinishSpeech):
                    self.logger.info("End of speech received")
                    finishSpeech = FinishSpeech(reqObject)
                    (decoder, encoder, dictation) = self.speech[finishSpeech.refId]
                    if decoder:
                        decoder.destroy()
                    encoder.finish()
                    flacBin = encoder.getBinary()
                    encoder.destroy()
                    del self.speech[finishSpeech.refId]

                    self.logger.info("Sending flac to google for recognition")
                    try:
                        self.httpClient.make_google_request(flacBin, finishSpeech.refId, dictation, language=self.assistant.language, allowCurses=True)
                    except AttributeError, TypeError:
                        self.logger.info("Unable to find language record for this assistant. Try turning Siri off and then back on.")

                elif ObjectIsCommand(reqObject, CancelRequest):
                        # this is probably called when we need to kill a plugin
                        # wait for thread to finish a send
                        cancelRequest = CancelRequest(reqObject)
                        if cancelRequest.refId in self.speech:
                            del self.speech[cancelRequest.refId]

                        self.send_object(CancelSucceeded(cancelRequest.aceId))

                elif ObjectIsCommand(reqObject, GetSessionCertificate):
                    getSessionCertificate = GetSessionCertificate(reqObject)
                    response = GetSessionCertificateResponse(getSessionCertificate.aceId, caCert.as_der(), serverCert.as_der())
                    self.send_object(response)

                elif ObjectIsCommand(reqObject, CreateSessionInfoRequest):
                    # how does a positive answer look like?
                    createSessionInfoRequest = CreateSessionInfoRequest(reqObject)
                    fail = CommandFailed(createSessionInfoRequest.aceId)
                    fail.reason = "Not authenticated"
                    fail.errorCode = 0
                    self.send_object(fail)

                    #self.send_plist({"class":"SessionValidationFailed", "properties":{"errorCode":"UnsupportedHardwareVersion"}, "aceId": str(uuid.uuid4()), "refId":reqObject['aceId'], "group":"com.apple.ace.system"})

                elif reqObject['class'] == 'CreateAssistant':
                    #create a new assistant
                    helper = Assistant()
                    c = self.dbConnection.cursor()
                    noError = True
                    try:
                        if db.db_type == "mysql":
                            assistant_str = db.adaptAssistant(helper)
                            c.execute("insert into assistants(assistantId, assistant) values (%s,%s)", (helper.assistantId, assistant_str))
                        else:
                            c.execute("insert into assistants(assistantId, assistant) values (?,?)", (helper.assistantId, helper))
                        self.dbConnection.commit()
                    except:
                        noError = False
                    c.close()
                    if noError:
                        self.assistant = helper
                        self.send_plist({"class": "AssistantCreated", "properties": {"speechId": str(uuid.uuid4()), "assistantId": helper.assistantId}, "group":"com.apple.ace.system", "callbacks":[], "aceId": str(uuid.uuid4()), "refId": reqObject['aceId']})
                    else:
                        self.send_plist({"class":"CommandFailed", "properties": {"reason":"Database error", "errorCode":2, "callbacks":[]}, "aceId": str(uuid.uuid4()), "refId": reqObject['aceId'], "group":"com.apple.ace.system"})

                elif reqObject['class'] == 'SetAssistantData':
                    # fill assistant
                    if self.assistant != None:
                        c = self.dbConnection.cursor()
                        objProperties = reqObject['properties']
                        self.assistant.censorSpeech = objProperties['censorSpeech']
                        self.assistant.timeZoneId = objProperties['timeZoneId']
                        self.assistant.language = objProperties['language']
                        self.assistant.region = objProperties['region']

                        try:
                            self.assistant.firstName = objProperties['meCards'][0]['properties']['firstName'].encode("utf-8")
                        except:
                            self.assistant.firstName = ""

                        try:
                            self.assistant.nickName = objProperties['meCards'][0]['properties']['nickName'].encode("utf-8")
                        except:
                            self.assistant.nickName = ""

                        try:
                            self.assistant.accountIdentifier = objProperties["abSources"][0]["properties"]["accountIdentifier"]
                        except:
                            self.assistant.accountIdentifier = ""

                        if db.db_type == "mysql":
                            assistant_str = db.adaptAssistant(self.assistant)
                            c.execute("update assistants set assistant = %s where assistantId = %s", (assistant_str, self.assistant.assistantId))
                        else:
                            c.execute("update assistants set assistant = ? where assistantId = ?", (self.assistant, self.assistant.assistantId))

                        self.dbConnection.commit()
                        c.close()


                elif reqObject['class'] == 'LoadAssistant':
                    c = self.dbConnection.cursor()
                    if db.db_type == "mysql":
                        c.execute("select assistant from assistants where assistantId = %s", (reqObject['properties']['assistantId'],))
                    else:
                        c.execute("select assistant from assistants where assistantId = ?", (reqObject['properties']['assistantId'],))
                    self.dbConnection.commit()
                    result = c.fetchone()
                    if result == None:
                        self.send_plist({"class": "AssistantNotFound", "aceId":str(uuid.uuid4()), "refId":reqObject['aceId'], "group":"com.apple.ace.system"})
                    else:
                        if db.db_type == "mysql":
                            self.assistant = db.convertAssistant(result[0].encode("utf-8"))
                        else:
                            self.assistant = result[0]
                        self.send_plist({"class": "AssistantLoaded", "properties": {"version": "20111216-32234-branches/telluride?cnxn=293552c2-8e11-4920-9131-5f5651ce244e", "requestSync":False, "dataAnchor":"removed"}, "aceId":str(uuid.uuid4()), "refId":reqObject['aceId'], "group":"com.apple.ace.system"})
                    c.close()

                elif reqObject['class'] == 'DestroyAssistant':
                    c = self.dbConnection.cursor()
                    if db.db_type == "mysql":
                        c.execute("delete from assistants where assistantId = %s", (reqObject['properties']['assistantId'],))
                    else:
                        c.execute("delete from assistants where assistantId = ?", (reqObject['properties']['assistantId'],))
                    self.dbConnection.commit()
                    c.close()
                    self.send_plist({"class": "AssistantDestroyed", "properties": {"assistantId": reqObject['properties']['assistantId']}, "aceId":str(uuid.uuid4()), "refId":reqObject['aceId'], "group":"com.apple.ace.system"})
                elif reqObject['class'] == 'StartRequest':
                    #this should also be handeled by special plugins, so lets call the plugin handling stuff
                    self.process_recognized_speech({'hypotheses': [{'utterance': reqObject['properties']['utterance'], 'confidence': 1.0}]}, reqObject['aceId'], False)
示例#2
0
 def process_compressed_data(self):
     self.unzipped_input += self.decompressor.decompress(self.data)
     self.data = ""
     while self.hasNextObj():
         reqObject = self.read_next_object_from_unzipped()
         if reqObject != None:
             self.logger.debug("Packet with class: {0}".format(reqObject['class']))
             self.logger.debug("packet with content:\n{0}".format(pprint.pformat(reqObject, width=40)))
             
             # first handle speech stuff
             
             if 'refId' in reqObject:
                 # if the following holds, this packet is an answer to a request by a plugin
                 if reqObject['refId'] == self.plugin_lastAceId and self.current_running_plugin != None:
                     if self.current_running_plugin.waitForResponse != None:
                         # just forward the object to the 
                         # don't change it's refId, further requests must reference last FinishSpeech
                         self.logger.info("Forwarding object to plugin")
                         self.plugin_lastAceId = None
                         self.current_running_plugin.response = reqObject if reqObject['class'] != "StartRequest" else reqObject['properties']['utterance']
                         self.current_running_plugin.waitForResponse.set()
                         continue
             
             if ObjectIsCommand(reqObject, StartSpeechRequest) or ObjectIsCommand(reqObject, StartSpeechDictation):
                 self.logger.info("New start of speech received")
                 startSpeech = None
                 if ObjectIsCommand(reqObject, StartSpeechDictation):
                     dictation = True
                     startSpeech = StartSpeechDictation(reqObject)
                 else:
                     dictation = False
                     startSpeech = StartSpeechRequest(reqObject)
                 
                 decoder = speex.Decoder()
                 encoder = flac.Encoder()
                 speexUsed = False
                 if startSpeech.codec == StartSpeech.CodecSpeex_WB_Quality8Value:
                     decoder.initialize(mode=speex.SPEEX_MODEID_WB)
                     encoder.initialize(16000, 1, 16)
                     speexUsed = True
                 elif startSpeech.codec == StartSpeech.CodecSpeex_NB_Quality7Value:
                     decoder.initialize(mode=speex.SPEEX_MODEID_NB)
                     encoder.initialize(16000, 1, 16)
                     speexUsed = True
                 elif startSpeech.codec == StartSpeech.CodecPCM_Mono_16Bit_8000HzValue:
                     encoder.initialize(8000, 1, 16)
                 elif startSpeech.codec == StartSpeech.CodecPCM_Mono_16Bit_11025HzValue:
                     encoder.initialize(11025, 1, 16)
                 elif startSpeech.coded == StartSpeech.CodecPCM_Mono_16Bit_16000HzValue:
                     encoder.initialize(16000, 1, 16)
                 elif startSpeech.coded == StartSpeech.CodecPCM_Mono_16Bit_22050HzValue:
                     encoder.initialize(22050, 1, 16)
                 elif startSpeech.coded == StartSpeech.CodecPCM_Mono_16Bit_32000HzValue:
                     encoder.initialize(32000, 1, 16)
                 # we probably need resampling for sample rates other than 16kHz...
                 
                 self.speech[startSpeech.aceId] = (decoder if speexUsed else None, encoder, dictation)
             
             elif ObjectIsCommand(reqObject, SpeechPacket):
                 self.logger.info("Decoding speech packet")
                 speechPacket = SpeechPacket(reqObject)
                 (decoder, encoder, dictation) = self.speech[speechPacket.refId]
                 if decoder:
                     pcm = decoder.decode(speechPacket.packets)
                 else:
                     pcm = SpeechPacket.data # <- probably data... if pcm
                 encoder.encode(pcm)
             
             elif reqObject['class'] == 'StartCorrectedSpeechRequest':
                 self.process_recognized_speech({u'hypotheses': [{'confidence': 1.0, 'utterance': str.lower(reqObject['properties']['utterance'])}]}, reqObject['aceId'], False)
             
             elif ObjectIsCommand(reqObject, FinishSpeech):
                 self.logger.info("End of speech received")
                 finishSpeech = FinishSpeech(reqObject)
                 (decoder, encoder, dictation) = self.speech[finishSpeech.refId]
                 if decoder:
                     decoder.destroy()
                 encoder.finish()
                 flacBin = encoder.getBinary()
                 encoder.destroy()
                 del self.speech[finishSpeech.refId]
                 
                 self.logger.info("Sending flac to google for recognition")
                 try:
                     self.httpClient.make_google_request(flacBin, finishSpeech.refId, dictation, language=self.assistant.language, allowCurses=True)
                 except AttributeError, TypeError:
                     self.logger.info("Unable to find language record for this assistant. Try turning Siri off and then back on.")
             
             elif ObjectIsCommand(reqObject, CancelRequest):
                 # this is probably called when we need to kill a plugin
                 # wait for thread to finish a send
                 cancelRequest = CancelRequest(reqObject)
                 if cancelRequest.refId in self.speech:
                     del self.speech[cancelRequest.refId]
                 
                 self.send_object(CancelSucceeded(cancelRequest.aceId))
             
             elif ObjectIsCommand(reqObject, GetSessionCertificate):
                 getSessionCertificate = GetSessionCertificate(reqObject)
                 response = GetSessionCertificateResponse(getSessionCertificate.aceId, caCert.as_der(), serverCert.as_der())
                 self.send_object(response)
             
             elif ObjectIsCommand(reqObject, CreateSessionInfoRequest):
                 # how does a positive answer look like?
                 createSessionInfoRequest = CreateSessionInfoRequest(reqObject)
                 fail = CommandFailed(createSessionInfoRequest.aceId)
                 fail.reason = "Not authenticated"
                 fail.errorCode = 0
                 self.send_object(fail)
             
             #self.send_plist({"class":"SessionValidationFailed", "properties":{"errorCode":"UnsupportedHardwareVersion"}, "aceId": str(uuid.uuid4()), "refId":reqObject['aceId'], "group":"com.apple.ace.system"})
             
             elif reqObject['class'] == 'CreateAssistant':
                 #create a new assistant
                 helper = Assistant()
                 c = self.dbConnection.cursor()
                 noError = True
                 try:
                     c.execute("INSERT INTO `assistants` (`assistantId`, `assistant`,`timeZoneId`, `language`, `region`) VALUES (%s,%s,%s,%s,%s)", (helper.assistantId,db.adaptAssistant(helper),helper.timeZoneId,helper.language,helper.region))
                     self.dbConnection.commit()
                 except MySQLdb.Error, e: 
                     noError = False
                 c.close()
                 if noError:
                     self.assistant = helper
                     self.send_plist({"class": "AssistantCreated", "properties": {"speechId": str(uuid.uuid4()), "assistantId": helper.assistantId}, "group":"com.apple.ace.system", "callbacks":[], "aceId": str(uuid.uuid4()), "refId": reqObject['aceId']})
                 else:
                     self.send_plist({"class":"CommandFailed", "properties": {"reason":"Database error", "errorCode":2, "callbacks":[]}, "aceId": str(uuid.uuid4()), "refId": reqObject['aceId'], "group":"com.apple.ace.system"})
             
             elif reqObject['class'] == 'SetAssistantData':
                 # fill assistant 
                 if self.assistant != None:
                     c = self.dbConnection.cursor()
                     objProperties = reqObject['properties'] 
                     self.assistant.censorSpeech = objProperties['censorSpeech']
                     self.assistant.timeZoneId = objProperties['timeZoneId']
                     self.assistant.language = objProperties['language']
                     self.assistant.region = objProperties['region']
                     c.execute("UPDATE `assistants` SET `assistant` = %s, `timeZoneId` = %s, `language` = %s, `region` = %s WHERE `assistantId` = %s", (db.adaptAssistant(self.assistant), self.assistant.timeZoneId, self.assistant.language, self.assistant.region, self.assistant.assistantId))
                     self.dbConnection.commit()
                     c.close()