[Spice-commits] 4 commits - client/marshallers.h common/messages.h python_modules/codegen.py python_modules/demarshal.py python_modules/ptypes.py python_modules/spice_parser.py server/snd_worker.c server/spice.h spice_codegen.py spice.proto

Marc-André Lureau elmarco at kemper.freedesktop.org
Wed Jun 22 05:30:21 PDT 2011


 client/marshallers.h           |    2 
 common/messages.h              |    9 +
 python_modules/codegen.py      |    6 -
 python_modules/demarshal.py    |   32 ++---
 python_modules/ptypes.py       |   22 ++-
 python_modules/spice_parser.py |    2 
 server/snd_worker.c            |  228 ++++++++++++++++++++++++++++++++++++++---
 server/spice.h                 |   10 +
 spice.proto                    |   13 ++
 spice_codegen.py               |    4 
 10 files changed, 285 insertions(+), 43 deletions(-)

New commits:
commit 0400769de16ca2ed01270d780e670129a26ef6a2
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jun 21 14:56:02 2011 +0200

    sndworker: check the caps before sending volume messages

diff --git a/server/snd_worker.c b/server/snd_worker.c
index 182eb3c..7dbc490 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -114,6 +114,8 @@ struct SndChannel {
     handle_message_proc handle_message;
     on_message_done_proc on_message_done;
     cleanup_channel_proc cleanup;
+    int num_caps;
+    uint32_t *caps;
 };
 
 typedef struct AudioFrame AudioFrame;
@@ -131,7 +133,6 @@ typedef struct PlaybackChannel {
     AudioFrame *pending_frame;
     CELTMode *celt_mode;
     CELTEncoder *celt_encoder;
-    int celt_allowed;
     uint32_t mode;
     struct {
         uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES];
@@ -191,6 +192,18 @@ static uint32_t playback_compression = SPICE_AUDIO_DATA_MODE_CELT_0_5_1;
 
 static void snd_receive(void* data);
 
+static int check_cap(uint32_t *caps, int num_caps, uint32_t cap)
+{
+    uint32_t i = cap / 32;
+
+    cap = 1 << (cap % 32);
+    if (i >= num_caps) {
+        return FALSE;
+    }
+
+    return caps[i] & cap;
+}
+
 static void snd_disconnect_channel(SndChannel *channel)
 {
     SndWorker *worker;
@@ -205,6 +218,7 @@ static void snd_disconnect_channel(SndChannel *channel)
     channel->stream->watch = NULL;
     reds_stream_free(channel->stream);
     spice_marshaller_destroy(channel->send_data.marshaller);
+    free(channel->caps);
     free(channel);
 }
 
@@ -544,6 +558,9 @@ static int snd_playback_send_volume(PlaybackChannel *playback_channel)
     SndChannel *channel = &playback_channel->base;
     SpicePlaybackState *st = SPICE_CONTAINEROF(channel->worker, SpicePlaybackState, worker);
 
+    if (!check_cap(channel->caps, channel->num_caps, SPICE_PLAYBACK_CAP_VOLUME))
+        return TRUE;
+
     return snd_send_volume(channel, &st->volume, SPICE_MSG_PLAYBACK_VOLUME);
 }
 
@@ -565,6 +582,9 @@ static int snd_playback_send_mute(PlaybackChannel *playback_channel)
     SndChannel *channel = &playback_channel->base;
     SpicePlaybackState *st = SPICE_CONTAINEROF(channel->worker, SpicePlaybackState, worker);
 
+    if (!check_cap(channel->caps, channel->num_caps, SPICE_PLAYBACK_CAP_VOLUME))
+        return TRUE;
+
     return snd_send_mute(channel, &st->volume, SPICE_MSG_PLAYBACK_MUTE);
 }
 
@@ -654,6 +674,9 @@ static int snd_record_send_volume(RecordChannel *record_channel)
     SndChannel *channel = &record_channel->base;
     SpiceRecordState *st = SPICE_CONTAINEROF(channel->worker, SpiceRecordState, worker);
 
+    if (!check_cap(channel->caps, channel->num_caps, SPICE_RECORD_CAP_VOLUME))
+        return TRUE;
+
     return snd_send_volume(channel, &st->volume, SPICE_MSG_RECORD_VOLUME);
 }
 
@@ -662,6 +685,9 @@ static int snd_record_send_mute(RecordChannel *record_channel)
     SndChannel *channel = &record_channel->base;
     SpiceRecordState *st = SPICE_CONTAINEROF(channel->worker, SpiceRecordState, worker);
 
+    if (!check_cap(channel->caps, channel->num_caps, SPICE_RECORD_CAP_VOLUME))
+        return TRUE;
+
     return snd_send_mute(channel, &st->volume, SPICE_MSG_RECORD_MUTE);
 }
 
@@ -833,7 +859,8 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i
                                  int migrate, send_messages_proc send_messages,
                                  handle_message_proc handle_message,
                                  on_message_done_proc on_message_done,
-                                 cleanup_channel_proc cleanup)
+                                 cleanup_channel_proc cleanup,
+                                 uint32_t *caps, int num_caps)
 {
     SndChannel *channel;
     int delay_val;
@@ -889,6 +916,8 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i
     channel->handle_message = handle_message;
     channel->on_message_done = on_message_done;
     channel->cleanup = cleanup;
+    channel->num_caps = num_caps;
+    channel->caps = spice_memdup(caps, num_caps * sizeof(uint32_t));
     return channel;
 
 error2:
@@ -1092,7 +1121,8 @@ static void snd_set_playback_peer(Channel *channel, RedsStream *stream, int migr
                                                               snd_playback_send,
                                                               snd_playback_handle_message,
                                                               snd_playback_on_message_done,
-                                                              snd_playback_cleanup))) {
+                                                              snd_playback_cleanup,
+                                                              caps, num_caps))) {
         goto error_2;
     }
     worker->connection = &playback_channel->base;
@@ -1102,9 +1132,8 @@ static void snd_set_playback_peer(Channel *channel, RedsStream *stream, int migr
 
     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));
-    playback_channel->mode = playback_channel->celt_allowed ? playback_compression :
-                                                              SPICE_AUDIO_DATA_MODE_RAW;
+    playback_channel->mode = check_cap(caps, num_caps, SPICE_PLAYBACK_CAP_CELT_0_5_1) ?
+        playback_compression : SPICE_AUDIO_DATA_MODE_RAW;
 
     on_new_playback_channel(worker);
     if (worker->active) {
@@ -1291,7 +1320,8 @@ static void snd_set_record_peer(Channel *channel, RedsStream *stream, int migrat
                                                           snd_record_send,
                                                           snd_record_handle_message,
                                                           snd_record_on_message_done,
-                                                          snd_record_cleanup))) {
+                                                          snd_record_cleanup,
+                                                          caps, num_caps))) {
         goto error_2;
     }
 
@@ -1359,7 +1389,9 @@ void snd_attach_playback(SpicePlaybackInstance *sin)
 
     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);
+    playback_worker->base.caps[0] =
+        (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1) |
+        (1 << SPICE_PLAYBACK_CAP_VOLUME);
 
     add_worker(playback_worker);
     reds_register_channel(&playback_worker->base);
@@ -1381,7 +1413,9 @@ void snd_attach_record(SpiceRecordInstance *sin)
 
     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);
+    record_worker->base.caps[0] =
+        (1 << SPICE_RECORD_CAP_CELT_0_5_1) |
+        (1 << SPICE_RECORD_CAP_VOLUME);
     add_worker(record_worker);
     reds_register_channel(&record_worker->base);
 }
@@ -1429,8 +1463,10 @@ 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) {
+            SndChannel* sndchannel = now->connection;
             PlaybackChannel* playback = (PlaybackChannel*)now->connection;
-            if (!playback->celt_allowed) {
+            if (!check_cap(sndchannel->caps, sndchannel->num_caps,
+                           SPICE_PLAYBACK_CAP_CELT_0_5_1)) {
                 ASSERT(playback->mode == SPICE_AUDIO_DATA_MODE_RAW);
                 continue;
             }
commit d1758b328811979beb58ff9ddb9cf4f318fa28f7
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Mon May 23 12:20:17 2011 +0200

    sndworker: add AudioVolume/AudioMute messages
    
    These messages allow the guest to send the audio device volume to the
    client. It uses an arbitrary scale of 16bits, which works good enough
    for now.
    
    Save VolumeState in {Playback,Record}State, so that we can send the
    current volume on channel connection.
    
    Note about future improvements:
    - add exact dB support
    - add client to guest volume change
    
    Updated since v2:
    - bumped record and playback interface minor version to allow
      conditional compilation
    Updated since v1:
    - sync record volume on connection too

diff --git a/client/marshallers.h b/client/marshallers.h
index c913a28..47faeff 100644
--- a/client/marshallers.h
+++ b/client/marshallers.h
@@ -26,6 +26,8 @@
 typedef struct {
     void (*msg_SpiceMsgEmpty)(SpiceMarshaller *m, SpiceMsgEmpty *msg);
     void (*msg_SpiceMsgData)(SpiceMarshaller *m, SpiceMsgData *msg);
+    void (*msg_SpiceMsgAudioVolume)(SpiceMarshaller *m, SpiceMsgAudioVolume *msg);
+    void (*msg_SpiceMsgAudioMute)(SpiceMarshaller *m, SpiceMsgAudioMute *msg);
     void (*msgc_ack_sync)(SpiceMarshaller *m, SpiceMsgcAckSync *msg);
     void (*msgc_pong)(SpiceMarshaller *m, SpiceMsgPing *msg);
     void (*msgc_disconnecting)(SpiceMarshaller *m, SpiceMsgDisconnect *msg);
diff --git a/common/messages.h b/common/messages.h
index 6fcd8be..8151dc0 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -369,6 +369,15 @@ typedef struct SpiceMsgcMouseRelease {
     int32_t buttons_state;
 } SpiceMsgcMouseRelease;
 
+typedef struct SpiceMsgAudioVolume {
+    uint8_t nchannels;
+    uint16_t volume[0];
+} SpiceMsgAudioVolume;
+
+typedef struct SpiceMsgAudioMute {
+    uint8_t mute;
+} SpiceMsgAudioMute;
+
 typedef struct SpiceMsgPlaybackMode {
     uint32_t time;
     uint32_t mode; //SPICE_AUDIO_DATA_MODE_?
diff --git a/server/snd_worker.c b/server/snd_worker.c
index 8da11e1..182eb3c 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -52,20 +52,24 @@ enum PlaybackeCommand {
     SND_PLAYBACK_MODE,
     SND_PLAYBACK_CTRL,
     SND_PLAYBACK_PCM,
+    SND_PLAYBACK_VOLUME,
 };
 
 enum RecordCommand {
     SND_RECORD_MIGRATE,
     SND_RECORD_CTRL,
+    SND_RECORD_VOLUME,
 };
 
 #define SND_PLAYBACK_MIGRATE_MASK (1 << SND_PLAYBACK_MIGRATE)
 #define SND_PLAYBACK_MODE_MASK (1 << SND_PLAYBACK_MODE)
 #define SND_PLAYBACK_CTRL_MASK (1 << SND_PLAYBACK_CTRL)
 #define SND_PLAYBACK_PCM_MASK (1 << SND_PLAYBACK_PCM)
+#define SND_PLAYBACK_VOLUME_MASK (1 << SND_PLAYBACK_VOLUME)
 
 #define SND_RECORD_MIGRATE_MASK (1 << SND_RECORD_MIGRATE)
 #define SND_RECORD_CTRL_MASK (1 << SND_RECORD_CTRL)
+#define SND_RECORD_VOLUME_MASK (1 << SND_RECORD_VOLUME)
 
 typedef struct SndChannel SndChannel;
 typedef void (*send_messages_proc)(void *in_channel);
@@ -141,14 +145,22 @@ struct SndWorker {
     int active;
 };
 
+typedef struct SpiceVolumeState {
+    uint8_t volume_nchannels;
+    uint16_t *volume;
+    int mute;
+} SpiceVolumeState;
+
 struct SpicePlaybackState {
     struct SndWorker worker;
     SpicePlaybackInstance *sin;
+    SpiceVolumeState volume;
 };
 
 struct SpiceRecordState {
     struct SndWorker worker;
     SpiceRecordInstance *sin;
+    SpiceVolumeState volume;
 };
 
 #define RECORD_MIG_VERSION 1
@@ -508,6 +520,54 @@ static int snd_playback_send_migrate(PlaybackChannel *channel)
     return snd_begin_send_message((SndChannel *)channel);
 }
 
+static int snd_send_volume(SndChannel *channel, SpiceVolumeState *st, int msg)
+{
+    SpiceMsgAudioVolume *vol;
+    uint8_t c;
+
+    vol = alloca(sizeof (SpiceMsgAudioVolume) +
+                 st->volume_nchannels * sizeof (uint16_t));
+    if (!snd_reset_send_data(channel, msg)) {
+        return FALSE;
+    }
+    vol->nchannels = st->volume_nchannels;
+    for (c = 0; c < st->volume_nchannels; ++c) {
+        vol->volume[c] = st->volume[c];
+    }
+    spice_marshall_SpiceMsgAudioVolume(channel->send_data.marshaller, vol);
+
+    return snd_begin_send_message(channel);
+}
+
+static int snd_playback_send_volume(PlaybackChannel *playback_channel)
+{
+    SndChannel *channel = &playback_channel->base;
+    SpicePlaybackState *st = SPICE_CONTAINEROF(channel->worker, SpicePlaybackState, worker);
+
+    return snd_send_volume(channel, &st->volume, SPICE_MSG_PLAYBACK_VOLUME);
+}
+
+static int snd_send_mute(SndChannel *channel, SpiceVolumeState *st, int msg)
+{
+    SpiceMsgAudioMute mute;
+
+    if (!snd_reset_send_data(channel, msg)) {
+        return FALSE;
+    }
+    mute.mute = st->mute;
+    spice_marshall_SpiceMsgAudioMute(channel->send_data.marshaller, &mute);
+
+    return snd_begin_send_message(channel);
+}
+
+static int snd_playback_send_mute(PlaybackChannel *playback_channel)
+{
+    SndChannel *channel = &playback_channel->base;
+    SpicePlaybackState *st = SPICE_CONTAINEROF(channel->worker, SpicePlaybackState, worker);
+
+    return snd_send_mute(channel, &st->volume, SPICE_MSG_PLAYBACK_MUTE);
+}
+
 static int snd_playback_send_start(PlaybackChannel *playback_channel)
 {
     SndChannel *channel = (SndChannel *)playback_channel;
@@ -589,6 +649,22 @@ static int snd_record_send_ctl(RecordChannel *record_channel)
     }
 }
 
+static int snd_record_send_volume(RecordChannel *record_channel)
+{
+    SndChannel *channel = &record_channel->base;
+    SpiceRecordState *st = SPICE_CONTAINEROF(channel->worker, SpiceRecordState, worker);
+
+    return snd_send_volume(channel, &st->volume, SPICE_MSG_RECORD_VOLUME);
+}
+
+static int snd_record_send_mute(RecordChannel *record_channel)
+{
+    SndChannel *channel = &record_channel->base;
+    SpiceRecordState *st = SPICE_CONTAINEROF(channel->worker, SpiceRecordState, worker);
+
+    return snd_send_mute(channel, &st->volume, SPICE_MSG_RECORD_MUTE);
+}
+
 static int snd_record_send_migrate(RecordChannel *record_channel)
 {
     SndChannel *channel = (SndChannel *)record_channel;
@@ -704,6 +780,13 @@ static void snd_playback_send(void* data)
             }
             channel->command &= ~SND_PLAYBACK_CTRL_MASK;
         }
+        if (channel->command & SND_PLAYBACK_VOLUME_MASK) {
+            if (!snd_playback_send_volume(playback_channel) ||
+                !snd_playback_send_mute(playback_channel)) {
+                return;
+            }
+            channel->command &= ~SND_PLAYBACK_VOLUME_MASK;
+        }
         if (channel->command & SND_PLAYBACK_MIGRATE_MASK) {
             if (!snd_playback_send_migrate(playback_channel)) {
                 return;
@@ -729,6 +812,13 @@ static void snd_record_send(void* data)
             }
             channel->command &= ~SND_RECORD_CTRL_MASK;
         }
+        if (channel->command & SND_RECORD_VOLUME_MASK) {
+            if (!snd_record_send_volume(record_channel) ||
+                !snd_record_send_mute(record_channel)) {
+                return;
+            }
+            channel->command &= ~SND_RECORD_VOLUME_MASK;
+        }
         if (channel->command & SND_RECORD_MIGRATE_MASK) {
             if (!snd_record_send_migrate(record_channel)) {
                 return;
@@ -823,6 +913,38 @@ static void snd_set_command(SndChannel *channel, uint32_t command)
     channel->command |= command;
 }
 
+__visible__ void spice_server_playback_set_volume(SpicePlaybackInstance *sin,
+                                                  uint8_t nchannels,
+                                                  uint16_t *volume)
+{
+    SpiceVolumeState *st = &sin->st->volume;
+    SndChannel *channel = sin->st->worker.connection;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
+
+    st->volume_nchannels = nchannels;
+    free(st->volume);
+    st->volume = spice_memdup(volume, sizeof(uint16_t) * nchannels);
+
+    if (!channel)
+        return;
+
+    snd_playback_send_volume(playback_channel);
+}
+
+__visible__ void spice_server_playback_set_mute(SpicePlaybackInstance *sin, uint8_t mute)
+{
+    SpiceVolumeState *st = &sin->st->volume;
+    SndChannel *channel = sin->st->worker.connection;
+    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
+
+    st->mute = mute;
+
+    if (!channel)
+        return;
+
+    snd_playback_send_mute(playback_channel);
+}
+
 __visible__ void spice_server_playback_start(SpicePlaybackInstance *sin)
 {
     SndChannel *channel = sin->st->worker.connection;
@@ -919,6 +1041,7 @@ static void on_new_playback_channel(SndWorker *worker)
     if (!playback_channel->base.migrate && playback_channel->base.active) {
         snd_set_command((SndChannel *)playback_channel, SND_PLAYBACK_CTRL_MASK);
     }
+    snd_set_command((SndChannel *)playback_channel, SND_PLAYBACK_VOLUME_MASK);
     if (playback_channel->base.active) {
         reds_disable_mm_timer();
     }
@@ -1006,6 +1129,38 @@ static void snd_record_migrate(Channel *channel)
     }
 }
 
+__visible__ void spice_server_record_set_volume(SpiceRecordInstance *sin,
+                                                uint8_t nchannels,
+                                                uint16_t *volume)
+{
+    SpiceVolumeState *st = &sin->st->volume;
+    SndChannel *channel = sin->st->worker.connection;
+    RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
+
+    st->volume_nchannels = nchannels;
+    free(st->volume);
+    st->volume = spice_memdup(volume, sizeof(uint16_t) * nchannels);
+
+    if (!channel)
+        return;
+
+    snd_record_send_volume(record_channel);
+}
+
+__visible__ void spice_server_record_set_mute(SpiceRecordInstance *sin, uint8_t mute)
+{
+    SpiceVolumeState *st = &sin->st->volume;
+    SndChannel *channel = sin->st->worker.connection;
+    RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base);
+
+    st->mute = mute;
+
+    if (!channel)
+        return;
+
+    snd_record_send_mute(record_channel);
+}
+
 __visible__ void spice_server_record_start(SpiceRecordInstance *sin)
 {
     SndChannel *channel = sin->st->worker.connection;
@@ -1087,6 +1242,7 @@ static void on_new_record_channel(SndWorker *worker)
     RecordChannel *record_channel = (RecordChannel *)worker->connection;
     ASSERT(record_channel);
 
+    snd_set_command((SndChannel *)record_channel, SND_RECORD_VOLUME_MASK);
     if (!record_channel->base.migrate) {
         if (record_channel->base.active) {
             snd_set_command((SndChannel *)record_channel, SND_RECORD_CTRL_MASK);
@@ -1242,16 +1398,28 @@ static void snd_detach_common(SndWorker *worker)
     reds_channel_dispose(&worker->base);
 }
 
+static void spice_playback_state_free(SpicePlaybackState *st)
+{
+    free(st->volume.volume);
+    free(st);
+}
+
 void snd_detach_playback(SpicePlaybackInstance *sin)
 {
     snd_detach_common(&sin->st->worker);
-    free(sin->st);
+    spice_playback_state_free(sin->st);
+}
+
+static void spice_record_state_free(SpiceRecordState *st)
+{
+    free(st->volume.volume);
+    free(st);
 }
 
 void snd_detach_record(SpiceRecordInstance *sin)
 {
     snd_detach_common(&sin->st->worker);
-    free(sin->st);
+    spice_record_state_free(sin->st);
 }
 
 void snd_set_playback_compression(int on)
diff --git a/server/spice.h b/server/spice.h
index 425d586..f64ff41 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -268,7 +268,7 @@ struct SpiceTabletInstance {
 
 #define SPICE_INTERFACE_PLAYBACK "playback"
 #define SPICE_INTERFACE_PLAYBACK_MAJOR 1
-#define SPICE_INTERFACE_PLAYBACK_MINOR 1
+#define SPICE_INTERFACE_PLAYBACK_MINOR 2
 typedef struct SpicePlaybackInterface SpicePlaybackInterface;
 typedef struct SpicePlaybackInstance SpicePlaybackInstance;
 typedef struct SpicePlaybackState SpicePlaybackState;
@@ -296,10 +296,13 @@ 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);
+void spice_server_playback_set_volume(SpicePlaybackInstance *sin,
+                                      uint8_t nchannels, uint16_t *volume);
+void spice_server_playback_set_mute(SpicePlaybackInstance *sin, uint8_t mute);
 
 #define SPICE_INTERFACE_RECORD "record"
 #define SPICE_INTERFACE_RECORD_MAJOR 2
-#define SPICE_INTERFACE_RECORD_MINOR 1
+#define SPICE_INTERFACE_RECORD_MINOR 2
 typedef struct SpiceRecordInterface SpiceRecordInterface;
 typedef struct SpiceRecordInstance SpiceRecordInstance;
 typedef struct SpiceRecordState SpiceRecordState;
@@ -321,6 +324,9 @@ 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);
+void spice_server_record_set_volume(SpiceRecordInstance *sin,
+                                    uint8_t nchannels, uint16_t *volume);
+void spice_server_record_set_mute(SpiceRecordInstance *sin, uint8_t mute);
 
 /* char device interfaces */
 
diff --git a/spice.proto b/spice.proto
index 6160de1..80c40d4 100644
--- a/spice.proto
+++ b/spice.proto
@@ -926,6 +926,15 @@ enum16 audio_fmt {
     S16,
 };
 
+message AudioVolume {
+    uint8 nchannels;
+    uint16 volume[nchannels] @end;
+};
+
+message AudioMute {
+    uint8 mute;
+};
+
 channel PlaybackChannel : BaseChannel {
  server:
     message {
@@ -947,6 +956,8 @@ channel PlaybackChannel : BaseChannel {
     } start;
 
     Empty stop;
+    AudioVolume volume;
+    AudioMute mute;
 };
 
 channel RecordChannel : BaseChannel {
@@ -958,6 +969,8 @@ channel RecordChannel : BaseChannel {
     } start = 101;
 
     Empty stop;
+    AudioVolume volume;
+    AudioMute mute;
  client:
     message {
 	uint32 time;
commit 5ec91855d818078523653e79562921bcea9bef14
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Tue Jun 21 13:20:33 2011 +0200

    python: remove c-ism trailing ;

diff --git a/python_modules/codegen.py b/python_modules/codegen.py
index 75033dc..116760c 100644
--- a/python_modules/codegen.py
+++ b/python_modules/codegen.py
@@ -116,7 +116,7 @@ class CodeWriter:
         writer.options = self.options
         writer.public_prefix = self.public_prefix
 
-        return writer;
+        return writer
 
     def write(self, s):
         # Ensure its a string
@@ -184,10 +184,10 @@ class CodeWriter:
             self.statement("goto %s" % label)
 
     def indent(self):
-        self.indentation += 4;
+        self.indentation += 4
 
     def unindent(self):
-        self.indentation -= 4;
+        self.indentation -= 4
         if self.indentation < 0:
             self.indenttation = 0
 
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 9d3b1e4..3a0178e 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -74,7 +74,7 @@ def write_parser_helpers(writer):
 
     writer.newline()
     writer.statement("typedef struct PointerInfo PointerInfo")
-    writer.statement("typedef void (*message_destructor_t)(uint8_t *message)");
+    writer.statement("typedef void (*message_destructor_t)(uint8_t *message)")
     writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)")
     writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message)")
     writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message)")
@@ -198,11 +198,11 @@ def write_validate_struct_function(writer, struct):
     writer = writer.function_helper()
     scope = writer.function(validate_function, "static intptr_t", "uint8_t *message_start, uint8_t *message_end, uint64_t offset, int minor")
     scope.variable_def("uint8_t *", "start = message_start + offset")
-    scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos");
-    scope.variable_def("size_t", "mem_size", "nw_size");
+    scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos")
+    scope.variable_def("size_t", "mem_size", "nw_size")
     num_pointers = struct.get_num_pointers()
     if  num_pointers != 0:
-        scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size");
+        scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
 
     writer.newline()
     with writer.if_block("offset == 0"):
@@ -766,8 +766,8 @@ def write_parse_ptr_function(writer, target_type):
 
     num_pointers = target_type.get_num_pointers()
     if  num_pointers != 0:
-        scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size");
-        scope.variable_def("uint32_t", "n_ptr=0");
+        scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
+        scope.variable_def("uint32_t", "n_ptr=0")
         scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
 
     writer.newline()
@@ -854,7 +854,7 @@ def write_parse_pointer_core(writer, target_type, offset, at_end, dest, member_n
     writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type))
     if at_end:
         writer.assign("ptr_info[n_ptr].dest", "(void **)end")
-        writer.increment("end", "sizeof(void *)");
+        writer.increment("end", "sizeof(void *)")
     else:
         writer.assign("ptr_info[n_ptr].dest", "(void **)&%s" % dest.get_ref(member_name))
     if target_type.is_array():
@@ -890,7 +890,7 @@ def write_member_parser(writer, container, member, dest, scope):
             assert(t.target_type.is_array())
             nelements = read_array_len(writer, member.name, t.target_type, dest, scope, True)
             writer.comment("Reuse data from network message as chunk").newline()
-            scope.variable_def("SpiceChunks *", "chunks");
+            scope.variable_def("SpiceChunks *", "chunks")
             writer.assign("chunks", "(SpiceChunks *)end")
             writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
             writer.assign(dest.get_ref(member.name), "chunks")
@@ -922,7 +922,7 @@ def write_member_parser(writer, container, member, dest, scope):
         if member.has_attr("chunk") and t.element_type.is_fixed_nw_size() and t.element_type.get_fixed_nw_size() == 1:
             writer.comment("use array as chunk").newline()
 
-            scope.variable_def("SpiceChunks *", "chunks");
+            scope.variable_def("SpiceChunks *", "chunks")
             writer.assign("chunks", "(SpiceChunks *)end")
             writer.increment("end", "sizeof(SpiceChunks) + sizeof(SpiceChunk)")
             writer.assign(dest.get_ref(member.name), "chunks")
@@ -1018,18 +1018,18 @@ def write_msg_parser(writer, message):
     parent_scope = writer.function(function_name,
                                    "uint8_t *",
                                    "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size, message_destructor_t *free_message", True)
-    parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos");
-    parent_scope.variable_def("uint8_t *", "start = message_start");
-    parent_scope.variable_def("uint8_t *", "data = NULL");
+    parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos")
+    parent_scope.variable_def("uint8_t *", "start = message_start")
+    parent_scope.variable_def("uint8_t *", "data = NULL")
     parent_scope.variable_def("size_t", "nw_size")
     if want_mem_size:
         parent_scope.variable_def("size_t", "mem_size")
     if not message.has_attr("nocopy"):
-        parent_scope.variable_def("uint8_t *", "in", "end");
+        parent_scope.variable_def("uint8_t *", "in", "end")
     num_pointers = message.get_num_pointers()
     if  num_pointers != 0:
-        parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size");
-        parent_scope.variable_def("uint32_t", "n_ptr=0");
+        parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size")
+        parent_scope.variable_def("uint32_t", "n_ptr=0")
         parent_scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
     writer.newline()
 
@@ -1121,7 +1121,7 @@ def write_channel_parser(writer, channel, server):
     d = 0
     for r in ranges:
         d = d + 1
-        writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0]));
+        writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0]))
         writer.begin_block()
         for i in range(r[0], r[1]):
             func = write_msg_parser(helpers, ids[i].message_type)
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index 9e444f5..f12a2f3 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -37,10 +37,10 @@ class FixedSize:
             new.vals[i] = self.vals[i] + other.vals[i]
 
         for i in range(shared,len(self.vals)):
-            new.vals[i] = self.vals[i];
+            new.vals[i] = self.vals[i]
 
         for i in range(shared,len(other.vals)):
-            new.vals[i] = new.vals[i] + other.vals[i];
+            new.vals[i] = new.vals[i] + other.vals[i]
 
         return new
 
@@ -689,7 +689,7 @@ class Switch(Containee):
     def get_fixed_nw_size(self):
         if not self.is_fixed_nw_size():
             raise Exception, "Not a fixed size type"
-        size = 0;
+        size = 0
         for c in self.cases:
             size = max(size, c.member.get_fixed_nw_size())
         return size
diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py
index 43e930c..4c8a57a 100644
--- a/python_modules/spice_parser.py
+++ b/python_modules/spice_parser.py
@@ -18,7 +18,7 @@ def parseVariableDef(toks):
         t = ptypes.ArrayType(t, array_size)
 
     if pointer != None:
-        t = ptypes.PointerType(t);
+        t = ptypes.PointerType(t)
 
     return ptypes.Member(name, t, attributes)
 
diff --git a/spice_codegen.py b/spice_codegen.py
index 05b47f6..c6d6aa9 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -16,7 +16,7 @@ def write_channel_enums(writer, channel, client):
     if len(messages) == 0:
         return
     writer.begin_block("enum")
-    i = 0;
+    i = 0
     if client:
         prefix = [ "MSGC" ]
     else:
@@ -53,7 +53,7 @@ def write_enums(writer):
         if isinstance(t, ptypes.EnumBaseType):
             t.c_define(writer)
 
-    i = 0;
+    i = 0
     writer.begin_block("enum")
     for c in proto.channels:
         enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
commit aa57d2f70cac4bcbaf9324c5efb8c9254caaeb30
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Sat Jun 18 00:08:35 2011 +0200

    codegen: typedef the protocol enums
    
    Commit 9d5ef9beeca722b2ceff7d15aaa3aaaaf07ecfbf in spice-protocol
    introduced a typedef manually in the generated enums.h header.
    
    This patch adds them automatically to all enums during enums.h generation.

diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index 9c4b7de..9e444f5 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -280,7 +280,7 @@ class EnumType(EnumBaseType):
         return "enum %s" % self.name
 
     def c_define(self, writer):
-        writer.write("enum ")
+        writer.write("typedef enum ")
         writer.write(self.c_name())
         writer.begin_block()
         values = self.names.keys()
@@ -296,7 +296,11 @@ class EnumType(EnumBaseType):
         writer.newline()
         writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END"))
         writer.newline()
-        writer.end_block(semicolon=True)
+        writer.end_block(newline=False)
+        writer.write(" ")
+        writer.write(self.c_name())
+        writer.write(";")
+        writer.newline()
         writer.newline()
 
 class FlagsType(EnumBaseType):
@@ -330,7 +334,7 @@ class FlagsType(EnumBaseType):
         return "flags %s" % self.name
 
     def c_define(self, writer):
-        writer.write("enum ")
+        writer.write("typedef enum ")
         writer.write(self.c_name())
         writer.begin_block()
         values = self.names.keys()
@@ -347,7 +351,11 @@ class FlagsType(EnumBaseType):
         writer.write(codegen.prefix_underscore_upper(self.name.upper(), "MASK"))
         writer.write(" = 0x%x" % (mask))
         writer.newline()
-        writer.end_block(semicolon=True)
+        writer.end_block(newline=False)
+        writer.write(" ")
+        writer.write(self.c_name())
+        writer.write(";")
+        writer.newline()
         writer.newline()
 
 class ArrayType(Type):


More information about the Spice-commits mailing list