aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-03-26 19:43:18 +0100
committerMax Kellermann <max@duempel.org>2009-03-26 19:43:18 +0100
commit617a4fd2d2eff45393c4e243129a4648822d5d86 (patch)
tree0b11f58f1dd145a273378e31a5ba8506251abe97
parent7475ded935a00d790d4e97ecf55f4fb3306d80fb (diff)
downloadmpd-617a4fd2d2eff45393c4e243129a4648822d5d86.tar.gz
mpd-617a4fd2d2eff45393c4e243129a4648822d5d86.tar.xz
mpd-617a4fd2d2eff45393c4e243129a4648822d5d86.zip
mixer: added flag "open"
Remember if a mixer object is open or closed. Don't call open() again if it is already open. This guarantees that the mixer plugin is always called in a consistent state, and we will be able to remove lots of checks from the implementations. To support mixers which are automatically opened even if the audio output is still closed (to set the volume before playback starts), this patch also adds the "global" flag to the mixer_plugin struct. Both ALSA and OSS set this flag, while PULSE does not.
-rw-r--r--src/mixer/alsa_mixer.c1
-rw-r--r--src/mixer/oss_mixer.c1
-rw-r--r--src/mixer_api.c1
-rw-r--r--src/mixer_api.h5
-rw-r--r--src/mixer_control.c41
-rw-r--r--src/mixer_control.h7
-rw-r--r--src/mixer_plugin.h7
-rw-r--r--src/output_control.c3
8 files changed, 61 insertions, 5 deletions
diff --git a/src/mixer/alsa_mixer.c b/src/mixer/alsa_mixer.c
index ea113b861..c5aac13d4 100644
--- a/src/mixer/alsa_mixer.c
+++ b/src/mixer/alsa_mixer.c
@@ -230,4 +230,5 @@ const struct mixer_plugin alsa_mixer = {
.close = alsa_mixer_close,
.get_volume = alsa_mixer_get_volume,
.set_volume = alsa_mixer_set_volume,
+ .global = true,
};
diff --git a/src/mixer/oss_mixer.c b/src/mixer/oss_mixer.c
index 8789ac00c..13e325823 100644
--- a/src/mixer/oss_mixer.c
+++ b/src/mixer/oss_mixer.c
@@ -198,4 +198,5 @@ const struct mixer_plugin oss_mixer = {
.close = oss_mixer_close,
.get_volume = oss_mixer_get_volume,
.set_volume = oss_mixer_set_volume,
+ .global = true,
};
diff --git a/src/mixer_api.c b/src/mixer_api.c
index aaa250d33..50bf8c1b1 100644
--- a/src/mixer_api.c
+++ b/src/mixer_api.c
@@ -27,4 +27,5 @@ mixer_init(struct mixer *mixer, const struct mixer_plugin *plugin)
{
mixer->plugin = plugin;
mixer->mutex = g_mutex_new();
+ mixer->open = false;
}
diff --git a/src/mixer_api.h b/src/mixer_api.h
index 9af49cd87..344d04453 100644
--- a/src/mixer_api.h
+++ b/src/mixer_api.h
@@ -33,6 +33,11 @@ struct mixer {
* implementation, so plugins don't have to deal with that.
*/
GMutex *mutex;
+
+ /**
+ * Is the mixer device currently open?
+ */
+ bool open;
};
void
diff --git a/src/mixer_control.c b/src/mixer_control.c
index f1d67a078..4e86a9aa2 100644
--- a/src/mixer_control.c
+++ b/src/mixer_control.c
@@ -76,7 +76,12 @@ mixer_open(struct mixer *mixer)
assert(mixer->plugin != NULL);
g_mutex_lock(mixer->mutex);
- success = mixer->plugin->open(mixer);
+
+ if (mixer->open)
+ success = true;
+ else
+ success = mixer->open = mixer->plugin->open(mixer);
+
g_mutex_unlock(mixer->mutex);
return success;
@@ -89,10 +94,22 @@ mixer_close(struct mixer *mixer)
assert(mixer->plugin != NULL);
g_mutex_lock(mixer->mutex);
- mixer->plugin->close(mixer);
+
+ if (mixer->open) {
+ mixer->plugin->close(mixer);
+ mixer->open = false;
+ }
+
g_mutex_unlock(mixer->mutex);
}
+void
+mixer_auto_close(struct mixer *mixer)
+{
+ if (!mixer->plugin->global)
+ mixer_close(mixer);
+}
+
int
mixer_get_volume(struct mixer *mixer)
{
@@ -100,8 +117,16 @@ mixer_get_volume(struct mixer *mixer)
assert(mixer != NULL);
+ if (mixer->plugin->global && !mixer_open(mixer))
+ return -1;
+
g_mutex_lock(mixer->mutex);
- volume = mixer->plugin->get_volume(mixer);
+
+ if (mixer->open) {
+ volume = mixer->plugin->get_volume(mixer);
+ } else
+ volume = -1;
+
g_mutex_unlock(mixer->mutex);
return volume;
@@ -114,8 +139,16 @@ mixer_set_volume(struct mixer *mixer, unsigned volume)
assert(mixer != NULL);
+ if (mixer->plugin->global && !mixer_open(mixer))
+ return false;
+
g_mutex_lock(mixer->mutex);
- success = mixer->plugin->set_volume(mixer, volume);
+
+ if (mixer->open) {
+ success = mixer->plugin->set_volume(mixer, volume);
+ } else
+ success = false;
+
g_mutex_unlock(mixer->mutex);
return success;
diff --git a/src/mixer_control.h b/src/mixer_control.h
index b126d8c81..0f73e8f75 100644
--- a/src/mixer_control.h
+++ b/src/mixer_control.h
@@ -46,6 +46,13 @@ mixer_open(struct mixer *mixer);
void
mixer_close(struct mixer *mixer);
+/**
+ * Close the mixer unless the plugin's "global" flag is set. This is
+ * called when the #audio_output is closed.
+ */
+void
+mixer_auto_close(struct mixer *mixer);
+
int
mixer_get_volume(struct mixer *mixer);
diff --git a/src/mixer_plugin.h b/src/mixer_plugin.h
index 8e9bb5804..2b9b440e5 100644
--- a/src/mixer_plugin.h
+++ b/src/mixer_plugin.h
@@ -68,6 +68,13 @@ struct mixer_plugin {
* @return true on success
*/
bool (*set_volume)(struct mixer *mixer, unsigned volume);
+
+ /**
+ * If true, then the mixer is automatically opened, even if
+ * its audio output is not open. If false, then the mixer is
+ * disabled as long as its audio output is closed.
+ */
+ bool global;
};
#endif
diff --git a/src/output_control.c b/src/output_control.c
index d19ce3583..4131594f0 100644
--- a/src/output_control.c
+++ b/src/output_control.c
@@ -22,6 +22,7 @@
#include "output_internal.h"
#include "output_thread.h"
#include "mixer_control.h"
+#include "mixer_plugin.h"
#include <assert.h>
#include <stdlib.h>
@@ -149,7 +150,7 @@ void audio_output_close(struct audio_output *ao)
assert(!ao->open || ao->fail_timer == NULL);
if (ao->mixer != NULL)
- mixer_close(ao->mixer);
+ mixer_auto_close(ao->mixer);
if (ao->open)
ao_command(ao, AO_COMMAND_CLOSE);