void handle_placing(GameInstance *g, const Server *s, Player *p, const char *req, int len) { SpeedRiskData *risk; int all_ready, i; SR_Command *cmd = (SR_Command*)req; risk = (SpeedRiskData*)g->data; if (cmd->to >= risk->board->territories) { player_error(s, p, SR_ERR_INVALID_DESTINATION); return; } switch (cmd->command) { case SR_CMD_READY: if (risk->players[p->in_game_id].ready) return; risk->players[p->in_game_id].ready = true; all_cmd_f(g, s, SR_CMD_READY, p->in_game_id); all_ready = true; for (i=0; i<risk->board->max_players; i++) { all_ready &= (risk->players[i].player == NULL || risk->players[i].ready); } if (all_ready) { s->change_state(g, &SR_RUNNING); } break; case SR_CMD_NOTREADY: if (!risk->players[p->in_game_id].ready) return; risk->players[p->in_game_id].ready = false; all_cmd_f(g, s, SR_CMD_NOTREADY, p->in_game_id); break; case SR_CMD_PLACE: if (not_holds((&risk->status), p, cmd->to)) { player_error(s, p, SR_ERR_NOT_OWNER); } else if (cmd->armies > risk->players[p->in_game_id].armies) { player_error(s, p, SR_ERR_NOT_ENOUGH_ARMIES); } else { risk->status.countries[cmd->to].armies += cmd->armies; risk->players[p->in_game_id].armies -= cmd ->armies; give_country_status(g, s, NULL, cmd->to); player_cmd_a(s, p, SR_CMD_GET_ARMIES, risk->players[p->in_game_id].armies); } case SR_CMD_PLAYER_STATUS: give_player_status(g, s, p, req, len); break; case SR_CMD_LIST_THEMES: list_themes(g, s, p); break; default: player_error(s, p, SR_ERR_INVALID_CMD); break; } }
void handle_playing(GameInstance *g, const Server *s, Player *p, const char *req, int len) { int armies; SpeedRiskData *risk; SR_Command *cmd = (SR_Command*)req; risk = (SpeedRiskData*)g->data; return_if_invalid(cmd); switch (cmd->command) { case SR_CMD_MOVE: do_move(g, s, p, cmd); break; case SR_CMD_ATTACK: do_attack(g, s, p, cmd); break; case SR_CMD_PLACE: if (not_holds((&risk->status), p, cmd->to)) { player_error(s, p, SR_ERR_NOT_OWNER); } else if (cmd->armies > risk->players[p->in_game_id].armies) { player_error(s, p, SR_ERR_NOT_ENOUGH_ARMIES); } else { armies = risk->status.countries[cmd->to].armies + cmd->armies; if (armies > 255) cmd->armies = 255 - risk->status.countries[cmd->to].armies; risk->status.countries[cmd->to].armies += cmd->armies; risk->players[p->in_game_id].armies -= cmd->armies; give_country_status(g, s, NULL, cmd->to); player_cmd_a(s, p, SR_CMD_GET_ARMIES, risk->players[p->in_game_id].armies); } break; case SR_CMD_GAME_STATUS: give_game_status(g, s, p); break; case SR_CMD_PLAYER_STATUS: msg_command.command = SR_CMD_PLAYER_STATUS; msg_command.from = p->in_game_id; msg_command.to = g->playing; msg_command.armies = risk->players[p->in_game_id].armies; s->tell_player(p,(char*)&msg_command,4); break; case SR_CMD_COUNTRY_STATUS: give_country_status(g, s, p, cmd->from); break; default: player_error(s, p, SR_ERR_INVALID_CMD); break; } }
static int _playerbackend_command(PlayerBackend * player, char const * cmd, size_t cmd_len) { char * p; if(player->pid == -1) { fputs(PROGNAME ": mplayer not running\n", stderr); if(player->timeout_id != 0) g_source_remove(player->timeout_id); player->timeout_id = g_timeout_add(1000, _command_on_timeout, player); return -1; } #ifdef DEBUG fprintf(stderr, "%s%d%s\"%s\"\n", "DEBUG: pid ", player->pid, ": write ", cmd); #endif if((p = realloc(player->buf, player->buf_len + cmd_len)) == NULL) return -player_error(NULL, "malloc", 1); player->buf = p; memcpy(&p[player->buf_len], cmd, cmd_len); player->buf_len += cmd_len; if(player->write_id == 0) player->write_id = g_io_add_watch(player->channel[1], G_IO_OUT, _command_write, player); return 0; }
/* playerbackend_destroy */ void playerbackend_destroy(PlayerBackend * player) { char const cmd[] = "\nquit\n"; gsize written; size_t i; int status = 0; pid_t res; struct timespec ts = { 0, 500000 }; if(player->read_id != 0) g_source_remove(player->read_id); if(player->write_id != 0) g_source_remove(player->write_id); if(player->timeout_id != 0) g_source_remove(player->timeout_id); g_io_channel_write_chars(player->channel[1], cmd, sizeof(cmd) - 1, &written, NULL); g_io_channel_shutdown(player->channel[1], FALSE, NULL); for(i = 0; i < 6; i++) { if((res = waitpid(player->pid, &status, WNOHANG)) == -1) { player_error(NULL, "waitpid", 0); break; } else if(res == 0) nanosleep(&ts, NULL); else if(WIFEXITED(status) || WIFSIGNALED(status)) break; if(i == 4) kill(player->pid, SIGTERM); } object_delete(player); }
static gboolean _command_read(GIOChannel * source, GIOCondition condition, gpointer data) { PlayerBackend * player = data; static char buf[512]; static size_t buf_len = 0; gsize read; size_t i; size_t j; GIOStatus status; GError * error = NULL; if(condition != G_IO_IN) { player_error(player->player, "", 0); /* FIXME */ gtk_main_quit(); return FALSE; /* FIXME report error */ } status = g_io_channel_read_chars(source, &buf[buf_len], sizeof(buf) - buf_len, &read, &error); if(status == G_IO_STATUS_EOF || read == 0) { player->read_id = 0; return FALSE; /* FIXME end of file? */ } else if(status != G_IO_STATUS_NORMAL) { player_error(player->player, error->message, 1); g_error_free(error); /* FIXME recover somehow */ gtk_main_quit(); return FALSE; } buf_len += read; j = 0; for(i = 0; i < buf_len; i++) { if(buf[i] != '\n') continue; buf[i] = '\0'; _read_parse(player, &buf[j]); j = i + 1; } buf_len -= j; memmove(buf, &buf[j], buf_len); return TRUE; }
void handle_waiting(GameInstance *g, const Server *s, Player *p, const char *req, int len) { SpeedRiskData *risk; int all_ready, i; SR_Command *cmd = (SR_Command*)req; risk = (SpeedRiskData*)g->data; switch (cmd->command) { case SR_CMD_READY: if (g->playing > 1) { if (risk->players[p->in_game_id].ready) { player_error(s, p, SR_ERR_INVALID_CMD); break; } risk->players[p->in_game_id].ready = true; all_cmd_f(g, s, SR_CMD_READY, p->in_game_id); all_ready = true; for (i=0; i<risk->board->max_players; i++) { all_ready &= (risk->players[i].player == NULL || risk->players[i].ready); } if (all_ready) { s->change_state(g, &SR_PLACING); } } else { player_error(s, p, SR_ERR_NOT_ENOUGH_PLAYERS); } break; case SR_CMD_NOTREADY: if (!risk->players[p->in_game_id].ready) { player_error(s, p, SR_ERR_INVALID_CMD); break; } risk->players[p->in_game_id].ready = false; all_cmd_f(g, s, SR_CMD_NOTREADY, p->in_game_id); break; case SR_CMD_PLAYER_STATUS: give_player_status(g, s, p, req, len); break; case SR_CMD_LIST_THEMES: list_themes(g, s, p); break; default: player_error(s, p, SR_ERR_INVALID_CMD); break; } }
void do_attack(GameInstance *g, const Server *s, Player *p, SR_Command *cmd) { SpeedRiskData *risk = (SpeedRiskData *)g->data; SR_Game_Status *status = &risk->status; int attacking, defending, attack_loss, defend_loss, defender; if (not_holds(status, p, cmd->from)) { player_error(s, p, SR_ERR_NOT_OWNER); } else if (holds(status, p, cmd->to)) { player_error(s, p, SR_ERR_INVALID_DESTINATION); } else if (!borders(cmd->from, cmd->to)) { player_error(s, p, SR_ERR_INVALID_DESTINATION); } else if (cmd->armies < 1 || cmd->armies >= status->countries[cmd->from].armies) { player_error(s, p, SR_ERR_NOT_ENOUGH_ARMIES); } else { attacking = cmd->armies > 3 ? 3 : cmd->armies; defending = status->countries[cmd->to].armies > 1 ? 2 : 1; roll_for_attack(attacking, defending, s->random, &attack_loss, &defend_loss); status->countries[cmd->from].armies -= attack_loss; status->countries[cmd->to].armies -= defend_loss; defender = status->countries[cmd->to].owner; if (status->countries[cmd->to].armies == 0) { attacking = cmd->armies - attack_loss; status->countries[cmd->from].armies -= attacking; status->countries[cmd->to].armies += attacking; status->countries[cmd->to].owner = p->in_game_id; risk->players[p->in_game_id].countries_held++; risk->players[defender].countries_held--; } tell_all_mv_at_result(g, s, SR_CMD_ATTACK_RESULT, cmd->from, cmd->to); if (risk->players[defender].countries_held == 0) { all_cmd_f(g, s, SR_CMD_DEFEAT, defender); if (risk->players[defender].player != NULL) { s->log(g, "%s defeated", risk->players[defender].player->name); } } if (risk->players[p->in_game_id].countries_held == risk->board->territories) { s->change_state(g, &SR_DONE); } } }
void handle_done (GameInstance *g, const Server *s, Player *p, const char *req, int len) { SpeedRiskData *risk; SR_Command *cmd = (SR_Command*)req; risk = (SpeedRiskData*)g->data; switch (cmd->command) { case SR_CMD_GAME_STATUS: give_game_status(g, s, p); break; case SR_CMD_COUNTRY_STATUS: if ( cmd->from >= risk->board->territories ) { player_error(s, p, SR_ERR_INVALID_DESTINATION); return; } give_country_status(g, s, p, cmd->from); break; default: player_error(s, p, SR_ERR_INVALID_CMD); break; } }
static void _consumer_handle_eof(void) { struct track_info *ti; if (ip_is_remote(ip)) { _producer_stop(); _consumer_drain_and_stop(); player_error("lost connection"); return; } if (player_info.ti) player_info.ti->play_count++; if (player_repeat_current) { if (player_cont) { ip_seek(ip, 0); reset_buffer(); } else { _producer_stop(); _consumer_drain_and_stop(); _player_status_changed(); } return; } if (get_next(&ti) == 0) { _producer_unload(); ip = ip_new(ti->filename); _producer_status_update(PS_STOPPED); /* PS_STOPPED, CS_PLAYING */ if (player_cont) { _producer_play(); if (producer_status == PS_UNLOADED) { _consumer_stop(); track_info_unref(ti); file_changed(NULL); } else { /* PS_PLAYING */ file_changed(ti); if (!change_sf(0)) _prebuffer(); } } else { _consumer_drain_and_stop(); file_changed(ti); } } else { _producer_unload(); _consumer_drain_and_stop(); file_changed(NULL); } _player_status_changed(); }
/* playerbackend_start */ int playerbackend_start(PlayerBackend * player) { int ret; char const buf[] = "pausing loadfile " PLAYER_SPLASH " 0\nframe_step\n"; char wid[32]; char * argv[] = { BINDIR "/mplayer", "mplayer", "-slave", "-wid", NULL, "-quiet", "-idle", "-framedrop", "-softvol", "-softvol-max", "200", "-identify", "-noconsolecontrols", "-nomouseinput", NULL }; GError * error = NULL; argv[4] = wid; /* XXX not portable */ snprintf(wid, sizeof(wid), "%lu", (unsigned long)gtk_socket_get_id( GTK_SOCKET(player->view))); if(pipe(player->fd[0]) != 0 || pipe(player->fd[1]) != 0) return -player_error(player->player, strerror(errno), 1); if((player->pid = fork()) == -1) return -player_error(player->player, strerror(errno), 1); if(player->pid == 0) /* child */ { close(player->fd[0][0]); close(player->fd[1][1]); if(dup2(player->fd[1][0], 0) == -1) exit(player_error(NULL, "dup2", 2)); if(dup2(player->fd[0][1], 1) == -1) exit(player_error(NULL, "dup2", 2)); execv(argv[0], &argv[1]); exit(player_error(NULL, argv[0], 2)); } close(player->fd[0][1]); close(player->fd[1][0]); player->channel[0] = g_io_channel_unix_new(player->fd[0][0]); if(g_io_channel_set_encoding(player->channel[0], NULL, &error) != G_IO_STATUS_NORMAL) { player_error(player->player, error->message, 1); g_error_free(error); error = NULL; } g_io_channel_set_buffered(player->channel[0], FALSE); player->read_id = g_io_add_watch(player->channel[0], G_IO_IN, _command_read, player); player->channel[1] = g_io_channel_unix_new(player->fd[1][1]); if(g_io_channel_set_encoding(player->channel[1], NULL, &error) != G_IO_STATUS_NORMAL) { player_error(player->player, error->message, 1); g_error_free(error); } g_io_channel_set_buffered(player->channel[1], FALSE); ret = _playerbackend_command(player, buf, sizeof(buf) - 1); player_set_paused(player->player, TRUE); return ret; }
/* command_write */ static gboolean _command_write(GIOChannel * source, GIOCondition condition, gpointer data) { PlayerBackend * player = data; gsize written; char * p; GError * error = NULL; if(condition != G_IO_OUT) { player_error(player->player, "", 0); /* FIXME */ gtk_main_quit(); player->write_id = 0; return FALSE; /* FIXME report error */ } if(g_io_channel_write_chars(source, player->buf, player->buf_len, &written, &error) != G_IO_STATUS_NORMAL) { player_error(player->player, error->message, 1); g_error_free(error); /* FIXME recover somehow */ gtk_main_quit(); player->write_id = 0; return FALSE; } #ifdef DEBUG fprintf(stderr, "DEBUG: wrote %zu bytes\n", written); #endif player->buf_len -= written; memmove(player->buf, &player->buf[written], player->buf_len); if(player->buf_len == 0) { player->write_id = 0; return FALSE; } if((p = realloc(player->buf, player->buf_len)) != NULL) player->buf = p; return TRUE; }
void do_move(GameInstance *g, const Server *s, Player *p, SR_Command *cmd) { int armies; SpeedRiskData *risk = (SpeedRiskData *)g->data; SR_Game_Status *status = &risk->status; if (!(holds(status, p, cmd->from) && holds(status, p, cmd->to))) { player_error(s, p, SR_ERR_NOT_OWNER); } else if (!borders(cmd->from, cmd->to)) { player_error(s, p, SR_ERR_INVALID_DESTINATION); } else if (cmd->armies>=status->countries[cmd->from].armies){ player_error(s, p, SR_ERR_NOT_ENOUGH_ARMIES); } else { armies = status->countries[cmd->to].armies + cmd->armies; if (armies > 255) cmd->armies = 255 - status->countries[cmd->to].armies; status->countries[cmd->from].armies -= cmd->armies; status->countries[cmd->to].armies += cmd->armies; tell_all_mv_at_result(g, s, SR_CMD_MOVE_RESULT, cmd->from, cmd->to); } }
/* playerbackend_on_sigchld */ static int _playerbackend_on_sigchld(PlayerBackend * player) { pid_t pid; int status; char buf[80]; if(player->pid == -1) return 1; if((pid = waitpid(player->pid, &status, WNOHANG)) == -1) return player_error(player->player, "waitpid", 1); if(pid == 0) return 1; if(WIFEXITED(status)) { snprintf(buf, sizeof(buf), "mplayer %d: exited with code %u", pid, WEXITSTATUS(status)); player_error(player->player, buf, 1); } else fprintf(stderr, "%s%s%d%s", PROGNAME ": ", "mplayer ", pid, ": Unknown state\n"); player->pid = -1; return 0; }
static void __FORMAT(2, 3) player_op_error(int rc, const char *format, ...) { char buffer[1024]; va_list ap; char *msg; int save = errno; va_start(ap, format); vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); errno = save; msg = op_get_error_msg(rc, buffer); player_error(msg); free(msg); }
static void _init_signal_handler(int signum) { PlayerBackend * player = _player; pid_t pid; int status; if(signum != SIGCHLD) return; if(_playerbackend_on_sigchld(player) == 0) return; if((pid = waitpid(-1, &status, WNOHANG)) == -1) { player_error(NULL, "waitpid", 1); return; } if(pid == 0) return; fputs(PROGNAME ": ", stderr); if(WIFEXITED(status)) fprintf(stderr, "%s%d%s%u\n", "child ", pid, ": exited with code ", WEXITSTATUS(status)); else fprintf(stderr, "%d%s", pid, ": Unknown state\n"); }