static GValueArray * gst_ks_video_src_get_device_name_values (GstKsVideoSrc * self) { GList *devices, *cur; GValueArray *array = g_value_array_new (0); devices = ks_enumerate_devices (&KSCATEGORY_VIDEO); if (devices == NULL) return array; devices = ks_video_device_list_sort_cameras_first (devices); for (cur = devices; cur != NULL; cur = cur->next) { GValue value = { 0, }; KsDeviceEntry *entry = cur->data; g_value_init (&value, G_TYPE_STRING); g_value_set_string (&value, entry->name); g_value_array_append (array, &value); g_value_unset (&value); ks_device_entry_free (entry); } g_list_free (devices); return array; }
void ks_device_list_free (GList * devices) { GList *cur; for (cur = devices; cur != NULL; cur = cur->next) ks_device_entry_free (cur->data); g_list_free (devices); }
static gboolean gst_ks_video_src_open_device (GstKsVideoSrc * self) { GstKsVideoSrcPrivate *priv = GST_KS_VIDEO_SRC_GET_PRIVATE (self); GstKsVideoDevice *device = NULL; GList *devices, *cur; g_assert (priv->device == NULL); devices = ks_enumerate_devices (&KSCATEGORY_VIDEO); if (devices == NULL) goto error_no_devices; devices = ks_video_device_list_sort_cameras_first (devices); for (cur = devices; cur != NULL; cur = cur->next) { KsDeviceEntry *entry = cur->data; GST_DEBUG_OBJECT (self, "device %d: name='%s' path='%s'", entry->index, entry->name, entry->path); } for (cur = devices; cur != NULL && device == NULL; cur = cur->next) { KsDeviceEntry *entry = cur->data; gboolean match; if (priv->device_path != NULL) { match = g_strcasecmp (entry->path, priv->device_path) == 0; } else if (priv->device_name != NULL) { match = g_strcasecmp (entry->name, priv->device_name) == 0; } else if (priv->device_index >= 0) { match = entry->index == priv->device_index; } else { match = TRUE; /* pick the first entry */ } if (match) { priv->ksclock = g_object_new (GST_TYPE_KS_CLOCK, NULL); if (priv->ksclock != NULL && gst_ks_clock_open (priv->ksclock)) { GstClock *clock = GST_ELEMENT_CLOCK (self); if (clock != NULL) gst_ks_clock_provide_master_clock (priv->ksclock, clock); } else { GST_WARNING_OBJECT (self, "failed to create/open KsClock"); g_object_unref (priv->ksclock); priv->ksclock = NULL; } device = gst_ks_video_device_new (entry->path, priv->ksclock, gst_ks_video_src_alloc_buffer, self); } ks_device_entry_free (entry); } g_list_free (devices); if (device == NULL) goto error_no_match; if (!gst_ks_video_device_open (device)) goto error_open; priv->device = device; return TRUE; /* ERRORS */ error_no_devices: { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("No video capture devices found"), (NULL)); return FALSE; } error_no_match: { if (priv->device_path != NULL) { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Specified video capture device with path '%s' not found", priv->device_path), (NULL)); } else if (priv->device_name != NULL) { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Specified video capture device with name '%s' not found", priv->device_name), (NULL)); } else { GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Specified video capture device with index %d not found", priv->device_index), (NULL)); } return FALSE; } error_open: { GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, ("Failed to open device"), (NULL)); g_object_unref (device); return FALSE; } }
GList * ks_enumerate_devices (const GUID * category) { GList *result = NULL; HDEVINFO devinfo; gint i; devinfo = SetupDiGetClassDevsW (category, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (!ks_is_valid_handle (devinfo)) return NULL; /* no devices */ for (i = 0;; i++) { BOOL success; SP_DEVICE_INTERFACE_DATA if_data = { 0, }; SP_DEVICE_INTERFACE_DETAIL_DATA_W *if_detail_data; DWORD if_detail_data_size; SP_DEVINFO_DATA devinfo_data = { 0, }; DWORD req_size; if_data.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); success = SetupDiEnumDeviceInterfaces (devinfo, NULL, category, i, &if_data); if (!success) /* all devices enumerated? */ break; if_detail_data_size = (MAX_PATH - 1) * sizeof (gunichar2); if_detail_data = g_malloc0 (if_detail_data_size); if_detail_data->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA_W); devinfo_data.cbSize = sizeof (SP_DEVINFO_DATA); success = SetupDiGetDeviceInterfaceDetailW (devinfo, &if_data, if_detail_data, if_detail_data_size, &req_size, &devinfo_data); if (success) { KsDeviceEntry *entry; WCHAR buf[512]; entry = g_new0 (KsDeviceEntry, 1); entry->index = i; entry->path = g_utf16_to_utf8 (if_detail_data->DevicePath, -1, NULL, NULL, NULL); if (SetupDiGetDeviceRegistryPropertyW (devinfo, &devinfo_data, SPDRP_FRIENDLYNAME, NULL, (BYTE *) buf, sizeof (buf), NULL)) { entry->name = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL); } if (entry->name == NULL) { if (SetupDiGetDeviceRegistryPropertyW (devinfo, &devinfo_data, SPDRP_DEVICEDESC, NULL, (BYTE *) buf, sizeof (buf), NULL)) { entry->name = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL); } } if (entry->name != NULL) result = g_list_prepend (result, entry); else ks_device_entry_free (entry); } g_free (if_detail_data); } SetupDiDestroyDeviceInfoList (devinfo); return g_list_reverse (result); }