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.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 { /* 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 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 /* chech 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-emphsasis 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));
231 radio->local_volume = 1.0;
233 /* create msg queue for msg thread */
234 radio->msg_queue = g_async_queue_new();
235 if (!radio->msg_queue) {
236 MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
237 return MM_ERROR_RADIO_INTERNAL;
240 /* create mutex and thread */
241 ret = __mmradio_create_threads(radio);
243 MMRADIO_LOG_ERROR("failed to create threads");
247 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
249 /* initialize resource manager */
250 ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
251 __resource_release_cb, radio, &radio->resource_manager);
253 MMRADIO_LOG_ERROR("failed to create resource manager");
254 ret = MM_ERROR_RADIO_INTERNAL;
258 MMRADIO_LOG_FLEAVE();
260 return MM_ERROR_NONE;
263 __mmradio_destroy_threads(radio);
265 if (radio->msg_queue)
266 g_async_queue_unref(radio->msg_queue);
270 int _mmradio_realize(mm_radio_t *radio)
272 int ret = MM_ERROR_NONE;
274 MMRADIO_LOG_FENTER();
276 MMRADIO_CHECK_INSTANCE(radio);
277 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
279 /* open radio device */
280 if (radio->radio_fd == -1) {
281 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
285 radio->radio_fd = 11;
287 MMRADIO_LOG_DEBUG("radio device fd : %d", radio->radio_fd);
289 /* check region country type if it's updated or not */
290 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
291 /* not initialized yet. set it with default region */
292 region = RADIO_DEFAULT_REGION;
295 /* already initialized by application */
296 region = radio->region_setting.country;
299 ret = _mmradio_apply_region(radio, region, update);
301 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info");
304 /* ready but nosound */
305 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
308 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
309 #ifdef USE_GST_PIPELINE
310 ret = _mmradio_realize_pipeline(radio);
312 MMRADIO_LOG_ERROR("failed to realize pipeline");
316 MMRADIO_LOG_FLEAVE();
318 return MM_ERROR_NONE;
321 int _mmradio_unrealize(mm_radio_t * radio)
323 int ret = MM_ERROR_NONE;
325 MMRADIO_LOG_FENTER();
327 MMRADIO_CHECK_INSTANCE(radio);
328 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
330 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
331 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
333 /* close radio device here !!!! */
334 if (radio->radio_fd >= 0)
335 radio->radio_fd = -1;
337 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
339 #ifdef USE_GST_PIPELINE
340 ret = _mmradio_destroy_pipeline(radio);
342 MMRADIO_LOG_ERROR("failed to destroy pipeline");
347 MMRADIO_LOG_FLEAVE();
352 int _mmradio_destroy(mm_radio_t * radio)
354 int ret = MM_ERROR_NONE;
356 MMRADIO_LOG_FENTER();
358 MMRADIO_CHECK_INSTANCE(radio);
359 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
361 _mmradio_unrealize(radio);
362 /* destroy mutex and thread */
363 __mmradio_destroy_threads(radio);
365 if (radio->msg_queue)
366 g_async_queue_unref(radio->msg_queue);
368 ret = mm_resource_manager_destroy(radio->resource_manager);
370 MMRADIO_LOG_ERROR("failed to destroy resource manager");
371 return MM_ERROR_RADIO_INTERNAL;
374 MMRADIO_LOG_FLEAVE();
376 return MM_ERROR_NONE;
379 /* unit should be KHz */
380 int _mmradio_set_frequency(mm_radio_t * radio, int freq)
382 MMRADIO_LOG_FENTER();
384 MMRADIO_CHECK_INSTANCE(radio);
385 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
387 MMRADIO_SLOG_DEBUG("Setting %d frequency", freq);
388 MMRADIO_LOG_DEBUG("radio->freq: %d freq: %d", radio->freq, freq);
390 if (radio->radio_fd < 0) {
391 MMRADIO_LOG_DEBUG("radio device is not opened yet");
392 return MM_ERROR_NONE;
395 /* check frequency range */
396 if (freq < radio->region_setting.band_min || freq > radio->region_setting.band_max) {
397 MMRADIO_LOG_ERROR("out of frequency range", freq);
398 return MM_ERROR_INVALID_ARGUMENT;
403 #ifdef USE_GST_PIPELINE
404 if (radio->pGstreamer_s) {
406 val = __mmradio_get_wave_num(radio);
407 g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, NULL);
410 MMRADIO_LOG_FLEAVE();
412 return MM_ERROR_NONE;
416 int _mmradio_get_frequency(mm_radio_t * radio, int *pFreq)
419 MMRADIO_LOG_FENTER();
421 MMRADIO_CHECK_INSTANCE(radio);
422 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
424 MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
426 /* just return stored frequency if radio device is not ready */
427 if (radio->radio_fd < 0) {
428 MMRADIO_SLOG_DEBUG("freq : %d", radio->freq);
429 *pFreq = radio->freq;
430 return MM_ERROR_NONE;
432 /* update freq in handle */
434 *pFreq = radio->freq;
436 MMRADIO_LOG_FLEAVE();
438 return MM_ERROR_NONE;
441 int _mmradio_mute(mm_radio_t * radio)
443 MMRADIO_LOG_FENTER();
445 MMRADIO_CHECK_INSTANCE(radio);
446 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
448 if (radio->radio_fd < 0)
449 return MM_ERROR_RADIO_NOT_INITIALIZED;
451 #ifdef USE_GST_PIPELINE
452 if (radio->pGstreamer_s) {
453 g_object_set(radio->pGstreamer_s->volume, "mute", 1, NULL);
454 MMRADIO_LOG_DEBUG("g_object set mute");
457 MMRADIO_LOG_FLEAVE();
459 return MM_ERROR_NONE;
463 int _mmradio_unmute(mm_radio_t * radio)
465 MMRADIO_LOG_FENTER();
467 MMRADIO_CHECK_INSTANCE(radio);
468 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
469 MMRADIO_CHECK_DEVICE_STATE(radio);
471 #ifdef USE_GST_PIPELINE
472 if (radio->pGstreamer_s) {
473 g_object_set(radio->pGstreamer_s->volume, "mute", 0, NULL);
474 MMRADIO_LOG_DEBUG("g_object set unmute");
478 MMRADIO_LOG_FLEAVE();
480 return MM_ERROR_NONE;
483 /* --------------------------------------------------------------------------
484 * Name : __mmradio_set_deemphasis
485 * Desc : apply de-emphasis value to device
487 * [in] radio : radio handle
488 * Return : zero on success, or negative value with error code
489 *---------------------------------------------------------------------------*/
490 int __mmradio_set_deemphasis(mm_radio_t * radio)
494 MMRADIO_LOG_FENTER();
495 return MM_ERROR_NONE;
496 MMRADIO_CHECK_INSTANCE(radio);
498 /* get de-emphasis */
499 switch (radio->region_setting.deemphasis) {
500 case MM_RADIO_DEEMPHASIS_50_US:
501 /* V4L2_DEEMPHASIS_50_uS; */
505 case MM_RADIO_DEEMPHASIS_75_US:
506 /* V4L2_DEEMPHASIS_75_uS; */
511 MMRADIO_LOG_ERROR("not availabe de-emphasis value");
512 return MM_ERROR_COMMON_INVALID_ARGUMENT;
515 MMRADIO_LOG_DEBUG("set deemphasis %d", value);
517 MMRADIO_LOG_FLEAVE();
519 return MM_ERROR_NONE;
522 /* --------------------------------------------------------------------------
523 * Name : __mmradio_set_band_range
524 * Desc : apply max and min frequency to device
526 * [in] radio : radio handle
527 * Return : zero on success, or negative value with error code
528 *---------------------------------------------------------------------------*/
529 int __mmradio_set_band_range(mm_radio_t * radio)
531 MMRADIO_LOG_FENTER();
532 return MM_ERROR_NONE;
533 MMRADIO_CHECK_INSTANCE(radio);
535 MMRADIO_LOG_FLEAVE();
537 return MM_ERROR_NONE;
540 int _mmradio_set_message_callback(mm_radio_t * radio, MMMessageCallback callback, void *user_param)
542 MMRADIO_LOG_FENTER();
544 MMRADIO_CHECK_INSTANCE(radio);
546 radio->msg_cb = callback;
547 radio->msg_cb_param = user_param;
549 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
551 MMRADIO_LOG_FLEAVE();
553 return MM_ERROR_NONE;
556 int _mmradio_get_state(mm_radio_t * radio, int *pState)
560 MMRADIO_LOG_FENTER();
562 MMRADIO_CHECK_INSTANCE(radio);
563 MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
565 state = __mmradio_get_state(radio);
569 MMRADIO_LOG_FLEAVE();
571 return MM_ERROR_NONE;
574 int _mmradio_start(mm_radio_t * radio)
576 int ret = MM_ERROR_NONE;
578 MMRADIO_LOG_FENTER();
580 MMRADIO_CHECK_INSTANCE(radio);
581 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
583 MMRADIO_SLOG_DEBUG("now tune to frequency : %d", radio->freq);
585 ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
586 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
587 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
588 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
589 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
590 return MM_ERROR_RADIO_INTERNAL;
593 radio->interrupted_by_resource_conflict = FALSE;
594 ret = mm_resource_manager_commit(radio->resource_manager);
595 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
596 MMRADIO_LOG_ERROR("failed to commit resource manager");
597 mm_resource_manager_mark_for_release(radio->resource_manager,
598 radio->radio_resource);
599 radio->radio_resource = NULL;
603 /* set stored frequency */
604 _mmradio_set_frequency(radio, radio->freq);
606 _mmradio_set_volume(radio, radio->local_volume);
609 /* if( _mmradio_unmute(radio) != MM_ERROR_NONE) */
610 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
612 #ifdef USE_GST_PIPELINE
613 ret = _mmradio_start_pipeline(radio);
615 MMRADIO_LOG_ERROR("failed to start pipeline");
620 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
622 MMRADIO_LOG_FLEAVE();
627 int _mmradio_stop(mm_radio_t * radio)
629 int ret = MM_ERROR_NONE;
631 MMRADIO_LOG_FENTER();
633 MMRADIO_CHECK_INSTANCE(radio);
634 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
636 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
637 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
639 if (!radio->interrupted_by_resource_conflict && /* is being released */
640 radio->radio_resource != NULL) {
641 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
642 radio->radio_resource);
643 radio->radio_resource = NULL;
644 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
645 MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
649 ret = mm_resource_manager_commit(radio->resource_manager);
650 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
651 MMRADIO_LOG_ERROR("resource manager commit fail");
654 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
656 #ifdef USE_GST_PIPELINE
657 ret = _mmradio_stop_pipeline(radio);
659 MMRADIO_LOG_ERROR("failed to stop pipeline");
664 MMRADIO_LOG_FLEAVE();
669 #ifdef USE_GST_PIPELINE
670 int _mmradio_realize_pipeline(mm_radio_t * radio)
672 int ret = MM_ERROR_NONE;
674 MMRADIO_LOG_FENTER();
675 gst_init(NULL, NULL);
676 radio->pGstreamer_s = g_new0(mm_radio_gstreamer_s, 1);
678 radio->pGstreamer_s->pipeline = gst_pipeline_new("fmradio");
680 radio->pGstreamer_s->audiosrc = gst_element_factory_make("audiotestsrc", "fm audio src");
681 radio->pGstreamer_s->queue2 = gst_element_factory_make("queue2", "queue2");
682 radio->pGstreamer_s->volume = gst_element_factory_make("volume", "volume");
683 radio->pGstreamer_s->audiosink = gst_element_factory_make("pulsesink", "audio sink");
685 val = __mmradio_get_wave_num(radio);
686 g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, "volume", 0.8, NULL);
688 if (!radio->pGstreamer_s->pipeline || !radio->pGstreamer_s->audiosrc || !radio->pGstreamer_s->queue2 || !radio->pGstreamer_s->volume || !radio->pGstreamer_s->audiosink) {
689 MMRADIO_LOG_DEBUG("One element could not be created. Exiting.");
690 return MM_ERROR_RADIO_NOT_INITIALIZED;
693 gst_bin_add_many(GST_BIN(radio->pGstreamer_s->pipeline),
694 radio->pGstreamer_s->audiosrc,
695 radio->pGstreamer_s->queue2,
696 radio->pGstreamer_s->volume,
697 radio->pGstreamer_s->audiosink,
699 if (!gst_element_link_many(
700 radio->pGstreamer_s->audiosrc,
701 radio->pGstreamer_s->queue2,
702 radio->pGstreamer_s->volume,
703 radio->pGstreamer_s->audiosink,
705 MMRADIO_LOG_DEBUG("failed to element link (src - queue - volue - sink)");
706 return MM_ERROR_RADIO_NOT_INITIALIZED;
708 MMRADIO_LOG_FLEAVE();
712 int _mmradio_start_pipeline(mm_radio_t * radio)
714 int ret = MM_ERROR_NONE;
715 GstStateChangeReturn ret_state;
717 MMRADIO_LOG_FENTER();
719 if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
720 MMRADIO_LOG_ERROR("failed to change pipeline state");
721 return MM_ERROR_RADIO_INVALID_STATE;
724 ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
725 if (ret_state == GST_STATE_CHANGE_FAILURE) {
726 MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
727 return MM_ERROR_RADIO_INVALID_STATE;
729 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
732 MMRADIO_LOG_FLEAVE();
736 int _mmradio_stop_pipeline(mm_radio_t * radio)
738 int ret = MM_ERROR_NONE;
739 GstStateChangeReturn ret_state;
741 MMRADIO_LOG_FENTER();
742 if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
743 MMRADIO_LOG_ERROR("Fail to change pipeline state");
744 return MM_ERROR_RADIO_INVALID_STATE;
747 ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
748 if (ret_state == GST_STATE_CHANGE_FAILURE) {
749 MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
750 return MM_ERROR_RADIO_INVALID_STATE;
752 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
754 MMRADIO_LOG_FLEAVE();
758 int _mmradio_destroy_pipeline(mm_radio_t * radio)
761 GstStateChangeReturn ret_state;
762 MMRADIO_LOG_FENTER();
764 MMRADIO_CHECK_ARG(radio->pGstreamer_s);
766 if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE) {
767 MMRADIO_LOG_DEBUG("failed to change pipeline state");
768 gst_object_unref(radio->pGstreamer_s->pipeline);
769 MMRADIO_GFREEIF(radio->pGstreamer_s);
770 return MM_ERROR_RADIO_INVALID_STATE;
773 ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
774 if (ret_state == GST_STATE_CHANGE_FAILURE) {
775 MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
776 gst_object_unref(radio->pGstreamer_s->pipeline);
777 MMRADIO_GFREEIF(radio->pGstreamer_s);
778 return MM_ERROR_RADIO_INVALID_STATE;
780 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
783 gst_object_unref(radio->pGstreamer_s->pipeline);
784 MMRADIO_GFREEIF(radio->pGstreamer_s);
785 MMRADIO_LOG_FLEAVE();
790 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
792 MMRadioThread_t *p_thread = NULL;
794 MMRADIO_LOG_FENTER();
796 MMRADIO_CHECK_INSTANCE(radio);
797 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
799 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
800 MMRADIO_CHECK_ARG(p_thread);
802 if (p_thread->is_running) {
803 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
804 return MM_ERROR_RADIO_INTERNAL;
807 MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d", direction);
808 radio->seek_direction = direction;
809 p_thread->is_running = true;
810 p_thread->stop = false;
811 MMRADIO_THREAD_SIGNAL(p_thread);
813 MMRADIO_LOG_FLEAVE();
815 return MM_ERROR_NONE;
818 int _mmradio_start_scan(mm_radio_t * radio)
820 MMRadioThread_t *p_thread = NULL;
822 MMRADIO_LOG_FENTER();
824 MMRADIO_CHECK_INSTANCE(radio);
825 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
827 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
828 MMRADIO_CHECK_ARG(p_thread);
830 p_thread->stop = false;
831 p_thread->is_running = true;
833 MMRADIO_THREAD_SIGNAL(p_thread);
835 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
837 MMRADIO_LOG_FLEAVE();
839 return MM_ERROR_NONE;
842 int _mmradio_stop_scan(mm_radio_t * radio)
844 MMRADIO_LOG_FENTER();
846 MMRADIO_CHECK_INSTANCE(radio);
847 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
849 radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
851 MMRADIO_LOG_FLEAVE();
853 return MM_ERROR_NONE;
856 int _mm_radio_get_signal_strength(mm_radio_t * radio, int *value)
858 MMRADIO_LOG_FENTER();
859 MMRADIO_CHECK_INSTANCE(radio);
861 MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
863 /* just return stored frequency if radio device is not ready */
864 if (radio->radio_fd < 0) {
865 MMRADIO_SLOG_DEBUG("Device not ready so sending 0");
867 return MM_ERROR_NONE;
870 unsigned int seed = (unsigned)time(NULL);
871 *value = 0 - ((rand_r(&seed) % 20 + 1) + 80);
872 MMRADIO_LOG_FLEAVE();
873 return MM_ERROR_NONE;
876 void __mmradio_scan_thread(mm_radio_t * radio)
882 MMRadioThread_t *p_thread = NULL;
884 MMRADIO_LOG_FENTER();
885 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
887 p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
888 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
890 MMRADIO_THREAD_LOCK(p_thread);
891 MMRADIO_THREAD_SIGNAL(p_thread);
892 MMRADIO_THREAD_UNLOCK(p_thread);
894 MMRADIO_THREAD_LOCK(p_thread);
896 while (!p_thread->thread_exit) {
897 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
898 MMRADIO_THREAD_WAIT(p_thread);
899 MMRADIO_LOG_DEBUG("scan thread started. got signal.");
901 if (p_thread->thread_exit) {
902 MMRADIO_LOG_DEBUG("exiting scan thread");
906 if (p_thread->stop) {
907 MMRADIO_LOG_INFO("scan was stopped");
911 if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
914 if (radio->old_state == MM_RADIO_STATE_PLAYING)
915 _mmradio_mute(radio);
917 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
918 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
923 while (!p_thread->stop) {
927 MMRADIO_LOG_DEBUG("scanning....");
929 /* now we can get new frequency from radio device */
930 if (p_thread->thread_exit) {
931 MMRADIO_LOG_DEBUG("exiting scan thread");
939 freq = MMRadioEmulatorFreq[emulatoridx];
940 MMRADIO_LOG_DEBUG("freq: %d", freq);
942 if (freq < prev_freq) {
943 MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan");
947 if (p_thread->thread_exit) {
948 MMRADIO_LOG_DEBUG("exiting scan thread");
955 if (freq == prev_freq)
959 MMRADIO_LOG_INFO("scanning : new frequency : [%d]", freq);
961 /* drop if out of range freq is scanned */
962 if (freq >= radio->region_setting.band_max
963 || freq < radio->region_setting.band_min) {
964 MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan", freq);
969 break; /* doesn't need to post */
971 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
973 if (emulatoridx >= EMULATOR_FREQ_MAX)
978 if (radio->old_state == MM_RADIO_STATE_READY) {
979 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
980 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
981 _mmradio_unmute(radio);
982 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
983 /* check if it's limit freq or not */
984 if (__is_tunable_frequency(radio, freq)) {
985 /* now tune to new frequency */
986 if (_mmradio_set_frequency(radio, freq))
987 MMRADIO_LOG_ERROR("failed to tune to new frequency");
992 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
994 __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
996 p_thread->is_running = false;
997 p_thread->stop = false;
1001 MMRADIO_THREAD_UNLOCK(p_thread);
1002 MMRADIO_LOG_FLEAVE();
1007 bool __is_tunable_frequency(mm_radio_t * radio, int freq)
1009 MMRADIO_LOG_FENTER();
1011 MMRADIO_CHECK_INSTANCE(radio);
1013 if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min)
1016 MMRADIO_LOG_FLEAVE();
1021 void __mmradio_seek_thread(mm_radio_t * radio)
1025 int emulatoridx = 0;
1026 MMRadioThread_t *p_thread = NULL;
1028 MMRADIO_LOG_FENTER();
1029 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1031 p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
1032 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1034 MMRADIO_THREAD_LOCK(p_thread);
1035 MMRADIO_THREAD_SIGNAL(p_thread);
1036 MMRADIO_THREAD_UNLOCK(p_thread);
1038 MMRADIO_THREAD_LOCK(p_thread);
1040 while (!p_thread->thread_exit) {
1041 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.\n");
1042 MMRADIO_THREAD_WAIT(p_thread);
1044 if (p_thread->thread_exit) {
1045 MMRADIO_LOG_DEBUG("exiting seek thread");
1049 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1050 MMRADIO_LOG_DEBUG("seeking....");
1052 if (p_thread->stop) {
1053 MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1058 MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
1061 if (radio->seek_direction == MM_RADIO_SEEK_UP) {
1062 for (i = 0; i < EMULATOR_FREQ_MAX; i++) {
1063 if (radio->freq < MMRadioEmulatorFreq[i]) {
1064 freq = MMRadioEmulatorFreq[i];
1069 if (freq == radio->freq) {
1070 freq = MMRadioEmulatorFreq[0];
1074 for (i = EMULATOR_FREQ_MAX - 1; i < 0; i--) {
1075 if (radio->freq > MMRadioEmulatorFreq[i]) {
1076 freq = MMRadioEmulatorFreq[i];
1081 if (freq == radio->freq) {
1082 freq = MMRadioEmulatorFreq[EMULATOR_FREQ_MAX - 1];
1083 emulatoridx = EMULATOR_FREQ_MAX - 1;
1088 MMRADIO_LOG_DEBUG("radio->freq: %d emulatoridx: %d", radio->freq, emulatoridx);
1090 MMRADIO_LOG_DEBUG("found frequency");
1092 /* if same freq is found, ignore it and search next one. */
1093 if (freq == radio->prev_seek_freq) {
1094 MMRADIO_LOG_DEBUG("It's same with previous found one. So, trying next one.");
1098 /* check if it's limit freq or not */
1099 if (__is_tunable_frequency(radio, freq)) {
1100 /* now tune to new frequency */
1101 if (_mmradio_set_frequency(radio, freq)) {
1102 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1107 radio->prev_seek_freq = freq;
1108 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
1109 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
1110 p_thread->stop = true;
1111 p_thread->is_running = false;
1115 /* freq -1 means it's failed to seek */
1116 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
1117 p_thread->stop = true;
1118 p_thread->is_running = false;
1121 MMRADIO_THREAD_UNLOCK(p_thread);
1122 MMRADIO_LOG_FLEAVE();
1127 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param)
1129 MMRADIO_CHECK_INSTANCE(radio);
1131 MMRADIO_LOG_FENTER();
1133 if (!radio->msg_cb) {
1134 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1138 MMRADIO_LOG_DEBUG("address of msg_cb : %d", radio->msg_cb);
1140 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1142 MMRADIO_LOG_FLEAVE();
1147 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command)
1149 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1151 MMRADIO_LOG_FENTER();
1153 MMRADIO_CHECK_INSTANCE(radio);
1155 radio_state = __mmradio_get_state(radio);
1157 MMRADIO_LOG_DEBUG("incomming command : %d current state : %d", command, radio_state);
1160 case MMRADIO_COMMAND_CREATE:
1162 if (radio_state != 0)
1167 case MMRADIO_COMMAND_REALIZE:
1169 if (radio_state == MM_RADIO_STATE_READY ||
1170 radio_state == MM_RADIO_STATE_PLAYING ||
1171 radio_state == MM_RADIO_STATE_SCANNING)
1174 if (radio_state == 0)
1179 case MMRADIO_COMMAND_UNREALIZE:
1181 if (radio_state == MM_RADIO_STATE_NULL)
1184 /* we can call unrealize at any higher state */
1188 case MMRADIO_COMMAND_START:
1190 if (radio_state == MM_RADIO_STATE_PLAYING)
1193 if (radio_state != MM_RADIO_STATE_READY)
1198 case MMRADIO_COMMAND_STOP:
1200 if (radio_state == MM_RADIO_STATE_READY)
1203 if (radio_state != MM_RADIO_STATE_PLAYING)
1208 case MMRADIO_COMMAND_START_SCAN:
1210 if (radio_state == MM_RADIO_STATE_SCANNING)
1213 if (radio_state == MM_RADIO_STATE_NULL)
1218 case MMRADIO_COMMAND_STOP_SCAN:
1220 if (radio_state == MM_RADIO_STATE_READY)
1223 if (radio_state != MM_RADIO_STATE_SCANNING)
1228 case MMRADIO_COMMAND_DESTROY:
1229 case MMRADIO_COMMAND_MUTE:
1230 case MMRADIO_COMMAND_UNMUTE:
1231 case MMRADIO_COMMAND_SET_FREQ:
1232 case MMRADIO_COMMAND_GET_FREQ:
1233 case MMRADIO_COMMAND_SET_REGION:
1235 /* we can do it at any state */
1239 case MMRADIO_COMMAND_SEEK:
1241 if (radio_state != MM_RADIO_STATE_PLAYING)
1246 case MMRADIO_COMMAND_GET_REGION:
1248 if (radio_state == MM_RADIO_STATE_NULL)
1254 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1258 MMRADIO_LOG_DEBUG("status OK");
1260 radio->cmd = command;
1262 MMRADIO_LOG_FLEAVE();
1264 return MM_ERROR_NONE;
1267 MMRADIO_LOG_WARNING("invalid state. current : %d command : %d", radio_state, command);
1268 MMRADIO_LOG_FLEAVE();
1269 return MM_ERROR_RADIO_INVALID_STATE;
1272 MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1273 MMRADIO_LOG_FLEAVE();
1274 return MM_ERROR_RADIO_NO_OP;
1278 static bool __mmradio_set_state(mm_radio_t * radio, int new_state)
1280 MMMessageParamType msg = { 0, };
1281 int msg_type = MM_MESSAGE_UNKNOWN;
1283 MMRADIO_LOG_FENTER();
1286 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1290 if (radio->current_state == new_state && radio->pending_state == 0) {
1291 MMRADIO_LOG_WARNING("we are in same state");
1296 radio->old_state = radio->current_state;
1297 radio->current_state = new_state;
1299 /* fill message param */
1300 msg.union_type = MM_MSG_UNION_STATE;
1301 msg.state.previous = radio->old_state;
1302 msg.state.current = radio->current_state;
1304 if (radio->interrupted_by_resource_conflict) {
1305 __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
1306 MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
1308 msg_type = MM_MESSAGE_STATE_CHANGED;
1309 MMRADIO_POST_MSG(radio, msg_type, &msg);
1312 MMRADIO_LOG_FLEAVE();
1317 static int __mmradio_get_state(mm_radio_t * radio)
1319 MMRADIO_CHECK_INSTANCE(radio);
1321 MMRADIO_LOG_DEBUG("radio state : current : [%d] old : [%d] pending : [%d]",
1322 radio->current_state, radio->old_state, radio->pending_state);
1324 return radio->current_state;
1327 int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type)
1329 MMRADIO_LOG_FENTER();
1330 MMRADIO_CHECK_INSTANCE(radio);
1331 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1333 MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1335 *type = radio->region_setting.country;
1337 MMRADIO_LOG_FLEAVE();
1338 return MM_ERROR_NONE;
1341 int _mmradio_get_region_frequency_range(mm_radio_t * radio, unsigned int *min_freq, unsigned int *max_freq)
1343 MMRADIO_LOG_FENTER();
1344 MMRADIO_CHECK_INSTANCE(radio);
1345 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1347 MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1349 *min_freq = radio->region_setting.band_min;
1350 *max_freq = radio->region_setting.band_max;
1352 MMRADIO_LOG_FLEAVE();
1353 return MM_ERROR_NONE;
1356 int _mmradio_get_channel_spacing(mm_radio_t * radio, unsigned int *ch_spacing)
1358 MMRADIO_LOG_FENTER();
1359 MMRADIO_CHECK_INSTANCE(radio);
1360 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1362 MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1364 *ch_spacing = radio->region_setting.channel_spacing;
1366 MMRADIO_LOG_FLEAVE();
1367 return MM_ERROR_NONE;
1370 static int __mmradio_get_wave_num(mm_radio_t * radio)
1373 MMRADIO_LOG_FENTER();
1374 switch (radio->freq) {
1399 MMRADIO_LOG_DEBUG("freq: %d, val : %d", radio->freq, val);
1400 MMRADIO_LOG_FLEAVE();
1404 static int __resource_release_cb(mm_resource_manager_h rm,
1405 mm_resource_manager_res_h res, void *user_data)
1407 mm_radio_t *radio = NULL;
1409 MMRADIO_LOG_FENTER();
1412 MMRADIO_LOG_ERROR("user_data is null");
1416 radio = (mm_radio_t *)user_data;
1417 radio->radio_resource = NULL;
1419 MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1421 radio->interrupted_by_resource_conflict = TRUE;
1423 MMRADIO_CMD_LOCK(radio);
1424 if (_mmradio_stop(radio) != MM_ERROR_NONE)
1425 MMRADIO_LOG_ERROR("failed to stop radio");
1426 MMRADIO_CMD_UNLOCK(radio);
1428 MMRADIO_LOG_FLEAVE();
1433 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1435 MMRADIO_LOG_FENTER();
1437 MMRADIO_CHECK_INSTANCE(radio);
1438 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1440 MMRADIO_SLOG_DEBUG("Setting %f volume", volume);
1442 /* check volume range */
1443 if (volume < RADIO_MIN_VOLUME || volume > RADIO_MAX_VOLUME) {
1444 MMRADIO_LOG_ERROR("out of volume range");
1445 return MM_ERROR_INVALID_ARGUMENT;
1448 if (radio->radio_fd < 0) {
1449 MMRADIO_LOG_DEBUG("radio device is not opened yet");
1450 radio->local_volume = volume;
1451 return MM_ERROR_NONE;
1454 radio->local_volume = volume;
1456 #ifdef USE_GST_PIPELINE
1457 if (radio->pGstreamer_s && radio->pGstreamer_s->volume) {
1458 g_object_set(radio->pGstreamer_s->volume, "volume", volume, NULL);
1459 MMRADIO_LOG_DEBUG("g_object set volume");
1462 MMRADIO_LOG_FLEAVE();
1464 return MM_ERROR_NONE;
1467 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1469 MMRADIO_LOG_FENTER();
1471 MMRADIO_CHECK_INSTANCE(radio);
1472 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1474 MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1476 MMRADIO_SLOG_DEBUG("volume : %f", radio->local_volume);
1478 *pVolume = radio->local_volume;
1480 MMRADIO_LOG_FLEAVE();
1482 return MM_ERROR_NONE;
1485 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1487 MMRadioThread_t *p_thread = NULL;
1489 MMRADIO_LOG_FENTER();
1491 MMRADIO_CHECK_INSTANCE(radio);
1493 if (type >= MM_RADIO_THREAD_NUM) {
1494 MMRADIO_LOG_WARNING("wrong argument thread type");
1495 return MM_ERROR_RADIO_INTERNAL;
1498 p_thread = &radio->thread[type];
1499 MMRADIO_CHECK_ARG(p_thread);
1501 MMRADIO_INIT_MUTEX(p_thread->mutex);
1502 MMRADIO_INIT_COND(p_thread->cond);
1504 MMRADIO_THREAD_LOCK(p_thread);
1505 p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
1506 (void *)__mmradio_thread_function[type], (void *)radio);
1507 if (p_thread->thread_id) {
1508 MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
1509 MMRADIO_THREAD_UNLOCK(p_thread);
1510 return MM_ERROR_RADIO_INTERNAL;
1513 MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
1514 MMRADIO_THREAD_WAIT(p_thread);
1515 MMRADIO_LOG_DEBUG("[%d] thread started", type);
1516 MMRADIO_THREAD_UNLOCK(p_thread);
1518 return MM_ERROR_NONE;
1521 pthread_mutex_destroy(&p_thread->mutex);
1522 pthread_cond_destroy(&p_thread->cond);
1523 return MM_ERROR_RADIO_INTERNAL;
1527 static int __mmradio_create_threads(mm_radio_t *radio)
1529 int ret = MM_ERROR_NONE;
1532 MMRADIO_LOG_FENTER();
1534 MMRADIO_CHECK_INSTANCE(radio);
1536 MMRADIO_INIT_MUTEX(radio->cmd_lock);
1538 for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
1539 ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
1541 MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
1542 while (--type >= (int)MM_RADIO_THREAD_MSG)
1543 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1548 MMRADIO_LOG_FLEAVE();
1552 pthread_mutex_destroy(&radio->cmd_lock);
1553 MMRADIO_LOG_FLEAVE();
1554 return MM_ERROR_RADIO_INTERNAL;
1557 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1559 MMRadioThread_t *p_thread = NULL;
1560 mm_radio_msg_t *msg = NULL;
1561 MMRADIO_LOG_FENTER();
1563 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1565 if (type >= MM_RADIO_THREAD_NUM) {
1566 MMRADIO_LOG_WARNING("wrong argument thread type");
1570 p_thread = &radio->thread[type];
1571 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1573 if (p_thread->thread) {
1575 case MM_RADIO_THREAD_MSG:
1576 msg = g_slice_new0(mm_radio_msg_t);
1578 MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
1580 msg->msg_type = MM_RADIO_MSG_DESTROY;
1581 g_async_queue_push_front(radio->msg_queue, msg);
1582 pthread_join(p_thread->thread, NULL);
1583 p_thread->thread = 0;
1586 case MM_RADIO_THREAD_SEEK:
1587 case MM_RADIO_THREAD_SCAN:
1588 MMRADIO_THREAD_LOCK(p_thread);
1589 p_thread->thread_exit = true;
1590 MMRADIO_THREAD_SIGNAL(p_thread);
1591 MMRADIO_THREAD_UNLOCK(p_thread);
1592 pthread_join(p_thread->thread, NULL);
1593 p_thread->thread = 0;
1596 MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
1600 MMRADIO_LOG_WARNING("(%d)thread is zero", type);
1603 pthread_mutex_destroy(&p_thread->mutex);
1604 pthread_cond_destroy(&p_thread->cond);
1606 MMRADIO_LOG_FLEAVE();
1609 static void __mmradio_destroy_threads(mm_radio_t *radio)
1611 int type = (int)MM_RADIO_THREAD_NUM;
1612 MMRADIO_LOG_FENTER();
1614 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1617 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1619 pthread_mutex_destroy(&radio->cmd_lock);
1621 MMRADIO_LOG_FLEAVE();
1625 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1627 mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1629 MMRADIO_LOG_ERROR("NULL msg pointer");
1633 msg->msg_type = msg_type;
1634 msg->data = msg_data;
1636 MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
1637 g_async_queue_push(radio->msg_queue, msg);
1640 void __mmradio_msg_thread(mm_radio_t *radio)
1642 mm_radio_msg_t *msg = NULL;
1643 MMRadioThread_t *p_thread = NULL;
1645 MMRADIO_LOG_FENTER();
1646 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1648 p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
1649 MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1651 p_thread->thread_exit = false;
1653 MMRADIO_THREAD_LOCK(p_thread);
1654 MMRADIO_THREAD_SIGNAL(p_thread);
1655 MMRADIO_THREAD_UNLOCK(p_thread);
1657 /*we run a while one loop*/
1658 while (!p_thread->thread_exit) {
1659 msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
1661 MMRADIO_LOG_ERROR("poped message is NULL!");
1665 MMMessageParamType param = {0,};
1667 switch (msg->msg_type) {
1668 case MM_RADIO_MSG_DESTROY:
1669 MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
1670 mm_radio_msg_t *msg_pop = NULL;
1671 while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
1672 if (msg_pop != NULL) {
1673 MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
1674 g_slice_free(mm_radio_msg_t, msg_pop);
1677 p_thread->thread_exit = true;
1679 case MM_RADIO_MSG_SCAN_INFO:
1680 MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
1681 param.radio_scan.frequency = (int) msg->data;
1682 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
1684 case MM_RADIO_MSG_SCAN_STOPPED:
1685 MMRADIO_LOG_INFO("get scan stopped");
1686 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1688 case MM_RADIO_MSG_SCAN_FINISHED:
1689 MMRADIO_LOG_INFO("get scan finished");
1690 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1692 case MM_RADIO_MSG_SEEK_FINISHED:
1693 MMRADIO_LOG_INFO("get seek finished frequency: %d", msg->data);
1694 param.radio_scan.frequency = (int) msg->data;
1695 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1697 case MM_RADIO_MSG_STATE_INTERRUPTED:
1698 MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
1699 param.union_type = MM_MSG_UNION_STATE;
1700 param.state.previous = radio->old_state;
1701 param.state.current = radio->current_state;
1702 param.state.code = msg->data;
1703 MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, ¶m);
1706 MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1711 g_slice_free(mm_radio_msg_t, msg);
1714 MMRADIO_LOG_INFO("msg thread is finished");
1715 MMRADIO_LOG_FLEAVE();