1
0
mirror of https://github.com/danog/php-libtgvoip.git synced 2024-12-02 17:28:12 +01:00
php-libtgvoip/audio/AudioInputModule.cpp

177 lines
4.8 KiB
C++
Raw Normal View History

//
// libtgvoip is free and unencumbered public domain software.
// For more information, see http://unlicense.org or the UNLICENSE file
// you should have received with this source code distribution.
//
2017-07-04 15:50:02 +02:00
#include "AudioInputModule.h"
#include <stdio.h>
2017-06-22 14:48:52 +02:00
#include "../libtgvoip/logging.h"
2017-07-11 21:11:23 +02:00
#include <queue>
2017-07-13 18:03:33 +02:00
#include <unistd.h>
#include <phpcpp.h>
using namespace tgvoip;
using namespace tgvoip::audio;
2017-07-13 18:03:33 +02:00
AudioInputModule::AudioInputModule(std::string deviceID, VoIPController *controller)
2017-07-09 21:12:01 +02:00
{
2017-07-13 18:03:33 +02:00
wrapper = (VoIP *)(controller->implData);
2017-07-10 12:30:13 +02:00
wrapper->in = this;
2017-07-13 18:03:33 +02:00
wrapper->inputState = AUDIO_STATE_CREATED;
init_mutex(inputMutex);
configuringInput = false;
}
2017-07-09 21:12:01 +02:00
AudioInputModule::~AudioInputModule()
{
2017-07-13 18:03:33 +02:00
wrapper->inputState = AUDIO_STATE_NONE;
2017-07-10 12:30:13 +02:00
wrapper->in = NULL;
2017-07-13 18:03:33 +02:00
2017-07-18 19:16:27 +02:00
if (senderThread) {
LOGD("before join senderThread");
join_thread(senderThread);
}
2017-07-13 18:03:33 +02:00
while (holdFiles.size()) {
fclose(holdFiles.front());
holdFiles.pop();
}
while (inputFiles.size()) {
fclose(inputFiles.front());
inputFiles.pop();
}
free_mutex(inputMutex);
}
2017-06-28 21:02:15 +02:00
2017-07-09 21:12:01 +02:00
void AudioInputModule::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels)
{
2017-07-11 21:11:23 +02:00
inputSampleNumber = 960;
inputSampleRate = sampleRate;
inputBitsPerSample = bitsPerSample;
inputChannels = channels;
inputSamplePeriod = 1.0 / sampleRate * 1000000;
inputWritePeriod = 1.0 / sampleRate * inputSampleNumber * 1000000;
inputSamplePeriodSec = 1.0 / sampleRate;
inputWritePeriodSec = 1.0 / sampleRate * inputSampleNumber;
inputSamplesSize = inputSampleNumber * inputChannels * inputBitsPerSample / 8;
inputCSamplesSize = inputSampleNumber * inputChannels * inputBitsPerSample / 8 * sizeof(unsigned char);
2017-06-28 21:02:15 +02:00
2017-07-13 18:03:33 +02:00
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;
}
2017-07-13 18:03:33 +02:00
2017-07-09 21:12:01 +02:00
void AudioInputModule::Start()
{
2017-07-13 18:03:33 +02:00
if (wrapper->inputState == AUDIO_STATE_RUNNING)
2017-06-19 15:39:45 +02:00
return;
2017-07-13 18:03:33 +02:00
wrapper->inputState = AUDIO_STATE_RUNNING;
2017-07-11 21:11:23 +02:00
LOGE("STARTING SENDER THREAD");
start_thread(senderThread, StartSenderThread, this);
set_thread_priority(senderThread, get_thread_max_priority());
set_thread_name(senderThread, "voip-sender");
2017-07-13 18:03:33 +02:00
}
2017-07-09 21:12:01 +02:00
void AudioInputModule::Stop()
{
2017-07-13 18:03:33 +02:00
if (wrapper->inputState != AUDIO_STATE_RUNNING)
2017-07-10 00:06:50 +02:00
return;
2017-07-13 18:03:33 +02:00
wrapper->inputState = AUDIO_STATE_CONFIGURED;
}
2017-07-11 21:11:23 +02:00
2017-07-13 18:03:33 +02:00
2017-07-11 21:11:23 +02:00
void* AudioInputModule::StartSenderThread(void* input){
((AudioInputModule*)input)->RunSenderThread();
return NULL;
2017-06-19 23:38:03 +02:00
}
2017-07-04 15:50:02 +02:00
2017-07-11 21:11:23 +02:00
void AudioInputModule::RunSenderThread() {
unsigned char *data = (unsigned char *) malloc(inputCSamplesSize);
size_t read;
double time = VoIPController::GetCurrentTime();
2017-07-13 18:03:33 +02:00
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) {
LOGE("Sender: I'm late!");
} else {
usleep(sleeptime);
}
2017-07-11 21:11:23 +02:00
time = VoIPController::GetCurrentTime();
2017-07-13 18:03:33 +02:00
if (!inputFiles.empty()) {
if ((read = fread(data, sizeof(unsigned char), inputSamplesSize, inputFiles.front())) != inputCSamplesSize) {
fclose(inputFiles.front());
inputFiles.pop();
2017-07-11 21:11:23 +02:00
memset(data + (read % inputCSamplesSize), 0, inputCSamplesSize - (read % inputCSamplesSize));
}
2017-07-13 18:54:59 +02:00
wrapper->playing = true;
2017-07-11 21:11:23 +02:00
} else {
2017-07-13 18:54:59 +02:00
wrapper->playing = false;
2017-07-13 18:03:33 +02:00
if (holdFiles.empty()) {
2017-07-11 21:11:23 +02:00
memset(data, 0, inputCSamplesSize);
} else {
2017-07-13 18:03:33 +02:00
if ((read = fread(data, sizeof(unsigned char), inputSamplesSize, holdFiles.front())) != inputCSamplesSize) {
fseek(holdFiles.front(), 0, SEEK_SET);
holdFiles.push(holdFiles.front());
holdFiles.pop();
2017-07-11 21:11:23 +02:00
memset(data + (read % inputCSamplesSize), 0, inputCSamplesSize - (read % inputCSamplesSize));
}
}
}
InvokeCallback(data, inputCSamplesSize);
}
2017-07-13 18:03:33 +02:00
unlock_mutex(inputMutex);
2017-07-11 21:11:23 +02:00
}
free(data);
2017-07-13 18:03:33 +02:00
}
2017-07-11 21:11:23 +02:00
2017-07-09 21:12:01 +02:00
void AudioInputModule::EnumerateDevices(std::vector<AudioInputDevice> &devs)
{
2017-07-04 15:50:02 +02:00
}