bool CoreAV::cancelCall(uint32_t friendNum) { if (QThread::currentThread() != coreavThread.get()) { if (threadSwitchLock.test_and_set(std::memory_order_acquire)) { qDebug() << "CoreAV::cancelCall: Backed off of thread-switch lock"; return false; } bool ret; QMetaObject::invokeMethod(this, "cancelCall", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(uint32_t, friendNum)); threadSwitchLock.clear(std::memory_order_release); return ret; } qDebug() << QString("Cancelling call with %1").arg(friendNum); if (!toxav_call_control(toxav, friendNum, TOXAV_CALL_CONTROL_CANCEL, nullptr)) { qWarning() << QString("Failed to cancel call with %1").arg(friendNum); return false; } calls.erase(friendNum); emit avEnd(friendNum); return true; }
void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *error_str; if ( argc != 0 ) { error_str = "Unknown arguments."; goto on_error; } if ( !CallControl.av ) { error_str = "Audio not supported!"; goto on_error; } if ( !CallControl.pending_call ) { error_str = "No incoming call!"; goto on_error; } /* Manually send a cancel call control because call hasn't started */ toxav_call_control(CallControl.av, self->num, TOXAV_CALL_CONTROL_CANCEL, NULL); CallControl.pending_call = false; /* Callback will print status... */ callback_call_rejected(self->num); return; on_error: print_err (self, error_str); }
int stop_transmission(Call *call, uint32_t friend_number) { if ( call->ttas ) { TOXAV_ERR_CALL_CONTROL error = TOXAV_ERR_CALL_CONTROL_OK; if ( CallControl.call_state != TOXAV_FRIEND_CALL_STATE_FINISHED ) toxav_call_control(CallControl.av, friend_number, TOXAV_CALL_CONTROL_CANCEL, &error); if ( error == TOXAV_ERR_CALL_CONTROL_OK ) { call->ttas = false; if ( call->in_idx != -1 ) close_device(input, call->in_idx); if ( call->out_idx != -1 ) close_device(output, call->out_idx); if ( set_call(call, false) == -1 ) return -1; return 0; } else { return -1; } } return -1; }
bool CoreAV::answerCall(uint32_t friendNum, bool video) { if (QThread::currentThread() != coreavThread.get()) { if (threadSwitchLock.test_and_set(std::memory_order_acquire)) { qDebug() << "CoreAV::answerCall: Backed off of thread-switch lock"; return false; } bool ret; QMetaObject::invokeMethod(this, "answerCall", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(uint32_t, friendNum), Q_ARG(bool, video)); threadSwitchLock.clear(std::memory_order_release); return ret; } qDebug() << QString("answering call %1").arg(friendNum); auto it = calls.find(friendNum); assert(it != calls.end()); TOXAV_ERR_ANSWER err; const uint32_t videoBitrate = video ? VIDEO_DEFAULT_BITRATE : 0; if (toxav_answer(toxav, friendNum, Settings::getInstance().getAudioBitrate(), videoBitrate, &err)) { it->second.setActive(true); return true; } else { qWarning() << "Failed to answer call with error" << err; toxav_call_control(toxav, friendNum, TOXAV_CALL_CONTROL_CANCEL, nullptr); calls.erase(it); return false; } }
bool CoreAV::answerCall(uint32_t friendNum) { if (QThread::currentThread() != coreavThread.get()) { if (threadSwitchLock.test_and_set(std::memory_order_acquire)) { qDebug() << "CoreAV::answerCall: Backed off of thread-switch lock"; return false; } bool ret; QMetaObject::invokeMethod(this, "answerCall", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(uint32_t, friendNum)); threadSwitchLock.clear(std::memory_order_release); return ret; } qDebug() << QString("answering call %1").arg(friendNum); assert(calls.contains(friendNum)); TOXAV_ERR_ANSWER err; if (toxav_answer(toxav, friendNum, AUDIO_DEFAULT_BITRATE, VIDEO_DEFAULT_BITRATE, &err)) { calls[friendNum].inactive = false; return true; } else { qWarning() << "Failed to answer call with error"<<err; toxav_call_control(toxav, friendNum, TOXAV_CALL_CONTROL_CANCEL, nullptr); calls.remove(friendNum); return false; } }
void utox_av_local_disconnect(ToxAV *av, int32_t friend_number) { TOXAV_ERR_CALL_CONTROL error = 0; if (av) { /* TODO HACK: tox_callbacks doesn't have access to toxav, so it just sets it as NULL, this is bad! */ toxav_call_control(av, friend_number, TOXAV_CALL_CONTROL_CANCEL, &error); } switch (error) { case TOXAV_ERR_CALL_CONTROL_OK: { debug("uToxAV:\tToxAV has disconnected!\n"); break; } case TOXAV_ERR_CALL_CONTROL_SYNC: { debug("uToxAV:\tToxAV sync error!\n"); break; } case TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND: { debug("uToxAV:\tToxAV friend #%i not found.\n", friend_number); break; } case TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL: { debug("uToxAV:\tToxAV no existing call for friend #%i.\n", friend_number); break; } case TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION: { debug("uToxAV:\tCall already paused, or already running.\n"); break; } } toxav_postmessage(UTOXAV_END_CALL, friend_number, 0, NULL); friend[friend_number].call_state_self = 0; friend[friend_number].call_state_friend = 0; postmessage(AV_CLOSE_WINDOW, friend_number + 1, 0, NULL); postmessage(AV_CALL_DISCONNECTED, friend_number, 0, NULL); }
/* * Callbacks */ void call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data) { Tox *m = (Tox *) user_data; CallControl.pending_call = true; if (video_enabled) /* FIXME enable video calls */ toxav_call_control(av, friend_number, TOXAV_CALL_CONTROL_CANCEL, NULL); else if (audio_enabled) callback_recv_invite(m, friend_number); }
void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *error_str; if ( argc != 0 ) { error_str = "Unknown arguments."; goto on_error; } if ( !CallControl.av ) { error_str = "Audio not supported!"; goto on_error; } #ifdef VIDEO callback_video_end(self->num); #endif /* VIDEO */ if ( CallControl.pending_call ) { /* Manually send a cancel call control because call hasn't started */ toxav_call_control(CallControl.av, self->num, TOXAV_CALL_CONTROL_CANCEL, NULL); callback_call_canceled(self->num); } else { stop_transmission(&CallControl.calls[self->num], self->num); callback_call_ended(self->num); } CallControl.pending_call = false; return; on_error: print_err (self, error_str); }
void utox_av_local_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control) { TOXAV_ERR_CALL_CONTROL err = 0; toxav_call_control(av, friend_number, control, &err); if (err) { debug("uToxAV:\tLocal call control error!\n"); } else { TOXAV_ERR_BIT_RATE_SET bitrate_err = 0; switch (control) { case TOXAV_CALL_CONTROL_HIDE_VIDEO: { toxav_bit_rate_set(av, friend_number, -1, 0, &bitrate_err); toxvideo_postmessage(VIDEO_RECORD_STOP, friend_number, 0, NULL); friend[friend_number].call_state_self &= (0xFF ^ TOXAV_FRIEND_CALL_STATE_SENDING_V); break; } case TOXAV_CALL_CONTROL_SHOW_VIDEO: { toxav_bit_rate_set(av, friend_number, -1, UTOX_DEFAULT_BITRATE_V, &bitrate_err); toxvideo_postmessage(VIDEO_RECORD_START, friend_number, 0, NULL); friend[friend_number].call_state_self |= TOXAV_FRIEND_CALL_STATE_SENDING_V; break; } default: { debug("uToxAV:\tUnhandled local call control\n"); } // TODO // TOXAV_CALL_CONTROL_RESUME, // TOXAV_CALL_CONTROL_PAUSE, // TOXAV_CALL_CONTROL_CANCEL, // TOXAV_CALL_CONTROL_MUTE_AUDIO, // TOXAV_CALL_CONTROL_UNMUTE_AUDIO, } if (bitrate_err) { debug("uToxAV:\tError setting/changing video bitrate\n"); } } return; }
void stop_current_call(ToxWindow* self) { TOXAV_ERR_CALL_CONTROL error; toxav_call_control(CallControl.av, self->num, TOXAV_CALL_CONTROL_CANCEL, &error); }
static void *call_thread(void *pd) { ToxAV *AliceAV = ((thread_data *) pd)->AliceAV; ToxAV *BobAV = ((thread_data *) pd)->BobAV; CallControl *AliceCC = ((thread_data *) pd)->AliceCC; CallControl *BobCC = ((thread_data *) pd)->BobCC; uint32_t friend_number = ((thread_data *) pd)->friend_number; memset(AliceCC, 0, sizeof(CallControl)); memset(BobCC, 0, sizeof(CallControl)); { /* Call */ TOXAV_ERR_CALL rc; toxav_call(AliceAV, friend_number, 48, 3000, &rc); if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } while (!BobCC->incoming) { c_sleep(10); } { /* Answer */ TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 8, 500, &rc); if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); ck_assert(0); } } c_sleep(30); int16_t *PCM = (int16_t *)calloc(960, sizeof(int16_t)); uint8_t *video_y = (uint8_t *)calloc(800 * 600, sizeof(uint8_t)); uint8_t *video_u = (uint8_t *)calloc(800 * 600 / 4, sizeof(uint8_t)); uint8_t *video_v = (uint8_t *)calloc(800 * 600 / 4, sizeof(uint8_t)); time_t start_time = time(NULL); while (time(NULL) - start_time < 4) { toxav_iterate(AliceAV); toxav_iterate(BobAV); toxav_audio_send_frame(AliceAV, friend_number, PCM, 960, 1, 48000, NULL); toxav_audio_send_frame(BobAV, 0, PCM, 960, 1, 48000, NULL); toxav_video_send_frame(AliceAV, friend_number, 800, 600, video_y, video_u, video_v, NULL); toxav_video_send_frame(BobAV, 0, 800, 600, video_y, video_u, video_v, NULL); c_sleep(10); } { /* Hangup */ TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, friend_number, TOXAV_CALL_CONTROL_CANCEL, &rc); if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d %p %p\n", rc, (void *)AliceAV, (void *)BobAV); } } c_sleep(30); free(PCM); free(video_y); free(video_u); free(video_v); printf("Closing thread\n"); pthread_exit(NULL); }