diff --git a/kstars/indi/streamform.ui b/kstars/indi/streamform.ui
index 0f936934f..c54c5b319 100644
--- a/kstars/indi/streamform.ui
+++ b/kstars/indi/streamform.ui
@@ -1,397 +1,376 @@
streamForm
0
0
- 491
+ 504
356
0
0
Video Stream
3
3
3
3
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
-
+
+
+
+ 0
+ 0
+
- Zoom out
-
-
-
-
-
-
- 32
- 32
-
+ Zoom level
+
-
+
+ 1x
+
+
+ -
+
+ 5x
+
+
+ -
+
+ 10x
+
+
-
3
-
-
-
+
-
+
false
+
+
+ 0
+ 0
+
+
- 32
- 32
+ 100
+ 0
-
-
+
+ Move zoomed view Up/Down
+
+
+ Qt::Horizontal
-
false
0
0
100
0
Move zoomed view Left/Right
Qt::Horizontal
- -
-
+
-
+
false
-
-
- 0
- 0
-
-
- 100
- 0
+ 32
+ 32
-
- Move zoomed view Up/Down
-
-
- Qt::Horizontal
+
+
-
Qt::Horizontal
QSizePolicy::Preferred
40
20
-
FPS
-
-
+
0
0
Target FPS
1
60
-
32
32
Apply FPS and restart stream
-
+
+ ..
24
24
-
FPS:
-
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 518e1eaa5..6cdf7d34a 100644
--- a/kstars/indi/streamwg.cpp
+++ b/kstars/indi/streamwg.cpp
@@ -1,341 +1,331 @@
/* 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
#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);
targetFPSSpin->setValue(1.0 / 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();
+ zoomLevelCombo->hide();
}
else
{
- connect(zoomInB, &QPushButton::clicked, [&]()
+ connect(zoomLevelCombo, static_cast(&QComboBox::activated), [&]()
{
ITextVectorProperty * tvp = eoszoom->getText();
- IUSaveText(&(tvp->tp[0]), "5");
- eoszoomActive = true;
+ QString zoomLevel = zoomLevelCombo->currentText().remove("x");
+ IUSaveText(&(tvp->tp[0]), zoomLevel.toLatin1().constData());
handLabel->setEnabled(true);
NSSlider->setEnabled(true);
WESlider->setEnabled(true);
+ // Set it twice!
currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp);
- });
+ QTimer::singleShot(1000, this, [ &, tvp]()
+ {
+ 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();
horizontalSpacer->changeSize(1, 1, QSizePolicy::Expanding);
}
else
{
connect(NSSlider, &QSlider::sliderReleased, [&]()
{
ITextVectorProperty * tvp = eoszoomposition->getText();
QString pos = QString("%1,%2").arg(WESlider->value()).arg(NSSlider->value());
IUSaveText(&(tvp->tp[0]), pos.toLatin1().constData());
currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp);
});
connect(WESlider, &QSlider::sliderReleased, [&]()
{
ITextVectorProperty * tvp = eoszoomposition->getText();
QString pos = QString("%1,%2").arg(WESlider->value()).arg(NSSlider->value());
IUSaveText(&(tvp->tp[0]), pos.toLatin1().constData());
currentCCD->getDriverInfo()->getClientManager()->sendNewText(tvp);
});
horizontalSpacer->changeSize(1, 1, QSizePolicy::Preferred);
}
connect(currentCCD, SIGNAL(newFPS(double, double)), this, SLOT(updateFPS(double, double)));
connect(changeFPSB, &QPushButton::clicked, this, [&]()
{
if (currentCCD)
{
currentCCD->setStreamExposure(1.0 / targetFPSSpin->value());
currentCCD->setVideoStreamEnabled(false);
QTimer::singleShot(1000, this, [&]()
{
currentCCD->setVideoStreamEnabled(true);
});
}
});
}
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("--");
avgFPS->setText("--");
hide();
}
}
void StreamWG::setSize(int wd, int ht)
{
if (wd != streamWidth || ht != streamHeight)
{
streamWidth = wd;
streamHeight = ht;
NSSlider->setMaximum(ht);
NSSlider->setSingleStep(ht / 30);
WESlider->setMaximum(wd);
WESlider->setSingleStep(wd / 30);
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)
{
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 6116a856f..ea17645f7 100644
--- a/kstars/indi/streamwg.h
+++ b/kstars/indi/streamwg.h
@@ -1,93 +1,100 @@
/* 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
+ Q_OBJECT
- public:
- explicit RecordOptions(QWidget *parent);
+ public:
+ explicit RecordOptions(QWidget *parent);
- public slots:
- void selectRecordDirectory();
+ public slots:
+ void selectRecordDirectory();
- private:
- QUrl dirPath;
+ private:
+ QUrl dirPath;
- friend class StreamWG;
+ 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;
+ 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};
+ RecordOptions *options;
};