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)
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()