mixer: protect the mixer struct with a mutex
In some rare cases, there was a race condition between the output thread and the main thread: when you disable/enable an output device in the main thread, this caused a crash in the output thread. Protect the whole mixer struct with a GMutex to prevent that.
This commit is contained in:
parent
82963ee023
commit
7deade8577
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "mixer_api.h"
|
#include "mixer_api.h"
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#undef G_LOG_DOMAIN
|
#undef G_LOG_DOMAIN
|
||||||
#define G_LOG_DOMAIN "mixer"
|
#define G_LOG_DOMAIN "mixer"
|
||||||
|
|
||||||
@ -28,4 +26,5 @@ void
|
|||||||
mixer_init(struct mixer *mixer, const struct mixer_plugin *plugin)
|
mixer_init(struct mixer *mixer, const struct mixer_plugin *plugin)
|
||||||
{
|
{
|
||||||
mixer->plugin = plugin;
|
mixer->plugin = plugin;
|
||||||
|
mixer->mutex = g_mutex_new();
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,16 @@
|
|||||||
#include "mixer_plugin.h"
|
#include "mixer_plugin.h"
|
||||||
#include "mixer_list.h"
|
#include "mixer_list.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
struct mixer {
|
struct mixer {
|
||||||
const struct mixer_plugin *plugin;
|
const struct mixer_plugin *plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mutex protects all of the mixer struct, including its
|
||||||
|
* implementation, so plugins don't have to deal with that.
|
||||||
|
*/
|
||||||
|
GMutex *mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -62,6 +62,9 @@ mixer_free(struct mixer *mixer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(mixer->plugin != NULL);
|
assert(mixer->plugin != NULL);
|
||||||
|
assert(mixer->mutex != NULL);
|
||||||
|
|
||||||
|
g_mutex_free(mixer->mutex);
|
||||||
|
|
||||||
mixer->plugin->finish(mixer);
|
mixer->plugin->finish(mixer);
|
||||||
}
|
}
|
||||||
@ -69,11 +72,18 @@ mixer_free(struct mixer *mixer)
|
|||||||
bool
|
bool
|
||||||
mixer_open(struct mixer *mixer)
|
mixer_open(struct mixer *mixer)
|
||||||
{
|
{
|
||||||
|
bool success;
|
||||||
|
|
||||||
if (!mixer) {
|
if (!mixer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(mixer->plugin != NULL);
|
assert(mixer->plugin != NULL);
|
||||||
return mixer->plugin->open(mixer);
|
|
||||||
|
g_mutex_lock(mixer->mutex);
|
||||||
|
success = mixer->plugin->open(mixer);
|
||||||
|
g_mutex_unlock(mixer->mutex);
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -83,17 +93,32 @@ mixer_close(struct mixer *mixer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(mixer->plugin != NULL);
|
assert(mixer->plugin != NULL);
|
||||||
|
|
||||||
|
g_mutex_lock(mixer->mutex);
|
||||||
mixer->plugin->close(mixer);
|
mixer->plugin->close(mixer);
|
||||||
|
g_mutex_unlock(mixer->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
mixer_get_volume(struct mixer *mixer)
|
mixer_get_volume(struct mixer *mixer)
|
||||||
{
|
{
|
||||||
return mixer->plugin->get_volume(mixer);
|
int volume;
|
||||||
|
|
||||||
|
g_mutex_lock(mixer->mutex);
|
||||||
|
volume = mixer->plugin->get_volume(mixer);
|
||||||
|
g_mutex_unlock(mixer->mutex);
|
||||||
|
|
||||||
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mixer_set_volume(struct mixer *mixer, unsigned volume)
|
mixer_set_volume(struct mixer *mixer, unsigned volume)
|
||||||
{
|
{
|
||||||
return mixer->plugin->set_volume(mixer, volume);
|
bool success;
|
||||||
|
|
||||||
|
g_mutex_lock(mixer->mutex);
|
||||||
|
success = mixer->plugin->set_volume(mixer, volume);
|
||||||
|
g_mutex_unlock(mixer->mutex);
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user