mirror of
https://github.com/Tha14/toxic.git
synced 2024-12-22 22:13:25 +01:00
Implement push-to-talk for conference audio
This commit is contained in:
parent
31f36318a2
commit
41be04a142
@ -222,6 +222,11 @@ Audio output device\&. Integer value\&. Number corresponds to
|
||||
Voice Activity Detection threshold\&. Float value\&. Recommended values are 1\&.0\-40\&.0
|
||||
.RE
|
||||
.PP
|
||||
\fBpush_to_talk\fR
|
||||
.RS 4
|
||||
Enable/Disable Push\-To\-Talk for conference audio chats (active key is F2)\&. true or false
|
||||
.RE
|
||||
.PP
|
||||
\fBconference_audio_channels\fR
|
||||
.RS 4
|
||||
Number of channels for conference audio broadcast\&. Integer value\&. 1 (mono) or 2 (stereo)
|
||||
|
@ -145,6 +145,9 @@ OPTIONS
|
||||
*chat_audio_channels*;;
|
||||
Number of channels for 1-on-1 audio broadcast. Integer value. 1 (mono) or 2 (stereo)
|
||||
|
||||
*push_to_talk*;;
|
||||
Enable/Disable Push-To-Talk for conference audio chats (active key is F2). true or false
|
||||
|
||||
*tox*::
|
||||
Configuration related to paths.
|
||||
|
||||
|
@ -90,6 +90,9 @@ audio = {
|
||||
|
||||
// Number of channels to use for 1-on-1 audio broadcasts; 1 for mono, 2 for stereo.
|
||||
chat_audio_channels=2;
|
||||
|
||||
// toggle conference push-to-talk
|
||||
push_to_talk=false;
|
||||
};
|
||||
|
||||
tox = {
|
||||
|
@ -100,6 +100,7 @@ static const char *conference_cmd_list[] = {
|
||||
"/quit",
|
||||
"/requests",
|
||||
#ifdef AUDIO
|
||||
"/ptt",
|
||||
"/sense",
|
||||
#endif
|
||||
"/status",
|
||||
@ -200,6 +201,10 @@ int init_conference_win(Tox *m, uint32_t conferencenum, uint8_t type, const char
|
||||
conferences[i].audio_enabled = false;
|
||||
conferences[i].last_sent_audio = 0;
|
||||
|
||||
#ifdef AUDIO
|
||||
conferences[i].push_to_talk_enabled = user_settings->push_to_talk;
|
||||
#endif
|
||||
|
||||
set_active_window_index(conferences[i].chatwin);
|
||||
|
||||
conference_set_title(self, conferencenum, title, length);
|
||||
@ -568,6 +573,22 @@ static ConferencePeer *peer_in_conference(uint32_t conferencenum, uint32_t peern
|
||||
}
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
/* Return true if ptt is disabled or enabled and active. */
|
||||
static bool conference_check_push_to_talk(ConferenceChat *chat)
|
||||
{
|
||||
if (!chat->push_to_talk_enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !timed_out(chat->ptt_last_pushed, 1);
|
||||
}
|
||||
|
||||
static void conference_enable_push_to_talk(ConferenceChat *chat)
|
||||
{
|
||||
chat->ptt_last_pushed = get_unix_time();
|
||||
}
|
||||
|
||||
static void set_peer_audio_position(Tox *m, uint32_t conferencenum, uint32_t peernum)
|
||||
{
|
||||
ConferenceChat *chat = &conferences[conferencenum];
|
||||
@ -599,7 +620,7 @@ static void set_peer_audio_position(Tox *m, uint32_t conferencenum, uint32_t pee
|
||||
const float angle = asinf(peer_posn - (float)(num_posns - 1) / 2);
|
||||
set_source_position(peer->audio_out_idx, sinf(angle), cosf(angle), 0);
|
||||
}
|
||||
#endif
|
||||
#endif // AUDIO
|
||||
|
||||
|
||||
static bool find_peer_by_pubkey(const ConferencePeer *list, uint32_t num_peers, uint8_t *pubkey, uint32_t *idx)
|
||||
@ -774,7 +795,6 @@ static int sidebar_offset(uint32_t conferencenum)
|
||||
return 2 + conferences[conferencenum].audio_enabled;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if input is recognized by handler
|
||||
*/
|
||||
@ -817,6 +837,15 @@ static bool conference_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
bool input_ret = false;
|
||||
ConferenceChat *chat = &conferences[self->num];
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
if (chat->audio_enabled && chat->push_to_talk_enabled && key == KEY_F(2)) {
|
||||
input_ret = true;
|
||||
conference_enable_push_to_talk(chat);
|
||||
}
|
||||
|
||||
#endif // AUDIO
|
||||
|
||||
if (key == L'\t') { /* TAB key: auto-completes peer name or command */
|
||||
input_ret = true;
|
||||
|
||||
@ -997,6 +1026,12 @@ static void conference_onDraw(ToxWindow *self, Tox *m)
|
||||
return;
|
||||
}
|
||||
|
||||
ConferenceChat *chat = &conferences[self->num];
|
||||
|
||||
if (!chat->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
@ -1019,8 +1054,8 @@ static void conference_onDraw(ToxWindow *self, Tox *m)
|
||||
mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
const uint32_t num_peers = conferences[self->num].num_peers;
|
||||
const bool audio = conferences[self->num].audio_enabled;
|
||||
const uint32_t num_peers = chat->num_peers;
|
||||
const bool audio = chat->audio_enabled;
|
||||
const int header_lines = sidebar_offset(self->num);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
@ -1029,32 +1064,45 @@ static void conference_onDraw(ToxWindow *self, Tox *m)
|
||||
if (audio) {
|
||||
#ifdef AUDIO
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
const bool mic_on = !device_is_muted(input, conferences[self->num].audio_in_idx);
|
||||
const bool ptt_idle = !conference_check_push_to_talk(chat) && chat->push_to_talk_enabled;
|
||||
const bool mic_on = !device_is_muted(input, chat->audio_in_idx);
|
||||
const float volume = get_input_volume();
|
||||
const float threshold = device_get_VAD_threshold(conferences[self->num].audio_in_idx);
|
||||
const float threshold = device_get_VAD_threshold(chat->audio_in_idx);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
wmove(ctx->sidebar, line, 1);
|
||||
wattron(ctx->sidebar, A_BOLD);
|
||||
wprintw(ctx->sidebar, "Mic: ");
|
||||
const int color = mic_on && volume > threshold ? GREEN : RED;
|
||||
wattron(ctx->sidebar, COLOR_PAIR(color));
|
||||
|
||||
if (mic_on) {
|
||||
if (!mic_on) {
|
||||
wattron(ctx->sidebar, COLOR_PAIR(RED));
|
||||
wprintw(ctx->sidebar, "MUTED");
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(RED));
|
||||
} else if (ptt_idle) {
|
||||
wattron(ctx->sidebar, COLOR_PAIR(GREEN));
|
||||
wprintw(ctx->sidebar, "PTT");
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(GREEN));
|
||||
} else {
|
||||
const int color = volume > threshold ? GREEN : RED;
|
||||
wattron(ctx->sidebar, COLOR_PAIR(color));
|
||||
|
||||
float v = volume;
|
||||
|
||||
if (v <= 0.0f) {
|
||||
wprintw(ctx->sidebar, ".");
|
||||
}
|
||||
|
||||
while (v > 0.0f) {
|
||||
wprintw(ctx->sidebar, v > 10.0f ? (v > 15.0f ? "*" : "+") : (v > 5.0f ? "-" : "."));
|
||||
v -= 20.0f;
|
||||
}
|
||||
} else {
|
||||
wprintw(ctx->sidebar, "OFF");
|
||||
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(color));
|
||||
}
|
||||
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(color));
|
||||
wattroff(ctx->sidebar, A_BOLD);
|
||||
++line;
|
||||
#endif
|
||||
#endif // AUDIO
|
||||
}
|
||||
|
||||
wmove(ctx->sidebar, line, 1);
|
||||
@ -1195,7 +1243,13 @@ static void conference_read_device_callback(const int16_t *captured, uint32_t si
|
||||
|
||||
AudioInputCallbackData *audio_input_callback_data = (AudioInputCallbackData *)data;
|
||||
|
||||
conferences[audio_input_callback_data->conferencenum].last_sent_audio = get_unix_time();
|
||||
ConferenceChat *chat = &conferences[audio_input_callback_data->conferencenum];
|
||||
|
||||
if (!conference_check_push_to_talk(chat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
chat->last_sent_audio = get_unix_time();
|
||||
|
||||
int channels = user_settings->conference_audio_channels;
|
||||
|
||||
@ -1228,6 +1282,19 @@ bool init_conference_audio_input(Tox *tox, uint32_t conferencenum)
|
||||
return success;
|
||||
}
|
||||
|
||||
bool toggle_conference_push_to_talk(uint32_t conferencenum, bool enabled)
|
||||
{
|
||||
ConferenceChat *chat = &conferences[conferencenum];
|
||||
|
||||
if (!chat->active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chat->push_to_talk_enabled = enabled;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool enable_conference_audio(Tox *tox, uint32_t conferencenum)
|
||||
{
|
||||
if (!toxav_groupchat_av_enabled(tox, conferencenum)) {
|
||||
@ -1312,4 +1379,4 @@ float conference_get_VAD_threshold(uint32_t conferencenum)
|
||||
|
||||
return device_get_VAD_threshold(chat->audio_in_idx);
|
||||
}
|
||||
#endif
|
||||
#endif // AUDIO
|
||||
|
@ -74,6 +74,9 @@ typedef struct {
|
||||
NameListEntry *name_list;
|
||||
uint32_t num_peers;
|
||||
|
||||
bool push_to_talk_enabled;
|
||||
time_t ptt_last_pushed;
|
||||
|
||||
bool audio_enabled;
|
||||
time_t last_sent_audio;
|
||||
uint32_t audio_in_idx;
|
||||
@ -104,6 +107,7 @@ uint32_t get_name_list_entries_by_prefix(uint32_t conferencenum, const char *pre
|
||||
bool init_conference_audio_input(Tox *tox, uint32_t conferencenum);
|
||||
bool enable_conference_audio(Tox *tox, uint32_t conferencenum);
|
||||
bool disable_conference_audio(Tox *tox, uint32_t conferencenum);
|
||||
bool toggle_conference_push_to_talk(uint32_t conferencenum, bool enabled);
|
||||
void audio_conference_callback(void *tox, uint32_t conferencenum, uint32_t peernum,
|
||||
const int16_t *pcm, unsigned int samples, uint8_t channels, uint32_t
|
||||
sample_rate, void *userdata);
|
||||
|
@ -112,7 +112,8 @@ void cmd_enable_audio(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*
|
||||
}
|
||||
|
||||
if (enable ? enable_conference_audio(m, self->num) : disable_conference_audio(m, self->num)) {
|
||||
print_err(self, enable ? "Enabled conference audio" : "Disabled conference audio");
|
||||
print_err(self, enable ? "Enabled conference audio. Use the '/ptt' command to toggle Push-To-Talk."
|
||||
: "Disabled conference audio");
|
||||
} else {
|
||||
print_err(self, enable ? "Failed to enable audio" : "Failed to disable audio");
|
||||
}
|
||||
@ -150,7 +151,7 @@ void cmd_conference_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
|
||||
if (conference_mute_peer(m, self->num, entries[0]->peernum)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Toggled audio mute status of %s", entries[0]->name);
|
||||
} else {
|
||||
print_err(self, "No such audio peer");
|
||||
print_err(self, "Peer is not on the call");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,4 +186,28 @@ void cmd_conference_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, cha
|
||||
print_err(self, "Failed to set conference audio input sensitivity.");
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_conference_push_to_talk(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
bool enable;
|
||||
|
||||
if (argc == 1 && !strcasecmp(argv[1], "on")) {
|
||||
enable = true;
|
||||
} else if (argc == 1 && !strcasecmp(argv[1], "off")) {
|
||||
enable = false;
|
||||
} else {
|
||||
print_err(self, "Please specify: on | off");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!toggle_conference_push_to_talk(self->num, enable)) {
|
||||
print_err(self, "Failed to toggle push to talk.");
|
||||
return;
|
||||
}
|
||||
|
||||
print_err(self, enable ? "Push-To-Talk is enabled. Push F2 to activate" : "Push-To-Talk is disabled");
|
||||
}
|
||||
#endif /* AUDIO */
|
||||
|
@ -30,5 +30,6 @@ void cmd_conference_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc,
|
||||
void cmd_enable_audio(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_conference_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_conference_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_conference_push_to_talk(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
|
||||
#endif /* CONFERENCE_COMMANDS_H */
|
||||
|
@ -105,6 +105,7 @@ static struct cmd_func conference_commands[] = {
|
||||
#ifdef AUDIO
|
||||
{ "/audio", cmd_enable_audio },
|
||||
{ "/mute", cmd_conference_mute },
|
||||
{ "/ptt", cmd_conference_push_to_talk },
|
||||
{ "/sense", cmd_conference_sense },
|
||||
#endif /* AUDIO */
|
||||
{ NULL, NULL },
|
||||
|
@ -306,7 +306,7 @@ static void help_draw_conference(ToxWindow *self)
|
||||
wprintw(win, "Conference commands:\n");
|
||||
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
||||
|
||||
wprintw(win, " /title <msg> : Set conference title (show current title if no msg)\n");
|
||||
wprintw(win, " /title <msg> : Show/set conference title\n");
|
||||
#ifdef AUDIO
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "\n Audio:\n");
|
||||
@ -314,6 +314,7 @@ static void help_draw_conference(ToxWindow *self)
|
||||
wprintw(win, " /audio <on> or <off> : Enable/disable audio in an audio conference\n");
|
||||
wprintw(win, " /mute : Toggle self audio mute status\n");
|
||||
wprintw(win, " /mute <nick> or <pubkey> : Toggle peer audio mute status\n");
|
||||
wprintw(win, " /ptt <on> or <off> : Toggle audio input Push-To-Talk (F2 to activate)\n");
|
||||
wprintw(win, " /sense <n> : VAD sensitivity threshold\n\n");
|
||||
#endif
|
||||
|
||||
@ -403,7 +404,7 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
case L'o':
|
||||
height = 6;
|
||||
#ifdef AUDIO
|
||||
height += 5;
|
||||
height += 7;
|
||||
#endif
|
||||
help_init_window(self, height, 80);
|
||||
self->help->type = HELP_CONFERENCE;
|
||||
|
@ -207,6 +207,7 @@ static const struct audio_strings {
|
||||
const char *VAD_threshold;
|
||||
const char *conference_audio_channels;
|
||||
const char *chat_audio_channels;
|
||||
const char *push_to_talk;
|
||||
} audio_strings = {
|
||||
"audio",
|
||||
"input_device",
|
||||
@ -214,6 +215,7 @@ static const struct audio_strings {
|
||||
"VAD_threshold",
|
||||
"conference_audio_channels",
|
||||
"chat_audio_channels",
|
||||
"push_to_talk",
|
||||
};
|
||||
|
||||
static void audio_defaults(struct user_settings *settings)
|
||||
@ -223,6 +225,7 @@ static void audio_defaults(struct user_settings *settings)
|
||||
settings->VAD_threshold = 5.0;
|
||||
settings->conference_audio_channels = 1;
|
||||
settings->chat_audio_channels = 2;
|
||||
settings->push_to_talk = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -519,6 +522,8 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
|
||||
config_setting_lookup_int(setting, audio_strings.chat_audio_channels, &s->chat_audio_channels);
|
||||
s->chat_audio_channels = s->chat_audio_channels <= 0 || s->chat_audio_channels > 2 ? 2 : s->chat_audio_channels;
|
||||
|
||||
config_setting_lookup_bool(setting, audio_strings.push_to_talk, &s->push_to_talk);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -87,6 +87,7 @@ struct user_settings {
|
||||
double VAD_threshold;
|
||||
int conference_audio_channels;
|
||||
int chat_audio_channels;
|
||||
int push_to_talk; /* boolean */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user