20#include <freerdp/config.h> 
   34#if defined(__OpenBSD__) 
   37#include <sys/soundcard.h> 
   41#include <freerdp/types.h> 
   42#include <freerdp/codec/dsp.h> 
   44#include "tsmf_audio.h" 
   48  ITSMFAudioDevice iface;
 
   50  char dev_name[PATH_MAX];
 
   55  UINT32 bits_per_sample;
 
   57  UINT32 data_size_last;
 
   60#define OSS_LOG_ERR(_text, _error)                                        \ 
   65      char ebuffer[256] = { 0 };                                    \ 
   66      WLog_ERR(TAG, "%s: %i - %s", (_text), (_error),               \ 
   67               winpr_strerror((_error), ebuffer, sizeof(ebuffer))); \ 
   71static BOOL tsmf_oss_open(ITSMFAudioDevice* audio, 
const char* device)
 
   74  TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
 
   76  if (oss == NULL || oss->pcm_handle != -1)
 
   81    strncpy(oss->dev_name, 
"/dev/dsp", 
sizeof(oss->dev_name));
 
   85    strncpy(oss->dev_name, device, 
sizeof(oss->dev_name) - 1);
 
   88  if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0)
 
   90    OSS_LOG_ERR(
"sound dev open failed", errno);
 
   95  const int rc = ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &tmp);
 
   98    OSS_LOG_ERR(
"SNDCTL_DSP_GETFMTS failed", errno);
 
   99    close(oss->pcm_handle);
 
  100    oss->pcm_handle = -1;
 
  104  if ((AFMT_S16_LE & tmp) == 0)
 
  106    OSS_LOG_ERR(
"SNDCTL_DSP_GETFMTS - AFMT_S16_LE", EOPNOTSUPP);
 
  107    close(oss->pcm_handle);
 
  108    oss->pcm_handle = -1;
 
  112  WLog_INFO(TAG, 
"open: %s", oss->dev_name);
 
  116static BOOL tsmf_oss_set_format(ITSMFAudioDevice* audio, UINT32 sample_rate, UINT32 channels,
 
  117                                UINT32 bits_per_sample)
 
  120  TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
 
  122  if (oss == NULL || oss->pcm_handle == -1)
 
  125  oss->sample_rate = sample_rate;
 
  126  oss->channels = channels;
 
  127  oss->bits_per_sample = bits_per_sample;
 
  130  if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1)
 
  131    OSS_LOG_ERR(
"SNDCTL_DSP_SETFMT failed", errno);
 
  133  tmp = WINPR_ASSERTING_INT_CAST(
int, channels);
 
  135  if (ioctl(oss->pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1)
 
  136    OSS_LOG_ERR(
"SNDCTL_DSP_CHANNELS failed", errno);
 
  138  tmp = WINPR_ASSERTING_INT_CAST(
int, sample_rate);
 
  140  if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1)
 
  141    OSS_LOG_ERR(
"SNDCTL_DSP_SPEED failed", errno);
 
  143  tmp = WINPR_ASSERTING_INT_CAST(
int, ((bits_per_sample / 8) * channels * sample_rate));
 
  145  if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
 
  146    OSS_LOG_ERR(
"SNDCTL_DSP_SETFRAGMENT failed", errno);
 
  148  DEBUG_TSMF(
"sample_rate %" PRIu32 
" channels %" PRIu32 
" bits_per_sample %" PRIu32 
"",
 
  149             sample_rate, channels, bits_per_sample);
 
  153static BOOL tsmf_oss_play(ITSMFAudioDevice* audio, 
const BYTE* data, UINT32 data_size)
 
  156  TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
 
  157  DEBUG_TSMF(
"tsmf_oss_play: data_size %" PRIu32 
"", data_size);
 
  159  if (oss == NULL || oss->pcm_handle == -1)
 
  162  if (data == NULL || data_size == 0)
 
  166  oss->data_size_last = data_size;
 
  168  while (offset < data_size)
 
  170    const ssize_t status = write(oss->pcm_handle, &data[offset], (data_size - offset));
 
  174      OSS_LOG_ERR(
"write fail", errno);
 
  184static UINT64 tsmf_oss_get_latency(ITSMFAudioDevice* audio)
 
  187  TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
 
  197static BOOL tsmf_oss_flush(ITSMFAudioDevice* audio)
 
  202static void tsmf_oss_free(ITSMFAudioDevice* audio)
 
  204  TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
 
  209  if (oss->pcm_handle != -1)
 
  211    WLog_INFO(TAG, 
"close: %s", oss->dev_name);
 
  212    close(oss->pcm_handle);
 
  218FREERDP_ENTRY_POINT(UINT VCAPITYPE oss_freerdp_tsmf_client_audio_subsystem_entry(
void* ptr))
 
  220  ITSMFAudioDevice** sptr = (ITSMFAudioDevice**)ptr;
 
  224  TSMFOssAudioDevice* oss = calloc(1, 
sizeof(TSMFOssAudioDevice));
 
  226    return ERROR_OUTOFMEMORY;
 
  228  oss->iface.Open = tsmf_oss_open;
 
  229  oss->iface.SetFormat = tsmf_oss_set_format;
 
  230  oss->iface.Play = tsmf_oss_play;
 
  231  oss->iface.GetLatency = tsmf_oss_get_latency;
 
  232  oss->iface.Flush = tsmf_oss_flush;
 
  233  oss->iface.Free = tsmf_oss_free;
 
  234  oss->pcm_handle = -1;
 
  236  return CHANNEL_RC_OK;