22#include <freerdp/config.h>
30#include <winpr/stream.h>
31#include <winpr/cmdline.h>
33#include <freerdp/types.h>
35#include "rdpsnd_main.h"
39 rdpsndDevicePlugin device;
45static BOOL rdpsnd_sndio_open(rdpsndDevicePlugin* device,
const AUDIO_FORMAT* format,
46 WINPR_ATTR_UNUSED UINT32 latency)
48 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)device;
50 if (device ==
nullptr || format ==
nullptr)
53 if (sndio->hdl !=
nullptr)
56 sndio->hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
57 if (sndio->hdl ==
nullptr)
59 WLog_ERR(TAG,
"could not open audio device");
63 sio_initpar(&sndio->par);
64 sndio->par.bits = format->wBitsPerSample;
65 sndio->par.pchan = format->nChannels;
66 sndio->par.rate = format->nSamplesPerSec;
67 if (!sio_setpar(sndio->hdl, &sndio->par))
69 WLog_ERR(TAG,
"could not set audio parameters");
72 if (!sio_getpar(sndio->hdl, &sndio->par))
74 WLog_ERR(TAG,
"could not get audio parameters");
78 if (!sio_start(sndio->hdl))
80 WLog_ERR(TAG,
"could not start audio device");
87static void rdpsnd_sndio_close(rdpsndDevicePlugin* device)
89 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)device;
91 if (device ==
nullptr)
94 if (sndio->hdl !=
nullptr)
97 sio_close(sndio->hdl);
102static BOOL rdpsnd_sndio_set_volume(rdpsndDevicePlugin* device, UINT32 value)
104 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)device;
106 if (device ==
nullptr || sndio->hdl ==
nullptr)
113 return sio_setvol(sndio->hdl, ((value & 0xFFFF) * SIO_MAXVOL) / 0xFFFF);
116static void rdpsnd_sndio_free(rdpsndDevicePlugin* device)
118 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)device;
120 if (device ==
nullptr)
123 rdpsnd_sndio_close(device);
127static BOOL rdpsnd_sndio_format_supported(WINPR_ATTR_UNUSED rdpsndDevicePlugin* device,
130 if (format ==
nullptr)
133 return (format->wFormatTag == WAVE_FORMAT_PCM);
136static UINT rdpsnd_sndio_play(rdpsndDevicePlugin* device,
const BYTE* data,
size_t size)
138 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)device;
140 if (device ==
nullptr || sndio->hdl ==
nullptr)
141 return ERROR_INVALID_PARAMETER;
143 const size_t rc = sio_write(sndio->hdl, data, size);
145 return CHANNEL_RC_OK;
146 return CHANNEL_RC_OK;
154static UINT rdpsnd_sndio_parse_addin_args(rdpsndDevicePlugin* device,
const ADDIN_ARGV* args)
156 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)device;
160 nullptr,
nullptr } };
162 COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
163 const int status = CommandLineParseArgumentsA(args->argc, args->argv, rdpsnd_sndio_args, flags,
164 sndio,
nullptr,
nullptr);
167 return ERROR_INVALID_DATA;
173 if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
176 CommandLineSwitchStart(arg) CommandLineSwitchEnd(arg)
177 }
while ((arg = CommandLineFindNextArgumentA(arg)) !=
nullptr);
179 return CHANNEL_RC_OK;
187FREERDP_ENTRY_POINT(UINT VCAPITYPE sndio_freerdp_rdpsnd_client_subsystem_entry(
190 UINT ret = CHANNEL_RC_OK;
191 rdpsndSndioPlugin* sndio = (rdpsndSndioPlugin*)calloc(1,
sizeof(rdpsndSndioPlugin));
193 if (sndio ==
nullptr)
194 return CHANNEL_RC_NO_MEMORY;
196 sndio->device.Open = rdpsnd_sndio_open;
197 sndio->device.FormatSupported = rdpsnd_sndio_format_supported;
198 sndio->device.SetVolume = rdpsnd_sndio_set_volume;
199 sndio->device.Play = rdpsnd_sndio_play;
200 sndio->device.Close = rdpsnd_sndio_close;
201 sndio->device.Free = rdpsnd_sndio_free;
206 ret = rdpsnd_sndio_parse_addin_args(&sndio->device, args);
208 if (ret != CHANNEL_RC_OK)
210 WLog_ERR(TAG,
"error parsing arguments");
215 pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, &sndio->device);
218 rdpsnd_sndio_free(&sndio->device);