1/* 2 * replay-input.c 3 * 4 * Copyright (c) 2010-2015 Institute for System Programming 5 * of the Russian Academy of Sciences. 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 * See the COPYING file in the top-level directory. 9 * 10 */ 11 12#include "qemu/osdep.h" 13#include "qapi/error.h" 14#include "qemu-common.h" 15#include "sysemu/replay.h" 16#include "replay-internal.h" 17#include "qemu/notify.h" 18#include "ui/input.h" 19#include "qapi/qmp-output-visitor.h" 20#include "qapi/qmp-input-visitor.h" 21#include "qapi-visit.h" 22 23static InputEvent *qapi_clone_InputEvent(InputEvent *src) 24{ 25 QmpOutputVisitor *qov; 26 QmpInputVisitor *qiv; 27 Visitor *ov, *iv; 28 QObject *obj; 29 InputEvent *dst = NULL; 30 31 qov = qmp_output_visitor_new(); 32 ov = qmp_output_get_visitor(qov); 33 visit_type_InputEvent(ov, NULL, &src, &error_abort); 34 obj = qmp_output_get_qobject(qov); 35 qmp_output_visitor_cleanup(qov); 36 if (!obj) { 37 return NULL; 38 } 39 40 qiv = qmp_input_visitor_new(obj); 41 iv = qmp_input_get_visitor(qiv); 42 visit_type_InputEvent(iv, NULL, &dst, &error_abort); 43 qmp_input_visitor_cleanup(qiv); 44 qobject_decref(obj); 45 46 return dst; 47} 48 49void replay_save_input_event(InputEvent *evt) 50{ 51 InputKeyEvent *key; 52 InputBtnEvent *btn; 53 InputMoveEvent *move; 54 replay_put_dword(evt->type); 55 56 switch (evt->type) { 57 case INPUT_EVENT_KIND_KEY: 58 key = evt->u.key.data; 59 replay_put_dword(key->key->type); 60 61 switch (key->key->type) { 62 case KEY_VALUE_KIND_NUMBER: 63 replay_put_qword(key->key->u.number.data); 64 replay_put_byte(key->down); 65 break; 66 case KEY_VALUE_KIND_QCODE: 67 replay_put_dword(key->key->u.qcode.data); 68 replay_put_byte(key->down); 69 break; 70 case KEY_VALUE_KIND__MAX: 71 /* keep gcc happy */ 72 break; 73 } 74 break; 75 case INPUT_EVENT_KIND_BTN: 76 btn = evt->u.btn.data; 77 replay_put_dword(btn->button); 78 replay_put_byte(btn->down); 79 break; 80 case INPUT_EVENT_KIND_REL: 81 move = evt->u.rel.data; 82 replay_put_dword(move->axis); 83 replay_put_qword(move->value); 84 break; 85 case INPUT_EVENT_KIND_ABS: 86 move = evt->u.abs.data; 87 replay_put_dword(move->axis); 88 replay_put_qword(move->value); 89 break; 90 case INPUT_EVENT_KIND__MAX: 91 /* keep gcc happy */ 92 break; 93 } 94} 95 96InputEvent *replay_read_input_event(void) 97{ 98 InputEvent evt; 99 KeyValue keyValue; 100 InputKeyEvent key; 101 key.key = &keyValue; 102 InputBtnEvent btn; 103 InputMoveEvent rel; 104 InputMoveEvent abs; 105 106 evt.type = replay_get_dword(); 107 switch (evt.type) { 108 case INPUT_EVENT_KIND_KEY: 109 evt.u.key.data = &key; 110 evt.u.key.data->key->type = replay_get_dword(); 111 112 switch (evt.u.key.data->key->type) { 113 case KEY_VALUE_KIND_NUMBER: 114 evt.u.key.data->key->u.number.data = replay_get_qword(); 115 evt.u.key.data->down = replay_get_byte(); 116 break; 117 case KEY_VALUE_KIND_QCODE: 118 evt.u.key.data->key->u.qcode.data = (QKeyCode)replay_get_dword(); 119 evt.u.key.data->down = replay_get_byte(); 120 break; 121 case KEY_VALUE_KIND__MAX: 122 /* keep gcc happy */ 123 break; 124 } 125 break; 126 case INPUT_EVENT_KIND_BTN: 127 evt.u.btn.data = &btn; 128 evt.u.btn.data->button = (InputButton)replay_get_dword(); 129 evt.u.btn.data->down = replay_get_byte(); 130 break; 131 case INPUT_EVENT_KIND_REL: 132 evt.u.rel.data = &rel; 133 evt.u.rel.data->axis = (InputAxis)replay_get_dword(); 134 evt.u.rel.data->value = replay_get_qword(); 135 break; 136 case INPUT_EVENT_KIND_ABS: 137 evt.u.abs.data = &abs; 138 evt.u.abs.data->axis = (InputAxis)replay_get_dword(); 139 evt.u.abs.data->value = replay_get_qword(); 140 break; 141 case INPUT_EVENT_KIND__MAX: 142 /* keep gcc happy */ 143 break; 144 } 145 146 return qapi_clone_InputEvent(&evt); 147} 148 149void replay_input_event(QemuConsole *src, InputEvent *evt) 150{ 151 if (replay_mode == REPLAY_MODE_PLAY) { 152 /* Nothing */ 153 } else if (replay_mode == REPLAY_MODE_RECORD) { 154 replay_add_input_event(qapi_clone_InputEvent(evt)); 155 } else { 156 qemu_input_event_send_impl(src, evt); 157 } 158} 159 160void replay_input_sync_event(void) 161{ 162 if (replay_mode == REPLAY_MODE_PLAY) { 163 /* Nothing */ 164 } else if (replay_mode == REPLAY_MODE_RECORD) { 165 replay_add_input_sync_event(); 166 } else { 167 qemu_input_event_sync_impl(); 168 } 169} 170