C_RESULT ardrone_tool_shutdown() { C_RESULT res = C_OK; #ifndef NO_ARDRONE_MAINLOOP res = ardrone_tool_shutdown_custom(); #endif // Shutdown subsystems ardrone_navdata_client_shutdown(); ardrone_control_shutdown(); ardrone_tool_input_shutdown(); JOIN_THREAD(ardrone_control); JOIN_THREAD(navdata_update); // Shutdown AT Commands ATcodec_exit_thread(); ATcodec_Shutdown_Library(); vp_com_disconnect(COM_NAVDATA()); vp_com_shutdown(COM_NAVDATA()); PRINT("Custom ardrone tool ended\n"); return res; }
C_RESULT ardrone_tool_shutdown() { C_RESULT res = C_OK; res = ardrone_tool_shutdown_custom(); // Shutdown subsystems ardrone_navdata_client_shutdown(); ardrone_control_shutdown(); ardrone_tool_input_shutdown(); JOIN_THREAD(ardrone_control); JOIN_THREAD(navdata_update); fflush (NULL); // Shutdown AT Commands ATcodec_exit_thread(); ATcodec_Shutdown_Library(); vp_com_disconnect(COM_NAVDATA()); vp_com_shutdown(COM_NAVDATA()); academy_download_shutdown(); academy_shutdown(); PRINT("Custom ardrone tool ended\n"); return res; }
int main(int argc, char **argv) { START_THREAD(escaper, NO_PARAM); START_THREAD(app, argv); JOIN_THREAD(escaper); JOIN_THREAD(app); return EXIT_SUCCESS; }
/* The delegate object calls this method when the event loop exit */ C_RESULT ardrone_tool_shutdown_custom() //Initiation Function { /* Relinquish all threads of your application */ JOIN_THREAD( video_stage ); JOIN_THREAD( thread1 ); ardrone_tool_set_ui_pad_start(0); /* Unregistering for the current device */ return C_OK; }
/* The delegate object calls this method when the event loop exit */ C_RESULT ardrone_tool_shutdown_custom() { /* Relinquish all threads of your application */ JOIN_THREAD( video_stage ); JOIN_THREAD(gui); /* Unregistering for the current device */ ardrone_tool_input_remove( &gamepad ); return C_OK; }
C_RESULT ardrone_tool_shutdown_custom () { video_stage_resume_thread(); //Resume thread to kill it ! JOIN_THREAD(video_stage); if (2 <= ARDRONE_VERSION ()) { video_recorder_resume_thread (); JOIN_THREAD (video_recorder); } return C_OK; }
C_RESULT ardrone_tool_shutdown_custom() { #ifdef USE_TABLE_PILOTAGE JOIN_THREAD(novadem); #endif // USE_TABLE_PILOTAGE #ifdef PC_USE_POLARIS JOIN_THREAD(polaris); #endif // PC_USE_POLARIS #ifdef USE_ARDRONE_VICON JOIN_THREAD(vicon); #endif // USE_ARDRONE_VICON JOIN_THREAD(ihm); video_stage_resume_thread(); //Resume thread to kill it ! JOIN_THREAD(video_stage); if (2 <= ARDRONE_VERSION ()) { video_recorder_resume_thread (); JOIN_THREAD (video_recorder); } #ifdef RAW_CAPTURE JOIN_THREAD(raw_capture); #endif JOIN_THREAD(remote_console); /*ardrone_tool_input_remove( &gamepad ); ardrone_tool_input_remove( &radioGP ); ardrone_tool_input_remove( &ps3pad ); ardrone_tool_input_remove( &wiimote_device );*/ ardrone_tool_input_remove(&control_device); return C_OK; }
C_RESULT ardrone_tool_shutdown_custom () { video_stage_resume_thread(); //Resume thread to kill it ! JOIN_THREAD(video_stage); JOIN_THREAD(kinect); if (2 <= ARDRONE_VERSION ()) { video_recorder_resume_thread (); JOIN_THREAD (video_recorder); } //JOIN_THREAD(main_application_thread); //ardrone_tool_input_remove(&input_controller); return C_OK; }
DEFINE_THREAD_ROUTINE(mobile_main, data) { C_RESULT res = C_FAIL; vp_com_wifi_config_t *config = NULL; mobile_main_param_t *param = (mobile_main_param_t *)data; ardroneEngineCallback callback = param->callback; vp_os_memset(drone_address, 0x0, sizeof(drone_address)); // TODO(johnb): Make this autodetect based on network interfaces while(((config = (vp_com_wifi_config_t *)wifi_config()) != NULL) && (strcmp(config->itfName, WIFI_ITFNAME) != 0)) { PRINT("Wait WIFI connection !\n"); vp_os_delay(250); } // Get drone_address vp_os_memcpy(drone_address, config->server, strlen(config->server)); PRINT("Drone address %s\n", drone_address); // Get iphone_mac_address get_iphone_mac_address(config->itfName); PRINT("Iphone MAC Address %s\n", iphone_mac_address); res = ardrone_tool_setup_com( NULL ); if( FAILED(res) ) { PRINT("Wifi initialization failed. It means either:\n"); PRINT("\t* you're not root (it's mandatory because you can set up wifi connection only as root)\n"); PRINT("\t* wifi device is not present (on your pc or on your card)\n"); PRINT("\t* you set the wrong name for wifi interface (for example rausb0 instead of wlan0) \n"); PRINT("\t* ap is not up (reboot card or remove wifi usb dongle)\n"); PRINT("\t* wifi device has no antenna\n"); } else { START_THREAD(video_stage, NULL); res = ardrone_tool_init(drone_address, strlen(drone_address), NULL, param->appName, param->usrName); callback(ARDRONE_ENGINE_INIT_OK); ardrone_tool_set_refresh_time(1000 / kAPS); while( SUCCEED(res) && bContinue == TRUE ) { ardrone_tool_update(); } JOIN_THREAD(video_stage); res = ardrone_tool_shutdown(); } vp_os_free (data); return (THREAD_RET)res; }
int main(int argc, char **argv) { START_THREAD(app, argv); JOIN_THREAD(app); return EXIT_SUCCESS; }
C_RESULT ardrone_tool_shutdown_custom (){ //King of the Hill threads JOIN_THREAD(wiimote_logic); JOIN_THREAD(drone_logic); JOIN_THREAD(score_logic); video_stage_resume_thread(); //Resume thread to kill it ! JOIN_THREAD(video_stage); if (2 <= ARDRONE_VERSION ()) { video_recorder_resume_thread (); JOIN_THREAD (video_recorder); } return C_OK; }
int main(int argc, char **argv) { if(argc != 2) { PRINT("You must specify a filename.\n"); return EXIT_FAILURE; } START_THREAD(escaper, NO_PARAM); START_THREAD(app, argv); JOIN_THREAD(escaper); JOIN_THREAD(app); return EXIT_SUCCESS; }
C_RESULT ardrone_tool_shutdown_custom() { PRINT("Shutting down ... \n "); JOIN_THREAD(update_jde); delete jdeDriver; video_stage_resume_thread(); ardrone_tool_input_remove(&teleop); return C_OK; }
void appDeinit() { gAppAlive = 0; INFO("shutting down application...\n"); video_deinit(); JOIN_THREAD( mobile_main ); }
C_RESULT ardrone_tool_shutdown_custom () { // Unregister the game controller ardrone_tool_input_remove( &gamepad ); video_stage_resume_thread(); //Resume thread to kill it ! JOIN_THREAD(video_stage); return C_OK; }
DEFINE_THREAD_ROUTINE(mobile_main, data) { C_RESULT res = C_FAIL; char drone_address[64]; unsigned long theAddr; ardroneEngineCallback callback = (ardroneEngineCallback)data; vp_os_memset(drone_address, 0x0, sizeof(drone_address)); while((theAddr = deviceIPAddress(WIFI_ITFNAME, iphone_mac_address)) == LOCALHOST) { PRINT("Wait WIFI connection !\n"); vp_os_delay(250); } struct in_addr drone_addr; drone_addr.s_addr = htonl( ntohl((in_addr_t)theAddr) - 1 ); vp_os_memcpy(drone_address, inet_ntoa(drone_addr), strlen(inet_ntoa(drone_addr))); PRINT("Drone address %s\n", drone_address); PRINT("Iphone MAC Address %s\n", iphone_mac_address); res = ardrone_tool_setup_com( NULL ); if( FAILED(res) ) { PRINT("Wifi initialization failed. It means either:\n"); PRINT("\t* you're not root (it's mandatory because you can set up wifi connection only as root)\n"); PRINT("\t* wifi device is not present (on your pc or on your card)\n"); PRINT("\t* you set the wrong name for wifi interface (for example rausb0 instead of wlan0) \n"); PRINT("\t* ap is not up (reboot card or remove wifi usb dongle)\n"); PRINT("\t* wifi device has no antenna\n"); } else { res = ardrone_tool_init(drone_address, strlen(drone_address), NULL); callback(ARDRONE_ENGINE_INIT_OK); if(SUCCEED(res)) { START_THREAD(video_stage, NULL); res = ardrone_tool_set_refresh_time(1000 / kAPS); while( SUCCEED(res) && bContinue == TRUE ) { res = ardrone_tool_update(); } JOIN_THREAD(video_stage); } res = ardrone_tool_shutdown(); } return (THREAD_RET)0; }
int main(int argc, char **argv) { int i; buf_str ctx; memset(&ctx, 0, sizeof(buf_str)); ctx.p.period = PERIOD_SIZE; ctx.p.buf_max = 0xFFF;//TODO variable buf ctx.p.mutex = malloc(sizeof(MUTEX_T) * (ctx.p.buf_max + 1)); for (i = 0; i <= ctx.p.buf_max; i++) { MUTEX_INIT(ctx.p.mutex + i); } ctx.p.update = malloc(sizeof(unsigned char) * (ctx.p.buf_max + 1)); memset(ctx.p.update, 0, sizeof(unsigned char) * (ctx.p.buf_max + 1)); ctx.p.buf = malloc((ctx.p.buf_max + 1) * ctx.p.period * CHANNELS * BITS / 8); //FIXME memory allocation failed ctx.list = listing(argv + 1); if(!ctx.list) force_exit_signal = 1; else list_shuffle(ctx.list); THREAD_T play, buffer; #ifndef _WIN32 pthread_attr_t rt; struct sched_param p = {}; p.sched_priority = sched_get_priority_max(SCHED_RR); pthread_attr_init(&rt); pthread_attr_setinheritsched(&rt, PTHREAD_EXPLICIT_SCHED); pthread_attr_setschedpolicy(&rt, SCHED_RR); pthread_attr_setschedparam(&rt, &p); #endif CREATE_THREAD(buffer, buffer_thread, &ctx); CREATE_THREAD_RT(play, play_thread, &ctx.p, &rt); console(); JOIN_THREAD(buffer); JOIN_THREAD(play); list_full_remove(ctx.list); for (i = 0; i <= ctx.p.buf_max; i++) { MUTEX_DESTROY(ctx.p.mutex + i); } free(ctx.p.mutex); free(ctx.p.update); free(ctx.p.buf); return 0; }
/*-------------------------------------------------------------------- The delegate object calls this method when the event loop exit --------------------------------------------------------------------*/ C_RESULT ardrone_tool_shutdown_custom() { /* Relinquish all threads of your application */ JOIN_THREAD( video_stage ); /* Unregistering for the current device */ ardrone_tool_input_remove( &dx_gamepad ); ardrone_tool_input_remove( &dx_keyboard ); vp_os_mutex_destroy(&consoleMutex); return C_OK; }
DEFINE_THREAD_ROUTINE(mobile_main, data) { __android_log_print( ANDROID_LOG_INFO, "ARDrone", "Enter in mobile_main thread\n" ); C_RESULT res = C_OK; char drone_address[24]; vp_os_memset(drone_address, 0x0, sizeof(drone_address)); sprintf(drone_address, WIFI_ARDRONE_IP); res = ardrone_tool_setup_com( NULL ); if( FAILED(res) ) { __android_log_print( ANDROID_LOG_INFO, "ARDrone", "Setup com failed\n" ); INFO("Wifi initialization failed. It means either:\n"); INFO("\t* you're not root (it's mandatory because you can set up wifi connection only as root)\n"); INFO("\t* wifi device is not present (on your pc or on your card)\n"); INFO("\t* you set the wrong name for wifi interface (for example rausb0 instead of wlan0) \n"); INFO("\t* ap is not up (reboot card or remove wifi usb dongle)\n"); INFO("\t* wifi device has no antenna\n"); } else { START_THREAD(video_stage, NULL); __android_log_print( ANDROID_LOG_INFO, "ARDrone", "Processing ardrone_tool_init\n" ); res = ardrone_tool_init(drone_address, strlen(drone_address), NULL); control_ack_init(); control_ack_configure_navdata_demo( FALSE ); if(SUCCEED(res)) { res = ardrone_tool_set_refresh_time(25); while( SUCCEED(res) && bContinue == TRUE ) { res = ardrone_tool_update(); } } JOIN_THREAD(video_stage); res = ardrone_tool_shutdown(); } __android_log_print( ANDROID_LOG_INFO, "ARDrone", "Exit mobile_main thread\n" ); return (THREAD_RET)0; }
/*-------------------------------------------------------------------- The delegate object calls this method when the event loop exit --------------------------------------------------------------------*/ C_RESULT ardrone_tool_shutdown_custom() { /* Relinquish all threads of your application */ JOIN_THREAD( video_stage ); /* Unregistering for the current device */ //ardrone_tool_input_remove( &dx_gamepad ); //ardrone_tool_input_remove( &dx_keyboard ); /* Mutex needs to be destroyed but may still be used by navdata thread */ /* todo : synchronize threads shutdown */ //vp_os_mutex_destroy(&consoleMutex); return C_OK; }
int drone_free() { pthread_mutex_lock(&drone_sharedDataMutex); pthread_mutex_lock(&drone_navdataCallbackMutex); drone_doRun = 0; drone_navdataCallback = NULL; pthread_mutex_unlock(&drone_navdataCallbackMutex); pthread_mutex_unlock(&drone_sharedDataMutex); printf("Joining main thread\n"); JOIN_THREAD(drone_main_thread); drone_doRunArdrone = 0; if (drone_receivedFirstNavdata) { ardrone_tool_shutdown(); } else { fprintf(stderr, "Warning! Did not shut down ardrone_tool because there was never a connection with the drone (freeze protection)!"); } drone_userdata = NULL; return 1; }
DEFINE_THREAD_ROUTINE(app_main, data) { C_RESULT res = C_FAIL; vp_com_wifi_config_t* config = NULL; JNIEnv* env = NULL; if (g_vm) { (*g_vm)->AttachCurrentThread (g_vm, (JNIEnv **) &env, NULL); } bContinue = TRUE; mobile_main_param_t *param = data; video_recorder_thread_param_t video_recorder_param; video_recorder_param.priority = VIDEO_RECORDER_THREAD_PRIORITY; video_recorder_param.finish_callback = param->academy_download_callback_func; vp_os_memset(&ardrone_info, 0x0, sizeof(ardrone_info_t)); while ((config = (vp_com_wifi_config_t *)wifi_config()) != NULL && strlen(config->itfName) == 0) { //Waiting for wifi initialization vp_os_delay(250); if (ardrone_tool_exit() == TRUE) { if (param != NULL && param->callback != NULL) { param->callback(env, param->obj, ARDRONE_MESSAGE_DISCONNECTED); } return 0; } } vp_os_memcpy(&ardrone_info.drone_address[0], config->server, strlen(config->server)); while (-1 == getDroneVersion (param->root_dir, &ardrone_info.drone_address[0], &ardroneVersion)) { LOGD (TAG, "Getting AR.Drone version"); vp_os_delay (250); } sprintf(&ardrone_info.drone_version[0], "%u.%u.%u", ardroneVersion.majorVersion, ardroneVersion.minorVersion, ardroneVersion.revision); LOGD (TAG, "ARDrone Version : %s\n", &ardrone_info.drone_version[0]); LOGI(TAG, "Drone Family: %d", ARDRONE_VERSION()); res = ardrone_tool_setup_com( NULL ); if( FAILED(res) ) { LOGII("Setup com failed"); LOGW(TAG, "Wifi initialization failed. It means either:"); LOGW(TAG, "\t* you're not root (it's mandatory because you can set up wifi connection only as root)\n"); LOGW(TAG, "\t* wifi device is not present (on your pc or on your card)\n"); LOGW(TAG, "\t* you set the wrong name for wifi interface (for example rausb0 instead of wlan0) \n"); LOGW(TAG, "\t* ap is not up (reboot card or remove wifi usb dongle)\n"); LOGW(TAG, "\t* wifi device has no antenna\n"); if (param != NULL && param->callback != NULL) { param->callback(env, param->obj, ARDRONE_MESSAGE_ERR_NO_WIFI); } } else { LOGII("ardrone_tool_setup_com [OK]"); #define NB_IPHONE_PRE_STAGES 0 #define NB_IPHONE_POST_STAGES 2 //Alloc structs specific_parameters_t * params = (specific_parameters_t *)vp_os_calloc(1, sizeof(specific_parameters_t)); specific_stages_t * iphone_pre_stages = (specific_stages_t*)vp_os_calloc(1, sizeof(specific_stages_t)); specific_stages_t * iphone_post_stages = (specific_stages_t*)vp_os_calloc(1, sizeof(specific_stages_t)); vp_api_picture_t * in_picture = (vp_api_picture_t*) vp_os_calloc(1, sizeof(vp_api_picture_t)); vp_api_picture_t * out_picture = (vp_api_picture_t*) vp_os_calloc(1, sizeof(vp_api_picture_t)); in_picture->width = STREAM_WIDTH; in_picture->height = STREAM_HEIGHT; out_picture->framerate = 20; out_picture->format = PIX_FMT_RGB565; out_picture->width = STREAM_WIDTH; out_picture->height = STREAM_HEIGHT; out_picture->y_buf = vp_os_malloc( STREAM_WIDTH * STREAM_HEIGHT * 2 ); out_picture->cr_buf = NULL; out_picture->cb_buf = NULL; out_picture->y_line_size = STREAM_WIDTH * 2; out_picture->cb_line_size = 0; out_picture->cr_line_size = 0; //Define the list of stages size iphone_pre_stages->length = NB_IPHONE_PRE_STAGES; iphone_post_stages->length = NB_IPHONE_POST_STAGES; //Alloc the lists iphone_pre_stages->stages_list = NULL; iphone_post_stages->stages_list = (vp_api_io_stage_t*)vp_os_calloc(iphone_post_stages->length,sizeof(vp_api_io_stage_t)); //Fill the POST-stages------------------------------------------------------ int postStageNumber = 0; vp_os_memset (&vlat, 0x0, sizeof (vlat)); vlat.state = 0; vlat.last_decoded_frame_info= (void *)&vec; iphone_post_stages->stages_list[postStageNumber].type = VP_API_FILTER_DECODER; iphone_post_stages->stages_list[postStageNumber].cfg = (void *)&vlat; iphone_post_stages->stages_list[postStageNumber++].funcs = vp_stages_latency_estimation_funcs; vp_os_memset (&ovsc, 0x0, sizeof (ovsc)); ovsc.video_decoder = &vec; iphone_post_stages->stages_list[postStageNumber].type = VP_API_OUTPUT_LCD; iphone_post_stages->stages_list[postStageNumber].cfg = (void *)&ovsc; iphone_post_stages->stages_list[postStageNumber++].funcs = opengl_video_stage_funcs; params->in_pic = in_picture; params->out_pic = out_picture; params->pre_processing_stages_list = iphone_pre_stages; params->post_processing_stages_list = iphone_post_stages; #if USE_THREAD_PRIORITIES params->needSetPriority = 1; params->priority = VIDEO_THREAD_PRIORITY; #else params->needSetPriority = 0; params->priority = 0; #endif START_THREAD(video_stage, params); if (IS_LEAST_ARDRONE2) { START_THREAD (video_recorder, (void *)&video_recorder_param); LOGD(TAG, "Video recorder thread start [OK]"); } res = ardrone_tool_init(&ardrone_info.drone_address[0], strlen(&ardrone_info.drone_address[0]), NULL, param->app_name, param->user_name, param->root_dir, param->flight_dir, param->flight_storing_size, param->academy_download_callback_func); if(SUCCEED(res)) { ardrone_tool_input_add(&virtual_gamepad); if (param != NULL && param->callback != NULL) { param->callback(env, param->obj, ARDRONE_MESSAGE_CONNECTED_OK); } } else { if (param != NULL && param->callback != NULL) { param->callback(env, param->obj, ARDRONE_MESSAGE_UNKNOWN_ERR); } bContinue = FALSE; } res = ardrone_tool_set_refresh_time(1000 / kAPS); #if USE_THREAD_PRIORITIES CHANGE_THREAD_PRIO (app_main, AT_THREAD_PRIORITY); CHANGE_THREAD_PRIO (navdata_update, NAVDATA_THREAD_PRIORITY); CHANGE_THREAD_PRIO (ardrone_control, NAVDATA_THREAD_PRIORITY); #endif while( SUCCEED(res) && bContinue == TRUE ) { ardrone_tool_update(); } JOIN_THREAD(video_stage); if (IS_LEAST_ARDRONE2) { JOIN_THREAD (video_recorder); } /* Unregistering for the current device */ ardrone_tool_input_remove( &virtual_gamepad ); res = ardrone_tool_shutdown(); LOGD(TAG, "AR.Drone tool shutdown [OK]"); if (param != NULL && param->callback != NULL) { param->callback(env, param->obj, ARDRONE_MESSAGE_DISCONNECTED); } } vp_os_free (data); data = NULL; (*env)->DeleteGlobalRef(env, param->obj); if (g_vm) { (*g_vm)->DetachCurrentThread (g_vm); } LOGI(TAG, "app_main thread has been stopped."); return (THREAD_RET) res; }
DEFINE_THREAD_ROUTINE(ihm, data) { C_RESULT res; WSADATA wsaData = {0}; int iResult = 0; /* Initializes Windows socket subsystem */ iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { wprintf(L"WSAStartup failed: %d\n", iResult); return 1; } /* Initializes communication sockets */ res = test_drone_connection(); // Nick disabled the press enter (wait) if(res!=0) { printf("%s","Could not detect the drone version ... press <Enter> to try connecting anyway.\n"); getchar(); //WSACleanup(); exit(-1); } res = ardrone_tool_setup_com( NULL ); if( FAILED(res) ) { PRINT("Wifi initialization failed.\n"); return -1; } START_THREAD(video_stage, 0); res = ardrone_tool_init(WIFI_ARDRONE_IP, strlen(WIFI_ARDRONE_IP), NULL, ARDRONE_CLIENT_APPNAME, ARDRONE_CLIENT_USRNAME); ardrone_tool_set_refresh_time(20); // 20 ms ardrone_at_reset_com_watchdog(); // config ardrone_control_config.euler_angle_max = 0.20943951f; // 12 degrees ardrone_control_config.video_channel = ZAP_CHANNEL_VERT; ardrone_control_config.video_codec = UVLC_CODEC; //P264_CODEC; ardrone_control_config.navdata_demo = FALSE; ardrone_control_config.altitude_max = 10000; ardrone_control_config.control_vz_max = 1000.0f; ardrone_control_config.outdoor = FALSE; //ardrone_control_config.flight_without_shell = TRUE; ARDRONE_TOOL_CONFIGURATION_ADDEVENT(video_channel, &ardrone_control_config.video_channel, (ardrone_tool_configuration_callback) ardrone_demo_config_callback); //ARDRONE_TOOL_CONFIGURATION_ADDEVENT(video_channel, &ardrone_control_config.video_channel, NULL); //ARDRONE_TOOL_CONFIGURATION_ADDEVENT(video_codec, &ardrone_control_config.video_codec, NULL); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (navdata_demo, &ardrone_control_config.navdata_demo, NULL); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (altitude_max, &ardrone_control_config.altitude_max, NULL); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (control_vz_max, &ardrone_control_config.control_vz_max, NULL); //ARDRONE_TOOL_CONFIGURATION_ADDEVENT (outdoor, &ardrone_control_config.outdoor, NULL); //ARDRONE_TOOL_CONFIGURATION_ADDEVENT (flight_without_shell, &ardrone_control_config.flight_without_shell, NULL); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (euler_angle_max, &ardrone_control_config.euler_angle_max, NULL); // flat trim ardrone_at_set_flat_trim(); //SetEvent(ardrone_ready); //ardrone_demo_redirect_to_interface = 1; while( VP_SUCCEEDED(res) && ardrone_tool_exit() == FALSE ) { res = ardrone_tool_update(); } JOIN_THREAD(video_stage); res = ardrone_tool_shutdown(); WSACleanup(); return (THREAD_RET)res; }