2015-09-27 23:25:22 +02:00
|
|
|
#ifndef MUMSI_PJSUACOMMUNICATOR_HPP
|
|
|
|
#define MUMSI_PJSUACOMMUNICATOR_HPP
|
|
|
|
|
2015-10-16 22:41:37 +02:00
|
|
|
#include "ISamplesBuffer.hpp"
|
2015-09-27 23:25:22 +02:00
|
|
|
|
|
|
|
#include <pjmedia.h>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <stdexcept>
|
2015-10-16 22:41:37 +02:00
|
|
|
#include <log4cpp/Category.hh>
|
|
|
|
#include <sndfile.hh>
|
|
|
|
#include <mutex>
|
|
|
|
#include <condition_variable>
|
2015-09-27 23:25:22 +02:00
|
|
|
|
2015-10-16 22:41:37 +02:00
|
|
|
namespace sip {
|
2015-09-27 23:25:22 +02:00
|
|
|
|
2015-10-17 22:27:37 +02:00
|
|
|
constexpr int DEFAULT_PORT = 5060;
|
2015-10-16 22:41:37 +02:00
|
|
|
constexpr int SAMPLING_RATE = 48000;
|
2015-09-27 23:25:22 +02:00
|
|
|
|
2015-10-16 22:41:37 +02:00
|
|
|
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<char *>(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 {
|
2015-09-27 23:25:22 +02:00
|
|
|
public:
|
2015-09-29 02:26:45 +02:00
|
|
|
PjsuaCommunicator(
|
|
|
|
std::string host,
|
|
|
|
std::string user,
|
2015-10-17 22:27:37 +02:00
|
|
|
std::string password,
|
|
|
|
unsigned int port = DEFAULT_PORT);
|
2015-09-27 23:25:22 +02:00
|
|
|
|
|
|
|
~PjsuaCommunicator();
|
|
|
|
|
2015-10-16 22:41:37 +02:00
|
|
|
virtual void pushSamples(int16_t *samples, unsigned int length);
|
|
|
|
|
|
|
|
virtual unsigned int pullSamples(int16_t *samples, unsigned int length, bool waitWhenEmpty);
|
2015-09-27 23:25:22 +02:00
|
|
|
|
|
|
|
private:
|
2015-10-16 22:41:37 +02:00
|
|
|
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);
|
2015-09-27 23:25:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //MUMSI_PJSUACOMMUNICATOR_HPP
|