1
0
mirror of https://github.com/danog/php-libtgvoip.git synced 2024-11-30 04:19:26 +01:00
This commit is contained in:
Daniil Gentili 2017-07-20 16:24:17 +02:00
parent ba582a826d
commit a17113448a
6 changed files with 196 additions and 190 deletions

View File

@ -9,7 +9,6 @@
#include "../libtgvoip/logging.h"
#include <queue>
#include <unistd.h>
#include <phpcpp.h>
using namespace tgvoip;
using namespace tgvoip::audio;
@ -19,8 +18,6 @@ AudioInputModule::AudioInputModule(std::string deviceID, VoIPController *control
wrapper = (VoIP *)(controller->implData);
wrapper->in = this;
wrapper->inputState = AUDIO_STATE_CREATED;
init_mutex(inputMutex);
configuringInput = false;
}
AudioInputModule::~AudioInputModule()
@ -28,21 +25,11 @@ AudioInputModule::~AudioInputModule()
wrapper->inputState = AUDIO_STATE_NONE;
wrapper->in = NULL;
if (senderThread) {
if (senderThread)
{
LOGD("before join senderThread");
join_thread(senderThread);
}
while (holdFiles.size()) {
fclose(holdFiles.front());
holdFiles.pop();
}
while (inputFiles.size()) {
fclose(inputFiles.front());
inputFiles.pop();
}
free_mutex(inputMutex);
}
void AudioInputModule::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels)
@ -61,59 +48,16 @@ void AudioInputModule::Configure(uint32_t sampleRate, uint32_t bitsPerSample, ui
wrapper->inputState = AUDIO_STATE_CONFIGURED;
}
bool AudioInputModule::play(const char *file) {
FILE *tmp = fopen(file, "rb");
if (tmp == NULL) {
throw Php::Exception("Could not open file!");
return false;
}
configuringInput = true;
lock_mutex(inputMutex);
inputFiles.push(tmp);
configuringInput = false;
unlock_mutex(inputMutex);
return true;
}
bool AudioInputModule::playOnHold(Php::Parameters &params) {
configuringInput = true;
FILE *tmp = NULL;
lock_mutex(inputMutex);
while (holdFiles.size()) {
fclose(holdFiles.front());
holdFiles.pop();
}
for (int i = 0; i < params[0].size(); i++) {
tmp = fopen(params[0][i], "rb");
if (tmp == NULL) {
throw Php::Exception("Could not open file!");
configuringInput = false;
unlock_mutex(inputMutex);
return false;
}
holdFiles.push(tmp);
}
configuringInput = false;
unlock_mutex(inputMutex);
return true;
}
void AudioInputModule::Start()
{
if (wrapper->inputState == AUDIO_STATE_RUNNING)
return;
wrapper->inputState = AUDIO_STATE_RUNNING;
LOGE("STARTING SENDER THREAD");
start_thread(senderThread, StartSenderThread, this);
set_thread_priority(senderThread, get_thread_max_priority());
set_thread_name(senderThread, "voip-sender");
}
void AudioInputModule::Stop()
@ -123,50 +67,64 @@ void AudioInputModule::Stop()
wrapper->inputState = AUDIO_STATE_CONFIGURED;
}
void* AudioInputModule::StartSenderThread(void* input){
((AudioInputModule*)input)->RunSenderThread();
void *AudioInputModule::StartSenderThread(void *input)
{
((AudioInputModule *)input)->RunSenderThread();
return NULL;
}
void AudioInputModule::RunSenderThread() {
unsigned char *data = (unsigned char *) malloc(inputCSamplesSize);
void AudioInputModule::RunSenderThread()
{
unsigned char *data = (unsigned char *)malloc(inputCSamplesSize);
size_t read;
double time = VoIPController::GetCurrentTime();
double sleeptime;
while (wrapper->inputState == AUDIO_STATE_RUNNING) {
lock_mutex(inputMutex);
while (!configuringInput && wrapper->inputState == AUDIO_STATE_RUNNING) {
if ((sleeptime = (inputWritePeriodSec - (VoIPController::GetCurrentTime() - time))*1000000.0) < 0) {
while (wrapper->inputState == AUDIO_STATE_RUNNING)
{
lock_mutex(wrapper->inputMutex);
while (!wrapper->configuringInput && wrapper->inputState == AUDIO_STATE_RUNNING)
{
if ((sleeptime = (inputWritePeriodSec - (VoIPController::GetCurrentTime() - time)) * 1000000.0) < 0)
{
LOGE("Sender: I'm late!");
} else {
}
else
{
usleep(sleeptime);
}
time = VoIPController::GetCurrentTime();
if (!inputFiles.empty()) {
if ((read = fread(data, sizeof(unsigned char), inputSamplesSize, inputFiles.front())) != inputCSamplesSize) {
fclose(inputFiles.front());
inputFiles.pop();
if (!wrapper->inputFiles.empty())
{
if ((read = fread(data, sizeof(unsigned char), inputSamplesSize, wrapper->inputFiles.front())) != inputCSamplesSize)
{
fclose(wrapper->inputFiles.front());
wrapper->inputFiles.pop();
memset(data + (read % inputCSamplesSize), 0, inputCSamplesSize - (read % inputCSamplesSize));
}
wrapper->playing = true;
} else {
}
else
{
wrapper->playing = false;
if (holdFiles.empty()) {
if (wrapper->holdFiles.empty())
{
memset(data, 0, inputCSamplesSize);
} else {
if ((read = fread(data, sizeof(unsigned char), inputSamplesSize, holdFiles.front())) != inputCSamplesSize) {
fseek(holdFiles.front(), 0, SEEK_SET);
holdFiles.push(holdFiles.front());
holdFiles.pop();
}
else
{
if ((read = fread(data, sizeof(unsigned char), inputSamplesSize, wrapper->holdFiles.front())) != inputCSamplesSize)
{
fseek(wrapper->holdFiles.front(), 0, SEEK_SET);
wrapper->holdFiles.push(wrapper->holdFiles.front());
wrapper->holdFiles.pop();
memset(data + (read % inputCSamplesSize), 0, inputCSamplesSize - (read % inputCSamplesSize));
}
}
}
InvokeCallback(data, inputCSamplesSize);
InvokeCallback(data, inputCSamplesSize);
}
unlock_mutex(inputMutex);
unlock_mutex(wrapper->inputMutex);
}
free(data);
}

View File

@ -29,9 +29,6 @@ public:
bool writeSamples(unsigned char *data);
static void EnumerateDevices(std::vector<AudioInputDevice>& devs);
bool play(const char *file);
bool playOnHold(Php::Parameters &params);
static void* StartSenderThread(void* input);
void RunSenderThread();
@ -47,11 +44,6 @@ public:
size_t inputCSamplesSize;
std::queue<FILE *> inputFiles;
std::queue<FILE *> holdFiles;
tgvoip_mutex_t inputMutex;
bool configuringInput;
private:

View File

@ -18,59 +18,16 @@ AudioOutputModule::AudioOutputModule(std::string deviceID, VoIPController *contr
wrapper = (VoIP *)(controller->implData);
wrapper->out = this;
wrapper->outputState = AUDIO_STATE_CREATED;
outputFile=NULL;
configuringOutput = false;
//init_mutex(outputMutex);
}
AudioOutputModule::~AudioOutputModule()
{
wrapper->outputState = AUDIO_STATE_NONE;
wrapper->out = NULL;
if (receiverThread) {
if (receiverThread)
{
LOGD("before join receiverThread");
join_thread(receiverThread);
}
this->unsetOutputFile();
free_mutex(outputMutex);
}
bool AudioOutputModule::unsetOutputFile() {
if (outputFile == NULL) {
return false;
}
configuringOutput = true;
lock_mutex(outputMutex);
fflush(outputFile);
fclose(outputFile);
outputFile = NULL;
configuringOutput = false;
unlock_mutex(outputMutex);
return true;
}
bool AudioOutputModule::setOutputFile(const char *file) {
configuringOutput = true;
lock_mutex(outputMutex);
if (outputFile != NULL) {
fclose(outputFile);
outputFile=NULL;
}
outputFile = fopen(file, "wb");
if (outputFile == NULL) {
throw Php::Exception("Could not open file!");
configuringOutput = false;
unlock_mutex(outputMutex);
return false;
}
configuringOutput = false;
unlock_mutex(outputMutex);
return true;
}
void AudioOutputModule::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels)
@ -87,8 +44,6 @@ void AudioOutputModule::Configure(uint32_t sampleRate, uint32_t bitsPerSample, u
outputCSamplesSize = outputSampleNumber * outputChannels * outputBitsPerSample / 8 * sizeof(unsigned char);
wrapper->outputState = AUDIO_STATE_CONFIGURED;
}
void AudioOutputModule::Start()
@ -96,12 +51,11 @@ void AudioOutputModule::Start()
if (wrapper->outputState == AUDIO_STATE_RUNNING)
return;
wrapper->outputState = AUDIO_STATE_RUNNING;
LOGE("STARTING RECEIVER THREAD");
start_thread(receiverThread, StartReceiverThread, this);
set_thread_priority(receiverThread, get_thread_max_priority());
set_thread_name(receiverThread, "voip-receiver");
}
void AudioOutputModule::Stop()
@ -121,36 +75,44 @@ float AudioOutputModule::GetLevel()
return outputLevel;
}
void* AudioOutputModule::StartReceiverThread(void* output){
((AudioOutputModule*)output)->RunReceiverThread();
void *AudioOutputModule::StartReceiverThread(void *output)
{
((AudioOutputModule *)output)->RunReceiverThread();
return NULL;
}
void AudioOutputModule::RunReceiverThread() {
unsigned char *data = (unsigned char *) malloc(outputCSamplesSize);
void AudioOutputModule::RunReceiverThread()
{
unsigned char *data = (unsigned char *)malloc(outputCSamplesSize);
double time = VoIPController::GetCurrentTime();
double sleeptime;
while (wrapper->outputState == AUDIO_STATE_RUNNING) {
lock_mutex(outputMutex);
while (!configuringOutput && wrapper->outputState == AUDIO_STATE_RUNNING) {
if ((sleeptime = (outputWritePeriodSec - (VoIPController::GetCurrentTime() - time))*1000000.0) < 0) {
while (wrapper->outputState == AUDIO_STATE_RUNNING)
{
lock_mutex(wrapper->outputMutex);
while (!wrapper->configuringOutput && wrapper->outputState == AUDIO_STATE_RUNNING)
{
if ((sleeptime = (outputWritePeriodSec - (VoIPController::GetCurrentTime() - time)) * 1000000.0) < 0)
{
LOGE("Receiver: I'm late!");
} else {
}
else
{
usleep(sleeptime);
}
time = VoIPController::GetCurrentTime();
InvokeCallback(data, outputCSamplesSize);
if (outputFile != NULL) {
if (fwrite(data, sizeof(unsigned char), outputSamplesSize, outputFile) != outputCSamplesSize) {
if (wrapper->outputFile != NULL)
{
if (fwrite(data, sizeof(unsigned char), outputSamplesSize, wrapper->outputFile) != outputCSamplesSize)
{
LOGE("COULD NOT WRITE DATA TO FILE");
}
}
}
unlock_mutex(outputMutex);
unlock_mutex(wrapper->outputMutex);
}
free(data);
}

View File

@ -12,49 +12,47 @@
#include "../main.h"
#include "../libtgvoip/threading.h"
namespace tgvoip{ namespace audio{
class AudioOutputModule : public AudioOutput{
namespace tgvoip
{
namespace audio
{
class AudioOutputModule : public AudioOutput
{
public:
AudioOutputModule(std::string deviceID, VoIPController* controller);
public:
AudioOutputModule(std::string deviceID, VoIPController *controller);
virtual ~AudioOutputModule();
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
virtual void Start();
virtual void Stop();
virtual bool IsPlaying() override;
virtual float GetLevel() override;
unsigned char * readSamples();
static void EnumerateDevices(std::vector<AudioOutputDevice>& devs);
unsigned char *readSamples();
static void EnumerateDevices(std::vector<AudioOutputDevice> &devs);
static void* StartReceiverThread(void* output);
static void *StartReceiverThread(void *output);
void RunReceiverThread();
bool unsetOutputFile();
bool setOutputFile(const char *file);
int outputBitsPerSample;
int outputSampleRate;
int outputChannels;
int outputSamplePeriod;
int outputWritePeriod;
double outputSamplePeriodSec;
double outputWritePeriodSec;
int outputSampleNumber;
int outputSamplesSize;
size_t outputCSamplesSize;
float outputLevel = 0.0;
int outputBitsPerSample;
int outputSampleRate;
int outputChannels;
int outputSamplePeriod;
int outputWritePeriod;
double outputSamplePeriodSec;
double outputWritePeriodSec;
int outputSampleNumber;
int outputSamplesSize;
size_t outputCSamplesSize;
float outputLevel = 0.0;
private:
private:
tgvoip_thread_t receiverThread;
VoIP *wrapper;
FILE *outputFile;
tgvoip_mutex_t outputMutex;
bool configuringOutput;
};
}}
}
}
#endif //LIBTGVOIP_AUDIOOUTPUTPHP_H

106
main.cpp
View File

@ -50,6 +50,12 @@ void VoIP::initVoIPController() {
out=NULL;
inst = new VoIPController();
outputFile=NULL;
configuringOutput = false;
init_mutex(outputMutex);
init_mutex(inputMutex);
configuringInput = false;
inst->implData = (void *) this;
inst->SetStateCallback([](VoIPController *controller, int state) {
((VoIP *)controller->implData)->state = state;
@ -64,6 +70,24 @@ void VoIP::deinitVoIPController() {
if (callState != CALL_STATE_ENDED) {
callState = CALL_STATE_ENDED;
delete inst;
lock_mutex(inputMutex);
unlock_mutex(inputMutex);
free_mutex(inputMutex);
lock_mutex(outputMutex);
unlock_mutex(outputMutex);
free_mutex(outputMutex);
while (holdFiles.size()) {
fclose(holdFiles.front());
holdFiles.pop();
}
while (inputFiles.size()) {
fclose(inputFiles.front());
inputFiles.pop();
}
unsetOutputFile();
}
}
@ -244,20 +268,82 @@ void VoIP::parseConfig() {
}
}
Php::Value VoIP::setOutputFile(Php::Parameters &params) {
return out->setOutputFile(params[0]);
}
Php::Value VoIP::unsetOutputFile() {
return out->unsetOutputFile();
}
Php::Value VoIP::play(Php::Parameters &params) {
if (in->play(params[0])) {
return this;
if (outputFile == NULL) {
return false;
}
return false;
configuringOutput = true;
lock_mutex(outputMutex);
fflush(outputFile);
fclose(outputFile);
outputFile = NULL;
configuringOutput = false;
unlock_mutex(outputMutex);
return true;
}
Php::Value VoIP::setOutputFile(Php::Parameters &params) {
configuringOutput = true;
lock_mutex(outputMutex);
if (outputFile != NULL) {
fclose(outputFile);
outputFile=NULL;
}
outputFile = fopen(params[0], "wb");
if (outputFile == NULL) {
throw Php::Exception("Could not open file!");
configuringOutput = false;
unlock_mutex(outputMutex);
return false;
}
configuringOutput = false;
unlock_mutex(outputMutex);
return true;
}
Php::Value VoIP::play(Php::Parameters &params) {
FILE *tmp = fopen(params[0], "rb");
if (tmp == NULL) {
throw Php::Exception("Could not open file!");
return false;
}
configuringInput = true;
lock_mutex(inputMutex);
inputFiles.push(tmp);
configuringInput = false;
unlock_mutex(inputMutex);
return this;
}
Php::Value VoIP::playOnHold(Php::Parameters &params) {
return in->playOnHold(params);
configuringInput = true;
FILE *tmp = NULL;
lock_mutex(inputMutex);
while (holdFiles.size()) {
fclose(holdFiles.front());
holdFiles.pop();
}
for (int i = 0; i < params[0].size(); i++) {
tmp = fopen(params[0][i], "rb");
if (tmp == NULL) {
throw Php::Exception("Could not open file!");
configuringInput = false;
unlock_mutex(inputMutex);
return false;
}
holdFiles.push(tmp);
}
configuringInput = false;
unlock_mutex(inputMutex);
return true;
}
void VoIP::setMicMute(Php::Parameters &params)

10
main.h
View File

@ -104,6 +104,16 @@ public:
void parseConfig();
void parseProxyConfig();
std::queue<FILE *> inputFiles;
std::queue<FILE *> holdFiles;
tgvoip_mutex_t inputMutex;
bool configuringInput;
FILE *outputFile;
tgvoip_mutex_t outputMutex;
bool configuringOutput;
private:
int callState = CALL_STATE_NONE;
VoIPController *inst;