Commit 617a4fd2 authored by Max Kellermann's avatar Max Kellermann

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.
parent 7475ded9
...@@ -230,4 +230,5 @@ const struct mixer_plugin alsa_mixer = { ...@@ -230,4 +230,5 @@ const struct mixer_plugin alsa_mixer = {
.close = alsa_mixer_close, .close = alsa_mixer_close,
.get_volume = alsa_mixer_get_volume, .get_volume = alsa_mixer_get_volume,
.set_volume = alsa_mixer_set_volume, .set_volume = alsa_mixer_set_volume,
.global = true,
}; };
...@@ -198,4 +198,5 @@ const struct mixer_plugin oss_mixer = { ...@@ -198,4 +198,5 @@ const struct mixer_plugin oss_mixer = {
.close = oss_mixer_close, .close = oss_mixer_close,
.get_volume = oss_mixer_get_volume, .get_volume = oss_mixer_get_volume,
.set_volume = oss_mixer_set_volume, .set_volume = oss_mixer_set_volume,
.global = true,
}; };
...@@ -27,4 +27,5 @@ mixer_init(struct mixer *mixer, const struct mixer_plugin *plugin) ...@@ -27,4 +27,5 @@ mixer_init(struct mixer *mixer, const struct mixer_plugin *plugin)
{ {
mixer->plugin = plugin; mixer->plugin = plugin;
mixer->mutex = g_mutex_new(); mixer->mutex = g_mutex_new();
mixer->open = false;
} }
...@@ -33,6 +33,11 @@ struct mixer { ...@@ -33,6 +33,11 @@ struct mixer {
* implementation, so plugins don't have to deal with that. * implementation, so plugins don't have to deal with that.
*/ */
GMutex *mutex; GMutex *mutex;
/**
* Is the mixer device currently open?
*/
bool open;
}; };
void void
......
...@@ -76,7 +76,12 @@ mixer_open(struct mixer *mixer) ...@@ -76,7 +76,12 @@ mixer_open(struct mixer *mixer)
assert(mixer->plugin != NULL); assert(mixer->plugin != NULL);
g_mutex_lock(mixer->mutex); 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); g_mutex_unlock(mixer->mutex);
return success; return success;
...@@ -89,10 +94,22 @@ mixer_close(struct mixer *mixer) ...@@ -89,10 +94,22 @@ mixer_close(struct mixer *mixer)
assert(mixer->plugin != NULL); assert(mixer->plugin != NULL);
g_mutex_lock(mixer->mutex); g_mutex_lock(mixer->mutex);
mixer->plugin->close(mixer);
if (mixer->open) {
mixer->plugin->close(mixer);
mixer->open = false;
}
g_mutex_unlock(mixer->mutex); g_mutex_unlock(mixer->mutex);
} }
void
mixer_auto_close(struct mixer *mixer)
{
if (!mixer->plugin->global)
mixer_close(mixer);
}
int int
mixer_get_volume(struct mixer *mixer) mixer_get_volume(struct mixer *mixer)
{ {
...@@ -100,8 +117,16 @@ mixer_get_volume(struct mixer *mixer) ...@@ -100,8 +117,16 @@ mixer_get_volume(struct mixer *mixer)
assert(mixer != NULL); assert(mixer != NULL);
if (mixer->plugin->global && !mixer_open(mixer))
return -1;
g_mutex_lock(mixer->mutex); 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); g_mutex_unlock(mixer->mutex);
return volume; return volume;
...@@ -114,8 +139,16 @@ mixer_set_volume(struct mixer *mixer, unsigned volume) ...@@ -114,8 +139,16 @@ mixer_set_volume(struct mixer *mixer, unsigned volume)
assert(mixer != NULL); assert(mixer != NULL);
if (mixer->plugin->global && !mixer_open(mixer))
return false;
g_mutex_lock(mixer->mutex); 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); g_mutex_unlock(mixer->mutex);
return success; return success;
......
...@@ -46,6 +46,13 @@ mixer_open(struct mixer *mixer); ...@@ -46,6 +46,13 @@ mixer_open(struct mixer *mixer);
void void
mixer_close(struct mixer *mixer); 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 int
mixer_get_volume(struct mixer *mixer); mixer_get_volume(struct mixer *mixer);
......
...@@ -68,6 +68,13 @@ struct mixer_plugin { ...@@ -68,6 +68,13 @@ struct mixer_plugin {
* @return true on success * @return true on success
*/ */
bool (*set_volume)(struct mixer *mixer, unsigned volume); 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 #endif
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "output_internal.h" #include "output_internal.h"
#include "output_thread.h" #include "output_thread.h"
#include "mixer_control.h" #include "mixer_control.h"
#include "mixer_plugin.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -149,7 +150,7 @@ void audio_output_close(struct audio_output *ao) ...@@ -149,7 +150,7 @@ void audio_output_close(struct audio_output *ao)
assert(!ao->open || ao->fail_timer == NULL); assert(!ao->open || ao->fail_timer == NULL);
if (ao->mixer != NULL) if (ao->mixer != NULL)
mixer_close(ao->mixer); mixer_auto_close(ao->mixer);
if (ao->open) if (ao->open)
ao_command(ao, AO_COMMAND_CLOSE); ao_command(ao, AO_COMMAND_CLOSE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment