00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifdef _WIN32
00017
00018
00019 #include <winsock.h>
00020
00021 #else
00022
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <pthread.h>
00026
00027 #endif
00028
00029 #include "displayreplicator.h"
00030
00031 #ifdef _WIN32
00032 #include <glut.h>
00033 #else
00034 #include <GLUT/glut.h>
00035 #include <OpenGL/gl.h>
00036 #endif
00037
00038
00039 #include <time.h>
00040 #include <sys/timeb.h>
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include "timer.h"
00044
00045
00046 #include <iostream>
00047
00048 #include "glui.h"
00049
00050 using namespace std;
00051
00052 const char* DisplayReplicator::rcsid = "@(#) $Id: displayreplicator.cpp,v 1.61 2006/05/31 00:39:08 craig Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00053
00054 #define BLOCKSIZE_X 16
00055 #define BLOCKSIZE_Y 16
00056 #define MAXBLOCKS_X 2048/BLOCKSIZE_X
00057 #define MAXBLOCKS_Y 2048/BLOCKSIZE_Y
00058 #define PERCENT_CHANGE_MAX (-100)
00059 #define RGB_CHANGE_MAX (25)
00060
00061 #define MAX_WIDTH 640
00062 #define MAX_HEIGHT 480
00063 #define MAX_LENGTH_JPEG 100000
00064
00065 char old_data[2][MAXBLOCKS_X][MAXBLOCKS_Y][BLOCKSIZE_X][BLOCKSIZE_Y][3];
00066 bool oldDataInitialized = false;
00067 bool headerInitialized = false;
00068 int do_switchboard = 1;
00069
00070
00071 const char* handshake = "displayserver v3.0";
00072
00073
00074 #ifndef SGI
00075 #ifndef __APPLE__
00076 LPBYTE OutputBuffer = new unsigned char[MAX_LENGTH_JPEG];
00077 DWORD OutputLength;
00078 BITMAPINFO OutputBitmapInfo;
00079 LPBYTE OutputBuffer2;
00080 DWORD OutputLength2;
00081 BITMAPINFO OutputBitmapInfo2;
00082 #endif // __APPLE__
00083 #endif // SGI
00084
00085 void DisplayReplicator::InitHeader(int conf_width, int conf_height)
00086 {
00087 #ifndef SGI
00088 #ifndef __APPLE__
00089 int main_size = conf_width*conf_height*3;
00090 #define PUT_2B(array,offset,value) \
00091 (array[offset] = (char) ((value) & 0xFF), \
00092 array[offset+1] = (char) (((value) >> 8) & 0xFF))
00093 #define PUT_4B(array,offset,value) \
00094 (array[offset] = (char) ((value) & 0xFF), \
00095 array[offset+1] = (char) (((value) >> 8) & 0xFF), \
00096 array[offset+2] = (char) (((value) >> 16) & 0xFF), \
00097 array[offset+3] = (char) (((value) >> 24) & 0xFF))
00098
00099 WHeader = (BYTE*)calloc(54+main_size,sizeof(BYTE));
00100
00101 WHeader[0] = 66;
00102 WHeader[1] = 77;
00103 PUT_4B(WHeader,2,main_size+54);
00104 PUT_4B(WHeader,10,54);
00105 PUT_4B(WHeader,14,40);
00106 PUT_4B(WHeader,18,conf_width);
00107 PUT_4B(WHeader,22,conf_height);
00108 PUT_2B(WHeader,26,1);
00109 PUT_2B(WHeader,28,24);
00110 PUT_4B(WHeader,34,main_size);
00111 #endif // __APPLE__
00112 #endif
00113 }
00114
00115 int DisplayReplicator::debug = 0;
00116
00117
00118 DisplayReplicator::DisplayReplicator(int port_in, source_type source_in)
00119 {
00120 num_socks = 0;
00121 port = port_in;
00122
00123 mode = unknown;
00124 source = source_in;
00125
00126 width = height = -1;
00127 height = MAX_HEIGHT;
00128 keyfn = NULL; specialfn = NULL; mousefn = NULL; motionfn = NULL;
00129
00130
00131 block_size = BLOCKSIZE_X * BLOCKSIZE_Y * 3;
00132 block = new char[block_size];
00133 buf_size = block_size + 4;
00134
00135 if (buf_size < MAX_BUF_SIZE)
00136 g_buf = new char[MAX_BUF_SIZE];
00137 else
00138 g_buf = new char[buf_size];
00139
00140 gl_buf = new char[640*480*3];
00141
00142
00143
00144 buf = g_buf;
00145
00146
00147 res_reduction = 1;
00148 compression = JPEG;
00149
00150
00151
00152
00153 comparison_threshold = (int) (PERCENT_CHANGE_MAX / 100.0f * block_size);
00154 from_windows = 0;
00155
00156 switch (compression) {
00157 default:
00158 case color_24bit:
00159 comp_size = BLOCKSIZE_X * BLOCKSIZE_Y * 3;
00160 break;
00161 case color_16bit:
00162 comp_size = BLOCKSIZE_X * BLOCKSIZE_Y * 2;
00163 break;
00164 case color_8bit:
00165 comp_size = BLOCKSIZE_X * BLOCKSIZE_Y * 1;
00166 break;
00167 case greyscale:
00168 comp_size = BLOCKSIZE_X * BLOCKSIZE_Y * 1;
00169 break;
00170 }
00171
00172 buf_size = comp_size + 4;
00173 if (buf_size < MAX_BUF_SIZE)
00174 g_buf = new char[MAX_BUF_SIZE];
00175 else
00176 g_buf = new char[buf_size];
00177 buf = g_buf;
00178
00179 JPEG_data = new char[MAX_WIDTH*MAX_HEIGHT*3];
00180
00181 mySocketBuffer = new char[MAX_BUF_SIZE];
00182 curBufLen = 0;
00183
00184 memset(old_data, 0, sizeof(old_data));
00185 }
00186
00187 DisplayReplicator::~DisplayReplicator()
00188 {
00189 for (int i=0; i<num_socks; i++)
00190 if (sock[i]) delete sock[i];
00191 mode = unknown;
00192 width = height = -1;
00193 keyfn = NULL; specialfn = NULL; mousefn = NULL; motionfn = NULL;
00194 if (block) { delete block; block = NULL; }
00195 if (g_buf) { delete buf; buf = NULL; }
00196 if (mySocketBuffer) { delete mySocketBuffer; mySocketBuffer = NULL; }
00197 }
00198
00199
00200 void DisplayReplicator::setCompression(compression_type comp)
00201 {
00202 compression = comp;
00203 }
00204
00205
00206 int DisplayReplicator::send_buf_out_socket(int sock_index, int size, char *whichBuf)
00207 {
00208 if (whichBuf == NULL)
00209 whichBuf = buf;
00210
00211 if (debug == 3)
00212 cerr << "DisplayReplicator::send_buf_out_socket(" << sock_index
00213 << ", " << size << ")\n";
00214
00215
00216 int start = 0, end = num_socks-1;
00217 int ret_val = 0;
00218
00219
00220 if (sock_index != -1) {
00221 start = sock_index; end = sock_index;
00222 }
00223
00224
00225 for (int i=start; i<=end; i++) {
00226 if (!sock[i]) continue;
00227
00228 int status = sock[i]->BufferedSend(whichBuf, size);
00229
00230
00231 if (!status) {
00232 cerr << "LOST CONNECTION ON SOCKET " << i << endl;
00233 Disconnect(i);
00234 ret_val = -1;
00235 continue;
00236 }
00237 }
00238 return(ret_val);
00239 }
00240
00241
00242 void DisplayReplicator::SetParams(int rr_in, compression_type compression_in,
00243 int comparison_threshold_in, int from_win)
00244 {
00245 res_reduction = rr_in;
00246 compression = compression_in;
00247 comparison_threshold = comparison_threshold_in;
00248
00249
00250 buf[0] = 3; buf[1] = char(res_reduction); buf[2] = char(compression);
00251 buf[3] = char(from_win);
00252
00253
00254 send_buf_out_socket(-1, buf_size);
00255 }
00256
00257
00258 int DisplayReplicator::compare_blocks(char* block1, char* block2)
00259 {
00260
00261 if ((comparison_threshold < 0) || (!oldDataInitialized)) return(1);
00262
00263
00264 int s = 0;
00265 for (int i=0; i<block_size; i++) {
00266 char c1 = block1[i], c2 = block2[i], cdiff;
00267 if (c1 > c2) cdiff = c1 - c2;
00268 else cdiff = c2 - c1;
00269 if (cdiff >= RGB_CHANGE_MAX) {
00270 if (comparison_threshold == s) return (1);
00271 ++s;
00272 }
00273 }
00274 return(0);
00275 }
00276
00277 int DisplayReplicator::encode_block_into_buf(int buf_code,
00278 int x_loc, int y_loc, int seq_id, char* block)
00279 {
00280 buf[0] = (char)0xe2;
00281 if (compression != JPEG)
00282 {
00283 buf[1] = 0x00;
00284 buf[2] = (unsigned char)(buf_code);
00285 buf[3]= (unsigned char)(x_loc);
00286 buf[4] = (unsigned char)(y_loc);
00287 }
00288 else
00289 {
00290 buf[1] = 0x01;
00291 buf[2] = (unsigned char)(buf_code);
00292 buf[3] = (unsigned char)(from_windows);
00293 buf[4] = 0x00;
00294 }
00295
00296 int reduction_factor = 1 << (res_reduction-1);
00297
00298 int x,y;
00299 int buf_index = 5;
00300 switch (compression) {
00301 default:
00302 case color_24bit:
00303 for ( x=0; x<BLOCKSIZE_X; x += reduction_factor)
00304 for ( y=0; y<BLOCKSIZE_Y; y += reduction_factor)
00305 {
00306 int block_index = x*BLOCKSIZE_Y*3+y*3;
00307 buf[buf_index++] = (unsigned char)block[block_index++];
00308 buf[buf_index++] = (unsigned char)block[block_index++];
00309 buf[buf_index++] = (unsigned char)block[block_index++];
00310 }
00311 break;
00312
00313 case color_16bit:
00314 for ( x=0; x<BLOCKSIZE_X; x += reduction_factor)
00315 for ( y=0; y<BLOCKSIZE_Y; y += reduction_factor)
00316 {
00317 int block_index = x*BLOCKSIZE_Y*3+y*3;
00318 unsigned char r = block[block_index+0];
00319 unsigned char g = block[block_index+1];
00320 unsigned char b = block[block_index+2];
00321 buf[buf_index+0] = (r >> 2) << 2 | (g >> 6);
00322 buf[buf_index+1] = ((g&0x3f) >> 3) << 5 | (b >> 3);
00323 buf_index += 2;
00324 }
00325 break;
00326
00327 case color_8bit:
00328 for ( x=0; x<BLOCKSIZE_X; x += reduction_factor)
00329 for ( y=0; y<BLOCKSIZE_Y; y += reduction_factor)
00330 {
00331 int block_index = x*BLOCKSIZE_Y*3+y*3;
00332 unsigned char r = block[block_index+0];
00333 unsigned char g = block[block_index+1];
00334 unsigned char b = block[block_index+2];
00335 buf[buf_index] = (r & 0xe0) | ((g&0xe0) >> 3) | ((b&0xc0) >> 6);
00336 buf_index++;
00337 }
00338 break;
00339
00340 case greyscale:
00341 for ( x=0; x<BLOCKSIZE_X; x += reduction_factor)
00342 for ( y=0; y<BLOCKSIZE_Y; y += reduction_factor)
00343 {
00344 int block_index = x*BLOCKSIZE_Y*3+y*3;
00345 unsigned char r = block[block_index+0];
00346 unsigned char g = block[block_index+1];
00347 unsigned char b = block[block_index+2];
00348 buf[buf_index] = (r + g + b)/3;
00349 buf_index++;
00350 }
00351 break;
00352 case JPEG: {
00353 #ifndef SGI
00354 #ifndef __APPLE__
00355 int lBufferSize = width*height*3;
00356 if (!headerInitialized)
00357 {
00358 InitHeader(width, height);
00359 headerInitialized = true;
00360 }
00361 memcpy(WHeader + 54,block,lBufferSize);
00362
00363 #ifdef _WIN32
00364 CompressToJPEG(WHeader,lBufferSize + 54,&OutputBuffer,&OutputLength);
00365 #endif
00366
00367 memcpy(buf+5, OutputBuffer, OutputLength);
00368 return (OutputLength+5);
00369 #endif // __APPLE__
00370 #endif
00371 }
00372 }
00373
00374 return(buf_index);
00375 }
00376
00377 void DisplayReplicator::decode_block_from_buf(int* buf_code_p,
00378 int* x_p, int* y_p, int* seq_id_p, char* block, int JPEG_size)
00379 {
00380 *buf_code_p = int((unsigned char)buf[2]);
00381 *x_p = int((unsigned char)buf[3]);
00382 *y_p = int((unsigned char)buf[4]);
00383 *seq_id_p = 1;
00384 int x,y;
00385
00386 int reduction_factor = 1 << (res_reduction-1);
00387
00388 if (reduction_factor == 1)
00389 {
00390
00391 char *ptBuf = buf + 4;
00392 char *ptBlock = block;
00393
00394 switch (compression) {
00395 default:
00396 case color_24bit:
00397 memcpy(block, buf + 4, block_size);
00398 break;
00399 case color_16bit:
00400 for ( x=0; x<BLOCKSIZE_X; ++x) {
00401 for ( y=0; y<BLOCKSIZE_Y; ++y) {
00402 *(ptBlock++) = *ptBuf & 0xfc;
00403 *ptBlock = *ptBuf << 6;
00404 *(ptBlock++) |= (*(++ptBuf) & 0xe0) >> 2;
00405 *(ptBlock++) = *(ptBuf++) << 3;
00406 }
00407 }
00408 break;
00409 case color_8bit:
00410 for ( x=0; x<BLOCKSIZE_X; ++x) {
00411 for ( y=0; y<BLOCKSIZE_Y; ++y) {
00412 *(ptBlock++) = *ptBuf & 0xe0;
00413 *(ptBlock++) = (*ptBuf & 0x1c) << 3;
00414 *(ptBlock++) = (*(ptBuf++) & 0x03) << 6;
00415 }
00416 }
00417 break;
00418 case greyscale:
00419 for ( x=0; x<BLOCKSIZE_X; ++x) {
00420 for ( y=0; y<BLOCKSIZE_Y; ++y) {
00421 *(ptBlock++) = *ptBuf;
00422 *(ptBlock++) = *ptBuf;
00423 *(ptBlock++) = *(ptBuf++);
00424 }
00425 }
00426 break;
00427 case JPEG: {
00428 #ifndef SGI
00429 #ifndef __APPLE__
00430 #ifdef WIN_32
00431 ExpandJPEGTo24BitDIB((BYTE*)ptBuf,JPEG_size,&OutputBuffer2,&OutputLength2);
00432 #endif
00433
00434 memcpy(ptBlock,OutputBuffer2, OutputLength2);
00435 delete OutputBuffer2;
00436 #endif // __APPLE__
00437 #endif
00438 break;
00439 }
00440 }
00441 }
00442 else
00443 {
00444 cerr << "Oups\n";
00445 int buf_index = 4;
00446 for ( x=0; x<BLOCKSIZE_X; x += reduction_factor) {
00447 for ( y=0; y<BLOCKSIZE_Y; y += reduction_factor) {
00448 int block_index = x*BLOCKSIZE_Y*3+y*3;
00449 unsigned char r,g,b;
00450 switch (compression) {
00451 default:
00452 case color_24bit:
00453 r = buf[buf_index+0];
00454 g = buf[buf_index+1];
00455 b = buf[buf_index+2];
00456 buf_index += 3;
00457 break;
00458 case color_16bit:
00459 r = buf[buf_index] & 0xfc;
00460 g = (buf[buf_index] << 6) | ((buf[buf_index+1]&0xe0) >> 2);
00461 b = (buf[buf_index+1] << 3);
00462 buf_index += 2;
00463 break;
00464 case color_8bit:
00465 r = buf[buf_index] & 0xe0;
00466 g = (buf[buf_index] & 0x1c) << 3;
00467 b = (buf[buf_index] & 0x03) << 6;
00468 buf_index++;
00469 break;
00470 case greyscale:
00471 r = g = b = buf[buf_index];
00472 buf_index++;
00473 break;
00474 }
00475
00476
00477
00478 for (int xx=0; xx<reduction_factor; xx++) {
00479 for (int yy=0; yy<reduction_factor; yy++) {
00480 int subblock_index = block_index + xx*BLOCKSIZE_Y*3 +yy*3;
00481 block[subblock_index + 0] = r;
00482 block[subblock_index + 1] = g;
00483 block[subblock_index + 2] = b;
00484 }
00485 }
00486 }
00487 }
00488 }
00489 }
00490
00491
00492 int DisplayReplicator::SendBlock(int buf_code, int x, int y,
00493 char* block, int which_socket, int is_a_resend, bool flushBuffer)
00494 {
00495 int len;
00496
00497
00498 if ((flushBuffer) && (block == NULL))
00499 {
00500 if (debug) cerr << "Flush Required with Block = NULL and curBufLen = " << curBufLen << "\n";
00501 if (curBufLen > 0)
00502 send_buf_out_socket(which_socket, curBufLen, (char *)mySocketBuffer);
00503 curBufLen = 0;
00504 return -1;
00505 }
00506
00507
00508 int seq_id = -1;
00509
00510
00511
00512 len = encode_block_into_buf(buf_code, x, y, seq_id, (char*)block);
00513
00514 if ((len > buf_size) && (debug))
00515 cerr << "Warning : size of encoded block (=" << len
00516 << ") > size of buffer (=" << buf_size << ")\n";
00517
00518
00519 if (debug == 3)
00520 cerr << "Sending block " << int(buf_code) << ", " << x << ", " << y << endl;
00521
00522
00523
00524
00525 if(flushBuffer)
00526 {
00527 if (debug) cerr << "Flush Required ";
00528
00529
00530 if ((curBufLen + len >= MAX_BUF_SIZE) && (curBufLen > 0))
00531 {
00532 if (debug) cerr << "causing BufferOverflow ";
00533 send_buf_out_socket(which_socket, curBufLen, (char *)mySocketBuffer);
00534 curBufLen = 0;
00535 }
00536
00537 if (debug) cerr << "with curBufLen = " << curBufLen << " and len = " << len << "\n";
00538
00539
00540 if (curBufLen == 0)
00541 send_buf_out_socket(which_socket, len, NULL);
00542
00543 else
00544 {
00545 memcpy(&mySocketBuffer[curBufLen], buf, len);
00546 send_buf_out_socket(which_socket, curBufLen + len, (char *)mySocketBuffer);
00547 curBufLen = 0;
00548 }
00549 }
00550
00551 else
00552 {
00553
00554 if (len > MAX_BUF_SIZE)
00555 {
00556 if (debug) cerr << "Flush Forced with MAX_BUF_SIZE < len (=" << len << ")\n";
00557 send_buf_out_socket(which_socket, len, NULL);
00558 }
00559
00560 else if (curBufLen + len >= MAX_BUF_SIZE)
00561 {
00562 if (debug) cerr << "Flush Forced with BufferOverflow, curBufLen = " << curBufLen << "\n";
00563 send_buf_out_socket(which_socket, curBufLen, (char *)mySocketBuffer);
00564 memcpy(&mySocketBuffer[0], buf, len);
00565 curBufLen = len;
00566 }
00567 else
00568 {
00569 memcpy(&mySocketBuffer[curBufLen], buf, len);
00570 curBufLen += len;
00571 }
00572 }
00573
00574
00575 return(len);
00576 }
00577
00578 void DisplayReplicator::PaintBlock(int which_buffer, char xloc, char yloc,
00579 char* block,bool paintAll)
00580 {
00581 if (!paintAll)
00582 {
00583 glDrawBuffer(which_buffer);
00584 glRasterPos2i(xloc * BLOCKSIZE_X, yloc * BLOCKSIZE_Y);
00585 glDrawPixels(BLOCKSIZE_X, BLOCKSIZE_Y, GL_RGB, GL_UNSIGNED_BYTE, block);
00586 }
00587 else
00588 {
00589 glDrawBuffer(which_buffer);
00590 glRasterPos2i(xloc * BLOCKSIZE_X, yloc * BLOCKSIZE_Y);
00591 if (!from_windows)
00592 glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, block);
00593 else {
00594 #ifdef _WIN32
00595 glDrawPixels(width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, block);
00596 #else
00597 glDrawPixels(width, height, GL_BGR, GL_UNSIGNED_BYTE, block);
00598 #endif
00599 }
00600 }
00601 }
00602
00603 void DisplayReplicator::Reshape(int w, int h)
00604 { width = w; height = h;
00605 #ifndef SGI
00606 #ifndef __APPLE__
00607 delete WHeader;
00608 InitHeader(w,h);
00609 headerInitialized = true;
00610 #endif // __APPLE__
00611 #endif
00612 }
00613
00614 void DisplayReplicator::SendKeyEvent(char key, int x, int y)
00615 {
00616 if (debug) cerr << "Sending key " << key << " @ " << x << ", " << y << endl;
00617 sprintf(buf, "%c %d %d %d", 'k', key, x, y);
00618 send_buf_out_socket(0, buf_size);
00619 }
00620
00621 void DisplayReplicator::SendSpecialKeyEvent(int key, int x, int y)
00622 {
00623 if (debug) cerr << "Sending special key " << key << " @ " << x << ", "
00624 << y << endl;
00625 sprintf(buf, "%c %d %d %d", 's', key, x, y);
00626 send_buf_out_socket(0, buf_size);
00627 }
00628
00629 void DisplayReplicator::SendMouseEvent(int button, int state, int x, int y)
00630 {
00631 if (debug) cerr << "Sending mouse " << button << "," << state << " @ "
00632 << x << ", " << y << endl;
00633 sprintf(buf, "%c %d %d %d %d", 'b', button, state, x, y);
00634 send_buf_out_socket(0, buf_size);
00635 }
00636
00637 void DisplayReplicator::SendMotionEvent(int x, int y)
00638 {
00639 if (debug) cerr << "Sending motion @ " << x << ", " << y << endl;
00640 sprintf(buf, "%c %d %d", 'm', x, y);
00641 send_buf_out_socket(0, buf_size);
00642 }
00643
00644 void DisplayReplicator::RegisterEventHandlers(
00645 void(*keyfn_in)(unsigned char,int,int),
00646 void(*specialfn_in)(int,int,int),
00647 void(*mousefn_in)(int,int,int,int),
00648 void(*motionfn_in)(int,int) )
00649 {
00650 keyfn = keyfn_in;
00651 specialfn = specialfn_in;
00652 mousefn = mousefn_in;
00653 motionfn = motionfn_in;
00654 }
00655
00656 void DisplayReplicator::SendScreenRefresh(int which_socket)
00657 {
00658 if (debug == 3)
00659 cerr << "SendScreenRefresh()\n";
00660
00661 if (num_socks == 0) return;
00662
00663
00664 buf[0] = 0;
00665
00666
00667 send_buf_out_socket(which_socket, buf_size);
00668 }
00669
00670
00671 void DisplayReplicator::SendWholeScreen(int which_buffer, int sock_index)
00672 {
00673 if (debug == 3)
00674 cerr << "SendWholeScreen(" << which_buffer << ", " << sock_index
00675 << ")\n";
00676
00677 if (num_socks == 0) return;
00678
00679 glReadBuffer(which_buffer);
00680
00681 int num_blocks_x = width/BLOCKSIZE_X;
00682 int num_blocks_y = height/BLOCKSIZE_Y;
00683 for (int x=0; x<num_blocks_x; x++) {
00684 for (int y=0; y<num_blocks_y; y++) {
00685 int xloc = x * BLOCKSIZE_X, yloc = y * BLOCKSIZE_Y;
00686 glReadPixels(xloc,yloc, BLOCKSIZE_X,BLOCKSIZE_Y, GL_RGB,
00687 GL_UNSIGNED_BYTE, &block);
00688
00689
00690 int buf_code = 1;
00691 if (which_buffer == GL_FRONT_RIGHT) buf_code = 2;
00692
00693
00694 SendBlock(buf_code, x, y, block, sock_index);
00695 }
00696 }
00697
00698
00699 SendScreenRefresh(sock_index);
00700 }
00701
00702 void DisplayReplicator::SendScreenUpdates(int which_buffer, void* data_in)
00703 {
00704 if (debug == 3) cerr << "SendScreenUpdates(" << which_buffer << ")\n";
00705
00706 if (num_socks == 0)
00707 {
00708 return; }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 static char data[1024 * 1024 * 3];
00719
00720 switch (source) {
00721 case source_memory:
00722 memcpy(data, data_in, width*height*3);
00723 break;
00724 case source_screen:
00725
00726
00727
00728 glReadBuffer(which_buffer);
00729
00730
00731 #ifdef _WIN32
00732 glReadPixels(0,0, width,height, GL_BGR_EXT, GL_UNSIGNED_BYTE, &data);
00733 #else
00734 glReadPixels(0,0, width,height, GL_BGR, GL_UNSIGNED_BYTE, &data);
00735 #endif
00736 break;
00737 }
00738
00739
00740 int buf_code = 1;
00741 if (which_buffer == GL_FRONT_RIGHT) buf_code = 2;
00742
00743
00744 Timer timer;
00745 int blocks_sent1 = 0, blocks_sent2 = 0, bytes_sent = 0;
00746 if (compression != JPEG)
00747 {
00748 int num_blocks_x = width/BLOCKSIZE_X;
00749 int num_blocks_y = height/BLOCKSIZE_Y;
00750 for (int x=0; x<num_blocks_x; x++) {
00751 for (int y=0; y<num_blocks_y; y++) {
00752
00753 int xloc = x * BLOCKSIZE_X, yloc = y * BLOCKSIZE_Y;
00754
00755 {
00756 for (int yy=0; yy<BLOCKSIZE_Y; yy++) {
00757 memcpy(&(block[yy*BLOCKSIZE_X*3]),
00758 &(data[(yloc+yy)*width*3+xloc*3]), BLOCKSIZE_X*3);
00759 }
00760 }
00761
00762
00763 int diff = compare_blocks(block, (char*)old_data[buf_code-1][x][y]);
00764
00765
00766
00767 if (diff) {
00768
00769
00770 int len = SendBlock(buf_code, x, y, block, -1, 0, false);
00771
00772
00773
00774
00775
00776 memcpy(old_data[buf_code-1][x][y], block, block_size);
00777
00778
00779 if (buf_code == 1)
00780 blocks_sent1++;
00781 else
00782 blocks_sent2++;
00783
00784 bytes_sent += len * num_socks;
00785 }
00786 }
00787 }
00788
00789
00790 SendBlock(0, 0, 0, NULL, -1, 0, true);
00791
00792
00793
00794
00795
00796 oldDataInitialized = true;
00797 }
00798 else
00799 {
00800 int len = SendBlock(buf_code,0,0,data,-1,0,true);
00801 bytes_sent += len;
00802 }
00803
00804 if (debug == 1) {
00805 int bps = int(bytes_sent/timer.GetElapsedTime());
00806
00807 cerr << bps * 8/1024 << " Kbits/second,relative\n";
00808 cerr << " seeing " << 1.0/global_timer.GetElapsedTime()
00809 << " updates per second, absolute\n";
00810 global_timer.Reset();
00811 }
00812 }
00813
00814 void DisplayReplicator::ReceiveScreenUpdate(int which_buffer, char* data, int JPEG_size)
00815 {
00816 int buf_code, x, y, seq_id;
00817
00818
00819 if (compression != JPEG)
00820 decode_block_from_buf(&buf_code, &x, &y, &seq_id, block,JPEG_size);
00821 else
00822 decode_block_from_buf(&buf_code, &x, &y, &seq_id, JPEG_data,JPEG_size);
00823
00824
00825
00826 switch (source) {
00827 case source_screen:
00828 if (compression != JPEG)
00829 PaintBlock(which_buffer, x, y, block);
00830 else
00831 PaintBlock(which_buffer, x, y, JPEG_data, true);
00832 break;
00833 case source_memory:
00834 if (!data) break;
00835
00836 int xloc = x * BLOCKSIZE_X, yloc = y * BLOCKSIZE_Y;
00837
00838
00839 for (int yy=0; yy<BLOCKSIZE_Y; yy++) {
00840 memcpy(&(data[(yloc+yy)*width*3+xloc*3]),
00841 &(block[yy*BLOCKSIZE_X*3]), BLOCKSIZE_X*3);
00842 }
00843 break;
00844 }
00845
00846 }
00847
00848
00849 void DisplayReplicator::Connect(char* server, bool switchboard, char channel, char* optBuffer, bool blocking)
00850 {
00851
00852 cerr << "connecting to " << server << "on port " << port << "..." << endl;
00853 int cur_sock = num_socks++;
00854
00855
00856 sock[cur_sock] = new Socket(server,Socket::tcp,port);
00857 if (!sock[cur_sock]) { num_socks--; return; }
00858
00859 do
00860 {
00861 int status;
00862 if (!switchboard) {
00863
00864 strcpy(buf, handshake);
00865
00866 cerr << "sent handshake of [" << buf << "]\n";
00867 }
00868 else {
00869 char system_info[80];
00870 #ifdef _WIN32
00871 sprintf(system_info, "WIN32 PC");
00872 #elif linux
00873 sprintf(system_info, "Linux PC");
00874 #else
00875 sprintf(system_info,"Unix Machine");
00876 #endif
00877 cerr << "channel " << int(channel) << "\n";
00878 char InitBuf[256];
00879
00880 if (channel != -1)
00881 sprintf(InitBuf, "%c%c%s", (char)CHANNEL_REQUEST_CODE, (char)channel, system_info);
00882 else
00883 sprintf(InitBuf, "%c%s", (char)SYSTEM_INFO_CODE, system_info);
00884
00885 if (optBuffer != NULL) strcat(InitBuf, optBuffer);
00886 cerr << "Switchboard initbuf = [" << InitBuf << "]\n";
00887 memcpy(buf,InitBuf,256);
00888 status = send_buf_out_socket(cur_sock, buf_size);
00889
00890 }
00891
00892
00893 #ifdef DO_HANDSHAKE
00894
00895 sock[cur_sock]->BufferedReceive(buf,buf_size);
00896 cout << "RESP: [" << buf << "]\n";
00897 if (strncmp(buf,"ACK", 3) == 0) {
00898
00899 if (debug)
00900 cerr << "Received Confirmation of ACK\n";
00901
00902
00903 #else
00904 if (1) {
00905 if (debug)
00906 cerr << "Not doing handshake- assumed okay\n";
00907
00908 #endif
00909 blocking = false;
00910
00911
00912
00913
00914 } else {
00915
00916 cerr << "Connection rejected! (buf = [" << buf << "])\n";
00917
00918 if (!blocking)
00919 {
00920 Disconnect(cur_sock);
00921 return;
00922 }
00923 }
00924 } while (blocking);
00925
00926
00927 mode = sender;
00928
00929
00930
00931 }
00932
00933 void DisplayReplicator::Disconnect(int connection_to_kill)
00934 {
00935 if (debug) cerr << "Disconnect(" << connection_to_kill << ")\n";
00936 if (connection_to_kill >= num_socks) return;
00937 delete sock[connection_to_kill];
00938 for (int i=connection_to_kill; i<num_socks-1; i++)
00939 sock[i] = sock[i+1];
00940 num_socks--;
00941 }
00942
00943
00944 void DisplayReplicator::Listen()
00945 {
00946
00947 cerr << "Waiting for communication...";
00948 int cur_sock = num_socks;
00949
00950
00951 sock[cur_sock] = new Socket(NULL,Socket::tcp,port+cur_sock);
00952 if (!sock[cur_sock]) return;
00953
00954
00955 cerr << "\n\n\n" << num_socks++ << "\n\n\n\n";
00956 cerr << endl;
00957
00958 #ifdef DO_HANDSHAKE
00959
00960 cerr << "received connection" << endl;
00961
00962 sock[cur_sock]->BufferedReceive(buf,buf_size);
00963
00964
00965 cout << "Got handshake of [" << buf << "]\n";
00966
00967
00968 if (strncmp(buf,handshake, strlen(handshake)) == 0) {
00969
00970 sprintf(buf, "ACK");
00971 send_buf_out_socket(cur_sock, buf_size);
00972 cerr << "handshake okay- Connection established.\n";
00973 } else {
00974
00975 cerr << "NAK\n";
00976 sprintf(buf, "NAK");
00977 send_buf_out_socket(cur_sock, buf_size);
00978
00979
00980 Disconnect(cur_sock);
00981 }
00982
00983 #endif
00984
00985
00986 mode = receiver;
00987 }
00988
00989
00990
00991 void DisplayReplicator::Update(int nonblocking)
00992 {
00993 if (debug == 4) cerr << "Update(" << nonblocking << ")\n";
00994
00995
00996 if (num_socks == 0) return;
00997
00998
00999 int num_messages = 0, num_bytes = 0;
01000 Timer timer;
01001
01002 do {
01003
01004 for (int i=0; i<num_socks; i++) {
01005
01006 if (debug == 4)
01007 cerr << "Queue on socket " << i << " is "
01008 << sock[i]->InputQueueSize() << endl;
01009
01010
01011 int g_count = 0;
01012
01013
01014 int curLen = 0;
01015 g_count++;
01016 if (!(g_count%100)) cerr << "g_count = " << g_count << "\n";
01017
01018 if (debug == 5)
01019 cerr << "Incoming! - command=" << int(buf[0]) << endl;
01020
01021
01022 int status = 1;
01023
01024
01025
01026 status = sock[i]->BufferedReceive(g_buf, MAX_BUF_SIZE);
01027 buf = g_buf;
01028
01029
01030 if (!status) {
01031 if (debug) cerr << "2:LOST CONNECTION ON SOCKET " << i << endl;
01032 Disconnect(i);
01033 continue;
01034 }
01035
01036 if (debug)
01037 cerr << "status " << status << " comp " << comp_size + 4 << "\n";
01038
01039 while (curLen*buf_size < status)
01040 {
01041
01042 if (debug) {
01043 cerr << " curLen " << curLen;
01044 cerr << " buf[0] " << (int)buf[0];
01045 cerr << " buf[1] " << (int)buf[1];
01046 cerr << " buf[2] " << (int)buf[2];
01047 cerr << " buf[3] " << (int)buf[3] << "\n";
01048 }
01049
01050
01051 switch (buf[0]) {
01052 case 0:
01053
01054 glutPostRedisplay();
01055 break;
01056 case 1: ReceiveScreenUpdate(GL_FRONT_LEFT, buf, status);
01057
01058 break;
01059 case 2: ReceiveScreenUpdate(GL_FRONT_RIGHT, buf, status);
01060
01061 break;
01062 case 3: {
01063 res_reduction = int(buf[1]);
01064 compression = compression_type(buf[2]);
01065 from_windows = int(buf[3]);
01066 cerr << "received res_reduce = " << int(buf[1])
01067 << ", compression = " << int(buf[2]) << endl;
01068 break;
01069 }
01070 case 'q': Disconnect(i); break;
01071 case 'k': {
01072 int x, y, dummykey;
01073 sscanf(buf, "%*c %d %d %d", &dummykey, &x, &y);
01074 char key = char(dummykey);
01075 if (debug) cerr << "Got key [" << key << "] at "
01076 << x << ", " << y << endl;
01077 if (keyfn) (*keyfn)(key,x,y);
01078 break;
01079 }
01080 case 's': {
01081 int key; int x, y;
01082 sscanf(buf, "%*c %d %d %d", &key, &x, &y);
01083 if (debug) cerr << "Got special key [" << key << "] at "
01084 << x << ", " << y << endl;
01085 if (specialfn) (*specialfn)(key,x,y);
01086 break;
01087 }
01088 case 'b': {
01089 int button, state, x, y;
01090 sscanf(buf, "%*c %d %d %d %d", &button, &state, &x, &y);
01091 if (debug) cerr << "Got mouse " << button << "," << state
01092 << " at " << x << ", " << y << endl;
01093 if (mousefn) (*mousefn)(button,state,x,y);
01094 break;
01095 }
01096 case 'm': {
01097 int x, y;
01098 sscanf(buf, "%*c %d %d", &x, &y);
01099 if (debug) cerr << "Got motion at " << x << ", " << y << endl;
01100 if (motionfn) (*motionfn)(x,y);
01101 break;
01102 }
01103 default: break;
01104
01105 }
01106 ++curLen;
01107 buf += comp_size + 4 ;
01108
01109 if (compression == JPEG) curLen = status;
01110 }
01111
01112 buf = g_buf;
01113
01114
01115 num_messages++;
01116 num_bytes += status;
01117
01118
01119 }
01120 } while(1);
01121
01122
01123
01124 if (debug == 2) {
01125 int bps = int(num_bytes/timer.GetElapsedTime());
01126 cerr << num_messages << " messages received from " << num_socks
01127 << " servers: ";
01128 cerr << bps * 8/1024 << " Kbits/second,relative\n";
01129 cerr << "seeing " << 1.0/global_timer.GetElapsedTime()
01130 << " updates per second, absolute\n";
01131 global_timer.Reset();
01132 }
01133 }
01134
01135 GLUI_StaticText* ac = NULL;
01136 char new_machine_name[300];
01137 int new_proto = 0;
01138 void DisplayReplicator::Connect_CB(int dr_p_in)
01139 {
01140 DisplayReplicator* dr_p = (DisplayReplicator*)dr_p_in;
01141
01142
01143 dr_p->Connect(new_machine_name,do_switchboard,-1,": Spring code");
01144
01145
01146 char buf[80];
01147 sprintf(buf, "Num Active Connections = %d", dr_p->NumConnections());
01148 if (ac) ac->set_text(buf);
01149 }
01150
01151 int new_rr = 1;
01152 int new_ct = 0;
01153 int new_compare = 0;
01154 void DisplayReplicator::Params_CB(int dr_p_in)
01155 {
01156 DisplayReplicator* dr_p = (DisplayReplicator*)dr_p_in;
01157 dr_p->SetParams(new_rr, DisplayReplicator::compression_type(new_ct),
01158 new_compare);
01159 }
01160
01161
01162 void DisplayReplicator::Menu()
01163 {
01164 extern int main_window_id;
01165 extern void Close(int);
01166
01167 GLUI *glui = GLUI_Master.create_glui((const char*)"Display Replicator", 0, -1, -1);
01168 { GLUI_Panel* p = glui->add_panel("Current info");
01169 p->set_alignment(GLUI_ALIGN_LEFT);
01170
01171 char buf[80];
01172 sprintf(buf, "Num Active Connections = %d", NumConnections());
01173 ac = glui->add_statictext_to_panel(p, buf);
01174
01175
01176 GetParams(&new_rr, (compression_type*)&new_ct, &new_compare);
01177
01178
01179 GLUI_Spinner* s0 = glui->add_spinner_to_panel(p, "Resolution Reduction",
01180 GLUI_SPINNER_INT, &new_rr);
01181 s0->set_int_limits(1,6);
01182 GLUI_Listbox* lb0 = glui->add_listbox_to_panel(p, "Compression Type",
01183 &new_ct);
01184 lb0->add_item((int)DisplayReplicator::JPEG, (const char*)"JPEG");
01185 lb0->add_item((int)DisplayReplicator::color_24bit, (const char*)"24bit Color");
01186 lb0->add_item((int)DisplayReplicator::color_16bit, (const char*)"16bit Color");
01187 lb0->add_item((int)DisplayReplicator::color_8bit, (const char*)"8bit Color");
01188 lb0->add_item((int)DisplayReplicator::greyscale, (const char*)"Greyscale");
01189 GLUI_Spinner* s1 = glui->add_spinner_to_panel(p, (const char*)"Comparison Threshold",
01190 GLUI_SPINNER_INT, &new_compare);
01191 s1->set_int_limits(-1,1000);
01192
01193 glui->add_button_to_panel(p, "Apply", (int)this,
01194 (GLUI_Update_CB)Params_CB);
01195 }
01196
01197 { GLUI_Panel* p = glui->add_panel("");
01198 GLUI_EditText* et1 = glui->add_edittext_to_panel(p, "Connect to:",
01199 GLUI_EDITTEXT_TEXT, new_machine_name);
01200
01201 et1->set_text("biocomp.stanford.edu");
01202
01203 et1->set_w(300); et1->set_h(20);
01204
01205 GLUI_Checkbox* cb1 = glui->add_checkbox_to_panel(p,"Use Switchboard", &do_switchboard);
01206 glui->add_button_to_panel(p, "Connect", (int)this,
01207 (GLUI_Update_CB)Connect_CB);
01208 }
01209
01210 glui->add_separator();
01211 { GLUI_Panel* pe = glui->add_panel("");
01212 glui->add_button_to_panel(pe, "Close", (int)glui,
01213 (GLUI_Update_CB)Close);
01214 }
01215 glui->set_main_gfx_window(main_window_id);
01216 }
01217