// ---------------------------------------------------------------------------------
 // utility conversion funcs
 public CTmap PI2CTmap(PlugInChannelMap picm) {
   CTmap ctmap = new CTmap();
   int nchan = picm.NumberOfChannels();
   for (int i = 0; i < nchan; i++) {
     //			ctmap.add(picm.GetName(i),new CTdata(picm.GetTimes(i), picm.GetDataAsFloat64(i)));
     ctmap.add(picm.GetName(i)); // only need names this direction
   }
   return ctmap;
 }
    public PlugInChannelMap CT2PImap(
        PlugInChannelMap picm, CTmap ctmap, double tget, double tdur, String tmode) {
      int nchan = ctmap.size();
      try {
        for (int i = 0; i < nchan; i++) {
          String cname = ctmap.getName(i);
          picm.Add(cname);
          CTdata td;
          //					if(tmode.equals("absolute")) td = ctmap.getTimeData(cname, tget, tdur);	// use
          // tget,tdur for trim
          //					else						 td = ctmap.getTimeData(cname);
          if (debug)
            System.err.println(
                "getTimeData, tget: " + tget + ", tdur: " + tdur + ", tmode: " + tmode);
          //					td = ctmap.getTimeData(cname, tget, tdur, tmode);
          td = ctmap.getTimeData(cname); // already trimmed MJM 4/27/16
          if (debug)
            System.err.println(
                "cname: "
                    + cname
                    + ", fileType: "
                    + CTinfo.fileType(cname, typeDefault)
                    + ", td.size: "
                    + td.size());
          if (td == null || td.size() == 0) continue; // no data found this time

          td.setSwap(swapFlag);
          char fileType = CTinfo.fileType(cname, typeDefault);

          if (fileType != 'B') picm.PutTimes(td.getTime()); // doesn't work with byte[][]
          //				System.err.println("PutTimes len: "+td.getTime().length);
          switch (fileType) {
            case 'F':
              picm.PutDataAsFloat64(i, td.getDataAsFloat64());
              break;
            case 'f':
              picm.PutDataAsFloat32(i, td.getDataAsFloat32());
              break;
            case 'I':
              picm.PutDataAsInt64(i, td.getDataAsInt64());
              break;
            case 'i':
              picm.PutDataAsInt32(i, td.getDataAsInt32());
              break;
            case 'j':
              picm.PutDataAsInt16(i, td.getDataAsInt16());
              break;
            case 'n':
              picm.PutDataAsFloat32(i, td.getDataAsNumericF32());
              break;
            case 'N':
              picm.PutDataAsFloat64(i, td.getDataAsNumericF64());
              break;
            case 'B':
            default:
              if (debug) System.err.println("PutByte[] len: " + td.size());
              double[] time = td.getTime();
              byte[][] bdata = td.getData();
              for (int j = 0; j < td.size(); j++) {
                picm.PutTime(time[j], 0.);
                picm.PutDataAsByteArray(i, bdata[j]);
              }
              break;
          }
        }
      } catch (Exception e) {
        System.err.println("CTplugin Exception: " + e);
        //				e.printStackTrace();
        return null;
      }
      return picm;
    }
    public void run() {
      if (debug) System.err.println("PIrun, sourceFolder: " + sourceFolder + ", sName: " + sName);

      PlugInChannelMap picm = new PlugInChannelMap();
      plugin = new PlugIn();

      try {
        plugin.OpenRBNBConnection(rbnbServer, sName);
        sink = new Sink();
        sink.OpenRBNBConnection(rbnbServer, sinkName);
      } catch (Exception e) {
        System.err.println("Error on connect: " + e);
        System.exit(0);
        //		    RBNBProcess.exit(0);
      }

      if (preRegister) {
        try {
          System.err.println("pre-registering channels for source: " + sName);
          picm.Add("...");
          regPicm = handleRegistration(picm);
          //					plugin.Register(picm);			// pre-register
          System.err.println("pre-register done: " + sName);
        } catch (Exception se) {
          System.err.println("Oops, exception on preRegister: " + se);
        }
      }

      // process is to wait for request, get data from sink, convert data, send response, repeat
      while (true) {
        try {
          if (debug) System.err.println("waiting on fetch...");
          picm = plugin.Fetch(-1); // block until request arrives
          if (debug) System.err.println("request picm: " + picm);

          if (picm.NumberOfChannels() == 0) {
            System.err.println("oops, no channels in request");
            continue;
          }

          if (picm.GetRequestReference().equals("registration")) {
            if (debug) System.err.println("registration request!");
            plugin.Flush(handleRegistration(picm));
            continue;
          } else {
            double tget = picm.GetRequestStart();
            double tdur = picm.GetRequestDuration();
            String tmode = picm.GetRequestReference();
            CTmap ctmap = PI2CTmap(picm);
            ctmap = ctreader.getDataMap(ctmap, sourceFolder, tget, tdur, tmode);
            picm = CT2PImap(picm, ctmap, tget, tdur, tmode);
            if (debug) System.err.println("Flush picm: " + picm + ", nframe: " + ctmap.size());
            if (picm == null) System.err.println("no channels!");
            else plugin.Flush(picm);
          }
        } catch (Exception e) {
          System.err.println("oops, exception: " + e + ", picm: " + picm);
          e.printStackTrace();
          try {
            Thread.sleep(1000);
            picm.PutDataAsString(0, "error: " + e);
            plugin.Flush(picm);
          } catch (Exception ee) {
          }
          ; // no busy loop
          //				System.exit(0);		// no infinite loops
        }
      }
    }