summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/main_dispatcher.c32
-rw-r--r--server/main_dispatcher.h1
-rw-r--r--server/reds-private.h2
-rw-r--r--server/reds.c28
-rw-r--r--server/reds.h2
5 files changed, 64 insertions, 1 deletions
diff --git a/server/main_dispatcher.c b/server/main_dispatcher.c
index 1126ec06..84024024 100644
--- a/server/main_dispatcher.c
+++ b/server/main_dispatcher.c
@@ -40,6 +40,7 @@ MainDispatcher main_dispatcher;
enum {
MAIN_DISPATCHER_CHANNEL_EVENT = 0,
MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
+ MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
MAIN_DISPATCHER_NUM_MESSAGES
};
@@ -53,6 +54,11 @@ typedef struct MainDispatcherMigrateSeamlessDstCompleteMessage {
RedClient *client;
} MainDispatcherMigrateSeamlessDstCompleteMessage;
+typedef struct MainDispatcherMmTimeLatencyMessage {
+ RedClient *client;
+ uint32_t latency;
+} MainDispatcherMmTimeLatencyMessage;
+
/* channel_event - calls core->channel_event, must be done in main thread */
static void main_dispatcher_self_handle_channel_event(
int event,
@@ -96,6 +102,13 @@ static void main_dispatcher_handle_migrate_complete(void *opaque,
reds_on_client_seamless_migrate_complete(mig_complete->client);
}
+static void main_dispatcher_handle_mm_time_latency(void *opaque,
+ void *payload)
+{
+ MainDispatcherMmTimeLatencyMessage *msg = payload;
+ reds_set_client_mm_time_latency(msg->client, msg->latency);
+}
+
void main_dispatcher_seamless_migrate_dst_complete(RedClient *client)
{
MainDispatcherMigrateSeamlessDstCompleteMessage msg;
@@ -109,6 +122,22 @@ void main_dispatcher_seamless_migrate_dst_complete(RedClient *client)
dispatcher_send_message(&main_dispatcher.base, MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
&msg);
}
+
+void main_dispatcher_set_mm_time_latency(RedClient *client, uint32_t latency)
+{
+ MainDispatcherMmTimeLatencyMessage msg;
+
+ if (pthread_self() == main_dispatcher.base.self) {
+ reds_set_client_mm_time_latency(client, latency);
+ return;
+ }
+
+ msg.client = client;
+ msg.latency = latency;
+ dispatcher_send_message(&main_dispatcher.base, MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
+ &msg);
+}
+
static void dispatcher_handle_read(int fd, int event, void *opaque)
{
Dispatcher *dispatcher = opaque;
@@ -129,4 +158,7 @@ void main_dispatcher_init(SpiceCoreInterface *core)
dispatcher_register_handler(&main_dispatcher.base, MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
main_dispatcher_handle_migrate_complete,
sizeof(MainDispatcherMigrateSeamlessDstCompleteMessage), 0 /* no ack */);
+ dispatcher_register_handler(&main_dispatcher.base, MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
+ main_dispatcher_handle_mm_time_latency,
+ sizeof(MainDispatcherMmTimeLatencyMessage), 0 /* no ack */);
}
diff --git a/server/main_dispatcher.h b/server/main_dispatcher.h
index d44ee3a5..0c79ca8d 100644
--- a/server/main_dispatcher.h
+++ b/server/main_dispatcher.h
@@ -6,6 +6,7 @@
void main_dispatcher_channel_event(int event, SpiceChannelEventInfo *info);
void main_dispatcher_seamless_migrate_dst_complete(RedClient *client);
+void main_dispatcher_set_mm_time_latency(RedClient *client, uint32_t latency);
void main_dispatcher_init(SpiceCoreInterface *core);
#endif //MAIN_DISPATCHER_H
diff --git a/server/reds-private.h b/server/reds-private.h
index 3db6565b..9358d27c 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -177,6 +177,8 @@ typedef struct RedsState {
int allow_multiple_clients;
RedsClientMonitorsConfig client_monitors_config;
+ int mm_timer_enabled;
+ uint32_t mm_time_latency;
} RedsState;
#endif
diff --git a/server/reds.c b/server/reds.c
index 822289bc..c3b5518c 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3031,6 +3031,29 @@ listen:
return slisten;
}
+static void reds_send_mm_time(void)
+{
+ main_channel_push_multi_media_time(reds->main_channel,
+ reds_get_mm_time() - reds->mm_time_latency);
+}
+
+void reds_set_client_mm_time_latency(RedClient *client, uint32_t latency)
+{
+ // TODO: multi-client support for mm_time
+ if (reds->mm_timer_enabled) {
+ // TODO: consider network latency
+ if (latency > reds->mm_time_latency) {
+ reds->mm_time_latency = latency;
+ reds_send_mm_time();
+ } else {
+ spice_debug("new latency %u is smaller than existing %u",
+ latency, reds->mm_time_latency);
+ }
+ } else {
+ snd_set_playback_latency(client, latency);
+ }
+}
+
static int reds_init_net(void)
{
if (spice_port != -1) {
@@ -3463,12 +3486,15 @@ void reds_enable_mm_timer(void)
if (!reds_main_channel_connected()) {
return;
}
- main_channel_push_multi_media_time(reds->main_channel, reds_get_mm_time() - MM_TIME_DELTA);
+ reds->mm_timer_enabled = TRUE;
+ reds->mm_time_latency = MM_TIME_DELTA;
+ reds_send_mm_time();
}
void reds_disable_mm_timer(void)
{
core->timer_cancel(reds->mm_timer);
+ reds->mm_timer_enabled = FALSE;
}
static void mm_timer_proc(void *opaque)
diff --git a/server/reds.h b/server/reds.h
index f8e8d56c..59f13cec 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -164,4 +164,6 @@ void reds_on_client_seamless_migrate_complete(RedClient *client);
void reds_on_main_channel_migrate(MainChannelClient *mcc);
void reds_on_char_device_state_destroy(SpiceCharDeviceState *dev);
+void reds_set_client_mm_time_latency(RedClient *client, uint32_t latency);
+
#endif