diff options
-rw-r--r-- | server/main_dispatcher.c | 32 | ||||
-rw-r--r-- | server/main_dispatcher.h | 1 | ||||
-rw-r--r-- | server/reds-private.h | 2 | ||||
-rw-r--r-- | server/reds.c | 28 | ||||
-rw-r--r-- | server/reds.h | 2 |
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 |