summaryrefslogtreecommitdiffstats
path: root/server/snd_worker.c
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2011-08-03 18:36:04 +0300
committerAlon Levy <alevy@redhat.com>2011-08-23 18:27:46 +0300
commitf84dfeb0aac4b6b49bc447a2140cbc7c2882de51 (patch)
tree67797cd53349553b101bf1f9c5ea4057b123bacb /server/snd_worker.c
parent1db936e64cfe955a757d9d77302f104f68a58bfd (diff)
downloadspice-f84dfeb0aac4b6b49bc447a2140cbc7c2882de51.tar.gz
spice-f84dfeb0aac4b6b49bc447a2140cbc7c2882de51.tar.xz
spice-f84dfeb0aac4b6b49bc447a2140cbc7c2882de51.zip
server: registering RedChannel in reds, instead of Channel
Merging the functionality of reds::channel, into RedChannel. In addition, cleanup and fix disconnection code: before this patch, red_dispatcher_disconnect_display_client could have been called from the red_worker thread (and it must be called only from the io thread). RedChannel holds only connected channel clients. RedClient holds all the channel clients that were created till it is destroyed (and then it destroys them as well). Note: snd_channel still doesn't use red_channel, however it creates dummy channel and channel clients, in order to register itself in reds. server/red_channel.c: a channel is connected if it holds at least one channel client Previously I changed RedChannel to hold only connected channel clients and RedClient, to hold all the channel clients as long as it is not destroyed. usbredir: multichannel has not been tested, it just compiles.
Diffstat (limited to 'server/snd_worker.c')
-rw-r--r--server/snd_worker.c157
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,