]> Pileus Git - ~andy/linux/blobdiff - sound/core/vmaster.c
ALSA: Add a hook capability to vmaster controls
[~andy/linux] / sound / core / vmaster.c
index 130cfe677d60a1ef8bf996c0a61bc0dea35a9da6..14a286a7bf2b01686e450b2a3bc258df59f24e21 100644 (file)
@@ -37,6 +37,8 @@ struct link_master {
        struct link_ctl_info info;
        int val;                /* the master value */
        unsigned int tlv[4];
+       void (*hook)(void *private_data, int);
+       void *hook_private_data;
 };
 
 /*
@@ -126,7 +128,9 @@ static int master_init(struct link_master *master)
                master->info.count = 1; /* always mono */
                /* set full volume as default (= no attenuation) */
                master->val = master->info.max_val;
-               return 0;
+               if (master->hook)
+                       master->hook(master->hook_private_data, master->val);
+               return 1;
        }
        return -ENOENT;
 }
@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol,
                slave_put_val(slave, uval);
        }
        kfree(uval);
+       if (master->hook && !err)
+               master->hook(master->hook_private_data, master->val);
        return 1;
 }
 
@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
        return kctl;
 }
 EXPORT_SYMBOL(snd_ctl_make_virtual_master);
+
+/**
+ * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
+ * @kcontrol: vmaster kctl element
+ * @hook: the hook function
+ *
+ * Adds the given hook to the vmaster control element so that it's called
+ * at each time when the value is changed.
+ */
+int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
+                            void (*hook)(void *private_data, int),
+                            void *private_data)
+{
+       struct link_master *master = snd_kcontrol_chip(kcontrol);
+       master->hook = hook;
+       master->hook_private_data = private_data;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
+
+/**
+ * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
+ * @kcontrol: vmaster kctl element
+ *
+ * Call the hook function to synchronize with the current value of the given
+ * vmaster element.  NOP when NULL is passed to @kcontrol or the hook doesn't
+ * exist.
+ */
+void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
+{
+       struct link_master *master;
+       if (!kcontrol)
+               return;
+       master = snd_kcontrol_chip(kcontrol);
+       if (master->hook)
+               master->hook(master->hook_private_data, master->val);
+}
+EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);