diff --git a/src/device.c b/src/device.c index 4a6a8a5..9ef26de 100644 --- a/src/device.c +++ b/src/device.c @@ -58,14 +58,14 @@ typedef struct Device { DataHandleCallback cb; /* Use this to handle data from input device usually */ void* cb_data; /* Data to be passed to callback */ int32_t call_idx; /* ToxAv call index */ - + uint32_t source, buffers[OPENAL_BUFS]; /* Playback source/buffers */ uint32_t ref_count; int32_t selection; bool enable_VAD; bool muted; pthread_mutex_t mutex[1]; - uint32_t sample_rate; + uint32_t sample_rate; uint32_t frame_duration; int32_t sound_mode; #ifdef AUDIO @@ -89,7 +89,7 @@ static ToxAv* av = NULL; pthread_mutex_t mutex; -bool thread_running = true, +bool thread_running = true, thread_paused = true; /* Thread control */ void* thread_poll(void*); @@ -105,19 +105,19 @@ DeviceError init_devices() size[input] = 0; if ( (stringed_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)) ) { ddevice_names[input] = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); - + for ( ; *stringed_device_list && size[input] < MAX_DEVICES; ++size[input] ) { - devices_names[input][size[input]] = stringed_device_list; + devices_names[input][size[input]] = stringed_device_list; stringed_device_list += strlen( stringed_device_list ) + 1; } } - + size[output] = 0; if ( (stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER)) ) { ddevice_names[output] = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); - + for ( ; *stringed_device_list && size[output] < MAX_DEVICES; ++size[output] ) { - devices_names[output][size[output]] = stringed_device_list; + devices_names[output][size[output]] = stringed_device_list; stringed_device_list += strlen( stringed_device_list ) + 1; } } @@ -125,27 +125,30 @@ DeviceError init_devices() // Start poll thread if (pthread_mutex_init(&mutex, NULL) != 0) return de_InternalError; - + pthread_t thread_id; - if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0) - return de_InternalError; - + if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0) + return de_InternalError; + #ifdef AUDIO av = av_; #endif /* AUDIO */ - + return (DeviceError) de_None; } DeviceError terminate_devices() { /* Cleanup if needed */ + lock; thread_running = false; + unlock; + usleep(20000); - + if (pthread_mutex_destroy(&mutex) != 0) return (DeviceError) de_InternalError; - + return (DeviceError) de_None; } @@ -153,16 +156,16 @@ DeviceError device_mute(DeviceType type, uint32_t device_idx) { if (device_idx >= MAX_DEVICES) return de_InvalidSelection; lock; - + Device* device = running[type][device_idx]; - - if (!device) { + + if (!device) { unlock; return de_DeviceNotActive; } - + device->muted = !device->muted; - + unlock; return de_None; } @@ -175,7 +178,7 @@ DeviceError device_set_VAD_treshold(uint32_t device_idx, float value) Device* device = running[input][device_idx]; - if (!device) { + if (!device) { unlock; return de_DeviceNotActive; } @@ -192,7 +195,7 @@ DeviceError set_primary_device(DeviceType type, int32_t selection) { if (size[type] <= selection || selection < 0) return de_InvalidSelection; primary_device[type] = selection; - + return de_None; } @@ -212,88 +215,88 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx if (size[type] <= selection || selection < 0) return de_InvalidSelection; if (channels != 1 && channels != 2) return de_UnsupportedMode; - + lock; const uint32_t frame_size = (sample_rate * frame_duration / 1000); - + uint32_t i; for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; ++i); - + if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; } else *device_idx = i; - + for (i = 0; i < MAX_DEVICES; i ++) { /* Check if any device has the same selection */ if ( running[type][i] && running[type][i]->selection == selection ) { // printf("a%d-%d:%p ", selection, i, running[type][i]->dhndl); - - running[type][*device_idx] = running[type][i]; + + running[type][*device_idx] = running[type][i]; running[type][i]->ref_count ++; - + unlock; return de_None; } } - + Device* device = running[type][*device_idx] = calloc(1, sizeof(Device)); device->selection = selection; - + device->sample_rate = sample_rate; device->frame_duration = frame_duration; device->sound_mode = channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; - + if (pthread_mutex_init(device->mutex, NULL) != 0) { free(device); unlock; return de_InternalError; } - + if (type == input) { - device->dhndl = alcCaptureOpenDevice(devices_names[type][selection], + device->dhndl = alcCaptureOpenDevice(devices_names[type][selection], sample_rate, device->sound_mode, frame_size * 2); #ifdef AUDIO device->VAD_treshold = user_settings->VAD_treshold; #endif } - else { + else { device->dhndl = alcOpenDevice(devices_names[type][selection]); - if ( !device->dhndl ) { + if ( !device->dhndl ) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } - + device->ctx = alcCreateContext(device->dhndl, NULL); alcMakeContextCurrent(device->ctx); - + alGenBuffers(OPENAL_BUFS, device->buffers); alGenSources((uint32_t)1, &device->source); alSourcei(device->source, AL_LOOPING, AL_FALSE); - + uint16_t zeros[frame_size]; memset(zeros, 0, frame_size*2); - + for ( i = 0; i < OPENAL_BUFS; ++i ) { alBufferData(device->buffers[i], device->sound_mode, zeros, frame_size*2, sample_rate); } - + alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers); alSourcePlay(device->source); } - + if (alcGetError(device->dhndl) != AL_NO_ERROR) { free(device); running[type][*device_idx] = NULL; unlock; return de_FailedStart; } - + if (type == input) { alcCaptureStart(device->dhndl); thread_paused = false; } - + unlock; return de_None; } @@ -301,47 +304,47 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx DeviceError close_device(DeviceType type, uint32_t device_idx) { if (device_idx >= MAX_DEVICES) return de_InvalidSelection; - + lock; Device* device = running[type][device_idx]; DeviceError rc = de_None; - - if (!device) { + + if (!device) { unlock; return de_DeviceNotActive; } - + running[type][device_idx] = NULL; - + if ( !device->ref_count ) { - + // printf("Closed device "); - + if (type == input) { if ( !alcCaptureCloseDevice(device->dhndl) ) rc = de_AlError; } - else { + else { if (alcGetCurrentContext() != device->ctx) alcMakeContextCurrent(device->ctx); - + alDeleteSources(1, &device->source); alDeleteBuffers(OPENAL_BUFS, device->buffers); - + alcMakeContextCurrent(NULL); if ( device->ctx ) alcDestroyContext(device->ctx); if ( !alcCloseDevice(device->dhndl) ) rc = de_AlError; } - + free(device); } else device->ref_count--; - + unlock; return rc; } DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD) -{ - if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL) +{ + if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL) return de_InvalidSelection; lock; @@ -375,9 +378,9 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t* data, uint32_ alSourceUnqueueBuffers(device->source, processed, bufids); alDeleteBuffers(processed - 1, bufids + 1); bufid = bufids[0]; - } + } else if(queued < 16) alGenBuffers(1, &bufid); - else { + else { pthread_mutex_unlock(device->mutex); return de_Busy; } @@ -404,44 +407,51 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source (void)arg; uint32_t i; int32_t sample = 0; - - - while (thread_running) + + + while (true) { + lock; + if (!thread_running) { + unlock; + break; + } + unlock; + 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) + if (running[input][i] != NULL) { alcGetIntegerv(running[input][i]->dhndl, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &sample); - + int f_size = (running[input][i]->sample_rate * running[input][i]->frame_duration / 1000); - - if (sample < f_size) { + + if (sample < f_size) { unlock; continue; } Device* device = running[input][i]; - + int16_t frame[16000]; alcCaptureSamples(device->dhndl, frame, f_size); - - if (device->muted) { + + if (device->muted) { unlock; continue; } - + if ( device->cb ) device->cb(frame, f_size, device->cb_data); - } + } unlock; } usleep(5000); } } - + pthread_exit(NULL); } @@ -462,8 +472,8 @@ DeviceError selection_valid(DeviceType type, int32_t selection) void* get_device_callback_data(uint32_t device_idx) { - if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL) + if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL) return NULL; - + return running[input][device_idx]->cb_data; } diff --git a/src/friendlist.c b/src/friendlist.c index 0e0b394..be2856c 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -624,10 +624,12 @@ static void draw_del_popup(void) wprintw(PendingDelete.popup, "Delete contact "); wattron(PendingDelete.popup, A_BOLD); + pthread_mutex_lock(&Winthread.lock); if (blocklist_view == 0) wprintw(PendingDelete.popup, "%s", Friends.list[PendingDelete.num].name); else wprintw(PendingDelete.popup, "%s", Blocked.list[PendingDelete.num].name); + pthread_mutex_unlock(&Winthread.lock); wattroff(PendingDelete.popup, A_BOLD); wprintw(PendingDelete.popup, "? y/n"); @@ -888,12 +890,13 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) return; } - uint64_t cur_time = get_unix_time(); - struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); + uint64_t cur_time = time(NULL); + struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); wattron(self->window, A_BOLD); wprintw(self->window, " Online: "); wattroff(self->window, A_BOLD); + wprintw(self->window, "%d/%d \n\n", Friends.num_online, Friends.num_friends); if ((y2 - FLIST_OFST) <= 0) @@ -902,18 +905,30 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) uint32_t selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ + pthread_mutex_lock(&Winthread.lock); int page = Friends.num_selected / (y2 - FLIST_OFST); + pthread_mutex_unlock(&Winthread.lock); + int start = (y2 - FLIST_OFST) * page; int end = y2 - FLIST_OFST + start; + pthread_mutex_lock(&Winthread.lock); + size_t num_friends = Friends.num_friends; + pthread_mutex_unlock(&Winthread.lock); + int i; - for (i = start; i < Friends.num_friends && i < end; ++i) { + for (i = start; i < num_friends && i < end; ++i) { + pthread_mutex_lock(&Winthread.lock); uint32_t f = Friends.index[i]; + bool is_active = Friends.list[f].active; + int num_selected = Friends.num_selected; + pthread_mutex_unlock(&Winthread.lock); + bool f_selected = false; - if (Friends.list[f].active) { - if (i == Friends.num_selected) { + if (is_active) { + if (i == num_selected) { wattron(self->window, A_BOLD); wprintw(self->window, " > "); wattroff(self->window, A_BOLD); @@ -923,8 +938,12 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) wprintw(self->window, " "); } - if (Friends.list[f].connection_status != TOX_CONNECTION_NONE) { - TOX_USER_STATUS status = Friends.list[f].status; + pthread_mutex_lock(&Winthread.lock); + TOX_CONNECTION connection_status = Friends.list[f].connection_status; + TOX_USER_STATUS status = Friends.list[f].status; + pthread_mutex_unlock(&Winthread.lock); + + if (connection_status != TOX_CONNECTION_NONE) { int colour = MAGENTA; switch (status) { @@ -947,7 +966,9 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); + pthread_mutex_lock(&Winthread.lock); wprintw(self->window, "%s", Friends.list[f].name); + pthread_mutex_unlock(&Winthread.lock); wattroff(self->window, A_BOLD); if (f_selected) @@ -960,17 +981,23 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) pthread_mutex_lock(&Winthread.lock); tox_friend_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, NULL); size_t s_len = tox_friend_get_status_message_size(m, Friends.list[f].num, NULL); - statusmsg[s_len] = '\0'; pthread_mutex_unlock(&Winthread.lock); + statusmsg[s_len] = '\0'; + filter_str(statusmsg, s_len); + + pthread_mutex_lock(&Winthread.lock); snprintf(Friends.list[f].statusmsg, sizeof(Friends.list[f].statusmsg), "%s", statusmsg); Friends.list[f].statusmsg_len = strlen(Friends.list[f].statusmsg); + pthread_mutex_unlock(&Winthread.lock); } /* Truncate note if it doesn't fit on one line */ size_t maxlen = x2 - getcurx(self->window) - 2; + pthread_mutex_lock(&Winthread.lock); + if (Friends.list[f].statusmsg_len > maxlen) { Friends.list[f].statusmsg[maxlen - 3] = '\0'; strcat(Friends.list[f].statusmsg, "..."); @@ -981,6 +1008,8 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) if (Friends.list[f].statusmsg_len > 0) wprintw(self->window, " %s", Friends.list[f].statusmsg); + pthread_mutex_unlock(&Winthread.lock); + wprintw(self->window, "\n"); } else { wprintw(self->window, "%s ", OFFLINE_CHAR); @@ -989,21 +1018,29 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); + pthread_mutex_lock(&Winthread.lock); wprintw(self->window, "%s", Friends.list[f].name); + pthread_mutex_unlock(&Winthread.lock); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); + pthread_mutex_lock(&Winthread.lock); uint64_t last_seen = Friends.list[f].last_online.last_on; + pthread_mutex_unlock(&Winthread.lock); if (last_seen != 0) { + pthread_mutex_lock(&Winthread.lock); + int day_dist = ( cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday + ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365) ); const char *hourmin = Friends.list[f].last_online.hour_min_str; + pthread_mutex_unlock(&Winthread.lock); + switch (day_dist) { case 0: wprintw(self->window, " Last seen: Today %s\n", hourmin); @@ -1026,7 +1063,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) self->x = x2; - if (Friends.num_friends) { + if (num_friends) { wmove(self->window, y2 - 1, 1); wattron(self->window, A_BOLD); diff --git a/src/misc_tools.c b/src/misc_tools.c index 54b3811..68f1963 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -54,6 +54,7 @@ void hst_to_net(uint8_t *num, uint16_t numbytes) return; } +/* Note: The time functions are not thread safe */ void update_unix_time(void) { current_unix_time = (uint64_t) time(NULL); diff --git a/src/misc_tools.h b/src/misc_tools.h index e64b896..605555f 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -53,16 +53,16 @@ int hex_string_to_bin(const char *hex_string, size_t hex_len, char *output, size /* convert a hex string to bytes. returns 0 on success, -1 on failure */ int hex_string_to_bytes(char *buf, int size, const char *keystr); -/* get the current unix time */ +/* get the current unix time (not thread safe) */ uint64_t get_unix_time(void); -/* Puts the current time in buf in the format of [HH:mm:ss] */ +/* Puts the current time in buf in the format of [HH:mm:ss] (not thread safe) */ void get_time_str(char *buf, int bufsize); /* Converts seconds to string in format HH:mm:ss; truncates hours and minutes when necessary */ void get_elapsed_time_str(char *buf, int bufsize, uint64_t secs); -/* get the current local time */ +/* get the current local time (not thread safe) */ struct tm *get_time(void); /* updates current unix time (should be run once per do_toxic loop) */ diff --git a/src/notify.c b/src/notify.c index dc58e94..b7aae76 100644 --- a/src/notify.c +++ b/src/notify.c @@ -257,7 +257,7 @@ void* do_playing(void* _p) } } #ifdef BOX_NOTIFY - else if (actives[i].box && get_unix_time() >= actives[i].n_timeout) + else if (actives[i].box && time(NULL) >= actives[i].n_timeout) { GError* ignore; notify_notification_close(actives[i].box, &ignore); @@ -278,7 +278,7 @@ void* do_playing(void* _p) /* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/ if (device_opened && !has_looping && - (get_unix_time() - last_opened_update) > DEVICE_COOLDOWN) { + (time(NULL) - last_opened_update) > DEVICE_COOLDOWN) { m_close_device(); } has_looping = false; @@ -323,7 +323,7 @@ void* do_playing(void* _p) int i; for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) { - if (actives[i].box && get_unix_time() >= actives[i].n_timeout) + if (actives[i].box && time(NULL) >= actives[i].n_timeout) { GError* ignore; notify_notification_close(actives[i].box, &ignore); @@ -391,7 +391,7 @@ int init_notify(int login_cooldown, int notification_timeout) } #endif - Control.cooldown = get_unix_time() + login_cooldown; + Control.cooldown = time(NULL) + login_cooldown; #ifdef BOX_NOTIFY diff --git a/src/prompt.c b/src/prompt.c index c032711..872481b 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -260,14 +260,23 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]); StatusBar *statusbar = self->stb; + mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2); wmove(statusbar->topline, 0, 0); - if (statusbar->connection != TOX_CONNECTION_NONE) { + pthread_mutex_lock(&Winthread.lock); + TOX_CONNECTION connection = statusbar->connection; + pthread_mutex_unlock(&Winthread.lock); + + if (connection != TOX_CONNECTION_NONE) { int colour = MAGENTA; const char *status_text = "ERROR"; - switch (statusbar->status) { + pthread_mutex_lock(&Winthread.lock); + TOX_USER_STATUS status = statusbar->status; + pthread_mutex_unlock(&Winthread.lock); + + switch (status) { case TOX_USER_STATUS_NONE: status_text = "Online"; colour = GREEN; @@ -287,12 +296,16 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); wattron(statusbar->topline, A_BOLD); + pthread_mutex_lock(&Winthread.lock); wprintw(statusbar->topline, " %s", statusbar->nick); + pthread_mutex_unlock(&Winthread.lock); wattroff(statusbar->topline, A_BOLD); } else { wprintw(statusbar->topline, " [Offline]"); wattron(statusbar->topline, A_BOLD); + pthread_mutex_lock(&Winthread.lock); wprintw(statusbar->topline, " %s", statusbar->nick); + pthread_mutex_unlock(&Winthread.lock); wattroff(statusbar->topline, A_BOLD); } @@ -304,10 +317,9 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) size_t slen = tox_self_get_status_message_size(m); tox_self_get_status_message (m, (uint8_t*) statusmsg); statusmsg[slen] = '\0'; - pthread_mutex_unlock(&Winthread.lock); - snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); statusbar->statusmsg_len = strlen(statusbar->statusmsg); + pthread_mutex_unlock(&Winthread.lock); } self->x = x2; @@ -315,6 +327,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) /* Truncate note if it doesn't fit in statusbar */ uint16_t maxlen = x2 - getcurx(statusbar->topline) - 3; + pthread_mutex_lock(&Winthread.lock); + if (statusbar->statusmsg_len > maxlen) { statusbar->statusmsg[maxlen - 3] = '\0'; strcat(statusbar->statusmsg, "..."); @@ -324,6 +338,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) if (statusbar->statusmsg[0]) wprintw(statusbar->topline, " : %s", statusbar->statusmsg); + pthread_mutex_unlock(&Winthread.lock); + mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2); int y, x; diff --git a/src/toxic.c b/src/toxic.c index 4e938b8..a0796da 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -807,10 +807,14 @@ static void do_bootstrap(Tox *m) static void do_toxic(Tox *m, ToxWindow *prompt) { - if (arg_opts.no_connect) - return; - pthread_mutex_lock(&Winthread.lock); + update_unix_time(); + + if (arg_opts.no_connect) { + pthread_mutex_unlock(&Winthread.lock); + return; + } + tox_iterate(m); do_bootstrap(m); check_file_transfer_timeouts(m); @@ -822,6 +826,7 @@ static void do_toxic(Tox *m, ToxWindow *prompt) void *thread_winref(void *data) { Tox *m = (Tox *) data; + uint8_t draw_count = 0; init_signal_catchers(); @@ -1105,14 +1110,16 @@ static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, ui return new_sleep; } +// this doesn't do anything (yet) #ifdef X11 -// FIXME void DnD_callback(const char* asdv, DropType dt) { - if (dt != DT_plain) - return; + // if (dt != DT_plain) + // return; - line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, asdv); + // pthread_mutex_lock(&Winthread.lock); + // line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, asdv); + pthread_mutex_unlock(&Winthread.lock); } #endif /* X11 */ @@ -1181,6 +1188,7 @@ int main(int argc, char *argv[]) if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0) exit_toxic_err("failed in main", FATALERR_THREAD_CREATE); + #ifdef AUDIO av = init_audio(prompt, m); @@ -1214,7 +1222,10 @@ int main(int argc, char *argv[]) if (init_mplex_away_timer(m) == -1) queue_init_message("Failed to init mplex auto-away."); + pthread_mutex_lock(&Winthread.lock); print_init_messages(prompt); + pthread_mutex_unlock(&Winthread.lock); + cleanup_init_messages(); /* set user avatar from config file. if no path is supplied tox_unset_avatar is called */ @@ -1228,7 +1239,6 @@ int main(int argc, char *argv[]) uint64_t loopcount = 0; while (true) { - update_unix_time(); do_toxic(m, prompt); uint64_t cur_time = get_unix_time(); diff --git a/src/windows.c b/src/windows.c index 6324b38..f0f37be 100644 --- a/src/windows.c +++ b/src/windows.c @@ -454,10 +454,16 @@ void on_window_resize(void) static void draw_window_tab(ToxWindow *toxwin) { + pthread_mutex_lock(&Winthread.lock); if (toxwin->alert != WINDOW_ALERT_NONE) attron(COLOR_PAIR(toxwin->alert)); + pthread_mutex_unlock(&Winthread.lock); + clrtoeol(); printw(" [%s]", toxwin->name); + + pthread_mutex_lock(&Winthread.lock); if (toxwin->alert != WINDOW_ALERT_NONE) attroff(COLOR_PAIR(toxwin->alert)); + pthread_mutex_unlock(&Winthread.lock); } static void draw_bar(void) @@ -505,7 +511,10 @@ static void draw_bar(void) void draw_active_window(Tox *m) { ToxWindow *a = active_window; + + pthread_mutex_lock(&Winthread.lock); a->alert = WINDOW_ALERT_NONE; + pthread_mutex_unlock(&Winthread.lock); wint_t ch = 0;