Clean up project.

This commit is contained in:
Michał Słomkowski 2015-11-03 02:13:15 +01:00
parent 0189d0f8ac
commit d4a01348e0
9 changed files with 116 additions and 152 deletions

View File

@ -9,12 +9,9 @@ find_package(PkgConfig REQUIRED)
pkg_check_modules(PJSIP "libpjproject") pkg_check_modules(PJSIP "libpjproject")
pkg_check_modules(LOG4CPP "log4cpp") pkg_check_modules(LOG4CPP "log4cpp")
pkg_check_modules(SNDFILE "sndfile")
include_directories(${PJSIP_INCLUDE_DIRS}) include_directories(${PJSIP_INCLUDE_DIRS})
include_directories(${LOG4CPP_INCLUDE_DIRS}) include_directories(${LOG4CPP_INCLUDE_DIRS})
include_directories(${SNDFILE_INCLUDE_DIRS})
include_directories(../mumlib/include) include_directories(../mumlib/include)
link_directories(../mumlib/build) link_directories(../mumlib/build)
@ -24,7 +21,7 @@ set(SOURCE_FILES
PjsuaCommunicator.hpp PjsuaCommunicator.hpp
MumbleCommunicator.cpp MumbleCommunicator.cpp
MumbleCommunicator.hpp MumbleCommunicator.hpp
ISamplesBuffer.hpp ICommunicator.hpp
Configuration.cpp Configuration.cpp
Configuration.hpp) Configuration.hpp)
@ -33,10 +30,8 @@ set(SOURCE_FILES
#) #)
add_executable(mumsi ${SOURCE_FILES} main.cpp) add_executable(mumsi ${SOURCE_FILES} main.cpp)
target_link_libraries(mumsi ${OPUS_LIBRARIES})
target_link_libraries(mumsi ${PJSIP_LIBRARIES}) target_link_libraries(mumsi ${PJSIP_LIBRARIES})
target_link_libraries(mumsi ${LOG4CPP_LIBRARIES}) target_link_libraries(mumsi ${LOG4CPP_LIBRARIES})
target_link_libraries(mumsi ${SNDFILE_LIBRARIES})
target_link_libraries(mumsi ${Boost_LIBRARIES}) target_link_libraries(mumsi ${Boost_LIBRARIES})
target_link_libraries(mumsi mumlib) target_link_libraries(mumsi mumlib)

View File

@ -1,5 +1,4 @@
#ifndef CONFIGURATION_HPP_ #pragma once
#define CONFIGURATION_HPP_
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
@ -35,5 +34,3 @@ namespace config {
ConfigurationImpl *impl; ConfigurationImpl *impl;
}; };
} }
#endif /* CONFIGURATION_HPP_ */

17
ICommunicator.hpp Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <functional>
#include <inttypes.h>
class ICommunicator {
public:
/**
* Send samples through the Communicator.
*/
virtual void sendPcmSamples(int16_t *samples, unsigned int length) = 0;
/**
* This callback is called when Communicator has received samples.
*/
std::function<void(int16_t *, int)> onIncomingPcmSamples;
};

View File

@ -1,14 +0,0 @@
#ifndef MUMSI_ISAMPLESBUFFER_HPP
#define MUMSI_ISAMPLESBUFFER_HPP
#include <inttypes.h>
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

View File

@ -12,22 +12,21 @@ namespace mumble {
virtual void audio( virtual void audio(
int16_t *pcm_data, int16_t *pcm_data,
uint32_t pcm_data_size) { uint32_t pcm_data_size) {
communicator->samplesBuffer.pushSamples(pcm_data, pcm_data_size); communicator->onIncomingPcmSamples(pcm_data, pcm_data_size);
} }
}; };
} }
mumble::MumbleCommunicator::MumbleCommunicator( mumble::MumbleCommunicator::MumbleCommunicator(boost::asio::io_service &ioService)
boost::asio::io_service &ioService, : ioService(ioService),
ISamplesBuffer &samplesBuffer, logger(log4cpp::Category::getInstance("MumbleCommunicator")) {
}
void mumble::MumbleCommunicator::connect(
std::string user, std::string user,
std::string password, std::string password,
std::string host, std::string host,
int port) : ioService(ioService), int port) {
samplesBuffer(samplesBuffer),
logger(log4cpp::Category::getInstance("MumbleCommunicator")) {
quit = false;
callback.reset(new MumlibCallback()); callback.reset(new MumlibCallback());
@ -38,7 +37,7 @@ mumble::MumbleCommunicator::MumbleCommunicator(
mum->connect(host, port, user, password); mum->connect(host, port, user, password);
} }
void mumble::MumbleCommunicator::sendAudioFrame(int16_t *samples, int length) { void mumble::MumbleCommunicator::sendPcmSamples(int16_t *samples, unsigned int length) {
mum->sendAudioData(samples, length); mum->sendAudioData(samples, length);
} }

View File

@ -1,14 +1,12 @@
#ifndef MUMSI_MUMBLECOMMUNICATOR_HPP #pragma once
#define MUMSI_MUMBLECOMMUNICATOR_HPP
#include "ICommunicator.hpp"
#include "ISamplesBuffer.hpp"
#include <mumlib.hpp> #include <mumlib.hpp>
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <log4cpp/Category.hh> #include <log4cpp/Category.hh>
#include <sndfile.hh>
#include <thread>
namespace mumble { namespace mumble {
@ -19,11 +17,12 @@ namespace mumble {
class MumlibCallback; class MumlibCallback;
class MumbleCommunicator { class MumbleCommunicator : public ICommunicator {
public: public:
MumbleCommunicator( MumbleCommunicator(
boost::asio::io_service &ioService, boost::asio::io_service &ioService);
ISamplesBuffer &samplesBuffer,
void connect(
std::string user, std::string user,
std::string password, std::string password,
std::string host, std::string host,
@ -31,31 +30,17 @@ namespace mumble {
~MumbleCommunicator(); ~MumbleCommunicator();
// void senderThreadFunction(); virtual void sendPcmSamples(int16_t *samples, unsigned int length);
//void receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size);
void sendAudioFrame(int16_t *samples, int length);
public: public:
boost::asio::io_service &ioService; boost::asio::io_service &ioService;
log4cpp::Category &logger; log4cpp::Category &logger;
ISamplesBuffer &samplesBuffer;
std::shared_ptr<mumlib::Mumlib> mum; std::shared_ptr<mumlib::Mumlib> mum;
std::unique_ptr<std::thread> senderThread;
SndfileHandle fileHandle;
std::unique_ptr<MumlibCallback> callback; std::unique_ptr<MumlibCallback> callback;
bool quit;
friend class MumlibCallback; friend class MumlibCallback;
}; };
} }
#endif //MUMSI_MUMBLECOMMUNICATOR_HPP

View File

@ -3,22 +3,17 @@
#include <pjlib.h> #include <pjlib.h>
#include <pjsua-lib/pjsua.h> #include <pjsua-lib/pjsua.h>
#include <boost/algorithm/string/replace.hpp>
#include <functional>
#include <cstring>
//todo wywalić
#define THIS_FILE "mumsi"
using namespace std; using namespace std;
/** /**
* This is global, because there's no way to pass it's value to onCallMediaState callback. * This is global, because there's no way to pass it's value to onCallMediaState callback.
*/ */
static int mediaPortSlot; static int mediaPortSlot;
static log4cpp::Category &pjLogger = log4cpp::Category::getInstance("PjSip");
static void onCallMediaState(pjsua_call_id call_id) { static void onCallMediaState(pjsua_call_id call_id) {
pjsua_call_info ci; pjsua_call_info ci;
@ -41,9 +36,7 @@ static void onIncomingCall(pjsua_acc_id acc_id,
pjsua_call_get_info(call_id, &ci); pjsua_call_get_info(call_id, &ci);
PJ_LOG(3, (THIS_FILE, "Incoming call from %.*s!!", pjLogger.notice("Incoming call from %s.", ci.remote_info.ptr);
(int) ci.remote_info.slen,
ci.remote_info.ptr));
/* Automatically answer incoming calls with 200/OK */ /* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL); pjsua_call_answer(call_id, 200, NULL, NULL);
@ -56,23 +49,30 @@ static void onCallState(pjsua_call_id call_id,
PJ_UNUSED_ARG(e); PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &ci); pjsua_call_get_info(call_id, &ci);
PJ_LOG(3, (THIS_FILE, "Call %d state=%.*s", call_id, pjLogger.notice("Call %d state=%s.", call_id, ci.state_text.ptr);
(int) ci.state_text.slen, }
ci.state_text.ptr));
static void pjLogToLog4CppBridgeFunction(int level, const char *data, int len) {
using namespace log4cpp;
std::map<int, Priority::Value> prioritiesMap = {
{1, Priority::ERROR},
{2, Priority::WARN},
{3, Priority::NOTICE},
{4, Priority::INFO},
{5, Priority::DEBUG},
{6, Priority::DEBUG}
};
string message(data);
message = message.substr(0, message.size() - 1); // remove newline
pjLogger << prioritiesMap.at(level) << message;
} }
sip::PjsuaCommunicator::PjsuaCommunicator() sip::PjsuaCommunicator::PjsuaCommunicator()
: logger(log4cpp::Category::getInstance("SipCommunicator")), : logger(log4cpp::Category::getInstance("SipCommunicator")),
callbackLogger(log4cpp::Category::getInstance("SipCommunicatorCallback")) { callbackLogger(log4cpp::Category::getInstance("SipCommunicatorCallback")) {
}
void sip::PjsuaCommunicator::connect(
std::string host,
std::string user,
std::string password,
unsigned int port) {
pj_status_t status; pj_status_t status;
status = pjsua_create(); status = pjsua_create();
@ -80,6 +80,8 @@ void sip::PjsuaCommunicator::connect(
throw sip::Exception("Error in pjsua_create()", status); throw sip::Exception("Error in pjsua_create()", status);
} }
pj_log_set_log_func(pjLogToLog4CppBridgeFunction);
pjsua_config generalConfig; pjsua_config generalConfig;
pjsua_config_default(&generalConfig); pjsua_config_default(&generalConfig);
@ -90,11 +92,10 @@ void sip::PjsuaCommunicator::connect(
generalConfig.cb.on_call_media_state = &onCallMediaState; generalConfig.cb.on_call_media_state = &onCallMediaState;
generalConfig.cb.on_call_state = &onCallState; generalConfig.cb.on_call_state = &onCallState;
//todo zrobić coś z logami
pjsua_logging_config logConfig; pjsua_logging_config logConfig;
pjsua_logging_config_default(&logConfig); pjsua_logging_config_default(&logConfig);
logConfig.cb = pjLogToLog4CppBridgeFunction;
logConfig.console_level = 4; logConfig.console_level = 5;
status = pjsua_init(&generalConfig, &logConfig, NULL); status = pjsua_init(&generalConfig, &logConfig, NULL);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
@ -103,7 +104,25 @@ void sip::PjsuaCommunicator::connect(
pjsua_set_null_snd_dev(); pjsua_set_null_snd_dev();
/* Add UDP transport. */ 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", 32768, 8192, nullptr);
// todo calculate sizes
pjmedia_circ_buf_create(pool, 960 * 10, &inputBuff);
mediaPort = createMediaPort();
pjsua_conf_add_port(pool, mediaPort, &mediaPortSlot);
}
void sip::PjsuaCommunicator::connect(
std::string host,
std::string user,
std::string password,
unsigned int port) {
pj_status_t status;
pjsua_transport_config transportConfig; pjsua_transport_config transportConfig;
pjsua_transport_config_default(&transportConfig); pjsua_transport_config_default(&transportConfig);
@ -114,18 +133,6 @@ void sip::PjsuaCommunicator::connect(
throw sip::Exception("Error creating transport", status); throw sip::Exception("Error creating transport", status);
} }
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", 32768, 8192, nullptr);
// create circular buffers
pjmedia_circ_buf_create(pool, 960 * 10, &inputBuff);
pjmedia_circ_buf_create(pool, 960 * 10, &outputBuff);
mediaPort = createMediaPort();
pjsua_conf_add_port(pool, mediaPort, &mediaPortSlot);
/* Initialization is done, now start sip */ /* Initialization is done, now start sip */
status = pjsua_start(); status = pjsua_start();
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
@ -210,16 +217,9 @@ pj_status_t sip::PjsuaCommunicator::mediaPortGetFrame(pjmedia_frame *frame) {
} }
void sip::PjsuaCommunicator::mediaPortPutFrame(pj_int16_t *samples, pj_size_t count) { void sip::PjsuaCommunicator::mediaPortPutFrame(pj_int16_t *samples, pj_size_t count) {
// std::unique_lock<std::mutex> lock(outBuffAccessMutex);
//
// callbackLogger.debug("Pushing %d samples to out-buff.", count);
// pjmedia_circ_buf_write(outputBuff, samples, count);
//
// lock.unlock();
//
// outBuffCondVar.notify_all();
if (count > 0) { if (count > 0) {
onIncomingSamples(samples, count); callbackLogger.debug("Calling onIncomingPcmSamples with %d samples.", count);
onIncomingPcmSamples(samples, count);
} }
} }
@ -228,7 +228,18 @@ void sip::PjsuaCommunicator::registerAccount(string host, string user, string pa
pjsua_acc_config accConfig; pjsua_acc_config accConfig;
pjsua_acc_config_default(&accConfig); pjsua_acc_config_default(&accConfig);
accConfig.id = toPjString(string("sip:") + user + "@" + host); string uri = string("sip:") + user + "@" + host;
pj_status_t status;
status = pjsua_verify_sip_url(uri.c_str());
if (status != PJ_SUCCESS) {
throw sip::Exception("failed to register account", status);
}
logger.info("Registering account for URI: %s.", uri.c_str());
accConfig.id = toPjString(uri);
accConfig.reg_uri = toPjString(string("sip:") + host); accConfig.reg_uri = toPjString(string("sip:") + host);
accConfig.cred_count = 1; accConfig.cred_count = 1;
@ -240,32 +251,14 @@ void sip::PjsuaCommunicator::registerAccount(string host, string user, string pa
pjsua_acc_id acc_id; pjsua_acc_id acc_id;
pj_status_t status = pjsua_acc_add(&accConfig, PJ_TRUE, &acc_id); status = pjsua_acc_add(&accConfig, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
throw sip::Exception("failed to register account", status); throw sip::Exception("failed to register account", status);
} }
} }
void sip::PjsuaCommunicator::pushSamples(int16_t *samples, unsigned int length) { void sip::PjsuaCommunicator::sendPcmSamples(int16_t *samples, unsigned int length) {
std::unique_lock<std::mutex> lock(inBuffAccessMutex); std::unique_lock<std::mutex> lock(inBuffAccessMutex);
callbackLogger.debug("Pushing %d samples to in-buff.", length); callbackLogger.debug("Pushing %d samples to in-buff.", length);
pjmedia_circ_buf_write(inputBuff, samples, length); pjmedia_circ_buf_write(inputBuff, samples, length);
} }
//unsigned int sip::PjsuaCommunicator::pullSamples(int16_t *samples, unsigned int length, bool waitWhenEmpty) {
// std::unique_lock<std::mutex> 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;
//}

View File

@ -1,7 +1,6 @@
#ifndef MUMSI_PJSUACOMMUNICATOR_HPP #pragma once
#define MUMSI_PJSUACOMMUNICATOR_HPP
#include "ISamplesBuffer.hpp" #include "ICommunicator.hpp"
#include <pjmedia.h> #include <pjmedia.h>
@ -44,7 +43,7 @@ namespace sip {
pj_status_t MediaPort_putFrameRawCallback(pjmedia_port *port, pjmedia_frame *frame); pj_status_t MediaPort_putFrameRawCallback(pjmedia_port *port, pjmedia_frame *frame);
class PjsuaCommunicator : public ISamplesBuffer { class PjsuaCommunicator : public ICommunicator {
public: public:
PjsuaCommunicator(); PjsuaCommunicator();
@ -56,11 +55,7 @@ namespace sip {
~PjsuaCommunicator(); ~PjsuaCommunicator();
virtual void pushSamples(int16_t *samples, unsigned int length); virtual void sendPcmSamples(int16_t *samples, unsigned int length);
std::function<void(int16_t *, int)> onIncomingSamples;
// virtual unsigned int pullSamples(int16_t *samples, unsigned int length, bool waitWhenEmpty);
private: private:
log4cpp::Category &logger; log4cpp::Category &logger;
@ -70,14 +65,9 @@ namespace sip {
pjmedia_port *mediaPort; pjmedia_port *mediaPort;
pjmedia_circ_buf *inputBuff; pjmedia_circ_buf *inputBuff;
pjmedia_circ_buf *outputBuff;
std::mutex inBuffAccessMutex; std::mutex inBuffAccessMutex;
std::mutex outBuffAccessMutex;
std::condition_variable outBuffCondVar;
// todo make it completely stateless // todo make it completely stateless
pjmedia_port *createMediaPort(); pjmedia_port *createMediaPort();
@ -101,5 +91,3 @@ namespace sip {
}; };
} }
#endif //MUMSI_PJSUACOMMUNICATOR_HPP

View File

@ -26,27 +26,31 @@ int main(int argc, char *argv[]) {
sip::PjsuaCommunicator pjsuaCommunicator; sip::PjsuaCommunicator pjsuaCommunicator;
mumble::MumbleCommunicator mumbleCommunicator( mumble::MumbleCommunicator mumbleCommunicator(ioService);
ioService,
pjsuaCommunicator, using namespace std::placeholders;
pjsuaCommunicator.onIncomingPcmSamples = std::bind(
&mumble::MumbleCommunicator::sendPcmSamples,
&mumbleCommunicator,
_1, _2);
mumbleCommunicator.onIncomingPcmSamples = std::bind(
&sip::PjsuaCommunicator::sendPcmSamples,
&pjsuaCommunicator,
_1, _2);
mumbleCommunicator.connect(
conf.getString("mumble.user"), conf.getString("mumble.user"),
conf.getString("mumble.password"), conf.getString("mumble.password"),
conf.getString("mumble.host"), conf.getString("mumble.host"),
conf.getInt("mumble.port")); conf.getInt("mumble.port"));
using namespace std::placeholders;
pjsuaCommunicator.onIncomingSamples = std::bind(
&mumble::MumbleCommunicator::sendAudioFrame,
&mumbleCommunicator,
_1, _2);
pjsuaCommunicator.connect( pjsuaCommunicator.connect(
conf.getString("sip.host"), conf.getString("sip.host"),
conf.getString("sip.user"), conf.getString("sip.user"),
conf.getString("sip.password"), conf.getString("sip.password"),
conf.getInt("sip.port")); conf.getInt("sip.port"));
logger.info("Application started."); logger.info("Application started.");
ioService.run(); ioService.run();