|
|
|
@ -29,16 +29,10 @@
@@ -29,16 +29,10 @@
|
|
|
|
|
|
|
|
|
|
#include "settings.h" |
|
|
|
|
|
|
|
|
|
#define GROUPCHAT_MAX_SIZE 32 |
|
|
|
|
#define TOX_SAVE_INTERVAL 30*1000 |
|
|
|
|
#define TOX_FILE_INTERVAL 20 |
|
|
|
|
#define TOX_BOOTSTRAP_INTERVAL 10*1000 |
|
|
|
|
#define TOXAV_MAX_CALLS 32 |
|
|
|
|
#define TOXAV_RINGING_TIME 15 |
|
|
|
|
|
|
|
|
|
const QString Core::CONFIG_FILE_NAME = "tox_save"; |
|
|
|
|
QList<ToxFile> Core::fileSendQueue; |
|
|
|
|
QList<ToxFile> Core::fileRecvQueue; |
|
|
|
|
ToxCall Core::calls[TOXAV_MAX_CALLS]; |
|
|
|
|
|
|
|
|
|
Core::Core() : |
|
|
|
|
tox(nullptr) |
|
|
|
@ -899,6 +893,8 @@ void Core::onAvStart(int32_t call_index, void* core)
@@ -899,6 +893,8 @@ void Core::onAvStart(int32_t call_index, void* core)
|
|
|
|
|
} |
|
|
|
|
qDebug() << QString("Core: AV start from %1").arg(friendId); |
|
|
|
|
|
|
|
|
|
prepareCall(friendId, call_index, static_cast<Core*>(core)->toxav); |
|
|
|
|
|
|
|
|
|
emit static_cast<Core*>(core)->avStart(friendId, call_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -930,6 +926,8 @@ void Core::onAvEnd(int32_t call_index, void* core)
@@ -930,6 +926,8 @@ void Core::onAvEnd(int32_t call_index, void* core)
|
|
|
|
|
} |
|
|
|
|
qDebug() << QString("Core: AV end from %1").arg(friendId); |
|
|
|
|
|
|
|
|
|
cleanupCall(call_index); |
|
|
|
|
|
|
|
|
|
emit static_cast<Core*>(core)->avEnd(friendId, call_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -956,6 +954,8 @@ void Core::onAvStarting(int32_t call_index, void* core)
@@ -956,6 +954,8 @@ void Core::onAvStarting(int32_t call_index, void* core)
|
|
|
|
|
} |
|
|
|
|
qDebug() << QString("Core: AV starting %1").arg(friendId); |
|
|
|
|
|
|
|
|
|
prepareCall(friendId, call_index, static_cast<Core*>(core)->toxav); |
|
|
|
|
|
|
|
|
|
emit static_cast<Core*>(core)->avStarting(friendId, call_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -969,6 +969,8 @@ void Core::onAvEnding(int32_t call_index, void* core)
@@ -969,6 +969,8 @@ void Core::onAvEnding(int32_t call_index, void* core)
|
|
|
|
|
} |
|
|
|
|
qDebug() << QString("Core: AV ending from %1").arg(friendId); |
|
|
|
|
|
|
|
|
|
cleanupCall(call_index); |
|
|
|
|
|
|
|
|
|
emit static_cast<Core*>(core)->avEnding(friendId, call_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1019,3 +1021,81 @@ void Core::cancelCall(int callId, int friendId)
@@ -1019,3 +1021,81 @@ void Core::cancelCall(int callId, int friendId)
|
|
|
|
|
qDebug() << QString("Core: Cancelling call with %1").arg(friendId); |
|
|
|
|
toxav_cancel(toxav, callId, friendId, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Core::prepareCall(int friendId, int callId, ToxAv* toxav) |
|
|
|
|
{ |
|
|
|
|
qDebug() << QString("Core: preparing call %1").arg(callId); |
|
|
|
|
calls[callId].callId = callId; |
|
|
|
|
calls[callId].friendId = friendId; |
|
|
|
|
calls[callId].audioBuffer.open(QBuffer::ReadWrite); |
|
|
|
|
calls[callId].codecSettings = av_DefaultSettings; |
|
|
|
|
toxav_prepare_transmission(toxav, callId, &calls[callId].codecSettings, false); |
|
|
|
|
QAudioFormat format; |
|
|
|
|
format.setSampleRate(calls[callId].codecSettings.audio_sample_rate); |
|
|
|
|
format.setChannelCount(calls[callId].codecSettings.audio_channels); |
|
|
|
|
format.setSampleSize(16); |
|
|
|
|
format.setCodec("audio/pcm"); |
|
|
|
|
format.setByteOrder(QAudioFormat::LittleEndian); |
|
|
|
|
format.setSampleType(QAudioFormat::SignedInt); |
|
|
|
|
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); |
|
|
|
|
if (!info.isFormatSupported(format)) { |
|
|
|
|
calls[callId].audioOutput = nullptr; |
|
|
|
|
qWarning() << "Core: Raw audio format not supported by backend, cannot play audio."; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
calls[callId].audioOutput = new QAudioOutput(format); |
|
|
|
|
calls[callId].active = true; |
|
|
|
|
|
|
|
|
|
QtConcurrent::run(playCallAudio, callId, toxav); |
|
|
|
|
calls[callId].audioOutput->start(&calls[callId].audioBuffer); |
|
|
|
|
if (calls[callId].audioOutput->state() == QAudio::StoppedState |
|
|
|
|
&& calls[callId].audioOutput->error() == QAudio::OpenError) |
|
|
|
|
qWarning() << "Core: Unable to start audio"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Core::cleanupCall(int callId) |
|
|
|
|
{ |
|
|
|
|
qDebug() << QString("Core: cleaning up call %1").arg(callId); |
|
|
|
|
calls[callId].active = false; |
|
|
|
|
if (calls[callId].audioOutput != nullptr) |
|
|
|
|
{ |
|
|
|
|
delete calls[callId].audioOutput; |
|
|
|
|
} |
|
|
|
|
calls[callId].audioBuffer.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Core::playCallAudio(int callId, ToxAv* toxav) |
|
|
|
|
{ |
|
|
|
|
while (calls[callId].active) |
|
|
|
|
{ |
|
|
|
|
int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000; |
|
|
|
|
int16_t buf[framesize]; |
|
|
|
|
int len = toxav_recv_audio(toxav, callId, framesize, buf); |
|
|
|
|
if (len < 0) |
|
|
|
|
{ |
|
|
|
|
qDebug() << "Core::playCallAudio: Error receiving audio"; |
|
|
|
|
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (len == 0) |
|
|
|
|
continue; |
|
|
|
|
qDebug() << QString("Core::playCallAudio: Playing %1 frames/sample").arg(len); |
|
|
|
|
calls[callId].audioBuffer.write((char*)buf, len*2); |
|
|
|
|
calls[callId].audioBuffer.seek(0); |
|
|
|
|
calls[callId].audioOutput->resume(); |
|
|
|
|
int error = calls[callId].audioOutput->error(); |
|
|
|
|
if (error != QAudio::NoError) |
|
|
|
|
qWarning() << QString("Core::playCallAudio: Error: %1").arg(error); |
|
|
|
|
|
|
|
|
|
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Core::sendCallAudio(int callId, ToxAv* toxav) |
|
|
|
|
{ |
|
|
|
|
while (calls[callId].active) |
|
|
|
|
{ |
|
|
|
|
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|