qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
toxcall.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2019 by The qTox Project Contributors
3 
4  This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6  qTox is libre software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  qTox is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with qTox. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "src/core/toxcall.h"
21 #include "audio/audio.h"
22 #include "src/core/coreav.h"
24 #include "src/video/camerasource.h"
26 #include "src/model/group.h"
27 #include <QTimer>
28 #include <QtConcurrent/QtConcurrent>
29 
51 ToxCall::ToxCall(bool VideoEnabled, CoreAV& av, IAudioControl& audio)
52  : av{&av}
53  , audio(audio)
54  , videoEnabled{VideoEnabled}
55  , audioSource(audio.makeSource())
56 {}
57 
59 {
60  if (videoEnabled) {
61  QObject::disconnect(videoInConn);
63  }
64 }
65 
66 bool ToxCall::isActive() const
67 {
68  return active;
69 }
70 
71 void ToxCall::setActive(bool value)
72 {
73  active = value;
74 }
75 
76 bool ToxCall::getMuteVol() const
77 {
78  return muteVol;
79 }
80 
81 void ToxCall::setMuteVol(bool value)
82 {
83  muteVol = value;
84 }
85 
86 bool ToxCall::getMuteMic() const
87 {
88  return muteMic;
89 }
90 
91 void ToxCall::setMuteMic(bool value)
92 {
93  muteMic = value;
94 }
95 
97 {
98  return videoEnabled;
99 }
100 
101 void ToxCall::setVideoEnabled(bool value)
102 {
103  videoEnabled = value;
104 }
105 
107 {
108  return nullVideoBitrate;
109 }
110 
112 {
113  nullVideoBitrate = value;
114 }
115 
117 {
118  return videoSource;
119 }
120 
121 ToxFriendCall::ToxFriendCall(uint32_t FriendNum, bool VideoEnabled, CoreAV& av, IAudioControl& audio)
122  : ToxCall(VideoEnabled, av, audio)
123  , sink(audio.makeSink())
124  , friendId{FriendNum}
125 {
126  connect(audioSource.get(), &IAudioSource::frameAvailable, this,
127  [this](const int16_t* pcm, size_t samples, uint8_t chans, uint32_t rate) {
128  this->av->sendCallAudio(this->friendId, pcm, samples, chans, rate);
129  });
130 
131  connect(audioSource.get(), &IAudioSource::invalidated, this, &ToxFriendCall::onAudioSourceInvalidated);
132 
133  if (sink) {
134  audioSinkInvalid = sink->connectTo_invalidated(this, [this]() { this->onAudioSinkInvalidated(); });
135  }
136 
137  // register video
138  if (videoEnabled) {
139  videoSource = new CoreVideoSource();
141 
142  if (source.isNone()) {
143  source.setupDefault();
144  }
145  source.subscribe();
146  videoInConn = QObject::connect(&source, &VideoSource::frameAvailable,
147  [&av, FriendNum](std::shared_ptr<VideoFrame> frame) {
148  av.sendCallVideo(FriendNum, frame);
149  });
150  if (!videoInConn) {
151  qDebug() << "Video connection not working";
152  }
153  }
154 }
155 
157 {
158  QObject::disconnect(audioSinkInvalid);
159 }
160 
162 {
163  auto newSrc = audio.makeSource();
164  connect(newSrc.get(), &IAudioSource::frameAvailable, this,
165  [this](const int16_t* pcm, size_t samples, uint8_t chans, uint32_t rate) {
166  this->av->sendCallAudio(this->friendId, pcm, samples, chans, rate);
167  });
168  audioSource = std::move(newSrc);
169 
170  connect(audioSource.get(), &IAudioSource::invalidated, this, &ToxFriendCall::onAudioSourceInvalidated);
171 }
172 
174 {
175  auto newSink = audio.makeSink();
176 
177  if (newSink) {
178  audioSinkInvalid = newSink->connectTo_invalidated(this, [this]() { this->onAudioSinkInvalidated(); });
179  }
180 
181  sink = std::move(newSink);
182 }
183 
184 TOXAV_FRIEND_CALL_STATE ToxFriendCall::getState() const
185 {
186  return state;
187 }
188 
189 void ToxFriendCall::setState(const TOXAV_FRIEND_CALL_STATE& value)
190 {
191  state = value;
192 }
193 
194 void ToxFriendCall::playAudioBuffer(const int16_t* data, int samples, unsigned channels,
195  int sampleRate) const
196 {
197  if (sink) {
198  sink->playAudioBuffer(data, samples, channels, sampleRate);
199  }
200 }
201 
202 ToxGroupCall::ToxGroupCall(const Group& group, CoreAV& av, IAudioControl& audio)
203  : ToxCall(false, av, audio)
204  , group{group}
205 {
206  // register audio
207  connect(audioSource.get(), &IAudioSource::frameAvailable, this,
208  [this](const int16_t* pcm, size_t samples, uint8_t chans, uint32_t rate) {
209  if (this->group.getPeersCount() <= 1) {
210  return;
211  }
212 
213  this->av->sendGroupCallAudio(this->group.getId(), pcm, samples, chans, rate);
214  });
215 
216  connect(audioSource.get(), &IAudioSource::invalidated, this, &ToxGroupCall::onAudioSourceInvalidated);
217 }
218 
220 {
221  // disconnect all Qt connections
222  clearPeers();
223 }
224 
226 {
227  auto newSrc = audio.makeSource();
228  connect(audioSource.get(), &IAudioSource::frameAvailable,
229  [this](const int16_t* pcm, size_t samples, uint8_t chans, uint32_t rate) {
230  if (this->group.getPeersCount() <= 1) {
231  return;
232  }
233 
234  this->av->sendGroupCallAudio(this->group.getId(), pcm, samples, chans, rate);
235  });
236 
237  audioSource = std::move(newSrc);
238 
239  connect(audioSource.get(), &IAudioSource::invalidated, this, &ToxGroupCall::onAudioSourceInvalidated);
240 }
241 
242 
244 {
245  removePeer(peerId);
246  addPeer(peerId);
247 }
248 
250 {
251  const auto& source = peers.find(peerId);
252  if (source == peers.cend()) {
253  qDebug() << "Peer:" << peerId.toString() << "does not have a source, can't remove";
254  return;
255  }
256 
257  peers.erase(source);
258  QObject::disconnect(sinkInvalid[peerId]);
259  sinkInvalid.erase(peerId);
260 }
261 
263 {
264  std::unique_ptr<IAudioSink> newSink = audio.makeSink();
265 
266  QMetaObject::Connection con;
267 
268  if (newSink) {
269  con = newSink->connectTo_invalidated(this, [this, peerId]() { this->onAudioSinkInvalidated(peerId); });
270  }
271 
272  peers.emplace(peerId, std::move(newSink));
273  sinkInvalid.insert({peerId, con});
274 }
275 
277 {
278  const auto& source = peers.find(peerId);
279  return source != peers.cend();
280 }
281 
283 {
284  peers.clear();
285  for (auto con : sinkInvalid) {
286  QObject::disconnect(con.second);
287  }
288 
289  sinkInvalid.clear();
290 }
291 
292 void ToxGroupCall::playAudioBuffer(const ToxPk& peer, const int16_t* data, int samples,
293  unsigned channels, int sampleRate)
294 {
295  if (!havePeer(peer)) {
296  addPeer(peer);
297  }
298  const auto& source = peers.find(peer);
299  if (source->second) {
300  source->second->playAudioBuffer(data, samples, channels, sampleRate);
301  }
302 }
ToxCall::ToxCall
ToxCall()=delete
CameraSource::setupDefault
void setupDefault()
Setup default device.
Definition: camerasource.cpp:145
ToxCall::muteVol
bool muteVol
Definition: toxcall.h:80
CameraSource::unsubscribe
void unsubscribe() override
Stop emitting frameAvailable signals, and free associated resources if necessary.
Definition: camerasource.cpp:246
ToxFriendCall::ToxFriendCall
ToxFriendCall()=delete
ToxCall::videoInConn
QMetaObject::Connection videoInConn
Definition: toxcall.h:83
ToxGroupCall::playAudioBuffer
void playAudioBuffer(const ToxPk &peer, const int16_t *data, int samples, unsigned channels, int sampleRate)
Definition: toxcall.cpp:292
settings.h
VideoSource::frameAvailable
void frameAvailable(std::shared_ptr< VideoFrame > frame)
Emitted when new frame available to use.
ToxCall::videoSource
CoreVideoSource * videoSource
Definition: toxcall.h:82
ToxFriendCall::getState
TOXAV_FRIEND_CALL_STATE getState() const
Definition: toxcall.cpp:184
ToxGroupCall::~ToxGroupCall
~ToxGroupCall()
Definition: toxcall.cpp:219
ToxGroupCall::peers
std::map< ToxPk, std::unique_ptr< IAudioSink > > peers
Keeps sources for users in group calls.
Definition: toxcall.h:135
group.h
ToxFriendCall::onAudioSourceInvalidated
void onAudioSourceInvalidated()
Definition: toxcall.cpp:161
ToxGroupCall::group
const Group & group
Definition: toxcall.h:137
ToxGroupCall::ToxGroupCall
ToxGroupCall()=delete
CameraSource
This class is a wrapper to share a camera's captured video frames.
Definition: camerasource.h:34
ToxCall::getVideoEnabled
bool getVideoEnabled() const
Definition: toxcall.cpp:96
ToxGroupCall::onAudioSinkInvalidated
void onAudioSinkInvalidated(ToxPk peerId)
Definition: toxcall.cpp:243
ToxGroupCall::havePeer
bool havePeer(ToxPk peerId)
Definition: toxcall.cpp:276
ToxCall::active
bool active
Definition: toxcall.h:75
ToxFriendCall::onAudioSinkInvalidated
void onAudioSinkInvalidated()
Definition: toxcall.cpp:173
ToxCall::setMuteVol
void setMuteVol(bool value)
Definition: toxcall.cpp:81
CameraSource::isNone
bool isNone() const
Definition: camerasource.cpp:193
ToxFriendCall::playAudioBuffer
void playAudioBuffer(const int16_t *data, int samples, unsigned channels, int sampleRate) const
Definition: toxcall.cpp:194
ToxCall::~ToxCall
~ToxCall()
Definition: toxcall.cpp:58
ToxCall
Definition: toxcall.h:41
ToxFriendCall::audioSinkInvalid
QMetaObject::Connection audioSinkInvalid
Definition: toxcall.h:109
ToxGroupCall::onAudioSourceInvalidated
void onAudioSourceInvalidated()
Definition: toxcall.cpp:225
ToxCall::setVideoEnabled
void setVideoEnabled(bool value)
Definition: toxcall.cpp:101
ToxCall::getMuteMic
bool getMuteMic() const
Definition: toxcall.cpp:86
ToxCall::nullVideoBitrate
bool nullVideoBitrate
Definition: toxcall.h:85
coreav.h
ToxFriendCall::sink
std::unique_ptr< IAudioSink > sink
Definition: toxcall.h:111
ToxCall::setActive
void setActive(bool value)
Definition: toxcall.cpp:71
ToxGroupCall::removePeer
void removePeer(ToxPk peerId)
Definition: toxcall.cpp:249
toxcall.h
ToxCall::audioSource
std::unique_ptr< IAudioSource > audioSource
Definition: toxcall.h:86
ToxCall::muteMic
bool muteMic
Definition: toxcall.h:79
ToxPk
This class represents a Tox Public Key, which is a part of Tox ID.
Definition: toxpk.h:26
camerasource.h
ToxCall::av
CoreAV * av
Definition: toxcall.h:76
ToxFriendCall::setState
void setState(const TOXAV_FRIEND_CALL_STATE &value)
Definition: toxcall.cpp:189
ToxFriendCall::state
TOXAV_FRIEND_CALL_STATE state
State of the peer (not ours!)
Definition: toxcall.h:110
ToxCall::setNullVideoBitrate
void setNullVideoBitrate(bool value)
Definition: toxcall.cpp:111
ToxCall::setMuteMic
void setMuteMic(bool value)
Definition: toxcall.cpp:91
Group
Definition: group.h:34
CameraSource::getInstance
static CameraSource & getInstance()
Returns the singleton instance.
Definition: camerasource.cpp:128
corevideosource.h
ToxCall::videoEnabled
bool videoEnabled
Definition: toxcall.h:84
ToxGroupCall::sinkInvalid
std::map< ToxPk, QMetaObject::Connection > sinkInvalid
Definition: toxcall.h:136
CoreVideoSource
A VideoSource that emits frames received by Core.
Definition: corevideosource.h:28
ContactId::toString
QString toString() const
Converts the ContactId to a uppercase hex string.
Definition: contactid.cpp:78
CameraSource::subscribe
void subscribe() override
If subscribe sucessfully opens the source, it will start emitting frameAvailable signals.
Definition: camerasource.cpp:238
ToxCall::getMuteVol
bool getMuteVol() const
Definition: toxcall.cpp:76
ToxCall::audio
IAudioControl & audio
Definition: toxcall.h:78
ToxGroupCall::clearPeers
void clearPeers()
Definition: toxcall.cpp:282
ToxFriendCall::~ToxFriendCall
~ToxFriendCall()
Definition: toxcall.cpp:156
ToxCall::getNullVideoBitrate
bool getNullVideoBitrate() const
Definition: toxcall.cpp:106
ToxGroupCall::addPeer
void addPeer(ToxPk peerId)
Definition: toxcall.cpp:262
CoreAV
Definition: coreav.h:47
ToxCall::isActive
bool isActive() const
Definition: toxcall.cpp:66
ToxCall::getVideoSource
CoreVideoSource * getVideoSource() const
Definition: toxcall.cpp:116