channels/rdpsnd: fix stop/start
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 27 Feb 2013 20:10:35 +0000 (15:10 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 27 Feb 2013 20:10:35 +0000 (15:10 -0500)
channels/rdpsnd/client/alsa/rdpsnd_alsa.c
channels/rdpsnd/client/rdpsnd_main.c

index 373435b..23e9046 100644 (file)
@@ -45,18 +45,19 @@ struct rdpsnd_alsa_plugin
 {
        rdpsndDevicePlugin device;
 
+       int latency;
+       int wformat;
+       int block_size;
        char* device_name;
        snd_pcm_t* pcm_handle;
        snd_mixer_t* mixer_handle;
        UINT32 source_rate;
        UINT32 actual_rate;
+       UINT32 wLocalTimeClose;
        snd_pcm_format_t format;
        UINT32 source_channels;
        UINT32 actual_channels;
        int bytes_per_channel;
-       int wformat;
-       int block_size;
-       int latency;
        snd_pcm_uframes_t buffer_size;
        snd_pcm_uframes_t period_size;
        snd_pcm_uframes_t start_threshold;
@@ -166,8 +167,6 @@ int rdpsnd_alsa_validate_params(rdpsndAlsaPlugin* alsa)
        status = snd_pcm_get_params(alsa->pcm_handle, &buffer_size, &period_size);
        SND_PCM_CHECK("snd_pcm_get_params", status);
 
-       printf("Parameters: BufferSize: %d PeriodSize: %d\n", (int) buffer_size, (int) period_size);
-
        return 0;
 }
 
@@ -195,7 +194,7 @@ static int rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
        snd_pcm_drop(alsa->pcm_handle);
 
        if (alsa->latency < 0)
-               alsa->latency = 250;
+               alsa->latency = 400;
 
        alsa->buffer_size = alsa->latency * (alsa->actual_rate / 1000);
 
@@ -330,7 +329,26 @@ static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, i
 
 static void rdpsnd_alsa_close(rdpsndDevicePlugin* device)
 {
-       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device;
+       int status;
+       snd_htimestamp_t tstamp;
+       snd_pcm_uframes_t frames;
+       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
+
+       if (!alsa->pcm_handle)
+               return;
+
+       status = snd_pcm_htimestamp(alsa->pcm_handle, &frames, &tstamp);
+
+       if (status != 0)
+               frames = 0;
+
+       alsa->wLocalTimeClose = GetTickCount();
+       alsa->wLocalTimeClose += (((frames * 1000) / alsa->actual_rate) / alsa->actual_channels);
+}
+
+static void rdpsnd_alsa_free(rdpsndDevicePlugin* device)
+{
+       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
 
        if (alsa->pcm_handle)
        {
@@ -344,13 +362,6 @@ static void rdpsnd_alsa_close(rdpsndDevicePlugin* device)
                snd_mixer_close(alsa->mixer_handle);
                alsa->mixer_handle = NULL;
        }
-}
-
-static void rdpsnd_alsa_free(rdpsndDevicePlugin* device)
-{
-       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
-
-       rdpsnd_alsa_close(device);
 
        free(alsa->device_name);
 
@@ -434,9 +445,6 @@ BYTE* rdpsnd_alsa_process_audio_sample(rdpsndDevicePlugin* device, BYTE* data, i
        int dstFrameSize;
        rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
 
-       if (!alsa->pcm_handle)
-               return NULL;
-
        if (alsa->wformat == WAVE_FORMAT_ADPCM)
        {
                alsa->dsp_context->decode_ms_adpcm(alsa->dsp_context,
@@ -500,21 +508,30 @@ static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
        int offset;
        int length;
        int status;
-       int frames;
        int frame_size;
-       snd_htimestamp_t tstampA;
-       snd_htimestamp_t tstampB;
-       snd_pcm_uframes_t framesA;
-       snd_pcm_uframes_t framesB;
+       UINT32 wCurrentTime;
+       snd_htimestamp_t tstamp;
+       snd_pcm_uframes_t frames;
+
        rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
 
        offset = 0;
        data = wave->data;
        length = wave->length;
        frame_size = alsa->actual_channels * alsa->bytes_per_channel;
-       frames = (length - offset) / frame_size;
 
-       snd_pcm_htimestamp(alsa->pcm_handle, &framesA, &tstampA);
+       if (alsa->wLocalTimeClose)
+       {
+               wCurrentTime = GetTickCount();
+
+               if (snd_pcm_htimestamp(alsa->pcm_handle, &frames, &tstamp) == -EPIPE)
+               {
+                       if (wCurrentTime > alsa->wLocalTimeClose)
+                               snd_pcm_recover(alsa->pcm_handle, -EPIPE, 1);
+               }
+
+               alsa->wLocalTimeClose = 0;
+       }
 
        while (offset < length)
        {
@@ -543,9 +560,9 @@ static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
 
        free(data);
 
-       snd_pcm_htimestamp(alsa->pcm_handle, &framesB, &tstampB);
+       snd_pcm_htimestamp(alsa->pcm_handle, &frames, &tstamp);
 
-       wave->wPlaybackDelay = ((framesB * 1000) / alsa->actual_rate);
+       wave->wPlaybackDelay = ((frames * 1000) / alsa->actual_rate);
 
        wave->wLocalTimeB = GetTickCount();
        wave->wLocalTimeB += wave->wPlaybackDelay;
@@ -557,16 +574,6 @@ static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
        device->WaveConfirm(device, wave);
 }
 
-static void rdpsnd_alsa_start(rdpsndDevicePlugin* device)
-{
-       rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
-
-       if (!alsa->pcm_handle)
-               return;
-
-       snd_pcm_start(alsa->pcm_handle);
-}
-
 COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] =
 {
        { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
@@ -621,7 +628,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
        alsa->device.SetVolume = rdpsnd_alsa_set_volume;
        alsa->device.WaveDecode = rdpsnd_alsa_wave_decode;
        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 3aacc61..a04d9d6 100644 (file)
@@ -69,8 +69,8 @@ struct rdpsnd_plugin
        UINT16 waveDataSize;
        UINT32 wTimeStamp;
 
-       BOOL isOpen;
        int latency;
+       BOOL isOpen;
        UINT16 fixedFormat;
        UINT16 fixedChannel;
        UINT32 fixedRate;
@@ -376,6 +376,8 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, STREAM* s, UINT16 Bo
        UINT16 wFormatNo;
        AUDIO_FORMAT* format;
 
+       rdpsnd->expectingWave = TRUE;
+
        stream_read_UINT16(s, rdpsnd->wTimeStamp);
        stream_read_UINT16(s, wFormatNo);
        stream_read_BYTE(s, rdpsnd->cBlockNo);
@@ -383,7 +385,6 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, STREAM* s, UINT16 Bo
        stream_read(s, rdpsnd->waveData, 4);
 
        rdpsnd->waveDataSize = BodySize - 8;
-       rdpsnd->expectingWave = TRUE;
 
        format = &rdpsnd->ClientFormats[wFormatNo];
 
@@ -392,8 +393,6 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, STREAM* s, UINT16 Bo
                rdpsnd->isOpen = TRUE;
                rdpsnd->wCurrentFormatNo = wFormatNo;
 
-               rdpsnd_print_audio_format(format);
-
                if (rdpsnd->device)
                {
                        IFCALL(rdpsnd->device->Open, rdpsnd->device, format, rdpsnd->latency);
@@ -495,8 +494,10 @@ static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
 
        if (rdpsnd->device)
        {
-               IFCALL(rdpsnd->device->Start, rdpsnd->device);
+               IFCALL(rdpsnd->device->Close, rdpsnd->device);
        }
+
+       rdpsnd->isOpen = FALSE;
 }
 
 static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, STREAM* s)
@@ -529,7 +530,7 @@ static void rdpsnd_recv_pdu(rdpSvcPlugin* plugin, STREAM* s)
        stream_seek_BYTE(s); /* bPad */
        stream_read_UINT16(s, BodySize);
 
-       DEBUG_SVC("msgType %d BodySize %d", msgType, BodySize);
+       //printf("msgType %d BodySize %d\n", msgType, BodySize);
 
        switch (msgType)
        {