Esempio n. 1
0
 def check_voice_server(self):
     """Check for messages from the voice server."""
     if self.voice_pipe.poll():
         msg = self.voice_pipe.recv()
         if msg["type"] == "CRITICAL":
             try:
                 raise VoiceServerError(msg["data"]["traceback"])
             except:
                 self.logger.critical("VoiceServer failed", exc_info=True)
                 raise
         elif msg["type"] == "TIMESTAMP":
             create_logger("voicetimes").debug(
                 json.dumps({
                     "voice_time": msg["data"]["timestamp"],
                     "main_time": time.time() * 1000,
                     "pyepl_time": timing.now()
                 }))
         elif msg["type"] == "VOCALIZATION":
             start = msg["data"]["speaking"]
             log_msg = {
                 "event":
                 "VOCALIZATION_START" if start else "VOCALIZATION_END",
                 "timestamp": msg["data"]["timestamp"]
             }
             self.event_log.info(json.dumps(log_msg))
             self.socket.enqueue_message(
                 self.build_message("STATE", "VOCALIZATION", start))
         else:
             self.logger.error("Received malformed message: %s", msg)
Esempio n. 2
0
    def __init__(self,
                 address="tcp://192.168.137.200:8889",
                 voiceserver=False,
                 connection_timeout=10,
                 log_level=logging.INFO):
        if self._instance is not None:
            raise Exception("Multiple RAM instances requested!")

        self.connection_timeout = connection_timeout

        self._synced = Event()
        self._started = False  # received START from control PC
        self._configured = False
        self._connected = False
        self._connection_failed = False
        self._last_heartbeat_received = -1.  # last time heartbeat was received

        # Experiment-specific data to be filled in later
        self.experiment = ''
        self.version = ''
        self.session_num = -1
        self.subject = ''

        # Configure basic message handlers
        self.handlers = {
            "ID": self.id_handler,
            "SYNC": self.sync_handler,
            "SYNCED": self.synced_handler,
            "START": self.start_handler,
            "EXIT": self.exit_handler,
            "HEARTBEAT": self.heartbeat_handler,
            "CONNECTED": self.connected_handler
        }

        # Enable logging
        self.logger = create_logger("controller", level=log_level)
        self.event_log = create_logger("events")

        self.ctx = zmq.Context()
        self.socket = SocketServer(ctx=self.ctx)
        self.socket.register_handler(self.dispatch)
        self.socket.bind(address)

        if voiceserver:
            self.voice_pipe, self._voice_child_pipe = Pipe()
            self.voice_server = VoiceServer(self._voice_child_pipe)
            self.voice_server.start()
        else:
            self.voice_pipe, self._voice_child_pipe = None, None
            self.voice_server = None
Esempio n. 3
0
    def copy_word_pool(self, data_root, language="en", include_lures=False):
        """Copy word pools to the subject's data root directory. This method
        only needs to be called the first time an experiment is run with a
        given subject.

        FIXME: this should probably be a member of WordTask

        :param str data_root: Path to data root directory.
        :param str language: Language to use for the pools (English or Spanish).
        :param bool include_lures: Include lure word pool.
        :raises LanguageError: when a passed language is unavailable

        """
        logger = create_logger(__name__)
        logger.info("Copying word pool(s)...")

        # Validate language selection
        lang = language[:2].lower()
        if lang not in ["en", "sp"]:
            raise LanguageError("Invalid language: " + lang)
        if include_lures:
            if lang == "sp":
                raise LanguageError("Spanish lures are not yet available.")

        if self.family == "FR" or self.family == "PAL":
            cat = False
        elif self.family == "catFR":
            cat = True
        else:
            raise RAMException("Invalid family: ", self.family)
        listgen.write_wordpool_txt(data_root,
                                   include_lure_words=include_lures,
                                   categorized=cat)
Esempio n. 4
0
    def __init__(self, ctx=None):
        self.ctx = ctx or zmq.Context()

        self._handlers = []

        self.sock = self.ctx.socket(zmq.PAIR)
        self._bound = False

        self.poller = zmq.Poller()
        self.poller.register(self.sock, zmq.POLLIN)

        # Outgoing message queue
        self._out_queue = Queue()

        # time of last sent heartbeat message
        self._last_heartbeat = 0.

        # Logging of sent and received messages.
        self.logger = create_logger("network")
Esempio n. 5
0
    def run(self):
        self.logger = create_logger("voiceserver", level=self.loglevel)

        audio = PyAudio()

        vad_thread = Thread(target=self.check_for_speech)
        vad_thread.daemon = True
        vad_thread.start()
        mic_thread = None  # later, the thread to read from the mic

        while not self.done.is_set():
            try:
                if self.pipe.poll(1):
                    msg = self.pipe.recv()
                else:
                    continue

                if msg["type"] == "START":
                    self.logger.info("Got request to start VAD")
                    stream, wav = self.open_audio_stream(audio)
                    mic_thread = Thread(target=self.read_audio_stream,
                                        args=(stream, wav))
                    mic_thread.start()
                    self.pipe.send(ipc.message("STARTED"))

                elif msg["type"] == "STOP":
                    self.logger.info("Got request to stop VAD")
                    self.stop_stream.set()
                    self.pipe.send(ipc.message("STOPPED"))

                else:
                    self.logger.error(
                        "Unexpected message type received. Message: %s", msg)
                    continue
            except EOFError:
                self.logger.error("Broken pipe", exc_info=True)
                self.quit()

        audio.terminate()
Esempio n. 6
0
    def __init__(self, epl_exp, family, debug=False, **kwargs):
        self.family = family
        self.debug = debug
        self.kwargs = kwargs

        assert isinstance(epl_exp, exputils.Experiment)
        self.epl_exp = epl_exp
        self.controller = RAMControl.instance()

        self.clock = exputils.PresentationClock()
        self.config = self.epl_exp.getConfig()
        self.logger = create_logger(
            "experiment", level=(logging.DEBUG if debug else logging.INFO))
        self.event_logger = create_logger("events")

        if self.debug and self.kwargs.get("fast_timing", False):
            self.timings = Timings.make_debug()
        else:
            self.timings = Timings.make_from_config(self.config)

        # Experiment name
        self.name = self.config.experiment

        # Session must be set before creating tracks, apparently
        self.epl_exp.setSession(self.session)

        # Create all tracks
        self.log = LogTrack("session")
        self.mathlog = LogTrack("math")
        self.keyboard = KeyTrack("keyboard")

        # Prepare the experiment if not already done
        if not self.experiment_started:
            self.prepare_experiment()

        # Set up the RAMControl instance
        # TODO: get rid of this monstrosity
        self.controller.configure(self.config.experiment, self.config.version,
                                  self.session, self.subject)

        # Set network log path
        self.controller.socket.log_path = self.session_data_dir

        # Initialize video and audi
        self.video = VideoTrack("video")
        self.audio = CustomAudioTrack("audio")

        # Helpers for common PyEPL routines
        self.epl_helpers = PyEPLHelpers(self.epl_exp, self.video, self.audio,
                                        self.clock)

        # If the session should be skipped, we're done here
        self._ok_to_run = not self._skip_session_dialog()
        if not self._ok_to_run:
            self.log_event('SESSION_SKIPPED')
            self.update_state(session_number=(self.session + 1),
                              session_started=False)
            self.reset_state()
            return

        # Finalize preparation for the session
        self.prepare_session()