char *lastErrorStr_mbrola(char *buffer, int bufsize) { if (mbr_pid) mbrola_has_errors(); snprintf(buffer, bufsize, "%s", mbr_errorbuf); return buffer; }
static int send_to_mbrola(const char *cmd) { ssize_t result; int len; if (!mbr_pid) return -1; len = strlen(cmd); result = write(mbr_cmd_fd, cmd, len); if (result == -1) { int error = errno; if (error == EPIPE && mbrola_has_errors()) return -1; else if (error == EAGAIN) result = 0; else { err("write(): %s", strerror(error)); return -1; } } if (result != len) { struct datablock *data; data = (struct datablock *)malloc(sizeof(*data) + len - result); if (data) { data->next = NULL; data->done = 0; data->size = len - result; memcpy(data->buffer, cmd + result, len - result); result = len; if (!mbr_pending_data_head) mbr_pending_data_head = data; else mbr_pending_data_tail->next = data; mbr_pending_data_tail = data; } } return result; }
void reset_mbrola(void) { int result, success = 1; char dummybuf[4096]; if (mbr_state == MBR_IDLE) return; if (!mbr_pid) return; if (kill(mbr_pid, SIGUSR1) == -1) success = 0; free_pending_data(); result = write(mbr_cmd_fd, "\n#\n", 3); if (result != 3) success = 0; do { result = read(mbr_audio_fd, dummybuf, sizeof(dummybuf)); } while (result > 0); if (result != -1 || errno != EAGAIN) success = 0; if (!mbrola_has_errors() && success) mbr_state = MBR_IDLE; }
static ssize_t receive_from_mbrola(void *buffer, size_t bufsize) { int result, wait = 1; size_t cursize = 0; if (!mbr_pid) return -1; do { struct pollfd pollfd[3]; nfds_t nfds = 0; int idle; pollfd[0].fd = mbr_audio_fd; pollfd[0].events = POLLIN; nfds++; pollfd[1].fd = mbr_error_fd; pollfd[1].events = POLLIN; nfds++; if (mbr_pending_data_head) { pollfd[2].fd = mbr_cmd_fd; pollfd[2].events = POLLOUT; nfds++; } idle = mbrola_is_idle(); result = poll(pollfd, nfds, idle ? 0 : wait); if (result == -1) { err("poll(): %s", strerror(errno)); return -1; } if (result == 0) { if (idle) { mbr_state = MBR_IDLE; break; } else { if (wait >= 5000 * (4-1)/4) { mbr_state = MBR_WEDGED; err("mbrola process is stalled"); break; } else { wait *= 4; continue; } } } wait = 1; if (pollfd[1].revents && mbrola_has_errors()) return -1; if (mbr_pending_data_head && pollfd[2].revents) { struct datablock *head = mbr_pending_data_head; char *data = head->buffer + head->done; int left = head->size - head->done; result = write(mbr_cmd_fd, data, left); if (result == -1) { int error = errno; if (error == EPIPE && mbrola_has_errors()) return -1; err("write(): %s", strerror(error)); return -1; } if (result != left) head->done += result; else { mbr_pending_data_head = head->next; free(head); if (!mbr_pending_data_head) mbr_pending_data_tail = NULL; else continue; } } if (pollfd[0].revents) { char *curpos = (char *)buffer + cursize; size_t space = bufsize - cursize; ssize_t obtained = read(mbr_audio_fd, curpos, space); if (obtained == -1) { err("read(): %s", strerror(errno)); return -1; } cursize += obtained; mbr_state = MBR_AUDIO; } } while (cursize < bufsize); return cursize; }