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();
}

Reply via email to