get_media_devices: Use a more generic way to get associated devices
authorMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 28 May 2011 16:13:01 +0000 (13:13 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 28 May 2011 16:13:01 +0000 (13:13 -0300)
Instead of having a method that works just for alsa, extend them
to be generic enough to show all types of devices.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
utils/libmedia_dev/get_media_devices.c
utils/libmedia_dev/get_media_devices.h
utils/v4l2-sysfs-path/v4l2-sysfs-path.c

index ef6f303..16dff1d 100644 (file)
@@ -27,6 +27,7 @@
 
 static char *device_type_str[] = {
        [UNKNOWN]       = "unknown",
+       [NONE]          = "none",
        [V4L_VIDEO]     = "video",
        [V4L_VBI]       = "vbi",
        [DVB_FRONTEND]  = "dvb frontend",
@@ -313,69 +314,75 @@ void display_media_devices(void *opaque)
        printf("\n");
 }
 
-char *get_first_alsa_cap_device(void *opaque, char *v4l_device)
+char *get_associated_device(void *opaque,
+                           char *last_seek,
+                           enum device_type desired_type,
+                           char *seek_device,
+                           enum device_type seek_type)
 {
        struct media_devices *md = opaque;
        struct media_device_entry *md_ptr = md->md_entry;
        int i;
        char *prev;
-       char p = strrchr(v4l_device, '/');
+       char *p = strrchr(seek_device, '/');
 
        /* Get just the device name */
        if (p)
-               v4l_device = p + 1;
+               seek_device = p + 1;
 
-       /* Step 1: Find the V4L node */
-       for (i = 0; i < md->md_size; i++, md_ptr++) {
-               if (md_ptr->type == V4L_VIDEO) {
-                       if (!strcmp(v4l_device,  md_ptr->node))
+       if (seek_type != NONE && seek_device[0]) {
+               /* Step 1: Find the seek node */
+               for (i = 0; i < md->md_size; i++, md_ptr++) {
+                       if (md_ptr->type == seek_type &&
+                           !strcmp(seek_device, md_ptr->node))
                                break;
                }
-       }
-       if (i == md->md_size)
-               return NULL;
+               if (i == md->md_size)
+                       return NULL;
+               i++;
+       } else
+               i = 0;
 
-       /* Step 2: find the alsa node */
+       /* Step 2: find the associated node */
        prev = md_ptr->device;
        md_ptr++;
-       for (i++;i < md->md_size && !strcmp(prev,md_ptr->device); i++) {
-               if (md_ptr->type == SND_CAP)
+       for (;i < md->md_size && !strcmp(prev,md_ptr->device); i++, md_ptr++) {
+               if (last_seek && !strcmp(md_ptr->node, last_seek))
+                       break;
+               if (md_ptr->type == desired_type)
                        return md_ptr->node;
-               md_ptr++;
        }
 
        return NULL;
 }
 
-char *get_first_no_video_out_device(void *opaque)
+char *get_not_associated_device(void *opaque,
+                           char *last_seek,
+                           enum device_type desired_type,
+                           enum device_type not_desired_type)
 {
        struct media_devices *md = opaque;
        struct media_device_entry *md_ptr = md->md_entry;
        int i, skip = 0;
-       char *prev = "";
+       char *prev = "", *result = NULL;
 
-       /* Step 1: Find a device without video4linux node */
+       /* Step 1: Find a device without seek_type node */
        for (i = 0; i < md->md_size; i++, md_ptr++) {
-               if (md_ptr->type == V4L_VIDEO)
-                       skip = 1;
-               else if (strcmp(prev, md_ptr->device)) {
+               if (strcmp(prev, md_ptr->device)) {
+                       if (!skip && result)
+                               break;
                        prev = md_ptr->device;
                        skip = 0;
+                       result = NULL;
+               }
+               if (md_ptr->type == not_desired_type) {
+                       skip = 1;
+               } else if (!skip && !result && md_ptr->type == desired_type) {
+                       result = md_ptr->node;
                }
-               if (!skip && md_ptr->type == SND_OUT)
-                       return md_ptr->node;
-       }
-
-       /*
-        * Step 2: Fallback: Find any alsa out node. Useful if a machine
-        * doesn't have an internal board, but an USB device like the
-        * Sirius webcam also provides an alsa output node
-        */
-       md_ptr = md->md_entry;
-       for (i = 0; i < md->md_size; i++, md++) {
-               if (!skip && md_ptr->type == SND_OUT)
-                       return md_ptr->node;
        }
+       if (skip)
+               result = NULL;
 
-       return NULL;
+       return result;
 }
index 0d3e809..aace262 100644 (file)
@@ -20,7 +20,7 @@
 /*
  * Version of the API
  */
-#define GET_MEDIA_DEVICES_VERSION      0x0101
+#define GET_MEDIA_DEVICES_VERSION      0x0102
 
 /*
  A typical usecase for the above API is:
@@ -55,6 +55,7 @@ Where alsa_handler() is some function that will need to handle
  */
 enum device_type {
        UNKNOWN = 65535,
+       NONE    = 65534,
        V4L_VIDEO = 0,
        V4L_VBI,
        DVB_FRONTEND,
@@ -102,38 +103,42 @@ void free_media_devices(void *opaque);
 void display_media_devices(void *opaque);
 
 /**
- * get_first_alsa_cap_device() - Gets the first alsa capture device for a
- *                              video node
+ * get_not_associated_device() - Return the next device not associated with
+ *                              an specific device type.
  *
- * @opaque:    media devices opaque descriptor
+ * @opaque:            media devices opaque descriptor
+ * @last_seek:         last seek result. Use NULL to get the first result
+ * @desired_type:      type of the desired device
+ * @not_desired_type:  type of the seek device
  *
- * This function seeks inside the media_devices struct for the first alsa
- * capture device (SND_CAP) that belongs to the same device where the video
- * node exists. The video node should belong to V4L_VIDEO type (video0,
- * video1, etc).
+ * This function seeks inside the media_devices struct for the next physical
+ * device that doesn't support a non_desired type.
+ * This method is useful for example to return the audio devices that are
+ * provided by the motherboard.
  */
-char *get_first_alsa_cap_device(void *opaque, char *v4l_device);
-
-/**
- * get_first_no_video_out_device() - Gets the first alsa playback device
- *                                  that is not associated to a video device.
- *
- * @opaque:    media devices opaque descriptor
- *
- * This function seeks inside the media_devices struct for the first alsa
- * playback device (SND_OUT) that is not associated to a video device.
- * The returned value is at the format expected by alsa libraries (like hw:0,0)
- *
- * If there's no playback device that are not associated to a video device,
- * the routine falls back to any existing audio playback device. This is useful
- * in the cases where there's no audio sound device on a system, and an external
- * USB device that provides both video and audio playback is connected.
+char *get_associated_device(void *opaque,
+                           char *last_seek,
+                           enum device_type desired_type,
+                           char *seek_device,
+                           enum device_type seek_type);
+
+                           /**
+ * get_associated_device() - Return the next device associated with another one
  *
- * Note that, as the devices are ordered by the devices ID, this routine
- * may not return hw:0,0. That's OK, as, if the media card is probed before
- * the audio card, the media card will receive the lowest address.
+ * @opaque:            media devices opaque descriptor
+ * @last_seek:         last seek result. Use NULL to get the first result
+ * @desired_type:      type of the desired device
+ * @seek_device:       name of the device with you want to get an association.
+ *@ seek_type:         type of the seek device. Using NONE produces the same
+ *                     result of using NULL for the seek_device.
  *
- * In general, it will return the alsa device for the default audio playback
- * device.
+ * This function seeks inside the media_devices struct for the next device
+ * that it is associated with a seek parameter.
+ * It can be used to get an alsa device associated with a video device. If
+ * the seek_device is NULL or seek_type is NONE, it will just search for
+ * devices of the desired_type.
  */
-char *get_first_no_video_out_device(void *opaque);
+char *get_not_associated_device(void *opaque,
+                           char *last_seek,
+                           enum device_type desired_type,
+                           enum device_type not_desired_type);
index 4b38566..3ba446d 100644 (file)
@@ -35,11 +35,11 @@ int main(void)
        md = discover_media_devices();
        display_media_devices(md);
 
-       alsa = get_first_alsa_cap_device(md, "video0");
+       alsa = get_associated_device(md, NULL, SND_CAP, "video0", V4L_VIDEO);
        if (alsa)
                printf("Alsa device associated with video0 capture: %s\n", alsa);
 
-       alsa = get_first_no_video_out_device(md);
+       alsa = get_not_associated_device(md, NULL, SND_OUT, V4L_VIDEO);
        if (alsa)
                printf("Alsa output device: %s\n", alsa);