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 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
130 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
131 static int __resource_release_cb(mm_resource_manager_h rm,
132 mm_resource_manager_res_h res, void *user_data);
133 static void __mmradio_msg_thread(mm_radio_t *radio);
134 static void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data);
136 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
138 int ret = MM_ERROR_NONE;
142 MMRADIO_LOG_FENTER();
144 MMRADIO_CHECK_INSTANCE(radio);
145 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
147 /* if needed, radio region must be updated.
148 * Otherwise, just applying settings to device without it.
151 count = ARRAY_SIZE(region_table);
153 /* TODO: if auto is supported...get the region info. here */
155 /* update radio region settings */
156 for (index = 0; index < count; index++) {
157 /* find the region from pre-defined table */
158 if (region_table[index].country == region) {
159 radio->region_setting.country = region_table[index].country;
160 radio->region_setting.deemphasis = region_table[index].deemphasis;
161 radio->region_setting.band_min = region_table[index].band_min;
162 radio->region_setting.band_max = region_table[index].band_max;
163 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
168 MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
169 radio->region_setting.country, radio->region_setting.deemphasis,
170 radio->region_setting.band_min, radio->region_setting.band_max);
172 MMRADIO_LOG_FLEAVE();
177 int _mmradio_create_radio(mm_radio_t *radio)
179 int ret = MM_ERROR_NONE;
181 MMRADIO_LOG_FENTER();
183 MMRADIO_CHECK_INSTANCE(radio);
184 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
186 /* set default value */
187 radio->freq = DEFAULT_FREQ;
188 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
189 radio->local_volume = 1.0;
191 /* create msg queue for msg thread */
192 radio->msg_queue = g_async_queue_new();
193 if (!radio->msg_queue) {
194 MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
195 return MM_ERROR_RADIO_INTERNAL;
198 /* create mutex and thread */
199 ret = __mmradio_create_thread(radio);
201 MMRADIO_LOG_ERROR("failed to create threads");
205 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
207 /* initialize resource manager */
208 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
209 __resource_release_cb, radio, &radio->resource_manager);
211 MMRADIO_LOG_ERROR("failed to create resource manager");
212 ret = MM_ERROR_RADIO_INTERNAL;
216 ret = radio_hal_interface_init(&(radio->hal_inf));
218 MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
222 MMRADIO_LOG_FLEAVE();
224 return MM_ERROR_NONE;
227 mm_resource_manager_destroy(radio->resource_manager);
229 __mmradio_destroy_thread(radio);
231 if (radio->msg_queue)
232 g_async_queue_unref(radio->msg_queue);
236 int _mmradio_realize(mm_radio_t *radio)
238 int ret = MM_ERROR_NONE;
242 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
244 MMRADIO_LOG_FENTER();
246 MMRADIO_CHECK_INSTANCE(radio);
247 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
249 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
250 /* not initialized yet. set it with default region */
251 region = RADIO_DEFAULT_REGION;
254 /* already initialized by application */
255 region = radio->region_setting.country;
258 ret = _mmradio_apply_region(radio, region, update);
260 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
261 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
262 if (ret != MM_ERROR_NONE) {
263 MMRADIO_LOG_ERROR("failed to create stream information");
264 MMRADIO_LOG_FLEAVE();
267 ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
268 if (ret != MM_ERROR_NONE) {
269 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
270 MMRADIO_LOG_FLEAVE();
275 ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
276 if (ret != MM_ERROR_NONE) {
277 MMRADIO_LOG_WARNING("failed to get max volume");
278 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
280 radio->max_media_volume = max;
283 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
285 if (ret != MM_ERROR_NONE)
286 MMRADIO_LOG_WARNING("failed to get media volume");
288 MMRADIO_VOLUME_LOCK(radio);
289 radio->media_volume = volume;
290 MMRADIO_VOLUME_UNLOCK(radio);
292 ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
293 if (ret != MM_ERROR_NONE)
294 MMRADIO_LOG_WARNING("failed to register volume changed callback");
296 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
298 MMRADIO_LOG_FLEAVE();
300 return MM_ERROR_NONE;
303 int _mmradio_unrealize(mm_radio_t *radio)
305 int ret = MM_ERROR_NONE;
307 MMRADIO_LOG_FENTER();
309 MMRADIO_CHECK_INSTANCE(radio);
310 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
312 ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
313 if (ret != MM_ERROR_NONE)
314 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
316 /*Finish if there are scans*/
317 _mmradio_stop_scan(radio);
319 /*Stop radio if started*/
320 _mmradio_stop(radio);
322 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
323 sound_manager_destroy_virtual_stream(radio->vstream);
324 sound_manager_destroy_stream_information(radio->stream_info);
327 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
329 MMRADIO_LOG_FLEAVE();
334 int _mmradio_destroy(mm_radio_t *radio)
336 int ret = MM_ERROR_NONE;
337 MMRADIO_LOG_FENTER();
339 MMRADIO_CHECK_INSTANCE(radio);
340 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
342 _mmradio_unrealize(radio);
344 /* destroy mutex and thread */
345 __mmradio_destroy_thread(radio);
347 if (radio->msg_queue)
348 g_async_queue_unref(radio->msg_queue);
350 ret = radio_hal_interface_deinit(radio->hal_inf);
352 MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
356 ret = mm_resource_manager_destroy(radio->resource_manager);
358 MMRADIO_LOG_ERROR("failed to destroy resource manager");
359 return MM_ERROR_RADIO_INTERNAL;
362 MMRADIO_LOG_FLEAVE();
364 return MM_ERROR_NONE;
367 /* unit should be KHz */
368 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
370 int ret = MM_ERROR_NONE;
372 MMRADIO_LOG_FENTER();
374 MMRADIO_CHECK_INSTANCE(radio);
375 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
377 MMRADIO_LOG_INFO("Setting %d frequency", freq);
381 ret = radio_hal_set_frequency(radio->hal_inf, freq);
382 if (ret != MM_ERROR_NONE) {
383 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
384 MMRADIO_LOG_FLEAVE();
388 MMRADIO_LOG_FLEAVE();
394 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
396 int ret = MM_ERROR_NONE;
398 MMRADIO_LOG_FENTER();
400 MMRADIO_CHECK_INSTANCE(radio);
401 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
403 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
405 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
406 if (ret != MM_ERROR_NONE) {
407 MMRADIO_LOG_ERROR("failed to get radio hal frequency");
412 /* update freq in handle */
413 MMRADIO_LOG_INFO("Updating %d frequency", freq);
416 *pFreq = (int)radio->freq;
418 MMRADIO_LOG_FLEAVE();
423 int _mmradio_mute(mm_radio_t *radio)
425 int ret = MM_ERROR_NONE;
426 MMRADIO_LOG_FENTER();
428 MMRADIO_CHECK_INSTANCE(radio);
429 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
431 ret = radio_hal_mute(radio->hal_inf);
432 if (ret == MM_ERROR_NOT_SUPPORT_API) {
433 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
434 } else if (ret != MM_ERROR_NONE) {
435 MMRADIO_LOG_ERROR("failed to set radio hal mute");
436 MMRADIO_LOG_FLEAVE();
440 radio->is_muted = true;
441 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
442 MMRADIO_LOG_FLEAVE();
447 int _mmradio_unmute(mm_radio_t *radio)
449 int ret = MM_ERROR_NONE;
450 MMRADIO_LOG_FENTER();
452 MMRADIO_CHECK_INSTANCE(radio);
453 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
455 ret = radio_hal_unmute(radio->hal_inf);
456 if (ret == MM_ERROR_NOT_SUPPORT_API) {
457 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
458 } else if (ret != MM_ERROR_NONE) {
459 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
460 MMRADIO_LOG_FLEAVE();
464 radio->is_muted = false;
465 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
466 MMRADIO_LOG_FLEAVE();
471 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
473 MMRADIO_LOG_FENTER();
475 MMRADIO_CHECK_INSTANCE(radio);
477 radio->msg_cb = callback;
478 radio->msg_cb_param = user_param;
480 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
482 MMRADIO_LOG_FLEAVE();
484 return MM_ERROR_NONE;
487 int _mmradio_get_state(mm_radio_t *radio, int *pState)
491 MMRADIO_LOG_FENTER();
493 MMRADIO_CHECK_INSTANCE(radio);
494 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
496 state = __mmradio_get_state(radio);
500 MMRADIO_LOG_FLEAVE();
502 return MM_ERROR_NONE;
505 int _mmradio_start(mm_radio_t *radio)
507 int ret = MM_ERROR_NONE;
508 unsigned int volume = 0;
510 MMRADIO_LOG_FENTER();
512 MMRADIO_CHECK_INSTANCE(radio);
513 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
515 MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
517 if (!radio->is_ready) {
518 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
519 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
520 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
521 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
522 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
523 return MM_ERROR_RADIO_INTERNAL;
526 radio->interrupted_by_resource_conflict = FALSE;
527 ret = mm_resource_manager_commit(radio->resource_manager);
528 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
529 MMRADIO_LOG_ERROR("failed to commit resource manager");
530 mm_resource_manager_mark_for_release(radio->resource_manager,
531 radio->radio_resource);
532 radio->radio_resource = NULL;
536 ret = radio_hal_prepare(radio->hal_inf);
537 if (ret == MM_ERROR_NOT_SUPPORT_API) {
538 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
539 } else if (ret != MM_ERROR_NONE) {
540 MMRADIO_LOG_ERROR("failed to prepare radio hal");
544 ret = radio_hal_open(radio->hal_inf);
545 if (ret == MM_ERROR_NOT_SUPPORT_API) {
546 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
547 } else if (ret != MM_ERROR_NONE) {
548 MMRADIO_LOG_ERROR("failed to open radio hal");
551 radio->is_ready = true;
553 MMRADIO_LOG_DEBUG("radio prepared and opened");
556 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
557 if (ret != MM_ERROR_NONE)
558 MMRADIO_LOG_WARNING("failed to get media volume");
560 ret = __mmradio_set_media_volume(radio, volume);
561 if (ret != MM_ERROR_NONE) {
562 MMRADIO_LOG_ERROR("failed to set media volume");
566 ret = radio_hal_start(radio->hal_inf);
567 if (ret == MM_ERROR_NOT_SUPPORT_API) {
568 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
570 MMRADIO_LOG_ERROR("failed to start radio hal");
574 /* set stored frequency */
575 ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
577 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
581 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
582 ret = sound_manager_start_virtual_stream(radio->vstream);
584 MMRADIO_LOG_ERROR("failed to start sound manager virtual stream");
589 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
591 MMRADIO_LOG_FLEAVE();
593 return MM_ERROR_NONE;
596 radio_hal_close(radio->hal_inf);
598 radio_hal_unprepare(radio->hal_inf);
599 radio->is_ready = false;
603 int _mmradio_stop(mm_radio_t *radio)
605 int ret = MM_ERROR_NONE;
607 MMRADIO_LOG_FENTER();
609 MMRADIO_CHECK_INSTANCE(radio);
610 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
612 /*cancel if any seek*/
613 _mmradio_seek_cancel(radio);
614 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
615 ret = sound_manager_stop_virtual_stream(radio->vstream);
616 if (ret != MM_ERROR_NONE) {
617 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
622 ret = radio_hal_stop(radio->hal_inf);
623 if (ret == MM_ERROR_NOT_SUPPORT_API) {
624 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
626 MMRADIO_LOG_ERROR("failed to stop radio hal");
630 if (radio->is_ready) {
631 /* close radio device here !!!! */
632 ret = radio_hal_close(radio->hal_inf);
633 if (ret == MM_ERROR_NOT_SUPPORT_API) {
634 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
635 } else if (ret != MM_ERROR_NONE) {
636 MMRADIO_LOG_ERROR("failed to close radio hal");
640 ret = radio_hal_unprepare(radio->hal_inf);
641 if (ret == MM_ERROR_NOT_SUPPORT_API) {
642 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
643 } else if (ret != MM_ERROR_NONE) {
644 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
648 if (!radio->interrupted_by_resource_conflict && /* is being released */
649 radio->radio_resource != NULL) {
650 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
651 radio->radio_resource);
652 radio->radio_resource = NULL;
653 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
654 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
658 ret = mm_resource_manager_commit(radio->resource_manager);
659 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
660 MMRADIO_LOG_ERROR("resource manager commit fail");
663 radio->is_ready = false;
666 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
668 MMRADIO_LOG_FLEAVE();
670 return MM_ERROR_NONE;
673 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
675 int ret = MM_ERROR_NONE;
677 MMRADIO_LOG_FENTER();
679 MMRADIO_CHECK_INSTANCE(radio);
680 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
682 if (radio->seek.is_running) {
683 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
684 return MM_ERROR_RADIO_INTERNAL;
687 radio->seek_unmute = false;
689 if (!radio->is_muted) {
690 ret = radio_hal_mute(radio->hal_inf);
691 if (ret == MM_ERROR_NOT_SUPPORT_API) {
692 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
694 MMRADIO_LOG_ERROR("failed to set radio hal mute");
697 radio->seek_unmute = true;
700 MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
701 radio->seek_direction = direction;
702 radio->seek.is_running = true;
703 radio->seek.stop = false;
705 MMRADIO_SEEK_THREAD_SIGNAL(radio);
707 MMRADIO_LOG_FLEAVE();
709 return MM_ERROR_NONE;
712 void _mmradio_seek_cancel(mm_radio_t *radio)
714 MMRADIO_LOG_FENTER();
716 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
718 /* cancel any outstanding seek request */
719 radio->seek.stop = true;
721 MMRADIO_LOG_FLEAVE();
724 int _mmradio_start_scan(mm_radio_t *radio)
726 int ret = MM_ERROR_NONE;
728 MMRADIO_LOG_FENTER();
730 MMRADIO_CHECK_INSTANCE(radio);
731 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
733 radio->scan.stop = false;
735 if (!radio->is_ready) {
736 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
737 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
738 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
739 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
740 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
741 return MM_ERROR_RADIO_INTERNAL;
744 radio->interrupted_by_resource_conflict = FALSE;
745 ret = mm_resource_manager_commit(radio->resource_manager);
746 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
747 MMRADIO_LOG_ERROR("failed to commit resource manager");
748 mm_resource_manager_mark_for_release(radio->resource_manager,
749 radio->radio_resource);
750 radio->radio_resource = NULL;
754 ret = radio_hal_prepare(radio->hal_inf);
755 if (ret == MM_ERROR_NOT_SUPPORT_API) {
756 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
757 } else if (ret != MM_ERROR_NONE) {
758 MMRADIO_LOG_ERROR("failed to prepare radio hal");
762 ret = radio_hal_open(radio->hal_inf);
763 if (ret == MM_ERROR_NOT_SUPPORT_API) {
764 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
765 } else if (ret != MM_ERROR_NONE) {
766 MMRADIO_LOG_ERROR("failed to open radio hal");
767 MMRADIO_LOG_FLEAVE();
770 radio->is_ready = true;
772 MMRADIO_LOG_DEBUG("radio prepared and opened");
775 radio->scan.is_running = true;
777 MMRADIO_SCAN_THREAD_SIGNAL(radio);
779 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
781 MMRADIO_LOG_FLEAVE();
783 return MM_ERROR_NONE;
786 int _mmradio_stop_scan(mm_radio_t *radio)
788 MMRADIO_LOG_FENTER();
790 MMRADIO_CHECK_INSTANCE(radio);
791 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
793 radio->scan.stop = true;
795 MMRADIO_LOG_FLEAVE();
797 return MM_ERROR_NONE;
800 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
802 int ret = MM_ERROR_NONE;
803 int32_t strength = 0;
804 MMRADIO_LOG_FENTER();
805 MMRADIO_CHECK_INSTANCE(radio);
807 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
809 /* just return stored frequency if radio device is not ready */
810 ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
811 if (ret == MM_ERROR_NOT_SUPPORT_API) {
812 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
813 } else if (ret != MM_ERROR_NONE) {
814 MMRADIO_LOG_ERROR("failed to get radio hal signal strength");
816 MMRADIO_LOG_FLEAVE();
819 *value = (int)strength;
820 MMRADIO_LOG_FLEAVE();
821 return MM_ERROR_NONE;
824 void __mmradio_scan_thread(mm_radio_t *radio)
826 int ret = MM_ERROR_NONE;
829 MMRADIO_LOG_FENTER();
830 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
832 MMRADIO_SCAN_THREAD_LOCK(radio);
834 while (!radio->scan.thread_exit) {
835 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
836 MMRADIO_SCAN_THREAD_WAIT(radio);
838 if (radio->scan.thread_exit) {
839 MMRADIO_LOG_DEBUG("exiting scan thread");
843 ret = radio_hal_mute(radio->hal_inf);
844 if (ret == MM_ERROR_NOT_SUPPORT_API) {
845 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
846 } else if (ret != MM_ERROR_NONE) {
847 MMRADIO_LOG_ERROR("faied to set radio hal mute");
851 ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
852 if (ret != MM_ERROR_NONE)
855 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
856 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
859 while (!radio->scan.stop) {
862 MMRADIO_LOG_DEBUG("scanning....");
864 if (radio->scan.thread_exit) {
865 MMRADIO_LOG_DEBUG("exiting scan thread");
869 if (radio->scan.stop) {
870 MMRADIO_LOG_INFO("scan was canceled");
874 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
875 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
876 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
877 if (ret != MM_ERROR_NONE) {
878 MMRADIO_LOG_ERROR("radio scanning error");
882 if (radio->scan.thread_exit) {
883 MMRADIO_LOG_DEBUG("exiting scan thread");
887 if (radio->scan.stop) {
888 MMRADIO_LOG_INFO("scan was canceled");
892 /* now we can get new frequency from radio device */
893 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
894 if (ret != MM_ERROR_NONE) {
895 MMRADIO_LOG_ERROR("failed to get current frequency");
897 if (freq <= prev_freq) {
898 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
902 prev_freq = (int)freq;
903 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", prev_freq);
905 /* drop if max freq is scanned */
906 if (prev_freq >= radio->region_setting.band_max) {
907 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", prev_freq);
911 if (radio->scan.stop) {
912 /* doesn't need to post */
916 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
921 if (radio->old_state == MM_RADIO_STATE_READY) {
922 MMRADIO_LOG_DEBUG("old state is ready");
923 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
924 MMRADIO_LOG_DEBUG("old state is playing");
925 ret = radio_hal_unmute(radio->hal_inf);
926 if (ret == MM_ERROR_NOT_SUPPORT_API) {
927 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
928 } else if (ret != MM_ERROR_NONE) {
929 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
932 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
933 if (ret == MM_ERROR_NOT_SUPPORT_API) {
934 MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
935 } else if (ret != MM_ERROR_NONE) {
936 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
942 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
943 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
945 /* close radio device here !!!! */
946 if (radio->is_ready) {
947 ret = radio_hal_close(radio->hal_inf);
948 if (ret == MM_ERROR_NOT_SUPPORT_API)
949 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
950 else if (ret != MM_ERROR_NONE)
951 MMRADIO_LOG_ERROR("failed to close radio hal");
953 ret = radio_hal_unprepare(radio->hal_inf);
954 if (ret == MM_ERROR_NOT_SUPPORT_API)
955 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
956 else if (ret != MM_ERROR_NONE)
957 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
959 if (!radio->interrupted_by_resource_conflict && /* is being released */
960 radio->radio_resource != NULL) {
961 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
962 radio->radio_resource);
963 radio->radio_resource = NULL;
964 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
965 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
968 ret = mm_resource_manager_commit(radio->resource_manager);
969 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
970 MMRADIO_LOG_ERROR("resource manager commit fail");
971 radio->is_ready = false;
973 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
976 if (!radio->scan.stop)
977 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
979 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
981 radio->scan.is_running = false;
986 radio->scan.is_running = false;
988 MMRADIO_SCAN_THREAD_UNLOCK(radio);
990 MMRADIO_LOG_FLEAVE();
996 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
998 MMRADIO_LOG_FENTER();
1000 MMRADIO_CHECK_INSTANCE(radio);
1002 if (freq >= radio->region_setting.band_max
1003 || freq <= radio->region_setting.band_min)
1006 MMRADIO_LOG_FLEAVE();
1011 void __mmradio_seek_thread(mm_radio_t *radio)
1013 int ret = MM_ERROR_NONE;
1016 MMRADIO_LOG_FENTER();
1017 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1019 MMRADIO_SEEK_THREAD_LOCK(radio);
1021 while (!radio->seek.thread_exit) {
1022 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
1023 MMRADIO_SEEK_THREAD_WAIT(radio);
1025 if (radio->seek.thread_exit) {
1026 MMRADIO_LOG_DEBUG("exiting seek thread");
1030 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1031 MMRADIO_LOG_DEBUG("seeking....");
1033 if (radio->seek.stop) {
1034 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1038 MMRADIO_LOG_DEBUG("try to seek ");
1039 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
1040 MMRADIO_LOG_DEBUG("seek start");
1041 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1042 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
1044 MMRADIO_LOG_ERROR("failed to seek radio hal");
1048 if (radio->seek.thread_exit) {
1049 MMRADIO_LOG_DEBUG("exiting seek thread");
1053 if (radio->seek.stop) {
1054 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1058 /* now we can get new frequency from radio device */
1059 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1061 MMRADIO_LOG_ERROR("failed to get current frequency");
1065 MMRADIO_LOG_DEBUG("found frequency");
1067 /* if same freq is found, ignore it and search next one. */
1068 if (freq == radio->prev_seek_freq) {
1069 MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1073 /* check if it's limit freq or not */
1074 if (__is_tunable_frequency(radio, freq)) {
1075 /* now tune to new frequency */
1076 ret = radio_hal_set_frequency(radio->hal_inf, freq);
1078 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1081 radio->freq = (int)freq;
1082 MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1085 if (radio->seek_unmute) {
1086 /* now turn on radio
1087 * In the case of limit freq, tuner should be unmuted.
1088 * Otherwise, sound can't output even though application set new frequency.
1090 ret = radio_hal_unmute(radio->hal_inf);
1092 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1095 radio->seek_unmute = false;
1098 radio->prev_seek_freq = (int)freq;
1099 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
1100 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
1101 radio->seek.is_running = false;
1105 if (radio->seek_unmute) {
1106 /* now turn on radio
1107 * In the case of limit freq, tuner should be unmuted.
1108 * Otherwise, sound can't output even though application set new frequency.
1110 ret = radio_hal_unmute(radio->hal_inf);
1112 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1113 radio->seek_unmute = false;
1115 /* freq -1 means it's failed to seek */
1116 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
1117 radio->seek.is_running = false;
1121 radio->seek.is_running = false;
1122 MMRADIO_SEEK_THREAD_UNLOCK(radio);
1123 MMRADIO_LOG_FLEAVE();
1127 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1129 MMRADIO_CHECK_INSTANCE(radio);
1131 MMRADIO_LOG_FENTER();
1133 if (!radio->msg_cb) {
1134 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1138 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1140 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1142 MMRADIO_LOG_FLEAVE();
1147 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1149 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1151 MMRADIO_LOG_FENTER();
1153 MMRADIO_CHECK_INSTANCE(radio);
1155 radio_state = __mmradio_get_state(radio);
1157 MMRADIO_LOG_INFO("incomming command : %d current state : %d", command, radio_state);
1160 case MMRADIO_COMMAND_CREATE:
1162 if (radio_state != 0)
1167 case MMRADIO_COMMAND_REALIZE:
1169 if (radio_state == MM_RADIO_STATE_READY ||
1170 radio_state == MM_RADIO_STATE_PLAYING ||
1171 radio_state == MM_RADIO_STATE_SCANNING)
1174 if (radio_state == 0)
1179 case MMRADIO_COMMAND_UNREALIZE:
1181 if (radio_state == MM_RADIO_STATE_NULL)
1184 /* we can call unrealize at any higher state */
1188 case MMRADIO_COMMAND_START:
1190 if (radio_state == MM_RADIO_STATE_PLAYING)
1193 if (radio_state != MM_RADIO_STATE_READY)
1198 case MMRADIO_COMMAND_STOP:
1200 if (radio_state == MM_RADIO_STATE_READY)
1203 if (radio_state != MM_RADIO_STATE_PLAYING)
1208 case MMRADIO_COMMAND_START_SCAN:
1210 if (radio_state == MM_RADIO_STATE_SCANNING)
1213 if (radio_state == MM_RADIO_STATE_NULL)
1218 case MMRADIO_COMMAND_STOP_SCAN:
1220 if (radio_state == MM_RADIO_STATE_READY)
1223 if (radio_state != MM_RADIO_STATE_SCANNING)
1228 case MMRADIO_COMMAND_DESTROY:
1229 case MMRADIO_COMMAND_MUTE:
1230 case MMRADIO_COMMAND_UNMUTE:
1231 case MMRADIO_COMMAND_SET_FREQ:
1232 case MMRADIO_COMMAND_GET_FREQ:
1233 case MMRADIO_COMMAND_SET_REGION:
1234 case MMRADIO_COMMAND_SET_VOLUME:
1235 case MMRADIO_COMMAND_GET_VOLUME:
1237 /* we can do it at any state */
1241 case MMRADIO_COMMAND_SEEK:
1243 if (radio_state != MM_RADIO_STATE_PLAYING)
1248 case MMRADIO_COMMAND_GET_REGION:
1250 if (radio_state == MM_RADIO_STATE_NULL)
1256 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1260 MMRADIO_LOG_DEBUG("status OK");
1262 radio->cmd = command;
1264 MMRADIO_LOG_FLEAVE();
1266 return MM_ERROR_NONE;
1269 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1270 MMRADIO_LOG_FLEAVE();
1271 return MM_ERROR_RADIO_INVALID_STATE;
1274 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1275 MMRADIO_LOG_FLEAVE();
1276 return MM_ERROR_RADIO_NO_OP;
1280 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1282 MMMessageParamType msg = { 0, };
1283 int msg_type = MM_MESSAGE_UNKNOWN;
1285 MMRADIO_LOG_FENTER();
1288 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1292 if (radio->current_state == new_state && radio->pending_state == 0) {
1293 MMRADIO_LOG_WARNING("we are in same state");
1298 radio->old_state = radio->current_state;
1299 radio->current_state = new_state;
1301 /* fill message param */
1302 msg.union_type = MM_MSG_UNION_STATE;
1303 msg.state.previous = radio->old_state;
1304 msg.state.current = radio->current_state;
1306 if (radio->interrupted_by_resource_conflict) {
1307 __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
1308 MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
1310 msg_type = MM_MESSAGE_STATE_CHANGED;
1311 MMRADIO_POST_MSG(radio, msg_type, &msg);
1314 MMRADIO_LOG_FLEAVE();
1319 static int __mmradio_get_state(mm_radio_t *radio)
1321 MMRADIO_CHECK_INSTANCE(radio);
1323 MMRADIO_LOG_INFO("radio state : current : [%d] old : [%d] pending : [%d]",
1324 radio->current_state, radio->old_state, radio->pending_state);
1326 return radio->current_state;
1329 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1331 mm_radio_t *radio = (mm_radio_t *)user_data;
1332 int ret = MM_ERROR_NONE;
1333 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1334 if (type == VOLUME_TYPE_MEDIA) {
1335 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1336 ret = __mmradio_set_media_volume(radio, volume);
1337 if (ret != MM_ERROR_NONE)
1338 MMRADIO_LOG_ERROR("failed to set media volume");
1343 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1345 MMRADIO_LOG_FENTER();
1346 MMRADIO_CHECK_INSTANCE(radio);
1347 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1349 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1351 *type = radio->region_setting.country;
1353 MMRADIO_LOG_FLEAVE();
1354 return MM_ERROR_NONE;
1357 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1359 MMRADIO_LOG_FENTER();
1360 MMRADIO_CHECK_INSTANCE(radio);
1361 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1363 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1365 *min_freq = radio->region_setting.band_min;
1366 *max_freq = radio->region_setting.band_max;
1368 MMRADIO_LOG_FLEAVE();
1369 return MM_ERROR_NONE;
1372 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1374 MMRADIO_LOG_FENTER();
1375 MMRADIO_CHECK_INSTANCE(radio);
1376 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1378 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1380 *ch_spacing = radio->region_setting.channel_spacing;
1382 MMRADIO_LOG_FLEAVE();
1383 return MM_ERROR_NONE;
1386 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1388 int ret = MM_ERROR_NONE;
1390 MMRADIO_LOG_FENTER();
1392 MMRADIO_CHECK_INSTANCE(radio);
1393 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1395 MMRADIO_LOG_INFO("Setting %f volume", volume);
1397 MMRADIO_VOLUME_LOCK(radio);
1398 radio->local_volume = volume;
1399 MMRADIO_VOLUME_UNLOCK(radio);
1401 ret = radio_hal_set_volume(radio->hal_inf, volume);
1402 if (ret != MM_ERROR_NONE)
1403 MMRADIO_LOG_ERROR("failed to set radio hal volume");
1405 MMRADIO_LOG_FLEAVE();
1410 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1412 int ret = MM_ERROR_NONE;
1414 MMRADIO_LOG_FENTER();
1416 MMRADIO_CHECK_INSTANCE(radio);
1417 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1419 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1421 ret = radio_hal_get_volume(radio->hal_inf, &volume);
1422 if (ret != MM_ERROR_NONE) {
1423 MMRADIO_LOG_ERROR("failed to get radio hal volume");
1428 MMRADIO_VOLUME_LOCK(radio);
1429 radio->local_volume = volume;
1430 *pVolume = (float)radio->local_volume;
1431 MMRADIO_VOLUME_UNLOCK(radio);
1433 MMRADIO_LOG_FLEAVE();
1438 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1440 int ret = MM_ERROR_NONE;
1442 MMRADIO_LOG_FENTER();
1444 MMRADIO_CHECK_INSTANCE(radio);
1445 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1447 MMRADIO_LOG_INFO("Setting %d volume", level);
1449 MMRADIO_VOLUME_LOCK(radio);
1450 radio->media_volume = level;
1451 MMRADIO_VOLUME_UNLOCK(radio);
1453 ret = radio_hal_set_media_volume(radio->hal_inf, level);
1454 if (ret != MM_ERROR_NONE)
1455 MMRADIO_LOG_ERROR("failed to set radio hal media volume");
1457 MMRADIO_LOG_FLEAVE();
1462 static int __resource_release_cb(mm_resource_manager_h rm,
1463 mm_resource_manager_res_h res, void *user_data)
1465 mm_radio_t *radio = NULL;
1467 MMRADIO_LOG_FENTER();
1470 MMRADIO_LOG_ERROR("user_data is null");
1474 radio = (mm_radio_t *)user_data;
1475 radio->radio_resource = NULL;
1477 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1479 radio->interrupted_by_resource_conflict = TRUE;
1481 MMRADIO_CMD_LOCK(radio);
1482 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1483 MMRADIO_LOG_ERROR("failed to stop radio");
1484 MMRADIO_CMD_UNLOCK(radio);
1486 MMRADIO_LOG_FLEAVE();
1491 static int __mmradio_create_thread(mm_radio_t *radio)
1493 int ret = MM_ERROR_NONE;
1495 MMRADIO_LOG_FENTER();
1497 MMRADIO_CHECK_INSTANCE(radio);
1499 MMRADIO_INIT_MUTEX(radio->cmd_lock);
1500 MMRADIO_INIT_MUTEX(radio->volume_lock);
1501 MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
1503 radio->msg.thread_id = pthread_create(&radio->msg.thread, NULL,
1504 (void *)__mmradio_msg_thread, (void *)radio);
1505 if (radio->msg.thread_id) {
1506 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
1507 MMRADIO_LOG_ERROR("failed to create thread : msg");
1511 MMRADIO_INIT_MUTEX(radio->seek.mutex);
1512 MMRADIO_INIT_COND(radio->seek.cond);
1514 radio->seek.thread_id = pthread_create(&radio->seek.thread, NULL,
1515 (void *)__mmradio_seek_thread, (void *)radio);
1516 if (radio->seek.thread_id) {
1517 MMRADIO_LOG_DEBUG("failed to create thread : seek");
1521 MMRADIO_INIT_MUTEX(radio->scan.mutex);
1522 MMRADIO_INIT_COND(radio->scan.cond);
1524 radio->scan.thread_id = pthread_create(&radio->scan.thread, NULL,
1525 (void *)__mmradio_scan_thread, (void *)radio);
1526 if (radio->scan.thread_id) {
1527 MMRADIO_LOG_ERROR("failed to create thread : scan");
1531 MMRADIO_LOG_FLEAVE();
1535 if (radio->seek.thread) {
1536 MMRADIO_SEEK_THREAD_LOCK(radio);
1537 radio->seek.thread_exit = true;
1538 MMRADIO_SEEK_THREAD_SIGNAL(radio);
1539 MMRADIO_SEEK_THREAD_UNLOCK(radio);
1540 pthread_join(radio->seek.thread, NULL);
1541 radio->seek.thread = 0;
1544 if (radio->msg.thread) {
1545 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1547 MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
1549 msg->msg_type = MM_RADIO_MSG_DESTROY;
1550 g_async_queue_push_front(radio->msg_queue, msg);
1551 pthread_join(radio->msg.thread, NULL);
1552 radio->msg.thread = 0;
1556 pthread_mutex_destroy(&radio->cmd_lock);
1557 pthread_mutex_destroy(&radio->volume_lock);
1558 pthread_mutex_destroy(&radio->hal_seek_mutex);
1559 pthread_mutex_destroy(&radio->seek.mutex);
1560 pthread_cond_destroy(&radio->seek.cond);
1561 pthread_mutex_destroy(&radio->scan.mutex);
1562 pthread_cond_destroy(&radio->scan.cond);
1564 return MM_ERROR_RADIO_INTERNAL;
1567 static void __mmradio_destroy_thread(mm_radio_t *radio)
1569 MMRADIO_LOG_FENTER();
1571 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1573 if (radio->seek.thread) {
1574 MMRADIO_SEEK_THREAD_LOCK(radio);
1575 radio->seek.thread_exit = true;
1576 MMRADIO_SEEK_THREAD_SIGNAL(radio);
1577 MMRADIO_SEEK_THREAD_UNLOCK(radio);
1578 pthread_join(radio->seek.thread, NULL);
1579 radio->seek.thread = 0;
1582 if (radio->scan.thread) {
1583 MMRADIO_SCAN_THREAD_LOCK(radio);
1584 radio->scan.thread_exit = true;
1585 MMRADIO_SCAN_THREAD_SIGNAL(radio);
1586 MMRADIO_SCAN_THREAD_UNLOCK(radio);
1587 pthread_join(radio->scan.thread, NULL);
1588 radio->scan.thread = 0;
1591 if (radio->msg.thread) {
1592 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1594 MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
1596 msg->msg_type = MM_RADIO_MSG_DESTROY;
1597 g_async_queue_push_front(radio->msg_queue, msg);
1598 pthread_join(radio->msg.thread, NULL);
1599 radio->msg.thread = 0;
1603 pthread_mutex_destroy(&radio->cmd_lock);
1604 pthread_mutex_destroy(&radio->volume_lock);
1605 pthread_mutex_destroy(&radio->hal_seek_mutex);
1607 pthread_mutex_destroy(&radio->seek.mutex);
1608 pthread_cond_destroy(&radio->seek.cond);
1610 pthread_mutex_destroy(&radio->scan.mutex);
1611 pthread_cond_destroy(&radio->scan.cond);
1613 MMRADIO_LOG_FLEAVE();
1616 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1618 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1620 MMRADIO_LOG_ERROR("NULL msg pointer");
1624 msg->msg_type = msg_type;
1625 msg->data = msg_data;
1627 MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
1628 g_async_queue_push(radio->msg_queue, msg);
1631 void __mmradio_msg_thread(mm_radio_t *radio)
1633 MMMessageParamType param = {0,};
1634 mm_radio_msg_t *msg = NULL;
1635 int exit_msg_thread = 0;
1637 /*we run a while one loop*/
1638 while (exit_msg_thread == 0) {
1639 msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
1641 MMRADIO_LOG_ERROR("poped message is NULL!");
1645 switch (msg->msg_type) {
1646 case MM_RADIO_MSG_DESTROY:
1647 MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
1648 mm_radio_msg_t *msg_pop = NULL;
1649 while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
1650 if (msg_pop != NULL) {
1651 MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
1652 g_slice_free(mm_radio_msg_t, msg_pop);
1655 exit_msg_thread = 1;
1657 case MM_RADIO_MSG_SCAN_INFO:
1658 MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
1659 param.radio_scan.frequency = (int) msg->data;
1660 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1662 case MM_RADIO_MSG_SCAN_STOPPED:
1663 MMRADIO_LOG_INFO("get scan stopped");
1664 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1666 case MM_RADIO_MSG_SCAN_FINISHED:
1667 MMRADIO_LOG_INFO("get scan finished");
1668 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1670 case MM_RADIO_MSG_SEEK_FINISHED:
1671 MMRADIO_LOG_INFO("get seek finish frequency: %d", msg->data);
1672 param.radio_scan.frequency = (int) msg->data;
1673 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1675 case MM_RADIO_MSG_STATE_INTERRUPTED:
1676 MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
1677 param.union_type = MM_MSG_UNION_STATE;
1678 param.state.previous = radio->old_state;
1679 param.state.current = radio->current_state;
1680 param.state.code = msg->data;
1681 MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, ¶m);
1684 MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1689 g_slice_free(mm_radio_msg_t, msg);
1693 MMRADIO_LOG_INFO("msg thread is finished");