replay-input.c 4.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
/*
 * replay-input.c
 *
 * Copyright (c) 2010-2015 Institute for System Programming
 *                         of the Russian Academy of Sciences.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#include "qemu-common.h"
#include "sysemu/replay.h"
#include "replay-internal.h"
#include "qemu/notify.h"
#include "ui/input.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi-visit.h"

static InputEvent *qapi_clone_InputEvent(InputEvent *src)
{
    QmpOutputVisitor *qov;
    QmpInputVisitor *qiv;
    Visitor *ov, *iv;
    QObject *obj;
    InputEvent *dst = NULL;

    qov = qmp_output_visitor_new();
    ov = qmp_output_get_visitor(qov);
    visit_type_InputEvent(ov, &src, NULL, &error_abort);
    obj = qmp_output_get_qobject(qov);
    qmp_output_visitor_cleanup(qov);
    if (!obj) {
        return NULL;
    }

    qiv = qmp_input_visitor_new(obj);
    iv = qmp_input_get_visitor(qiv);
    visit_type_InputEvent(iv, &dst, NULL, &error_abort);
    qmp_input_visitor_cleanup(qiv);
    qobject_decref(obj);

    return dst;
}

void replay_save_input_event(InputEvent *evt)
{
    replay_put_dword(evt->type);

    switch (evt->type) {
    case INPUT_EVENT_KIND_KEY:
        replay_put_dword(evt->u.key->key->type);

        switch (evt->u.key->key->type) {
        case KEY_VALUE_KIND_NUMBER:
            replay_put_qword(evt->u.key->key->u.number);
            replay_put_byte(evt->u.key->down);
            break;
        case KEY_VALUE_KIND_QCODE:
            replay_put_dword(evt->u.key->key->u.qcode);
            replay_put_byte(evt->u.key->down);
            break;
        case KEY_VALUE_KIND_MAX:
            /* keep gcc happy */
            break;
        }
        break;
    case INPUT_EVENT_KIND_BTN:
        replay_put_dword(evt->u.btn->button);
        replay_put_byte(evt->u.btn->down);
        break;
    case INPUT_EVENT_KIND_REL:
        replay_put_dword(evt->u.rel->axis);
        replay_put_qword(evt->u.rel->value);
        break;
    case INPUT_EVENT_KIND_ABS:
        replay_put_dword(evt->u.abs->axis);
        replay_put_qword(evt->u.abs->value);
        break;
    case INPUT_EVENT_KIND_MAX:
        /* keep gcc happy */
        break;
    }
}

InputEvent *replay_read_input_event(void)
{
    InputEvent evt;
    KeyValue keyValue;
    InputKeyEvent key;
    key.key = &keyValue;
    InputBtnEvent btn;
    InputMoveEvent rel;
    InputMoveEvent abs;

    evt.type = replay_get_dword();
    switch (evt.type) {
    case INPUT_EVENT_KIND_KEY:
        evt.u.key = &key;
        evt.u.key->key->type = replay_get_dword();

        switch (evt.u.key->key->type) {
        case KEY_VALUE_KIND_NUMBER:
            evt.u.key->key->u.number = replay_get_qword();
            evt.u.key->down = replay_get_byte();
            break;
        case KEY_VALUE_KIND_QCODE:
            evt.u.key->key->u.qcode = (QKeyCode)replay_get_dword();
            evt.u.key->down = replay_get_byte();
            break;
        case KEY_VALUE_KIND_MAX:
            /* keep gcc happy */
            break;
        }
        break;
    case INPUT_EVENT_KIND_BTN:
        evt.u.btn = &btn;
        evt.u.btn->button = (InputButton)replay_get_dword();
        evt.u.btn->down = replay_get_byte();
        break;
    case INPUT_EVENT_KIND_REL:
        evt.u.rel = &rel;
        evt.u.rel->axis = (InputAxis)replay_get_dword();
        evt.u.rel->value = replay_get_qword();
        break;
    case INPUT_EVENT_KIND_ABS:
        evt.u.abs = &abs;
        evt.u.abs->axis = (InputAxis)replay_get_dword();
        evt.u.abs->value = replay_get_qword();
        break;
    case INPUT_EVENT_KIND_MAX:
        /* keep gcc happy */
        break;
    }

    return qapi_clone_InputEvent(&evt);
}

void replay_input_event(QemuConsole *src, InputEvent *evt)
{
    if (replay_mode == REPLAY_MODE_PLAY) {
        /* Nothing */
    } else if (replay_mode == REPLAY_MODE_RECORD) {
        replay_add_input_event(qapi_clone_InputEvent(evt));
    } else {
        qemu_input_event_send_impl(src, evt);
    }
}

void replay_input_sync_event(void)
{
    if (replay_mode == REPLAY_MODE_PLAY) {
        /* Nothing */
    } else if (replay_mode == REPLAY_MODE_RECORD) {
        replay_add_input_sync_event();
    } else {
        qemu_input_event_sync_impl();
    }
}