@@ 1,3 1,4 @@
+#define _POSIX_C_SOURCE 1
#include <pulse/simple.h>
#include <signal.h>
#include <snikket.h>
@@ 5,15 6,17 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <termios.h>
// NOTE: callbacks all happen on other threads, so be careful
// Globals, ew
-static volatile sig_atomic_t hangup = 0; // Gross control flow flag
static void *chat = NULL;
+static void *dtmf = NULL;
static pa_simple *pulse = NULL;
static pa_sample_spec ss_rec;
static pa_simple *pulse_rec = NULL;
+static bool exiting = false;
struct online_ctx {
void *client;
@@ 31,14 34,14 @@ void on_call_retract(const char *chat_id, void *dummy) {
snikket_release(chat_id);
puts("Hung up...");
chat = NULL; // So we don't call hangup again
- hangup = 1;
+ if (!exiting) exit(0);
}
// User asked to stop
void sigint_handler(int sig) {
(void)sig;
puts("Hang up...");
- hangup = 1;
+ exit(0);
}
// Audio track got some from the other side, so let's play it
@@ 112,6 115,9 @@ void on_call_media(void* session, bool audio, bool video, void* dummy) {
streams[cstreams++] = snikket_jingle_media_stream_make_audio();
size_t ctracks = snikket_jingle_media_stream_get_tracks(streams[cstreams-1], &tracks);
for (size_t i = 0; i < ctracks; i++) {
+ if (!dtmf) {
+ dtmf = snikket_jingle_dtmf_sender_new(tracks[i]);
+ }
snikket_jingle_media_stream_track_add_pcm_listener(tracks[i], &on_pcm, NULL);
snikket_jingle_media_stream_track_add_ready_for_pcm_listener(tracks[i], &on_ready_for_pcm, tracks[i]);
snikket_release(tracks[i]);
@@ 170,6 176,21 @@ void on_password_needed(void *client, void *password) {
snikket_release(client);
}
+void at_exit(void) {
+ exiting = true;
+
+ // If it was us, send the hangup signal
+ if (chat) {
+ snikket_chat_hangup(chat);
+ sleep(3); // Give time for hangup to send, etc
+ }
+
+ // We could release stuff here, but we're gonna exit anyway
+
+ // Stop the SDK, no waiting
+ snikket_stop(false);
+}
+
int main(int argc, const char **argv) {
const char *err;
@@ 187,6 208,9 @@ int main(int argc, const char **argv) {
return 1;
}
+ // Set cleanup hook
+ atexit(&at_exit);
+
// And make a persistence layer
void *persistence = snikket_persistence_dummy_new();
@@ 208,20 232,28 @@ int main(int argc, const char **argv) {
puts("Connecting...");
snikket_client_start(client);
- // Wait for one side to hang up
- while (!hangup) {
- sleep(1);
+ struct termios term;
+ int fd = fileno(stdin);
+
+ // Get the current terminal attributes
+ if (tcgetattr(fd, &term) == -1) {
+ perror("tcgetattr");
+ return 1;
}
- // If it was us, send the hangup signal
- if (chat) {
- snikket_chat_hangup(chat);
- sleep(3); // Give time for hangup to send, etc
+ // Set non-canonical mode, to get characters immediately
+ term.c_lflag &= ~ICANON;
+
+ // Apply the new attributes immediately
+ if (tcsetattr(fd, TCSANOW, &term) == -1) {
+ perror("tcsetattr");
+ return 1;
}
- // We could release stuff here, but we're gonna exit anyway
+ char tone[2] = " ";
+ while ((tone[0] = fgetc(stdin)) != EOF) {
+ if (dtmf) snikket_jingle_dtmf_sender_insert_dtmf(dtmf, tone);
+ }
- // Stop the SDK, no waiting
- snikket_stop(false);
return 0;
}