diff options
Diffstat (limited to 'server/snd_worker.c')
-rw-r--r-- | server/snd_worker.c | 157 |
1 files changed, 97 insertions, 60 deletions
diff --git a/server/snd_worker.c b/server/snd_worker.c index 332612f5..4c9a6f01 100644 --- a/server/snd_worker.c +++ b/server/snd_worker.c @@ -28,6 +28,7 @@ #include "spice.h" #include "red_common.h" +#include "main_channel.h" #include "reds.h" #include "red_dispatcher.h" #include "snd_worker.h" @@ -35,12 +36,6 @@ #include "generated_marshallers.h" #include "demarshallers.h" -/* main_channel.h inclusion drags red_channel.h which has conflicting types. - * until the channels here are defined in terms of red_channel.h we have some - * duplicate declarations */ -MainChannelClient *red_client_get_main(RedClient *client); -int main_channel_client_is_low_bandwidth(MainChannelClient *mcc); - #define MAX_SEND_VEC 100 #define RECIVE_BUF_SIZE (16 * 1024 * 2) @@ -78,10 +73,10 @@ enum RecordCommand { #define SND_RECORD_VOLUME_MASK (1 << SND_RECORD_VOLUME) typedef struct SndChannel SndChannel; -typedef void (*send_messages_proc)(void *in_channel); -typedef int (*handle_message_proc)(SndChannel *channel, size_t size, uint32_t type, void *message); -typedef void (*on_message_done_proc)(SndChannel *channel); -typedef void (*cleanup_channel_proc)(SndChannel *channel); +typedef void (*snd_channel_send_messages_proc)(void *in_channel); +typedef int (*snd_channel_handle_message_proc)(SndChannel *channel, size_t size, uint32_t type, void *message); +typedef void (*snd_channel_on_message_done_proc)(SndChannel *channel); +typedef void (*snd_channel_cleanup_channel_proc)(SndChannel *channel); typedef struct SndWorker SndWorker; @@ -90,6 +85,8 @@ struct SndChannel { SndWorker *worker; spice_parse_channel_func_t parser; + RedChannelClient *channel_client; + int active; int client_active; int blocked; @@ -116,10 +113,10 @@ struct SndChannel { uint8_t *end; } recive_data; - send_messages_proc send_messages; - handle_message_proc handle_message; - on_message_done_proc on_message_done; - cleanup_channel_proc cleanup; + snd_channel_send_messages_proc send_messages; + snd_channel_handle_message_proc handle_message; + snd_channel_on_message_done_proc on_message_done; + snd_channel_cleanup_channel_proc cleanup; int num_caps; uint32_t *caps; }; @@ -146,7 +143,7 @@ typedef struct PlaybackChannel { } PlaybackChannel; struct SndWorker { - Channel base; + RedChannel *base_channel; SndChannel *connection; SndWorker *next; int active; @@ -193,7 +190,7 @@ typedef struct RecordChannel { uint32_t celt_buf[FRAME_SIZE]; } RecordChannel; -static SndWorker *workers = NULL; +static SndWorker *workers; static uint32_t playback_compression = SPICE_AUDIO_DATA_MODE_CELT_0_5_1; static void snd_receive(void* data); @@ -863,10 +860,11 @@ static void snd_record_send(void* data) static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_id, RedClient *client, RedsStream *stream, - int migrate, send_messages_proc send_messages, - handle_message_proc handle_message, - on_message_done_proc on_message_done, - cleanup_channel_proc cleanup, + int migrate, + snd_channel_send_messages_proc send_messages, + snd_channel_handle_message_proc handle_message, + snd_channel_on_message_done_proc on_message_done, + snd_channel_cleanup_channel_proc cleanup, uint32_t *caps, int num_caps) { SndChannel *channel; @@ -926,6 +924,10 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i channel->cleanup = cleanup; channel->num_caps = num_caps; channel->caps = spice_memdup(caps, num_caps * sizeof(uint32_t)); + + channel->channel_client = red_channel_client_create_dummy(sizeof(RedChannelClient), + worker->base_channel, + client); return channel; error2: @@ -936,9 +938,15 @@ error1: return NULL; } -static void snd_shutdown(Channel *channel) +static void snd_disconnect_channel_client(RedChannelClient *rcc) { - SndWorker *worker = (SndWorker *)channel; + SndWorker *worker; + + ASSERT(rcc->channel); + ASSERT(rcc->channel->data); + worker = (SndWorker *)rcc->channel->data; + + ASSERT(worker->connection->channel_client == rcc); snd_disconnect_channel(worker->connection); } @@ -1096,13 +1104,13 @@ static void snd_playback_cleanup(SndChannel *channel) celt051_mode_destroy(playback_channel->celt_mode); } -static void snd_set_playback_peer(Channel *channel, RedClient *client, RedsStream *stream, +static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) { - SndWorker *worker = (SndWorker *)channel; - SpicePlaybackState *st = SPICE_CONTAINEROF(worker, SpicePlaybackState, worker); + SndWorker *worker = channel->data; PlaybackChannel *playback_channel; + SpicePlaybackState *st = SPICE_CONTAINEROF(worker, SpicePlaybackState, worker); CELTEncoder *celt_encoder; CELTMode *celt_mode; int celt_error; @@ -1158,10 +1166,16 @@ error_1: celt051_mode_destroy(celt_mode); } -static void snd_record_migrate(Channel *channel) +static void snd_record_migrate_channel_client(RedChannelClient *rcc) { - SndWorker *worker = (SndWorker *)channel; + SndWorker *worker; + + ASSERT(rcc->channel); + ASSERT(rcc->channel->data); + worker = (SndWorker *)rcc->channel->data; + if (worker->connection) { + ASSERT(worker->connection->channel_client == rcc); snd_set_command(worker->connection, SND_RECORD_MIGRATE_MASK); snd_record_send(worker->connection); } @@ -1290,19 +1304,19 @@ static void on_new_record_channel(SndWorker *worker) static void snd_record_cleanup(SndChannel *channel) { - RecordChannel *record_channel = (RecordChannel *)channel; + RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base); celt051_decoder_destroy(record_channel->celt_decoder); celt051_mode_destroy(record_channel->celt_mode); } -static void snd_set_record_peer(Channel *channel, RedClient *client, RedsStream *stream, +static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) { - SndWorker *worker = (SndWorker *)channel; - SpiceRecordState *st = SPICE_CONTAINEROF(worker, SpiceRecordState, worker); + SndWorker *worker = channel->data; RecordChannel *record_channel; + SpiceRecordState *st = SPICE_CONTAINEROF(worker, SpiceRecordState, worker); CELTDecoder *celt_decoder; CELTMode *celt_mode; int celt_error; @@ -1354,11 +1368,16 @@ error_2: celt051_mode_destroy(celt_mode); } -static void snd_playback_migrate(Channel *channel) +static void snd_playback_migrate_channel_client(RedChannelClient *rcc) { - SndWorker *worker = (SndWorker *)channel; + SndWorker *worker; + + ASSERT(rcc->channel); + ASSERT(rcc->channel->data); + worker = (SndWorker *)rcc->channel->data; if (worker->connection) { + ASSERT(worker->connection->channel_client == rcc); snd_set_command(worker->connection, SND_PLAYBACK_MIGRATE_MASK); snd_playback_send(worker->connection); } @@ -1386,48 +1405,67 @@ static void remove_worker(SndWorker *worker) void snd_attach_playback(SpicePlaybackInstance *sin) { SndWorker *playback_worker; + int num_caps; + uint32_t *caps; + RedChannel *channel; + ClientCbs client_cbs = {0,}; sin->st = spice_new0(SpicePlaybackState, 1); sin->st->sin = sin; playback_worker = &sin->st->worker; - playback_worker->base.type = SPICE_CHANNEL_PLAYBACK; - playback_worker->base.link = snd_set_playback_peer; - playback_worker->base.shutdown = snd_shutdown; - playback_worker->base.migrate = snd_playback_migrate; - playback_worker->base.data = NULL; + // TODO: Make RedChannel base of worker? instead of assigning it to channel->data + channel = red_channel_create_dummy(sizeof(RedChannel), SPICE_CHANNEL_PLAYBACK, 0); + + channel->data = playback_worker; + client_cbs.connect = snd_set_playback_peer; + client_cbs.disconnect = snd_disconnect_channel_client; + client_cbs.migrate = snd_playback_migrate_channel_client; + red_channel_register_client_cbs(channel, &client_cbs); + red_channel_set_data(channel, playback_worker); - playback_worker->base.num_caps = 1; - playback_worker->base.caps = spice_new(uint32_t, 1); - playback_worker->base.caps[0] = - (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1) | - (1 << SPICE_PLAYBACK_CAP_VOLUME); + num_caps = 1; + caps = spice_new(uint32_t, 1); + caps[0] = (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1) | + (1 << SPICE_PLAYBACK_CAP_VOLUME); + red_channel_set_caps(channel, num_caps, caps); + playback_worker->base_channel = channel; add_worker(playback_worker); - reds_register_channel(&playback_worker->base); + reds_register_channel(playback_worker->base_channel); } void snd_attach_record(SpiceRecordInstance *sin) { SndWorker *record_worker; + int num_caps; + uint32_t *caps; + RedChannel *channel; + ClientCbs client_cbs = {0,}; sin->st = spice_new0(SpiceRecordState, 1); sin->st->sin = sin; record_worker = &sin->st->worker; - record_worker->base.type = SPICE_CHANNEL_RECORD; - record_worker->base.link = snd_set_record_peer; - record_worker->base.shutdown = snd_shutdown; - record_worker->base.migrate = snd_record_migrate; - record_worker->base.data = NULL; - - record_worker->base.num_caps = 1; - record_worker->base.caps = spice_new(uint32_t, 1); - record_worker->base.caps[0] = - (1 << SPICE_RECORD_CAP_CELT_0_5_1) | - (1 << SPICE_RECORD_CAP_VOLUME); + // TODO: Make RedChannel base of worker? instead of assigning it to channel->data + channel = red_channel_create_dummy(sizeof(RedChannel), SPICE_CHANNEL_RECORD, 0); + + channel->data = record_worker; + client_cbs.connect = snd_set_record_peer; + client_cbs.disconnect = snd_disconnect_channel_client; + client_cbs.migrate = snd_record_migrate_channel_client; + red_channel_register_client_cbs(channel, &client_cbs); + red_channel_set_data(channel, record_worker); + + num_caps = 1; + caps = spice_new(uint32_t, 1); + caps[0] = (1 << SPICE_RECORD_CAP_CELT_0_5_1) | + (1 << SPICE_RECORD_CAP_VOLUME); + red_channel_set_caps(channel, num_caps, caps); + + record_worker->base_channel = channel; add_worker(record_worker); - reds_register_channel(&record_worker->base); + reds_register_channel(record_worker->base_channel); } static void snd_detach_common(SndWorker *worker) @@ -1437,9 +1475,8 @@ static void snd_detach_common(SndWorker *worker) } remove_worker(worker); snd_disconnect_channel(worker->connection); - reds_unregister_channel(&worker->base); - - reds_channel_dispose(&worker->base); + reds_unregister_channel(worker->base_channel); + red_channel_destroy(worker->base_channel); } static void spice_playback_state_free(SpicePlaybackState *st) @@ -1472,7 +1509,7 @@ void snd_set_playback_compression(int on) playback_compression = on ? SPICE_AUDIO_DATA_MODE_CELT_0_5_1 : SPICE_AUDIO_DATA_MODE_RAW; for (; now; now = now->next) { - if (now->base.type == SPICE_CHANNEL_PLAYBACK && now->connection) { + if (now->base_channel->type == SPICE_CHANNEL_PLAYBACK && now->connection) { SndChannel* sndchannel = now->connection; PlaybackChannel* playback = (PlaybackChannel*)now->connection; if (!check_cap(sndchannel->caps, sndchannel->num_caps, |