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
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;
};