channels/rdpsnd: start work on WavePlay/WaveConfirm
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 21 Feb 2013 18:25:43 +0000 (13:25 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 21 Feb 2013 18:25:43 +0000 (13:25 -0500)
channels/rdpsnd/client/alsa/rdpsnd_alsa.c
channels/rdpsnd/client/rdpsnd_main.c
channels/rdpsnd/client/rdpsnd_main.h
include/freerdp/channels/rdpsnd.h

index 3284ada..a036ecd 100644 (file)
@@ -66,6 +66,16 @@ struct rdpsnd_alsa_plugin
        FREERDP_DSP_CONTEXT* dsp_context;
 };
 
+struct _RDPSND_WAVE_INFO
+{
+       BYTE* data;
+       int length;
+       BYTE cBlockNo;
+       UINT16 wTimeStamp;
+       UINT16 wFormatNo;
+};
+typedef struct _RDPSND_WAVE_INFO RDPSND_WAVE_INFO;
+
 static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
 {
        int status;
@@ -365,6 +375,7 @@ static void* rdpsnd_alsa_schedule_thread(void* arg)
        int offset;
        int frame_size;
        wMessage message;
+       RDPSND_WAVE_INFO* waveInfo;
        snd_pcm_sframes_t available_input;
        snd_pcm_sframes_t available_output;
        rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) arg;
@@ -380,8 +391,18 @@ static void* rdpsnd_alsa_schedule_thread(void* arg)
                if (message.id == WMQ_QUIT)
                        break;
 
-               data = (BYTE*) message.wParam;
-               length = (int) (size_t) message.lParam;
+               if (message.id == 0)
+               {
+                       data = (BYTE*) message.wParam;
+                       length = (int) (size_t) message.lParam;
+               }
+               else if (message.id == 1)
+               {
+                       waveInfo = (RDPSND_WAVE_INFO*) message.wParam;
+
+                       data = waveInfo->data;
+                       length = waveInfo->length;
+               }
 
                offset = 0;
                available_output = snd_pcm_avail_update(alsa->pcm_handle);
@@ -430,69 +451,96 @@ static void* rdpsnd_alsa_schedule_thread(void* arg)
        return NULL;
 }
 
-static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, BYTE* data, int size)
+BYTE* rdpsnd_process_audio_sample(rdpsndDevicePlugin* device, BYTE* data, int* size)
 {
-       BYTE* src;
        int frames;
-       int rbytes_per_frame;
-       int sbytes_per_frame;
+       BYTE* srcData;
+       int srcFrameSize;
+       int dstFrameSize;
        rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
 
        if (!alsa->pcm_handle)
-               return;
+               return NULL;
 
        if (alsa->wformat == WAVE_FORMAT_ADPCM)
        {
                alsa->dsp_context->decode_ms_adpcm(alsa->dsp_context,
-                       data, size, alsa->source_channels, alsa->block_size);
+                       data, *size, alsa->source_channels, alsa->block_size);
 
-               size = alsa->dsp_context->adpcm_size;
-               src = alsa->dsp_context->adpcm_buffer;
+               *size = alsa->dsp_context->adpcm_size;
+               srcData = alsa->dsp_context->adpcm_buffer;
        }
        else if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM)
        {
                alsa->dsp_context->decode_ima_adpcm(alsa->dsp_context,
-                       data, size, alsa->source_channels, alsa->block_size);
+                       data, *size, alsa->source_channels, alsa->block_size);
 
-               size = alsa->dsp_context->adpcm_size;
-               src = alsa->dsp_context->adpcm_buffer;
+               *size = alsa->dsp_context->adpcm_size;
+               srcData = alsa->dsp_context->adpcm_buffer;
        }
        else
        {
-               src = data;
+               srcData = data;
        }
 
-       sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel;
-       rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
+       srcFrameSize = alsa->source_channels * alsa->bytes_per_channel;
+       dstFrameSize = alsa->actual_channels * alsa->bytes_per_channel;
 
-       if ((size % sbytes_per_frame) != 0)
-       {
-               DEBUG_WARN("error len mod");
-               return;
-       }
+       if ((*size % srcFrameSize) != 0)
+               return NULL;
 
-       if ((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels))
-       {
-
-       }
-       else
+       if (!((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels)))
        {
-               alsa->dsp_context->resample(alsa->dsp_context, src, alsa->bytes_per_channel,
-                       alsa->source_channels, alsa->source_rate, size / sbytes_per_frame,
+               alsa->dsp_context->resample(alsa->dsp_context, srcData, alsa->bytes_per_channel,
+                       alsa->source_channels, alsa->source_rate, *size / srcFrameSize,
                        alsa->actual_channels, alsa->actual_rate);
+
                frames = alsa->dsp_context->resampled_frames;
 
                DEBUG_SVC("resampled %d frames at %d to %d frames at %d",
-                       size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
+                       length / srcFrameSize, alsa->source_rate, frames, alsa->actual_rate);
 
-               size = frames * rbytes_per_frame;
-               src = alsa->dsp_context->resampled_buffer;
+               *size = frames * dstFrameSize;
+               srcData = alsa->dsp_context->resampled_buffer;
        }
 
-       data = (BYTE*) malloc(size);
-       CopyMemory(data, src, size);
+       data = srcData;
+
+       return data;
+}
+
+static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, BYTE* data, int size)
+{
+       BYTE* sample;
+       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
+
+       data = rdpsnd_process_audio_sample(device, data, &size);
+
+       sample = (BYTE*) malloc(size);
+       CopyMemory(sample, data, size);
+
+       MessageQueue_Post(alsa->queue, (void*) alsa, 0, (void*) sample, (void*) (size_t) size);
+}
+
+static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device,
+               UINT16 wTimeStamp, UINT16 wFormatNo, BYTE cBlockNo, BYTE* data, int size)
+{
+       RDPSND_WAVE_INFO* waveInfo;
+       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
+
+       waveInfo = (RDPSND_WAVE_INFO*) malloc(sizeof(RDPSND_WAVE_INFO));
+
+       waveInfo->wTimeStamp = wTimeStamp;
+       waveInfo->wFormatNo = wFormatNo;
+       waveInfo->cBlockNo = cBlockNo;
+
+       data = rdpsnd_process_audio_sample(device, data, &size);
+
+       waveInfo->data = (BYTE*) malloc(size);
+       CopyMemory(waveInfo->data, data, size);
+       waveInfo->length = size;
 
-       MessageQueue_Post(alsa->queue, (void*) alsa, 0, (void*) data, (void*) (size_t) size);
+       MessageQueue_Post(alsa->queue, (void*) alsa, 1, (void*) waveInfo, (void*) (size_t) size);
 }
 
 static void rdpsnd_alsa_start(rdpsndDevicePlugin* device)
@@ -558,6 +606,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
        alsa->device.SetFormat = rdpsnd_alsa_set_format;
        alsa->device.SetVolume = rdpsnd_alsa_set_volume;
        alsa->device.Play = rdpsnd_alsa_play;
+       alsa->device.WavePlay = rdpsnd_alsa_wave_play;
        alsa->device.Start = rdpsnd_alsa_start;
        alsa->device.Close = rdpsnd_alsa_close;
        alsa->device.Free = rdpsnd_alsa_free;
index cbf031e..46a2648 100644 (file)
@@ -149,34 +149,46 @@ static void rdpsnd_free_supported_formats(rdpsndPlugin* rdpsnd)
        rdpsnd->n_supported_formats = 0;
 }
 
-/* receives a list of server supported formats and returns a list
-   of client supported formats */
-static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in)
+void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
 {
+       STREAM* pdu;
+
+       pdu = stream_new(8);
+       stream_write_BYTE(pdu, SNDC_QUALITYMODE); /* msgType */
+       stream_write_BYTE(pdu, 0); /* bPad */
+       stream_write_UINT16(pdu, 4); /* BodySize */
+       stream_write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */
+       stream_write_UINT16(pdu, 0); /* Reserved */
+
+       svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
+}
+
+static void rdpsnd_recv_formats_pdu(rdpsndPlugin* rdpsnd, STREAM* s)
+{
+       int pos;
+       STREAM* pdu;
        UINT32 dwVolume;
        UINT16 dwVolumeLeft;
        UINT16 dwVolumeRight;
        UINT16 wNumberOfFormats;
        UINT16 nFormat;
        UINT16 wVersion;
-       STREAM* data_out;
-       rdpsndFormat* out_formats;
-       UINT16 n_out_formats;
-       rdpsndFormat* format;
-       BYTE* format_mark;
        BYTE* data_mark;
-       int pos;
+       BYTE* format_mark;
+       rdpsndFormat* format;
+       UINT16 n_out_formats;
+       rdpsndFormat* out_formats;
 
        rdpsnd_free_supported_formats(rdpsnd);
 
-       stream_seek_UINT32(data_in); /* dwFlags */
-       stream_seek_UINT32(data_in); /* dwVolume */
-       stream_seek_UINT32(data_in); /* dwPitch */
-       stream_seek_UINT16(data_in); /* wDGramPort */
-       stream_read_UINT16(data_in, wNumberOfFormats);
-       stream_read_BYTE(data_in, rdpsnd->cBlockNo); /* cLastBlockConfirmed */
-       stream_read_UINT16(data_in, wVersion);
-       stream_seek_BYTE(data_in); /* bPad */
+       stream_seek_UINT32(s); /* dwFlags */
+       stream_seek_UINT32(s); /* dwVolume */
+       stream_seek_UINT32(s); /* dwPitch */
+       stream_seek_UINT16(s); /* wDGramPort */
+       stream_read_UINT16(s, wNumberOfFormats);
+       stream_read_BYTE(s, rdpsnd->cBlockNo); /* cLastBlockConfirmed */
+       stream_read_UINT16(s, wVersion);
+       stream_seek_BYTE(s); /* bPad */
 
        DEBUG_SVC("wNumberOfFormats %d wVersion %d", wNumberOfFormats, wVersion);
 
@@ -194,32 +206,32 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
        dwVolumeRight = (0xFFFF / 2); /* 50% ? */
        dwVolume = (dwVolumeLeft << 16) | dwVolumeRight;
 
-       data_out = stream_new(24);
-       stream_write_BYTE(data_out, SNDC_FORMATS); /* msgType */
-       stream_write_BYTE(data_out, 0); /* bPad */
-       stream_seek_UINT16(data_out); /* BodySize */
-       stream_write_UINT32(data_out, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */
-       stream_write_UINT32(data_out, dwVolume); /* dwVolume */
-       stream_write_UINT32(data_out, 0); /* dwPitch */
-       stream_write_UINT16_be(data_out, 0); /* wDGramPort */
-       stream_seek_UINT16(data_out); /* wNumberOfFormats */
-       stream_write_BYTE(data_out, 0); /* cLastBlockConfirmed */
-       stream_write_UINT16(data_out, 6); /* wVersion */
-       stream_write_BYTE(data_out, 0); /* bPad */
+       pdu = stream_new(24);
+       stream_write_BYTE(pdu, SNDC_FORMATS); /* msgType */
+       stream_write_BYTE(pdu, 0); /* bPad */
+       stream_seek_UINT16(pdu); /* BodySize */
+       stream_write_UINT32(pdu, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */
+       stream_write_UINT32(pdu, dwVolume); /* dwVolume */
+       stream_write_UINT32(pdu, 0); /* dwPitch */
+       stream_write_UINT16_be(pdu, 0); /* wDGramPort */
+       stream_seek_UINT16(pdu); /* wNumberOfFormats */
+       stream_write_BYTE(pdu, 0); /* cLastBlockConfirmed */
+       stream_write_UINT16(pdu, 6); /* wVersion */
+       stream_write_BYTE(pdu, 0); /* bPad */
 
        for (nFormat = 0; nFormat < wNumberOfFormats; nFormat++)
        {
-               stream_get_mark(data_in, format_mark);
+               stream_get_mark(s, format_mark);
                format = &out_formats[n_out_formats];
-               stream_read_UINT16(data_in, format->wFormatTag);
-               stream_read_UINT16(data_in, format->nChannels);
-               stream_read_UINT32(data_in, format->nSamplesPerSec);
-               stream_seek_UINT32(data_in); /* nAvgBytesPerSec */
-               stream_read_UINT16(data_in, format->nBlockAlign);
-               stream_read_UINT16(data_in, format->wBitsPerSample);
-               stream_read_UINT16(data_in, format->cbSize);
-               stream_get_mark(data_in, data_mark);
-               stream_seek(data_in, format->cbSize);
+               stream_read_UINT16(s, format->wFormatTag);
+               stream_read_UINT16(s, format->nChannels);
+               stream_read_UINT32(s, format->nSamplesPerSec);
+               stream_seek_UINT32(s); /* nAvgBytesPerSec */
+               stream_read_UINT16(s, format->nBlockAlign);
+               stream_read_UINT16(s, format->wBitsPerSample);
+               stream_read_UINT16(s, format->cbSize);
+               stream_get_mark(s, data_mark);
+               stream_seek(s, format->cbSize);
                format->data = NULL;
 
                DEBUG_SVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d nBlockAlign=%d wBitsPerSample=%d",
@@ -239,8 +251,8 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
                {
                        DEBUG_SVC("format supported.");
 
-                       stream_check_size(data_out, 18 + format->cbSize);
-                       stream_write(data_out, format_mark, 18 + format->cbSize);
+                       stream_check_size(pdu, 18 + format->cbSize);
+                       stream_write(pdu, format_mark, 18 + format->cbSize);
 
                        if (format->cbSize > 0)
                        {
@@ -264,49 +276,45 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
                DEBUG_WARN("no formats supported");
        }
 
-       pos = stream_get_pos(data_out);
-       stream_set_pos(data_out, 2);
-       stream_write_UINT16(data_out, pos - 4);
-       stream_set_pos(data_out, 18);
-       stream_write_UINT16(data_out, n_out_formats);
-       stream_set_pos(data_out, pos);
+       pos = stream_get_pos(pdu);
+       stream_set_pos(pdu, 2);
+       stream_write_UINT16(pdu, pos - 4);
+       stream_set_pos(pdu, 18);
+       stream_write_UINT16(pdu, n_out_formats);
+       stream_set_pos(pdu, pos);
 
-       svc_plugin_send((rdpSvcPlugin*) rdpsnd, data_out);
+       svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
 
        if (wVersion >= 6)
-       {
-               data_out = stream_new(8);
-               stream_write_BYTE(data_out, SNDC_QUALITYMODE); /* msgType */
-               stream_write_BYTE(data_out, 0); /* bPad */
-               stream_write_UINT16(data_out, 4); /* BodySize */
-               stream_write_UINT16(data_out, HIGH_QUALITY); /* wQualityMode */
-               stream_write_UINT16(data_out, 0); /* Reserved */
-
-               svc_plugin_send((rdpSvcPlugin*) rdpsnd, data_out);
-       }
+               rdpsnd_send_quality_mode_pdu(rdpsnd);
+}
+
+void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize)
+{
+       STREAM* pdu;
+
+       pdu = stream_new(8);
+       stream_write_BYTE(pdu, SNDC_TRAINING); /* msgType */
+       stream_write_BYTE(pdu, 0); /* bPad */
+       stream_write_UINT16(pdu, 4); /* BodySize */
+       stream_write_UINT16(pdu, wTimeStamp);
+       stream_write_UINT16(pdu, wPackSize);
+
+       svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
 }
 
-/* server is getting a feel of the round trip time */
-static void rdpsnd_process_message_training(rdpsndPlugin* rdpsnd, STREAM* data_in)
+static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, STREAM* s)
 {
        UINT16 wTimeStamp;
        UINT16 wPackSize;
-       STREAM* data_out;
 
-       stream_read_UINT16(data_in, wTimeStamp);
-       stream_read_UINT16(data_in, wPackSize);
+       stream_read_UINT16(s, wTimeStamp);
+       stream_read_UINT16(s, wPackSize);
 
-       data_out = stream_new(8);
-       stream_write_BYTE(data_out, SNDC_TRAINING); /* msgType */
-       stream_write_BYTE(data_out, 0); /* bPad */
-       stream_write_UINT16(data_out, 4); /* BodySize */
-       stream_write_UINT16(data_out, wTimeStamp);
-       stream_write_UINT16(data_out, wPackSize);
-
-       svc_plugin_send((rdpSvcPlugin*) rdpsnd, data_out);
+       rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
 }
 
-static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_in, UINT16 BodySize)
+static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, STREAM* data_in, UINT16 BodySize)
 {
        UINT16 wFormatNo;
 
@@ -347,17 +355,43 @@ static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_
        }
 }
 
-/* header is not removed from data in this function */
-static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
+void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
+{
+       STREAM* pdu;
+
+       pdu = stream_new(8);
+       stream_write_BYTE(pdu, SNDC_WAVECONFIRM);
+       stream_write_BYTE(pdu, 0);
+       stream_write_UINT16(pdu, 4);
+       stream_write_UINT16(pdu, wTimeStamp);
+       stream_write_BYTE(pdu, cConfirmedBlockNo); /* cConfirmedBlockNo */
+       stream_write_BYTE(pdu, 0); /* bPad */
+
+       svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
+}
+
+void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, UINT16 wTimeStamp, BYTE cConfirmedBlockNo)
+{
+       rdpsnd_send_wave_confirm_pdu(device->rdpsnd, wTimeStamp, cConfirmedBlockNo);
+}
+
+static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, STREAM* s)
 {
        STREAM* data;
        UINT16 wTimeStamp;
 
        rdpsnd->expectingWave = FALSE;
 
-       CopyMemory(stream_get_head(data_in), rdpsnd->waveData, 4);
+       /**
+        * The Wave PDU is a special case: it is always sent after a Wave Info PDU,
+        * and we do not process its header. Instead, the header is pad that needs
+        * to be filled with the first four bytes of the audio sample data sent as
+        * part of the preceding Wave Info PDU.
+        */
+
+       CopyMemory(stream_get_head(s), rdpsnd->waveData, 4);
 
-       if (stream_get_size(data_in) != rdpsnd->waveDataSize)
+       if (stream_get_size(s) != rdpsnd->waveDataSize)
        {
                DEBUG_WARN("size error");
                return;
@@ -365,7 +399,15 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
 
        if (rdpsnd->device)
        {
-               IFCALL(rdpsnd->device->Play, rdpsnd->device, stream_get_head(data_in), stream_get_size(data_in));
+               if (rdpsnd->device->WavePlay)
+               {
+                       IFCALL(rdpsnd->device->WavePlay, rdpsnd->device, rdpsnd->wTimeStamp,
+                                       rdpsnd->current_format, rdpsnd->cBlockNo, stream_get_head(s), stream_get_size(s));
+               }
+               else
+               {
+                       IFCALL(rdpsnd->device->Play, rdpsnd->device, stream_get_head(s), stream_get_size(s));
+               }
        }
 
        wTimeStamp = rdpsnd->wTimeStamp + TIME_DELAY_MS;
@@ -382,7 +424,7 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
        MessageQueue_Post(rdpsnd->MsgPipe->Out, NULL, 0, (void*) data, (void*) (size_t) wTimeStamp);
 }
 
-static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd)
+static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
 {
        DEBUG_SVC("server closes.");
 
@@ -394,7 +436,7 @@ static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd)
        rdpsnd->close_timestamp = GetTickCount() + 2000;
 }
 
-static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_in)
+static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, STREAM* data_in)
 {
        UINT32 dwVolume;
 
@@ -407,7 +449,7 @@ static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_
        }
 }
 
-static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
+static void rdpsnd_recv_pdu(rdpSvcPlugin* plugin, STREAM* data_in)
 {
        BYTE msgType;
        UINT16 BodySize;
@@ -415,7 +457,7 @@ static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
 
        if (rdpsnd->expectingWave)
        {
-               rdpsnd_process_message_wave(rdpsnd, data_in);
+               rdpsnd_recv_wave_pdu(rdpsnd, data_in);
                stream_free(data_in);
                return;
        }
@@ -429,23 +471,23 @@ static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
        switch (msgType)
        {
                case SNDC_FORMATS:
-                       rdpsnd_process_message_formats(rdpsnd, data_in);
+                       rdpsnd_recv_formats_pdu(rdpsnd, data_in);
                        break;
 
                case SNDC_TRAINING:
-                       rdpsnd_process_message_training(rdpsnd, data_in);
+                       rdpsnd_recv_training_pdu(rdpsnd, data_in);
                        break;
 
                case SNDC_WAVE:
-                       rdpsnd_process_message_wave_info(rdpsnd, data_in, BodySize);
+                       rdpsnd_recv_wave_info_pdu(rdpsnd, data_in, BodySize);
                        break;
 
                case SNDC_CLOSE:
-                       rdpsnd_process_message_close(rdpsnd);
+                       rdpsnd_recv_close_pdu(rdpsnd);
                        break;
 
                case SNDC_SETVOLUME:
-                       rdpsnd_process_message_setvolume(rdpsnd, data_in);
+                       rdpsnd_recv_volume_pdu(rdpsnd, data_in);
                        break;
 
                default:
@@ -463,7 +505,11 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlug
                DEBUG_WARN("existing device, abort.");
                return;
        }
+
        rdpsnd->device = device;
+       device->rdpsnd = rdpsnd;
+
+       device->WaveConfirm = rdpsnd_device_send_wave_confirm_pdu;
 }
 
 static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args)
@@ -473,7 +519,7 @@ static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, AD
 
        entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
 
-       if (entry == NULL)
+       if (!entry)
                return FALSE;
 
        entryPoints.rdpsnd = rdpsnd;
@@ -625,6 +671,7 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
        if (!rdpsnd->device)
        {
                DEBUG_WARN("no sound device.");
+               return;
        }
 }
 
@@ -670,7 +717,7 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
        strcpy(_p->plugin.channel_def.name, "rdpsnd");
 
        _p->plugin.connect_callback = rdpsnd_process_connect;
-       _p->plugin.receive_callback = rdpsnd_process_receive;
+       _p->plugin.receive_callback = rdpsnd_recv_pdu;
        _p->plugin.event_callback = rdpsnd_process_event;
        _p->plugin.terminate_callback = rdpsnd_process_terminate;
 
index 654dad2..d576546 100644 (file)
@@ -35,8 +35,13 @@ typedef void (*pcStart) (rdpsndDevicePlugin* device);
 typedef void (*pcClose) (rdpsndDevicePlugin* device);
 typedef void (*pcFree) (rdpsndDevicePlugin* device);
 
+typedef void (*pcWavePlay) (rdpsndDevicePlugin* device, UINT16 wTimeStamp, UINT16 wFormatNo, BYTE cBlockNo, BYTE* data, int size);
+typedef void (*pcWaveConfirm) (rdpsndDevicePlugin* device, UINT16 wTimeStamp, BYTE cConfirmedBlockNo);
+
 struct rdpsnd_device_plugin
 {
+       rdpsndPlugin* rdpsnd;
+
        pcFormatSupported FormatSupported;
        pcOpen Open;
        pcSetFormat SetFormat;
@@ -45,6 +50,9 @@ struct rdpsnd_device_plugin
        pcStart Start;
        pcClose Close;
        pcFree Free;
+
+       pcWavePlay WavePlay;
+       pcWaveConfirm WaveConfirm;
 };
 
 #define RDPSND_DEVICE_EXPORT_FUNC_NAME "freerdp_rdpsnd_client_subsystem_entry"
index d618f50..2513d7f 100644 (file)
@@ -48,6 +48,7 @@ struct rdpsnd_format
 #define SNDC_UDPWAVE           10
 #define SNDC_UDPWAVELAST       11
 #define SNDC_QUALITYMODE       12
+#define SNDC_WAVE2             13
 
 #define TSSNDCAPS_ALIVE                1
 #define TSSNDCAPS_VOLUME       2