// Public facade function. int gcodep_parse_stream(GCodeParser_t *parser, int input_fd, FILE *err_stream) { if (err_stream) { // Output needs to be unbuffered, otherwise they'll never make it. setvbuf(err_stream, NULL, _IONBF, 0); } FILE *gcode_stream = fdopen(input_fd, "r"); if (gcode_stream == NULL) { perror("Opening gcode stream"); return 1; } fd_set read_fds; struct timeval wait_time; int select_ret; wait_time.tv_sec = 0; wait_time.tv_usec = 50 * 1000; FD_ZERO(&read_fds); arm_signal_handler(); char buffer[8192]; while (!caught_signal) { // Read with timeout. If we don't get anything on our input, but it // is not finished yet, we tell our FD_SET(input_fd, &read_fds); // When we're already in idle mode, we're not interested in change. wait_time.tv_usec = 50 * 1000; select_ret = select(input_fd + 1, &read_fds, NULL, NULL, &wait_time); if (select_ret < 0) // Broken stream. break; if (select_ret == 0) { // Timeout. Regularly call. parser->callbacks.input_idle(parser->callbacks.user_data); continue; } // Filedescriptor readable. Now wait for a line to finish. if (fgets(buffer, sizeof(buffer), gcode_stream) == NULL) break; gcodep_parse_line(parser, buffer, err_stream); } disarm_signal_handler(); if (err_stream) { fflush(err_stream); } fclose(gcode_stream); if (parser->program_in_progress) { parser->callbacks.gcode_finished(parser->callbacks.user_data); } return caught_signal ? 2 : 0; }
int determine_print_stats(int input_fd, float max_feedrate, float speed_factor, struct BeagleGPrintStats *result) { struct StatsData data; bzero(&data, sizeof(data)); data.max_feedrate = max_feedrate; data.cfg_speed_factor = speed_factor; data.prog_speed_factor = 1.0f; data.current_G1_feedrate = max_feedrate / 10; // some reasonable default. bzero(result, sizeof(*result)); data.stats = result; struct GCodeParserCb callbacks; bzero(&callbacks, sizeof(callbacks)); callbacks.rapid_move = &duration_G0; callbacks.coordinated_move = &duration_G1; callbacks.dwell = &duration_dwell; callbacks.set_speed_factor = &duration_set_speed_factor; // Not implemented callbacks.go_home = &dummy_home; callbacks.unprocessed = &ignore_other_commands; callbacks.set_fanspeed = &dummy_setvalue; callbacks.set_temperature = &dummy_setvalue; callbacks.motors_enable = &dummy_motors_enable; callbacks.wait_temperature = &dummy_noparam; FILE *f = fdopen(input_fd, "r"); if (f == NULL) { perror("Couldn't determine print stats"); return 1; } GCodeParser_t *parser = gcodep_new(&callbacks, &data); char buffer[8192]; while (fgets(buffer, sizeof(buffer), f)) { gcodep_parse_line(parser, buffer, stderr); } fclose(f); gcodep_delete(parser); return 0; }