/***************************************************************************
                          hdsensorslist.cpp  -  description
                             -------------------
    begin                : vie abr 26 2002
    copyright            : (C) 2002 by Miguel Novas
    email                : michaell@teleline.es
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <stdlib.h>
#include <tqstringlist.h>
#include <tdelocale.h>
#include <tqregexp.h>

#include "sensor.h"
#include "hdsensorslist.h"


HDSensorsList::HDSensorsList(TQObject *parent, const char * name): SensorsList(parent,name)
{
 process= 0;

 setDescription( i18n("Hard Disks") );

 setClass(Sensor::hdSensor);

 readConfig();

 if(!isHddTempInstalled()) return;

 TQStringList disks;
 if(!getDisks(disks)) return;

 for(TQStringList::Iterator it = disks.begin(); it != disks.end(); ++it ) {
   ProcessExec proc;
   proc << "hddtemp" << "-q";
   proc << *it;
   if(proc.runAndWait()) {
     double value;
     TQString str;
     if(getDiskInfo(proc.getStdoutData(),str,value)) {
       Sensor *sensor= new Sensor(this);
       sensor->setType(Sensor::lmTemp);
       sensor->setName(it->utf8());
       sensor->setDescription(str);
       sensor->setValueMax  (40   , Sensor::dgCelsius);
       sensor->setValueMin  ( 0   , Sensor::dgCelsius);
       sensor->setValueIdeal(value, Sensor::dgCelsius);
       sensor->setValue     (value, Sensor::dgCelsius);
       sensor->readConfig();
     }
   }
 }
}

HDSensorsList::~HDSensorsList()
{
 delete process;
}

//*************

void HDSensorsList::updateSensors()
{
 if(process) return;

 TQObjectList *list= (TQObjectList *)children();
 if(!list) return;

 TQStringList params;
 for(Sensor *obj= (Sensor *)list->first(); obj!=0; obj= (Sensor *)list->next())
  if(obj->monitorized())
     params << obj->name();

 if(params.count()>0) {
   process= new ProcessExec;
   *process << "hddtemp" << "-q" << params;
   connect( process, TQ_SIGNAL(processExited(TDEProcess *)), this, TQ_SLOT(slotProcessExited(TDEProcess *)) );
   process->run();
 }
}

void HDSensorsList::slotProcessExited(TDEProcess *)
{
 TQObjectList *list= (TQObjectList *)children();

 if (!list) return;

 if (process->outputErrors())
   tqWarning("HddTemp Error:\n%s", process->getStdoutData().ascii());

 TQStringList buf = TQStringList::split(TQChar('\n'), process->getStdoutData());
 for(TQStringList::Iterator it = buf.begin(); it != buf.end(); ++it ) {
   for(Sensor *obj= (Sensor *)list->first(); obj!=0; obj= (Sensor *)list->next()) {
     TQRegExp rx(TQString(obj->name()) + TQString(":\\s+.+:\\s+(\\d+).*C"));
     if (rx.search((*it)) > -1)
       obj->setValue(rx.cap(1).toDouble(), Sensor::dgCelsius); 
   }
 }
 delete process;
 process= 0;
}

// ***************  Static methods


bool HDSensorsList::getDiskInfo(const TQString buf, TQString &name, double &value)
{
 TQRegExp rx(":\\s+(.+):\\s+(\\d+).*C");

 if (rx.search(buf) > -1) {
   bool ok;
   name = rx.cap(1);
   value = rx.cap(2).toDouble(&ok);
   if (ok)
     return true;
   else
     return false;
 }
 else 
   return false;
}


bool HDSensorsList::isHddTempInstalled()
{
 ProcessExec proc;

 proc << "hddtemp" << "-v" ;
 if(proc.runAndWait()) {
   if(proc.getStdoutData().contains("ERROR")==0) return true;
   tqWarning("HddTemp Error:\n%s", proc.getStdoutData().ascii());
 }
 return false;
}

bool HDSensorsList::getDisks(TQStringList &disks )
{
  DIR *dir;

  /* Get a listing of the hard drives looking under sysfs first then falling back to /proc/ide */
  if((dir = opendir ("/sys/block")) == NULL)
    if ((dir = opendir ("/proc/ide")) == NULL)
      return false;
  TQString str;
  struct dirent *ptr;
  while((ptr= readdir(dir))) {
    if((ptr->d_name[0]=='h' || ptr->d_name[0]=='s') && ptr->d_name[1]=='d') {
       str.sprintf("/dev/%s",ptr->d_name);
       disks << str;
    }
  }
  closedir(dir);
  return true;
}

// ***************

#include "hdsensorslist.moc"
