Skip to content
Snippets Groups Projects
szgPartiview.cc 35.9 KiB
Newer Older
    delete scene;
    // delete clk;  Don't delete the clock -- might be shared with other objects
}
    

Ppszg::Ppszg() {
    scene = new PvScene();
    st = NULL;
    clipnear_ = 0.1;
    clipfar_ = 2500;
    focallen_ = 3;

    snapfmt = NULL;
    snapfno = 0;
    pickrange = 3.5;
    
    memset(home, 0, sizeof(home));

    clk = new SClock();
    clock_init( clk );
    clock_set_speed( clk, 1.0 );
    clk->continuous = 1;
    clk->walltimed = 1;

    memset( &path, 0, sizeof(path) );
    playing = 0;
    playevery = 0;
    playidling = 0;
    playspeed = 20;
    framebase = 1;
    playtimebase = 0;
    playloop = 0;

    timebasetime = 0;

    subcam = 0;
    /* List of connected arSockets */
    socketList = NULL;
bool Ppszg::onStart( arSZGClient& SZGClient ) {
  /*
   * Add Transfer Fields to Framework so data is
   * accessible and syncronized to all clients
   * Added July 23, 2008 William Davis
   */
  processid = SZGClient.getProcessID();	// for msg() log files

  addTransferField("curtime", &(ppszg.clk->curtime), AR_DOUBLE, 1);
  addTransferField("running", &(ppszg.clk->running), AR_INT, 1);
  addTransferField("continuous", &(ppszg.clk->continuous), AR_INT, 1);
  addTransferField("center_", &(ppszg.scene->center_), AR_FLOAT, 3);
  addTransferField("censize_", &(ppszg.scene->censize_), AR_FLOAT, 1);
  addTransferField("quitnow", &(ppszg.quitnow_), AR_INT, 1);
  addInternalTransferField( "commands", AR_CHAR, 1 );
  parti_bgcolor( "0 0 0" );

  parti_add_commands( pp_parse_args, "partiview", NULL );
  parti_add_reader( pp_read, "partiview", NULL );
  plugin_init();


  // pp_ui_init();
  // ppui.view->pickbuffer( COUNT(pickbuffer), pickbuffer );

  parti_clip( "0.1", "2500" );
  parti_censize( 1.0 );
  // parti_pickrange( 3.5 );

  parti_object( "g1", NULL, 1 );
  readrc( &ppszg.st );

  for(int i = 1; i < globalArgc; i++) {
    specks_read( &ppszg.st, globalArgv[i] );

#if 0
bool arMasterSlaveFramework::addInternalTransferField( std::string fieldName,
                                                         arDataType dataType,
                                                         int numElements );

The pointer argument is omitted, and the numElements argument now denotes the initial size. The size can be changed by calling:

  bool arMasterSlaveFramework::setInternalTransferFieldSize( std::string fieldName,
                                                             arDataType dataType,
                                                             int newSize );
#endif


void Ppszg::onWindowStartGL( arGUIWindowInfo * ) {
  set_dsp_context( 0 );	/* assign a display context, so texture code can track window changes */
}

void Ppszg::onPreExchange( void ) {	// called on master only
  // do navigation...
  // process commands read from network...
  //   and package any with
  /* Here we want to do the listening on the sockets to interpret
   * any commands we might receive over them
   */
  static int socketid = 0;
  if(ppszg.listenSocket == 0) {
    // Create listener socket.  Do this only in a *live* master
    /* arSockets - originally from salimiman by Jim Crowell */
    /* I'm not sure if some of this should be done elsewhere */
    msg("master on pid %d listening on port 8675", processid);
    listenSocket = new arSocket(AR_LISTENING_SOCKET);
    listenSocket->ar_create();
    listenSocket->setSendBufferSize(2048);
    listenSocket->setReceiveBufferSize(2048);
    listenSocket->reuseAddress(true);
    list<string> acceptMask;
    listenSocket->setAcceptMask(acceptMask);
    /* Bind to port 8675 */
    listenSocket->ar_bind(NULL, 8675);
    listenSocket->ar_listen(256);
  }

  if(ppszg.listenSocket->readable())
  {
    bufferedSocket* sockp = new bufferedSocket();
    arSocketAddress addr;
    ppszg.listenSocket->ar_accept(sockp, &addr);
    warn("pid %d accepted connection", processid);
    sockp->setID(socketid++);
    sockp->next = ppszg.socketList;
    ppszg.socketList = sockp;
  cmdbuf_.clear();		// wipe master->slaves buffer for this cycle

  /* Now read data into the buffer */
  bufferedSocket* sock = ppszg.socketList;
  bufferedSocket** previousSocketp = &ppszg.socketList;
  while( sock != NULL ) {
	int len = sock->poll();
	while(len >= 0) {		// repeat for all the lines in buffer
            int maxargs = len/2 + 2;    // max possible number of args
            char **av = new char *[maxargs];
            char tbuf[ 2*len + 1024 ];
		// temp buffer.  Extra room allows for $expansion etc.
		// XXX should pass this length to tokenize!

            int ac = tokenize( sock->str(), tbuf, maxargs, av, NULL );

            if(ac > 0) {
		// Not a comment nor a blank line.  Try to parse it locally.
		if( ! specks_parse_args( &ppszg.st, ac, av ) ) {
		    msg("Unrecognized control command: %s", sock->str());
		}
		// In any case, pass it on to slaves
		PpCmd cmd( CMD_CONTROL, ac, av );
		cmd.freezeInto( cmdbuf_ );
            }
	    delete av;

            len = sock->consume();      // Done processing that line.  Got another on hand?
	}
	   *previousSocketp = sock->next;
	   delete sock;
	} else {
	    previousSocketp = &sock->next;
	}
	sock = *previousSocketp;
  }

  // Now ship bundled commands to slaves

  if(cmdbuf_.size() == 0)
      cmdbuf_.append( 1, '\000' );	// ensure nonzero size

  setInternalTransferFieldSize( "commands", AR_CHAR, cmdbuf_.size() );

  if(cmdbuf_.size() > 1 && getenv("CMDTEST")) {
	PpCmd tcmd;
	int offset = 0;
	int room = cmdbuf_.size();
	    msg("Got %d-bytes of command packet", room-1);	// XXX DEBUG
	while(offset+1 < room) {
	    int oof = offset;
	    if( tcmd.thawFrom( &cmdbuf_[0], offset, false ) < 0)
		break;
	    // false -> build argc/argv which point into cmdp string directly
	    msg("Offset %d..%d: command [%d] %s", oof,offset, tcmd.argc, rejoinargs( 0, tcmd.argc, tcmd.argv ));
            if(tcmd.argc <= 0 || oof == offset) {
                msg("Had enough: tcmd.argc=%d, offset %d, room %d", tcmd.argc, offset, room);
                break;
            }
        }
  int room = 0;
  char *cmdp = (char *)getTransferField( "commands", AR_CHAR, room );
  if(cmdp == 0 || room != cmdbuf_.size()) {
    msg("panic: transfer field size %d != the size %d we told it to be!\n",
		room, cmdbuf_.size());
  } else {
       memcpy( cmdp, &cmdbuf_[0], room );
  }

  /*
   * Added July 23, 2008 William Davis
   * Forces the framework to listen to updates to navigation matrix
   * changed from a "jump" command
   */ 
  navUpdate();

  clock_tick( ppszg.clk );		// let time advance
void Ppszg::onPostExchange( void )	// called on master + slaves
{
    if(! this->getMaster() ) {
	// We're a slave.  Decode any commands passed by master this cycle.
	int room = 0;
	char *cmdp = (char *)getTransferField( "commands", AR_CHAR, room );
	if(cmdp == 0) {
	    static int once = 1;
	    if(once) msg("Ppszg::onPostExchange: can't get transfer field \"commands\"");
	    once = 0;
	    return;
	}

#if 0
	if(room > 1) {
	    msg("postExchange: GOT %d-bytes of cmd pkt", room-1);
	    char unk[512];
	    int u,uu;
	    for(u=uu=0; u<room; u++)
		uu += sprintf(&unk[uu], cmdp[u]<' ' ? "\\x%02x" : "%c", cmdp[u]);
	    unk[uu] = '\0';
	    msg("Received: \"%s\"", unk); // XXX debug
	}
#endif

	int offset = 0;
	while(offset+1 < room) {
            int oof = offset;
	    bool done;
	    done = (pp.thawFrom( cmdp, offset, false ) < 0);
	    // false -> build argc/argv which point into cmdp string directly
            if(done || oof >= offset || pp.argc <= 0) {
              msg("Had enough of cmd pkt: done %d offset %d was %d, room %d, argc %d, type 0x%x", done, offset, oof, room, pp.argc, pp.type);
              break;
            }
	    msg("postExchange: processing '%s'", rejoinargs(0,pp.argc,pp.argv));
	    if(pp.type == CMD_CONTROL) {
		if(! specks_parse_args( &ppszg.st, pp.argc, pp.argv ) ) {
		    warn("Unrecognized control command on slave: %s",
			rejoinargs( 0, pp.argc, pp.argv ));
		}
	    } else {
		warn("can only handle control cmds, not: %s",
		    rejoinargs(0, pp.argc, pp.argv));
	    }
	}
    }

    /* terminate if we're asked to... */
    /* is this the right way to do this? */
    if(ppszg.quitnow_)
	exit(0);
void Ppszg::onWindowInit( void ) {	// clear to background...
    glClearColor( bgcolor.x[0], bgcolor.x[1], bgcolor.x[2], 1 );
    ar_defaultWindowInitCallback();
}

void Ppszg::onDraw( arGraphicsWindow& win, arViewport& vp ) {
    /*
     * Addded July 23, 2008 William Davis
     * Loads the navigation matrix into the framework, making
     * sure we listen to the changes enacted by the "jump" command
     * in parti_setc2w()
     */
    loadNavMatrix();

void Ppszg::onDisconnectDraw( void ) {
    glClearColor( 1, .1, .1, 1 );
    glClear( GL_COLOR_BUFFER_BIT );
}

void Ppszg::onCleanup( void ) {
void Ppszg::onUserMessage( const string& messageBody ) {
    // called in master on "dex <N> user <some message for this program>"
    // parse messageBody, add to command queue for next preExchange time
}

#ifdef __linux__
#include <GL/glut.h>	// hack: Syzygy uses glutWireSphere() in simulator mode, but freeglut insists on glutInit() first
#endif

#ifdef __linux__
    int targc = 1;		// rest of hack.
    glutInit( &targc, argv );
#endif
    globalArgc = argc; //Make these two variables accessible to the
    globalArgv = argv; // onStart callback

    if( ! ppszg.init( argc, argv ) ) {
	fprintf(stderr, "arMasterSlaveFramework::init() failed, giving up...\n");
	exit(1);
    }

    if( ! ppszg.start() ) {
	fprintf(stderr, "arMasterSlaveFramework::start() failed, giving up...\n");
	exit(1);
    }
    // Shouldn't reach here.
    fprintf(stderr, "Shouldn't reach here.\n");
    exit(2);
}