/** Header section handler */ static apt_bool_t mrcp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context) { mrcp_message_t *mrcp_message = context->message; if(mrcp_message->start_line.version == MRCP_VERSION_2) { mrcp_resource_t *resource; mrcp_parser_t *mrcp_parser; if(mrcp_channel_id_parse(&mrcp_message->channel_id,&mrcp_message->header,mrcp_message->pool) == FALSE) { return FALSE; } mrcp_parser = apt_message_parser_object_get(parser); /* find resource */ resource = mrcp_resource_find(mrcp_parser->resource_factory,&mrcp_message->channel_id.resource_name); if(!resource) { return FALSE; } if(mrcp_message_resource_set(mrcp_message,resource) == FALSE) { return FALSE; } } if(mrcp_header_fields_parse(&mrcp_message->header,mrcp_message->pool) == FALSE) { return FALSE; } if(context->body && mrcp_generic_header_property_check(mrcp_message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) { mrcp_generic_header_t *generic_header = mrcp_generic_header_get(mrcp_message); if(generic_header && generic_header->content_length) { context->body->length = generic_header->content_length; } } return TRUE; }
static apt_bool_t recog_pending_requests_remove(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *request_message, mrcp_message_t *response_message) { apt_list_elem_t *elem; mrcp_message_t *pending_message; mrcp_request_id_list_t *request_id_list = NULL; mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request_message); mrcp_generic_header_t *response_generic_header = mrcp_generic_header_prepare(response_message); if(generic_header && mrcp_generic_header_property_check(request_message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) { if(generic_header->active_request_id_list.count) { /* selective STOP request */ request_id_list = &generic_header->active_request_id_list; } } elem = apt_list_first_elem_get(state_machine->queue); while(elem) { pending_message = apt_list_elem_object_get(elem); if(!request_id_list || active_request_id_list_find(generic_header,pending_message->start_line.request_id) == TRUE) { apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove Pending RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]", MRCP_MESSAGE_SIDRES(pending_message), pending_message->start_line.request_id); elem = apt_list_elem_remove(state_machine->queue,elem); /* append active id list */ active_request_id_list_append(response_generic_header,pending_message->start_line.request_id); } else { /* speak request remains in the queue, just proceed to the next one */ elem = apt_list_next_elem_get(state_machine->queue,elem); } } if(response_generic_header->active_request_id_list.count) { mrcp_generic_header_property_add(response_message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST); } return TRUE; }
static apt_bool_t recog_request_stop(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message) { mrcp_message_t *response_message; if(state_machine->state == RECOGNIZER_STATE_RECOGNIZING) { mrcp_request_id_list_t *request_id_list = NULL; mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message); if(generic_header && mrcp_generic_header_property_check(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) { if(generic_header->active_request_id_list.count) { /* selective STOP request */ request_id_list = &generic_header->active_request_id_list; } } if(!request_id_list || active_request_id_list_find(generic_header,state_machine->recog->start_line.request_id) == TRUE) { /* found in-progress RECOGNIZE request, stop it */ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Found IN-PROGRESS RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]", MRCP_MESSAGE_SIDRES(message), message->start_line.request_id); return recog_request_dispatch(state_machine,message); } } else if(state_machine->state == RECOGNIZER_STATE_RECOGNIZED) { recog_state_change(state_machine,RECOGNIZER_STATE_IDLE,message); } /* found no in-progress RECOGNIZE request, sending immediate response */ response_message = mrcp_response_create(message,message->pool); recog_pending_requests_remove(state_machine,message,response_message); return recog_response_dispatch(state_machine,response_message); }
/** Process SPEAK request */ static apt_bool_t demo_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { char *file_path; demo_synth_channel_t *synth_channel = channel->method_obj; synth_channel->time_to_complete = 0; file_path = apt_datadir_filepath_get(channel->engine->dir_layout,DEMO_SPEECH_SOURCE_FILE,channel->pool); if(file_path) { synth_channel->audio_file = fopen(file_path,"rb"); if(synth_channel->audio_file) { apt_log(APT_PRIO_INFO,"Set [%s] as Speech Source",file_path); } else { apt_log(APT_PRIO_INFO,"No Speech Source [%s] Found",file_path); /* calculate estimated time to complete */ if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) { mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request); if(generic_header) { synth_channel->time_to_complete = generic_header->content_length * 10; /* 10 msec per character */ } } } } response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS; /* send asynchronous response */ mrcp_engine_channel_message_send(channel,response); synth_channel->speak_request = request; return TRUE; }
static apt_bool_t synth_request_stop(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message) { mrcp_message_t *response_message; if(state_machine->speaker) { mrcp_request_id_list_t *request_id_list = NULL; mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message); if(generic_header && mrcp_generic_header_property_check(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) { if(generic_header->active_request_id_list.ids && generic_header->active_request_id_list.count) { /* selective STOP request */ request_id_list = &generic_header->active_request_id_list; } } if(!request_id_list || active_request_id_list_find(generic_header,state_machine->speaker->start_line.request_id) == TRUE) { /* found in-progress SPEAK request, stop it */ apt_log(APT_PRIO_INFO,"Process STOP Request [%d]",message->start_line.request_id); return synth_request_dispatch(state_machine,message); } } /* found no in-progress SPEAK request, sending immediate response */ response_message = mrcp_response_create(message,message->pool); synth_pending_requests_remove(state_machine,message,response_message); return synth_response_dispatch(state_machine,response_message); }
/** Generate MRCP message-body */ static mrcp_stream_result_e mrcp_message_body_generate(mrcp_message_t *message, apt_text_stream_t *stream) { if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) { mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message); if(generic_header && generic_header->content_length) { apt_str_t *body = &message->body; body->length = 0; return mrcp_message_body_write(message,stream); } } return MRCP_STREAM_MESSAGE_COMPLETE; }
/** Set Swift port params */ static apt_bool_t mrcp_swift_channel_params_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message) { const char *name; mrcp_synth_header_t *synth_header = mrcp_resource_header_get(message); mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message); if(synth_header) { if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_PROSODY_VOLUME) == TRUE) { int volume = 0; if(swift_prosody_volume_get(&synth_header->prosody_param.volume,&volume) == TRUE) { name = "audio/volume"; apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%d",name,volume); mrcp_swift_channel_param_set(synth_channel,name,swift_val_int(volume)); } } if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_PROSODY_RATE) == TRUE) { int rate = 0; if(swift_prosody_rate_get(&synth_header->prosody_param.rate,&rate) == TRUE) { name = "speech/rate"; apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%d",name,rate); mrcp_swift_channel_param_set(synth_channel,name,swift_val_int(rate)); } } } if(generic_header) { if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_TYPE) == TRUE) { name = "tts/content-type"; apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%s",name,generic_header->content_type); mrcp_swift_channel_param_set(synth_channel,name,swift_val_string(generic_header->content_type.buf)); } if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_ENCODING) == TRUE) { name = "tts/text-encoding"; apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%s",name,generic_header->content_encoding); mrcp_swift_channel_param_set(synth_channel,name,swift_val_string(generic_header->content_encoding.buf)); } } return TRUE; }
/* Test SPEAK request */ static apt_bool_t speak_request_test(mrcp_resource_factory_t *factory, mrcp_message_t *message) { apt_bool_t res; mrcp_generic_header_t *generic_header; mrcp_synth_header_t *synth_header; apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Test SPEAK Request"); res = FALSE; /* get generic header */ generic_header = mrcp_generic_header_get(message); if(generic_header) { /* test content type header */ if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_TYPE) == TRUE) { if(strncasecmp(generic_header->content_type.buf,SAMPLE_CONTENT_TYPE,generic_header->content_type.length) == 0) { /* OK */ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get Content-Type: %s",generic_header->content_type.buf); res = TRUE; } } } if(res == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Test Generic Header"); return FALSE; } res = FALSE; /* get synthesizer header */ synth_header = mrcp_resource_header_get(message); if(synth_header) { /* test voice age header */ if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) { if(synth_header->voice_param.age == SAMPLE_VOICE_AGE) { /* OK */ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get Voice-Age: %"APR_SIZE_T_FMT,synth_header->voice_param.age); res = TRUE; } } } if(res == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Test Synthesizer Header"); return FALSE; } if(strncasecmp(message->body.buf,SAMPLE_CONTENT,message->body.length) != 0) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Test Message Body"); return FALSE; } apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get Body: %s",message->body.buf); return TRUE; }
/** Parse MRCP message-body */ MRCP_DECLARE(apt_bool_t) mrcp_body_parse(mrcp_message_t *message, apt_text_stream_t *text_stream, apr_pool_t *pool) { if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) { mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message); if(generic_header && generic_header->content_length) { apt_str_t *body = &message->body; body->length = generic_header->content_length; if(body->length > (text_stream->text.length - (text_stream->pos - text_stream->text.buf))) { body->length = text_stream->text.length - (text_stream->pos - text_stream->text.buf); } body->buf = apr_pstrmemdup(pool,text_stream->pos,body->length); text_stream->pos += body->length; } } return TRUE; }
/** Validate MRCP message */ MRCP_DECLARE(apt_bool_t) mrcp_message_validate(mrcp_message_t *message) { if(message->body.length) { /* content length must be specified */ mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message); if(!generic_header) { return FALSE; } if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) != TRUE || !generic_header->content_length) { generic_header->content_length = message->body.length; mrcp_generic_header_property_add(message,GENERIC_HEADER_CONTENT_LENGTH); } } return TRUE; }
/** Process SPEAK request */ static apt_bool_t demo_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { char *file_path = NULL; demo_synth_channel_t *synth_channel = channel->method_obj; const mpf_codec_descriptor_t *descriptor = mrcp_engine_source_stream_codec_get(channel); if(!descriptor) { apt_log(SYNTH_LOG_MARK,APT_PRIO_WARNING,"Failed to Get Codec Descriptor "APT_SIDRES_FMT, MRCP_MESSAGE_SIDRES(request)); response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED; return FALSE; } synth_channel->time_to_complete = 0; if(channel->engine) { char *file_name = apr_psprintf(channel->pool,"demo-%dkHz.pcm",descriptor->sampling_rate/1000); file_path = apt_datadir_filepath_get(channel->engine->dir_layout,file_name,channel->pool); } if(file_path) { synth_channel->audio_file = fopen(file_path,"rb"); if(synth_channel->audio_file) { apt_log(SYNTH_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source "APT_SIDRES_FMT, file_path, MRCP_MESSAGE_SIDRES(request)); } else { apt_log(SYNTH_LOG_MARK,APT_PRIO_INFO,"No Speech Source [%s] Found "APT_SIDRES_FMT, file_path, MRCP_MESSAGE_SIDRES(request)); /* calculate estimated time to complete */ if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) { mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request); if(generic_header) { synth_channel->time_to_complete = generic_header->content_length * 10; /* 10 msec per character */ } } } } response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS; /* send asynchronous response */ mrcp_engine_channel_message_send(channel,response); synth_channel->speak_request = request; return TRUE; }
/* Create GET-PARAMS response */ static mrcp_message_t* get_params_response_create(mrcp_resource_factory_t *factory, mrcp_message_t *request) { apt_bool_t res; mrcp_message_t *response; apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create GET-PARAMS Response"); response = mrcp_response_create(request,request->pool); if(response) { mrcp_generic_header_t *generic_header; mrcp_synth_header_t *synth_header; res = FALSE; /* get generic header */ generic_header = mrcp_generic_header_get(request); if(generic_header) { mrcp_generic_header_t *res_generic_header = mrcp_generic_header_prepare(response); /* test content id header */ if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_ID) == TRUE) { apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Content-ID: %s",SAMPLE_CONTENT_ID); apt_string_assign(&res_generic_header->content_id,SAMPLE_CONTENT_ID,response->pool); mrcp_generic_header_property_add(response,GENERIC_HEADER_CONTENT_ID); res = TRUE; } /* test vendor specific header */ if(mrcp_generic_header_property_check(request,GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS) == TRUE) { apt_str_t name; const apt_pair_t *pair; res_generic_header->vendor_specific_params = apt_pair_array_create(1,response->pool); apt_string_set(&name,SAMPLE_PARAM_NAME); pair = apt_pair_array_find(generic_header->vendor_specific_params,&name); if(pair) { apt_str_t value; apt_string_set(&value,SAMPLE_PARAM_VALUE); apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Vendor-Specific-Params: %s=%s",name.buf,value.buf); apt_pair_array_append(res_generic_header->vendor_specific_params,&name,&value,response->pool); } mrcp_generic_header_property_add(response,GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS); res = TRUE; } } if(res == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Test Generic Header"); return NULL; } res = FALSE; /* get synthesizer header */ synth_header = mrcp_resource_header_get(request); if(synth_header) { mrcp_synth_header_t *res_synth_header = mrcp_resource_header_prepare(response); /* test voice age header */ if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) { res_synth_header->voice_param.age = SAMPLE_VOICE_AGE; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Voice-Age: %"APR_SIZE_T_FMT,res_synth_header->voice_param.age); mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_VOICE_AGE); res = TRUE; } } if(res == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Test Synthesizer Header"); return NULL; } } return response; }