[Merge] lp:~jhodapp/qtubuntu-camera/audio-recording into lp:qtubuntu-camera

Jim Hodapp jim.hodapp at canonical.com
Thu Jul 31 16:50:52 UTC 2014



Diff comments:

> === modified file 'debian/control'
> --- debian/control	2014-05-29 08:35:50 +0000
> +++ debian/control	2014-07-31 13:31:20 +0000
> @@ -13,6 +13,7 @@
>                 pkg-config,
>                 qt5-default,
>                 qtmultimedia5-dev,
> +               libpulse-dev
>  Standards-Version: 3.9.4
>  Homepage: https://launchpad.net/qtubuntu-camera
>  # If you aren't a member of ~phablet-team but need to upload packaging changes,
> 
> === modified file 'src/aalcameraservice.cpp'
> --- src/aalcameraservice.cpp	2014-07-21 15:21:42 +0000
> +++ src/aalcameraservice.cpp	2014-07-31 13:31:20 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2013 Canonical, Ltd.
> + * Copyright (C) 2013-2014 Canonical, Ltd.
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU Lesser General Public License as published by
> @@ -27,8 +27,8 @@
>  #include "aalvideoencodersettingscontrol.h"
>  #include "aalvideorenderercontrol.h"
>  #include "aalviewfindersettingscontrol.h"
> +#include "storagemanager.h"
>  #include "aalcameraexposurecontrol.h"
> -#include <storagemanager.h>
>  
>  #include <hybris/camera/camera_compatibility_layer.h>
>  
> 
> === modified file 'src/aalcameraservice.h'
> --- src/aalcameraservice.h	2014-07-21 15:21:42 +0000
> +++ src/aalcameraservice.h	2014-07-31 13:31:20 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2013 Canonical, Ltd.
> + * Copyright (C) 2013-2014 Canonical, Ltd.
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU Lesser General Public License as published by
> 
> === modified file 'src/aalmediarecordercontrol.cpp'
> --- src/aalmediarecordercontrol.cpp	2014-06-19 20:54:56 +0000
> +++ src/aalmediarecordercontrol.cpp	2014-07-31 13:31:20 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2013 Canonical, Ltd.
> + * Copyright (C) 2013-2014 Canonical, Ltd.
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU Lesser General Public License as published by
> @@ -19,10 +19,12 @@
>  #include "aalmetadatawritercontrol.h"
>  #include "aalvideoencodersettingscontrol.h"
>  #include "aalviewfindersettingscontrol.h"
> +#include "audiocapture.h"
>  #include "storagemanager.h"
>  
>  #include <QDebug>
>  #include <QFile>
> +#include <QThread>
>  #include <QTimer>
>  
>  #include <hybris/camera/camera_compatibility_layer.h>
> @@ -37,7 +39,7 @@
>  const int AalMediaRecorderControl::RECORDER_NOT_AVAILABLE_ERROR;
>  const int AalMediaRecorderControl::RECORDER_INITIALIZATION_ERROR;
>  
> -const int AalMediaRecorderControl::DURATION_UPDATE_INTERVALL;
> +const int AalMediaRecorderControl::DURATION_UPDATE_INTERVAL;
>  
>  const QLatin1String AalMediaRecorderControl::PARAM_AUDIO_BITRATE = QLatin1String("audio-param-encoding-bitrate");
>  const QLatin1String AalMediaRecorderControl::PARAM_AUDIO_CHANNELS = QLatin1String("audio-param-number-of-channels");
> @@ -55,10 +57,12 @@
>     : QMediaRecorderControl(parent),
>      m_service(service),
>      m_mediaRecorder(0),
> +    m_audioCapture(0),
>      m_duration(0),
>      m_currentState(QMediaRecorder::StoppedState),
>      m_currentStatus(QMediaRecorder::UnloadedStatus),
> -    m_recordingTimer(0)
> +    m_recordingTimer(0),
> +    m_workerThread(new QThread)
>  {
>  }
>  
> @@ -68,6 +72,8 @@
>  AalMediaRecorderControl::~AalMediaRecorderControl()
>  {
>      delete m_recordingTimer;
> +    delete m_workerThread;
> +    delete m_audioCapture;
>      deleteRecorder();

Fixed

>  }
>  
> @@ -143,6 +149,17 @@
>  }
>  
>  /*!
> + * \brief Starts the main microphone reader/writer loop in AudioCapture (run)
> + */
> +void AalMediaRecorderControl::onStartThread()
> +{
> +    qDebug() << "Starting microphone reader/writer worker thread";
> +    // Start the microphone read/write worker thread
> +    m_workerThread->start();
> +    Q_EMIT startWorkerThread();
> +}
> +
> +/*!
>   * \brief AalMediaRecorderControl::init makes sure the mediarecorder is
>   * initialized
>   */
> @@ -151,6 +168,34 @@
>      if (m_mediaRecorder == 0) {
>          m_mediaRecorder = android_media_new_recorder();
>  
> +        m_audioCapture = new AudioCapture(m_mediaRecorder);
> +
> +        if (m_audioCapture == 0) {

Not going to make this change just so I'm consistent with the rest of the existing code. I always value consistency when adding new code. Revising this code should be a separate MR. I do agree nullptr is preferred over a check for 0 or NULL.

> +            qWarning() << "Unable to create new audio capture, audio recording won't function";
> +            Q_EMIT error(RECORDER_INITIALIZATION_ERROR, "Unable to create new audio capture, audio recording won't function");
> +        }
> +        else
> +        {
> +            bool ret = false;
> +
> +            // Make sure that m_audioCapture is executed within the m_workerThread affinity
> +            m_audioCapture->moveToThread(m_workerThread);
> +
> +            // Finished signal is for when the workerThread is completed. Important to connect this so that
> +            // resources are cleaned up in the proper order and not leaked
> +            ret = connect(m_workerThread, SIGNAL(finished()), m_audioCapture, SLOT(deleteLater()));
> +            if (!ret)
> +                qWarning() << "Failed to connect deleteLater() to the m_workerThread finished signal";
> +            // startWorkerThread signal comes from an Android layer callback that resides down in
> +            // the AudioRecordHybris class
> +            ret = connect(this, SIGNAL(startWorkerThread()), m_audioCapture, SLOT(run()));
> +            if (!ret)
> +                qWarning() << "Failed to connect run() to the local startWorkerThread signal";
> +
> +            // Call onStartThreadCb when the reader side of the named pipe has been setup
> +            m_audioCapture->init(&AalMediaRecorderControl::onStartThreadCb, this);
> +        }
> +
>          if (m_mediaRecorder == 0) {
>              qWarning() << "Unable to create new media recorder";
>              Q_EMIT error(RECORDER_INITIALIZATION_ERROR, "Unable to create new media recorder");
> @@ -163,7 +208,7 @@
>  
>      if (m_recordingTimer == 0) {
>          m_recordingTimer = new QTimer(this);
> -        m_recordingTimer->setInterval(DURATION_UPDATE_INTERVALL);
> +        m_recordingTimer->setInterval(DURATION_UPDATE_INTERVAL);
>          m_recordingTimer->setSingleShot(false);
>          QObject::connect(m_recordingTimer, SIGNAL(timeout()),
>                           this, SLOT(updateDuration()));
> @@ -196,6 +241,16 @@
>                                "handleError", Qt::QueuedConnection);
>  }
>  
> +MediaRecorderWrapper* AalMediaRecorderControl::mediaRecorder() const
> +{
> +    return m_mediaRecorder;
> +}

This should be ok right now. I agree with your idea, but like the above comment of not using nullptr, this would have to be a separate MR to fix this across all of qtubuntu-camera.

> +
> +AudioCapture *AalMediaRecorderControl::audioCapture()
> +{
> +    return m_audioCapture;
> +}
> +
>  /*!
>   * \reimp
>   */
> @@ -243,7 +298,7 @@
>  
>  void AalMediaRecorderControl::updateDuration()
>  {
> -    m_duration += DURATION_UPDATE_INTERVALL;
> +    m_duration += DURATION_UPDATE_INTERVAL;
>      Q_EMIT durationChanged(m_duration);
>  }
>  
> @@ -273,7 +328,7 @@
>   * FIXME add support for recording audio only
>   */
>  int AalMediaRecorderControl::startRecording()
> -{    
> +{
>      if (m_service->androidControl() == 0) {
>          Q_EMIT error(RECORDER_INITIALIZATION_ERROR, "No camera connection");
>          return RECORDER_INITIALIZATION_ERROR;
> @@ -406,7 +461,13 @@
>   */
>  void AalMediaRecorderControl::stopRecording()
>  {
> +    qDebug() << __PRETTY_FUNCTION__;
>      if (m_mediaRecorder == 0) {
> +        qWarning() << "Can't stop recording properly, m_mediaRecorder is NULL";
> +        return;
> +    }
> +    if (m_audioCapture == 0) {
> +        qWarning() << "Can't stop recording properly, m_audioCapture is NULL";
>          return;
>      }
>  
> @@ -419,6 +480,12 @@
>          return;
>      }
>  
> +    // Stop microphone reader/writer loop
> +    // NOTE: This must come after the android_recorder_stop call, otherwise the
> +    // RecordThread instance will block the MPEG4Writer pthread_join when trying to
> +    // cleanly stop recording.
> +    m_audioCapture->stopCapture();
> +
>      android_recorder_reset(m_mediaRecorder);
>  
>      m_currentState = QMediaRecorder::StoppedState;
> @@ -438,3 +505,10 @@
>      QString param =  parameter + QChar('=') + QString::number(value);
>      android_recorder_setParameters(m_mediaRecorder, param.toLocal8Bit().data());
>  }
> +
> +void AalMediaRecorderControl::onStartThreadCb(void *context)
> +{
> +    AalMediaRecorderControl *thiz = static_cast<AalMediaRecorderControl*>(context);
> +    if (thiz != NULL)
> +        thiz->onStartThread();
> +}
> 
> === modified file 'src/aalmediarecordercontrol.h'
> --- src/aalmediarecordercontrol.h	2013-06-22 06:54:48 +0000
> +++ src/aalmediarecordercontrol.h	2014-07-31 13:31:20 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2013 Canonical, Ltd.
> + * Copyright (C) 2013-2014 Canonical, Ltd.
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU Lesser General Public License as published by
> @@ -28,6 +28,8 @@
>  struct CameraControl;
>  struct CameraControlListener;
>  struct MediaRecorderWrapper;
> +class AudioCapture;
> +class QThread;
>  class QTimer;
>  
>  class AalMediaRecorderControl : public QMediaRecorderControl
> @@ -49,11 +51,17 @@
>      static void errorCB(void* context);
>  
>      void init(CameraControl *control, CameraControlListener *listener);
> +    MediaRecorderWrapper* mediaRecorder() const;
> +    AudioCapture *audioCapture();

Good catch, should have been - fixed.

>  
>  public Q_SLOTS:
>      virtual void setMuted(bool muted);
>      virtual void setState(QMediaRecorder::State state);
>      virtual void setVolume(qreal gain);
> +    void onStartThread();
> +
> +signals:
> +    void startWorkerThread();
>  
>  private Q_SLOTS:
>      virtual void updateDuration();
> @@ -66,20 +74,23 @@
>      int startRecording();
>      void stopRecording();
>      void setParameter(const QString &parameter, int value);
> +    static void onStartThreadCb(void *context);
>  
>      AalCameraService *m_service;
>      MediaRecorderWrapper *m_mediaRecorder;
> +    AudioCapture *m_audioCapture;
>      QUrl m_outputLocation;
>      qint64 m_duration;
>      QMediaRecorder::State m_currentState;
>      QMediaRecorder::Status m_currentStatus;
>      QTimer *m_recordingTimer;
> +    QThread *m_workerThread;
>  
>      static const int RECORDER_GENERAL_ERROR = -1;
>      static const int RECORDER_NOT_AVAILABLE_ERROR = -2;
>      static const int RECORDER_INITIALIZATION_ERROR = -3;
>  
> -    static const int DURATION_UPDATE_INTERVALL = 1000; // update every second
> +    static const int DURATION_UPDATE_INTERVAL = 1000; // update every second

This is good in the class for now. A future improvement could be to do your suggestion.

>  
>      static const QLatin1String PARAM_AUDIO_BITRATE;
>      static const QLatin1String PARAM_AUDIO_CHANNELS;
> 
> === added file 'src/audiocapture.cpp'
> --- src/audiocapture.cpp	1970-01-01 00:00:00 +0000
> +++ src/audiocapture.cpp	2014-07-31 13:31:20 +0000
> @@ -0,0 +1,217 @@
> +/*
> + * Copyright (C) 2014 Canonical, Ltd.
> + *
> + * This program 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; version 3.
> + *
> + * This program 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 Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Jim Hodapp <jim.hodapp at canonical.com>
> + */
> +
> +#include "audiocapture.h"
> +
> +#include <pulse/simple.h>
> +#include <pulse/error.h>
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +
> +#include <QDebug>
> +#include <QThread>
> +
> +AudioCapture::AudioCapture(MediaRecorderWrapper *mediaRecorder)
> +    : m_paStream(NULL),
> +      m_audioPipe(-1),
> +      m_flagExit(false),
> +      m_mediaRecorder(mediaRecorder)
> +{
> +}
> +
> +AudioCapture::~AudioCapture()
> +{
> +    if (m_audioPipe >= 0)
> +        close(m_audioPipe);
> +    if (m_paStream != NULL)
> +        pa_simple_free(m_paStream);
> +}
> +
> +/*!
> + * \brief Initializes AudioCapture so that it's ready to read microphone data from Pulseaudio
> + */
> +bool AudioCapture::init(StartWorkerThreadCb cb, void *context)
> +{
> +    // The MediaRecorderLayer will call method (cb) when it's ready to encode a new audio buffer
> +    android_recorder_set_audio_read_cb(m_mediaRecorder, cb, context);
> +
> +    return true;

Yep, there's no failure possible at the moment, but added the bool just in case for the future.

> +}
> +
> +/*!
> + * \brief Stops the microphone data capture thread loop
> + */
> +void AudioCapture::stopCapture()
> +{
> +    qDebug() << __PRETTY_FUNCTION__;
> +    m_flagExit = true;
> +}
> +
> +/*!
> + * \brief The main microphone reader/writer loop. Reads from Pulseaudio, writes to named pipe
> + */
> +void AudioCapture::run()
> +{
> +    qDebug() << __PRETTY_FUNCTION__;
> +
> +    int bytesWritten = 0, bytesRead = 0;
> +    const size_t readSize = sizeof(m_audioBuf);
> +
> +    if (!setupMicrophoneStream())
> +    {
> +        qWarning() << "Failed to setup PulseAudio microphone recording stream";
> +        return;
> +    }
> +
> +    if (!setupPipe())
> +    {
> +        qWarning() << "Failed to open /dev/socket/micshm, cannot write data to pipe";
> +        return;
> +    }
> +
> +    do {
> +        bytesRead = readMicrophone();
> +        if (bytesRead > 0)
> +        {
> +            bytesWritten = writeDataToPipe();
> +        }
> +    } while (bytesRead == readSize
> +                && bytesWritten == readSize
> +                && !m_flagExit);
> +
> +    Q_EMIT finished();
> +}
> +
> +/*!
> + * \brief Reads microphone data from Pulseaudio
> + */
> +int AudioCapture::readMicrophone()
> +{
> +    int ret = 0, error = 0;
> +    const size_t readSize = sizeof(m_audioBuf);
> +    ret = pa_simple_read(m_paStream, m_audioBuf, readSize, &error);
> +    if (ret < 0)
> +    {
> +        qWarning() << "Failed to read audio from the microphone: " << pa_strerror(error);
> +        goto exit;

Good suggestion, fixed.

> +    }
> +    else
> +        ret = readSize;
> +
> +exit:
> +    return ret;
> +}
> +
> +/*!
> + * \brief Signals AalMediaRecorderControl to start the main thread loop.
> + * \detail This is necessary due to thread contexts. Starting of the main thread loop
> + * for AudioCapture must be done in the main thread context and not in the AudioCapture
> + * thread context, otherwise the loop start signal will never be seen.
> + */
> +void AudioCapture::startThreadLoop()
> +{
> +    Q_EMIT startThread();
> +    qDebug() << "Emitted startThread(), should start reading from mic";
> +}
> +
> +/*!
> + * \brief Sets up the Pulseaudio microphone input channel
> + */
> +bool AudioCapture::setupMicrophoneStream()
> +{
> +    // FIXME: Get these parameters more dynamically from the control
> +    static const pa_sample_spec ss = {
> +        .format = PA_SAMPLE_S16LE,
> +        .rate = 48000,
> +        .channels = 1
> +    };
> +    int error = 0;
> +
> +    m_paStream = pa_simple_new(NULL, "qtubuntu-camera", PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error);
> +    if (m_paStream == NULL)
> +    {
> +        qWarning() << "Failed to open a PulseAudio channel to read the microphone: " << pa_strerror(error);
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
> +/*!
> + * \brief Opens the named pipe /dev/socket/micshm for writing mic data to the Android (reader) side
> + */
> +bool AudioCapture::setupPipe()
> +{
> +    if (m_audioPipe >= 0)
> +    {
> +        qWarning() << "/dev/socket/micshm already opened, not opening twice";
> +        return true;
> +    }
> +
> +    // Open the named pipe for writing only
> +    m_audioPipe = open("/dev/socket/micshm", O_WRONLY);
> +    if (m_audioPipe < 0)
> +    {
> +        qWarning() << "Failed to open audio data pipe /dev/socket/micshm: " << strerror(errno);
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
> +/*!
> + * \brief Writes mic data to the named pipe /dev/socket/micshm
> + */
> +int AudioCapture::writeDataToPipe()
> +{
> +    // Don't open the named pipe twice
> +    if (m_audioPipe < 0)

Good suggestion, fixed.

> +    {
> +        if (!setupPipe())
> +        {
> +            qWarning() << "Failed to open /dev/socket/micshm, cannot write data to pipe";
> +            return 0;
> +        }
> +    }
> +
> +    int num = 0;
> +    const size_t writeSize = sizeof(m_audioBuf);
> +    num = loopWrite(m_audioPipe, m_audioBuf, writeSize);
> +    if (num != writeSize)
> +        qWarning() << "Failed to write " << num << " bytes to /dev/socket/micshm: " << strerror(errno) << " (" << errno << ")";
> +
> +    return num;
> +}
> +
> +ssize_t AudioCapture::loopWrite(int fd, const void *data, size_t size)
> +{
> +    ssize_t ret = 0;
> +    while (size > 0)
> +    {
> +        ssize_t r;
> +        if ((r = write(fd, data, size)) < 0)
> +            return r;
> +        if (r == 0)
> +            break;
> +        ret += r;
> +        data = (const int16_t*) data + r;
> +        size -= (size_t) r;
> +    }
> +    return ret;
> +}
> 
> === added file 'src/audiocapture.h'
> --- src/audiocapture.h	1970-01-01 00:00:00 +0000
> +++ src/audiocapture.h	2014-07-31 13:31:20 +0000
> @@ -0,0 +1,71 @@
> +/*
> + * Copyright (C) 2014 Canonical, Ltd.
> + *
> + * This program 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; version 3.
> + *
> + * This program 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 Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Jim Hodapp <jim.hodapp at canonical.com>
> + */
> +
> +#ifndef AUDIOCAPTURE_H
> +#define AUDIOCAPTURE_H
> +
> +#include <hybris/media/media_recorder_layer.h>
> +
> +#include <stdint.h>
> +
> +#include <QObject>
> +
> +class AalMediaRecorderControl;
> +struct MediaRecorderWrapper;
> +
> +struct pa_simple;
> +
> +class AudioCapture : public QObject
> +{
> +    Q_OBJECT
> +
> +    typedef void (*StartWorkerThreadCb)(void *context);
> +public:
> +    explicit AudioCapture(MediaRecorderWrapper *mediaRecorder);
> +    ~AudioCapture();
> +
> +    bool init(StartWorkerThreadCb cb, void *context);
> +    /* Terminates the Pulseaudio reader/writer QThread */
> +    void stopCapture();
> +
> +signals:
> +    void startThread();
> +    void finished();
> +
> +public Q_SLOTS:
> +    void run();
> +
> +private Q_SLOTS:
> +    void startThreadLoop();
> +
> +private:
> +    int readMicrophone();
> +    bool setupMicrophoneStream();
> +    bool setupPipe();
> +    ssize_t loopWrite(int fd, const void *data, size_t len);
> +    int writeDataToPipe();
> +
> +    pa_simple *m_paStream;
> +    int16_t m_audioBuf[MIC_READ_BUF_SIZE];
> +
> +    int m_audioPipe;
> +    bool m_flagExit;
> +    MediaRecorderWrapper *m_mediaRecorder;
> +};
> +
> +#endif // AUDIOCAPTURE_H
> 
> === modified file 'src/src.pro'
> --- src/src.pro	2014-07-08 15:12:58 +0000
> +++ src/src.pro	2014-07-31 13:31:20 +0000
> @@ -2,7 +2,7 @@
>  TARGET = aalcamera
>  TEMPLATE = lib
>  CONFIG += plugin
> -QT += multimedia opengl
> +QT += concurrent multimedia opengl
>  
>  PLUGIN_TYPE = mediaservice
>  
> @@ -14,7 +14,9 @@
>      -lcamera \
>      -lmedia \
>      -lubuntu_application_api \
> -    -lqtubuntu-media-signals
> +    -lqtubuntu-media-signals \
> +    -lpulse \
> +    -lpulse-simple
>  
>  OTHER_FILES += aalcamera.json
>  
> @@ -33,6 +35,7 @@
>      aalvideoencodersettingscontrol.h \
>      aalvideorenderercontrol.h \
>      aalviewfindersettingscontrol.h \
> +    audiocapture.h \
>      aalcameraexposurecontrol.h \
>      storagemanager.h
>  
> @@ -51,5 +54,6 @@
>      aalvideoencodersettingscontrol.cpp \
>      aalvideorenderercontrol.cpp \
>      aalviewfindersettingscontrol.cpp \
> +    audiocapture.cpp \
>      aalcameraexposurecontrol.cpp \
>      storagemanager.cpp
> 
> === modified file 'unittests/aalmediarecordercontrol/aalmediarecordercontrol.pro'
> --- unittests/aalmediarecordercontrol/aalmediarecordercontrol.pro	2014-01-16 14:20:08 +0000
> +++ unittests/aalmediarecordercontrol/aalmediarecordercontrol.pro	2014-07-31 13:31:20 +0000
> @@ -12,14 +12,16 @@
>      ../../src/aalcameraservice.h \
>      ../../src/aalvideoencodersettingscontrol.h \
>      ../../src/aalmetadatawritercontrol.h \
> +    ../../src/audiocapture.h \

Couldn't get this one to work, ${CMAKE_SOURCE_DIR} always expanded to an empty string.

>      ../../src/storagemanager.h
>  
>  SOURCES += tst_aalmediarecordercontrol.cpp \
> +    ../stubs/audiocapture_stub.cpp \
>      ../../src/aalmediarecordercontrol.cpp \
>      ../stubs/aalcameraservice_stub.cpp \
>      ../stubs/aalvideoencodersettingscontrol_stub.cpp \
>      ../stubs/aalmetadatawritercontrol_stub.cpp \
> -    ../stubs/storagemanager_stub.cpp 
> +    ../stubs/storagemanager_stub.cpp
>  
>  check.depends = $${TARGET}
>  check.commands = ./$${TARGET}
> 
> === added file 'unittests/stubs/audiocapture_stub.cpp'
> --- unittests/stubs/audiocapture_stub.cpp	1970-01-01 00:00:00 +0000
> +++ unittests/stubs/audiocapture_stub.cpp	2014-07-31 13:31:20 +0000
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright (C) 2014 Canonical, Ltd.
> + *
> + * This program 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; version 3.
> + *
> + * This program 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 Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "audiocapture.h"
> +
> +#include <QThread>
> +
> +#include <hybris/media/media_recorder_layer.h>
> +
> +AudioCapture::AudioCapture(MediaRecorderWrapper *mediaRecorder)
> +{
> +    Q_UNUSED(mediaRecorder);
> +}
> +
> +AudioCapture::~AudioCapture()
> +{
> +}
> +
> +bool AudioCapture::init(StartWorkerThreadCb cb, void *context)
> +{
> +    Q_UNUSED(cb);
> +    Q_UNUSED(context);
> +    return true;
> +}
> +
> +void AudioCapture::stopCapture()
> +{
> +}
> +
> +void AudioCapture::run()
> +{
> +}
> +
> +void AudioCapture::startThreadLoop()
> +{
> +}
> +
> +int AudioCapture::readMicrophone()
> +{
> +    return 0;
> +}
> 


-- 
https://code.launchpad.net/~jhodapp/qtubuntu-camera/audio-recording/+merge/228935
Your team Ubuntu Phablet Team is requested to review the proposed merge of lp:~jhodapp/qtubuntu-camera/audio-recording into lp:qtubuntu-camera.



More information about the Ubuntu-reviews mailing list