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);
138 static int __resource_release_cb(mm_resource_manager_h rm,
139 mm_resource_manager_res_h res, void *user_data);
141 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
143 int ret = MM_ERROR_NONE;
147 MMRADIO_LOG_FENTER();
149 MMRADIO_CHECK_INSTANCE(radio);
150 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
152 /* if needed, radio region must be updated.
153 * Otherwise, just applying settings to device without it.
156 count = ARRAY_SIZE(region_table);
158 /* TODO: if auto is supported...get the region info. here */
160 /* update radio region settings */
161 for (index = 0; index < count; index++) {
162 /* find the region from pre-defined table */
163 if (region_table[index].country == region) {
164 radio->region_setting.country = region_table[index].country;
165 radio->region_setting.deemphasis = region_table[index].deemphasis;
166 radio->region_setting.band_min = region_table[index].band_min;
167 radio->region_setting.band_max = region_table[index].band_max;
168 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
173 MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
174 radio->region_setting.country, radio->region_setting.deemphasis,
175 radio->region_setting.band_min, radio->region_setting.band_max);
177 MMRADIO_LOG_FLEAVE();
182 int _mmradio_create_radio(mm_radio_t *radio)
184 int ret = MM_ERROR_NONE;
186 MMRADIO_LOG_FENTER();
188 MMRADIO_CHECK_INSTANCE(radio);
189 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
191 /* set default value */
192 radio->freq = DEFAULT_FREQ;
193 #ifdef TIZEN_FEATURE_SOUND_FOCUS
194 memset(&radio->sound_focus, 0, sizeof(mm_radio_sound_focus));
196 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
197 radio->local_volume = 1.0;
199 /* create command lock */
200 ret = pthread_mutex_init(&radio->cmd_lock, NULL);
202 MMRADIO_LOG_ERROR("failed to create mutex");
203 return MM_ERROR_RADIO_INTERNAL;
206 ret = pthread_mutex_init(&radio->volume_lock, NULL);
208 MMRADIO_LOG_ERROR("failed to create volume mutex");
209 return MM_ERROR_RADIO_INTERNAL;
212 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
214 /* initialize resource manager */
215 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
216 __resource_release_cb, radio, &radio->resource_manager);
218 MMRADIO_LOG_ERROR("failed to create resource manager");
219 return MM_ERROR_RADIO_INTERNAL;
222 #ifdef TIZEN_FEATURE_SOUND_FOCUS
223 ret = mmradio_sound_focus_register(&radio->sound_focus,
224 (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb,
225 (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb,
229 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
230 MMRADIO_LOG_ERROR("failed to register sound focus");
231 return MM_ERROR_RADIO_INTERNAL;
235 ret = radio_hal_interface_init(&(radio->hal_inf));
237 MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
241 MMRADIO_LOG_FLEAVE();
243 return MM_ERROR_NONE;
246 int _mmradio_realize(mm_radio_t *radio)
248 int ret = MM_ERROR_NONE;
252 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
254 MMRADIO_LOG_FENTER();
256 MMRADIO_CHECK_INSTANCE(radio);
257 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
259 ret = pthread_mutex_init(&radio->seek_cancel_mutex, NULL);
261 MMRADIO_LOG_ERROR("failed to create seek cancel mutex %d", ret);
262 return MM_ERROR_RADIO_INTERNAL;
265 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
266 /* not initialized yet. set it with default region */
267 region = RADIO_DEFAULT_REGION;
270 /* already initialized by application */
271 region = radio->region_setting.country;
274 ret = _mmradio_apply_region(radio, region, update);
276 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
277 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
278 if (ret != MM_ERROR_NONE) {
279 MMRADIO_LOG_ERROR("failed to create stream information");
280 MMRADIO_LOG_FLEAVE();
283 ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
284 if (ret != MM_ERROR_NONE) {
285 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
286 MMRADIO_LOG_FLEAVE();
291 ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
292 if (ret != MM_ERROR_NONE) {
293 MMRADIO_LOG_WARNING("failed to get max volume");
294 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
296 radio->max_media_volume = max;
299 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
301 if (ret != MM_ERROR_NONE)
302 MMRADIO_LOG_WARNING("failed to get media volume");
304 MMRADIO_VOLUME_LOCK(radio);
305 radio->media_volume = volume;
306 MMRADIO_VOLUME_UNLOCK(radio);
308 ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
309 if (ret != MM_ERROR_NONE)
310 MMRADIO_LOG_WARNING("failed to register volume changed callback");
312 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
314 MMRADIO_LOG_FLEAVE();
316 return MM_ERROR_NONE;
319 int _mmradio_unrealize(mm_radio_t *radio)
321 int ret = MM_ERROR_NONE;
323 MMRADIO_LOG_FENTER();
325 MMRADIO_CHECK_INSTANCE(radio);
326 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
328 ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
329 if (ret != MM_ERROR_NONE)
330 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
332 /*Finish if there are scans*/
333 _mmradio_stop_scan(radio);
335 /*Stop radio if started*/
336 _mmradio_stop(radio);
338 /* close radio device here !!!! */
339 radio_hal_close(radio->hal_inf);
340 radio_hal_unprepare(radio->hal_inf);
341 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
342 sound_manager_destroy_virtual_stream(radio->vstream);
343 sound_manager_destroy_stream_information(radio->stream_info);
346 pthread_mutex_destroy(&radio->seek_cancel_mutex);
348 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
350 MMRADIO_LOG_FLEAVE();
355 int _mmradio_destroy(mm_radio_t *radio)
357 int ret = MM_ERROR_NONE;
358 MMRADIO_LOG_FENTER();
360 MMRADIO_CHECK_INSTANCE(radio);
361 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
363 _mmradio_unrealize(radio);
365 ret = radio_hal_interface_deinit(radio->hal_inf);
367 MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
371 /* destroy command lock */
372 ret = pthread_mutex_destroy(&radio->cmd_lock);
374 MMRADIO_LOG_ERROR("failed to destory muxtex");
376 ret = pthread_mutex_destroy(&radio->volume_lock);
378 MMRADIO_LOG_ERROR("failed to destory volume mutex");
380 #ifdef TIZEN_FEATURE_SOUND_FOCUS
381 ret = mmradio_sound_focus_deregister(&radio->sound_focus);
383 MMRADIO_LOG_ERROR("failed to deregister sound focus");
384 return MM_ERROR_RADIO_INTERNAL;
388 ret = mm_resource_manager_destroy(radio->resource_manager);
390 MMRADIO_LOG_ERROR("failed to destroy resource manager");
391 return MM_ERROR_RADIO_INTERNAL;
394 MMRADIO_LOG_FLEAVE();
396 return MM_ERROR_NONE;
399 /* unit should be KHz */
400 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
402 int ret = MM_ERROR_NONE;
404 MMRADIO_LOG_FENTER();
406 MMRADIO_CHECK_INSTANCE(radio);
407 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
409 MMRADIO_LOG_INFO("Setting %d frequency", freq);
413 ret = radio_hal_set_frequency(radio->hal_inf, freq);
414 if (ret != MM_ERROR_NONE) {
415 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
416 MMRADIO_LOG_FLEAVE();
420 MMRADIO_LOG_FLEAVE();
426 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
428 int ret = MM_ERROR_NONE;
430 MMRADIO_LOG_FENTER();
432 MMRADIO_CHECK_INSTANCE(radio);
433 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
435 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
437 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
438 if (ret != MM_ERROR_NONE) {
439 MMRADIO_LOG_ERROR("failed to get radio hal frequency");
444 /* update freq in handle */
445 MMRADIO_LOG_INFO("Updating %d frequency", freq);
448 *pFreq = (int)radio->freq;
450 MMRADIO_LOG_FLEAVE();
455 int _mmradio_mute(mm_radio_t *radio)
457 int ret = MM_ERROR_NONE;
458 MMRADIO_LOG_FENTER();
460 MMRADIO_CHECK_INSTANCE(radio);
461 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
463 ret = radio_hal_mute(radio->hal_inf);
464 if (ret == MM_ERROR_NOT_SUPPORT_API) {
465 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
466 } else if (ret != MM_ERROR_NONE) {
467 MMRADIO_LOG_ERROR("failed to set radio hal mute");
468 MMRADIO_LOG_FLEAVE();
472 radio->is_muted = TRUE;
473 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
474 MMRADIO_LOG_FLEAVE();
479 int _mmradio_unmute(mm_radio_t *radio)
481 int ret = MM_ERROR_NONE;
482 MMRADIO_LOG_FENTER();
484 MMRADIO_CHECK_INSTANCE(radio);
485 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
487 ret = radio_hal_unmute(radio->hal_inf);
488 if (ret == MM_ERROR_NOT_SUPPORT_API) {
489 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
490 } else if (ret != MM_ERROR_NONE) {
491 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
492 MMRADIO_LOG_FLEAVE();
496 radio->is_muted = FALSE;
497 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
498 MMRADIO_LOG_FLEAVE();
503 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
505 MMRADIO_LOG_FENTER();
507 MMRADIO_CHECK_INSTANCE(radio);
509 radio->msg_cb = callback;
510 radio->msg_cb_param = user_param;
512 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
514 MMRADIO_LOG_FLEAVE();
516 return MM_ERROR_NONE;
519 int _mmradio_get_state(mm_radio_t *radio, int *pState)
523 MMRADIO_LOG_FENTER();
525 MMRADIO_CHECK_INSTANCE(radio);
526 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
528 state = __mmradio_get_state(radio);
532 MMRADIO_LOG_FLEAVE();
534 return MM_ERROR_NONE;
537 int _mmradio_start(mm_radio_t *radio)
539 int ret = MM_ERROR_NONE;
540 unsigned int volume = 0;
542 MMRADIO_LOG_FENTER();
544 MMRADIO_CHECK_INSTANCE(radio);
545 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
547 MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
549 #ifdef TIZEN_FEATURE_SOUND_FOCUS
550 if (radio->sound_focus.handle > 0) {
551 ret = mmradio_acquire_sound_focus(&radio->sound_focus);
552 if (ret != MM_ERROR_NONE) {
553 MMRADIO_LOG_ERROR("failed to acquire sound focus");
558 /* check previous acquired focus */
559 if (radio->sound_focus.watch_id > 0) {
560 char *stream_type = NULL;
561 char *ext_info = NULL;
564 ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info);
565 if (ret == MM_ERROR_NONE) {
566 MMRADIO_LOG_DEBUG("Focus is acquired by stream_type[%s], option[%d], ext_info[%s]",
567 stream_type, option, ext_info);
568 if (!strcmp(stream_type, "alarm") || !strcmp(stream_type, "ringtone-voip") ||
569 !strcmp(stream_type, "ringtone-call") || !strcmp(stream_type, "voip") ||
570 !strcmp(stream_type, "call-voice") || !strcmp(stream_type, "call-video")) {
571 MMRADIO_LOG_DEBUG("Blcoked by session policy, focus_acquired_by[%s]", stream_type);
574 return MM_ERROR_POLICY_BLOCKED;
582 if (!radio->is_ready) {
583 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
584 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
585 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
586 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
587 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
588 return MM_ERROR_RADIO_INTERNAL;
591 radio->interrupted_by_resource_conflict = FALSE;
592 ret = mm_resource_manager_commit(radio->resource_manager);
593 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
594 MMRADIO_LOG_ERROR("failed to commit resource manager");
595 mm_resource_manager_mark_for_release(radio->resource_manager,
596 radio->radio_resource);
597 radio->radio_resource = NULL;
601 ret = radio_hal_prepare(radio->hal_inf);
602 if (ret == MM_ERROR_NOT_SUPPORT_API) {
603 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
604 } else if (ret != MM_ERROR_NONE) {
605 MMRADIO_LOG_ERROR("failed to prepare radio hal");
609 ret = radio_hal_open(radio->hal_inf);
610 if (ret == MM_ERROR_NOT_SUPPORT_API) {
611 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
612 } else if (ret != MM_ERROR_NONE) {
613 MMRADIO_LOG_ERROR("failed to open radio hal");
616 radio->is_ready = TRUE;
618 MMRADIO_LOG_DEBUG("radio prepared and opened");
621 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
622 if (ret != MM_ERROR_NONE)
623 MMRADIO_LOG_WARNING("failed to get media volume");
625 ret = __mmradio_set_media_volume(radio, volume);
626 if (ret != MM_ERROR_NONE) {
627 MMRADIO_LOG_ERROR("failed to set media volume");
631 ret = radio_hal_start(radio->hal_inf);
632 if (ret == MM_ERROR_NOT_SUPPORT_API) {
633 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
635 MMRADIO_LOG_ERROR("failed to start radio hal");
639 /* set stored frequency */
640 ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
642 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
646 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
647 ret = sound_manager_start_virtual_stream(radio->vstream);
649 MMRADIO_LOG_ERROR("failed to start sound manager virtual stream");
654 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
656 MMRADIO_LOG_FLEAVE();
658 return MM_ERROR_NONE;
661 radio_hal_close(radio->hal_inf);
663 radio_hal_unprepare(radio->hal_inf);
664 radio->is_ready = FALSE;
668 int _mmradio_stop(mm_radio_t *radio)
670 int ret = MM_ERROR_NONE;
672 MMRADIO_LOG_FENTER();
674 MMRADIO_CHECK_INSTANCE(radio);
675 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
677 radio->seek_unmute = FALSE;
678 /*cancel if any seek*/
679 _mmradio_seek_cancel(radio);
680 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
681 ret = sound_manager_stop_virtual_stream(radio->vstream);
682 if (ret != MM_ERROR_NONE) {
683 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
688 ret = radio_hal_stop(radio->hal_inf);
689 if (ret == MM_ERROR_NOT_SUPPORT_API) {
690 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
692 MMRADIO_LOG_ERROR("failed to stop radio hal");
696 /* close radio device here !!!! */
697 ret = radio_hal_close(radio->hal_inf);
698 if (ret == MM_ERROR_NOT_SUPPORT_API) {
699 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
700 } else if (ret != MM_ERROR_NONE) {
701 MMRADIO_LOG_ERROR("failed to close radio hal");
705 ret = radio_hal_unprepare(radio->hal_inf);
706 if (ret == MM_ERROR_NOT_SUPPORT_API) {
707 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
708 } else if (ret != MM_ERROR_NONE) {
709 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
713 radio->is_ready = FALSE;
715 if (!radio->interrupted_by_resource_conflict && /* is being released */
716 radio->radio_resource != NULL) {
717 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
718 radio->radio_resource);
719 radio->radio_resource = NULL;
720 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
721 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
725 ret = mm_resource_manager_commit(radio->resource_manager);
726 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
727 MMRADIO_LOG_ERROR("resource manager commit fail");
730 #ifdef TIZEN_FEATURE_SOUND_FOCUS
731 if (radio->sound_focus.handle > 0) {
732 ret = mmradio_release_sound_focus(&radio->sound_focus);
734 MMRADIO_LOG_ERROR("failed to release sound focus");
739 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
741 MMRADIO_LOG_FLEAVE();
743 return MM_ERROR_NONE;
746 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
748 int ret = MM_ERROR_NONE;
750 MMRADIO_LOG_FENTER();
752 MMRADIO_CHECK_INSTANCE(radio);
753 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
755 if (radio->is_seeking) {
756 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
757 return MM_ERROR_RADIO_INTERNAL;
760 radio->seek_unmute = FALSE;
761 radio->is_seeking = TRUE;
762 radio->seek_cancel = FALSE;
764 if (!radio->is_muted) {
765 ret = radio_hal_mute(radio->hal_inf);
766 if (ret == MM_ERROR_NOT_SUPPORT_API) {
767 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
769 MMRADIO_LOG_ERROR("failed to set radio hal mute");
772 radio->seek_unmute = TRUE;
775 MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
776 radio->seek_direction = direction;
778 ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
781 MMRADIO_LOG_DEBUG("failed to create thread");
782 radio->is_seeking = FALSE;
783 radio->seek_cancel = TRUE;
784 if (radio->seek_unmute) {
785 ret = radio_hal_mute(radio->hal_inf);
786 if (ret == MM_ERROR_NOT_SUPPORT_API) {
787 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
789 MMRADIO_LOG_ERROR("failed to set radio hal mute");
790 radio->seek_unmute = FALSE;
794 return MM_ERROR_RADIO_INTERNAL;
797 MMRADIO_LOG_FLEAVE();
799 return MM_ERROR_NONE;
802 void _mmradio_seek_cancel(mm_radio_t *radio)
804 int ret = MM_ERROR_NONE;
805 char str_error[READ_MAX_BUFFER_SIZE];
806 MMRADIO_LOG_FENTER();
808 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
810 /*cancel any outstanding seek request*/
811 radio->seek_cancel = TRUE;
812 if (radio->seek_thread) {
813 ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
814 MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
815 if (ret == EBUSY) { /* it was already locked by other */
816 MMRADIO_LOG_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
817 } else if (ret == 0) {
818 MMRADIO_LOG_INFO("trylock is successful. unlock now");
819 pthread_mutex_unlock(&radio->seek_cancel_mutex);
821 MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
823 MMRADIO_LOG_DEBUG("pthread_join seek_thread");
824 pthread_join(radio->seek_thread, NULL);
825 MMRADIO_LOG_DEBUG("done");
826 radio->is_seeking = FALSE;
827 radio->seek_thread = 0;
829 MMRADIO_LOG_FLEAVE();
833 int _mmradio_start_scan(mm_radio_t *radio)
835 int ret = MM_ERROR_NONE;
837 MMRADIO_LOG_FENTER();
839 MMRADIO_CHECK_INSTANCE(radio);
840 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
844 radio->stop_scan = false;
846 if (!radio->is_ready) {
847 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
848 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
849 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
850 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
851 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
852 return MM_ERROR_RADIO_INTERNAL;
855 radio->interrupted_by_resource_conflict = FALSE;
856 ret = mm_resource_manager_commit(radio->resource_manager);
857 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
858 MMRADIO_LOG_ERROR("failed to commit resource manager");
859 mm_resource_manager_mark_for_release(radio->resource_manager,
860 radio->radio_resource);
861 radio->radio_resource = NULL;
865 ret = radio_hal_prepare(radio->hal_inf);
866 if (ret == MM_ERROR_NOT_SUPPORT_API) {
867 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
868 } else if (ret != MM_ERROR_NONE) {
869 MMRADIO_LOG_ERROR("failed to prepare radio hal");
873 ret = radio_hal_open(radio->hal_inf);
874 if (ret == MM_ERROR_NOT_SUPPORT_API) {
875 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
876 } else if (ret != MM_ERROR_NONE) {
877 MMRADIO_LOG_ERROR("failed to open radio hal");
878 MMRADIO_LOG_FLEAVE();
881 radio->is_ready = TRUE;
883 MMRADIO_LOG_DEBUG("radio prepared and opened");
886 scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
888 if (scan_tr_id != 0) {
889 MMRADIO_LOG_ERROR("failed to create thread : scan");
890 return MM_ERROR_RADIO_NOT_INITIALIZED;
893 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
895 MMRADIO_LOG_FLEAVE();
897 return MM_ERROR_NONE;
900 int _mmradio_stop_scan(mm_radio_t *radio)
903 char str_error[READ_MAX_BUFFER_SIZE];
904 MMRADIO_LOG_FENTER();
906 MMRADIO_CHECK_INSTANCE(radio);
907 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
909 radio->stop_scan = true;
911 if (radio->scan_thread > 0) {
912 /* make sure all the search is stopped else we'll wait till search finish which is not ideal*/
913 ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
914 MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
915 if (ret == EBUSY) { /* it was already locked by other */
916 MMRADIO_LOG_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
917 } else if (ret == 0) {
918 MMRADIO_LOG_INFO("trylock is successful. unlock now");
919 pthread_mutex_unlock(&radio->seek_cancel_mutex);
921 MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
923 MMRADIO_LOG_DEBUG("pthread_join scan_thread");
924 pthread_join(radio->scan_thread, NULL);
925 radio->scan_thread = 0;
928 MMRADIO_LOG_FLEAVE();
930 return MM_ERROR_NONE;
933 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
935 int ret = MM_ERROR_NONE;
936 int32_t strength = 0;
937 MMRADIO_LOG_FENTER();
938 MMRADIO_CHECK_INSTANCE(radio);
940 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
942 /* just return stored frequency if radio device is not ready */
943 ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
944 if (ret == MM_ERROR_NOT_SUPPORT_API) {
945 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
946 } else if (ret != MM_ERROR_NONE) {
947 MMRADIO_LOG_ERROR("failed to get radio hal signal strength");
949 MMRADIO_LOG_FLEAVE();
952 *value = (int)strength;
953 MMRADIO_LOG_FLEAVE();
954 return MM_ERROR_NONE;
957 void __mmradio_scan_thread(mm_radio_t *radio)
959 int ret = MM_ERROR_NONE;
962 MMRADIO_LOG_FENTER();
963 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
965 ret = radio_hal_mute(radio->hal_inf);
967 if (ret == MM_ERROR_NOT_SUPPORT_API) {
968 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
969 } else if (ret != MM_ERROR_NONE) {
970 MMRADIO_LOG_ERROR("faied to set radio hal mute");
973 ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
975 if (ret != MM_ERROR_NONE)
978 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
979 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
981 while (!radio->stop_scan) {
983 MMMessageParamType param = { 0, };
985 MMRADIO_LOG_DEBUG("scanning....");
987 pthread_mutex_lock(&radio->seek_cancel_mutex);
989 if (radio->stop_scan) {
990 MMRADIO_LOG_INFO("scan was canceled");
991 pthread_mutex_unlock(&radio->seek_cancel_mutex);
995 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
997 pthread_mutex_unlock(&radio->seek_cancel_mutex);
999 if (ret != MM_ERROR_NONE) {
1000 MMRADIO_LOG_ERROR("radio scanning error");
1004 /* now we can get new frequency from radio device */
1005 if (radio->stop_scan)
1008 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1009 if (ret != MM_ERROR_NONE) {
1010 MMRADIO_LOG_ERROR("failed to get current frequency");
1012 if (freq <= prev_freq) {
1013 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
1017 prev_freq = param.radio_scan.frequency = (int)freq;
1018 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
1020 /* drop if max freq is scanned */
1021 if (param.radio_scan.frequency >= radio->region_setting.band_max) {
1022 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", param.radio_scan.frequency);
1026 if (radio->stop_scan) {
1027 /* doesn't need to post */
1031 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1035 if (radio->old_state == MM_RADIO_STATE_READY) {
1036 MMRADIO_LOG_DEBUG("old state is ready");
1037 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
1038 MMRADIO_LOG_DEBUG("old state is playing");
1039 ret = radio_hal_unmute(radio->hal_inf);
1040 if (ret == MM_ERROR_NOT_SUPPORT_API) {
1041 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
1042 } else if (ret != MM_ERROR_NONE) {
1043 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
1046 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
1047 if (ret == MM_ERROR_NOT_SUPPORT_API) {
1048 MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
1049 } else if (ret != MM_ERROR_NONE) {
1050 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
1057 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
1058 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
1060 /* close radio device here !!!! */
1061 ret = radio_hal_close(radio->hal_inf);
1062 if (ret == MM_ERROR_NOT_SUPPORT_API)
1063 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
1064 else if (ret != MM_ERROR_NONE)
1065 MMRADIO_LOG_ERROR("failed to close radio hal");
1067 ret = radio_hal_unprepare(radio->hal_inf);
1068 if (ret == MM_ERROR_NOT_SUPPORT_API)
1069 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
1070 else if (ret != MM_ERROR_NONE)
1071 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
1073 radio->is_ready = FALSE;
1075 if (!radio->interrupted_by_resource_conflict && /* is being released */
1076 radio->radio_resource != NULL) {
1077 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
1078 radio->radio_resource);
1079 radio->radio_resource = NULL;
1080 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
1081 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
1084 ret = mm_resource_manager_commit(radio->resource_manager);
1085 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
1086 MMRADIO_LOG_ERROR("resource manager commit fail");
1088 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
1091 if (!radio->stop_scan)
1092 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1094 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1096 MMRADIO_LOG_FLEAVE();
1098 radio->scan_thread = 0;
1102 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
1104 MMRADIO_LOG_FENTER();
1106 MMRADIO_CHECK_INSTANCE(radio);
1108 if (freq >= radio->region_setting.band_max
1109 || freq <= radio->region_setting.band_min)
1112 MMRADIO_LOG_FLEAVE();
1117 void __mmradio_seek_thread(mm_radio_t *radio)
1119 int ret = MM_ERROR_NONE;
1121 MMMessageParamType param = {0, };
1123 MMRADIO_LOG_FENTER();
1124 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1126 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1128 MMRADIO_LOG_DEBUG("seeking....");
1130 if (!radio->seek_cancel) {
1132 MMRADIO_LOG_DEBUG("try to seek ");
1133 pthread_mutex_lock(&radio->seek_cancel_mutex);
1134 MMRADIO_LOG_DEBUG("seek start");
1136 if (radio->seek_cancel) {
1137 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1138 pthread_mutex_unlock(&radio->seek_cancel_mutex);
1142 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1143 pthread_mutex_unlock(&radio->seek_cancel_mutex);
1145 MMRADIO_LOG_ERROR("failed to seek radio hal");
1149 /* now we can get new frequency from radio device */
1150 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1152 MMRADIO_LOG_ERROR("failed to get current frequency");
1156 MMRADIO_LOG_DEBUG("found frequency");
1158 /* if same freq is found, ignore it and search next one. */
1159 if (freq == radio->prev_seek_freq) {
1160 MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1164 /* check if it's limit freq or not */
1165 if (__is_tunable_frequency(radio, freq)) {
1166 /* now tune to new frequency */
1167 ret = radio_hal_set_frequency(radio->hal_inf, freq);
1169 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1172 radio->freq = (int)freq;
1173 MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1176 if (radio->seek_unmute) {
1177 /* now turn on radio
1178 * In the case of limit freq, tuner should be unmuted.
1179 * Otherwise, sound can't output even though application set new frequency.
1181 ret = radio_hal_unmute(radio->hal_inf);
1183 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1186 radio->seek_unmute = FALSE;
1189 param.radio_scan.frequency = radio->prev_seek_freq = (int)freq;
1190 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", param.radio_scan.frequency);
1191 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1194 radio->seek_thread = 0;
1195 radio->is_seeking = FALSE;
1197 MMRADIO_LOG_FLEAVE();
1202 if (radio->seek_unmute) {
1203 /* now turn on radio
1204 * In the case of limit freq, tuner should be unmuted.
1205 * Otherwise, sound can't output even though application set new frequency.
1207 ret = radio_hal_unmute(radio->hal_inf);
1209 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1210 radio->seek_unmute = FALSE;
1212 /* freq -1 means it's failed to seek */
1213 param.radio_scan.frequency = -1;
1214 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1215 radio->is_seeking = FALSE;
1216 radio->seek_thread = 0;
1220 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1222 MMRADIO_CHECK_INSTANCE(radio);
1224 MMRADIO_LOG_FENTER();
1226 if (!radio->msg_cb) {
1227 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1231 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1233 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1235 MMRADIO_LOG_FLEAVE();
1240 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1242 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1244 MMRADIO_LOG_FENTER();
1246 MMRADIO_CHECK_INSTANCE(radio);
1248 radio_state = __mmradio_get_state(radio);
1250 MMRADIO_LOG_INFO("incomming command : %d current state : %d", command, radio_state);
1253 case MMRADIO_COMMAND_CREATE:
1255 if (radio_state != 0)
1260 case MMRADIO_COMMAND_REALIZE:
1262 if (radio_state == MM_RADIO_STATE_READY ||
1263 radio_state == MM_RADIO_STATE_PLAYING ||
1264 radio_state == MM_RADIO_STATE_SCANNING)
1267 if (radio_state == 0)
1272 case MMRADIO_COMMAND_UNREALIZE:
1274 if (radio_state == MM_RADIO_STATE_NULL)
1277 /* we can call unrealize at any higher state */
1281 case MMRADIO_COMMAND_START:
1283 if (radio_state == MM_RADIO_STATE_PLAYING)
1286 if (radio_state != MM_RADIO_STATE_READY)
1291 case MMRADIO_COMMAND_STOP:
1293 if (radio_state == MM_RADIO_STATE_READY)
1296 if (radio_state != MM_RADIO_STATE_PLAYING)
1301 case MMRADIO_COMMAND_START_SCAN:
1303 if (radio_state == MM_RADIO_STATE_SCANNING)
1306 if (radio_state == MM_RADIO_STATE_NULL)
1311 case MMRADIO_COMMAND_STOP_SCAN:
1313 if (radio_state == MM_RADIO_STATE_READY)
1316 if (radio_state != MM_RADIO_STATE_SCANNING)
1321 case MMRADIO_COMMAND_DESTROY:
1322 case MMRADIO_COMMAND_MUTE:
1323 case MMRADIO_COMMAND_UNMUTE:
1324 case MMRADIO_COMMAND_SET_FREQ:
1325 case MMRADIO_COMMAND_GET_FREQ:
1326 case MMRADIO_COMMAND_SET_REGION:
1327 case MMRADIO_COMMAND_SET_VOLUME:
1328 case MMRADIO_COMMAND_GET_VOLUME:
1330 /* we can do it at any state */
1334 case MMRADIO_COMMAND_SEEK:
1336 if (radio_state != MM_RADIO_STATE_PLAYING)
1341 case MMRADIO_COMMAND_GET_REGION:
1343 if (radio_state == MM_RADIO_STATE_NULL)
1349 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1353 MMRADIO_LOG_DEBUG("status OK");
1355 radio->cmd = command;
1357 MMRADIO_LOG_FLEAVE();
1359 return MM_ERROR_NONE;
1362 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1363 MMRADIO_LOG_FLEAVE();
1364 return MM_ERROR_RADIO_INVALID_STATE;
1367 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1368 MMRADIO_LOG_FLEAVE();
1369 return MM_ERROR_RADIO_NO_OP;
1373 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1375 MMMessageParamType msg = { 0, };
1376 int msg_type = MM_MESSAGE_UNKNOWN;
1378 MMRADIO_LOG_FENTER();
1381 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1385 if (radio->current_state == new_state && radio->pending_state == 0) {
1386 MMRADIO_LOG_WARNING("we are in same state");
1391 radio->old_state = radio->current_state;
1392 radio->current_state = new_state;
1394 /* fill message param */
1395 msg.union_type = MM_MSG_UNION_STATE;
1396 msg.state.previous = radio->old_state;
1397 msg.state.current = radio->current_state;
1399 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1400 /* post message to application */
1401 if (radio->sound_focus.by_focus_cb) {
1402 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1403 msg.state.code = radio->sound_focus.event_src;
1404 MMRADIO_POST_MSG(radio, msg_type, &msg);
1405 } else if (radio->interrupted_by_resource_conflict) {
1406 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1407 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1408 MMRADIO_POST_MSG(radio, msg_type, &msg);
1410 msg_type = MM_MESSAGE_STATE_CHANGED;
1411 MMRADIO_POST_MSG(radio, msg_type, &msg);
1414 if (radio->interrupted_by_resource_conflict) {
1415 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1416 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1417 MMRADIO_POST_MSG(radio, msg_type, &msg);
1419 msg_type = MM_MESSAGE_STATE_CHANGED;
1420 MMRADIO_POST_MSG(radio, msg_type, &msg);
1425 MMRADIO_LOG_FLEAVE();
1430 static int __mmradio_get_state(mm_radio_t *radio)
1432 MMRADIO_CHECK_INSTANCE(radio);
1434 MMRADIO_LOG_INFO("radio state : current : [%d] old : [%d] pending : [%d]",
1435 radio->current_state, radio->old_state, radio->pending_state);
1437 return radio->current_state;
1440 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1441 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
1442 mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
1443 const char *additional_info, void *user_data)
1445 mm_radio_t *radio = (mm_radio_t *)user_data;
1446 enum MMMessageInterruptedCode event_source;
1447 int result = MM_ERROR_NONE;
1448 int postMsg = false;
1450 MMRADIO_LOG_FENTER();
1451 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1452 MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1454 mmradio_get_sound_focus_reason(focus_state, reason_for_change, FALSE, &event_source, &postMsg);
1455 radio->sound_focus.event_src = event_source;
1457 switch (focus_state) {
1458 case FOCUS_IS_RELEASED:{
1459 radio->sound_focus.cur_focus_type &= ~focus_type;
1460 radio->sound_focus.by_focus_cb = true;
1462 MMRADIO_CMD_LOCK(radio);
1463 result = _mmradio_stop(radio);
1465 MMRADIO_LOG_ERROR("failed to stop radio");
1466 MMRADIO_CMD_UNLOCK(radio);
1468 radio->sound_focus.by_focus_cb = false;
1470 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1474 case FOCUS_IS_ACQUIRED:{
1475 MMMessageParamType msg = { 0, };
1476 msg.union_type = MM_MSG_UNION_CODE;
1477 msg.code = event_source;
1479 radio->sound_focus.cur_focus_type |= focus_type;
1481 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1482 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1484 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1489 MMRADIO_LOG_DEBUG("Unknown focus_state");
1493 MMRADIO_LOG_FLEAVE();
1496 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
1497 mm_sound_focus_state_e focus_state, const char *reason_for_change,
1498 const char *additional_info, void *user_data)
1500 mm_radio_t *radio = (mm_radio_t *)user_data;
1501 enum MMMessageInterruptedCode event_source;
1502 int result = MM_ERROR_NONE;
1503 int postMsg = false;
1505 MMRADIO_LOG_FENTER();
1506 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1507 MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1509 mmradio_get_sound_focus_reason(focus_state, reason_for_change, TRUE, &event_source, &postMsg);
1510 radio->sound_focus.event_src = event_source;
1512 switch (focus_state) {
1513 case FOCUS_IS_ACQUIRED: {
1514 radio->sound_focus.cur_focus_type &= ~focus_type;
1515 radio->sound_focus.by_focus_cb = true;
1517 MMRADIO_CMD_LOCK(radio);
1518 result = _mmradio_stop(radio);
1520 MMRADIO_LOG_ERROR("failed to stop radio");
1521 MMRADIO_CMD_UNLOCK(radio);
1523 radio->sound_focus.by_focus_cb = false;
1525 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
1529 case FOCUS_IS_RELEASED: {
1530 MMMessageParamType msg = { 0, };
1531 msg.union_type = MM_MSG_UNION_CODE;
1532 msg.code = event_source;
1534 radio->sound_focus.cur_focus_type |= focus_type;
1536 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1537 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1539 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1544 MMRADIO_LOG_DEBUG("Unknown focus_state");
1548 MMRADIO_LOG_FLEAVE();
1552 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1554 mm_radio_t *radio = (mm_radio_t *)user_data;
1555 int ret = MM_ERROR_NONE;
1556 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1557 if (type == VOLUME_TYPE_MEDIA) {
1558 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1559 ret = __mmradio_set_media_volume(radio, volume);
1560 if (ret != MM_ERROR_NONE)
1561 MMRADIO_LOG_ERROR("failed to set media volume");
1566 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1568 MMRADIO_LOG_FENTER();
1569 MMRADIO_CHECK_INSTANCE(radio);
1570 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1572 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1574 *type = radio->region_setting.country;
1576 MMRADIO_LOG_FLEAVE();
1577 return MM_ERROR_NONE;
1580 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1582 MMRADIO_LOG_FENTER();
1583 MMRADIO_CHECK_INSTANCE(radio);
1584 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1586 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1588 *min_freq = radio->region_setting.band_min;
1589 *max_freq = radio->region_setting.band_max;
1591 MMRADIO_LOG_FLEAVE();
1592 return MM_ERROR_NONE;
1595 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1597 MMRADIO_LOG_FENTER();
1598 MMRADIO_CHECK_INSTANCE(radio);
1599 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1601 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1603 *ch_spacing = radio->region_setting.channel_spacing;
1605 MMRADIO_LOG_FLEAVE();
1606 return MM_ERROR_NONE;
1609 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1611 int ret = MM_ERROR_NONE;
1613 MMRADIO_LOG_FENTER();
1615 MMRADIO_CHECK_INSTANCE(radio);
1616 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1618 MMRADIO_LOG_INFO("Setting %f volume", volume);
1620 MMRADIO_VOLUME_LOCK(radio);
1621 radio->local_volume = volume;
1622 MMRADIO_VOLUME_UNLOCK(radio);
1624 ret = radio_hal_set_volume(radio->hal_inf, volume);
1625 if (ret != MM_ERROR_NONE)
1626 MMRADIO_LOG_ERROR("failed to set radio hal volume");
1628 MMRADIO_LOG_FLEAVE();
1633 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1635 int ret = MM_ERROR_NONE;
1637 MMRADIO_LOG_FENTER();
1639 MMRADIO_CHECK_INSTANCE(radio);
1640 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1642 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1644 ret = radio_hal_get_volume(radio->hal_inf, &volume);
1645 if (ret != MM_ERROR_NONE) {
1646 MMRADIO_LOG_ERROR("failed to get radio hal volume");
1651 MMRADIO_VOLUME_LOCK(radio);
1652 radio->local_volume = volume;
1653 *pVolume = (float)radio->local_volume;
1654 MMRADIO_VOLUME_UNLOCK(radio);
1656 MMRADIO_LOG_FLEAVE();
1661 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1663 int ret = MM_ERROR_NONE;
1665 MMRADIO_LOG_FENTER();
1667 MMRADIO_CHECK_INSTANCE(radio);
1668 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1670 MMRADIO_LOG_INFO("Setting %d volume", level);
1672 MMRADIO_VOLUME_LOCK(radio);
1673 radio->media_volume = level;
1674 MMRADIO_VOLUME_UNLOCK(radio);
1676 ret = radio_hal_set_media_volume(radio->hal_inf, level);
1677 if (ret != MM_ERROR_NONE)
1678 MMRADIO_LOG_ERROR("failed to set radio hal media volume");
1680 MMRADIO_LOG_FLEAVE();
1685 static int __resource_release_cb(mm_resource_manager_h rm,
1686 mm_resource_manager_res_h res, void *user_data)
1688 mm_radio_t *radio = NULL;
1690 MMRADIO_LOG_FENTER();
1693 MMRADIO_LOG_ERROR("user_data is null");
1697 radio = (mm_radio_t *)user_data;
1698 radio->radio_resource = NULL;
1700 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1702 radio->interrupted_by_resource_conflict = TRUE;
1704 MMRADIO_CMD_LOCK(radio);
1705 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1706 MMRADIO_LOG_ERROR("failed to stop radio");
1707 MMRADIO_CMD_UNLOCK(radio);
1709 MMRADIO_LOG_FLEAVE();