diff options
author | Gilbok Lee <gilbok.lee@samsung.com> | 2016-10-20 19:44:41 +0900 |
---|---|---|
committer | Gilbok Lee <gilbok.lee@samsung.com> | 2016-11-03 19:25:54 +0900 |
commit | 4dd8d5309b074cab27a5dac23dd92cbc1d47803b (patch) | |
tree | 63d0e5232a97a964a613331b3f6ca82f28b991ed /src | |
parent | 6779ede5625e9c3003c06d8b8399a7cc9bcf1ed7 (diff) | |
download | libmm-radio-4dd8d5309b074cab27a5dac23dd92cbc1d47803b.tar.gz libmm-radio-4dd8d5309b074cab27a5dac23dd92cbc1d47803b.tar.bz2 libmm-radio-4dd8d5309b074cab27a5dac23dd92cbc1d47803b.zip |
First version of libmm-radio using radio-hal
[Version] 0.2.7
[Profile] Mobile
[Issue Type] Refactoring
Change-Id: I332bae2294a30988afb5a8c65864336277b1d5c9
Diffstat (limited to 'src')
-rwxr-xr-x | src/Makefile.am | 49 | ||||
-rw-r--r-- | src/include/mm_radio.h | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | src/include/mm_radio_priv.h | 17 | ||||
-rw-r--r-- | src/include/mm_radio_priv_hal.h | 216 | ||||
-rw-r--r--[-rwxr-xr-x] | src/include/mm_radio_sound_focus.h (renamed from src/include/mm_radio_audio_focus.h) | 24 | ||||
-rw-r--r-- | src/include/mm_radio_utils.h | 24 | ||||
-rw-r--r-- | src/include/radio_hal_interface.h | 56 | ||||
-rw-r--r-- | src/include/tizen-radio.h | 264 | ||||
-rw-r--r--[-rwxr-xr-x] | src/mm_radio.c | 15 | ||||
-rwxr-xr-x | src/mm_radio_audio_focus.c | 181 | ||||
-rw-r--r-- | src/mm_radio_priv_emulator.c | 187 | ||||
-rw-r--r--[-rwxr-xr-x] | src/mm_radio_priv_hal.c (renamed from src/mm_radio_priv.c) | 1050 | ||||
-rw-r--r-- | src/mm_radio_sound_focus.c | 355 | ||||
-rw-r--r-- | src/radio_hal_interface.c | 353 |
14 files changed, 1946 insertions, 851 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index fae2c44..1b67d95 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,26 +3,43 @@ lib_LTLIBRARIES = libmmfradio.la includelibmmfradiodir = $(includedir)/mmf includelibmmfradio_HEADERS = include/mm_radio.h -libmmfradio_la_SOURCES = mm_radio.c \ - mm_radio_audio_focus.c -if ENABLE_EMULATOR -libmmfradio_la_SOURCES += mm_radio_priv_emulator.c -else -libmmfradio_la_SOURCES += mm_radio_priv.c -endif +libmmfradio_la_SOURCES = mm_radio.c libmmfradio_la_CFLAGS = -I. -I./include \ $(GTHREAD_CFLAGS) \ $(MMCOMMON_CFLAGS) \ - $(MMSESSION_CFLAGS) \ - $(MMSOUND_CFLAGS) \ - $(GST_CFLAGS) \ - $(GSTAPP_CFLAGS) \ -DMMF_LOG_OWNER=0x200000 -DMMF_DEBUG_PREFIX=\"MM-RADIO\" libmmfradio_la_LIBADD = $(GTHREAD_LIBS) \ - $(MMCOMMON_LIBS) \ - $(MMSESSION_LIBS) \ - $(MMSOUND_LIBS) \ - $(GST_LIBS) \ - $(GSTAPP_LIBS)
\ No newline at end of file + $(MMCOMMON_LIBS) + +if ENABLE_EMULATOR +libmmfradio_la_SOURCES += mm_radio_priv_emulator.c + +libmmfradio_la_CFLAGS += $(GST_CFLAGS) \ + $(GSTAPP_CFLAGS) + +libmmfradio_la_LIBADD += $(GST_LIBS) \ + $(GSTAPP_LIBS) +else +libmmfradio_la_SOURCES += mm_radio_priv_hal.c \ + radio_hal_interface.c +endif + +if ENABLE_SOUND_FOCUS +libmmfradio_la_SOURCES += mm_radio_sound_focus.c + +libmmfradio_la_CFLAGS += $(MMSESSION_CFLAGS) \ + $(MMSOUND_CFLAGS) \ + -DTIZEN_FEATURE_SOUND_FOCUS + +libmmfradio_la_LIBADD += $(MMSESSION_LIBS) \ + $(MMSOUND_LIBS) +endif + +if ENABLE_SOUND_VSTREAM +libmmfradio_la_CFLAGS += $(SOUNDMGR_CFLAGS) \ + -DTIZEN_FEATURE_SOUND_VSTREAM + +libmmfradio_la_LIBADD += $(SOUNDMGR_LIBS) +endif diff --git a/src/include/mm_radio.h b/src/include/mm_radio.h index 9106199..493280e 100644 --- a/src/include/mm_radio.h +++ b/src/include/mm_radio.h @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio.h * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2000 - 2016 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. diff --git a/src/include/mm_radio_priv.h b/src/include/mm_radio_priv.h index b6569bb..ca8dfe5 100755..100644 --- a/src/include/mm_radio_priv.h +++ b/src/include/mm_radio_priv.h @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio_priv.h * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2000 - 2016 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. @@ -18,7 +16,7 @@ * limitations under the License. * */ - + #ifndef __MM_Radio_INTERNAL_H__ #define __MM_Radio_INTERNAL_H__ @@ -35,7 +33,10 @@ #include <mm_types.h> #include <mm_message.h> -#include "mm_radio_audio_focus.h" +#ifdef TIZEN_FEATURE_SOUND_FOCUS +#include "mm_radio_sound_focus.h" +#endif + #include "mm_radio.h" #include "mm_radio_utils.h" #include <linux/videodev2.h> @@ -184,7 +185,9 @@ typedef struct { int prev_seek_freq; MMRadioSeekDirectionType seek_direction; - MMRadioAudioFocus sm; +#ifdef TIZEN_FEATURE_SOUND_FOCUS + mm_radio_sound_focus sound_focus; +#endif int freq; #ifdef USE_GST_PIPELINE diff --git a/src/include/mm_radio_priv_hal.h b/src/include/mm_radio_priv_hal.h new file mode 100644 index 0000000..e214df1 --- /dev/null +++ b/src/include/mm_radio_priv_hal.h @@ -0,0 +1,216 @@ +/* + * mm_radio_priv_hal.h + * + * Copyright (c) 2000 - 2016 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 __MM_Radio_INTERNAL_H__ +#define __MM_Radio_INTERNAL_H__ + +/*=========================================================================================== + INCLUDE FILES +========================================================================================== */ +#include <stdio.h> +#include <stdbool.h> +#include <unistd.h> +#include <malloc.h> +#include <pthread.h> +#include <signal.h> + +#include <mm_types.h> +#include <mm_message.h> + +#ifdef TIZEN_FEATURE_SOUND_FOCUS +#include "mm_radio_sound_focus.h" +#endif + +#ifdef TIZEN_FEATURE_SOUND_VSTREAM +#include <media/sound_manager.h> +#include <media/sound_manager_internal.h> +#endif + +#include "mm_radio.h" +#include "mm_radio_utils.h" +#include "radio_hal_interface.h" +#include <linux/videodev2.h> + +#ifdef __cplusplus + extern "C" { +#endif + +/*=========================================================================================== + GLOBAL DEFINITIONS AND DECLARATIONS FOR MODULE +========================================================================================== */ + +/*--------------------------------------------------------------------------- + GLOBAL #defines: +---------------------------------------------------------------------------*/ +#define SAMPLEDELAY 15000 + +/* si470x dependent define */ +#define SYSCONFIG1 4 /* System Configuration 1 */ +#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable */ +#define SYSCONFIG1_RDS_OFFSET 12 /* bits 12..12: RDS Enable Offset */ + +#define SYSCONFIG2 5 /* System Configuration 2 */ +#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ +#define SYSCONFIG2_SEEKTH_OFFSET 8 /* bits 15..08: RSSI Seek Threshold Offset */ + +#define SYSCONFIG3 6 /* System Configuration 3 */ +#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */ +#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */ +#define SYSCONFIG3_SKSNR_OFFSET 4 /* bits 07..04: Seek SNR Threshold Offset */ +#define SYSCONFIG3_SKCNT_OFFSET 0 /* bits 03..00: Seek FM Impulse Detection Threshold Offset */ + +#define DEFAULT_CHIP_MODEL "radio-si470x" + +/*--------------------------------------------------------------------------- + GLOBAL CONSTANT DEFINITIONS: +---------------------------------------------------------------------------*/ +typedef enum { + MMRADIO_COMMAND_CREATE = 0, + MMRADIO_COMMAND_DESTROY, + MMRADIO_COMMAND_REALIZE, + MMRADIO_COMMAND_UNREALIZE, + MMRADIO_COMMAND_START, + MMRADIO_COMMAND_STOP, + MMRADIO_COMMAND_START_SCAN, + MMRADIO_COMMAND_STOP_SCAN, + MMRADIO_COMMAND_SET_FREQ, + MMRADIO_COMMAND_GET_FREQ, + MMRADIO_COMMAND_VOLUME, + MMRADIO_COMMAND_MUTE, + MMRADIO_COMMAND_UNMUTE, + MMRADIO_COMMAND_SEEK, + MMRADIO_COMMAND_SET_REGION, + MMRADIO_COMMAND_GET_REGION, + MMRADIO_COMMAND_NUM +} MMRadioCommand; + +/* max and mix frequency types, KHz */ +typedef enum { + MM_RADIO_FREQ_NONE = 0, + /* min band types */ + MM_RADIO_FREQ_MIN_76100_KHZ = 76100, + MM_RADIO_FREQ_MIN_87500_KHZ = 87500, + MM_RADIO_FREQ_MIN_88100_KHZ = 88100, + /* max band types */ + MM_RADIO_FREQ_MAX_89900_KHZ = 89900, + MM_RADIO_FREQ_MAX_108000_KHZ = 108000, +} MMRadioFreqTypes; + +/* de-emphasis types */ +typedef enum { + MM_RADIO_DEEMPHASIS_NONE = 0, + MM_RADIO_DEEMPHASIS_50_US, + MM_RADIO_DEEMPHASIS_75_US, +} MMRadioDeemphasis; + +/* radio region settings */ +typedef struct { + MMRadioRegionType country; + MMRadioDeemphasis deemphasis; // unit : us + MMRadioFreqTypes band_min; // <- freq. range, unit : KHz + MMRadioFreqTypes band_max; // -> + int channel_spacing; // TBD +} MMRadioRegion_t; + +/*--------------------------------------------------------------------------- + GLOBAL DATA TYPE DEFINITIONS: +---------------------------------------------------------------------------*/ + +typedef struct { + /* radio state */ + int current_state; + int old_state; + int pending_state; + + int cmd; + + /* command lock */ + pthread_mutex_t cmd_lock; + + /* radio attributes */ + MMHandleType *attrs; + + /* message callback */ + MMMessageCallback msg_cb; + void *msg_cb_param; + + /* scan */ + pthread_t scan_thread; + bool stop_scan; + + /* seek */ + pthread_t seek_thread; + pthread_mutex_t seek_cancel_mutex; + bool stop_seek; + bool is_seeking; + int prev_seek_freq; + int is_muted; + int is_ready; + + int seek_unmute; + bool seek_cancel; + + MMRadioSeekDirectionType seek_direction; + +#ifdef TIZEN_FEATURE_SOUND_FOCUS + mm_radio_sound_focus sound_focus; +#endif +#ifdef TIZEN_FEATURE_SOUND_VSTREAM + sound_stream_info_h stream_info; + virtual_sound_stream_h vstream; +#endif + + int freq; + + /* region settings */ + MMRadioRegion_t region_setting; + + mm_radio_hal_interface *hal_inf; + +} mm_radio_t; + +/*=========================================================================================== + GLOBAL FUNCTION PROTOTYPES +========================================================================================== */ +int _mmradio_create_radio(mm_radio_t *radio); +int _mmradio_destroy(mm_radio_t *radio); +int _mmradio_realize(mm_radio_t *radio); +int _mmradio_unrealize(mm_radio_t *radio); +int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param); +int _mmradio_get_state(mm_radio_t *radio, int *pState); +int _mmradio_set_frequency(mm_radio_t *radio, int freq); +int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq); +int _mmradio_mute(mm_radio_t *radio); +int _mmradio_unmute(mm_radio_t *radio); +int _mmradio_start(mm_radio_t *radio); +int _mmradio_stop(mm_radio_t *radio); +int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction); +int _mmradio_start_scan(mm_radio_t *radio); +int _mmradio_stop_scan(mm_radio_t *radio); +int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value); +int _mmradio_apply_region(mm_radio_t*radio, MMRadioRegionType region, bool update); +int _mmradio_get_region_type(mm_radio_t*radio, MMRadioRegionType *type); +int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq); +int _mmradio_get_channel_spacing(mm_radio_t* radio, unsigned int *ch_spacing); + +#ifdef __cplusplus +} +#endif + +#endif /* __MM_Radio_INTERNAL_H__ */ diff --git a/src/include/mm_radio_audio_focus.h b/src/include/mm_radio_sound_focus.h index e14d371..ce8ec8e 100755..100644 --- a/src/include/mm_radio_audio_focus.h +++ b/src/include/mm_radio_sound_focus.h @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio_sound_focus.h * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2000 - 2016 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. @@ -36,18 +34,22 @@ enum { MMRADIO_FOCUS_CB_SKIP_POSTMSG }; typedef struct { + int focus_id; + int watch_id; + unsigned int subscribe_id; + unsigned int device_subs_id; int handle; int pid; int by_focus_cb; int event_src; int snd_session_flags; + int session_type; mm_sound_focus_type_e cur_focus_type; -} MMRadioAudioFocus; - -int mmradio_audio_focus_register(MMRadioAudioFocus* sm, mm_sound_focus_changed_cb callback, void* param); -int mmradio_audio_focus_deregister(MMRadioAudioFocus* sm); -int mmradio_acquire_audio_focus(MMRadioAudioFocus* sm); -int mmradio_release_audio_focus(MMRadioAudioFocus* sm); -void mmradio_get_audio_focus_reason(mm_sound_focus_state_e focus_state, const char *reason_for_change, enum MMMessageInterruptedCode *event_source, int *postMsg); +} mm_radio_sound_focus; +int mmradio_sound_focus_register(mm_radio_sound_focus *sound_focus, mm_sound_focus_changed_cb focus_cb, mm_sound_focus_changed_watch_cb watch_cb, void *param); +int mmradio_sound_focus_deregister(mm_radio_sound_focus *sound_focus); +int mmradio_acquire_sound_focus(mm_radio_sound_focus *sound_focus); +int mmradio_release_sound_focus(mm_radio_sound_focus *sound_focus); +void mmradio_get_sound_focus_reason(mm_sound_focus_state_e focus_state, const char *reason_for_change, enum MMMessageInterruptedCode *event_source, int *postMsg); #endif /* MM_RADIO_AUDIO_FOCUS_H_ */ diff --git a/src/include/mm_radio_utils.h b/src/include/mm_radio_utils.h index 8187adb..d498b59 100644 --- a/src/include/mm_radio_utils.h +++ b/src/include/mm_radio_utils.h @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio_utils.h * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2000 - 2016 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. @@ -25,6 +23,7 @@ #include <assert.h> #include <mm_types.h> #include <mm_error.h> +#include <mm_debug.h> #include <mm_message.h> /* radio log */ @@ -32,7 +31,7 @@ #define MMRADIO_LOG_FLEAVE debug_fleave #define MMRADIO_LOG_DEBUG debug_log #define MMRADIO_LOG_ERROR debug_error -#define MMRADIO_LOG_WARNING debug_warning +#define MMRADIO_LOG_WARNING debug_warning #define MMRADIO_LOG_CRITICAL debug_critical #define MMRADIO_SLOG_DEBUG debug_log /* secure_debug_log */ @@ -41,6 +40,13 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + #define MMRADIO_MAX_INT (2147483647) #define MMRADIO_FREEIF(x) \ @@ -55,6 +61,14 @@ if ( ! x_radio ) \ return MM_ERROR_RADIO_NOT_INITIALIZED; \ } +#define MMRADIO_CHECK_ARG( x_radio ) \ +if ( ! x_radio ) \ +{ \ + debug_error("argument is NULL\n"); \ + return MM_ERROR_COMMON_INVALID_ARGUMENT; \ +} + + #define MMRADIO_CHECK_INSTANCE_RETURN_VOID( x_radio ) \ if ( ! x_radio ) \ { \ diff --git a/src/include/radio_hal_interface.h b/src/include/radio_hal_interface.h new file mode 100644 index 0000000..68bfb14 --- /dev/null +++ b/src/include/radio_hal_interface.h @@ -0,0 +1,56 @@ +/* + * radio_hal_interface.h + * + * Copyright (c) 2000 - 2016 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include "tizen-radio.h" + +typedef enum _seek_direction_type { + SEEK_DIRECTION_UP, /**< Seek upward */ + SEEK_DIRECTION_DOWN /**< Seek downward */ +} seek_direction_type_t; + +typedef struct _mmradio_hal_interface { + void *dl_handle; + void *rh_handle; + radio_interface_t intf; +} mm_radio_hal_interface; + +int radio_hal_interface_init(mm_radio_hal_interface **handle); +int radio_hal_interface_deinit(mm_radio_hal_interface *handle); +int radio_hal_open(mm_radio_hal_interface *radio_handle); +int radio_hal_prepare(mm_radio_hal_interface *radio_handle); +int radio_hal_unprepare(mm_radio_hal_interface *radio_handle); +int radio_hal_close(mm_radio_hal_interface *radio_handle); +int radio_hal_start(mm_radio_hal_interface *radio_handle); +int radio_hal_stop(mm_radio_hal_interface *radio_handle); +int radio_hal_seek(mm_radio_hal_interface *radio_handle, seek_direction_type_t direction); +int radio_hal_get_frequency(mm_radio_hal_interface *radio_handle, uint32_t *frequency); +int radio_hal_set_frequency(mm_radio_hal_interface *radio_handle, uint32_t frequency); +int radio_hal_get_signal_strength(mm_radio_hal_interface *radio_handle, uint32_t *strength); +int radio_hal_mute(mm_radio_hal_interface *radio_handle); +int radio_hal_unmute(mm_radio_hal_interface *radio_handle); +#ifdef __cplusplus +} +#endif diff --git a/src/include/tizen-radio.h b/src/include/tizen-radio.h new file mode 100644 index 0000000..8f6ce17 --- /dev/null +++ b/src/include/tizen-radio.h @@ -0,0 +1,264 @@ +/* + * tizen-radio.h + * + * Copyright (c) 2016 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_RADIO_HAL_H__ +#define __TIZEN_RADIO_HAL_H__ + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file tizen-radio.h + * @brief This file contains the Tizen radio HAL API, related structures and enumerations. + * @since_tizen 3.0 + */ + +/** + * @addtogroup TIZEN_RADIO_HAL_MODULE + * @{ + */ + +/** + * @brief Enumeration for the radio error. + * @since_tizen 3.0 + */ +typedef enum radio_error { + RADIO_ERROR_NONE, + RADIO_ERROR_INVALID_PARAMETER, + RADIO_ERROR_INVALID_STATE, + RADIO_ERROR_INVALID_OPERATION, + RADIO_ERROR_PERMISSION_DENIED, + RADIO_ERROR_NOT_SUPPORTED, + RADIO_ERROR_OUT_OF_MEMORY, + RADIO_ERROR_DEVICE_NOT_PREPARED, + RADIO_ERROR_DEVICE_NOT_OPENED, + RADIO_ERROR_DEVICE_NOT_FOUND, + RADIO_ERROR_DEVICE_NOT_SUPPORTED, + RADIO_ERROR_NO_ANTENNA, + RADIO_ERROR_INTERNAL, + RADIO_ERROR_UNKNOWN +} radio_error_t; + +/** + * @brief Enumeration for the radio seek direction. + * @since_tizen 3.0 + */ +typedef enum radio_seek_direction_type { + RADIO_SEEK_DIRECTION_UP, /**< Seek upward */ + RADIO_SEEK_DIRECTION_DOWN /**< Seek downward */ +} radio_seek_direction_type_t; + +typedef struct radio_interface { + /* create & destroy */ + radio_error_t (*init)(void **radio_hanle); + radio_error_t (*deinit)(void *radio_handle); + radio_error_t (*prepare)(void *radio_handle); + radio_error_t (*unprepare)(void *radio_handle); + radio_error_t (*open)(void *radio_handle); + radio_error_t (*close)(void *radio_handle); + radio_error_t (*start)(void *radio_handle); + radio_error_t (*stop)(void *radio_handle); + radio_error_t (*seek)(void *radio_handle, radio_seek_direction_type_t direction); + radio_error_t (*get_frequency)(void *radio_handle, uint32_t *frequency); + radio_error_t (*set_frequency)(void *radio_handle, uint32_t frequency); + radio_error_t (*mute)(void *radio_handle); + radio_error_t (*unmute)(void *radio_handle); + radio_error_t (*get_signal_strength)(void *radio_handle, uint32_t *strength); +} radio_interface_t; + +/** + * @brief Initializes new handle of radio HAL. + * @since_tizen 3.0 + * @param[out] radio_handle A newly returned handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_OUT_OF_MEMORY Out of memory + * @see radio_deinit() + */ +radio_error_t radio_init(void **radio_handle); + +/** + * @brief Deinitializes handle of camera HAL. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @see radio_init() + */ +radio_error_t radio_deinit(void *radio_handle); + +/** + * @brief Prepare the device of radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_DEVICE_NOT_OPENED The radio device is not opened + * @see radio_unprepare() + */ +radio_error_t radio_prepare(void *radio_handle); + +/** + * @brief Unprepare the device of radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @see radio_prepare() + */ +radio_error_t radio_unprepare(void *radio_handle); + +/** + * @brief Opens the device of radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_DEVICE_NOT_FOUND Failed to find radio device + * @retval #RADIO_ERROR_DEVICE_NOT_OPENED The radio device is not opened + * @retval #RADIO_ERROR_PERMISSION_DENIED The access to the resources can not be granted. + * @retval #RADIO_ERROR_DEVICE_NOT_PREPARED Not prepared the radio device + * @see radio_close() + */ +radio_error_t radio_open(void *radio_handle); + +/** + * @brief Closes the device of radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @see radio_open() + */ +radio_error_t radio_close(void *radio_handle); + +/** + * @brief Starts the device of radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @see radio_stop() + */ +radio_error_t radio_start(void *radio_handle); + +/** + * @brief Stops the device of radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @see radio_start() + */ +radio_error_t radio_stop(void *radio_handle); + +/** + * @brief Seeks (up or down) the effective frequency of the radio. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @param[in] direction The seek direction type (up or down) + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_DEVICE_NOT_OPENED The radio device is not opened + * @retval #RADIO_ERROR_INVALID_OPERATION Invalid operation + */ +radio_error_t radio_seek(void *radio_handle, radio_seek_direction_type_t direction); + +/** + * @brief Gets the radio frequency. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @param[out] frequency The current frequency (khz) + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_DEVICE_NOT_OPENED The radio device is not opened + * @retval #RADIO_ERROR_INVALID_OPERATION Invalid operation + */ +radio_error_t radio_get_frequency(void *radio_handle, uint32_t *frequency); + +/** + * @brief Sets the radio frequency. + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @param[in] frequency The frequency to set (khz) + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_DEVICE_NOT_OPENED The radio device is not opened + * @retval #RADIO_ERROR_INVALID_OPERATION Invalid operation + */ +radio_error_t radio_set_frequency(void *radio_handle, uint32_t frequency); + +/** + * @brief Sets the radio's mute + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_INVALID_OPERATION Invalid operation + */ +radio_error_t radio_mute(void *radio_handle); + +/** + * @brief Unsets the radio's mute + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_INVALID_OPERATION Invalid operation + */ +radio_error_t radio_unmute(void *radio_handle); + +/** + * @brief Gets the current signal strength of the radio + * @since_tizen 3.0 + * @param[in] radio_handle The handle to the radio HAL + * @param[out] strength The current signal strength (dBm) + * @return @c 0 on success, otherwise a negative error value + * @retval #RADIO_ERROR_NONE Successful + * @retval #RADIO_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RADIO_ERROR_INVALID_OPERATION Invalid operation + */ +radio_error_t radio_get_signal_strength(void *radio_handle, uint32_t *strength); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_RADIO_HAL_H__ */ + diff --git a/src/mm_radio.c b/src/mm_radio.c index 2847ee6..5f8b495 100755..100644 --- a/src/mm_radio.c +++ b/src/mm_radio.c @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio.c * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2000 - 2016 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. @@ -26,11 +24,16 @@ ========================================================================================== */ #include <string.h> +#include <glib.h> +#include <mm_types.h> +#include <mm_message.h> #include "mm_radio.h" +#ifdef TIZEN_FEATURE_RADIO_HAL +#include "mm_radio_priv_hal.h" +#else #include "mm_radio_priv.h" +#endif #include "mm_radio_utils.h" -#include <mm_types.h> -#include <mm_message.h> #include "mm_debug.h" /*=========================================================================================== diff --git a/src/mm_radio_audio_focus.c b/src/mm_radio_audio_focus.c deleted file mode 100755 index 6e20751..0000000 --- a/src/mm_radio_audio_focus.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * libmm-radio - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> - * - * 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 <assert.h> -#include <mm_debug.h> -#include "mm_radio_audio_focus.h" -#include "mm_radio_utils.h" -#include "mm_sound_focus.h" -#include "unistd.h" - -int mmradio_audio_focus_register(MMRadioAudioFocus *sm, mm_sound_focus_changed_cb callback, void *param) -{ - /* read mm-session information */ - int session_type = MM_SESSION_TYPE_MEDIA; - int session_flags = 0; - int errorcode = MM_ERROR_NONE; - int pid = getpid(); - int handle; - - MMRADIO_LOG_FENTER(); - - if (!sm) { - MMRADIO_LOG_ERROR("invalid session handle\n"); - return MM_ERROR_RADIO_NOT_INITIALIZED; - } - sm->cur_focus_type = FOCUS_NONE; - - /* read session information */ - errorcode = _mm_session_util_read_information(pid, &session_type, &session_flags); - if (errorcode == MM_ERROR_NONE) { - debug_warning("Read Session Information success. session_type : %d flags: %d \n", session_type, session_flags); - sm->snd_session_flags = session_flags; - session_type = MM_SESSION_TYPE_MEDIA; - } else { - debug_warning("Read Session Information failed. skip sound focus register function. errorcode %x \n", errorcode); - } - - /* check if it's MEDIA type */ - if (session_type != MM_SESSION_TYPE_MEDIA) { - MMRADIO_LOG_DEBUG("session type is not MEDIA (%d)\n", session_type); - return MM_ERROR_RADIO_INTERNAL; - } - - /* check if it's running on the media_server */ - sm->pid = pid; - - MMRADIO_LOG_DEBUG("sound register focus pid[%d]", pid); - - mm_sound_focus_get_id(&handle); - sm->handle = handle; - - if (mm_sound_register_focus_for_session(handle, pid, "radio", callback, param) != MM_ERROR_NONE) { - MMRADIO_LOG_DEBUG("mm_sound_register_focus_for_session is failed\n"); - return MM_ERROR_POLICY_BLOCKED; - } - - MMRADIO_LOG_FLEAVE(); - - return MM_ERROR_NONE; -} - -int mmradio_audio_focus_deregister(MMRadioAudioFocus *sm) -{ - MMRADIO_LOG_FENTER(); - - if (!sm) { - MMRADIO_LOG_ERROR("invalid session handle\n"); - return MM_ERROR_RADIO_NOT_INITIALIZED; - } - - if (MM_ERROR_NONE != mm_sound_unregister_focus(sm->handle)) - MMRADIO_LOG_ERROR("mm_sound_unregister_focus failed\n"); - - MMRADIO_LOG_FLEAVE(); - - return MM_ERROR_NONE; -} - -int mmradio_acquire_audio_focus(MMRadioAudioFocus *sm) -{ - int ret = MM_ERROR_NONE; - mm_sound_focus_type_e focus_type = FOCUS_NONE; - MMRADIO_LOG_FENTER(); - - MMRADIO_LOG_ERROR("mmradio_acquire_audio_focus sm->cur_focus_type : %d\n", sm->cur_focus_type); - - focus_type = FOCUS_FOR_BOTH & ~(sm->cur_focus_type); - if (focus_type != FOCUS_NONE) { - ret = mm_sound_acquire_focus(sm->handle, focus_type, NULL); - if (ret != MM_ERROR_NONE) { - MMRADIO_LOG_ERROR("mm_sound_acquire_focus is failed\n"); - return MM_ERROR_POLICY_BLOCKED; - } - sm->cur_focus_type = FOCUS_FOR_BOTH; - } - - MMRADIO_LOG_FLEAVE(); - return ret; -} - -int mmradio_release_audio_focus(MMRadioAudioFocus *sm) -{ - int ret = MM_ERROR_NONE; - MMRADIO_LOG_FENTER(); - - MMRADIO_LOG_ERROR("mmradio_release_audio_focus sm->cur_focus_type : %d\n", sm->cur_focus_type); - if (sm->cur_focus_type != FOCUS_NONE) { - ret = mm_sound_release_focus(sm->handle, sm->cur_focus_type, NULL); - if (ret != MM_ERROR_NONE) { - MMRADIO_LOG_ERROR("mm_sound_release_focus is failed\n"); - return MM_ERROR_POLICY_BLOCKED; - } - sm->cur_focus_type = FOCUS_NONE; - } - - MMRADIO_LOG_FLEAVE(); - return ret; -} - -#define AUDIO_FOCUS_REASON_MAX 128 - -void mmradio_get_audio_focus_reason(mm_sound_focus_state_e focus_state, const char *reason_for_change, enum MMMessageInterruptedCode *event_source, int *postMsg) -{ - MMRADIO_LOG_FENTER(); - MMRADIO_LOG_ERROR("mmradio_get_audio_focus_reason focus_state : %d reason_for_change :%s\n", focus_state, reason_for_change); - - if (0 == strncmp(reason_for_change, "call-voice", AUDIO_FOCUS_REASON_MAX) - || (0 == strncmp(reason_for_change, "voip", AUDIO_FOCUS_REASON_MAX)) - || (0 == strncmp(reason_for_change, "ringtone-voip", AUDIO_FOCUS_REASON_MAX)) - || (0 == strncmp(reason_for_change, "ringtone-call", AUDIO_FOCUS_REASON_MAX)) - ) { - if (focus_state == FOCUS_IS_RELEASED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_START; - else if (focus_state == FOCUS_IS_ACQUIRED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_END; - *postMsg = true; - } else if (0 == strncmp(reason_for_change, "alarm", AUDIO_FOCUS_REASON_MAX)) { - if (focus_state == FOCUS_IS_RELEASED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_START; - else if (focus_state == FOCUS_IS_ACQUIRED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_END; - *postMsg = true; - } else if (0 == strncmp(reason_for_change, "notification", AUDIO_FOCUS_REASON_MAX)) { - if (focus_state == FOCUS_IS_RELEASED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START; - else if (focus_state == FOCUS_IS_ACQUIRED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END; - *postMsg = true; - } else if (0 == strncmp(reason_for_change, "emergency", AUDIO_FOCUS_REASON_MAX)) { - if (focus_state == FOCUS_IS_RELEASED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START; - else if (focus_state == FOCUS_IS_ACQUIRED) - *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END; - *postMsg = false; - } else if (0 == strncmp(reason_for_change, "media", AUDIO_FOCUS_REASON_MAX)) { - *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA; - *postMsg = false; - } else { - *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA; - *postMsg = false; - } - MMRADIO_LOG_FLEAVE(); -} diff --git a/src/mm_radio_priv_emulator.c b/src/mm_radio_priv_emulator.c index d468ef3..e601266 100644 --- a/src/mm_radio_priv_emulator.c +++ b/src/mm_radio_priv_emulator.c @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio_priv_emulator.c * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2000 - 2016 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. @@ -39,9 +37,11 @@ #include <mm_message.h> #include <time.h> +#ifdef TIZEN_FEATURE_SOUND_FOCUS #include <mm_sound.h> #include <mm_sound_focus.h> #include <mm_sound_device.h> +#endif #include "mm_radio_priv.h" @@ -136,11 +136,14 @@ static bool __is_tunable_frequency(mm_radio_t * radio, int freq); static int __mmradio_set_deemphasis(mm_radio_t * radio); static int __mmradio_set_band_range(mm_radio_t * radio); static int __mmradio_get_wave_num(mm_radio_t * radio); +#ifdef TIZEN_FEATURE_SOUND_FOCUS static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, - mm_sound_focus_state_e focus_state, const char *reason_for_change,int option, + mm_sound_focus_state_e focus_state, const char *reason_for_change, int option, const char *additional_info, void *user_data); -static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data); - +static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, + mm_sound_focus_state_e focus_state, const char *reason_for_change, + const char *additional_info, void *user_data); +#endif /*=========================================================================== FUNCTION DEFINITIONS ========================================================================== */ @@ -234,22 +237,19 @@ int _mmradio_create_radio(mm_radio_t * radio) MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL); - /* add device conneted callback */ - ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, - (mm_sound_device_connected_cb)__mmradio_device_connected_cb, - (void *)radio, &radio->subs_id); - if (ret) { - MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n"); - return MM_ERROR_RADIO_INTERNAL; - } - +#ifdef TIZEN_FEATURE_SOUND_FOCUS /* register to audio focus */ - ret = mmradio_audio_focus_register(&radio->sm, __mmradio_sound_focus_cb, (void *)radio); + ret = mmradio_sound_focus_register(&radio->sound_focus, + (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb, + (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb, + (void *)radio); + if (ret) { /* NOTE : we are dealing it as an error since we cannot expect it's behavior */ MMRADIO_LOG_ERROR("mmradio_audio_focus_register is failed\n"); return MM_ERROR_RADIO_INTERNAL; } +#endif MMRADIO_LOG_FLEAVE(); @@ -305,17 +305,6 @@ int _mmradio_realize(mm_radio_t * radio) MMRADIO_LOG_FLEAVE(); return MM_ERROR_NONE; - -/* error: - if (radio->radio_fd >= 0) { - close(radio->radio_fd); - radio->radio_fd = -1; - } - - MMRADIO_LOG_FLEAVE(); - - return MM_ERROR_RADIO_INTERNAL; -*/ } int _mmradio_unrealize(mm_radio_t * radio) @@ -335,11 +324,15 @@ int _mmradio_unrealize(mm_radio_t * radio) radio->radio_fd = -1; MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL); - ret = mmradio_release_audio_focus(&radio->sm); + +#ifdef TIZEN_FEATURE_SOUND_FOCUS + ret = mmradio_release_sound_focus(&radio->sound_focus); if (ret) { - MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n"); + MMRADIO_LOG_ERROR("mmradio_release_sound_focus is failed\n"); return ret; } +#endif + #ifdef USE_GST_PIPELINE ret = _mmradio_destroy_pipeline(radio); if (ret) { @@ -355,24 +348,21 @@ int _mmradio_unrealize(mm_radio_t * radio) int _mmradio_destroy(mm_radio_t * radio) { - int ret = 0; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY); - ret = mmradio_audio_focus_deregister(&radio->sm); - if (ret) { - MMRADIO_LOG_ERROR("failed to deregister audio focus\n"); - return MM_ERROR_RADIO_INTERNAL; - } + _mmradio_unrealize(radio); - ret = mm_sound_remove_device_connected_callback(radio->subs_id); +#ifdef TIZEN_FEATURE_SOUND_FOCUS + int ret = 0; + ret = mmradio_sound_focus_deregister(&radio->sound_focus); if (ret) { - MMRADIO_LOG_ERROR("mm_sound_remove_device_connected_callback error %d\n", ret); + MMRADIO_LOG_ERROR("failed to deregister sound focus\n"); return MM_ERROR_RADIO_INTERNAL; } - _mmradio_unrealize(radio); +#endif MMRADIO_LOG_FLEAVE(); @@ -585,11 +575,15 @@ int _mmradio_start(mm_radio_t * radio) MMRADIO_SLOG_DEBUG("now tune to frequency : %d\n", radio->freq); - ret = mmradio_acquire_audio_focus(&radio->sm); - if (ret) { - MMRADIO_LOG_ERROR("failed to set audio focus\n"); - return ret; +#ifdef TIZEN_FEATURE_SOUND_FOCUS + if (radio->sound_focus.handle > 0) { + ret = mmradio_acquire_sound_focus(&radio->sound_focus); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("failed to set sound focus"); + return ret; + } } +#endif /* set stored frequency */ _mmradio_set_frequency(radio, radio->freq); @@ -624,6 +618,16 @@ int _mmradio_stop(mm_radio_t * radio) /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */ /* return MM_ERROR_RADIO_NOT_INITIALIZED; */ +#ifdef TIZEN_FEATURE_SOUND_FOCUS + if (radio->sound_focus.handle > 0) { + ret = mmradio_release_sound_focus(&radio->sound_focus); + if (ret) { + MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n"); + return ret; + } + } +#endif + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); #ifdef USE_GST_PIPELINE @@ -1238,8 +1242,9 @@ static bool __mmradio_set_state(mm_radio_t * radio, int new_state) msg.state.previous = radio->old_state; msg.state.current = radio->current_state; +#ifdef TIZEN_FEATURE_SOUND_FOCUS /* post message to application */ - switch (radio->sm.by_focus_cb) { + switch (radio->sound_focus.by_focus_cb) { case MMRADIO_FOCUS_CB_NONE: { msg_type = MM_MESSAGE_STATE_CHANGED; @@ -1251,7 +1256,7 @@ static bool __mmradio_set_state(mm_radio_t * radio, int new_state) { msg_type = MM_MESSAGE_STATE_INTERRUPTED; msg.union_type = MM_MSG_UNION_CODE; - msg.code = radio->sm.event_src; + msg.code = radio->sound_focus.event_src; MMRADIO_POST_MSG(radio, msg_type, &msg); } break; @@ -1260,7 +1265,10 @@ static bool __mmradio_set_state(mm_radio_t * radio, int new_state) default: break; } - +#else + msg_type = MM_MESSAGE_STATE_CHANGED; + MMRADIO_POST_MSG(radio, msg_type, &msg); +#endif MMRADIO_LOG_FLEAVE(); return true; @@ -1276,11 +1284,12 @@ static int __mmradio_get_state(mm_radio_t * radio) return radio->current_state; } +#ifdef TIZEN_FEATURE_SOUND_FOCUS static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, int option, const char *additional_info, void *user_data) { - mm_radio_t *radio = (mm_radio_t *) user_data; + mm_radio_t *radio = (mm_radio_t *)user_data; enum MMMessageInterruptedCode event_source; int result = MM_ERROR_NONE; int postMsg = false; @@ -1288,19 +1297,19 @@ static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); - mmradio_get_audio_focus_reason(focus_state, reason_for_change, &event_source, &postMsg); - radio->sm.event_src = event_source; + mmradio_get_sound_focus_reason(focus_state, reason_for_change, &event_source, &postMsg); + radio->sound_focus.event_src = event_source; switch (focus_state) { case FOCUS_IS_RELEASED:{ - radio->sm.cur_focus_type &= ~focus_type; - radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; + radio->sound_focus.cur_focus_type &= ~focus_type; + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; result = _mmradio_stop(radio); if (result) MMRADIO_LOG_ERROR("failed to stop radio\n"); - MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sm.cur_focus_type); + MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); } break; @@ -1309,14 +1318,14 @@ static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, msg.union_type = MM_MSG_UNION_CODE; msg.code = event_source; - radio->sm.cur_focus_type |= focus_type; + radio->sound_focus.cur_focus_type |= focus_type; - if ((postMsg) && (FOCUS_FOR_BOTH == radio->sm.cur_focus_type)) + if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type)) MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg); - radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_NONE; + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_NONE; - MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sm.cur_focus_type); + MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); } break; @@ -1328,40 +1337,58 @@ static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, MMRADIO_LOG_FLEAVE(); } -static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data) +static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, + mm_sound_focus_state_e focus_state, const char *reason_for_change, + const char *additional_info, void *user_data) { - mm_radio_t *radio = (mm_radio_t *) user_data; + mm_radio_t *radio = (mm_radio_t *)user_data; + enum MMMessageInterruptedCode event_source; int result = MM_ERROR_NONE; - mm_sound_device_type_e type; + int postMsg = false; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); - if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) { - debug_error("getting device type failed"); - } else { - switch (type) { - case MM_SOUND_DEVICE_TYPE_AUDIOJACK: - case MM_SOUND_DEVICE_TYPE_BLUETOOTH: - case MM_SOUND_DEVICE_TYPE_HDMI: - case MM_SOUND_DEVICE_TYPE_MIRRORING: - case MM_SOUND_DEVICE_TYPE_USB_AUDIO: - if (!is_connected) { - MMRADIO_LOG_ERROR("sound device unplugged"); - radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; - radio->sm.event_src = MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG; - - result = _mmradio_stop(radio); - if (result != MM_ERROR_NONE) - MMRADIO_LOG_ERROR("failed to stop radio\n"); - } - break; - default: - break; + mmradio_get_sound_focus_reason(focus_state, reason_for_change, &event_source, &postMsg); + radio->sound_focus.event_src = event_source; + + switch (focus_state) { + case FOCUS_IS_ACQUIRED: { + radio->sound_focus.cur_focus_type &= ~focus_type; + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; + + result = _mmradio_stop(radio); + if (result) + MMRADIO_LOG_ERROR("failed to stop radio\n"); + + MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); } + break; + + case FOCUS_IS_RELEASED: { + MMMessageParamType msg = { 0, }; + msg.union_type = MM_MSG_UNION_CODE; + msg.code = event_source; + + radio->sound_focus.cur_focus_type |= focus_type; + + if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type)) + MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg); + + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_NONE; + + MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); + } + break; + + default: + MMRADIO_LOG_DEBUG("Unknown focus_state\n"); + break; } + MMRADIO_LOG_FLEAVE(); } +#endif int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type) { diff --git a/src/mm_radio_priv.c b/src/mm_radio_priv_hal.c index 4ba943c..6ac3757 100755..100644 --- a/src/mm_radio_priv.c +++ b/src/mm_radio_priv_hal.c @@ -1,9 +1,7 @@ /* - * libmm-radio + * mm_radio_priv_hal.c * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * Copyright (c) 2016 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. @@ -38,11 +36,7 @@ #include <mm_debug.h> #include <mm_message.h> -#include <mm_sound.h> -#include <mm_sound_focus.h> -#include <mm_sound_device.h> - -#include "mm_radio_priv.h" +#include "mm_radio_priv_hal.h" /*=========================================================================================== LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE @@ -123,28 +117,20 @@ static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command); static int __mmradio_get_state(mm_radio_t *radio); static bool __mmradio_set_state(mm_radio_t *radio, int new_state); +void _mmradio_seek_cancel(mm_radio_t *radio); static void __mmradio_seek_thread(mm_radio_t *radio); static void __mmradio_scan_thread(mm_radio_t *radio); static bool __is_tunable_frequency(mm_radio_t *radio, int freq); -static int __mmradio_set_deemphasis(mm_radio_t *radio); -static int __mmradio_set_band_range(mm_radio_t *radio); + +#ifdef TIZEN_FEATURE_SOUND_FOCUS static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, int option, const char *additional_info, void *user_data); -static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data); - -/*=========================================================================== - FUNCTION DEFINITIONS -========================================================================== */ -/* -------------------------------------------------------------------------- - * Name : _mmradio_apply_region() - * Desc : update radio region information and set values to device - * Param : - * [in] radio : radio handle - * [in] region : region type - * [in] update : update region values or not - * Return : zero on success, or negative value with error code - *---------------------------------------------------------------------------*/ +static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, + mm_sound_focus_state_e focus_state, const char *reason_for_change, + const char *additional_info, void *user_data); +#endif + int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update) { int ret = MM_ERROR_NONE; @@ -177,26 +163,10 @@ int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool upda } } - /* chech device is opened or not. if it's not ready, skip to apply region to device now */ - if (radio->radio_fd < 0) { - MMRADIO_LOG_DEBUG("not opened device. just updating region info. \n"); - return MM_ERROR_NONE; - } - MMRADIO_LOG_DEBUG("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz\n", radio->region_setting.country, radio->region_setting.deemphasis, radio->region_setting.band_min, radio->region_setting.band_max); - /* set de-emphsasis to device */ - ret = __mmradio_set_deemphasis(radio); - - MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set de-emphasis"); - - /* set band range to device */ - ret = __mmradio_set_band_range(radio); - - MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set band range"); - MMRADIO_LOG_FLEAVE(); return ret; @@ -204,7 +174,7 @@ int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool upda int _mmradio_create_radio(mm_radio_t *radio) { - int ret = 0; + int ret = MM_ERROR_NONE; MMRADIO_LOG_FENTER(); @@ -212,10 +182,11 @@ int _mmradio_create_radio(mm_radio_t *radio) MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE); /* set default value */ - radio->radio_fd = -1; radio->freq = DEFAULT_FREQ; +#ifdef TIZEN_FEATURE_SOUND_FOCUS + memset(&radio->sound_focus, 0, sizeof(mm_radio_sound_focus)); +#endif memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t)); - radio->subs_id = 0; /* create command lock */ ret = pthread_mutex_init(&radio->cmd_lock, NULL); @@ -226,22 +197,24 @@ int _mmradio_create_radio(mm_radio_t *radio) MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL); - /* add device conneted callback */ - ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, - (mm_sound_device_connected_cb)__mmradio_device_connected_cb, - (void *)radio, &radio->subs_id); - if (ret) { - MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n"); - return MM_ERROR_RADIO_INTERNAL; - } +#ifdef TIZEN_FEATURE_SOUND_FOCUS + ret = mmradio_sound_focus_register(&radio->sound_focus, + (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb, + (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb, + (void *)radio); - /* register to audio focus */ - ret = mmradio_audio_focus_register(&radio->sm, __mmradio_sound_focus_cb, (void *)radio); if (ret) { /* NOTE : we are dealing it as an error since we cannot expect it's behavior */ MMRADIO_LOG_ERROR("mmradio_audio_focus_register is failed\n"); return MM_ERROR_RADIO_INTERNAL; } +#endif + + ret = radio_hal_interface_init(&(radio->hal_inf)); + if (ret) { + MMRADIO_LOG_ERROR("mmradio hal interface init failed\n"); + return ret; + } MMRADIO_LOG_FLEAVE(); @@ -251,101 +224,49 @@ int _mmradio_create_radio(mm_radio_t *radio) int _mmradio_realize(mm_radio_t *radio) { int ret = MM_ERROR_NONE; - char str_error[READ_MAX_BUFFER_SIZE]; + bool update = false; + MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE); - /* open radio device */ - if (radio->radio_fd == -1) { - MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE; - bool update = false; - - /* open device */ - radio->radio_fd = open(DEFAULT_DEVICE, O_RDONLY); - if (radio->radio_fd < 0) { - MMRADIO_LOG_ERROR("failed to open radio device[%s] because of %s(%d)\n", - DEFAULT_DEVICE, strerror_r(errno, str_error, sizeof(str_error)), errno); - - /* check error */ - switch (errno) { - case ENOENT: - return MM_ERROR_RADIO_DEVICE_NOT_FOUND; - case EACCES: - return MM_ERROR_RADIO_PERMISSION_DENIED; - default: - return MM_ERROR_RADIO_DEVICE_NOT_OPENED; - } - } - MMRADIO_LOG_DEBUG("radio device fd : %d\n", radio->radio_fd); - - /* query radio device capabilities. */ - if (ioctl(radio->radio_fd, VIDIOC_QUERYCAP, &(radio->vc)) < 0) { - MMRADIO_LOG_ERROR("VIDIOC_QUERYCAP failed!\n"); - goto error; - } - - if (!(radio->vc.capabilities & V4L2_CAP_TUNER)) { - MMRADIO_LOG_ERROR("this system can't support fm-radio!\n"); - goto error; - } - - /* set tuner audio mode */ - ioctl(radio->radio_fd, VIDIOC_G_TUNER, &(radio->vt)); - - if (!((radio->vt).capability & V4L2_TUNER_CAP_STEREO)) { - MMRADIO_LOG_ERROR("this system can support mono!\n"); - (radio->vt).audmode = V4L2_TUNER_MODE_MONO; - } else { - (radio->vt).audmode = V4L2_TUNER_MODE_STEREO; - } - - /* set tuner index. Must be 0. */ - (radio->vt).index = TUNER_INDEX; - ioctl(radio->radio_fd, VIDIOC_S_TUNER, &(radio->vt)); - - /* check region country type if it's updated or not */ - if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) { - /* not initialized yet. set it with default region */ - region = RADIO_DEFAULT_REGION; - update = true; - } else { - /* already initialized by application */ - region = radio->region_setting.country; - } - - ret = _mmradio_apply_region(radio, region, update); + ret = pthread_mutex_init(&radio->seek_cancel_mutex, NULL); + if (ret < 0) { + MMRADIO_LOG_DEBUG("Mutex creation failed %d", ret); + } - MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info"); + if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) { + /* not initialized yet. set it with default region */ + region = RADIO_DEFAULT_REGION; + update = true; + } else { + /* already initialized by application */ + region = radio->region_setting.country; } - /* ready but nosound */ - if (_mmradio_mute(radio) != MM_ERROR_NONE) - goto error; + ret = _mmradio_apply_region(radio, region, update); - MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); -#ifdef USE_GST_PIPELINE - ret = _mmradio_realize_pipeline(radio); - if (ret) { - debug_error("_mmradio_realize_pipeline is failed\n"); +#ifdef TIZEN_FEATURE_SOUND_VSTREAM + ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("sound_manager_create_stream_information_internal error"); + MMRADIO_LOG_FLEAVE(); return ret; } -#endif - MMRADIO_LOG_FLEAVE(); - - return MM_ERROR_NONE; - -error: - if (radio->radio_fd >= 0) { - close(radio->radio_fd); - radio->radio_fd = -1; + ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error"); + MMRADIO_LOG_FLEAVE(); + return ret; } +#endif + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); MMRADIO_LOG_FLEAVE(); - return MM_ERROR_RADIO_INTERNAL; + return MM_ERROR_NONE; } int _mmradio_unrealize(mm_radio_t *radio) @@ -357,29 +278,31 @@ int _mmradio_unrealize(mm_radio_t *radio) MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE); - if (_mmradio_mute(radio) != MM_ERROR_NONE) - return MM_ERROR_RADIO_NOT_INITIALIZED; - - /* close radio device here !!!! */ - if (radio->radio_fd >= 0) { - close(radio->radio_fd); - radio->radio_fd = -1; + ret = radio_hal_unmute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unmute is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_unmute error"); + MMRADIO_LOG_FLEAVE(); + return ret; } - MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL); + /*Finish if there are scans*/ + _mmradio_stop_scan(radio); - ret = mmradio_release_audio_focus(&radio->sm); - if (ret) { - MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n"); - return ret; - } -#ifdef USE_GST_PIPELINE - ret = _mmradio_destroy_pipeline(radio); - if (ret) { - debug_error("_mmradio_destroy_pipeline is failed\n"); - return ret; - } + /*Stop radio if started*/ + _mmradio_stop(radio); + + /* close radio device here !!!! */ + radio_hal_close(radio->hal_inf); + radio_hal_unprepare(radio->hal_inf); +#ifdef TIZEN_FEATURE_SOUND_VSTREAM + sound_manager_destroy_virtual_stream(radio->vstream); + sound_manager_destroy_stream_information(radio->stream_info); #endif + pthread_mutex_destroy(&radio->seek_cancel_mutex); + + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL); MMRADIO_LOG_FLEAVE(); @@ -388,25 +311,26 @@ int _mmradio_unrealize(mm_radio_t *radio) int _mmradio_destroy(mm_radio_t *radio) { - int ret = 0; + int ret = MM_ERROR_NONE; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY); - ret = mmradio_audio_focus_deregister(&radio->sm); + _mmradio_unrealize(radio); + + ret = radio_hal_interface_deinit(radio->hal_inf); if (ret) { - MMRADIO_LOG_ERROR("failed to deregister audio focus\n"); - return MM_ERROR_RADIO_INTERNAL; + MMRADIO_LOG_ERROR("mmradio hal interface deinit failed\n"); + return ret; } - - ret = mm_sound_remove_device_connected_callback(radio->subs_id); +#ifdef TIZEN_FEATURE_SOUND_FOCUS + ret = mmradio_sound_focus_deregister(&radio->sound_focus); if (ret) { - MMRADIO_LOG_ERROR("mm_sound_remove_device_connected_callback error %d\n", ret); + MMRADIO_LOG_ERROR("failed to deregister sound focus\n"); return MM_ERROR_RADIO_INTERNAL; } - _mmradio_unrealize(radio); - +#endif MMRADIO_LOG_FLEAVE(); return MM_ERROR_NONE; @@ -415,6 +339,8 @@ int _mmradio_destroy(mm_radio_t *radio) /* unit should be KHz */ int _mmradio_set_frequency(mm_radio_t *radio, int freq) { + int ret = MM_ERROR_NONE; + MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); @@ -424,33 +350,23 @@ int _mmradio_set_frequency(mm_radio_t *radio, int freq) radio->freq = freq; - if (radio->radio_fd < 0) { - MMRADIO_LOG_DEBUG("radio device is not opened yet\n"); - return MM_ERROR_NONE; - } - - /* check frequency range */ - if (freq < radio->region_setting.band_min || freq > radio->region_setting.band_max) { - MMRADIO_LOG_ERROR("out of frequency range\n", freq); - return MM_ERROR_INVALID_ARGUMENT; + ret = radio_hal_set_frequency(radio->hal_inf, freq); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_set_frequency error"); + MMRADIO_LOG_FLEAVE(); + return ret; } - /* set it */ - (radio->vf).tuner = 0; - (radio->vf).frequency = RADIO_FREQ_FORMAT_SET(freq); - - if (ioctl(radio->radio_fd, VIDIOC_S_FREQUENCY, &(radio->vf)) < 0) - return MM_ERROR_RADIO_NOT_INITIALIZED; - MMRADIO_LOG_FLEAVE(); - return MM_ERROR_NONE; + return ret; } int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq) { - int freq = 0; + int ret = MM_ERROR_NONE; + uint32_t freq = 0; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); @@ -458,146 +374,68 @@ int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq) return_val_if_fail(pFreq, MM_ERROR_INVALID_ARGUMENT); - /* just return stored frequency if radio device is not ready */ - if (radio->radio_fd < 0) { - MMRADIO_LOG_DEBUG("freq : %d\n", radio->freq); - *pFreq = radio->freq; - return MM_ERROR_NONE; - } - - if (ioctl(radio->radio_fd, VIDIOC_G_FREQUENCY, &(radio->vf)) < 0) { - MMRADIO_LOG_ERROR("failed to do VIDIOC_G_FREQUENCY\n"); - return MM_ERROR_RADIO_INTERNAL; + ret = radio_hal_get_frequency(radio->hal_inf, &freq); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_get_frequency error"); + *pFreq = 0; + return ret; } - freq = RADIO_FREQ_FORMAT_GET((radio->vf).frequency); - /* update freq in handle */ radio->freq = freq; - *pFreq = radio->freq; + *pFreq = (int)radio->freq; MMRADIO_LOG_FLEAVE(); - return MM_ERROR_NONE; + return ret; } int _mmradio_mute(mm_radio_t *radio) { + int ret = MM_ERROR_NONE; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE); - if (radio->radio_fd < 0) - return MM_ERROR_RADIO_NOT_INITIALIZED; - - (radio->vctrl).id = V4L2_CID_AUDIO_MUTE; - /* mute */ - (radio->vctrl).value = 1; - - if (ioctl(radio->radio_fd, VIDIOC_S_CTRL, &(radio->vctrl)) < 0) - return MM_ERROR_RADIO_NOT_INITIALIZED; + ret = radio_hal_mute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_mute is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_mute error"); + MMRADIO_LOG_FLEAVE(); + return ret; + } + radio->is_muted = TRUE; MMRADIO_LOG_FLEAVE(); - return MM_ERROR_NONE; - + return ret; } int _mmradio_unmute(mm_radio_t *radio) { + int ret = MM_ERROR_NONE; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE); - MMRADIO_CHECK_DEVICE_STATE(radio); - (radio->vctrl).id = V4L2_CID_AUDIO_MUTE; - /* unmute */ - (radio->vctrl).value = 0; - - if (ioctl(radio->radio_fd, VIDIOC_S_CTRL, &(radio->vctrl)) < 0) - return MM_ERROR_RADIO_NOT_INITIALIZED; - - MMRADIO_LOG_FLEAVE(); - - return MM_ERROR_NONE; -} - -/* -------------------------------------------------------------------------- - * Name : __mmradio_set_deemphasis - * Desc : apply de-emphasis value to device - * Param : - * [in] radio : radio handle - * Return : zero on success, or negative value with error code - *---------------------------------------------------------------------------*/ -int __mmradio_set_deemphasis(mm_radio_t *radio) -{ - int value = 0; - - MMRADIO_LOG_FENTER(); - - MMRADIO_CHECK_INSTANCE(radio); - - /* get de-emphasis */ - switch (radio->region_setting.deemphasis) { - case MM_RADIO_DEEMPHASIS_50_US: - /* V4L2_DEEMPHASIS_50_uS; */ - value = 1; - break; - - case MM_RADIO_DEEMPHASIS_75_US: - /* V4L2_DEEMPHASIS_75_uS; */ - value = 2; - break; - - default: - MMRADIO_LOG_ERROR("not availabe de-emphasis value\n"); - return MM_ERROR_COMMON_INVALID_ARGUMENT; + ret = radio_hal_unmute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unmute is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_unmute error"); + MMRADIO_LOG_FLEAVE(); + return ret; } - /* set it to device */ - /* V4L2_CID_TUNE_DEEMPHASIS; */ - (radio->vctrl).id = (0x009d0000 | 0x900) + 1; - (radio->vctrl).value = value; - - if (ioctl(radio->radio_fd, VIDIOC_S_CTRL, &(radio->vctrl)) < 0) { - MMRADIO_LOG_ERROR("failed to set de-emphasis\n"); - return MM_ERROR_RADIO_INTERNAL; - } + radio->is_muted = FALSE; MMRADIO_LOG_FLEAVE(); - return MM_ERROR_NONE; -} - -/* -------------------------------------------------------------------------- - * Name : __mmradio_set_band_range - * Desc : apply max and min frequency to device - * Param : - * [in] radio : radio handle - * Return : zero on success, or negative value with error code - *---------------------------------------------------------------------------*/ -int __mmradio_set_band_range(mm_radio_t *radio) -{ - MMRADIO_LOG_FENTER(); - - MMRADIO_CHECK_INSTANCE(radio); - - /* get min and max freq. */ - (radio->vt).rangelow = RADIO_FREQ_FORMAT_SET(radio->region_setting.band_min); - (radio->vt).rangehigh = RADIO_FREQ_FORMAT_SET(radio->region_setting.band_max); - - /* set it to device */ - if (ioctl(radio->radio_fd, VIDIOC_S_TUNER, &(radio->vt)) < 0) { - MMRADIO_LOG_ERROR("failed to set band range\n"); - return MM_ERROR_RADIO_INTERNAL; - } - - MMRADIO_LOG_FLEAVE(); - - return MM_ERROR_NONE; + return ret; } int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param) @@ -645,30 +483,72 @@ int _mmradio_start(mm_radio_t *radio) MMRADIO_LOG_DEBUG("now tune to frequency : %d\n", radio->freq); - ret = mmradio_acquire_audio_focus(&radio->sm); - if (ret) { - MMRADIO_LOG_ERROR("failed to set audio focus\n"); - return ret; +#ifdef TIZEN_FEATURE_SOUND_FOCUS + if (radio->sound_focus.handle > 0) { + ret = mmradio_acquire_sound_focus(&radio->sound_focus); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("failed to set sound focus"); + return ret; + } } +#endif - /* set stored frequency */ - _mmradio_set_frequency(radio, radio->freq); + if (!radio->is_ready) { + ret = radio_hal_prepare(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_prepare is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_prepare_device error"); + goto error; + } - /* unmute */ - if (_mmradio_unmute(radio) != MM_ERROR_NONE) - return MM_ERROR_RADIO_NOT_INITIALIZED; + ret = radio_hal_open(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_open is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_init error"); + goto error; + } + radio->is_ready = TRUE; + } else { + MMRADIO_LOG_DEBUG("radio prepared and opened"); + } - MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING); -#ifdef USE_GST_PIPELINE - ret = _mmradio_start_pipeline(radio); + ret = radio_hal_start(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_start is not supported"); + } else if (ret) { + MMRADIO_LOG_ERROR("failed to radio_hal_start\n"); + goto error; + } + + /* set stored frequency */ + ret = radio_hal_set_frequency(radio->hal_inf, radio->freq); if (ret) { - debug_error("_mmradio_start_pipeline is failed\n"); - return ret; + MMRADIO_LOG_ERROR("failed to radio_hal_set_frequency\n"); + goto error; + } + +#ifdef TIZEN_FEATURE_SOUND_VSTREAM + ret = sound_manager_start_virtual_stream(radio->vstream); + if (ret) { + MMRADIO_LOG_ERROR("failed to sound_manager_start_virtual_stream\n"); + goto error; } #endif + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING); + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_NONE; + +error: +#ifdef TIZEN_FEATURE_SOUND_VSTREAM + sound_manager_stop_virtual_stream(radio->vstream); +#endif + radio_hal_close(radio->hal_inf); + radio_hal_unprepare(radio->hal_inf); return ret; } @@ -681,147 +561,90 @@ int _mmradio_stop(mm_radio_t *radio) MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP); - if (_mmradio_mute(radio) != MM_ERROR_NONE) - return MM_ERROR_RADIO_NOT_INITIALIZED; - - MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); - -#ifdef USE_GST_PIPELINE - ret = _mmradio_stop_pipeline(radio); - if (ret) { - debug_error("_mmradio_stop_pipeline is failed\n"); - return ret; - } + radio->seek_unmute = FALSE; + /*cancel if any seek*/ + _mmradio_seek_cancel(radio); +#ifdef TIZEN_FEATURE_SOUND_VSTREAM + ret = sound_manager_stop_virtual_stream(radio->vstream); #endif - - MMRADIO_LOG_FLEAVE(); - - return ret; -} - -#ifdef USE_GST_PIPELINE -int _mmradio_realize_pipeline(mm_radio_t *radio) -{ - int ret = MM_ERROR_NONE; - - gst_init(NULL, NULL); - radio->pGstreamer_s = g_new0(mm_radio_gstreamer_s, 1); - - radio->pGstreamer_s->pipeline = gst_pipeline_new("fmradio"); - - radio->pGstreamer_s->audiosrc = gst_element_factory_make("pulsesrc", "fm audio src"); - radio->pGstreamer_s->queue2 = gst_element_factory_make("queue2", "queue2"); - radio->pGstreamer_s->audiosink = gst_element_factory_make("pulsesink", "audio sink"); - - /* g_object_set(radio->pGstreamer_s->audiosrc, "latency", 2, NULL); */ - g_object_set(radio->pGstreamer_s->audiosink, "sync", false, NULL); - - if (!radio->pGstreamer_s->pipeline || !radio->pGstreamer_s->audiosrc || - !radio->pGstreamer_s->queue2 || !radio->pGstreamer_s->audiosink) { - debug_error("[%s][%05d] One element could not be created. Exiting.\n", __func__, __LINE__); - return MM_ERROR_RADIO_NOT_INITIALIZED; + ret = radio_hal_mute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unmute is not supported"); + } else if (ret) { + MMRADIO_LOG_ERROR("failed to radio_hal_mute\n"); + return ret; } - gst_bin_add_many(GST_BIN(radio->pGstreamer_s->pipeline), - radio->pGstreamer_s->audiosrc, radio->pGstreamer_s->queue2, - radio->pGstreamer_s->audiosink, NULL); - if (!gst_element_link_many(radio->pGstreamer_s->audiosrc, - radio->pGstreamer_s->queue2, radio->pGstreamer_s->audiosink, NULL)) { - debug_error("[%s][%05d] Fail to link b/w appsrc and ffmpeg in rotate\n", __func__, __LINE__); - return MM_ERROR_RADIO_NOT_INITIALIZED; + ret = radio_hal_stop(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unmute is not supported"); + } else if (ret) { + MMRADIO_LOG_ERROR("failed to radio_hal_stop\n"); + return ret; } - return ret; -} -int _mmradio_start_pipeline(mm_radio_t *radio) -{ - int ret = MM_ERROR_NONE; - GstStateChangeReturn ret_state; - debug_log("\n"); - - if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { - debug_error("Fail to change pipeline state"); - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return MM_ERROR_RADIO_INVALID_STATE; + /* close radio device here !!!! */ + ret = radio_hal_close(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_close is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_close_device error"); + return ret; } - - ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); - if (ret_state == GST_STATE_CHANGE_FAILURE) { - debug_error("GST_STATE_CHANGE_FAILURE"); - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return MM_ERROR_RADIO_INVALID_STATE; - } else { - debug_log("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state); + ret = radio_hal_unprepare(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_close_device error"); + return ret; } - return ret; -} -int _mmradio_stop_pipeline(mm_radio_t *radio) -{ - int ret = MM_ERROR_NONE; - GstStateChangeReturn ret_state; - - debug_log("\n"); - if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) { - debug_error("Fail to change pipeline state"); - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return MM_ERROR_RADIO_INVALID_STATE; - } + radio->is_ready = FALSE; - ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); - if (ret_state == GST_STATE_CHANGE_FAILURE) { - debug_error("GST_STATE_CHANGE_FAILURE"); - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return MM_ERROR_RADIO_INVALID_STATE; - } else { - debug_log("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state); +#ifdef TIZEN_FEATURE_SOUND_FOCUS + if (radio->sound_focus.handle > 0) { + ret = mmradio_release_sound_focus(&radio->sound_focus); + if (ret) { + MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n"); + return ret; + } } - return ret; -} +#endif + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); -int _mmradio_destroy_pipeline(mm_radio_t *radio) -{ - int ret = 0; - GstStateChangeReturn ret_state; - debug_log("\n"); - - if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE) { - debug_error("Fail to change pipeline state"); - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return MM_ERROR_RADIO_INVALID_STATE; - } + MMRADIO_LOG_FLEAVE(); - ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); - if (ret_state == GST_STATE_CHANGE_FAILURE) { - debug_error("GST_STATE_CHANGE_FAILURE"); - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return MM_ERROR_RADIO_INVALID_STATE; - } else { - debug_log("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state); - } - gst_object_unref(radio->pGstreamer_s->pipeline); - g_free(radio->pGstreamer_s); - return ret; + return MM_ERROR_NONE; } -#endif int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction) { + int ret = MM_ERROR_NONE; + MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK); - int ret = 0; + if (radio->is_seeking) { + MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again"); + return MM_ERROR_RADIO_INTERNAL; + } - if (_mmradio_mute(radio) != MM_ERROR_NONE) - return MM_ERROR_RADIO_NOT_INITIALIZED; + radio->seek_unmute = FALSE; + radio->is_seeking = TRUE; + radio->seek_cancel = FALSE; + + if (!radio->is_muted) { + ret = radio_hal_mute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_mute is not supported"); + } else if (ret) { + MMRADIO_LOG_ERROR("failed to radio_hal_mute\n"); + return ret; + } + radio->seek_unmute = TRUE; + } MMRADIO_LOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d\n", direction); radio->seek_direction = direction; @@ -830,6 +653,18 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction) if (ret) { MMRADIO_LOG_DEBUG("failed create thread\n"); + radio->is_seeking = FALSE; + radio->seek_cancel = TRUE; + if (radio->seek_unmute) { + ret = radio_hal_mute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_mute is not supported"); + } else if (ret) { + MMRADIO_LOG_ERROR("failed to radio_hal_mute\n"); + radio->seek_unmute = FALSE; + return ret; + } + } return MM_ERROR_RADIO_INTERNAL; } @@ -838,8 +673,41 @@ int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction) return MM_ERROR_NONE; } +void _mmradio_seek_cancel(mm_radio_t *radio) +{ + int ret = MM_ERROR_NONE; + char str_error[READ_MAX_BUFFER_SIZE]; + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); + + /*cancel any outstanding seek request*/ + radio->seek_cancel = TRUE; + if (radio->seek_thread) { + ret = pthread_mutex_trylock(&radio->seek_cancel_mutex); + MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret); + if (ret == EBUSY) { /* it was already locked by other */ + MMRADIO_LOG_DEBUG("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT"); + } else if (ret == 0) { + MMRADIO_LOG_DEBUG("trylock is successful. unlock now"); + pthread_mutex_unlock(&radio->seek_cancel_mutex); + } else { + MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret); + } + MMRADIO_LOG_DEBUG("pthread_join seek_thread"); + pthread_join(radio->seek_thread, NULL); + MMRADIO_LOG_DEBUG("done"); + radio->is_seeking = FALSE; + radio->seek_thread = 0; + } + MMRADIO_LOG_FLEAVE(); +} + + int _mmradio_start_scan(mm_radio_t *radio) { + int ret = MM_ERROR_NONE; + MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); @@ -849,6 +717,28 @@ int _mmradio_start_scan(mm_radio_t *radio) radio->stop_scan = false; + if (!radio->is_ready) { + ret = radio_hal_prepare(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_prepare is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_prepare_device error"); + return ret; + } + + ret = radio_hal_open(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_open is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_init error"); + MMRADIO_LOG_FLEAVE(); + return ret; + } + radio->is_ready = TRUE; + } else { + MMRADIO_LOG_DEBUG("radio prepared and opened"); + } + scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio); if (scan_tr_id != 0) { @@ -865,6 +755,8 @@ int _mmradio_start_scan(mm_radio_t *radio) int _mmradio_stop_scan(mm_radio_t *radio) { + int ret = 0; + char str_error[READ_MAX_BUFFER_SIZE]; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); @@ -873,6 +765,18 @@ int _mmradio_stop_scan(mm_radio_t *radio) radio->stop_scan = true; if (radio->scan_thread > 0) { + /* make sure all the search is stopped else we'll wait till search finish which is not ideal*/ + ret = pthread_mutex_trylock(&radio->seek_cancel_mutex); + MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret); + if (ret == EBUSY) { /* it was already locked by other */ + MMRADIO_LOG_DEBUG("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT"); + } else if (ret == 0) { + MMRADIO_LOG_DEBUG("trylock is successful. unlock now"); + pthread_mutex_unlock(&radio->seek_cancel_mutex); + } else { + MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret); + } + MMRADIO_LOG_DEBUG("pthread_join scan_thread"); pthread_cancel(radio->scan_thread); pthread_join(radio->scan_thread, NULL); radio->scan_thread = 0; @@ -888,76 +792,81 @@ int _mmradio_stop_scan(mm_radio_t *radio) int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value) { + int ret = MM_ERROR_NONE; + uint32_t strength = 0; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE(radio); return_val_if_fail(value, MM_ERROR_INVALID_ARGUMENT); /* just return stored frequency if radio device is not ready */ - if (radio->radio_fd < 0) { - MMRADIO_LOG_DEBUG("Device not ready so sending 0\n"); + ret = radio_hal_get_signal_strength(radio->hal_inf, &strength); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unmute is not supported"); + } else if (ret != MM_ERROR_NONE) { + debug_error("radio_hal_get_signal_strength error\n"); *value = 0; - return MM_ERROR_NONE; - } - if (ioctl(radio->radio_fd, VIDIOC_G_TUNER, &(radio->vt)) < 0) { - debug_error("ioctl VIDIOC_G_TUNER error\n"); - return MM_ERROR_RADIO_INTERNAL; + MMRADIO_LOG_FLEAVE(); + return ret; } - *value = radio->vt.signal; + *value = (int)strength; MMRADIO_LOG_FLEAVE(); return MM_ERROR_NONE; } void __mmradio_scan_thread(mm_radio_t *radio) { - int ret = 0; + int ret = MM_ERROR_NONE; int prev_freq = 0; - char str_error[READ_MAX_BUFFER_SIZE]; - - struct v4l2_hw_freq_seek vs = { 0, }; - vs.tuner = TUNER_INDEX; - vs.type = V4L2_TUNER_RADIO; - vs.wrap_around = 0; /* around:1 not around:0 */ - vs.seek_upward = 1; /* up : 1 ------- down : 0 */ MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); - if (_mmradio_mute(radio) != MM_ERROR_NONE) + + ret = radio_hal_mute(radio->hal_inf); + + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_mute is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_mute error"); goto FINISHED; + } + ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min); - if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE) + if (ret != MM_ERROR_NONE) goto FINISHED; MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL); MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING); while (!radio->stop_scan) { - int freq = 0; + uint32_t freq = 0; MMMessageParamType param = { 0, }; MMRADIO_LOG_DEBUG("scanning....\n"); - ret = ioctl(radio->radio_fd, VIDIOC_S_HW_FREQ_SEEK, &vs); - if (ret == -1) { - if (errno == EAGAIN) { - MMRADIO_LOG_ERROR("scanning timeout\n"); - continue; - } else if (errno == EINVAL) { - MMRADIO_LOG_ERROR("The tuner index is out of bounds or the value in the type field is wrong."); - break; - } else { - MMRADIO_LOG_ERROR("Error: %s, %d\n", strerror_r(errno, str_error, sizeof(str_error)), errno); - break; - } + pthread_mutex_lock(&radio->seek_cancel_mutex); + + if (radio->stop_scan) { + MMRADIO_LOG_DEBUG("scan was canceled"); + pthread_mutex_unlock(&radio->seek_cancel_mutex); + goto FINISHED; } - /* now we can get new frequency from radio device */ + ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP); + + pthread_mutex_unlock(&radio->seek_cancel_mutex); + + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio scanning error"); + break; + } + /* now we can get new frequency from radio device */ if (radio->stop_scan) break; - ret = _mmradio_get_frequency(radio, &freq); - if (ret) { + ret = radio_hal_get_frequency(radio->hal_inf, &freq); + if (ret != MM_ERROR_NONE) { MMRADIO_LOG_ERROR("failed to get current frequency\n"); } else { if (freq < prev_freq) { @@ -968,7 +877,7 @@ void __mmradio_scan_thread(mm_radio_t *radio) if (freq == prev_freq) continue; - prev_freq = param.radio_scan.frequency = freq; + prev_freq = param.radio_scan.frequency = (int)freq; MMRADIO_LOG_DEBUG("scanning : new frequency : [%d]\n", param.radio_scan.frequency); /* drop if max freq is scanned */ @@ -985,16 +894,50 @@ void __mmradio_scan_thread(mm_radio_t *radio) MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m); } } - FINISHED: - radio->scan_thread = 0; - +FINISHED: if (radio->old_state == MM_RADIO_STATE_READY) { - MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); + MMRADIO_LOG_DEBUG("old state is ready"); } else if (radio->old_state == MM_RADIO_STATE_PLAYING) { MMRADIO_LOG_DEBUG("old state is playing"); - ret = _mmradio_unmute(radio); - ret = _mmradio_set_frequency(radio->hal_inf, prev_freq); + ret = radio_hal_unmute(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_unmute is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_unmute error"); + goto FINISHED_ERR; + } + ret = radio_hal_set_frequency(radio->hal_inf, prev_freq); + if (ret == MM_ERROR_NOT_SUPPORT_API) { + MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported"); + } else if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal_set_frequency error"); + goto FINISHED_ERR; + } + } + +FINISHED_ERR: + + radio->scan_thread = 0; + + if (radio->old_state == MM_RADIO_STATE_PLAYING) { MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING); + } else { + /* close radio device here !!!! */ + ret = radio_hal_close(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) + MMRADIO_LOG_WARNING("radio_hal_close is not supported"); + else if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("radio_hal_close_device error"); + + ret = radio_hal_unprepare(radio->hal_inf); + if (ret == MM_ERROR_NOT_SUPPORT_API) + MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported"); + else if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("radio_hal_close_device error"); + + radio->is_ready = FALSE; + + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); } if (!radio->stop_scan) @@ -1013,7 +956,8 @@ bool __is_tunable_frequency(mm_radio_t *radio, int freq) MMRADIO_CHECK_INSTANCE(radio); - if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min) + if (freq >= radio->region_setting.band_max + || freq <= radio->region_setting.band_min) return false; MMRADIO_LOG_FLEAVE(); @@ -1023,53 +967,38 @@ bool __is_tunable_frequency(mm_radio_t *radio, int freq) void __mmradio_seek_thread(mm_radio_t *radio) { - int ret = 0; - int freq = 0; - char str_error[READ_MAX_BUFFER_SIZE]; - bool seek_stop = false; + int ret = MM_ERROR_NONE; + uint32_t freq = 0; MMMessageParamType param = {0, }; - struct v4l2_hw_freq_seek vs = {0, }; - - vs.tuner = TUNER_INDEX; - vs.type = V4L2_TUNER_RADIO; - vs.wrap_around = DEFAULT_WRAP_AROUND; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); - /* check direction */ - switch (radio->seek_direction) { - case MM_RADIO_SEEK_UP: - vs.seek_upward = 1; - break; - default: - vs.seek_upward = 0; - break; - } - MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL); MMRADIO_LOG_DEBUG("seeking....\n"); - while (!seek_stop) { - ret = ioctl(radio->radio_fd, VIDIOC_S_HW_FREQ_SEEK, &vs); + if (!radio->seek_cancel) { - if (ret == -1) { - if (errno == EAGAIN) { - /* FIXIT : we need retrying code here */ - MMRADIO_LOG_ERROR("scanning timeout\n"); - goto SEEK_FAILED; - } else if (errno == EINVAL) { - MMRADIO_LOG_ERROR("The tuner index is out of bounds or the value in the type field is wrong."); - goto SEEK_FAILED; - } else { - MMRADIO_LOG_ERROR("Error: %s, %d\n", strerror_r(errno, str_error, sizeof(str_error)), errno); - goto SEEK_FAILED; - } + MMRADIO_LOG_DEBUG("try to seek "); + pthread_mutex_lock(&radio->seek_cancel_mutex); + MMRADIO_LOG_DEBUG("seek start\n"); + + if (radio->seek_cancel) { + MMRADIO_LOG_DEBUG("seek was canceled so we return failure to application"); + pthread_mutex_unlock(&radio->seek_cancel_mutex); + goto SEEK_FAILED; + } + + ret = radio_hal_seek(radio->hal_inf, radio->seek_direction); + pthread_mutex_unlock(&radio->seek_cancel_mutex); + if (ret) { + MMRADIO_LOG_ERROR("radio_hal_seek failed\n"); + goto SEEK_FAILED; } /* now we can get new frequency from radio device */ - ret = _mmradio_get_frequency(radio, &freq); + ret = radio_hal_get_frequency(radio->hal_inf, &freq); if (ret) { MMRADIO_LOG_ERROR("failed to get current frequency\n"); goto SEEK_FAILED; @@ -1080,36 +1009,39 @@ void __mmradio_seek_thread(mm_radio_t *radio) /* if same freq is found, ignore it and search next one. */ if (freq == radio->prev_seek_freq) { MMRADIO_LOG_DEBUG("It's same with previous found one. So, trying next one. \n"); - continue; + goto SEEK_FAILED; } /* check if it's limit freq or not */ if (__is_tunable_frequency(radio, freq)) { /* now tune to new frequency */ - ret = _mmradio_set_frequency(radio, freq); + ret = radio_hal_set_frequency(radio->hal_inf, freq); if (ret) { MMRADIO_LOG_ERROR("failed to tune to new frequency\n"); goto SEEK_FAILED; } } - /* now turn on radio - * In the case of limit freq, tuner should be unmuted. - * Otherwise, sound can't output even though application set new frequency. - */ - ret = _mmradio_unmute(radio); - if (ret) { - MMRADIO_LOG_ERROR("failed to tune to new frequency\n"); - goto SEEK_FAILED; + if (radio->seek_unmute) { + /* now turn on radio + * In the case of limit freq, tuner should be unmuted. + * Otherwise, sound can't output even though application set new frequency. + */ + ret = radio_hal_unmute(radio->hal_inf); + if (ret) { + MMRADIO_LOG_ERROR("failed to tune to new frequency\n"); + goto SEEK_FAILED; + } + radio->seek_unmute = FALSE; } - param.radio_scan.frequency = radio->prev_seek_freq = freq; + param.radio_scan.frequency = radio->prev_seek_freq = (int)freq; MMRADIO_LOG_DEBUG("seeking : new frequency : [%d]\n", param.radio_scan.frequency); MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m); - seek_stop = true; } radio->seek_thread = 0; + radio->is_seeking = FALSE; MMRADIO_LOG_FLEAVE(); @@ -1117,9 +1049,21 @@ void __mmradio_seek_thread(mm_radio_t *radio) return; SEEK_FAILED: + + if (radio->seek_unmute) { + /* now turn on radio + * In the case of limit freq, tuner should be unmuted. + * Otherwise, sound can't output even though application set new frequency. + */ + ret = radio_hal_unmute(radio->hal_inf); + if (ret) + MMRADIO_LOG_ERROR("failed to tune to new frequency\n"); + radio->seek_unmute = FALSE; + } /* freq -1 means it's failed to seek */ param.radio_scan.frequency = -1; MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m); + radio->is_seeking = FALSE; pthread_exit(NULL); return; } @@ -1135,7 +1079,7 @@ static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype return false; } - MMRADIO_LOG_DEBUG("address of msg_cb : %d\n", radio->msg_cb); + MMRADIO_LOG_DEBUG("address of msg_cb : %p\n", radio->msg_cb); radio->msg_cb(msgtype, param, radio->msg_cb_param); @@ -1301,8 +1245,9 @@ static bool __mmradio_set_state(mm_radio_t *radio, int new_state) msg.state.previous = radio->old_state; msg.state.current = radio->current_state; +#ifdef TIZEN_FEATURE_SOUND_FOCUS /* post message to application */ - switch (radio->sm.by_focus_cb) { + switch (radio->sound_focus.by_focus_cb) { case MMRADIO_FOCUS_CB_NONE: { msg_type = MM_MESSAGE_STATE_CHANGED; @@ -1314,7 +1259,7 @@ static bool __mmradio_set_state(mm_radio_t *radio, int new_state) { msg_type = MM_MESSAGE_STATE_INTERRUPTED; msg.union_type = MM_MSG_UNION_CODE; - msg.code = radio->sm.event_src; + msg.code = radio->sound_focus.event_src; MMRADIO_POST_MSG(radio, msg_type, &msg); } break; @@ -1323,6 +1268,10 @@ static bool __mmradio_set_state(mm_radio_t *radio, int new_state) default: break; } +#else + msg_type = MM_MESSAGE_STATE_CHANGED; + MMRADIO_POST_MSG(radio, msg_type, &msg); +#endif MMRADIO_LOG_FLEAVE(); @@ -1339,6 +1288,7 @@ static int __mmradio_get_state(mm_radio_t *radio) return radio->current_state; } +#ifdef TIZEN_FEATURE_SOUND_FOCUS static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, int option, const char *additional_info, void *user_data) @@ -1351,19 +1301,19 @@ static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); - mmradio_get_audio_focus_reason(focus_state, reason_for_change, &event_source, &postMsg); - radio->sm.event_src = event_source; + mmradio_get_sound_focus_reason(focus_state, reason_for_change, &event_source, &postMsg); + radio->sound_focus.event_src = event_source; switch (focus_state) { case FOCUS_IS_RELEASED:{ - radio->sm.cur_focus_type &= ~focus_type; - radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; + radio->sound_focus.cur_focus_type &= ~focus_type; + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; result = _mmradio_stop(radio); if (result) MMRADIO_LOG_ERROR("failed to stop radio\n"); - MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sm.cur_focus_type); + MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); } break; @@ -1372,14 +1322,14 @@ static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, msg.union_type = MM_MSG_UNION_CODE; msg.code = event_source; - radio->sm.cur_focus_type |= focus_type; + radio->sound_focus.cur_focus_type |= focus_type; - if ((postMsg) && (FOCUS_FOR_BOTH == radio->sm.cur_focus_type)) + if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type)) MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg); - radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_NONE; + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_NONE; - MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sm.cur_focus_type); + MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); } break; @@ -1391,40 +1341,58 @@ static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type, MMRADIO_LOG_FLEAVE(); } -static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data) +static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, + mm_sound_focus_state_e focus_state, const char *reason_for_change, + const char *additional_info, void *user_data) { mm_radio_t *radio = (mm_radio_t *)user_data; + enum MMMessageInterruptedCode event_source; int result = MM_ERROR_NONE; - mm_sound_device_type_e type; + int postMsg = false; MMRADIO_LOG_FENTER(); MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); - if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) { - debug_error("getting device type failed"); - } else { - switch (type) { - case MM_SOUND_DEVICE_TYPE_AUDIOJACK: - case MM_SOUND_DEVICE_TYPE_BLUETOOTH: - case MM_SOUND_DEVICE_TYPE_HDMI: - case MM_SOUND_DEVICE_TYPE_MIRRORING: - case MM_SOUND_DEVICE_TYPE_USB_AUDIO: - if (!is_connected) { - MMRADIO_LOG_ERROR("sound device unplugged"); - radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; - radio->sm.event_src = MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG; - - result = _mmradio_stop(radio); - if (result != MM_ERROR_NONE) - MMRADIO_LOG_ERROR("failed to stop radio\n"); - } - break; - default: - break; + mmradio_get_sound_focus_reason(focus_state, reason_for_change, &event_source, &postMsg); + radio->sound_focus.event_src = event_source; + + switch (focus_state) { + case FOCUS_IS_ACQUIRED: { + radio->sound_focus.cur_focus_type &= ~focus_type; + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; + + result = _mmradio_stop(radio); + if (result) + MMRADIO_LOG_ERROR("failed to stop radio\n"); + + MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); } + break; + + case FOCUS_IS_RELEASED: { + MMMessageParamType msg = { 0, }; + msg.union_type = MM_MSG_UNION_CODE; + msg.code = event_source; + + radio->sound_focus.cur_focus_type |= focus_type; + + if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type)) + MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg); + + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_NONE; + + MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type); + } + break; + + default: + MMRADIO_LOG_DEBUG("Unknown focus_state\n"); + break; } + MMRADIO_LOG_FLEAVE(); } +#endif int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type) { diff --git a/src/mm_radio_sound_focus.c b/src/mm_radio_sound_focus.c new file mode 100644 index 0000000..19c72bc --- /dev/null +++ b/src/mm_radio_sound_focus.c @@ -0,0 +1,355 @@ +/* + * mm_radio_sound_focus.c + * + * Copyright (c) 2000 - 2016 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 <assert.h> +#include <unistd.h> +#include <mm_debug.h> +#include <mm_sound.h> +#include <mm_sound_focus.h> +#include <mm_sound_device.h> +#include "mm_radio_utils.h" +#include "mm_radio_priv_hal.h" +#include "mm_radio_sound_focus.h" + +static void _mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data) +{ + mm_radio_t *radio = (mm_radio_t *)user_data; + int result = MM_ERROR_NONE; + mm_sound_device_type_e type; + + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); + + if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("getting device type failed"); + } else { + switch (type) { + case MM_SOUND_DEVICE_TYPE_AUDIOJACK: + case MM_SOUND_DEVICE_TYPE_BLUETOOTH: + case MM_SOUND_DEVICE_TYPE_HDMI: + case MM_SOUND_DEVICE_TYPE_MIRRORING: + case MM_SOUND_DEVICE_TYPE_USB_AUDIO: + if (!is_connected) { + MMRADIO_LOG_ERROR("sound device unplugged"); + radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG; + radio->sound_focus.event_src = MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG; + + result = _mmradio_stop(radio); + if (result != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to stop radio\n"); + } + break; + default: + break; + } + } + MMRADIO_LOG_FLEAVE(); +} + +void _mmradio_sound_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data) +{ + mm_radio_sound_focus *sound_focus = (mm_radio_sound_focus *)user_data; + int ret = MM_ERROR_NONE; + + MMRADIO_LOG_DEBUG("sound signal callback %d / %d", signal, value); + + if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) { + if (value == 1) { + /* unregister watch callback */ + if (sound_focus->watch_id > 0) { + MMRADIO_LOG_DEBUG("unset the focus watch cb %d", sound_focus->watch_id); + + ret = mm_sound_unset_focus_watch_callback(sound_focus->watch_id); + sound_focus->watch_id = 0; + if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to mm_sound_unset_focus_watch_callback()"); + } + /* unregister focus callback */ + if (sound_focus->focus_id > 0) { + ret = mm_sound_unregister_focus(sound_focus->focus_id); + sound_focus->focus_id = 0; + if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to mm_sound_unregister_focus() %d", sound_focus->focus_id); + } + /* unregister device connected callback */ + if (sound_focus->device_subs_id > 0) { + MMRADIO_LOG_DEBUG("unset the device connected cb %d", sound_focus->device_subs_id); + ret = mm_sound_remove_device_connected_callback(sound_focus->device_subs_id); + sound_focus->device_subs_id = 0; + if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to mm_sound_remove_device_connected_callback()"); + } + } + } +} + +int mmradio_sound_focus_register(mm_radio_sound_focus *sound_focus, + mm_sound_focus_changed_cb focus_cb, mm_sound_focus_changed_watch_cb watch_cb, void *param) +{ + /* read mm-session information */ + int session_type = MM_SESSION_TYPE_MEDIA; + int session_flags = 0; + int ret = MM_ERROR_NONE; + int pid = getpid(); + int handle = 0; + + MMRADIO_LOG_FENTER(); + + if (!sound_focus) { + MMRADIO_LOG_ERROR("invalid session handle\n"); + return MM_ERROR_RADIO_NOT_INITIALIZED; + } + sound_focus->cur_focus_type = FOCUS_NONE; + + /* read session information */ + ret = _mm_session_util_read_information(pid, &session_type, &session_flags); + MMRADIO_LOG_DEBUG("Read Session type ret:0x%X", ret); + if (ret == MM_ERROR_INVALID_HANDLE) { + MMRADIO_LOG_WARNING("subscribe_id=%d\n", sound_focus->subscribe_id); + if (sound_focus->subscribe_id == 0) { + ret = mm_sound_subscribe_signal_for_daemon(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, pid, &sound_focus->subscribe_id, + (mm_sound_signal_callback)_mmradio_sound_signal_callback, (void*)sound_focus); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_subscribe_signal is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + + MMRADIO_LOG_DEBUG("register focus watch callback for the value is 0, sub_cb id %d\n", sound_focus->subscribe_id); + /* register watch callback */ + ret = mm_sound_set_focus_watch_callback_for_session(pid, + FOCUS_FOR_BOTH, watch_cb, (void *)param, &sound_focus->watch_id); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_set_focus_watch_callback is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_DEBUG("(%p) set focus watch callback = %d", param, sound_focus->watch_id); + + /* register device connected callback */ + ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG, + (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void *)param, &sound_focus->device_subs_id); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_ERROR("register device connected callback for the value is 0, sub_cb id %d\n", sound_focus->device_subs_id); + } + ret = MM_ERROR_NONE; + } else if (ret == MM_ERROR_NONE) { + MMRADIO_LOG_WARNING("Read Session Information success. session_type : %d flags: %d \n", session_type, session_flags); + sound_focus->session_type = session_type; + sound_focus->snd_session_flags = session_flags; + if (sound_focus->session_type == MM_SESSION_TYPE_MEDIA) { + if (sound_focus->snd_session_flags & MM_SESSION_OPTION_PAUSE_OTHERS) { + /* register focus session */ + sound_focus->pid = pid; + MMRADIO_LOG_DEBUG("sound register focus pid[%d]", pid); + ret = mm_sound_focus_get_id(&handle); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("Failed to get sound focus id"); + return MM_ERROR_POLICY_BLOCKED; + } + sound_focus->handle = handle; + + ret = mm_sound_register_focus_for_session(handle, pid, "radio", focus_cb, param); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_DEBUG("mm_sound_register_focus_for_session is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_DEBUG("(%p) register focus for session %d", param, pid); + /* register device_connected_cb */ + ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG, + (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void *)param, &sound_focus->device_subs_id); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_DEBUG("(%p) add device connected callback = %d", param, sound_focus->device_subs_id); + + } else if (sound_focus->snd_session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE) { + /* register device_connected_cb */ + ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG, + (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void*)param, &sound_focus->device_subs_id); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_DEBUG("add device connected callback = %d", sound_focus->device_subs_id); + MMRADIO_LOG_WARNING("settion flags isn't OPTION_PAUSE_OTHERS and UNINTERRUPTIBLE. skip it.."); + } else { + /* register watch callback */ + ret = mm_sound_set_focus_watch_callback_for_session(pid, + FOCUS_FOR_BOTH, watch_cb, (void*)param, &sound_focus->watch_id); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_set_focus_watch_callback is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_DEBUG("set focus watch callback = %d", sound_focus->watch_id); + + /* register device connected callback */ + ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG, + (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void*)param, &sound_focus->device_subs_id); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + MMRADIO_LOG_DEBUG("(%p) add device connected callback = %d", param, sound_focus->device_subs_id); + } + } else if (sound_focus->session_type == MM_SESSION_TYPE_REPLACED_BY_STREAM) { + /* didn't register device connected cb */ + MMRADIO_LOG_WARNING("this process is using stream info. skip it.."); + } else { + MMRADIO_LOG_WARNING("seesion type is not MEDIA (%d)", sound_focus->session_type); + return MM_ERROR_RADIO_INTERNAL; + } + ret = MM_ERROR_NONE; + } else { + MMRADIO_LOG_WARNING("Read Session Information failed. skip sound focus register function. errorcode %x \n", ret); + } + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +int mmradio_sound_focus_deregister(mm_radio_sound_focus *sound_focus) +{ + + int ret = MM_ERROR_NONE; + + MMRADIO_LOG_FENTER(); + + if (!sound_focus) { + MMRADIO_LOG_ERROR("invalid session handle\n"); + return MM_ERROR_RADIO_NOT_INITIALIZED; + } + + if (sound_focus->watch_id > 0) { + MMRADIO_LOG_DEBUG("unset the focus watch cb %d", sound_focus->watch_id); + + ret = mm_sound_unset_focus_watch_callback(sound_focus->watch_id); + sound_focus->watch_id = 0; + if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to mm_sound_unset_focus_watch_callback() ret = %d", ret); + } + /* unregister focus callback */ + if (sound_focus->focus_id > 0) { + ret = mm_sound_unregister_focus(sound_focus->focus_id); + sound_focus->focus_id = 0; + if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to mm_sound_unregister_focus() ret = %d", ret); + } + /* unregister device connected callback */ + if (sound_focus->device_subs_id > 0) { + MMRADIO_LOG_DEBUG("unset the device connected cb %d", sound_focus->device_subs_id); + ret = mm_sound_remove_device_connected_callback(sound_focus->device_subs_id); + sound_focus->device_subs_id = 0; + if (ret != MM_ERROR_NONE) + MMRADIO_LOG_ERROR("failed to mm_sound_remove_device_connected_callback() ret = %d", ret); + } + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +int mmradio_acquire_sound_focus(mm_radio_sound_focus *sound_focus) +{ + int ret = MM_ERROR_NONE; + mm_sound_focus_type_e focus_type = FOCUS_NONE; + MMRADIO_LOG_FENTER(); + + MMRADIO_LOG_ERROR("mmradio_acquire_sound_focus sound_focus->cur_focus_type : %d\n", sound_focus->cur_focus_type); + + focus_type = FOCUS_FOR_BOTH & ~(sound_focus->cur_focus_type); + if (focus_type != FOCUS_NONE) { + ret = mm_sound_acquire_focus(sound_focus->handle, focus_type, NULL); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_acquire_focus is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + sound_focus->cur_focus_type = FOCUS_FOR_BOTH; + } + + MMRADIO_LOG_FLEAVE(); + return ret; +} + +int mmradio_release_sound_focus(mm_radio_sound_focus *sound_focus) +{ + int ret = MM_ERROR_NONE; + MMRADIO_LOG_FENTER(); + + MMRADIO_LOG_ERROR("mmradio_release_sound_focus sound_focus->cur_focus_type : %d\n", sound_focus->cur_focus_type); + if (sound_focus->cur_focus_type != FOCUS_NONE) { + ret = mm_sound_release_focus(sound_focus->handle, sound_focus->cur_focus_type, NULL); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("mm_sound_release_focus is failed\n"); + return MM_ERROR_POLICY_BLOCKED; + } + sound_focus->cur_focus_type = FOCUS_NONE; + } + + MMRADIO_LOG_FLEAVE(); + return ret; +} + +#define AUDIO_FOCUS_REASON_MAX 128 + +void mmradio_get_sound_focus_reason(mm_sound_focus_state_e focus_state, const char *reason_for_change, enum MMMessageInterruptedCode *event_source, int *postMsg) +{ + MMRADIO_LOG_FENTER(); + MMRADIO_LOG_ERROR("mmradio_get_sound_focus_reason focus_state : %d reason_for_change :%s\n", focus_state, reason_for_change); + + if (0 == strncmp(reason_for_change, "call-voice", AUDIO_FOCUS_REASON_MAX) + || (0 == strncmp(reason_for_change, "voip", AUDIO_FOCUS_REASON_MAX)) + || (0 == strncmp(reason_for_change, "ringtone-voip", AUDIO_FOCUS_REASON_MAX)) + || (0 == strncmp(reason_for_change, "ringtone-call", AUDIO_FOCUS_REASON_MAX)) + ) { + if (focus_state == FOCUS_IS_RELEASED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_START; + else if (focus_state == FOCUS_IS_ACQUIRED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_END; + *postMsg = true; + } else if (0 == strncmp(reason_for_change, "alarm", AUDIO_FOCUS_REASON_MAX)) { + if (focus_state == FOCUS_IS_RELEASED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_START; + else if (focus_state == FOCUS_IS_ACQUIRED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_END; + *postMsg = true; + } else if (0 == strncmp(reason_for_change, "notification", AUDIO_FOCUS_REASON_MAX)) { + if (focus_state == FOCUS_IS_RELEASED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START; + else if (focus_state == FOCUS_IS_ACQUIRED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END; + *postMsg = true; + } else if (0 == strncmp(reason_for_change, "emergency", AUDIO_FOCUS_REASON_MAX)) { + if (focus_state == FOCUS_IS_RELEASED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START; + else if (focus_state == FOCUS_IS_ACQUIRED) + *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END; + *postMsg = false; + } else if (0 == strncmp(reason_for_change, "media", AUDIO_FOCUS_REASON_MAX)) { + *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA; + *postMsg = false; + } else { + *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA; + *postMsg = false; + } + MMRADIO_LOG_FLEAVE(); +} diff --git a/src/radio_hal_interface.c b/src/radio_hal_interface.c new file mode 100644 index 0000000..499cd57 --- /dev/null +++ b/src/radio_hal_interface.c @@ -0,0 +1,353 @@ +/* + * radio_hal_interface.c + * + * Copyright (c) 2016 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. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <dlfcn.h> +#include "mm_radio_utils.h" +#include "radio_hal_interface.h" + +#define LIB_TIZEN_RADIO "libtizen-radio.so" + +static int __convert_error_code(int code, char *func_name) +{ + int ret = RADIO_ERROR_NONE; + char *msg = "RADIO_ERROR_NONE"; + MMRADIO_LOG_DEBUG("[%s] Enter code :%x", func_name, code); + + switch (code) { + + case RADIO_ERROR_NONE : + ret = MM_ERROR_NONE; + msg = "MM_ERROR_NONE"; + break; + case RADIO_ERROR_INVALID_PARAMETER : + ret = MM_ERROR_COMMON_INVALID_ARGUMENT; + msg = "MM_ERROR_COMMON_INVALID_ARGUMENT"; + break; + case RADIO_ERROR_INVALID_STATE : + ret = MM_ERROR_RADIO_INVALID_STATE; + msg = "MM_ERROR_RADIO_INVALID_STATE"; + break; + case RADIO_ERROR_OUT_OF_MEMORY : + ret = MM_ERROR_RADIO_NO_FREE_SPACE; + msg = "MM_ERROR_RADIO_NO_FREE_SPACE"; + break; + case RADIO_ERROR_PERMISSION_DENIED : + case RADIO_ERROR_DEVICE_NOT_PREPARED : + ret = MM_ERROR_RADIO_PERMISSION_DENIED; + msg = "MM_ERROR_RADIO_PERMISSION_DENIED"; + break; + case RADIO_ERROR_DEVICE_NOT_OPENED : + ret = MM_ERROR_RADIO_DEVICE_NOT_OPENED; + msg = "MM_ERROR_RADIO_DEVICE_NOT_OPENED"; + break; + case RADIO_ERROR_NOT_SUPPORTED : + case RADIO_ERROR_DEVICE_NOT_SUPPORTED : + case RADIO_ERROR_DEVICE_NOT_FOUND : + ret = MM_ERROR_RADIO_DEVICE_NOT_FOUND; + msg = "MM_ERROR_RADIO_DEVICE_NOT_FOUND"; + break; + case RADIO_ERROR_NO_ANTENNA: + ret = MM_ERROR_RADIO_NO_ANTENNA; + msg = "MM_ERROR_RADIO_NO_ANTENNA"; + break; + case RADIO_ERROR_UNKNOWN : + case RADIO_ERROR_INTERNAL : + default: + ret = MM_ERROR_RADIO_INTERNAL; + msg = "MM_ERROR_RADIO_INTERNAL"; + break; + } + MMRADIO_LOG_ERROR("[%s] %s(0x%08x) : core fw error(0x%x)", func_name, msg, ret, code); + return ret; +} + +int radio_hal_interface_init(mm_radio_hal_interface **handle) +{ + mm_radio_hal_interface *h = NULL; + int ret = MM_ERROR_NONE; + h = (mm_radio_hal_interface *)malloc(sizeof(mm_radio_hal_interface)); + + if(!h) { + MMRADIO_LOG_ERROR("cannot allocate memory for radio_hal interface"); + return MM_ERROR_RADIO_NO_FREE_SPACE; + } + + h->dl_handle = dlopen(LIB_TIZEN_RADIO, RTLD_NOW); + + if(h->dl_handle) { + h->intf.init = dlsym(h->dl_handle, "radio_init"); + h->intf.deinit = dlsym(h->dl_handle, "radio_deinit"); + h->intf.prepare = dlsym(h->dl_handle, "radio_prepare"); + h->intf.unprepare = dlsym(h->dl_handle, "radio_unprepare"); + h->intf.open = dlsym(h->dl_handle, "radio_open"); + h->intf.close = dlsym(h->dl_handle, "radio_close"); + h->intf.start = dlsym(h->dl_handle, "radio_start"); + h->intf.stop = dlsym(h->dl_handle, "radio_stop"); + h->intf.seek = dlsym(h->dl_handle, "radio_seek"); + h->intf.get_frequency = dlsym(h->dl_handle, "radio_get_frequency"); + h->intf.set_frequency = dlsym(h->dl_handle, "radio_set_frequency"); + h->intf.mute = dlsym(h->dl_handle, "radio_mute"); + h->intf.unmute = dlsym(h->dl_handle, "radio_unmute"); + h->intf.get_signal_strength = dlsym(h->dl_handle, "radio_get_signal_strength"); + + if (h->intf.init == NULL || h->intf.deinit == NULL) { + MMRADIO_LOG_ERROR("could not get mandatory funtion"); + goto FAIL; + } + + if (h->intf.init) { + ret = h->intf.init(&h->rh_handle); + if (ret != MM_ERROR_NONE) { + MMRADIO_LOG_ERROR("radio_hal init failed %d", ret); + goto FAIL; + } + } + } else { + MMRADIO_LOG_ERROR("open radio hal_interface failed : %s", dlerror()); + return MM_ERROR_RADIO_INTERNAL; + } + + *handle = h; + + MMRADIO_LOG_ERROR("open radio_hal interface"); + + return MM_ERROR_NONE; +FAIL: + if (h) { + if (h->dl_handle) + dlclose(h->dl_handle); + free(h); + } + + return ret; +} + +int radio_hal_interface_deinit(mm_radio_hal_interface *handle) +{ + int ret = MM_ERROR_NONE; + MMRADIO_CHECK_ARG(handle); + + if (handle->dl_handle) { + ret = handle->intf.deinit(handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + + handle->rh_handle = NULL; + + dlclose(handle->dl_handle); + handle->dl_handle = NULL; + } + + free(handle); + handle = NULL; + + return ret; +} + +int radio_hal_open(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.open) { + ret = radio_handle->intf.open(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal open is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_prepare(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.prepare) { + ret = radio_handle->intf.prepare(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal prepare is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_unprepare(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.prepare) { + ret = radio_handle->intf.unprepare(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal prepare is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + + +int radio_hal_close(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.close) { + ret = radio_handle->intf.close(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal close is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_start(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.start) { + ret = radio_handle->intf.start(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal start is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_stop(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.stop) { + ret = radio_handle->intf.stop(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal stop is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + + +int radio_hal_seek(mm_radio_hal_interface *radio_handle, seek_direction_type_t direction) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.seek) { + ret = radio_handle->intf.seek(radio_handle->rh_handle, (radio_seek_direction_type_t)direction); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal seek is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_get_frequency(mm_radio_hal_interface *radio_handle, uint32_t *frequency) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.get_frequency) { + ret = radio_handle->intf.get_frequency(radio_handle->rh_handle, frequency); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal get_frequency is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_set_frequency(mm_radio_hal_interface *radio_handle, uint32_t frequency) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.set_frequency) { + ret = radio_handle->intf.set_frequency(radio_handle->rh_handle, frequency); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal get_frequency is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_get_signal_strength(mm_radio_hal_interface *radio_handle, uint32_t *strength) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.get_signal_strength) { + ret = radio_handle->intf.get_signal_strength(radio_handle->rh_handle, strength); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal get_signal_strength is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_mute(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.mute) { + ret = radio_handle->intf.mute(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal mute is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; +} + +int radio_hal_unmute(mm_radio_hal_interface *radio_handle) +{ + radio_error_t ret = RADIO_ERROR_NONE; + MMRADIO_CHECK_ARG(radio_handle); + if (radio_handle->intf.unmute) { + ret = radio_handle->intf.unmute(radio_handle->rh_handle); + if (ret != RADIO_ERROR_NONE) + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + MMRADIO_LOG_WARNING("radio_hal unmute is NULL"); + return MM_ERROR_NOT_SUPPORT_API; + } + return MM_ERROR_NONE; + +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + |