diff --git a/.gitignore b/.gitignore index 417c574..15d3321 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.iml .idea/ -config.ini \ No newline at end of file +config.ini + +build/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f2ec93..5de41e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,19 +7,17 @@ INCLUDE(FindPkgConfig) find_package(Boost COMPONENTS system unit_test_framework program_options filesystem REQUIRED) find_package(PkgConfig REQUIRED) -pkg_check_modules(OPUS "opus") pkg_check_modules(PJSIP "libpjproject") pkg_check_modules(LOG4CPP "log4cpp") pkg_check_modules(SNDFILE "sndfile") -include_directories(${OPUS_INCLUDE_DIRS}) include_directories(${PJSIP_INCLUDE_DIRS}) include_directories(${LOG4CPP_INCLUDE_DIRS}) include_directories(${SNDFILE_INCLUDE_DIRS}) -include_directories(libmumble) +include_directories(../mumlib/include) -link_directories(libmumble) +link_directories(../mumlib/build) set(SOURCE_FILES PjsuaCommunicator.cpp @@ -40,7 +38,7 @@ target_link_libraries(mumsi ${PJSIP_LIBRARIES}) target_link_libraries(mumsi ${LOG4CPP_LIBRARIES}) target_link_libraries(mumsi ${SNDFILE_LIBRARIES}) target_link_libraries(mumsi ${Boost_LIBRARIES}) -target_link_libraries(mumsi mumble) +target_link_libraries(mumsi mumlib) #add_executable(mumsi_test ${SOURCE_FILES} ${TEST_SOURCE_FILES} test_main.cpp) #target_link_libraries(mumsi_test ${OPUS_LIBRARIES}) diff --git a/MumbleCommunicator.cpp b/MumbleCommunicator.cpp index 29d1245..916fb0b 100644 --- a/MumbleCommunicator.cpp +++ b/MumbleCommunicator.cpp @@ -3,163 +3,47 @@ #include "MumbleCommunicator.hpp" -void mumble::MumbleCommunicator::receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size) { - int dataPointer = 1; - opus_int16 pcmData[1024]; +namespace mumble { + class MumlibCallback : public mumlib::BasicCallback { + public: + std::shared_ptr mum; + MumbleCommunicator *communicator; - if (audio_data[0] == 0x80) { - int64_t sessionId; - int64_t sequenceNumber; - int64_t opusDataLength; - bool lastPacket; - - dataPointer += mumble_parse_variant(&sessionId, &audio_data[dataPointer]); - dataPointer += mumble_parse_variant(&sequenceNumber, &audio_data[dataPointer]); - dataPointer += mumble_parse_variant(&opusDataLength, &audio_data[dataPointer]); - - lastPacket = (opusDataLength & 0x2000) != 0; - opusDataLength = opusDataLength & 0x1fff; - - - unsigned int iAudioBufferSize; - unsigned int iFrameSize = mumble::SAMPLE_RATE / 100; - iAudioBufferSize = iFrameSize; - iAudioBufferSize *= 12; - int decodedSamples = opus_decode(opusDecoder, - reinterpret_cast(&audio_data[dataPointer]), - opusDataLength, - pcmData, - iAudioBufferSize, - 0); - - fileHandle.write(pcmData, decodedSamples); - - logger.debug("Received %d bytes of Opus data (seq %ld), decoded to %d bytes. Push it to outputQueue.", - opusDataLength, sequenceNumber, decodedSamples); - - samplesBuffer.pushSamples(pcmData, decodedSamples); - - } else { - logger.warn("Received %d bytes of non-recognisable audio data.", audio_data_size); - } -} - -static void mumble_audio_callback(uint8_t *audio_data, uint32_t audio_data_size, void *userData) { - mumble::MumbleCommunicator *mumbleCommunicator = static_cast(userData); - mumbleCommunicator->receiveAudioFrameCallback(audio_data, audio_data_size); -} - -static void mumble_serversync_callback(char *welcome_text, - int32_t session, - int32_t max_bandwidth, - int64_t permissions, - void *usterData) { - printf("%s\n", welcome_text); -} - -void mumble_cryptsetup_callback(uint32_t key_size, - uint8_t *key, - uint32_t client_nonce_size, - uint8_t *client_nonce, - uint32_t server_nonce_size, - uint8_t *server_nonce, - void *userData) { - mumble::MumbleCommunicator *mumbleCommunicator = static_cast(userData); - printf("received crypto nonce\n"); -} - - -static int verify_cert(uint8_t *, uint32_t) { - // Accept every cert - return 1; + virtual void audio( + int16_t *pcm_data, + uint32_t pcm_data_size) { + communicator->samplesBuffer.pushSamples(pcm_data, pcm_data_size); + } + }; } mumble::MumbleCommunicator::MumbleCommunicator( + boost::asio::io_service &ioService, ISamplesBuffer &samplesBuffer, std::string user, std::string password, std::string host, - int port) : samplesBuffer(samplesBuffer), - outgoingAudioSequenceNumber(1), + int port) : ioService(ioService), + samplesBuffer(samplesBuffer), logger(log4cpp::Category::getInstance("MumbleCommunicator")) { quit = false; - opusDecoder = opus_decoder_create(SAMPLE_RATE, 1, nullptr); //todo grab error + callback.reset(new MumlibCallback()); - opusEncoder = opus_encoder_create(SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, nullptr); - opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(0)); + mum.reset(new mumlib::Mumlib(*callback, ioService)); + callback->communicator = this; + callback->mum = mum; - fileHandle = SndfileHandle("capture_mumble.wav", SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 1, SAMPLE_RATE); - - struct mumble_config config; - std::memset(&config, 0, sizeof(config)); - - config.user_data = this; - - config.size = sizeof(config); - config.host = const_cast(host.c_str()); - if (port > 0) { - config.port = const_cast(std::to_string(port).c_str()); - } - config.server_password = const_cast(password.c_str()); - config.username = const_cast(user.c_str()); - config.user_cert_filename = nullptr; - config.user_privkey_filename = nullptr; - - config.ssl_verification_callback = verify_cert; - config.audio_callback = mumble_audio_callback; - config.serversync_callback = mumble_serversync_callback; - config.cryptsetup_callback = mumble_cryptsetup_callback; - - mumble = mumble_connect(nullptr, &config); - - if (mumble == nullptr) { - throw mumble::Exception("couldn't establish mumble connection"); - } + mum->connect(host, port, user, password); } mumble::MumbleCommunicator::~MumbleCommunicator() { - mumble_close(mumble); -} - -void mumble::MumbleCommunicator::loop() { - - 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); - } - - //todo Other processing here? - } -} - - -void mumble::MumbleCommunicator::senderThreadFunction() { - while (!quit) { - opus_int16 pcmData[1024]; - unsigned char outputBuffer[1024]; - - int pcmLength = samplesBuffer.pullSamples(pcmData, 480, 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; - } - } + mum->disconnect(); } +// +//void mumble::MumbleCommunicator::senderThreadFunction() { +// while (!quit) { +// +// } +//} diff --git a/MumbleCommunicator.hpp b/MumbleCommunicator.hpp index 783f91b..90182f9 100644 --- a/MumbleCommunicator.hpp +++ b/MumbleCommunicator.hpp @@ -2,30 +2,27 @@ #define MUMSI_MUMBLECOMMUNICATOR_HPP #include "ISamplesBuffer.hpp" - -extern "C" { -#include "libmumble.h" -} +#include #include #include -#include #include #include #include namespace mumble { - constexpr unsigned int SAMPLE_RATE = 48000; - class Exception : public std::runtime_error { public: Exception(const char *message) : std::runtime_error(message) { } }; + class MumlibCallback; + class MumbleCommunicator { public: MumbleCommunicator( + boost::asio::io_service &ioService, ISamplesBuffer &samplesBuffer, std::string user, std::string password, @@ -34,28 +31,29 @@ namespace mumble { ~MumbleCommunicator(); - void loop(); +// void senderThreadFunction(); - void senderThreadFunction(); + //void receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size); - void receiveAudioFrameCallback(uint8_t *audio_data, uint32_t audio_data_size); - private: + public: + boost::asio::io_service &ioService; + log4cpp::Category &logger; ISamplesBuffer &samplesBuffer; + std::shared_ptr mum; + std::unique_ptr senderThread; - mumble_struct *mumble; - OpusDecoder *opusDecoder; - OpusEncoder *opusEncoder; - - int outgoingAudioSequenceNumber; - SndfileHandle fileHandle; + std::unique_ptr callback; + bool quit; + + friend class MumlibCallback; }; } diff --git a/main.cpp b/main.cpp index 988ab60..fd8d713 100644 --- a/main.cpp +++ b/main.cpp @@ -22,6 +22,8 @@ int main(int argc, char *argv[]) { config::Configuration conf(argv[1]); + boost::asio::io_service ioService; + sip::PjsuaCommunicator pjsuaCommunicator( conf.getString("sip.host"), conf.getString("sip.user"), @@ -29,6 +31,7 @@ int main(int argc, char *argv[]) { conf.getInt("sip.port")); mumble::MumbleCommunicator mumbleCommunicator( + ioService, pjsuaCommunicator, conf.getString("mumble.user"), conf.getString("mumble.password"), @@ -37,8 +40,7 @@ int main(int argc, char *argv[]) { logger.info("Application started."); - mumbleCommunicator.loop(); - + ioService.run(); return 0; }