static gboolean
gst_core_audio_select_device_impl (GstCoreAudio * core_audio)
{
  AudioDeviceID *devices = NULL;
  AudioDeviceID device_id = core_audio->device_id;
  AudioDeviceID default_device_id = 0;
  gint i, ndevices = 0;
  gboolean output = !core_audio->is_src;
  gboolean res = FALSE;
#ifdef GST_CORE_AUDIO_DEBUG
  AudioChannelLayout *channel_layout;
#endif

  devices = _audio_system_get_devices (&ndevices);

  if (ndevices < 1) {
    GST_ERROR ("no audio output devices found");
    goto done;
  }

  GST_DEBUG ("found %d audio device(s)", ndevices);

#ifdef GST_CORE_AUDIO_DEBUG
  for (i = 0; i < ndevices; i++) {
    gchar *device_name;

    if ((device_name = _audio_device_get_name (devices[i], output))) {
      if (!_audio_device_has_output (devices[i])) {
        GST_DEBUG ("Input Device ID: %u Name: %s",
            (unsigned) devices[i], device_name);
      } else {
        GST_DEBUG ("Output Device ID: %u Name: %s",
            (unsigned) devices[i], device_name);

        channel_layout =
            gst_core_audio_audio_device_get_channel_layout (devices[i], output);
        if (channel_layout) {
          gst_core_audio_dump_channel_layout (channel_layout);
          g_free (channel_layout);
        }
      }

      g_free (device_name);
    }
  }
#endif

  /* Find the ID of the default output device */
  default_device_id = _audio_system_get_default_device (output);

  /* Here we decide if selected device is valid or autoselect
   * the default one when required */
  if (device_id == kAudioDeviceUnknown) {
    if (default_device_id != kAudioDeviceUnknown) {
      device_id = default_device_id;
      res = TRUE;
    } else {
      /* No device of required type available */
      res = FALSE;
    }
  } else {
    for (i = 0; i < ndevices; i++) {
      if (device_id == devices[i]) {
        res = TRUE;
      }
    }

    if (res && !_audio_device_is_alive (device_id, output)) {
      GST_ERROR ("Requested device not usable");
      res = FALSE;
      goto done;
    }
  }

  if (res)
    core_audio->device_id = device_id;

done:
  g_free (devices);
  return res;
}
Esempio n. 2
0
static gboolean
gst_osx_audio_sink_allowed_caps (GstOsxAudioSink * osxsink)
{
  gint i, channels;
  gboolean spdif_allowed;
  AudioChannelLayout *layout;
  GstElementClass *element_class;
  GstPadTemplate *pad_template;
  GstCaps *caps, *in_caps;
  guint64 channel_mask = 0;
  GstAudioChannelPosition *pos = osxsink->channel_positions;

  /* First collect info about the HW capabilites and preferences */
  spdif_allowed =
      gst_core_audio_audio_device_is_spdif_avail (osxsink->device_id);
  layout = gst_core_audio_audio_device_get_channel_layout (osxsink->device_id);

  GST_DEBUG_OBJECT (osxsink, "Selected device ID: %u SPDIF allowed: %d",
      (unsigned) osxsink->device_id, spdif_allowed);

  if (layout) {
    channels = MIN (layout->mNumberChannelDescriptions,
        GST_OSX_AUDIO_MAX_CHANNEL);
  } else {
    GST_WARNING_OBJECT (osxsink, "This driver does not support "
        "kAudioDevicePropertyPreferredChannelLayout.");
    channels = 2;
  }

  switch (channels) {
    case 0:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE;
      break;
    case 1:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
      break;
    case 2:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
      channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT);
      channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
      break;
    default:
      channels = MIN (layout->mNumberChannelDescriptions,
          GST_OSX_AUDIO_MAX_CHANNEL);
      for (i = 0; i < channels; i++) {
        switch (layout->mChannelDescriptions[i].mChannelLabel) {
          case kAudioChannelLabel_Left:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
            break;
          case kAudioChannelLabel_Right:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
            break;
          case kAudioChannelLabel_Center:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
            break;
          case kAudioChannelLabel_LFEScreen:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
            break;
          case kAudioChannelLabel_LeftSurround:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
            break;
          case kAudioChannelLabel_RightSurround:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
            break;
          case kAudioChannelLabel_RearSurroundLeft:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
            break;
          case kAudioChannelLabel_RearSurroundRight:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
            break;
          case kAudioChannelLabel_CenterSurround:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
            break;
          default:
            GST_WARNING_OBJECT (osxsink, "unrecognized channel: %d",
                (int) layout->mChannelDescriptions[i].mChannelLabel);
            channel_mask = 0;
            channels = 2;
            break;
        }
      }
  }
  g_free (layout);

  /* Recover the template caps */
  element_class = GST_ELEMENT_GET_CLASS (osxsink);
  pad_template = gst_element_class_get_pad_template (element_class, "sink");
  in_caps = gst_pad_template_get_caps (pad_template);

  /* Create the allowed subset  */
  caps = gst_caps_new_empty ();
  for (i = 0; i < gst_caps_get_size (in_caps); i++) {
    GstStructure *in_s, *out_s;

    in_s = gst_caps_get_structure (in_caps, i);

    if (gst_structure_has_name (in_s, "audio/x-ac3") ||
        gst_structure_has_name (in_s, "audio/x-dts")) {
      if (spdif_allowed) {
        gst_caps_append_structure (caps, gst_structure_copy (in_s));
      }
    }
    gst_audio_channel_positions_to_mask (pos, channels, false, &channel_mask);
    out_s = gst_structure_copy (in_s);
    gst_structure_remove_fields (out_s, "channels", "channel-mask", NULL);
    gst_structure_set (out_s, "channels", G_TYPE_INT, channels,
        "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
    gst_caps_append_structure (caps, out_s);
  }

  if (osxsink->cached_caps) {
    gst_caps_unref (osxsink->cached_caps);
  }

  osxsink->cached_caps = caps;
  osxsink->channels = channels;

  return TRUE;
}