From 62c9a6ef2669fde6a35b7a613b4d611c83562db7 Mon Sep 17 00:00:00 2001
From: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
Date: Fri, 15 Jun 2018 11:03:09 -0400
Subject: [PATCH] localrecorder (avmodel): initial implementation

Initial implementation of the avmodel, the model for handling video
and audio related parts of the daemon API in the LRC.

Change-Id: I0ec32e4751d023c1ba022aabb00191bf699c47a4
Reviewed-by: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
---
 CMakeLists.txt                       |   2 +
 src/api/avmodel.h                    |  59 +++++++++++++++
 src/api/lrc.h                        |   8 +-
 src/avmodel.cpp                      | 108 +++++++++++++++++++++++++++
 src/lrc.cpp                          |   9 +++
 src/private/videorenderermanager.cpp |   4 -
 src/private/videorenderermanager.h   |   2 +-
 src/qtwrapper/videomanager_wrap.h    |  10 +++
 src/video/previewmanager.h           |   2 +-
 test/mocks/videomanager_mock.h       |  13 +++-
 10 files changed, 209 insertions(+), 8 deletions(-)
 create mode 100644 src/api/avmodel.h
 create mode 100644 src/avmodel.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3c155ea5..8363a8d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -392,6 +392,7 @@ SET( libringclient_LIB_SRCS
   src/dbuserrorhandlerdefault.cpp
 
   #Other
+  src/avmodel.cpp
   src/hookmanager.cpp
   src/namedirectory.cpp
   src/itembase.cpp
@@ -519,6 +520,7 @@ SET(libringclient_api_LIB_HDRS
   src/api/call.h
   src/api/account.h
   src/api/lrc.h
+  src/api/avmodel.h
   src/api/newaccountmodel.h
   src/api/newcallmodel.h
   src/api/newcodecmodel.h
diff --git a/src/api/avmodel.h b/src/api/avmodel.h
new file mode 100644
index 00000000..6e170827
--- /dev/null
+++ b/src/api/avmodel.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ *   Copyright (C) 2018 Savoir-faire Linux                                  *
+ *   Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>             *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library is distributed in the hope that it will be useful,        *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#pragma once
+
+// std
+#include <memory>
+#include <string>
+
+// Qt
+#include <qobject.h>
+
+// LRC
+#include "typedefs.h"
+
+namespace lrc
+{
+
+class AVModelPimpl;
+
+namespace api
+{
+
+class LIB_EXPORT AVModel : public QObject {
+    Q_OBJECT
+public:
+    AVModel();
+    ~AVModel();
+    /**
+     * Stop local record at given path
+     * @param path
+     */
+    void stopLocalRecorder(const std::string& path) const;
+    /**
+     * Start a local recorder and return it path.
+     * @param audioOnly
+     */
+    std::string startLocalRecorder(const bool& audioOnly) const;
+
+private:
+    std::unique_ptr<AVModelPimpl> pimpl_;
+};
+
+} // namespace api
+} // namespace lrc
diff --git a/src/api/lrc.h b/src/api/lrc.h
index 64907049..8847a216 100644
--- a/src/api/lrc.h
+++ b/src/api/lrc.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- *   Copyright (C) 2017-2018 Savoir-faire Linux                                  *
+ *   Copyright (C) 2017-2018 Savoir-faire Linux                             *
  *   Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com>             *
  *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
  *                                                                          *
@@ -35,6 +35,7 @@ namespace api
 class BehaviorController;
 class NewAccountModel;
 class DataTransferModel;
+class AVModel;
 
 class LIB_EXPORT Lrc {
 public:
@@ -55,6 +56,11 @@ public:
      * @return a DataTransferModel&.
      */
     DataTransferModel& getDataTransferModel() const;
+    /**
+     * get a reference on the audio-video controller.
+     * @return a AVModel&.
+     */
+    AVModel& getAVModel() const;
 
     /**
      * Inform the daemon that the connectivity changed
diff --git a/src/avmodel.cpp b/src/avmodel.cpp
new file mode 100644
index 00000000..dcaaa7cf
--- /dev/null
+++ b/src/avmodel.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+ *   Copyright (C) 2018 Savoir-faire Linux                                  *
+ *   Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>             *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library is distributed in the hope that it will be useful,        *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#include "api/avmodel.h"
+
+// Std
+#include <chrono>
+#include <iomanip> // for std::put_time
+#include <fstream>
+#include <string>
+#include <sstream>
+
+// Qt
+#include <QtCore/QStandardPaths>
+#include <QtCore/QDir>
+
+// LRC
+#include "dbus/videomanager.h"
+
+namespace lrc
+{
+
+using namespace api;
+
+class AVModelPimpl: public QObject
+{
+    Q_OBJECT
+public:
+    AVModelPimpl(AVModel& linked);
+    std::string getRecordingPath() const;
+    static const std::string recorderSavesSubdir;
+    AVModel& linked_;
+};
+
+const std::string AVModelPimpl::recorderSavesSubdir = "sent_data";
+
+AVModel::AVModel()
+: QObject()
+, pimpl_(std::make_unique<AVModelPimpl>(*this))
+{
+}
+
+AVModel::~AVModel()
+{
+}
+
+AVModelPimpl::AVModelPimpl(AVModel& linked)
+: linked_(linked)
+{
+    std::srand(std::time(nullptr));
+}
+
+std::string
+AVModelPimpl::getRecordingPath() const
+{
+    const QDir dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + recorderSavesSubdir.c_str();
+    dir.mkpath(".");
+
+    std::chrono::time_point<std::chrono::system_clock> time_now = std::chrono::system_clock::now();
+    std::time_t time_now_t = std::chrono::system_clock::to_time_t(time_now);
+    std::tm now_tm = *std::localtime(&time_now_t);
+
+    std::stringstream ss;
+    ss << dir.path().toStdString();
+    ss << "/";
+    ss << std::put_time(&now_tm, "%Y%m%d-%H%M%S");
+    ss << "-";
+    ss << std::rand();
+
+    QDir file_path(ss.str().c_str());
+
+    return file_path.path().toStdString();
+}
+
+void AVModel::stopLocalRecorder(const std::string& path) const
+{
+   if (path.empty()) {
+      qDebug("stopLocalRecorder: can't stop non existing recording");
+      return;
+   }
+
+   VideoManager::instance().stopLocalRecorder(QString::fromStdString(path));
+}
+
+std::string AVModel::startLocalRecorder(const bool& audioOnly) const
+{
+   const QString path = QString::fromStdString(pimpl_->getRecordingPath());
+   const QString finalPath = VideoManager::instance().startLocalRecorder(audioOnly, path);
+   return finalPath.toStdString();
+}
+} // namespace lrc
+
+#include "api/moc_avmodel.cpp"
+#include "avmodel.moc"
diff --git a/src/lrc.cpp b/src/lrc.cpp
index b8777f4d..07afd3a2 100644
--- a/src/lrc.cpp
+++ b/src/lrc.cpp
@@ -20,6 +20,7 @@
 
 // Models and database
 #include "api/newaccountmodel.h"
+#include "api/avmodel.h"
 #include "api/datatransfermodel.h"
 #include "api/behaviorcontroller.h"
 #include "database.h"
@@ -44,6 +45,7 @@ public:
     std::unique_ptr<Database> database;
     std::unique_ptr<NewAccountModel> accountModel;
     std::unique_ptr<DataTransferModel> dataTransferModel;
+    std::unique_ptr<AVModel> AVModel_;
 };
 
 Lrc::Lrc()
@@ -76,6 +78,12 @@ Lrc::getDataTransferModel() const
     return *lrcPimpl_->dataTransferModel;
 }
 
+AVModel&
+Lrc::getAVModel() const
+{
+    return *lrcPimpl_->AVModel_;
+}
+
 void
 Lrc::connectivityChanged() const
 {
@@ -109,6 +117,7 @@ LrcPimpl::LrcPimpl(Lrc& linked)
 , database(std::make_unique<Database>())
 , accountModel(std::make_unique<NewAccountModel>(linked, *database, *callbackHandler, *behaviorController))
 , dataTransferModel {std::make_unique<DataTransferModel>()}
+, AVModel_ {std::make_unique<AVModel>()}
 {
 }
 
diff --git a/src/private/videorenderermanager.cpp b/src/private/videorenderermanager.cpp
index f5d65214..ff14d532 100644
--- a/src/private/videorenderermanager.cpp
+++ b/src/private/videorenderermanager.cpp
@@ -161,24 +161,20 @@ Video::Renderer* VideoRendererManager::previewRenderer()
 ///Stop video preview
 void VideoRendererManager::stopPreview()
 {
-
    VideoManager::instance().stopCamera();
 
    d_ptr->m_PreviewState = false;
-
 }
 
 ///Start video preview
 void VideoRendererManager::startPreview()
 {
-
    if (d_ptr->m_PreviewState)
       return;
 
    VideoManager::instance().startCamera();
 
    d_ptr->m_PreviewState = true;
-
 }
 
 ///Is the video model fetching preview from a camera
diff --git a/src/private/videorenderermanager.h b/src/private/videorenderermanager.h
index 071e48ce..8a418c22 100644
--- a/src/private/videorenderermanager.h
+++ b/src/private/videorenderermanager.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- *   Copyright (C) 2012-2018 Savoir-faire Linux                            *
+ *   Copyright (C) 2012-2018 Savoir-faire Linux                               *
  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>   *
  *                                                                            *
  *   This library is free software; you can redistribute it and/or            *
diff --git a/src/qtwrapper/videomanager_wrap.h b/src/qtwrapper/videomanager_wrap.h
index 810335a2..211e9da6 100644
--- a/src/qtwrapper/videomanager_wrap.h
+++ b/src/qtwrapper/videomanager_wrap.h
@@ -220,6 +220,16 @@ public Q_SLOTS: // METHODS
         DRing::setDecodingAccelerated(state);
     }
 
+    void stopLocalRecorder(const QString& path)
+    {
+        DRing::stopLocalRecorder(path.toStdString());
+    }
+
+    QString startLocalRecorder(bool audioOnly, const QString& path)
+    {
+        return QString::fromStdString(DRing::startLocalRecorder(audioOnly, path.toStdString()));
+    }
+
 Q_SIGNALS: // SIGNALS
     void deviceEvent();
     void startedDecoding(const QString &id, const QString &shmPath, int width, int height, bool isMixer);
diff --git a/src/video/previewmanager.h b/src/video/previewmanager.h
index 097e2088..07d954ef 100644
--- a/src/video/previewmanager.h
+++ b/src/video/previewmanager.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- *   Copyright (C) 2012-2018 Savoir-faire Linux                            *
+ *   Copyright (C) 2012-2018 Savoir-faire Linux                               *
  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>   *
  *                                                                            *
  *   This library is free software; you can redistribute it and/or            *
diff --git a/test/mocks/videomanager_mock.h b/test/mocks/videomanager_mock.h
index 4ba0afa9..530db103 100644
--- a/test/mocks/videomanager_mock.h
+++ b/test/mocks/videomanager_mock.h
@@ -175,10 +175,21 @@ public Q_SLOTS: // METHODS
 
     void setDecodingAccelerated(bool state)
     {
-
         Q_UNUSED(state)
     }
 
+    void stopLocalRecorder(const QString& path)
+    {
+        Q_UNUSED(path)
+    }
+
+    QString startLocalRecorder(bool audioOnly, const QString& path)
+    {
+        Q_UNUSED(audioOnly)
+        Q_UNUSED(path)
+        return "/tmp/foobar";
+    }
+
 Q_SIGNALS: // SIGNALS
     void deviceEvent();
     void startedDecoding(const QString &id, const QString &shmPath, int width, int height, bool isMixer);
-- 
GitLab