summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2012-09-16 20:16:00 +0200
committerPaul Kocialkowski <contact@paulk.fr>2012-09-16 20:16:00 +0200
commit38f53573aad8deef4b2fe0663091f9c9336f711a (patch)
treefb94d01bfdb968522d0cb08e66a0da9f153eb314
downloadhardware_tinyalsa-audio-38f53573aad8deef4b2fe0663091f9c9336f711a.zip
hardware_tinyalsa-audio-38f53573aad8deef4b2fe0663091f9c9336f711a.tar.gz
hardware_tinyalsa-audio-38f53573aad8deef4b2fe0663091f9c9336f711a.tar.bz2
Initial commit: TinyALSA-Audio audio module for ice cream sandwich
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r--Android.mk47
-rw-r--r--audio_hw.c198
-rw-r--r--audio_hw.h49
-rw-r--r--audio_in.c158
-rw-r--r--audio_out.c165
5 files changed, 617 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..f412a89
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(strip $(BOARD_USES_TINYALSA_LIBAUDIO)),true)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ audio_hw.c
+
+LOCAL_C_INCLUDES += \
+ external/tinyalsa/include \
+ system/media/audio_utils/include \
+ system/media/audio_effects/include \
+ hardware/tinyalsa-audio/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libc \
+ libcutils \
+ libutils \
+ libtinyalsa \
+ libaudioutils \
+ libdl
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/audio_hw.c b/audio_hw.c
new file mode 100644
index 0000000..5e18a0b
--- /dev/null
+++ b/audio_hw.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This is based on Galaxy Nexus audio.primary.tuna implementation:
+ * Copyright 2011, The Android Open-Source Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define LOG_TAG "audio_hw"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <sys/time.h>
+
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+
+/*
+ * Output
+ */
+
+#include "audio_out.c"
+
+/*
+ * Input
+ */
+
+#include "audio_in.c"
+
+/*
+ * Functions
+ */
+
+static uint32_t audio_hw_get_supported_devices(const struct audio_hw_device *dev)
+{
+ int supported_output_devices = AUDIO_DEVICE_OUT_EARPIECE |
+ AUDIO_DEVICE_OUT_SPEAKER |
+ AUDIO_DEVICE_OUT_WIRED_HEADSET |
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
+ AUDIO_DEVICE_OUT_AUX_DIGITAL |
+ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
+ AUDIO_DEVICE_OUT_ALL_SCO |
+ AUDIO_DEVICE_OUT_DEFAULT;
+
+ int supported_input_devices = AUDIO_DEVICE_IN_COMMUNICATION |
+ AUDIO_DEVICE_IN_AMBIENT |
+ AUDIO_DEVICE_IN_BUILTIN_MIC |
+ AUDIO_DEVICE_IN_WIRED_HEADSET |
+ AUDIO_DEVICE_IN_AUX_DIGITAL |
+ AUDIO_DEVICE_IN_BACK_MIC |
+ AUDIO_DEVICE_IN_ALL_SCO |
+ AUDIO_DEVICE_IN_DEFAULT;
+
+ return supported_output_devices | supported_input_devices;
+}
+
+static int audio_hw_init_check(const struct audio_hw_device *dev)
+{
+ if(dev != NULL)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+static int audio_hw_set_voice_volume(struct audio_hw_device *dev, float volume)
+{
+ return -ENOSYS;
+}
+
+static int audio_hw_set_master_volume(struct audio_hw_device *dev, float volume)
+{
+ return -ENOSYS;
+}
+
+static int audio_hw_set_mode(struct audio_hw_device *dev, int mode)
+{
+ return 0;
+}
+
+static int audio_hw_set_mic_mute(struct audio_hw_device *dev, bool state)
+{
+ return -ENOSYS;
+}
+
+static int audio_hw_get_mic_mute(const struct audio_hw_device *dev, bool *state)
+{
+ return -ENOSYS;
+}
+
+static int audio_hw_set_parameters(struct audio_hw_device *dev,
+ const char *kvpairs)
+{
+ return -ENOSYS;
+}
+
+static char * audio_hw_get_parameters(const struct audio_hw_device *dev,
+ const char *keys)
+{
+ return NULL;
+}
+
+static size_t audio_hw_get_input_buffer_size(const struct audio_hw_device *dev,
+ uint32_t sample_rate, int format, int channel_count)
+{
+ return 320;
+}
+
+static int audio_hw_dump(const audio_hw_device_t *device, int fd)
+{
+ return 0;
+}
+
+/*
+ * Interface
+ */
+
+int audio_hw_close(hw_device_t *device)
+{
+ if(device != NULL)
+ free(device);
+
+ return 0;
+}
+
+int audio_hw_open(const hw_module_t *module, const char *name,
+ hw_device_t **device)
+{
+ struct tinyalsa_audio_device *tinyalsa_audio_device;
+ struct audio_hw_device *dev;
+
+ if(strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
+ return -EINVAL;
+
+ tinyalsa_audio_device = calloc(1, sizeof(struct tinyalsa_audio_device));
+ if(tinyalsa_audio_device == NULL)
+ return -ENOMEM;
+
+ dev = &(tinyalsa_audio_device->device);
+
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = (struct hw_module_t *) module;
+ dev->common.close = audio_hw_close;
+
+ dev->get_supported_devices = audio_hw_get_supported_devices;
+ dev->init_check = audio_hw_init_check;
+ dev->set_voice_volume = audio_hw_set_voice_volume;
+ dev->set_master_volume = audio_hw_set_master_volume;
+ dev->set_mode = audio_hw_set_mode;
+ dev->set_mic_mute = audio_hw_set_mic_mute;
+ dev->get_mic_mute = audio_hw_get_mic_mute;
+ dev->set_parameters = audio_hw_set_parameters;
+ dev->get_parameters = audio_hw_get_parameters;
+ dev->get_input_buffer_size = audio_hw_get_input_buffer_size;
+
+ dev->open_output_stream = audio_hw_open_output_stream;
+ dev->close_output_stream = audio_hw_close_output_stream;
+
+ dev->open_input_stream = audio_hw_open_input_stream;
+ dev->close_input_stream = audio_hw_close_input_stream;
+
+ dev->dump = audio_hw_dump;
+
+ *device = &(dev->common);
+
+ return 0;
+}
+
+struct hw_module_methods_t audio_hw_module_methods = {
+ .open = audio_hw_open,
+};
+
+struct audio_module HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = AUDIO_HARDWARE_MODULE_ID,
+ .name = "TinyALSA-Audio",
+ .author = "Paul Kocialkowski",
+ .methods = &audio_hw_module_methods,
+ },
+};
diff --git a/audio_hw.h b/audio_hw.h
new file mode 100644
index 0000000..d8beb81
--- /dev/null
+++ b/audio_hw.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TINYALSA_AUDIO_HW_H
+#define TINYALSA_AUDIO_HW_H
+
+#include <hardware/hardware.h>
+#include <hardware/audio.h>
+#include <system/audio.h>
+
+struct tinyalsa_audio_stream_out {
+ struct audio_stream_out stream;
+ struct tinyalsa_audio_device *dev;
+};
+
+struct tinyalsa_audio_stream_in {
+ struct audio_stream_in stream;
+ struct tinyalsa_audio_device *dev;
+};
+
+struct tinyalsa_audio_device {
+ struct audio_hw_device device;
+
+ struct tinyalsa_audio_stream_out *stream_out;
+ struct tinyalsa_audio_stream_in *stream_in;
+};
+
+int audio_hw_open_output_stream(struct audio_hw_device *dev,
+ uint32_t devices, int *format, uint32_t *channels, uint32_t *sample_rate,
+ struct audio_stream_out **stream_out);
+
+void audio_hw_close_output_stream(struct audio_hw_device *dev,
+ struct audio_stream_out *stream);
+
+#endif
diff --git a/audio_in.c b/audio_in.c
new file mode 100644
index 0000000..dffed01
--- /dev/null
+++ b/audio_in.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This is based on Galaxy Nexus audio.primary.tuna implementation:
+ * Copyright 2011, The Android Open-Source Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "audio_in"
+
+/*
+ * Functions
+ */
+
+static uint32_t audio_in_get_sample_rate(const struct audio_stream *stream)
+{
+ return 8000;
+}
+
+static int audio_in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
+{
+ return 0;
+}
+
+static size_t audio_in_get_buffer_size(const struct audio_stream *stream)
+{
+ return 320;
+}
+
+static uint32_t audio_in_get_channels(const struct audio_stream *stream)
+{
+ return AUDIO_CHANNEL_IN_MONO;
+}
+
+static int audio_in_get_format(const struct audio_stream *stream)
+{
+ return AUDIO_FORMAT_PCM_16_BIT;
+}
+
+static int audio_in_set_format(struct audio_stream *stream, int format)
+{
+ return 0;
+}
+
+static int audio_in_standby(struct audio_stream *stream)
+{
+ return 0;
+}
+
+static int audio_in_dump(const struct audio_stream *stream, int fd)
+{
+ return 0;
+}
+
+static int audio_in_set_parameters(struct audio_stream *stream, const char *kvpairs)
+{
+ return 0;
+}
+
+static char * audio_in_get_parameters(const struct audio_stream *stream,
+ const char *keys)
+{
+ return strdup("");
+}
+
+static int audio_in_set_gain(struct audio_stream_in *stream, float gain)
+{
+ return 0;
+}
+
+static ssize_t audio_in_read(struct audio_stream_in *stream, void* buffer,
+ size_t bytes)
+{
+ /* XXX: fake timing for audio input */
+ usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
+ audio_in_get_sample_rate(&stream->common));
+ return bytes;
+}
+
+static uint32_t audio_in_get_input_frames_lost(struct audio_stream_in *stream)
+{
+ return 0;
+}
+
+static int audio_in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+ return 0;
+}
+
+static int audio_in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+ return 0;
+}
+
+/*
+ * Interface
+ */
+
+static void audio_hw_close_input_stream(struct audio_hw_device *dev,
+ struct audio_stream_in *stream)
+{
+ if(stream != NULL)
+ free(stream);
+}
+
+static int audio_hw_open_input_stream(struct audio_hw_device *dev,
+ uint32_t devices, int *format, uint32_t *channels, uint32_t *sample_rate,
+ audio_in_acoustics_t acoustics, struct audio_stream_in **stream_in)
+{
+ struct tinyalsa_audio_device *tinyalsa_audio_device;
+ struct tinyalsa_audio_stream_in *tinyalsa_audio_stream_in;
+ struct audio_stream_in *stream;
+
+ if(dev == NULL)
+ return -EINVAL;
+
+ tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev;
+ tinyalsa_audio_stream_in = calloc(1, sizeof(struct tinyalsa_audio_stream_in));
+
+ if(tinyalsa_audio_stream_in == NULL)
+ return -ENOMEM;
+
+ tinyalsa_audio_stream_in->dev = tinyalsa_audio_device;
+ stream = &(tinyalsa_audio_stream_in->stream);
+
+ stream->common.get_sample_rate = audio_in_get_sample_rate;
+ stream->common.set_sample_rate = audio_in_set_sample_rate;
+ stream->common.get_buffer_size = audio_in_get_buffer_size;
+ stream->common.get_channels = audio_in_get_channels;
+ stream->common.get_format = audio_in_get_format;
+ stream->common.set_format = audio_in_set_format;
+ stream->common.standby = audio_in_standby;
+ stream->common.dump = audio_in_dump;
+ stream->common.set_parameters = audio_in_set_parameters;
+ stream->common.get_parameters = audio_in_get_parameters;
+ stream->common.add_audio_effect = audio_in_add_audio_effect;
+ stream->common.remove_audio_effect = audio_in_remove_audio_effect;
+ stream->set_gain = audio_in_set_gain;
+ stream->read = audio_in_read;
+ stream->get_input_frames_lost = audio_in_get_input_frames_lost;
+
+ *stream_in = stream;
+
+ return 0;
+}
diff --git a/audio_out.c b/audio_out.c
new file mode 100644
index 0000000..ae69f52
--- /dev/null
+++ b/audio_out.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This is based on Galaxy Nexus audio.primary.tuna implementation:
+ * Copyright 2011, The Android Open-Source Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "audio_out"
+
+/*
+ * Functions
+ */
+
+static uint32_t audio_out_get_sample_rate(const struct audio_stream *stream)
+{
+ return 44100;
+}
+
+static int audio_out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
+{
+ return 0;
+}
+
+static size_t audio_out_get_buffer_size(const struct audio_stream *stream)
+{
+ return 4096;
+}
+
+static uint32_t audio_out_get_channels(const struct audio_stream *stream)
+{
+ return AUDIO_CHANNEL_OUT_STEREO;
+}
+
+static int audio_out_get_format(const struct audio_stream *stream)
+{
+ return AUDIO_FORMAT_PCM_16_BIT;
+}
+
+static int audio_out_set_format(struct audio_stream *stream, int format)
+{
+ return 0;
+}
+
+static int audio_out_standby(struct audio_stream *stream)
+{
+ return 0;
+}
+
+static int audio_out_dump(const struct audio_stream *stream, int fd)
+{
+ return 0;
+}
+
+static int audio_out_set_parameters(struct audio_stream *stream, const char *kvpairs)
+{
+ return 0;
+}
+
+static char * audio_out_get_parameters(const struct audio_stream *stream, const char *keys)
+{
+ return strdup("");
+}
+
+static uint32_t audio_out_get_latency(const struct audio_stream_out *stream)
+{
+ return 0;
+}
+
+static int audio_out_set_volume(struct audio_stream_out *stream, float left,
+ float right)
+{
+ return 0;
+}
+
+static ssize_t audio_out_write(struct audio_stream_out *stream, const void* buffer,
+ size_t bytes)
+{
+ /* XXX: fake timing for audio output */
+ usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
+ audio_out_get_sample_rate(&stream->common));
+ return bytes;
+}
+
+static int audio_out_get_render_position(const struct audio_stream_out *stream,
+ uint32_t *dsp_frames)
+{
+ return -EINVAL;
+}
+
+static int audio_out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+ return 0;
+}
+
+static int audio_out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+ return 0;
+}
+
+/*
+ * Interface
+ */
+
+void audio_hw_close_output_stream(struct audio_hw_device *dev,
+ struct audio_stream_out *stream)
+{
+ if(stream != NULL)
+ free(stream);
+}
+
+int audio_hw_open_output_stream(struct audio_hw_device *dev,
+ uint32_t devices, int *format, uint32_t *channels, uint32_t *sample_rate,
+ struct audio_stream_out **stream_out)
+{
+ struct tinyalsa_audio_device *tinyalsa_audio_device;
+ struct tinyalsa_audio_stream_out *tinyalsa_audio_stream_out;
+ struct audio_stream_out *stream;
+
+ if(dev == NULL)
+ return -EINVAL;
+
+ tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev;
+ tinyalsa_audio_stream_out = calloc(1, sizeof(struct tinyalsa_audio_stream_out));
+
+ if(tinyalsa_audio_stream_out == NULL)
+ return -ENOMEM;
+
+ tinyalsa_audio_stream_out->dev = tinyalsa_audio_device;
+ stream = &(tinyalsa_audio_stream_out->stream);
+
+ stream->common.get_sample_rate = audio_out_get_sample_rate;
+ stream->common.set_sample_rate = audio_out_set_sample_rate;
+ stream->common.get_buffer_size = audio_out_get_buffer_size;
+ stream->common.get_channels = audio_out_get_channels;
+ stream->common.get_format = audio_out_get_format;
+ stream->common.set_format = audio_out_set_format;
+ stream->common.standby = audio_out_standby;
+ stream->common.dump = audio_out_dump;
+ stream->common.set_parameters = audio_out_set_parameters;
+ stream->common.get_parameters = audio_out_get_parameters;
+ stream->common.add_audio_effect = audio_out_add_audio_effect;
+ stream->common.remove_audio_effect = audio_out_remove_audio_effect;
+ stream->get_latency = audio_out_get_latency;
+ stream->set_volume = audio_out_set_volume;
+ stream->write = audio_out_write;
+ stream->get_render_position = audio_out_get_render_position;
+
+ *stream_out = stream;
+
+ return 0;
+}