gnome-chess/src/chess-engine.vala

161 lines
3.7 KiB
Vala
Raw Normal View History

2011-01-01 01:42:50 +00:00
public class ChessEngine : Object
{
public string binary;
public string args;
2011-01-01 01:42:50 +00:00
private Pid pid;
private int stdin_fd;
private int stderr_fd;
2011-01-01 01:42:50 +00:00
private IOChannel stdout_channel;
protected virtual void process_input (char[] data) {}
public signal void starting ();
public signal void ready_changed ();
public signal void moved (string move);
public signal void resigned ();
public signal void stopped ();
private bool _ready = false;
public bool ready
{
protected set
{
_ready = value;
ready_changed ();
}
public get
{
return _ready;
}
}
public bool start ()
{
string[] argv = { binary, args, null };
int stdout_fd;
try
{
2011-01-01 01:42:50 +00:00
Process.spawn_async_with_pipes (null, argv, null,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
null,
out pid, out stdin_fd, out stdout_fd, out stderr_fd);
}
2011-01-01 01:42:50 +00:00
catch (SpawnError e)
{
stderr.printf ("Failed to execute chess engine: %s\n", e.message);
return false;
}
ChildWatch.add (pid, engine_stopped_cb);
2011-01-01 01:42:50 +00:00
stdout_channel = new IOChannel.unix_new (stdout_fd);
try
{
2011-01-01 01:42:50 +00:00
stdout_channel.set_flags (IOFlags.NONBLOCK);
}
2011-01-01 01:42:50 +00:00
catch (IOChannelError e)
{
stderr.printf ("Failed to set input from chess engine to non-blocking: %s", e.message);
}
2011-01-01 01:42:50 +00:00
stdout_channel.add_watch (IOCondition.IN, read_cb);
starting ();
return true;
}
private void engine_stopped_cb (Pid pid, int status)
{
stopped ();
}
public virtual void start_game ()
{
}
public virtual void request_move ()
{
}
public virtual void report_move (ChessMove move)
{
}
2011-01-25 11:44:15 +00:00
public virtual void undo ()
{
}
public void stop ()
{
if (pid != 0)
Posix.kill (pid, Posix.SIGTERM);
}
2011-01-01 01:42:50 +00:00
private bool read_cb (IOChannel source, IOCondition condition)
{
char[] buf;
size_t n_read;
2011-01-01 01:42:50 +00:00
IOStatus status;
buf = new char[1024];
try
{
status = source.read_chars (buf, out n_read);
}
2011-01-01 01:42:50 +00:00
catch (ConvertError e)
{
return false;
}
2011-01-01 01:42:50 +00:00
catch (IOChannelError e)
{
return false;
}
2011-01-01 01:42:50 +00:00
if (status == IOStatus.EOF)
{
stdout.printf ("EOF\n");
return false;
}
2011-01-01 01:42:50 +00:00
if (status == IOStatus.NORMAL)
{
2011-01-01 01:42:50 +00:00
//debug ("Read %zu octets from engine", n_read);
buf.resize ((int) n_read);
process_input (buf);
}
return true;
}
protected void write (char[] data)
{
size_t offset = 0;
size_t n_written;
while (offset < data.length)
{
/* Unnecessary copying but there seems to be a vala bug here */
char[] d = new char[data.length - offset];
for (int i = 0; i < data.length - offset; i++)
d[i] = data[offset + i];
n_written = Posix.write(stdin_fd, d, d.length);
if (n_written < 0)
return;
2011-01-01 01:42:50 +00:00
//debug ("Wrote %zu octets to engine", n_written);
offset += n_written;
}
}
protected void write_line (string line)
{
string l = line + "\n";
2011-01-01 01:42:50 +00:00
debug ("Writing line to engine: '%s'", line);
char[] d = l.to_utf8 ();
if (d != null)
write (d);
}
}