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)
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
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)
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")
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()
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()