Line data Source code
1 : /* 2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc. 3 : * 4 : * This program is free software: you can redistribute it and/or modify 5 : * it under the terms of the GNU General Public License as published by 6 : * the Free Software Foundation, either version 3 of the License, or 7 : * (at your option) any later version. 8 : * 9 : * This program is distributed in the hope that it will be useful, 10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : * GNU General Public License for more details. 13 : * 14 : * You should have received a copy of the GNU General Public License 15 : * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 : */ 17 : 18 : #include "localrecorder.h" 19 : #include "audio/ringbufferpool.h" 20 : #include "audio/ringbuffer.h" 21 : #include "client/videomanager.h" 22 : #include "media_stream.h" 23 : #include "manager.h" 24 : #include "logger.h" 25 : #include "client/videomanager.h" 26 : 27 : namespace jami { 28 : 29 0 : LocalRecorder::LocalRecorder(const std::string& inputUri) 30 : { 31 0 : inputUri_ = inputUri; 32 0 : isAudioOnly_ = inputUri_.empty(); 33 0 : recorder_->audioOnly(isAudioOnly_); 34 0 : } 35 : 36 0 : LocalRecorder::~LocalRecorder() 37 : { 38 0 : if (isRecording()) 39 0 : stopRecording(); 40 0 : } 41 : 42 : void 43 0 : LocalRecorder::setPath(const std::string& path) 44 : { 45 0 : if (isRecording()) { 46 0 : JAMI_ERR("Unable to set path while recording"); 47 0 : return; 48 : } 49 : 50 0 : recorder_->setPath(path); 51 0 : path_ = path; 52 : } 53 : 54 : bool 55 0 : LocalRecorder::startRecording() 56 : { 57 0 : if (isRecording()) { 58 0 : JAMI_ERR("Recording already started!"); 59 0 : return false; 60 : } 61 : 62 0 : if (path_.empty()) { 63 0 : JAMI_ERR("Unable to start recording (path not set)"); 64 0 : return false; 65 : } 66 : 67 0 : if (!recorder_) { 68 0 : JAMI_ERR("Unable to start recording (no recorder)"); 69 0 : return false; 70 : } 71 : 72 : // audio recording 73 : // create read offset in RingBuffer 74 0 : Manager::instance().getRingBufferPool().bindHalfDuplexOut(path_, RingBufferPool::DEFAULT_ID); 75 : 76 0 : audioInput_ = getAudioInput(path_); 77 0 : audioInput_->setFormat(AudioFormat::STEREO()); 78 0 : audioInput_->attach(recorder_->addStream(audioInput_->getInfo())); 79 0 : audioInput_->switchInput(""); 80 : 81 : #ifdef ENABLE_VIDEO 82 : // video recording 83 0 : if (!isAudioOnly_) { 84 0 : videoInput_ = std::static_pointer_cast<video::VideoInput>(getVideoInput(inputUri_)); 85 0 : if (videoInput_) { 86 0 : videoInput_->attach(recorder_->addStream(videoInput_->getInfo())); 87 : } else { 88 0 : JAMI_ERR() << "Unable to record video (no video input)"; 89 0 : return false; 90 : } 91 : } 92 : #endif 93 : 94 0 : return Recordable::startRecording(path_); 95 : } 96 : 97 : void 98 0 : LocalRecorder::stopRecording() 99 : { 100 0 : if (auto ob = recorder_->getStream(audioInput_->getInfo().name)) 101 0 : audioInput_->detach(ob); 102 : #ifdef ENABLE_VIDEO 103 0 : if (videoInput_) 104 0 : if (auto ob = recorder_->getStream(videoInput_->getInfo().name)) 105 0 : videoInput_->detach(ob); 106 : #endif 107 0 : Manager::instance().getRingBufferPool().unBindHalfDuplexOut(path_, RingBufferPool::DEFAULT_ID); 108 : // NOTE stopRecording should be last call to avoid data races 109 0 : Recordable::stopRecording(); 110 0 : } 111 : 112 : } // namespace jami