4 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 /*===========================================================================================
24 ========================================================================================== */
32 #include <sys/ioctl.h>
37 #include <mm_message.h>
40 #include "mm_radio_priv_hal.h"
42 /*===========================================================================================
43 LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
44 ========================================================================================== */
45 /*---------------------------------------------------------------------------
46 GLOBAL CONSTANT DEFINITIONS:
47 ---------------------------------------------------------------------------*/
49 /*---------------------------------------------------------------------------
50 IMPORTED VARIABLE DECLARATIONS:
51 ---------------------------------------------------------------------------*/
53 /*---------------------------------------------------------------------------
54 IMPORTED FUNCTION DECLARATIONS:
55 ---------------------------------------------------------------------------*/
57 /*---------------------------------------------------------------------------
59 ---------------------------------------------------------------------------*/
60 #define DEFAULT_DEVICE "/dev/radio0"
63 #define DEFAULT_FREQ 107700
66 #define RADIO_FREQ_FORMAT_SET(x_freq) ((x_freq) * FREQ_FRAC)
67 #define RADIO_FREQ_FORMAT_GET(x_freq) ((x_freq) / FREQ_FRAC)
68 /* If non-zero, wrap around when at the end of the frequency range, else stop seeking */
69 #define DEFAULT_WRAP_AROUND 1
71 #define RADIO_DEFAULT_REGION MM_RADIO_REGION_GROUP_USA
72 #define READ_MAX_BUFFER_SIZE 1024
73 #define DEFAULT_MAX_MEDIA_VOLUME 15
74 /*---------------------------------------------------------------------------
75 LOCAL CONSTANT DEFINITIONS:
76 ---------------------------------------------------------------------------*/
78 /*---------------------------------------------------------------------------
79 LOCAL DATA TYPE DEFINITIONS:
80 ---------------------------------------------------------------------------*/
82 /*---------------------------------------------------------------------------
83 GLOBAL VARIABLE DEFINITIONS:
84 ---------------------------------------------------------------------------*/
87 /*---------------------------------------------------------------------------
88 LOCAL VARIABLE DEFINITIONS:
89 ---------------------------------------------------------------------------*/
90 /* radio region configuration table */
91 static const MMRadioRegion_t region_table[] = {
92 { /* Notrh America, South America, South Korea, Taiwan, Australia */
93 MM_RADIO_REGION_GROUP_USA, /* region type */
94 MM_RADIO_DEEMPHASIS_75_US, /* de-emphasis */
95 MM_RADIO_FREQ_MIN_87500_KHZ, /* min freq. */
96 MM_RADIO_FREQ_MAX_108000_KHZ, /* max freq. */
99 { /* China, Europe, Africa, Middle East, Hong Kong, India, Indonesia, Russia, Singapore */
100 MM_RADIO_REGION_GROUP_EUROPE,
101 MM_RADIO_DEEMPHASIS_50_US,
102 MM_RADIO_FREQ_MIN_87500_KHZ,
103 MM_RADIO_FREQ_MAX_108000_KHZ,
107 MM_RADIO_REGION_GROUP_JAPAN,
108 MM_RADIO_DEEMPHASIS_50_US,
109 MM_RADIO_FREQ_MIN_76100_KHZ,
110 MM_RADIO_FREQ_MAX_89900_KHZ,
115 /*---------------------------------------------------------------------------
116 LOCAL FUNCTION PROTOTYPES:
117 ---------------------------------------------------------------------------*/
118 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param);
119 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command);
120 static int __mmradio_get_state(mm_radio_t *radio);
121 static bool __mmradio_set_state(mm_radio_t *radio, int new_state);
122 void _mmradio_seek_cancel(mm_radio_t *radio);
123 static void __mmradio_seek_thread(mm_radio_t *radio);
124 static void __mmradio_scan_thread(mm_radio_t *radio);
125 static bool __is_tunable_frequency(mm_radio_t *radio, int freq);
127 #ifdef TIZEN_FEATURE_SOUND_FOCUS
128 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
129 mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
130 const char *additional_info, void *user_data);
131 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
132 mm_sound_focus_state_e focus_state, const char *reason_for_change,
133 const char *additional_info, void *user_data);
136 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
137 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
139 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
141 int ret = MM_ERROR_NONE;
145 MMRADIO_LOG_FENTER();
147 MMRADIO_CHECK_INSTANCE(radio);
148 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
150 /* if needed, radio region must be updated.
151 * Otherwise, just applying settings to device without it.
154 count = ARRAY_SIZE(region_table);
156 /* TODO: if auto is supported...get the region info. here */
158 /* update radio region settings */
159 for (index = 0; index < count; index++) {
160 /* find the region from pre-defined table */
161 if (region_table[index].country == region) {
162 radio->region_setting.country = region_table[index].country;
163 radio->region_setting.deemphasis = region_table[index].deemphasis;
164 radio->region_setting.band_min = region_table[index].band_min;
165 radio->region_setting.band_max = region_table[index].band_max;
166 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
171 MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
172 radio->region_setting.country, radio->region_setting.deemphasis,
173 radio->region_setting.band_min, radio->region_setting.band_max);
175 MMRADIO_LOG_FLEAVE();
180 int _mmradio_create_radio(mm_radio_t *radio)
182 int ret = MM_ERROR_NONE;
184 MMRADIO_LOG_FENTER();
186 MMRADIO_CHECK_INSTANCE(radio);
187 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
189 /* set default value */
190 radio->freq = DEFAULT_FREQ;
191 #ifdef TIZEN_FEATURE_SOUND_FOCUS
192 memset(&radio->sound_focus, 0, sizeof(mm_radio_sound_focus));
194 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
195 radio->local_volume = 1.0;
197 /* create command lock */
198 ret = pthread_mutex_init(&radio->cmd_lock, NULL);
200 MMRADIO_LOG_ERROR("mutex creation failed");
201 return MM_ERROR_RADIO_INTERNAL;
204 ret = pthread_mutex_init(&radio->volume_lock, NULL);
206 MMRADIO_LOG_ERROR("volume mutex creation failed");
207 return MM_ERROR_RADIO_INTERNAL;
210 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
212 /* initialize resource manager */
213 ret = mmradio_resource_manager_init(&radio->resource_manager, radio);
215 MMRADIO_LOG_ERROR("failed to initialize resource manager\n");
216 return MM_ERROR_RADIO_INTERNAL;
219 #ifdef TIZEN_FEATURE_SOUND_FOCUS
220 ret = mmradio_sound_focus_register(&radio->sound_focus,
221 (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb,
222 (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb,
226 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
227 MMRADIO_LOG_ERROR("mmradio_audio_focus_register is failed");
228 return MM_ERROR_RADIO_INTERNAL;
232 ret = radio_hal_interface_init(&(radio->hal_inf));
234 MMRADIO_LOG_ERROR("mmradio hal interface init failed");
238 MMRADIO_LOG_FLEAVE();
240 return MM_ERROR_NONE;
243 int _mmradio_realize(mm_radio_t *radio)
245 int ret = MM_ERROR_NONE;
249 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
251 MMRADIO_LOG_FENTER();
253 MMRADIO_CHECK_INSTANCE(radio);
254 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
256 ret = pthread_mutex_init(&radio->seek_cancel_mutex, NULL);
258 MMRADIO_LOG_ERROR("Mutex creation failed %d", ret);
259 return MM_ERROR_RADIO_INTERNAL;
262 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
263 /* not initialized yet. set it with default region */
264 region = RADIO_DEFAULT_REGION;
267 /* already initialized by application */
268 region = radio->region_setting.country;
271 ret = _mmradio_apply_region(radio, region, update);
273 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
274 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
275 if (ret != MM_ERROR_NONE) {
276 MMRADIO_LOG_ERROR("sound_manager_create_stream_information_internal error");
277 MMRADIO_LOG_FLEAVE();
280 ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
281 if (ret != MM_ERROR_NONE) {
282 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
283 MMRADIO_LOG_FLEAVE();
288 ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
289 if (ret != MM_ERROR_NONE) {
290 MMRADIO_LOG_WARNING("sound_manager_get_max_volume error");
291 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
293 radio->max_media_volume = max;
296 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
298 if (ret != MM_ERROR_NONE)
299 MMRADIO_LOG_WARNING("failed to get MEDIA_VOLUME");
301 MMRADIO_VOLUME_LOCK(radio);
302 radio->media_volume = volume;
303 MMRADIO_VOLUME_UNLOCK(radio);
305 ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
306 if (ret != MM_ERROR_NONE)
307 MMRADIO_LOG_WARNING("mm_sound_add_volume_changed_callback error");
309 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
311 MMRADIO_LOG_FLEAVE();
313 return MM_ERROR_NONE;
316 int _mmradio_unrealize(mm_radio_t *radio)
318 int ret = MM_ERROR_NONE;
320 MMRADIO_LOG_FENTER();
322 MMRADIO_CHECK_INSTANCE(radio);
323 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
325 ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
326 if (ret != MM_ERROR_NONE)
327 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
329 /*Finish if there are scans*/
330 _mmradio_stop_scan(radio);
332 /*Stop radio if started*/
333 _mmradio_stop(radio);
335 /* close radio device here !!!! */
336 radio_hal_close(radio->hal_inf);
337 radio_hal_unprepare(radio->hal_inf);
338 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
339 sound_manager_destroy_virtual_stream(radio->vstream);
340 sound_manager_destroy_stream_information(radio->stream_info);
343 pthread_mutex_destroy(&radio->seek_cancel_mutex);
345 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
347 MMRADIO_LOG_FLEAVE();
352 int _mmradio_destroy(mm_radio_t *radio)
354 int ret = MM_ERROR_NONE;
355 MMRADIO_LOG_FENTER();
357 MMRADIO_CHECK_INSTANCE(radio);
358 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
360 _mmradio_unrealize(radio);
362 ret = radio_hal_interface_deinit(radio->hal_inf);
364 MMRADIO_LOG_ERROR("mmradio hal interface deinit failed");
368 /* destroy command lock */
369 ret = pthread_mutex_destroy(&radio->cmd_lock);
371 MMRADIO_LOG_ERROR("mutex destroy failed\n");
373 ret = pthread_mutex_destroy(&radio->volume_lock);
375 MMRADIO_LOG_ERROR("volume mutex destroy failed\n");
377 #ifdef TIZEN_FEATURE_SOUND_FOCUS
378 ret = mmradio_sound_focus_deregister(&radio->sound_focus);
380 MMRADIO_LOG_ERROR("failed to deregister sound focus");
381 return MM_ERROR_RADIO_INTERNAL;
385 ret = mmradio_resource_manager_deinit(&radio->resource_manager);
387 MMRADIO_LOG_ERROR("failed to initialize resource manager\n");
388 return MM_ERROR_RADIO_INTERNAL;
391 MMRADIO_LOG_FLEAVE();
393 return MM_ERROR_NONE;
396 /* unit should be KHz */
397 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
399 int ret = MM_ERROR_NONE;
401 MMRADIO_LOG_FENTER();
403 MMRADIO_CHECK_INSTANCE(radio);
404 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
406 MMRADIO_LOG_INFO("Setting %d frequency", freq);
410 ret = radio_hal_set_frequency(radio->hal_inf, freq);
411 if (ret != MM_ERROR_NONE) {
412 MMRADIO_LOG_ERROR("radio_hal_set_frequency error");
413 MMRADIO_LOG_FLEAVE();
417 MMRADIO_LOG_FLEAVE();
423 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
425 int ret = MM_ERROR_NONE;
427 MMRADIO_LOG_FENTER();
429 MMRADIO_CHECK_INSTANCE(radio);
430 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
432 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
434 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
435 if (ret != MM_ERROR_NONE) {
436 MMRADIO_LOG_ERROR("radio_hal_get_frequency error");
441 /* update freq in handle */
442 MMRADIO_LOG_INFO("Updating %d frequency", freq);
445 *pFreq = (int)radio->freq;
447 MMRADIO_LOG_FLEAVE();
452 int _mmradio_mute(mm_radio_t *radio)
454 int ret = MM_ERROR_NONE;
455 MMRADIO_LOG_FENTER();
457 MMRADIO_CHECK_INSTANCE(radio);
458 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
460 ret = radio_hal_mute(radio->hal_inf);
461 if (ret == MM_ERROR_NOT_SUPPORT_API) {
462 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
463 } else if (ret != MM_ERROR_NONE) {
464 MMRADIO_LOG_ERROR("radio_hal_mute error");
465 MMRADIO_LOG_FLEAVE();
469 radio->is_muted = TRUE;
470 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
471 MMRADIO_LOG_FLEAVE();
476 int _mmradio_unmute(mm_radio_t *radio)
478 int ret = MM_ERROR_NONE;
479 MMRADIO_LOG_FENTER();
481 MMRADIO_CHECK_INSTANCE(radio);
482 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
484 ret = radio_hal_unmute(radio->hal_inf);
485 if (ret == MM_ERROR_NOT_SUPPORT_API) {
486 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
487 } else if (ret != MM_ERROR_NONE) {
488 MMRADIO_LOG_ERROR("radio_hal_unmute error");
489 MMRADIO_LOG_FLEAVE();
493 radio->is_muted = FALSE;
494 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
495 MMRADIO_LOG_FLEAVE();
500 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
502 MMRADIO_LOG_FENTER();
504 MMRADIO_CHECK_INSTANCE(radio);
506 radio->msg_cb = callback;
507 radio->msg_cb_param = user_param;
509 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
511 MMRADIO_LOG_FLEAVE();
513 return MM_ERROR_NONE;
516 int _mmradio_get_state(mm_radio_t *radio, int *pState)
520 MMRADIO_LOG_FENTER();
522 MMRADIO_CHECK_INSTANCE(radio);
523 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
525 state = __mmradio_get_state(radio);
529 MMRADIO_LOG_FLEAVE();
531 return MM_ERROR_NONE;
534 int _mmradio_start(mm_radio_t *radio)
536 int ret = MM_ERROR_NONE;
537 unsigned int volume = 0;
539 MMRADIO_LOG_FENTER();
541 MMRADIO_CHECK_INSTANCE(radio);
542 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
544 MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
546 #ifdef TIZEN_FEATURE_SOUND_FOCUS
547 if (radio->sound_focus.handle > 0) {
548 ret = mmradio_acquire_sound_focus(&radio->sound_focus);
549 if (ret != MM_ERROR_NONE) {
550 MMRADIO_LOG_ERROR("failed to set sound focus");
555 /* check previous acquired focus */
556 if (radio->sound_focus.watch_id > 0) {
557 char *stream_type = NULL;
558 char *ext_info = NULL;
561 ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info);
562 if (ret == MM_ERROR_NONE) {
563 MMRADIO_LOG_DEBUG("Focus is acquired by stream_type[%s], option[%d], ext_info[%s]",
564 stream_type, option, ext_info);
565 if (!strcmp(stream_type, "alarm") || !strcmp(stream_type, "ringtone-voip") ||
566 !strcmp(stream_type, "ringtone-call") || !strcmp(stream_type, "voip") ||
567 !strcmp(stream_type, "call-voice") || !strcmp(stream_type, "call-video")) {
568 MMRADIO_LOG_DEBUG("Blcoked by session policy, focus_acquired_by[%s]", stream_type);
571 return MM_ERROR_POLICY_BLOCKED;
579 if (!radio->is_ready) {
580 ret = mmradio_resource_manager_prepare(&radio->resource_manager, MM_RADIO_RESOURCE_TYPE_RADIO);
581 if (ret != MM_ERROR_NONE) {
582 MMRADIO_LOG_ERROR("resource manager prepare fail");
583 return MM_ERROR_RADIO_INTERNAL;
585 ret = mmradio_resource_manager_acquire(&radio->resource_manager);
586 if (ret != MM_ERROR_NONE) {
587 MMRADIO_LOG_ERROR("failed to acquire resource manager");
588 mmradio_resource_manager_unprepare(&radio->resource_manager);
591 ret = radio_hal_prepare(radio->hal_inf);
592 if (ret == MM_ERROR_NOT_SUPPORT_API) {
593 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
594 } else if (ret != MM_ERROR_NONE) {
595 MMRADIO_LOG_ERROR("radio_hal_prepare_device error");
599 ret = radio_hal_open(radio->hal_inf);
600 if (ret == MM_ERROR_NOT_SUPPORT_API) {
601 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
602 } else if (ret != MM_ERROR_NONE) {
603 MMRADIO_LOG_ERROR("radio_hal_init error");
606 radio->is_ready = TRUE;
608 MMRADIO_LOG_DEBUG("radio prepared and opened");
611 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
612 if (ret != MM_ERROR_NONE)
613 MMRADIO_LOG_WARNING("failed to get MEDIA_VOLUME");
615 ret = __mmradio_set_media_volume(radio, volume);
616 if (ret != MM_ERROR_NONE) {
617 MMRADIO_LOG_ERROR("failed to media volume");
621 ret = radio_hal_start(radio->hal_inf);
622 if (ret == MM_ERROR_NOT_SUPPORT_API) {
623 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
625 MMRADIO_LOG_ERROR("failed to radio_hal_start");
629 /* set stored frequency */
630 ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
632 MMRADIO_LOG_ERROR("failed to radio_hal_set_frequency");
636 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
637 ret = sound_manager_start_virtual_stream(radio->vstream);
639 MMRADIO_LOG_ERROR("failed to sound_manager_start_virtual_stream");
644 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
646 MMRADIO_LOG_FLEAVE();
648 return MM_ERROR_NONE;
650 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
652 sound_manager_stop_virtual_stream(radio->vstream);
655 radio_hal_close(radio->hal_inf);
657 radio_hal_unprepare(radio->hal_inf);
658 radio->is_ready = FALSE;
662 int _mmradio_stop(mm_radio_t *radio)
664 int ret = MM_ERROR_NONE;
665 mm_radio_resource_state_e resource_state = MM_RADIO_RESOURCE_STATE_NONE;
667 MMRADIO_LOG_FENTER();
669 MMRADIO_CHECK_INSTANCE(radio);
670 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
672 radio->seek_unmute = FALSE;
673 /*cancel if any seek*/
674 _mmradio_seek_cancel(radio);
675 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
676 ret = sound_manager_stop_virtual_stream(radio->vstream);
677 if (ret != MM_ERROR_NONE) {
678 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
683 ret = radio_hal_stop(radio->hal_inf);
684 if (ret == MM_ERROR_NOT_SUPPORT_API) {
685 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
687 MMRADIO_LOG_ERROR("failed to radio_hal_stop");
691 /* close radio device here !!!! */
692 ret = radio_hal_close(radio->hal_inf);
693 if (ret == MM_ERROR_NOT_SUPPORT_API) {
694 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
695 } else if (ret != MM_ERROR_NONE) {
696 MMRADIO_LOG_ERROR("radio_hal_close_device error");
700 ret = radio_hal_unprepare(radio->hal_inf);
701 if (ret == MM_ERROR_NOT_SUPPORT_API) {
702 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
703 } else if (ret != MM_ERROR_NONE) {
704 MMRADIO_LOG_ERROR("radio_hal_close_device error");
708 radio->is_ready = FALSE;
710 if (!radio->resource_manager.by_rm_cb && /* is being released */
711 mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
712 if (resource_state == MM_RADIO_RESOURCE_STATE_ACQUIRED) {
713 ret = mmradio_resource_manager_release(&radio->resource_manager);
714 if (ret != MM_ERROR_NONE) {
715 MMRADIO_LOG_ERROR("failed to release resource, ret(0x%x)", ret);
721 if (mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
722 if (resource_state == MM_RADIO_RESOURCE_STATE_PREPARED) {
723 ret = mmradio_resource_manager_unprepare(&radio->resource_manager);
724 if (ret != MM_ERROR_NONE)
725 MMRADIO_LOG_ERROR("resource manager unprepare fail");
729 #ifdef TIZEN_FEATURE_SOUND_FOCUS
730 if (radio->sound_focus.handle > 0) {
731 ret = mmradio_release_sound_focus(&radio->sound_focus);
733 MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed");
738 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
740 MMRADIO_LOG_FLEAVE();
742 return MM_ERROR_NONE;
745 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
747 int ret = MM_ERROR_NONE;
749 MMRADIO_LOG_FENTER();
751 MMRADIO_CHECK_INSTANCE(radio);
752 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
754 if (radio->is_seeking) {
755 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
756 return MM_ERROR_RADIO_INTERNAL;
759 radio->seek_unmute = FALSE;
760 radio->is_seeking = TRUE;
761 radio->seek_cancel = FALSE;
763 if (!radio->is_muted) {
764 ret = radio_hal_mute(radio->hal_inf);
765 if (ret == MM_ERROR_NOT_SUPPORT_API) {
766 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
768 MMRADIO_LOG_ERROR("failed to radio_hal_mute");
771 radio->seek_unmute = TRUE;
774 MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
775 radio->seek_direction = direction;
777 ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
780 MMRADIO_LOG_DEBUG("failed create thread");
781 radio->is_seeking = FALSE;
782 radio->seek_cancel = TRUE;
783 if (radio->seek_unmute) {
784 ret = radio_hal_mute(radio->hal_inf);
785 if (ret == MM_ERROR_NOT_SUPPORT_API) {
786 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
788 MMRADIO_LOG_ERROR("failed to radio_hal_mute");
789 radio->seek_unmute = FALSE;
793 return MM_ERROR_RADIO_INTERNAL;
796 MMRADIO_LOG_FLEAVE();
798 return MM_ERROR_NONE;
801 void _mmradio_seek_cancel(mm_radio_t *radio)
803 int ret = MM_ERROR_NONE;
804 char str_error[READ_MAX_BUFFER_SIZE];
805 MMRADIO_LOG_FENTER();
807 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
809 /*cancel any outstanding seek request*/
810 radio->seek_cancel = TRUE;
811 if (radio->seek_thread) {
812 ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
813 MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
814 if (ret == EBUSY) { /* it was already locked by other */
815 MMRADIO_LOG_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
816 } else if (ret == 0) {
817 MMRADIO_LOG_INFO("trylock is successful. unlock now");
818 pthread_mutex_unlock(&radio->seek_cancel_mutex);
820 MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
822 MMRADIO_LOG_DEBUG("pthread_join seek_thread");
823 pthread_join(radio->seek_thread, NULL);
824 MMRADIO_LOG_DEBUG("done");
825 radio->is_seeking = FALSE;
826 radio->seek_thread = 0;
828 MMRADIO_LOG_FLEAVE();
832 int _mmradio_start_scan(mm_radio_t *radio)
834 int ret = MM_ERROR_NONE;
836 MMRADIO_LOG_FENTER();
838 MMRADIO_CHECK_INSTANCE(radio);
839 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
843 radio->stop_scan = false;
845 if (!radio->is_ready) {
846 ret = mmradio_resource_manager_prepare(&radio->resource_manager, MM_RADIO_RESOURCE_TYPE_RADIO);
847 if (ret != MM_ERROR_NONE) {
848 MMRADIO_LOG_ERROR("resource manager prepare fail");
849 return MM_ERROR_RADIO_INTERNAL;
851 ret = mmradio_resource_manager_acquire(&radio->resource_manager);
852 if (ret != MM_ERROR_NONE) {
853 MMRADIO_LOG_ERROR("failed to acquire resource manager");
854 mmradio_resource_manager_unprepare(&radio->resource_manager);
858 ret = radio_hal_prepare(radio->hal_inf);
859 if (ret == MM_ERROR_NOT_SUPPORT_API) {
860 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
861 } else if (ret != MM_ERROR_NONE) {
862 MMRADIO_LOG_ERROR("radio_hal_prepare_device error");
866 ret = radio_hal_open(radio->hal_inf);
867 if (ret == MM_ERROR_NOT_SUPPORT_API) {
868 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
869 } else if (ret != MM_ERROR_NONE) {
870 MMRADIO_LOG_ERROR("radio_hal_init error");
871 MMRADIO_LOG_FLEAVE();
874 radio->is_ready = TRUE;
876 MMRADIO_LOG_DEBUG("radio prepared and opened");
879 scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
881 if (scan_tr_id != 0) {
882 MMRADIO_LOG_ERROR("failed to create thread : scan");
883 return MM_ERROR_RADIO_NOT_INITIALIZED;
886 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
888 MMRADIO_LOG_FLEAVE();
890 return MM_ERROR_NONE;
893 int _mmradio_stop_scan(mm_radio_t *radio)
896 char str_error[READ_MAX_BUFFER_SIZE];
897 MMRADIO_LOG_FENTER();
899 MMRADIO_CHECK_INSTANCE(radio);
900 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
902 radio->stop_scan = true;
904 if (radio->scan_thread > 0) {
905 /* make sure all the search is stopped else we'll wait till search finish which is not ideal*/
906 ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
907 MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
908 if (ret == EBUSY) { /* it was already locked by other */
909 MMRADIO_LOG_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
910 } else if (ret == 0) {
911 MMRADIO_LOG_INFO("trylock is successful. unlock now");
912 pthread_mutex_unlock(&radio->seek_cancel_mutex);
914 MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
916 MMRADIO_LOG_DEBUG("pthread_join scan_thread");
917 pthread_join(radio->scan_thread, NULL);
918 radio->scan_thread = 0;
921 MMRADIO_LOG_FLEAVE();
923 return MM_ERROR_NONE;
926 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
928 int ret = MM_ERROR_NONE;
929 int32_t strength = 0;
930 MMRADIO_LOG_FENTER();
931 MMRADIO_CHECK_INSTANCE(radio);
933 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
935 /* just return stored frequency if radio device is not ready */
936 ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
937 if (ret == MM_ERROR_NOT_SUPPORT_API) {
938 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
939 } else if (ret != MM_ERROR_NONE) {
940 MMRADIO_LOG_ERROR("radio_hal_get_signal_strength error");
942 MMRADIO_LOG_FLEAVE();
945 *value = (int)strength;
946 MMRADIO_LOG_FLEAVE();
947 return MM_ERROR_NONE;
950 void __mmradio_scan_thread(mm_radio_t *radio)
952 int ret = MM_ERROR_NONE;
954 mm_radio_resource_state_e resource_state = MM_RADIO_RESOURCE_STATE_NONE;
956 MMRADIO_LOG_FENTER();
957 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
959 ret = radio_hal_mute(radio->hal_inf);
961 if (ret == MM_ERROR_NOT_SUPPORT_API) {
962 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
963 } else if (ret != MM_ERROR_NONE) {
964 MMRADIO_LOG_ERROR("radio_hal_mute error");
967 ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
969 if (ret != MM_ERROR_NONE)
972 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
973 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
975 while (!radio->stop_scan) {
977 MMMessageParamType param = { 0, };
979 MMRADIO_LOG_DEBUG("scanning....");
981 pthread_mutex_lock(&radio->seek_cancel_mutex);
983 if (radio->stop_scan) {
984 MMRADIO_LOG_INFO("scan was canceled");
985 pthread_mutex_unlock(&radio->seek_cancel_mutex);
989 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
991 pthread_mutex_unlock(&radio->seek_cancel_mutex);
993 if (ret != MM_ERROR_NONE) {
994 MMRADIO_LOG_ERROR("radio scanning error");
998 /* now we can get new frequency from radio device */
999 if (radio->stop_scan)
1002 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1003 if (ret != MM_ERROR_NONE) {
1004 MMRADIO_LOG_ERROR("failed to get current frequency");
1006 if (freq <= prev_freq) {
1007 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
1011 prev_freq = param.radio_scan.frequency = (int)freq;
1012 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
1014 /* drop if max freq is scanned */
1015 if (param.radio_scan.frequency >= radio->region_setting.band_max) {
1016 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", param.radio_scan.frequency);
1020 if (radio->stop_scan) {
1021 /* doesn't need to post */
1025 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1029 if (radio->old_state == MM_RADIO_STATE_READY) {
1030 MMRADIO_LOG_DEBUG("old state is ready");
1031 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
1032 MMRADIO_LOG_DEBUG("old state is playing");
1033 ret = radio_hal_unmute(radio->hal_inf);
1034 if (ret == MM_ERROR_NOT_SUPPORT_API) {
1035 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
1036 } else if (ret != MM_ERROR_NONE) {
1037 MMRADIO_LOG_ERROR("radio_hal_unmute error");
1040 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
1041 if (ret == MM_ERROR_NOT_SUPPORT_API) {
1042 MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
1043 } else if (ret != MM_ERROR_NONE) {
1044 MMRADIO_LOG_ERROR("radio_hal_set_frequency error");
1051 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
1052 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
1054 /* close radio device here !!!! */
1055 ret = radio_hal_close(radio->hal_inf);
1056 if (ret == MM_ERROR_NOT_SUPPORT_API)
1057 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
1058 else if (ret != MM_ERROR_NONE)
1059 MMRADIO_LOG_ERROR("radio_hal_close_device error");
1061 ret = radio_hal_unprepare(radio->hal_inf);
1062 if (ret == MM_ERROR_NOT_SUPPORT_API)
1063 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
1064 else if (ret != MM_ERROR_NONE)
1065 MMRADIO_LOG_ERROR("radio_hal_close_device error");
1067 radio->is_ready = FALSE;
1069 if (!radio->resource_manager.by_rm_cb && /* is being released */
1070 mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
1071 if (resource_state == MM_RADIO_RESOURCE_STATE_ACQUIRED) {
1072 ret = mmradio_resource_manager_release(&radio->resource_manager);
1073 if (ret != MM_ERROR_NONE)
1074 MMRADIO_LOG_ERROR("failed to release resource, ret(0x%x)", ret);
1078 if (mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
1079 if (resource_state == MM_RADIO_RESOURCE_STATE_PREPARED) {
1080 ret = mmradio_resource_manager_unprepare(&radio->resource_manager);
1081 if (ret != MM_ERROR_NONE)
1082 MMRADIO_LOG_ERROR("resource manager unprepare fail");
1086 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
1089 if (!radio->stop_scan)
1090 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1092 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1094 MMRADIO_LOG_FLEAVE();
1096 radio->scan_thread = 0;
1100 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
1102 MMRADIO_LOG_FENTER();
1104 MMRADIO_CHECK_INSTANCE(radio);
1106 if (freq >= radio->region_setting.band_max
1107 || freq <= radio->region_setting.band_min)
1110 MMRADIO_LOG_FLEAVE();
1115 void __mmradio_seek_thread(mm_radio_t *radio)
1117 int ret = MM_ERROR_NONE;
1119 MMMessageParamType param = {0, };
1121 MMRADIO_LOG_FENTER();
1122 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1124 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1126 MMRADIO_LOG_DEBUG("seeking....");
1128 if (!radio->seek_cancel) {
1130 MMRADIO_LOG_DEBUG("try to seek ");
1131 pthread_mutex_lock(&radio->seek_cancel_mutex);
1132 MMRADIO_LOG_DEBUG("seek start");
1134 if (radio->seek_cancel) {
1135 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1136 pthread_mutex_unlock(&radio->seek_cancel_mutex);
1140 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1141 pthread_mutex_unlock(&radio->seek_cancel_mutex);
1143 MMRADIO_LOG_ERROR("radio_hal_seek failed");
1147 /* now we can get new frequency from radio device */
1148 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1150 MMRADIO_LOG_ERROR("failed to get current frequency");
1154 MMRADIO_LOG_DEBUG("found frequency");
1156 /* if same freq is found, ignore it and search next one. */
1157 if (freq == radio->prev_seek_freq) {
1158 MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1162 /* check if it's limit freq or not */
1163 if (__is_tunable_frequency(radio, freq)) {
1164 /* now tune to new frequency */
1165 ret = radio_hal_set_frequency(radio->hal_inf, freq);
1167 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1170 radio->freq = (int)freq;
1171 MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1174 if (radio->seek_unmute) {
1175 /* now turn on radio
1176 * In the case of limit freq, tuner should be unmuted.
1177 * Otherwise, sound can't output even though application set new frequency.
1179 ret = radio_hal_unmute(radio->hal_inf);
1181 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1184 radio->seek_unmute = FALSE;
1187 param.radio_scan.frequency = radio->prev_seek_freq = (int)freq;
1188 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", param.radio_scan.frequency);
1189 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1192 radio->seek_thread = 0;
1193 radio->is_seeking = FALSE;
1195 MMRADIO_LOG_FLEAVE();
1200 if (radio->seek_unmute) {
1201 /* now turn on radio
1202 * In the case of limit freq, tuner should be unmuted.
1203 * Otherwise, sound can't output even though application set new frequency.
1205 ret = radio_hal_unmute(radio->hal_inf);
1207 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1208 radio->seek_unmute = FALSE;
1210 /* freq -1 means it's failed to seek */
1211 param.radio_scan.frequency = -1;
1212 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1213 radio->is_seeking = FALSE;
1214 radio->seek_thread = 0;
1218 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1220 MMRADIO_CHECK_INSTANCE(radio);
1222 MMRADIO_LOG_FENTER();
1224 if (!radio->msg_cb) {
1225 MMRADIO_LOG_WARNING("failed to post a message");
1229 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1231 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1233 MMRADIO_LOG_FLEAVE();
1238 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1240 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1242 MMRADIO_LOG_FENTER();
1244 MMRADIO_CHECK_INSTANCE(radio);
1246 radio_state = __mmradio_get_state(radio);
1248 MMRADIO_LOG_INFO("incomming command : %d current state : %d", command, radio_state);
1251 case MMRADIO_COMMAND_CREATE:
1253 if (radio_state != 0)
1258 case MMRADIO_COMMAND_REALIZE:
1260 if (radio_state == MM_RADIO_STATE_READY ||
1261 radio_state == MM_RADIO_STATE_PLAYING ||
1262 radio_state == MM_RADIO_STATE_SCANNING)
1265 if (radio_state == 0)
1270 case MMRADIO_COMMAND_UNREALIZE:
1272 if (radio_state == MM_RADIO_STATE_NULL)
1275 /* we can call unrealize at any higher state */
1279 case MMRADIO_COMMAND_START:
1281 if (radio_state == MM_RADIO_STATE_PLAYING)
1284 if (radio_state != MM_RADIO_STATE_READY)
1289 case MMRADIO_COMMAND_STOP:
1291 if (radio_state == MM_RADIO_STATE_READY)
1294 if (radio_state != MM_RADIO_STATE_PLAYING)
1299 case MMRADIO_COMMAND_START_SCAN:
1301 if (radio_state == MM_RADIO_STATE_SCANNING)
1304 if (radio_state == MM_RADIO_STATE_NULL)
1309 case MMRADIO_COMMAND_STOP_SCAN:
1311 if (radio_state == MM_RADIO_STATE_READY)
1314 if (radio_state != MM_RADIO_STATE_SCANNING)
1319 case MMRADIO_COMMAND_DESTROY:
1320 case MMRADIO_COMMAND_MUTE:
1321 case MMRADIO_COMMAND_UNMUTE:
1322 case MMRADIO_COMMAND_SET_FREQ:
1323 case MMRADIO_COMMAND_GET_FREQ:
1324 case MMRADIO_COMMAND_SET_REGION:
1325 case MMRADIO_COMMAND_SET_VOLUME:
1326 case MMRADIO_COMMAND_GET_VOLUME:
1328 /* we can do it at any state */
1332 case MMRADIO_COMMAND_SEEK:
1334 if (radio_state != MM_RADIO_STATE_PLAYING)
1339 case MMRADIO_COMMAND_GET_REGION:
1341 if (radio_state == MM_RADIO_STATE_NULL)
1347 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1351 MMRADIO_LOG_DEBUG("status OK");
1353 radio->cmd = command;
1355 MMRADIO_LOG_FLEAVE();
1357 return MM_ERROR_NONE;
1360 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1361 MMRADIO_LOG_FLEAVE();
1362 return MM_ERROR_RADIO_INVALID_STATE;
1365 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1366 MMRADIO_LOG_FLEAVE();
1367 return MM_ERROR_RADIO_NO_OP;
1371 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1373 MMMessageParamType msg = { 0, };
1374 int msg_type = MM_MESSAGE_UNKNOWN;
1376 MMRADIO_LOG_FENTER();
1379 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1383 if (radio->current_state == new_state && radio->pending_state == 0) {
1384 MMRADIO_LOG_WARNING("we are in same state");
1389 radio->old_state = radio->current_state;
1390 radio->current_state = new_state;
1392 /* fill message param */
1393 msg.union_type = MM_MSG_UNION_STATE;
1394 msg.state.previous = radio->old_state;
1395 msg.state.current = radio->current_state;
1397 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1398 /* post message to application */
1399 if (radio->sound_focus.by_focus_cb) {
1400 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1401 msg.state.code = radio->sound_focus.event_src;
1402 MMRADIO_POST_MSG(radio, msg_type, &msg);
1403 } else if (radio->resource_manager.by_rm_cb) {
1404 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1405 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1406 MMRADIO_POST_MSG(radio, msg_type, &msg);
1408 msg_type = MM_MESSAGE_STATE_CHANGED;
1409 MMRADIO_POST_MSG(radio, msg_type, &msg);
1412 if (radio->resource_manager.by_rm_cb) {
1413 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1414 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1415 MMRADIO_POST_MSG(radio, msg_type, &msg);
1417 msg_type = MM_MESSAGE_STATE_CHANGED;
1418 MMRADIO_POST_MSG(radio, msg_type, &msg);
1423 MMRADIO_LOG_FLEAVE();
1428 static int __mmradio_get_state(mm_radio_t *radio)
1430 MMRADIO_CHECK_INSTANCE(radio);
1432 MMRADIO_LOG_INFO("radio state : current : [%d] old : [%d] pending : [%d]",
1433 radio->current_state, radio->old_state, radio->pending_state);
1435 return radio->current_state;
1438 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1439 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
1440 mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
1441 const char *additional_info, void *user_data)
1443 mm_radio_t *radio = (mm_radio_t *)user_data;
1444 enum MMMessageInterruptedCode event_source;
1445 int result = MM_ERROR_NONE;
1446 int postMsg = false;
1448 MMRADIO_LOG_FENTER();
1449 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1450 MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1452 mmradio_get_sound_focus_reason(focus_state, reason_for_change, FALSE, &event_source, &postMsg);
1453 radio->sound_focus.event_src = event_source;
1455 switch (focus_state) {
1456 case FOCUS_IS_RELEASED:{
1457 radio->sound_focus.cur_focus_type &= ~focus_type;
1458 radio->sound_focus.by_focus_cb = true;
1460 MMRADIO_CMD_LOCK(radio);
1461 result = _mmradio_stop(radio);
1463 MMRADIO_LOG_ERROR("failed to stop radio");
1464 MMRADIO_CMD_UNLOCK(radio);
1466 radio->sound_focus.by_focus_cb = false;
1468 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1472 case FOCUS_IS_ACQUIRED:{
1473 MMMessageParamType msg = { 0, };
1474 msg.union_type = MM_MSG_UNION_CODE;
1475 msg.code = event_source;
1477 radio->sound_focus.cur_focus_type |= focus_type;
1479 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1480 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1482 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1487 MMRADIO_LOG_DEBUG("Unknown focus_state");
1491 MMRADIO_LOG_FLEAVE();
1494 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
1495 mm_sound_focus_state_e focus_state, const char *reason_for_change,
1496 const char *additional_info, void *user_data)
1498 mm_radio_t *radio = (mm_radio_t *)user_data;
1499 enum MMMessageInterruptedCode event_source;
1500 int result = MM_ERROR_NONE;
1501 int postMsg = false;
1503 MMRADIO_LOG_FENTER();
1504 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1505 MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1507 mmradio_get_sound_focus_reason(focus_state, reason_for_change, TRUE, &event_source, &postMsg);
1508 radio->sound_focus.event_src = event_source;
1510 switch (focus_state) {
1511 case FOCUS_IS_ACQUIRED: {
1512 radio->sound_focus.cur_focus_type &= ~focus_type;
1513 radio->sound_focus.by_focus_cb = true;
1515 MMRADIO_CMD_LOCK(radio);
1516 result = _mmradio_stop(radio);
1518 MMRADIO_LOG_ERROR("failed to stop radio");
1519 MMRADIO_CMD_UNLOCK(radio);
1521 radio->sound_focus.by_focus_cb = false;
1523 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
1527 case FOCUS_IS_RELEASED: {
1528 MMMessageParamType msg = { 0, };
1529 msg.union_type = MM_MSG_UNION_CODE;
1530 msg.code = event_source;
1532 radio->sound_focus.cur_focus_type |= focus_type;
1534 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1535 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1537 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1542 MMRADIO_LOG_DEBUG("Unknown focus_state");
1546 MMRADIO_LOG_FLEAVE();
1550 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1552 mm_radio_t *radio = (mm_radio_t *)user_data;
1553 int ret = MM_ERROR_NONE;
1554 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1555 if (type == VOLUME_TYPE_MEDIA) {
1556 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1557 ret = __mmradio_set_media_volume(radio, volume);
1558 if (ret != MM_ERROR_NONE)
1559 MMRADIO_LOG_ERROR("__mmradio_set_media_volume error");
1564 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1566 MMRADIO_LOG_FENTER();
1567 MMRADIO_CHECK_INSTANCE(radio);
1568 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1570 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1572 *type = radio->region_setting.country;
1574 MMRADIO_LOG_FLEAVE();
1575 return MM_ERROR_NONE;
1578 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1580 MMRADIO_LOG_FENTER();
1581 MMRADIO_CHECK_INSTANCE(radio);
1582 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1584 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1586 *min_freq = radio->region_setting.band_min;
1587 *max_freq = radio->region_setting.band_max;
1589 MMRADIO_LOG_FLEAVE();
1590 return MM_ERROR_NONE;
1593 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1595 MMRADIO_LOG_FENTER();
1596 MMRADIO_CHECK_INSTANCE(radio);
1597 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1599 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1601 *ch_spacing = radio->region_setting.channel_spacing;
1603 MMRADIO_LOG_FLEAVE();
1604 return MM_ERROR_NONE;
1607 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1609 int ret = MM_ERROR_NONE;
1611 MMRADIO_LOG_FENTER();
1613 MMRADIO_CHECK_INSTANCE(radio);
1614 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1616 MMRADIO_LOG_INFO("Setting %f volume", volume);
1618 MMRADIO_VOLUME_LOCK(radio);
1619 radio->local_volume = volume;
1620 MMRADIO_VOLUME_UNLOCK(radio);
1622 ret = radio_hal_set_volume(radio->hal_inf, volume);
1623 if (ret != MM_ERROR_NONE)
1624 MMRADIO_LOG_ERROR("radio_hal_set_volume error");
1626 MMRADIO_LOG_FLEAVE();
1631 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1633 int ret = MM_ERROR_NONE;
1635 MMRADIO_LOG_FENTER();
1637 MMRADIO_CHECK_INSTANCE(radio);
1638 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1640 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1642 ret = radio_hal_get_volume(radio->hal_inf, &volume);
1643 if (ret != MM_ERROR_NONE) {
1644 MMRADIO_LOG_ERROR("radio_hal_get_volume error");
1649 MMRADIO_VOLUME_LOCK(radio);
1650 radio->local_volume = volume;
1651 *pVolume = (float)radio->local_volume;
1652 MMRADIO_VOLUME_UNLOCK(radio);
1654 MMRADIO_LOG_FLEAVE();
1659 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1661 int ret = MM_ERROR_NONE;
1663 MMRADIO_LOG_FENTER();
1665 MMRADIO_CHECK_INSTANCE(radio);
1666 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1668 MMRADIO_LOG_INFO("Setting %d volume", level);
1670 MMRADIO_VOLUME_LOCK(radio);
1671 radio->media_volume = level;
1672 MMRADIO_VOLUME_UNLOCK(radio);
1674 ret = radio_hal_set_media_volume(radio->hal_inf, level);
1675 if (ret != MM_ERROR_NONE)
1676 MMRADIO_LOG_ERROR("radio_hal_set_media_volume error");
1678 MMRADIO_LOG_FLEAVE();