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;
200 /* create msg queue for msg thread */
201 radio->msg_queue = g_async_queue_new();
202 if (!radio->msg_queue) {
203 MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
204 return MM_ERROR_RADIO_INTERNAL;
207 /* create mutex and thread */
208 ret = __mmradio_create_threads(radio);
210 MMRADIO_LOG_ERROR("failed to create threads");
214 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
216 /* initialize resource manager */
217 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
218 __resource_release_cb, radio, &radio->resource_manager);
220 MMRADIO_LOG_ERROR("failed to create resource manager");
221 ret = MM_ERROR_RADIO_INTERNAL;
225 ret = radio_hal_interface_init(&(radio->hal_inf));
227 MMRADIO_LOG_ERROR("failed to init mmradio hal interface");
231 MMRADIO_LOG_FLEAVE();
233 return MM_ERROR_NONE;
236 mm_resource_manager_destroy(radio->resource_manager);
238 __mmradio_destroy_threads(radio);
240 if (radio->msg_queue)
241 g_async_queue_unref(radio->msg_queue);
245 int _mmradio_realize(mm_radio_t *radio)
247 int ret = MM_ERROR_NONE;
251 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
253 MMRADIO_LOG_FENTER();
255 MMRADIO_CHECK_INSTANCE(radio);
256 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
258 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
259 /* not initialized yet. set it with default region */
260 region = RADIO_DEFAULT_REGION;
263 /* already initialized by application */
264 region = radio->region_setting.country;
267 ret = _mmradio_apply_region(radio, region, update);
269 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
270 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
271 if (ret != MM_ERROR_NONE) {
272 MMRADIO_LOG_ERROR("failed to create stream information");
273 MMRADIO_LOG_FLEAVE();
276 ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
277 if (ret != MM_ERROR_NONE) {
278 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
279 MMRADIO_LOG_FLEAVE();
284 ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
285 if (ret != MM_ERROR_NONE) {
286 MMRADIO_LOG_WARNING("failed to get max volume");
287 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
289 radio->max_media_volume = max;
292 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
294 if (ret != MM_ERROR_NONE)
295 MMRADIO_LOG_WARNING("failed to get media volume");
297 MMRADIO_VOLUME_LOCK(radio);
298 radio->media_volume = volume;
299 MMRADIO_VOLUME_UNLOCK(radio);
301 ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
302 if (ret != MM_ERROR_NONE)
303 MMRADIO_LOG_WARNING("failed to register volume changed callback");
305 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
307 MMRADIO_LOG_FLEAVE();
309 return MM_ERROR_NONE;
312 int _mmradio_unrealize(mm_radio_t *radio)
314 int ret = MM_ERROR_NONE;
316 MMRADIO_LOG_FENTER();
318 MMRADIO_CHECK_INSTANCE(radio);
319 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
321 ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
322 if (ret != MM_ERROR_NONE)
323 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
325 /*Finish if there are scans*/
326 _mmradio_stop_scan(radio);
328 /*Stop radio if started*/
329 _mmradio_stop(radio);
331 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
332 sound_manager_destroy_virtual_stream(radio->vstream);
333 sound_manager_destroy_stream_information(radio->stream_info);
336 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
338 MMRADIO_LOG_FLEAVE();
343 int _mmradio_destroy(mm_radio_t *radio)
345 int ret = MM_ERROR_NONE;
346 MMRADIO_LOG_FENTER();
348 MMRADIO_CHECK_INSTANCE(radio);
349 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
351 _mmradio_unrealize(radio);
353 /* destroy mutex and thread */
354 __mmradio_destroy_threads(radio);
356 if (radio->msg_queue)
357 g_async_queue_unref(radio->msg_queue);
359 ret = radio_hal_interface_deinit(radio->hal_inf);
361 MMRADIO_LOG_ERROR("failed to deinitialize radio hal interface");
365 ret = mm_resource_manager_destroy(radio->resource_manager);
367 MMRADIO_LOG_ERROR("failed to destroy resource manager");
368 return MM_ERROR_RADIO_INTERNAL;
371 MMRADIO_LOG_FLEAVE();
373 return MM_ERROR_NONE;
376 /* unit should be KHz */
377 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
379 int ret = MM_ERROR_NONE;
381 MMRADIO_LOG_FENTER();
383 MMRADIO_CHECK_INSTANCE(radio);
384 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
386 MMRADIO_LOG_INFO("Setting %d frequency", freq);
390 ret = radio_hal_set_frequency(radio->hal_inf, freq);
391 if (ret != MM_ERROR_NONE) {
392 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
393 MMRADIO_LOG_FLEAVE();
397 MMRADIO_LOG_FLEAVE();
403 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
405 int ret = MM_ERROR_NONE;
407 MMRADIO_LOG_FENTER();
409 MMRADIO_CHECK_INSTANCE(radio);
410 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
412 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
414 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
415 if (ret != MM_ERROR_NONE) {
416 MMRADIO_LOG_ERROR("failed to get radio hal frequency");
421 /* update freq in handle */
422 MMRADIO_LOG_INFO("Updating %d frequency", freq);
425 *pFreq = (int)radio->freq;
427 MMRADIO_LOG_FLEAVE();
432 int _mmradio_mute(mm_radio_t *radio)
434 int ret = MM_ERROR_NONE;
435 MMRADIO_LOG_FENTER();
437 MMRADIO_CHECK_INSTANCE(radio);
438 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
440 ret = radio_hal_mute(radio->hal_inf);
441 if (ret == MM_ERROR_NOT_SUPPORT_API) {
442 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
443 } else if (ret != MM_ERROR_NONE) {
444 MMRADIO_LOG_ERROR("failed to set radio hal mute");
445 MMRADIO_LOG_FLEAVE();
449 radio->is_muted = true;
450 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
451 MMRADIO_LOG_FLEAVE();
456 int _mmradio_unmute(mm_radio_t *radio)
458 int ret = MM_ERROR_NONE;
459 MMRADIO_LOG_FENTER();
461 MMRADIO_CHECK_INSTANCE(radio);
462 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
464 ret = radio_hal_unmute(radio->hal_inf);
465 if (ret == MM_ERROR_NOT_SUPPORT_API) {
466 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
467 } else if (ret != MM_ERROR_NONE) {
468 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
469 MMRADIO_LOG_FLEAVE();
473 radio->is_muted = false;
474 MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
475 MMRADIO_LOG_FLEAVE();
480 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
482 MMRADIO_LOG_FENTER();
484 MMRADIO_CHECK_INSTANCE(radio);
486 radio->msg_cb = callback;
487 radio->msg_cb_param = user_param;
489 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
491 MMRADIO_LOG_FLEAVE();
493 return MM_ERROR_NONE;
496 int _mmradio_get_state(mm_radio_t *radio, int *pState)
500 MMRADIO_LOG_FENTER();
502 MMRADIO_CHECK_INSTANCE(radio);
503 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
505 state = __mmradio_get_state(radio);
509 MMRADIO_LOG_FLEAVE();
511 return MM_ERROR_NONE;
514 int _mmradio_start(mm_radio_t *radio)
516 int ret = MM_ERROR_NONE;
517 unsigned int volume = 0;
519 MMRADIO_LOG_FENTER();
521 MMRADIO_CHECK_INSTANCE(radio);
522 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
524 MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
526 if (!radio->is_ready) {
527 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
528 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
529 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
530 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
531 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
532 return MM_ERROR_RADIO_INTERNAL;
535 radio->interrupted_by_resource_conflict = FALSE;
536 ret = mm_resource_manager_commit(radio->resource_manager);
537 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
538 MMRADIO_LOG_ERROR("failed to commit resource manager");
539 mm_resource_manager_mark_for_release(radio->resource_manager,
540 radio->radio_resource);
541 radio->radio_resource = NULL;
545 ret = radio_hal_prepare(radio->hal_inf);
546 if (ret == MM_ERROR_NOT_SUPPORT_API) {
547 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
548 } else if (ret != MM_ERROR_NONE) {
549 MMRADIO_LOG_ERROR("failed to prepare radio hal");
553 ret = radio_hal_open(radio->hal_inf);
554 if (ret == MM_ERROR_NOT_SUPPORT_API) {
555 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
556 } else if (ret != MM_ERROR_NONE) {
557 MMRADIO_LOG_ERROR("failed to open radio hal");
560 radio->is_ready = true;
562 MMRADIO_LOG_DEBUG("radio prepared and opened");
565 ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
566 if (ret != MM_ERROR_NONE)
567 MMRADIO_LOG_WARNING("failed to get media volume");
569 ret = __mmradio_set_media_volume(radio, volume);
570 if (ret != MM_ERROR_NONE) {
571 MMRADIO_LOG_ERROR("failed to set media volume");
575 ret = radio_hal_start(radio->hal_inf);
576 if (ret == MM_ERROR_NOT_SUPPORT_API) {
577 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
579 MMRADIO_LOG_ERROR("failed to start radio hal");
583 /* set stored frequency */
584 ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
586 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
590 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
591 ret = sound_manager_start_virtual_stream(radio->vstream);
593 MMRADIO_LOG_ERROR("failed to start sound manager virtual stream");
598 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
600 MMRADIO_LOG_FLEAVE();
602 return MM_ERROR_NONE;
605 radio_hal_close(radio->hal_inf);
607 radio_hal_unprepare(radio->hal_inf);
608 radio->is_ready = false;
612 int _mmradio_stop(mm_radio_t *radio)
614 int ret = MM_ERROR_NONE;
616 MMRADIO_LOG_FENTER();
618 MMRADIO_CHECK_INSTANCE(radio);
619 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
621 /*cancel if any seek*/
622 _mmradio_seek_cancel(radio);
623 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
624 ret = sound_manager_stop_virtual_stream(radio->vstream);
625 if (ret != MM_ERROR_NONE) {
626 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
631 ret = radio_hal_stop(radio->hal_inf);
632 if (ret == MM_ERROR_NOT_SUPPORT_API) {
633 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
635 MMRADIO_LOG_ERROR("failed to stop radio hal");
639 if (radio->is_ready) {
640 /* close radio device here !!!! */
641 ret = radio_hal_close(radio->hal_inf);
642 if (ret == MM_ERROR_NOT_SUPPORT_API) {
643 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
644 } else if (ret != MM_ERROR_NONE) {
645 MMRADIO_LOG_ERROR("failed to close radio hal");
649 ret = radio_hal_unprepare(radio->hal_inf);
650 if (ret == MM_ERROR_NOT_SUPPORT_API) {
651 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
652 } else if (ret != MM_ERROR_NONE) {
653 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
657 if (!radio->interrupted_by_resource_conflict && /* is being released */
658 radio->radio_resource != NULL) {
659 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
660 radio->radio_resource);
661 radio->radio_resource = NULL;
662 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
663 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
667 ret = mm_resource_manager_commit(radio->resource_manager);
668 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
669 MMRADIO_LOG_ERROR("resource manager commit fail");
672 radio->is_ready = false;
675 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
677 MMRADIO_LOG_FLEAVE();
679 return MM_ERROR_NONE;
682 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
684 int ret = MM_ERROR_NONE;
685 MMRadioThread_t *p_thread = NULL;
687 MMRADIO_LOG_FENTER();
689 MMRADIO_CHECK_INSTANCE(radio);
690 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
692 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
693 MMRADIO_CHECK_ARG(p_thread);
695 if (p_thread->is_running) {
696 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
697 return MM_ERROR_RADIO_INTERNAL;
700 radio->seek_unmute = false;
702 if (!radio->is_muted) {
703 ret = radio_hal_mute(radio->hal_inf);
704 if (ret == MM_ERROR_NOT_SUPPORT_API) {
705 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
707 MMRADIO_LOG_ERROR("failed to set radio hal mute");
710 radio->seek_unmute = true;
713 MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
714 radio->seek_direction = direction;
715 p_thread->is_running = true;
716 p_thread->stop = false;
718 MMRADIO_THREAD_SIGNAL(p_thread);
720 MMRADIO_LOG_FLEAVE();
722 return MM_ERROR_NONE;
725 void _mmradio_seek_cancel(mm_radio_t *radio)
727 MMRADIO_LOG_FENTER();
729 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
731 /* cancel any outstanding seek request */
732 radio->thread[MM_RADIO_THREAD_SEEK].stop = true;
734 MMRADIO_LOG_FLEAVE();
737 int _mmradio_start_scan(mm_radio_t *radio)
739 int ret = MM_ERROR_NONE;
740 MMRadioThread_t *p_thread = NULL;;
742 MMRADIO_LOG_FENTER();
744 MMRADIO_CHECK_INSTANCE(radio);
745 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
747 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
748 MMRADIO_CHECK_ARG(p_thread);
750 p_thread->stop = false;
752 if (!radio->is_ready) {
753 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
754 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
755 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
756 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
757 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
758 return MM_ERROR_RADIO_INTERNAL;
761 radio->interrupted_by_resource_conflict = FALSE;
762 ret = mm_resource_manager_commit(radio->resource_manager);
763 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
764 MMRADIO_LOG_ERROR("failed to commit resource manager");
765 mm_resource_manager_mark_for_release(radio->resource_manager,
766 radio->radio_resource);
767 radio->radio_resource = NULL;
771 ret = radio_hal_prepare(radio->hal_inf);
772 if (ret == MM_ERROR_NOT_SUPPORT_API) {
773 MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
774 } else if (ret != MM_ERROR_NONE) {
775 MMRADIO_LOG_ERROR("failed to prepare radio hal");
779 ret = radio_hal_open(radio->hal_inf);
780 if (ret == MM_ERROR_NOT_SUPPORT_API) {
781 MMRADIO_LOG_WARNING("radio_hal_open is not supported");
782 } else if (ret != MM_ERROR_NONE) {
783 MMRADIO_LOG_ERROR("failed to open radio hal");
784 MMRADIO_LOG_FLEAVE();
787 radio->is_ready = true;
789 MMRADIO_LOG_DEBUG("radio prepared and opened");
792 p_thread->is_running = true;
794 MMRADIO_THREAD_SIGNAL(p_thread);
796 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
798 MMRADIO_LOG_FLEAVE();
800 return MM_ERROR_NONE;
803 int _mmradio_stop_scan(mm_radio_t *radio)
805 MMRADIO_LOG_FENTER();
807 MMRADIO_CHECK_INSTANCE(radio);
808 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
810 radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
812 MMRADIO_LOG_FLEAVE();
814 return MM_ERROR_NONE;
817 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
819 int ret = MM_ERROR_NONE;
820 int32_t strength = 0;
821 MMRADIO_LOG_FENTER();
822 MMRADIO_CHECK_INSTANCE(radio);
824 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
826 /* just return stored frequency if radio device is not ready */
827 ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
828 if (ret == MM_ERROR_NOT_SUPPORT_API) {
829 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
830 } else if (ret != MM_ERROR_NONE) {
831 MMRADIO_LOG_ERROR("failed to get radio hal signal strength");
833 MMRADIO_LOG_FLEAVE();
836 *value = (int)strength;
837 MMRADIO_LOG_FLEAVE();
838 return MM_ERROR_NONE;
841 void __mmradio_scan_thread(mm_radio_t *radio)
843 int ret = MM_ERROR_NONE;
846 MMRadioThread_t *p_thread = NULL;
848 MMRADIO_LOG_FENTER();
849 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
851 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
852 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
854 MMRADIO_THREAD_LOCK(p_thread);
855 MMRADIO_THREAD_SIGNAL(p_thread);
856 MMRADIO_THREAD_UNLOCK(p_thread);
858 MMRADIO_THREAD_LOCK(p_thread);
860 while (!p_thread->thread_exit) {
861 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
862 MMRADIO_THREAD_WAIT(p_thread);
864 if (p_thread->thread_exit) {
865 MMRADIO_LOG_DEBUG("exiting scan thread");
869 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
870 ret = radio_hal_mute(radio->hal_inf);
871 if (ret == MM_ERROR_NOT_SUPPORT_API) {
872 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
873 } else if (ret != MM_ERROR_NONE) {
874 MMRADIO_LOG_ERROR("faied to set radio hal mute");
879 ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
880 if (ret != MM_ERROR_NONE)
883 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
884 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
887 while (!p_thread->stop) {
890 MMRADIO_LOG_DEBUG("scanning....");
892 if (p_thread->thread_exit) {
893 MMRADIO_LOG_DEBUG("exiting scan thread");
897 if (p_thread->stop) {
898 MMRADIO_LOG_INFO("scan was canceled");
902 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
903 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
904 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
905 if (ret != MM_ERROR_NONE) {
906 MMRADIO_LOG_ERROR("radio scanning error");
910 if (p_thread->thread_exit) {
911 MMRADIO_LOG_DEBUG("exiting scan thread");
915 if (p_thread->stop) {
916 MMRADIO_LOG_INFO("scan was canceled");
920 /* now we can get new frequency from radio device */
921 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
922 if (ret != MM_ERROR_NONE) {
923 MMRADIO_LOG_ERROR("failed to get current frequency");
925 if (freq <= prev_freq) {
926 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
930 prev_freq = (int)freq;
931 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", prev_freq);
933 /* drop if max freq is scanned */
934 if (prev_freq >= radio->region_setting.band_max) {
935 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", prev_freq);
939 if (p_thread->stop) {
940 /* doesn't need to post */
944 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
949 if (radio->old_state == MM_RADIO_STATE_READY) {
950 MMRADIO_LOG_DEBUG("old state is ready");
951 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
952 MMRADIO_LOG_DEBUG("old state is playing");
953 ret = radio_hal_unmute(radio->hal_inf);
954 if (ret == MM_ERROR_NOT_SUPPORT_API) {
955 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
956 } else if (ret != MM_ERROR_NONE) {
957 MMRADIO_LOG_ERROR("failed to set radio hal unmute");
960 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
961 if (ret == MM_ERROR_NOT_SUPPORT_API) {
962 MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
963 } else if (ret != MM_ERROR_NONE) {
964 MMRADIO_LOG_ERROR("failed to set radio hal frequency");
970 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
971 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
973 /* close radio device here !!!! */
974 if (radio->is_ready) {
975 ret = radio_hal_close(radio->hal_inf);
976 if (ret == MM_ERROR_NOT_SUPPORT_API)
977 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
978 else if (ret != MM_ERROR_NONE)
979 MMRADIO_LOG_ERROR("failed to close radio hal");
981 ret = radio_hal_unprepare(radio->hal_inf);
982 if (ret == MM_ERROR_NOT_SUPPORT_API)
983 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
984 else if (ret != MM_ERROR_NONE)
985 MMRADIO_LOG_ERROR("failed to unprepare radio hal");
987 if (!radio->interrupted_by_resource_conflict && /* is being released */
988 radio->radio_resource != NULL) {
989 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
990 radio->radio_resource);
991 radio->radio_resource = NULL;
992 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
993 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
996 ret = mm_resource_manager_commit(radio->resource_manager);
997 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
998 MMRADIO_LOG_ERROR("resource manager commit fail");
999 radio->is_ready = false;
1001 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
1004 if (!p_thread->stop)
1005 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
1007 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
1009 p_thread->is_running = false;
1014 p_thread->is_running = false;
1016 MMRADIO_THREAD_UNLOCK(p_thread);
1018 MMRADIO_LOG_FLEAVE();
1024 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
1026 MMRADIO_LOG_FENTER();
1028 MMRADIO_CHECK_INSTANCE(radio);
1030 if (freq >= radio->region_setting.band_max
1031 || freq <= radio->region_setting.band_min)
1034 MMRADIO_LOG_FLEAVE();
1039 void __mmradio_seek_thread(mm_radio_t *radio)
1041 int ret = MM_ERROR_NONE;
1043 MMRadioThread_t *p_thread = NULL;
1045 MMRADIO_LOG_FENTER();
1046 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1048 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
1049 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1051 MMRADIO_THREAD_LOCK(p_thread);
1052 MMRADIO_THREAD_SIGNAL(p_thread);
1053 MMRADIO_THREAD_UNLOCK(p_thread);
1055 MMRADIO_THREAD_LOCK(p_thread);
1057 while (!p_thread->thread_exit) {
1058 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.");
1059 MMRADIO_THREAD_WAIT(p_thread);
1061 if (p_thread->thread_exit) {
1062 MMRADIO_LOG_DEBUG("exiting seek thread");
1066 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1067 MMRADIO_LOG_DEBUG("seeking....");
1069 if (p_thread->stop) {
1070 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1074 MMRADIO_LOG_DEBUG("try to seek ");
1075 MMRADIO_HAL_SEEK_THREAD_LOCK(radio);
1076 MMRADIO_LOG_DEBUG("seek start");
1077 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1078 MMRADIO_HAL_SEEK_THREAD_UNLOCK(radio);
1080 MMRADIO_LOG_ERROR("failed to seek radio hal");
1084 if (p_thread->thread_exit) {
1085 MMRADIO_LOG_DEBUG("exiting seek thread");
1089 if (p_thread->stop) {
1090 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1094 /* now we can get new frequency from radio device */
1095 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1097 MMRADIO_LOG_ERROR("failed to get current frequency");
1101 MMRADIO_LOG_DEBUG("found frequency");
1103 /* if same freq is found, ignore it and search next one. */
1104 if (freq == radio->prev_seek_freq) {
1105 MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1109 /* check if it's limit freq or not */
1110 if (__is_tunable_frequency(radio, freq)) {
1111 /* now tune to new frequency */
1112 ret = radio_hal_set_frequency(radio->hal_inf, freq);
1114 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1117 radio->freq = (int)freq;
1118 MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1121 if (radio->seek_unmute) {
1122 /* now turn on radio
1123 * In the case of limit freq, tuner should be unmuted.
1124 * Otherwise, sound can't output even though application set new frequency.
1126 ret = radio_hal_unmute(radio->hal_inf);
1128 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1131 radio->seek_unmute = false;
1134 radio->prev_seek_freq = (int)freq;
1135 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
1136 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
1137 p_thread->is_running = false;
1141 if (radio->seek_unmute) {
1142 /* now turn on radio
1143 * In the case of limit freq, tuner should be unmuted.
1144 * Otherwise, sound can't output even though application set new frequency.
1146 ret = radio_hal_unmute(radio->hal_inf);
1148 MMRADIO_LOG_ERROR("failed to set unmute radio hal");
1149 radio->seek_unmute = false;
1151 /* freq -1 means it's failed to seek */
1152 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
1153 p_thread->is_running = false;
1157 p_thread->is_running = false;
1158 MMRADIO_THREAD_UNLOCK(p_thread);
1159 MMRADIO_LOG_FLEAVE();
1163 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1165 MMRADIO_CHECK_INSTANCE(radio);
1167 MMRADIO_LOG_FENTER();
1169 if (!radio->msg_cb) {
1170 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1174 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1176 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1178 MMRADIO_LOG_FLEAVE();
1183 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1185 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1187 MMRADIO_LOG_FENTER();
1189 MMRADIO_CHECK_INSTANCE(radio);
1191 radio_state = __mmradio_get_state(radio);
1193 MMRADIO_LOG_INFO("incomming command : %d current state : %d", command, radio_state);
1196 case MMRADIO_COMMAND_CREATE:
1198 if (radio_state != 0)
1203 case MMRADIO_COMMAND_REALIZE:
1205 if (radio_state == MM_RADIO_STATE_READY ||
1206 radio_state == MM_RADIO_STATE_PLAYING ||
1207 radio_state == MM_RADIO_STATE_SCANNING)
1210 if (radio_state == 0)
1215 case MMRADIO_COMMAND_UNREALIZE:
1217 if (radio_state == MM_RADIO_STATE_NULL)
1220 /* we can call unrealize at any higher state */
1224 case MMRADIO_COMMAND_START:
1226 if (radio_state == MM_RADIO_STATE_PLAYING)
1229 if (radio_state != MM_RADIO_STATE_READY)
1234 case MMRADIO_COMMAND_STOP:
1236 if (radio_state == MM_RADIO_STATE_READY)
1239 if (radio_state != MM_RADIO_STATE_PLAYING)
1244 case MMRADIO_COMMAND_START_SCAN:
1246 if (radio_state == MM_RADIO_STATE_SCANNING)
1249 if (radio_state == MM_RADIO_STATE_NULL)
1254 case MMRADIO_COMMAND_STOP_SCAN:
1256 if (radio_state == MM_RADIO_STATE_READY)
1259 if (radio_state != MM_RADIO_STATE_SCANNING)
1264 case MMRADIO_COMMAND_DESTROY:
1265 case MMRADIO_COMMAND_MUTE:
1266 case MMRADIO_COMMAND_UNMUTE:
1267 case MMRADIO_COMMAND_SET_FREQ:
1268 case MMRADIO_COMMAND_GET_FREQ:
1269 case MMRADIO_COMMAND_SET_REGION:
1270 case MMRADIO_COMMAND_SET_VOLUME:
1271 case MMRADIO_COMMAND_GET_VOLUME:
1273 /* we can do it at any state */
1277 case MMRADIO_COMMAND_SEEK:
1279 if (radio_state != MM_RADIO_STATE_PLAYING)
1284 case MMRADIO_COMMAND_GET_REGION:
1286 if (radio_state == MM_RADIO_STATE_NULL)
1292 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1296 MMRADIO_LOG_DEBUG("status OK");
1298 radio->cmd = command;
1300 MMRADIO_LOG_FLEAVE();
1302 return MM_ERROR_NONE;
1305 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1306 MMRADIO_LOG_FLEAVE();
1307 return MM_ERROR_RADIO_INVALID_STATE;
1310 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1311 MMRADIO_LOG_FLEAVE();
1312 return MM_ERROR_RADIO_NO_OP;
1316 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1318 MMMessageParamType msg = { 0, };
1319 int msg_type = MM_MESSAGE_UNKNOWN;
1321 MMRADIO_LOG_FENTER();
1324 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1328 if (radio->current_state == new_state && radio->pending_state == 0) {
1329 MMRADIO_LOG_WARNING("we are in same state");
1334 radio->old_state = radio->current_state;
1335 radio->current_state = new_state;
1337 /* fill message param */
1338 msg.union_type = MM_MSG_UNION_STATE;
1339 msg.state.previous = radio->old_state;
1340 msg.state.current = radio->current_state;
1342 if (radio->interrupted_by_resource_conflict) {
1343 __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
1344 MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
1346 msg_type = MM_MESSAGE_STATE_CHANGED;
1347 MMRADIO_POST_MSG(radio, msg_type, &msg);
1350 MMRADIO_LOG_FLEAVE();
1355 static int __mmradio_get_state(mm_radio_t *radio)
1357 MMRADIO_CHECK_INSTANCE(radio);
1359 MMRADIO_LOG_INFO("radio state : current : [%d] old : [%d] pending : [%d]",
1360 radio->current_state, radio->old_state, radio->pending_state);
1362 return radio->current_state;
1365 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1367 mm_radio_t *radio = (mm_radio_t *)user_data;
1368 int ret = MM_ERROR_NONE;
1369 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1370 if (type == VOLUME_TYPE_MEDIA) {
1371 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1372 ret = __mmradio_set_media_volume(radio, volume);
1373 if (ret != MM_ERROR_NONE)
1374 MMRADIO_LOG_ERROR("failed to set media volume");
1379 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1381 MMRADIO_LOG_FENTER();
1382 MMRADIO_CHECK_INSTANCE(radio);
1383 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1385 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1387 *type = radio->region_setting.country;
1389 MMRADIO_LOG_FLEAVE();
1390 return MM_ERROR_NONE;
1393 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1395 MMRADIO_LOG_FENTER();
1396 MMRADIO_CHECK_INSTANCE(radio);
1397 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1399 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1401 *min_freq = radio->region_setting.band_min;
1402 *max_freq = radio->region_setting.band_max;
1404 MMRADIO_LOG_FLEAVE();
1405 return MM_ERROR_NONE;
1408 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1410 MMRADIO_LOG_FENTER();
1411 MMRADIO_CHECK_INSTANCE(radio);
1412 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1414 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1416 *ch_spacing = radio->region_setting.channel_spacing;
1418 MMRADIO_LOG_FLEAVE();
1419 return MM_ERROR_NONE;
1422 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1424 int ret = MM_ERROR_NONE;
1426 MMRADIO_LOG_FENTER();
1428 MMRADIO_CHECK_INSTANCE(radio);
1429 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1431 MMRADIO_LOG_INFO("Setting %f volume", volume);
1433 MMRADIO_VOLUME_LOCK(radio);
1434 radio->local_volume = volume;
1435 MMRADIO_VOLUME_UNLOCK(radio);
1437 ret = radio_hal_set_volume(radio->hal_inf, volume);
1438 if (ret != MM_ERROR_NONE)
1439 MMRADIO_LOG_ERROR("failed to set radio hal volume");
1441 MMRADIO_LOG_FLEAVE();
1446 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1448 int ret = MM_ERROR_NONE;
1450 MMRADIO_LOG_FENTER();
1452 MMRADIO_CHECK_INSTANCE(radio);
1453 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1455 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1457 ret = radio_hal_get_volume(radio->hal_inf, &volume);
1458 if (ret != MM_ERROR_NONE) {
1459 MMRADIO_LOG_ERROR("failed to get radio hal volume");
1464 MMRADIO_VOLUME_LOCK(radio);
1465 radio->local_volume = volume;
1466 *pVolume = (float)radio->local_volume;
1467 MMRADIO_VOLUME_UNLOCK(radio);
1469 MMRADIO_LOG_FLEAVE();
1474 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1476 int ret = MM_ERROR_NONE;
1478 MMRADIO_LOG_FENTER();
1480 MMRADIO_CHECK_INSTANCE(radio);
1481 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1483 MMRADIO_LOG_INFO("Setting %d volume", level);
1485 MMRADIO_VOLUME_LOCK(radio);
1486 radio->media_volume = level;
1487 MMRADIO_VOLUME_UNLOCK(radio);
1489 ret = radio_hal_set_media_volume(radio->hal_inf, level);
1490 if (ret != MM_ERROR_NONE)
1491 MMRADIO_LOG_ERROR("failed to set radio hal media volume");
1493 MMRADIO_LOG_FLEAVE();
1498 static int __resource_release_cb(mm_resource_manager_h rm,
1499 mm_resource_manager_res_h res, void *user_data)
1501 mm_radio_t *radio = NULL;
1503 MMRADIO_LOG_FENTER();
1506 MMRADIO_LOG_ERROR("user_data is null");
1510 radio = (mm_radio_t *)user_data;
1511 radio->radio_resource = NULL;
1513 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1515 radio->interrupted_by_resource_conflict = TRUE;
1517 MMRADIO_CMD_LOCK(radio);
1518 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1519 MMRADIO_LOG_ERROR("failed to stop radio");
1520 MMRADIO_CMD_UNLOCK(radio);
1522 MMRADIO_LOG_FLEAVE();
1527 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1529 MMRadioThread_t *p_thread = NULL;
1531 MMRADIO_LOG_FENTER();
1533 MMRADIO_CHECK_INSTANCE(radio);
1535 if (type >= MM_RADIO_THREAD_NUM) {
1536 MMRADIO_LOG_WARNING("wrong argument thread type");
1537 return MM_ERROR_RADIO_INTERNAL;
1540 p_thread = &radio->thread[type];
1541 MMRADIO_CHECK_ARG(p_thread);
1543 MMRADIO_INIT_MUTEX(p_thread->mutex);
1544 MMRADIO_INIT_COND(p_thread->cond);
1546 MMRADIO_THREAD_LOCK(p_thread);
1547 p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
1548 (void *)__mmradio_thread_function[type], (void *)radio);
1549 if (p_thread->thread_id) {
1550 MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
1551 MMRADIO_THREAD_UNLOCK(p_thread);
1552 return MM_ERROR_RADIO_INTERNAL;
1555 MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
1556 MMRADIO_THREAD_WAIT(p_thread);
1557 MMRADIO_LOG_DEBUG("[%d] thread started", type);
1558 MMRADIO_THREAD_UNLOCK(p_thread);
1560 return MM_ERROR_NONE;
1563 pthread_mutex_destroy(&p_thread->mutex);
1564 pthread_cond_destroy(&p_thread->cond);
1565 return MM_ERROR_RADIO_INTERNAL;
1569 static int __mmradio_create_threads(mm_radio_t *radio)
1571 int ret = MM_ERROR_NONE;
1574 MMRADIO_LOG_FENTER();
1576 MMRADIO_CHECK_INSTANCE(radio);
1578 MMRADIO_INIT_MUTEX(radio->cmd_lock);
1579 MMRADIO_INIT_MUTEX(radio->volume_lock);
1580 MMRADIO_INIT_MUTEX(radio->hal_seek_mutex);
1582 for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
1583 ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
1585 MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
1586 while (--type >= (int)MM_RADIO_THREAD_MSG)
1587 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1592 MMRADIO_LOG_FLEAVE();
1596 pthread_mutex_destroy(&radio->cmd_lock);
1597 pthread_mutex_destroy(&radio->volume_lock);
1598 pthread_mutex_destroy(&radio->hal_seek_mutex);
1600 MMRADIO_LOG_FLEAVE();
1601 return MM_ERROR_RADIO_INTERNAL;
1604 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1606 MMRadioThread_t *p_thread = NULL;
1607 mm_radio_msg_t *msg = NULL;
1608 MMRADIO_LOG_FENTER();
1610 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1612 if (type >= MM_RADIO_THREAD_NUM) {
1613 MMRADIO_LOG_WARNING("wrong argument thread type");
1617 p_thread = &radio->thread[type];
1618 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1620 if (p_thread->thread) {
1622 case MM_RADIO_THREAD_MSG:
1623 msg = g_slice_new0(mm_radio_msg_t);
1625 MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
1627 msg->msg_type = MM_RADIO_MSG_DESTROY;
1628 g_async_queue_push_front(radio->msg_queue, msg);
1629 pthread_join(p_thread->thread, NULL);
1630 p_thread->thread = 0;
1633 case MM_RADIO_THREAD_SEEK:
1634 case MM_RADIO_THREAD_SCAN:
1635 MMRADIO_THREAD_LOCK(p_thread);
1636 p_thread->thread_exit = true;
1637 MMRADIO_THREAD_SIGNAL(p_thread);
1638 MMRADIO_THREAD_UNLOCK(p_thread);
1639 pthread_join(p_thread->thread, NULL);
1640 p_thread->thread = 0;
1643 MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
1647 MMRADIO_LOG_WARNING("(%d)thread is zero", type);
1650 pthread_mutex_destroy(&p_thread->mutex);
1651 pthread_cond_destroy(&p_thread->cond);
1653 MMRADIO_LOG_FLEAVE();
1656 static void __mmradio_destroy_threads(mm_radio_t *radio)
1658 int type = (int)MM_RADIO_THREAD_NUM;
1659 MMRADIO_LOG_FENTER();
1661 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1664 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1666 pthread_mutex_destroy(&radio->cmd_lock);
1667 pthread_mutex_destroy(&radio->volume_lock);
1668 pthread_mutex_destroy(&radio->hal_seek_mutex);
1670 MMRADIO_LOG_FLEAVE();
1673 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1675 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1677 MMRADIO_LOG_ERROR("NULL msg pointer");
1681 msg->msg_type = msg_type;
1682 msg->data = msg_data;
1684 MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
1685 g_async_queue_push(radio->msg_queue, msg);
1688 void __mmradio_msg_thread(mm_radio_t *radio)
1691 mm_radio_msg_t *msg = NULL;
1692 MMRadioThread_t *p_thread = NULL;
1694 MMRADIO_LOG_FENTER();
1695 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1697 p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
1698 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1700 p_thread->thread_exit = false;
1703 MMRADIO_THREAD_LOCK(p_thread);
1704 MMRADIO_THREAD_SIGNAL(p_thread);
1705 MMRADIO_THREAD_UNLOCK(p_thread);
1707 /* we run a while one loop*/
1708 while (!p_thread->thread_exit) {
1709 msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
1711 MMRADIO_LOG_ERROR("poped message is NULL!");
1715 MMMessageParamType param = {0,};
1717 switch (msg->msg_type) {
1718 case MM_RADIO_MSG_DESTROY:
1719 MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
1720 mm_radio_msg_t *msg_pop = NULL;
1721 while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
1722 if (msg_pop != NULL) {
1723 MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
1724 g_slice_free(mm_radio_msg_t, msg_pop);
1727 p_thread->thread_exit = true;
1729 case MM_RADIO_MSG_SCAN_INFO:
1730 MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
1731 param.radio_scan.frequency = (int) msg->data;
1732 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1734 case MM_RADIO_MSG_SCAN_STOPPED:
1735 MMRADIO_LOG_INFO("get scan stopped");
1736 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1738 case MM_RADIO_MSG_SCAN_FINISHED:
1739 MMRADIO_LOG_INFO("get scan finished");
1740 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1742 case MM_RADIO_MSG_SEEK_FINISHED:
1743 MMRADIO_LOG_INFO("get seek finish frequency: %d", msg->data);
1744 param.radio_scan.frequency = (int) msg->data;
1745 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1747 case MM_RADIO_MSG_STATE_INTERRUPTED:
1748 MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
1749 param.union_type = MM_MSG_UNION_STATE;
1750 param.state.previous = radio->old_state;
1751 param.state.current = radio->current_state;
1752 param.state.code = msg->data;
1753 MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, ¶m);
1756 MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1761 g_slice_free(mm_radio_msg_t, msg);
1765 MMRADIO_LOG_INFO("msg thread is finished");
1766 MMRADIO_LOG_FLEAVE();