00001 /*!@file Psycho/StimListener.H an abstraction that recieves stimulus 00002 commands from a host and pushes them into a buffer that can be 00003 shared by other compononents. A specific implementation using UDP 00004 packets for the Rex recording system is included. Rex used in the 00005 Doug Munoz laboratory in Kinston, ON. This system is a standard 00006 electrophysiology tool. */ 00007 00008 // //////////////////////////////////////////////////////////////////// // 00009 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00010 // University of Southern California (USC) and the iLab at USC. // 00011 // See http://iLab.usc.edu for information about this project. // 00012 // //////////////////////////////////////////////////////////////////// // 00013 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00014 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00015 // in Visual Environments, and Applications'' by Christof Koch and // 00016 // Laurent Itti, California Institute of Technology, 2001 (patent // 00017 // pending; application number 09/912,225 filed July 23, 2001; see // 00018 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00019 // //////////////////////////////////////////////////////////////////// // 00020 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00023 // redistribute it and/or modify it under the terms of the GNU General // 00024 // Public License as published by the Free Software Foundation; either // 00025 // version 2 of the License, or (at your option) any later version. // 00026 // // 00027 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00028 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00029 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00030 // PURPOSE. See the GNU General Public License for more details. // 00031 // // 00032 // You should have received a copy of the GNU General Public License // 00033 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00034 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00035 // Boston, MA 02111-1307 USA. // 00036 // //////////////////////////////////////////////////////////////////// // 00037 // 00038 // Primary maintainer for this file: David Berg <dberg@usc.edu> 00039 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/StimListener.H $ 00040 00041 #ifndef PSYCHO_STIMLISTENER_H_FEFINED 00042 #define PSYCHO_STIMLISTENER_H_FEFINED 00043 00044 #include <sys/socket.h> 00045 #include <netdb.h> 00046 00047 #include "Component/EventLog.H" 00048 #include "Util/JobServer.H" 00049 #include "Util/SharedBuffer.H" 00050 #include "rutz/shared_ptr.h" 00051 #include "Psycho/StimData.H" 00052 00053 //!Interface for a stimulus listener 00054 /*!A StimListener can listen for stimulus commands from connected 00055 hosts and places them in a shared buffer. This buffer can then be 00056 read by other components to actually render the requested stimuli 00057 on the screen. This class is a JobServer::Job, which should be used 00058 with a JobServer derivitive. When queued this job will listen for 00059 commands in its own thread.*/ 00060 //###################################################################### 00061 class StimListener : public JobServer::Job 00062 { 00063 public: 00064 //!constructor 00065 StimListener(); 00066 00067 //!destructor 00068 virtual ~StimListener(); 00069 00070 //!set the buffer from a shared pointer 00071 void setBuffer(const rutz::shared_ptr<SharedBuffer<StimData> >& buffer); 00072 00073 //! set the log file from a shared pointer 00074 void setEventLog(const nub::soft_ref<EventLog>& log); 00075 00076 //! any pre listening initialization should go here 00077 virtual void start(); 00078 00079 //! clean things up after listening is over 00080 virtual void stop(); 00081 00082 /*! send a message, usually back to the sender. Derived classes need 00083 to implement this.*/ 00084 virtual bool sendMessage(const unsigned char* msg) = 0; 00085 00086 //! listen for stimulus codes, Default is Empty. 00087 virtual bool listen() = 0; 00088 00089 //!From Jobserver::Job 00090 //###################################################################### 00091 00092 //!the actual work, called by JobServer after being queued 00093 virtual void run(); 00094 00095 //!return the job name 00096 virtual const char* jobType() const; 00097 00098 //!return the priority, 0 for highest 00099 virtual int priority() const; 00100 00101 protected: 00102 //! push an event to the log, if uselinfo is true also display to the screen 00103 void pushEvent(const std::string& msg, const bool& uselinfo = false); 00104 00105 //!push data onto the shared buffer 00106 void addData(const StimData& const data); 00107 00108 private: 00109 //prohibit copy and assignment 00110 StimListener& operator=(const StimListener& rhs); 00111 StimListener(const StimListener& rhs); 00112 00113 // log stuff if desired: 00114 nub::soft_ref<EventLog> itsEventLog; 00115 00116 //shared buffer to store incoming commands 00117 rutz::shared_ptr<SharedBuffer<StimData> > itsBuffer; 00118 }; 00119 00120 // ###################################################################### 00121 //!a class to control communication with the Rex experimental control system 00122 // ###################################################################### 00123 /*! A derived class of StimulusListener to support comunication with 00124 the Rex experimental control system, which is a standard tool in 00125 electrophysiology labs. This system is designed to recieve UPD 00126 packets from Rex that indicate the stimulus to be drawn. The 00127 packets contain 1 byte for the stimulus primitive type (e.g. circle), 00128 and several bytes for the stimulus parameters (e.g. size, color). */ 00129 00130 class StimListenerDML: public StimListener 00131 { 00132 public: 00133 //!constructor 00134 StimListenerDML(unsigned char exitcode = '0', const unsigned char[] = "1\0"); 00135 00136 //!destructor 00137 virtual ~StimListenerDML(); 00138 00139 //!send a message back to the host using a UDP packet 00140 bool sendMessage(const unsigned char* msg); 00141 00142 //! listen for codes, which are UDP packets, usually 2-4 bytes long 00143 bool listen(); 00144 00145 //! set the host name 00146 /*! If set the listener will only accept packets from a specific 00147 host. Additionally, messages will be sent specifically to this 00148 host. If no host is set packets will be accepted by anyone, and 00149 status messages will be sent back to the last sender (Not 00150 gaurnteed on all systems). In most cases the host should be set 00151 to avoid problems with some systems not supplying the packet 00152 senders address and erroring on sendMessage() and sendOK() */ 00153 void setHostName(const std::string hostname); 00154 00155 //!get our component going and do pre-listening stuff 00156 void start(); 00157 00158 //!clean things up 00159 void stop(); 00160 00161 //!return the job name 00162 const char* jobType() const; 00163 00164 00165 private: 00166 //!Send an confirmation message to the host 00167 void sendOK(); 00168 00169 int sockfd; //our socket 00170 00171 struct addrinfo *myInfo, *hostInfo; //adress info 00172 00173 //hold info about the last socket 00174 struct sockaddr lasthost_addr; 00175 socklen_t lasthost_addrlen; 00176 00177 fd_set master; // master file descriptor list 00178 00179 volatile bool keepGoing; // to sop all listening loops without a command, 00180 // maybe this needs to be atomic, but I think OK. 00181 00182 //!defaults status code to stop listening 00183 unsigned char itsExitCode; 00184 00185 //!are we ready to listen? 00186 bool itsConnected; 00187 00188 //for our status message - used during sendOK() 00189 unsigned char* itsMsg; 00190 }; 00191 00192 #endif 00193 // ###################################################################### 00194 /* So things look consistent in everyone's emacs... */ 00195 /* Local Variables: */ 00196 /* indent-tabs-mode: nil */ 00197 /* End: */ 00198