/* Send a scroll event to the streaming machine */ int LiSendScrollEvent(signed char scrollClicks) { PPACKET_HOLDER holder; int err; if (!initialized) { return -2; } holder = malloc(sizeof(*holder)); if (holder == NULL) { return -1; } holder->packetLength = sizeof(NV_SCROLL_PACKET); holder->packet.scroll.header.packetType = htonl(PACKET_TYPE_SCROLL); holder->packet.scroll.magicA = MAGIC_A; holder->packet.scroll.zero1 = 0; holder->packet.scroll.zero2 = 0; holder->packet.scroll.scrollAmt1 = htons(scrollClicks * 120); holder->packet.scroll.scrollAmt2 = holder->packet.scroll.scrollAmt1; holder->packet.scroll.zero3 = 0; err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); if (err != LBQ_SUCCESS) { free(holder); } return err; }
/* Send a key press event to the streaming machine */ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) { PPACKET_HOLDER holder; int err; if (!initialized) { return -2; } holder = malloc(sizeof(*holder)); if (holder == NULL) { return -1; } holder->packetLength = sizeof(NV_KEYBOARD_PACKET); holder->packet.keyboard.header.packetType = htonl(PACKET_TYPE_KEYBOARD); holder->packet.keyboard.keyAction = keyAction; holder->packet.keyboard.zero1 = 0; holder->packet.keyboard.keyCode = keyCode; holder->packet.keyboard.modifiers = modifiers; holder->packet.keyboard.zero2 = 0; err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); if (err != LBQ_SUCCESS) { free(holder); } return err; }
/* Send a mouse button event to the streaming machine */ int LiSendMouseButtonEvent(char action, int button) { PPACKET_HOLDER holder; int err; if (!initialized) { return -2; } holder = malloc(sizeof(*holder)); if (holder == NULL) { return -1; } holder->packetLength = sizeof(NV_MOUSE_BUTTON_PACKET); holder->packet.mouseButton.header.packetType = htonl(PACKET_TYPE_MOUSE_BUTTON); holder->packet.mouseButton.action = action; holder->packet.mouseButton.button = htonl(button); err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); if (err != LBQ_SUCCESS) { free(holder); } return err; }
/* Send a mouse move event to the streaming machine */ int LiSendMouseMoveEvent(short deltaX, short deltaY) { PPACKET_HOLDER holder; int err; if (!initialized) { return -2; } holder = malloc(sizeof(*holder)); if (holder == NULL) { return -1; } holder->packetLength = sizeof(NV_MOUSE_MOVE_PACKET); holder->packet.mouseMove.header.packetType = htonl(PACKET_TYPE_MOUSE_MOVE); holder->packet.mouseMove.magic = htonl(MOUSE_MOVE_MAGIC); holder->packet.mouseMove.deltaX = htons(deltaX); holder->packet.mouseMove.deltaY = htons(deltaY); err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); if (err != LBQ_SUCCESS) { free(holder); } return err; }
static int sendControllerEventInternal(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger, short leftStickX, short leftStickY, short rightStickX, short rightStickY) { PPACKET_HOLDER holder; int err; if (!initialized) { return -2; } holder = malloc(sizeof(*holder)); if (holder == NULL) { return -1; } if (ServerMajorVersion == 3) { // Generation 3 servers don't support multiple controllers so we send // the legacy packet holder->packetLength = sizeof(NV_CONTROLLER_PACKET); holder->packet.controller.header.packetType = htonl(PACKET_TYPE_CONTROLLER); holder->packet.controller.headerA = C_HEADER_A; holder->packet.controller.headerB = C_HEADER_B; holder->packet.controller.buttonFlags = buttonFlags; holder->packet.controller.leftTrigger = leftTrigger; holder->packet.controller.rightTrigger = rightTrigger; holder->packet.controller.leftStickX = leftStickX; holder->packet.controller.leftStickY = leftStickY; holder->packet.controller.rightStickX = rightStickX; holder->packet.controller.rightStickY = rightStickY; holder->packet.controller.tailA = C_TAIL_A; holder->packet.controller.tailB = C_TAIL_B; } else { // Generation 4+ servers support passing the controller number holder->packetLength = sizeof(NV_MULTI_CONTROLLER_PACKET); holder->packet.multiController.header.packetType = htonl(PACKET_TYPE_MULTI_CONTROLLER); holder->packet.multiController.headerA = MC_HEADER_A; holder->packet.multiController.headerB = MC_HEADER_B; holder->packet.multiController.controllerNumber = controllerNumber; holder->packet.multiController.midA = MC_MID_A; holder->packet.multiController.midB = MC_MID_B; holder->packet.multiController.buttonFlags = buttonFlags; holder->packet.multiController.leftTrigger = leftTrigger; holder->packet.multiController.rightTrigger = rightTrigger; holder->packet.multiController.leftStickX = leftStickX; holder->packet.multiController.leftStickY = leftStickY; holder->packet.multiController.rightStickX = rightStickX; holder->packet.multiController.rightStickY = rightStickY; holder->packet.multiController.tailA = MC_TAIL_A; holder->packet.multiController.tailB = MC_TAIL_B; } err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); if (err != LBQ_SUCCESS) { free(holder); } return err; }
static void ReceiveThreadProc(void* context) { SOCK_RET err; PRTP_PACKET rtp; int packetSize; char* buffer = NULL; while (!PltIsThreadInterrupted(&receiveThread)) { if (buffer == NULL) { buffer = (char*) malloc(MAX_PACKET_SIZE + sizeof(int)); if (buffer == NULL) { Limelog("Receive thread terminating\n"); listenerCallbacks->connectionTerminated(-1); return; } } err = recv(rtpSocket, &buffer[sizeof(int)], MAX_PACKET_SIZE, 0); if (err <= 0) { Limelog("Receive thread terminating #2\n"); free(buffer); listenerCallbacks->connectionTerminated(LastSocketError()); return; } packetSize = (int)err; if (packetSize < sizeof(RTP_PACKET)) { // Runt packet continue; } rtp = (PRTP_PACKET) &buffer[sizeof(int)]; if (rtp->packetType != 97) { // Not audio continue; } memcpy(buffer, &packetSize, sizeof(int)); err = LbqOfferQueueItem(&packetQueue, buffer); if (err == LBQ_SUCCESS) { // The queue owns the buffer now buffer = NULL; } if (err == LBQ_BOUND_EXCEEDED) { Limelog("Audio packet queue overflow\n"); freePacketList(LbqFlushQueueItems(&packetQueue)); } else if (err == LBQ_INTERRUPTED) { Limelog("Receive thread terminating #2\n"); free(buffer); return; } } }
static int queuePacketToLbq(PQUEUED_AUDIO_PACKET* packet) { int err; err = LbqOfferQueueItem(&packetQueue, *packet, &(*packet)->q.lentry); if (err == LBQ_SUCCESS) { // The LBQ owns the buffer now *packet = NULL; } else if (err == LBQ_BOUND_EXCEEDED) { Limelog("Audio packet queue overflow\n"); freePacketList(LbqFlushQueueItems(&packetQueue)); } else if (err == LBQ_INTERRUPTED) { return 0; } return 1; }
void queueFrameInvalidationTuple(int startFrame, int endFrame) { if (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION) { PQUEUED_FRAME_INVALIDATION_TUPLE qfit; qfit = malloc(sizeof(*qfit)); if (qfit != NULL) { qfit->startFrame = startFrame; qfit->endFrame = endFrame; if (LbqOfferQueueItem(&invalidReferenceFrameTuples, qfit, &qfit->entry) == LBQ_BOUND_EXCEEDED) { // Too many invalidation tuples, so we need an IDR frame now free(qfit); idrFrameRequired = 1; } } else { idrFrameRequired = 1; } } else { idrFrameRequired = 1; } PltSetEvent(&invalidateRefFramesEvent); }