static BOOL rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { MMRESULT mmResult; rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device; if (winmm->hWaveOut) return TRUE; rdpsnd_winmm_set_format(device, format, latency); freerdp_dsp_context_reset_adpcm(winmm->dsp_context); mmResult = waveOutOpen(&winmm->hWaveOut, WAVE_MAPPER, &winmm->format, (DWORD_PTR) rdpsnd_winmm_callback_function, (DWORD_PTR) winmm, CALLBACK_FUNCTION); if (mmResult != MMSYSERR_NOERROR) { WLog_ERR(TAG, "waveOutOpen failed: %"PRIu32"", mmResult); return FALSE; } mmResult = waveOutSetVolume(winmm->hWaveOut, winmm->volume); if (mmResult != MMSYSERR_NOERROR) { WLog_ERR(TAG, "waveOutSetVolume failed: %"PRIu32"", mmResult); return FALSE; } return TRUE; }
static void* audin_alsa_thread_func(void* arg) { int error; uint8* buffer; int rbytes_per_frame; int tbytes_per_frame; snd_pcm_t* capture_handle = NULL; AudinALSADevice* alsa = (AudinALSADevice*) arg; DEBUG_DVC("in"); rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel; alsa->buffer = (uint8*) xzalloc(tbytes_per_frame * alsa->frames_per_packet); alsa->buffer_frames = 0; buffer = (uint8*) xzalloc(rbytes_per_frame * alsa->frames_per_packet); freerdp_dsp_context_reset_adpcm(alsa->dsp_context); do { if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { DEBUG_WARN("snd_pcm_open (%s)", snd_strerror(error)); break; } if (!audin_alsa_set_params(alsa, capture_handle)) { break; } while (!freerdp_thread_is_stopped(alsa->thread)) { error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet); if (error == -EPIPE) { snd_pcm_recover(capture_handle, error, 0); continue; } else if (error < 0) { DEBUG_WARN("snd_pcm_readi (%s)", snd_strerror(error)); break; } if (!audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)) break; } } while (0); xfree(buffer); xfree(alsa->buffer); alsa->buffer = NULL; if (capture_handle) snd_pcm_close(capture_handle); freerdp_thread_quit(alsa->thread); DEBUG_DVC("out"); return NULL; }
static void rdpsnd_server_select_format(rdpsnd_server_context* context, int client_format_index) { int bs; int out_buffer_size; rdpsndFormat *format; rdpsnd_server* rdpsnd = (rdpsnd_server*) context; if (client_format_index < 0 || client_format_index >= context->num_client_formats) { printf("rdpsnd_server_select_format: index %d is not correct.\n", client_format_index); return; } rdpsnd->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; rdpsnd->src_bytes_per_frame = rdpsnd->src_bytes_per_sample * context->src_format.nChannels; context->selected_client_format = client_format_index; format = &context->client_formats[client_format_index]; if (format->wFormatTag == 0x11) { bs = (format->nBlockAlign - 4 * format->nChannels) * 4; rdpsnd->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2); } else if (format->wFormatTag == 0x02) { bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2; rdpsnd->out_frames = bs * 4; } else { rdpsnd->out_frames = 0x4000 / rdpsnd->src_bytes_per_frame; } if (format->nSamplesPerSec != context->src_format.nSamplesPerSec) { rdpsnd->out_frames = (rdpsnd->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec; } rdpsnd->out_pending_frames = 0; out_buffer_size = rdpsnd->out_frames * rdpsnd->src_bytes_per_frame; if (rdpsnd->out_buffer_size < out_buffer_size) { rdpsnd->out_buffer = (BYTE*) realloc(rdpsnd->out_buffer, out_buffer_size); rdpsnd->out_buffer_size = out_buffer_size; } freerdp_dsp_context_reset_adpcm(rdpsnd->dsp_context); }
static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_stream_state_t state; pa_stream_flags_t flags; pa_buffer_attr buffer_attr = { 0 }; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (!pulse->context || pulse->stream) { DEBUG_WARN("pulse stream has been created."); return; } rdpsnd_pulse_set_format_spec(pulse, format); pulse->latency = latency; if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); DEBUG_WARN("Invalid sample spec %s", ss); return; } pa_threaded_mainloop_lock(pulse->mainloop); pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL); if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return; } /* install essential callbacks */ pa_stream_set_state_callback(pulse->stream, rdpsnd_pulse_stream_state_callback, pulse); pa_stream_set_write_callback(pulse->stream, rdpsnd_pulse_stream_request_callback, pulse); flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; if (pulse->latency > 0) { buffer_attr.maxlength = pa_usec_to_bytes(pulse->latency * 2 * 1000, &pulse->sample_spec); buffer_attr.tlength = pa_usec_to_bytes(pulse->latency * 1000, &pulse->sample_spec); buffer_attr.prebuf = (uint32_t) -1; buffer_attr.minreq = (uint32_t) -1; buffer_attr.fragsize = (uint32_t) -1; flags |= PA_STREAM_ADJUST_LATENCY; } if (pa_stream_connect_playback(pulse->stream, pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); return; } for (;;) { state = pa_stream_get_state(pulse->stream); if (state == PA_STREAM_READY) break; if (!PA_STREAM_IS_GOOD(state)) { DEBUG_WARN("bad stream state (%d)", pa_context_errno(pulse->context)); break; } pa_threaded_mainloop_wait(pulse->mainloop); } pa_threaded_mainloop_unlock(pulse->mainloop); if (state == PA_STREAM_READY) { freerdp_dsp_context_reset_adpcm(pulse->dsp_context); DEBUG_SVC("connected"); } else { rdpsnd_pulse_close(device); } }
static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index) { int bs; int out_buffer_size; AUDIO_FORMAT *format; if (client_format_index < 0 || client_format_index >= context->num_client_formats) { fprintf(stderr, "%s: index %d is not correct.\n", __FUNCTION__, client_format_index); return FALSE; } context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels; context->selected_client_format = client_format_index; format = &context->client_formats[client_format_index]; if (format->nSamplesPerSec == 0) { fprintf(stderr, "%s: invalid Client Sound Format!!\n", __FUNCTION__); return FALSE; } switch(format->wFormatTag) { case WAVE_FORMAT_DVI_ADPCM: bs = (format->nBlockAlign - 4 * format->nChannels) * 4; context->priv->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2); break; case WAVE_FORMAT_ADPCM: bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2; context->priv->out_frames = bs * 4; break; default: context->priv->out_frames = 0x4000 / context->priv->src_bytes_per_frame; break; } if (format->nSamplesPerSec != context->src_format.nSamplesPerSec) { context->priv->out_frames = (context->priv->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec; } context->priv->out_pending_frames = 0; out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame; if (context->priv->out_buffer_size < out_buffer_size) { BYTE *newBuffer; newBuffer = (BYTE *)realloc(context->priv->out_buffer, out_buffer_size); if (!newBuffer) return FALSE; context->priv->out_buffer = newBuffer; context->priv->out_buffer_size = out_buffer_size; } freerdp_dsp_context_reset_adpcm(context->priv->dsp_context); return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index) { int bs; int out_buffer_size; AUDIO_FORMAT *format; UINT error = CHANNEL_RC_OK; if (client_format_index < 0 || client_format_index >= context->num_client_formats) { WLog_ERR(TAG, "index %d is not correct.", client_format_index); return ERROR_INVALID_DATA; } EnterCriticalSection(&context->priv->lock); context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8; context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels; context->selected_client_format = client_format_index; format = &context->client_formats[client_format_index]; if (format->nSamplesPerSec == 0) { WLog_ERR(TAG, "invalid Client Sound Format!!"); error = ERROR_INVALID_DATA; goto out; } if (context->latency <= 0) context->latency = 50; context->priv->out_frames = context->src_format.nSamplesPerSec * context->latency / 1000; if (context->priv->out_frames < 1) context->priv->out_frames = 1; switch(format->wFormatTag) { case WAVE_FORMAT_DVI_ADPCM: bs = (format->nBlockAlign - 4 * format->nChannels) * 4; context->priv->out_frames -= context->priv->out_frames % bs; if (context->priv->out_frames < bs) context->priv->out_frames = bs; break; case WAVE_FORMAT_ADPCM: bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2; context->priv->out_frames -= context->priv->out_frames % bs; if (context->priv->out_frames < bs) context->priv->out_frames = bs; break; } context->priv->out_pending_frames = 0; out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame; if (context->priv->out_buffer_size < out_buffer_size) { BYTE *newBuffer; newBuffer = (BYTE *)realloc(context->priv->out_buffer, out_buffer_size); if (!newBuffer) { WLog_ERR(TAG, "realloc failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } context->priv->out_buffer = newBuffer; context->priv->out_buffer_size = out_buffer_size; } freerdp_dsp_context_reset_adpcm(context->priv->dsp_context); out: LeaveCriticalSection(&context->priv->lock); return error; }