mirror of
https://github.com/danog/php-libtgvoip.git
synced 2024-11-30 04:19:26 +01:00
done
This commit is contained in:
parent
ba582a826d
commit
a17113448a
@ -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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
|
@ -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 ¶ms);
|
||||
|
||||
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:
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
106
main.cpp
@ -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 ¶ms) {
|
||||
return out->setOutputFile(params[0]);
|
||||
}
|
||||
|
||||
Php::Value VoIP::unsetOutputFile() {
|
||||
return out->unsetOutputFile();
|
||||
}
|
||||
Php::Value VoIP::play(Php::Parameters ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms)
|
||||
|
10
main.h
10
main.h
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user