Line data Source code
1 : /*
2 : * Copyright (C) 2004-2026 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 "client/videomanager.h"
21 : #include "media_stream.h"
22 : #include "manager.h"
23 : #include "logger.h"
24 : #include "client/videomanager.h"
25 :
26 : namespace jami {
27 :
28 0 : LocalRecorder::LocalRecorder(const std::string& inputUri)
29 : {
30 0 : inputUri_ = inputUri;
31 0 : isAudioOnly_ = inputUri_.empty();
32 0 : recorder_->audioOnly(isAudioOnly_);
33 0 : }
34 :
35 0 : LocalRecorder::~LocalRecorder()
36 : {
37 0 : if (isRecording())
38 0 : stopRecording();
39 0 : }
40 :
41 : void
42 0 : LocalRecorder::setPath(const std::string& path)
43 : {
44 0 : if (isRecording()) {
45 0 : JAMI_ERROR("Unable to set path while recording");
46 0 : return;
47 : }
48 :
49 0 : recorder_->setPath(path);
50 0 : path_ = path;
51 : }
52 :
53 : bool
54 0 : LocalRecorder::start()
55 : {
56 0 : if (isRecording()) {
57 0 : JAMI_ERROR("Recording already started!");
58 0 : return false;
59 : }
60 :
61 0 : if (path_.empty()) {
62 0 : JAMI_ERROR("Unable to start recording (path not set)");
63 0 : return false;
64 : }
65 :
66 0 : if (!recorder_) {
67 0 : JAMI_ERROR("Unable to start recording (no recorder)");
68 0 : return false;
69 : }
70 :
71 : // audio recording
72 : // create read offset in RingBuffer
73 0 : Manager::instance().getRingBufferPool().bindHalfDuplexOut(path_, RingBufferPool::DEFAULT_ID);
74 :
75 0 : audioInput_ = getAudioInput(path_);
76 0 : audioInput_->setFormat(AudioFormat::STEREO());
77 0 : audioInput_->attach(recorder_->addStream(audioInput_->getInfo()));
78 0 : audioInput_->switchInput("");
79 :
80 : #ifdef ENABLE_VIDEO
81 : // video recording
82 0 : if (!isAudioOnly_) {
83 0 : videoInput_ = std::static_pointer_cast<video::VideoInput>(getVideoInput(inputUri_));
84 0 : if (videoInput_) {
85 0 : videoInput_->attach(recorder_->addStream(videoInput_->getInfo()));
86 : } else {
87 0 : JAMI_ERROR("Unable to record video (no video input)");
88 0 : return false;
89 : }
90 : }
91 : #endif
92 :
93 0 : return Recordable::startRecording(path_);
94 : }
95 :
96 : void
97 0 : LocalRecorder::stopRecording()
98 : {
99 0 : if (auto* ob = recorder_->getStream(audioInput_->getInfo().name))
100 0 : audioInput_->detach(ob);
101 : #ifdef ENABLE_VIDEO
102 0 : if (videoInput_)
103 0 : if (auto* ob = recorder_->getStream(videoInput_->getInfo().name))
104 0 : videoInput_->detach(ob);
105 : #endif
106 0 : Manager::instance().getRingBufferPool().unBindHalfDuplexOut(path_, RingBufferPool::DEFAULT_ID);
107 : // NOTE stopRecording should be last call to avoid data races
108 0 : Recordable::stopRecording();
109 0 : }
110 :
111 : } // namespace jami
|