blob: 965409282fe27e9ea09fd79683c01d59b43bea83 [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Edric Milaret4bba46d2015-04-29 16:33:38 -04002 * Copyright (C) 2015 by Savoir-Faire Linux *
Edric Milaret627500d2015-03-27 16:41:40 -04003 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 **************************************************************************/
18
19#include "videowidget.h"
20
Edric Milaret7153eed2015-06-03 15:29:03 -040021#include <QApplication>
22#include <QDesktopWidget>
23
Edric Milaretaa503362015-06-08 14:07:04 -040024#include <memory>
25
26#include "video/devicemodel.h"
27
Edric Milaret7153eed2015-06-03 15:29:03 -040028#include "selectareadialog.h"
Edric Milaret627500d2015-03-27 16:41:40 -040029
30VideoWidget::VideoWidget(QWidget *parent) :
31 QWidget(parent)
32 , previewRenderer_(nullptr)
33 , renderer_(nullptr)
34 , previewFrame_(nullptr)
35 , distantFrame_(nullptr)
36{
37 connect(Video::PreviewManager::instance(),
38 SIGNAL(previewStarted(Video::Renderer*)),
Edric Milaret72c406d2015-04-28 13:23:54 -040039 this, SLOT(previewStarted(Video::Renderer*)));
Edric Milaret627500d2015-03-27 16:41:40 -040040 connect(CallModel::instance(),
41 SIGNAL(rendererAdded(Call*,Video::Renderer*)),
42 this, SLOT(callInitiated(Call*, Video::Renderer*)),
43 Qt::ConnectionType::DirectConnection);
Edric Milareta9f937f2015-06-01 17:10:34 -040044
45 QPalette pal(palette());
46 pal.setColor(QPalette::Background, Qt::black);
47 this->setAutoFillBackground(true);
48 this->setPalette(pal);
Edric Milaret7153eed2015-06-03 15:29:03 -040049
50 this->setContextMenuPolicy(Qt::CustomContextMenu);
51 connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
52 this, SLOT(showContextMenu(const QPoint&)));
Edric Milaret627500d2015-03-27 16:41:40 -040053}
54
55VideoWidget::~VideoWidget()
56{}
57
58void
59VideoWidget::previewStarted(Video::Renderer *renderer) {
Edric Milaret627500d2015-03-27 16:41:40 -040060 previewRenderer_ = renderer;
61 connect(previewRenderer_, SIGNAL(frameUpdated()),
62 this, SLOT(frameFromPreview()));
63 connect(previewRenderer_, SIGNAL(stopped()),
Edric Milaret72c406d2015-04-28 13:23:54 -040064 this, SLOT(previewStopped()));
Edric Milaret627500d2015-03-27 16:41:40 -040065}
66
67void
Edric Milaret72c406d2015-04-28 13:23:54 -040068VideoWidget::previewStopped() {
69 QMutexLocker {&lock_};
70 disconnect(previewRenderer_, SIGNAL(frameUpdated()),
71 this, SLOT(frameFromPreview()));
72 disconnect(previewRenderer_, SIGNAL(stopped()),
73 this, SLOT(renderingStopped()));
Edric Milaret627500d2015-03-27 16:41:40 -040074 previewRenderer_ = nullptr;
75}
76
77void
78VideoWidget::frameFromPreview() {
79 if (previewFrame_) {
80 delete previewFrame_;
81 previewFrame_ = nullptr;
82 }
83 if (previewRenderer_ && previewRenderer_->isRendering()) {
84 const QSize size(previewRenderer_->size());
85 previewFrame_ = new QImage(
86 (const uchar*)previewRenderer_->currentFrame().constData(),
87 size.width(), size.height(), QImage::Format_RGBA8888);
Edric Milaret72c406d2015-04-28 13:23:54 -040088 update();
Edric Milaret627500d2015-03-27 16:41:40 -040089 }
Edric Milaret627500d2015-03-27 16:41:40 -040090}
91
92void
93VideoWidget::paintEvent(QPaintEvent* evt) {
94 Q_UNUSED(evt)
95 QMutexLocker {&lock_};
96 QPainter painter(this);
Edric Milareta9f937f2015-06-01 17:10:34 -040097
98 if (distantFrame_ && renderer_ && renderer_->isRendering()) {
99 auto scaledDistant = distantFrame_->scaled(size(), Qt::KeepAspectRatio);
100 auto xDiff = (width() - scaledDistant.width()) / 2;
101 auto yDiff = (height() - scaledDistant.height()) /2;
102 painter.drawImage(QRect(xDiff,yDiff,scaledDistant.width(),scaledDistant.height()), scaledDistant);
103 }
Edric Milaret627500d2015-03-27 16:41:40 -0400104 if (previewFrame_ && previewRenderer_ && previewRenderer_->isRendering()) {
Edric Milareta9f937f2015-06-01 17:10:34 -0400105 auto previewHeight = !renderer_ ? height() : height()/4;
106 auto previewWidth = !renderer_ ? width() : width()/4;
107 auto scaledPreview = previewFrame_->scaled(previewWidth, previewHeight, Qt::KeepAspectRatio);
108 auto xDiff = (previewWidth - scaledPreview.width()) / 2;
109 auto yDiff = (previewHeight - scaledPreview.height()) / 2;
110 auto yPos = !renderer_ ? yDiff : height() - previewHeight - previewMargin_;
111 auto xPos = !renderer_ ? xDiff : width() - scaledPreview.width() - previewMargin_;
112 painter.drawImage(QRect(xPos,yPos,scaledPreview.width(),scaledPreview.height()),
113 scaledPreview);
Edric Milaret627500d2015-03-27 16:41:40 -0400114 }
115 painter.end();
116}
117
118void
119VideoWidget::callInitiated(Call* call, Video::Renderer *renderer) {
120 Q_UNUSED(call)
121 renderer_ = renderer;
122 connect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
123 connect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()),
124 Qt::ConnectionType::DirectConnection);
125}
126
127void
128VideoWidget::frameFromDistant() {
Edric Milaret627500d2015-03-27 16:41:40 -0400129 if (distantFrame_) {
130 delete distantFrame_;
131 distantFrame_ = nullptr;
132 }
133 if (renderer_) {
134 const QSize size(renderer_->size());
135 distantFrame_ = new QImage(
136 (const uchar*) renderer_->currentFrame().constData(),
137 size.width(), size.height(), QImage::Format_RGBA8888);
Edric Milaret72c406d2015-04-28 13:23:54 -0400138 update();
Edric Milaret627500d2015-03-27 16:41:40 -0400139 }
Edric Milaret627500d2015-03-27 16:41:40 -0400140}
141
142void
143VideoWidget::renderingStopped() {
144 QMutexLocker {&lock_};
145 if (distantFrame_) {
146 delete distantFrame_;
147 distantFrame_ = nullptr;
148 }
Edric Milaret72c406d2015-04-28 13:23:54 -0400149 disconnect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
150 disconnect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()));
Edric Milaret627500d2015-03-27 16:41:40 -0400151 renderer_ = nullptr;
152}
Edric Milaret435cdfc2015-06-01 16:15:50 -0400153
154void
155VideoWidget::mouseDoubleClickEvent(QMouseEvent *e) {
156 QWidget::mouseDoubleClickEvent(e);
157 if(isFullScreen()) {
158 this->setParent(oldParent_);
159 this->showNormal();
160 this->resize(oldSize_.width(), oldSize_.height());
161 } else {
162 oldSize_ = this->size();
163 oldParent_ = static_cast<QWidget*>(this->parent());
164 this->setParent(0);
165 this->showFullScreen();
166 this->show();
167 }
168}
Edric Milaretaa503362015-06-08 14:07:04 -0400169
Edric Milaret7153eed2015-06-03 15:29:03 -0400170void
171VideoWidget::showContextMenu(const QPoint& pos)
172{
173 QPoint globalPos = this->mapToGlobal(pos);
174
175 QMenu menu;
176
Edric Milaretaa503362015-06-08 14:07:04 -0400177 for (auto device : Video::DeviceModel::instance()->devices()) {
178 std::unique_ptr<QAction> deviceAction(new QAction(device->name(), this));
179 deviceAction->setCheckable(true);
180 if (device == Video::DeviceModel::instance()->activeDevice())
181 deviceAction->setChecked(true);
182 auto ptr = deviceAction.release();
183 menu.addAction(ptr);
184 connect(ptr, &QAction::toggled, [=](bool checked) {
185 if (checked == true) {
186 Video::SourceModel::instance()->switchTo(device);
187 Video::DeviceModel::instance()->setActive(device);
188 }
189 });
190 }
191
192 menu.addSeparator();
193
Edric Milaret7153eed2015-06-03 15:29:03 -0400194 auto shareAction = new QAction("Share entire screen", this);
195 menu.addAction(shareAction);
196 connect(shareAction, &QAction::triggered, [=]() {
197 Video::SourceModel::instance()->setDisplay(0, QApplication::desktop()->rect());
198 });
199 auto shareAreaAction = new QAction("Share screen area", this);
200 menu.addAction(shareAreaAction);
201 connect(shareAreaAction, &QAction::triggered, [=]() {
202 SelectAreaDialog selec;
203 selec.exec();
204 });
205
206 menu.exec(globalPos);
207}