summaryrefslogtreecommitdiffstats
path: root/src/modules/module-protocol-native/protocol-footer.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/modules/module-protocol-native/protocol-footer.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/modules/module-protocol-native/protocol-footer.c b/src/modules/module-protocol-native/protocol-footer.c
new file mode 100644
index 0000000..9b6fe62
--- /dev/null
+++ b/src/modules/module-protocol-native/protocol-footer.c
@@ -0,0 +1,152 @@
+/* PipeWire
+ *
+ * Copyright © 2018 Wim Taymans
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <spa/pod/builder.h>
+#include <spa/pod/parser.h>
+#include <spa/utils/result.h>
+
+#include <pipewire/private.h>
+
+#include "connection.h"
+#include "protocol-footer.h"
+#include "defs.h"
+
+PW_LOG_TOPIC_EXTERN(mod_topic);
+#define PW_LOG_TOPIC_DEFAULT mod_topic
+
+struct footer_builder {
+ struct spa_pod_builder *builder;
+ struct spa_pod_frame outer;
+ struct spa_pod_frame inner;
+ unsigned int started:1;
+};
+
+#define FOOTER_BUILDER_INIT(builder) ((struct footer_builder) { (builder) })
+
+static void start_footer_entry(struct footer_builder *fb, uint32_t opcode)
+{
+ if (!fb->started) {
+ spa_pod_builder_push_struct(fb->builder, &fb->outer);
+ fb->started = true;
+ }
+
+ spa_pod_builder_id(fb->builder, opcode);
+ spa_pod_builder_push_struct(fb->builder, &fb->inner);
+}
+
+static void end_footer_entry(struct footer_builder *fb)
+{
+ spa_pod_builder_pop(fb->builder, &fb->inner);
+}
+
+static void end_footer(struct footer_builder *fb)
+{
+ if (!fb->started)
+ return;
+
+ spa_pod_builder_pop(fb->builder, &fb->outer);
+}
+
+void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core,
+ struct spa_pod_builder *builder)
+{
+ struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
+
+ if (core->recv_generation != state->last_recv_generation) {
+ state->last_recv_generation = core->recv_generation;
+
+ pw_log_trace("core %p: send client registry generation:%"PRIu64,
+ core, core->recv_generation);
+
+ start_footer_entry(&fb, FOOTER_CLIENT_OPCODE_GENERATION);
+ spa_pod_builder_long(fb.builder, core->recv_generation);
+ end_footer_entry(&fb);
+ }
+
+ end_footer(&fb);
+}
+
+void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client,
+ struct spa_pod_builder *builder)
+{
+ struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
+
+ if (client->context->generation != client->sent_generation) {
+ client->sent_generation = client->context->generation;
+
+ pw_log_trace("impl-client %p: send server registry generation:%"PRIu64,
+ client, client->context->generation);
+
+ start_footer_entry(&fb, FOOTER_CORE_OPCODE_GENERATION);
+ spa_pod_builder_long(fb.builder, client->context->generation);
+ end_footer_entry(&fb);
+ }
+
+ end_footer(&fb);
+}
+
+int demarshal_core_generation(void *object, struct spa_pod_parser *parser)
+{
+ struct pw_core *core = object;
+ int64_t generation;
+
+ if (spa_pod_parser_get_long(parser, &generation) < 0)
+ return -EINVAL;
+
+ core->recv_generation = SPA_MAX(core->recv_generation,
+ (uint64_t)generation);
+
+ pw_log_trace("core %p: recv server registry generation:%"PRIu64,
+ core, generation);
+
+ return 0;
+}
+
+int demarshal_client_generation(void *object, struct spa_pod_parser *parser)
+{
+ struct pw_impl_client *client = object;
+ int64_t generation;
+
+ if (spa_pod_parser_get_long(parser, &generation) < 0)
+ return -EINVAL;
+
+ client->recv_generation = SPA_MAX(client->recv_generation,
+ (uint64_t)generation);
+
+ pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64,
+ client, generation);
+
+ return 0;
+}
+
+const struct footer_demarshal footer_core_demarshal[FOOTER_CORE_OPCODE_LAST] = {
+ [FOOTER_CORE_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_core_generation },
+};
+
+const struct footer_demarshal footer_client_demarshal[FOOTER_CLIENT_OPCODE_LAST] = {
+ [FOOTER_CLIENT_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_client_generation },
+};