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 : #pragma once
18 :
19 : #include <atomic>
20 : #include <future>
21 : #include <mutex>
22 : #include <chrono>
23 :
24 : #include "audio_format.h"
25 : #include "media/media_device.h"
26 : #include "media/media_buffer.h"
27 : #include "observer.h"
28 : #include "threadloop.h"
29 : #include "media/media_codec.h"
30 :
31 : namespace jami {
32 : class AudioDeviceGuard;
33 : class AudioFrameResizer;
34 : class MediaDemuxer;
35 : class MediaDecoder;
36 : class MediaRecorder;
37 : struct MediaStream;
38 : class Resampler;
39 : class RingBuffer;
40 :
41 : class AudioInput : public Observable<std::shared_ptr<MediaFrame>>
42 : {
43 : public:
44 : AudioInput(const std::string& id);
45 : AudioInput(const std::string& id, const std::string& resource);
46 : ~AudioInput();
47 :
48 : std::shared_future<DeviceParams> switchInput(const std::string& resource);
49 5 : void start() { loop_.start(); };
50 :
51 0 : bool isCapturing() const { return loop_.isRunning(); }
52 : void setFormat(const AudioFormat& fmt);
53 : void setMuted(bool isMuted);
54 : MediaStream getInfo() const;
55 : MediaStream getInfo(const std::string& name) const;
56 : void updateStartTime(int64_t start);
57 : void setPaused(bool paused);
58 : void configureFilePlayback(const std::string& path, std::shared_ptr<MediaDemuxer>& demuxer, int index);
59 : void flushBuffers();
60 : void setSeekTime(int64_t time);
61 :
62 176 : void setSuccessfulSetupCb(const std::function<void(MediaType, bool)>& cb) { onSuccessfulSetup_ = cb; }
63 :
64 : void setRecorderCallback(const std::function<void(const MediaStream& ms)>& cb);
65 :
66 176 : std::string getId() const { return id_; };
67 :
68 : /**
69 : * Return the ring-buffer ID that other components should read from
70 : * to get this input's audio data. For capture streams this is the
71 : * target device ID (e.g. "desktop"); for files it is the
72 : * AudioInput's own ID (where the decoder writes).
73 : */
74 0 : std::string getSourceRingBufferId() const { return sourceRingBufferId_; };
75 :
76 : private:
77 : void readFromDevice();
78 : void readFromFile();
79 : void readFromQueue();
80 : bool initDevice(const std::string& device);
81 : bool initFile(const std::string& path);
82 : bool initCapture(const std::string& device);
83 : bool createDecoder();
84 : void frameResized(std::shared_ptr<AudioFrame>&& ptr);
85 :
86 : std::string id_;
87 : std::string sourceRingBufferId_; // ring buffer ID to read this input's audio from
88 : std::shared_ptr<RingBuffer> ringBuf_;
89 : bool muteState_ {false};
90 : uint64_t sent_samples = 0;
91 : mutable std::mutex fmtMutex_ {};
92 : AudioFormat format_;
93 : int frameSize_;
94 : std::atomic_bool paused_ {true};
95 :
96 : std::unique_ptr<Resampler> resampler_;
97 : std::unique_ptr<AudioFrameResizer> resizer_;
98 : std::unique_ptr<MediaDecoder> decoder_;
99 :
100 : std::string resource_;
101 : std::mutex resourceMutex_ {};
102 : DeviceParams devOpts_;
103 : std::promise<DeviceParams> foundDevOpts_;
104 : std::shared_future<DeviceParams> futureDevOpts_;
105 : std::atomic_bool devOptsFound_ {false};
106 : void foundDevOpts(const DeviceParams& params);
107 :
108 : std::atomic_bool playingDevice_ {false};
109 : std::atomic_bool decodingFile_ {false};
110 : std::atomic_bool playingFile_ {false};
111 : std::unique_ptr<AudioDeviceGuard> deviceGuard_;
112 :
113 : ThreadLoop loop_;
114 : void process();
115 :
116 : std::chrono::time_point<std::chrono::steady_clock> wakeUp_;
117 :
118 : std::function<void(MediaType, bool)> onSuccessfulSetup_;
119 : std::function<void(const MediaStream& ms)> recorderCallback_;
120 : std::atomic_bool settingMS_ {true};
121 : };
122 :
123 : } // namespace jami
|