SoundInterfaces: redesign

This commit is contained in:
Gerd Hoffmann 2010-04-13 14:35:32 +02:00
parent 4701a063da
commit 6fdcb9310d
4 changed files with 142 additions and 142 deletions

View File

@ -4126,23 +4126,23 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
reds->monitor_mode.y_res);
}
} else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
red_printf("VD_INTERFACE_PLAYBACK");
if (interface->major_version != VD_INTERFACE_PLAYBACK_MAJOR ||
interface->minor_version < VD_INTERFACE_PLAYBACK_MINOR) {
} else if (strcmp(interface->type, SPICE_INTERFACE_PLAYBACK) == 0) {
red_printf("SPICE_INTERFACE_PLAYBACK");
if (interface->major_version != SPICE_INTERFACE_PLAYBACK_MAJOR ||
interface->minor_version < SPICE_INTERFACE_PLAYBACK_MINOR) {
red_printf("unsuported playback interface");
return -1;
}
snd_attach_playback((PlaybackInterface *)interface);
snd_attach_playback(SPICE_CONTAINEROF(sin, SpicePlaybackInstance, base));
} else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
} else if (strcmp(interface->type, SPICE_INTERFACE_RECORD) == 0) {
red_printf("VD_INTERFACE_RECORD");
if (interface->major_version != VD_INTERFACE_RECORD_MAJOR ||
interface->minor_version < VD_INTERFACE_RECORD_MINOR) {
if (interface->major_version != SPICE_INTERFACE_RECORD_MAJOR ||
interface->minor_version < SPICE_INTERFACE_RECORD_MINOR) {
red_printf("unsuported record interface");
return -1;
}
snd_attach_record((RecordInterface *)interface);
snd_attach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
} else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
red_printf("VD_INTERFACE_VDI_PORT");
@ -4191,13 +4191,13 @@ __visible__ int spice_server_remove_interface(SpiceBaseInstance *sin)
reds_update_mouse_mode();
}
} else if (strcmp(interface->type, VD_INTERFACE_PLAYBACK) == 0) {
red_printf("remove VD_INTERFACE_PLAYBACK");
snd_detach_playback((PlaybackInterface *)interface);
} else if (strcmp(interface->type, SPICE_INTERFACE_PLAYBACK) == 0) {
red_printf("remove SPICE_INTERFACE_PLAYBACK");
snd_detach_playback(SPICE_CONTAINEROF(sin, SpicePlaybackInstance, base));
} else if (strcmp(interface->type, VD_INTERFACE_RECORD) == 0) {
red_printf("remove VD_INTERFACE_RECORD");
snd_detach_record((RecordInterface *)interface);
} else if (strcmp(interface->type, SPICE_INTERFACE_RECORD) == 0) {
red_printf("remove SPICE_INTERFACE_RECORD");
snd_detach_record(SPICE_CONTAINEROF(sin, SpiceRecordInstance, base));
} else if (strcmp(interface->type, VD_INTERFACE_VDI_PORT) == 0) {
red_printf("remove VD_INTERFACE_VDI_PORT");

View File

@ -37,7 +37,7 @@
#define PLAYBACK_BUF_SIZE (FRAME_SIZE * 4)
#define CELT_BIT_RATE (64 * 1024)
#define CELT_COMPRESSED_FRAME_BYTES (FRAME_SIZE * CELT_BIT_RATE / VD_INTERFACE_PLAYBACK_FREQ / 8)
#define CELT_COMPRESSED_FRAME_BYTES (FRAME_SIZE * CELT_BIT_RATE / SPICE_INTERFACE_PLAYBACK_FREQ / 8)
#define RECORD_SAMPLES_SIZE (RECIVE_BUF_SIZE >> 2)
@ -121,7 +121,6 @@ struct AudioFrame {
typedef struct PlaybackChannel {
SndChannel base;
AudioFrame frames[3];
PlaybackPlug plug;
VDObjectRef plug_ref;
AudioFrame *free_frames;
AudioFrame *in_progress;
@ -147,6 +146,14 @@ struct SndWorker {
SndWorker *next;
};
struct SpicePlaybackState {
struct SndWorker worker;
};
struct SpiceRecordState {
struct SndWorker worker;
};
#define RECORD_MIG_VERSION 1
typedef struct __attribute__ ((__packed__)) RecordMigrateData {
@ -165,7 +172,6 @@ typedef struct __attribute__ ((__packed__)) RecordMigrateMessage {
typedef struct RecordChannel {
SndChannel base;
RecordPlug plug;
VDObjectRef plug_ref;
uint32_t samples[RECORD_SAMPLES_SIZE];
uint32_t write_pos;
@ -551,9 +557,9 @@ static int snd_playback_send_start(PlaybackChannel *playback_channel)
}
start = &playback_channel->send_data.u.start;
start->channels = VD_INTERFACE_PLAYBACK_CHAN;
start->frequency = VD_INTERFACE_PLAYBACK_FREQ;
ASSERT(VD_INTERFACE_PLAYBACK_FMT == VD_INTERFACE_AUDIO_FMT_S16);
start->channels = SPICE_INTERFACE_PLAYBACK_CHAN;
start->frequency = SPICE_INTERFACE_PLAYBACK_FREQ;
ASSERT(SPICE_INTERFACE_PLAYBACK_FMT == SPICE_INTERFACE_AUDIO_FMT_S16);
start->format = SPICE_AUDIO_FMT_S16;
start->time = reds_get_mm_time();
snd_add_buf(channel, start, sizeof(*start));
@ -592,9 +598,9 @@ static int snd_record_send_start(RecordChannel *record_channel)
}
start = &record_channel->send_data.u.start;
start->channels = VD_INTERFACE_RECORD_CHAN;
start->frequency = VD_INTERFACE_RECORD_FREQ;
ASSERT(VD_INTERFACE_RECORD_FMT == VD_INTERFACE_AUDIO_FMT_S16);
start->channels = SPICE_INTERFACE_RECORD_CHAN;
start->frequency = SPICE_INTERFACE_RECORD_FREQ;
ASSERT(SPICE_INTERFACE_RECORD_FMT == SPICE_INTERFACE_AUDIO_FMT_S16);
start->format = SPICE_AUDIO_FMT_S16;
snd_add_buf(channel, start, sizeof(*start));
@ -846,10 +852,13 @@ static void snd_set_command(SndChannel *channel, uint32_t command)
channel->command |= command;
}
static void snd_playback_start(PlaybackPlug *plug)
__visible__ void spice_server_playback_start(SpicePlaybackInstance *sin)
{
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
SndChannel *channel = sin->st->worker.connection;
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
if (!channel)
return;
ASSERT(!playback_channel->base.active);
reds_desable_mm_timer();
playback_channel->base.active = TRUE;
@ -861,10 +870,13 @@ static void snd_playback_start(PlaybackPlug *plug)
}
}
static void snd_playback_stop(PlaybackPlug *plug)
__visible__ void spice_server_playback_stop(SpicePlaybackInstance *sin)
{
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
SndChannel *channel = sin->st->worker.connection;
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
if (!channel)
return;
ASSERT(playback_channel->base.active);
reds_enable_mm_timer();
playback_channel->base.active = FALSE;
@ -884,27 +896,32 @@ static void snd_playback_stop(PlaybackPlug *plug)
}
}
static void snd_playback_get_frame(PlaybackPlug *plug, uint32_t **frame, uint32_t *num_samples)
__visible__ void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
uint32_t **frame, uint32_t *num_samples)
{
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
SndChannel *channel = sin->st->worker.connection;
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
ASSERT(playback_channel->base.active);
if (!playback_channel->free_frames) {
if (!channel || !playback_channel->free_frames) {
*frame = NULL;
*num_samples = 0;
return;
}
ASSERT(playback_channel->base.active);
*frame = playback_channel->free_frames->samples;
playback_channel->free_frames = playback_channel->free_frames->next;
*num_samples = FRAME_SIZE;
}
static void snd_playback_put_frame(PlaybackPlug *plug, uint32_t *samples)
__visible__ void spice_server_playback_put_samples(SpicePlaybackInstance *sin, uint32_t *samples)
{
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(plug, PlaybackChannel, plug);
SndChannel *channel = sin->st->worker.connection;
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
AudioFrame *frame;
if (!channel)
return;
ASSERT(playback_channel->base.active);
if (playback_channel->pending_frame) {
@ -920,12 +937,11 @@ static void snd_playback_put_frame(PlaybackPlug *plug, uint32_t *samples)
static void on_new_playback_channel(SndWorker *worker)
{
PlaybackChannel *playback_channel = (PlaybackChannel *)worker->connection;
PlaybackInterface *interface = (PlaybackInterface *)worker->interface;
PlaybackChannel *playback_channel =
SPICE_CONTAINEROF(worker->connection, PlaybackChannel, base);
ASSERT(playback_channel);
playback_channel->plug_ref = interface->plug(interface, &playback_channel->plug,
&playback_channel->base.active);
snd_set_command((SndChannel *)playback_channel, SND_PLAYBACK_MODE_MASK);
if (!playback_channel->base.migrate && playback_channel->base.active) {
snd_set_command((SndChannel *)playback_channel, SND_PLAYBACK_CTRL_MASK);
@ -937,13 +953,11 @@ static void on_new_playback_channel(SndWorker *worker)
static void snd_playback_cleanup(SndChannel *channel)
{
PlaybackChannel *playback_channel = (PlaybackChannel *)channel;
PlaybackInterface *interface = (PlaybackInterface *)channel->worker->interface;
PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
if (playback_channel->base.active) {
reds_enable_mm_timer();
}
interface->unplug(interface, playback_channel->plug_ref);
celt051_encoder_destroy(playback_channel->celt_encoder);
celt051_mode_destroy(playback_channel->celt_mode);
@ -961,7 +975,8 @@ static void snd_set_playback_peer(Channel *channel, RedsStreamContext *peer, int
snd_disconnect_channel(worker->connection);
if (!(celt_mode = celt051_mode_create(VD_INTERFACE_PLAYBACK_FREQ, VD_INTERFACE_PLAYBACK_CHAN,
if (!(celt_mode = celt051_mode_create(SPICE_INTERFACE_PLAYBACK_FREQ,
SPICE_INTERFACE_PLAYBACK_CHAN,
FRAME_SIZE, &celt_error))) {
red_printf("create celt mode failed %d", celt_error);
return;
@ -987,12 +1002,6 @@ static void snd_set_playback_peer(Channel *channel, RedsStreamContext *peer, int
snd_playback_free_frame(playback_channel, &playback_channel->frames[1]);
snd_playback_free_frame(playback_channel, &playback_channel->frames[2]);
playback_channel->plug.major_version = VD_INTERFACE_PLAYBACK_MAJOR;
playback_channel->plug.minor_version = VD_INTERFACE_PLAYBACK_MINOR;
playback_channel->plug.start = snd_playback_start;
playback_channel->plug.stop = snd_playback_stop;
playback_channel->plug.get_frame = snd_playback_get_frame;
playback_channel->plug.put_frame = snd_playback_put_frame;
playback_channel->celt_mode = celt_mode;
playback_channel->celt_encoder = celt_encoder;
playback_channel->celt_allowed = num_caps > 0 && (caps[0] & (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1));
@ -1019,10 +1028,13 @@ static void snd_record_migrate(Channel *channel)
}
}
static void snd_record_start(RecordPlug *plug)
__visible__ void spice_server_record_start(SpiceRecordInstance *sin)
{
RecordChannel *record_channel = SPICE_CONTAINEROF(plug, RecordChannel, plug);
SndChannel *channel = sin->st->worker.connection;
RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
if (!channel)
return;
ASSERT(!record_channel->base.active);
record_channel->base.active = TRUE;
record_channel->read_pos = record_channel->write_pos = 0; //todo: improve by
@ -1035,10 +1047,13 @@ static void snd_record_start(RecordPlug *plug)
}
}
static void snd_record_stop(RecordPlug *plug)
__visible__ void spice_server_record_stop(SpiceRecordInstance *sin)
{
RecordChannel *record_channel = SPICE_CONTAINEROF(plug, RecordChannel, plug);
SndChannel *channel = sin->st->worker.connection;
RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
if (!channel)
return;
ASSERT(record_channel->base.active);
record_channel->base.active = FALSE;
if (record_channel->base.client_active) {
@ -1049,28 +1064,32 @@ static void snd_record_stop(RecordPlug *plug)
}
}
static uint32_t snd_record_read(RecordPlug *plug, uint32_t num_samples, uint32_t *samples)
__visible__ uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
uint32_t *samples, uint32_t bufsize)
{
RecordChannel *record_channel = SPICE_CONTAINEROF(plug, RecordChannel, plug);
SndChannel *channel = sin->st->worker.connection;
RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
uint32_t read_pos;
uint32_t now;
uint32_t len;
if (!channel)
return 0;
ASSERT(record_channel->base.active);
if (record_channel->write_pos < RECORD_SAMPLES_SIZE / 2) {
return 0;
}
len = MIN(record_channel->write_pos - record_channel->read_pos, num_samples);
len = MIN(record_channel->write_pos - record_channel->read_pos, bufsize);
if (len < num_samples) {
if (len < bufsize) {
SndWorker *worker = record_channel->base.worker;
snd_receive(record_channel);
if (!worker->connection) {
return 0;
}
len = MIN(record_channel->write_pos - record_channel->read_pos, num_samples);
len = MIN(record_channel->write_pos - record_channel->read_pos, bufsize);
}
read_pos = record_channel->read_pos % RECORD_SAMPLES_SIZE;
@ -1086,11 +1105,8 @@ static uint32_t snd_record_read(RecordPlug *plug, uint32_t num_samples, uint32_t
static void on_new_record_channel(SndWorker *worker)
{
RecordChannel *record_channel = (RecordChannel *)worker->connection;
RecordInterface *interface = (RecordInterface *)worker->interface;
ASSERT(record_channel);
record_channel->plug_ref = interface->plug(interface, &record_channel->plug,
&record_channel->base.active);
if (!record_channel->base.migrate) {
if (record_channel->base.active) {
snd_set_command((SndChannel *)record_channel, SND_RECORD_CTRL_MASK);
@ -1101,8 +1117,6 @@ static void on_new_record_channel(SndWorker *worker)
static void snd_record_cleanup(SndChannel *channel)
{
RecordChannel *record_channel = (RecordChannel *)channel;
RecordInterface *interface = (RecordInterface *)channel->worker->interface;
interface->unplug(interface, record_channel->plug_ref);
celt051_decoder_destroy(record_channel->celt_decoder);
celt051_mode_destroy(record_channel->celt_mode);
@ -1120,7 +1134,8 @@ static void snd_set_record_peer(Channel *channel, RedsStreamContext *peer, int m
snd_disconnect_channel(worker->connection);
if (!(celt_mode = celt051_mode_create(VD_INTERFACE_RECORD_FREQ, VD_INTERFACE_RECORD_CHAN,
if (!(celt_mode = celt051_mode_create(SPICE_INTERFACE_RECORD_FREQ,
SPICE_INTERFACE_RECORD_CHAN,
FRAME_SIZE, &celt_error))) {
red_printf("create celt mode failed %d", celt_error);
return;
@ -1144,11 +1159,6 @@ static void snd_set_record_peer(Channel *channel, RedsStreamContext *peer, int m
worker->connection = &record_channel->base;
record_channel->plug.major_version = VD_INTERFACE_RECORD_MAJOR;
record_channel->plug.minor_version = VD_INTERFACE_RECORD_MINOR;
record_channel->plug.start = snd_record_start;
record_channel->plug.stop = snd_record_stop;
record_channel->plug.read = snd_record_read;
record_channel->celt_mode = celt_mode;
record_channel->celt_decoder = celt_decoder;
@ -1192,29 +1202,19 @@ static void remove_worker(SndWorker *worker)
red_printf("not found");
}
static SndWorker *find_worker(SpiceBaseInterface *interface)
{
SndWorker *worker = workers;
while (worker) {
if (worker->interface == interface) {
break;
}
worker = worker->next;
}
return worker;
}
void snd_attach_playback(PlaybackInterface *interface)
void snd_attach_playback(SpicePlaybackInstance *sin)
{
SndWorker *playback_worker;
playback_worker = spice_new0(SndWorker, 1);
sin->st = spice_new0(SpicePlaybackState, 1);
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;
playback_worker->interface = &interface->base;
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);
@ -1223,18 +1223,19 @@ void snd_attach_playback(PlaybackInterface *interface)
reds_register_channel(&playback_worker->base);
}
void snd_attach_record(RecordInterface *interface)
void snd_attach_record(SpiceRecordInstance *sin)
{
SndWorker *record_worker;
record_worker = spice_new0(SndWorker, 1);
sin->st = spice_new0(SpiceRecordState, 1);
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->interface = &interface->base;
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);
@ -1242,10 +1243,8 @@ void snd_attach_record(RecordInterface *interface)
reds_register_channel(&record_worker->base);
}
static void snd_detach_common(SpiceBaseInterface *interface)
static void snd_detach_common(SndWorker *worker)
{
SndWorker *worker = find_worker(interface);
if (!worker) {
return;
}
@ -1255,17 +1254,18 @@ static void snd_detach_common(SpiceBaseInterface *interface)
free(worker->base.common_caps);
free(worker->base.caps);
free(worker);
}
void snd_detach_playback(PlaybackInterface *interface)
void snd_detach_playback(SpicePlaybackInstance *sin)
{
snd_detach_common(&interface->base);
snd_detach_common(&sin->st->worker);
free(sin->st);
}
void snd_detach_record(RecordInterface *interface)
void snd_detach_record(SpiceRecordInstance *sin)
{
snd_detach_common(&interface->base);
snd_detach_common(&sin->st->worker);
free(sin->st);
}
void snd_set_playback_compression(int on)

View File

@ -20,11 +20,11 @@
#include "vd_interface.h"
void snd_attach_playback(PlaybackInterface *interface);
void snd_detach_playback(PlaybackInterface *interface);
void snd_attach_playback(SpicePlaybackInstance *sin);
void snd_detach_playback(SpicePlaybackInstance *sin);
void snd_attach_record(RecordInterface *interface);
void snd_detach_record(RecordInterface *interface);
void snd_attach_record(SpiceRecordInstance *sin);
void snd_detach_record(SpiceRecordInstance *sin);
void snd_set_playback_compression(int on);
int snd_get_playback_compression();

View File

@ -311,62 +311,62 @@ typedef struct VDICmdArg {
typedef void (*VDICmdHandler)(const VDICmdArg* args);
typedef void (*VDIInfoCmdHandler)(void);
#define VD_INTERFACE_PLAYBACK "playback"
#define VD_INTERFACE_PLAYBACK_MAJOR 1
#define VD_INTERFACE_PLAYBACK_MINOR 1
typedef struct PlaybackInterface PlaybackInterface;
#define SPICE_INTERFACE_PLAYBACK "playback"
#define SPICE_INTERFACE_PLAYBACK_MAJOR 1
#define SPICE_INTERFACE_PLAYBACK_MINOR 1
typedef struct SpicePlaybackInterface SpicePlaybackInterface;
typedef struct SpicePlaybackInstance SpicePlaybackInstance;
typedef struct SpicePlaybackState SpicePlaybackState;
enum {
VD_INTERFACE_AUDIO_FMT_S16 = 1,
SPICE_INTERFACE_AUDIO_FMT_S16 = 1,
};
#define VD_INTERFACE_PLAYBACK_FREQ 44100
#define VD_INTERFACE_PLAYBACK_CHAN 2
#define VD_INTERFACE_PLAYBACK_FMT VD_INTERFACE_AUDIO_FMT_S16
#define SPICE_INTERFACE_PLAYBACK_FREQ 44100
#define SPICE_INTERFACE_PLAYBACK_CHAN 2
#define SPICE_INTERFACE_PLAYBACK_FMT SPICE_INTERFACE_AUDIO_FMT_S16
typedef struct PlaybackPlug PlaybackPlug;
struct PlaybackPlug {
uint32_t minor_version;
uint32_t major_version;
void (*start)(PlaybackPlug *plug);
void (*stop)(PlaybackPlug *plug);
void (*get_frame)(PlaybackPlug *plug, uint32_t **frame, uint32_t *samples);
void (*put_frame)(PlaybackPlug *plug, uint32_t *frame);
};
struct PlaybackInterface {
struct SpicePlaybackInterface {
SpiceBaseInterface base;
VDObjectRef (*plug)(PlaybackInterface *playback, PlaybackPlug* plug, int *enable);
void (*unplug)(PlaybackInterface *playback, VDObjectRef);
};
#define VD_INTERFACE_RECORD "record"
#define VD_INTERFACE_RECORD_MAJOR 2
#define VD_INTERFACE_RECORD_MINOR 1
typedef struct RecordInterface RecordInterface;
#define VD_INTERFACE_RECORD_FREQ 44100
#define VD_INTERFACE_RECORD_CHAN 2
#define VD_INTERFACE_RECORD_FMT VD_INTERFACE_AUDIO_FMT_S16
typedef struct RecordPlug RecordPlug;
struct RecordPlug {
uint32_t minor_version;
uint32_t major_version;
void (*start)(RecordPlug *plug);
void (*stop)(RecordPlug *plug);
uint32_t (*read)(RecordPlug *plug, uint32_t num_samples, uint32_t *samples);
struct SpicePlaybackInstance {
SpiceBaseInstance base;
SpicePlaybackState *st;
};
struct RecordInterface {
void spice_server_playback_start(SpicePlaybackInstance *sin);
void spice_server_playback_stop(SpicePlaybackInstance *sin);
void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
uint32_t **samples, uint32_t *nsamples);
void spice_server_playback_put_samples(SpicePlaybackInstance *sin,
uint32_t *samples);
#define SPICE_INTERFACE_RECORD "record"
#define SPICE_INTERFACE_RECORD_MAJOR 2
#define SPICE_INTERFACE_RECORD_MINOR 1
typedef struct SpiceRecordInterface SpiceRecordInterface;
typedef struct SpiceRecordInstance SpiceRecordInstance;
typedef struct SpiceRecordState SpiceRecordState;
#define SPICE_INTERFACE_RECORD_FREQ 44100
#define SPICE_INTERFACE_RECORD_CHAN 2
#define SPICE_INTERFACE_RECORD_FMT SPICE_INTERFACE_AUDIO_FMT_S16
struct SpiceRecordInterface {
SpiceBaseInterface base;
VDObjectRef (*plug)(RecordInterface *recorder, RecordPlug* plug, int *enable);
void (*unplug)(RecordInterface *recorder, VDObjectRef);
};
struct SpiceRecordInstance {
SpiceBaseInstance base;
SpiceRecordState *st;
};
void spice_server_record_start(SpiceRecordInstance *sin);
void spice_server_record_stop(SpiceRecordInstance *sin);
uint32_t spice_server_record_get_samples(SpiceRecordInstance *sin,
uint32_t *samples, uint32_t bufsize);
#define VD_INTERFACE_VDI_PORT "vdi_port"
#define VD_INTERFACE_VDI_PORT_MAJOR 1
#define VD_INTERFACE_VDI_PORT_MINOR 1