40 #include <SDL2/SDL_error.h>
41 #include <SDL2/SDL_events.h>
42 #include <SDL2/SDL_keyboard.h>
43 #include <SDL2/SDL_mouse.h>
44 #include <SDL2/SDL_render.h>
45 #include <SDL2/SDL_surface.h>
46 #include <SDL2/SDL_syswm.h>
47 #include <SDL2/SDL_version.h>
48 #include <SDL2/SDL_video.h>
69 #define LOG_TAG "main"
71 #define USER_EVENT_ROTATION 1
73 #define USER_EVENT_NEWCLIENT 2
76 #define INPUT_PORT 22469
78 static SDL_Surface* s_window_surface = NULL;
79 static SDL_Window* s_window = NULL;
80 static char* s_vmip = NULL;
81 static int input_in_progress = 0;
106 static SDL_Window* open_window(
int width,
int height)
110 SDL_Renderer* renderer;
112 if (SDL_Init(SDL_INIT_VIDEO))
113 LOGE(
"SDL_Init failed: %s\n", SDL_GetError());
116 snprintf(title,
sizeof(title),
"AiC Player (%i * %i)", width, height);
118 SDL_CreateWindow(title, 0, 0, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);
120 LOGE(
"Can't create window");
123 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
125 if (renderer == NULL)
126 LOGE(
"Can't create renderer");
128 s_window_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0);
129 SDL_SetRenderDrawColor(renderer, 3, 169, 244, 255);
130 SDL_RenderClear(renderer);
131 SDL_RenderPresent(renderer);
137 static void* get_window_id(SDL_Window* window)
139 SDL_SysWMinfo wminfo;
142 SDL_VERSION(&wminfo.version);
143 SDL_GetWindowWMInfo(window, &wminfo);
144 winhandle = (
void*) wminfo.info.x11.window;
149 static void callback_rotation(
float angle)
151 float* angle_alloc = (
float*) malloc(
sizeof(
float));
153 LOGE(
"callback_rotation(): out of memory");
154 SDL_Event rotation_event;
155 rotation_event.type = SDL_USEREVENT;
157 LOGI(
"Rotation callback from the VM: %f ", angle);
158 *angle_alloc = angle;
159 rotation_event.user.data2 = angle_alloc;
160 SDL_PushEvent(&rotation_event);
164 static void recreate_subwindow(
int width,
int height,
float rotation)
168 SDL_FreeSurface(s_window_surface);
169 s_window_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0, 0, 0, 0);
170 if (!s_window_surface)
171 LOGE(
"Unable to recreate Window surface");
175 SDL_SetWindowSize(s_window, width, height);
179 static void do_rotation(
float rotation)
181 LOGI(
"Rotating the screen to: %f°", rotation);
182 switch ((
int) rotation)
193 LOGE(
"Unknown rotation value: %f°", rotation);
201 static void rotation_received(
float rotation)
203 if (rotation == 0.0 || rotation == 90.0 || rotation == 180.0 || rotation == 270.0)
204 do_rotation(rotation);
206 LOGW(
"Unexpected rotation value: %f°", rotation);
210 static void* connect_input(
void* arg)
213 input_in_progress = 1;
217 LOGE(
"connect_input thread: out of memory");
223 LOGW(
"Could not connect to input daemon (:%d): %s",
INPUT_PORT, strerror(errno));
227 LOGI(
"input client connected with socket %d", *input_socket);
229 SDL_Event conn_event;
230 conn_event.type = SDL_USEREVENT;
232 conn_event.user.data1 = input_socket;
233 SDL_PushEvent(&conn_event);
234 input_in_progress = 0;
240 static void main_loop(
int width,
int height)
244 pthread_t input_thread;
247 if (input_socket > 0)
251 if (!input_in_progress)
253 if (pthread_create(&input_thread, NULL, connect_input, NULL) != 0)
254 LOGE(
"Unable to start input thread, exiting...");
258 while (SDL_WaitEvent(&event))
263 switch (event.user.code)
266 rotation_received(*(
float*) event.user.data2);
267 free(event.user.data2);
273 input_socket = *(
socket_t*) event.user.data1;
274 free(event.user.data1);
275 LOGI(
"Got new uinput client, socket=%d", input_socket);
276 snprintf(buffer,
BUF_SIZE,
"CONFIG:%d:%d\n", width, height);
277 send(input_socket, buffer, strlen(buffer), 0);
281 case SDL_MOUSEMOTION:
285 case SDL_MOUSEBUTTONDOWN:
286 case SDL_MOUSEBUTTONUP:
319 static char port_gl[] =
"22468";
322 pthread_t input_thread;
323 pthread_t amqp_grabber_thread;
324 pthread_t socket_grabber_thread;
331 signal(SIGPIPE, SIG_IGN);
350 LOGI(
"Creating window surface: %dx%d", width, height);
351 s_window = open_window(width, height);
355 LOGE(
"Unable to initialize Library");
358 LOGE(
"invalid stream mode for setStreamMode()");
361 LOGE(
"initOpenGLRenderer failed");
364 LOGE(
"Error creating thread");
367 LOGE(
"Unable to setup SubWindow");
375 char sensor_name[] =
"recording";
377 const int32_t str_length =
BUF_SIZE;
378 g_strlcpy(param_listener.
sensor, sensor_name, str_length);
379 param_listener.
gvmip = s_vmip;
380 g_strlcpy(param_listener.
exchange, sensor_name, str_length);
382 snprintf(param_listener.
queue, str_length,
"android-events.%s.%s", vm_id, sensor_name);
384 if (strncmp(amqp_host,
"0", 1))
387 LOGI(
"Working without AMQP");
392 if (pthread_create(&input_thread, NULL, connect_input, NULL) != 0)
393 LOGE(
"Unable to start input thread");
395 main_loop(width, height);
Utilities to get config values from the environment.
int sdl_key(SDL_Event *event, socket_t input_socket)
Produce a key press/release event to the virtual input.
char sensor[BUF_SIZE]
Sensor name.
int configvar_int(char *varname)
Get the value of a integer config variable from the env.
Parameter for sensor threads.
void grabber_set_path_results(char *results)
Set the static path to the screenshots/movies dir.
int configvar_bool(char *varname)
Get the value of a boolean config variable from the env.
#define LOGE(...)
Log at ERROR level (makes the application abort)
#define BUF_SIZE
Small, fixed-size buffers.
void dump_trace()
Dump a backtrace if there is a segfault.
int socket_t
Alias to differenciate between regular ints and socket fds.
int sdl_mouse_wheel(SDL_Event *event, socket_t input_socket)
Produce a mouse wheel event to the virtual input.
int initOpenGLRenderer(int width, int height, char *addr, size_t addrLen)
int manage_socket_gl(void *arg)
Manage the remote OpenGL to the VM.
int createOpenGLSubwindow(void *window, int x, int y, int width, int height, float zRot)
void grabber_set_display(Display *display)
Set the static X display pointer.
void * grab_handler_amqp(void *args)
socket_t open_socket(const char *ip, short port)
Connect to a host:port couple.
#define USER_EVENT_ROTATION
int g_height
Global variable for the window height.
char queue[BUF_SIZE]
Queue name.
void * g_window_id
Global variable for the X window id.
void repaintOpenGLDisplay(void)
Defines ports and structures for sensor threads.
char * configvar_string(char *varname)
Get the value of a config variable from the env.
char exchange[BUF_SIZE]
Exchange name.
int destroyOpenGLSubwindow(void)
float AiC_CallbackRotation(void(*fn)(float))
int g_width
Global variable for the window width.
#define LOGW(...)
Log at WARNING level.
int sdl_mouse_motion(SDL_Event *event, socket_t input_socket)
Produce a mouse motion event to the virtual input.
int setStreamMode(int mode)
grabber records videos or snapshots from ampq messages
void setOpenGLDisplayRotation(float zRot)
Produce virtual input events from SDL events.
void * grab_handler_sock()
Start/Stop from socket connection via protobuf message.
#define SOCKET_ERROR
Alias for the recv() return value in case of error.
Define common buffer sizes.
Define socket utilities to simplify networking.
#define USER_EVENT_NEWCLIENT
int sdl_mouse_button(SDL_Event *event, socket_t input_socket)
Produce a mouse click event to the virtual input.
#define LOGI(...)
Log at INFO level.
Header for functions defined in the AOSP opengl libs.