@ -1,10 +1,11 @@ 
			
		
	
		
		
			
				
					
					# include  <stdio.h> # include  <stdio.h>  
			
		
	
		
		
			
				
					
					# include  <stdlib.h> # include  <stdlib.h>  
			
		
	
		
		
			
				
					
					# include  <stdbool.h> # include  <stdbool.h>  
			
		
	
		
		
			
				
					
					# include  <signal.h>  
			
		
	
		
		
			
				
					
					# include  <unistd.h> # include  <unistd.h>  
			
		
	
		
		
			
				
					
					# include  <assert.h> # include  <assert.h>  
			
		
	
		
		
			
				
					
					# include  <poll.h>  
			
		
	
		
		
			
				
					
					# include  <sys/mman.h> # include  <sys/mman.h>  
			
		
	
		
		
			
				
					
					# include  <czmq.h>  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					# include  "common/util.h" # include  "common/util.h"  
			
		
	
		
		
			
				
					
					# include  "common/swaglog.h" # include  "common/swaglog.h"  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -15,23 +16,20 @@ 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					extern  volatile  sig_atomic_t  do_exit ; extern  volatile  sig_atomic_t  do_exit ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					int  write_param_float ( float  param ,  const  char *  param_name ,  bool  persistent_param )  { int  write_param_float ( float  param ,  const  char *  param_name ,  bool  persistent_param )  {  
			
		
	
		
		
			
				
					
					  char  s [ 16 ] ;    char  s [ 16 ] ;   
			
		
	
		
		
			
				
					
					  int  size  =  snprintf ( s ,  sizeof ( s ) ,  " %f " ,  param ) ;    int  size  =  snprintf ( s ,  sizeof ( s ) ,  " %f " ,  param ) ;   
			
		
	
		
		
			
				
					
					  return  write_db_value ( param_name ,  s ,  MIN ( size ,  sizeof ( s ) ) ,  persistent_param ) ;    return  write_db_value ( param_name ,  s ,  size  <  sizeof ( s )  ?  size  :  sizeof ( s ) ,  persistent_param ) ;   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void  ui_init ( UIState  * s )  { void  ui_init ( UIState  * s )  {  
			
		
	
		
		
			
				
					
					  pthread_mutex_init ( & s - > lock ,  NULL ) ;   
			
		
	
		
		
			
				
					
					  s - > sm  =  new  SubMaster ( { " model " ,  " controlsState " ,  " uiLayoutState " ,  " liveCalibration " ,  " radarState " ,  " thermal " ,    s - > sm  =  new  SubMaster ( { " model " ,  " controlsState " ,  " uiLayoutState " ,  " liveCalibration " ,  " radarState " ,  " thermal " ,   
			
		
	
		
		
			
				
					
					                         " health " ,  " carParams " ,  " ubloxGnss " ,  " driverState " ,  " dMonitoringState "                           " health " ,  " carParams " ,  " ubloxGnss " ,  " driverState " ,  " dMonitoringState " } ) ;   
			
				
				
			
		
	
		
		
			
				
					
					  } ) ;   
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > ipc_fd  =  - 1 ;   
			
		
	
		
		
			
				
					
					  s - > scene . satelliteCount  =  - 1 ;   
			
		
	
		
		
			
				
					
					  s - > started  =  false ;    s - > started  =  false ;   
			
		
	
		
		
			
				
					
					  s - > vision_seen  =  false ;    s - > status  =  STATUS_OFFROAD ;   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					  s - > scene . satelliteCount  =  - 1 ;   
			
		
	
		
		
			
				
					
					  read_param ( & s - > is_metric ,  " IsMetric " ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > fb  =  framebuffer_init ( " ui " ,  0 ,  true ,  & s - > fb_w ,  & s - > fb_h ) ;    s - > fb  =  framebuffer_init ( " ui " ,  0 ,  true ,  & s - > fb_w ,  & s - > fb_h ) ;   
			
		
	
		
		
			
				
					
					  assert ( s - > fb ) ;    assert ( s - > fb ) ;   
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -39,41 +37,72 @@ void ui_init(UIState *s) { 
			
		
	
		
		
			
				
					
					  ui_nvg_init ( s ) ;    ui_nvg_init ( s ) ;   
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  void  ui_init_vision ( UIState  * s ,  const  VisionStreamBufs  back_bufs , static  void  ui_init_vision ( UIState  * s )  {  
			
				
				
			
		
	
		
		
			
				
					
					                           int  num_back_fds ,  const  int  * back_fds ,    // Invisible until we receive a calibration message.
   
			
				
				
			
		
	
		
		
			
				
					
					                           const  VisionStreamBufs  front_bufs ,  int  num_front_fds ,    s - > scene . world_objects_visible  =  false ;   
			
				
				
			
		
	
		
		
			
				
					
					                           const  int  * front_fds )  {   
			
		
	
		
		
			
				
					
					  assert ( num_back_fds  = =  UI_BUF_COUNT ) ;   
			
		
	
		
		
			
				
					
					  assert ( num_front_fds  = =  UI_BUF_COUNT ) ;   
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  vipc_bufs_load ( s - > bufs ,  & back_bufs ,  num_back_fds ,  back_fds ) ;    for  ( int  i  =  0 ;  i  <  UI_BUF_COUNT ;  i + + )  {   
			
				
				
			
		
	
		
		
			
				
					
					  vipc_bufs_load ( s - > front_bufs ,  & front_bufs ,  num_front_fds ,  front_fds ) ;      if  ( s - > khr [ i ]  ! =  0 )  {   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					      visionimg_destroy_gl ( s - > khr [ i ] ,  s - > priv_hnds [ i ] ) ;   
			
		
	
		
		
			
				
					
					      glDeleteTextures ( 1 ,  & s - > frame_texs [ i ] ) ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > cur_vision_idx  =  - 1 ;      VisionImg  img  =  {   
			
				
				
			
		
	
		
		
			
				
					
					  s - > cur_vision_front_idx  =  - 1 ;        . fd  =  s - > stream . bufs [ i ] . fd ,   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					      . format  =  VISIONIMG_FORMAT_RGB24 ,   
			
		
	
		
		
			
				
					
					      . width  =  s - > stream . bufs_info . width ,   
			
		
	
		
		
			
				
					
					      . height  =  s - > stream . bufs_info . height ,   
			
		
	
		
		
			
				
					
					      . stride  =  s - > stream . bufs_info . stride ,   
			
		
	
		
		
			
				
					
					      . bpp  =  3 ,   
			
		
	
		
		
			
				
					
					      . size  =  s - > stream . bufs_info . buf_len ,   
			
		
	
		
		
			
				
					
					    } ;   
			
		
	
		
		
			
				
					
					# ifndef QCOM  
			
		
	
		
		
			
				
					
					    s - > priv_hnds [ i ]  =  s - > stream . bufs [ i ] . addr ;   
			
		
	
		
		
			
				
					
					# endif  
			
		
	
		
		
			
				
					
					    s - > frame_texs [ i ]  =  visionimg_to_gl ( & img ,  & s - > khr [ i ] ,  & s - > priv_hnds [ i ] ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    glBindTexture ( GL_TEXTURE_2D ,  s - > frame_texs [ i ] ) ;   
			
		
	
		
		
			
				
					
					    glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_MAG_FILTER ,  GL_NEAREST ) ;   
			
		
	
		
		
			
				
					
					    glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_MIN_FILTER ,  GL_NEAREST ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    // BGR
   
			
		
	
		
		
			
				
					
					    glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_R ,  GL_BLUE ) ;   
			
		
	
		
		
			
				
					
					    glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_G ,  GL_GREEN ) ;   
			
		
	
		
		
			
				
					
					    glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_B ,  GL_RED ) ;   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					  assert ( glGetError ( )  = =  GL_NO_ERROR ) ;   
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > scene . frontview  =  getenv ( " FRONTVIEW " )  ! =  NULL ;  void  ui_update_vision ( UIState  * s )  {  
			
				
				
			
		
	
		
		
			
				
					
					  s - > scene . fullview  =  getenv ( " FULLVIEW " )  ! =  NULL ;   
			
		
	
		
		
			
				
					
					  s - > scene . world_objects_visible  =  false ;   // Invisible until we receive a calibration message.
   
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > rgb_width  =  back_bufs . width ;    if  ( ! s - > vision_connected  & &  s - > started )  {   
			
				
				
			
		
	
		
		
			
				
					
					  s - > rgb_height  =  back_bufs . height ;      const  VisionStreamType  type  =  s - > scene . frontview  ?  VISION_STREAM_RGB_FRONT  :  VISION_STREAM_RGB_BACK ;   
			
				
				
			
		
	
		
		
			
				
					
					  s - > rgb_stride  =  back_bufs . stride ;      int  err  =  visionstream_init ( & s - > stream ,  type ,  true ,  nullptr ) ;   
			
				
				
			
		
	
		
		
			
				
					
					  s - > rgb_buf_len  =  back_bufs . buf_len ;      if  ( err  = =  0 )  {   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					      ui_init_vision ( s ) ;   
			
		
	
		
		
			
				
					
					      s - > vision_connected  =  true ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > rgb_front_width  =  front_bufs . width ;    if  ( s - > vision_connected )  {   
			
				
				
			
		
	
		
		
			
				
					
					  s - > rgb_front_height  =  front_bufs . height ;      if  ( ! s - > started )  goto  destroy ;   
			
				
				
			
		
	
		
		
			
				
					
					  s - > rgb_front_stride  =  front_bufs . stride ;  
 
			
				
				
			
		
	
		
		
			
				
					
					  s - > rgb_front_buf_len  =  front_bufs . buf_len ;      // poll for a new frame
   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					    struct  pollfd  fds [ 1 ]  =  { {   
			
		
	
		
		
			
				
					
					      . fd  =  s - > stream . ipc_fd ,   
			
		
	
		
		
			
				
					
					      . events  =  POLLOUT ,   
			
		
	
		
		
			
				
					
					    } } ;   
			
		
	
		
		
			
				
					
					    int  ret  =  poll ( fds ,  1 ,  100 ) ;   
			
		
	
		
		
			
				
					
					    if  ( ret  >  0 )  {   
			
		
	
		
		
			
				
					
					      if  ( ! visionstream_get ( & s - > stream ,  nullptr ) )  goto  destroy ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  read_param ( & s - > is_metric ,  " IsMetric " ) ;    return ;   
			
				
				
			
		
	
		
		
			
				
					
					  read_param ( & s - > longitudinal_control ,  " LongitudinalControl " ) ;   
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void  update_status ( UIState  * s ,  int  status )  { destroy :  
			
				
				
			
		
	
		
		
			
				
					
					  if  ( s - > status  ! =  status )  {    visionstream_destroy ( & s - > stream ) ;   
			
				
				
			
		
	
		
		
			
				
					
					    s - > status  =  status ;    s - > vision_connected  =  false ;   
			
				
				
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  inline  void  fill_path_points ( const  cereal : : ModelData : : PathData : : Reader  & path ,  float  * points )  { static  inline  void  fill_path_points ( const  cereal : : ModelData : : PathData : : Reader  & path ,  float  * points )  {  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -83,13 +112,21 @@ static inline void fill_path_points(const cereal::ModelData::PathData::Reader &p 
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void  handle_message ( UIState  * s ,  SubMaster  & sm )  { void  update_sockets ( UIState  * s )  {  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  UIScene  & scene  =  s - > scene ;    UIScene  & scene  =  s - > scene ;   
			
		
	
		
		
			
				
					
					  SubMaster  & sm  =  * ( s - > sm ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  // poll sockets
   
			
		
	
		
		
			
				
					
					  if  ( sm . update ( 0 )  = =  0 ) {   
			
		
	
		
		
			
				
					
					    return ;   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  if  ( s - > started  & &  sm . updated ( " controlsState " ) )  {    if  ( s - > started  & &  sm . updated ( " controlsState " ) )  {   
			
		
	
		
		
			
				
					
					    auto  event  =  sm [ " controlsState " ] ;      auto  event  =  sm [ " controlsState " ] ;   
			
		
	
		
		
			
				
					
					    scene . controls_state  =  event . getControlsState ( ) ;      scene . controls_state  =  event . getControlsState ( ) ;   
			
		
	
		
		
			
				
					
					    s - > controls_seen  =  true ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    // TODO: the alert stuff shouldn't be handled here
   
			
		
	
		
		
			
				
					
					    auto  alert_sound  =  scene . controls_state . getAlertSound ( ) ;      auto  alert_sound  =  scene . controls_state . getAlertSound ( ) ;   
			
		
	
		
		
			
				
					
					    if  ( scene . alert_type . compare ( scene . controls_state . getAlertType ( ) )  ! =  0 )  {      if  ( scene . alert_type . compare ( scene . controls_state . getAlertType ( ) )  ! =  0 )  {   
			
		
	
		
		
			
				
					
					      if  ( alert_sound  = =  AudibleAlert : : NONE )  {        if  ( alert_sound  = =  AudibleAlert : : NONE )  {   
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -104,11 +141,11 @@ void handle_message(UIState *s, SubMaster &sm) { 
			
		
	
		
		
			
				
					
					    scene . alert_type  =  scene . controls_state . getAlertType ( ) ;      scene . alert_type  =  scene . controls_state . getAlertType ( ) ;   
			
		
	
		
		
			
				
					
					    auto  alertStatus  =  scene . controls_state . getAlertStatus ( ) ;      auto  alertStatus  =  scene . controls_state . getAlertStatus ( ) ;   
			
		
	
		
		
			
				
					
					    if  ( alertStatus  = =  cereal : : ControlsState : : AlertStatus : : USER_PROMPT )  {      if  ( alertStatus  = =  cereal : : ControlsState : : AlertStatus : : USER_PROMPT )  {   
			
		
	
		
		
			
				
					
					      update_status ( s ,  STATUS_WARNING ) ;        s - > status  =  STATUS_WARNING ;   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    }  else  if  ( alertStatus  = =  cereal : : ControlsState : : AlertStatus : : CRITICAL )  {      }  else  if  ( alertStatus  = =  cereal : : ControlsState : : AlertStatus : : CRITICAL )  {   
			
		
	
		
		
			
				
					
					      update_status ( s ,  STATUS_ALERT ) ;        s - > status  =  STATUS_ALERT ;   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    }  else {      }  else {   
			
		
	
		
		
			
				
					
					      update_status ( s , scene . controls_state . getEnabled ( )  ?  STATUS_ENGAGED  :  STATUS_DISENGAGED ) ;        s - > status  = scene . controls_state . getEnabled ( )  ?  STATUS_ENGAGED  :  STATUS_DISENGAGED ;   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    }      }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    float  alert_blinkingrate  =  scene . controls_state . getAlertBlinkingRate ( ) ;      float  alert_blinkingrate  =  scene . controls_state . getAlertBlinkingRate ( ) ;   
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -147,16 +184,6 @@ void handle_message(UIState *s, SubMaster &sm) { 
			
		
	
		
		
			
				
					
					    fill_path_points ( scene . model . getLeftLane ( ) ,  scene . left_lane_points ) ;      fill_path_points ( scene . model . getLeftLane ( ) ,  scene . left_lane_points ) ;   
			
		
	
		
		
			
				
					
					    fill_path_points ( scene . model . getRightLane ( ) ,  scene . right_lane_points ) ;      fill_path_points ( scene . model . getRightLane ( ) ,  scene . right_lane_points ) ;   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					  // else if (which == cereal::Event::LIVE_MPC) {
   
			
		
	
		
		
			
				
					
					  //   auto data = event.getLiveMpc();
   
			
		
	
		
		
			
				
					
					  //   auto x_list = data.getX();
   
			
		
	
		
		
			
				
					
					  //   auto y_list = data.getY();
   
			
		
	
		
		
			
				
					
					  //   for (int i = 0; i < 50; i++){
   
			
		
	
		
		
			
				
					
					  //     scene.mpc_x[i] = x_list[i];
   
			
		
	
		
		
			
				
					
					  //     scene.mpc_y[i] = y_list[i];
   
			
		
	
		
		
			
				
					
					  //   }
   
			
		
	
		
		
			
				
					
					  //   s->livempc_or_radarstate_changed = true;
   
			
		
	
		
		
			
				
					
					  // }
   
			
		
	
		
		
			
				
					
					  if  ( sm . updated ( " uiLayoutState " ) )  {    if  ( sm . updated ( " uiLayoutState " ) )  {   
			
		
	
		
		
			
				
					
					    auto  data  =  sm [ " uiLayoutState " ] . getUiLayoutState ( ) ;      auto  data  =  sm [ " uiLayoutState " ] . getUiLayoutState ( ) ;   
			
		
	
		
		
			
				
					
					    s - > active_app  =  data . getActiveApp ( ) ;      s - > active_app  =  data . getActiveApp ( ) ;   
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -173,6 +200,8 @@ void handle_message(UIState *s, SubMaster &sm) { 
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					  if  ( sm . updated ( " health " ) )  {    if  ( sm . updated ( " health " ) )  {   
			
		
	
		
		
			
				
					
					    scene . hwType  =  sm [ " health " ] . getHealth ( ) . getHwType ( ) ;      scene . hwType  =  sm [ " health " ] . getHealth ( ) . getHwType ( ) ;   
			
		
	
		
		
			
				
					
					  }  else  if  ( ( s - > sm - > frame  -  s - > sm - > rcv_frame ( " health " ) )  >  5 * UI_FREQ )  {   
			
		
	
		
		
			
				
					
					    scene . hwType  =  cereal : : HealthData : : HwType : : UNKNOWN ;   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					  if  ( sm . updated ( " carParams " ) )  {    if  ( sm . updated ( " carParams " ) )  {   
			
		
	
		
		
			
				
					
					    s - > longitudinal_control  =  sm [ " carParams " ] . getCarParams ( ) . getOpenpilotLongitudinalControl ( ) ;      s - > longitudinal_control  =  sm [ " carParams " ] . getCarParams ( ) . getOpenpilotLongitudinalControl ( ) ;   
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -184,267 +213,67 @@ void handle_message(UIState *s, SubMaster &sm) { 
			
		
	
		
		
			
				
					
					    scene . dmonitoring_state  =  sm [ " dMonitoringState " ] . getDMonitoringState ( ) ;      scene . dmonitoring_state  =  sm [ " dMonitoringState " ] . getDMonitoringState ( ) ;   
			
		
	
		
		
			
				
					
					    scene . is_rhd  =  scene . dmonitoring_state . getIsRHD ( ) ;      scene . is_rhd  =  scene . dmonitoring_state . getIsRHD ( ) ;   
			
		
	
		
		
			
				
					
					    scene . frontview  =  scene . dmonitoring_state . getIsPreview ( ) ;      scene . frontview  =  scene . dmonitoring_state . getIsPreview ( ) ;   
			
		
	
		
		
			
				
					
					  }  else  if  ( ( sm . frame  -  sm . rcv_frame ( " dMonitoringState " ) )  >  1 * UI_FREQ )  {    }  else  if  ( ( sm . frame  -  sm . rcv_frame ( " dMonitoringState " ) )  >  UI_FREQ / 2 )  {   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    scene . frontview  =  false ;      scene . frontview  =  false ;   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  s - > started  =  scene . thermal . getStarted ( )  | |  scene . frontview ;    s - > started  =  scene . thermal . getStarted ( )  | |  scene . frontview ;   
			
		
	
		
		
			
				
					
					  // Handle onroad/offroad transition
   
			
		
	
		
		
			
				
					
					  if  ( ! s - > started )  {   
			
		
	
		
		
			
				
					
					    if  ( s - > status  ! =  STATUS_STOPPED )  {   
			
		
	
		
		
			
				
					
					      update_status ( s ,  STATUS_STOPPED ) ;   
			
		
	
		
		
			
				
					
					      s - > vision_seen  =  false ;   
			
		
	
		
		
			
				
					
					      s - > controls_seen  =  false ;   
			
		
	
		
		
			
				
					
					      s - > active_app  =  cereal : : UiLayoutState : : App : : HOME ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					  }  else  if  ( s - > status  = =  STATUS_STOPPED )  {   
			
		
	
		
		
			
				
					
					    update_status ( s ,  STATUS_DISENGAGED ) ;   
			
		
	
		
		
			
				
					
					    s - > active_app  =  cereal : : UiLayoutState : : App : : NONE ;   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void  check_messages ( UIState  * s )  {  
			
		
	
		
		
			
				
					
					  if  ( s - > sm - > update ( 0 )  >  0 ) {   
			
		
	
		
		
			
				
					
					    handle_message ( s ,  * ( s - > sm ) ) ;   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void  ui_update_sizes ( UIState  * s ) {  
			
		
	
		
		
			
				
					
					  // resize vision for collapsing sidebar
   
			
		
	
		
		
			
				
					
					  const  bool  hasSidebar  =  ! s - > scene . uilayout_sidebarcollapsed ;   
			
		
	
		
		
			
				
					
					  s - > scene . ui_viz_rx  =  hasSidebar  ?  box_x  :  ( box_x  -  sbr_w  +  ( bdr_s  *  2 ) ) ;   
			
		
	
		
		
			
				
					
					  s - > scene . ui_viz_rw  =  hasSidebar  ?  box_w  :  ( box_w  +  sbr_w  -  ( bdr_s  *  2 ) ) ;   
			
		
	
		
		
			
				
					
					  s - > scene . ui_viz_ro  =  hasSidebar  ?  - ( sbr_w  -  6  *  bdr_s )  :  0 ;   
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void  ui_update ( UIState  * s )  { void  ui_update ( UIState  * s )  {  
			
		
	
		
		
			
				
					
					  int  err ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  if  ( s - > vision_connect_firstrun )  {   
			
		
	
		
		
			
				
					
					    // cant run this in connector thread because opengl.
   
			
		
	
		
		
			
				
					
					    // do this here for now in lieu of a run_on_main_thread event
   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    for  ( int  i = 0 ;  i < UI_BUF_COUNT ;  i + + )  {   
			
		
	
		
		
			
				
					
					      if ( s - > khr [ i ]  ! =  0 )  {   
			
		
	
		
		
			
				
					
					        visionimg_destroy_gl ( s - > khr [ i ] ,  s - > priv_hnds [ i ] ) ;   
			
		
	
		
		
			
				
					
					        glDeleteTextures ( 1 ,  & s - > frame_texs [ i ] ) ;   
			
		
	
		
		
			
				
					
					      }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      VisionImg  img  =  {   
			
		
	
		
		
			
				
					
					        . fd  =  s - > bufs [ i ] . fd ,   
			
		
	
		
		
			
				
					
					        . format  =  VISIONIMG_FORMAT_RGB24 ,   
			
		
	
		
		
			
				
					
					        . width  =  s - > rgb_width ,   
			
		
	
		
		
			
				
					
					        . height  =  s - > rgb_height ,   
			
		
	
		
		
			
				
					
					        . stride  =  s - > rgb_stride ,   
			
		
	
		
		
			
				
					
					        . bpp  =  3 ,   
			
		
	
		
		
			
				
					
					        . size  =  s - > rgb_buf_len ,   
			
		
	
		
		
			
				
					
					      } ;   
			
		
	
		
		
			
				
					
					      # ifndef QCOM   
			
		
	
		
		
			
				
					
					        s - > priv_hnds [ i ]  =  s - > bufs [ i ] . addr ;   
			
		
	
		
		
			
				
					
					      # endif   
			
		
	
		
		
			
				
					
					      s - > frame_texs [ i ]  =  visionimg_to_gl ( & img ,  & s - > khr [ i ] ,  & s - > priv_hnds [ i ] ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      glBindTexture ( GL_TEXTURE_2D ,  s - > frame_texs [ i ] ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_MAG_FILTER ,  GL_NEAREST ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_MIN_FILTER ,  GL_NEAREST ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      // BGR
   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_R ,  GL_BLUE ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_G ,  GL_GREEN ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_B ,  GL_RED ) ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    for  ( int  i = 0 ;  i < UI_BUF_COUNT ;  i + + )  {   
			
		
	
		
		
			
				
					
					      if ( s - > khr_front [ i ]  ! =  0 )  {   
			
		
	
		
		
			
				
					
					        visionimg_destroy_gl ( s - > khr_front [ i ] ,  s - > priv_hnds_front [ i ] ) ;   
			
		
	
		
		
			
				
					
					        glDeleteTextures ( 1 ,  & s - > frame_front_texs [ i ] ) ;   
			
		
	
		
		
			
				
					
					      }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      VisionImg  img  =  {    update_sockets ( s ) ;   
			
				
				
			
		
	
		
		
			
				
					
					        . fd  =  s - > front_bufs [ i ] . fd ,    ui_update_vision ( s ) ;   
			
				
				
			
		
	
		
		
			
				
					
					        . format  =  VISIONIMG_FORMAT_RGB24 ,   
			
		
	
		
		
			
				
					
					        . width  =  s - > rgb_front_width ,   
			
		
	
		
		
			
				
					
					        . height  =  s - > rgb_front_height ,   
			
		
	
		
		
			
				
					
					        . stride  =  s - > rgb_front_stride ,   
			
		
	
		
		
			
				
					
					        . bpp  =  3 ,   
			
		
	
		
		
			
				
					
					        . size  =  s - > rgb_front_buf_len ,   
			
		
	
		
		
			
				
					
					      } ;   
			
		
	
		
		
			
				
					
					      # ifndef QCOM   
			
		
	
		
		
			
				
					
					        s - > priv_hnds_front [ i ]  =  s - > bufs [ i ] . addr ;   
			
		
	
		
		
			
				
					
					      # endif   
			
		
	
		
		
			
				
					
					      s - > frame_front_texs [ i ]  =  visionimg_to_gl ( & img ,  & s - > khr_front [ i ] ,  & s - > priv_hnds_front [ i ] ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      glBindTexture ( GL_TEXTURE_2D ,  s - > frame_front_texs [ i ] ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_MAG_FILTER ,  GL_NEAREST ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_MIN_FILTER ,  GL_NEAREST ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      // BGR
   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_R ,  GL_BLUE ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_G ,  GL_GREEN ) ;   
			
		
	
		
		
			
				
					
					      glTexParameteri ( GL_TEXTURE_2D ,  GL_TEXTURE_SWIZZLE_B ,  GL_RED ) ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    assert ( glGetError ( )  = =  GL_NO_ERROR ) ;    // Handle onroad/offroad transition
   
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					  if  ( ! s - > started  & &  s - > status  ! =  STATUS_OFFROAD )  {   
			
		
	
		
		
			
				
					
					    s - > status  =  STATUS_OFFROAD ;   
			
		
	
		
		
			
				
					
					    s - > active_app  =  cereal : : UiLayoutState : : App : : HOME ;   
			
		
	
		
		
			
				
					
					    s - > scene . uilayout_sidebarcollapsed  =  false ;   
			
		
	
		
		
			
				
					
					  }  else  if  ( s - > started  & &  s - > status  = =  STATUS_OFFROAD )  {   
			
		
	
		
		
			
				
					
					    s - > status  =  STATUS_DISENGAGED ;   
			
		
	
		
		
			
				
					
					    s - > started_frame  =  s - > sm - > frame ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    s - > active_app  =  cereal : : UiLayoutState : : App : : NONE ;   
			
		
	
		
		
			
				
					
					    s - > scene . uilayout_sidebarcollapsed  =  true ;      s - > scene . uilayout_sidebarcollapsed  =  true ;   
			
		
	
		
		
			
				
					
					    s - > scene . ui_viz_rx  =  ( box_x - sbr_w + bdr_s * 2 ) ;   
			
		
	
		
		
			
				
					
					    s - > scene . ui_viz_rw  =  ( box_w + sbr_w - ( bdr_s * 2 ) ) ;   
			
		
	
		
		
			
				
					
					    s - > scene . ui_viz_ro  =  0 ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    s - > vision_connect_firstrun  =  false ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    s - > alert_blinking_alpha  =  1.0 ;   
			
		
	
		
		
			
				
					
					    s - > alert_blinked  =  false ;      s - > alert_blinked  =  false ;   
			
		
	
		
		
			
				
					
					    s - > alert_blinking_alpha  =  1.0 ;   
			
		
	
		
		
			
				
					
					    s - > scene . alert_size  =  cereal : : ControlsState : : AlertSize : : NONE ;   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  zmq_pollitem_t  polls [ 1 ]  =  { { 0 } } ;    // Handle controls timeout
   
			
				
				
			
		
	
		
		
			
				
					
					  // Take an rgb image from visiond if there is one
    bool  controls_timeout  =  ( ( s - > sm ) - > frame  -  ( s - > sm ) - > rcv_frame ( " controlsState " ) )  >  10 * UI_FREQ ;   
			
				
				
			
		
	
		
		
			
				
					
					  assert ( s - > ipc_fd  > =  0 ) ;    if  ( s - > started  & &  ! s - > scene . frontview  & &  controls_timeout )  {   
			
				
				
			
		
	
		
		
			
				
					
					  while ( true )  {      if  ( ( s - > sm ) - > rcv_frame ( " controlsState " )  <  s - > started_frame )  {   
			
				
				
			
		
	
		
		
			
				
					
					    if  ( s - > ipc_fd  <  0 )  {        // car is started, but controlsState hasn't been seen at all
   
			
				
				
			
		
	
		
		
			
				
					
					      // TODO: rethink this, for now it should only trigger on PC
        s - > scene . alert_text1  =  " openpilot Unavailable " ;   
			
				
				
			
		
	
		
		
			
				
					
					      LOGW ( " vision disconnected by other thread " ) ;        s - > scene . alert_text2  =  " Waiting for controls to start " ;   
			
				
				
			
		
	
		
		
			
				
					
					      s - > vision_connected  =  false ;        s - > scene . alert_size  =  cereal : : ControlsState : : AlertSize : : MID ;   
			
				
				
			
		
	
		
		
			
				
					
					      return ;      }  else  {   
			
				
				
			
		
	
		
		
			
				
					
					    }        // car is started, but controls is lagging or died
   
			
				
				
			
		
	
		
		
			
				
					
					    polls [ 0 ] . fd  =  s - > ipc_fd ;        if  ( s - > scene . alert_text2  ! =  " Controls Unresponsive " )  {   
			
				
				
			
		
	
		
		
			
				
					
					    polls [ 0 ] . events  =  ZMQ_POLLIN ;          s - > sound . play ( AudibleAlert : : CHIME_WARNING_REPEAT ) ;   
			
				
				
			
		
	
		
		
			
				
					
					    # ifdef UI_60FPS          LOGE ( " Controls unresponsive " ) ;   
			
				
				
			
		
	
		
		
			
				
					
					      // uses more CPU in both UI and surfaceflinger
   
			
		
	
		
		
			
				
					
					      // 16% / 21%
   
			
		
	
		
		
			
				
					
					      int  ret  =  zmq_poll ( polls ,  1 ,  1 ) ;   
			
		
	
		
		
			
				
					
					    # else   
			
		
	
		
		
			
				
					
					      // 9% / 13% = a 14% savings
   
			
		
	
		
		
			
				
					
					      int  ret  =  zmq_poll ( polls ,  1 ,  1000 ) ;   
			
		
	
		
		
			
				
					
					    # endif   
			
		
	
		
		
			
				
					
					    if  ( ret  <  0 )  {   
			
		
	
		
		
			
				
					
					      if  ( errno  = =  EINTR  | |  errno  = =  EAGAIN )  continue ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      LOGE ( " poll failed (%d - %d) " ,  ret ,  errno ) ;   
			
		
	
		
		
			
				
					
					      close ( s - > ipc_fd ) ;   
			
		
	
		
		
			
				
					
					      s - > ipc_fd  =  - 1 ;   
			
		
	
		
		
			
				
					
					      s - > vision_connected  =  false ;   
			
		
	
		
		
			
				
					
					      return ;   
			
		
	
		
		
			
				
					
					    }  else  if  ( ret  = =  0 )  {   
			
		
	
		
		
			
				
					
					      break ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					    // vision ipc event
   
			
		
	
		
		
			
				
					
					    VisionPacket  rp ;   
			
		
	
		
		
			
				
					
					    err  =  vipc_recv ( s - > ipc_fd ,  & rp ) ;   
			
		
	
		
		
			
				
					
					    if  ( err  < =  0 )  {   
			
		
	
		
		
			
				
					
					      LOGW ( " vision disconnected " ) ;   
			
		
	
		
		
			
				
					
					      close ( s - > ipc_fd ) ;   
			
		
	
		
		
			
				
					
					      s - > ipc_fd  =  - 1 ;   
			
		
	
		
		
			
				
					
					      s - > vision_connected  =  false ;   
			
		
	
		
		
			
				
					
					      return ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					    if  ( rp . type  = =  VIPC_STREAM_ACQUIRE )  {   
			
		
	
		
		
			
				
					
					      bool  front  =  rp . d . stream_acq . type  = =  VISION_STREAM_RGB_FRONT ;   
			
		
	
		
		
			
				
					
					      int  idx  =  rp . d . stream_acq . idx ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      int  release_idx ;   
			
		
	
		
		
			
				
					
					      if  ( front )  {   
			
		
	
		
		
			
				
					
					        release_idx  =  s - > cur_vision_front_idx ;   
			
		
	
		
		
			
				
					
					      }  else  {   
			
		
	
		
		
			
				
					
					        release_idx  =  s - > cur_vision_idx ;   
			
		
	
		
		
			
				
					
					      }   
			
		
	
		
		
			
				
					
					      if  ( release_idx  > =  0 )  {   
			
		
	
		
		
			
				
					
					        VisionPacket  rep  =  {   
			
		
	
		
		
			
				
					
					          . type  =  VIPC_STREAM_RELEASE ,   
			
		
	
		
		
			
				
					
					          . d  =  {  . stream_rel  =  {   
			
		
	
		
		
			
				
					
					            . type  =  rp . d . stream_acq . type ,   
			
		
	
		
		
			
				
					
					            . idx  =  release_idx ,   
			
		
	
		
		
			
				
					
					          } } ,   
			
		
	
		
		
			
				
					
					        } ;   
			
		
	
		
		
			
				
					
					        vipc_send ( s - > ipc_fd ,  & rep ) ;   
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					      }        }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					      if  ( front )  {        s - > scene . alert_text1  =  " TAKE CONTROL IMMEDIATELY " ;   
			
				
				
			
		
	
		
		
			
				
					
					        assert ( idx  <  UI_BUF_COUNT ) ;        s - > scene . alert_text2  =  " Controls Unresponsive " ;   
			
				
				
			
		
	
		
		
			
				
					
					        s - > cur_vision_front_idx  =  idx ;        s - > scene . alert_size  =  cereal : : ControlsState : : AlertSize : : FULL ;   
			
				
				
			
		
	
		
		
			
				
					
					      }  else  {        s - > status  =  STATUS_ALERT ;   
			
				
				
			
		
	
		
		
			
				
					
					        assert ( idx  <  UI_BUF_COUNT ) ;   
			
		
	
		
		
			
				
					
					        s - > cur_vision_idx  =  idx ;   
			
		
	
		
		
			
				
					
					        // printf("v %d\n", ((uint8_t*)s->bufs[idx].addr)[0]);
   
			
		
	
		
		
			
				
					
					      }   
			
		
	
		
		
			
				
					
					    }  else  {   
			
		
	
		
		
			
				
					
					      assert ( false ) ;   
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					    }      }   
			
		
	
		
		
			
				
					
					    break ;   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					static  int  vision_subscribe ( int  fd ,  VisionPacket  * rp ,  VisionStreamType  type )  {  
			
		
	
		
		
			
				
					
					  int  err ;   
			
		
	
		
		
			
				
					
					  LOGW ( " vision_subscribe type:%d " ,  type ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  VisionPacket  p1  =  {   
			
		
	
		
		
			
				
					
					    . type  =  VIPC_STREAM_SUBSCRIBE ,   
			
		
	
		
		
			
				
					
					    . d  =  {  . stream_sub  =  {  . type  =  type ,  . tbuffer  =  true ,  } ,  } ,   
			
		
	
		
		
			
				
					
					  } ;   
			
		
	
		
		
			
				
					
					  err  =  vipc_send ( fd ,  & p1 ) ;   
			
		
	
		
		
			
				
					
					  if  ( err  <  0 )  {   
			
		
	
		
		
			
				
					
					    close ( fd ) ;   
			
		
	
		
		
			
				
					
					    return  0 ;   
			
		
	
		
		
			
				
					
					  }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  do  {   
			
		
	
		
		
			
				
					
					    err  =  vipc_recv ( fd ,  rp ) ;   
			
		
	
		
		
			
				
					
					    if  ( err  < =  0 )  {   
			
		
	
		
		
			
				
					
					      close ( fd ) ;   
			
		
	
		
		
			
				
					
					      return  0 ;   
			
		
	
		
		
			
				
					
					    }   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    // release what we aren't ready for yet
    // Read params
   
			
				
				
			
		
	
		
		
			
				
					
					    if  ( rp - > type  = =  VIPC_STREAM_ACQUIRE )  {    if  ( ( s - > sm ) - > frame  %  ( 5 * UI_FREQ )  = =  0 )  {   
			
				
				
			
		
	
		
		
			
				
					
					      VisionPacket  rep  =  {      read_param ( & s - > is_metric ,  " IsMetric " ) ;   
			
				
				
			
		
	
		
		
			
				
					
					        . type  =  VIPC_STREAM_RELEASE ,    }  else  if  ( ( s - > sm ) - > frame  %  ( 6 * UI_FREQ )  = =  0 )  {   
			
				
				
			
		
	
		
		
			
				
					
					        . d  =  {  . stream_rel  =  {      int  param_read  =  read_param ( & s - > last_athena_ping ,  " LastAthenaPingTime " ) ;   
			
				
				
			
		
	
		
		
			
				
					
					          . type  =  rp - > d . stream_acq . type ,      if  ( param_read  ! =  0 )  {  // Failed to read param
   
			
				
				
			
		
	
		
		
			
				
					
					          . idx  =  rp - > d . stream_acq . idx ,        s - > scene . athenaStatus  =  NET_DISCONNECTED ;   
			
				
				
			
		
	
		
		
			
				
					
					        } } ,      }  else  if  ( nanos_since_boot ( )  -  s - > last_athena_ping  <  70e9 )  {   
			
				
				
			
		
	
		
		
			
				
					
					      } ;        s - > scene . athenaStatus  =  NET_CONNECTED ;   
			
				
				
			
		
	
		
		
			
				
					
					      vipc_send ( fd ,  & rep ) ;      }  else  {   
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					      s - > scene . athenaStatus  =  NET_ERROR ;   
			
		
	
		
		
			
				
					
					    }      }   
			
		
	
		
		
			
				
					
					  }  while  ( rp - > type  ! =  VIPC_STREAM_BUFS  | |  rp - > d . stream_bufs . type  ! =  type ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  return  1 ;   
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					void *  vision_connect_thread ( void  * args )  {  
			
		
	
		
		
			
				
					
					  set_thread_name ( " vision_connect " ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  UIState  * s  =  ( UIState * ) args ;   
			
		
	
		
		
			
				
					
					  while  ( ! do_exit )  {   
			
		
	
		
		
			
				
					
					    usleep ( 100000 ) ;   
			
		
	
		
		
			
				
					
					    pthread_mutex_lock ( & s - > lock ) ;   
			
		
	
		
		
			
				
					
					    bool  connected  =  s - > vision_connected ;   
			
		
	
		
		
			
				
					
					    pthread_mutex_unlock ( & s - > lock ) ;   
			
		
	
		
		
			
				
					
					    if  ( connected )  continue ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    int  fd  =  vipc_connect ( ) ;   
			
		
	
		
		
			
				
					
					    if  ( fd  <  0 )  continue ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    VisionPacket  back_rp ,  front_rp ;   
			
		
	
		
		
			
				
					
					    if  ( ! vision_subscribe ( fd ,  & back_rp ,  VISION_STREAM_RGB_BACK ) )  continue ;   
			
		
	
		
		
			
				
					
					    if  ( ! vision_subscribe ( fd ,  & front_rp ,  VISION_STREAM_RGB_FRONT ) )  continue ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    pthread_mutex_lock ( & s - > lock ) ;   
			
		
	
		
		
			
				
					
					    assert ( ! s - > vision_connected ) ;   
			
		
	
		
		
			
				
					
					    s - > ipc_fd  =  fd ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    ui_init_vision ( s ,   
			
		
	
		
		
			
				
					
					                   back_rp . d . stream_bufs ,  back_rp . num_fds ,  back_rp . fds ,   
			
		
	
		
		
			
				
					
					                   front_rp . d . stream_bufs ,  front_rp . num_fds ,  front_rp . fds ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    s - > vision_connected  =  true ;   
			
		
	
		
		
			
				
					
					    s - > vision_seen  =  true ;   
			
		
	
		
		
			
				
					
					    s - > vision_connect_firstrun  =  true ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    // Drain sockets
   
			
		
	
		
		
			
				
					
					    s - > sm - > drain ( ) ;   
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    pthread_mutex_unlock ( & s - > lock ) ;   
			
		
	
		
		
			
				
					
					  }    }   
			
		
	
		
		
			
				
					
					  return  NULL ;   
			
		
	
		
		
			
				
					
					} }