Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 1 | /*************************************************************************** |
Edric Milaret | 4bba46d | 2015-04-29 16:33:38 -0400 | [diff] [blame] | 2 | * Copyright (C) 2015 by Savoir-Faire Linux * |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 3 | * 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 Milaret | 7153eed | 2015-06-03 15:29:03 -0400 | [diff] [blame] | 21 | #include <QApplication> |
| 22 | #include <QDesktopWidget> |
| 23 | |
Edric Milaret | aa50336 | 2015-06-08 14:07:04 -0400 | [diff] [blame^] | 24 | #include <memory> |
| 25 | |
| 26 | #include "video/devicemodel.h" |
| 27 | |
Edric Milaret | 7153eed | 2015-06-03 15:29:03 -0400 | [diff] [blame] | 28 | #include "selectareadialog.h" |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 29 | |
| 30 | VideoWidget::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 Milaret | 72c406d | 2015-04-28 13:23:54 -0400 | [diff] [blame] | 39 | this, SLOT(previewStarted(Video::Renderer*))); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 40 | connect(CallModel::instance(), |
| 41 | SIGNAL(rendererAdded(Call*,Video::Renderer*)), |
| 42 | this, SLOT(callInitiated(Call*, Video::Renderer*)), |
| 43 | Qt::ConnectionType::DirectConnection); |
Edric Milaret | a9f937f | 2015-06-01 17:10:34 -0400 | [diff] [blame] | 44 | |
| 45 | QPalette pal(palette()); |
| 46 | pal.setColor(QPalette::Background, Qt::black); |
| 47 | this->setAutoFillBackground(true); |
| 48 | this->setPalette(pal); |
Edric Milaret | 7153eed | 2015-06-03 15:29:03 -0400 | [diff] [blame] | 49 | |
| 50 | this->setContextMenuPolicy(Qt::CustomContextMenu); |
| 51 | connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), |
| 52 | this, SLOT(showContextMenu(const QPoint&))); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | VideoWidget::~VideoWidget() |
| 56 | {} |
| 57 | |
| 58 | void |
| 59 | VideoWidget::previewStarted(Video::Renderer *renderer) { |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 60 | previewRenderer_ = renderer; |
| 61 | connect(previewRenderer_, SIGNAL(frameUpdated()), |
| 62 | this, SLOT(frameFromPreview())); |
| 63 | connect(previewRenderer_, SIGNAL(stopped()), |
Edric Milaret | 72c406d | 2015-04-28 13:23:54 -0400 | [diff] [blame] | 64 | this, SLOT(previewStopped())); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | void |
Edric Milaret | 72c406d | 2015-04-28 13:23:54 -0400 | [diff] [blame] | 68 | VideoWidget::previewStopped() { |
| 69 | QMutexLocker {&lock_}; |
| 70 | disconnect(previewRenderer_, SIGNAL(frameUpdated()), |
| 71 | this, SLOT(frameFromPreview())); |
| 72 | disconnect(previewRenderer_, SIGNAL(stopped()), |
| 73 | this, SLOT(renderingStopped())); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 74 | previewRenderer_ = nullptr; |
| 75 | } |
| 76 | |
| 77 | void |
| 78 | VideoWidget::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 Milaret | 72c406d | 2015-04-28 13:23:54 -0400 | [diff] [blame] | 88 | update(); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 89 | } |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | void |
| 93 | VideoWidget::paintEvent(QPaintEvent* evt) { |
| 94 | Q_UNUSED(evt) |
| 95 | QMutexLocker {&lock_}; |
| 96 | QPainter painter(this); |
Edric Milaret | a9f937f | 2015-06-01 17:10:34 -0400 | [diff] [blame] | 97 | |
| 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 Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 104 | if (previewFrame_ && previewRenderer_ && previewRenderer_->isRendering()) { |
Edric Milaret | a9f937f | 2015-06-01 17:10:34 -0400 | [diff] [blame] | 105 | 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 Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 114 | } |
| 115 | painter.end(); |
| 116 | } |
| 117 | |
| 118 | void |
| 119 | VideoWidget::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 | |
| 127 | void |
| 128 | VideoWidget::frameFromDistant() { |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 129 | 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 Milaret | 72c406d | 2015-04-28 13:23:54 -0400 | [diff] [blame] | 138 | update(); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 139 | } |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | void |
| 143 | VideoWidget::renderingStopped() { |
| 144 | QMutexLocker {&lock_}; |
| 145 | if (distantFrame_) { |
| 146 | delete distantFrame_; |
| 147 | distantFrame_ = nullptr; |
| 148 | } |
Edric Milaret | 72c406d | 2015-04-28 13:23:54 -0400 | [diff] [blame] | 149 | disconnect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant())); |
| 150 | disconnect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped())); |
Edric Milaret | 627500d | 2015-03-27 16:41:40 -0400 | [diff] [blame] | 151 | renderer_ = nullptr; |
| 152 | } |
Edric Milaret | 435cdfc | 2015-06-01 16:15:50 -0400 | [diff] [blame] | 153 | |
| 154 | void |
| 155 | VideoWidget::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 Milaret | aa50336 | 2015-06-08 14:07:04 -0400 | [diff] [blame^] | 169 | |
Edric Milaret | 7153eed | 2015-06-03 15:29:03 -0400 | [diff] [blame] | 170 | void |
| 171 | VideoWidget::showContextMenu(const QPoint& pos) |
| 172 | { |
| 173 | QPoint globalPos = this->mapToGlobal(pos); |
| 174 | |
| 175 | QMenu menu; |
| 176 | |
Edric Milaret | aa50336 | 2015-06-08 14:07:04 -0400 | [diff] [blame^] | 177 | 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 Milaret | 7153eed | 2015-06-03 15:29:03 -0400 | [diff] [blame] | 194 | 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 | } |