Esempio n. 1
0
bool CAESinkOSS::IsCompatible(const AEAudioFormat &format, const std::string &device)
{
  AEAudioFormat tmp  = format;
  tmp.m_channelLayout = GetChannelLayout(format);

  return (
    tmp.m_sampleRate    == m_initFormat.m_sampleRate    &&
    tmp.m_dataFormat    == m_initFormat.m_dataFormat    &&
    tmp.m_channelLayout == m_initFormat.m_channelLayout &&
    GetDeviceUse(tmp, device) == m_device
  );
}
/**
 * Write the info for device dev into the buffer pointed to by info.
 *
 * @return The number of bytes used.
 */
static int
ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info)
{
    char *any = (char *) &info[1];
    int len = 0, total_len = 0;

    info->deviceid = dev->id;
    info->use = GetDeviceUse(dev, &info->attachment);
    info->num_classes = 0;
    info->name_len = strlen(dev->name);
    info->enabled = dev->enabled;
    total_len = sizeof(xXIDeviceInfo);

    len = pad_to_int32(info->name_len);
    memset(any, 0, len);
    strncpy(any, dev->name, info->name_len);
    any += len;
    total_len += len;

    total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
    return total_len;
}
Esempio n. 3
0
bool CAESinkOSS::Initialize(AEAudioFormat &format, std::string &device)
{
  m_initFormat = format;
  format.m_channelLayout = GetChannelLayout(format);
  device = GetDeviceUse(format, device);

#ifdef __linux__
  /* try to open in exclusive mode first (no software mixing) */
  m_fd = open(device.c_str(), O_WRONLY | O_EXCL, 0);
  if (m_fd == -1)
#endif
    m_fd = open(device.c_str(), O_WRONLY, 0);
  if (m_fd == -1)
  {
    CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to open the audio device: %s", device.c_str());
    return false;
  }

  int format_mask;
  if (ioctl(m_fd, SNDCTL_DSP_GETFMTS, &format_mask) == -1)
  {
    close(m_fd);
    CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to get supported formats, assuming AFMT_S16_NE");
    return false;
  }

#ifdef OSS4
  bool useCooked = true;
#endif

  int oss_fmt = 0;
#ifdef AFMT_FLOAT
  if ((format.m_dataFormat == AE_FMT_FLOAT) && (format_mask & AFMT_FLOAT ))
    oss_fmt = AFMT_FLOAT;
  else
#endif
#ifdef AFMT_S32_NE
  if ((format.m_dataFormat == AE_FMT_S32NE) && (format_mask & AFMT_S32_NE))
    oss_fmt = AFMT_S32_NE;
  else if ((format.m_dataFormat == AE_FMT_S32BE) && (format_mask & AFMT_S32_BE))
    oss_fmt = AFMT_S32_BE;
  else if ((format.m_dataFormat == AE_FMT_S32LE) && (format_mask & AFMT_S32_LE))
    oss_fmt = AFMT_S32_LE;
  else
#endif
  if ((format.m_dataFormat == AE_FMT_S16NE) && (format_mask & AFMT_S16_NE))
    oss_fmt = AFMT_S16_NE;
  else if ((format.m_dataFormat == AE_FMT_S16BE) && (format_mask & AFMT_S16_BE))
    oss_fmt = AFMT_S16_BE;
  else if ((format.m_dataFormat == AE_FMT_S16LE) && (format_mask & AFMT_S16_LE))
    oss_fmt = AFMT_S16_LE;
  else if ((format.m_dataFormat == AE_FMT_S8   ) && (format_mask & AFMT_S8    ))
    oss_fmt = AFMT_S8;
  else if ((format.m_dataFormat == AE_FMT_U8   ) && (format_mask & AFMT_U8    ))
    oss_fmt = AFMT_U8;
  else if ((AE_IS_RAW(format.m_dataFormat)     ) && (format_mask & AFMT_AC3   ))
  {
    oss_fmt = AFMT_AC3;
    format.m_dataFormat = AE_FMT_S16NE;
  }
  else if (AE_IS_RAW(format.m_dataFormat))
  {
    close(m_fd);
    CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to find a suitable RAW output format");
    return false;
  }
  else
  {
    CLog::Log(LOGINFO, "CAESinkOSS::Initialize - Your hardware does not support %s, trying other formats", CAEUtil::DataFormatToStr(format.m_dataFormat));

    /* fallback to the best supported format */
#ifdef AFMT_FLOAT
    if (format_mask & AFMT_FLOAT )
    {
      oss_fmt = AFMT_FLOAT;
      format.m_dataFormat = AE_FMT_FLOAT;
    }
    else
#endif
#ifdef AFMT_S32_NE
    if (format_mask & AFMT_S32_NE)
    {
      oss_fmt = AFMT_S32_NE;
      format.m_dataFormat = AE_FMT_S32NE;
    }
    else if (format_mask & AFMT_S32_BE)
    {
      oss_fmt = AFMT_S32_BE;
      format.m_dataFormat = AE_FMT_S32BE;
    }
    else if (format_mask & AFMT_S32_LE)
    {
      oss_fmt = AFMT_S32_LE;
      format.m_dataFormat = AE_FMT_S32LE;
    }
    else
#endif
    if (format_mask & AFMT_S16_NE)
    {
      oss_fmt = AFMT_S16_NE;
      format.m_dataFormat = AE_FMT_S16NE;
    }
    else if (format_mask & AFMT_S16_BE)
    {
      oss_fmt = AFMT_S16_BE;
      format.m_dataFormat = AE_FMT_S16BE;
    }
    else if (format_mask & AFMT_S16_LE)
    {
      oss_fmt = AFMT_S16_LE;
      format.m_dataFormat = AE_FMT_S16LE;
    }
    else if (format_mask & AFMT_S8    )
    {
      oss_fmt = AFMT_S8;
      format.m_dataFormat = AE_FMT_S8;
    }
    else if (format_mask & AFMT_U8    )
    {
      oss_fmt = AFMT_U8;
      format.m_dataFormat = AE_FMT_U8;
    }
    else
    {
      CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to find a suitable native output format, will try to use AE_FMT_S16NE anyway");
      oss_fmt             = AFMT_S16_NE;
      format.m_dataFormat = AE_FMT_S16NE;
#ifdef OSS4
      /* dont use cooked if we did not find a native format, OSS might be able to convert */
      useCooked           = false;
#endif
    }
  }

#ifdef OSS4
  if (useCooked)
  {
    int oss_cooked = 1;
    if (ioctl(m_fd, SNDCTL_DSP_COOKEDMODE, &oss_cooked) == -1)
      CLog::Log(LOGWARNING, "CAESinkOSS::Initialize - Failed to set cooked mode");
  }
#endif

  if (ioctl(m_fd, SNDCTL_DSP_SETFMT, &oss_fmt) == -1)
  {
    close(m_fd);
    CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to set the data format (%s)", CAEUtil::DataFormatToStr(format.m_dataFormat));
    return false;
  }

  /* find the number we need to open to access the channels we need */
  bool found = false;
  int oss_ch = 0;
  for (int ch = format.m_channelLayout.Count(); ch < 9; ++ch)
  {
    oss_ch = ch;
    if (ioctl(m_fd, SNDCTL_DSP_CHANNELS, &oss_ch) != -1 && oss_ch >= (int)format.m_channelLayout.Count())
    {
      found = true;
      break;
    }
  }

  if (!found)
    CLog::Log(LOGWARNING, "CAESinkOSS::Initialize - Failed to access the number of channels required, falling back");

#if defined(TARGET_FREEBSD)
  /* fix hdmi 8 channels order */
  if ((oss_fmt != AFMT_AC3) && 8 == oss_ch)
  {
    unsigned long long order = 0x0000000087346521ULL;

    if (ioctl(m_fd, SNDCTL_DSP_SET_CHNORDER, &order) == -1)
      CLog::Log(LOGWARNING, "CAESinkOSS::Initialize - Failed to set the channel order");
  }
#elif defined(OSS4)
  unsigned long long order = 0;

  for (unsigned int i = 0; i < format.m_channelLayout.Count(); ++i)
    switch (format.m_channelLayout[i])
    {
      case AE_CH_FL : order = (order << 4) | CHID_L  ; break;
      case AE_CH_FR : order = (order << 4) | CHID_R  ; break;
      case AE_CH_FC : order = (order << 4) | CHID_C  ; break;
      case AE_CH_LFE: order = (order << 4) | CHID_LFE; break;
      case AE_CH_SL : order = (order << 4) | CHID_LS ; break;
      case AE_CH_SR : order = (order << 4) | CHID_RS ; break;
      case AE_CH_BL : order = (order << 4) | CHID_LR ; break;
      case AE_CH_BR : order = (order << 4) | CHID_RR ; break;

      default:
        continue;
    }

  if (ioctl(m_fd, SNDCTL_DSP_SET_CHNORDER, &order) == -1)
  {
    if (ioctl(m_fd, SNDCTL_DSP_GET_CHNORDER, &order) == -1)
    {
      CLog::Log(LOGWARNING, "CAESinkOSS::Initialize - Failed to get the channel order, assuming CHNORDER_NORMAL");
    }
  }
#endif

  int tmp = (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3) * format.m_channelLayout.Count() * OSS_FRAMES;
  int pos = 0;
  while ((tmp & 0x1) == 0x0)
  {
    tmp = tmp >> 1;
    ++pos;
  }

  int oss_frag = (4 << 16) | pos;
  if (ioctl(m_fd, SNDCTL_DSP_SETFRAGMENT, &oss_frag) == -1)
    CLog::Log(LOGWARNING, "CAESinkOSS::Initialize - Failed to set the fragment size");

  int oss_sr = format.m_sampleRate;
  if (ioctl(m_fd, SNDCTL_DSP_SPEED, &oss_sr) == -1)
  {
    close(m_fd);
    CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to set the sample rate");
    return false;
  }

  audio_buf_info bi;
  if (ioctl(m_fd, SNDCTL_DSP_GETOSPACE, &bi) == -1)
  {
    close(m_fd);
    CLog::Log(LOGERROR, "CAESinkOSS::Initialize - Failed to get the output buffer size");
    return false;
  }

  format.m_sampleRate    = oss_sr;
  format.m_frameSize     = (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3) * format.m_channelLayout.Count();
  format.m_frames        = bi.fragsize / format.m_frameSize;
  format.m_frameSamples  = format.m_frames * format.m_channelLayout.Count();

  m_device = device;
  m_format = format;
  return true;
}
Esempio n. 4
0
/**
 * Send the current state of the device hierarchy to all clients.
 */
void XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
{
    xXIHierarchyEvent *ev;
    xXIHierarchyInfo *info;
    DeviceIntRec dummyDev;
    DeviceIntPtr dev;
    int i;

    if (!flags)
        return;

    ev = calloc(1, sizeof(xXIHierarchyEvent) +
                 MAXDEVICES * sizeof(xXIHierarchyInfo));
    if (!ev)
        return;
    ev->type = GenericEvent;
    ev->extension = IReqCode;
    ev->evtype = XI_HierarchyChanged;
    ev->time = GetTimeInMillis();
    ev->flags = 0;
    ev->num_info = inputInfo.numDevices;

    info = (xXIHierarchyInfo*)&ev[1];
    for (dev = inputInfo.devices; dev; dev = dev->next)
    {
        info->deviceid = dev->id;
        info->enabled = dev->enabled;
        info->use = GetDeviceUse(dev, &info->attachment);
        info->flags = flags[dev->id];
        ev->flags |= info->flags;
        info++;
    }
    for (dev = inputInfo.off_devices; dev; dev = dev->next)
    {
        info->deviceid = dev->id;
        info->enabled = dev->enabled;
        info->use = GetDeviceUse(dev, &info->attachment);
        info->flags = flags[dev->id];
        ev->flags |= info->flags;
        info++;
    }


    for (i = 0; i < MAXDEVICES; i++)
    {
        if (flags[i] & (XIMasterRemoved | XISlaveRemoved))
        {
            info->deviceid = i;
            info->enabled = FALSE;
            info->flags = flags[i];
            info->use = 0;
            ev->flags |= info->flags;
            ev->num_info++;
            info++;
        }
    }

    ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo));

    memset(&dummyDev, 0, sizeof(dummyDev));
    dummyDev.id = XIAllDevices;
    dummyDev.type = SLAVE;
    SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1);
    free(ev);
}