Commit 8f8eb254 authored by Guillaume Roguez's avatar Guillaume Roguez

media: make recordable non audio dedicated

To add video recording this patch changes recordable and
audio related class non-dependent.
This moves AudioRecorder handling into AudioRecord class.

Fixes also Audio recording start/stop that not working as waited:
- first start was just creating the file
- recording was started at second "toggle", confusing user.


Change-Id: I07f69b76ad711d7fc4d64e57e78b5704d60b4861
Tuleap: #337
parent 4c71686e
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "audio/ringbufferpool.h" #include "audio/ringbufferpool.h"
#include "dring/call_const.h" #include "dring/call_const.h"
#include "client/ring_signal.h" #include "client/ring_signal.h"
#include "audio/audiorecorder.h" #include "audio/audiorecord.h"
#include "sip/sip_utils.h" #include "sip/sip_utils.h"
#include "ip_utils.h" #include "ip_utils.h"
#include "array_size.h" #include "array_size.h"
...@@ -260,14 +260,12 @@ bool ...@@ -260,14 +260,12 @@ bool
Call::toggleRecording() Call::toggleRecording()
{ {
const bool startRecording = Recordable::toggleRecording(); const bool startRecording = Recordable::toggleRecording();
std::string process_id = Recordable::recAudio_->getRecorderID();
RingBufferPool &rbPool = Manager::instance().getRingBufferPool(); RingBufferPool &rbPool = Manager::instance().getRingBufferPool();
std::string process_id = Recordable::recorder_->getRecorderID();
if (startRecording) { if (startRecording) {
rbPool.bindHalfDuplexOut(process_id, id_); rbPool.bindHalfDuplexOut(process_id, id_);
rbPool.bindHalfDuplexOut(process_id, RingBufferPool::DEFAULT_ID); rbPool.bindHalfDuplexOut(process_id, RingBufferPool::DEFAULT_ID);
Recordable::recorder_->start();
} else { } else {
rbPool.unBindHalfDuplexOut(process_id, id_); rbPool.unBindHalfDuplexOut(process_id, id_);
rbPool.unBindHalfDuplexOut(process_id, RingBufferPool::DEFAULT_ID); rbPool.unBindHalfDuplexOut(process_id, RingBufferPool::DEFAULT_ID);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "manager.h" #include "manager.h"
#include "audio/audiolayer.h" #include "audio/audiolayer.h"
#include "audio/ringbufferpool.h" #include "audio/ringbufferpool.h"
#include "audio/audiorecorder.h" #include "audio/audiorecord.h"
#ifdef RING_VIDEO #ifdef RING_VIDEO
#include "sip/sipcall.h" #include "sip/sipcall.h"
...@@ -148,18 +148,15 @@ Conference::getDisplayNames() const ...@@ -148,18 +148,15 @@ Conference::getDisplayNames() const
bool Conference::toggleRecording() bool Conference::toggleRecording()
{ {
const bool startRecording = Recordable::toggleRecording(); const bool startRecording = Recordable::toggleRecording();
std::string process_id(Recordable::recAudio_->getRecorderID());
auto& rbPool = Manager::instance().getRingBufferPool(); auto& rbPool = Manager::instance().getRingBufferPool();
std::string process_id(Recordable::recorder_->getRecorderID());
// start recording // start recording
if (startRecording) { if (startRecording) {
for (const auto &item : participants_) for (const auto &item : participants_)
rbPool.bindHalfDuplexOut(process_id, item); rbPool.bindHalfDuplexOut(process_id, item);
rbPool.bindHalfDuplexOut(process_id, RingBufferPool::DEFAULT_ID); rbPool.bindHalfDuplexOut(process_id, RingBufferPool::DEFAULT_ID);
Recordable::recorder_->start();
} else { } else {
for (const auto &item : participants_) for (const auto &item : participants_)
rbPool.unBindHalfDuplexOut(process_id, item); rbPool.unBindHalfDuplexOut(process_id, item);
......
...@@ -1125,7 +1125,7 @@ Manager::joinParticipant(const std::string& callId1, ...@@ -1125,7 +1125,7 @@ Manager::joinParticipant(const std::string& callId1,
conf->setState(Conference::ACTIVE_ATTACHED); conf->setState(Conference::ACTIVE_ATTACHED);
// set recording sampling rate // set recording sampling rate
conf->setRecordingFormat(ringbufferpool_->getInternalAudioFormat()); conf->setRecordingAudioFormat(ringbufferpool_->getInternalAudioFormat());
return true; return true;
} }
...@@ -1166,7 +1166,7 @@ Manager::createConfFromParticipantList(const std::vector< std::string > &partici ...@@ -1166,7 +1166,7 @@ Manager::createConfFromParticipantList(const std::vector< std::string > &partici
if (successCounter >= 2) { if (successCounter >= 2) {
conferenceMap_[conf->getConfID()] = conf; conferenceMap_[conf->getConfID()] = conf;
emitSignal<DRing::CallSignal::ConferenceCreated>(conf->getConfID()); emitSignal<DRing::CallSignal::ConferenceCreated>(conf->getConfID());
conf->setRecordingFormat(ringbufferpool_->getInternalAudioFormat()); conf->setRecordingAudioFormat(ringbufferpool_->getInternalAudioFormat());
} }
} }
...@@ -2110,7 +2110,7 @@ Manager::toggleRecordingCall(const std::string& id) ...@@ -2110,7 +2110,7 @@ Manager::toggleRecordingCall(const std::string& id)
} }
const bool result = rec->toggleRecording(); const bool result = rec->toggleRecording();
emitSignal<DRing::CallSignal::RecordPlaybackFilepath>(id, rec->getFilename()); emitSignal<DRing::CallSignal::RecordPlaybackFilepath>(id, rec->getAudioFilename());
emitSignal<DRing::CallSignal::RecordingStateChanged>(id, result); emitSignal<DRing::CallSignal::RecordingStateChanged>(id, result);
return result; return result;
} }
......
/* /*
* Copyright (C) 2004-2015 Savoir-faire Linux Inc. * Copyright (C) 2004-2016 Savoir-faire Linux Inc.
* *
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
#include "audiorecord.h" #include "audiorecord.h"
#include "logger.h" #include "logger.h"
#include "fileutils.h" #include "fileutils.h"
#include "manager.h"
#include <sndfile.hh> #include <sndfile.hh>
...@@ -80,10 +82,16 @@ AudioRecord::AudioRecord() ...@@ -80,10 +82,16 @@ AudioRecord::AudioRecord()
: sndFormat_(AudioFormat::MONO()) : sndFormat_(AudioFormat::MONO())
, filename_(createFilename()) , filename_(createFilename())
, savePath_() , savePath_()
, recorder_(this, Manager::instance().getRingBufferPool())
{ {
RING_DBG("Generate filename for this call %s ", filename_.c_str()); RING_DBG("Generate filename for this call %s ", filename_.c_str());
} }
AudioRecord::~AudioRecord()
{
closeFile();
}
void AudioRecord::setSndFormat(AudioFormat format) void AudioRecord::setSndFormat(AudioFormat format)
{ {
sndFormat_ = format; sndFormat_ = format;
...@@ -141,7 +149,6 @@ AudioRecord::openFile() ...@@ -141,7 +149,6 @@ AudioRecord::openFile()
{ {
fileHandle_.reset(); // do it before calling fileExists() fileHandle_.reset(); // do it before calling fileExists()
bool result = false;
const bool doAppend = fileExists(); const bool doAppend = fileExists();
const int access = doAppend ? SFM_RDWR : SFM_WRITE; const int access = doAppend ? SFM_RDWR : SFM_WRITE;
...@@ -162,7 +169,7 @@ AudioRecord::openFile() ...@@ -162,7 +169,7 @@ AudioRecord::openFile()
if (doAppend and fileHandle_->seek(0, SEEK_END) < 0) if (doAppend and fileHandle_->seek(0, SEEK_END) < 0)
RING_WARN("Couldn't seek to the end of the file "); RING_WARN("Couldn't seek to the end of the file ");
return result; return true;
} }
void void
...@@ -193,8 +200,10 @@ AudioRecord::toggleRecording() ...@@ -193,8 +200,10 @@ AudioRecord::toggleRecording()
{ {
if (isOpenFile()) if (isOpenFile())
recordingEnabled_ = !recordingEnabled_; recordingEnabled_ = !recordingEnabled_;
else if (openFile()) else if (openFile()) {
recordingEnabled_ = true; recordingEnabled_ = true;
recorder_.start();
}
return recordingEnabled_; return recordingEnabled_;
} }
...@@ -202,7 +211,7 @@ AudioRecord::toggleRecording() ...@@ -202,7 +211,7 @@ AudioRecord::toggleRecording()
void void
AudioRecord::stopRecording() const noexcept AudioRecord::stopRecording() const noexcept
{ {
RING_DBG("Stop recording"); RING_DBG("Stop recording %s", savePath_.c_str());
recordingEnabled_ = false; recordingEnabled_ = false;
} }
......
/* /*
* Copyright (C) 2004-2015 Savoir-faire Linux Inc. * Copyright (C) 2004-2016 Savoir-faire Linux Inc.
* *
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -18,10 +19,10 @@ ...@@ -18,10 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef _AUDIO_RECORD_H #pragma once
#define _AUDIO_RECORD_H
#include "audiobuffer.h" #include "audiobuffer.h"
#include "audiorecorder.h"
#include "noncopyable.h" #include "noncopyable.h"
#include <atomic> #include <atomic>
...@@ -36,6 +37,7 @@ namespace ring { ...@@ -36,6 +37,7 @@ namespace ring {
class AudioRecord { class AudioRecord {
public: public:
AudioRecord(); AudioRecord();
~AudioRecord();
void setSndFormat(AudioFormat format); void setSndFormat(AudioFormat format);
void setRecordingOptions(AudioFormat format, const std::string &path); void setRecordingOptions(AudioFormat format, const std::string &path);
...@@ -96,6 +98,10 @@ class AudioRecord { ...@@ -96,6 +98,10 @@ class AudioRecord {
*/ */
void recData(AudioBuffer& buffer); void recData(AudioBuffer& buffer);
std::string getRecorderID() const {
return recorder_.getRecorderID();
}
private: private:
NON_COPYABLE(AudioRecord); NON_COPYABLE(AudioRecord);
...@@ -138,8 +144,11 @@ class AudioRecord { ...@@ -138,8 +144,11 @@ class AudioRecord {
* Path for this recording * Path for this recording
*/ */
std::string savePath_; std::string savePath_;
/**
* Audio recording thread
*/
AudioRecorder recorder_;
}; };
} // namespace ring } // namespace ring
#endif // _AUDIO_RECORD_H
/* /*
* Copyright (C) 2004-2015 Savoir-faire Linux Inc. * Copyright (C) 2004-2016 Savoir-faire Linux Inc.
* *
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
#include "audiorecorder.h" #include "audiorecorder.h"
#include "audiorecord.h" #include "audiorecord.h"
#include "ringbufferpool.h" #include "ringbufferpool.h"
#include "audiobuffer.h" #include "audiobuffer.h"
...@@ -32,11 +33,11 @@ ...@@ -32,11 +33,11 @@
namespace ring { namespace ring {
static constexpr std::size_t BUFFER_LENGTH {10000}; static constexpr std::size_t BUFFER_LENGTH {10000};
static constexpr std::chrono::milliseconds SLEEP_TIME {20}; static constexpr auto SLEEP_TIME = std::chrono::milliseconds(20);
AudioRecorder::AudioRecorder(AudioRecord* arec, RingBufferPool& rbp) AudioRecorder::AudioRecorder(AudioRecord* arec, RingBufferPool& rbp)
: ringBufferPool_(rbp) : ringBufferPool_(rbp)
, buffer_(new AudioBuffer(BUFFER_LENGTH, ringBufferPool_.getInternalAudioFormat())) , buffer_(new AudioBuffer(BUFFER_LENGTH, AudioFormat::NONE()))
, arecord_(arec) , arecord_(arec)
, thread_( , thread_(
[this] { return true; }, [this] { return true; },
...@@ -54,6 +55,11 @@ AudioRecorder::AudioRecorder(AudioRecord* arec, RingBufferPool& rbp) ...@@ -54,6 +55,11 @@ AudioRecorder::AudioRecorder(AudioRecord* arec, RingBufferPool& rbp)
recorderId_ = id.append(s); recorderId_ = id.append(s);
} }
AudioRecorder::~AudioRecorder()
{
thread_.join();
}
unsigned unsigned
AudioRecorder::nextProcessID() noexcept AudioRecorder::nextProcessID() noexcept
{ {
...@@ -61,17 +67,12 @@ AudioRecorder::nextProcessID() noexcept ...@@ -61,17 +67,12 @@ AudioRecorder::nextProcessID() noexcept
return ++id; return ++id;
} }
void
AudioRecorder::init() {
if (!arecord_->isRecording())
arecord_->setSndFormat(ringBufferPool_.getInternalAudioFormat());
}
void void
AudioRecorder::start() AudioRecorder::start()
{ {
if (thread_.isRunning()) if (thread_.isRunning())
return; return;
buffer_->setFormat(ringBufferPool_.getInternalAudioFormat());
thread_.start(); thread_.start();
} }
......
/* /*
* Copyright (C) 2004-2015 Savoir-faire Linux Inc. * Copyright (C) 2004-2016 Savoir-faire Linux Inc.
* *
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
...@@ -36,17 +36,12 @@ class AudioBuffer; ...@@ -36,17 +36,12 @@ class AudioBuffer;
class AudioRecorder { class AudioRecorder {
public: public:
AudioRecorder(AudioRecord* arec, RingBufferPool& rbp); AudioRecorder(AudioRecord* arec, RingBufferPool& rbp);
~AudioRecorder();
std::string getRecorderID() const noexcept { std::string getRecorderID() const {
return recorderId_; return recorderId_;
} }
/**
* Set the record to the current audio format.
* Should be called before start() at least once.
*/
void init();
/** /**
* Call to start recording. * Call to start recording.
*/ */
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "recordable.h" #include "recordable.h"
#include "audio/audiorecord.h" #include "audio/audiorecord.h"
#include "audio/audiorecorder.h" #include "audio/ringbufferpool.h"
#include "manager.h" #include "manager.h"
#include "logger.h" #include "logger.h"
...@@ -28,7 +28,6 @@ namespace ring { ...@@ -28,7 +28,6 @@ namespace ring {
Recordable::Recordable() Recordable::Recordable()
: recAudio_(new AudioRecord) : recAudio_(new AudioRecord)
, recorder_(new AudioRecorder {recAudio_.get(), Manager::instance().getRingBufferPool()})
{ {
auto record_path = Manager::instance().audioPreference.getRecordPath(); auto record_path = Manager::instance().audioPreference.getRecordPath();
RING_DBG("Set recording options: %s", record_path.c_str()); RING_DBG("Set recording options: %s", record_path.c_str());
...@@ -36,46 +35,46 @@ Recordable::Recordable() ...@@ -36,46 +35,46 @@ Recordable::Recordable()
} }
Recordable::~Recordable() Recordable::~Recordable()
{ {}
if (recAudio_->isOpenFile())
recAudio_->closeFile();
}
void void
Recordable::initRecFilename(const std::string &filename) Recordable::initRecFilename(const std::string& filename)
{ {
recAudio_->initFilename(filename); recAudio_->initFilename(filename);
} }
std::string std::string
Recordable::getFilename() const Recordable::getAudioFilename() const
{ {
return recAudio_->getFilename(); return recAudio_->getFilename();
} }
void void
Recordable::setRecordingFormat(AudioFormat format) Recordable::setRecordingAudioFormat(AudioFormat format)
{ {
recAudio_->setSndFormat(format); recAudio_->setSndFormat(format);
} }
bool
Recordable::isRecording() const
{
return recAudio_->isRecording();
}
bool bool
Recordable::toggleRecording() Recordable::toggleRecording()
{ {
if (not isRecording()) std::lock_guard<std::mutex> lk {apiMutex_};
recorder_->init(); if (not recording_) {
return recAudio_->toggleRecording(); recAudio_->setSndFormat(Manager::instance().getRingBufferPool().getInternalAudioFormat());
recAudio_->toggleRecording();
} else {
recAudio_->stopRecording();
}
recording_ = not recording_;
return recording_;
} }
void void
Recordable::stopRecording() Recordable::stopRecording()
{ {
std::lock_guard<std::mutex> lk {apiMutex_};
if (not recording_)
return;
recAudio_->stopRecording(); recAudio_->stopRecording();
} }
......
...@@ -25,11 +25,11 @@ ...@@ -25,11 +25,11 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <mutex>
namespace ring { namespace ring {
class AudioRecord; class AudioRecord;
class AudioRecorder;
class Recordable { class Recordable {
public: public:
...@@ -39,7 +39,10 @@ public: ...@@ -39,7 +39,10 @@ public:
/** /**
* Return recording state (true/false) * Return recording state (true/false)
*/ */
bool isRecording() const; bool isRecording() const {
std::lock_guard<std::mutex> lk {apiMutex_};
return recording_;
}
/** /**
* This method must be implemented for this interface as calls and conferences * This method must be implemented for this interface as calls and conferences
...@@ -59,18 +62,19 @@ public: ...@@ -59,18 +62,19 @@ public:
void initRecFilename(const std::string& filename); void initRecFilename(const std::string& filename);
/** /**
* Return the file path for this recording * Return the audio file path for this recording
*/ */
virtual std::string getFilename() const; virtual std::string getAudioFilename() const;
/** /**
* Set recording sampling rate. * Set audio recording sampling rate.
*/ */
void setRecordingFormat(AudioFormat format); void setRecordingAudioFormat(AudioFormat format);
protected: protected:
mutable std::mutex apiMutex_;
bool recording_ {false};
std::unique_ptr<AudioRecord> recAudio_; std::unique_ptr<AudioRecord> recAudio_;
std::unique_ptr<AudioRecorder> recorder_;
}; };
} // namespace ring } // namespace ring
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