Commit 5d3cefcc authored by Ronan Abhamon's avatar Ronan Abhamon

feat(app): add camera component used by Calls views

parent 8de2b05b
...@@ -55,6 +55,7 @@ set(SOURCES ...@@ -55,6 +55,7 @@ set(SOURCES
src/app/Database.cpp src/app/Database.cpp
src/app/DefaultTranslator.cpp src/app/DefaultTranslator.cpp
src/app/Logger.cpp src/app/Logger.cpp
src/components/camera/Camera.cpp
src/components/chat/ChatModel.cpp src/components/chat/ChatModel.cpp
src/components/chat/ChatProxyModel.cpp src/components/chat/ChatProxyModel.cpp
src/components/contacts/ContactModel.cpp src/components/contacts/ContactModel.cpp
...@@ -76,6 +77,7 @@ set(HEADERS ...@@ -76,6 +77,7 @@ set(HEADERS
src/app/Database.hpp src/app/Database.hpp
src/app/DefaultTranslator.hpp src/app/DefaultTranslator.hpp
src/app/Logger.hpp src/app/Logger.hpp
src/components/camera/Camera.hpp
src/components/chat/ChatModel.hpp src/components/chat/ChatModel.hpp
src/components/chat/ChatProxyModel.hpp src/components/chat/ChatProxyModel.hpp
src/components/contacts/ContactModel.hpp src/components/contacts/ContactModel.hpp
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <QQuickView> #include <QQuickView>
#include <QtDebug> #include <QtDebug>
#include "../components/camera/Camera.hpp"
#include "../components/chat/ChatProxyModel.hpp" #include "../components/chat/ChatProxyModel.hpp"
#include "../components/contacts/ContactsListModel.hpp" #include "../components/contacts/ContactsListModel.hpp"
#include "../components/contacts/ContactsListProxyModel.hpp" #include "../components/contacts/ContactsListProxyModel.hpp"
...@@ -21,7 +22,7 @@ ...@@ -21,7 +22,7 @@
#define QML_VIEW_MAIN_WINDOW "qrc:/ui/views/App/MainWindow/MainWindow.qml" #define QML_VIEW_MAIN_WINDOW "qrc:/ui/views/App/MainWindow/MainWindow.qml"
#define QML_VIEW_CALL_WINDOW "qrc:/ui/views/App/Calls/Calls.qml" #define QML_VIEW_CALL_WINDOW "qrc:/ui/views/App/Calls/Calls.qml"
// =================================================================== // =============================================================================
App *App::m_instance = nullptr; App *App::m_instance = nullptr;
...@@ -102,6 +103,8 @@ void App::registerTypes () { ...@@ -102,6 +103,8 @@ void App::registerTypes () {
); );
// Register models. // Register models.
qmlRegisterType<Camera>("Linphone", 1, 0, "Camera");
qmlRegisterUncreatableType<ContactModel>( qmlRegisterUncreatableType<ContactModel>(
"Linphone", 1, 0, "ContactModel", "ContactModel is uncreatable" "Linphone", 1, 0, "ContactModel", "ContactModel is uncreatable"
); );
...@@ -163,14 +166,17 @@ void App::setTrayIcon () { ...@@ -163,14 +166,17 @@ void App::setTrayIcon () {
root->connect(restore_action, &QAction::triggered, root, &QQuickWindow::showNormal); root->connect(restore_action, &QAction::triggered, root, &QQuickWindow::showNormal);
// trayIcon: Left click actions. // trayIcon: Left click actions.
root->connect(m_system_tray_icon, &QSystemTrayIcon::activated, [root](QSystemTrayIcon::ActivationReason reason) { root->connect(
if (reason == QSystemTrayIcon::Trigger) { m_system_tray_icon, &QSystemTrayIcon::activated, [root](
if (root->visibility() == QWindow::Hidden) QSystemTrayIcon::ActivationReason reason) {
root->showNormal(); if (reason == QSystemTrayIcon::Trigger) {
else if (root->visibility() == QWindow::Hidden)
root->hide(); root->showNormal();
else
root->hide();
}
} }
}); );
// Build trayIcon menu. // Build trayIcon menu.
menu->addAction(restore_action); menu->addAction(restore_action);
......
#include <QOpenGLFunctions>
#include "Camera.hpp"
#define ATTRIBUTE_VERTEX 0
// =============================================================================
static const char *_vertex_shader = "attribute vec2 vertex;"
"uniform mat4 projection;"
"void main() {"
" gl_Position = projection * vec4(vertex.xy, 0, 1);"
"}";
static const char *_fragment_shader = "void main() {"
" gl_FragColor = vec4(vec3(1.0, 0.0, 0.0), 1.0);"
"}";
static const GLfloat _camera_vertices[] = {
0.0f, 0.0f,
50.0f, 0.0f,
0.0f, 50.0f,
50.0f, 50.0f
};
// -----------------------------------------------------------------------------
struct CameraStateBinder {
CameraStateBinder (CameraRenderer *renderer) : m_renderer(renderer) {
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnable(GL_DEPTH_TEST);
f->glEnable(GL_CULL_FACE);
f->glDepthMask(GL_TRUE);
f->glDepthFunc(GL_LESS);
f->glFrontFace(GL_CCW);
f->glCullFace(GL_BACK);
m_renderer->m_program->bind();
}
~CameraStateBinder () {
m_renderer->m_program->release();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glDisable(GL_CULL_FACE);
f->glDisable(GL_DEPTH_TEST);
}
CameraRenderer *m_renderer;
};
// -----------------------------------------------------------------------------
QOpenGLFramebufferObject *CameraRenderer::createFramebufferObject (const QSize &size) {
m_projection.setToIdentity();
m_projection.ortho(
0, size.width(),
0, size.height(),
-1, 1
);
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(4);
return new QOpenGLFramebufferObject(size, format);
}
void CameraRenderer::render () {
init();
m_vao.bind();
CameraStateBinder state(this);
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClearColor(0.f, 0.f, 0.f, 1.f);
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_program->setUniformValue(m_projection_loc, m_projection);
// Draw.
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
m_vao.release();
}
void CameraRenderer::init () {
if (m_inited)
return;
m_inited = true;
initProgram();
initBuffer();
}
void CameraRenderer::initBuffer () {
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
m_vbo.create();
m_vbo.bind();
m_vbo.allocate(&_camera_vertices, sizeof _camera_vertices);
m_vbo.bind();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(ATTRIBUTE_VERTEX);
f->glVertexAttribPointer(ATTRIBUTE_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0);
m_vbo.release();
}
void CameraRenderer::initProgram () {
m_program.reset(new QOpenGLShaderProgram());
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, _vertex_shader);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, _fragment_shader);
m_program->bindAttributeLocation("vertex", ATTRIBUTE_VERTEX);
m_program->link();
m_projection_loc = m_program->uniformLocation("projection");
}
// -----------------------------------------------------------------------------
Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
}
QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
return new CameraRenderer();
}
void Camera::hoverMoveEvent (QHoverEvent *) {}
void Camera::mousePressEvent (QMouseEvent *) {
setFocus(true);
}
void Camera::keyPressEvent (QKeyEvent *) {}
#ifndef CAMERA_H_
#define CAMERA_H_
#include <QOpenGLBuffer>
#include <QOpenGLFramebufferObject>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QQuickFramebufferObject>
// =============================================================================
class CameraRenderer : public QQuickFramebufferObject::Renderer {
friend struct CameraStateBinder;
public:
QOpenGLFramebufferObject *createFramebufferObject (const QSize &size) override;
void render () override;
private:
void init ();
void initBuffer ();
void initProgram ();
bool m_inited = false;
QMatrix4x4 m_projection;
int m_projection_loc;
QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vbo;
QScopedPointer<QOpenGLShaderProgram> m_program;
};
// -----------------------------------------------------------------------------
class Camera : public QQuickFramebufferObject {
Q_OBJECT;
public:
Camera (QQuickItem *parent = Q_NULLPTR);
~Camera () = default;
QQuickFramebufferObject::Renderer *createRenderer () const override;
protected:
void hoverMoveEvent (QHoverEvent *event) override;
void mousePressEvent (QMouseEvent *event) override;
void keyPressEvent (QKeyEvent *event) override;
};
#endif // CAMERA_H_
...@@ -8,7 +8,7 @@ import LinphoneUtils 1.0 ...@@ -8,7 +8,7 @@ import LinphoneUtils 1.0
import App.Styles 1.0 import App.Styles 1.0
// =================================================================== // =============================================================================
Rectangle { Rectangle {
id: call id: call
...@@ -20,7 +20,7 @@ Rectangle { ...@@ -20,7 +20,7 @@ Rectangle {
sipAddress sipAddress
) || sipAddress ) || sipAddress
// ----------------------------------------------------------------- // ---------------------------------------------------------------------------
color: StartingCallStyle.backgroundColor color: StartingCallStyle.backgroundColor
...@@ -32,11 +32,11 @@ Rectangle { ...@@ -32,11 +32,11 @@ Rectangle {
spacing: 0 spacing: 0
// --------------------------------------------------------------- // -------------------------------------------------------------------------
// Call info. // Call info.
// --------------------------------------------------------------- // -------------------------------------------------------------------------
RowLayout { Item {
id: info id: info
Layout.fillWidth: true Layout.fillWidth: true
...@@ -45,15 +45,29 @@ Rectangle { ...@@ -45,15 +45,29 @@ Rectangle {
Layout.preferredHeight: StartingCallStyle.contactDescriptionHeight Layout.preferredHeight: StartingCallStyle.contactDescriptionHeight
Icon { Icon {
iconSize: 40 id: callQuality
anchors.left: parent.left
icon: 'call_quality_' + 2 icon: 'call_quality_' + 2
iconSize: 40
} }
Item { ContactDescription {
Layout.fillWidth: true id: contactDescription
anchors.centerIn: parent
horizontalTextAlignment: Text.AlignHCenter
sipAddress: call.sipAddress
username: LinphoneUtils.getContactUsername(_contact)
height: parent.height
width: parent.width - cameraActions.width - callQuality.width - 150
} }
ActionBar { ActionBar {
id: cameraActions
anchors.right: parent.right
iconSize: 40 iconSize: 40
ActionButton { ActionButton {
...@@ -70,18 +84,9 @@ Rectangle { ...@@ -70,18 +84,9 @@ Rectangle {
} }
} }
ContactDescription { // -------------------------------------------------------------------------
id: contactDescription
anchors.fill: info
username: LinphoneUtils.getContactUsername(_contact)
sipAddress: call.sipAddress
horizontalTextAlignment: Text.AlignHCenter
}
// ---------------------------------------------------------------
// Contact visual. // Contact visual.
// --------------------------------------------------------------- // -------------------------------------------------------------------------
Item { Item {
id: container id: container
...@@ -90,26 +95,41 @@ Rectangle { ...@@ -90,26 +95,41 @@ Rectangle {
Layout.fillHeight: true Layout.fillHeight: true
Layout.margins: StartingCallStyle.containerMargins Layout.margins: StartingCallStyle.containerMargins
Avatar { Component {
id: avatar id: avatar
function _computeAvatarSize () { Avatar {
var height = container.height function _computeAvatarSize () {
var width = container.width var height = container.height
var width = container.width
var size = height < StartingCallStyle.avatar.maxSize && height > 0
? height
: StartingCallStyle.avatar.maxSize
return size < width ? size : width
}
backgroundColor: StartingCallStyle.avatar.backgroundColor
image: _contact.avatar
username: contactDescription.username
var size = height < StartingCallStyle.avatar.maxSize && height > 0 height: _computeAvatarSize()
? height width: height
: StartingCallStyle.avatar.maxSize
return size < width ? size : width
} }
}
anchors.centerIn: parent Component {
backgroundColor: StartingCallStyle.avatar.backgroundColor id: camera
image: _contact.avatar
username: contactDescription.username Camera {
height: container.height
width: container.width
}
}
height: _computeAvatarSize() Loader {
width: height anchors.centerIn: parent
sourceComponent: isVideoCall ? camera : avatar
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment