diff options
author | jk7744.park <jk7744.park@samsung.com> | 2015-09-08 22:08:11 +0900 |
---|---|---|
committer | jk7744.park <jk7744.park@samsung.com> | 2015-09-08 22:08:11 +0900 |
commit | db7ddd104db9bdfb1364f6ee12f2daf30b039b60 (patch) | |
tree | ca87a89f4723ae0b837679bd1f8b6d6f61d6432c | |
parent | 3a3385014d5efcbb756528a748b8a9777efb50c5 (diff) | |
download | audio-io-tizen_2.3.1.tar.gz audio-io-tizen_2.3.1.tar.bz2 audio-io-tizen_2.3.1.zip |
tizen 2.3.1 releasetizen_2.3.1_releasesubmit/tizen_2.3.1/20150915.075630tizen_2.3.1
-rw-r--r-- | .gitignore | 27 | ||||
-rw-r--r--[-rwxr-xr-x] | CMakeLists.txt | 8 | ||||
-rw-r--r-- | capi-media-audio-io.manifest | 5 | ||||
-rw-r--r-- | doc/audio_io_doc.h | 93 | ||||
-rw-r--r-- | include/audio_io.h | 730 | ||||
-rw-r--r-- | include/audio_io_private.h | 76 | ||||
-rw-r--r-- | packaging/capi-media-audio-io.spec | 21 | ||||
-rw-r--r-- | src/audio_io.c | 563 | ||||
-rw-r--r-- | src/audio_io_private.c | 495 | ||||
-rw-r--r-- | test/CMakeLists.txt | 3 | ||||
-rw-r--r--[-rwxr-xr-x] | test/audio_io_test.c | 583 |
11 files changed, 2148 insertions, 456 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03736b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +CMakeCache.txt +*/CMakeFiles/* +*.cmake +CMakeFiles* +*.a +*.so +Testing +cmake.depends +cmake.check_depends +cmake.check_cache +core +core.* +gmon.out +install_manifest.txt +*~ +.kdev_include_paths +src.kdev4 +.cproject +.project +tet_captured +tet_lock +*.pc +Makefile +*-test +*-test_* +*tester.c +.gitattributes diff --git a/CMakeLists.txt b/CMakeLists.txt index b018af6..a3dfa67 100755..100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(INC_DIR include) INCLUDE_DIRECTORIES(${INC_DIR}) -SET(dependents "dlog mm-sound capi-base-common capi-media-sound-manager") +SET(dependents "dlog glib-2.0 mm-sound capi-base-common capi-media-sound-manager") SET(pc_dependents "capi-base-common capi-media-sound-manager") INCLUDE(FindPkgConfig) @@ -70,16 +70,16 @@ CONFIGURE_FILE( ) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION lib/pkgconfig) -ADD_SUBDIRECTORY(test) +#ADD_SUBDIRECTORY(test) IF(UNIX) ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution) ADD_CUSTOM_COMMAND( - DEPENDS clean + DEPENDS clean COMMENT "distribution clean" COMMAND find - ARGS . + ARGS . -not -name config.cmake -and \( -name tester.c -or -name Testing -or diff --git a/capi-media-audio-io.manifest b/capi-media-audio-io.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/capi-media-audio-io.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_" /> + </request> +</manifest> diff --git a/doc/audio_io_doc.h b/doc/audio_io_doc.h new file mode 100644 index 0000000..a875a31 --- /dev/null +++ b/doc/audio_io_doc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __TIZEN_MEDIA_AUDIO_IO_DOC_H__ +#define __TIZEN_MEDIA_AUDIO_IO_DOC_H__ + + +/** + * @file audio_io_doc.h + * @brief This file contains high level documentation for the Audio I/O API. + * + */ + +/** + * @defgroup CAPI_MEDIA_AUDIO_IO_MODULE Audio I/O + * @ingroup CAPI_MEDIA_FRAMEWORK + */ + +/** + * @ingroup CAPI_MEDIA_FRAMEWORK + * @addtogroup CAPI_MEDIA_AUDIO_IO_MODULE + * @brief The @ref CAPI_MEDIA_AUDIO_IO_MODULE API provides functions for controlling audio devices. + * @section CAPI_MEDIA_AUDIO_IO_MODULE_HEADER Required Header + * \#include <audio_io.h> + * + * @section CAPI_MEDIA_AUDIO_IO_MODULE_OVERVIEW Overview + * The Audio I/O API provides a set of functions to directly manage the system audio devices. + * It gives easy access to the hardware layer of the sound card with a professional multichannel audio interface. + * It should be used for activities requiring raw audio data buffers(PCM format). + * + * Programming the interface requires first obtaining a handle to the device, via the audio_in_create() or audio_out_create() function. + * + * The input and output devices both have an available set of queries, to find the suggested buffer size, sampling rate, channel type, + * and sample type. For output, there is an additional query, to get the sound type (these types are defined in the @ref CAPI_MEDIA_SOUND_MANAGER_MODULE API). + * + * Reading and writing is done by allocating a buffer and passing the buffer to the input device + * via audio_in_start_recording(), audio_in_read(), or writing to the buffer and passing it to the output device via audio_out_write(). + * + */ + + /** + * @ingroup CAPI_MEDIA_AUDIO_IO_MODULE + * @defgroup CAPI_MEDIA_AUDIO_IN_MODULE Audio Input + * @brief The @ref CAPI_MEDIA_AUDIO_IN_MODULE API provides a set of functions to directly manage the system audio input devices. + * @section CAPI_MEDIA_AUDIO_IN_MODULE_HEADER Required Header + * \#include <audio_io.h> + * + * @section CAPI_MEDIA_AUDIO_IN_MODULE_OVERVIEW Overview + * The Audio Input API provides a set of functions to record audio data (PCM format) from audio devices. + * + * @section CAPI_MEDIA_AUDIO_IN_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - http://tizen.org/feature/microphone\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from <a href="../org.tizen.mobile.native.appprogramming/html/ide_sdk_tools/feature_element.htm"><b>Feature Element</b>.</a> + * + */ + + /** + * @ingroup CAPI_MEDIA_AUDIO_IO_MODULE + * @defgroup CAPI_MEDIA_AUDIO_OUT_MODULE Audio Output + * @brief The @ref CAPI_MEDIA_AUDIO_OUT_MODULE API provides a set of functions to directly manage the system audio output devices. + * @section CAPI_MEDIA_AUDIO_OUT_MODULE_HEADER Required Header + * \#include <audio_io.h> + * + * @section CAPI_MEDIA_AUDIO_OUT_MODULE_OVERVIEW Overview + * The Audio Output API provides a set of functions to play recorded audio data from Audio Input. + * + * + */ +#endif /* __TIZEN_MEDIA_AUDIO_IO_DOC_H__ */ + + diff --git a/include/audio_io.h b/include/audio_io.h index 1aa7bab..484a9c1 100644 --- a/include/audio_io.h +++ b/include/audio_io.h @@ -1,62 +1,63 @@ /* -* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __TIZEN_MEDIA_AUDIO_IO_H__ #define __TIZEN_MEDIA_AUDIO_IO_H__ #include <tizen.h> #include <sound_manager.h> +#include <sys/types.h> #ifdef __cplusplus extern "C" { #endif -#define AUDIO_IO_ERROR_CLASS TIZEN_ERROR_MULTIMEDIA_CLASS | 0x40 - /** * @file audio_io.h - * @brief This file contains the Audio Input and Output API. + * @brief This file contains the Audio Input and Audio Output API. */ /** * @addtogroup CAPI_MEDIA_AUDIO_IN_MODULE * @{ -*/ + */ /** - * @brief Audio input handle type. + * @brief The audio input handle. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef struct audio_in_s *audio_in_h; /** * @} -*/ + */ /** * @addtogroup CAPI_MEDIA_AUDIO_OUT_MODULE * @{ */ - + /** - * @brief Audio output handle type. + * @brief The audio output handle. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef struct audio_out_s *audio_out_h; - /** +/** * @} */ @@ -66,198 +67,435 @@ typedef struct audio_out_s *audio_out_h; */ /** - * @brief Enumerations of audio sample type with bit depth + * @brief Enumeration for audio sample type with bit depth. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef enum { - AUDIO_SAMPLE_TYPE_U8 = 0x70, /**< Unsigned 8-bit audio samples */ - AUDIO_SAMPLE_TYPE_S16_LE, /**< Signed 16-bit audio samples */ + AUDIO_SAMPLE_TYPE_U8 = 0x70, /**< Unsigned 8-bit audio samples */ + AUDIO_SAMPLE_TYPE_S16_LE, /**< Signed 16-bit audio samples */ } audio_sample_type_e; /** - * @brief Enumerations of audio channel + * @brief Enumeration for audio channel. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef enum { - AUDIO_CHANNEL_MONO = 0x80, /**< 1 channel, mono */ - AUDIO_CHANNEL_STEREO, /**< 2 channel, stereo */ + AUDIO_CHANNEL_MONO = 0x80, /**< 1 channel, mono */ + AUDIO_CHANNEL_STEREO, /**< 2 channel, stereo */ } audio_channel_e; /** - * @brief Enumerations of audio input and output error code + * @brief Enumeration for audio input and output error. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef enum{ - AUDIO_IO_ERROR_NONE = TIZEN_ERROR_NONE, /**<Successful */ + AUDIO_IO_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ AUDIO_IO_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ AUDIO_IO_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ AUDIO_IO_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */ - AUDIO_IO_ERROR_DEVICE_NOT_OPENED = AUDIO_IO_ERROR_CLASS | 0x01, /**< Device open error */ - AUDIO_IO_ERROR_DEVICE_NOT_CLOSED = AUDIO_IO_ERROR_CLASS | 0x02, /**< Device close error */ - AUDIO_IO_ERROR_INVALID_BUFFER = AUDIO_IO_ERROR_CLASS | 0x03, /**< Invalid buffer pointer */ - AUDIO_IO_ERROR_SOUND_POLICY = AUDIO_IO_ERROR_CLASS | 0x04, /**< Sound policy error */ + AUDIO_IO_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Device open error by security */ + AUDIO_IO_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + AUDIO_IO_ERROR_DEVICE_NOT_OPENED = TIZEN_ERROR_AUDIO_IO | 0x01, /**< Device open error */ + AUDIO_IO_ERROR_DEVICE_NOT_CLOSED = TIZEN_ERROR_AUDIO_IO | 0x02, /**< Device close error */ + AUDIO_IO_ERROR_INVALID_BUFFER = TIZEN_ERROR_AUDIO_IO | 0x03, /**< Invalid buffer pointer */ + AUDIO_IO_ERROR_SOUND_POLICY = TIZEN_ERROR_AUDIO_IO | 0x04, /**< Sound policy error */ } audio_io_error_e; +/** + * @brief Enumeration for audio IO interrupted messages. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + */ +typedef enum +{ + AUDIO_IO_INTERRUPTED_COMPLETED = 0, /**< Interrupt completed */ + AUDIO_IO_INTERRUPTED_BY_MEDIA, /**< Interrupted by a media application */ + AUDIO_IO_INTERRUPTED_BY_CALL, /**< Interrupted by an incoming call */ + AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG, /**< Interrupted by unplugging headphones */ + AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT, /**< Interrupted by a resource conflict */ + AUDIO_IO_INTERRUPTED_BY_ALARM, /**< Interrupted by an alarm */ + AUDIO_IO_INTERRUPTED_BY_EMERGENCY, /**< Interrupted by an emergency */ + AUDIO_IO_INTERRUPTED_BY_NOTIFICATION, /**< Interrupted by a notification */ +} audio_io_interrupted_code_e; + +/** + * @brief Called when audio input or output is interrupted. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @param[in] error_code The interrupted error code + * @param[in] user_data The user data passed from the callback registration function + * + * @see audio_in_set_interrupted_cb() + * @see audio_out_set_interrupted_cb() + * @see audio_in_unset_interrupted_cb() + * @see audio_out_unset_interrupted_cb() + */ +typedef void (*audio_io_interrupted_cb)(audio_io_interrupted_code_e code, void *user_data); /** * @} -*/ + */ /** * @addtogroup CAPI_MEDIA_AUDIO_IN_MODULE * @{ -*/ - + */ // //AUDIO INPUT // +/** + * @brief Called when audio input data is available in asynchronous(event) mode. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @remarks @a use audio_in_peek() to get audio in data inside callback, use audio_in_drop() after use of peeked data. + * + * @param[in] handle The handle to the audio input + * @param[in] nbytes The amount of available audio in data which can be peeked. + * @param[in] userdata The user data passed from the callback registration function + * + * @see audio_in_set_stream_cb() + */ +typedef void (*audio_in_stream_cb)(audio_in_h handle, size_t nbytes, void *userdata); /** - * @brief Creates an audio device instance and returns an input handle to record PCM (pulse-code modulation) data - * @details This function is used for audio input initialization. + * @brief Creates an audio device instance and returns an input handle to record PCM (pulse-code modulation) data. * - * @remarks @a input must be release audio_in_destroy() by you. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @privlevel public + * @privilege %http://tizen.org/privilege/recorder * - * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz] - * @param[in] channel The audio channel type, mono, or stereo - * @param[in] type The type of audio sample (8- or 16-bit) - * @param[out] input An audio input handle will be created, if successful + * @details This function is used for audio input initialization. * - * @return 0 on success, otherwise a negative error value. + * @remarks @a input must be released using audio_in_destroy(). + * + * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz] + * @param[in] channel The audio channel type (mono or stereo) + * @param[in] type The type of audio sample (8- or 16-bit) + * @param[out] input An audio input handle is created on success + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_PERMISSION_DENIED Permission denied * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened - * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported * @see audio_in_destroy() */ -int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h *input); - +int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input); +/** + * @brief Creates an audio loopback device instance and returns an input handle to record PCM (pulse-code modulation) data. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @privlevel public + * @privilege %http://tizen.org/privilege/recorder + * + * @details This function is used for audio loopback input initialization. + * + * @remarks @a input must be released using audio_in_destroy(). + * + * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz] + * @param[in] channel The audio channel type, mono, or stereo + * @param[in] type The type of audio sample (8- or 16-bit) + * @param[out] input An audio input handle will be created, if successful + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_PERMISSION_DENIED Permission denied + * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory + * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * @see audio_in_destroy() + */ +int audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input); /** - * @brief Releases the audio input handle and all its resources associated with an audio stream + * @brief Releases the audio input handle and all its resources associated with an audio stream. * - * @param[in] input The handle to the audio input to destroy + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. + * @param[in] input The handle to the audio input to destroy + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter * @retval #AUDIO_IO_ERROR_DEVICE_NOT_CLOSED Device not closed + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported * @see audio_in_create() */ int audio_in_destroy(audio_in_h input); - - /** - * @brief Prepare reading audio in by starting buffering the audio data from the device - * @param[in] input The handle to the audio input - * @return 0 on success, otherwise a negative error value. + * @brief Prepares reading audio input by starting buffering of audio data from the device. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] input The handle to the audio input + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * * @see audio_in_unprepare() */ int audio_in_prepare(audio_in_h input); - - /** - * @brief Unprepare reading audio in by stopping buffering the audio data from the device - * @param[in] input The handle to the audio input - * @return 0 on success, otherwise a negative error value. + * @brief Unprepares reading audio input by stopping buffering the audio data from the device. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] input The handle to the audio input + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported * @see audio_in_prepare() */ int audio_in_unprepare(audio_in_h input); - - /** - * @brief Reads audio data from the audio input buffer + * @brief Reads audio data from the audio input buffer. * - * @param[in] input The handle to the audio input - * @param[out] buffer The PCM buffer address - * @param[in] length The length of PCM data buffer (in bytes) + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return Number of read bytes on success, otherwise a negative error value. - * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #AUDIO_IO_ERROR_INVALID_BUFFER Invalid buffer pointer - * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error - * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation - * @pre audio_in_start_recording() -*/ + * @param[in] input The handle to the audio input + * @param[out] buffer The PCM buffer address + * @param[in] length The length of the PCM data buffer (in bytes) + * @return The number of read bytes on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_BUFFER Invalid buffer pointer + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * @pre audio_in_start_recording(). + */ int audio_in_read(audio_in_h input, void *buffer, unsigned int length); - - /** - * @brief Gets the size to be allocated for audio input buffer - * @param[in] input The handle to the audio input - * @param[out] size The buffer size (in bytes). \n The maximum size is 1 MB. + * @brief Gets the size to be allocated for the audio input buffer. * - * @return 0 on success, otherwise a negative error value. - * @retval #AUDIO_IO_ERROR_NONE Successful - * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] input The handle to the audio input + * @param[out] size The buffer size (in bytes, the maximum size is 1 MB) + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported * @see audio_in_read() -*/ + */ int audio_in_get_buffer_size(audio_in_h input, int *size); - - /** - * @brief Gets the sample rate of the audio input data stream + * @brief Gets the sample rate of the audio input data stream. * - * @param[in] input The handle to the audio input - * @param[out] sample_rate The audio sample rate in Hertz (8000 ~ 48000) + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. - * @retval #AUDIO_IO_ERROR_NONE Successful - * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ + * @param[in] input The handle to the audio input + * @param[out] sample_rate The audio sample rate in Hertz (8000 ~ 48000) + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + */ int audio_in_get_sample_rate(audio_in_h input, int *sample_rate); +/** + * @brief Gets the channel type of the audio input data stream. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @details The audio channel type defines whether the audio is mono or stereo. + * + * @param[in] input The handle to the audio input + * @param[out] channel The audio channel type + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + */ +int audio_in_get_channel(audio_in_h input, audio_channel_e *channel); +/** + * @brief Gets the sample audio format (8-bit or 16-bit) of the audio input data stream. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] input The handle to the audio input + * @param[out] type The audio sample type + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + */ +int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type); /** - * @brief Gets the channel type of audio input data stream + * @brief Registers a callback function to be invoked when the audio input handle is interrupted or the interrupt is completed. * - * @details The audio channel type defines whether the audio is mono or stereo. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @param[in] input The handle to the audio input - * @param[out] channel The audio channel type + * @param[in] input The handle to the audio input + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * @post audio_io_interrupted_cb() will be invoked. * - * @return 0 on success, otherwise a negative error value. + * @see audio_in_unset_interrupted_cb() + * @see audio_io_interrupted_cb() + */ +int audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data); + +/** + * @brief Unregisters the callback function. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] input The handle to the audio input + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ -int audio_in_get_channel(audio_in_h input, audio_channel_e *channel); + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * + * @see audio_in_set_interrupted_cb() + */ +int audio_in_unset_interrupted_cb(audio_in_h input); +/** + * @brief Ignores session for input. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] input The handle to the audio input + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + */ +int audio_in_ignore_session(audio_in_h input); +/** + * @brief Sets an asynchronous(event) callback function to handle recording PCM (pulse-code modulation) data. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @details @a callback will be called when you can read a PCM data. + * It might cause dead lock if change the state of audio handle in callback. + * (ex: audio_in_destroy, audio_in_prepare, audio_in_unprepare) + * Recommend to use as a VOIP only. + * Recommend not to hold callback too long.(it affects latency) + * + * @remarks @a input must be created using audio_in_create(). + * + * @param[in] input An audio input handle + * @param[in] callback notify stream callback when user can read data (#audio_in_stream_cb) + * @param[in] userdata user data to be retrieved when callback is called + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory + * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * + * @see audio_out_set_stream_cb() + */ +int audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* userdata); /** - * @brief Gets the sample audio format (8-bit or 16-bit) of audio input data stream + * @brief Unregisters the callback function. * - * @param[in] input The handle to the audio input - * @param[out] type The audio sample type + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. + * @param[in] input The handle to the audio input + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ -int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type); + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * + * @see audio_in_set_interrupted_cb() + */ +int audio_in_unset_stream_cb(audio_in_h input); + +/** + * @brief peek from audio in buffer + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @details This function works correctly only with read, write callback. Otherwise it won't operate as intended. + * + * @remarks @a Works only in asynchronous(event) mode. This will just retrieve buffer pointer from audio in buffer. Drop after use. + * + * @param[in] input The handle to the audio input + * @param[out] buffer start buffer pointer of peeked audio in data + * @param[in,out] length amount of audio in data to be peeked + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * + * @see audio_in_drop() + */ +int audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length); +/** + * @brief drop peeked audio buffer. + * + * @details This function works correctly only with read, write callback. Otherwise it won't operate as intended. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @remarks @a Works only in asynchronous(event) mode. This will remove audio in data from actual stream buffer. Use this if peeked data is not needed anymore. + * + * @param[in] input The handle to the audio input + * @return 0 on success, otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported + * + * @see audio_in_peek() + */ +int audio_in_drop(audio_in_h input); // -// AUDIO OUTPUT +// AUDIO OUTPUT // /** * @} -*/ + */ /** * @addtogroup CAPI_MEDIA_AUDIO_OUT_MODULE @@ -265,159 +503,277 @@ int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type); */ /** - * @brief Creates an audio device instance and returns an output handle to play PCM (pulse-code modulation) data - * @details This function is used for audio output initialization. - * @remarks @a output must be released audio_out_destroy() by you. + * @brief Called when audio out data can be written in asynchronous(event) mode. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @remarks @a use audio_out_write() to write pcm data inside this callback. + * @param[in] handle The handle to the audio output + * @param[in] nbytes The amount of audio in data which can be written. + * @param[in] userdata The user data passed from the callback registration function + * + * @see audio_out_set_stream_cb() + */ +typedef void (*audio_out_stream_cb)(audio_out_h handle, size_t nbytes, void *userdata); + +/** + * @brief Creates an audio device instance and returns an output handle to play PCM (pulse-code modulation) data. + + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @details This function is used for audio output initialization. * - * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz] - * @param[in] channel The audio channel type, mono, or stereo - * @param[in] type The type of audio sample (8- or 16-bit) - * @param[in] sound_type The type of sound (#sound_type_e) - * @param[out] output An audio output handle will be created, if successful + * @remarks @a output must be released by audio_out_destroy(). * - * @return 0 on success, otherwise a negative error value. + * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz] + * @param[in] channel The audio channel type (mono or stereo) + * @param[in] type The type of audio sample (8- or 16-bit) + * @param[in] sound_type The type of sound (#sound_type_e) + * @param[out] output An audio output handle is created on success + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened - * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error * * @see audio_out_destroy() -*/ -int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h *output); - - + */ +int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h *output); /** - * @brief Releases the audio output handle, along with all its resources + * @brief Releases the audio output handle, along with all its resources. * - * @param[in] output The handle to the audio output to destroy + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. - * @retval #AUDIO_IO_ERROR_NONE Successful - * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory - * @retval #AUDIO_IO_ERROR_DEVICE_NOT_CLOSED Device not closed + * @param[in] output The handle to the audio output to destroy + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory + * @retval #AUDIO_IO_ERROR_DEVICE_NOT_CLOSED Device not closed * * @see audio_out_create() -*/ + */ int audio_out_destroy(audio_out_h output); /** - * @brief Prepare playing audio out, this must be called before audio_out_write() - * @param[in] input The handle to the audio output - * @return 0 on success, otherwise a negative error value. + * @brief Prepares playing audio output, this must be called before audio_out_write(). + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * * @see audio_out_unprepare() */ int audio_out_prepare(audio_out_h output); - - /** - * @brief Unprepare playing audio out. - * @param[in] input The handle to the audio output - * @return 0 on success, otherwise a negative error value. + * @brief Unprepares playing audio output. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * * @see audio_out_prepare() */ int audio_out_unprepare(audio_out_h output); - - - /** - * @brief Starts writing the audio data to the device + * @brief Starts writing the audio data to the device. * - * @param[in] output The handle to the audio output - * @param[in,out] buffer The PCM buffer address - * @param[in] length The length of PCM buffer (in bytes) + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return Written data size on success, otherwise a negative error value. - * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #AUDIO_IO_ERROR_INVALID_BUFFER Invalid buffer pointer - * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error -*/ + * @param[in] output The handle to the audio output + * @param[in,out] buffer The PCM buffer address + * @param[in] length The length of the PCM buffer (in bytes) + * @return The written data size on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_BUFFER Invalid buffer pointer + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + */ int audio_out_write(audio_out_h output, void *buffer, unsigned int length); - - /** - * @brief Gets the size to be allocated for audio output buffer - * @param[in] output The handle to the audio output - * @param[out] size The suggested buffer size (in bytes). \n The maximum size is 1 MB. + * @brief Gets the size to be allocated for the audio output buffer. * - * @return 0 on success, otherwise a negative error value. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @param[out] size The suggested buffer size (in bytes, the maximum size is 1 MB) + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter - * @see audio_out_write() * -*/ + * @see audio_out_write() + */ int audio_out_get_buffer_size(audio_out_h output, int *size); - - /** - * @brief Gets the sample rate of audio output data stream + * @brief Gets the sample rate of the audio output data stream. * - * @param[in] output The handle to the audio output - * @param[out] sample_rate The audio sample rate in Hertz (8000 ~ 48000) + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. + * @param[in] output The handle to the audio output + * @param[out] sample_rate The audio sample rate in Hertz (8000 ~ 48000) + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ + */ int audio_out_get_sample_rate(audio_out_h output, int *sample_rate); - - /** - * @brief Gets the channel type of audio output data stream - * - * @details The audio channel type defines whether the audio is mono or stereo. + * @brief Gets the channel type of the audio output data stream. + * @details The audio channel type defines whether the audio is mono or stereo. * - * @param[in] output The handle to the audio output - * @param[out] channel The audio channel type + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. + * @param[in] output The handle to the audio output + * @param[out] channel The audio channel type + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ + */ int audio_out_get_channel(audio_out_h output, audio_channel_e *channel); +/** + * @brief Gets the sample audio format (8-bit or 16-bit) of the audio output data stream. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @param[out] type The audio sample type + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + */ +int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type); /** - * @brief Gets the sample audio format (8-bit or 16-bit) of audio output data stream + * @brief Gets the sound type supported by the audio output device. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @param[in] output The handle to the audio output - * @param[out] type The audio sample type - * @return 0 on success, otherwise a negative error value. + * @param[in] output The handle to the audio output + * @param[out] type The sound type + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ -int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type); + */ +int audio_out_get_sound_type(audio_out_h output, sound_type_e *type); +/** + * @brief Registers a callback function to be invoked when the audio output handle is interrupted or the interrupt is completed. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * + * @post audio_io_interrupted_cb() will be invoked. + * @see audio_out_unset_interrupted_cb() + * @see audio_io_interrupted_cb() + */ +int audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data); +/** + * @brief Unregisters the callback function. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * + * @see audio_out_set_interrupted_cb() + */ +int audio_out_unset_interrupted_cb(audio_out_h output); /** - * @brief Gets the sound type supported by the audio output device - * @param[in] output The handle to the audio output - * @param[out] type The sound type + * @brief Ignores session for output. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @return 0 on success, otherwise a negative error value. + * @param[in] output The handle to the audio output + * @return @c 0 on success, + * otherwise a negative error value * @retval #AUDIO_IO_ERROR_NONE Successful * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter -*/ -int audio_out_get_sound_type(audio_out_h output, sound_type_e *type); + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + */ +int audio_out_ignore_session(audio_out_h output); +/** + * @brief Sets an asynchronous(event) callback function to handle playing PCM (pulse-code modulation) data. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @details @a callback will be called when you can write a PCM data. + * It might cause dead lock if change the state of audio handle in callback. + * (ex: audio_in_destroy, audio_in_prepare, audio_in_unprepare) + * Recommend to use as a VOIP only. + * Recommend not to hold callback too long.(it affects latency) + * + * @remarks @a output must be created using audio_out_create(). + * + * @param[in] output An audio output handle + * @param[in] callback notify stream callback when user can write data (#audio_out_stream_cb) + * @param[in] userdata user data to be retrieved when callback is called + * @return 0 on success, otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory + * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened + * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error + * + * @see audio_in_set_stream_cb() + */ +int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* userdata); +/** + * @brief Unregisters the callback function. + * + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * + * @param[in] output The handle to the audio output + * @return 0 on success, otherwise a negative error value + * @retval #AUDIO_IO_ERROR_NONE Successful + * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation + * + * @see audio_out_set_stream_cb() + */ +int audio_out_unset_stream_cb(audio_out_h output); /** * @} -*/ + */ #ifdef __cplusplus } diff --git a/include/audio_io_private.h b/include/audio_io_private.h index 9645657..6fbe201 100644 --- a/include/audio_io_private.h +++ b/include/audio_io_private.h @@ -1,47 +1,87 @@ /* -* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __TIZEN_MEDIA_AUDIO_IO_PRIVATE_H__ -#define __TIZEN_MEDIA_AUDIO_IO_PRIVATE_H__ -#include <audio_io.h> +#define __TIZEN_MEDIA_AUDIO_IO_PRIVATE_H__ + #include <sound_manager.h> #include <mm_sound.h> +#include "audio_io.h" + +/* + * Internal Macros + */ + +#define AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA (AUDIO_IO_INTERRUPTED_BY_NOTIFICATION + 1) +#define AUDIO_IO_INTERRUPTED_BY_RESUMABLE_CANCELED (AUDIO_IO_INTERRUPTED_BY_NOTIFICATION + 2) + +#define AUDIO_IO_CHECK_CONDITION(condition,error,msg) \ + if(condition) {} else \ + { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \ + +#define AUDIO_IO_NULL_ARG_CHECK(arg) \ + AUDIO_IO_CHECK_CONDITION(arg != NULL, AUDIO_IO_ERROR_INVALID_PARAMETER, "AUDIO_IO_ERROR_INVALID_PARAMETER" ) #ifdef __cplusplus extern "C" { #endif - typedef struct _audio_in_s{ MMSoundPcmHandle_t mm_handle; + int is_async; + int is_loopback; int _buffer_size; int _sample_rate; audio_channel_e _channel; - audio_sample_type_e _type; + audio_sample_type_e _type; + audio_io_interrupted_cb user_cb; + void* user_data; + audio_in_stream_cb stream_cb; + void* stream_userdata; } audio_in_s; typedef struct _audio_out_s{ MMSoundPcmHandle_t mm_handle; + int is_async; + int is_loopback; int _buffer_size; int _sample_rate; audio_channel_e _channel; audio_sample_type_e _type; sound_type_e _sound_type; + audio_io_interrupted_cb user_cb; + void* user_data; + audio_out_stream_cb stream_cb; + void* stream_userdata; } audio_out_s; +int __convert_audio_io_error_code(int code, char *func_name); +int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type); +int __mm_sound_pcm_capture_msg_cb (int message, void *param, void *user_param); +audio_io_interrupted_code_e __translate_interrupted_code (int code); + +int audio_in_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type , int source_type, audio_in_h* input); + +int audio_in_set_callback_private(audio_in_h input, audio_in_stream_cb callback, void* userdata); + +int audio_out_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output); + +int audio_out_set_callback_private(audio_out_h output, audio_out_stream_cb callback, void* userdata); + + #ifdef __cplusplus } #endif diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 0516ec5..c742d92 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,17 +1,20 @@ +#sbs-git:slp/api/audio-io capi-media-audio-io 0.1.0 da265a7364928d92084360809316e36f666f053f Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.1.0 -Release: 10 -Group: TO_BE/FILLED_IN -License: TO BE FILLED IN +Version: 0.2.28 +Release: 0 +Group: libdevel +License: Apache-2.0 Source0: %{name}-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(mm-sound) +BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(capi-media-sound-manager) BuildRequires: pkgconfig(capi-base-common) -Requires(post): /sbin/ldconfig +Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig +Requires(post): libprivilege-control %description An Audio Input & Audio Output library in Tizen Native API @@ -38,18 +41,22 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} %make_install +mkdir -p %{buildroot}/usr/share/privilege-control -%post -p /sbin/ldconfig +%post +/sbin/ldconfig +/usr/bin/api_feature_loader --verbose --dir=/usr/share/privilege-control %postun -p /sbin/ldconfig %files %{_libdir}/libcapi-media-audio-io.so.* +%manifest capi-media-audio-io.manifest %files devel %{_includedir}/media/audio_io.h %{_libdir}/pkgconfig/*.pc %{_libdir}/libcapi-media-audio-io.so - +#%{_prefix}/bin/audio_io_test diff --git a/src/audio_io.c b/src/audio_io.c index 97a54e1..0b0fec8 100644 --- a/src/audio_io.c +++ b/src/audio_io.c @@ -1,25 +1,24 @@ /* -* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <mm.h> -#include <glib.h> -#include <audio_io_private.h> +#include "audio_io_private.h" #include <dlog.h> #ifdef LOG_TAG @@ -27,171 +26,104 @@ #endif #define LOG_TAG "TIZEN_N_AUDIO_IO" -/* -* Internal Macros -*/ -#define AUDIO_IO_CHECK_CONDITION(condition,error,msg) \ - if(condition) {} else \ - { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \ +#include <mm_sound_pcm_async.h> -#define AUDIO_IO_NULL_ARG_CHECK(arg) \ - AUDIO_IO_CHECK_CONDITION(arg != NULL, AUDIO_IO_ERROR_INVALID_PARAMETER, "AUDIO_IO_ERROR_INVALID_PARAMETER" ) +/* + * Internal Implementation + */ /* -* Internal Implementation -*/ -static int __convert_error_code(int code, char *func_name) -{ - int ret = AUDIO_IO_ERROR_NONE; - char* msg="AUDIO_IO_ERROR_NONE"; - switch(code) - { - case MM_ERROR_NONE: - ret = AUDIO_IO_ERROR_NONE; - msg = "AUDIO_IO_ERROR_NONE"; - break; - case MM_ERROR_INVALID_ARGUMENT: - case MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE: - case MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL: - case MM_ERROR_SOUND_DEVICE_INVALID_FORMAT: - ret = AUDIO_IO_ERROR_INVALID_PARAMETER; - msg = "AUDIO_IO_ERROR_INVALID_PARAMETER"; - break; - case MM_ERROR_SOUND_DEVICE_NOT_OPENED: - ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED; - msg = "AUDIO_IO_ERROR_DEVICE_NOT_OPENED"; - break; - case MM_ERROR_SOUND_INTERNAL: - ret = AUDIO_IO_ERROR_DEVICE_NOT_CLOSED; - msg = "AUDIO_IO_ERROR_DEVICE_NOT_CLOSED"; - break; - case MM_ERROR_SOUND_INVALID_POINTER: - ret = AUDIO_IO_ERROR_INVALID_BUFFER; - msg = "AUDIO_IO_ERROR_INVALID_BUFFER"; - break; - case MM_ERROR_POLICY_BLOCKED: - case MM_ERROR_POLICY_INTERRUPTED: - case MM_ERROR_POLICY_INTERNAL: - case MM_ERROR_POLICY_DUPLICATED: - ret = AUDIO_IO_ERROR_SOUND_POLICY; - msg = "AUDIO_IO_ERROR_SOUND_POLICY"; - break; - } - LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code); - return ret; -} + * Public Implementation + */ -static int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type) +/* Audio In */ +int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input) { - if(sample_rate<8000 || sample_rate > 48000) - { - LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample rate (8000~48000Hz) : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,sample_rate); - return AUDIO_IO_ERROR_INVALID_PARAMETER; - } - if (channel < AUDIO_CHANNEL_MONO || channel > AUDIO_CHANNEL_STEREO) - { - LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid audio channel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,channel); - return AUDIO_IO_ERROR_INVALID_PARAMETER; - } - if (type < AUDIO_SAMPLE_TYPE_U8 || type > AUDIO_SAMPLE_TYPE_S16_LE) - { - LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample typel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,type); - return AUDIO_IO_ERROR_INVALID_PARAMETER; - } - return AUDIO_IO_ERROR_NONE; + return audio_in_create_private (sample_rate, channel, type, SUPPORT_SOURCE_TYPE_DEFAULT, input); } -/* -* Public Implementation -*/ -int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input) +int audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h* input) { - AUDIO_IO_NULL_ARG_CHECK(input); - if(__check_parameter(sample_rate, channel, type)!=AUDIO_IO_ERROR_NONE) - return AUDIO_IO_ERROR_INVALID_PARAMETER; - - audio_in_s * handle; - handle = (audio_in_s*)malloc( sizeof(audio_in_s)); - if (handle != NULL) - memset(handle, 0 , sizeof(audio_in_s)); - else - { - LOGE("[%s] ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)" ,__FUNCTION__,AUDIO_IO_ERROR_OUT_OF_MEMORY ); - return AUDIO_IO_ERROR_OUT_OF_MEMORY; - } - int ret = mm_sound_pcm_capture_open( &handle->mm_handle,sample_rate, channel, type); - if( ret < 0) - { - return __convert_error_code(ret, (char*)__FUNCTION__); - } - else - { - *input = (audio_in_h)handle; - handle->_buffer_size= ret; - handle->_sample_rate= sample_rate; - handle->_channel= channel; - handle->_type= type; - return AUDIO_IO_ERROR_NONE; - } + return audio_in_create_private (sample_rate, channel, type, SUPPORT_SOURCE_TYPE_LOOPBACK, input); } int audio_in_destroy(audio_in_h input) { AUDIO_IO_NULL_ARG_CHECK(input); - audio_in_s * handle = (audio_in_s *) input; - int ret = mm_sound_pcm_capture_close(handle->mm_handle); - if (ret != MM_ERROR_NONE) - { - return __convert_error_code(ret, (char*)__FUNCTION__); + audio_in_s *handle = (audio_in_s *) input; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_capture_close_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_capture_close(handle->mm_handle); } - else - { + if (ret != MM_ERROR_NONE) { free(handle); - return AUDIO_IO_ERROR_NONE; + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); } + free(handle); + + LOGI("[%s] mm_sound_pcm_capture_close() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; } int audio_in_prepare(audio_in_h input) { AUDIO_IO_NULL_ARG_CHECK(input); - audio_in_s * handle = (audio_in_s *) input; - int ret = mm_sound_pcm_capture_start(handle->mm_handle); - if (ret != MM_ERROR_NONE) - { - return __convert_error_code(ret, (char*)__FUNCTION__); + audio_in_s *handle = (audio_in_s *) input; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_capture_start_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_capture_start(handle->mm_handle); + } + + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); } - else - return AUDIO_IO_ERROR_NONE; + + LOGI("[%s] mm_sound_pcm_capture_start() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; } int audio_in_unprepare(audio_in_h input) { AUDIO_IO_NULL_ARG_CHECK(input); - audio_in_s * handle = (audio_in_s *) input; - int ret = mm_sound_pcm_capture_stop(handle->mm_handle); - if (ret != MM_ERROR_NONE) - { - return __convert_error_code(ret, (char*)__FUNCTION__); + audio_in_s *handle = (audio_in_s *) input; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_capture_stop_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_capture_stop(handle->mm_handle); + } + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); } - else - return AUDIO_IO_ERROR_NONE; + + LOGI("[%s] mm_sound_pcm_capture_stop() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; } int audio_in_read(audio_in_h input, void *buffer, unsigned int length ) { AUDIO_IO_NULL_ARG_CHECK(input); AUDIO_IO_NULL_ARG_CHECK(buffer); - audio_in_s * handle = (audio_in_s *) input; - int ret; - int result; - ret = mm_sound_pcm_capture_read(handle->mm_handle, (void*) buffer, length); + audio_in_s *handle = (audio_in_s *) input; + int ret = 0; + int result = 0; - if (ret >0) - { - LOGI("[%s] %d bytes read" ,__FUNCTION__, ret); - return ret; + if (handle->is_async) { + LOGE ("audio_in_read doesn't operate in async mode!!!, use audio_in_peek/audio_in_drop instead"); + return AUDIO_IO_ERROR_INVALID_OPERATION; } + ret = mm_sound_pcm_capture_read(handle->mm_handle, (void*) buffer, length); + if (ret > 0) + return ret; + switch(ret) { case MM_ERROR_SOUND_INVALID_STATE: @@ -199,7 +131,7 @@ int audio_in_read(audio_in_h input, void *buffer, unsigned int length ) LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION); break; default: - result = __convert_error_code(ret, (char*)__FUNCTION__); + result = __convert_audio_io_error_code(ret, (char*)__FUNCTION__); break; } return result; @@ -209,8 +141,11 @@ int audio_in_get_buffer_size(audio_in_h input, int *size) { AUDIO_IO_NULL_ARG_CHECK(input); AUDIO_IO_NULL_ARG_CHECK(size); - audio_in_s * handle = (audio_in_s *) input; + audio_in_s *handle = (audio_in_s *) input; + *size = handle->_buffer_size; + + LOGI("[%s] buffer size = %d",__FUNCTION__, *size); return AUDIO_IO_ERROR_NONE; } @@ -218,18 +153,23 @@ int audio_in_get_sample_rate(audio_in_h input, int *sample_rate) { AUDIO_IO_NULL_ARG_CHECK(input); AUDIO_IO_NULL_ARG_CHECK(sample_rate); - audio_in_s * handle = (audio_in_s *) input; + audio_in_s *handle = (audio_in_s *) input; + *sample_rate = handle->_sample_rate; + + LOGI("[%s] sample rate = %d",__FUNCTION__, *sample_rate); return AUDIO_IO_ERROR_NONE; } - int audio_in_get_channel(audio_in_h input, audio_channel_e *channel) { AUDIO_IO_NULL_ARG_CHECK(input); AUDIO_IO_NULL_ARG_CHECK(channel); - audio_in_s * handle = (audio_in_s *) input; + audio_in_s *handle = (audio_in_s *) input; + *channel = handle->_channel; + + LOGI("[%s] channel = %d",__FUNCTION__, *channel); return AUDIO_IO_ERROR_NONE; } @@ -237,104 +177,221 @@ int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type) { AUDIO_IO_NULL_ARG_CHECK(input); AUDIO_IO_NULL_ARG_CHECK(type); - audio_in_s * handle = (audio_in_s *) input; + audio_in_s *handle = (audio_in_s *) input; + *type = handle->_type; + + LOGI("[%s] sample type = %d",__FUNCTION__, *type); return AUDIO_IO_ERROR_NONE; } -int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output) +int audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data) { - AUDIO_IO_NULL_ARG_CHECK(output); - if(__check_parameter(sample_rate, channel, type)!=AUDIO_IO_ERROR_NONE) - return AUDIO_IO_ERROR_INVALID_PARAMETER; - if(sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_CALL) - { - LOGE("[%s] ERROR : AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample sound type : %d" ,__FUNCTION__,AUDIO_IO_ERROR_INVALID_PARAMETER,sound_type ); - return AUDIO_IO_ERROR_INVALID_PARAMETER; + AUDIO_IO_NULL_ARG_CHECK(input); + AUDIO_IO_NULL_ARG_CHECK(callback); + audio_in_s *handle = (audio_in_s *) input; + + handle->user_cb = callback; + handle->user_data = user_data; + + LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data); + return AUDIO_IO_ERROR_NONE; +} + +int audio_in_unset_interrupted_cb(audio_in_h input) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + audio_in_s * handle = (audio_in_s *) input; + + handle->user_cb = NULL; + handle->user_data = NULL; + + LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data); + return AUDIO_IO_ERROR_NONE; +} + +int audio_in_ignore_session(audio_in_h input) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + audio_in_s * handle = (audio_in_s *) input; + int ret = 0; + + if (handle->is_async) { + LOGE ("Not supported in async mode"); + return AUDIO_IO_ERROR_INVALID_OPERATION; } - - audio_out_s * handle; - handle = (audio_out_s*)malloc( sizeof(audio_out_s)); - if (handle != NULL) - memset(handle, 0 , sizeof(audio_out_s)); - else - { - LOGE("[%s] ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)" ,__FUNCTION__,AUDIO_IO_ERROR_OUT_OF_MEMORY ); - return AUDIO_IO_ERROR_OUT_OF_MEMORY; + + ret = mm_sound_pcm_capture_ignore_session(handle->mm_handle); + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + + LOGI("[%s] mm_sound_pcm_capture_ignore_session() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; +} + +int audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* userdata) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + AUDIO_IO_NULL_ARG_CHECK(callback); + return audio_in_set_callback_private(input, callback, userdata); +} + +int audio_in_unset_stream_cb(audio_in_h input) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + return audio_in_set_callback_private(input, NULL, NULL); +} + +int audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + AUDIO_IO_NULL_ARG_CHECK(buffer); + audio_in_s *handle = (audio_in_s *) input; + int ret = 0; + int result = 0; + +#ifdef _AUDIO_IO_DEBUG_TIMING_ + LOGE("handle->is_async : %d", handle->is_async); +#endif + if (!handle->is_async) { + LOGE ("audio_in_peek doesn't operate in poll mode!!!, use audio_in_read instead"); + return AUDIO_IO_ERROR_INVALID_OPERATION; } - int ret = mm_sound_pcm_play_open(&handle->mm_handle,sample_rate, channel, type, sound_type); - if( ret < 0) + +#ifdef _AUDIO_IO_DEBUG_TIMING_ + LOGE("before mm_sound_pcm_capture_peek(handle[%p], buffer[%p], length[%d])", handle->mm_handle, buffer, length); +#endif + ret = mm_sound_pcm_capture_peek(handle->mm_handle, buffer, length); +#ifdef _AUDIO_IO_DEBUG_TIMING_ + LOGE("after mm_sound_pcm_capture_peek() ret[%d]", ret); +#endif + switch(ret) { - return __convert_error_code(ret, (char*)__FUNCTION__); + case MM_ERROR_SOUND_INVALID_STATE: + result = AUDIO_IO_ERROR_INVALID_OPERATION; + LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION); + break; + default: + result = __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + break; } - else + return result; +} + +int audio_in_drop(audio_in_h input) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + audio_in_s *handle = (audio_in_s *) input; + int ret = 0; + int result = 0; + + if (!handle->is_async) { + LOGE ("audio_in_drop doesn't operate in poll mode!!!, use audio_in_read instead"); + return AUDIO_IO_ERROR_INVALID_OPERATION; + } + + ret = mm_sound_pcm_capture_drop(handle->mm_handle); + if (ret == MM_ERROR_NONE) { + return ret; + } + + switch(ret) { - *output = (audio_out_h)handle; - handle->_buffer_size= ret; - handle->_sample_rate= sample_rate; - handle->_channel= channel; - handle->_type= type; - handle->_sound_type= sound_type; - return AUDIO_IO_ERROR_NONE; + case MM_ERROR_SOUND_INVALID_STATE: + result = AUDIO_IO_ERROR_INVALID_OPERATION; + LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION); + break; + default: + result = __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + break; } + return result; +} + +/* Audio Out */ +int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output) +{ + return audio_out_create_private(sample_rate, channel, type, sound_type, output); } int audio_out_destroy(audio_out_h output) { AUDIO_IO_NULL_ARG_CHECK(output); - audio_out_s * handle = (audio_out_s *) output; - int ret = mm_sound_pcm_play_close(handle->mm_handle); - if (ret != MM_ERROR_NONE) - { - return __convert_error_code(ret, (char*)__FUNCTION__); + audio_out_s *handle = (audio_out_s *) output; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_play_close_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_play_close(handle->mm_handle); } - else - { + if (ret != MM_ERROR_NONE) { free(handle); - return AUDIO_IO_ERROR_NONE; + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); } + free(handle); + + LOGI("[%s] mm_sound_pcm_play_close() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; } int audio_out_prepare(audio_out_h output) { AUDIO_IO_NULL_ARG_CHECK(output); - audio_out_s * handle = (audio_out_s *) output; - int ret = mm_sound_pcm_play_start(handle->mm_handle); - if (ret != MM_ERROR_NONE) - { - return __convert_error_code(ret, (char*)__FUNCTION__); + audio_out_s *handle = (audio_out_s *) output; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_play_start_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_play_start(handle->mm_handle); + } + + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); } - else - return AUDIO_IO_ERROR_NONE; + + LOGI("[%s] mm_sound_pcm_play_start() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; } int audio_out_unprepare(audio_out_h output) { AUDIO_IO_NULL_ARG_CHECK(output); - audio_out_s * handle = (audio_out_s *) output; - int ret = mm_sound_pcm_play_stop(handle->mm_handle); - if (ret != MM_ERROR_NONE) - { - return __convert_error_code(ret, (char*)__FUNCTION__); + audio_out_s *handle = (audio_out_s *) output; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_play_stop_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_play_stop(handle->mm_handle); } - else - return AUDIO_IO_ERROR_NONE; -} + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("[%s] mm_sound_pcm_play_stop() success",__FUNCTION__); + return AUDIO_IO_ERROR_NONE; +} int audio_out_write(audio_out_h output, void* buffer, unsigned int length) { AUDIO_IO_NULL_ARG_CHECK(output); AUDIO_IO_NULL_ARG_CHECK(buffer); - audio_out_s * handle = (audio_out_s *) output; - int ret; - ret = mm_sound_pcm_play_write(handle->mm_handle, (void*) buffer, length); - if (ret >0) - { - LOGI("[%s] %d bytes written" ,__FUNCTION__, ret); - return ret; + audio_out_s *handle = (audio_out_s *) output; + int ret = MM_ERROR_NONE; + + if (handle->is_async) { + ret = mm_sound_pcm_play_write_async(handle->mm_handle, (void*) buffer, length); + } else { + ret = mm_sound_pcm_play_write(handle->mm_handle, (void*) buffer, length); } + + if (ret > 0) + return ret; + switch(ret) { case MM_ERROR_SOUND_INVALID_STATE: @@ -342,58 +399,126 @@ int audio_out_write(audio_out_h output, void* buffer, unsigned int length) LOGE("[%s] (0x%08x) : Not playing started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION); break; default: - ret = __convert_error_code(ret, (char*)__FUNCTION__); + ret = __convert_audio_io_error_code(ret, (char*)__FUNCTION__); break; } return ret; } - int audio_out_get_buffer_size(audio_out_h output, int *size) { AUDIO_IO_NULL_ARG_CHECK(output); AUDIO_IO_NULL_ARG_CHECK(size); - audio_out_s * handle = (audio_out_s *) output; + audio_out_s *handle = (audio_out_s *) output; + *size = handle->_buffer_size; + + LOGI("[%s] buffer size = %d",__FUNCTION__, *size); return AUDIO_IO_ERROR_NONE; } - int audio_out_get_sample_rate(audio_out_h output, int *sample_rate) { AUDIO_IO_NULL_ARG_CHECK(output); AUDIO_IO_NULL_ARG_CHECK(sample_rate); - audio_out_s * handle = (audio_out_s *) output; + audio_out_s *handle = (audio_out_s *) output; + *sample_rate = handle->_sample_rate; + + LOGI("[%s] sample rate = %d",__FUNCTION__, *sample_rate); return AUDIO_IO_ERROR_NONE; } - int audio_out_get_channel(audio_out_h output, audio_channel_e *channel) { AUDIO_IO_NULL_ARG_CHECK(output); AUDIO_IO_NULL_ARG_CHECK(channel); - audio_out_s * handle = (audio_out_s *) output; + audio_out_s *handle = (audio_out_s *) output; + *channel = handle->_channel; + + LOGI("[%s] channel = %d",__FUNCTION__, *channel); return AUDIO_IO_ERROR_NONE; } - int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type) { AUDIO_IO_NULL_ARG_CHECK(output); AUDIO_IO_NULL_ARG_CHECK(type); - audio_out_s * handle = (audio_out_s *) output; + audio_out_s *handle = (audio_out_s *) output; + *type = handle->_type; + + LOGI("[%s] sample type = %d",__FUNCTION__, *type); return AUDIO_IO_ERROR_NONE; } - int audio_out_get_sound_type(audio_out_h output, sound_type_e *type) { AUDIO_IO_NULL_ARG_CHECK(output); AUDIO_IO_NULL_ARG_CHECK(type); - audio_out_s * handle = (audio_out_s *) output; + audio_out_s *handle = (audio_out_s *) output; + *type = handle->_sound_type; + + LOGI("[%s] sound type = %d",__FUNCTION__, *type); + return AUDIO_IO_ERROR_NONE; +} + +int audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data) +{ + AUDIO_IO_NULL_ARG_CHECK(output); + AUDIO_IO_NULL_ARG_CHECK(callback); + audio_out_s *handle = (audio_out_s *) output; + + handle->user_cb = callback; + handle->user_data = user_data; + + LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data); return AUDIO_IO_ERROR_NONE; } + +int audio_out_unset_interrupted_cb(audio_out_h output) +{ + AUDIO_IO_NULL_ARG_CHECK(output); + audio_out_s *handle = (audio_out_s *) output; + + handle->user_cb = NULL; + handle->user_data = NULL; + + LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data); + return AUDIO_IO_ERROR_NONE; +} + +int audio_out_ignore_session(audio_out_h output) +{ + AUDIO_IO_NULL_ARG_CHECK(output); + audio_out_s *handle = (audio_out_s *) output; + int ret = 0; + + if (handle->is_async) { + LOGE ("Not supported in async mode"); + return AUDIO_IO_ERROR_INVALID_OPERATION; + } + + ret = mm_sound_pcm_play_ignore_session(handle->mm_handle); + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("[%s] mm_sound_pcm_play_ignore_session() success",__FUNCTION__); + + return AUDIO_IO_ERROR_NONE; +} + +int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* userdata) +{ + AUDIO_IO_NULL_ARG_CHECK(output); + AUDIO_IO_NULL_ARG_CHECK(callback); + return audio_out_set_callback_private(output, callback, userdata); +} + +int audio_out_unset_stream_cb(audio_out_h output) +{ + AUDIO_IO_NULL_ARG_CHECK(output); + return audio_out_set_callback_private(output, NULL, NULL); +} diff --git a/src/audio_io_private.c b/src/audio_io_private.c new file mode 100644 index 0000000..abacab6 --- /dev/null +++ b/src/audio_io_private.c @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <mm.h> +#include "audio_io_private.h" +#include <dlog.h> + +#include <mm_sound_pcm_async.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "TIZEN_N_AUDIO_IO" + +/* + * Internal Implementation + */ + +int __convert_audio_io_error_code(int code, char *func_name) +{ + int ret = AUDIO_IO_ERROR_INVALID_OPERATION; + char* msg = "AUDIO_IO_ERROR_INVALID_OPERATION"; + + switch(code) + { + case MM_ERROR_NONE: + ret = AUDIO_IO_ERROR_NONE; + msg = "AUDIO_IO_ERROR_NONE"; + break; + case MM_ERROR_INVALID_ARGUMENT: + case MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE: + case MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL: + case MM_ERROR_SOUND_DEVICE_INVALID_FORMAT: + ret = AUDIO_IO_ERROR_INVALID_PARAMETER; + msg = "AUDIO_IO_ERROR_INVALID_PARAMETER"; + break; + case MM_ERROR_SOUND_DEVICE_NOT_OPENED: + ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED; + msg = "AUDIO_IO_ERROR_DEVICE_NOT_OPENED"; + break; + case MM_ERROR_SOUND_PERMISSION_DENIED: + ret = AUDIO_IO_ERROR_PERMISSION_DENIED; + msg = "AUDIO_IO_ERROR_PERMISSION_DENIED"; + break; + case MM_ERROR_SOUND_INTERNAL: + ret = AUDIO_IO_ERROR_INVALID_OPERATION; + msg = "AUDIO_IO_ERROR_INVALID_OPERATION"; + break; + case MM_ERROR_SOUND_INVALID_POINTER: + ret = AUDIO_IO_ERROR_INVALID_BUFFER; + msg = "AUDIO_IO_ERROR_INVALID_BUFFER"; + break; + case MM_ERROR_POLICY_BLOCKED: + case MM_ERROR_POLICY_INTERRUPTED: + case MM_ERROR_POLICY_INTERNAL: + case MM_ERROR_POLICY_DUPLICATED: + ret = AUDIO_IO_ERROR_SOUND_POLICY; + msg = "AUDIO_IO_ERROR_SOUND_POLICY"; + break; + } + if(ret != AUDIO_IO_ERROR_NONE) { + LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code); + } + return ret; +} + +int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type) +{ + if(sample_rate<8000 || sample_rate > 48000) { + LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample rate (8000~48000Hz) : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,sample_rate); + return AUDIO_IO_ERROR_INVALID_PARAMETER; + } + if (channel < AUDIO_CHANNEL_MONO || channel > AUDIO_CHANNEL_STEREO) { + LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid audio channel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,channel); + return AUDIO_IO_ERROR_INVALID_PARAMETER; + } + if (type < AUDIO_SAMPLE_TYPE_U8 || type > AUDIO_SAMPLE_TYPE_S16_LE) { + LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample typel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,type); + return AUDIO_IO_ERROR_INVALID_PARAMETER; + } + return AUDIO_IO_ERROR_NONE; +} + +//LCOV_EXCL_START +audio_io_interrupted_code_e __translate_interrupted_code (int code) +{ + audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED; + + switch(code) + { + case MM_MSG_CODE_INTERRUPTED_BY_CALL_END: + case MM_MSG_CODE_INTERRUPTED_BY_ALARM_END: + case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END: + case MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END: + e = AUDIO_IO_INTERRUPTED_COMPLETED; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_MEDIA: + case MM_MSG_CODE_INTERRUPTED_BY_OTHER_PLAYER_APP: + e = AUDIO_IO_INTERRUPTED_BY_MEDIA; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_CALL_START: + e = AUDIO_IO_INTERRUPTED_BY_CALL; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG: + e = AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT: + e = AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_ALARM_START: + e = AUDIO_IO_INTERRUPTED_BY_ALARM; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START: + e = AUDIO_IO_INTERRUPTED_BY_NOTIFICATION; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START: + e = AUDIO_IO_INTERRUPTED_BY_EMERGENCY; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_MEDIA: + e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA; + break; + + case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_CANCELED: + e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_CANCELED; + break; + } + + return e; +} + +int __mm_sound_pcm_capture_msg_cb (int message, void *param, void *user_param) +{ + audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED; + audio_in_s *handle = (audio_in_s *) user_param; + MMMessageParamType *msg = (MMMessageParamType*)param; + + LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code); + + if (handle->user_cb == NULL) { + LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__); + return 0; + } + + if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) { + e = __translate_interrupted_code (msg->code); + } else if (message == MM_MESSAGE_SOUND_PCM_CAPTURE_RESTRICTED) { + /* TODO : handling restricted code is needed */ + /* e = _translate_restricted_code (msg->code); */ + } + + handle->user_cb (e, handle->user_data); + + return 0; +} + +static int __mm_sound_pcm_playback_msg_cb (int message, void *param, void *user_param) +{ + audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED; + audio_out_s *handle = (audio_out_s *) user_param; + MMMessageParamType *msg = (MMMessageParamType*)param; + + LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code); + + if (handle->user_cb == NULL) { + LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__); + return 0; + } + + if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) { + e = __translate_interrupted_code (msg->code); + } + + handle->user_cb (e, handle->user_data); + + return 0; +} +//LCOV_EXCL_STOP + +static int __audio_in_stream_cb (void* p, int nbytes, void* userdata) +{ + audio_in_s *handle = (audio_in_s *) userdata; + +#ifdef _AUDIO_IO_DEBUG_TIMING_ + LOGI("<< p=%p, nbytes=%d, userdata=%p", p, nbytes, userdata); +#endif + + if (handle && handle->stream_cb) { + handle->stream_cb ((audio_in_h)handle, nbytes, handle->stream_userdata); +#ifdef _AUDIO_IO_DEBUG_TIMING_ + LOGI("<< handle->stream_cb(handle:%p, nbytes:%d, handle->stream_userdata:%p)", p, nbytes, userdata); +#endif + } else { + LOGI("No stream callback is set. Skip this"); + } + return 0; +} + +static int __audio_out_stream_cb (void* p, int nbytes, void* userdata) +{ + audio_out_s *handle = (audio_out_s *) userdata; + bool is_started = false; + char * dummy = NULL; + +#ifdef _AUDIO_IO_DEBUG_TIMING_ + LOGI(">> p=%p, nbytes=%d, userdata=%p", p, nbytes, userdata); +#endif + + if (handle) { + mm_sound_pcm_is_started_async(handle->mm_handle, &is_started); + if (is_started) { + if (handle->stream_cb) { + handle->stream_cb ((audio_out_h)handle, nbytes, handle->stream_userdata); + } else { + LOGI("Started state but No stream callback is set. Skip this"); + } + } else { + LOGI("Not started....write dummy data"); + if ((dummy = (char*)malloc(nbytes)) != NULL) { + memset (dummy, 0, nbytes); + mm_sound_pcm_play_write_async(handle->mm_handle, (void*) dummy, nbytes); + free (dummy); + LOGI("write done!!!"); + } else { + LOGE("ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY); + } + } + } else { + LOGE("Handle is invalid..."); + } + + return 0; +} + +int audio_in_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type , int source_type, audio_in_h* input) +{ + int ret = 0; + audio_in_s *handle = NULL; + + /* input condition check */ + AUDIO_IO_NULL_ARG_CHECK(input); + if(__check_parameter(sample_rate, channel, type) != AUDIO_IO_ERROR_NONE) + return AUDIO_IO_ERROR_INVALID_PARAMETER; + + /* Create Handle & Fill information */ + if ((handle = (audio_in_s*)malloc( sizeof(audio_in_s))) == NULL) { + LOGE("ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY); + return AUDIO_IO_ERROR_OUT_OF_MEMORY; + } + memset(handle, 0, sizeof(audio_in_s)); + + /* Capture open */ + if ((ret = mm_sound_pcm_capture_open_ex(&handle->mm_handle, sample_rate, channel, type, source_type)) < 0) { + LOGE("mm_sound_pcm_capture_open_ex() failed [0x%x]", ret); + goto ERROR; + } + LOGI("mm_sound_pcm_capture_open_ex() success"); + + + if (source_type == SUPPORT_SOURCE_TYPE_LOOPBACK) + { + handle->is_loopback = 1; + } + + handle->_buffer_size = ret; /* return by pcm_open */ + handle->_sample_rate = sample_rate; + handle->_channel = channel; + handle->_type = type; + + /* Set message interrupt callback */ + if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_capture_msg_cb, handle)) < 0) { + LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret); + goto ERROR; + } + LOGI("mm_sound_pcm_set_message_callback() success"); + + /* Handle assign */ + *input = (audio_in_h)handle; + + return AUDIO_IO_ERROR_NONE; + +ERROR: + if (handle) + free (handle); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); +} + +int audio_in_set_callback_private(audio_in_h input, audio_in_stream_cb callback, void* userdata) +{ + AUDIO_IO_NULL_ARG_CHECK(input); + + int ret = AUDIO_IO_ERROR_NONE; + int source_type = SUPPORT_SOURCE_TYPE_DEFAULT; + audio_in_s* handle = (audio_in_s*)input; + + // at first, release existing audio handle + if (handle->is_async) { + ret = mm_sound_pcm_capture_close_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_capture_close(handle->mm_handle); + } + + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + + // Initialize flags + handle->stream_cb = NULL; + handle->stream_userdata = NULL; + handle->is_async = 0; + + // Checks loopback type + if (handle->is_loopback == 1) { + source_type = SUPPORT_SOURCE_TYPE_LOOPBACK; + } + + /* Async (callback exists) or Sync (otherwise) */ + if (callback != NULL) { + handle->stream_cb = callback; + handle->stream_userdata = userdata; + handle->is_async = 1; + + /* Capture open */ + if ((ret = mm_sound_pcm_capture_open_async(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, source_type, + (mm_sound_pcm_stream_cb_t)__audio_in_stream_cb, handle)) < 0) { + LOGE("mm_sound_pcm_capture_open_async() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_capture_open_async() success"); + + /* Set message interrupt callback */ + if ((ret = mm_sound_pcm_set_message_callback_async(handle->mm_handle, __mm_sound_pcm_capture_msg_cb, handle)) < 0) { + LOGE("mm_sound_pcm_set_message_callback_async() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_set_message_callback_async() success"); + } else { + /* Capture open */ + if ((ret = mm_sound_pcm_capture_open_ex(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, source_type)) < 0) { + LOGE("mm_sound_pcm_capture_open_ex() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_capture_open_ex() success"); + + /* Set message interrupt callback */ + if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_capture_msg_cb, handle)) < 0) { + LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_set_message_callback() success"); + } + + handle->_buffer_size = ret; /* return by pcm_open */ + + return AUDIO_IO_ERROR_NONE; +} + +int audio_out_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output) +{ + audio_out_s *handle = NULL; + int ret = 0; + + /* input condition check */ + AUDIO_IO_NULL_ARG_CHECK(output); + if(__check_parameter(sample_rate, channel, type)!=AUDIO_IO_ERROR_NONE) + return AUDIO_IO_ERROR_INVALID_PARAMETER; + if(sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_VOICE) { + LOGE("ERROR : AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample sound type : %d", + AUDIO_IO_ERROR_INVALID_PARAMETER,sound_type ); + return AUDIO_IO_ERROR_INVALID_PARAMETER; + } + + /* Create Handle & Fill information */ + if ((handle = (audio_out_s*)malloc( sizeof(audio_out_s))) == NULL) { + LOGE("ERROR : AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY); + return AUDIO_IO_ERROR_OUT_OF_MEMORY; + } + memset(handle, 0 , sizeof(audio_out_s)); + + if ((ret = mm_sound_pcm_play_open(&handle->mm_handle,sample_rate, channel, type, sound_type)) < 0) { + LOGE("mm_sound_pcm_play_open() failed [0x%x]", ret); + goto ERROR; + } + LOGI("mm_sound_pcm_play_open() success"); + + handle->_buffer_size = ret; /* return by pcm_open */ + handle->_sample_rate = sample_rate; + handle->_channel = channel; + handle->_type = type; + handle->_sound_type = sound_type; + + /* Set message interrupt callback */ + if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_playback_msg_cb, handle)) < 0) { + LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret); + goto ERROR; + } + LOGI("mm_sound_pcm_set_message_callback() success"); + + /* Handle assign */ + *output = (audio_out_h)handle; + + return AUDIO_IO_ERROR_NONE; + +ERROR: + if (handle) + free (handle); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); +} + +int audio_out_set_callback_private(audio_out_h output, audio_out_stream_cb callback, void* userdata) +{ + AUDIO_IO_NULL_ARG_CHECK(output); + + int ret = AUDIO_IO_ERROR_NONE; + audio_out_s* handle = (audio_out_s*)output; + + // at first, release existing mm handle + if (handle->is_async) { + ret = mm_sound_pcm_play_close_async(handle->mm_handle); + } else { + ret = mm_sound_pcm_play_close(handle->mm_handle); + } + + if (ret != MM_ERROR_NONE) { + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + + // Initialize flags + handle->stream_cb = NULL; + handle->stream_userdata = NULL; + handle->is_async = 0; + + /* Async (callback exists) or Sync (otherwise) */ + if (callback != NULL) { + handle->stream_cb = callback; + handle->stream_userdata = userdata; + handle->is_async = 1; + + /* Playback open */ + if ((ret = mm_sound_pcm_play_open_async(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, handle->_sound_type, + (mm_sound_pcm_stream_cb_t)__audio_out_stream_cb, handle)) < 0) { + LOGE("mm_sound_pcm_play_open_async() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_play_open_async() success"); + + /* Set message interrupt callback */ + if ((ret = mm_sound_pcm_set_message_callback_async(handle->mm_handle, __mm_sound_pcm_playback_msg_cb, handle)) < 0) { + LOGE("mm_sound_pcm_set_message_callback_async() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_set_message_callback_async() success"); + + } else { + if ((ret = mm_sound_pcm_play_open(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, handle->_sound_type)) < 0) { + LOGE("mm_sound_pcm_play_open() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_play_open() success"); + + /* Set message interrupt callback */ + if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_playback_msg_cb, handle)) < 0) { + LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret); + return __convert_audio_io_error_code(ret, (char*)__FUNCTION__); + } + LOGI("mm_sound_pcm_set_message_callback() success"); + } + + handle->_buffer_size = ret; /* return by pcm_open */ + + return AUDIO_IO_ERROR_NONE; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 795370d..b59cc26 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,7 @@ FOREACH(flag ${${fw_test}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror -pie") aux_source_directory(. sources) FOREACH(src ${sources}) @@ -16,3 +16,4 @@ FOREACH(src ${sources}) TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS}) ENDFOREACH() +INSTALL(TARGETS audio_io_test DESTINATION bin) diff --git a/test/audio_io_test.c b/test/audio_io_test.c index 2647c16..f28da0e 100755..100644 --- a/test/audio_io_test.c +++ b/test/audio_io_test.c @@ -1,32 +1,575 @@ /* -* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <audio_io.h> +#include <unistd.h> +#include <audio_io.h> + +static int ch_table[3] = { 0, AUDIO_CHANNEL_MONO, AUDIO_CHANNEL_STEREO }; + +void play_file(char *file, int length, int ch) +{ + audio_out_h output; + FILE* fp = fopen (file, "r"); + if (fp == NULL) { + printf ("fopen failed\n"); + return; + } + + char * buf = malloc (length); + if (buf == NULL) { + printf ("malloc failed\n"); + fclose (fp); + return; + } + + printf ("start to play [%s][%d][%d]\n", file, length, ch); + audio_out_create(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output); + if (fread (buf, 1, length, fp) != length) { + printf ("error!!!!\n"); + } + + audio_out_prepare(output); + audio_out_write(output, buf, length); + audio_out_unprepare(output); + + audio_out_destroy (output); + + fclose (fp); + + printf ("play done\n"); +} + +#define DUMP_FILE "/root/test.raw" + + +void play_file_sample(char *file, int frequency, int ch, int type) +{ + audio_out_h output; + int file_size = 0; + int read_bytes = 0; + int buffer_size = 0; + char * buf = NULL; + + if(ch < 0 || ch > 2) { + ch = 0; + } + + FILE* fp = fopen (file, "r"); + if (fp == NULL) { + printf("open failed\n"); + return; + } + /*Get the size*/ + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + printf ("start to play [%s] of size [%d] with [%d][%d][%d]\n", file, file_size, frequency, ch, type); + if (type) { + audio_out_create(frequency, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output); + } + else { + audio_out_create(frequency, ch_table[ch] ,AUDIO_SAMPLE_TYPE_U8, SOUND_TYPE_MEDIA, &output); + } + audio_out_get_buffer_size(output, &buffer_size); + + buf = (char *) malloc(buffer_size); + if (buf == NULL) { + printf ("malloc failed\n"); + audio_out_destroy (output); + fclose (fp); + return; + } + audio_out_prepare(output); + + while (file_size > 0) { + read_bytes = fread (buf, 1, buffer_size, fp); + printf ("Read %d Requested - %d\n", read_bytes, buffer_size); + audio_out_write(output, buf, read_bytes); + file_size = file_size - read_bytes; + } + + audio_out_unprepare(output); + audio_out_destroy (output); + + free(buf); + fclose (fp); + printf ("play done\n"); +} + +int audio_io_test(int length, int num, int ch) +{ + int ret, size, i; + audio_in_h input; + if ((ret = audio_in_create(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, &input)) == AUDIO_IO_ERROR_NONE) { + ret = audio_in_ignore_session(input); + if (ret != 0) { + printf ("ERROR, set session mix\n"); + audio_in_destroy(input); + return 0; + } + + ret = audio_in_prepare(input); + if (ret != 0) { + printf ("ERROR, prepare\n"); + audio_in_destroy(input); + return 0; + } + + FILE* fp = fopen (DUMP_FILE, "wb+"); -int audio_io_test() + if (fp == NULL) { + printf ("ERROR, file open failed\n"); + audio_in_destroy(input); + return 0; + } + + if ((ret = audio_in_get_buffer_size(input, &size)) == AUDIO_IO_ERROR_NONE) { + size = length; + char *buffer = alloca(size); + + for (i=0; i<num; i++) { + printf ("### loop = %d ============== \n", i); + if ((ret = audio_in_read(input, (void*)buffer, size)) > AUDIO_IO_ERROR_NONE) { + fwrite (buffer, size, sizeof(char), fp); + printf ("PASS, size=%d, ret=%d\n", size, ret); + } + else { + printf ("FAIL, size=%d, ret=%d\n", size, ret); + } + } + } + + fclose (fp); + + audio_in_destroy(input); + } + + play_file (DUMP_FILE, length*num, ch); + + return 1; +} + + +int audio_io_loopback_in_test() { - return 1; + int ret, size; + audio_in_h input; + FILE* fp = fopen ("/tmp/dump_test.raw", "wb+"); + + if(fp == NULL) { + printf("open failed \n"); + return 0; + } + + if ((ret = audio_in_create(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, &input)) == AUDIO_IO_ERROR_NONE) { + ret = audio_in_ignore_session(input); + if (ret != 0) { + printf ("ERROR, set session mix\n"); + goto exit; + } + + ret = audio_in_prepare(input); + if (ret != 0) { + printf ("ERROR, prepare\n"); + goto exit; + } + + ret = audio_in_get_buffer_size(input, &size); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_get_buffer_size failed.\n"); + goto exit; + } + + while(1) { + char *buffer = alloca(size); + if ((ret = audio_in_read(input, (void*)buffer, size)) > AUDIO_IO_ERROR_NONE) { + fwrite (buffer, size, sizeof(char), fp); + printf ("PASS, size=%d, ret=%d\n", size, ret); + } + else { + printf ("FAIL, size=%d, ret=%d\n", size, ret); + } + } + } + +exit: + audio_in_destroy(input); + + fclose (fp); + + return ret; + +} + +int audio_io_loopback_test() +{ + int ret, size; + audio_in_h input; + audio_out_h output; + char *buffer = NULL; + + ret = audio_in_create(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, &input); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_create_ex failed. \n"); + return 0; + } + + ret = audio_out_create(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_CALL, &output); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_out_create failed. \n"); + return 0; + } + + ret = audio_in_prepare(input); + if (ret != 0) { + printf ("audio_in_prepare failed.\n"); + audio_in_destroy(input); + return 0; + } else { + ret = audio_in_get_buffer_size(input, &size); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_get_buffer_size failed.\n"); + return 0; + } + else { + printf("size(%d)\n", size); + buffer = alloca(size); + } + } + + ret = audio_out_prepare(output); + if (ret != 0) { + printf ("audio_out_prepare failed.\n"); + audio_out_destroy(output); + return 0; + } + + if(buffer == NULL) { + printf("buffer is null\n"); + return 0; + } + + while(1) { + ret = audio_in_read(input, (void*)buffer, size); + if(ret > AUDIO_IO_ERROR_NONE) { + ret = audio_out_write(output, buffer, size); + if(ret > AUDIO_IO_ERROR_NONE) { + printf("audio read/write success. buffer(%p), size(%d)\n", buffer, size); + } else { + printf("audio read success, write failed. buffer(%p), size(%d)\n", buffer, size); + } + } else + printf("audio read/write failed. buffer(%p), size(%d)\n", buffer, size); + } + +} + +audio_in_h input; +audio_out_h output; + +FILE* fp_r = NULL; +FILE* fp_w = NULL; + +static void _audio_io_stream_read_cb (audio_in_h handle, size_t nbytes, void *userdata) +{ + const void * buffer = NULL; + +// printf("_audio_io_stream_read_cb : handle=%p, nbytes=%d, userdata=%p\n", handle, nbytes, userdata); + + if (nbytes > 0) { + audio_in_peek (handle, &buffer, &nbytes); + if (fp_w) { + fwrite(buffer, sizeof(char), nbytes, fp_w); + } + audio_in_drop (handle); + } +} + +static void _audio_io_stream_write_cb (audio_out_h handle, size_t nbytes, void *userdata) +{ + char* buffer = NULL; + int ret = 0; + +// printf("_audio_io_stream_write_cb : handle=%p, nbytes=%d, userdata=%p\n", handle, nbytes, userdata); + + if (nbytes > 0) { + buffer = malloc (nbytes); + if (buffer == NULL) { + printf ("malloc failed\n"); + return; + } + memset (buffer, 0, nbytes); + + ret = fread (buffer, 1, nbytes, fp_r); + if (ret != nbytes) { + printf ("Error!!!! %d/%d", ret, nbytes); + } + + ret = audio_out_write(handle, buffer, nbytes); + if(ret > AUDIO_IO_ERROR_NONE) { +// printf("audio write success. buffer(%p), nbytes(%d)\n", buffer, nbytes); + } + + free (buffer); + } +} + +void _audio_out_interrupted_cb (audio_io_interrupted_code_e code, void *user_data) +{ + int ret = 0; + static audio_io_interrupted_code_e old_code; + + printf ("old code = %d, code = %d, user_data = %p\n", old_code, code, user_data); + + if (code == AUDIO_IO_INTERRUPTED_COMPLETED && + (old_code == AUDIO_IO_INTERRUPTED_BY_CALL || + old_code == AUDIO_IO_INTERRUPTED_BY_ALARM || + old_code == AUDIO_IO_INTERRUPTED_BY_EMERGENCY || + old_code == AUDIO_IO_INTERRUPTED_BY_NOTIFICATION)) + { + ret = audio_out_prepare(output); + if(ret > AUDIO_IO_ERROR_NONE) { + printf("RESUME : audio_out_prepare() error[%x]", ret); + } + } + old_code = code; +} + +void _audio_in_interrupted_cb (audio_io_interrupted_code_e code, void *user_data) +{ + int ret = 0; + static audio_io_interrupted_code_e old_code; + + printf ("old code = %d, code = %d, user_data = %p\n", old_code, code, user_data); + + if (code == AUDIO_IO_INTERRUPTED_COMPLETED && + (old_code == AUDIO_IO_INTERRUPTED_BY_CALL || + old_code == AUDIO_IO_INTERRUPTED_BY_ALARM || + old_code == AUDIO_IO_INTERRUPTED_BY_EMERGENCY || + old_code == AUDIO_IO_INTERRUPTED_BY_NOTIFICATION)) + { + ret = audio_in_prepare(input); + if(ret > AUDIO_IO_ERROR_NONE) { + printf("RESUME : audio_in_prepare() error[%x]", ret); + } + } + old_code = code; +} + +int _convert_cmd_and_run(char cmd, int mode) { + int ret = 0; + switch (cmd) { + case 'P': + if(mode & 0x01) ret = audio_out_prepare(output); + if(mode & 0x02) ret = audio_in_prepare(input); + break; + case 'u': + if(mode & 0x01) ret = audio_out_unprepare(output); + if(mode & 0x02) ret = audio_in_unprepare(input); + break; + case 'i': +#ifdef _SESSION_SOUND_MANAGER_API_ + ret = sound_manager_set_session_type(SOUND_SESSION_TYPE_MEDIA); + if (ret) { + printf ("fail to sound_manager_set_session_type(), ret(0x%x)\n", ret); + } + ret = sound_manager_set_media_session_option (SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START, SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY); + if (ret) { + printf ("fail to sound_manager_set_media_session_option(), ret(0x%x)\n", ret); + } +#endif + break; + case 'q': /* quit */ + ret = 1; + break; + default: + ret = 1; + break; + } + return ret; +} + +int audio_io_async_test(int mode) +{ + int ret, size; + char *buffer = NULL; + + char cmd = 0; + int cmd_ret; + + int read_mode = (mode & 0x02); + int write_mode = (mode & 0x01); + + if (read_mode) { + printf ("audio_in_create\n"); + ret = audio_in_create(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, &input); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_create_ex failed. \n"); + return 0; + } + printf ("audio_in_create success!!! [%p]\n", input); + + ret = audio_in_set_stream_cb(input, _audio_io_stream_read_cb, NULL); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_set_stream_cb failed. \n"); + return 0; + } + printf ("audio_in_set_stream_cb success!!! [%p]\n", input); + + fp_w = fopen( "/tmp/pcm_w.raw", "w"); + } + + if (write_mode) { + printf ("before audio_out_create\n"); + getchar(); + printf ("audio_out_create\n"); + ret = audio_out_create(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_out_create failed. \n"); + return 0; + } + printf ("audio_out_create success!!! [%p]\n", output); + + ret = audio_out_set_stream_cb(output, _audio_io_stream_write_cb, NULL); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_out_set_stream_cb failed. \n"); + return 0; + } + printf ("audio_out_set_stream_cb success!!! [%p]\n", input); + + ret = audio_out_set_interrupted_cb(output, _audio_out_interrupted_cb, output); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_out_set_interrupted_cb failed. \n"); + return 0; + } + + fp_r = fopen( "/tmp/pcm.raw", "r"); + } + + if (read_mode) { + printf ("before audio_in_prepare\n"); + getchar(); + printf ("audio_in_prepare\n"); + ret = audio_in_prepare(input); + if (ret != 0) { + printf ("audio_in_prepare failed.\n"); + audio_in_destroy(input); + return 0; + } else { + ret = audio_in_get_buffer_size(input, &size); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_get_buffer_size failed.\n"); + return 0; + } + else { + printf("size(%d)\n", size); + buffer = alloca(size); + } + } + + if(buffer == NULL) { + printf("buffer is null\n"); + return 0; + } + + ret = audio_in_set_interrupted_cb(input, _audio_in_interrupted_cb, input); + if(ret != AUDIO_IO_ERROR_NONE) { + printf ("audio_in_set_interrupted_cb failed. \n"); + return 0; + } + } + + if (write_mode) { + printf ("before audio_out_prepare\n"); + getchar(); + printf ("audio_out_prepare\n"); + ret = audio_out_prepare(output); + if (ret != 0) { + printf ("audio_out_prepare failed.\n"); + audio_out_destroy(output); + return 0; + } + } + + //getchar(); + do { + printf ("command(q:quit) : "); + cmd = (char) getchar(); + if(cmd != '\n') getchar(); + cmd_ret = _convert_cmd_and_run(cmd, mode); + printf (" - result code : %d\n", cmd_ret); + } while (cmd != 'q'); + + //printf ("loop start\n"); + //for (i=0; i<10; i++) { + // printf ("-------- %d -------\n",i); + // usleep (1000000); + //} + + //getchar(); + + if (read_mode) { + printf ("audio_in_unprepare\n"); + audio_in_unprepare(input); + printf ("audio_in_destroy\n"); + audio_in_destroy(input); + + fclose(fp_w); + fp_w = NULL; + } + + getchar(); + + if (write_mode) { + printf ("audio_out_unprepare\n"); + audio_out_unprepare(output); + printf ("audio_out_destroy\n"); + audio_out_destroy(output); + + fclose(fp_r); + fp_r = NULL; + } + + return 0; } int main(int argc, char ** argv) { - audio_io_test(); - return 0; + if ( argc == 2 && !strcmp(argv[1],"call-forwarding-loop")) { + audio_io_loopback_test(); + } else if ( argc == 2 && !strcmp(argv[1],"call-forwarding-in")) { + audio_io_loopback_in_test(); + } else if ( argc == 3 && !strcmp(argv[1],"async")) { + audio_io_async_test(atoi(argv[2])); + } else if (argc == 4) { + printf ("run with [%s][%s][%s]\n", argv[1],argv[2],argv[3]); +#if 0 + audio_io_test(atoi (argv[1]), atoi (argv[2]), atoi(argv[3])); +#endif + } else if (argc == 6) { + play_file_sample(argv[2], atoi(argv[3]), atoi(argv[4]), atoi(argv[5])); + } else { + printf ("1. usage : audio_io_test [length to read] [number of iteration] [channels]\n"); + printf ("2. usage : audio_io_test mirroring\n"); + printf ("3. Uasge : audio_io_test play <filename> <sample rate> <channels> <type(0:U8)>"); + } + return 0; } |