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/mm_radio_priv_hal.c | |
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/mm_radio_priv_hal.c')
-rw-r--r-- | src/mm_radio_priv_hal.c | 1438 |
1 files changed, 1438 insertions, 0 deletions
diff --git a/src/mm_radio_priv_hal.c b/src/mm_radio_priv_hal.c new file mode 100644 index 0000000..6ac3757 --- /dev/null +++ b/src/mm_radio_priv_hal.c @@ -0,0 +1,1438 @@ +/* + * mm_radio_priv_hal.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. + * + */ + +/*=========================================================================================== +| | +| INCLUDE FILES | +| | +========================================================================================== */ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <errno.h> + +#include <mm_error.h> +#include <mm_debug.h> +#include <mm_message.h> + +#include "mm_radio_priv_hal.h" + +/*=========================================================================================== + LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE +========================================================================================== */ +/*--------------------------------------------------------------------------- + GLOBAL CONSTANT DEFINITIONS: +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + IMPORTED VARIABLE DECLARATIONS: +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + IMPORTED FUNCTION DECLARATIONS: +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + LOCAL #defines: +---------------------------------------------------------------------------*/ +#define DEFAULT_DEVICE "/dev/radio0" +#define TUNER_INDEX 0 + +#define DEFAULT_FREQ 107700 + +#define FREQ_FRAC 16 +#define RADIO_FREQ_FORMAT_SET(x_freq) ((x_freq) * FREQ_FRAC) +#define RADIO_FREQ_FORMAT_GET(x_freq) ((x_freq) / FREQ_FRAC) +/* If non-zero, wrap around when at the end of the frequency range, else stop seeking */ +#define DEFAULT_WRAP_AROUND 1 + +#define RADIO_DEFAULT_REGION MM_RADIO_REGION_GROUP_USA +#define READ_MAX_BUFFER_SIZE 1024 +/*--------------------------------------------------------------------------- + LOCAL CONSTANT DEFINITIONS: +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + LOCAL DATA TYPE DEFINITIONS: +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + GLOBAL VARIABLE DEFINITIONS: +---------------------------------------------------------------------------*/ +extern int errno; + +/*--------------------------------------------------------------------------- + LOCAL VARIABLE DEFINITIONS: +---------------------------------------------------------------------------*/ +/* radio region configuration table */ +static const MMRadioRegion_t region_table[] = { + { /* Notrh America, South America, South Korea, Taiwan, Australia */ + MM_RADIO_REGION_GROUP_USA, /* region type */ + MM_RADIO_DEEMPHASIS_75_US, /* de-emphasis */ + MM_RADIO_FREQ_MIN_87500_KHZ, /* min freq. */ + MM_RADIO_FREQ_MAX_108000_KHZ, /* max freq. */ + 50, + }, + { /* China, Europe, Africa, Middle East, Hong Kong, India, Indonesia, Russia, Singapore */ + MM_RADIO_REGION_GROUP_EUROPE, + MM_RADIO_DEEMPHASIS_50_US, + MM_RADIO_FREQ_MIN_87500_KHZ, + MM_RADIO_FREQ_MAX_108000_KHZ, + 50, + }, + { + MM_RADIO_REGION_GROUP_JAPAN, + MM_RADIO_DEEMPHASIS_50_US, + MM_RADIO_FREQ_MIN_76100_KHZ, + MM_RADIO_FREQ_MAX_89900_KHZ, + 50, + }, +}; + +/*--------------------------------------------------------------------------- + LOCAL FUNCTION PROTOTYPES: +---------------------------------------------------------------------------*/ +static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param); +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); + +#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_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; + int count = 0; + int index = 0; + + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE(radio); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION); + + /* if needed, radio region must be updated. + * Otherwise, just applying settings to device without it. + */ + if (update) { + count = ARRAY_SIZE(region_table); + + /* TODO: if auto is supported...get the region info. here */ + + /* update radio region settings */ + for (index = 0; index < count; index++) { + /* find the region from pre-defined table */ + if (region_table[index].country == region) { + radio->region_setting.country = region_table[index].country; + radio->region_setting.deemphasis = region_table[index].deemphasis; + radio->region_setting.band_min = region_table[index].band_min; + radio->region_setting.band_max = region_table[index].band_max; + radio->region_setting.channel_spacing = region_table[index].channel_spacing; + } + } + } + + 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); + + MMRADIO_LOG_FLEAVE(); + + return ret; +} + +int _mmradio_create_radio(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_CREATE); + + /* set default value */ + 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)); + + /* create command lock */ + ret = pthread_mutex_init(&radio->cmd_lock, NULL); + if (ret) { + MMRADIO_LOG_ERROR("mutex creation failed\n"); + return MM_ERROR_RADIO_INTERNAL; + } + + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL); + +#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); + + 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(); + + return MM_ERROR_NONE; +} + +int _mmradio_realize(mm_radio_t *radio) +{ + int ret = MM_ERROR_NONE; + 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); + + ret = pthread_mutex_init(&radio->seek_cancel_mutex, NULL); + if (ret < 0) { + MMRADIO_LOG_DEBUG("Mutex creation failed %d", ret); + } + + 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); + +#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; + } + 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_NONE; +} + +int _mmradio_unrealize(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_UNREALIZE); + + 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; + } + + /*Finish if there are scans*/ + _mmradio_stop_scan(radio); + + /*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(); + + return MM_ERROR_NONE; +} + +int _mmradio_destroy(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_DESTROY); + + _mmradio_unrealize(radio); + + ret = radio_hal_interface_deinit(radio->hal_inf); + if (ret) { + MMRADIO_LOG_ERROR("mmradio hal interface deinit failed\n"); + return ret; + } +#ifdef TIZEN_FEATURE_SOUND_FOCUS + ret = mmradio_sound_focus_deregister(&radio->sound_focus); + if (ret) { + MMRADIO_LOG_ERROR("failed to deregister sound focus\n"); + return MM_ERROR_RADIO_INTERNAL; + } +#endif + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +/* 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); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ); + + MMRADIO_LOG_DEBUG("Setting %d frequency\n", freq); + + radio->freq = freq; + + 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; + } + + MMRADIO_LOG_FLEAVE(); + + return ret; + +} + +int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq) +{ + int ret = MM_ERROR_NONE; + uint32_t freq = 0; + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE(radio); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ); + + return_val_if_fail(pFreq, MM_ERROR_INVALID_ARGUMENT); + + 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; + } + + /* update freq in handle */ + radio->freq = freq; + + *pFreq = (int)radio->freq; + + MMRADIO_LOG_FLEAVE(); + + 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); + + 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 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); + + 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; + } + + radio->is_muted = FALSE; + + MMRADIO_LOG_FLEAVE(); + + return ret; +} + +int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param) +{ + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE(radio); + + radio->msg_cb = callback; + radio->msg_cb_param = user_param; + + MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x\n", callback, user_param); + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +int _mmradio_get_state(mm_radio_t *radio, int *pState) +{ + int state = 0; + + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE(radio); + return_val_if_fail(pState, MM_ERROR_INVALID_ARGUMENT); + + state = __mmradio_get_state(radio); + + *pState = state; + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +int _mmradio_start(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_START); + + MMRADIO_LOG_DEBUG("now tune to frequency : %d\n", radio->freq); + +#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 + + 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; + } + + 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"); + } + + 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) { + 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; +} + +int _mmradio_stop(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_STOP); + + 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 + 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; + } + + 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; + } + + /* 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 = 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; + } + + radio->is_ready = FALSE; + +#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); + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +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); + + 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; + } + + 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; + + ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio); + + 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; + } + + MMRADIO_LOG_FLEAVE(); + + 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); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN); + + int scan_tr_id = 0; + + 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) { + MMRADIO_LOG_DEBUG("failed to create thread : scan\n"); + return MM_ERROR_RADIO_NOT_INITIALIZED; + } + + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING); + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +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); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN); + + 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; + } + + MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY); + MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL); + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; +} + +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 */ + 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; + MMRADIO_LOG_FLEAVE(); + return ret; + } + *value = (int)strength; + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_NONE; +} + +void __mmradio_scan_thread(mm_radio_t *radio) +{ + int ret = MM_ERROR_NONE; + int prev_freq = 0; + + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); + + 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 (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) { + uint32_t freq = 0; + MMMessageParamType param = { 0, }; + + MMRADIO_LOG_DEBUG("scanning....\n"); + + 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; + } + + 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 = 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) { + MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan\n"); + break; + } + + if (freq == prev_freq) + continue; + + 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 */ + if (param.radio_scan.frequency == radio->region_setting.band_max) { + MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan\n", param.radio_scan.frequency); + break; + } + + if (radio->stop_scan) { + /* doesn't need to post */ + break; + } + + MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m); + } + } +FINISHED: + if (radio->old_state == 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 = 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) + MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL); + + MMRADIO_LOG_FLEAVE(); + + pthread_exit(NULL); + + return; +} + +bool __is_tunable_frequency(mm_radio_t *radio, int freq) +{ + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE(radio); + + if (freq >= radio->region_setting.band_max + || freq <= radio->region_setting.band_min) + return false; + + MMRADIO_LOG_FLEAVE(); + + return true; +} + +void __mmradio_seek_thread(mm_radio_t *radio) +{ + int ret = MM_ERROR_NONE; + uint32_t freq = 0; + MMMessageParamType param = {0, }; + + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); + + MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL); + + MMRADIO_LOG_DEBUG("seeking....\n"); + + if (!radio->seek_cancel) { + + 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 = radio_hal_get_frequency(radio->hal_inf, &freq); + if (ret) { + MMRADIO_LOG_ERROR("failed to get current frequency\n"); + goto SEEK_FAILED; + } + + MMRADIO_LOG_DEBUG("found frequency\n"); + + /* 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"); + goto SEEK_FAILED; + } + + /* check if it's limit freq or not */ + if (__is_tunable_frequency(radio, freq)) { + /* now tune to new frequency */ + ret = radio_hal_set_frequency(radio->hal_inf, freq); + 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 = (int)freq; + MMRADIO_LOG_DEBUG("seeking : new frequency : [%d]\n", param.radio_scan.frequency); + MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m); + } + + radio->seek_thread = 0; + radio->is_seeking = FALSE; + + MMRADIO_LOG_FLEAVE(); + + pthread_exit(NULL); + 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; +} + +static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param) +{ + MMRADIO_CHECK_INSTANCE(radio); + + MMRADIO_LOG_FENTER(); + + if (!radio->msg_cb) { + debug_warning("failed to post a message\n"); + return false; + } + + MMRADIO_LOG_DEBUG("address of msg_cb : %p\n", radio->msg_cb); + + radio->msg_cb(msgtype, param, radio->msg_cb_param); + + MMRADIO_LOG_FLEAVE(); + + return true; +} + +static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command) +{ + MMRadioStateType radio_state = MM_RADIO_STATE_NUM; + + MMRADIO_LOG_FENTER(); + + MMRADIO_CHECK_INSTANCE(radio); + + radio_state = __mmradio_get_state(radio); + + MMRADIO_LOG_DEBUG("incomming command : %d current state : %d\n", command, radio_state); + + switch (command) { + case MMRADIO_COMMAND_CREATE: + { + if (radio_state != 0) + goto NO_OP; + } + break; + + case MMRADIO_COMMAND_REALIZE: + { + if (radio_state == MM_RADIO_STATE_READY || + radio_state == MM_RADIO_STATE_PLAYING || + radio_state == MM_RADIO_STATE_SCANNING) + goto NO_OP; + + if (radio_state == 0) + goto INVALID_STATE; + } + break; + + case MMRADIO_COMMAND_UNREALIZE: + { + if (radio_state == MM_RADIO_STATE_NULL) + goto NO_OP; + + /* we can call unrealize at any higher state */ + } + break; + + case MMRADIO_COMMAND_START: + { + if (radio_state == MM_RADIO_STATE_PLAYING) + goto NO_OP; + + if (radio_state != MM_RADIO_STATE_READY) + goto INVALID_STATE; + } + break; + + case MMRADIO_COMMAND_STOP: + { + if (radio_state == MM_RADIO_STATE_READY) + goto NO_OP; + + if (radio_state != MM_RADIO_STATE_PLAYING) + goto INVALID_STATE; + } + break; + + case MMRADIO_COMMAND_START_SCAN: + { + if (radio_state == MM_RADIO_STATE_SCANNING) + goto NO_OP; + + if (radio_state == MM_RADIO_STATE_NULL) + goto INVALID_STATE; + } + break; + + case MMRADIO_COMMAND_STOP_SCAN: + { + if (radio_state == MM_RADIO_STATE_READY) + goto NO_OP; + + if (radio_state != MM_RADIO_STATE_SCANNING) + goto INVALID_STATE; + } + break; + + case MMRADIO_COMMAND_DESTROY: + case MMRADIO_COMMAND_MUTE: + case MMRADIO_COMMAND_UNMUTE: + case MMRADIO_COMMAND_SET_FREQ: + case MMRADIO_COMMAND_GET_FREQ: + case MMRADIO_COMMAND_SET_REGION: + { + /* we can do it at any state */ + } + break; + + case MMRADIO_COMMAND_SEEK: + { + if (radio_state != MM_RADIO_STATE_PLAYING) + goto INVALID_STATE; + } + break; + + case MMRADIO_COMMAND_GET_REGION: + { + if (radio_state == MM_RADIO_STATE_NULL) + goto INVALID_STATE; + } + break; + + default: + MMRADIO_LOG_DEBUG("not handled in FSM. don't care it\n"); + break; + } + + MMRADIO_LOG_DEBUG("status OK\n"); + + radio->cmd = command; + + MMRADIO_LOG_FLEAVE(); + + return MM_ERROR_NONE; + + INVALID_STATE: + debug_warning("invalid state. current : %d command : %d\n", radio_state, command); + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_RADIO_INVALID_STATE; + + NO_OP: + debug_warning("mm-radio is in the desired state(%d). doing noting\n", radio_state); + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_RADIO_NO_OP; + +} + +static bool __mmradio_set_state(mm_radio_t *radio, int new_state) +{ + MMMessageParamType msg = { 0, }; + int msg_type = MM_MESSAGE_UNKNOWN; + + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE(radio); + + if (!radio) { + debug_warning("calling set_state with invalid radio handle\n"); + return false; + } + + if (radio->current_state == new_state && radio->pending_state == 0) { + debug_warning("we are in same state\n"); + return true; + } + + /* set state */ + radio->old_state = radio->current_state; + radio->current_state = new_state; + + /* fill message param */ + msg.state.previous = radio->old_state; + msg.state.current = radio->current_state; + +#ifdef TIZEN_FEATURE_SOUND_FOCUS + /* post message to application */ + switch (radio->sound_focus.by_focus_cb) { + case MMRADIO_FOCUS_CB_NONE: + { + msg_type = MM_MESSAGE_STATE_CHANGED; + MMRADIO_POST_MSG(radio, msg_type, &msg); + } + break; + + case MMRADIO_FOCUS_CB_POSTMSG: + { + msg_type = MM_MESSAGE_STATE_INTERRUPTED; + msg.union_type = MM_MSG_UNION_CODE; + msg.code = radio->sound_focus.event_src; + MMRADIO_POST_MSG(radio, msg_type, &msg); + } + break; + + case MMRADIO_FOCUS_CB_SKIP_POSTMSG: + default: + break; + } +#else + msg_type = MM_MESSAGE_STATE_CHANGED; + MMRADIO_POST_MSG(radio, msg_type, &msg); +#endif + + MMRADIO_LOG_FLEAVE(); + + return true; +} + +static int __mmradio_get_state(mm_radio_t *radio) +{ + MMRADIO_CHECK_INSTANCE(radio); + + MMRADIO_LOG_DEBUG("radio state : current : [%d] old : [%d] pending : [%d]\n", + radio->current_state, radio->old_state, radio->pending_state); + + 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; + enum MMMessageInterruptedCode event_source; + int result = MM_ERROR_NONE; + int postMsg = false; + + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); + + 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->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_ACQUIRED:{ + 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(); +} + +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; + int postMsg = false; + + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio); + + 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) +{ + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE(radio); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION); + + return_val_if_fail(type, MM_ERROR_INVALID_ARGUMENT); + + *type = radio->region_setting.country; + + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_NONE; +} + +int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq) +{ + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE(radio); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION); + + return_val_if_fail(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT); + + *min_freq = radio->region_setting.band_min; + *max_freq = radio->region_setting.band_max; + + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_NONE; +} + +int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing) +{ + MMRADIO_LOG_FENTER(); + MMRADIO_CHECK_INSTANCE(radio); + MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION); + + return_val_if_fail(ch_spacing, MM_ERROR_INVALID_ARGUMENT); + + *ch_spacing = radio->region_setting.channel_spacing; + + MMRADIO_LOG_FLEAVE(); + return MM_ERROR_NONE; +} |