You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
969 lines
25 KiB
969 lines
25 KiB
/***************************************************************************
|
|
INDI Driver
|
|
-------------------
|
|
begin : Wed May 7th 2003
|
|
copyright : (C) 2001 by Jasem Mutlaq
|
|
email : mutlaqja@ikarustech.com
|
|
***************************************************************************/
|
|
/***************************************************************************
|
|
* *
|
|
* 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 "indidriver.h"
|
|
#include "indimenu.h"
|
|
#include "indihostconf.h"
|
|
#include "devicemanager.h"
|
|
#include "indidevice.h"
|
|
#include "indi/indicom.h"
|
|
|
|
#include "kstars.h"
|
|
#include "kstarsdata.h"
|
|
#include "ksutils.h"
|
|
|
|
#include <tqfile.h>
|
|
#include <tqvaluelist.h>
|
|
#include <tqcstring.h>
|
|
#include <tqradiobutton.h>
|
|
#include <tqtextedit.h>
|
|
|
|
#include <kiconloader.h>
|
|
#include <tdelistview.h>
|
|
#include <tdepopupmenu.h>
|
|
#include <kprocess.h>
|
|
#include <tdemessagebox.h>
|
|
#include <kpushbutton.h>
|
|
#include <klineedit.h>
|
|
#include <kstandarddirs.h>
|
|
#include <tdeaction.h>
|
|
|
|
#include <kextsock.h>
|
|
#include <unistd.h>
|
|
|
|
/*
|
|
* The dialog will by default be modeless, unless you set 'modal' to
|
|
* TRUE to construct a modal dialog.
|
|
*/
|
|
INDIDriver::INDIDriver(TQWidget *parent) : devManager( parent )
|
|
|
|
{
|
|
|
|
lastPort = 7263;
|
|
lastGroup = NULL;
|
|
lastDevice = NULL;
|
|
|
|
ksw = (KStars *) parent;
|
|
|
|
//FormLayout = makeVBoxMainWidget();
|
|
|
|
localListView->setSorting(-1);
|
|
clientListView->setSorting(-1);
|
|
|
|
TDEIconLoader *icons = TDEGlobal::iconLoader();
|
|
runningPix = icons->loadIcon( "application-x-executable", TDEIcon::Small);
|
|
stopPix = icons->loadIcon( "button_cancel", TDEIcon::Small);
|
|
localMode = icons->loadIcon( "network_local", TDEIcon::Small);
|
|
serverMode = icons->loadIcon( "network", TDEIcon::Small);
|
|
|
|
LocalpopMenu = new TDEPopupMenu(localListView);
|
|
LocalpopMenu->insertItem( runningPix, i18n("Run Service") , 0);
|
|
LocalpopMenu->insertItem( stopPix, i18n("Stop Service"), 1);
|
|
|
|
localListView->setRootIsDecorated(true);
|
|
|
|
connected = icons->loadIcon( "connect_established", TDEIcon::Small);
|
|
disconnected = icons->loadIcon( "connect_no", TDEIcon::Small);
|
|
establishConnection = icons->loadIcon( "connect_creating", TDEIcon::Small);
|
|
|
|
ClientpopMenu = new TDEPopupMenu(clientListView);
|
|
ClientpopMenu->insertItem( establishConnection, i18n("Connect") , 0);
|
|
ClientpopMenu->insertItem( disconnected, i18n("Disconnect"), 1);
|
|
|
|
|
|
for (uint i = 0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
{
|
|
TQListViewItem *item = new TQListViewItem(clientListView, lastGroup);
|
|
lastGroup = item;
|
|
item->setPixmap(0, disconnected);
|
|
item->setText(1, ksw->data()->INDIHostsList.at(i)->name);
|
|
item->setText(2, ksw->data()->INDIHostsList.at(i)->portnumber);
|
|
|
|
}
|
|
|
|
lastGroup = NULL;
|
|
|
|
TQObject::connect(addB, TQT_SIGNAL(clicked()), this, TQT_SLOT(addINDIHost()));
|
|
TQObject::connect(modifyB, TQT_SIGNAL(clicked()), this, TQT_SLOT(modifyINDIHost()));
|
|
TQObject::connect(removeB, TQT_SIGNAL(clicked()), this, TQT_SLOT(removeINDIHost()));
|
|
|
|
TQObject::connect(clientListView, TQT_SIGNAL(rightButtonPressed ( TQListViewItem *, const TQPoint &, int )), this, TQT_SLOT(ClientprocessRightButton( TQListViewItem *, const TQPoint &, int )));
|
|
|
|
TQObject::connect(ClientpopMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(processHostStatus(int)));
|
|
|
|
TQObject::connect(localListView, TQT_SIGNAL(rightButtonPressed ( TQListViewItem *, const TQPoint &, int )), this, TQT_SLOT(LocalprocessRightButton( TQListViewItem *, const TQPoint &, int )));
|
|
|
|
TQObject::connect(LocalpopMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(processDeviceStatus(int)));
|
|
|
|
TQObject::connect(ksw->getINDIMenu(), TQT_SIGNAL(driverDisconnected(int)), this, TQT_SLOT(shutdownHost(int)));
|
|
|
|
TQObject::connect(connectHostB, TQT_SIGNAL(clicked()), this, TQT_SLOT(activateHostConnection()));
|
|
TQObject::connect(disconnectHostB, TQT_SIGNAL(clicked()), this, TQT_SLOT(activateHostDisconnection()));
|
|
|
|
TQObject::connect(runServiceB, TQT_SIGNAL(clicked()), this, TQT_SLOT(activateRunService()));
|
|
TQObject::connect(stopServiceB, TQT_SIGNAL(clicked()), this, TQT_SLOT(activateStopService()));
|
|
|
|
TQObject::connect(localListView, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(updateLocalButtons()));
|
|
TQObject::connect(clientListView, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(updateClientButtons()));
|
|
|
|
readXMLDriver();
|
|
resize( 500, 300);
|
|
|
|
}
|
|
|
|
void INDIDriver::shutdownHost(int mgrID)
|
|
{
|
|
TQListViewItem *affectedItem;
|
|
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
{
|
|
if (ksw->data()->INDIHostsList.at(i)->mgrID == mgrID)
|
|
{
|
|
affectedItem = clientListView->itemAtIndex(i);
|
|
ksw->data()->INDIHostsList.at(i)->mgrID = -1;
|
|
ksw->data()->INDIHostsList.at(i)->isConnected = false;
|
|
affectedItem->setPixmap(0, disconnected);
|
|
connectHostB->setEnabled(true);
|
|
disconnectHostB->setEnabled(false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (uint i=0; i < devices.size(); i++)
|
|
{
|
|
if (devices[i]->mgrID == mgrID)
|
|
{
|
|
affectedItem = localListView->findItem(devices[i]->label, 0);
|
|
if (!affectedItem) return;
|
|
affectedItem->setPixmap(1, stopPix);
|
|
affectedItem->setPixmap(2, NULL);
|
|
affectedItem->setText(4, TQString(""));
|
|
runServiceB->setEnabled(true);
|
|
stopServiceB->setEnabled(false);
|
|
devices[i]->managed = false;
|
|
devices[i]->restart();
|
|
return;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void INDIDriver::ClientprocessRightButton( TQListViewItem *item, const TQPoint &p, int column)
|
|
{
|
|
|
|
column = 0;
|
|
|
|
if (item && item->childCount() == 0)
|
|
ClientpopMenu->popup(p);
|
|
}
|
|
|
|
void INDIDriver::LocalprocessRightButton( TQListViewItem *item, const TQPoint &p, int column)
|
|
{
|
|
|
|
column = 0;
|
|
|
|
if (item && item->childCount() == 0)
|
|
LocalpopMenu->popup(p);
|
|
}
|
|
|
|
void INDIDriver::activateRunService()
|
|
{
|
|
processDeviceStatus(0);
|
|
}
|
|
|
|
void INDIDriver::activateStopService()
|
|
{
|
|
processDeviceStatus(1);
|
|
}
|
|
|
|
void INDIDriver::activateHostConnection()
|
|
{
|
|
processHostStatus(0);
|
|
}
|
|
|
|
void INDIDriver::activateHostDisconnection()
|
|
{
|
|
processHostStatus(1);
|
|
}
|
|
|
|
void INDIDriver::updateLocalButtons()
|
|
{
|
|
|
|
if (localListView->selectedItem() == NULL)
|
|
return;
|
|
|
|
for (uint i=0; i < devices.size(); i++)
|
|
if (localListView->selectedItem()->text(0) == devices[i]->label)
|
|
{
|
|
runServiceB->setEnabled(devices[i]->state == 0);
|
|
stopServiceB->setEnabled(devices[i]->state == 1);
|
|
|
|
serverLogText->clear();
|
|
|
|
for ( TQStringList::Iterator it = devices[i]->serverBuffer.begin(); it != devices[i]->serverBuffer.end(); ++it )
|
|
serverLogText->insert(*it);
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void INDIDriver::updateClientButtons()
|
|
{
|
|
INDIHostsInfo *hostInfo;
|
|
if (clientListView->currentItem() == NULL)
|
|
return;
|
|
|
|
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
{
|
|
hostInfo = ksw->data()->INDIHostsList.at(i);
|
|
if (clientListView->currentItem()->text(1) == hostInfo->name && clientListView->currentItem()->text(2) == hostInfo->portnumber)
|
|
{
|
|
connectHostB->setEnabled(!hostInfo->isConnected);
|
|
disconnectHostB->setEnabled(hostInfo->isConnected);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void INDIDriver::processDeviceStatus(int id)
|
|
{
|
|
if (localListView->selectedItem() == NULL)
|
|
return;
|
|
|
|
for (uint i=0; i < devices.size(); i++)
|
|
if (localListView->selectedItem()->text(0) == devices[i]->label)
|
|
{
|
|
devices[i]->state = (id == 0) ? 1 : 0;
|
|
if (devices[i]->state)
|
|
{
|
|
|
|
ksw->getINDIMenu()->setCustomLabel(devices[i]->label);
|
|
devices[i]->label = ksw->getINDIMenu()->currentLabel;
|
|
|
|
devices[i]->serverBuffer.clear();
|
|
|
|
if (!runDevice(devices[i]))
|
|
{
|
|
devices[i]->restart();
|
|
return;
|
|
}
|
|
|
|
if (devices[i]->mode == IDevice::M_LOCAL)
|
|
{
|
|
//Allow time for the INDI server to listen
|
|
usleep(50000);
|
|
|
|
if (!ksw->getINDIMenu()->processServer())
|
|
{
|
|
devices[i]->restart();
|
|
return;
|
|
}
|
|
}
|
|
|
|
localListView->selectedItem()->setPixmap(1, runningPix);
|
|
localListView->selectedItem()->setText(4, TQString("%1").arg(devices[i]->indiPort));
|
|
runServiceB->setEnabled(false);
|
|
stopServiceB->setEnabled(true);
|
|
|
|
return;
|
|
}
|
|
|
|
if (devices[i]->mode == IDevice::M_LOCAL)
|
|
ksw->getINDIMenu()->processServer();
|
|
|
|
localListView->selectedItem()->setPixmap(1, stopPix);
|
|
localListView->selectedItem()->setPixmap(2, NULL);
|
|
localListView->selectedItem()->setText(4, TQString(""));
|
|
runServiceB->setEnabled(true);
|
|
stopServiceB->setEnabled(false);
|
|
devices[i]->restart();
|
|
updateMenuActions();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void INDIDriver::processHostStatus(int id)
|
|
{
|
|
int mgrID;
|
|
bool toConnect = (id == 0);
|
|
TQListViewItem *currentItem = clientListView->selectedItem();
|
|
if (!currentItem) return;
|
|
INDIHostsInfo *hostInfo;
|
|
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
{
|
|
hostInfo = ksw->data()->INDIHostsList.at(i);
|
|
if (currentItem->text(1) == hostInfo->name && currentItem->text(2) == hostInfo->portnumber)
|
|
{
|
|
// Nothing changed, return
|
|
if (hostInfo->isConnected == toConnect)
|
|
return;
|
|
|
|
// connect to host
|
|
if (toConnect)
|
|
{
|
|
// if connection successful
|
|
if ( (mgrID = ksw->getINDIMenu()->processClient(hostInfo->hostname, hostInfo->portnumber)) >= 0)
|
|
{
|
|
currentItem->setPixmap(0, connected);
|
|
hostInfo->isConnected = true;
|
|
hostInfo->mgrID = mgrID;
|
|
connectHostB->setEnabled(false);
|
|
disconnectHostB->setEnabled(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ksw->getINDIMenu()->removeDeviceMgr(hostInfo->mgrID);
|
|
hostInfo->mgrID = mgrID = -1;
|
|
hostInfo->isConnected = false;
|
|
currentItem->setPixmap(0, disconnected);
|
|
connectHostB->setEnabled(true);
|
|
disconnectHostB->setEnabled(false);
|
|
updateMenuActions();
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void INDIDriver::updateMenuActions()
|
|
{
|
|
// We iterate over devices, we enable INDI Control Panel if we have any active device
|
|
// We enable capture image sequence if we have any imaging device
|
|
|
|
TDEAction *tmpAction;
|
|
INDIMenu *devMenu = ksw->getINDIMenu();
|
|
bool activeDevice = false;
|
|
bool activeImaging = false;
|
|
INDI_P *imgProp = NULL;
|
|
|
|
if (devMenu == NULL)
|
|
return;
|
|
|
|
if (devMenu->mgr.count() > 0)
|
|
activeDevice = true;
|
|
|
|
for (uint i=0; i < devMenu->mgr.count(); i++)
|
|
{
|
|
for (uint j=0; j < devMenu->mgr.at(i)->indi_dev.count(); j++)
|
|
{
|
|
imgProp = devMenu->mgr.at(i)->indi_dev.at(j)->findProp("CCD_EXPOSE_DURATION");
|
|
if (imgProp && devMenu->mgr.at(i)->indi_dev.at(j)->isOn())
|
|
{
|
|
activeImaging = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
tmpAction = ksw->actionCollection()->action("indi_control_panel");
|
|
if (!tmpAction)
|
|
kdDebug() << "Warning: indi_control_panel action not found" << endl;
|
|
else
|
|
tmpAction->setEnabled(activeDevice);
|
|
|
|
tmpAction = ksw->actionCollection()->action("capture_sequence");
|
|
if (!tmpAction)
|
|
kdDebug() << "Warning: capture_sequence action not found" << endl;
|
|
else
|
|
tmpAction->setEnabled(activeImaging);
|
|
|
|
}
|
|
|
|
bool INDIDriver::runDevice(IDevice *dev)
|
|
{
|
|
dev->indiPort = getINDIPort();
|
|
|
|
if (dev->indiPort < 0)
|
|
{
|
|
KMessageBox::error(0, i18n("Cannot start INDI server: port error."));
|
|
return false;
|
|
}
|
|
|
|
dev->proc = new TDEProcess;
|
|
|
|
*dev->proc << "indiserver";
|
|
*dev->proc << "-v" << "-r" << "0" << "-p" << TQString("%1").arg(dev->indiPort) << dev->driver;
|
|
|
|
// Check Mode
|
|
dev->mode = localR->isChecked() ? IDevice::M_LOCAL : IDevice::M_SERVER;
|
|
|
|
if (dev->mode == IDevice::M_LOCAL)
|
|
localListView->selectedItem()->setPixmap(2, localMode);
|
|
else
|
|
localListView->selectedItem()->setPixmap(2, serverMode);
|
|
|
|
connect(dev->proc, TQT_SIGNAL(receivedStderr (TDEProcess *, char *, int)), dev, TQT_SLOT(processstd(TDEProcess *, char*, int)));
|
|
|
|
dev->proc->start(TDEProcess::NotifyOnExit, TDEProcess::Stderr);
|
|
//dev->proc->start();
|
|
|
|
return (dev->proc->isRunning());
|
|
}
|
|
|
|
void INDIDriver::removeDevice(IDevice *dev)
|
|
{
|
|
|
|
for (unsigned int i=0 ; i < devices.size(); i++)
|
|
if (dev->label == devices[i]->label)
|
|
devices[i]->restart();
|
|
}
|
|
|
|
void INDIDriver::removeDevice(TQString deviceLabel)
|
|
{
|
|
for (unsigned int i=0 ; i < devices.size(); i++)
|
|
if (deviceLabel == devices[i]->label)
|
|
devices[i]->restart();
|
|
|
|
}
|
|
|
|
void INDIDriver::saveDevicesToDisk()
|
|
{
|
|
|
|
TQFile file;
|
|
TQString elementData;
|
|
|
|
file.setName( locateLocal( "appdata", "drivers.xml" ) ); //determine filename in local user KDE directory tree.
|
|
|
|
if ( !file.open( IO_WriteOnly))
|
|
{
|
|
TQString message = i18n( "unable to write to file 'drivers.xml'\nAny changes to INDI device drivers will not be saved." );
|
|
KMessageBox::sorry( 0, message, i18n( "Could Not Open File" ) );
|
|
return;
|
|
}
|
|
|
|
TQTextStream outstream(&file);
|
|
|
|
// Let's write drivers first
|
|
outstream << "<ScopeDrivers>" << endl;
|
|
for (unsigned int i=0; i < driversList.count(); i++)
|
|
outstream << " <driver>" << driversList[i] << "</driver>" << endl;
|
|
outstream << "</ScopeDrivers>" << endl;
|
|
|
|
// Next we write devices, in the following order:
|
|
// Telescopes, CCDs, Filter Wheels, Video, Dome, GPS
|
|
|
|
// #1 Telescopes
|
|
outstream << "<devGroup group='Telescopes'>" << endl;
|
|
for (unsigned i=0; i < devices.size(); i++)
|
|
{
|
|
if (devices[i]->deviceType == KSTARS_TELESCOPE)
|
|
{
|
|
outstream << TQString("<device label='%1' focal_length='%2' aperture='%3'>").arg(devices[i]->label).arg(devices[i]->focal_length > 0 ? devices[i]->focal_length : -1).arg(devices[i]->aperture > 0 ? devices[i]->aperture : -1) << endl;
|
|
|
|
outstream << " <driver>" << devices[i]->driver << "</driver>" << endl;
|
|
outstream << " <version>" << devices[i]->version << "</version>" << endl;
|
|
outstream << "</device>" << endl;
|
|
}
|
|
}
|
|
outstream << "</devGroup>" << endl;
|
|
|
|
// #2 CCDs
|
|
outstream << "<devGroup group='CCDs'>" << endl;
|
|
for (unsigned i=0; i < devices.size(); i++)
|
|
{
|
|
if (devices[i]->deviceType == KSTARS_CCD)
|
|
{
|
|
outstream << TQString("<device label='%1'>").arg(devices[i]->label) << endl;
|
|
outstream << " <driver>" << devices[i]->driver << "</driver>" << endl;
|
|
outstream << " <version>" << devices[i]->version << "</version>" << endl;
|
|
outstream << "</device>" << endl;
|
|
}
|
|
}
|
|
outstream << "</devGroup>" << endl;
|
|
|
|
// #3 Filter wheels
|
|
outstream << "<devGroup group='Filter Wheels'>" << endl;
|
|
for (unsigned i=0; i < devices.size(); i++)
|
|
{
|
|
if (devices[i]->deviceType == KSTARS_FILTER)
|
|
{
|
|
outstream << TQString("<device label='%1'>").arg(devices[i]->label) << endl;
|
|
outstream << " <driver>" << devices[i]->driver << "</driver>" << endl;
|
|
outstream << " <version>" << devices[i]->version << "</version>" << endl;
|
|
outstream << "</device>" << endl;
|
|
}
|
|
}
|
|
outstream << "</devGroup>" << endl;
|
|
|
|
// #4 Video
|
|
outstream << "<devGroup group='Video'>" << endl;
|
|
for (unsigned i=0; i < devices.size(); i++)
|
|
{
|
|
if (devices[i]->deviceType == KSTARS_VIDEO)
|
|
{
|
|
outstream << TQString("<device label='%1'>").arg(devices[i]->label) << endl;
|
|
outstream << " <driver>" << devices[i]->driver << "</driver>" << endl;
|
|
outstream << " <version>" << devices[i]->version << "</version>" << endl;
|
|
outstream << "</device>" << endl;
|
|
}
|
|
}
|
|
outstream << "</devGroup>" << endl;
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
bool INDIDriver::isDeviceRunning(TQString deviceLabel)
|
|
{
|
|
|
|
for (unsigned int i=0 ; i < devices.size(); i++)
|
|
if (deviceLabel == devices[i]->label)
|
|
{
|
|
if (!devices[i]->proc)
|
|
return false;
|
|
else return (devices[i]->proc->isRunning());
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int INDIDriver::getINDIPort()
|
|
{
|
|
|
|
lastPort+=5;
|
|
|
|
KExtendedSocket ks(TQString(), lastPort, KExtendedSocket::passiveSocket | KExtendedSocket::noResolve);
|
|
|
|
for (uint i=0 ; i < 10; i++)
|
|
{
|
|
if (ks.listen() < 0)
|
|
{
|
|
lastPort+=5;
|
|
ks.setPort(lastPort);
|
|
}
|
|
else
|
|
return lastPort;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool INDIDriver::readXMLDriver()
|
|
{
|
|
TQString indiFile("drivers.xml");
|
|
TQFile file;
|
|
char errmsg[1024];
|
|
|
|
if ( !KSUtils::openDataFile( file, indiFile ) )
|
|
{
|
|
KMessageBox::error(0, i18n("Unable to find device driver file 'drivers.xml'. Please locate the file and place it in one of the following locations:\n\n \t$(TDEDIR)/share/apps/kstars/%1 \n\t~/.trinity/share/apps/kstars/%1"));
|
|
|
|
return false;
|
|
}
|
|
|
|
signed char c;
|
|
LilXML *xmlParser = newLilXML();
|
|
XMLEle *root = NULL;
|
|
|
|
while ( (c = (signed char) file.getch()) != -1)
|
|
{
|
|
root = readXMLEle(xmlParser, c, errmsg);
|
|
|
|
if (root)
|
|
{
|
|
if (!buildDeviceGroup(root, errmsg))
|
|
prXMLEle(stderr, root, 0);
|
|
|
|
delXMLEle(root);
|
|
}
|
|
else if (errmsg[0])
|
|
{
|
|
kdDebug() << TQString(errmsg);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
delLilXML(xmlParser);
|
|
return true;
|
|
|
|
}
|
|
|
|
bool INDIDriver::buildDriversList( XMLEle *root, char* /*errmsg[]*/)
|
|
{
|
|
|
|
XMLEle *ep;
|
|
|
|
for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
|
|
driversList << pcdataXMLEle(ep);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool INDIDriver::buildDeviceGroup(XMLEle *root, char errmsg[])
|
|
{
|
|
|
|
XMLAtt *ap;
|
|
XMLEle *ep;
|
|
TQString groupName;
|
|
int groupType = KSTARS_TELESCOPE;
|
|
|
|
if (!strcmp(tagXMLEle(root), "ScopeDrivers"))
|
|
return buildDriversList(root, errmsg);
|
|
|
|
// avoid overflow
|
|
if (strlen(tagXMLEle(root)) > 1024)
|
|
return false;
|
|
|
|
// Get device grouping name
|
|
ap = findXMLAtt(root, "group");
|
|
|
|
if (!ap)
|
|
{
|
|
snprintf(errmsg, ERRMSG_SIZE, "Tag %.64s does not have a group attribute", tagXMLEle(root));
|
|
return false;
|
|
}
|
|
|
|
groupName = valuXMLAtt(ap);
|
|
|
|
if (groupName.find("Telescopes") != -1)
|
|
groupType = KSTARS_TELESCOPE;
|
|
else if (groupName.find("CCDs") != -1)
|
|
groupType = KSTARS_CCD;
|
|
else if (groupName.find("Filter") != -1)
|
|
groupType = KSTARS_FILTER;
|
|
else if (groupName.find("Video") != -1)
|
|
groupType = KSTARS_VIDEO;
|
|
else if (groupName.find("Focusers") != -1)
|
|
groupType = KSTARS_FOCUSER;
|
|
else if (groupName.find("Domes") != -1)
|
|
groupType = KSTARS_DOME;
|
|
else if (groupName.find("GPS") != -1)
|
|
groupType = KSTARS_GPS;
|
|
|
|
|
|
//TDEListViewItem *group = new TDEListViewItem(topItem, lastGroup);
|
|
TQListViewItem *group = new TQListViewItem(localListView, lastGroup);
|
|
group->setText(0, groupName);
|
|
lastGroup = group;
|
|
//group->setOpen(true);
|
|
|
|
|
|
for (ep = nextXMLEle(root, 1) ; ep != NULL ; ep = nextXMLEle(root, 0))
|
|
/*for (int i = 0; i < root->nel; i++)*/
|
|
if (!buildDriverElement(ep, group, groupType, errmsg))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool INDIDriver::buildDriverElement(XMLEle *root, TQListViewItem *DGroup, int groupType, char errmsg[])
|
|
{
|
|
XMLAtt *ap;
|
|
XMLEle *el;
|
|
IDevice *dv;
|
|
TQString label;
|
|
TQString driver;
|
|
TQString version;
|
|
double focal_length (-1), aperture (-1);
|
|
|
|
ap = findXMLAtt(root, "label");
|
|
if (!ap)
|
|
{
|
|
snprintf(errmsg, ERRMSG_SIZE, "Tag %.64s does not have a label attribute", tagXMLEle(root));
|
|
return false;
|
|
}
|
|
|
|
label = valuXMLAtt(ap);
|
|
|
|
// Let's look for telescope-specfic attributes: focal length and aperture
|
|
ap = findXMLAtt(root, "focal_length");
|
|
if (ap)
|
|
focal_length = TQString(valuXMLAtt(ap)).toDouble();
|
|
|
|
ap = findXMLAtt(root, "aperture");
|
|
if (ap)
|
|
aperture = TQString(valuXMLAtt(ap)).toDouble();
|
|
|
|
|
|
el = findXMLEle(root, "driver");
|
|
|
|
if (!el)
|
|
return false;
|
|
|
|
driver = pcdataXMLEle(el);
|
|
|
|
el = findXMLEle(root, "version");
|
|
|
|
if (!el)
|
|
return false;
|
|
|
|
version = pcdataXMLEle(el);
|
|
|
|
TQListViewItem *device = new TQListViewItem(DGroup, lastDevice);
|
|
|
|
device->setText(0, TQString(label));
|
|
device->setPixmap(1, stopPix);
|
|
device->setText(3, TQString(version));
|
|
|
|
lastDevice = device;
|
|
|
|
dv = new IDevice(label, driver, version);
|
|
dv->deviceType = groupType;
|
|
connect(dv, TQT_SIGNAL(newServerInput()), this, TQT_SLOT(updateLocalButtons()));
|
|
if (focal_length > 0)
|
|
dv->focal_length = focal_length;
|
|
if (aperture > 0)
|
|
dv->aperture = aperture;
|
|
|
|
devices.push_back(dv);
|
|
|
|
// SLOTS/SIGNAL, pop menu, indi server logic
|
|
return true;
|
|
}
|
|
|
|
int INDIDriver::activeDriverCount()
|
|
{
|
|
int count = 0;
|
|
|
|
for (uint i=0; i < devices.size(); i++)
|
|
if (devices[i]->state && devices[i]->mode == IDevice::M_LOCAL)
|
|
count++;
|
|
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
if (ksw->data()->INDIHostsList.at(i)->isConnected)
|
|
count++;
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
void INDIDriver::addINDIHost()
|
|
{
|
|
INDIHostConf hostConf(this);
|
|
hostConf.setCaption(i18n("Add Host"));
|
|
bool portOk = false;
|
|
|
|
if (hostConf.exec() == TQDialog::Accepted)
|
|
{
|
|
INDIHostsInfo *hostItem = new INDIHostsInfo;
|
|
hostItem->name = hostConf.nameIN->text();
|
|
hostItem->hostname = hostConf.hostname->text();
|
|
hostItem->portnumber = hostConf.portnumber->text();
|
|
hostItem->isConnected = false;
|
|
hostItem->mgrID = -1;
|
|
|
|
hostItem->portnumber.toInt(&portOk);
|
|
|
|
if (portOk == false)
|
|
{
|
|
KMessageBox::error(0, i18n("Error: the port number is invalid."));
|
|
return;
|
|
}
|
|
|
|
//search for duplicates
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
if (hostItem->name == ksw->data()->INDIHostsList.at(i)->name &&
|
|
hostItem->portnumber == ksw->data()->INDIHostsList.at(i)->portnumber)
|
|
{
|
|
KMessageBox::error(0, i18n("Host: %1 Port: %2 already exists.").arg(hostItem->name).arg(hostItem->portnumber));
|
|
return;
|
|
}
|
|
|
|
ksw->data()->INDIHostsList.append(hostItem);
|
|
|
|
TQListViewItem *item = new TQListViewItem(clientListView);
|
|
item->setPixmap(0, disconnected);
|
|
item->setText(1, hostConf.nameIN->text());
|
|
item->setText(2, hostConf.portnumber->text());
|
|
|
|
}
|
|
|
|
saveHosts();
|
|
}
|
|
|
|
|
|
|
|
void INDIDriver::modifyINDIHost()
|
|
{
|
|
|
|
INDIHostConf hostConf(this);
|
|
hostConf.setCaption(i18n("Modify Host"));
|
|
|
|
TQListViewItem *currentItem = clientListView->currentItem();
|
|
|
|
if (currentItem == NULL)
|
|
return;
|
|
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
if (currentItem->text(1) == ksw->data()->INDIHostsList.at(i)->name &&
|
|
currentItem->text(2) == ksw->data()->INDIHostsList.at(i)->portnumber)
|
|
{
|
|
|
|
hostConf.nameIN->setText(ksw->data()->INDIHostsList.at(i)->name);
|
|
hostConf.hostname->setText(ksw->data()->INDIHostsList.at(i)->hostname);
|
|
hostConf.portnumber->setText(ksw->data()->INDIHostsList.at(i)->portnumber);
|
|
|
|
if (hostConf.exec() == TQDialog::Accepted)
|
|
{
|
|
INDIHostsInfo *hostItem = new INDIHostsInfo;
|
|
hostItem->name = hostConf.nameIN->text();
|
|
hostItem->hostname = hostConf.hostname->text();
|
|
hostItem->portnumber = hostConf.portnumber->text();
|
|
|
|
currentItem->setText(1, hostConf.nameIN->text());
|
|
currentItem->setText(2, hostConf.portnumber->text());
|
|
|
|
ksw->data()->INDIHostsList.replace(clientListView->itemIndex(currentItem), hostItem);
|
|
|
|
saveHosts();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void INDIDriver::removeINDIHost()
|
|
{
|
|
|
|
if (clientListView->currentItem() == NULL)
|
|
return;
|
|
|
|
for (uint i=0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
if (clientListView->currentItem()->text(1) == ksw->data()->INDIHostsList.at(i)->name &&
|
|
clientListView->currentItem()->text(2) == ksw->data()->INDIHostsList.at(i)->portnumber)
|
|
{
|
|
if (ksw->data()->INDIHostsList.at(i)->isConnected)
|
|
{
|
|
KMessageBox::error( 0, i18n("You need to disconnect the client before removing it."));
|
|
return;
|
|
}
|
|
|
|
if (KMessageBox::warningContinueCancel( 0, i18n("Are you sure you want to remove the %1 client?").arg(clientListView->currentItem()->text(1)), i18n("Delete Confirmation"),KStdGuiItem::del())!=KMessageBox::Continue)
|
|
return;
|
|
|
|
ksw->data()->INDIHostsList.remove(i);
|
|
clientListView->takeItem(clientListView->currentItem());
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
saveHosts();
|
|
|
|
}
|
|
|
|
void INDIDriver::saveHosts()
|
|
{
|
|
|
|
TQFile file;
|
|
TQString hostData;
|
|
|
|
file.setName( locateLocal( "appdata", "indihosts.xml" ) ); //determine filename in local user KDE directory tree.
|
|
|
|
if ( !file.open( IO_WriteOnly))
|
|
{
|
|
TQString message = i18n( "unable to write to file 'indihosts.xml'\nAny changes to INDI hosts configurations will not be saved." );
|
|
KMessageBox::sorry( 0, message, i18n( "Could Not Open File" ) );
|
|
return;
|
|
}
|
|
|
|
TQTextStream outstream(&file);
|
|
|
|
for (uint i= 0; i < ksw->data()->INDIHostsList.count(); i++)
|
|
{
|
|
|
|
hostData = "<INDIHost name='";
|
|
hostData += ksw->data()->INDIHostsList.at(i)->name;
|
|
hostData += "' hostname='";
|
|
hostData += ksw->data()->INDIHostsList.at(i)->hostname;
|
|
hostData += "' port='";
|
|
hostData += ksw->data()->INDIHostsList.at(i)->portnumber;
|
|
hostData += "' />\n";
|
|
|
|
outstream << hostData;
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
INDIDriver::~INDIDriver()
|
|
{
|
|
|
|
for (uint i=0; i < devices.size(); i++)
|
|
delete (devices[i]);
|
|
|
|
}
|
|
|
|
IDevice::IDevice(TQString inLabel, TQString inDriver, TQString inVersion)
|
|
{
|
|
label = inLabel;;
|
|
driver = inDriver;;
|
|
version = inVersion;
|
|
|
|
// Initially off
|
|
state = 0;
|
|
|
|
// No port initially
|
|
indiPort = -1;
|
|
|
|
// not yet managed by DeviceManager
|
|
managed = false;
|
|
|
|
mgrID = -1;
|
|
|
|
focal_length = -1;
|
|
aperture = -1;
|
|
|
|
proc = NULL;
|
|
|
|
}
|
|
|
|
void IDevice::processstd(TDEProcess* /*proc*/, char* buffer, int /*buflen*/)
|
|
{
|
|
serverBuffer.append(buffer);
|
|
emit newServerInput();
|
|
}
|
|
|
|
|
|
IDevice::~IDevice()
|
|
{
|
|
if (proc)
|
|
proc->kill();
|
|
|
|
}
|
|
|
|
void IDevice::restart()
|
|
{
|
|
|
|
mgrID = -1;
|
|
|
|
state = 0;
|
|
|
|
indiPort = -1;
|
|
|
|
if (proc)
|
|
proc->kill();
|
|
|
|
proc = NULL;
|
|
|
|
}
|
|
|
|
#include "indidriver.moc"
|