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_threads(mm_radio_t *radio);
127 static void __mmradio_destroy_threads(mm_radio_t *radio);
128 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
129 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
131 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
132 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
133 static int __resource_release_cb(mm_resource_manager_h rm,
134 mm_resource_manager_res_h res, void *user_data);
135 static void __mmradio_msg_thread(mm_radio_t *radio);
136 static void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data);
138 typedef void (*thread_function)(mm_radio_t *);
139 thread_function __mmradio_thread_function[] = {
140 &__mmradio_msg_thread,
141 &__mmradio_seek_thread,
142 &__mmradio_scan_thread
145 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
147 int ret = MM_ERROR_NONE;
151 MMRADIO_LOG_FENTER();
153 MMRADIO_CHECK_INSTANCE(radio);
154 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
156 /* if needed, radio region must be updated.
157 * Otherwise, just applying settings to device without it.
160 count = ARRAY_SIZE(region_table);
162 /* TODO: if auto is supported...get the region info. here */
164 /* update radio region settings */
165 for (index = 0; index < count; index++) {
166 /* find the region from pre-defined table */
167 if (region_table[index].country == region) {
168 radio->region_setting.country = region_table[index].country;
169 radio->region_setting.deemphasis = region_table[index].deemphasis;
170 radio->region_setting.band_min = region_table[index].band_min;
171 radio->region_setting.band_max = region_table[index].band_max;
172 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
177 MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
178 radio->region_setting.country, radio->region_setting.deemphasis,
179 radio->region_setting.band_min, radio->region_setting.band_max);
181 MMRADIO_LOG_FLEAVE();
186 int _mmradio_create_radio(mm_radio_t *radio)
188 int ret = MM_ERROR_NONE;
190 MMRADIO_LOG_FENTER();
192 MMRADIO_CHECK_INSTANCE(radio);
193 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
195 /* set default value */
196 radio->freq = DEFAULT_FREQ;
197 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
198 radio->local_volume = 1.0;
199 radio->vstream = NULL;
200 radio->stream_info = NULL;
202 /* create msg queue for msg thread */
203 radio->msg_queue = g_async_queue_new();
204 if (!radio->msg_queue) {
205 MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
206 return MM_ERROR_RADIO_INTERNAL;
209 /* create mutex and thread */
210 ret = __mmradio_create_threads(radio);
212 MMRADIO_LOG_ERROR("failed to create threads");
216 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
218 /* initialize resource manager */
219 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
220 __resource_release_cb, radio, &radio->resource_manager);
222 MMRADIO_LOG_ERROR("failed to create resource manager");
223 ret = MM_ERROR_RADIO_INTERNAL;
227 ret = radio_hal_interface_init(&(radio->hal_inf));
229 MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
233 MMRADIO_LOG_FLEAVE();
235 return MM_ERROR_NONE;
238 mm_resource_manager_destroy(radio->resource_manager);
240 __mmradio_destroy_threads(radio);
242 if (radio->msg_queue)
243 g_async_queue_unref(radio->msg_queue);
247 int _mmradio_realize(mm_radio_t *radio)
249 int ret = MM_ERROR_NONE;
253 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
255 MMRADIO_LOG_FENTER();
257 MMRADIO_CHECK_INSTANCE(radio);
258 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
260 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
261 /* not initialized yet. set it with default region */
262 region = RADIO_DEFAULT_REGION;
265 /* already initialized by application */
266 region = radio->region_setting.country;
269 ret = _mmradio_apply_region(radio, region, update);
271 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
272 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
273 if (ret != MM_ERROR_NONE) {
274 MMRADIO_LOG_ERROR("failed to create stream information");
275 MMRADIO_LOG_FLEAVE();
278 ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
279 if (ret != MM_ERROR_NONE) {
280 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
281 MMRADIO_LOG_FLEAVE();
286 ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
287 if (ret != MM_ERROR_NONE) {
288 MMRADIO_LOG_WARNING("failed to get max volume");
289 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
291 radio->max_media_volume = max;
294 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
296 if (ret != MM_ERROR_NONE)
297 MMRADIO_LOG_WARNING("failed to get media volume");
299 MMRADIO_VOLUME_LOCK(radio);
300 radio->media_volume = volume;
301 MMRADIO_VOLUME_UNLOCK(radio);
303 ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
304 if (ret != MM_ERROR_NONE)
305 MMRADIO_LOG_WARNING("failed to register volume changed callback");
307 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
309 MMRADIO_LOG_FLEAVE();
311 return MM_ERROR_NONE;
314 int _mmradio_unrealize(mm_radio_t *radio)
316 int ret = MM_ERROR_NONE;
318 MMRADIO_LOG_FENTER();
320 MMRADIO_CHECK_INSTANCE(radio);
321 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
323 ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
324 if (ret != MM_ERROR_NONE)
325 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
327 /*Finish if there are scans*/
328 _mmradio_stop_scan(radio);
330 /*Stop radio if started*/
331 _mmradio_stop(radio);
333 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
334 if (radio->vstream) {
335 sound_manager_destroy_virtual_stream(radio->vstream);
336 radio->vstream = NULL;
338 if (radio->stream_info) {
339 sound_manager_destroy_stream_information(radio->stream_info);
340 radio->stream_info = NULL;
344 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
346 MMRADIO_LOG_FLEAVE();
351 int _mmradio_destroy(mm_radio_t *radio)
353 int ret = MM_ERROR_NONE;
354 MMRADIO_LOG_FENTER();
356 MMRADIO_CHECK_INSTANCE(radio);
357 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
359 _mmradio_unrealize(radio);
361 /* destroy mutex and thread */
362 __mmradio_destroy_threads(radio);
364 if (radio->msg_queue)
365 g_async_queue_unref(radio->msg_queue);
367 ret = radio_hal_interface_deinit(radio->hal_inf);
369 MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
373 ret = mm_resource_manager_destroy(radio->resource_manager);
375 MMRADIO_LOG_ERROR("failed to destroy resource manager");
376 return MM_ERROR_RADIO_INTERNAL;
379 MMRADIO_LOG_FLEAVE();
381 return MM_ERROR_NONE;
384 /* unit should be KHz */
385 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
387 int ret = MM_ERROR_NONE;
389 MMRADIO_LOG_FENTER();
391 MMRADIO_CHECK_INSTANCE(radio);
392 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
394 MMRADIO_LOG_INFO("Setting %d frequency", freq);
398 ret = radio_hal_set_frequency(radio->hal_inf, freq);
399 if (ret != MM_ERROR_NONE) {
400 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
401 MMRADIO_LOG_FLEAVE();
405 MMRADIO_LOG_FLEAVE();
411 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
413 int ret = MM_ERROR_NONE;
415 MMRADIO_LOG_FENTER();
417 MMRADIO_CHECK_INSTANCE(radio);
418 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
420 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
422 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
423 if (ret != MM_ERROR_NONE) {
424 MMRADIO_LOG_ERROR("failed to get radio hal frequency");
429 /* update freq in handle */
430 MMRADIO_LOG_INFO("Updating %d frequency", freq);
433 *pFreq = (int)radio->freq;
435 MMRADIO_LOG_FLEAVE();
440 int _mmradio_mute(mm_radio_t *radio)
442 int ret = MM_ERROR_NONE;
443 MMRADIO_LOG_FENTER();
445 MMRADIO_CHECK_INSTANCE(radio);
446 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
448 ret = radio_hal_mute(radio->hal_inf);
449 if (ret == MM_ERROR_NOT_SUPPORT_API) {
450 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
451 } else if (ret != MM_ERROR_NONE) {
452 MMRADIO_LOG_ERROR("failed to set radio hal mute");
453 MMRADIO_LOG_FLEAVE();
457 radio->is_muted = true;
458 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
459 MMRADIO_LOG_FLEAVE();
464 int _mmradio_unmute(mm_radio_t *radio)
466 int ret = MM_ERROR_NONE;
467 MMRADIO_LOG_FENTER();
469 MMRADIO_CHECK_INSTANCE(radio);
470 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
472 ret = radio_hal_unmute(radio->hal_inf);
473 if (ret == MM_ERROR_NOT_SUPPORT_API) {
474 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
475 } else if (ret != MM_ERROR_NONE) {
476 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
477 MMRADIO_LOG_FLEAVE();
481 radio->is_muted = false;
482 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
483 MMRADIO_LOG_FLEAVE();
488 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
490 MMRADIO_LOG_FENTER();
492 MMRADIO_CHECK_INSTANCE(radio);
494 radio->msg_cb = callback;
495 radio->msg_cb_param = user_param;
497 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
499 MMRADIO_LOG_FLEAVE();
501 return MM_ERROR_NONE;
504 int _mmradio_get_state(mm_radio_t *radio, int *pState)
508 MMRADIO_LOG_FENTER();
510 MMRADIO_CHECK_INSTANCE(radio);
511 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
513 state = __mmradio_get_state(radio);
517 MMRADIO_LOG_FLEAVE();
519 return MM_ERROR_NONE;
522 int _mmradio_start(mm_radio_t *radio)
524 int ret = MM_ERROR_NONE;
525 unsigned int volume = 0;
527 MMRADIO_LOG_FENTER();
529 MMRADIO_CHECK_INSTANCE(radio);
530 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
532 MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
534 if (!radio->is_ready) {
535 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
536 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
537 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
538 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
539 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
540 return MM_ERROR_RADIO_INTERNAL;
543 radio->interrupted_by_resource_conflict = FALSE;
544 ret = mm_resource_manager_commit(radio->resource_manager);
545 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
546 MMRADIO_LOG_ERROR("failed to commit resource manager");
547 mm_resource_manager_mark_for_release(radio->resource_manager,
548 radio->radio_resource);
549 radio->radio_resource = NULL;
553 ret = radio_hal_prepare(radio->hal_inf);
554 if (ret == MM_ERROR_NOT_SUPPORT_API) {
555 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
556 } else if (ret != MM_ERROR_NONE) {
557 MMRADIO_LOG_ERROR("failed to prepare radio hal");
561 ret = radio_hal_open(radio->hal_inf);
562 if (ret == MM_ERROR_NOT_SUPPORT_API) {
563 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
564 } else if (ret != MM_ERROR_NONE) {
565 MMRADIO_LOG_ERROR("failed to open radio hal");
568 radio->is_ready = true;
570 MMRADIO_LOG_DEBUG("radio prepared and opened");
573 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
574 if (ret != MM_ERROR_NONE)
575 MMRADIO_LOG_WARNING("failed to get media volume");
577 ret = __mmradio_set_media_volume(radio, volume);
578 if (ret != MM_ERROR_NONE) {
579 MMRADIO_LOG_ERROR("failed to set media volume");
583 ret = radio_hal_start(radio->hal_inf);
584 if (ret == MM_ERROR_NOT_SUPPORT_API) {
585 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
587 MMRADIO_LOG_ERROR("failed to start radio hal");
591 /* set stored frequency */
592 ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
594 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
598 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
599 ret = sound_manager_start_virtual_stream(radio->vstream);
601 MMRADIO_LOG_ERROR("failed to start sound manager virtual stream");
606 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
608 MMRADIO_LOG_FLEAVE();
610 return MM_ERROR_NONE;
613 radio_hal_close(radio->hal_inf);
615 radio_hal_unprepare(radio->hal_inf);
616 radio->is_ready = false;
620 int _mmradio_stop(mm_radio_t *radio)
622 int ret = MM_ERROR_NONE;
624 MMRADIO_LOG_FENTER();
626 MMRADIO_CHECK_INSTANCE(radio);
627 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
629 /*cancel if any seek*/
630 _mmradio_seek_cancel(radio);
631 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
632 ret = sound_manager_stop_virtual_stream(radio->vstream);
633 if (ret != MM_ERROR_NONE) {
634 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
639 ret = radio_hal_stop(radio->hal_inf);
640 if (ret == MM_ERROR_NOT_SUPPORT_API) {
641 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
643 MMRADIO_LOG_ERROR("failed to stop radio hal");
647 if (radio->is_ready) {
648 /* close radio device here !!!! */
649 ret = radio_hal_close(radio->hal_inf);
650 if (ret == MM_ERROR_NOT_SUPPORT_API) {
651 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
652 } else if (ret != MM_ERROR_NONE) {
653 MMRADIO_LOG_ERROR("failed to close radio hal");
657 ret = radio_hal_unprepare(radio->hal_inf);
658 if (ret == MM_ERROR_NOT_SUPPORT_API) {
659 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
660 } else if (ret != MM_ERROR_NONE) {
661 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
665 if (!radio->interrupted_by_resource_conflict && /* is being released */
666 radio->radio_resource != NULL) {
667 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
668 radio->radio_resource);
669 radio->radio_resource = NULL;
670 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
671 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
675 ret = mm_resource_manager_commit(radio->resource_manager);
676 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
677 MMRADIO_LOG_ERROR("resource manager commit fail");
680 radio->is_ready = false;
683 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
685 MMRADIO_LOG_FLEAVE();
687 return MM_ERROR_NONE;
690 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
692 int ret = MM_ERROR_NONE;
693 MMRadioThread_t *p_thread = NULL;
695 MMRADIO_LOG_FENTER();
697 MMRADIO_CHECK_INSTANCE(radio);
698 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
700 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
701 MMRADIO_CHECK_ARG(p_thread);
703 if (p_thread->is_running) {
704 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
705 return MM_ERROR_RADIO_INTERNAL;
708 radio->seek_unmute = false;
710 if (!radio->is_muted) {
711 ret = radio_hal_mute(radio->hal_inf);
712 if (ret == MM_ERROR_NOT_SUPPORT_API) {
713 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
715 MMRADIO_LOG_ERROR("failed to set radio hal mute");
718 radio->seek_unmute = true;
721 MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
722 radio->seek_direction = direction;
723 p_thread->is_running = true;
724 p_thread->stop = false;
726 MMRADIO_THREAD_SIGNAL(p_thread);
728 MMRADIO_LOG_FLEAVE();
730 return MM_ERROR_NONE;
733 void _mmradio_seek_cancel(mm_radio_t *radio)
735 MMRADIO_LOG_FENTER();
737 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
739 /* cancel any outstanding seek request */
740 radio->thread[MM_RADIO_THREAD_SEEK].stop = true;
742 MMRADIO_LOG_FLEAVE();
745 int _mmradio_start_scan(mm_radio_t *radio)
747 int ret = MM_ERROR_NONE;
748 MMRadioThread_t *p_thread = NULL;;
750 MMRADIO_LOG_FENTER();
752 MMRADIO_CHECK_INSTANCE(radio);
753 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
755 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
756 MMRADIO_CHECK_ARG(p_thread);
758 p_thread->stop = false;
760 if (!radio->is_ready) {
761 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
762 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
763 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
764 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
765 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
766 return MM_ERROR_RADIO_INTERNAL;
769 radio->interrupted_by_resource_conflict = FALSE;
770 ret = mm_resource_manager_commit(radio->resource_manager);
771 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
772 MMRADIO_LOG_ERROR("failed to commit resource manager");
773 mm_resource_manager_mark_for_release(radio->resource_manager,
774 radio->radio_resource);
775 radio->radio_resource = NULL;
779 ret = radio_hal_prepare(radio->hal_inf);
780 if (ret == MM_ERROR_NOT_SUPPORT_API) {
781 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
782 } else if (ret != MM_ERROR_NONE) {
783 MMRADIO_LOG_ERROR("failed to prepare radio hal");
787 ret = radio_hal_open(radio->hal_inf);
788 if (ret == MM_ERROR_NOT_SUPPORT_API) {
789 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
790 } else if (ret != MM_ERROR_NONE) {
791 MMRADIO_LOG_ERROR("failed to open radio hal");
792 MMRADIO_LOG_FLEAVE();
795 radio->is_ready = true;
797 MMRADIO_LOG_DEBUG("radio prepared and opened");
800 p_thread->is_running = true;
802 MMRADIO_THREAD_SIGNAL(p_thread);
804 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
806 MMRADIO_LOG_FLEAVE();
808 return MM_ERROR_NONE;
811 int _mmradio_stop_scan(mm_radio_t *radio)
813 MMRADIO_LOG_FENTER();
815 MMRADIO_CHECK_INSTANCE(radio);
816 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
818 radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
820 MMRADIO_LOG_FLEAVE();
822 return MM_ERROR_NONE;
825 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
827 int ret = MM_ERROR_NONE;
828 int32_t strength = 0;
829 MMRADIO_LOG_FENTER();
830 MMRADIO_CHECK_INSTANCE(radio);
832 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
834 /* just return stored frequency if radio device is not ready */
835 ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
836 if (ret == MM_ERROR_NOT_SUPPORT_API) {
837 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
838 } else if (ret != MM_ERROR_NONE) {
839 MMRADIO_LOG_ERROR("failed to get radio hal signal strength");
841 MMRADIO_LOG_FLEAVE();
844 *value = (int)strength;
845 MMRADIO_LOG_FLEAVE();
846 return MM_ERROR_NONE;
849 void __mmradio_scan_thread(mm_radio_t *radio)
851 int ret = MM_ERROR_NONE;
854 MMRadioThread_t *p_thread = NULL;
856 MMRADIO_LOG_FENTER();
857 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
859 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
860 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
862 MMRADIO_THREAD_LOCK(p_thread);
863 MMRADIO_THREAD_SIGNAL(p_thread);
864 MMRADIO_THREAD_UNLOCK(p_thread);
866 MMRADIO_THREAD_LOCK(p_thread);
868 while (!p_thread->thread_exit) {
869 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
870 MMRADIO_THREAD_WAIT(p_thread);
872 if (p_thread->thread_exit) {
873 MMRADIO_LOG_DEBUG("exiting scan thread");
877 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
878 ret = radio_hal_mute(radio->hal_inf);
879 if (ret == MM_ERROR_NOT_SUPPORT_API) {
880 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
881 } else if (ret != MM_ERROR_NONE) {
882 MMRADIO_LOG_ERROR("faied to set radio hal mute");
887 ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
888 if (ret != MM_ERROR_NONE)
891 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
892 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
895 while (!p_thread->stop) {
898 MMRADIO_LOG_DEBUG("scanning....");
900 if (p_thread->thread_exit) {
901 MMRADIO_LOG_DEBUG("exiting scan thread");
905 if (p_thread->stop) {
906 MMRADIO_LOG_INFO("scan was canceled");
910 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
911 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
912 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
913 if (ret != MM_ERROR_NONE) {
914 MMRADIO_LOG_ERROR("radio scanning error");
918 if (p_thread->thread_exit) {
919 MMRADIO_LOG_DEBUG("exiting scan thread");
923 if (p_thread->stop) {
924 MMRADIO_LOG_INFO("scan was canceled");
928 /* now we can get new frequency from radio device */
929 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
930 if (ret != MM_ERROR_NONE) {
931 MMRADIO_LOG_ERROR("failed to get current frequency");
933 if (freq <= prev_freq) {
934 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
938 prev_freq = (int)freq;
939 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", prev_freq);
941 /* drop if max freq is scanned */
942 if (prev_freq >= radio->region_setting.band_max) {
943 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", prev_freq);
947 if (p_thread->stop) {
948 /* doesn't need to post */
952 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
957 if (radio->old_state == MM_RADIO_STATE_READY) {
958 MMRADIO_LOG_DEBUG("old state is ready");
959 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
960 MMRADIO_LOG_DEBUG("old state is playing");
961 ret = radio_hal_unmute(radio->hal_inf);
962 if (ret == MM_ERROR_NOT_SUPPORT_API) {
963 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
964 } else if (ret != MM_ERROR_NONE) {
965 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
968 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
969 if (ret == MM_ERROR_NOT_SUPPORT_API) {
970 MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
971 } else if (ret != MM_ERROR_NONE) {
972 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
978 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
979 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
981 /* close radio device here !!!! */
982 if (radio->is_ready) {
983 ret = radio_hal_close(radio->hal_inf);
984 if (ret == MM_ERROR_NOT_SUPPORT_API)
985 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
986 else if (ret != MM_ERROR_NONE)
987 MMRADIO_LOG_ERROR("failed to close radio hal");
989 ret = radio_hal_unprepare(radio->hal_inf);
990 if (ret == MM_ERROR_NOT_SUPPORT_API)
991 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
992 else if (ret != MM_ERROR_NONE)
993 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
995 if (!radio->interrupted_by_resource_conflict && /* is being released */
996 radio->radio_resource != NULL) {
997 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
998 radio->radio_resource);
999 radio->radio_resource = NULL;
1000 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
1001 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
1004 ret = mm_resource_manager_commit(radio->resource_manager);
1005 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
1006 MMRADIO_LOG_ERROR("resource manager commit fail");
1007 radio->is_ready = false;
1009 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
1012 if (!p_thread->stop)
1013 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
1015 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
1017 p_thread->is_running = false;
1022 p_thread->is_running = false;
1024 MMRADIO_THREAD_UNLOCK(p_thread);
1026 MMRADIO_LOG_FLEAVE();
1032 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
1034 MMRADIO_LOG_FENTER();
1036 MMRADIO_CHECK_INSTANCE(radio);
1038 if (freq >= radio->region_setting.band_max
1039 || freq <= radio->region_setting.band_min)
1042 MMRADIO_LOG_FLEAVE();
1047 void __mmradio_seek_thread(mm_radio_t *radio)
1049 int ret = MM_ERROR_NONE;
1051 MMRadioThread_t *p_thread = NULL;
1053 MMRADIO_LOG_FENTER();
1054 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1056 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
1057 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1059 MMRADIO_THREAD_LOCK(p_thread);
1060 MMRADIO_THREAD_SIGNAL(p_thread);
1061 MMRADIO_THREAD_UNLOCK(p_thread);
1063 MMRADIO_THREAD_LOCK(p_thread);
1065 while (!p_thread->thread_exit) {
1066 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
1067 MMRADIO_THREAD_WAIT(p_thread);
1069 if (p_thread->thread_exit) {
1070 MMRADIO_LOG_DEBUG("exiting seek thread");
1074 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1075 MMRADIO_LOG_DEBUG("seeking....");
1077 if (p_thread->stop) {
1078 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1082 MMRADIO_LOG_DEBUG("try to seek ");
1083 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
1084 MMRADIO_LOG_DEBUG("seek start");
1085 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1086 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
1088 MMRADIO_LOG_ERROR("failed to seek radio hal");
1092 if (p_thread->thread_exit) {
1093 MMRADIO_LOG_DEBUG("exiting seek thread");
1097 if (p_thread->stop) {
1098 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1102 /* now we can get new frequency from radio device */
1103 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1105 MMRADIO_LOG_ERROR("failed to get current frequency");
1109 MMRADIO_LOG_DEBUG("found frequency");
1111 /* if same freq is found, ignore it and search next one. */
1112 if (freq == radio->prev_seek_freq) {
1113 MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1117 /* check if it's limit freq or not */
1118 if (__is_tunable_frequency(radio, freq)) {
1119 /* now tune to new frequency */
1120 ret = radio_hal_set_frequency(radio->hal_inf, freq);
1122 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1125 radio->freq = (int)freq;
1126 MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1129 if (radio->seek_unmute) {
1130 /* now turn on radio
1131 * In the case of limit freq, tuner should be unmuted.
1132 * Otherwise, sound can't output even though application set new frequency.
1134 ret = radio_hal_unmute(radio->hal_inf);
1136 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1139 radio->seek_unmute = false;
1142 radio->prev_seek_freq = (int)freq;
1143 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
1144 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
1145 p_thread->is_running = false;
1149 if (radio->seek_unmute) {
1150 /* now turn on radio
1151 * In the case of limit freq, tuner should be unmuted.
1152 * Otherwise, sound can't output even though application set new frequency.
1154 ret = radio_hal_unmute(radio->hal_inf);
1156 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1157 radio->seek_unmute = false;
1159 /* freq -1 means it's failed to seek */
1160 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
1161 p_thread->is_running = false;
1165 p_thread->is_running = false;
1166 MMRADIO_THREAD_UNLOCK(p_thread);
1167 MMRADIO_LOG_FLEAVE();
1171 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1173 MMRADIO_CHECK_INSTANCE(radio);
1175 MMRADIO_LOG_FENTER();
1177 if (!radio->msg_cb) {
1178 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1182 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1184 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1186 MMRADIO_LOG_FLEAVE();
1191 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1193 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1195 MMRADIO_LOG_FENTER();
1197 MMRADIO_CHECK_INSTANCE(radio);
1199 radio_state = __mmradio_get_state(radio);
1201 MMRADIO_LOG_INFO("incomming command : %d current state : %d", command, radio_state);
1204 case MMRADIO_COMMAND_CREATE:
1206 if (radio_state != 0)
1211 case MMRADIO_COMMAND_REALIZE:
1213 if (radio_state == MM_RADIO_STATE_READY ||
1214 radio_state == MM_RADIO_STATE_PLAYING ||
1215 radio_state == MM_RADIO_STATE_SCANNING)
1218 if (radio_state == 0)
1223 case MMRADIO_COMMAND_UNREALIZE:
1225 if (radio_state == MM_RADIO_STATE_NULL)
1228 /* we can call unrealize at any higher state */
1232 case MMRADIO_COMMAND_START:
1234 if (radio_state == MM_RADIO_STATE_PLAYING)
1237 if (radio_state != MM_RADIO_STATE_READY)
1242 case MMRADIO_COMMAND_STOP:
1244 if (radio_state == MM_RADIO_STATE_READY)
1247 if (radio_state != MM_RADIO_STATE_PLAYING)
1252 case MMRADIO_COMMAND_START_SCAN:
1254 if (radio_state == MM_RADIO_STATE_SCANNING)
1257 if (radio_state == MM_RADIO_STATE_NULL)
1262 case MMRADIO_COMMAND_STOP_SCAN:
1264 if (radio_state == MM_RADIO_STATE_READY)
1267 if (radio_state != MM_RADIO_STATE_SCANNING)
1272 case MMRADIO_COMMAND_DESTROY:
1273 case MMRADIO_COMMAND_MUTE:
1274 case MMRADIO_COMMAND_UNMUTE:
1275 case MMRADIO_COMMAND_SET_FREQ:
1276 case MMRADIO_COMMAND_GET_FREQ:
1277 case MMRADIO_COMMAND_SET_REGION:
1278 case MMRADIO_COMMAND_SET_VOLUME:
1279 case MMRADIO_COMMAND_GET_VOLUME:
1281 /* we can do it at any state */
1285 case MMRADIO_COMMAND_SEEK:
1287 if (radio_state != MM_RADIO_STATE_PLAYING)
1292 case MMRADIO_COMMAND_GET_REGION:
1294 if (radio_state == MM_RADIO_STATE_NULL)
1300 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1304 MMRADIO_LOG_DEBUG("status OK");
1306 radio->cmd = command;
1308 MMRADIO_LOG_FLEAVE();
1310 return MM_ERROR_NONE;
1313 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1314 MMRADIO_LOG_FLEAVE();
1315 return MM_ERROR_RADIO_INVALID_STATE;
1318 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1319 MMRADIO_LOG_FLEAVE();
1320 return MM_ERROR_RADIO_NO_OP;
1324 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1326 MMMessageParamType msg = { 0, };
1327 int msg_type = MM_MESSAGE_UNKNOWN;
1329 MMRADIO_LOG_FENTER();
1332 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1336 if (radio->current_state == new_state && radio->pending_state == 0) {
1337 MMRADIO_LOG_WARNING("we are in same state");
1342 radio->old_state = radio->current_state;
1343 radio->current_state = new_state;
1345 /* fill message param */
1346 msg.union_type = MM_MSG_UNION_STATE;
1347 msg.state.previous = radio->old_state;
1348 msg.state.current = radio->current_state;
1350 if (radio->interrupted_by_resource_conflict) {
1351 __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
1352 MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
1354 msg_type = MM_MESSAGE_STATE_CHANGED;
1355 MMRADIO_POST_MSG(radio, msg_type, &msg);
1358 MMRADIO_LOG_FLEAVE();
1363 static int __mmradio_get_state(mm_radio_t *radio)
1365 MMRADIO_CHECK_INSTANCE(radio);
1367 MMRADIO_LOG_INFO("radio state : current : [%d] old : [%d] pending : [%d]",
1368 radio->current_state, radio->old_state, radio->pending_state);
1370 return radio->current_state;
1373 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1375 mm_radio_t *radio = (mm_radio_t *)user_data;
1376 int ret = MM_ERROR_NONE;
1377 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1378 if (type == VOLUME_TYPE_MEDIA) {
1379 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1380 ret = __mmradio_set_media_volume(radio, volume);
1381 if (ret != MM_ERROR_NONE)
1382 MMRADIO_LOG_ERROR("failed to set media volume");
1387 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1389 MMRADIO_LOG_FENTER();
1390 MMRADIO_CHECK_INSTANCE(radio);
1391 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1393 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1395 *type = radio->region_setting.country;
1397 MMRADIO_LOG_FLEAVE();
1398 return MM_ERROR_NONE;
1401 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1403 MMRADIO_LOG_FENTER();
1404 MMRADIO_CHECK_INSTANCE(radio);
1405 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1407 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1409 *min_freq = radio->region_setting.band_min;
1410 *max_freq = radio->region_setting.band_max;
1412 MMRADIO_LOG_FLEAVE();
1413 return MM_ERROR_NONE;
1416 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1418 MMRADIO_LOG_FENTER();
1419 MMRADIO_CHECK_INSTANCE(radio);
1420 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1422 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1424 *ch_spacing = radio->region_setting.channel_spacing;
1426 MMRADIO_LOG_FLEAVE();
1427 return MM_ERROR_NONE;
1430 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1432 int ret = MM_ERROR_NONE;
1434 MMRADIO_LOG_FENTER();
1436 MMRADIO_CHECK_INSTANCE(radio);
1437 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1439 MMRADIO_LOG_INFO("Setting %f volume", volume);
1441 MMRADIO_VOLUME_LOCK(radio);
1442 radio->local_volume = volume;
1443 MMRADIO_VOLUME_UNLOCK(radio);
1445 ret = radio_hal_set_volume(radio->hal_inf, volume);
1446 if (ret != MM_ERROR_NONE)
1447 MMRADIO_LOG_ERROR("failed to set radio hal volume");
1449 MMRADIO_LOG_FLEAVE();
1454 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1456 int ret = MM_ERROR_NONE;
1458 MMRADIO_LOG_FENTER();
1460 MMRADIO_CHECK_INSTANCE(radio);
1461 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1463 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1465 ret = radio_hal_get_volume(radio->hal_inf, &volume);
1466 if (ret != MM_ERROR_NONE) {
1467 MMRADIO_LOG_ERROR("failed to get radio hal volume");
1472 MMRADIO_VOLUME_LOCK(radio);
1473 radio->local_volume = volume;
1474 *pVolume = (float)radio->local_volume;
1475 MMRADIO_VOLUME_UNLOCK(radio);
1477 MMRADIO_LOG_FLEAVE();
1482 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1484 int ret = MM_ERROR_NONE;
1486 MMRADIO_LOG_FENTER();
1488 MMRADIO_CHECK_INSTANCE(radio);
1489 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1491 MMRADIO_LOG_INFO("Setting %d volume", level);
1493 MMRADIO_VOLUME_LOCK(radio);
1494 radio->media_volume = level;
1495 MMRADIO_VOLUME_UNLOCK(radio);
1497 ret = radio_hal_set_media_volume(radio->hal_inf, level);
1498 if (ret != MM_ERROR_NONE)
1499 MMRADIO_LOG_ERROR("failed to set radio hal media volume");
1501 MMRADIO_LOG_FLEAVE();
1506 static int __resource_release_cb(mm_resource_manager_h rm,
1507 mm_resource_manager_res_h res, void *user_data)
1509 mm_radio_t *radio = NULL;
1511 MMRADIO_LOG_FENTER();
1514 MMRADIO_LOG_ERROR("user_data is null");
1518 radio = (mm_radio_t *)user_data;
1519 radio->radio_resource = NULL;
1521 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1523 radio->interrupted_by_resource_conflict = TRUE;
1525 MMRADIO_CMD_LOCK(radio);
1526 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1527 MMRADIO_LOG_ERROR("failed to stop radio");
1528 MMRADIO_CMD_UNLOCK(radio);
1530 MMRADIO_LOG_FLEAVE();
1535 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1537 MMRadioThread_t *p_thread = NULL;
1539 MMRADIO_LOG_FENTER();
1541 MMRADIO_CHECK_INSTANCE(radio);
1543 if (type >= MM_RADIO_THREAD_NUM) {
1544 MMRADIO_LOG_WARNING("wrong argument thread type");
1545 return MM_ERROR_RADIO_INTERNAL;
1548 p_thread = &radio->thread[type];
1549 MMRADIO_CHECK_ARG(p_thread);
1551 MMRADIO_INIT_MUTEX(p_thread->mutex);
1552 MMRADIO_INIT_COND(p_thread->cond);
1554 MMRADIO_THREAD_LOCK(p_thread);
1555 p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
1556 (void *)__mmradio_thread_function[type], (void *)radio);
1557 if (p_thread->thread_id) {
1558 MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
1559 MMRADIO_THREAD_UNLOCK(p_thread);
1560 return MM_ERROR_RADIO_INTERNAL;
1563 MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
1564 MMRADIO_THREAD_WAIT(p_thread);
1565 MMRADIO_LOG_DEBUG("[%d] thread started", type);
1566 MMRADIO_THREAD_UNLOCK(p_thread);
1568 return MM_ERROR_NONE;
1571 pthread_mutex_destroy(&p_thread->mutex);
1572 pthread_cond_destroy(&p_thread->cond);
1573 return MM_ERROR_RADIO_INTERNAL;
1577 static int __mmradio_create_threads(mm_radio_t *radio)
1579 int ret = MM_ERROR_NONE;
1582 MMRADIO_LOG_FENTER();
1584 MMRADIO_CHECK_INSTANCE(radio);
1586 MMRADIO_INIT_MUTEX(radio->cmd_lock);
1587 MMRADIO_INIT_MUTEX(radio->volume_lock);
1588 MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
1590 for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
1591 ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
1593 MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
1594 while (--type >= (int)MM_RADIO_THREAD_MSG)
1595 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1600 MMRADIO_LOG_FLEAVE();
1604 pthread_mutex_destroy(&radio->cmd_lock);
1605 pthread_mutex_destroy(&radio->volume_lock);
1606 pthread_mutex_destroy(&radio->hal_seek_mutex);
1608 MMRADIO_LOG_FLEAVE();
1609 return MM_ERROR_RADIO_INTERNAL;
1612 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1614 MMRadioThread_t *p_thread = NULL;
1615 mm_radio_msg_t *msg = NULL;
1616 MMRADIO_LOG_FENTER();
1618 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1620 if (type >= MM_RADIO_THREAD_NUM) {
1621 MMRADIO_LOG_WARNING("wrong argument thread type");
1625 p_thread = &radio->thread[type];
1626 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1628 if (p_thread->thread) {
1630 case MM_RADIO_THREAD_MSG:
1631 msg = g_slice_new0(mm_radio_msg_t);
1633 MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
1635 msg->msg_type = MM_RADIO_MSG_DESTROY;
1636 g_async_queue_push_front(radio->msg_queue, msg);
1637 pthread_join(p_thread->thread, NULL);
1638 p_thread->thread = 0;
1641 case MM_RADIO_THREAD_SEEK:
1642 case MM_RADIO_THREAD_SCAN:
1643 MMRADIO_THREAD_LOCK(p_thread);
1644 p_thread->thread_exit = true;
1645 MMRADIO_THREAD_SIGNAL(p_thread);
1646 MMRADIO_THREAD_UNLOCK(p_thread);
1647 pthread_join(p_thread->thread, NULL);
1648 p_thread->thread = 0;
1651 MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
1655 MMRADIO_LOG_WARNING("(%d)thread is zero", type);
1658 pthread_mutex_destroy(&p_thread->mutex);
1659 pthread_cond_destroy(&p_thread->cond);
1661 MMRADIO_LOG_FLEAVE();
1664 static void __mmradio_destroy_threads(mm_radio_t *radio)
1666 int type = (int)MM_RADIO_THREAD_NUM;
1667 MMRADIO_LOG_FENTER();
1669 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1672 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1674 pthread_mutex_destroy(&radio->cmd_lock);
1675 pthread_mutex_destroy(&radio->volume_lock);
1676 pthread_mutex_destroy(&radio->hal_seek_mutex);
1678 MMRADIO_LOG_FLEAVE();
1681 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1683 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1685 MMRADIO_LOG_ERROR("NULL msg pointer");
1689 msg->msg_type = msg_type;
1690 msg->data = msg_data;
1692 MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
1693 g_async_queue_push(radio->msg_queue, msg);
1696 void __mmradio_msg_thread(mm_radio_t *radio)
1699 mm_radio_msg_t *msg = NULL;
1700 MMRadioThread_t *p_thread = NULL;
1702 MMRADIO_LOG_FENTER();
1703 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1705 p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
1706 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1708 p_thread->thread_exit = false;
1711 MMRADIO_THREAD_LOCK(p_thread);
1712 MMRADIO_THREAD_SIGNAL(p_thread);
1713 MMRADIO_THREAD_UNLOCK(p_thread);
1715 /* we run a while one loop*/
1716 while (!p_thread->thread_exit) {
1717 msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
1719 MMRADIO_LOG_ERROR("poped message is NULL!");
1723 MMMessageParamType param = {0,};
1725 switch (msg->msg_type) {
1726 case MM_RADIO_MSG_DESTROY:
1727 MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
1728 mm_radio_msg_t *msg_pop = NULL;
1729 while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
1730 if (msg_pop != NULL) {
1731 MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
1732 g_slice_free(mm_radio_msg_t, msg_pop);
1735 p_thread->thread_exit = true;
1737 case MM_RADIO_MSG_SCAN_INFO:
1738 MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
1739 param.radio_scan.frequency = (int) msg->data;
1740 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1742 case MM_RADIO_MSG_SCAN_STOPPED:
1743 MMRADIO_LOG_INFO("get scan stopped");
1744 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1746 case MM_RADIO_MSG_SCAN_FINISHED:
1747 MMRADIO_LOG_INFO("get scan finished");
1748 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1750 case MM_RADIO_MSG_SEEK_FINISHED:
1751 MMRADIO_LOG_INFO("get seek finish frequency: %d", msg->data);
1752 param.radio_scan.frequency = (int) msg->data;
1753 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1755 case MM_RADIO_MSG_STATE_INTERRUPTED:
1756 MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
1757 param.union_type = MM_MSG_UNION_STATE;
1758 param.state.previous = radio->old_state;
1759 param.state.current = radio->current_state;
1760 param.state.code = msg->data;
1761 MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, ¶m);
1764 MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1769 g_slice_free(mm_radio_msg_t, msg);
1773 MMRADIO_LOG_INFO("msg thread is finished");
1774 MMRADIO_LOG_FLEAVE();