summaryrefslogtreecommitdiff
path: root/src/spice-stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/spice-stream.cpp')
-rw-r--r--src/spice-stream.cpp162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/spice-stream.cpp b/src/spice-stream.cpp
new file mode 100644
index 0000000..3aa951c
--- /dev/null
+++ b/src/spice-stream.cpp
@@ -0,0 +1,162 @@
+/* Utility to manage registration of plugins compiled statically
+ *
+ * \copyright
+ * Copyright 2017 Red Hat Inc. All rights reserved.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <syslog.h>
+#include <string.h>
+#include <memory>
+#include <spice/stream-device.h>
+#include <spice/enums.h>
+
+#include "spice-stream.hpp"
+
+// FIXME
+extern int streaming_requested;
+
+using namespace SpiceStreamingAgent;
+
+struct SpiceStreamFormatMessage
+{
+ StreamDevHeader hdr;
+ StreamMsgFormat msg;
+};
+
+struct SpiceStreamDataMessage
+{
+ StreamDevHeader hdr;
+ StreamMsgData msg;
+};
+
+int SpiceStream::read_command()
+{
+ StreamDevHeader hdr;
+ uint8_t msg[64];
+ int n;
+
+ std::lock_guard<std::mutex> stream_guard(stream_mtx);
+ n = read(streamfd, &hdr, sizeof(hdr));
+ if (n != sizeof(hdr)) {
+ syslog(LOG_WARNING,
+ "read command from device FAILED -- read %d expected %lu\n",
+ n, sizeof(hdr));
+ return -1;
+ }
+ if (hdr.protocol_version != STREAM_DEVICE_PROTOCOL) {
+ syslog(LOG_WARNING, "BAD VERSION %d (expected is %d)\n", hdr.protocol_version,
+ STREAM_DEVICE_PROTOCOL);
+ return 0; // return -1; -- fail over this ?
+ }
+ if (hdr.type != STREAM_TYPE_START_STOP) {
+ syslog(LOG_WARNING, "UNKNOWN msg of type %d\n", hdr.type);
+ return 0; // return -1;
+ }
+ if (hdr.size >= sizeof(msg)) {
+ syslog(LOG_WARNING,
+ "msg size (%d) is too long (longer than %lu)\n",
+ hdr.size, sizeof(msg));
+ return 0; // return -1;
+ }
+ n = read(streamfd, &msg, hdr.size);
+ if (n != hdr.size) {
+ syslog(LOG_WARNING,
+ "read command from device FAILED -- read %d expected %d\n",
+ n, hdr.size);
+ return -1;
+ }
+ streaming_requested = msg[0]; /* num_codecs */
+ syslog(LOG_INFO, "GOT START_STOP message -- request to %s streaming\n",
+ streaming_requested ? "START" : "STOP");
+ return 1;
+}
+
+int SpiceStream::send_format(unsigned w, unsigned h, unsigned c)
+{
+
+ SpiceStreamFormatMessage msg;
+ const size_t msgsize = sizeof(msg);
+ const size_t hdrsize = sizeof(msg.hdr);
+ memset(&msg, 0, msgsize);
+ msg.hdr.protocol_version = STREAM_DEVICE_PROTOCOL;
+ msg.hdr.type = STREAM_TYPE_FORMAT;
+ msg.hdr.size = msgsize - hdrsize; /* includes only the body? */
+ msg.msg.width = w;
+ msg.msg.height = h;
+ msg.msg.codec = c;
+ syslog(LOG_DEBUG, "writing format\n");
+ std::lock_guard<std::mutex> stream_guard(stream_mtx);
+ if (write_all(&msg, msgsize) != msgsize) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+int SpiceStream::send_frame(const void *buf, const unsigned size)
+{
+ SpiceStreamDataMessage msg;
+ const size_t msgsize = sizeof(msg);
+ ssize_t n;
+
+ memset(&msg, 0, msgsize);
+ msg.hdr.protocol_version = STREAM_DEVICE_PROTOCOL;
+ msg.hdr.type = STREAM_TYPE_DATA;
+ msg.hdr.size = size; /* includes only the body? */
+ std::lock_guard<std::mutex> stream_guard(stream_mtx);
+ n = write_all(&msg, msgsize);
+ syslog(LOG_DEBUG,
+ "wrote %ld bytes of header of data msg with frame of size %u bytes\n",
+ n, msg.hdr.size);
+ if (n != msgsize) {
+ syslog(LOG_WARNING, "write_all header: wrote %ld expected %lu\n",
+ n, msgsize);
+ return EXIT_FAILURE;
+ }
+ n = write_all(buf, size);
+ syslog(LOG_DEBUG, "wrote data msg body of size %ld\n", n);
+ if (n != size) {
+ syslog(LOG_WARNING, "write_all header: wrote %ld expected %u\n",
+ n, size);
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+void SpiceStream::send_cursor(unsigned width, unsigned height, int hotspot_x, int hotspot_y,
+ std::function<void(uint32_t *)> fill_cursor)
+{
+ if (width >= STREAM_MSG_CURSOR_SET_MAX_WIDTH ||
+ height >= STREAM_MSG_CURSOR_SET_MAX_HEIGHT)
+ return;
+
+ size_t cursor_size =
+ sizeof(StreamDevHeader) + sizeof(StreamMsgCursorSet) +
+ width * height * sizeof(uint32_t);
+ std::unique_ptr<uint8_t[]> msg(new uint8_t[cursor_size]);
+
+ StreamDevHeader &dev_hdr(*reinterpret_cast<StreamDevHeader*>(msg.get()));
+ memset(&dev_hdr, 0, sizeof(dev_hdr));
+ dev_hdr.protocol_version = STREAM_DEVICE_PROTOCOL;
+ dev_hdr.type = STREAM_TYPE_CURSOR_SET;
+ dev_hdr.size = cursor_size - sizeof(StreamDevHeader);
+
+ StreamMsgCursorSet &cursor_msg(*reinterpret_cast<StreamMsgCursorSet *>(msg.get() + sizeof(StreamDevHeader)));
+ memset(&cursor_msg, 0, sizeof(cursor_msg));
+
+ cursor_msg.type = SPICE_CURSOR_TYPE_ALPHA;
+ cursor_msg.width = width;
+ cursor_msg.height = height;
+ cursor_msg.hot_spot_x = hotspot_x;
+ cursor_msg.hot_spot_y = hotspot_y;
+
+ uint32_t *pixels = reinterpret_cast<uint32_t *>(cursor_msg.data);
+ fill_cursor(pixels);
+
+ std::lock_guard<std::mutex> stream_guard(stream_mtx);
+ write_all(msg.get(), cursor_size);
+}
+