summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indistd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indistd.cpp')
-rw-r--r--kstars/kstars/indistd.cpp1045
1 files changed, 1045 insertions, 0 deletions
diff --git a/kstars/kstars/indistd.cpp b/kstars/kstars/indistd.cpp
new file mode 100644
index 00000000..429e8824
--- /dev/null
+++ b/kstars/kstars/indistd.cpp
@@ -0,0 +1,1045 @@
+/* INDI STD
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This apppication 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.
+
+ 2004-01-18: This class handles INDI Standard properties.
+ */
+
+ #include "indistd.h"
+ #include "Options.h"
+ #include "indielement.h"
+ #include "indiproperty.h"
+ #include "indigroup.h"
+ #include "indidevice.h"
+ #include "indidriver.h"
+ #include "kstars.h"
+ #include "kstarsdata.h"
+ #include "skymap.h"
+ #include "skyobject.h"
+ #include "simclock.h"
+ #include "devicemanager.h"
+ #include "timedialog.h"
+ #include "streamwg.h"
+ #include "ccdpreviewwg.h"
+ #include "fitsviewer.h"
+
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <ctype.h>
+ #include <zlib.h>
+ #include <stdlib.h>
+
+ #include <qtimer.h>
+ #include <qlabel.h>
+ #include <qfont.h>
+ #include <qeventloop.h>
+ #include <qsocketnotifier.h>
+
+ #include <klocale.h>
+ #include <kdebug.h>
+ #include <kpushbutton.h>
+ #include <klineedit.h>
+ #include <kstatusbar.h>
+ #include <kmessagebox.h>
+ #include <kapplication.h>
+ #include <kprogress.h>
+ #include <kurl.h>
+ #include <kdirlister.h>
+ #include <kaction.h>
+
+
+ #define STD_BUFFER_SIZ 1024000
+ #define FRAME_ILEN 1024
+
+ INDIStdDevice::INDIStdDevice(INDI_D *associatedDevice, KStars * kswPtr)
+ {
+
+ dp = associatedDevice;
+ ksw = kswPtr;
+ initDevCounter = 0;
+ seqCount = 0;
+ batchMode = false;
+ ISOMode = false;
+
+ currentObject = NULL;
+ streamWindow = new StreamWG(this, ksw);
+ CCDPreviewWindow = new CCDPreviewWG(this, ksw);
+
+ devTimer = new QTimer(this);
+ seqLister = new KDirLister();
+
+ telescopeSkyObject = new SkyObject(0, 0, 0, 0, i18n("Telescope"));
+ ksw->data()->appendTelescopeObject(telescopeSkyObject);
+
+ connect( devTimer, SIGNAL(timeout()), this, SLOT(timerDone()) );
+ connect( seqLister, SIGNAL(newItems (const KFileItemList & )), this, SLOT(checkSeqBoundary(const KFileItemList &)));
+
+ downloadDialog = new KProgressDialog(NULL, 0, i18n("INDI"), i18n("Downloading Data..."));
+ downloadDialog->cancel();
+
+ parser = newLilXML();
+ }
+
+ INDIStdDevice::~INDIStdDevice()
+ {
+ streamWindow->enableStream(false);
+ streamWindow->close();
+ CCDPreviewWindow->enableStream(false);
+ CCDPreviewWindow->close();
+ streamDisabled();
+ delete (seqLister);
+ }
+
+void INDIStdDevice::handleBLOB(unsigned char *buffer, int bufferSize, QString dataFormat)
+{
+
+ if (dataFormat == ".fits") dataType = DATA_FITS;
+ else if (dataFormat == ".stream") dataType = DATA_STREAM;
+ else if (dataFormat == ".ccdpreview") dataType = DATA_CCDPREVIEW;
+ else dataType = DATA_OTHER;
+
+ if (dataType == DATA_STREAM)
+ {
+ if (!streamWindow->processStream)
+ return;
+
+ streamWindow->show();
+ streamWindow->streamFrame->newFrame( buffer, bufferSize, streamWindow->streamWidth, streamWindow->streamHeight);
+ }
+ else if (dataType == DATA_CCDPREVIEW)
+ {
+ if (!CCDPreviewWindow->processStream)
+ return;
+ CCDPreviewWindow->show();
+ CCDPreviewWindow->streamFrame->newFrame( buffer, bufferSize, CCDPreviewWindow->streamWidth, CCDPreviewWindow->streamHeight);
+ }
+ else if (dataType == DATA_FITS || dataType == DATA_OTHER)
+ {
+ char filename[256];
+ FILE *fitsTempFile;
+ int fd, nr, n=0;
+ QString currentDir = Options::fitsSaveDirectory();
+
+ streamWindow->close();
+
+ if (dataType == DATA_FITS && !batchMode && Options::indiFITSDisplay())
+ {
+ strcpy(filename, "/tmp/fitsXXXXXX");
+ if ((fd = mkstemp(filename)) < 0)
+ {
+ KMessageBox::error(NULL, "Error making temporary filename.");
+ return;
+ }
+ close(fd);
+ }
+ else
+ {
+ char ts[32];
+ struct tm *tp;
+ time_t t;
+ time (&t);
+ tp = gmtime (&t);
+
+ if (currentDir[currentDir.length() -1] == '/')
+ currentDir.truncate(currentDir.length() - 1);
+
+ strncpy(filename, currentDir.ascii(), currentDir.length());
+ filename[currentDir.length()] = '\0';
+
+ if (dataType == DATA_FITS)
+ {
+ char tempFileStr[256];
+ strncpy(tempFileStr, filename, 256);
+
+ if ( batchMode && !ISOMode)
+ snprintf(filename, sizeof(filename), "%s/%s_%02d.fits", tempFileStr, seqPrefix.ascii(), seqCount);
+ else if (!batchMode && !Options::indiFITSDisplay())
+ {
+ strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
+ snprintf(filename, sizeof(filename), "%s/file_%s.fits", tempFileStr, ts);
+ }
+ else
+ {
+ strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
+ snprintf(filename, sizeof(filename), "%s/%s_%02d_%s.fits", tempFileStr, seqPrefix.ascii(), seqCount, ts);
+ }
+
+ seqCount++;
+ }
+ else
+ {
+ strftime (ts, sizeof(ts), "/file-%Y-%m-%dT%H:%M:%S.", tp);
+ strncat(filename, ts, sizeof(ts));
+ strncat(filename, dataFormat.ascii(), 10);
+ }
+ }
+
+ fitsTempFile = fopen(filename, "w");
+
+ if (fitsTempFile == NULL) return;
+
+ for (nr=0; nr < (int) bufferSize; nr += n)
+ n = fwrite( ((unsigned char *) buffer) + nr, 1, bufferSize - nr, fitsTempFile);
+
+ fclose(fitsTempFile);
+
+ // We're done if we have DATA_OTHER
+ if (dataType == DATA_OTHER)
+ {
+ ksw->statusBar()->changeItem( i18n("Data file saved to %1").arg(filename), 0);
+ return;
+ }
+ else if (dataType == DATA_FITS && (batchMode || !Options::indiFITSDisplay()))
+ {
+ ksw->statusBar()->changeItem( i18n("FITS file saved to %1").arg(filename), 0);
+ emit FITSReceived(dp->label);
+ return;
+ }
+
+ KURL fileURL(filename);
+
+ FITSViewer * fv = new FITSViewer(&fileURL, ksw);
+ fv->fitsChange();
+ fv->show();
+ }
+
+}
+
+ /* Process standard Text and Number properties arrives from the driver */
+ void INDIStdDevice::setTextValue(INDI_P *pp)
+ {
+ INDI_E *el;
+ int wd, ht, bpp, bo, mu;
+ long mgd;
+ double fwhm;
+ int d, m, y, min, sec, hour;
+ ExtDate indiDate;
+ QTime indiTime;
+ KStarsDateTime indiDateTime;
+
+ switch (pp->stdID)
+ {
+
+ case TIME:
+ if ( Options::indiAutoTime() )
+ handleDevCounter();
+
+ // Update KStars time once we receive update from INDI
+ el = pp->findElement("UTC");
+ if (!el) return;
+
+ sscanf(el->text.ascii(), "%d%*[^0-9]%d%*[^0-9]%dT%d%*[^0-9]%d%*[^0-9]%d", &y, &m, &d, &hour, &min, &sec);
+ indiDate.setYMD(y, m, d);
+ indiTime.setHMS(hour, min, sec);
+ indiDateTime.setDate(indiDate);
+ indiDateTime.setTime(indiTime);
+
+ ksw->data()->changeDateTime(indiDateTime);
+ ksw->data()->syncLST();
+
+ break;
+
+ case SDTIME:
+ if ( Options::indiAutoTime())
+ handleDevCounter();
+ break;
+
+ case GEOGRAPHIC_COORD:
+ if ( Options::indiAutoGeo() )
+ handleDevCounter();
+ break;
+
+ case CCD_EXPOSE_DURATION:
+ if (pp->state == PS_IDLE || pp->state == PS_OK)
+ pp->set_w->setText(i18n("Start"));
+ break;
+
+ case CCD_FRAME:
+ el = pp->findElement("WIDTH");
+ if (!el) return;
+ wd = (int) el->value;
+ el = pp->findElement("HEIGHT");
+ if (!el) return;
+ ht = (int) el->value;
+
+ streamWindow->setSize(wd, ht);
+ //streamWindow->allocateStreamBuffer();
+ break;
+ case CCDPREVIEW_CTRL:
+ el = pp->findElement("WIDTH");
+ if (!el) return;
+ wd = (int) el->value;
+ el = pp->findElement("HEIGHT");
+ if (!el) return;
+ ht = (int) el->value;
+ el = pp->findElement("BYTEORDER");
+ if (!el) return;
+ bo = (int) el->value;
+ el = pp->findElement("BYTESPERPIXEL");
+ if (!el) return;
+ bpp = (int) el->value;
+ el = pp->findElement("MAXGOODDATA");
+ if (!el) return;
+ mgd = (long) el->value;
+ CCDPreviewWindow->setCtrl(wd, ht, bo ,bpp,mgd);
+
+ break;
+
+ case CCD_INFO:
+ el = pp->findElement("CCD_FWHM_PIXEL");
+ if (!el) return;
+ fwhm = el->value;
+ el = pp->findElement("CCD_PIXEL_SIZE");
+ if (!el) return;
+ mu = (int) el->value;
+ CCDPreviewWindow->setCCDInfo(fwhm, mu);
+ break;
+
+ case EQUATORIAL_COORD:
+ case EQUATORIAL_EOD_COORD:
+ if (!dp->isOn()) break;
+ el = pp->findElement("RA");
+ if (!el) return;
+ telescopeSkyObject->setRA(el->value);
+ el = pp->findElement("DEC");
+ if (!el) return;
+ telescopeSkyObject->setDec(el->value);
+ telescopeSkyObject->EquatorialToHorizontal(ksw->LST(), ksw->geo()->lat());
+ // Force immediate update of skymap if the focus object is our telescope.
+ if (ksw->map()->focusObject() == telescopeSkyObject)
+ ksw->map()->updateFocus();
+ else
+ ksw->map()->update();
+ break;
+
+ case HORIZONTAL_COORD:
+ if (!dp->isOn()) break;
+ el = pp->findElement("ALT");
+ if (!el) return;
+ telescopeSkyObject->setAlt(el->value);
+ el = pp->findElement("AZ");
+ if (!el) return;
+ telescopeSkyObject->setAz(el->value);
+ telescopeSkyObject->HorizontalToEquatorial(ksw->LST(), ksw->geo()->lat());
+ // Force immediate update of skymap if the focus object is our telescope.
+ if (ksw->map()->focusObject() == telescopeSkyObject)
+ ksw->map()->updateFocus();
+ else
+ ksw->map()->update();
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ void INDIStdDevice::setLabelState(INDI_P *pp)
+ {
+ INDI_E *lp;
+ INDI_P *imgProp;
+ KAction *tmpAction;
+ INDIDriver *drivers = ksw->getINDIDriver();
+ QFont buttonFont;
+
+ switch (pp->stdID)
+ {
+ case CONNECTION:
+ lp = pp->findElement("CONNECT");
+ if (!lp) return;
+
+ if (lp->state == PS_ON)
+ {
+ initDeviceOptions();
+ emit linkAccepted();
+
+ imgProp = dp->findProp("CCD_EXPOSE_DURATION");
+ if (imgProp)
+ {
+ tmpAction = ksw->actionCollection()->action("capture_sequence");
+ if (!tmpAction)
+ kdDebug() << "Warning: capture_sequence action not found" << endl;
+ else
+ tmpAction->setEnabled(true);
+ }
+ }
+ else
+ {
+ if (streamWindow)
+ {
+ //sNotifier->disconnect();
+ //dp->parentMgr->sNotifier->disconnect();
+ streamWindow->enableStream(false);
+ streamWindow->close();
+
+ //close(streamFD);
+ }
+
+ if (ksw->map()->focusObject() == telescopeSkyObject)
+ {
+ ksw->map()->stopTracking();
+ ksw->map()->setFocusObject(NULL);
+ }
+
+ drivers->updateMenuActions();
+ ksw->map()->forceUpdateNow();
+ emit linkRejected();
+ }
+ break;
+
+ case VIDEO_STREAM:
+ lp = pp->findElement("ON");
+ if (!lp) return;
+ if (lp->state == PS_ON)
+ streamWindow->enableStream(true);
+ else
+ streamWindow->enableStream(false);
+ break;
+
+ case CCDPREVIEW_STREAM:
+ lp = pp->findElement("ON");
+ if (!lp) return;
+ if (lp->state == PS_ON)
+ CCDPreviewWindow->enableStream(true);
+ else
+ CCDPreviewWindow->enableStream(false);
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ void INDIStdDevice::streamDisabled()
+ {
+ INDI_P *pp;
+ INDI_E *el;
+
+ //pp = dp->findProp("CONNECTION");
+ //if (!pp) return;
+ //if (pp->state == PS_OFF) return;
+
+ pp = dp->findProp("VIDEO_STREAM");
+ if (!pp) return;
+
+ el = pp->findElement("OFF");
+ if (!el) return;
+
+ if (el->state == PS_ON)
+ return;
+
+ // Turn stream off
+ pp->newSwitch(1);
+
+}
+
+ void INDIStdDevice::updateSequencePrefix(QString newPrefix)
+ {
+ seqPrefix = newPrefix;
+
+ seqLister->setNameFilter(QString("%1_*.fits").arg(seqPrefix));
+
+ seqCount = 0;
+
+ if (ISOMode) return;
+
+ seqLister->openURL(Options::fitsSaveDirectory());
+
+ checkSeqBoundary(seqLister->items());
+
+ }
+
+ void INDIStdDevice::checkSeqBoundary(const KFileItemList & items)
+ {
+ int newFileIndex;
+ QString tempName;
+ char *tempPrefix = new char[64];
+
+ // No need to check when in ISO mode
+ if (ISOMode)
+ return;
+
+ for ( KFileItemListIterator it( items ) ; it.current() ; ++it )
+ {
+ tempName = it.current()->name();
+
+ // find the prefix first
+ if (tempName.find(seqPrefix) == -1)
+ continue;
+
+ strncpy(tempPrefix, tempName.ascii(), 64);
+ tempPrefix[63] = '\0';
+
+ char * t = tempPrefix;
+
+ // skip chars
+ while (*t) { if (isdigit(*t)) break; t++; }
+ //tempPrefix = t;
+
+ newFileIndex = strtol(t, NULL, 10);
+
+ if (newFileIndex >= seqCount)
+ seqCount = newFileIndex + 1;
+ }
+
+ delete [] (tempPrefix);
+
+ }
+
+ void INDIStdDevice::updateTime()
+{
+ INDI_P *pp;
+ INDI_E *lp;
+
+ pp = dp->findProp("TIME");
+ if (!pp) return;
+
+ lp = pp->findElement("UTC");
+
+ if (!lp) return;
+
+ QTime newTime( ksw->data()->ut().time());
+ ExtDate newDate( ksw->data()->ut().date());
+
+ lp->write_w->setText(QString("%1-%2-%3T%4:%5:%6").arg(newDate.year()).arg(newDate.month())
+ .arg(newDate.day()).arg(newTime.hour())
+ .arg(newTime.minute()).arg(newTime.second()));
+ pp->newText();
+
+ pp = dp->findProp("SDTIME");
+ if (!pp) return;
+ lp = pp->findElement("LST");
+ if (!lp) return;
+
+ lp->write_w->setText(ksw->LST()->toHMSString());
+ pp->newText();
+}
+
+void INDIStdDevice::updateLocation()
+{
+ INDI_P *pp;
+ INDI_E * latEle, * longEle;
+ GeoLocation *geo = ksw->geo();
+
+ pp = dp->findProp("GEOGRAPHIC_COORD");
+ if (!pp) return;
+
+ dms tempLong (geo->lng()->degree(), geo->lng()->arcmin(), geo->lng()->arcsec());
+ dms fullCir(360,0,0);
+
+ if (tempLong.degree() < 0)
+ tempLong.setD ( fullCir.Degrees() + tempLong.Degrees());
+
+ latEle = pp->findElement("LAT");
+ if (!latEle) return;
+ longEle = pp->findElement("LONG");
+ if (!longEle) return;
+
+ longEle->write_w->setText(QString("%1:%2:%3").arg(tempLong.degree()).arg(tempLong.arcmin()).arg(tempLong.arcsec()));
+ latEle->write_w->setText(QString("%1:%2:%3").arg(geo->lat()->degree()).arg(geo->lat()->arcmin()).arg(geo->lat()->arcsec()));
+
+ pp->newText();
+}
+
+
+ void INDIStdDevice::registerProperty(INDI_P *pp)
+ {
+ INDI_E * portEle;
+ INDIDriver *drivers = ksw->getINDIDriver();
+ QString str;
+
+ switch (pp->stdID)
+ {
+ case DEVICE_PORT:
+ portEle = pp->findElement("PORT");
+ if (!portEle) return;
+
+ if (drivers)
+ {
+ for (unsigned int i=0; i < drivers->devices.size(); i++)
+ {
+ if (drivers->devices[i]->mgrID == dp->parentMgr->mgrID)
+ {
+ if (drivers->devices[i]->deviceType == KSTARS_TELESCOPE)
+ {
+ portEle->read_w->setText( Options::indiTelescopePort() );
+ portEle->write_w->setText( Options::indiTelescopePort() );
+ portEle->text = Options::indiTelescopePort();
+ break;
+ }
+ else if (drivers->devices[i]->deviceType == KSTARS_VIDEO)
+ {
+ portEle->read_w->setText( Options::indiVideoPort() );
+ portEle->write_w->setText( Options::indiVideoPort() );
+ portEle->text = Options::indiVideoPort();
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ }
+
+}
+
+void INDIStdDevice::initDeviceOptions()
+{
+
+ INDI_P *prop;
+
+ initDevCounter = 0;
+
+ if ( Options::indiAutoTime() )
+ {
+ prop = dp->findProp("TIME");
+ if (prop)
+ {
+ updateTime();
+ initDevCounter += 5;
+ }
+ }
+
+ if ( Options::indiAutoGeo() )
+ {
+ prop = dp->findProp("GEOGRAPHIC_COORD");
+ if (prop)
+ {
+ updateLocation();
+ initDevCounter += 2;
+ }
+ }
+
+ if ( Options::indiMessages() )
+ ksw->statusBar()->changeItem( i18n("%1 is online.").arg(dp->name), 0);
+
+ ksw->map()->forceUpdateNow();
+}
+
+ void INDIStdDevice::handleDevCounter()
+{
+
+ if (initDevCounter <= 0)
+ return;
+
+ initDevCounter--;
+
+ if ( initDevCounter == 0 && Options::indiMessages() )
+ ksw->statusBar()->changeItem( i18n("%1 is online and ready.").arg(dp->name), 0);
+
+}
+
+bool INDIStdDevice::handleNonSidereal()
+{
+ if (!currentObject)
+ return false;
+
+ int trackIndex=0;
+ INDI_E *nameEle;
+
+ kdDebug() << "Object of type " << currentObject->typeName() << endl;
+ //TODO Meade claims that the library access is available to
+ // all telescopes, which is unture. Only classic meade support
+ // that. They claim that library funcion will be available to all
+ // in "later" firmware revisions for the autostar and GPS.
+ // As a temprory solution, I'm going to explicity check for the
+ // device name which ideally I'm not supposed to do since all properties
+ // should be defined from the INDI driver, but since the INDI autostar
+ // and gps define the library functions (based on Meade's future claims)
+ // I will check the device name until Meade's respondes to my query.
+
+ // Update: Solution
+ // Only Meade Classic will offer an explicit SOLAR_SYSTEM property. If such a property exists
+ // then we take advantage of it. Otherwise, we send RA/DEC to the telescope and start a timer
+ // based on the object type. Objects with high proper motions will require faster updates.
+ // handle Non Sideral is ONLY called when tracking an object, not slewing.
+ INDI_P *prop = dp->findProp(QString("SOLAR_SYSTEM"));
+ INDI_P *setMode = dp->findProp(QString("ON_COORD_SET"));
+
+ // If the device support it
+ if (prop && setMode)
+ {
+ for (unsigned int i=0; i < setMode->el.count(); i++)
+ if (setMode->el.at(i)->name == "TRACK")
+ { trackIndex = i; break; }
+
+ kdDebug() << "Device supports SOLAR_SYSTEM property" << endl;
+
+ for (unsigned int i=0; i < prop->el.count(); i++)
+ if (currentObject->name().lower() == prop->el.at(i)->label.lower())
+ {
+ prop->newSwitch(i);
+ setMode->newSwitch(trackIndex);
+
+ /* Send object name if available */
+ nameEle = dp->findElem("OBJECT_NAME");
+ if (nameEle && nameEle->pp->perm != PP_RO)
+ {
+ nameEle->write_w->setText(currentObject->name());
+ nameEle->pp->newText();
+ }
+
+ return true;
+ }
+ }
+
+ kdDebug() << "Device doesn't support SOLAR_SYSTEM property, issuing a timer" << endl;
+ kdDebug() << "Starting timer for object of type " << currentObject->typeName() << endl;
+
+
+ switch (currentObject->type())
+ {
+ // Planet/Moon
+ case 2:
+ kdDebug() << "Initiating pulse tracking for " << currentObject->name() << endl;
+ devTimer->start(INDI_PULSE_TRACKING);
+ break;
+ // Comet/Asteroid
+ case 9:
+ case 10:
+ kdDebug() << "Initiating pulse tracking for " << currentObject->name() << endl;
+ devTimer->start(INDI_PULSE_TRACKING);
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+void INDIStdDevice::timerDone()
+{
+ INDI_P *prop;
+ INDI_E *RAEle, *DecEle;
+ INDI_E *el;
+ bool useJ2000 = false;
+
+ if (!dp->isOn())
+ {
+ devTimer->stop();
+ return;
+ }
+
+ prop = dp->findProp("ON_COORD_SET");
+ if (prop == NULL || !currentObject)
+ return;
+
+ el = prop->findElement("TRACK");
+ if (!el) return;
+
+ if (el->state != PS_ON)
+ {
+ devTimer->stop();
+ return;
+ }
+
+ prop = dp->findProp("EQUATORIAL_EOD_COORD");
+
+ if (prop == NULL)
+ {
+ prop = dp->findProp("EQUATORIAL_COORD");
+ if (prop) useJ2000 = true;
+ }
+
+ if (prop == NULL || !currentObject)
+ return;
+
+ // wait until slew is done
+ if (prop->state == PS_BUSY)
+ return;
+
+ kdDebug() << "Timer called, starting processing" << endl;
+
+ SkyPoint sp(currentObject->ra(), currentObject->dec());
+
+ kdDebug() << "RA: " << currentObject->ra()->toHMSString() << " - DEC: " << currentObject->dec()->toDMSString() << endl;
+ kdDebug() << "Az: " << currentObject->az()->toHMSString() << " - Alt " << currentObject->alt()->toDMSString() << endl;
+
+ if (useJ2000)
+ {
+ sp.set(currentObject->ra(), currentObject->dec());
+ sp.apparentCoord( ksw->data()->ut().djd() , (long double) J2000);
+ }
+
+ // We need to get from JNow (Skypoint) to J2000
+ // The ra0() of a skyPoint is the same as its JNow ra() without this process
+
+ // Use J2000 coordinate as required by INDI
+ RAEle = prop->findElement("RA");
+ if (!RAEle) return;
+ DecEle = prop->findElement("DEC");
+ if (!DecEle) return;
+
+ RAEle->write_w->setText(QString("%1:%2:%3").arg(sp.ra()->hour())
+ .arg(sp.ra()->minute())
+ .arg(sp.ra()->second()));
+ DecEle->write_w->setText(QString("%1:%2:%3").arg(sp.dec()->degree())
+ .arg(sp.dec()->arcmin())
+ .arg(sp.dec()->arcsec()));
+ prop->newText();
+
+}
+
+INDIStdProperty::INDIStdProperty(INDI_P *associatedProperty, KStars * kswPtr, INDIStdDevice *stdDevPtr)
+{
+ pp = associatedProperty;
+ ksw = kswPtr;
+ stdDev = stdDevPtr;
+}
+
+ INDIStdProperty::~INDIStdProperty()
+ {
+
+ }
+
+ void INDIStdProperty::newText()
+ {
+ INDI_E *lp;
+ INDIDriver *drivers = ksw->getINDIDriver();
+
+ switch (pp->stdID)
+ {
+ /* Set expose duration button to 'cancel' when busy */
+ case CCD_EXPOSE_DURATION:
+ pp->set_w->setText(i18n("Cancel"));
+ break;
+
+ /* Save Port name in KStars options */
+ case DEVICE_PORT:
+ lp = pp->findElement("PORT");
+
+ if (lp && drivers)
+ {
+ for (unsigned int i=0; i < drivers->devices.size(); i++)
+ {
+ if (drivers->devices[i]->mgrID == stdDev->dp->parentMgr->mgrID)
+ {
+ if (drivers->devices[i]->deviceType == KSTARS_TELESCOPE)
+ {
+ Options::setIndiTelescopePort( lp->text );
+ kdDebug() << "Setting telescope port " << lp->text << endl;
+ }
+ else if (drivers->devices[i]->deviceType == KSTARS_VIDEO)
+ {
+ Options::setIndiVideoPort( lp->text );
+ kdDebug() << "Setting video port " << lp->text << endl;
+ }
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ }
+
+ bool INDIStdProperty::convertSwitch(int switchIndex, INDI_E *lp)
+ {
+
+ INDI_E *RAEle(NULL), *DecEle(NULL), *AzEle(NULL), *AltEle(NULL), *nameEle(NULL);
+ INDI_P * prop;
+ SkyPoint sp;
+ int selectedCoord=0; /* 0 for Equatorial, 1 for Horizontal */
+ bool useJ2000 (false);
+
+ switch (pp->stdID)
+ {
+ /* Handle Slew/Track/Sync */
+ case ON_COORD_SET:
+ // #1 set current object to NULL
+ stdDev->currentObject = NULL;
+ // #2 Deactivate timer if present
+ if (stdDev->devTimer->isActive())
+ stdDev->devTimer->stop();
+
+ prop = pp->pg->dp->findProp("EQUATORIAL_EOD_COORD");
+ if (prop == NULL)
+ {
+ prop = pp->pg->dp->findProp("EQUATORIAL_COORD");
+ if (prop == NULL)
+ {
+ prop = pp->pg->dp->findProp("HORIZONTAL_COORD");
+ if (prop == NULL)
+ return false;
+ else
+ selectedCoord = 1; /* Select horizontal */
+ }
+ else
+ useJ2000 = true;
+ }
+
+ switch (selectedCoord)
+ {
+ // Equatorial
+ case 0:
+ if (prop->perm == PP_RO) return false;
+ RAEle = prop->findElement("RA");
+ if (!RAEle) return false;
+ DecEle = prop->findElement("DEC");
+ if (!DecEle) return false;
+ break;
+
+ // Horizontal
+ case 1:
+ if (prop->perm == PP_RO) return false;
+ AzEle = prop->findElement("AZ");
+ if (!AzEle) return false;
+ AltEle = prop->findElement("ALT");
+ if (!AltEle) return false;
+ break;
+ }
+
+ stdDev->currentObject = ksw->map()->clickedObject();
+ // Track is similar to slew, except that for non-sidereal objects
+ // it tracks the objects automatically via a timer.
+ if ((lp->name == "TRACK"))
+ if (stdDev->handleNonSidereal())
+ return true;
+
+ /* Send object name if available */
+ if (stdDev->currentObject)
+ {
+ nameEle = pp->pg->dp->findElem("OBJECT_NAME");
+ if (nameEle && nameEle->pp->perm != PP_RO)
+ {
+ nameEle->write_w->setText(stdDev->currentObject->name());
+ nameEle->pp->newText();
+ }
+ }
+
+ switch (selectedCoord)
+ {
+ case 0:
+ if (stdDev->currentObject)
+ sp.set (stdDev->currentObject->ra(), stdDev->currentObject->dec());
+ else
+ sp.set (ksw->map()->clickedPoint()->ra(), ksw->map()->clickedPoint()->dec());
+
+ if (useJ2000)
+ sp.apparentCoord(ksw->data()->ut().djd(), (long double) J2000);
+
+ RAEle->write_w->setText(QString("%1:%2:%3").arg(sp.ra()->hour()).arg(sp.ra()->minute()).arg(sp.ra()->second()));
+ DecEle->write_w->setText(QString("%1:%2:%3").arg(sp.dec()->degree()).arg(sp.dec()->arcmin()).arg(sp.dec()->arcsec()));
+
+ break;
+
+ case 1:
+ if (stdDev->currentObject)
+ {
+ sp.setAz(*stdDev->currentObject->az());
+ sp.setAlt(*stdDev->currentObject->alt());
+ }
+ else
+ {
+ sp.setAz(*ksw->map()->clickedPoint()->az());
+ sp.setAlt(*ksw->map()->clickedPoint()->alt());
+ }
+
+ AzEle->write_w->setText(QString("%1:%2:%3").arg(sp.az()->degree()).arg(sp.az()->arcmin()).arg(sp.az()->arcsec()));
+ AltEle->write_w->setText(QString("%1:%2:%3").arg(sp.alt()->degree()).arg(sp.alt()->arcmin()).arg(sp.alt()->arcsec()));
+
+ break;
+ }
+
+ pp->newSwitch(switchIndex);
+ prop->newText();
+
+ return true;
+ break;
+
+ /* Handle Abort */
+ case ABORT_MOTION:
+ kdDebug() << "Stopping timer." << endl;
+ stdDev->devTimer->stop();
+ pp->newSwitch(switchIndex);
+ return true;
+ break;
+
+ case MOVEMENT:
+ pp->newSwitch(switchIndex);
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ return false;
+
+ }
+
+// Return true if the complete operation is done here, or false if the operation is to be completed in the properties newSwitch()
+bool INDIStdProperty::newSwitch(int id, INDI_E* el)
+{
+ INDI_P *prop;
+ el=el;
+
+ switch (pp->stdID)
+ {
+ case CONNECTION:
+ if (id == 1)
+ stdDev->streamDisabled();
+ else
+ {
+ prop = pp->pg->dp->findProp("DEVICE_PORT");
+ if (prop)
+ prop->newText();
+ }
+ break;
+ case ABORT_MOTION:
+ case PARK:
+ case MOVEMENT:
+ //TODO add text in the status bar "Slew aborted."
+ stdDev->devTimer->stop();
+ break;
+ default:
+ break;
+ }
+
+ return false;
+
+}
+
+void INDIStdProperty::newTime()
+{
+ INDI_E * timeEle;
+ INDI_P *SDProp;
+
+ timeEle = pp->findElement("UTC");
+ if (!timeEle) return;
+
+ TimeDialog timedialog ( ksw->data()->ut(), ksw );
+
+ if ( timedialog.exec() == QDialog::Accepted )
+ {
+ QTime newTime( timedialog.selectedTime() );
+ ExtDate newDate( timedialog.selectedDate() );
+
+ timeEle->write_w->setText(QString("%1-%2-%3T%4:%5:%6")
+ .arg(newDate.year()).arg(newDate.month())
+ .arg(newDate.day()).arg(newTime.hour())
+ .arg(newTime.minute()).arg(newTime.second()));
+ pp->newText();
+ }
+ else return;
+
+ SDProp = pp->pg->dp->findProp("SDTIME");
+ if (!SDProp) return;
+ timeEle = SDProp->findElement("LST");
+ if (!timeEle) return;
+
+ timeEle->write_w->setText(ksw->LST()->toHMSString());
+ SDProp->newText();
+}
+
+#include "indistd.moc"