On Monday 19 August 2002 10:46 am, Andre Poenitz wrote: > PS: I'll attach the stuff in case anybody wants to have a look.
Ok, this does rather more than I was anticipating. It takes a command as argument, eg "maple -q" and forks a new process, allowing you to send data to, and receive data from, maple. The lyxserver wants something less complex. It just opens and closes named pipes and sends, recieves data. Over the w/e, I turned the server_monitor.c file to be found in development/lyxserver into C++, also implementing a Controller/View split. Attached is the resultant ClientController.C. It communicates with LyX using low-level open, close, read and write C-library calls. I was imagining that pipestream would wrap these. Angus
#include "ClientController.h" #include "ClientView.h" #include "support.h" #include <cstdio> // temporary for sprintf #include <iostream> #include <sstream> #include <fcntl.h> #include <unistd.h> extern bool finished; ClientController::ClientController() : view_(0), pipein_(-1), pipeout_(-1), lyx_listen_(0) {} void ClientController::setView(ClientView & v) { view_ = &v; } ClientView & ClientController::view() const { lyx::Assert(view_); return *view_; } void ClientController::show() { view().show(); } void ClientController::hide() { if (pipein_ != -1) close_pipes(); view().hide(); finished = true; } void ClientController::submit() { if (pipein_ == -1 ) { std::cerr << "ClientController::submit:\n" << "The pipes are not open." << std::endl; return; } char s[255]; sprintf(s, "LYXCMD:%s:%s:%s\n", view().clientname().c_str(), view().command().c_str(), view().argument().c_str()); write(pipein_, s, strlen(s)); // stringstream ss; // ss << "LYXSRV:" // << view().clientname().c_str() << ':' // << view().command().c_str() << ':' // << view().argument().c_str() << '\n'; // string const message = ss.str(); // write(pipein_, message.c_str(), message.size()); } void ClientController::message_ready(int pipe) { if (pipe != pipeout_) return; static size_t const size = 1024; char s[size]; int const n = read(pipeout_, &s[0], size); if (n == 0) return; string message = s; if (prefixIs(message, "LYXSRV:")) { string prefix = "LYXSRV:"; message = ltrim(message, prefix.c_str()); prefix = view().clientname() + string(":"); prefix = ltrim(message, prefix.c_str()); split(prefix, message, '\n'); if (message == "bye") { std::cerr << "LyX has closed connection!" << std::endl; lyx_listen_ = 0; view().monitor_pipe(pipeout_, false); view().pipes_closed(); } if (message == "hello") { std::cerr << "LyX is listening!" << std::endl; lyx_listen_ = 1; view().can_submit(); } } view().setMessage(message); } void ClientController::open_pipes(string const & pipe_base) { if (pipein_ != -1) { std::cerr << "ClientController::open_pipes:\n" << "The pipes are open already. Close then first" << std::endl; return; } string const pipe_in = pipe_base + ".in"; string const pipe_out = pipe_base + ".out"; std::cerr << "Opening pipes " << pipe_in << " and " << pipe_out << std::endl; pipein_ = open(pipe_in.c_str(), O_RDWR); pipeout_ = open(pipe_out.c_str(), O_RDONLY|O_NONBLOCK); if (pipein_ < 0 || pipeout_ < 0) { std::cerr << "Failed!" << std::endl; pipein_ = pipeout_ = -1; return; } view().monitor_pipe(pipeout_, true); view().pipes_opened(); // Greet LyX string const greeting = message("hello"); write(pipein_, greeting.c_str(), greeting.size()); } void ClientController::close_pipes() { if (pipein_ == -1 && pipeout_ == -1) { std::cerr << "ClientController::close_pipes:\n" << "The pipes are not open." << std::endl; return; } if (pipein_ >= 0) { if (lyx_listen_) { // Say goodbye lyx_listen_ = 0; string const farewell = message("bye"); write(pipein_, farewell.c_str(), farewell.size()); close(pipein_); } } if (pipeout_ >= 0) { close(pipeout_); } view().monitor_pipe(pipeout_, false); view().pipes_closed(); pipein_ = pipeout_ = -1; } string const ClientController::message(string const & str) const { stringstream ss; ss << "LYXSRV:" << view().clientname() << ':' << str << '\n'; return ss.str(); }