[vlc-commits] aout: add proper event for device hotplug (refs #8248)

Rémi Denis-Courmont git at videolan.org
Sun Apr 14 10:51:34 CEST 2013


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Apr 14 11:13:13 2013 +0300| [51406fae40544f6b9181b7429fd018d0120c70f5] | committer: Rémi Denis-Courmont

aout: add proper event for device hotplug (refs #8248)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=51406fae40544f6b9181b7429fd018d0120c70f5
---

 include/vlc_aout.h               |   12 +++++
 src/audio_output/aout_internal.h |    8 ++++
 src/audio_output/output.c        |   95 ++++++++++++++++++++++++++++++++------
 3 files changed, 100 insertions(+), 15 deletions(-)

diff --git a/include/vlc_aout.h b/include/vlc_aout.h
index e660d47..eff26a8 100644
--- a/include/vlc_aout.h
+++ b/include/vlc_aout.h
@@ -178,6 +178,7 @@ struct audio_output
         void (*mute_report)(audio_output_t *, bool);
         void (*policy_report)(audio_output_t *, bool);
         void (*device_report)(audio_output_t *, const char *);
+        void (*hotplug_report)(audio_output_t *, const char *, const char *);
         int (*gain_request)(audio_output_t *, float);
         void (*restart_request)(audio_output_t *, unsigned);
     } event;
@@ -299,6 +300,17 @@ static inline void aout_DeviceReport(audio_output_t *aout, const char *id)
 }
 
 /**
+ * Report a device hot-plug event.
+ * @param id device ID
+ * @param name human-readable device name (NULL for hot unplug)
+ */
+static inline void aout_HotplugReport(audio_output_t *aout,
+                                      const char *id, const char *name)
+{
+    aout->event.hotplug_report(aout, id, name);
+}
+
+/**
  * Request a change of software audio amplification.
  * \param gain linear amplitude gain (must be positive)
  * \warning Values in excess 1.0 may cause overflow and distorsion.
diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index 93c828f..b45df53 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -45,6 +45,7 @@ typedef struct
 } aout_request_vout_t;
 
 typedef struct aout_volume aout_volume_t;
+typedef struct aout_dev aout_dev_t;
 
 typedef struct
 {
@@ -62,6 +63,13 @@ typedef struct
 
     struct
     {
+        vlc_mutex_t lock;
+        aout_dev_t *list;
+        unsigned count;
+    } dev;
+
+    struct
+    {
         mtime_t end; /**< Last seen PTS */
         unsigned resamp_start_drift; /**< Resampler drift absolute value */
         int resamp_type; /**< Resampler mode (FIXME: redundant / resampling) */
diff --git a/src/audio_output/output.c b/src/audio_output/output.c
index 2f92c11..84653c3 100644
--- a/src/audio_output/output.c
+++ b/src/audio_output/output.c
@@ -37,6 +37,14 @@
 
 static const char unset_str[1] = ""; /* Non-NULL constant string pointer */
 
+struct aout_dev
+{
+    aout_dev_t *next;
+    char *name;
+    char id[1];
+};
+
+
 /* Local functions */
 static void aout_OutputAssertLocked (audio_output_t *aout)
 {
@@ -86,6 +94,50 @@ static void aout_DeviceNotify (audio_output_t *aout, const char *id)
     var_SetString (aout, "device", (id != NULL) ? id : "");
 }
 
+static void aout_HotplugNotify (audio_output_t *aout,
+                                const char *id, const char *name)
+{
+    aout_owner_t *owner = aout_owner (aout);
+    aout_dev_t *dev, **pp = &owner->dev.list;
+
+    vlc_mutex_lock (&owner->dev.lock);
+    while ((dev = *pp) != NULL)
+    {
+        if (!strcmp (id, dev->id))
+            break;
+        pp = &dev->next;
+    }
+
+    if (name != NULL)
+    {
+        if (dev == NULL) /* Added device */
+        {
+            dev = malloc (sizeof (*dev) + strlen (id));
+            if (unlikely(dev == NULL))
+                goto out;
+            dev->next = NULL;
+            strcpy (dev->id, id);
+            *pp = dev;
+            owner->dev.count++;
+        }
+        else /* Modified device */
+            free (dev->name);
+        dev->name = strdup (name);
+    }
+    else
+    {
+        if (dev != NULL) /* Removed device */
+        {
+            owner->dev.count--;
+            *pp = dev->next;
+            free (dev->name);
+            free (dev);
+        }
+    }
+out:
+    vlc_mutex_unlock (&owner->dev.lock);
+}
+
 static void aout_RestartNotify (audio_output_t *aout, unsigned mode)
 {
     aout_RequestRestart (aout, mode);
@@ -118,6 +170,7 @@ audio_output_t *aout_New (vlc_object_t *parent)
 
     vlc_mutex_init (&owner->lock);
     vlc_mutex_init (&owner->req.lock);
+    vlc_mutex_init (&owner->dev.lock);
     owner->req.device = (char *)unset_str;
     owner->req.volume = -1.f;
     owner->req.mute = -1;
@@ -133,8 +186,9 @@ audio_output_t *aout_New (vlc_object_t *parent)
 
     aout->event.volume_report = aout_VolumeNotify;
     aout->event.mute_report = aout_MuteNotify;
-    aout->event.device_report = aout_DeviceNotify;
     aout->event.policy_report = aout_PolicyNotify;
+    aout->event.device_report = aout_DeviceNotify;
+    aout->event.hotplug_report = aout_HotplugNotify;
     aout->event.gain_request = aout_GainNotify;
     aout->event.restart_request = aout_RestartNotify;
 
@@ -143,7 +197,6 @@ audio_output_t *aout_New (vlc_object_t *parent)
     aout->stop = NULL;
     aout->volume_set = NULL;
     aout->mute_set = NULL;
-    aout->device_enum = NULL;
     aout->device_select = NULL;
     owner->module = module_need (aout, "audio output", "$aout", false);
     if (owner->module == NULL)
@@ -277,6 +330,14 @@ static void aout_Destructor (vlc_object_t *obj)
     audio_output_t *aout = (audio_output_t *)obj;
     aout_owner_t *owner = aout_owner (aout);
 
+    vlc_mutex_destroy (&owner->dev.lock);
+    for (aout_dev_t *dev = owner->dev.list, *next; dev != NULL; dev = next)
+    {
+        next = dev->next;
+        free (dev->name);
+        free (dev);
+    }
+
     assert (owner->req.device == unset_str);
     vlc_mutex_destroy (&owner->req.lock);
     vlc_mutex_destroy (&owner->lock);
@@ -461,14 +522,6 @@ static int aout_OutputDeviceSet (audio_output_t *aout, const char *id)
     return (aout->device_select != NULL) ? aout->device_select (aout, id) : -1;
 }
 
-static int aout_OutputDevicesEnum (audio_output_t *aout,
-                                   char ***ids, char ***names)
-{
-    aout_OutputAssertLocked (aout);
-    return (aout->device_enum != NULL) ? aout->device_enum (aout, ids, names)
-                                       : -1;
-}
-
 void aout_OutputLock (audio_output_t *aout)
 {
     aout_owner_t *owner = aout_owner (aout);
@@ -624,10 +677,22 @@ int aout_DeviceSet (audio_output_t *aout, const char *id)
  */
 int aout_DevicesList (audio_output_t *aout, char ***ids, char ***names)
 {
-    int ret;
+    aout_owner_t *owner = aout_owner (aout);
+    char **tabid, **tabname;
+    unsigned count;
+
+    vlc_mutex_lock (&owner->dev.lock);
+    count = owner->dev.count;
+    tabid = xmalloc (sizeof (*tabid) * count);
+    tabname = xmalloc (sizeof (*tabname) * count);
+    *ids = tabid;
+    *names = tabname;
+    for (aout_dev_t *dev = owner->dev.list; dev != NULL; dev = dev->next)
+    {
+        *(tabid++) = xstrdup (dev->id);
+        *(tabname++) = xstrdup (dev->name);
+    }
+    vlc_mutex_unlock (&owner->dev.lock);
 
-    aout_OutputLock (aout);
-    ret = aout_OutputDevicesEnum (aout, ids, names);
-    aout_OutputUnlock (aout);
-    return ret;
+    return count;
 }



More information about the vlc-commits mailing list