static void dispatch_event(arcan_event* ev, struct rwstat_ch* ch, struct senseye_priv* chp) { if (rwstat_consume_event(ch, ev)) return; if (ev->category == EVENT_TARGET) switch (ev->tgt.kind){ case TARGET_COMMAND_REQFAIL: chp->running = false; break; case TARGET_COMMAND_PAUSE: chp->paused = true; break; case TARGET_COMMAND_DISPLAYHINT:{ size_t base = ev->tgt.ioevs[0].iv; if (base > 0 && (base & (base - 1)) == 0 && arcan_shmif_resize(&chp->cont, base, base)) ch->resize(ch, base); else FLOG("Senseye:FDsense: bad displayhint: %d\n", ev->tgt.ioevs[0].iv); } /* resize buffer to new base */ break; case TARGET_COMMAND_UNPAUSE: chp->paused = false; break; case TARGET_COMMAND_STEPFRAME: chp->framecount = ev->tgt.ioevs[0].iv; break; case TARGET_COMMAND_EXIT: chp->running = false; break; default: #ifdef _DEBUG printf("unhandled event : %s\n", arcan_shmif_eventstr(ev, NULL, 0)); #endif break; } }
static void on_cl_event( struct arcan_shmif_cont* cont, int chid, struct arcan_event* ev, void* tag) { if (!cont){ debug_print(1, "ignore incoming event on unknown context"); return; } if (arcan_shmif_descrevent(ev)){ /* * Events needed to be handled here: * NEWSEGMENT, map it, add it to the context channel list. */ debug_print(1, "incoming descr- event ignored"); } else { debug_print(2, "client event: %s on ch %d", arcan_shmif_eventstr(ev, NULL, 0), chid); arcan_shmif_enqueue(cont, ev); } }
int main(int argc, char** argv) { int id = SEGID_APPLICATION; struct arg_arr* aarr; if (argc > 1){ if (strcmp(argv[1], "-game") == 0) id = SEGID_GAME; else if (strcmp(argv[1], "-terminal") == 0) id = SEGID_TERMINAL; else if (strcmp(argv[1], "-vm") == 0) id = SEGID_VM; else{ printf("usage: \n\tiodump to identify as normal application" "\n\tiodump -game to identify as game" "\n\tiodump -terminal to identify as terminal" "\n\tiodump -vm to identify as vm\n" ); return EXIT_FAILURE; } } struct arcan_shmif_cont cont = arcan_shmif_open( id, SHMIF_ACQUIRE_FATALFAIL, &aarr); printf("open\n"); arcan_event ev; /* just send garbage so the correct events are being propagated */ arcan_shmif_signal(&cont, SHMIF_SIGVID); printf("loop\n"); while (arcan_shmif_wait(&cont, &ev)){ if (ev.category == EVENT_TARGET){ switch (ev.tgt.kind){ case TARGET_COMMAND_BCHUNK_IN: printf("bchunk in\n"); dump_eof(ev.tgt.ioevs[0].iv); break; case TARGET_COMMAND_BCHUNK_OUT: printf("bchunk out\n"); write_eof(ev.tgt.ioevs[0].iv); break; case TARGET_COMMAND_MESSAGE: printf("message: %s\n", ev.tgt.message); break; case TARGET_COMMAND_EXIT: return EXIT_SUCCESS; default: printf("event: %s\n", arcan_shmif_eventstr(&ev, NULL, 0)); break; } } else if (ev.category == EVENT_IO){ switch (ev.io.datatype){ case EVENT_IDATATYPE_TRANSLATED: printf("(%s)[kbd(%d):%s] %d:mask=%d,sym:%d,code:%d,utf8:%s\n", ev.io.label, ev.io.devid, ev.io.input.translated.active ? "pressed" : "released", (int)ev.io.subid, (int)ev.io.input.translated.modifiers, (int)ev.io.input.translated.keysym, (int)ev.io.input.translated.scancode, ev.io.input.translated.utf8 ); break; case EVENT_IDATATYPE_ANALOG: printf("(%s)[%s(%d):%d] rel: %s, v(%d){%d, %d, %d, %d}\n", ev.io.label, ev.io.devkind == EVENT_IDEVKIND_MOUSE ? "mouse" : "analog", ev.io.devid, ev.io.subid, ev.io.input.analog.gotrel ? "yes" : "no", (int)ev.io.input.analog.nvalues, (int)ev.io.input.analog.axisval[0], (int)ev.io.input.analog.axisval[1], (int)ev.io.input.analog.axisval[2], (int)ev.io.input.analog.axisval[3] ); break; case EVENT_IDATATYPE_TOUCH: printf("(%s)[touch(%d)] %d: @%d,%d pressure: %f, size: %f\n", ev.io.label, ev.io.devid, ev.io.subid, (int) ev.io.input.touch.x, (int) ev.io.input.touch.y, ev.io.input.touch.pressure, ev.io.input.touch.size ); break; case EVENT_IDATATYPE_DIGITAL: if (ev.io.devkind == EVENT_IDEVKIND_MOUSE) printf("[mouse(%d):%d], %s:%s\n", ev.io.devid, ev.io.subid, msub_to_lbl(ev.io.subid), ev.io.input.digital.active ? "pressed" : "released" ); else printf("[digital(%d):%d], %s\n", ev.io.devid, ev.io.subid, ev.io.input.digital.active ? "pressed" : "released"); break; default: break; } } } return EXIT_SUCCESS; }
int a12helper_a12srv_shmifcl( struct a12_state* S, const char* cp, int fd_in, int fd_out) { if (!cp) cp = getenv("ARCAN_CONNPATH"); else setenv("ARCAN_CONNPATH", cp, 1); if (!cp){ debug_print(1, "No connection point was specified"); return -ENOENT; } /* Channel - connection mapping */ struct cl_state cl_state = {}; /* Open / set the primary connection */ cl_state.wnd[0] = arcan_shmif_open(SEGID_UNKNOWN, SHMIF_NOACTIVATE, NULL); if (!cl_state.wnd[0].addr){ debug_print(1, "Couldn't connect to an arcan display server"); return -ENOENT; } cl_state.n_segments = 1; debug_print(1, "Segment connected"); a12_set_destination(S, &cl_state.wnd[0], 0); /* set to non-blocking */ int flags = fcntl(fd_in, F_GETFL); fcntl(fd_in, F_SETFL, flags | O_NONBLOCK); uint8_t* outbuf; size_t outbuf_sz = 0; debug_print(1, "got proxy connection, waiting for source"); int status; while (-1 != (status = a12helper_poll_triple( cl_state.wnd[0].epipe, fd_in, outbuf_sz ? fd_out : -1, 4))){ if (status & A12HELPER_WRITE_OUT){ if (outbuf_sz || (outbuf_sz = a12_channel_flush(S, &outbuf))){ ssize_t nw = write(fd_out, outbuf, outbuf_sz); if (nw > 0){ outbuf += nw; outbuf_sz -= nw; } } } if (status & A12HELPER_DATA_IN){ uint8_t inbuf[9000]; ssize_t nr = read(fd_in, inbuf, 9000); if (-1 == nr && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR){ debug_print(1, "failed to read from input: %d", errno); break; } debug_print(2, "unpack %zd bytes", nr); a12_channel_unpack(S, inbuf, nr, NULL, on_cl_event); } /* 1 client can have multiple segments */ for (size_t i = 0, count = cl_state.n_segments; i < 256 && count; i++){ if (!cl_state.wnd[i].addr) continue; count--; struct arcan_event newev; int sc; while (( sc = arcan_shmif_poll(&cl_state.wnd[i], &newev)) > 0){ /* we got a descriptor passing event, some of these we could/should discard, * while others need to be forwarded as a binary- chunk stream and kept out- * of order on the other side */ if (arcan_shmif_descrevent(&newev)){ debug_print(1, "(cl:%zu) ign-descr-event: %s", i, arcan_shmif_eventstr(&newev, NULL, 0)); } else { debug_print(2, "enqueue %s", arcan_shmif_eventstr(&newev, NULL, 0)); a12_channel_enqueue(S, &newev); } } } /* we might have gotten data to flush, so use that as feedback */ if (!outbuf_sz){ outbuf_sz = a12_channel_flush(S, &outbuf); if (outbuf_sz) debug_print(2, "output buffer size: %zu", outbuf_sz); } } /* though a proper cleanup would cascade, it doesn't help being careful */ for (size_t i = 0, count = cl_state.n_segments; i < 256 && count; i++){ if (!cl_state.wnd[i].addr) continue; arcan_shmif_drop(&cl_state.wnd[i]); cl_state.wnd[i].addr = NULL; } return 0; }