示例#1
0
def run_gobbler(lines, output_queue):
    pipe = MockPipe(lines)
    line_queue = queue.Queue()
    gobbler = None
    try:
        gobbler = StreamGobbler(pipe, line_queue)
        gobbler.start()
        gobbler.wait_for_cursor()
        for _ in range(3):
            output_queue.put(line_queue.get(timeout=0.1))
    finally:
        gobbler.stop()
示例#2
0
 def test_read_lines(self):
     lines = [b"test1\n", b"test2\n", b"test3\n"]
     pipe = MockPipe(lines)
     line_queue = queue.Queue()
     gobbler = None
     try:
         gobbler = StreamGobbler(pipe, line_queue)
         gobbler.start()
         gobbler.wait_for_cursor()
         for i in range(3):
             assert_that(line_queue.get(timeout=0.1),
                         is_(equal_to(lines[i][:-1])))
     finally:
         gobbler.stop()
示例#3
0
class Console(object):

    # Starts up an instance of MAME with POpen
    # Uses a separate thread for reading from the console outputs
    # render is for displaying the frames to the emulator window, disabling it has little to no effect
    # throttle enabled will run any game at the intended gameplay speed, disabling it will run the game as fast as the computer can handle
    # debug enabled will print everything that comes out of the Lua engine console
    def __init__(self, roms_path, game_id, cheat_debugger=False, render=True, throttle=False, debug=False):
        self.logger = logging.getLogger("Console")

        command = f"exec ./mame -rompath '{str(Path(roms_path).absolute())}' -pluginspath plugins -skip_gameinfo -sound none -console "+game_id
        if not render:
            command += " -video none"

        if cheat_debugger:
            command += " -debug"

        if throttle:
            command += " -throttle"
        else:
            command += " -frameskip 10"

        # Start lua console
        script_path = os.path.dirname(os.path.abspath(__file__))
        self.process = Popen(command, cwd=f"{script_path}/mame", shell=True, stdin=PIPE, stdout=PIPE)

        # Start read queues
        self.stdout_queue = queue.Queue()
        self.gobbler = StreamGobbler(self.process.stdout, self.stdout_queue, debug=debug)
        self.gobbler.wait_for_cursor()
        self.gobbler.start()

    # Read the oldest line which may have been output by the console
    # Uses the FIFO principle, once a line is read it is removed from the queue
    # timeout determines how long the function will wait for an output if there is nothing immediately available
    def readln(self, timeout=0.5):
        line = self.stdout_queue.get(timeout=timeout)
        while len(line)>0 and line[0] == 27:
            line = line[19:]
        return line.decode("utf-8")

    # Read as many lines from the console as there are available
    # timeout determines how long the function will wait for an output if there is nothing immediately available
    def readAll(self, timeout=0.5):
        lines = []
        while True:
            try:
                lines.append(self.readln(timeout=timeout))
            except queue.Empty as e:
                break
        return lines

    def writeln(self, command, expect_output=False, timeout=0.5, raiseError=True):
        self.process.stdin.write(command.encode("utf-8") + b'\n')
        self.process.stdin.flush()
        output = self.readAll(timeout=timeout)

        if expect_output and len(output) == 0:
            error = "Expected output but received nothing from emulator after '" + command + "'"
            if raiseError:
                self.logger.error(error)
                raise IOError(error)
            else:
                return None
        if not expect_output and len(output) > 0:
            error = "No output expected from command '" + command + "', but recieved: " + "\n".join(output)
            if raiseError:
                self.logger.error(error)
                raise IOError(error)
            else:
                return None
        if expect_output:
            return output

    # Mainly for testing
    # Safely kills the emulator process
    def close(self):
        self.process.kill()
        try:
            self.process.wait(timeout=3)
        except Exception as e:
            error = "Failed to close emulator console"
            self.logger.error(error, e)
            raise EnvironmentError(error)
        self.gobbler.stop()