From 09bbec79cf0140290ee90b8fca7a4eeca194a85a Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 26 Nov 2014 15:22:34 -0500 Subject: [PATCH] group audio almost works --- src/audio_call.c | 73 ++++++++++++++++++++++++------------------- src/audio_call.h | 13 ++++++-- src/chat_commands.c | 7 ++++- src/device.c | 16 +++++----- src/global_commands.c | 6 +++- src/groupchat.c | 27 +++++++++++----- src/groupchat.h | 4 +++ src/toxic.c | 27 ++-------------- src/toxic.h | 5 --- src/windows.c | 15 --------- 10 files changed, 98 insertions(+), 95 deletions(-) diff --git a/src/audio_call.c b/src/audio_call.c index 2fa54a5..277c417 100644 --- a/src/audio_call.c +++ b/src/audio_call.c @@ -55,14 +55,6 @@ #define frame_size (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000) -typedef struct Call { - pthread_t ttid; /* Transmission thread id */ - bool ttas, has_output; /* Transmission thread active status (0 - stopped, 1- running) */ - uint32_t in_idx, out_idx; - pthread_mutex_t mutex; -} Call; - - static int set_call(Call* call, bool start) { call->in_idx = -1; @@ -105,8 +97,9 @@ void callback_requ_timeout ( void* av, int32_t call_index, void *arg ); void callback_peer_timeout ( void* av, int32_t call_index, void *arg ); void callback_media_change ( void* av, int32_t call_index, void *arg ); -int stop_transmission(int call_index); void write_device_callback( void* agent, int32_t call_index, const int16_t* PCM, uint16_t size, void* arg ); +void write_device_callback_group( Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, + uint8_t channels, unsigned int sample_rate, void *arg ); static void print_err (ToxWindow *self, const char *error_str) { @@ -160,8 +153,8 @@ ToxAv *init_audio(ToxWindow *self, Tox *tox) void terminate_audio() { int i; - for (i = 0; i < MAX_CALLS; i ++) - stop_transmission(i); + for (i = 0; i < MAX_CALLS; ++i) + stop_transmission(&ASettins.calls[i], i); if ( ASettins.av ) toxav_kill(ASettins.av); @@ -192,56 +185,60 @@ void write_device_callback(void *agent, int32_t call_index, const int16_t* PCM, } } -int start_transmission(ToxWindow *self) +int start_transmission(ToxWindow *self, Call *call) { - if ( !ASettins.av || self->call_idx == -1 ) return -1; + if ( !self || !ASettins.av || self->call_idx == -1 ) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Could not prepare transmission"); + return -1; + } /* Don't provide support for video */ if ( 0 != toxav_prepare_transmission(ASettins.av, self->call_idx, 0) ) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Could not prepare transmission"); + return -1; } if ( !toxav_capability_supported(ASettins.av, self->call_idx, av_AudioDecoding) || !toxav_capability_supported(ASettins.av, self->call_idx, av_AudioEncoding) ) return -1; - if (set_call(&ASettins.calls[self->call_idx], true) == -1) + if (set_call(call, true) == -1) return -1; ToxAvCSettings csettings; toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings); - if ( open_primary_device(input, &ASettins.calls[self->call_idx].in_idx, + if ( open_primary_device(input, &call->in_idx, csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input device!"); - if ( register_device_callback(self->call_idx, ASettins.calls[self->call_idx].in_idx, + if ( register_device_callback(self->call_idx, call->in_idx, read_device_callback, &self->call_idx, true) != de_None) /* Set VAD as true for all; TODO: Make it more dynamic */ line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!"); - if ( open_primary_device(output, &ASettins.calls[self->call_idx].out_idx, + if ( open_primary_device(output, &call->out_idx, csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None ) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open output device!"); - ASettins.calls[self->call_idx].has_output = 0; + call->has_output = 0; } return 0; } -int stop_transmission(int call_index) +int stop_transmission(Call *call, int32_t call_index) { - if ( ASettins.calls[call_index].ttas ) { + if ( call->ttas ) { toxav_kill_transmission(ASettins.av, call_index); - ASettins.calls[call_index].ttas = false; + call->ttas = false; - if ( ASettins.calls[call_index].in_idx != -1 ) - close_device(input, ASettins.calls[call_index].in_idx); + if ( call->in_idx != -1 ) + close_device(input, call->in_idx); - if ( ASettins.calls[call_index].out_idx != -1 ) - close_device(output, ASettins.calls[call_index].out_idx); + if ( call->out_idx != -1 ) + close_device(output, call->out_idx); - if (set_call(&ASettins.calls[call_index], false) == -1) + if (set_call(call, false) == -1) return -1; return 0; @@ -279,7 +276,7 @@ void callback_recv_starting ( void* av, int32_t call_index, void* arg ) for (i = 0; i < MAX_WINDOWS_NUM; ++i) if (windows[i].onStarting != NULL && windows[i].call_idx == call_index) { windows[i].onStarting(&windows[i], ASettins.av, call_index); - if ( 0 != start_transmission(&windows[i]) ) {/* YEAH! */ + if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index])) {/* YEAH! */ line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0 , "Error starting transmission!"); } return; @@ -288,7 +285,7 @@ void callback_recv_starting ( void* av, int32_t call_index, void* arg ) void callback_recv_ending ( void* av, int32_t call_index, void* arg ) { CB_BODY(call_index, arg, onEnding); - stop_transmission(call_index); + stop_transmission(&ASettins.calls[call_index], call_index); } void callback_call_started ( void* av, int32_t call_index, void* arg ) @@ -298,7 +295,7 @@ void callback_call_started ( void* av, int32_t call_index, void* arg ) for (i = 0; i < MAX_WINDOWS_NUM; ++i) if (windows[i].onStart != NULL && windows[i].call_idx == call_index) { windows[i].onStart(&windows[i], ASettins.av, call_index); - if ( 0 != start_transmission(&windows[i]) ) {/* YEAH! */ + if ( 0 != start_transmission(&windows[i], &ASettins.calls[call_index]) ) {/* YEAH! */ line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Error starting transmission!"); return; } @@ -309,7 +306,7 @@ void callback_call_canceled ( void* av, int32_t call_index, void* arg ) CB_BODY(call_index, arg, onCancel); /* In case call is active */ - stop_transmission(call_index); + stop_transmission(&ASettins.calls[call_index], call_index); } void callback_call_rejected ( void* av, int32_t call_index, void* arg ) { @@ -318,7 +315,7 @@ void callback_call_rejected ( void* av, int32_t call_index, void* arg ) void callback_call_ended ( void* av, int32_t call_index, void* arg ) { CB_BODY(call_index, arg, onEnd); - stop_transmission(call_index); + stop_transmission(&ASettins.calls[call_index], call_index); } void callback_requ_timeout ( void* av, int32_t call_index, void* arg ) @@ -328,12 +325,24 @@ void callback_requ_timeout ( void* av, int32_t call_index, void* arg ) void callback_peer_timeout ( void* av, int32_t call_index, void* arg ) { CB_BODY(call_index, arg, onPeerTimeout); - stop_transmission(call_index); + stop_transmission(&ASettins.calls[call_index], call_index); /* Call is stopped manually since there might be some other * actions that one can possibly take on timeout */ toxav_stop_call(ASettins.av, call_index); } +void write_device_callback_group(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, + uint8_t channels, unsigned int sample_rate, void *arg) +{ + ToxWindow *windows = arg; + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onWriteDevice != NULL) + windows[i].onWriteDevice(&windows[i], m, groupnum, peernum, pcm, samples, channels, samples); + } +} + // void callback_media_change(void* av, int32_t call_index, void* arg) // { /*... TODO cancel all media change requests */ diff --git a/src/audio_call.h b/src/audio_call.h index c5e0ed8..685a51c 100644 --- a/src/audio_call.h +++ b/src/audio_call.h @@ -34,10 +34,19 @@ typedef enum _AudioError { ae_StartingCoreAudio = 1 << 2 } AudioError; +typedef struct Call { + pthread_t ttid; /* Transmission thread id */ + bool ttas, has_output; /* Transmission thread active status (0 - stopped, 1- running) */ + uint32_t in_idx, out_idx; + pthread_mutex_t mutex; +} Call; + /* You will have to pass pointer to first member of 'windows' declared in windows.c */ ToxAv *init_audio(ToxWindow *self, Tox *tox); void terminate_audio(); - +int start_transmission(ToxWindow *self, Call *call); +int stop_transmission(Call *call, int call_index); void stop_current_call(ToxWindow *self); - +void write_device_callback_group(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, + uint8_t channels, unsigned int sample_rate, void *arg); #endif /* AUDIO_H */ diff --git a/src/chat_commands.c b/src/chat_commands.c index 8b2e98d..b759900 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -33,6 +33,10 @@ #include "chat.h" #include "file_senders.h" +#ifdef AUDIO +#include "audio_call.h" +#endif + extern ToxWindow *prompt; extern FriendsList Friends; @@ -138,7 +142,8 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length); #ifdef AUDIO else - groupnum = toxav_join_av_groupchat(m, self->num, (uint8_t *) groupkey, length, NULL, NULL); + groupnum = toxav_join_av_groupchat(m, self->num, (uint8_t *) groupkey, length, + write_device_callback_group, self); #endif if (groupnum == -1) { diff --git a/src/device.c b/src/device.c index 6662f9c..32f6129 100644 --- a/src/device.c +++ b/src/device.c @@ -356,12 +356,14 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t* data, uint32_ if (device_idx >= MAX_DEVICES) return de_InvalidSelection; Device* device = running[output][device_idx]; - + if (!device) + fprintf(stderr, "DEVICE IS NULL SILLY\n"); + if (!device || device->muted) return de_DeviceNotActive; - + pthread_mutex_lock(device->mutex); - - + + ALuint bufid; ALint processed, queued; alGetSourcei(device->source, AL_BUFFERS_PROCESSED, &processed); @@ -387,8 +389,8 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t* data, uint32_ alGetSourcei(device->source, AL_SOURCE_STATE, &state); if(state != AL_PLAYING) alSourcePlay(device->source); - - + + pthread_mutex_unlock(device->mutex); return de_None; } @@ -408,7 +410,7 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source if (thread_paused) usleep(10000); /* Wait for unpause. */ else { - for (i = 0; i < size[input]; i ++) + for (i = 0; i < size[input]; ++i) { lock; if (running[input][i] != NULL) diff --git a/src/global_commands.c b/src/global_commands.c index 52ca34e..b4e241f 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -35,6 +35,10 @@ #include "prompt.h" #include "help.h" +#ifdef AUDIO +#include "audio_call.h" +#endif + extern char *DATA_FILE; extern ToxWindow *prompt; extern FriendsList Friends; @@ -347,7 +351,7 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg groupnum = tox_add_groupchat(m); #ifdef AUDIO else - groupnum = toxav_add_av_groupchat(m, NULL, NULL); + groupnum = toxav_add_av_groupchat(m, write_device_callback_group, self); #endif if (groupnum == -1) { diff --git a/src/groupchat.c b/src/groupchat.c index 70bc426..1b9e0e4 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -45,6 +45,7 @@ #include "help.h" #include "notify.h" #include "autocomplete.h" +#include "device.h" extern char *DATA_FILE; @@ -96,11 +97,12 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type) if (groupnum > MAX_GROUPCHAT_NUM) return -1; + ToxWindow self = new_group_chat(m, groupnum); int i; for (i = 0; i <= max_groupchat_index; ++i) { if (!groupchats[i].active) { - groupchats[i].chatwin = add_window(m, new_group_chat(m, groupnum)); + groupchats[i].chatwin = add_window(m, self); groupchats[i].active = true; groupchats[i].num_peers = 0; groupchats[i].type = type; @@ -118,6 +120,9 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type) memcpy(&groupchats[i].oldpeer_names[0], UNKNOWN_NAME, sizeof(UNKNOWN_NAME)); groupchats[i].oldpeer_name_lengths[0] = (uint16_t) strlen(UNKNOWN_NAME); +#ifdef AUDIO + start_transmission(&self, &groupchats[i].call); +#endif set_active_window(groupchats[i].chatwin); if (i == max_groupchat_index) @@ -147,6 +152,10 @@ void kill_groupchat_window(ToxWindow *self) static void close_groupchat(ToxWindow *self, Tox *m, int groupnum) { +#ifdef AUDIO + stop_transmission(&groupchats[groupnum].call, self->call_idx); +#endif + tox_del_groupchat(m, groupnum); free(groupchats[groupnum].peer_names); @@ -704,19 +713,20 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) } #ifdef AUDIO - void groupchat_onWriteDevice(ToxWindow *self, Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate) { - // if (groupnum != self->num) - // return; + if (groupnum != self->num) + return; - // if (peernum < 0 || channels == 0 || channels > 2) - // return; + if (peernum < 0 || channels == 0 || channels > 2 || !pcm) + return; - // uint32_t length = samples * channels * sizeof(int16_t); + Call *call = &groupchats[groupnum].call; + uint32_t length = samples * channels * sizeof(int16_t); + int ret = write_out(call->out_idx, pcm, length, channels); + fprintf(stderr, "groupnum: %d, out_idx: %d, ret: %d\n", groupnum, call->out_idx, ret); } - #endif /* AUDIO */ ToxWindow new_group_chat(Tox *m, int groupnum) @@ -738,6 +748,7 @@ ToxWindow new_group_chat(Tox *m, int groupnum) #ifdef AUDIO ret.onWriteDevice = &groupchat_onWriteDevice; ret.device_selection[0] = ret.device_selection[1] = -1; + ret.call_idx = -1; #endif snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); diff --git a/src/groupchat.h b/src/groupchat.h index 4769662..73d33ae 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -50,6 +50,10 @@ typedef struct { uint8_t *oldpeer_names; uint16_t *peer_name_lengths; uint16_t *oldpeer_name_lengths; + +#ifdef AUDIO + Call call; +#endif } GroupChat; void kill_groupchat_window(ToxWindow *self); diff --git a/src/toxic.c b/src/toxic.c index e9a4e66..31fcc51 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -957,25 +957,6 @@ static int init_default_data_files(void) return config_err; } -#define REC_TOX_DO_LOOPS_PER_SEC 25 - -/* Adjusts usleep value so that tox_do runs close to the recommended number of times per second */ -static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, uint64_t cur_time, useconds_t msleepval) -{ - useconds_t new_sleep = msleepval; - ++(*loopcount); - - if (*looptimer == cur_time) - return new_sleep; - - if (*loopcount != REC_TOX_DO_LOOPS_PER_SEC) - new_sleep *= (double) *loopcount / REC_TOX_DO_LOOPS_PER_SEC; - - *looptimer = cur_time; - *loopcount = 0; - return new_sleep; -} - #ifdef X11 void cb(const char* asdv, DropType dt) { @@ -1086,9 +1067,6 @@ int main(int argc, char *argv[]) execute(prompt->chatwin->history, prompt, m, avatarstr, GLOBAL_COMMAND_MODE); uint64_t last_save = (uint64_t) time(NULL); - uint64_t looptimer = last_save; - useconds_t msleepval = 40000; - uint64_t loopcount = 0; while (true) { update_unix_time(); @@ -1097,15 +1075,16 @@ int main(int argc, char *argv[]) if (timed_out(last_save, cur_time, AUTOSAVE_FREQ)) { pthread_mutex_lock(&Winthread.lock); + if (store_data(m, DATA_FILE) != 0) line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "WARNING: Failed to save to data file"); + pthread_mutex_unlock(&Winthread.lock); last_save = cur_time; } - msleepval = optimal_msleepval(&looptimer, &loopcount, cur_time, msleepval); - usleep(msleepval); + usleep((MIN(tox_do_interval(m), toxav_do_interval(av)))); } return 0; diff --git a/src/toxic.h b/src/toxic.h index 706efa7..32f46f4 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -116,9 +116,4 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_ void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata); void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata); -#ifdef AUDIO -void on_write_device(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, - uint8_t channels, unsigned int sample_rate, void *userdata); -#endif /* AUDIO */ - #endif /* #define TOXIC_H */ diff --git a/src/windows.c b/src/windows.c index a6b624b..0a6fb5f 100644 --- a/src/windows.c +++ b/src/windows.c @@ -268,21 +268,6 @@ void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userd } } -#ifdef AUDIO - -void on_write_device(Tox *m, int groupnum, int peernum, const int16_t *pcm, unsigned int samples, - uint8_t channels, unsigned int sample_rate, void *userdata) -{ - int i; - - for (i = 0; i < MAX_WINDOWS_NUM; ++i) { - if (windows[i].onWriteDevice != NULL) - windows[i].onWriteDevice(&windows[i], m, groupnum, peernum, pcm, samples, channels, samples); - } -} - -#endif /* AUDIO */ - /* CALLBACKS END */ int add_window(Tox *m, ToxWindow w)