Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 167)
+++ Evidence/Edd/Edd.cc	(revision 168)
@@ -20,18 +20,18 @@
 	Qt::gray, Qt::darkGray, Qt::lightGray};
 
-class GUI *Handler;
+
+class Edd_DIM *Handler;
 
 
 // History chooser function (opens plot for numeric data, TextHist for all other)
-QWidget *OpenHistory(char *Service) {
+QWidget *OpenHistory(char *Service, int Index) {
 
   char *Name, *Format;
   DimBrowser Browser;
-  
-  //if (Browser.getServices(Service) == 0) return NULL;
+
   Browser.getServices(Service);
   if (Browser.getNextService(Name, Format) != DimSERVICE) return NULL;
   
-  if (strlen(Format) == 1 && *Format != 'C') return new Edd_Plot(Service);
+  if (strlen(Format) == 1 && *Format != 'C') return new Edd_Plot(Service, Index);
   else return new Edd_TextHist(Service);
 }
@@ -43,6 +43,7 @@
 
 // Constructor
-Edd_Indicator::Edd_Indicator(QString DIMService, QWidget *P): QLineEdit(P) {
-
+Edd_Indicator::Edd_Indicator(QString Name, int Index, QWidget *P):
+	QLineEdit(P), ServiceName(Name), Index(Index) {
+ 
   // Widget properties
   setReadOnly(true);
@@ -52,5 +53,5 @@
   // Connect to DIM handler
   if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) {
-    printf("Failed connection for %s\n", DIMService.toAscii().data());
+    printf("Failed connection for %s\n", Name.toAscii().data());
   }
 
@@ -61,11 +62,12 @@
   Menu->addAction("Copy data", this, SLOT(MenuCopyData()));
 
-  // DIM client
-  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, NO_LINK, Handler);
+  // Subscribe to service
+  Handler->Subscribe(Name);
 }
 
 // Destructor
 Edd_Indicator::~Edd_Indicator() {
-  delete Data;
+
+  Handler->Unsubscribe(ServiceName);
 }
 
@@ -73,6 +75,6 @@
 void Edd_Indicator::Update(DimInfo *Info, int Time, QByteArray Array, QString Text) {
 
-  if (Info != Data) return;
-    
+  if (ServiceName != Info->getName()) return;
+
   QPalette Pal = palette();  
 
@@ -93,9 +95,12 @@
     }
 	
+	if (toupper(*(Info->getFormat()) != 'C')) Text = Text.section(' ', Index, Index);
+
 	if (!ShowAsTime) setText(Text);
 	else setText(QDateTime::fromTime_t(Text.toInt()).toString());
-	
+	setCursorPosition(0);
+
     // Update status tip
-    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Info->getFormat()));
+    setStatusTip(QString("%1:  Last update %2   Format '%3'   Index %4").arg(Info->getName()).arg(  QDateTime::fromTime_t(Time).toString()).arg(Info->getFormat()).arg(Index));
   }
   
@@ -135,5 +140,5 @@
   QDrag *Drag = new QDrag(this);
   QMimeData *MimeData = new QMimeData;
-  MimeData->setText(QString(Data->getName()));
+  MimeData->setText(ServiceName);
   Drag->setMimeData(MimeData);
   Drag->exec();
@@ -151,5 +156,5 @@
 void Edd_Indicator::MenuOpenHistory() {
   
-  LastPlot = OpenHistory(Data->getName());
+  LastPlot = OpenHistory(ServiceName.toAscii().data(), Index);
   if (LastPlot != NULL) LastPlot->show();
 }
@@ -158,5 +163,5 @@
 void Edd_Indicator::MenuCopyService() {
   
-  QApplication::clipboard()->setText(QString(Data->getName()));
+  QApplication::clipboard()->setText(ServiceName);
 }
 
@@ -174,10 +179,12 @@
 // Constructor
 //
-Edd_Plot::Edd_Plot(QString DIMService, QWidget *P): QwtPlot(P), EvidenceHistory() {
-
+Edd_Plot::Edd_Plot(QString DIMService, int Index, QWidget *P):
+	QwtPlot(P), EvidenceHistory() {
+
+  Mutex = new QMutex(QMutex::Recursive);
+  
+  // Widget properties
   setAcceptDrops(true);
   setAttribute(Qt::WA_DeleteOnClose);
-  
-  // Graph properties
   setAutoReplot(false);
   setCanvasBackground(QColor(Qt::yellow));
@@ -220,5 +227,5 @@
 
   // DIM client
-  if (!DIMService.isEmpty()) AddService(DIMService);
+  if (!DIMService.isEmpty()) AddService(DIMService, Index);
 }
 
@@ -229,8 +236,9 @@
 
   for (int i=0; i<Items.size(); i++) {
-    delete Items[i].LiveData;
+    Handler->Unsubscribe(Items[i].Name);
     delete Items[i].Signal;
   }  
   delete Grid;
+  delete Mutex;
 }
 
@@ -238,13 +246,13 @@
 // Add history service to plot
 //
-void Edd_Plot::AddService(QString Name) {
-
+void Edd_Plot::AddService(QString Name, int Index) {
+return;
   // Lock before accessing Items list
-  QMutexLocker Locker(&Mutex);
+  QMutexLocker Locker(Mutex);
 
   // Check if already subscribed to service
   for (int i=0; i<Items.size(); i++) {
-    if (Name == Items[i].LiveData->getName()) {
-      QMessageBox::warning(this, "Edd Message",Name+".hist already present",QMessageBox::Ok);
+    if (Name == Items[i].Name && Index == Items[i].Index) {
+      QMessageBox::warning(this, "Edd Message",Name+" (index "+QString::number(Index)+") already present",QMessageBox::Ok);
       return;
     }
@@ -253,12 +261,15 @@
   // Generate new curve and subscribe to service
   struct PlotItem New;
+
+  New.Name = Name;
   New.Signal = new QwtPlotCurve;
   New.Signal->attach(this);
-  New.Signal->setTitle(Name+".hist");
+  New.Signal->setTitle(Name+"("+QString::number(Index)+")");
   New.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))]));
   New.SizeLimit = 5000;
-  New.LiveData = new DimStampedInfo(Name.toAscii().data(), NO_LINK, Handler); 
+  New.Index = Index;
 
   Items.append(New);
+  Handler->Subscribe(Name);
 }
 
@@ -269,12 +280,13 @@
   if (Time == -1) {
 	setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
+	return;
   }
 
   // Lock before accessing Items list
-  QMutexLocker Locker(&Mutex);
+  QMutexLocker Locker(Mutex);
 
   // Determine which plot item this call belongs to
   int ItemNo;
-  for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Info == Items[ItemNo].LiveData) {
+  for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Items[ItemNo].Name == Info->getName()) {
   
 	// If size limit reached, clear buffer
@@ -289,14 +301,15 @@
 	  void *Data;
 
-	  if (GetHistory(Items[ItemNo].LiveData->getName())) {
+	  if (GetHistory(Items[ItemNo].Name.toAscii().data())) {
      	double Smallest = DBL_MAX, Largest = DBL_MIN;
 		double Number=0;
 		while (Next(Time, Size, Data)) {
-		  switch (*(Info->getFormat())) {
-    		case 'I':  Number = *(int *) Data;   break;
-    		case 'S':  Number = *(short *) Data;   break;
-    		case 'F':  Number = *(float *) Data;   break;
-    		case 'D':  Number = *(double *) Data;   break;
-    		case 'X':  Number = *(long long *) Data;   break;
+		  switch (toupper(*(Info->getFormat()))) {
+    		case 'I':
+			case 'L':  Number = *((int *) Data + Items[ItemNo].Index);   break;
+    		case 'S':  Number = *((short *) Data + Items[ItemNo].Index);   break;
+    		case 'F':  Number = *((float *) Data + Items[ItemNo].Index);   break;
+    		case 'D':  Number = *((double *) Data + Items[ItemNo].Index);   break;
+    		case 'X':  Number = *((long long *) Data + Items[ItemNo].Index);   break;
     		default: break;
 		  }
@@ -320,4 +333,6 @@
 
     // Append data
+	Text = Text.section(' ', Items[ItemNo].Index, Items[ItemNo].Index);
+
     Items[ItemNo].x.append(Time);
     Items[ItemNo].y.append(atof(Text.toAscii().data()));
@@ -329,8 +344,6 @@
     // Update status tip
     QDateTime Timex = QDateTime::fromTime_t(Time); 
-    StatusTip = QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), Timex.toString()).arg(Info->getFormat());
-  }
-
-  Locker.unlock();
+    setStatusTip(QString("%1:  Last update %2   Format '%3'").arg(Info->getName(), Timex.toString()).arg(Info->getFormat()));
+  }
 
   UpdatePlot();
@@ -352,8 +365,6 @@
 
   // Lock before accessing Items list
-  QMutexLocker Locker(&Mutex);
-
-  setStatusTip(StatusTip);
-  
+  QMutexLocker Locker(Mutex);
+
   for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
 
@@ -440,13 +451,11 @@
 
   // Lock before accessing Items list
-  QMutexLocker Locker(&Mutex);
+  QMutexLocker Locker(Mutex);
 
   while (Items.size() > 1) {  
-    delete Items.last().LiveData;
+    Handler->Unsubscribe(Items.last().Name);
     delete Items.last().Signal;
     Items.takeLast();
   }
-  
-  Locker.unlock();
   UpdatePlot();
 }
@@ -465,10 +474,10 @@
   
   // Lock before accessing Items list
-  QMutexLocker Locker(&Mutex);
+  QMutexLocker Locker(Mutex);
   QTextStream Stream(&File);
 
    // Write x and y data for all signals to file
   for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
-    Stream << QString("# ")+Items[ItemNo].LiveData->getName()+".hist" << endl;
+    Stream << QString("# ") + Items[ItemNo].Name + ".hist" << endl;
     for (int i=0; i<Items[ItemNo].Signal->dataSize(); i++) {
       Stream << (int) Items[ItemNo].x.at(i) << " " << Items[ItemNo].Signal->y(i) << endl;
@@ -518,5 +527,6 @@
 // Constructor
 //
-Edd_TextHist::Edd_TextHist(QString DIMService, QWidget *P): QTextEdit(P), EvidenceHistory() {
+Edd_TextHist::Edd_TextHist(QString Name, QWidget *P):
+	QTextEdit(P), EvidenceHistory(), Name(Name) {
   
   // Widget properties
@@ -528,5 +538,5 @@
   // Connect to DIM handler
   if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) {
-    printf("Failed connection for %s\n", DIMService.toAscii().data());
+    printf("Failed connection for %s\n", Name.toAscii().data());
   }
 
@@ -535,5 +545,5 @@
   void *Data;
 
-  if (GetHistory(DIMService.toAscii().data())) {
+  if (GetHistory(Name.toAscii().data())) {
 	while (Next(Time, Size, Data)) {
 	  moveCursor (QTextCursor::Start);
@@ -544,5 +554,5 @@
 
   // DIM client
-  Service = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, NO_LINK, Handler);
+  Handler->Subscribe(Name);
 }
 
@@ -550,5 +560,5 @@
 Edd_TextHist::~Edd_TextHist() {
 
-  delete Service;
+  Handler->Unsubscribe(Name);
 }
 
@@ -557,5 +567,5 @@
 void Edd_TextHist::Update(DimInfo *Info, int Time, QByteArray, QString Text) {
 
-  if (Info != this->Service) return;
+  if (Name != Info->getName()) return;
 
   // Check if service available
@@ -572,5 +582,5 @@
 	
   // Update status tip
-  StatusTip = QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), Timex.toString()).arg(Info->getFormat());
+  setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), Timex.toString()).arg(Info->getFormat()));
 }
 
@@ -581,5 +591,5 @@
 
 // Constructor
-Edd_Textout::Edd_Textout(QString DIMService, QWidget *P): QTextEdit(P) {
+Edd_Textout::Edd_Textout(QString Name, QWidget *P): QTextEdit(P), Name(Name) {
 
   // Widget properties
@@ -591,9 +601,9 @@
   // Connect to DIM handler
   if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) {
-    printf("Failed connection for %s\n", DIMService.toAscii().data());
-  }
-
-  // DIM client
-  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, NO_LINK, Handler);
+    printf("Failed connection for %s\n", Name.toAscii().data());
+  }
+
+  // Subscribe to service
+  Handler->Subscribe(Name);
 }
 
@@ -601,5 +611,5 @@
 Edd_Textout::~Edd_Textout() {
 
-  delete Data;
+  Handler->Unsubscribe(Name);
 }
 
@@ -607,5 +617,5 @@
 void Edd_Textout::Update(DimInfo *Info, int Time, QByteArray, QString Text) {
 
-  if (Info != this->Data) return;
+  if (Name != Info->getName()) return;
   
   QPalette Pal = palette();  
@@ -622,11 +632,93 @@
 	if (Accumulate == false) clear();
 	
-    // Add if service contains only a string
-    if (strcmp(Info->getFormat(), "C") == 0) insertPlainText(Text);
-
-    // Update status tip
-    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Info->getFormat()));
+	// Add if service contains only a string
+	if (strcmp(Info->getFormat(), "C") == 0) insertPlainText(Text);
+
+	// Update status tip
+	setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Info->getFormat()));
   }
   setPalette(Pal);
+}
+
+
+/////////////////////////////
+// Interface to Dim system //
+/////////////////////////////
+Edd_DIM::Edd_DIM() {
+
+  Mutex = new QMutex(QMutex::Recursive);
+
+  // Connect to DIM handler
+  if (connect(this, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) {
+    printf("Failed connection in Edd_DIM()\n");
+  }
+}
+
+Edd_DIM::~Edd_DIM() {
+
+  delete Mutex;
+}
+
+// Subscribe to DIM service
+void Edd_DIM::Subscribe(QString Name) {
+
+  // Lock before accessing list
+  QMutexLocker Locker(Mutex);
+
+  // Check if already subscribed to service, then increase usage count and emit last service data
+  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
+	ServiceList[i].Count++;
+	YEP(ServiceList[i].DIMService, ServiceList[i].TimeStamp, ServiceList[i].ByteArray, ServiceList[i].Text);
+	return;
+  }
+
+  // Create new entry in service list
+  struct Item New;
+  New.Name = Name;
+  New.DIMService = new DimStampedInfo(Name.toAscii().data(), INT_MAX, NO_LINK, this);
+  New.Count = 1;
+  ServiceList.append(New);
+
+  return;
+}
+
+// Unsubsribe from DIM service
+void Edd_DIM::Unsubscribe(QString Name) {
+
+  // Lock before accessing list
+  QMutexLocker Locker(Mutex);
+
+  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
+	ServiceList[i].Count--;
+	if (ServiceList[i].Count == 0) {
+	  delete ServiceList[i].DIMService;
+	  ServiceList.removeAt(i);
+	  return;
+	}
+  }
+}
+
+// Store service information for usage by Subscribe()
+void Edd_DIM::Update(DimInfo *Info, int Time, QByteArray Data, QString Text) {
+
+  // Lock before accessing list
+  QMutexLocker Locker(Mutex);
+
+  for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Info->getName()) {
+	  ServiceList[i].TimeStamp = Time;
+	  ServiceList[i].ByteArray = Data;
+	  ServiceList[i].Text = Text;
+  }
+}
+
+// Handling of DIM service update
+void Edd_DIM::infoHandler() {
+
+  if (!EvidenceServer::ServiceOK(getInfo())) YEP(getInfo(), -1);
+  else {
+	char *Txt = EvidenceServer::ToString(getInfo());
+	YEP(getInfo(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt));
+	free(Txt);
+  }
 }
 
@@ -637,5 +729,5 @@
 GUI::GUI() {
  
-  Handler = this;
+  Handler = new Edd_DIM();
   
   // Set features of main window
@@ -685,10 +777,4 @@
   MainLayout->addWidget(Textout, 1, 0, 1, 2);
 
-  QFrame *Val = new QFrame();
-  Val->setFrameStyle(QFrame::HLine);
-  Val->setLineWidth(10);
-  //Value->setMaximumWidth(200);
-  MainLayout->addWidget(Val, 2, 0, 2, 1);      
-
   Value = new Edd_Indicator("DColl/Status");
   Value->setMaximumWidth(200);
@@ -718,8 +804,4 @@
   connect(Button, SIGNAL(released()), SLOT(StartDIMBrowser()));
   MainLayout->addWidget(Button, 7, 1, 1, 1);
-
-  Edd_TextHist *Bla;
-  Bla = new Edd_TextHist("DColl/CurrentFile");
-  MainLayout->addWidget(Bla, 8, 0, 1, 1);
 
   // Layout of all widgets
@@ -737,20 +819,24 @@
   Graph = new Edd_Plot();
   for (int i=0; i<36; i++) {
-    Text = Text.sprintf("Feedback/Average/ID%.2d/%.2d",i/8, i%8);
-    Value = new Edd_Indicator(Text);
-
+    //Text = Text.sprintf("Feedback/Average/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8);
+    Text = Text.sprintf("Feedback/AverageTest/ID%.2d",i/16);
+    Value = new Edd_Indicator(Text, i%16);
     FeedbackLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1);
     //Graph->AddService(Text);
-
-    //Text = Text.sprintf("Bias/VOLT/ID00/01-%.3d",i);
-    //Value = new Edd_Indicator(Text);
-    //BiasLayout->addWidget(Value, i%9+1, 2+i/9, 1, 1);
+  }
+  FeedbackLayout->addWidget(Graph, 0, 4, 11, 3);
+
+  //Graph = new Edd_Plot();
+  //for (int i=0; i<36; i++) {
+    //Text = Text.sprintf("Feedback/Sigma/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8);
     //Graph->AddService(Text);
-  }
-
-  FeedbackLayout->addWidget(Graph, 0, 4, 12, 3);
+  //}
+  //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3);
+
   Value = new Edd_Indicator("Feedback/Status");
   Value->setMaximumWidth(200);
   FeedbackLayout->addWidget(Value, 0, 0, 1, 3);      
+  Value = new Edd_Indicator("Feedback/Count");
+  FeedbackLayout->addWidget(Value, 0, 3, 1, 1);      
 
   // Bias voltage page
@@ -759,14 +845,11 @@
   Graph = new Edd_Plot();
   for (int i=0; i<18; i++) {
-    Text = Text.sprintf("Bias/VOLT/ID00/00-%.3d",i);
-    Value = new Edd_Indicator(Text);
-
+    Value = new Edd_Indicator("Bias/VOLT/ID00", i);
     BiasLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1);
-    Graph->AddService(Text);
-
-    Text = Text.sprintf("Bias/VOLT/ID00/01-%.3d",i);
-    Value = new Edd_Indicator(Text);
+    //Graph->AddService(Text, i);
+
+    Value = new Edd_Indicator("Bias/VOLT/ID00", i+32);
     BiasLayout->addWidget(Value, i%9+1, 2+i/9, 1, 1);
-    Graph->AddService(Text);
+    //Graph->AddService(Text,i+32);
   }
 
@@ -789,8 +872,7 @@
   Graph = new Edd_Plot();
   for (int i=0; i<10; i++) {
-    Text = Text.sprintf("ARDUINO/VAL%.2d", i);
-    Value = new Edd_Indicator(Text);
+    Value = new Edd_Indicator("ARDUINO/Data", i);
     EnvironmentLayout->addWidget(Value, i%5+1, i/5, 1, 1);
-    Graph->AddService(Text);
+    Graph->AddService("ARDUINO/Data", i);
   }
   EnvironmentLayout->addWidget(Graph, 0, 3, 7, 4);      
@@ -857,19 +939,6 @@
     Result = Result.trimmed();
     if (Result.endsWith(".hist")) Result.chop(5);
-    QWidget *Hist = OpenHistory(Result.toAscii().data());
+    QWidget *Hist = OpenHistory(Result.toAscii().data(), 0);
     if (Hist != NULL) Hist->show();
-  }
-}
-
-// Handling of DIM service update
-void GUI::infoHandler() {
-
-  // Check if service available
-  if (!EvidenceServer::ServiceOK(getInfo())) YEP(getInfo(), -1);
-  else {
-    char *Txt = EvidenceServer::ToString(getInfo());
-
-    YEP(getInfo(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt));
-	free(Txt);
   }
 }
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 167)
+++ Evidence/Edd/Edd.h	(revision 168)
@@ -25,5 +25,5 @@
 #define SVN_REVISION "$Revision$"
 
-QWidget *OpenHistory(char *);
+QWidget *OpenHistory(char *, int);
 
 // Time scale for axis
@@ -33,5 +33,5 @@
     virtual QwtText label(double v) const {
       QDateTime t = QDateTime::fromTime_t((int) v);
-      return t.toString("dMMM'\n'h:m:s");
+      return t.toString("dMMM'\n'hh:mm:ss");
     }
 };
@@ -39,13 +39,13 @@
 		  
 // General indicator for DIM service
-class Edd_Indicator: public QLineEdit, public DimClient {
+class Edd_Indicator: public QLineEdit {
     Q_OBJECT
 
     QMenu *Menu;
     QPoint dragStart;
-    //QwtPlot *LastPlot;
     QWidget *LastPlot;
 	
-    DimStampedInfo *Data;
+	QString ServiceName;
+	int Index;
 	
     void mousePressEvent(QMouseEvent *); 
@@ -54,5 +54,5 @@
 	
   public:
-    Edd_Indicator(QString, QWidget * = NULL);
+    Edd_Indicator(QString, int=0, QWidget * = NULL);
     ~Edd_Indicator();
 
@@ -72,5 +72,5 @@
 
     struct PlotItem {
-      DimInfo *LiveData;
+      QString Name;
       QwtPlotCurve *Signal;
       double Smallest;
@@ -78,12 +78,11 @@
 	  int SizeLimit;
 	  QVector<double> x;
-	  QVector<double> y;	  
+	  QVector<double> y;
+	  int Index;	  
     };
 
     QList<struct PlotItem> Items;
-    QMutex Mutex;
-    
-	QString StatusTip;
-	
+    QMutex *Mutex;
+    
     QMenu *Menu;
     QAction *YLogAction;
@@ -100,7 +99,7 @@
 
   public:
-    Edd_Plot(QString = QString(), QWidget * = NULL);
+    Edd_Plot(QString = QString(), int = 0, QWidget * = NULL);
     ~Edd_Plot();
-    void AddService(QString);
+    void AddService(QString, int = 0);
 
   private slots:
@@ -123,6 +122,5 @@
     Q_OBJECT
 
-	QString StatusTip;
-	DimStampedInfo *Service;
+	QString Name;
 	
   public:
@@ -138,5 +136,5 @@
     Q_OBJECT
 
-    DimStampedInfo *Data;
+    QString Name;
 
   public:
@@ -150,6 +148,38 @@
 };
 
+// Interface to DIM system
+class Edd_DIM: public QObject, public DimInfo {
+    Q_OBJECT
+
+	struct Item {
+	  QString Name;
+	  DimStampedInfo *DIMService;
+	  int Count;
+	  int TimeStamp;
+	  QByteArray ByteArray;
+	  QString Text;
+	};
+    QList<Item> ServiceList;
+    QMutex *Mutex;
+
+	void infoHandler();
+
+  private slots:
+	void Update(DimInfo *, int, QByteArray, QString);
+
+  public:
+    Edd_DIM();
+    ~Edd_DIM();
+
+	void Subscribe(QString);
+	void Unsubscribe (QString);
+
+  signals:
+    void YEP(DimInfo *, int, QByteArray = QByteArray(), QString = QString());
+};
+
+
 // Main window class
-class GUI: public QMainWindow, public DimBrowser, public DimInfo {
+class GUI: public QMainWindow, public DimBrowser {
     Q_OBJECT
 
@@ -162,5 +192,4 @@
             
     void closeEvent(QCloseEvent *);
-	void infoHandler();
 	
   public:
@@ -172,7 +201,4 @@
     void MenuNewHistory();
 	void StartDIMBrowser();
-	
-  signals:
-    void YEP(DimInfo *, int, QByteArray = QByteArray(), QString = QString());
 };
 
