static ssize_t softsynth_read(struct file *fp, char *buf, size_t count, loff_t *pos) { int chars_sent = 0; char *cp; char *init; char ch; int empty; unsigned long flags; DEFINE_WAIT(wait); spk_lock(flags); while (1) { prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE); if (!synth_buffer_empty() || speakup_info.flushing) break; spk_unlock(flags); if (fp->f_flags & O_NONBLOCK) { finish_wait(&speakup_event, &wait); return -EAGAIN; } if (signal_pending(current)) { finish_wait(&speakup_event, &wait); return -ERESTARTSYS; } schedule(); spk_lock(flags); } finish_wait(&speakup_event, &wait); cp = buf; init = get_initstring(); while (chars_sent < count) { if (speakup_info.flushing) { speakup_info.flushing = 0; ch = '\x18'; } else if (synth_buffer_empty()) { break; } else if (init[init_pos]) { ch = init[init_pos++]; } else { ch = synth_buffer_getc(); } spk_unlock(flags); if (copy_to_user(cp, &ch, 1)) return -EFAULT; spk_lock(flags); chars_sent++; cp++; } *pos += chars_sent; empty = synth_buffer_empty(); spk_unlock(flags); if (empty) { speakup_start_ttys(); *pos = 0; } return chars_sent; }
static void do_catch_up(struct spk_synth *synth) { u_char ch; unsigned long flags; unsigned long jiff_max; struct var_t *jiffy_delta; struct var_t *delay_time; int jiffy_delta_val; int delay_time_val; jiffy_delta = get_var(JIFFY); delay_time = get_var(DELAY); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } set_current_state(TASK_INTERRUPTIBLE); delay_time_val = delay_time->u.n.value; spk_unlock(flags); if (synth_full()) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } set_current_state(TASK_RUNNING); spk_lock(flags); ch = synth_buffer_getc(); spk_unlock(flags); if (ch == '\n') ch = PROCSPEECH; spk_out(ch); if ((jiffies >= jiff_max) && (ch == SPACE)) { spk_out(PROCSPEECH); spk_lock(flags); delay_time_val = delay_time->u.n.value; jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); schedule_timeout(msecs_to_jiffies(delay_time_val)); jiff_max = jiffies + jiffy_delta_val; } } spk_out(PROCSPEECH); }
/* * This is called when a user reads the keymap parameter. */ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { char *cp = buf; int i; int n; int num_keys; int nstates; u_char *cp1; u_char ch; unsigned long flags; spk_lock(flags); cp1 = key_buf + SHIFT_TBL_SIZE; num_keys = (int)(*cp1); nstates = (int)cp1[1]; cp += sprintf(cp, "%d, %d, %d,\n", KEY_MAP_VER, num_keys, nstates); cp1 += 2; /* now pointing at shift states */ /* dump num_keys+1 as first row is shift states + flags, * each subsequent row is key + states */ for (n = 0; n <= num_keys; n++) { for (i = 0; i <= nstates; i++) { ch = *cp1++; cp += sprintf(cp, "%d,", (int)ch); *cp++ = (i < nstates) ? SPACE : '\n'; } } cp += sprintf(cp, "0, %d\n", KEY_MAP_VER); spk_unlock(flags); return (int)(cp-buf); }
/* * This is called when a user changes the value of the silent parameter. */ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int len; struct vc_data *vc = vc_cons[fg_console].d; char ch = 0; char shut; unsigned long flags; len = strlen(buf); if (len > 0 && len < 3) { ch = buf[0]; if (ch == '\n') ch = '0'; } if (ch < '0' || ch > '7') { pr_warn("silent value '%c' not in range (0,7)\n", ch); return -EINVAL; } spk_lock(flags); if (ch&2) { shut = 1; do_flush(); } else { shut = 0; } if (ch&4) shut |= 0x40; if (ch&1) spk_shut_up |= shut; else spk_shut_up &= ~shut; spk_unlock(flags); return count; }
static int softsynth_close(struct inode *inode, struct file *fp) { unsigned long flags; spk_lock(flags); synth_soft.alive = 0; initialized = 0; spk_unlock(flags); /* */ speakup_start_ttys(); return 0; }
static int softsynth_close(struct inode *inode, struct file *fp) { unsigned long flags; spk_lock(flags); synth_soft.alive = 0; init_pos = 0; spk_unlock(flags); /* Make sure we let applications go before leaving */ speakup_start_ttys(); return 0; }
/* * This is called when a user changes the keymap parameter. */ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int i; ssize_t ret = count; char *in_buff = NULL; char *cp; u_char *cp1; unsigned long flags; spk_lock(flags); <<<<<<< HEAD
static ssize_t message_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { ssize_t retval = 0; struct msg_group_t *group = find_msg_group(attr->attr.name); unsigned long flags; BUG_ON(!group); spk_lock(flags); retval = message_show_helper(buf, group->start, group->end); spk_unlock(flags); return retval; }
static unsigned int softsynth_poll(struct file *fp, struct poll_table_struct *wait) { unsigned long flags; int ret = 0; poll_wait(fp, &speakup_event, wait); spk_lock(flags); if (!synth_buffer_empty() || speakup_info.flushing) ret = POLLIN | POLLRDNORM; spk_unlock(flags); return ret; }
static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) { unsigned long flags; int c; spk_lock(flags); while (inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR) { c = inb_p(speakup_info.port_tts+UART_RX); synth->read_buff_add((u_char) c); } spk_unlock(flags); return IRQ_HANDLED; }
/* * This function is called when a user reads one of the variable parameters. */ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int rv = 0; struct st_var_header *param; struct var_t *var; char *cp1; char *cp; char ch; unsigned long flags; param = var_header_by_name(attr->attr.name); if (param == NULL) return -EINVAL; spk_lock(flags); var = (struct var_t *) param->data; switch (param->var_type) { case VAR_NUM: case VAR_TIME: if (var) rv = sprintf(buf, "%i\n", var->u.n.value); else rv = sprintf(buf, "0\n"); break; case VAR_STRING: if (var) { cp1 = buf; *cp1++ = '"'; for (cp = (char *)param->p_val; (ch = *cp); cp++) { if (ch >= ' ' && ch < '~') *cp1++ = ch; else cp1 += sprintf(cp1, "\\""x%02x", ch); } *cp1++ = '"'; *cp1++ = '\n'; *cp1 = '\0'; rv = cp1-buf; } else { rv = sprintf(buf, "\"\"\n"); } break; default: rv = sprintf(buf, "Bad parameter %s, type %i\n", param->name, param->var_type); break; } spk_unlock(flags); return rv; }
static int softsynth_open(struct inode *inode, struct file *fp) { unsigned long flags; /* */ /* */ spk_lock(flags); if (synth_soft.alive) { spk_unlock(flags); return -EBUSY; } synth_soft.alive = 1; spk_unlock(flags); return 0; }
static int softsynth_open(struct inode *inode, struct file *fp) { unsigned long flags; /*if ((fp->f_flags & O_ACCMODE) != O_RDONLY) */ /* return -EPERM; */ spk_lock(flags); if (synth_soft.alive) { spk_unlock(flags); return -EBUSY; } synth_soft.alive = 1; spk_unlock(flags); return 0; }
int speakup_thread(void *data) { unsigned long flags; int should_break; struct bleep our_sound; our_sound.active = 0; our_sound.freq = 0; our_sound.jiffies = 0; mutex_lock(&spk_mutex); while (1) { DEFINE_WAIT(wait); while (1) { spk_lock(flags); our_sound = unprocessed_sound; unprocessed_sound.active = 0; prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE); should_break = kthread_should_stop() || our_sound.active || (synth && synth->catch_up && synth->alive && (speakup_info.flushing || !synth_buffer_empty())); spk_unlock(flags); if (should_break) break; mutex_unlock(&spk_mutex); schedule(); mutex_lock(&spk_mutex); } finish_wait(&speakup_event, &wait); if (kthread_should_stop()) break; if (our_sound.active) kd_mksound(our_sound.freq, our_sound.jiffies); if (synth && synth->catch_up && synth->alive) { /* It is up to the callee to take the lock, so that it * can sleep whenever it likes */ synth->catch_up(synth); } speakup_start_ttys(); } mutex_unlock(&spk_mutex); return 0; }
/* * This is called when a user reads the characters or chartab sys file. */ static ssize_t chars_chartab_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int i; int len = 0; char *cp; char *buf_pointer = buf; size_t bufsize = PAGE_SIZE; unsigned long flags; spk_lock(flags); *buf_pointer = '\0'; for (i = 0; i < 256; i++) { if (bufsize <= 1) break; if (strcmp("characters", attr->attr.name) == 0) { len = scnprintf(buf_pointer, bufsize, "%d\t%s\n", i, characters[i]); } else { /* show chartab entry */ if (IS_TYPE(i, B_CTL)) cp = "B_CTL"; else if (IS_TYPE(i, WDLM)) cp = "WDLM"; else if (IS_TYPE(i, A_PUNC)) cp = "A_PUNC"; else if (IS_TYPE(i, PUNC)) cp = "PUNC"; else if (IS_TYPE(i, NUM)) cp = "NUM"; else if (IS_TYPE(i, A_CAP)) cp = "A_CAP"; else if (IS_TYPE(i, ALPHA)) cp = "ALPHA"; else if (IS_TYPE(i, B_CAPSYM)) cp = "B_CAPSYM"; else if (IS_TYPE(i, B_SYM)) cp = "B_SYM"; else cp = "0"; len = scnprintf(buf_pointer, bufsize, "%d\t%s\n", i, cp); } bufsize -= len; buf_pointer += len; } spk_unlock(flags); return buf_pointer - buf; }
static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) { unsigned long flags; /*printk(KERN_ERR "in irq\n"); */ /*pr_warn("in IRQ\n"); */ int c; spk_lock(flags); while (inb_p(speakup_info.port_tts + UART_LSR) & UART_LSR_DR) { c = inb_p(speakup_info.port_tts+UART_RX); synth->read_buff_add((u_char) c); /*printk(KERN_ERR "c = %d\n", c); */ /*pr_warn("C = %d\n", c); */ } spk_unlock(flags); return IRQ_HANDLED; }
/* * This is called when a user changes the punctuation settings. */ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int x; struct st_var_header *p_header; struct punc_var_t *var; char punc_buf[100]; unsigned long flags; x = strlen(buf); if (x < 1 || x > 99) return -EINVAL; p_header = var_header_by_name(attr->attr.name); if (p_header == NULL) { pr_warn("p_header is null, attr->attr.name is %s\n", attr->attr.name); return -EINVAL; } var = get_punc_var(p_header->var_id); if (var == NULL) { pr_warn("var is null, p_header->var_id is %i\n", p_header->var_id); return -EINVAL; } strncpy(punc_buf, buf, x); while (x && punc_buf[x - 1] == '\n') x--; punc_buf[x] = '\0'; spk_lock(flags); if (*punc_buf == 'd' || *punc_buf == 'r') x = set_mask_bits(0, var->value, 3); else x = set_mask_bits(punc_buf, var->value, 3); spk_unlock(flags); return count; }
void synth_release(void) { struct var_t *var; unsigned long flags; if (synth == NULL) return; spk_lock(flags); pr_info("releasing synth %s\n", synth->name); synth->alive = 0; del_timer(&thread_timer); spk_unlock(flags); if (synth->attributes.name) sysfs_remove_group(speakup_kobj, &(synth->attributes)); for (var = synth->vars; var->var_id != MAXVARS; var++) speakup_unregister_var(var->var_id); stop_serial_interrupt(); synth->release(); synth = NULL; }
static ssize_t speakup_file_write(struct file *fp, const char *buffer, size_t nbytes, loff_t *ppos) { size_t count = nbytes; const char *ptr = buffer; size_t bytes; unsigned long flags; u_char buf[256]; if (synth == NULL) return -ENODEV; while (count > 0) { bytes = min(count, sizeof(buf)); if (copy_from_user(buf, ptr, bytes)) return -EFAULT; count -= bytes; ptr += bytes; spk_lock(flags); synth_write(buf, bytes); spk_unlock(flags); } return (ssize_t) nbytes; }
/* * This is called when a user reads the punctuation settings. */ static ssize_t punc_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int i; char *cp = buf; struct st_var_header *p_header; struct punc_var_t *var; struct st_bits_data *pb; short mask; unsigned long flags; p_header = var_header_by_name(attr->attr.name); if (p_header == NULL) { pr_warn("p_header is null, attr->attr.name is %s\n", attr->attr.name); return -EINVAL; } var = get_punc_var(p_header->var_id); if (var == NULL) { pr_warn("var is null, p_header->var_id is %i\n", p_header->var_id); return -EINVAL; } spk_lock(flags); pb = (struct st_bits_data *) &punc_info[var->value]; mask = pb->mask; for (i = 33; i < 128; i++) { if (!(spk_chartab[i]&mask)) continue; *cp++ = (char)i; } spk_unlock(flags); return cp-buf; }
static void do_catch_up(struct spk_synth *synth) { u_char ch; unsigned long flags; unsigned long jiff_max; int timeout; int delay_time_val; int jiffy_delta_val; int full_time_val; struct var_t *delay_time; struct var_t *full_time; struct var_t *jiffy_delta; jiffy_delta = spk_get_var(JIFFY); delay_time = spk_get_var(DELAY); full_time = spk_get_var(FULL); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } set_current_state(TASK_INTERRUPTIBLE); full_time_val = full_time->u.n.value; spk_unlock(flags); if (synth_full()) { schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } set_current_state(TASK_RUNNING); timeout = SPK_XMITR_TIMEOUT; while (synth_writable()) { if (!--timeout) break; udelay(1); } spk_lock(flags); ch = synth_buffer_getc(); spk_unlock(flags); if (ch == '\n') ch = PROCSPEECH; outb_p(ch, speakup_info.port_tts); if (jiffies >= jiff_max && ch == SPACE) { timeout = SPK_XMITR_TIMEOUT; while (synth_writable()) { if (!--timeout) break; udelay(1); } outb_p(PROCSPEECH, speakup_info.port_tts); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spk_unlock(flags); schedule_timeout(msecs_to_jiffies(delay_time_val)); jiff_max = jiffies+jiffy_delta_val; } } timeout = SPK_XMITR_TIMEOUT; while (synth_writable()) { if (!--timeout) break; udelay(1); } outb_p(PROCSPEECH, speakup_info.port_tts); }
/* * This is called when a user changes the keymap parameter. */ static ssize_t keymap_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int i; ssize_t ret = count; char *in_buff = NULL; char *cp; u_char *cp1; unsigned long flags; spk_lock(flags); in_buff = kmalloc(count + 1, GFP_ATOMIC); if (!in_buff) { spk_unlock(flags); return -ENOMEM; } memcpy(in_buff, buf, count + 1); if (strchr("dDrR", *in_buff)) { set_key_info(key_defaults, key_buf); pr_info("keymap set to default values\n"); kfree(in_buff); spk_unlock(flags); return count; } if (in_buff[count - 1] == '\n') in_buff[count - 1] = '\0'; cp = in_buff; cp1 = (u_char *)in_buff; for (i = 0; i < 3; i++) { cp = s2uchar(cp, cp1); cp1++; } i = (int)cp1[-2]+1; i *= (int)cp1[-1]+1; i += 2; /* 0 and last map ver */ if (cp1[-3] != KEY_MAP_VER || cp1[-1] > 10 || i+SHIFT_TBL_SIZE+4 >= sizeof(key_buf)) { pr_warn("i %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1]); kfree(in_buff); spk_unlock(flags); return -EINVAL; } while (--i >= 0) { cp = s2uchar(cp, cp1); cp1++; if (!(*cp)) break; } if (i != 0 || cp1[-1] != KEY_MAP_VER || cp1[-2] != 0) { ret = -EINVAL; pr_warn("end %d %d %d %d\n", i, (int)cp1[-3], (int)cp1[-2], (int)cp1[-1]); } else { if (set_key_info(in_buff, key_buf)) { set_key_info(key_defaults, key_buf); ret = -EINVAL; pr_warn("set key failed\n"); } } kfree(in_buff); spk_unlock(flags); return ret; }
/* * This is called when a user changes the characters or chartab parameters. */ static ssize_t chars_chartab_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { char *cp = (char *) buf; char *end = cp + count; /* the null at the end of the buffer */ char *linefeed = NULL; char keyword[MAX_DESC_LEN + 1]; char *outptr = NULL; /* Will hold keyword or desc. */ char *temp = NULL; char *desc = NULL; ssize_t retval = count; unsigned long flags; unsigned long index = 0; int charclass = 0; int received = 0; int used = 0; int rejected = 0; int reset = 0; int do_characters = !strcmp(attr->attr.name, "characters"); size_t desc_length = 0; int i; spk_lock(flags); while (cp < end) { while ((cp < end) && (*cp == ' ' || *cp == '\t')) cp++; if (cp == end) break; if ((*cp == '\n') || strchr("dDrR", *cp)) { reset = 1; break; } received++; linefeed = strchr(cp, '\n'); if (!linefeed) { rejected++; break; } if (!isdigit(*cp)) { rejected++; cp = linefeed + 1; continue; } index = simple_strtoul(cp, &temp, 10); if (index > 255) { rejected++; cp = linefeed + 1; continue; } while ((temp < linefeed) && (*temp == ' ' || *temp == '\t')) temp++; desc_length = linefeed - temp; if (desc_length > MAX_DESC_LEN) { rejected++; cp = linefeed + 1; continue; } if (do_characters) { desc = kmalloc(desc_length + 1, GFP_ATOMIC); if (!desc) { retval = -ENOMEM; reset = 1; /* just reset on error. */ break; } outptr = desc; } else { outptr = keyword; } for (i = 0; i < desc_length; i++) outptr[i] = temp[i]; outptr[desc_length] = '\0'; if (do_characters) { if (characters[index] != default_chars[index]) kfree(characters[index]); characters[index] = desc; used++; } else { charclass = chartab_get_value(keyword); if (charclass == 0) { rejected++; cp = linefeed + 1; continue; } if (charclass != spk_chartab[index]) { spk_chartab[index] = charclass; used++; } } cp = linefeed + 1; } if (reset) { if (do_characters) reset_default_chars(); else reset_default_chartab(); } spk_unlock(flags); report_char_chartab_status(reset, received, used, rejected, do_characters); return retval; }
static void do_catch_up(struct spk_synth *synth) { u_char ch; unsigned long flags; unsigned long jiff_max; struct var_t *jiffy_delta; struct var_t *delay_time; struct var_t *full_time; int full_time_val = 0; int delay_time_val = 0; int jiffy_delta_val = 0; jiffy_delta = get_var(JIFFY); delay_time = get_var(DELAY); full_time = get_var(FULL); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; full_time_val = full_time->u.n.value; delay_time_val = delay_time->u.n.value; if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } ch = synth_buffer_peek(); set_current_state(TASK_INTERRUPTIBLE); full_time_val = full_time->u.n.value; spk_unlock(flags); if (!spk_serial_out(ch)) { outb(UART_MCR_DTR, speakup_info.port_tts + UART_MCR); outb(UART_MCR_DTR | UART_MCR_RTS, speakup_info.port_tts + UART_MCR); schedule_timeout(msecs_to_jiffies(full_time_val)); continue; } if ((jiffies >= jiff_max) && (ch == SPACE)) { spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; full_time_val = full_time->u.n.value; delay_time_val = delay_time->u.n.value; spk_unlock(flags); if (spk_serial_out(synth->procspeech)) schedule_timeout(msecs_to_jiffies (delay_time_val)); else schedule_timeout(msecs_to_jiffies (full_time_val)); jiff_max = jiffies + jiffy_delta_val; } set_current_state(TASK_RUNNING); spk_lock(flags); synth_buffer_getc(); spk_unlock(flags); } spk_serial_out(PROCSPEECH); }
static void do_catch_up(struct spk_synth *synth) { u_char ch; static u_char last = '\0'; unsigned long flags; unsigned long jiff_max; struct var_t *jiffy_delta; struct var_t *delay_time; int jiffy_delta_val = 0; int delay_time_val = 0; jiffy_delta = spk_get_var(JIFFY); delay_time = spk_get_var(DELAY); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; spk_unlock(flags); jiff_max = jiffies + jiffy_delta_val; while (!kthread_should_stop()) { spk_lock(flags); if (speakup_info.flushing) { speakup_info.flushing = 0; spk_unlock(flags); synth->flush(synth); continue; } if (synth_buffer_empty()) { spk_unlock(flags); break; } ch = synth_buffer_peek(); set_current_state(TASK_INTERRUPTIBLE); delay_time_val = delay_time->u.n.value; spk_unlock(flags); if (ch == '\n') ch = 0x0D; if (synth_full() || !spk_serial_out(ch)) { schedule_timeout(msecs_to_jiffies(delay_time_val)); continue; } set_current_state(TASK_RUNNING); spk_lock(flags); synth_buffer_getc(); spk_unlock(flags); if (ch == '[') in_escape = 1; else if (ch == ']') in_escape = 0; else if (ch <= SPACE) { if (!in_escape && strchr(",.!?;:", last)) spk_serial_out(PROCSPEECH); if (jiffies >= jiff_max) { if (!in_escape) spk_serial_out(PROCSPEECH); spk_lock(flags); jiffy_delta_val = jiffy_delta->u.n.value; delay_time_val = delay_time->u.n.value; spk_unlock(flags); schedule_timeout(msecs_to_jiffies (delay_time_val)); jiff_max = jiffies + jiffy_delta_val; } } last = ch; } if (!in_escape) spk_serial_out(PROCSPEECH); }
/* * This function is called when a user echos a value to one of the * variable parameters. */ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { struct st_var_header *param; int ret; int len; char *cp; struct var_t *var_data; int value; unsigned long flags; param = var_header_by_name(attr->attr.name); if (param == NULL) return -EINVAL; if (param->data == NULL) return 0; ret = 0; cp = xlate((char *) buf); spk_lock(flags); switch (param->var_type) { case VAR_NUM: case VAR_TIME: if (*cp == 'd' || *cp == 'r' || *cp == '\0') len = E_DEFAULT; else if (*cp == '+' || *cp == '-') len = E_INC; else len = E_SET; speakup_s2i(cp, &value); ret = set_num_var(value, param, len); if (ret == E_RANGE) { var_data = param->data; pr_warn("value for %s out of range, expect %d to %d\n", attr->attr.name, var_data->u.n.low, var_data->u.n.high); } break; case VAR_STRING: len = strlen(buf); if ((len >= 1) && (buf[len - 1] == '\n')) --len; if ((len >= 2) && (buf[0] == '"') && (buf[len - 1] == '"')) { ++buf; len -= 2; } cp = (char *) buf; cp[len] = '\0'; ret = set_string_var(buf, param, len); if (ret == E_TOOLONG) pr_warn("value too long for %s\n", attr->attr.name); break; default: pr_warn("%s unknown type %d\n", param->name, (int)param->var_type); break; } /* * If voice was just changed, we might need to reset our default * pitch and volume. */ if (strcmp(attr->attr.name, "voice") == 0) { if (synth && synth->default_pitch) { param = var_header_by_name("pitch"); if (param) { set_num_var(synth->default_pitch[value], param, E_NEW_DEFAULT); set_num_var(0, param, E_DEFAULT); } } if (synth && synth->default_vol) { param = var_header_by_name("vol"); if (param) { set_num_var(synth->default_vol[value], param, E_NEW_DEFAULT); set_num_var(0, param, E_DEFAULT); } } } spk_unlock(flags); if (ret == SET_DEFAULT) pr_info("%s reset to default value\n", attr->attr.name); return count; }