main.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <sndfile.hh>
  5. #include <opus.h>
  6. #include <pjsua-lib/pjsua.h>
  7. extern "C" {
  8. #include "libmumble.h"
  9. }
  10. unsigned int SAMPLE_RATE =48000;
  11. OpusDecoder *opusState;
  12. SndfileHandle fileHandle;
  13. static int verify_cert(uint8_t *x509_pem_certificates, uint32_t size) {
  14. printf("I received a buffer of %d bytes!\n", size);
  15. const char FILENAME[] = "/tmp/cert";
  16. FILE *outfile = fopen(FILENAME, "wb");
  17. if (outfile != NULL) {
  18. fwrite(x509_pem_certificates, 1, size, outfile);
  19. fclose(outfile);
  20. printf("Written to %s\n", FILENAME);
  21. }
  22. // Accept every cert
  23. return 1;
  24. }
  25. void mumble_version_callback(uint16_t major, uint8_t minor, uint8_t patch, char *release, char *os, char *os_version) {
  26. printf("Version Callback: v%d.%d.%d. %s/%s/%s\n", major, minor, patch, release, os, os_version);
  27. }
  28. void mumble_audio_callback(uint8_t *audio_data, uint32_t audio_data_size) {
  29. int dataPointer = 1;
  30. float pcmData[1000];
  31. if (audio_data[0] == 0x80) {
  32. int64_t sessionId;
  33. int64_t sequenceNumber;
  34. int64_t opusDataLength;
  35. bool lastPacket = false;
  36. dataPointer += mumble_parse_variant(&sessionId, &audio_data[dataPointer]);
  37. dataPointer += mumble_parse_variant(&sequenceNumber, &audio_data[dataPointer]);
  38. dataPointer += mumble_parse_variant(&opusDataLength, &audio_data[dataPointer]);
  39. lastPacket = (opusDataLength & 0x2000) != 0;
  40. opusDataLength = opusDataLength & 0x1fff;
  41. unsigned int iAudioBufferSize;
  42. unsigned int iFrameSize = SAMPLE_RATE / 100;
  43. iAudioBufferSize = iFrameSize;
  44. iAudioBufferSize *= 12;
  45. int decodedSamples = opus_decode_float(opusState,
  46. reinterpret_cast<const unsigned char *>(&audio_data[dataPointer]),
  47. opusDataLength,
  48. pcmData,
  49. iAudioBufferSize,
  50. 0);
  51. printf("\nsessionId: %ld, seqNum: %ld, opus data len: %ld, last: %d, pos: %ld, decoded: %d\n",
  52. sessionId, sequenceNumber, opusDataLength, lastPacket, dataPointer, decodedSamples);
  53. fileHandle.write(pcmData, decodedSamples);
  54. }
  55. printf("I received %d bytes of audio data\n", audio_data_size);
  56. }
  57. void mumble_serversync_callback(char *welcome_text, int32_t session, int32_t max_bandwidth, int64_t permissions) {
  58. printf("%s\n", welcome_text);
  59. }
  60. void mumble_channelremove_callback(uint32_t channel_id) {
  61. printf("Channel %d removed\n", channel_id);
  62. }
  63. void mumble_channelstate_callback(char *name, int32_t channel_id, int32_t parent, char *description, uint32_t *links,
  64. uint32_t n_links, uint32_t *links_add, uint32_t n_links_add, uint32_t *links_remove,
  65. uint32_t n_links_remove, int32_t temporary, int32_t position) {
  66. printf("Obtained channel state\n");
  67. }
  68. void mumble_userremove_callback(uint32_t session, int32_t actor, char *reason, int32_t ban) {
  69. printf("User %d removed\n", actor);
  70. }
  71. void mumble_userstate_callback(int32_t session, int32_t actor, char *name, int32_t user_id, int32_t channel_id,
  72. int32_t mute, int32_t deaf, int32_t suppress, int32_t self_mute, int32_t self_deaf,
  73. char *comment, int32_t priority_speaker, int32_t recording) {
  74. printf("userstate_callback\n");
  75. }
  76. void mumble_banlist_callback(uint8_t *ip_data, uint32_t ip_data_size, uint32_t mask, char *name, char *hash,
  77. char *reason, char *start, int32_t duration) {
  78. printf("banlist_callback\n");
  79. }
  80. void mumble_textmessage_callback(uint32_t actor, uint32_t n_session, uint32_t *session, uint32_t n_channel_id,
  81. uint32_t *channel_id, uint32_t n_tree_id, uint32_t *tree_id, char *message) {
  82. printf("textmessage_callback\n");
  83. }
  84. void mumble_permissiondenied_callback(int32_t permission, int32_t channel_id, int32_t session, char *reason,
  85. int32_t deny_type, char *name) {
  86. printf("permissiondenied_callback\n");
  87. }
  88. void mumble_acl_callback(void) {
  89. printf("acl_callback\n");
  90. }
  91. void mumble_queryusers_callback(uint32_t n_ids, uint32_t *ids, uint32_t n_names, char **names) {
  92. printf("queryusers_callback\n");
  93. }
  94. void mumble_cryptsetup_callback(uint32_t key_size, uint8_t *key, uint32_t client_nonce_size, uint8_t *client_nonce,
  95. uint32_t server_nonce_size, uint8_t *server_nonce) {
  96. printf("cryptsetup_callback\n");
  97. }
  98. void mumble_contextactionmodify_callback(char *action, char *text, uint32_t m_context, uint32_t operation) {
  99. printf("contextactionmodify_callback\n");
  100. }
  101. void mumble_contextaction_callback(int32_t session, int32_t channel_id, char *action) {
  102. printf("contextaction_callback\n");
  103. }
  104. void mumble_userlist_callback(uint32_t user_id, char *name, char *last_seen, int32_t last_channel) {
  105. printf("userlist_callback\n");
  106. }
  107. void mumble_voicetarget_callback(void) {
  108. printf("voicetarget_callback\n");
  109. }
  110. void mumble_permissionquery_callback(int32_t channel_id, uint32_t permissions, int32_t flush) {
  111. printf("permissionquery_callback\n");
  112. }
  113. void mumble_codecversion_callback(int32_t alpha, int32_t beta, uint32_t prefer_alpha, int32_t opus) {
  114. printf("codecversion_callback\n");
  115. }
  116. void mumble_userstats_callback(void) {
  117. printf("userstats_callback\n");
  118. }
  119. void mumble_requestblob_callback(void) {
  120. printf("requestblob_callback\n");
  121. }
  122. void mumble_serverconfig_callback(uint32_t max_bandwidth, char *welcome_text, uint32_t allow_html,
  123. uint32_t message_length, uint32_t image_message_length) {
  124. printf("serverconfig_callback\n");
  125. }
  126. void mumble_suggestconfig_callback(uint32_t version, uint32_t positional, uint32_t push_to_talk) {
  127. printf("suggestconfig_callback\n");
  128. }
  129. int main(int argc, char *argv[]) {
  130. if (argc < 2) {
  131. printf("Usage: %s <mumble server ip> [mumble server port] [server password]\n", argv[0]);
  132. return -1;
  133. }
  134. char *host = argv[1];
  135. char *port = "64738";
  136. char *password = "hello";
  137. if (argc >= 3) {
  138. port = argv[2];
  139. }
  140. if (argc >= 4) {
  141. password = argv[3];
  142. }
  143. opusState = opus_decoder_create(SAMPLE_RATE, 1, nullptr);
  144. fileHandle = SndfileHandle("capture.wav", SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, SAMPLE_RATE);
  145. struct mumble_config config;
  146. memset(&config, 0, sizeof(config));
  147. config.size = sizeof(config);
  148. config.host = host;
  149. config.port = port;
  150. config.server_password = password;
  151. config.username = "example_username";
  152. config.user_cert_filename = NULL;
  153. config.user_privkey_filename = NULL;
  154. config.ssl_verification_callback = verify_cert;
  155. config.version_callback = mumble_version_callback;
  156. config.audio_callback = mumble_audio_callback;
  157. config.serversync_callback = mumble_serversync_callback;
  158. config.channelremove_callback = mumble_channelremove_callback;
  159. config.channelstate_callback = mumble_channelstate_callback;
  160. config.userremove_callback = mumble_userremove_callback;
  161. config.userstate_callback = mumble_userstate_callback;
  162. config.banlist_callback = mumble_banlist_callback;
  163. config.textmessage_callback = mumble_textmessage_callback;
  164. config.permissiondenied_callback = mumble_permissiondenied_callback;
  165. config.acl_callback = mumble_acl_callback;
  166. config.queryusers_callback = mumble_queryusers_callback;
  167. config.cryptsetup_callback = mumble_cryptsetup_callback;
  168. config.contextactionmodify_callback = mumble_contextactionmodify_callback;
  169. config.contextaction_callback = mumble_contextaction_callback;
  170. config.userlist_callback = mumble_userlist_callback;
  171. config.voicetarget_callback = mumble_voicetarget_callback;
  172. config.permissionquery_callback = mumble_permissionquery_callback;
  173. config.codecversion_callback = mumble_codecversion_callback;
  174. config.userstats_callback = mumble_userstats_callback;
  175. config.requestblob_callback = mumble_requestblob_callback;
  176. config.serverconfig_callback = mumble_serverconfig_callback;
  177. config.suggestconfig_callback = mumble_suggestconfig_callback;
  178. struct mumble_struct *mumble = mumble_connect(NULL, &config);
  179. if (mumble == NULL) {
  180. printf("Couldn't establish mumble connection\n");
  181. return -1;
  182. }
  183. // Start processing here?
  184. int quit = 0;
  185. while (quit == 0) {
  186. if (mumble_tick(mumble) < 0) {
  187. quit = 1;
  188. }
  189. // Other processing here?
  190. }
  191. mumble_close(mumble);
  192. printf("Done\n");
  193. return 0;
  194. }