summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2012-10-31 15:21:04 +0100
committerPaul Kocialkowski <contact@paulk.fr>2012-10-31 15:21:04 +0100
commit3660b5ae8d6bcd134072aae742b5682f40a96573 (patch)
tree8e29c6f5dd5be3748bd1d3d1e9ba319caba7f611
parent07f20ab0fd9089a1b5c97a9bcbec1df5979f318e (diff)
downloadhardware_tinyalsa-audio-3660b5ae8d6bcd134072aae742b5682f40a96573.zip
hardware_tinyalsa-audio-3660b5ae8d6bcd134072aae742b5682f40a96573.tar.gz
hardware_tinyalsa-audio-3660b5ae8d6bcd134072aae742b5682f40a96573.tar.bz2
Use mutexes to make audio thread-proof
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r--audio_hw.c31
-rw-r--r--audio_hw.h6
-rw-r--r--audio_in.c59
-rw-r--r--audio_out.c64
-rw-r--r--audio_ril_interface.c41
-rw-r--r--audio_ril_interface.h2
6 files changed, 181 insertions, 22 deletions
diff --git a/audio_hw.c b/audio_hw.c
index cfe4058..63a9303 100644
--- a/audio_hw.c
+++ b/audio_hw.c
@@ -90,6 +90,8 @@ static int audio_hw_set_voice_volume(struct audio_hw_device *dev, float volume)
return -1;
if(volume != device->voice_volume) {
+ pthread_mutex_lock(&device->lock);
+
if(device->mode == AUDIO_MODE_IN_CALL) {
if(device->ril_interface != NULL)
device_modem = device->ril_interface->device_current;
@@ -106,6 +108,8 @@ static int audio_hw_set_voice_volume(struct audio_hw_device *dev, float volume)
}
device->voice_volume = volume;
+
+ pthread_mutex_unlock(&device->lock);
}
return 0;
@@ -125,7 +129,9 @@ static int audio_hw_set_master_volume(struct audio_hw_device *dev, float volume)
if(device->mixer == NULL)
return -1;
+ pthread_mutex_lock(&device->lock);
tinyalsa_mixer_set_master_volume(device->mixer, volume);
+ pthread_mutex_unlock(&device->lock);
return 0;
}
@@ -145,6 +151,8 @@ static int audio_hw_set_mode(struct audio_hw_device *dev, int mode)
device = (struct tinyalsa_audio_device *) dev;
if(mode != device->mode) {
+ pthread_mutex_lock(&device->lock);
+
if(mode == AUDIO_MODE_IN_CALL) {
tinyalsa_mixer_set_modem_state(device->mixer, 1);
@@ -187,6 +195,8 @@ static int audio_hw_set_mode(struct audio_hw_device *dev, int mode)
}
device->mode = mode;
+
+ pthread_mutex_unlock(&device->lock);
}
return 0;
@@ -208,6 +218,8 @@ static int audio_hw_set_mic_mute(struct audio_hw_device *dev, bool state)
return -1;
if(device->mic_mute != state) {
+ pthread_mutex_lock(&device->lock);
+
if(device->mode == AUDIO_MODE_IN_CALL) {
if(device->ril_interface != NULL)
device_modem = device->ril_interface->device_current;
@@ -229,6 +241,8 @@ static int audio_hw_set_mic_mute(struct audio_hw_device *dev, bool state)
}
device->mic_mute = state;
+
+ pthread_mutex_unlock(&device->lock);
}
return 0;
@@ -279,16 +293,27 @@ static int audio_hw_set_parameters(struct audio_hw_device *dev,
value = atoi(value_string);
+ pthread_mutex_lock(&device->lock);
+
if(audio_is_output_device((audio_devices_t) value)) {
- if(device->stream_out != NULL && device->stream_out->device_current != (audio_devices_t) value)
+ if(device->stream_out != NULL && device->stream_out->device_current != (audio_devices_t) value) {
+ pthread_mutex_lock(&device->stream_out->lock);
audio_out_set_route(device->stream_out, (audio_devices_t) value);
- if(device->ril_interface != NULL && device->ril_interface->device_current != (audio_devices_t) value)
+ pthread_mutex_unlock(&device->stream_out->lock);
+ }
+ if(device->ril_interface != NULL && device->ril_interface->device_current != (audio_devices_t) value) {
audio_ril_interface_set_route(device->ril_interface, (audio_devices_t) value);
+ }
} else if(audio_is_input_device((audio_devices_t) value)) {
- if(device->stream_in != NULL && device->stream_in->device_current != (audio_devices_t) value)
+ if(device->stream_in != NULL && device->stream_in->device_current != (audio_devices_t) value) {
+ pthread_mutex_lock(&device->stream_in->lock);
audio_in_set_route(device->stream_in, (audio_devices_t) value);
+ pthread_mutex_unlock(&device->stream_in->lock);
+ }
}
+ pthread_mutex_unlock(&device->lock);
+
str_parms_destroy(parms);
return 0;
diff --git a/audio_hw.h b/audio_hw.h
index a06ef9b..d0be2a1 100644
--- a/audio_hw.h
+++ b/audio_hw.h
@@ -47,6 +47,8 @@ struct tinyalsa_audio_stream_out {
struct pcm *pcm;
int standby;
+
+ pthread_mutex_t lock;
};
struct tinyalsa_audio_stream_in {
@@ -67,6 +69,8 @@ struct tinyalsa_audio_stream_in {
struct pcm *pcm;
int standby;
+
+ pthread_mutex_t lock;
};
struct tinyalsa_audio_device {
@@ -85,6 +89,8 @@ struct tinyalsa_audio_device {
float voice_volume;
int mic_mute;
+
+ pthread_mutex_t lock;
};
int audio_out_set_route(struct tinyalsa_audio_stream_out *stream_out,
diff --git a/audio_in.c b/audio_in.c
index 3933bbf..618daf1 100644
--- a/audio_in.c
+++ b/audio_in.c
@@ -99,9 +99,10 @@ int audio_in_set_route(struct tinyalsa_audio_stream_in *stream_in,
stream_in->device_current = device;
- if(device == 0)
+ if(device == 0) {
+ pthread_mutex_unlock(&stream_in->lock);
return stream_in->stream.common.standby((struct audio_stream *) stream_in);
-
+ }
tinyalsa_mixer_set_device(stream_in->device->mixer, stream_in->device_current);
@@ -363,6 +364,8 @@ static int audio_in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
stream_in = (struct tinyalsa_audio_stream_in *) stream;
if(stream_in->rate != (int) rate) {
+ pthread_mutex_lock(&stream_in->lock);
+
stream_in->rate = rate;
if(stream_in->rate != stream_in->mixer_props->rate) {
@@ -371,6 +374,8 @@ static int audio_in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
stream_in->standby = 1;
}
+
+ pthread_mutex_unlock(&stream_in->lock);
}
return 0;
@@ -430,10 +435,14 @@ static int audio_in_set_format(struct audio_stream *stream, int format)
stream_in = (struct tinyalsa_audio_stream_in *) stream;
if(stream_in->format != (audio_format_t) format) {
+ pthread_mutex_lock(&stream_in->lock);
+
stream_in->format = format;
if(stream_in->format != stream_in->mixer_props->format)
stream_in->standby = 1;
+
+ pthread_mutex_unlock(&stream_in->lock);
}
return 0;
@@ -451,6 +460,8 @@ static int audio_in_standby(struct audio_stream *stream)
stream_in = (struct tinyalsa_audio_stream_in *) stream;
+ pthread_mutex_lock(&stream_in->lock);
+
if(stream_in->pcm != NULL)
audio_in_pcm_close(stream_in);
@@ -465,6 +476,8 @@ static int audio_in_standby(struct audio_stream *stream)
stream_in->standby = 1;
+ pthread_mutex_unlock(&stream_in->lock);
+
return 0;
}
@@ -503,8 +516,15 @@ static int audio_in_set_parameters(struct audio_stream *stream, const char *kvpa
value = atoi(value_string);
- if(stream_in->device_current != (audio_devices_t) value)
+ pthread_mutex_lock(&stream_in->device->lock);
+
+ if(stream_in->device_current != (audio_devices_t) value) {
+ pthread_mutex_lock(&stream_in->lock);
audio_in_set_route(stream_in, (audio_devices_t) value);
+ pthread_mutex_unlock(&stream_in->lock);
+ }
+
+ pthread_mutex_unlock(&stream_in->device->lock);
str_parms_destroy(parms);
@@ -538,8 +558,10 @@ static int audio_in_set_gain(struct audio_stream_in *stream, float gain)
if(stream_in->device == NULL || stream_in->device->mixer == NULL)
return -1;
+ pthread_mutex_lock(&stream_in->device->lock);
tinyalsa_mixer_set_input_gain(stream_in->device->mixer,
stream_in->device_current, gain);
+ pthread_mutex_unlock(&stream_in->device->lock);
return 0;
}
@@ -555,6 +577,11 @@ static ssize_t audio_in_read(struct audio_stream_in *stream,
stream_in = (struct tinyalsa_audio_stream_in *) stream;
+ if(stream_in->device == NULL)
+ return -1;
+
+ pthread_mutex_lock(&stream_in->lock);
+
if(stream_in->standby) {
#ifdef YAMAHA_MC1N2_AUDIO
rc = yamaha_mc1n2_audio_input_start(stream_in->device->mc1n2_pdata);
@@ -566,7 +593,7 @@ static ssize_t audio_in_read(struct audio_stream_in *stream,
rc = audio_in_pcm_open(stream_in);
if(rc < 0) {
LOGE("Unable to open pcm device");
- return -1;
+ goto error;
}
stream_in->standby = 0;
@@ -575,13 +602,20 @@ static ssize_t audio_in_read(struct audio_stream_in *stream,
rc = audio_in_read_process(stream_in, buffer, (int) bytes);
if(rc < 0) {
LOGE("Read and process failed!");
- return -1;
+ goto error;
}
if(stream_in->device != NULL && stream_in->device->mic_mute)
memset(buffer, 0, bytes);
+ pthread_mutex_unlock(&stream_in->lock);
+
return bytes;
+
+error:
+ pthread_mutex_unlock(&stream_in->lock);
+
+ return -1;
}
static uint32_t audio_in_get_input_frames_lost(struct audio_stream_in *stream)
@@ -633,9 +667,12 @@ void audio_hw_close_input_stream(struct audio_hw_device *dev,
tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev;
- tinyalsa_mixer_set_input_state(tinyalsa_audio_device->mixer, 0);
+ pthread_mutex_lock(&tinyalsa_audio_device->lock);
+ tinyalsa_mixer_set_input_state(tinyalsa_audio_device->mixer, 0);
tinyalsa_audio_device->stream_in = NULL;
+
+ pthread_mutex_unlock(&tinyalsa_audio_device->lock);
}
int audio_hw_open_input_stream(struct audio_hw_device *dev,
@@ -729,17 +766,25 @@ int audio_hw_open_input_stream(struct audio_hw_device *dev,
*channels = (uint32_t) tinyalsa_audio_stream_in->channels;
*format = (uint32_t) tinyalsa_audio_stream_in->format;
+ pthread_mutex_lock(&tinyalsa_audio_device->lock);
+
rc = tinyalsa_mixer_set_input_state(tinyalsa_audio_device->mixer, 1);
if(rc < 0) {
LOGE("Unable to set input state");
+ pthread_mutex_unlock(&tinyalsa_audio_device->lock);
goto error_stream;
}
+ pthread_mutex_lock(&tinyalsa_audio_stream_in->lock);
+
audio_in_set_route(tinyalsa_audio_stream_in, devices);
+ pthread_mutex_unlock(&tinyalsa_audio_device->lock);
+
rc = audio_in_pcm_open(tinyalsa_audio_stream_in);
if(rc < 0) {
LOGE("Unable to open pcm device");
+ pthread_mutex_unlock(&tinyalsa_audio_stream_in->lock);
goto error_stream;
}
@@ -747,6 +792,8 @@ int audio_hw_open_input_stream(struct audio_hw_device *dev,
tinyalsa_audio_stream_in->standby = 1;
+ pthread_mutex_unlock(&tinyalsa_audio_stream_in->lock);
+
*stream_in = stream;
return 0;
diff --git a/audio_out.c b/audio_out.c
index 3438f53..8a8814c 100644
--- a/audio_out.c
+++ b/audio_out.c
@@ -103,8 +103,10 @@ int audio_out_set_route(struct tinyalsa_audio_stream_out *stream_out,
stream_out->device_current = device;
- if(device == 0)
+ if(device == 0) {
+ pthread_mutex_unlock(&stream_out->lock);
return stream_out->stream.common.standby((struct audio_stream *) stream_out);
+ }
tinyalsa_mixer_set_device(stream_out->device->mixer, stream_out->device_current);
@@ -278,6 +280,8 @@ static int audio_out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
stream_out = (struct tinyalsa_audio_stream_out *) stream;
if(stream_out->rate != (int) rate) {
+ pthread_mutex_lock(&stream_out->lock);
+
stream_out->rate = rate;
if(stream_out->rate != stream_out->mixer_props->rate) {
@@ -286,6 +290,8 @@ static int audio_out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
stream_out->standby = 1;
}
+
+ pthread_mutex_unlock(&stream_out->lock);
}
return 0;
@@ -345,10 +351,14 @@ static int audio_out_set_format(struct audio_stream *stream, int format)
stream_out = (struct tinyalsa_audio_stream_out *) stream;
if(stream_out->format != (audio_format_t) format) {
+ pthread_mutex_lock(&stream_out->lock);
+
stream_out->format = format;
if(stream_out->format != stream_out->mixer_props->format)
stream_out->standby = 1;
+
+ pthread_mutex_unlock(&stream_out->lock);
}
return 0;
@@ -366,6 +376,8 @@ static int audio_out_standby(struct audio_stream *stream)
stream_out = (struct tinyalsa_audio_stream_out *) stream;
+ pthread_mutex_lock(&stream_out->lock);
+
if(stream_out->pcm != NULL)
audio_out_pcm_close(stream_out);
@@ -380,6 +392,8 @@ static int audio_out_standby(struct audio_stream *stream)
stream_out->standby = 1;
+ pthread_mutex_unlock(&stream_out->lock);
+
return 0;
}
@@ -418,10 +432,18 @@ static int audio_out_set_parameters(struct audio_stream *stream, const char *kvp
value = atoi(value_string);
- if(stream_out->device_current != (audio_devices_t) value)
+ pthread_mutex_lock(&stream_out->device->lock);
+
+ if(stream_out->device_current != (audio_devices_t) value) {
+ pthread_mutex_lock(&stream_out->lock);
audio_out_set_route(stream_out, (audio_devices_t) value);
- if(stream_out->device->ril_interface != NULL && stream_out->device->ril_interface->device_current != (audio_devices_t) value)
+ pthread_mutex_unlock(&stream_out->lock);
+ }
+ if(stream_out->device->ril_interface != NULL && stream_out->device->ril_interface->device_current != (audio_devices_t) value) {
audio_ril_interface_set_route(stream_out->device->ril_interface, (audio_devices_t) value);
+ }
+
+ pthread_mutex_unlock(&stream_out->device->lock);
str_parms_destroy(parms);
@@ -477,8 +499,10 @@ static int audio_out_set_volume(struct audio_stream_out *stream, float left,
volume = (left + right) / 2;
+ pthread_mutex_lock(&stream_out->device->lock);
tinyalsa_mixer_set_output_volume(stream_out->device->mixer,
stream_out->device_current, volume);
+ pthread_mutex_unlock(&stream_out->device->lock);
return 0;
}
@@ -494,6 +518,11 @@ static ssize_t audio_out_write(struct audio_stream_out *stream,
stream_out = (struct tinyalsa_audio_stream_out *) stream;
+ if(stream_out->device == NULL)
+ return -1;
+
+ pthread_mutex_lock(&stream_out->lock);
+
if(stream_out->standby) {
#ifdef YAMAHA_MC1N2_AUDIO
rc = yamaha_mc1n2_audio_output_start(stream_out->device->mc1n2_pdata);
@@ -505,7 +534,7 @@ static ssize_t audio_out_write(struct audio_stream_out *stream,
rc = audio_out_pcm_open(stream_out);
if(rc < 0) {
LOGE("Unable to open pcm device");
- return -1;
+ goto error;
}
stream_out->standby = 0;
@@ -514,10 +543,17 @@ static ssize_t audio_out_write(struct audio_stream_out *stream,
rc = audio_out_write_process(stream_out, (void *) buffer, (int) bytes);
if(rc < 0) {
LOGE("Process and write failed!");
- return -1;
+ goto error;
}
+ pthread_mutex_unlock(&stream_out->lock);
+
return bytes;
+
+error:
+ pthread_mutex_unlock(&stream_out->lock);
+
+ return -1;
}
static int audio_out_get_render_position(const struct audio_stream_out *stream,
@@ -556,6 +592,9 @@ void audio_hw_close_output_stream(struct audio_hw_device *dev,
stream_out = (struct tinyalsa_audio_stream_out *) stream;
+ if(stream_out != NULL && stream_out->resampler != NULL)
+ audio_out_resampler_close(stream_out);
+
#ifdef YAMAHA_MC1N2_AUDIO
if(stream_out != NULL && !stream_out->standby)
yamaha_mc1n2_audio_output_stop(stream_out->device->mc1n2_pdata);
@@ -569,9 +608,12 @@ void audio_hw_close_output_stream(struct audio_hw_device *dev,
tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev;
- tinyalsa_mixer_set_output_state(tinyalsa_audio_device->mixer, 0);
+ pthread_mutex_lock(&tinyalsa_audio_device->lock);
+ tinyalsa_mixer_set_output_state(tinyalsa_audio_device->mixer, 0);
tinyalsa_audio_device->stream_out = NULL;
+
+ pthread_mutex_unlock(&tinyalsa_audio_device->lock);
}
int audio_hw_open_output_stream(struct audio_hw_device *dev,
@@ -659,17 +701,25 @@ int audio_hw_open_output_stream(struct audio_hw_device *dev,
*channels = (uint32_t) tinyalsa_audio_stream_out->channels;
*format = (uint32_t) tinyalsa_audio_stream_out->format;
+ pthread_mutex_lock(&tinyalsa_audio_device->lock);
+
rc = tinyalsa_mixer_set_output_state(tinyalsa_audio_device->mixer, 1);
if(rc < 0) {
LOGE("Unable to set output state");
+ pthread_mutex_unlock(&tinyalsa_audio_device->lock);
goto error_stream;
}
+ pthread_mutex_lock(&tinyalsa_audio_stream_out->lock);
+
audio_out_set_route(tinyalsa_audio_stream_out, devices);
+ pthread_mutex_unlock(&tinyalsa_audio_device->lock);
+
rc = audio_out_pcm_open(tinyalsa_audio_stream_out);
if(rc < 0) {
LOGE("Unable to open pcm device");
+ pthread_mutex_unlock(&tinyalsa_audio_stream_out->lock);
goto error_stream;
}
@@ -677,6 +727,8 @@ int audio_hw_open_output_stream(struct audio_hw_device *dev,
tinyalsa_audio_stream_out->standby = 1;
+ pthread_mutex_unlock(&tinyalsa_audio_stream_out->lock);
+
*stream_out = stream;
return 0;
diff --git a/audio_ril_interface.c b/audio_ril_interface.c
index d3a8658..0b4383d 100644
--- a/audio_ril_interface.c
+++ b/audio_ril_interface.c
@@ -42,16 +42,25 @@ int audio_ril_interface_set_mic_mute(struct tinyalsa_audio_ril_interface *ril_in
LOGD("%s(%d)", __func__, state);
+ pthread_mutex_lock(&ril_interface->lock);
+
if(ril_interface->interface->mic_mute == NULL)
- return -1;
+ goto error;
rc = ril_interface->interface->mic_mute(ril_interface->interface->pdata, (int) state);
if(rc < 0) {
LOGE("Failed to set RIL interface mic mute");
- return -1;
+ goto error;
}
+ pthread_mutex_unlock(&ril_interface->lock);
+
return 0;
+
+error:
+ pthread_mutex_unlock(&ril_interface->lock);
+
+ return -1;
}
int audio_ril_interface_set_voice_volume(struct tinyalsa_audio_ril_interface *ril_interface,
@@ -64,39 +73,57 @@ int audio_ril_interface_set_voice_volume(struct tinyalsa_audio_ril_interface *ri
LOGD("%s(%d, %f)", __func__, device, volume);
+ pthread_mutex_lock(&ril_interface->lock);
+
if(ril_interface->interface->voice_volume == NULL)
- return -1;
+ goto error;
rc = ril_interface->interface->voice_volume(ril_interface->interface->pdata, device, volume);
if(rc < 0) {
LOGE("Failed to set RIL interface voice volume");
- return -1;
+ goto error;
}
+ pthread_mutex_unlock(&ril_interface->lock);
+
return 0;
+
+error:
+ pthread_mutex_unlock(&ril_interface->lock);
+
+ return -1;
}
int audio_ril_interface_set_route(struct tinyalsa_audio_ril_interface *ril_interface, audio_devices_t device)
{
int rc;
+ LOGD("%s(%d)", __func__, device);
+
if(ril_interface == NULL)
return -1;
- LOGD("%s(%d)", __func__, device);
+ pthread_mutex_lock(&ril_interface->lock);
ril_interface->device_current = device;
if(ril_interface->interface->route == NULL)
- return -1;
+ goto error;
rc = ril_interface->interface->route(ril_interface->interface->pdata, device);
if(rc < 0) {
LOGE("Failed to set RIL interface route");
- return -1;
+ goto error;
}
+ pthread_mutex_unlock(&ril_interface->lock);
+
return 0;
+
+error:
+ pthread_mutex_unlock(&ril_interface->lock);
+
+ return -1;
}
/*
diff --git a/audio_ril_interface.h b/audio_ril_interface.h
index c1befae..3d7e3f1 100644
--- a/audio_ril_interface.h
+++ b/audio_ril_interface.h
@@ -28,6 +28,8 @@ struct tinyalsa_audio_ril_interface {
void *dl_handle;
audio_devices_t device_current;
+
+ pthread_mutex_t lock;
};
int audio_ril_interface_set_mic_mute(struct tinyalsa_audio_ril_interface *ril_interface, bool state);