| /* SSIP Guile interface */ |
| |
| /* Copyright (C) 2004 Brailcom, o.p.s. |
| |
| Author: Milan Zamazal <pdm@brailcom.org> |
| |
| COPYRIGHT NOTICE |
| |
| This program is free software; you can redistribute it and/or modify it |
| under the terms of the GNU Lesser General Public License as published by the Free |
| Software Foundation; either version 2.1, or (at your option) any later |
| version. |
| |
| This program is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License |
| for more details. |
| |
| You should have received a copy of the GNU Lesser General Public License |
| along with this program. If not, see <https://www.gnu.org/licenses/>. |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include <libguile.h> |
| #include <libspeechd.h> |
| |
| #include "gssip.h" |
| |
| #define ASSIGN_VAR(var, pos, checker, setter) \ |
| SCM_ASSERT (SCM_##checker##P (var), var, SCM_ARG##pos, FUNC_NAME); \ |
| c_##var = SCM_##setter (var) |
| #define ASSIGN_INT(var, pos) ASSIGN_VAR (var, pos, INUM, INUM) |
| #define ASSIGN_STRING(var, pos) ASSIGN_VAR (var, pos, STRING, STRING_CHARS) |
| #define ASSIGN_SYMBOL(var, pos) ASSIGN_VAR (var, pos, SYMBOL, SYMBOL_CHARS) |
| #define ASSIGN_CONNECTION() ASSIGN_INT (connection, 1); |
| #define ASSIGN_PRIORITY() c_priority = assign_priority (priority, FUNC_NAME) |
| |
| #define RETURN_SUCCESS(value) return ((value) ? SCM_BOOL_F : SCM_BOOL_T) |
| |
| static SPDPriority assign_priority(SCM priority, const char *func_name) |
| { |
| char *c_priority; |
| SCM_ASSERT(SCM_SYMBOLP(priority), priority, SCM_ARG3, func_name); |
| c_priority = SCM_SYMBOL_CHARS(priority); |
| |
| { |
| const int invalid_priority = -1000; |
| int int_priority = |
| ((!strcmp(c_priority, "important")) ? SPD_IMPORTANT |
| : (!strcmp(c_priority, "message")) ? SPD_MESSAGE |
| : (!strcmp(c_priority, "text")) ? SPD_TEXT |
| : (!strcmp(c_priority, "notification")) ? SPD_NOTIFICATION |
| : (!strcmp(c_priority, "progress")) ? SPD_PROGRESS |
| : invalid_priority); |
| if (int_priority == invalid_priority) |
| scm_wrong_type_arg(func_name, SCM_ARG3, priority); |
| return int_priority; |
| } |
| } |
| |
| /* SSIP connection opening/closing functions */ |
| |
| SCM_DEFINE(ssip_open, "%ssip-open", 3, 0, 0, |
| (SCM user, SCM client, SCM component), |
| "Open new SSIP connection and return its identifier.") |
| #define FUNC_NAME s_ssip_open |
| { |
| char *c_user, *c_client, *c_component; |
| ASSIGN_STRING(user, 1); |
| ASSIGN_STRING(client, 2); |
| ASSIGN_STRING(component, 3); |
| |
| { |
| int connection = spd_open(c_client, c_component, c_user); |
| return (connection ? SCM_MAKINUM(connection) : SCM_EOL); |
| } |
| } |
| |
| #undef FUNC_NAME |
| |
| SCM_DEFINE(ssip_close, "%ssip-close", 1, 0, 0, (SCM connection), |
| "Close the given SSIP connection.") |
| #define FUNC_NAME s_ssip_close |
| { |
| int c_connection; |
| ASSIGN_CONNECTION(); |
| |
| spd_close(c_connection); |
| |
| return SCM_UNSPECIFIED; |
| } |
| |
| #undef FUNC_NAME |
| |
| /* Speech output functions */ |
| |
| #define SSIP_OUTPUT_DECL(name, sname) \ |
| SCM_DEFINE (ssip_say_##name, "%ssip-say-" sname, 3, 0, 0, \ |
| (SCM connection, SCM text, SCM priority), \ |
| "Say " sname " on CONNECTION with PRIORITY and return whether it succeeded.") |
| #define SSIP_OUTPUT_BODY(spd_func) \ |
| { \ |
| int c_connection; \ |
| char *c_text; \ |
| SPDPriority c_priority; \ |
| ASSIGN_CONNECTION (); \ |
| ASSIGN_STRING (text, 2); \ |
| ASSIGN_PRIORITY (); \ |
| RETURN_SUCCESS (spd_func (c_connection, c_priority, c_text)); \ |
| } |
| |
| #define FUNC_NAME s_ssip_say_text |
| SSIP_OUTPUT_DECL(text, "text") |
| SSIP_OUTPUT_BODY(spd_say) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_say_character |
| SSIP_OUTPUT_DECL(character, "character") |
| SSIP_OUTPUT_BODY(spd_char) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_say_key |
| SSIP_OUTPUT_DECL(key, "key") |
| SSIP_OUTPUT_BODY(spd_key) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_say_icon |
| SSIP_OUTPUT_DECL(icon, "icon") |
| SSIP_OUTPUT_BODY(spd_sound_icon) |
| #undef FUNC_NAME |
| /* Speech output management functions */ |
| #define SSIP_CONTROL_DECL(name, sname) \ |
| SCM_DEFINE (ssip_##name, "%ssip-" sname, 2, 0, 0, \ |
| (SCM connection, SCM id), \ |
| sname "speaking and return whether it succeeded.") |
| #define SSIP_CONTROL_BODY(name) \ |
| { \ |
| int c_connection; \ |
| int result_code; \ |
| ASSIGN_CONNECTION (); \ |
| if (SCM_INUMP (id)) \ |
| result_code = spd_stop_uid (c_connection, SCM_INUM (id)); \ |
| else if (id == SCM_EOL) \ |
| result_code = spd_stop (c_connection); \ |
| else if (SCM_SYMBOLP (id) \ |
| && (! strcmp (SCM_SYMBOL_CHARS (id), "t"))) \ |
| result_code = spd_stop_all (c_connection); \ |
| else \ |
| scm_wrong_type_arg (FUNC_NAME, SCM_ARG2, id); \ |
| RETURN_SUCCESS (result_code); \ |
| } |
| #define FUNC_NAME s_ssip_stop |
| SSIP_CONTROL_DECL(stop, "stop") |
| SSIP_CONTROL_BODY(stop) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_cancel |
| SSIP_CONTROL_DECL(cancel, "cancel") |
| SSIP_CONTROL_BODY(cancel) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_pause |
| SSIP_CONTROL_DECL(pause, "pause") |
| SSIP_CONTROL_BODY(pause) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_resume |
| SSIP_CONTROL_DECL(resume, "resume") |
| SSIP_CONTROL_BODY(resume) |
| #undef FUNC_NAME |
| /* Speech parameters functions */ |
| #define SSIP_SET_DECL(name, sname) \ |
| SCM_DEFINE (ssip_set_##name, "%ssip-set-" sname, 2, 0, 0, \ |
| (SCM connection, SCM value), \ |
| "Set " sname " for CONNECTION.") |
| #define SSIP_PROCESS_SET_ARGS(type, type_f) \ |
| int c_connection; \ |
| type c_value; \ |
| ASSIGN_CONNECTION (); \ |
| ASSIGN_##type_f (value, 2); |
| #define SSIP_SET_STRING_BODY(name) \ |
| { \ |
| SSIP_PROCESS_SET_ARGS (char *, STRING); \ |
| RETURN_SUCCESS (spd_set_##name (c_connection, c_value)); \ |
| } |
| #define SSIP_SET_INT_BODY(name) \ |
| { \ |
| SSIP_PROCESS_SET_ARGS (int, INT); \ |
| SCM_ASSERT ((-100 <= c_value && c_value <= 100), value, SCM_ARG2, \ |
| FUNC_NAME); \ |
| RETURN_SUCCESS (spd_set_##name (c_connection, c_value)); \ |
| } |
| #define FUNC_NAME s_ssip_set_language |
| SSIP_SET_DECL(language, "language") |
| SSIP_SET_STRING_BODY(language) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_set_output_module |
| SSIP_SET_DECL(output_module, "output-module") |
| SSIP_SET_STRING_BODY(output_module) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_set_rate |
| SSIP_SET_DECL(rate, "rate") |
| SSIP_SET_INT_BODY(voice_rate) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_set_pitch |
| SSIP_SET_DECL(pitch, "pitch") |
| SSIP_SET_INT_BODY(voice_pitch) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_set_pitch_range |
| SSIP_SET_DECL(pitch_range, "pitch_range") |
| SSIP_SET_INT_BODY(voice_pitch_range) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_set_volume |
| SSIP_SET_DECL(volume, "volume") |
| SSIP_SET_INT_BODY(volume) |
| #undef FUNC_NAME |
| #define FUNC_NAME s_ssip_set_voice |
| SSIP_SET_DECL(voice, "voice") |
| { |
| SSIP_PROCESS_SET_ARGS(char *, STRING); |
| { |
| char *command; |
| int result_code; |
| |
| if (asprintf(&command, "SET self VOICE %s", c_value) < 0) |
| scm_memory_error(FUNC_NAME); |
| result_code = spd_execute_command(c_connection, command); |
| free(command); |
| RETURN_SUCCESS(result_code); |
| } |
| } |
| |
| #undef FUNC_NAME |
| |
| #define FUNC_NAME s_ssip_set_punctuation_mode |
| SSIP_SET_DECL(punctuation_mode, "punctuation-mode") |
| { |
| SSIP_PROCESS_SET_ARGS(char *, SYMBOL); |
| { |
| SPDPunctuation mode; |
| if (!strcmp(c_value, "none")) |
| mode = SPD_PUNCT_NONE; |
| else if (!strcmp(c_value, "some")) |
| mode = SPD_PUNCT_SOME; |
| else if (!strcmp(c_value, "most")) |
| mode = SPD_PUNCT_MOST; |
| else if (!strcmp(c_value, "all")) |
| mode = SPD_PUNCT_ALL; |
| else |
| scm_wrong_type_arg(FUNC_NAME, SCM_ARG2, value); |
| RETURN_SUCCESS(spd_set_punctuation(c_connection, mode)); |
| } |
| } |
| |
| #undef FUNC_NAME |
| |
| #define FUNC_NAME s_ssip_set_spelling_mode |
| SSIP_SET_DECL(spelling_mode, "spelling-mode") |
| { |
| SSIP_PROCESS_SET_ARGS(char *, SYMBOL); |
| { |
| SPDSpelling mode; |
| if (!strcmp(c_value, "on")) |
| mode = SPD_SPELL_ON; |
| else if (!strcmp(c_value, "off")) |
| mode = SPD_SPELL_OFF; |
| else |
| scm_wrong_type_arg(FUNC_NAME, SCM_ARG2, value); |
| RETURN_SUCCESS(spd_set_spelling(c_connection, mode)); |
| } |
| } |
| |
| #undef FUNC_NAME |
| |
| /* Raw SSIP commands */ |
| |
| SCM_DEFINE(ssip_raw_command, "%ssip-raw-command", 2, 0, 0, |
| (SCM connection, SCM command), |
| "Send raw COMMAND to CONNECTION and return whether it succeeded.") |
| #define FUNC_NAME s_ssip_raw_command |
| { |
| int c_connection; |
| char *c_command; |
| ASSIGN_CONNECTION(); |
| ASSIGN_STRING(command, 2); |
| |
| RETURN_SUCCESS(spd_execute_command(c_connection, c_command)); |
| } |
| |
| #undef FUNC_NAME |
| |
| /* Define the Scheme bindings */ |
| |
| void init_gssip() |
| { |
| #include "gssip.x" |
| } |