예제 #1
0
 def findPhoneForNumberType(self, person, numberType, language):
     # first check if a specific number was already requested
     phoneToCall = None
     if numberType != None:
         # try to find the phone that fits the numberType
         phoneToCall = filter(lambda x: x.label == numberType,
                              person.phones)
     else:
         favPhones = filter(
             lambda y: y.favoriteVoice
             if hasattr(y, "favoriteVoice") else False, person.phones)
         if len(favPhones) == 1:
             phoneToCall = favPhones[0]
     if phoneToCall == None:
         # lets check if there is more than one number
         if len(person.phones) == 1:
             if numberType != None:
                 self.say(
                     errorNumberNotPresent.format(
                         numberTypesLocalized[numberType][language],
                         person.fullName))
             phoneToCall = person.phones[0]
         else:
             # damn we need to ask the user which one he wants...
             while (phoneToCall == None):
                 rootView = AddViews(self.refId,
                                     temporary=False,
                                     dialogPhase="Clarification",
                                     scrollToTop=False,
                                     views=[])
                 sayit = responses['selectNumber'][language].format(
                     person.fullName)
                 rootView.views.append(
                     AssistantUtteranceView(
                         text=sayit,
                         speakableText=sayit,
                         listenAfterSpeaking=True,
                         dialogIdentifier=
                         "ContactDataResolutionDucs#foundAmbiguousPhoneNumberForContact"
                     ))
                 lst = DisambiguationList(
                     items=[],
                     speakableSelectionResponse="OK...",
                     listenAfterSpeaking=True,
                     speakableText="",
                     speakableFinalDemitter=speakableDemitter[language],
                     speakableDemitter=", ",
                     selectionResponse="OK...")
                 rootView.views.append(lst)
                 for phone in person.phones:
                     numberType = phone.label
                     item = ListItem()
                     item.title = ""
                     item.text = u"{0}: {1}".format(
                         numberTypesLocalized[numberType][language],
                         phone.number)
                     item.selectionText = item.text
                     item.speakableText = u"{0}  ".format(
                         numberTypesLocalized[numberType][language])
                     item.object = phone
                     item.commands.append(
                         SendCommands(commands=[
                             StartRequest(
                                 handsFree=False,
                                 utterance=numberTypesLocalized[numberType]
                                 [language])
                         ]))
                     lst.items.append(item)
                 answer = self.getResponseForRequest(rootView)
                 if re.match(InterruptCall[language], answer,
                             re.IGNORECASE):
                     self.say(random.choice(
                         InterruptCallResponse[language]))
                     return None
                 numberType = self.getNumberTypeForName(answer, language)
                 if numberType != None:
                     print numberType
                     matches = filter(lambda x: x.label == numberType,
                                      person.phones)
                     if len(matches) == 1:
                         phoneToCall = matches[0]
                     else:
                         self.say(errorNumberTypes[language])
                 else:
                     self.say(errorNumberTypes[language])
     return phoneToCall
예제 #2
0
def findMailForMailType(plugin, person, mailType, language):
    mail = None
    if mailType != None:
        mailToWrite = filter(lambda x: x.label == mailType, person.emails)
    else:
        favMails = filter(
            lambda y: y.favoriteVoice
            if hasattr(y, "favoriteVoice") else False, person.emails)
        if len(favMails) == 1:
            mail = favMails[0]
    if mail == None:
        if len(person.emails) == 1:
            if mailType != None:
                plugin.say(text["numberNotPresent"][language].format(
                    mailTypes[language][mailType], person.fullName))
            mail = person.emails[0]
        else:
            while (mail == None):
                rootView = UIAddViews(plugin.refId)
                rootView.temporary = False
                rootView.dialogPhase = "Clarification"
                rootView.scrollToTop = False
                rootView.views = []
                sayit = text['selectMail'][language].format(person.fullName)
                assistant = UIAssistantUtteranceView()
                assistant.text = assistant.speakableText = sayit
                assistant.listenAfterSpeaking = True
                assistant.dialogIdentifier = "ContactDataResolutionDucs#foundAmbiguousMailForContact"
                rootView.views.append(assistant)
                lst = UIDisambiguationList()
                lst.items = []
                lst.speakableSelectionResponse = "OK..."
                lst.listenAfterSpeaking = True
                lst.speakableText = ""
                lst.speakableFinalDemitter = speakableDemitter[language]
                lst.speakableDemitter = ", "
                lst.selectionResponse = "OK..."
                rootView.views.append(lst)
                for email in person.emails:
                    mailType = email.label
                    item = UIListItem()
                    item.title = ""
                    item.text = u"{0}: {1}".format(
                        mailTypes[language][mailType], email.emailAddress)
                    item.selectionText = item.text
                    item.speakableText = u"{0}  ".format(
                        mailTypes[language][mailType])
                    item.object = email
                    item.commands = []
                    item.commands.append(
                        SendCommands(commands=[
                            StartRequest(handsFree=False,
                                         utterance=mailTypes[language]
                                         [mailType])
                        ]))
                    lst.items.append(item)
                answer = plugin.getResponseForRequest(rootView)
                answer = replaceMailType(answer, language)
                mailType = answer
                if mailType != None:
                    matches = filter(lambda x: x.label == mailType,
                                     person.emails)
                    if len(matches) == 1:
                        mail = matches[0]
                    else:
                        plugin.say(text['errorNumberTypes'][language])
                else:
                    plugin.say(text['errorNumberTypes'][language])
    return mail
예제 #3
0
def findPhoneForNumberType(plugin, person, numberType, language):
    number = None
    if numberType != None:
        phoneToCall = filter(lambda x: x.label == numberType, person.phones)
    else:
        favPhones = filter(
            lambda y: y.favoriteVoice
            if hasattr(y, "favoriteVoice") else False, person.phones)
        if len(favPhones) == 1:
            number = favPhones[0]
    if number == None:
        if len(person.phones) == 1:
            if numberType != None:
                plugin.say(text["numberNotPresent"][language].format(
                    numberTypes[language][numberType], person.fullName))
            number = person.phones[0]
        else:
            while (number == None):
                rootView = UIAddViews(plugin.refId)
                rootView.temporary = False
                rootView.dialogPhase = "Clarification"
                rootView.scrollToTop = False
                rootView.views = []
                sayit = text['selectNumber'][language].format(person.fullName)
                assistant = UIAssistantUtteranceView()
                assistant.text = assistant.speakableText = sayit
                assistant.listenAfterSpeaking = True
                assistant.dialogIdentifier = "ContactDataResolutionDucs#foundAmbiguousPhoneNumberForContact"
                rootView.views.append(assistant)
                lst = UIDisambiguationList()
                lst.items = []
                lst.speakableSelectionResponse = "OK..."
                lst.listenAfterSpeaking = True
                lst.speakableText = ""
                lst.speakableFinalDemitter = speakableDemitter[language]
                lst.speakableDemitter = ", "
                lst.selectionResponse = "OK..."
                rootView.views.append(lst)
                for phone in person.phones:
                    numberType = numberTypesLocalized[phone.label][
                        language] if phone.label in numberTypesLocalized else phone.label
                    item = UIListItem()
                    item.title = ""
                    item.text = u"{0}: {1}".format(numberType, phone.number)
                    item.selectionText = item.text
                    item.speakableText = u"{0}  ".format(numberType)
                    item.object = phone
                    item.commands = [
                        SendCommands(commands=[
                            StartRequest(handsFree=False, utterance=numberType)
                        ])
                    ]
                    lst.items.append(item)
                answer = plugin.getResponseForRequest(rootView)
                answer = getNumberTypeForName(answer, language)
                numberType = answer
                if numberType != None:
                    matches = filter(lambda x: x.label == numberType,
                                     person.phones)
                    if len(matches) == 1:
                        number = matches[0]
                    else:
                        plugin.say(text['errorNumberTypes'][language])
                else:
                    plugin.say(text['errorNumberTypes'][language])
    return number
    def received_plist(self, plist):
        self.logger.debug("Got packet with class: {0}".format(plist['class']))
        self.logger.debug("packet with content:\n{0}".format(
            pprint.pformat(plist, width=40)))

        # first handle speech stuff

        if 'refId' in plist:
            # if the following holds, this packet is an answer to a request by a plugin
            if plist[
                    '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.debug("Forwarding object to plugin")
                    self.plugin_lastAceId = None
                    self.current_running_plugin.response = plist if plist[
                        'class'] != "StartRequest" else plist['properties'][
                            'utterance']
                    self.current_running_plugin.waitForResponse.set()
                    return

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

            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(plist, SpeechPacket):
            self.logger.debug("Decoding speech packet")
            speechPacket = SpeechPacket(plist)
            if speechPacket.refId in self.speech:
                (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)
            else:
                self.logger.debug(
                    "Got a speech packet that did not match any current request"
                )

        elif plist['class'] == 'StartCorrectedSpeechRequest':
            self.process_recognized_speech(
                {
                    u'hypotheses':
                    [{
                        'confidence': 1.0,
                        'utterance': plist['properties']['utterance']
                    }]
                }, plist['aceId'], False)

        elif ObjectIsCommand(plist, FinishSpeech):
            self.logger.debug("End of speech received")
            finishSpeech = FinishSpeech(plist)
            if finishSpeech.refId in self.speech:
                (decoder, encoder, dictation) = self.speech[finishSpeech.refId]
                if decoder:
                    decoder.destroy()
                flacBin = None
                if encoder:
                    encoder.finish()
                    flacBin = encoder.getBinary()
                    encoder.destroy()
                del self.speech[finishSpeech.refId]
                if flacBin != None:
                    self.logger.info("Sending flac to google for recognition")
                    try:
                        self.current_google_request = self.httpClient.make_google_request(
                            flacBin,
                            finishSpeech.refId,
                            dictation,
                            language=self.assistant.language,
                            allowCurses=True)
                    except (AttributeError, TypeError):
                        self.logger.warning(
                            "Unable to find language record for this assistant. Try turning Siri off and then back on."
                        )
                else:
                    self.logger.info("There was no speech")
            else:
                self.logger.debug(
                    "Got a finish speech packet that did not match any current request"
                )

        elif ObjectIsCommand(plist, CancelRequest):
            # this is probably called when we need to kill a plugin
            # wait for thread to finish a send
            self.logger.debug("Should cancel current request")
            cancelRequest = CancelRequest(plist)
            if cancelRequest.refId in self.speech:
                (decoder, encoder,
                 dictation) = self.speech[cancelRequest.refId]
                if decoder:
                    decoder.destroy()
                if encoder:
                    encoder.finish()
                    encoder.destroy()
                del self.speech[cancelRequest.refId]
            if self.current_google_request != None:
                self.current_google_request.cancel()
                # if a google request is running (follow up listening..., plugin might get killed there by user)
                if self.current_running_plugin != None:
                    if self.current_running_plugin.waitForResponse != None:
                        self.current_running_plugin._abortPluginRun()
                        self.current_running_plugin.waitForResponse.set()

            # if a plugin is running (processing, but not waiting for data from the device we kill it)
            if self.current_running_plugin != None:
                if self.current_running_plugin.waitForResponse == None:
                    self.current_running_plugin._abortPluginRun()

            self.send_object(CancelSucceeded(cancelRequest.aceId))

        elif ObjectIsCommand(plist, RollbackRequest):
            pass

        elif ObjectIsCommand(plist, SyncChunk):
            chunk = SyncChunk(plist)
            previous = self.syncAnchors[
                chunk.key] if chunk.key in self.syncAnchors else None
            if previous != None:
                if previous.generation != chunk.preGen:
                    chunkDenied = SyncChunkDenied(chunk.aceId)
                    self.send_object(chunkDenied)
                    return
            current = SyncAnchor()
            current.generation = chunk.postGen
            current.value = chunk.postGen
            current.validity = chunk.validity
            current.key = chunk.key
            self.syncAnchors[current.key] = current
            chunkAccepted = SyncChunkAccepted(chunk.aceId)
            chunkAccepted.current = current
            self.send_object(chunkAccepted)
            pass

        elif ObjectIsCommand(plist, GetSessionCertificate):
            getSessionCertificate = GetSessionCertificate(plist)
            sessionCA_DER = crypto.dump_certificate(crypto.FILETYPE_ASN1,
                                                    self.server.sessionCACert)
            sessionCert_DER = crypto.dump_certificate(crypto.FILETYPE_ASN1,
                                                      self.server.sessionCert)
            response = GetSessionCertificateResponse(
                getSessionCertificate.aceId, sessionCA_DER, sessionCert_DER)
            self.send_object(response)

        elif ObjectIsCommand(plist, CreateSessionInfoRequest):
            # how does a positive answer look like?
            createSessionInfoRequest = CreateSessionInfoRequest(plist)

            #success = CreateSessionInfoResponse(createSessionInfoRequest.aceId)
            #success.sessionInfo = biplist.Data("\x01\x02BLABLABLBALBALBALBALBALBALBALBA")
            #success.validityDuration = 9600

            #self.send_object(success)
            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":plist['aceId'], "group":"com.apple.ace.system"})

        elif ObjectIsCommand(plist, CreateAssistant):
            createAssistant = CreateAssistant(plist)
            #create a new assistant
            helper = Assistant()
            helper.assistantId = str.upper(str(uuid.uuid4()))
            helper.language = createAssistant.language
            helper.activationToken = createAssistant.activationToken
            helper.connectionType = createAssistant.connectionType
            helper.validationData = createAssistant.validationData
            c = self.dbConnection.cursor()
            noError = True
            try:
                c.execute(
                    "insert into assistants(assistantId, assistant) values (?,?)",
                    (helper.assistantId, helper))
                self.dbConnection.commit()
            except sqlite3.Error:
                noError = False
            c.close()
            if noError:
                self.assistant = helper
                assiCreatedCMD = AssistantCreated(createAssistant.aceId)
                assiCreatedCMD.assistantId = helper.assistantId
                assiCreatedCMD.speechId = str(uuid.uuid4())
                self.send_object(assiCreatedCMD)
            else:
                cmdFailed = CommandFailed(createAssistant.aceId)
                cmdFailed.reason = "Database Error"
                cmdFailed.errorCode = 2
                self.send_object(cmdFailed)

        elif ObjectIsCommand(plist, SetAssistantData):
            setAssistantData = SetAssistantData(plist)
            # fill assistant
            if self.assistant != None:
                try:
                    c = self.dbConnection.cursor()
                    assi_id = self.assistant.assistantId
                    self.assistant.initializeFromPlist(
                        setAssistantData.to_plist())
                    self.assistant.assistantId = assi_id
                    #Record the user firstName and nickName
                    try:
                        self.assistant.firstName = self.assistant.meCards[
                            0].firstName.encode("utf-8")
                    except:
                        self.assistant.firstName = u''
                    try:
                        self.assistant.nickName = self.assistant.meCards[
                            0].nickName.encode("utf-8")
                    except:
                        self.assistant.nickName = u''
                    #Done recording
                    c.execute(
                        "update assistants set assistant = ? where assistantId = ?",
                        (self.assistant, self.assistant.assistantId))
                    self.dbConnection.commit()
                    c.close()
                except:
                    cmdFailed = CommandFailed(setAssistantData.aceId)
                    cmdFailed.reason = "Database Error"
                    cmdFailed.errorCode = 2
                    self.send_object(cmdFailed)
                    self.logger.exception(
                        "Database Error on setting assistant data")
            else:
                cmdFailed = CommandFailed(setAssistantData.aceId)
                cmdFailed.reason = "Assistant to set data not found"
                cmdFailed.errorCode = 2
                self.send_object(cmdFailed)
                self.logger.warning(
                    "Trying to set assistant data without having a valid assistant"
                )

        elif ObjectIsCommand(plist, LoadAssistant):
            loadAssistant = LoadAssistant(plist)
            try:
                c = self.dbConnection.cursor()
                c.execute(
                    "select assistant from assistants where assistantId = ?",
                    (loadAssistant.assistantId, ))
                self.dbConnection.commit()
                result = c.fetchone()
                if result == None:
                    self.send_object(AssistantNotFound(loadAssistant.aceId))
                    self.logger.warning("Assistant not found in database!!")
                else:
                    self.assistant = result[0]
                    #update assistant from LoadAssistant
                    self.assistant.language = loadAssistant.language
                    self.assistant.connectionType = loadAssistant.connectionType

                    if self.assistant.language == '' or self.assistant.language == None:
                        self.logger.error(
                            "No language is set for this assistant")
                        c.execute(
                            "delete from assistants where assistantId = ?",
                            (plist['properties']['assistantId'], ))
                        self.dbConnection.commit()
                        cmdFailed = CommandFailed(loadAssistant.aceId)
                        cmdFailed.reason = "Database error Assistant not found or language settings"
                        cmdFailed.errorCode = 2
                        self.send_object(cmdFailed)
                    else:
                        loaded = AssistantLoaded(loadAssistant.aceId)
                        loaded.version = "20111216-32234-branches/telluride?cnxn=293552c2-8e11-4920-9131-5f5651ce244e"
                        loaded.requestSync = 0
                        try:
                            loaded.dataAnchor = self.assistant.anchor
                        except:
                            loaded.dataAnchor = "removed"
                        self.send_object(loaded)
                c.close()
            except:
                self.send_object(AssistantNotFound(loadAssistant.aceId))
                self.logger.warning("Database error on fetching assistant")

        elif ObjectIsCommand(plist, DestroyAssistant):
            destroyAssistant = DestroyAssistant(plist)
            try:
                c = self.dbConnection.cursor()
                c.execute("delete from assistants where assistantId = ?",
                          (plist['properties']['assistantId'], ))
                self.dbConnection.commit()
                c.close()
                destroyed = AssistantDestroyed(destroyAssistant.aceId)
                destroyed.assistantId = destroyAssistant.assistantId
                self.send_object(destroyed)
            except:
                self.send_object(AssistantNotFound(destroyAssistant.aceId))
                self.logger.error("Database error on deleting assistant")

        elif ObjectIsCommand(plist, StartRequest):
            startRequest = StartRequest(plist)
            #this should also be handeled by special plugins, so lets call the plugin handling stuff
            self.process_recognized_speech(
                {
                    'hypotheses': [{
                        'utterance': startRequest.utterance,
                        'confidence': 1.0
                    }]
                }, startRequest.aceId, False)
        pass
    def process_recognized_speech(self, googleJson, requestId, dictation):
        possible_matches = googleJson['hypotheses']
        if len(possible_matches) > 0:
            best_match = possible_matches[0]['utterance']
            best_match_confidence = possible_matches[0]['confidence']
            self.logger.info(
                u"Best matching result: \"{0}\" with a confidence of {1}%".
                format(best_match,
                       round(float(best_match_confidence) * 100, 2)))
            # construct a SpeechRecognized
            token = Token(best_match, 0, 0, 1000.0, True, True)
            interpretation = Interpretation([token])
            phrase = Phrase(lowConfidence=False,
                            interpretations=[interpretation])
            recognition = Recognition([phrase])
            recognized = SpeechRecognized(requestId, recognition)

            if not dictation:
                if self.current_running_plugin == None:
                    plugin = PluginManager.getPluginForImmediateExecution(
                        self.assistant.assistantId, best_match,
                        self.assistant.language,
                        (self.send_object, self.send_plist, self.assistant,
                         self.current_location))
                    if plugin != None:
                        plugin.refId = requestId
                        plugin.connection = self
                        self.current_running_plugin = plugin
                        self.send_object(recognized)
                        self.current_running_plugin.start()
                    else:
                        self.send_object(recognized)
                        view = UIAddViews(requestId)
                        errorText = SiriProtocolHandler.__not_recognized[
                            self.assistant.
                            language] if self.assistant.language in SiriProtocolHandler.__not_recognized else SiriProtocolHandler.__not_recognized[
                                "en-US"]
                        errorView = UIAssistantUtteranceView()
                        errorView.text = errorText.format(best_match)
                        errorView.speakableText = errorText.format(best_match)
                        view.views = [errorView]
                        websearchText = SiriProtocolHandler.__websearch[
                            self.assistant.
                            language] if self.assistant.language in SiriProtocolHandler.__websearch else SiriProtocolHandler.__websearch[
                                "en-US"]
                        button = UIButton()
                        button.text = websearchText
                        cmd = SendCommands()
                        cmd.commands = [
                            StartRequest(
                                utterance=
                                u"^webSearchQuery^=^{0}^^webSearchConfirmation^=^Yes^"
                                .format(best_match))
                        ]
                        button.commands = [cmd]
                        view.views.append(button)
                        self.send_object(view)
                        self.send_object(RequestCompleted(requestId))
                elif self.current_running_plugin.waitForResponse != None:
                    # do we need to send a speech recognized here? i.d.k
                    self.current_running_plugin.response = best_match
                    self.current_running_plugin.refId = requestId
                    self.current_running_plugin.waitForResponse.set()
                else:
                    self.send_object(recognized)
                    self.send_object(RequestCompleted(requestId))
            else:
                self.send_object(recognized)
                self.send_object(RequestCompleted(requestId))
예제 #6
0
    def findPhoneForNumberType(self, person, numberType, language):
        # first check if a specific number was already requested
        phoneToMessage = None
        if numberType != None:
            # try to find the phone that fits the numberType
            listToMessage = filter(lambda x: x.label == numberType,
                                   person.phones)
            if len(listToMessage) == 1:
                phoneToMessage = listToMessage[0]
        else:
            favPhones = filter(
                lambda y: y.favoriteVoice
                if hasattr(y, "favoriteVoice") else False, person.phones)
            if len(favPhones) == 1:
                phoneToMessage = favPhones[0]
        if phoneToMessage == None:
            # lets check if there is more than one number
            if len(person.phones) == 1:
                if numberType != None:
                    self.say(
                        errorNumberNotPresent.format(
                            numberTypesLocalized[numberType][language],
                            person.fullName))
                phoneToMessage = person.phones[0]
            else:
                # damn we need to ask the user which one he wants...
                if phoneToMessage == None:
                    root = UIAddViews(self.refId)
                    root.dialogPhase = root.DialogPhaseClarificationValue

                    utterance = UIAssistantUtteranceView()
                    utterance.dialogIdentifier = "ContactDataResolutionDucs#foundAmbiguousPhoneNumberForContact"
                    utterance.speakableText = utterance.text = responses[
                        'selectNumber'][language].format(person.fullName)
                    utterance.listenAfterSpeaking = True

                    root.views = [utterance]

                    lst = UIDisambiguationList()
                    lst.items = []
                    lst.speakableSelectionResponse = ""
                    lst.listenAfterSpeaking = True
                    lst.selectionResponse = ""
                    root.views.append(lst)
                    for phone in person.phones:
                        numberType = numberTypesLocalized[phone.label][
                            language] if phone.label in numberTypesLocalized else phone.label
                        item = UIListItem()
                        item.title = ""
                        item.text = u"{0}: {1}".format(numberType,
                                                       phone.number)
                        item.selectionText = item.text
                        item.speakableText = u"{0}, ".format(numberType)
                        item.object = phone
                        item.commands = [
                            SendCommands(commands=[
                                StartRequest(handsFree=False,
                                             utterance=numberType)
                            ])
                        ]
                        lst.items.append(item)

                    answer = self.getResponseForRequest(root)
                    numberType = self.getNumberTypeForName(answer, language)
                    if numberType != None:
                        matches = filter(lambda x: x.label == numberType,
                                         person.phones)
                        if len(matches) == 1:
                            phoneToMessage = matches[0]
                        else:
                            self.say(errorNumberTypes[language])
                    else:
                        self.say(errorNumberTypes[language])
        return phoneToMessage