//////////////////////////////////////////////////////////////////////// // // TobiiClient.c: こじ研 TobiiClient API ソースファイル // version 1.1 (August 25, 2010) // xkozima@myu.ac.jp (subject to GPLv2) // // document: http://www.myu.ac.jp/~xkozima/lab/gaze-tobii2.html #ifdef _WIN32 // Windows #include #include #include #include #include "TobiiClient.h" #define UnivSocket SOCKET #define UnivSockaddrIn SOCKADDR_IN #define UnivHostentP LPHOSTENT #define UnivInAddrP LPIN_ADDR #define UnivInvalidSocket INVALID_SOCKET #define UnivSocketError SOCKET_ERROR #define univWrite(s,b,l) send(s,b,l,0) #define univRead(s,b,l) recv(s,b,l,0) #define univClose(s) {closesocket(s);WSACleanup();} #define univSleep(msec) Sleep(msec) // #else // Mac/Linux #include #include #include #include #include #include #include #include #include #include "TobiiClient.h" #define UnivSocket int #define UnivSockaddrIn struct sockaddr_in #define UnivHostentP struct hostent* #define UnivInAddrP struct in_addr* #define UnivInvalidSocket -1 #define UnivSocketError -1 #define univWrite(s,b,l) write(s,b,l) #define univRead(s,b,l) read(s,b,l) #define univClose(s) close(s) #define univSleep(msec) usleep((msec)*1000) // #endif #define TOBII_PORT 16439 //////////////////////////////////// // // 要求データ Request #define TOBII_NONE 0 // 何もしない #define TOBII_GETGAZE 1 // 視線データをゲット struct _TobiiRequest { int action; // 0:TOBII_NONE, 1:TOBII_GETGAZE int param; // 未使用(拡張機能のために予約) }; typedef struct _TobiiRequest TobiiRequest; //////////////////////////////////// // // API 関数群 static int Connected = 0; static UnivSocket Socket; // // TobiiServer に接続する(最初に1回これを呼ぶ) // int res = TobiiConnect("10.0.1.6"); // int res = TobiiConnect("tobii.myu.ac.jp"); // (戻り値:0=成功, -1=失敗) int TobiiConnect (char *server_name) { UnivHostentP entry; UnivSockaddrIn address; int res; // もし既にサーバに接続していたら何もしない if (Connected) return 0; #ifdef _WIN32 // ウインドウズ特有のオマジナイ(ソケット関係の初期化) WORD wVersionRequested = MAKEWORD(2, 0); WSADATA wsaData; res = WSAStartup(wVersionRequested, &wsaData); if (res != 0) return -1; #endif // ホスト名からアドレスを引く entry = gethostbyname(server_name); if (entry == NULL) { fprintf(stderr, "TobiiConnect: server not found\n"); return -1; } if (entry->h_addrtype != AF_INET) { fprintf(stderr, "TobiiConnect: not an IP host\n"); return -1; } // ソケットに与えるアドレスの設定 memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; #ifdef _WIN32 address.sin_addr = * ((UnivInAddrP) *entry->h_addr_list); #else address.sin_addr = * ((UnivInAddrP) entry->h_addr); #endif address.sin_port = htons(TOBII_PORT); // ソケットを生成 Socket = socket(AF_INET, SOCK_STREAM, 0); if (Socket == UnivInvalidSocket) { fprintf(stderr, "TobiiConnect: cannot creat a socket\n"); return -1; } // サーバにソケットを接続 res = connect(Socket, (struct sockaddr *) &address, sizeof(address)); if (res == UnivSocketError) { fprintf(stderr, "TobiiConnect: cannot connect to the server\n"); univClose(Socket); return -1; } // 接続完了 Connected = 1; return 0; } // // パケットを送信・受信(内部使用) int tobii_send (char *pac, int len) { int res; // 未接続なら何もしない if (! Connected) return 0; // サーバへデータを送信(最初) res = univWrite(Socket, pac, len); if (res == 0 || res == UnivSocketError) { // サーバと切断されたらしい fprintf(stderr, "tobii_send: writing to the socket failed\n"); univClose(Socket); Connected = 0; return -1; } // 全バイト送り出すまで繰り返し while (res < len) { int res_rem; // 残りデータを送信 res_rem = univWrite(Socket, pac+res, len-res); if (res_rem == -1) { // サーバと切断されたらしい fprintf(stderr, "tobii_send: writing the remainder failed\n"); univClose(Socket); Connected = 0; return -1; } res += res_rem; } // 送信完了 return res; } // // パケットを受信(内部使用) int tobii_receive (char *pac, int len) { int res; // 未接続なら何もしない if (! Connected) return 0; // サーバからデータを受信(最初) res = univRead(Socket, pac, len); if (res == 0 || res == UnivSocketError) { // サーバと切断されたらしい fprintf(stderr, "tobii_receive: reading from the socket failed\n"); univClose(Socket); Connected = 0; return -1; } // 全バイト受け取るまで繰り返し while (res < len) { int res_rem; // reading the remainder res_rem = univRead(Socket, pac+res, len-res); if (res_rem == -1) { // サーバと切断されたらしい fprintf(stderr, "tobii_receive: reading the remainder failed\n"); univClose(Socket); Connected = 0; return -1; } res += res_rem; } // 受信完了 return res; } // // TobiiServer から視線データを取得する // TobiiGazeData data; // TobiiGetData(&data); // float X = (data.x_gazepos_lefteye + data.x_gazepos_righteye) / 2.0; // float Y = (data.y_gazepos_lefteye + data.y_gazepos_righteye) / 2.0; // doSomething(X, Y); void TobiiGetData (TobiiGazeData *gaze_data) { TobiiRequest request; int res; // 未接続なら何もしない if (! Connected) return; // 要求パケットを用意 request.action = TOBII_GETGAZE; request.param = 0; res = tobii_send((char *) &request, sizeof(TobiiRequest)); if (res <= 0) { fprintf(stderr, "TobiiGetData: failed to send a request\n"); return; } // receive gaze data res = tobii_receive((char *) gaze_data, sizeof(TobiiGazeData)); if (res <= 0) { fprintf(stderr, "TobiiGetData: failed to receive data\n"); return; } } // // TobiiServer から切断する(最後に1回これを呼ぶ) void TobiiDisconnect () { // 未接続なら何もしない if (! Connected) return; // サーバへの接続ソケットを閉じる univClose(Socket); Connected = 0; } // // TobiiServer との接続の有無を調べる // if (TobiiIsConnected()) // printf("Yes, we can!\n"); // else // printf("I'm disconnected from the world...\n"); // (戻り値:0=接続なし, 1=接続あり) int TobiiIsConnected () { return Connected; } // // ミリ秒単位のスリープ(時間調整用) void TobiiSleep (int msec) { univSleep(msec); } ////////////////////////////////////////////////////////////////////////