diff options
Diffstat (limited to 'navit/speech/cmdline/speech_cmdline.c')
-rw-r--r-- | navit/speech/cmdline/speech_cmdline.c | 378 |
1 files changed, 187 insertions, 191 deletions
diff --git a/navit/speech/cmdline/speech_cmdline.c b/navit/speech/cmdline/speech_cmdline.c index 15ba15c1a..6d572d170 100644 --- a/navit/speech/cmdline/speech_cmdline.c +++ b/navit/speech/cmdline/speech_cmdline.c @@ -38,219 +38,215 @@ #endif -static char *urldecode(char *str) -{ - char *ret=g_strdup(str); - char *src=ret; - char *dst=ret; - while (*src) { - if (*src == '%') { - int val; - if (sscanf(src+1,"%02x",&val)) { - src+=2; - *dst++=val; - } - src++; - } else - *dst++=*src++; - } - *dst++='\0'; - return ret; +static char *urldecode(char *str) { + char *ret=g_strdup(str); + char *src=ret; + char *dst=ret; + while (*src) { + if (*src == '%') { + int val; + if (sscanf(src+1,"%02x",&val)) { + src+=2; + *dst++=val; + } + src++; + } else + *dst++=*src++; + } + *dst++='\0'; + return ret; } static GList * -speech_cmdline_search(GList *samples, int suffix_len, const char *text, int decode) -{ - GList *loop_samples=samples,*result=NULL,*recursion_result; - int shortest_result_length=INT_MAX; - dbg(lvl_debug,"searching samples for text: '%s'",text); - while (loop_samples) { - char *sample_name=loop_samples->data; - int sample_name_len; - if (decode) - sample_name=urldecode(sample_name); - sample_name_len=strlen(sample_name)-suffix_len; - // TODO: Here we compare UTF-8 text with a filename. - // It's unclear how a case-insensitive comparison should work - // in general, so for now we only do it for ASCII text. - if (!g_ascii_strncasecmp(text, sample_name, sample_name_len)) { - const char *remaining_text=text+sample_name_len; - while (*remaining_text == ' ' || *remaining_text == ',') - remaining_text++; - dbg(lvl_debug,"sample '%s' matched; remaining text: '%s'",sample_name,remaining_text); - if (*remaining_text) { - recursion_result=speech_cmdline_search(samples, suffix_len, remaining_text, decode); - if (recursion_result && g_list_length(recursion_result) < shortest_result_length) { - g_list_free(result); - result=recursion_result; - result=g_list_prepend(result, loop_samples->data); - shortest_result_length=g_list_length(result); - } else { - dbg(lvl_debug,"no (shorter) result found for remaining text '%s', " - "trying next sample\n", remaining_text); - g_list_free(recursion_result); - } - } else { - g_list_free(result); - result=g_list_prepend(NULL, loop_samples->data); - break; - } - } - if (decode) - g_free(sample_name); - loop_samples=g_list_next(loop_samples); - } - return result; +speech_cmdline_search(GList *samples, int suffix_len, const char *text, int decode) { + GList *loop_samples=samples,*result=NULL,*recursion_result; + int shortest_result_length=INT_MAX; + dbg(lvl_debug,"searching samples for text: '%s'",text); + while (loop_samples) { + char *sample_name=loop_samples->data; + int sample_name_len; + if (decode) + sample_name=urldecode(sample_name); + sample_name_len=strlen(sample_name)-suffix_len; + // TODO: Here we compare UTF-8 text with a filename. + // It's unclear how a case-insensitive comparison should work + // in general, so for now we only do it for ASCII text. + if (!g_ascii_strncasecmp(text, sample_name, sample_name_len)) { + const char *remaining_text=text+sample_name_len; + while (*remaining_text == ' ' || *remaining_text == ',') + remaining_text++; + dbg(lvl_debug,"sample '%s' matched; remaining text: '%s'",sample_name,remaining_text); + if (*remaining_text) { + recursion_result=speech_cmdline_search(samples, suffix_len, remaining_text, decode); + if (recursion_result && g_list_length(recursion_result) < shortest_result_length) { + g_list_free(result); + result=recursion_result; + result=g_list_prepend(result, loop_samples->data); + shortest_result_length=g_list_length(result); + } else { + dbg(lvl_debug,"no (shorter) result found for remaining text '%s', " + "trying next sample\n", remaining_text); + g_list_free(recursion_result); + } + } else { + g_list_free(result); + result=g_list_prepend(NULL, loop_samples->data); + break; + } + } + if (decode) + g_free(sample_name); + loop_samples=g_list_next(loop_samples); + } + return result; } struct speech_priv { - char *cmdline; - char *sample_dir; - char *sample_suffix; - int flags; - GList *samples; - struct spawn_process_info *spi; + char *cmdline; + char *sample_dir; + char *sample_suffix; + int flags; + GList *samples; + struct spawn_process_info *spi; }; -static int -speechd_say(struct speech_priv *this, const char *text) -{ - char **cmdv=g_strsplit(this->cmdline," ", -1); - int variable_arg_no=-1; - GList *argl=NULL; - guint listlen; - int samplesmode=0; - int i; - - for(i=0;cmdv[i];i++) - if(strchr(cmdv[i],'%')) { - variable_arg_no=i; - break; - } - - if (this->sample_dir && this->sample_suffix) { - argl=speech_cmdline_search(this->samples, strlen(this->sample_suffix), text, !!(this->flags & 1)); - samplesmode=1; - listlen=g_list_length(argl); - dbg(lvl_debug,"For text: '%s', found %d samples.",text,listlen); - if (!listlen){ - dbg(lvl_error,"No matching samples found. Cannot speak text: '%s'",text); - } - } else { - listlen=1; - } - if(listlen>0) { - dbg(lvl_debug,"Speaking text '%s'",text); - int argc; - char**argv; - int j; - int cmdvlen=g_strv_length(cmdv); - argc=cmdvlen + listlen - (variable_arg_no>0?1:0); - argv=g_new(char *,argc+1); - if(variable_arg_no==-1) { - argv[cmdvlen]=g_strdup("%s"); - variable_arg_no=cmdvlen; - } - - for(i=0,j=0;j<argc;) { - if( i==variable_arg_no ) { - if (samplesmode) { - GList *l=argl; - while(l) { - char *new_arg; - new_arg=g_strdup_printf("%s/%s",this->sample_dir,(char *)l->data); - dbg(lvl_debug,"new_arg %s",new_arg); - argv[j++]=g_strdup_printf(cmdv[i],new_arg); - g_free(new_arg); - l=g_list_next(l); - } - } else { - argv[j++]=g_strdup_printf(cmdv[i],text); - } - i++; - } else { - argv[j++]=g_strdup(cmdv[i++]); - } - } - argv[j]=NULL; - if (argl) - // No need to free data elements here as they are - // still referenced from this->samples - g_list_free(argl); +static int +speechd_say(struct speech_priv *this, const char *text) { + char **cmdv=g_strsplit(this->cmdline," ", -1); + int variable_arg_no=-1; + GList *argl=NULL; + guint listlen; + int samplesmode=0; + int i; - if(this->spi) { - spawn_process_check_status(this->spi,1); // Block until previous spawned speech process is terminated. - spawn_process_info_free(this->spi); - } - this->spi=spawn_process(argv); - g_strfreev(argv); - } - g_strfreev(cmdv); - return 0; + for(i=0; cmdv[i]; i++) + if(strchr(cmdv[i],'%')) { + variable_arg_no=i; + break; + } + + if (this->sample_dir && this->sample_suffix) { + argl=speech_cmdline_search(this->samples, strlen(this->sample_suffix), text, !!(this->flags & 1)); + samplesmode=1; + listlen=g_list_length(argl); + dbg(lvl_debug,"For text: '%s', found %d samples.",text,listlen); + if (!listlen) { + dbg(lvl_error,"No matching samples found. Cannot speak text: '%s'",text); + } + } else { + listlen=1; + } + if(listlen>0) { + dbg(lvl_debug,"Speaking text '%s'",text); + int argc; + char**argv; + int j; + int cmdvlen=g_strv_length(cmdv); + argc=cmdvlen + listlen - (variable_arg_no>0?1:0); + argv=g_new(char *,argc+1); + if(variable_arg_no==-1) { + argv[cmdvlen]=g_strdup("%s"); + variable_arg_no=cmdvlen; + } + + for(i=0,j=0; j<argc;) { + if( i==variable_arg_no ) { + if (samplesmode) { + GList *l=argl; + while(l) { + char *new_arg; + new_arg=g_strdup_printf("%s/%s",this->sample_dir,(char *)l->data); + dbg(lvl_debug,"new_arg %s",new_arg); + argv[j++]=g_strdup_printf(cmdv[i],new_arg); + g_free(new_arg); + l=g_list_next(l); + } + } else { + argv[j++]=g_strdup_printf(cmdv[i],text); + } + i++; + } else { + argv[j++]=g_strdup(cmdv[i++]); + } + } + argv[j]=NULL; + if (argl) + // No need to free data elements here as they are + // still referenced from this->samples + g_list_free(argl); + + if(this->spi) { + spawn_process_check_status(this->spi,1); // Block until previous spawned speech process is terminated. + spawn_process_info_free(this->spi); + } + this->spi=spawn_process(argv); + g_strfreev(argv); + } + g_strfreev(cmdv); + return 0; } -static void +static void speechd_destroy(struct speech_priv *this) { - GList *l=this->samples; - g_free(this->cmdline); - g_free(this->sample_dir); - g_free(this->sample_suffix); - while(l) { - g_free(l->data); - } - g_list_free(this->samples); - if(this->spi) - spawn_process_info_free(this->spi); - g_free(this); + GList *l=this->samples; + g_free(this->cmdline); + g_free(this->sample_dir); + g_free(this->sample_suffix); + while(l) { + g_free(l->data); + } + g_list_free(this->samples); + if(this->spi) + spawn_process_info_free(this->spi); + g_free(this); } static struct speech_methods speechd_meth = { - speechd_destroy, - speechd_say, + speechd_destroy, + speechd_say, }; static struct speech_priv * speechd_new(struct speech_methods *meth, struct attr **attrs, struct attr *parent) { - struct speech_priv *this; - struct attr *attr; - attr=attr_search(attrs, NULL, attr_data); - if (! attr) - return NULL; - this=g_new0(struct speech_priv,1); - this->cmdline=g_strdup(attr->u.str); - if ((attr=attr_search(attrs, NULL, attr_sample_dir))) - this->sample_dir=g_strdup(attr->u.str); - if ((attr=attr_search(attrs, NULL, attr_sample_suffix))) - this->sample_suffix=g_strdup(attr->u.str); - if ((attr=attr_search(attrs, NULL, attr_flags))) - this->flags=attr->u.num; - if (this->sample_dir && this->sample_suffix) { - void *handle=file_opendir(this->sample_dir); - if (!handle) { - dbg(lvl_error,"Cannot read sample directory contents: %s", this->sample_dir); - return NULL; - } - char *name; - int suffix_len=strlen(this->sample_suffix); - while((name=file_readdir(handle))) { - int len=strlen(name); - if (len > suffix_len) { - if (!strcmp(name+len-suffix_len, this->sample_suffix)) { - dbg(lvl_debug,"found %s",name); - this->samples=g_list_prepend(this->samples, g_strdup(name)); - } - } - } - file_closedir(handle); - } - *meth=speechd_meth; - return this; + struct speech_priv *this; + struct attr *attr; + attr=attr_search(attrs, NULL, attr_data); + if (! attr) + return NULL; + this=g_new0(struct speech_priv,1); + this->cmdline=g_strdup(attr->u.str); + if ((attr=attr_search(attrs, NULL, attr_sample_dir))) + this->sample_dir=g_strdup(attr->u.str); + if ((attr=attr_search(attrs, NULL, attr_sample_suffix))) + this->sample_suffix=g_strdup(attr->u.str); + if ((attr=attr_search(attrs, NULL, attr_flags))) + this->flags=attr->u.num; + if (this->sample_dir && this->sample_suffix) { + void *handle=file_opendir(this->sample_dir); + if (!handle) { + dbg(lvl_error,"Cannot read sample directory contents: %s", this->sample_dir); + return NULL; + } + char *name; + int suffix_len=strlen(this->sample_suffix); + while((name=file_readdir(handle))) { + int len=strlen(name); + if (len > suffix_len) { + if (!strcmp(name+len-suffix_len, this->sample_suffix)) { + dbg(lvl_debug,"found %s",name); + this->samples=g_list_prepend(this->samples, g_strdup(name)); + } + } + } + file_closedir(handle); + } + *meth=speechd_meth; + return this; } void -plugin_init(void) -{ - plugin_register_category_speech("cmdline", speechd_new); +plugin_init(void) { + plugin_register_category_speech("cmdline", speechd_new); } |