/* Use this function to set the current channel state without locking the * speech channel. Do this if you already have the speech channel locked. */ void speech_channel_set_state_unlocked(speech_channel_t *schannel, speech_channel_state_t state) { if (schannel != NULL) { /* Wake anyone waiting for audio data. */ if ((schannel->state == SPEECH_CHANNEL_PROCESSING) && (state != SPEECH_CHANNEL_PROCESSING)) audio_queue_clear(schannel->audio_queue); ast_log(LOG_DEBUG, "(%s) %s ==> %s\n", schannel->name, speech_channel_state_to_string(schannel->state), speech_channel_state_to_string(state)); schannel->state = state; if (schannel->cond != NULL) apr_thread_cond_signal(schannel->cond); } }
/* Receive a command from the client and execute it. */ static void handle_command (const int client_id) { int cmd; int err = 0; struct client *cli = &clients[client_id]; if (!get_int(cli->socket, &cmd)) { logit ("Failed to get command from the client"); close (cli->socket); del_client (cli); return; } switch (cmd) { case CMD_QUIT: logit ("Exit request from the client"); close (cli->socket); del_client (cli); server_quit = 1; break; case CMD_LIST_CLEAR: logit ("Clearing the list"); audio_plist_clear (); break; case CMD_LIST_ADD: if (!req_list_add(cli)) err = 1; break; case CMD_PLAY: if (!req_play(cli)) err = 1; break; case CMD_DISCONNECT: logit ("Client disconnected"); close (cli->socket); del_client (cli); break; case CMD_PAUSE: audio_pause (); break; case CMD_UNPAUSE: audio_unpause (); break; case CMD_STOP: audio_stop (); break; case CMD_GET_CTIME: if (!send_data_int(cli, MAX(0, audio_get_time()))) err = 1; break; case CMD_SEEK: if (!req_seek(cli)) err = 1; break; case CMD_JUMP_TO: if (!req_jump_to(cli)) err = 1; break; case CMD_GET_SNAME: if (!send_sname(cli)) err = 1; break; case CMD_GET_STATE: if (!send_data_int(cli, audio_get_state())) err = 1; break; case CMD_GET_BITRATE: if (!send_data_int(cli, sound_info.bitrate)) err = 1; break; case CMD_GET_AVG_BITRATE: if (!send_data_int(cli, sound_info.avg_bitrate)) err = 1; break; case CMD_GET_RATE: if (!send_data_int(cli, sound_info.rate)) err = 1; break; case CMD_GET_CHANNELS: if (!send_data_int(cli, sound_info.channels)) err = 1; break; case CMD_NEXT: audio_next (); break; case CMD_PREV: audio_prev (); break; case CMD_PING: if (!send_int(cli->socket, EV_PONG)) err = 1; break; case CMD_GET_OPTION: if (!send_option(cli)) err = 1; break; case CMD_SET_OPTION: if (!get_set_option(cli)) err = 1; break; case CMD_GET_MIXER: if (!send_data_int(cli, audio_get_mixer())) err = 1; break; case CMD_SET_MIXER: if (!set_mixer(cli)) err = 1; break; case CMD_DELETE: if (!delete_item(cli)) err = 1; break; case CMD_SEND_PLIST_EVENTS: cli->wants_plist_events = 1; logit ("Request for events"); break; case CMD_GET_PLIST: if (!get_client_plist(cli)) err = 1; break; case CMD_SEND_PLIST: if (!req_send_plist(cli)) err = 1; break; case CMD_CAN_SEND_PLIST: cli->can_send_plist = 1; break; case CMD_CLI_PLIST_ADD: case CMD_CLI_PLIST_DEL: case CMD_CLI_PLIST_CLEAR: case CMD_CLI_PLIST_MOVE: if (!plist_sync_cmd(cli, cmd)) err = 1; break; case CMD_LOCK: if (!client_lock(cli)) err = 1; break; case CMD_UNLOCK: if (!client_unlock(cli)) err = 1; break; case CMD_GET_SERIAL: if (!send_serial(cli)) err = 1; break; case CMD_PLIST_GET_SERIAL: if (!req_plist_get_serial(cli)) err = 1; break; case CMD_PLIST_SET_SERIAL: if (!req_plist_set_serial(cli)) err = 1; break; case CMD_GET_TAGS: if (!req_get_tags(cli)) err = 1; break; case CMD_TOGGLE_MIXER_CHANNEL: req_toggle_mixer_channel (); break; case CMD_TOGGLE_SOFTMIXER: req_toggle_softmixer (); break; case CMD_GET_MIXER_CHANNEL_NAME: if (!req_get_mixer_channel_name(cli)) err = 1; break; case CMD_GET_FILE_TAGS: if (!get_file_tags(client_id)) err = 1; break; case CMD_ABORT_TAGS_REQUESTS: if (!abort_tags_requests(client_id)) err = 1; break; case CMD_LIST_MOVE: if (!req_list_move(cli)) err = 1; break; case CMD_TOGGLE_EQUALIZER: req_toggle_equalizer(); break; case CMD_EQUALIZER_REFRESH: req_equalizer_refresh(); break; case CMD_EQUALIZER_PREV: req_equalizer_prev(); break; case CMD_EQUALIZER_NEXT: req_equalizer_next(); break; case CMD_TOGGLE_MAKE_MONO: req_toggle_make_mono(); break; case CMD_QUEUE_ADD: if (!req_queue_add(cli)) err = 1; break; case CMD_QUEUE_DEL: if (!req_queue_del(cli)) err = 1; break; case CMD_QUEUE_CLEAR: logit ("Clearing the queue"); audio_queue_clear (); add_event_all (EV_QUEUE_CLEAR, NULL); break; case CMD_QUEUE_MOVE: if (!req_queue_move(cli)) err = 1; break; case CMD_GET_QUEUE: if (!req_send_queue(cli)) err = 1; break; default: logit ("Bad command (0x%x) from the client", cmd); err = 1; } if (err) { logit ("Closing client connection due to error"); close (cli->socket); del_client (cli); } }
/* Send SPEAK request to synthesizer. */ static int synth_channel_speak(speech_channel_t *schannel, const char *content, const char *content_type, apr_hash_t *header_fields) { int status = 0; mrcp_message_t *mrcp_message = NULL; mrcp_generic_header_t *generic_header = NULL; mrcp_synth_header_t *synth_header = NULL; if (!schannel || !content || !content_type) { ast_log(LOG_ERROR, "synth_channel_speak: unknown channel error!\n"); return -1; } apr_thread_mutex_lock(schannel->mutex); if (schannel->state != SPEECH_CHANNEL_READY) { apr_thread_mutex_unlock(schannel->mutex); return -1; } if ((mrcp_message = mrcp_application_message_create(schannel->unimrcp_session, schannel->unimrcp_channel, SYNTHESIZER_SPEAK)) == NULL) { ast_log(LOG_ERROR, "(%s) Failed to create SPEAK message\n", schannel->name); apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Set generic header fields (content-type). */ if ((generic_header = (mrcp_generic_header_t *)mrcp_generic_header_prepare(mrcp_message)) == NULL) { apr_thread_mutex_unlock(schannel->mutex); return -1; } apt_string_assign(&generic_header->content_type, content_type, mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message, GENERIC_HEADER_CONTENT_TYPE); /* Set synthesizer header fields (voice, rate, etc.). */ if ((synth_header = (mrcp_synth_header_t *)mrcp_resource_header_prepare(mrcp_message)) == NULL) { apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Add params to MRCP message. */ speech_channel_set_params(schannel, mrcp_message, header_fields); /* Set body (plain text or SSML). */ apt_string_assign(&mrcp_message->body, content, schannel->pool); /* Empty audio queue and send SPEAK to MRCP server. */ audio_queue_clear(schannel->audio_queue); if (!mrcp_application_message_send(schannel->unimrcp_session, schannel->unimrcp_channel, mrcp_message)) { ast_log(LOG_ERROR,"(%s) Failed to send SPEAK message", schannel->name); apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Wait for IN PROGRESS. */ apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC); if (schannel->state != SPEECH_CHANNEL_PROCESSING) { apr_thread_mutex_unlock(schannel->mutex); return -1; } apr_thread_mutex_unlock(schannel->mutex); return status; }