2 * mm_radio_priv_emulator.c
4 * Copyright (c) 2000 - 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 ========================================================================================== */
31 #include <sys/ioctl.h>
36 #include <mm_message.h>
39 #include "mm_radio_priv_emul.h"
41 /*===========================================================================================
42 LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
43 ========================================================================================== */
44 /*---------------------------------------------------------------------------
45 GLOBAL CONSTANT DEFINITIONS:
46 ---------------------------------------------------------------------------*/
48 /*---------------------------------------------------------------------------
49 IMPORTED VARIABLE DECLARATIONS:
50 ---------------------------------------------------------------------------*/
52 /*---------------------------------------------------------------------------
53 IMPORTED FUNCTION DECLARATIONS:
54 ---------------------------------------------------------------------------*/
56 /*---------------------------------------------------------------------------
58 ---------------------------------------------------------------------------*/
61 #define DEFAULT_FREQ 107700
64 #define RADIO_FREQ_FORMAT_SET(x_freq) ((x_freq) * FREQ_FRAC)
65 #define RADIO_FREQ_FORMAT_GET(x_freq) ((x_freq) / FREQ_FRAC)
66 /* If non-zero, wrap around when at the end of the frequency range, else stop seeking */
67 #define DEFAULT_WRAP_AROUND 1
69 #define RADIO_DEFAULT_REGION MM_RADIO_REGION_GROUP_USA
70 #define EMULATOR_FREQ_MAX 5
71 #define RADIO_MIN_VOLUME 0.0
72 #define RADIO_MAX_VOLUME 1.0
73 #define RADIO_GST_STATE_CHANGE_TIMEOUT (10 * GST_SECOND)
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 { /* North 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 static int MMRadioEmulatorFreq[EMULATOR_FREQ_MAX] = {
116 89100, 89900, 91900, 99900, 107700
119 /*---------------------------------------------------------------------------
120 LOCAL FUNCTION PROTOTYPES:
121 ---------------------------------------------------------------------------*/
122 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param);
123 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command);
124 static int __mmradio_get_state(mm_radio_t * radio);
125 static bool __mmradio_set_state(mm_radio_t * radio, int new_state);
126 static void __mmradio_seek_thread(mm_radio_t * radio);
127 static void __mmradio_scan_thread(mm_radio_t * radio);
128 static bool __is_tunable_frequency(mm_radio_t * radio, int freq);
129 static int __mmradio_create_threads(mm_radio_t *radio);
130 static void __mmradio_destroy_threads(mm_radio_t *radio);
131 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
132 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type);
133 static int __mmradio_set_deemphasis(mm_radio_t * radio);
134 static int __mmradio_set_band_range(mm_radio_t * radio);
135 static int __mmradio_get_wave_num(mm_radio_t * radio);
136 static int __resource_release_cb(mm_resource_manager_h rm,
137 mm_resource_manager_res_h res, void *user_data);
138 static void __mmradio_msg_thread(mm_radio_t *radio);
139 static void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data);
141 typedef void (*thread_function)(mm_radio_t *);
142 thread_function __mmradio_thread_function[] = {
143 &__mmradio_msg_thread,
144 &__mmradio_seek_thread,
145 &__mmradio_scan_thread
148 /*===========================================================================
150 ========================================================================== */
151 /* --------------------------------------------------------------------------
152 * Name : _mmradio_apply_region()
153 * Desc : update radio region information and set values to device
155 * [in] radio : radio handle
156 * [in] region : region type
157 * [in] update : update region values or not
158 * Return : zero on success, or negative value with error code
159 *---------------------------------------------------------------------------*/
160 int _mmradio_apply_region(mm_radio_t * radio, MMRadioRegionType region, bool update)
162 int ret = MM_ERROR_NONE;
166 MMRADIO_LOG_FENTER();
168 MMRADIO_CHECK_INSTANCE(radio);
169 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
171 /* if needed, radio region must be updated.
172 * Otherwise, just applying settings to device without it.
175 count = ARRAY_SIZE(region_table);
177 /* TODO: if auto is supported...get the region info. here */
179 /* update radio region settings */
180 for (index = 0; index < count; index++) {
181 /* find the region from pre-defined table */
182 if (region_table[index].country == region) {
183 radio->region_setting.country = region_table[index].country;
184 radio->region_setting.deemphasis = region_table[index].deemphasis;
185 radio->region_setting.band_min = region_table[index].band_min;
186 radio->region_setting.band_max = region_table[index].band_max;
187 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
192 /* check device is opened or not. if it's not ready, skip to apply region to device now */
193 if (radio->radio_fd < 0) {
194 MMRADIO_LOG_DEBUG("not opened device. just updating region info.");
195 return MM_ERROR_NONE;
198 MMRADIO_SLOG_DEBUG("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz\n",
199 radio->region_setting.country, radio->region_setting.deemphasis,
200 radio->region_setting.band_min, radio->region_setting.band_max);
202 /* set de-emphasis to device */
203 ret = __mmradio_set_deemphasis(radio);
205 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set de-emphasis");
207 /* set band range to device */
208 ret = __mmradio_set_band_range(radio);
210 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set band range");
212 MMRADIO_LOG_FLEAVE();
217 int _mmradio_create_radio(mm_radio_t * radio)
219 int ret = MM_ERROR_NONE;
221 MMRADIO_LOG_FENTER();
223 MMRADIO_CHECK_INSTANCE(radio);
224 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
226 /* set default value */
227 radio->radio_fd = -1;
228 radio->freq = DEFAULT_FREQ;
229 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
230 radio->local_volume = 1.0;
232 /* create msg queue for msg thread */
233 radio->msg_queue = g_async_queue_new();
234 if (!radio->msg_queue) {
235 MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
236 return MM_ERROR_RADIO_INTERNAL;
239 /* create mutex and thread */
240 ret = __mmradio_create_threads(radio);
242 MMRADIO_LOG_ERROR("failed to create threads");
246 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
248 /* initialize resource manager */
249 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
250 __resource_release_cb, radio, &radio->resource_manager);
252 MMRADIO_LOG_ERROR("failed to create resource manager");
253 ret = MM_ERROR_RADIO_INTERNAL;
257 MMRADIO_LOG_FLEAVE();
259 return MM_ERROR_NONE;
262 __mmradio_destroy_threads(radio);
264 if (radio->msg_queue)
265 g_async_queue_unref(radio->msg_queue);
269 int _mmradio_realize(mm_radio_t *radio)
271 int ret = MM_ERROR_NONE;
273 MMRADIO_LOG_FENTER();
275 MMRADIO_CHECK_INSTANCE(radio);
276 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
278 /* open radio device */
279 if (radio->radio_fd == -1) {
280 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
284 radio->radio_fd = 11;
286 MMRADIO_LOG_DEBUG("radio device fd : %d", radio->radio_fd);
288 /* check region country type if it's updated or not */
289 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
290 /* not initialized yet. set it with default region */
291 region = RADIO_DEFAULT_REGION;
294 /* already initialized by application */
295 region = radio->region_setting.country;
298 ret = _mmradio_apply_region(radio, region, update);
300 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info");
303 /* ready but no sound */
304 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
307 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
309 ret = _mmradio_realize_pipeline(radio);
311 MMRADIO_LOG_ERROR("failed to realize pipeline");
315 MMRADIO_LOG_FLEAVE();
317 return MM_ERROR_NONE;
320 int _mmradio_unrealize(mm_radio_t * radio)
322 int ret = MM_ERROR_NONE;
324 MMRADIO_LOG_FENTER();
326 MMRADIO_CHECK_INSTANCE(radio);
327 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
329 /*Finish if there are scans*/
330 ret = _mmradio_stop_scan(radio);
331 if (ret != MM_ERROR_NONE)
332 MMRADIO_LOG_WARNING("failed to stop radio scan");
334 /*Stop radio if started*/
335 ret = _mmradio_stop(radio);
336 if (ret != MM_ERROR_NONE)
337 MMRADIO_LOG_WARNING("failed to stop radio");
339 /* close radio device here !!!! */
340 if (radio->radio_fd >= 0)
341 radio->radio_fd = -1;
343 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
345 ret = _mmradio_destroy_pipeline(radio);
347 MMRADIO_LOG_ERROR("failed to destroy pipeline");
351 MMRADIO_LOG_FLEAVE();
356 int _mmradio_destroy(mm_radio_t * radio)
358 int ret = MM_ERROR_NONE;
360 MMRADIO_LOG_FENTER();
362 MMRADIO_CHECK_INSTANCE(radio);
363 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
365 _mmradio_unrealize(radio);
367 /* destroy mutex and thread */
368 __mmradio_destroy_threads(radio);
370 if (radio->msg_queue)
371 g_async_queue_unref(radio->msg_queue);
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)
389 MMRADIO_LOG_FENTER();
391 MMRADIO_CHECK_INSTANCE(radio);
392 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
394 MMRADIO_SLOG_DEBUG("Setting %d frequency", freq);
395 MMRADIO_LOG_DEBUG("radio->freq: %d freq: %d", radio->freq, freq);
397 if (radio->radio_fd < 0) {
398 MMRADIO_LOG_DEBUG("radio device is not opened yet");
399 return MM_ERROR_NONE;
402 /* check frequency range */
403 if (freq < radio->region_setting.band_min || freq > radio->region_setting.band_max) {
404 MMRADIO_LOG_ERROR("out of frequency range %d", freq);
405 return MM_ERROR_INVALID_ARGUMENT;
409 val = __mmradio_get_wave_num(radio);
411 if (radio->pipeline && radio->pipeline->audiosrc)
412 g_object_set(radio->pipeline->audiosrc, "wave", val, NULL);
414 MMRADIO_LOG_FLEAVE();
416 return MM_ERROR_NONE;
420 int _mmradio_get_frequency(mm_radio_t * radio, int *pFreq)
423 MMRADIO_LOG_FENTER();
425 MMRADIO_CHECK_INSTANCE(radio);
426 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
428 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
430 /* just return stored frequency if radio device is not ready */
431 if (radio->radio_fd < 0) {
432 MMRADIO_SLOG_DEBUG("freq : %d", radio->freq);
433 *pFreq = radio->freq;
434 return MM_ERROR_NONE;
436 /* update freq in handle */
438 *pFreq = radio->freq;
440 MMRADIO_LOG_FLEAVE();
442 return MM_ERROR_NONE;
445 int _mmradio_mute(mm_radio_t * radio)
447 MMRADIO_LOG_FENTER();
449 MMRADIO_CHECK_INSTANCE(radio);
450 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
452 if (radio->radio_fd < 0)
453 return MM_ERROR_RADIO_NOT_INITIALIZED;
455 if (radio->pipeline && radio->pipeline->volume) {
456 g_object_set(radio->pipeline->volume, "mute", 1, NULL);
457 MMRADIO_LOG_DEBUG("g_object set mute");
460 MMRADIO_LOG_FLEAVE();
462 return MM_ERROR_NONE;
466 int _mmradio_unmute(mm_radio_t * radio)
468 MMRADIO_LOG_FENTER();
470 MMRADIO_CHECK_INSTANCE(radio);
471 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
472 MMRADIO_CHECK_DEVICE_STATE(radio);
474 if (radio->pipeline && radio->pipeline->volume) {
475 g_object_set(radio->pipeline->volume, "mute", 0, NULL);
476 MMRADIO_LOG_DEBUG("g_object set unmute");
479 MMRADIO_LOG_FLEAVE();
481 return MM_ERROR_NONE;
484 /* --------------------------------------------------------------------------
485 * Name : __mmradio_set_deemphasis
486 * Desc : apply de-emphasis value to device
488 * [in] radio : radio handle
489 * Return : zero on success, or negative value with error code
490 *---------------------------------------------------------------------------*/
491 int __mmradio_set_deemphasis(mm_radio_t * radio)
495 MMRADIO_LOG_FENTER();
496 return MM_ERROR_NONE;
497 MMRADIO_CHECK_INSTANCE(radio);
499 /* get de-emphasis */
500 switch (radio->region_setting.deemphasis) {
501 case MM_RADIO_DEEMPHASIS_50_US:
502 /* V4L2_DEEMPHASIS_50_uS; */
506 case MM_RADIO_DEEMPHASIS_75_US:
507 /* V4L2_DEEMPHASIS_75_uS; */
512 MMRADIO_LOG_ERROR("not available de-emphasis value");
513 return MM_ERROR_COMMON_INVALID_ARGUMENT;
516 MMRADIO_LOG_DEBUG("set deemphasis %d", value);
518 MMRADIO_LOG_FLEAVE();
520 return MM_ERROR_NONE;
523 /* --------------------------------------------------------------------------
524 * Name : __mmradio_set_band_range
525 * Desc : apply max and min frequency to device
527 * [in] radio : radio handle
528 * Return : zero on success, or negative value with error code
529 *---------------------------------------------------------------------------*/
530 int __mmradio_set_band_range(mm_radio_t * radio)
532 MMRADIO_LOG_FENTER();
533 return MM_ERROR_NONE;
534 MMRADIO_CHECK_INSTANCE(radio);
536 MMRADIO_LOG_FLEAVE();
538 return MM_ERROR_NONE;
541 int _mmradio_set_message_callback(mm_radio_t * radio, MMMessageCallback callback, void *user_param)
543 MMRADIO_LOG_FENTER();
545 MMRADIO_CHECK_INSTANCE(radio);
547 radio->msg_cb = callback;
548 radio->msg_cb_param = user_param;
550 MMRADIO_LOG_DEBUG("msg_cb : %p msg_cb_param : %p", callback, user_param);
552 MMRADIO_LOG_FLEAVE();
554 return MM_ERROR_NONE;
557 int _mmradio_get_state(mm_radio_t * radio, int *pState)
561 MMRADIO_LOG_FENTER();
563 MMRADIO_CHECK_INSTANCE(radio);
564 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
566 state = __mmradio_get_state(radio);
570 MMRADIO_LOG_FLEAVE();
572 return MM_ERROR_NONE;
575 int _mmradio_start(mm_radio_t * radio)
577 int ret = MM_ERROR_NONE;
579 MMRADIO_LOG_FENTER();
581 MMRADIO_CHECK_INSTANCE(radio);
582 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
584 MMRADIO_SLOG_DEBUG("now tune to frequency : %d", radio->freq);
586 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
587 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
588 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
589 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
590 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
591 return MM_ERROR_RADIO_INTERNAL;
594 radio->interrupted_by_resource_conflict = FALSE;
595 ret = mm_resource_manager_commit(radio->resource_manager);
596 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
597 MMRADIO_LOG_ERROR("failed to commit resource manager");
598 mm_resource_manager_mark_for_release(radio->resource_manager,
599 radio->radio_resource);
600 radio->radio_resource = NULL;
604 /* set stored frequency */
605 _mmradio_set_frequency(radio, radio->freq);
607 _mmradio_set_volume(radio, radio->local_volume);
609 ret = _mmradio_start_pipeline(radio);
611 MMRADIO_LOG_ERROR("failed to start pipeline");
615 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
617 MMRADIO_LOG_FLEAVE();
622 int _mmradio_stop(mm_radio_t * radio)
624 int ret = MM_ERROR_NONE;
626 MMRADIO_LOG_FENTER();
628 MMRADIO_CHECK_INSTANCE(radio);
629 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
631 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
632 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
634 if (!radio->interrupted_by_resource_conflict && /* is being released */
635 radio->radio_resource != NULL) {
636 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
637 radio->radio_resource);
638 radio->radio_resource = NULL;
639 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
640 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
644 ret = mm_resource_manager_commit(radio->resource_manager);
645 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
646 MMRADIO_LOG_ERROR("resource manager commit fail");
649 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
651 ret = _mmradio_stop_pipeline(radio);
653 MMRADIO_LOG_ERROR("failed to stop pipeline");
657 MMRADIO_LOG_FLEAVE();
662 int _mmradio_realize_pipeline(mm_radio_t * radio)
664 int ret = MM_ERROR_NONE;
666 MMRADIO_LOG_FENTER();
667 gst_init(NULL, NULL);
668 radio->pipeline = g_new0(mm_radio_gstreamer_s, 1);
670 radio->pipeline->pipeline = gst_pipeline_new("fmradio");
672 radio->pipeline->audiosrc = gst_element_factory_make("audiotestsrc", "fm audio src");
673 radio->pipeline->converter = gst_element_factory_make("audioconvert", "audioconvert");
674 radio->pipeline->volume = gst_element_factory_make("volume", "audiovolume");
675 radio->pipeline->audiosink = gst_element_factory_make("pulsesink", "audio sink");
677 val = __mmradio_get_wave_num(radio);
678 g_object_set(radio->pipeline->audiosrc, "wave", val, "volume", 0.8, NULL);
680 if (!radio->pipeline->pipeline || !radio->pipeline->audiosrc
681 || !radio->pipeline->converter || !radio->pipeline->volume
682 || !radio->pipeline->audiosink) {
683 MMRADIO_LOG_DEBUG("One element could not be created. Exiting.");
684 return MM_ERROR_RADIO_NOT_INITIALIZED;
687 gst_bin_add_many(GST_BIN(radio->pipeline->pipeline),
688 radio->pipeline->audiosrc,
689 radio->pipeline->converter,
690 radio->pipeline->volume,
691 radio->pipeline->audiosink,
693 if (!gst_element_link_many(radio->pipeline->audiosrc,
694 radio->pipeline->converter,
695 radio->pipeline->volume,
696 radio->pipeline->audiosink,
698 MMRADIO_LOG_DEBUG("failed to element link (src - queue - sink)");
699 return MM_ERROR_RADIO_NOT_INITIALIZED;
701 MMRADIO_LOG_FLEAVE();
705 int _mmradio_start_pipeline(mm_radio_t * radio)
707 int ret = MM_ERROR_NONE;
708 GstStateChangeReturn ret_state;
710 MMRADIO_LOG_FENTER();
712 if (gst_element_set_state(radio->pipeline->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
713 MMRADIO_LOG_ERROR("failed to change pipeline state");
714 return MM_ERROR_RADIO_INVALID_STATE;
717 ret_state = gst_element_get_state(radio->pipeline->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
718 if (ret_state == GST_STATE_CHANGE_FAILURE) {
719 MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
720 return MM_ERROR_RADIO_INVALID_STATE;
722 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
725 MMRADIO_LOG_FLEAVE();
729 int _mmradio_stop_pipeline(mm_radio_t * radio)
731 int ret = MM_ERROR_NONE;
732 GstStateChangeReturn ret_state;
734 MMRADIO_LOG_FENTER();
735 if (gst_element_set_state(radio->pipeline->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
736 MMRADIO_LOG_ERROR("Fail to change pipeline state");
737 return MM_ERROR_RADIO_INVALID_STATE;
740 ret_state = gst_element_get_state(radio->pipeline->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
741 if (ret_state == GST_STATE_CHANGE_FAILURE) {
742 MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
743 return MM_ERROR_RADIO_INVALID_STATE;
745 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
747 MMRADIO_LOG_FLEAVE();
751 int _mmradio_destroy_pipeline(mm_radio_t * radio)
754 GstStateChangeReturn ret_state;
755 MMRADIO_LOG_FENTER();
757 MMRADIO_CHECK_ARG(radio->pipeline);
759 if (gst_element_set_state(radio->pipeline->pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE) {
760 MMRADIO_LOG_DEBUG("failed to change pipeline state");
761 gst_object_unref(radio->pipeline->pipeline);
762 MMRADIO_GFREEIF(radio->pipeline);
763 return MM_ERROR_RADIO_INVALID_STATE;
766 ret_state = gst_element_get_state(radio->pipeline->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
767 if (ret_state == GST_STATE_CHANGE_FAILURE) {
768 MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
769 gst_object_unref(radio->pipeline->pipeline);
770 MMRADIO_GFREEIF(radio->pipeline);
771 return MM_ERROR_RADIO_INVALID_STATE;
773 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
776 gst_object_unref(radio->pipeline->pipeline);
777 MMRADIO_GFREEIF(radio->pipeline);
778 MMRADIO_LOG_FLEAVE();
782 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
784 MMRadioThread_t *p_thread = NULL;
786 MMRADIO_LOG_FENTER();
788 MMRADIO_CHECK_INSTANCE(radio);
789 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
791 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
792 MMRADIO_CHECK_ARG(p_thread);
794 if (p_thread->is_running) {
795 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
796 return MM_ERROR_RADIO_INTERNAL;
799 MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d", direction);
800 radio->seek_direction = direction;
801 p_thread->is_running = true;
802 p_thread->stop = false;
803 MMRADIO_THREAD_SIGNAL(p_thread);
805 MMRADIO_LOG_FLEAVE();
807 return MM_ERROR_NONE;
810 int _mmradio_start_scan(mm_radio_t * radio)
812 MMRadioThread_t *p_thread = NULL;
814 MMRADIO_LOG_FENTER();
816 MMRADIO_CHECK_INSTANCE(radio);
817 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
819 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
820 MMRADIO_CHECK_ARG(p_thread);
822 p_thread->stop = false;
823 p_thread->is_running = true;
825 MMRADIO_THREAD_SIGNAL(p_thread);
827 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
829 MMRADIO_LOG_FLEAVE();
831 return MM_ERROR_NONE;
834 int _mmradio_stop_scan(mm_radio_t * radio)
836 MMRADIO_LOG_FENTER();
838 MMRADIO_CHECK_INSTANCE(radio);
839 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
841 radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
843 MMRADIO_LOG_FLEAVE();
845 return MM_ERROR_NONE;
848 int _mm_radio_get_signal_strength(mm_radio_t * radio, int *value)
850 MMRADIO_LOG_FENTER();
851 MMRADIO_CHECK_INSTANCE(radio);
853 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
855 /* just return stored frequency if radio device is not ready */
856 if (radio->radio_fd < 0) {
857 MMRADIO_SLOG_DEBUG("Device not ready so sending 0");
859 return MM_ERROR_NONE;
862 unsigned int seed = (unsigned)time(NULL);
863 *value = 0 - ((rand_r(&seed) % 20 + 1) + 80);
864 MMRADIO_LOG_FLEAVE();
865 return MM_ERROR_NONE;
868 void __mmradio_scan_thread(mm_radio_t * radio)
874 MMRadioThread_t *p_thread = NULL;
876 MMRADIO_LOG_FENTER();
877 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
879 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
880 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
882 MMRADIO_THREAD_LOCK(p_thread);
883 MMRADIO_THREAD_SIGNAL(p_thread);
884 MMRADIO_THREAD_UNLOCK(p_thread);
886 MMRADIO_THREAD_LOCK(p_thread);
888 while (!p_thread->thread_exit) {
889 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
890 MMRADIO_THREAD_WAIT(p_thread);
891 MMRADIO_LOG_DEBUG("scan thread started. got signal.");
893 if (p_thread->thread_exit) {
894 MMRADIO_LOG_DEBUG("exiting scan thread");
898 if (p_thread->stop) {
899 MMRADIO_LOG_INFO("scan was stopped");
903 if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
906 if (radio->old_state == MM_RADIO_STATE_PLAYING)
907 _mmradio_mute(radio);
909 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
910 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
915 while (!p_thread->stop) {
919 MMRADIO_LOG_DEBUG("scanning....");
921 /* now we can get new frequency from radio device */
922 if (p_thread->thread_exit) {
923 MMRADIO_LOG_DEBUG("exiting scan thread");
931 freq = MMRadioEmulatorFreq[emulatoridx];
932 MMRADIO_LOG_DEBUG("freq: %d", freq);
934 if (freq < prev_freq) {
935 MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan");
939 if (p_thread->thread_exit) {
940 MMRADIO_LOG_DEBUG("exiting scan thread");
947 if (freq == prev_freq)
951 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", freq);
953 /* drop if out of range freq is scanned */
954 if (freq >= radio->region_setting.band_max
955 || freq < radio->region_setting.band_min) {
956 MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan", freq);
961 break; /* doesn't need to post */
963 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
965 if (emulatoridx >= EMULATOR_FREQ_MAX)
970 if (radio->old_state == MM_RADIO_STATE_READY) {
971 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
972 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
973 _mmradio_unmute(radio);
974 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
975 /* check if it's limit freq or not */
976 if (__is_tunable_frequency(radio, freq)) {
977 /* now tune to new frequency */
978 if (_mmradio_set_frequency(radio, freq))
979 MMRADIO_LOG_ERROR("failed to tune to new frequency");
983 p_thread->is_running = false;
986 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
988 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
990 /* reset thread stop flag */
991 p_thread->stop = false;
996 MMRADIO_THREAD_UNLOCK(p_thread);
997 MMRADIO_LOG_FLEAVE();
1002 bool __is_tunable_frequency(mm_radio_t * radio, int freq)
1004 MMRADIO_LOG_FENTER();
1006 MMRADIO_CHECK_INSTANCE(radio);
1008 if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min)
1011 MMRADIO_LOG_FLEAVE();
1016 void __mmradio_seek_thread(mm_radio_t * radio)
1020 int emulatoridx = 0;
1021 MMRadioThread_t *p_thread = NULL;
1023 MMRADIO_LOG_FENTER();
1024 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1026 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
1027 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1029 MMRADIO_THREAD_LOCK(p_thread);
1030 MMRADIO_THREAD_SIGNAL(p_thread);
1031 MMRADIO_THREAD_UNLOCK(p_thread);
1033 MMRADIO_THREAD_LOCK(p_thread);
1035 while (!p_thread->thread_exit) {
1036 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.\n");
1037 MMRADIO_THREAD_WAIT(p_thread);
1039 if (p_thread->thread_exit) {
1040 MMRADIO_LOG_DEBUG("exiting seek thread");
1044 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1045 MMRADIO_LOG_DEBUG("seeking....");
1047 if (p_thread->stop) {
1048 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1054 MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
1056 if (radio->seek_direction == MM_RADIO_SEEK_UP) {
1057 for (i = 0; i < EMULATOR_FREQ_MAX; i++) {
1058 if (radio->freq < MMRadioEmulatorFreq[i]) {
1059 freq = MMRadioEmulatorFreq[i];
1065 freq = MMRadioEmulatorFreq[0];
1069 for (i = EMULATOR_FREQ_MAX - 1; i >= 0; i--) {
1070 if (radio->freq > MMRadioEmulatorFreq[i]) {
1071 freq = MMRadioEmulatorFreq[i];
1077 freq = MMRadioEmulatorFreq[EMULATOR_FREQ_MAX - 1];
1078 emulatoridx = EMULATOR_FREQ_MAX - 1;
1083 MMRADIO_LOG_DEBUG("radio->freq: %d emulatoridx: %d", radio->freq, emulatoridx);
1085 MMRADIO_LOG_DEBUG("found frequency");
1087 /* if same freq is found, ignore it and search next one. */
1088 if (freq == radio->prev_seek_freq) {
1089 MMRADIO_LOG_DEBUG("It's same with previous found one. So, trying next one.");
1093 /* check if it's limit freq or not */
1094 if (__is_tunable_frequency(radio, freq)) {
1095 /* now tune to new frequency */
1096 if (_mmradio_set_frequency(radio, freq)) {
1097 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1102 radio->prev_seek_freq = freq;
1103 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
1104 p_thread->is_running = false;
1105 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
1106 p_thread->stop = true;
1110 /* freq -1 means it's failed to seek */
1111 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
1112 p_thread->stop = true;
1113 p_thread->is_running = false;
1116 MMRADIO_THREAD_UNLOCK(p_thread);
1117 MMRADIO_LOG_FLEAVE();
1122 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param)
1124 MMRADIO_CHECK_INSTANCE(radio);
1126 MMRADIO_LOG_FENTER();
1128 if (!radio->msg_cb) {
1129 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1133 MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1135 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1137 MMRADIO_LOG_FLEAVE();
1142 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command)
1144 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1146 MMRADIO_LOG_FENTER();
1148 MMRADIO_CHECK_INSTANCE(radio);
1150 radio_state = __mmradio_get_state(radio);
1152 MMRADIO_LOG_DEBUG("incoming command : %d current state : %d", command, radio_state);
1155 case MMRADIO_COMMAND_CREATE:
1157 if (radio_state != 0)
1162 case MMRADIO_COMMAND_REALIZE:
1164 if (radio_state == MM_RADIO_STATE_READY ||
1165 radio_state == MM_RADIO_STATE_PLAYING ||
1166 radio_state == MM_RADIO_STATE_SCANNING)
1169 if (radio_state == 0)
1174 case MMRADIO_COMMAND_UNREALIZE:
1176 if (radio_state == MM_RADIO_STATE_NULL)
1179 /* we can call unrealize at any higher state */
1183 case MMRADIO_COMMAND_START:
1185 if (radio_state == MM_RADIO_STATE_PLAYING)
1188 if (radio_state != MM_RADIO_STATE_READY)
1193 case MMRADIO_COMMAND_STOP:
1195 if (radio_state == MM_RADIO_STATE_READY)
1198 if (radio_state != MM_RADIO_STATE_PLAYING)
1203 case MMRADIO_COMMAND_START_SCAN:
1205 if (radio_state == MM_RADIO_STATE_SCANNING)
1208 if (radio_state == MM_RADIO_STATE_NULL)
1213 case MMRADIO_COMMAND_STOP_SCAN:
1215 if (radio_state == MM_RADIO_STATE_READY)
1218 if (radio_state != MM_RADIO_STATE_SCANNING)
1223 case MMRADIO_COMMAND_DESTROY:
1224 case MMRADIO_COMMAND_MUTE:
1225 case MMRADIO_COMMAND_UNMUTE:
1226 case MMRADIO_COMMAND_SET_FREQ:
1227 case MMRADIO_COMMAND_GET_FREQ:
1228 case MMRADIO_COMMAND_SET_REGION:
1230 /* we can do it at any state */
1234 case MMRADIO_COMMAND_SEEK:
1236 if (radio_state != MM_RADIO_STATE_PLAYING)
1241 case MMRADIO_COMMAND_GET_REGION:
1243 if (radio_state == MM_RADIO_STATE_NULL)
1249 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1253 MMRADIO_LOG_DEBUG("status OK");
1255 radio->cmd = command;
1257 MMRADIO_LOG_FLEAVE();
1259 return MM_ERROR_NONE;
1262 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1263 MMRADIO_LOG_FLEAVE();
1264 return MM_ERROR_RADIO_INVALID_STATE;
1267 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1268 MMRADIO_LOG_FLEAVE();
1269 return MM_ERROR_RADIO_NO_OP;
1273 static bool __mmradio_set_state(mm_radio_t * radio, int new_state)
1275 MMMessageParamType msg = { 0, };
1276 int msg_type = MM_MESSAGE_UNKNOWN;
1278 MMRADIO_LOG_FENTER();
1281 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1285 if (radio->current_state == new_state && radio->pending_state == 0) {
1286 MMRADIO_LOG_WARNING("we are in same state");
1291 radio->old_state = radio->current_state;
1292 radio->current_state = new_state;
1294 /* fill message param */
1295 msg.union_type = MM_MSG_UNION_STATE;
1296 msg.state.previous = radio->old_state;
1297 msg.state.current = radio->current_state;
1299 if (radio->interrupted_by_resource_conflict) {
1300 __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
1301 MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
1303 msg_type = MM_MESSAGE_STATE_CHANGED;
1304 MMRADIO_POST_MSG(radio, msg_type, &msg);
1307 MMRADIO_LOG_FLEAVE();
1312 static int __mmradio_get_state(mm_radio_t * radio)
1314 MMRADIO_CHECK_INSTANCE(radio);
1316 MMRADIO_LOG_DEBUG("radio state : current : [%d] old : [%d] pending : [%d]",
1317 radio->current_state, radio->old_state, radio->pending_state);
1319 return radio->current_state;
1322 int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type)
1324 MMRADIO_LOG_FENTER();
1325 MMRADIO_CHECK_INSTANCE(radio);
1326 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1328 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1330 *type = radio->region_setting.country;
1332 MMRADIO_LOG_FLEAVE();
1333 return MM_ERROR_NONE;
1336 int _mmradio_get_region_frequency_range(mm_radio_t * radio, unsigned int *min_freq, unsigned int *max_freq)
1338 MMRADIO_LOG_FENTER();
1339 MMRADIO_CHECK_INSTANCE(radio);
1340 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1342 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1344 *min_freq = radio->region_setting.band_min;
1345 *max_freq = radio->region_setting.band_max;
1347 MMRADIO_LOG_FLEAVE();
1348 return MM_ERROR_NONE;
1351 int _mmradio_get_channel_spacing(mm_radio_t * radio, unsigned int *ch_spacing)
1353 MMRADIO_LOG_FENTER();
1354 MMRADIO_CHECK_INSTANCE(radio);
1355 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1357 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1359 *ch_spacing = radio->region_setting.channel_spacing;
1361 MMRADIO_LOG_FLEAVE();
1362 return MM_ERROR_NONE;
1365 static int __mmradio_get_wave_num(mm_radio_t * radio)
1368 MMRADIO_LOG_FENTER();
1370 if (radio->freq <= MMRadioEmulatorFreq[0])
1372 else if (radio->freq <= MMRadioEmulatorFreq[1])
1374 else if (radio->freq <= MMRadioEmulatorFreq[2])
1376 else if (radio->freq <= MMRadioEmulatorFreq[3])
1378 else if (radio->freq <= MMRadioEmulatorFreq[4])
1383 MMRADIO_LOG_DEBUG("freq: %d, val : %d", radio->freq, val);
1384 MMRADIO_LOG_FLEAVE();
1388 static int __resource_release_cb(mm_resource_manager_h rm,
1389 mm_resource_manager_res_h res, void *user_data)
1391 mm_radio_t *radio = NULL;
1393 MMRADIO_LOG_FENTER();
1396 MMRADIO_LOG_ERROR("user_data is null");
1400 radio = (mm_radio_t *)user_data;
1401 radio->radio_resource = NULL;
1403 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1405 radio->interrupted_by_resource_conflict = TRUE;
1407 MMRADIO_CMD_LOCK(radio);
1408 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1409 MMRADIO_LOG_ERROR("failed to stop radio");
1410 MMRADIO_CMD_UNLOCK(radio);
1412 MMRADIO_LOG_FLEAVE();
1417 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1419 MMRADIO_LOG_FENTER();
1421 MMRADIO_CHECK_INSTANCE(radio);
1422 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1424 MMRADIO_SLOG_DEBUG("Setting %f volume", volume);
1426 /* check volume range */
1427 if (volume < RADIO_MIN_VOLUME || volume > RADIO_MAX_VOLUME) {
1428 MMRADIO_LOG_ERROR("out of volume range");
1429 return MM_ERROR_INVALID_ARGUMENT;
1432 if (radio->radio_fd < 0) {
1433 MMRADIO_LOG_DEBUG("radio device is not opened yet");
1434 radio->local_volume = volume;
1435 return MM_ERROR_NONE;
1438 radio->local_volume = volume;
1440 if (radio->pipeline && radio->pipeline->volume) {
1441 g_object_set(radio->pipeline->volume, "volume", volume, NULL);
1442 MMRADIO_LOG_DEBUG("g_object set volume");
1445 MMRADIO_LOG_FLEAVE();
1447 return MM_ERROR_NONE;
1450 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1452 MMRADIO_LOG_FENTER();
1454 MMRADIO_CHECK_INSTANCE(radio);
1455 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1457 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1459 MMRADIO_SLOG_DEBUG("volume : %f", radio->local_volume);
1461 *pVolume = radio->local_volume;
1463 MMRADIO_LOG_FLEAVE();
1465 return MM_ERROR_NONE;
1468 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1470 MMRadioThread_t *p_thread = NULL;
1472 MMRADIO_LOG_FENTER();
1474 MMRADIO_CHECK_INSTANCE(radio);
1476 if (type >= MM_RADIO_THREAD_NUM) {
1477 MMRADIO_LOG_WARNING("wrong argument thread type");
1478 return MM_ERROR_RADIO_INTERNAL;
1481 p_thread = &radio->thread[type];
1482 MMRADIO_CHECK_ARG(p_thread);
1484 MMRADIO_INIT_MUTEX(p_thread->mutex);
1485 MMRADIO_INIT_COND(p_thread->cond);
1487 MMRADIO_THREAD_LOCK(p_thread);
1488 p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
1489 (void *)__mmradio_thread_function[type], (void *)radio);
1490 if (p_thread->thread_id) {
1491 MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
1492 MMRADIO_THREAD_UNLOCK(p_thread);
1493 return MM_ERROR_RADIO_INTERNAL;
1496 MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
1497 MMRADIO_THREAD_WAIT(p_thread);
1498 MMRADIO_LOG_DEBUG("[%d] thread started", type);
1499 MMRADIO_THREAD_UNLOCK(p_thread);
1501 return MM_ERROR_NONE;
1504 pthread_mutex_destroy(&p_thread->mutex);
1505 pthread_cond_destroy(&p_thread->cond);
1506 return MM_ERROR_RADIO_INTERNAL;
1510 static int __mmradio_create_threads(mm_radio_t *radio)
1512 int ret = MM_ERROR_NONE;
1515 MMRADIO_LOG_FENTER();
1517 MMRADIO_CHECK_INSTANCE(radio);
1519 MMRADIO_INIT_MUTEX(radio->cmd_lock);
1521 for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
1522 ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
1524 MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
1525 while (--type >= (int)MM_RADIO_THREAD_MSG)
1526 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1531 MMRADIO_LOG_FLEAVE();
1535 pthread_mutex_destroy(&radio->cmd_lock);
1536 MMRADIO_LOG_FLEAVE();
1537 return MM_ERROR_RADIO_INTERNAL;
1540 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1542 MMRadioThread_t *p_thread = NULL;
1543 mm_radio_msg_t *msg = NULL;
1544 MMRADIO_LOG_FENTER();
1546 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1548 if (type >= MM_RADIO_THREAD_NUM) {
1549 MMRADIO_LOG_WARNING("wrong argument thread type");
1553 p_thread = &radio->thread[type];
1554 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1556 if (p_thread->thread) {
1558 case MM_RADIO_THREAD_MSG:
1559 msg = g_slice_new0(mm_radio_msg_t);
1560 msg->msg_type = MM_RADIO_MSG_DESTROY;
1561 g_async_queue_push_front(radio->msg_queue, msg);
1562 pthread_join(p_thread->thread, NULL);
1563 p_thread->thread = 0;
1565 case MM_RADIO_THREAD_SEEK:
1566 case MM_RADIO_THREAD_SCAN:
1567 MMRADIO_THREAD_LOCK(p_thread);
1568 p_thread->thread_exit = true;
1569 MMRADIO_THREAD_SIGNAL(p_thread);
1570 MMRADIO_THREAD_UNLOCK(p_thread);
1571 pthread_join(p_thread->thread, NULL);
1572 p_thread->thread = 0;
1575 MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
1579 MMRADIO_LOG_WARNING("(%d)thread is zero", type);
1582 pthread_mutex_destroy(&p_thread->mutex);
1583 pthread_cond_destroy(&p_thread->cond);
1585 MMRADIO_LOG_FLEAVE();
1588 static void __mmradio_destroy_threads(mm_radio_t *radio)
1590 int type = (int)MM_RADIO_THREAD_NUM;
1591 MMRADIO_LOG_FENTER();
1593 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1596 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1598 pthread_mutex_destroy(&radio->cmd_lock);
1600 MMRADIO_LOG_FLEAVE();
1604 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1606 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1608 msg->msg_type = msg_type;
1609 msg->data = msg_data;
1611 MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
1612 g_async_queue_push(radio->msg_queue, msg);
1615 void __mmradio_msg_thread(mm_radio_t *radio)
1617 mm_radio_msg_t *msg = NULL;
1618 MMRadioThread_t *p_thread = NULL;
1620 MMRADIO_LOG_FENTER();
1621 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1623 p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
1624 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1626 p_thread->thread_exit = false;
1628 MMRADIO_THREAD_LOCK(p_thread);
1629 MMRADIO_THREAD_SIGNAL(p_thread);
1630 MMRADIO_THREAD_UNLOCK(p_thread);
1632 /*we run a while one loop*/
1633 while (!p_thread->thread_exit) {
1634 msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
1636 MMRADIO_LOG_ERROR("popped message is NULL!");
1640 MMMessageParamType param = {0,};
1642 switch (msg->msg_type) {
1643 case MM_RADIO_MSG_DESTROY:
1644 MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
1645 mm_radio_msg_t *msg_pop = NULL;
1646 while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
1647 if (msg_pop != NULL) {
1648 MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
1649 g_slice_free(mm_radio_msg_t, msg_pop);
1652 p_thread->thread_exit = true;
1654 case MM_RADIO_MSG_SCAN_INFO:
1655 MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
1656 param.radio_scan.frequency = (int) msg->data;
1657 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1659 case MM_RADIO_MSG_SCAN_STOPPED:
1660 MMRADIO_LOG_INFO("get scan stopped");
1661 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1663 case MM_RADIO_MSG_SCAN_FINISHED:
1664 MMRADIO_LOG_INFO("get scan finished");
1665 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1667 case MM_RADIO_MSG_SEEK_FINISHED:
1668 MMRADIO_LOG_INFO("get seek finished frequency: %d", msg->data);
1669 param.radio_scan.frequency = (int) msg->data;
1670 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1672 case MM_RADIO_MSG_STATE_INTERRUPTED:
1673 MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
1674 param.union_type = MM_MSG_UNION_STATE;
1675 param.state.previous = radio->old_state;
1676 param.state.current = radio->current_state;
1677 param.state.code = msg->data;
1678 MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, ¶m);
1681 MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1686 g_slice_free(mm_radio_msg_t, msg);
1689 MMRADIO_LOG_INFO("msg thread is finished");
1690 MMRADIO_LOG_FLEAVE();