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);
126 static int __mmradio_create_thread(mm_radio_t *radio);
127 static void __mmradio_destroy_thread(mm_radio_t *radio);
129 #ifdef TIZEN_FEATURE_SOUND_FOCUS
130 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
131 mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
132 const char *additional_info, void *user_data);
133 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
134 mm_sound_focus_state_e focus_state, const char *reason_for_change,
135 const char *additional_info, void *user_data);
138 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
139 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
140 static int __resource_release_cb(mm_resource_manager_h rm,
141 mm_resource_manager_res_h res, void *user_data);
143 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
145 int ret = MM_ERROR_NONE;
149 MMRADIO_LOG_FENTER();
151 MMRADIO_CHECK_INSTANCE(radio);
152 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
154 /* if needed, radio region must be updated.
155 * Otherwise, just applying settings to device without it.
158 count = ARRAY_SIZE(region_table);
160 /* TODO: if auto is supported...get the region info. here */
162 /* update radio region settings */
163 for (index = 0; index < count; index++) {
164 /* find the region from pre-defined table */
165 if (region_table[index].country == region) {
166 radio->region_setting.country = region_table[index].country;
167 radio->region_setting.deemphasis = region_table[index].deemphasis;
168 radio->region_setting.band_min = region_table[index].band_min;
169 radio->region_setting.band_max = region_table[index].band_max;
170 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
175 MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
176 radio->region_setting.country, radio->region_setting.deemphasis,
177 radio->region_setting.band_min, radio->region_setting.band_max);
179 MMRADIO_LOG_FLEAVE();
184 int _mmradio_create_radio(mm_radio_t *radio)
186 int ret = MM_ERROR_NONE;
188 MMRADIO_LOG_FENTER();
190 MMRADIO_CHECK_INSTANCE(radio);
191 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
193 /* set default value */
194 radio->freq = DEFAULT_FREQ;
195 #ifdef TIZEN_FEATURE_SOUND_FOCUS
196 memset(&radio->sound_focus, 0, sizeof(mm_radio_sound_focus));
198 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
199 radio->local_volume = 1.0;
201 /* create mutex and thread */
202 ret = __mmradio_create_thread(radio);
204 MMRADIO_LOG_ERROR("failed to create threads");
208 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
210 /* initialize resource manager */
211 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
212 __resource_release_cb, radio, &radio->resource_manager);
214 MMRADIO_LOG_ERROR("failed to create resource manager");
215 return MM_ERROR_RADIO_INTERNAL;
218 #ifdef TIZEN_FEATURE_SOUND_FOCUS
219 ret = mmradio_sound_focus_register(&radio->sound_focus,
220 (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb,
221 (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb,
225 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
226 MMRADIO_LOG_ERROR("failed to register sound focus");
227 return MM_ERROR_RADIO_INTERNAL;
231 ret = radio_hal_interface_init(&(radio->hal_inf));
233 MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
237 MMRADIO_LOG_FLEAVE();
239 return MM_ERROR_NONE;
242 int _mmradio_realize(mm_radio_t *radio)
244 int ret = MM_ERROR_NONE;
248 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
250 MMRADIO_LOG_FENTER();
252 MMRADIO_CHECK_INSTANCE(radio);
253 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
255 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
256 /* not initialized yet. set it with default region */
257 region = RADIO_DEFAULT_REGION;
260 /* already initialized by application */
261 region = radio->region_setting.country;
264 ret = _mmradio_apply_region(radio, region, update);
266 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
267 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
268 if (ret != MM_ERROR_NONE) {
269 MMRADIO_LOG_ERROR("failed to create stream information");
270 MMRADIO_LOG_FLEAVE();
273 ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
274 if (ret != MM_ERROR_NONE) {
275 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
276 MMRADIO_LOG_FLEAVE();
281 ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
282 if (ret != MM_ERROR_NONE) {
283 MMRADIO_LOG_WARNING("failed to get max volume");
284 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
286 radio->max_media_volume = max;
289 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
291 if (ret != MM_ERROR_NONE)
292 MMRADIO_LOG_WARNING("failed to get media volume");
294 MMRADIO_VOLUME_LOCK(radio);
295 radio->media_volume = volume;
296 MMRADIO_VOLUME_UNLOCK(radio);
298 ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
299 if (ret != MM_ERROR_NONE)
300 MMRADIO_LOG_WARNING("failed to register volume changed callback");
302 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
304 MMRADIO_LOG_FLEAVE();
306 return MM_ERROR_NONE;
309 int _mmradio_unrealize(mm_radio_t *radio)
311 int ret = MM_ERROR_NONE;
313 MMRADIO_LOG_FENTER();
315 MMRADIO_CHECK_INSTANCE(radio);
316 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
318 ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
319 if (ret != MM_ERROR_NONE)
320 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
322 /*Finish if there are scans*/
323 _mmradio_stop_scan(radio);
325 /*Stop radio if started*/
326 _mmradio_stop(radio);
328 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
329 sound_manager_destroy_virtual_stream(radio->vstream);
330 sound_manager_destroy_stream_information(radio->stream_info);
333 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
335 MMRADIO_LOG_FLEAVE();
340 int _mmradio_destroy(mm_radio_t *radio)
342 int ret = MM_ERROR_NONE;
343 MMRADIO_LOG_FENTER();
345 MMRADIO_CHECK_INSTANCE(radio);
346 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
348 _mmradio_unrealize(radio);
350 /* destroy mutex and thread */
351 __mmradio_destroy_thread(radio);
353 ret = radio_hal_interface_deinit(radio->hal_inf);
355 MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
359 #ifdef TIZEN_FEATURE_SOUND_FOCUS
360 ret = mmradio_sound_focus_deregister(&radio->sound_focus);
362 MMRADIO_LOG_ERROR("failed to deregister sound focus");
363 return MM_ERROR_RADIO_INTERNAL;
367 ret = mm_resource_manager_destroy(radio->resource_manager);
369 MMRADIO_LOG_ERROR("failed to destroy resource manager");
370 return MM_ERROR_RADIO_INTERNAL;
373 MMRADIO_LOG_FLEAVE();
375 return MM_ERROR_NONE;
378 /* unit should be KHz */
379 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
381 int ret = MM_ERROR_NONE;
383 MMRADIO_LOG_FENTER();
385 MMRADIO_CHECK_INSTANCE(radio);
386 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
388 MMRADIO_LOG_INFO("Setting %d frequency", freq);
392 ret = radio_hal_set_frequency(radio->hal_inf, freq);
393 if (ret != MM_ERROR_NONE) {
394 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
395 MMRADIO_LOG_FLEAVE();
399 MMRADIO_LOG_FLEAVE();
405 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
407 int ret = MM_ERROR_NONE;
409 MMRADIO_LOG_FENTER();
411 MMRADIO_CHECK_INSTANCE(radio);
412 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
414 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
416 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
417 if (ret != MM_ERROR_NONE) {
418 MMRADIO_LOG_ERROR("failed to get radio hal frequency");
423 /* update freq in handle */
424 MMRADIO_LOG_INFO("Updating %d frequency", freq);
427 *pFreq = (int)radio->freq;
429 MMRADIO_LOG_FLEAVE();
434 int _mmradio_mute(mm_radio_t *radio)
436 int ret = MM_ERROR_NONE;
437 MMRADIO_LOG_FENTER();
439 MMRADIO_CHECK_INSTANCE(radio);
440 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
442 ret = radio_hal_mute(radio->hal_inf);
443 if (ret == MM_ERROR_NOT_SUPPORT_API) {
444 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
445 } else if (ret != MM_ERROR_NONE) {
446 MMRADIO_LOG_ERROR("failed to set radio hal mute");
447 MMRADIO_LOG_FLEAVE();
451 radio->is_muted = true;
452 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
453 MMRADIO_LOG_FLEAVE();
458 int _mmradio_unmute(mm_radio_t *radio)
460 int ret = MM_ERROR_NONE;
461 MMRADIO_LOG_FENTER();
463 MMRADIO_CHECK_INSTANCE(radio);
464 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
466 ret = radio_hal_unmute(radio->hal_inf);
467 if (ret == MM_ERROR_NOT_SUPPORT_API) {
468 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
469 } else if (ret != MM_ERROR_NONE) {
470 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
471 MMRADIO_LOG_FLEAVE();
475 radio->is_muted = false;
476 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
477 MMRADIO_LOG_FLEAVE();
482 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
484 MMRADIO_LOG_FENTER();
486 MMRADIO_CHECK_INSTANCE(radio);
488 radio->msg_cb = callback;
489 radio->msg_cb_param = user_param;
491 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
493 MMRADIO_LOG_FLEAVE();
495 return MM_ERROR_NONE;
498 int _mmradio_get_state(mm_radio_t *radio, int *pState)
502 MMRADIO_LOG_FENTER();
504 MMRADIO_CHECK_INSTANCE(radio);
505 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
507 state = __mmradio_get_state(radio);
511 MMRADIO_LOG_FLEAVE();
513 return MM_ERROR_NONE;
516 int _mmradio_start(mm_radio_t *radio)
518 int ret = MM_ERROR_NONE;
519 unsigned int volume = 0;
521 MMRADIO_LOG_FENTER();
523 MMRADIO_CHECK_INSTANCE(radio);
524 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
526 MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
528 #ifdef TIZEN_FEATURE_SOUND_FOCUS
529 if (radio->sound_focus.handle > 0) {
530 ret = mmradio_acquire_sound_focus(&radio->sound_focus);
531 if (ret != MM_ERROR_NONE) {
532 MMRADIO_LOG_ERROR("failed to acquire sound focus");
537 /* check previous acquired focus */
538 if (radio->sound_focus.watch_id > 0) {
539 char *stream_type = NULL;
540 char *ext_info = NULL;
543 ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info);
544 if (ret == MM_ERROR_NONE) {
545 MMRADIO_LOG_DEBUG("Focus is acquired by stream_type[%s], option[%d], ext_info[%s]",
546 stream_type, option, ext_info);
547 if (!strcmp(stream_type, "alarm") || !strcmp(stream_type, "ringtone-voip") ||
548 !strcmp(stream_type, "ringtone-call") || !strcmp(stream_type, "voip") ||
549 !strcmp(stream_type, "call-voice") || !strcmp(stream_type, "call-video")) {
550 MMRADIO_LOG_DEBUG("Blcoked by session policy, focus_acquired_by[%s]", stream_type);
553 return MM_ERROR_POLICY_BLOCKED;
561 if (!radio->is_ready) {
562 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
563 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
564 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
565 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
566 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
567 return MM_ERROR_RADIO_INTERNAL;
570 radio->interrupted_by_resource_conflict = FALSE;
571 ret = mm_resource_manager_commit(radio->resource_manager);
572 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
573 MMRADIO_LOG_ERROR("failed to commit resource manager");
574 mm_resource_manager_mark_for_release(radio->resource_manager,
575 radio->radio_resource);
576 radio->radio_resource = NULL;
580 ret = radio_hal_prepare(radio->hal_inf);
581 if (ret == MM_ERROR_NOT_SUPPORT_API) {
582 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
583 } else if (ret != MM_ERROR_NONE) {
584 MMRADIO_LOG_ERROR("failed to prepare radio hal");
588 ret = radio_hal_open(radio->hal_inf);
589 if (ret == MM_ERROR_NOT_SUPPORT_API) {
590 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
591 } else if (ret != MM_ERROR_NONE) {
592 MMRADIO_LOG_ERROR("failed to open radio hal");
595 radio->is_ready = true;
597 MMRADIO_LOG_DEBUG("radio prepared and opened");
600 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
601 if (ret != MM_ERROR_NONE)
602 MMRADIO_LOG_WARNING("failed to get media volume");
604 ret = __mmradio_set_media_volume(radio, volume);
605 if (ret != MM_ERROR_NONE) {
606 MMRADIO_LOG_ERROR("failed to set media volume");
610 ret = radio_hal_start(radio->hal_inf);
611 if (ret == MM_ERROR_NOT_SUPPORT_API) {
612 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
614 MMRADIO_LOG_ERROR("failed to start radio hal");
618 /* set stored frequency */
619 ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
621 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
625 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
626 ret = sound_manager_start_virtual_stream(radio->vstream);
628 MMRADIO_LOG_ERROR("failed to start sound manager virtual stream");
633 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
635 MMRADIO_LOG_FLEAVE();
637 return MM_ERROR_NONE;
640 radio_hal_close(radio->hal_inf);
642 radio_hal_unprepare(radio->hal_inf);
643 radio->is_ready = false;
647 int _mmradio_stop(mm_radio_t *radio)
649 int ret = MM_ERROR_NONE;
651 MMRADIO_LOG_FENTER();
653 MMRADIO_CHECK_INSTANCE(radio);
654 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
656 /*cancel if any seek*/
657 _mmradio_seek_cancel(radio);
658 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
659 ret = sound_manager_stop_virtual_stream(radio->vstream);
660 if (ret != MM_ERROR_NONE) {
661 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
666 ret = radio_hal_stop(radio->hal_inf);
667 if (ret == MM_ERROR_NOT_SUPPORT_API) {
668 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
670 MMRADIO_LOG_ERROR("failed to stop radio hal");
674 if (radio->is_ready) {
675 /* close radio device here !!!! */
676 ret = radio_hal_close(radio->hal_inf);
677 if (ret == MM_ERROR_NOT_SUPPORT_API) {
678 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
679 } else if (ret != MM_ERROR_NONE) {
680 MMRADIO_LOG_ERROR("failed to close radio hal");
684 ret = radio_hal_unprepare(radio->hal_inf);
685 if (ret == MM_ERROR_NOT_SUPPORT_API) {
686 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
687 } else if (ret != MM_ERROR_NONE) {
688 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
692 if (!radio->interrupted_by_resource_conflict && /* is being released */
693 radio->radio_resource != NULL) {
694 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
695 radio->radio_resource);
696 radio->radio_resource = NULL;
697 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
698 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
702 ret = mm_resource_manager_commit(radio->resource_manager);
703 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
704 MMRADIO_LOG_ERROR("resource manager commit fail");
707 radio->is_ready = false;
709 #ifdef TIZEN_FEATURE_SOUND_FOCUS
710 if (radio->sound_focus.handle > 0) {
711 ret = mmradio_release_sound_focus(&radio->sound_focus);
713 MMRADIO_LOG_ERROR("failed to release sound focus");
718 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
720 MMRADIO_LOG_FLEAVE();
722 return MM_ERROR_NONE;
725 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
727 int ret = MM_ERROR_NONE;
729 MMRADIO_LOG_FENTER();
731 MMRADIO_CHECK_INSTANCE(radio);
732 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
734 if (radio->seek.is_running) {
735 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
736 return MM_ERROR_RADIO_INTERNAL;
739 radio->seek_unmute = false;
741 if (!radio->is_muted) {
742 ret = radio_hal_mute(radio->hal_inf);
743 if (ret == MM_ERROR_NOT_SUPPORT_API) {
744 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
746 MMRADIO_LOG_ERROR("failed to set radio hal mute");
749 radio->seek_unmute = true;
752 MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
753 radio->seek_direction = direction;
754 radio->seek.is_running = true;
755 radio->seek.stop = false;
757 MMRADIO_SEEK_THREAD_SIGNAL(radio);
759 MMRADIO_LOG_FLEAVE();
761 return MM_ERROR_NONE;
764 void _mmradio_seek_cancel(mm_radio_t *radio)
766 MMRADIO_LOG_FENTER();
768 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
770 /* cancel any outstanding seek request */
771 radio->seek.stop = true;
773 MMRADIO_LOG_FLEAVE();
776 int _mmradio_start_scan(mm_radio_t *radio)
778 int ret = MM_ERROR_NONE;
780 MMRADIO_LOG_FENTER();
782 MMRADIO_CHECK_INSTANCE(radio);
783 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
785 radio->scan.stop = false;
787 if (!radio->is_ready) {
788 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
789 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
790 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
791 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
792 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
793 return MM_ERROR_RADIO_INTERNAL;
796 radio->interrupted_by_resource_conflict = FALSE;
797 ret = mm_resource_manager_commit(radio->resource_manager);
798 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
799 MMRADIO_LOG_ERROR("failed to commit resource manager");
800 mm_resource_manager_mark_for_release(radio->resource_manager,
801 radio->radio_resource);
802 radio->radio_resource = NULL;
806 ret = radio_hal_prepare(radio->hal_inf);
807 if (ret == MM_ERROR_NOT_SUPPORT_API) {
808 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
809 } else if (ret != MM_ERROR_NONE) {
810 MMRADIO_LOG_ERROR("failed to prepare radio hal");
814 ret = radio_hal_open(radio->hal_inf);
815 if (ret == MM_ERROR_NOT_SUPPORT_API) {
816 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
817 } else if (ret != MM_ERROR_NONE) {
818 MMRADIO_LOG_ERROR("failed to open radio hal");
819 MMRADIO_LOG_FLEAVE();
822 radio->is_ready = true;
824 MMRADIO_LOG_DEBUG("radio prepared and opened");
827 radio->scan.is_running = true;
829 MMRADIO_SCAN_THREAD_SIGNAL(radio);
831 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
833 MMRADIO_LOG_FLEAVE();
835 return MM_ERROR_NONE;
838 int _mmradio_stop_scan(mm_radio_t *radio)
840 MMRADIO_LOG_FENTER();
842 MMRADIO_CHECK_INSTANCE(radio);
843 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
845 radio->scan.stop = true;
847 MMRADIO_LOG_FLEAVE();
849 return MM_ERROR_NONE;
852 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
854 int ret = MM_ERROR_NONE;
855 int32_t strength = 0;
856 MMRADIO_LOG_FENTER();
857 MMRADIO_CHECK_INSTANCE(radio);
859 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
861 /* just return stored frequency if radio device is not ready */
862 ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
863 if (ret == MM_ERROR_NOT_SUPPORT_API) {
864 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
865 } else if (ret != MM_ERROR_NONE) {
866 MMRADIO_LOG_ERROR("failed to get radio hal signal strength");
868 MMRADIO_LOG_FLEAVE();
871 *value = (int)strength;
872 MMRADIO_LOG_FLEAVE();
873 return MM_ERROR_NONE;
876 void __mmradio_scan_thread(mm_radio_t *radio)
878 int ret = MM_ERROR_NONE;
881 MMRADIO_LOG_FENTER();
882 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
884 MMRADIO_SCAN_THREAD_LOCK(radio);
886 while (!radio->scan.thread_exit) {
887 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
888 MMRADIO_SCAN_THREAD_WAIT(radio);
890 if (radio->scan.thread_exit) {
891 MMRADIO_LOG_DEBUG("exiting scan thread");
895 ret = radio_hal_mute(radio->hal_inf);
896 if (ret == MM_ERROR_NOT_SUPPORT_API) {
897 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
898 } else if (ret != MM_ERROR_NONE) {
899 MMRADIO_LOG_ERROR("faied to set radio hal mute");
903 ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
904 if (ret != MM_ERROR_NONE)
907 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
908 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
910 while (!radio->scan.stop) {
913 MMMessageParamType param = { 0, };
915 MMRADIO_LOG_DEBUG("scanning....");
917 if (radio->scan.thread_exit) {
918 MMRADIO_LOG_DEBUG("exiting scan thread");
922 if (radio->scan.stop) {
923 MMRADIO_LOG_INFO("scan was canceled");
927 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
928 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
929 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
930 if (ret != MM_ERROR_NONE) {
931 MMRADIO_LOG_ERROR("radio scanning error");
935 if (radio->scan.thread_exit) {
936 MMRADIO_LOG_DEBUG("exiting scan thread");
940 if (radio->scan.stop) {
941 MMRADIO_LOG_INFO("scan was canceled");
945 /* now we can get new frequency from radio device */
946 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
947 if (ret != MM_ERROR_NONE) {
948 MMRADIO_LOG_ERROR("failed to get current frequency");
950 if (freq <= prev_freq) {
951 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
955 prev_freq = param.radio_scan.frequency = (int)freq;
956 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
958 /* drop if max freq is scanned */
959 if (param.radio_scan.frequency >= radio->region_setting.band_max) {
960 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", param.radio_scan.frequency);
964 if (radio->scan.stop) {
965 /* doesn't need to post */
969 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
974 if (radio->old_state == MM_RADIO_STATE_READY) {
975 MMRADIO_LOG_DEBUG("old state is ready");
976 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
977 MMRADIO_LOG_DEBUG("old state is playing");
978 ret = radio_hal_unmute(radio->hal_inf);
979 if (ret == MM_ERROR_NOT_SUPPORT_API) {
980 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
981 } else if (ret != MM_ERROR_NONE) {
982 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
985 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
986 if (ret == MM_ERROR_NOT_SUPPORT_API) {
987 MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
988 } else if (ret != MM_ERROR_NONE) {
989 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
995 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
996 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
998 /* close radio device here !!!! */
999 if (radio->is_ready) {
1000 ret = radio_hal_close(radio->hal_inf);
1001 if (ret == MM_ERROR_NOT_SUPPORT_API)
1002 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
1003 else if (ret != MM_ERROR_NONE)
1004 MMRADIO_LOG_ERROR("failed to close radio hal");
1006 ret = radio_hal_unprepare(radio->hal_inf);
1007 if (ret == MM_ERROR_NOT_SUPPORT_API)
1008 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
1009 else if (ret != MM_ERROR_NONE)
1010 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
1012 if (!radio->interrupted_by_resource_conflict && /* is being released */
1013 radio->radio_resource != NULL) {
1014 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
1015 radio->radio_resource);
1016 radio->radio_resource = NULL;
1017 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
1018 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
1021 ret = mm_resource_manager_commit(radio->resource_manager);
1022 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
1023 MMRADIO_LOG_ERROR("resource manager commit fail");
1024 radio->is_ready = false;
1026 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
1029 if (!radio->scan.stop)
1030 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1032 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1034 radio->scan.is_running = false;
1039 radio->scan.is_running = false;
1041 MMRADIO_SCAN_THREAD_UNLOCK(radio);
1043 MMRADIO_LOG_FLEAVE();
1049 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
1051 MMRADIO_LOG_FENTER();
1053 MMRADIO_CHECK_INSTANCE(radio);
1055 if (freq >= radio->region_setting.band_max
1056 || freq <= radio->region_setting.band_min)
1059 MMRADIO_LOG_FLEAVE();
1064 void __mmradio_seek_thread(mm_radio_t *radio)
1066 int ret = MM_ERROR_NONE;
1068 MMMessageParamType param = {0, };
1070 MMRADIO_LOG_FENTER();
1071 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1073 MMRADIO_SEEK_THREAD_LOCK(radio);
1075 while (!radio->seek.thread_exit) {
1076 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
1077 MMRADIO_SEEK_THREAD_WAIT(radio);
1079 if (radio->seek.thread_exit) {
1080 MMRADIO_LOG_DEBUG("exiting seek thread");
1084 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1085 MMRADIO_LOG_DEBUG("seeking....");
1087 if (radio->seek.stop) {
1088 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1092 MMRADIO_LOG_DEBUG("try to seek ");
1093 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
1094 MMRADIO_LOG_DEBUG("seek start");
1095 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1096 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
1098 MMRADIO_LOG_ERROR("failed to seek radio hal");
1102 if (radio->seek.thread_exit) {
1103 MMRADIO_LOG_DEBUG("exiting seek thread");
1107 if (radio->seek.stop) {
1108 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1112 /* now we can get new frequency from radio device */
1113 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1115 MMRADIO_LOG_ERROR("failed to get current frequency");
1119 MMRADIO_LOG_DEBUG("found frequency");
1121 /* if same freq is found, ignore it and search next one. */
1122 if (freq == radio->prev_seek_freq) {
1123 MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1127 /* check if it's limit freq or not */
1128 if (__is_tunable_frequency(radio, freq)) {
1129 /* now tune to new frequency */
1130 ret = radio_hal_set_frequency(radio->hal_inf, freq);
1132 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1135 radio->freq = (int)freq;
1136 MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1139 if (radio->seek_unmute) {
1140 /* now turn on radio
1141 * In the case of limit freq, tuner should be unmuted.
1142 * Otherwise, sound can't output even though application set new frequency.
1144 ret = radio_hal_unmute(radio->hal_inf);
1146 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1149 radio->seek_unmute = false;
1152 param.radio_scan.frequency = radio->prev_seek_freq = (int)freq;
1153 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", param.radio_scan.frequency);
1154 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1155 radio->seek.is_running = false;
1159 if (radio->seek_unmute) {
1160 /* now turn on radio
1161 * In the case of limit freq, tuner should be unmuted.
1162 * Otherwise, sound can't output even though application set new frequency.
1164 ret = radio_hal_unmute(radio->hal_inf);
1166 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1167 radio->seek_unmute = false;
1169 /* freq -1 means it's failed to seek */
1170 param.radio_scan.frequency = -1;
1171 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1172 radio->seek.is_running = false;
1176 radio->seek.is_running = false;
1177 MMRADIO_SEEK_THREAD_UNLOCK(radio);
1178 MMRADIO_LOG_FLEAVE();
1182 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1184 MMRADIO_CHECK_INSTANCE(radio);
1186 MMRADIO_LOG_FENTER();
1188 if (!radio->msg_cb) {
1189 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1193 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1195 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1197 MMRADIO_LOG_FLEAVE();
1202 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1204 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1206 MMRADIO_LOG_FENTER();
1208 MMRADIO_CHECK_INSTANCE(radio);
1210 radio_state = __mmradio_get_state(radio);
1212 MMRADIO_LOG_INFO("incomming command : %d current state : %d", command, radio_state);
1215 case MMRADIO_COMMAND_CREATE:
1217 if (radio_state != 0)
1222 case MMRADIO_COMMAND_REALIZE:
1224 if (radio_state == MM_RADIO_STATE_READY ||
1225 radio_state == MM_RADIO_STATE_PLAYING ||
1226 radio_state == MM_RADIO_STATE_SCANNING)
1229 if (radio_state == 0)
1234 case MMRADIO_COMMAND_UNREALIZE:
1236 if (radio_state == MM_RADIO_STATE_NULL)
1239 /* we can call unrealize at any higher state */
1243 case MMRADIO_COMMAND_START:
1245 if (radio_state == MM_RADIO_STATE_PLAYING)
1248 if (radio_state != MM_RADIO_STATE_READY)
1253 case MMRADIO_COMMAND_STOP:
1255 if (radio_state == MM_RADIO_STATE_READY)
1258 if (radio_state != MM_RADIO_STATE_PLAYING)
1263 case MMRADIO_COMMAND_START_SCAN:
1265 if (radio_state == MM_RADIO_STATE_SCANNING)
1268 if (radio_state == MM_RADIO_STATE_NULL)
1273 case MMRADIO_COMMAND_STOP_SCAN:
1275 if (radio_state == MM_RADIO_STATE_READY)
1278 if (radio_state != MM_RADIO_STATE_SCANNING)
1283 case MMRADIO_COMMAND_DESTROY:
1284 case MMRADIO_COMMAND_MUTE:
1285 case MMRADIO_COMMAND_UNMUTE:
1286 case MMRADIO_COMMAND_SET_FREQ:
1287 case MMRADIO_COMMAND_GET_FREQ:
1288 case MMRADIO_COMMAND_SET_REGION:
1289 case MMRADIO_COMMAND_SET_VOLUME:
1290 case MMRADIO_COMMAND_GET_VOLUME:
1292 /* we can do it at any state */
1296 case MMRADIO_COMMAND_SEEK:
1298 if (radio_state != MM_RADIO_STATE_PLAYING)
1303 case MMRADIO_COMMAND_GET_REGION:
1305 if (radio_state == MM_RADIO_STATE_NULL)
1311 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1315 MMRADIO_LOG_DEBUG("status OK");
1317 radio->cmd = command;
1319 MMRADIO_LOG_FLEAVE();
1321 return MM_ERROR_NONE;
1324 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1325 MMRADIO_LOG_FLEAVE();
1326 return MM_ERROR_RADIO_INVALID_STATE;
1329 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1330 MMRADIO_LOG_FLEAVE();
1331 return MM_ERROR_RADIO_NO_OP;
1335 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1337 MMMessageParamType msg = { 0, };
1338 int msg_type = MM_MESSAGE_UNKNOWN;
1340 MMRADIO_LOG_FENTER();
1343 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1347 if (radio->current_state == new_state && radio->pending_state == 0) {
1348 MMRADIO_LOG_WARNING("we are in same state");
1353 radio->old_state = radio->current_state;
1354 radio->current_state = new_state;
1356 /* fill message param */
1357 msg.union_type = MM_MSG_UNION_STATE;
1358 msg.state.previous = radio->old_state;
1359 msg.state.current = radio->current_state;
1361 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1362 /* post message to application */
1363 if (radio->sound_focus.by_focus_cb) {
1364 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1365 msg.state.code = radio->sound_focus.event_src;
1366 MMRADIO_POST_MSG(radio, msg_type, &msg);
1367 } else if (radio->interrupted_by_resource_conflict) {
1368 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1369 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1370 MMRADIO_POST_MSG(radio, msg_type, &msg);
1372 msg_type = MM_MESSAGE_STATE_CHANGED;
1373 MMRADIO_POST_MSG(radio, msg_type, &msg);
1376 if (radio->interrupted_by_resource_conflict) {
1377 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1378 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1379 MMRADIO_POST_MSG(radio, msg_type, &msg);
1381 msg_type = MM_MESSAGE_STATE_CHANGED;
1382 MMRADIO_POST_MSG(radio, msg_type, &msg);
1387 MMRADIO_LOG_FLEAVE();
1392 static int __mmradio_get_state(mm_radio_t *radio)
1394 MMRADIO_CHECK_INSTANCE(radio);
1396 MMRADIO_LOG_INFO("radio state : current : [%d] old : [%d] pending : [%d]",
1397 radio->current_state, radio->old_state, radio->pending_state);
1399 return radio->current_state;
1402 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1403 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
1404 mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
1405 const char *additional_info, void *user_data)
1407 mm_radio_t *radio = (mm_radio_t *)user_data;
1408 enum MMMessageInterruptedCode event_source;
1409 int result = MM_ERROR_NONE;
1410 int postMsg = false;
1412 MMRADIO_LOG_FENTER();
1413 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1414 MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1416 mmradio_get_sound_focus_reason(focus_state, reason_for_change, FALSE, &event_source, &postMsg);
1417 radio->sound_focus.event_src = event_source;
1419 switch (focus_state) {
1420 case FOCUS_IS_RELEASED:{
1421 radio->sound_focus.cur_focus_type &= ~focus_type;
1422 radio->sound_focus.by_focus_cb = true;
1424 MMRADIO_CMD_LOCK(radio);
1425 result = _mmradio_stop(radio);
1427 MMRADIO_LOG_ERROR("failed to stop radio");
1428 MMRADIO_CMD_UNLOCK(radio);
1430 radio->sound_focus.by_focus_cb = false;
1432 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1436 case FOCUS_IS_ACQUIRED:{
1437 MMMessageParamType msg = { 0, };
1438 msg.union_type = MM_MSG_UNION_CODE;
1439 msg.code = event_source;
1441 radio->sound_focus.cur_focus_type |= focus_type;
1443 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1444 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1446 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1451 MMRADIO_LOG_DEBUG("Unknown focus_state");
1455 MMRADIO_LOG_FLEAVE();
1458 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
1459 mm_sound_focus_state_e focus_state, const char *reason_for_change,
1460 const char *additional_info, void *user_data)
1462 mm_radio_t *radio = (mm_radio_t *)user_data;
1463 enum MMMessageInterruptedCode event_source;
1464 int result = MM_ERROR_NONE;
1465 int postMsg = false;
1467 MMRADIO_LOG_FENTER();
1468 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1469 MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1471 mmradio_get_sound_focus_reason(focus_state, reason_for_change, true, &event_source, &postMsg);
1472 radio->sound_focus.event_src = event_source;
1474 switch (focus_state) {
1475 case FOCUS_IS_ACQUIRED: {
1476 radio->sound_focus.cur_focus_type &= ~focus_type;
1477 radio->sound_focus.by_focus_cb = true;
1479 MMRADIO_CMD_LOCK(radio);
1480 result = _mmradio_stop(radio);
1482 MMRADIO_LOG_ERROR("failed to stop radio");
1483 MMRADIO_CMD_UNLOCK(radio);
1485 radio->sound_focus.by_focus_cb = false;
1487 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
1491 case FOCUS_IS_RELEASED: {
1492 MMMessageParamType msg = { 0, };
1493 msg.union_type = MM_MSG_UNION_CODE;
1494 msg.code = event_source;
1496 radio->sound_focus.cur_focus_type |= focus_type;
1498 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1499 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1501 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1506 MMRADIO_LOG_DEBUG("Unknown focus_state");
1510 MMRADIO_LOG_FLEAVE();
1514 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1516 mm_radio_t *radio = (mm_radio_t *)user_data;
1517 int ret = MM_ERROR_NONE;
1518 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1519 if (type == VOLUME_TYPE_MEDIA) {
1520 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1521 ret = __mmradio_set_media_volume(radio, volume);
1522 if (ret != MM_ERROR_NONE)
1523 MMRADIO_LOG_ERROR("failed to set media volume");
1528 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1530 MMRADIO_LOG_FENTER();
1531 MMRADIO_CHECK_INSTANCE(radio);
1532 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1534 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1536 *type = radio->region_setting.country;
1538 MMRADIO_LOG_FLEAVE();
1539 return MM_ERROR_NONE;
1542 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1544 MMRADIO_LOG_FENTER();
1545 MMRADIO_CHECK_INSTANCE(radio);
1546 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1548 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1550 *min_freq = radio->region_setting.band_min;
1551 *max_freq = radio->region_setting.band_max;
1553 MMRADIO_LOG_FLEAVE();
1554 return MM_ERROR_NONE;
1557 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1559 MMRADIO_LOG_FENTER();
1560 MMRADIO_CHECK_INSTANCE(radio);
1561 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1563 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1565 *ch_spacing = radio->region_setting.channel_spacing;
1567 MMRADIO_LOG_FLEAVE();
1568 return MM_ERROR_NONE;
1571 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1573 int ret = MM_ERROR_NONE;
1575 MMRADIO_LOG_FENTER();
1577 MMRADIO_CHECK_INSTANCE(radio);
1578 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1580 MMRADIO_LOG_INFO("Setting %f volume", volume);
1582 MMRADIO_VOLUME_LOCK(radio);
1583 radio->local_volume = volume;
1584 MMRADIO_VOLUME_UNLOCK(radio);
1586 ret = radio_hal_set_volume(radio->hal_inf, volume);
1587 if (ret != MM_ERROR_NONE)
1588 MMRADIO_LOG_ERROR("failed to set radio hal volume");
1590 MMRADIO_LOG_FLEAVE();
1595 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1597 int ret = MM_ERROR_NONE;
1599 MMRADIO_LOG_FENTER();
1601 MMRADIO_CHECK_INSTANCE(radio);
1602 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1604 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1606 ret = radio_hal_get_volume(radio->hal_inf, &volume);
1607 if (ret != MM_ERROR_NONE) {
1608 MMRADIO_LOG_ERROR("failed to get radio hal volume");
1613 MMRADIO_VOLUME_LOCK(radio);
1614 radio->local_volume = volume;
1615 *pVolume = (float)radio->local_volume;
1616 MMRADIO_VOLUME_UNLOCK(radio);
1618 MMRADIO_LOG_FLEAVE();
1623 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1625 int ret = MM_ERROR_NONE;
1627 MMRADIO_LOG_FENTER();
1629 MMRADIO_CHECK_INSTANCE(radio);
1630 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1632 MMRADIO_LOG_INFO("Setting %d volume", level);
1634 MMRADIO_VOLUME_LOCK(radio);
1635 radio->media_volume = level;
1636 MMRADIO_VOLUME_UNLOCK(radio);
1638 ret = radio_hal_set_media_volume(radio->hal_inf, level);
1639 if (ret != MM_ERROR_NONE)
1640 MMRADIO_LOG_ERROR("failed to set radio hal media volume");
1642 MMRADIO_LOG_FLEAVE();
1647 static int __resource_release_cb(mm_resource_manager_h rm,
1648 mm_resource_manager_res_h res, void *user_data)
1650 mm_radio_t *radio = NULL;
1652 MMRADIO_LOG_FENTER();
1655 MMRADIO_LOG_ERROR("user_data is null");
1659 radio = (mm_radio_t *)user_data;
1660 radio->radio_resource = NULL;
1662 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1664 radio->interrupted_by_resource_conflict = TRUE;
1666 MMRADIO_CMD_LOCK(radio);
1667 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1668 MMRADIO_LOG_ERROR("failed to stop radio");
1669 MMRADIO_CMD_UNLOCK(radio);
1671 MMRADIO_LOG_FLEAVE();
1676 static int __mmradio_create_thread(mm_radio_t *radio)
1678 int ret = MM_ERROR_NONE;
1680 MMRADIO_LOG_FENTER();
1682 MMRADIO_CHECK_INSTANCE(radio);
1684 MMRADIO_INIT_MUTEX(radio->cmd_lock);
1685 MMRADIO_INIT_MUTEX(radio->volume_lock);
1686 MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
1688 MMRADIO_INIT_MUTEX(radio->seek.mutex);
1689 MMRADIO_INIT_COND(radio->seek.cond);
1691 radio->seek.thread_id = pthread_create(&radio->seek.thread, NULL,
1692 (void *)__mmradio_seek_thread, (void *)radio);
1693 if (radio->seek.thread_id) {
1694 MMRADIO_LOG_DEBUG("failed to create thread : seek");
1698 MMRADIO_INIT_MUTEX(radio->scan.mutex);
1699 MMRADIO_INIT_COND(radio->scan.cond);
1701 radio->scan.thread_id = pthread_create(&radio->scan.thread, NULL,
1702 (void *)__mmradio_scan_thread, (void *)radio);
1703 if (radio->scan.thread_id) {
1704 MMRADIO_LOG_ERROR("failed to create thread : scan");
1708 MMRADIO_LOG_FLEAVE();
1713 if (radio->seek.thread) {
1714 MMRADIO_SEEK_THREAD_LOCK(radio);
1715 radio->seek.thread_exit = true;
1716 MMRADIO_SEEK_THREAD_SIGNAL(radio);
1717 MMRADIO_SEEK_THREAD_UNLOCK(radio);
1718 pthread_join(radio->seek.thread, NULL);
1719 radio->seek.thread = 0;
1722 pthread_mutex_destroy(&radio->cmd_lock);
1723 pthread_mutex_destroy(&radio->volume_lock);
1724 pthread_mutex_destroy(&radio->hal_seek_mutex);
1725 pthread_mutex_destroy(&radio->seek.mutex);
1726 pthread_cond_destroy(&radio->seek.cond);
1727 pthread_mutex_destroy(&radio->scan.mutex);
1728 pthread_cond_destroy(&radio->scan.cond);
1730 return MM_ERROR_RADIO_INTERNAL;
1733 static void __mmradio_destroy_thread(mm_radio_t *radio)
1735 MMRADIO_LOG_FENTER();
1737 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1739 if (radio->seek.thread) {
1740 MMRADIO_SEEK_THREAD_LOCK(radio);
1741 radio->seek.thread_exit = true;
1742 MMRADIO_SEEK_THREAD_SIGNAL(radio);
1743 MMRADIO_SEEK_THREAD_UNLOCK(radio);
1744 pthread_join(radio->seek.thread, NULL);
1745 radio->seek.thread = 0;
1748 if (radio->scan.thread) {
1749 MMRADIO_SCAN_THREAD_LOCK(radio);
1750 radio->scan.thread_exit = true;
1751 MMRADIO_SCAN_THREAD_SIGNAL(radio);
1752 MMRADIO_SCAN_THREAD_UNLOCK(radio);
1753 pthread_join(radio->scan.thread, NULL);
1754 radio->scan.thread = 0;
1757 pthread_mutex_destroy(&radio->cmd_lock);
1758 pthread_mutex_destroy(&radio->volume_lock);
1759 pthread_mutex_destroy(&radio->hal_seek_mutex);
1761 pthread_mutex_destroy(&radio->seek.mutex);
1762 pthread_cond_destroy(&radio->seek.cond);
1764 pthread_mutex_destroy(&radio->scan.mutex);
1765 pthread_cond_destroy(&radio->scan.cond);
1767 MMRADIO_LOG_FLEAVE();