diff --git a/kstars/indi/streamform.ui b/kstars/indi/streamform.ui index 9620e5063..d5c544781 100644 --- a/kstars/indi/streamform.ui +++ b/kstars/indi/streamform.ui @@ -1,267 +1,372 @@ streamForm 0 0 - 326 - 281 + 491 + 356 0 0 Video Stream 3 3 3 3 - 1 + 3 3 32 32 64 64 Start recording 32 32 32 32 64 64 Recording options 32 32 32 32 64 64 Reset frame 32 32 + + + + Qt::Vertical + + + + + + + true + + + + 32 + 32 + + + + Zoom in + + + + + + + 32 + 32 + + + + + + + + true + + + + 32 + 32 + + + + Zoom out + + + + + + + 32 + 32 + + + + + + + + 3 + + + + + false + + + + 32 + 32 + + + + + + + + + + + false + + + + 0 + 0 + + + + + 100 + 0 + + + + Move zoomed view Left/Right + + + Qt::Horizontal + + + + + + + false + + + + 0 + 0 + + + + + 100 + 0 + + + + Move zoomed view Up/Down + + + Qt::Horizontal + + + + + Qt::Horizontal + + QSizePolicy::Preferred + 40 20 Exp: 3 0.001000000000000 10.000000000000000 0.100000000000000 0.100000000000000 FPS: - - - - - 50 - 0 - - - - Instant FPS - - - font-weight:bold; - - - QFrame::NoFrame - - - QFrame::Plain - - - -- - - - Qt::AlignCenter - - - 50 0 Average FPS font-weight:bold; QFrame::NoFrame QFrame::Plain -- Qt::AlignCenter 0 0 320 240 false background-color:black; Qt::AlignCenter VideoWG QLabel
indi/videowg.h
diff --git a/kstars/indi/streamwg.cpp b/kstars/indi/streamwg.cpp index f46ffd1a6..03b65e94f 100644 --- a/kstars/indi/streamwg.cpp +++ b/kstars/indi/streamwg.cpp @@ -1,262 +1,325 @@ /* Stream Widget Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com) This application 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-03-16: A class to handle video streaming. */ #include "streamwg.h" #include "indistd.h" +#include "driverinfo.h" +#include "clientmanager.h" #include "kstars.h" #include "Options.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include RecordOptions::RecordOptions(QWidget *parent) : QDialog(parent) { #ifdef Q_OS_OSX setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); #endif setupUi(this); dirPath = QUrl::fromLocalFile(QDir::homePath()); selectDirB->setIcon( QIcon::fromTheme("document-open-folder")); connect(selectDirB, SIGNAL(clicked()), this, SLOT(selectRecordDirectory())); } void RecordOptions::selectRecordDirectory() { QString dir = QFileDialog::getExistingDirectory(KStars::Instance(), i18n("SER Record Directory"), dirPath.toLocalFile()); if (dir.isEmpty()) return; recordDirectoryEdit->setText(dir); } StreamWG::StreamWG(ISD::CCD *ccd) : QDialog(KStars::Instance()) { setupUi(this); currentCCD = ccd; streamWidth = streamHeight = -1; processStream = colorFrame = isRecording = false; options = new RecordOptions(this); connect(optionsB, SIGNAL(clicked()), options, SLOT(show())); QString filename, directory; ccd->getSERNameDirectory(filename, directory); double duration = 0.1; currentCCD->getStreamExposure(&duration); videoExposure->setValue(duration); options->recordFilenameEdit->setText(filename); options->recordDirectoryEdit->setText(directory); setWindowTitle(i18n("%1 Live Video", ccd->getDeviceName())); #ifdef Q_OS_OSX setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); #endif recordIcon = QIcon::fromTheme("media-record"); stopIcon = QIcon::fromTheme("media-playback-stop"); optionsB->setIcon(QIcon::fromTheme("run-build")); resetFrameB->setIcon(QIcon::fromTheme("view-restore")); connect(resetFrameB, SIGNAL(clicked()), this, SLOT(resetFrame())); recordB->setIcon(recordIcon); connect(recordB, SIGNAL(clicked()), this, SLOT(toggleRecord())); connect(ccd, SIGNAL(videoRecordToggled(bool)), this, SLOT(updateRecordStatus(bool))); connect(videoFrame, &VideoWG::newSelection, this, &StreamWG::setStreamingFrame); connect(videoFrame, &VideoWG::imageChanged, this, &StreamWG::imageChanged); resize(Options::streamWindowWidth(), Options::streamWindowHeight()); + zoomInB->setIcon(QIcon::fromTheme("zoom-in")); + zoomOutB->setIcon(QIcon::fromTheme("zoom-out")); + handLabel->setPixmap(QIcon::fromTheme("hand").pixmap(32,32)); + + eoszoom = currentCCD->getProperty("eoszoom"); + if (eoszoom == nullptr) + { + zoomInB->hide(); + zoomOutB->hide(); + } + else + { + connect(zoomInB, &QPushButton::clicked, [&]() { + ITextVectorProperty *tvp = eoszoom->getText(); + IUSaveText(&(tvp->tp[0]), "5"); + eoszoomActive = true; + handLabel->setEnabled(true); + NSSlider->setEnabled(true); + WESlider->setEnabled(true); + currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp); + }); + + connect(zoomOutB, &QPushButton::clicked, [&]() { + ITextVectorProperty *tvp = eoszoom->getText(); + IUSaveText(&(tvp->tp[0]), "0"); + eoszoomActive = false; + handLabel->setEnabled(false); + NSSlider->setEnabled(false); + WESlider->setEnabled(false); + currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp); + }); + } + + eoszoomposition = currentCCD->getProperty("eoszoomposition"); + if (eoszoomposition == nullptr) + { + handLabel->hide(); + NSSlider->hide(); + WESlider->hide(); + } + else + { + connect(NSSlider, &QSlider::valueChanged, [&]() { + ITextVectorProperty *tvp = eoszoomposition->getText(); + QString pos = QString("%1,%2").arg(NSSlider->value()).arg(WESlider->value()); + IUSaveText(&(tvp->tp[0]), pos.toLatin1().constData()); + currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp); + }); + + connect(WESlider, &QSlider::valueChanged, [&]() { + ITextVectorProperty *tvp = eoszoomposition->getText(); + QString pos = QString("%1,%2").arg(NSSlider->value()).arg(WESlider->value()); + IUSaveText(&(tvp->tp[0]), pos.toLatin1().constData()); + currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp); + }); + } + connect(currentCCD, SIGNAL(newFPS(double,double)), this, SLOT(updateFPS(double,double))); connect(videoExposure, static_cast(&QDoubleSpinBox::valueChanged), [&](double value) { if (currentCCD) currentCCD->setStreamExposure(value); }); } QSize StreamWG::sizeHint() const { QSize size(Options::streamWindowWidth(), Options::streamWindowHeight()); return size; } void StreamWG::closeEvent(QCloseEvent *ev) { processStream = false; Options::setStreamWindowWidth(width()); Options::setStreamWindowHeight(height()); ev->accept(); emit hidden(); } void StreamWG::setColorFrame(bool color) { colorFrame = color; } void StreamWG::enableStream(bool enable) { if (enable) { processStream = true; show(); } else { processStream = false; - instFPS->setText("--"); + //instFPS->setText("--"); avgFPS->setText("--"); hide(); } } void StreamWG::setSize(int wd, int ht) { - // Initial resize - /*if (streamWidth == -1) - resize(Options::streamWindowWidth() + layout()->margin() * 2, - Options::streamWindowHeight()+ playB->height() + layout()->margin() * 4 + layout()->spacing());*/ + if (wd != streamWidth || ht != streamHeight) + { + streamWidth = wd; + streamHeight = ht; - streamWidth = wd; - streamHeight = ht; + NSSlider->setMaximum(ht); + NSSlider->setSingleStep(ht/30); + WESlider->setMaximum(wd); + WESlider->setSingleStep(wd/30); - videoFrame->setSize(wd, ht); + videoFrame->setSize(wd, ht); + } } /*void StreamWG::resizeEvent(QResizeEvent *ev) { streamFrame->resize(ev->size().width() - layout()->margin() * 2, ev->size().height() - playB->height() - layout()->margin() * 4 - layout()->spacing()); }*/ void StreamWG::updateRecordStatus(bool enabled) { if ((enabled && isRecording) || (!enabled && !isRecording)) return; isRecording = enabled; if (isRecording) { recordB->setIcon(stopIcon); recordB->setToolTip(i18n("Stop recording")); } else { recordB->setIcon(recordIcon); recordB->setToolTip(i18n("Start recording")); } } void StreamWG::toggleRecord() { if (isRecording) { recordB->setIcon(recordIcon); isRecording = false; recordB->setToolTip(i18n("Start recording")); currentCCD->stopRecording(); } else { currentCCD->setSERNameDirectory(options->recordFilenameEdit->text(), options->recordDirectoryEdit->text()); // Save config in INDI so the filename and directory templates are reloaded next time currentCCD->setConfig(SAVE_CONFIG); if (options->recordUntilStoppedR->isChecked()) { isRecording = currentCCD->startRecording(); } else if (options->recordDurationR->isChecked()) { isRecording = currentCCD->startDurationRecording(options->durationSpin->value()); } else { isRecording = currentCCD->startFramesRecording(options->framesSpin->value()); } if (isRecording) { recordB->setIcon(stopIcon); recordB->setToolTip(i18n("Stop recording")); } } } void StreamWG::newFrame(IBLOB *bp) { bool rc = videoFrame->newFrame(bp); if (rc == false) qWarning() << "Failed to load video frame."; } void StreamWG::resetFrame() { currentCCD->resetStreamingFrame(); } void StreamWG::setStreamingFrame(QRect newFrame) { int w = newFrame.width(); // Must be divisable by 4 while (w % 4) { w++; } currentCCD->setStreamingFrame(newFrame.x(), newFrame.y(), w, newFrame.height()); } void StreamWG::updateFPS(double instantFPS, double averageFPS) { - instFPS->setText(QString::number(instantFPS, 'f', 1)); + Q_UNUSED(instantFPS); + //instFPS->setText(QString::number(instantFPS, 'f', 1)); avgFPS->setText(QString::number(averageFPS, 'f', 1)); } diff --git a/kstars/indi/streamwg.h b/kstars/indi/streamwg.h index 9b45435b8..6116a856f 100644 --- a/kstars/indi/streamwg.h +++ b/kstars/indi/streamwg.h @@ -1,89 +1,93 @@ /* Stream Widget Copyright (C) 2003-2017 Jasem Mutlaq (mutlaqja@ikarustech.com) This application 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. */ #pragma once #include "indi/indiccd.h" #include "ui_streamform.h" #include "ui_recordingoptions.h" #include #include #include #include #include #include #include #include #include #include class RecordOptions : public QDialog, public Ui::recordingOptions { Q_OBJECT public: explicit RecordOptions(QWidget *parent); public slots: void selectRecordDirectory(); private: QUrl dirPath; friend class StreamWG; }; class StreamWG : public QDialog, public Ui::streamForm { Q_OBJECT public: explicit StreamWG(ISD::CCD *ccd); virtual ~StreamWG() override = default; void setColorFrame(bool color); void setSize(int wd, int ht); void enableStream(bool enable); bool isStreamEnabled() { return processStream; } void newFrame(IBLOB *bp); int getStreamWidth() { return streamWidth; } int getStreamHeight() { return streamHeight; } protected: void closeEvent(QCloseEvent *ev) override; QSize sizeHint() const override; public slots: void toggleRecord(); void updateRecordStatus(bool enabled); void resetFrame(); protected slots: void setStreamingFrame(QRect newFrame); void updateFPS(double instantFPS, double averageFPS); signals: void hidden(); void imageChanged(std::unique_ptr & frame); private: bool processStream; int streamWidth, streamHeight; bool colorFrame, isRecording; QIcon recordIcon, stopIcon; ISD::CCD *currentCCD; + // For Canon DSLRs + INDI::Property *eoszoom {nullptr}, *eoszoomposition {nullptr}; + bool eoszoomActive { false }; + RecordOptions *options; };