diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..249963d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.iml +.idea/ \ No newline at end of file diff --git a/AbstractCommunicator.hpp b/AbstractCommunicator.hpp deleted file mode 100644 index e0c2a77..0000000 --- a/AbstractCommunicator.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MUMSI_ABSTRACTCOMMUNICATOR_HPP -#define MUMSI_ABSTRACTCOMMUNICATOR_HPP - -#include "SoundSampleQueue.hpp" -#include - -#define SOUND_SAMPLE_TYPE int16_t - -class AbstractCommunicator { -public: - - virtual void loop() = 0; - -protected: - AbstractCommunicator( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue) - : inputQueue(inputQueue), - outputQueue(outputQueue) { } - - SoundSampleQueue &inputQueue; - SoundSampleQueue &outputQueue; -}; - -#endif //MUMSI_ABSTRACTCOMMUNICATOR_HPP diff --git a/CMakeLists.txt b/CMakeLists.txt index f10d875..c39653c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,15 +23,14 @@ link_directories(libmumble) set(SOURCE_FILES PjsuaCommunicator.cpp - PjsuaMediaPort.cpp + PjsuaCommunicator.hpp MumbleCommunicator.cpp - SoundSampleQueue.cpp - AbstractCommunicator.hpp -) + MumbleCommunicator.hpp + ISamplesBuffer.hpp) -set(TEST_SOURCE_FILES - SoundSampleQueueTest.cpp -) +#set(TEST_SOURCE_FILES +# SoundSampleQueueTest.cpp +#) add_executable(mumsi ${SOURCE_FILES} main.cpp) target_link_libraries(mumsi ${OPUS_LIBRARIES}) @@ -41,10 +40,10 @@ target_link_libraries(mumsi ${SNDFILE_LIBRARIES}) target_link_libraries(mumsi ${Boost_LIBRARIES}) target_link_libraries(mumsi mumble) -add_executable(mumsi_test ${SOURCE_FILES} ${TEST_SOURCE_FILES} test_main.cpp) -target_link_libraries(mumsi_test ${OPUS_LIBRARIES}) -target_link_libraries(mumsi_test ${PJSIP_LIBRARIES}) -target_link_libraries(mumsi_test ${LOG4CPP_LIBRARIES}) -target_link_libraries(mumsi_test ${SNDFILE_LIBRARIES}) -target_link_libraries(mumsi_test ${Boost_LIBRARIES}) -target_link_libraries(mumsi_test mumble) +#add_executable(mumsi_test ${SOURCE_FILES} ${TEST_SOURCE_FILES} test_main.cpp) +#target_link_libraries(mumsi_test ${OPUS_LIBRARIES}) +#target_link_libraries(mumsi_test ${PJSIP_LIBRARIES}) +#target_link_libraries(mumsi_test ${LOG4CPP_LIBRARIES}) +#target_link_libraries(mumsi_test ${SNDFILE_LIBRARIES}) +#target_link_libraries(mumsi_test ${Boost_LIBRARIES}) +#target_link_libraries(mumsi_test mumble) diff --git a/ISamplesBuffer.hpp b/ISamplesBuffer.hpp new file mode 100644 index 0000000..6c0b2e4 --- /dev/null +++ b/ISamplesBuffer.hpp @@ -0,0 +1,14 @@ +#ifndef MUMSI_ISAMPLESBUFFER_HPP +#define MUMSI_ISAMPLESBUFFER_HPP + +#include + +class ISamplesBuffer { +public: + virtual void pushSamples(int16_t *samples, unsigned int length) = 0; + + virtual unsigned int pullSamples(int16_t *samples, unsigned int length, bool waitWhenEmpty) = 0; +}; + + +#endif //MUMSI_ISAMPLESBUFFER_HPP diff --git a/MumbleCommunicator.cpp b/MumbleCommunicator.cpp index 2fceb36..0e2a05c 100644 --- a/MumbleCommunicator.cpp +++ b/MumbleCommunicator.cpp @@ -37,7 +37,7 @@ void mumble::MumbleCommunicator::receiveAudioFrameCallback(uint8_t *audio_data, logger.debug("Received %d bytes of Opus data (seq %ld), decoded to %d bytes. Push it to outputQueue.", opusDataLength, sequenceNumber, decodedSamples); - outputQueue.push_back(pcmData, decodedSamples); + samplesBuffer.pushSamples(pcmData, decodedSamples); } else { logger.warn("Received %d bytes of non-recognisable audio data.", audio_data_size); @@ -63,15 +63,16 @@ static int verify_cert(uint8_t *, uint32_t) { } mumble::MumbleCommunicator::MumbleCommunicator( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue, + ISamplesBuffer &samplesBuffer, std::string user, std::string password, std::string host, - int port) : AbstractCommunicator(inputQueue, outputQueue), + int port) : samplesBuffer(samplesBuffer), outgoingAudioSequenceNumber(1), logger(log4cpp::Category::getInstance("MumbleCommunicator")) { + quit = false; + opusDecoder = opus_decoder_create(SAMPLE_RATE, 1, nullptr); //todo grab error opusEncoder = opus_encoder_create(SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, nullptr); @@ -110,31 +111,12 @@ mumble::MumbleCommunicator::~MumbleCommunicator() { } void mumble::MumbleCommunicator::loop() { - int quit = 0; - while (quit == 0) { - opus_int16 pcmData[1024]; - unsigned char outputBuffer[1024]; -// int pcmLength = inputQueue.pop(pcmData, 960); -// -// logger.debug("Pop %d samples from inputQueue.", pcmLength); -// -// if (pcmLength > 0) { -// int encodedSamples = opus_encode(opusEncoder, pcmData, pcmLength, outputBuffer, sizeof(outputBuffer)); -// -// if (encodedSamples < 1) { -// logger.warn("opus_encode returned %d: %s", encodedSamples, opus_strerror(encodedSamples)); -// } else { -// logger.debug("Sending %d bytes of Opus audio data (seq %d).", encodedSamples, -// outgoingAudioSequenceNumber); -// -// mumble_send_audio_data(mumble, outgoingAudioSequenceNumber, outputBuffer, encodedSamples); -// -// outgoingAudioSequenceNumber += 1; -// } -// } + senderThread.reset(new std::thread(&MumbleCommunicator::senderThreadFunction, this)); + while (!quit) { int status = mumble_tick(mumble); + logger.debug("tick"); if (status < 0) { throw mumble::Exception("mumble_tick status " + status); } @@ -144,3 +126,27 @@ void mumble::MumbleCommunicator::loop() { } +void mumble::MumbleCommunicator::senderThreadFunction() { + while (!quit) { + opus_int16 pcmData[1024]; + unsigned char outputBuffer[1024]; + + int pcmLength = samplesBuffer.pullSamples(pcmData, 960, true); + + logger.debug("Pop %d samples from inputQueue.", pcmLength); + + int encodedSamples = opus_encode(opusEncoder, pcmData, pcmLength, outputBuffer, sizeof(outputBuffer)); + + if (encodedSamples < 1) { + logger.warn("opus_encode returned %d: %s", encodedSamples, opus_strerror(encodedSamples)); + } else { +// logger.debug("Sending %d bytes of Opus audio data (seq %d).", encodedSamples, +// outgoingAudioSequenceNumber); +// +// //todo to powinno dać się bezpiecznie wykonać w osobnym wątku +// mumble_send_audio_data(mumble, outgoingAudioSequenceNumber, outputBuffer, encodedSamples); +// +// outgoingAudioSequenceNumber += 1; + } + } +} diff --git a/MumbleCommunicator.hpp b/MumbleCommunicator.hpp index 04eb686..783f91b 100644 --- a/MumbleCommunicator.hpp +++ b/MumbleCommunicator.hpp @@ -1,7 +1,7 @@ #ifndef MUMSI_MUMBLECOMMUNICATOR_HPP #define MUMSI_MUMBLECOMMUNICATOR_HPP -#include "AbstractCommunicator.hpp" +#include "ISamplesBuffer.hpp" extern "C" { #include "libmumble.h" @@ -12,6 +12,7 @@ extern "C" { #include #include #include +#include namespace mumble { @@ -22,11 +23,10 @@ namespace mumble { Exception(const char *message) : std::runtime_error(message) { } }; - class MumbleCommunicator : public AbstractCommunicator { + class MumbleCommunicator { public: MumbleCommunicator( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue, + ISamplesBuffer &samplesBuffer, std::string user, std::string password, std::string host, @@ -36,11 +36,17 @@ namespace mumble { void loop(); + void senderThreadFunction(); + void receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size); private: log4cpp::Category &logger; + ISamplesBuffer &samplesBuffer; + + std::unique_ptr senderThread; + mumble_struct *mumble; OpusDecoder *opusDecoder; OpusEncoder *opusEncoder; @@ -48,6 +54,8 @@ namespace mumble { int outgoingAudioSequenceNumber; SndfileHandle fileHandle; + + bool quit; }; } diff --git a/PjsuaCommunicator.cpp b/PjsuaCommunicator.cpp index cc7d86c..d3a19eb 100644 --- a/PjsuaCommunicator.cpp +++ b/PjsuaCommunicator.cpp @@ -6,6 +6,8 @@ #include +#include + //todo wywalić #define THIS_FILE "mumsi" @@ -59,28 +61,24 @@ static void onCallState(pjsua_call_id call_id, ci.state_text.ptr)); } - -pjsua::PjsuaCommunicator::PjsuaCommunicator( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue, +sip::PjsuaCommunicator::PjsuaCommunicator( std::string host, std::string user, - std::string password) - : AbstractCommunicator(inputQueue, outputQueue), - mediaPort(inputQueue, outputQueue) { + std::string password) : logger(log4cpp::Category::getInstance("SipCommunicator")), + callbackLogger(log4cpp::Category::getInstance("SipCommunicatorCallback")) { pj_status_t status; status = pjsua_create(); if (status != PJ_SUCCESS) { - throw pjsua::Exception("Error in pjsua_create()", status); + throw sip::Exception("Error in pjsua_create()", status); } - /* Init pjsua */ pjsua_config generalConfig; pjsua_config_default(&generalConfig); - using namespace std::placeholders; + generalConfig.user_agent = toPjString("Mumsi Mumble-SIP Bridge"); + generalConfig.max_calls = 1; generalConfig.cb.on_incoming_call = &onIncomingCall; generalConfig.cb.on_call_media_state = &onCallMediaState; @@ -94,37 +92,128 @@ pjsua::PjsuaCommunicator::PjsuaCommunicator( status = pjsua_init(&generalConfig, &logConfig, NULL); if (status != PJ_SUCCESS) { - throw pjsua::Exception("Error in pjsua_init()", status); + throw sip::Exception("Error in pjsua_init()", status); } + pjsua_set_null_snd_dev(); + /* Add UDP transport. */ pjsua_transport_config transportConfig; pjsua_transport_config_default(&transportConfig); - transportConfig.port = pjsua::SIP_PORT; + transportConfig.port = sip::SIP_PORT; status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &transportConfig, NULL); if (status != PJ_SUCCESS) { - throw pjsua::Exception("Error creating transport", status); + throw sip::Exception("Error creating transport", status); } - pjsua_set_null_snd_dev(); - pj_caching_pool cachingPool; pj_caching_pool_init(&cachingPool, &pj_pool_factory_default_policy, 0); - pj_pool_t *pool = pj_pool_create(&cachingPool.factory, "wav", 4096, 4096, nullptr); + pj_pool_t *pool = pj_pool_create(&cachingPool.factory, "wav", 32768, 8192, nullptr); - pjsua_conf_add_port(pool, mediaPort.create_pjmedia_port(), &mediaPortSlot); + // create circular buffers + pjmedia_circ_buf_create(pool, 960 * 10, &inputBuff); + pjmedia_circ_buf_create(pool, 960 * 10, &outputBuff); - /* Initialization is done, now start pjsua */ + mediaPort = createMediaPort(); + + pjsua_conf_add_port(pool, mediaPort, &mediaPortSlot); + + /* Initialization is done, now start sip */ status = pjsua_start(); if (status != PJ_SUCCESS) { - throw pjsua::Exception("Error starting pjsua", status); + throw sip::Exception("Error starting sip", status); } - /* Register to SIP server by creating SIP account. */ - pjsua_acc_config accConfig; + registerAccount(host, user, password); +} +sip::PjsuaCommunicator::~PjsuaCommunicator() { + pjsua_destroy(); +} + +pjmedia_port *sip::PjsuaCommunicator::createMediaPort() { + + pjmedia_port *mp = new pjmedia_port(); + + pj_str_t name = toPjString("Pjsuamp"); + + pj_status_t status = pjmedia_port_info_init(&(mp->info), + &name, + PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'), + SAMPLING_RATE, + 1, + 16, + SAMPLING_RATE * 20 / 1000); // todo recalculate to match mumble specs + + if (status != PJ_SUCCESS) { + throw sip::Exception("error while calling pjmedia_port_info_init().", status); + } + + mp->get_frame = &MediaPort_getFrameRawCallback; + mp->put_frame = &MediaPort_putFrameRawCallback; + + mp->port_data.pdata = this; + + return mp; +} + +pj_status_t sip::MediaPort_getFrameRawCallback(pjmedia_port *port, + pjmedia_frame *frame) { + PjsuaCommunicator *communicator = static_cast(port->port_data.pdata); + frame->type = PJMEDIA_FRAME_TYPE_AUDIO; + + return communicator->mediaPortGetFrame(frame); +} + +pj_status_t sip::MediaPort_putFrameRawCallback(pjmedia_port *port, + pjmedia_frame *frame) { + PjsuaCommunicator *communicator = static_cast(port->port_data.pdata); + pj_int16_t *samples = static_cast(frame->buf); + pj_size_t count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info); + frame->type = PJMEDIA_FRAME_TYPE_AUDIO; + + communicator->mediaPortPutFrame(samples, count); + + return PJ_SUCCESS; +} + +pj_status_t sip::PjsuaCommunicator::mediaPortGetFrame(pjmedia_frame *frame) { + std::unique_lock lock(inBuffAccessMutex); + + pj_int16_t *samples = static_cast(frame->buf); + pj_size_t count = frame->size / 2 / PJMEDIA_PIA_CCNT(&mediaPort->info); + + pj_size_t availableSamples = pjmedia_circ_buf_get_len(inputBuff); + const int samplesToRead = std::min(count, availableSamples); + + callbackLogger.debug("Pulling %d samples from in-buff.", samplesToRead); + pjmedia_circ_buf_read(inputBuff, samples, samplesToRead); + + if (availableSamples < count) { + callbackLogger.debug("Requested %d samples, available %d, filling remaining with zeros.", count, + availableSamples); + std::memset(&(samples[availableSamples]), 0, sizeof(pj_int16_t) * (count - availableSamples)); + } + + return PJ_SUCCESS; +} + +void sip::PjsuaCommunicator::mediaPortPutFrame(pj_int16_t *samples, pj_size_t count) { + std::unique_lock lock(outBuffAccessMutex); + + callbackLogger.debug("Pushing %d samples to out-buff.", count); + pjmedia_circ_buf_write(outputBuff, samples, count); + + lock.unlock(); + + outBuffCondVar.notify_all(); +} + +void sip::PjsuaCommunicator::registerAccount(string host, string user, string password) { + + pjsua_acc_config accConfig; pjsua_acc_config_default(&accConfig); accConfig.id = toPjString(string("sip:") + user + "@" + host); @@ -138,16 +227,33 @@ pjsua::PjsuaCommunicator::PjsuaCommunicator( accConfig.cred_info[0].data = toPjString(password); pjsua_acc_id acc_id; - status = pjsua_acc_add(&accConfig, PJ_TRUE, &acc_id); + + pj_status_t status = pjsua_acc_add(&accConfig, PJ_TRUE, &acc_id); if (status != PJ_SUCCESS) { - throw pjsua::Exception("Error adding account", status); + throw sip::Exception("failed to register account", status); } } -pjsua::PjsuaCommunicator::~PjsuaCommunicator() { - pjsua_destroy(); +void sip::PjsuaCommunicator::pushSamples(int16_t *samples, unsigned int length) { + std::unique_lock lock(inBuffAccessMutex); + callbackLogger.debug("Pushing %d samples to in-buff.", length); + pjmedia_circ_buf_write(inputBuff, samples, length); } -void pjsua::PjsuaCommunicator::loop() { +unsigned int sip::PjsuaCommunicator::pullSamples(int16_t *samples, unsigned int length, bool waitWhenEmpty) { + std::unique_lock lock(outBuffAccessMutex); + unsigned int availableSamples; + + while ((availableSamples = pjmedia_circ_buf_get_len(inputBuff)) < length) { + callbackLogger.debug("Not enough samples in buffer: %d, requested %d. Waiting.", availableSamples, length); + outBuffCondVar.wait(lock); + } + + const int samplesToRead = std::min(length, availableSamples); + + callbackLogger.debug("Pulling %d samples from out-buff.", samplesToRead); + pjmedia_circ_buf_read(inputBuff, samples, samplesToRead); + + return samplesToRead; } diff --git a/PjsuaCommunicator.hpp b/PjsuaCommunicator.hpp index 8391eb6..f8f2b14 100644 --- a/PjsuaCommunicator.hpp +++ b/PjsuaCommunicator.hpp @@ -1,33 +1,97 @@ #ifndef MUMSI_PJSUACOMMUNICATOR_HPP #define MUMSI_PJSUACOMMUNICATOR_HPP -#include "PjsuaMediaPort.hpp" -#include "AbstractCommunicator.hpp" +#include "ISamplesBuffer.hpp" #include #include #include +#include +#include +#include +#include -namespace pjsua { +namespace sip { constexpr int SIP_PORT = 5060; + constexpr int SAMPLING_RATE = 48000; - class PjsuaCommunicator : public AbstractCommunicator { + class Exception : public std::runtime_error { + public: + Exception(const char *title, pj_status_t status) : std::runtime_error(title) { + char errorMsgBuffer[500]; + pj_strerror(status, errorMsgBuffer, sizeof(errorMsgBuffer)); + + mesg += title; + mesg += ": "; + mesg += errorMsgBuffer; + } + + virtual const char *what() const throw() { + return mesg.c_str(); + } + + private: + std::string mesg; + }; + + inline pj_str_t toPjString(std::string str) { + return pj_str(const_cast(str.c_str())); + } + + pj_status_t MediaPort_getFrameRawCallback(pjmedia_port *port, pjmedia_frame *frame); + + pj_status_t MediaPort_putFrameRawCallback(pjmedia_port *port, pjmedia_frame *frame); + + class PjsuaCommunicator : public ISamplesBuffer { public: PjsuaCommunicator( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue, std::string host, std::string user, std::string password); ~PjsuaCommunicator(); - void loop(); + virtual void pushSamples(int16_t *samples, unsigned int length); + + virtual unsigned int pullSamples(int16_t *samples, unsigned int length, bool waitWhenEmpty); private: - PjsuaMediaPort mediaPort; + log4cpp::Category &logger; + log4cpp::Category &callbackLogger; + + + pjmedia_port *mediaPort; + + pjmedia_circ_buf *inputBuff; + pjmedia_circ_buf *outputBuff; + + std::mutex inBuffAccessMutex; + + std::mutex outBuffAccessMutex; + std::condition_variable outBuffCondVar; + + // todo make it completely stateless + pjmedia_port *createMediaPort(); + + void registerAccount(std::string host, + std::string user, + std::string password); + + pj_status_t mediaPortGetFrame(pjmedia_frame *frame); + + void mediaPortPutFrame(pj_int16_t *samples, pj_size_t count); + + /** + * For PJMEDIA implementation reasons, these callbacks have to be functions, not methods. + * That is the reason to use 'friend'. + */ + friend pj_status_t MediaPort_getFrameRawCallback(pjmedia_port *port, + pjmedia_frame *frame); + + friend pj_status_t MediaPort_putFrameRawCallback(pjmedia_port *port, + pjmedia_frame *frame); }; } diff --git a/PjsuaMediaPort.cpp b/PjsuaMediaPort.cpp deleted file mode 100644 index 6d73a39..0000000 --- a/PjsuaMediaPort.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "PjsuaMediaPort.hpp" - -using namespace std; -using namespace pjsua; - - -pj_status_t pjsua::MediaPort_getFrame(pjmedia_port *port, - pjmedia_frame *frame) { - PjsuaMediaPort *mediaPort = static_cast(port->port_data.pdata); - pj_int16_t *samples = static_cast(frame->buf); - pj_size_t count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info); - - int takenSamples = mediaPort->inputQueue.pop_front(samples, count); - - mediaPort->fileHandle.write(samples, takenSamples); - - mediaPort->logger.debug("Pop %d samples from inputQueue.", takenSamples); - - for (int i = takenSamples; i < count; ++i) { - samples[i] = 0; - } - - // todo wrzucić sample do wav - - frame->type = PJMEDIA_FRAME_TYPE_AUDIO; - - return PJ_SUCCESS; -} - -pj_status_t pjsua::MediaPort_putFrame(pjmedia_port *port, - pjmedia_frame *frame) { - PjsuaMediaPort *mediaPort = static_cast(port->port_data.pdata); - pj_int16_t *samples = static_cast(frame->buf); - pj_size_t count = frame->size / 2 / PJMEDIA_PIA_CCNT(&port->info); - -// if (count > 0) { -// mediaPort->outputQueue.push_back(samples, count); -// -// mediaPort->logger.debug("Push %d samples into outputQueue.", count); -// } - - return PJ_SUCCESS; -} - -PjsuaMediaPort::PjsuaMediaPort( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue) - : inputQueue(inputQueue), - outputQueue(outputQueue), - _pjmedia_port(nullptr), - logger(log4cpp::Category::getInstance("PjsuaMediaPort")) { - - fileHandle = SndfileHandle("capture_pjsua.wav", SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 1, SAMPLING_RATE); -} - -pjmedia_port *pjsua::PjsuaMediaPort::create_pjmedia_port() { - - _pjmedia_port = new pjmedia_port(); - - pj_str_t name = toPjString("PjsuaMediaPort"); - - pj_status_t status = pjmedia_port_info_init(&(_pjmedia_port->info), - &name, - PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'), - SAMPLING_RATE, - 1, - 16, - SAMPLING_RATE * 20 / 1000); // todo recalculate to match mumble specs - - if (status != PJ_SUCCESS) { - throw pjsua::Exception("Error while calling pjmedia_port_info_init().", status); - } - - _pjmedia_port->get_frame = &MediaPort_getFrame; - _pjmedia_port->put_frame = &MediaPort_putFrame; - - _pjmedia_port->port_data.pdata = this; - - return _pjmedia_port; -} - -pjsua::PjsuaMediaPort::~PjsuaMediaPort() { - if (this->_pjmedia_port != nullptr) { - delete _pjmedia_port; - } -} \ No newline at end of file diff --git a/PjsuaMediaPort.hpp b/PjsuaMediaPort.hpp deleted file mode 100644 index f9a3697..0000000 --- a/PjsuaMediaPort.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef MUMSI_PJSUAMEDIAPORT_HPP -#define MUMSI_PJSUAMEDIAPORT_HPP - -//todo wywalić i wrzucić do nagłówka z definicjami -#include "AbstractCommunicator.hpp" - -#include -#include - -#include - -#include -#include - -namespace pjsua { - - constexpr int SAMPLING_RATE = 48000; - - inline pj_str_t toPjString(std::string str) { - return pj_str(const_cast(str.c_str())); - } - - class Exception : public std::runtime_error { - public: - Exception(const char *title, pj_status_t status) : std::runtime_error(title) { - //todo status code - } - }; - - pj_status_t MediaPort_getFrame(pjmedia_port *port, pjmedia_frame *frame); - - pj_status_t MediaPort_putFrame(pjmedia_port *port, pjmedia_frame *frame); - - class PjsuaMediaPort { - public: - - PjsuaMediaPort( - SoundSampleQueue &inputQueue, - SoundSampleQueue &outputQueue); - - ~PjsuaMediaPort(); - - pjmedia_port *create_pjmedia_port(); - - - private: - log4cpp::Category &logger; - - SoundSampleQueue &inputQueue; - SoundSampleQueue &outputQueue; - - pjmedia_port *_pjmedia_port; - - SndfileHandle fileHandle; - - /** - * For PJSUA implementation reasons, these callbacks have to be functions, not methods. - * Since 'friend' usage. - */ - friend pj_status_t MediaPort_getFrame(pjmedia_port *port, - pjmedia_frame *frame); - - friend pj_status_t MediaPort_putFrame(pjmedia_port *port, - pjmedia_frame *frame); - }; -} - -#endif //MUMSI_PJSUAMEDIAPORT_HPP diff --git a/SoundSampleQueue.cpp b/SoundSampleQueue.cpp deleted file mode 100644 index 83fee88..0000000 --- a/SoundSampleQueue.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// -// Created by michal on 28.09.15. -// - -#include "SoundSampleQueue.hpp" - diff --git a/SoundSampleQueue.hpp b/SoundSampleQueue.hpp deleted file mode 100644 index 7ea98da..0000000 --- a/SoundSampleQueue.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef MUMSI_SOUNDSAMPLEQUEUE_HPP -#define MUMSI_SOUNDSAMPLEQUEUE_HPP - -#include -#include -#include -#include - -template -class SoundSampleQueue { -public: - SoundSampleQueue() - : start(0), - stop(0) { - buffer = new SAMPLE_TYPE[10000000]; - } - - ~SoundSampleQueue() { - delete[] buffer; - } - - void push_back(SAMPLE_TYPE *data, int length) { - std::lock_guard lock(accessMutex); - - for (int i = 0; i < length; ++i) { - buffer[stop + i] = data[i]; - } - - stop += length; - } - - int pop_front(SAMPLE_TYPE *data, int maxLength) { - std::lock_guard lock(accessMutex); - - int samplesToTake = std::min(stop - start, maxLength); - - for (int i = 0; i < samplesToTake; ++i) { - data[i] = buffer[start + i]; - } - start += samplesToTake; - - return samplesToTake; - } - -private: - int start; - int stop; - - std::mutex accessMutex; - - SAMPLE_TYPE *buffer; -}; - - -#endif //MUMSI_SOUNDSAMPLEQUEUE_HPP diff --git a/SoundSampleQueueTest.cpp b/SoundSampleQueueTest.cpp deleted file mode 100644 index c3d7220..0000000 --- a/SoundSampleQueueTest.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "SoundSampleQueue.hpp" - -#include - -constexpr int CHUNK = 10; - -BOOST_AUTO_TEST_CASE(SoundSampleQueueTest_Run) { - - SoundSampleQueue queue; - - int16_t buffer[CHUNK]; - - int content = 0; - for (int j = 0; j < 10; ++j) { - for (int i = 0; i < CHUNK; ++i) { - buffer[i] = content; - content++; - } - queue.push_back(buffer, CHUNK); - } - - for (int j = 0; j < 12; ++j) { - int how_many = queue.pop_front(buffer, CHUNK); - - printf("%d: ", how_many); - for (int i = 0; i < CHUNK; ++i) { - printf("%d ", buffer[i]); - } - printf("\n"); - } - - BOOST_CHECK_EQUAL(1, 1); -} \ No newline at end of file diff --git a/libmumble b/libmumble index 584f353..15ad984 160000 --- a/libmumble +++ b/libmumble @@ -1 +1 @@ -Subproject commit 584f3533384d7d3b47856d5ffc270f39f353040f +Subproject commit 15ad9844680e44d32995bf8ed6858fe75fae737f diff --git a/main.cpp b/main.cpp index 93e2eee..48e4118 100644 --- a/main.cpp +++ b/main.cpp @@ -1,16 +1,10 @@ #include "log4cpp/Category.hh" -#include "log4cpp/Appender.hh" #include "log4cpp/FileAppender.hh" #include "log4cpp/OstreamAppender.hh" -#include "log4cpp/Layout.hh" -#include "log4cpp/BasicLayout.hh" -#include "log4cpp/Priority.hh" #include "PjsuaCommunicator.hpp" #include "MumbleCommunicator.hpp" -#include "SoundSampleQueue.hpp" - #define SIP_DOMAIN "sip.antisip.com" #define SIP_USER "melangtone" #define SIP_PASSWD "b8DU9AZXbd9tVCWg" @@ -24,28 +18,22 @@ int main(int argc, char *argv[]) { log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout); appender1->setLayout(new log4cpp::BasicLayout()); log4cpp::Category &logger = log4cpp::Category::getRoot(); - logger.setPriority(log4cpp::Priority::DEBUG); + logger.setPriority(log4cpp::Priority::NOTICE); logger.addAppender(appender1); - SoundSampleQueue mumbleToSipQueue; - SoundSampleQueue sipToMumbleQueue; + + sip::PjsuaCommunicator pjsuaCommunicator( + SIP_DOMAIN, SIP_USER, SIP_PASSWD); mumble::MumbleCommunicator mumbleCommunicator( - sipToMumbleQueue, - mumbleToSipQueue, + pjsuaCommunicator, MUMBLE_USER, MUMBLE_PASSWD, MUMBLE_DOMAIN); - pjsua::PjsuaCommunicator pjsuaCommunicator( - mumbleToSipQueue, - sipToMumbleQueue, - SIP_DOMAIN, SIP_USER, SIP_PASSWD); - logger.info("Application started."); - pjsuaCommunicator.loop(); - mumbleCommunicator.loop(); + return 0; } diff --git a/test_main.cpp b/test_main.cpp deleted file mode 100644 index 03e1944..0000000 --- a/test_main.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#define BOOST_TEST_MODULE SZARKServerTest -#define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MAIN - -#include