4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 /*===========================================================================================
26 ========================================================================================== */
33 #include <sys/ioctl.h>
39 #include <mm_message.h>
43 #include <mm_sound_focus.h>
44 #include <mm_sound_device.h>
46 #include "mm_radio_priv.h"
48 /*===========================================================================================
49 LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
50 ========================================================================================== */
51 /*---------------------------------------------------------------------------
52 GLOBAL CONSTANT DEFINITIONS:
53 ---------------------------------------------------------------------------*/
55 /*---------------------------------------------------------------------------
56 IMPORTED VARIABLE DECLARATIONS:
57 ---------------------------------------------------------------------------*/
59 /*---------------------------------------------------------------------------
60 IMPORTED FUNCTION DECLARATIONS:
61 ---------------------------------------------------------------------------*/
63 /*---------------------------------------------------------------------------
65 ---------------------------------------------------------------------------*/
68 #define DEFAULT_FREQ 107700
71 #define RADIO_FREQ_FORMAT_SET(x_freq) ((x_freq) * FREQ_FRAC)
72 #define RADIO_FREQ_FORMAT_GET(x_freq) ((x_freq) / FREQ_FRAC)
73 /* If non-zero, wrap around when at the end of the frequency range, else stop seeking */
74 #define DEFAULT_WRAP_AROUND 1
76 #define RADIO_DEFAULT_REGION MM_RADIO_REGION_GROUP_USA
77 #define EMULATOR_FREQ_MAX 5
79 /*---------------------------------------------------------------------------
80 LOCAL CONSTANT DEFINITIONS:
81 ---------------------------------------------------------------------------*/
83 /*---------------------------------------------------------------------------
84 LOCAL DATA TYPE DEFINITIONS:
85 ---------------------------------------------------------------------------*/
87 /*---------------------------------------------------------------------------
88 GLOBAL VARIABLE DEFINITIONS:
89 ---------------------------------------------------------------------------*/
92 /*---------------------------------------------------------------------------
93 LOCAL VARIABLE DEFINITIONS:
94 ---------------------------------------------------------------------------*/
95 /* radio region configuration table */
96 static const MMRadioRegion_t region_table[] = {
97 { /* Notrh America, South America, South Korea, Taiwan, Australia */
98 MM_RADIO_REGION_GROUP_USA, /* region type */
99 MM_RADIO_DEEMPHASIS_75_US, /* de-emphasis */
100 MM_RADIO_FREQ_MIN_87500_KHZ, /* min freq. */
101 MM_RADIO_FREQ_MAX_108000_KHZ, /* max freq. */
104 { /* China, Europe, Africa, Middle East, Hong Kong, India, Indonesia, Russia, Singapore */
105 MM_RADIO_REGION_GROUP_EUROPE,
106 MM_RADIO_DEEMPHASIS_50_US,
107 MM_RADIO_FREQ_MIN_87500_KHZ,
108 MM_RADIO_FREQ_MAX_108000_KHZ,
112 MM_RADIO_REGION_GROUP_JAPAN,
113 MM_RADIO_DEEMPHASIS_50_US,
114 MM_RADIO_FREQ_MIN_76100_KHZ,
115 MM_RADIO_FREQ_MAX_89900_KHZ,
120 static int MMRadioEmulatorFreq[EMULATOR_FREQ_MAX] = {
121 89100, 89900, 91900, 99900, 107700
124 static int EmultatorIdx = 0;
126 /*---------------------------------------------------------------------------
127 LOCAL FUNCTION PROTOTYPES:
128 ---------------------------------------------------------------------------*/
129 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param);
130 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command);
131 static int __mmradio_get_state(mm_radio_t * radio);
132 static bool __mmradio_set_state(mm_radio_t * radio, int new_state);
133 static void __mmradio_seek_thread(mm_radio_t * radio);
134 static void __mmradio_scan_thread(mm_radio_t * radio);
135 static bool __is_tunable_frequency(mm_radio_t * radio, int freq);
136 static int __mmradio_set_deemphasis(mm_radio_t * radio);
137 static int __mmradio_set_band_range(mm_radio_t * radio);
138 static int __mmradio_get_wave_num(mm_radio_t * radio);
139 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
140 mm_sound_focus_state_e focus_state, const char *reason_for_change,
141 const char *additional_info, void *user_data);
142 static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data);
144 /*===========================================================================
146 ========================================================================== */
147 /* --------------------------------------------------------------------------
148 * Name : _mmradio_apply_region()
149 * Desc : update radio region information and set values to device
151 * [in] radio : radio handle
152 * [in] region : region type
153 * [in] update : update region values or not
154 * Return : zero on success, or negative value with error code
155 *---------------------------------------------------------------------------*/
156 int _mmradio_apply_region(mm_radio_t * radio, MMRadioRegionType region, bool update)
158 int ret = MM_ERROR_NONE;
162 MMRADIO_LOG_FENTER();
164 MMRADIO_CHECK_INSTANCE(radio);
165 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
167 /* if needed, radio region must be updated.
168 * Otherwise, just applying settings to device without it.
171 count = ARRAY_SIZE(region_table);
173 /* TODO: if auto is supported...get the region info. here */
175 /* update radio region settings */
176 for (index = 0; index < count; index++) {
177 /* find the region from pre-defined table */
178 if (region_table[index].country == region) {
179 radio->region_setting.country = region_table[index].country;
180 radio->region_setting.deemphasis = region_table[index].deemphasis;
181 radio->region_setting.band_min = region_table[index].band_min;
182 radio->region_setting.band_max = region_table[index].band_max;
183 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
188 /* chech device is opened or not. if it's not ready, skip to apply region to device now */
189 if (radio->radio_fd < 0) {
190 MMRADIO_LOG_DEBUG("not opened device. just updating region info. \n");
191 return MM_ERROR_NONE;
194 MMRADIO_SLOG_DEBUG("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz\n",
195 radio->region_setting.country, radio->region_setting.deemphasis,
196 radio->region_setting.band_min, radio->region_setting.band_max);
198 /* set de-emphsasis to device */
199 ret = __mmradio_set_deemphasis(radio);
201 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set de-emphasis");
203 /* set band range to device */
204 ret = __mmradio_set_band_range(radio);
206 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set band range");
208 MMRADIO_LOG_FLEAVE();
213 int _mmradio_create_radio(mm_radio_t * radio)
217 MMRADIO_LOG_FENTER();
219 MMRADIO_CHECK_INSTANCE(radio);
220 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
222 /* set default value */
223 radio->radio_fd = -1;
224 radio->freq = DEFAULT_FREQ;
225 memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
228 /* create command lock */
229 ret = pthread_mutex_init(&radio->cmd_lock, NULL);
231 MMRADIO_LOG_ERROR("mutex creation failed\n");
232 return MM_ERROR_RADIO_INTERNAL;
235 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
237 /* add device conneted callback */
238 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
239 (mm_sound_device_connected_cb)__mmradio_device_connected_cb,
240 (void *)radio, &radio->subs_id);
242 MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n");
243 return MM_ERROR_RADIO_INTERNAL;
246 /* register to audio focus */
247 ret = mmradio_audio_focus_register(&radio->sm, __mmradio_sound_focus_cb, (void *)radio);
249 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
250 MMRADIO_LOG_ERROR("mmradio_audio_focus_register is failed\n");
251 return MM_ERROR_RADIO_INTERNAL;
254 MMRADIO_LOG_FLEAVE();
256 return MM_ERROR_NONE;
259 int _mmradio_realize(mm_radio_t * radio)
261 int ret = MM_ERROR_NONE;
263 MMRADIO_LOG_FENTER();
265 MMRADIO_CHECK_INSTANCE(radio);
266 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
268 /* open radio device */
269 if (radio->radio_fd == -1) {
270 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
274 radio->radio_fd = 11;
276 MMRADIO_LOG_DEBUG("radio device fd : %d\n", radio->radio_fd);
278 /* check region country type if it's updated or not */
279 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
280 /* not initialized yet. set it with default region */
281 region = RADIO_DEFAULT_REGION;
284 /* already initialized by application */
285 region = radio->region_setting.country;
288 ret = _mmradio_apply_region(radio, region, update);
290 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info");
293 /* ready but nosound */
294 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
297 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
298 #ifdef USE_GST_PIPELINE
299 ret = _mmradio_realize_pipeline(radio);
301 debug_error("_mmradio_realize_pipeline is failed\n");
305 MMRADIO_LOG_FLEAVE();
307 return MM_ERROR_NONE;
310 if (radio->radio_fd >= 0) {
311 close(radio->radio_fd);
312 radio->radio_fd = -1;
315 MMRADIO_LOG_FLEAVE();
317 return MM_ERROR_RADIO_INTERNAL;
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);
338 ret = mmradio_release_audio_focus(&radio->sm);
340 MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n");
343 #ifdef USE_GST_PIPELINE
344 ret = _mmradio_destroy_pipeline(radio);
346 MMRADIO_LOG_ERROR("_mmradio_destroy_pipeline is failed\n");
351 MMRADIO_LOG_FLEAVE();
353 return MM_ERROR_NONE;
356 int _mmradio_destroy(mm_radio_t * radio)
359 MMRADIO_LOG_FENTER();
361 MMRADIO_CHECK_INSTANCE(radio);
362 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
364 ret = mmradio_audio_focus_deregister(&radio->sm);
366 MMRADIO_LOG_ERROR("failed to deregister audio focus\n");
367 return MM_ERROR_RADIO_INTERNAL;
370 ret = mm_sound_remove_device_connected_callback(radio->subs_id);
372 MMRADIO_LOG_ERROR("mm_sound_remove_device_connected_callback error %d\n", ret);
373 return MM_ERROR_RADIO_INTERNAL;
375 _mmradio_unrealize(radio);
377 MMRADIO_LOG_FLEAVE();
379 return MM_ERROR_NONE;
382 /* unit should be KHz */
383 int _mmradio_set_frequency(mm_radio_t * radio, int freq)
385 MMRADIO_LOG_FENTER();
387 MMRADIO_CHECK_INSTANCE(radio);
388 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
390 MMRADIO_SLOG_DEBUG("Setting %d frequency\n", freq);
391 MMRADIO_LOG_DEBUG("radio->freq: %d freq: %d\n", radio->freq, freq);
393 if (radio->radio_fd < 0) {
394 MMRADIO_LOG_DEBUG("radio device is not opened yet\n");
395 return MM_ERROR_NONE;
398 /* check frequency range */
399 if (freq < radio->region_setting.band_min || freq > radio->region_setting.band_max) {
400 MMRADIO_LOG_ERROR("out of frequency range\n", freq);
401 return MM_ERROR_INVALID_ARGUMENT;
406 #ifdef USE_GST_PIPELINE
407 if (radio->pGstreamer_s) {
409 val = __mmradio_get_wave_num(radio);
410 g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, NULL);
413 MMRADIO_LOG_FLEAVE();
415 return MM_ERROR_NONE;
419 int _mmradio_get_frequency(mm_radio_t * radio, int *pFreq)
422 MMRADIO_LOG_FENTER();
424 MMRADIO_CHECK_INSTANCE(radio);
425 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
427 return_val_if_fail(pFreq, MM_ERROR_INVALID_ARGUMENT);
429 /* just return stored frequency if radio device is not ready */
430 if (radio->radio_fd < 0) {
431 MMRADIO_SLOG_DEBUG("freq : %d\n", radio->freq);
432 *pFreq = radio->freq;
433 return MM_ERROR_NONE;
435 /* update freq in handle */
437 *pFreq = radio->freq;
439 MMRADIO_LOG_FLEAVE();
441 return MM_ERROR_NONE;
444 int _mmradio_mute(mm_radio_t * radio)
446 MMRADIO_LOG_FENTER();
448 MMRADIO_CHECK_INSTANCE(radio);
449 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
451 if (radio->radio_fd < 0)
452 return MM_ERROR_RADIO_NOT_INITIALIZED;
454 #ifdef USE_GST_PIPELINE
455 if (radio->pGstreamer_s) {
456 g_object_set(radio->pGstreamer_s->volume, "mute", 1, NULL);
457 MMRADIO_LOG_DEBUG("g_object set mute\n");
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 #ifdef USE_GST_PIPELINE
475 if (radio->pGstreamer_s) {
476 g_object_set(radio->pGstreamer_s->volume, "mute", 0, NULL);
477 MMRADIO_LOG_DEBUG("g_object set un-mute\n");
481 MMRADIO_LOG_FLEAVE();
483 return MM_ERROR_NONE;
486 /* --------------------------------------------------------------------------
487 * Name : __mmradio_set_deemphasis
488 * Desc : apply de-emphasis value to device
490 * [in] radio : radio handle
491 * Return : zero on success, or negative value with error code
492 *---------------------------------------------------------------------------*/
493 int __mmradio_set_deemphasis(mm_radio_t * radio)
497 MMRADIO_LOG_FENTER();
498 return MM_ERROR_NONE;
499 MMRADIO_CHECK_INSTANCE(radio);
501 /* get de-emphasis */
502 switch (radio->region_setting.deemphasis) {
503 case MM_RADIO_DEEMPHASIS_50_US:
504 /* V4L2_DEEMPHASIS_50_uS; */
508 case MM_RADIO_DEEMPHASIS_75_US:
509 /* V4L2_DEEMPHASIS_75_uS; */
514 MMRADIO_LOG_ERROR("not availabe de-emphasis value\n");
515 return MM_ERROR_COMMON_INVALID_ARGUMENT;
518 MMRADIO_LOG_DEBUG("set deemphasis %d", value);
520 MMRADIO_LOG_FLEAVE();
522 return MM_ERROR_NONE;
525 /* --------------------------------------------------------------------------
526 * Name : __mmradio_set_band_range
527 * Desc : apply max and min frequency to device
529 * [in] radio : radio handle
530 * Return : zero on success, or negative value with error code
531 *---------------------------------------------------------------------------*/
532 int __mmradio_set_band_range(mm_radio_t * radio)
534 MMRADIO_LOG_FENTER();
535 return MM_ERROR_NONE;
536 MMRADIO_CHECK_INSTANCE(radio);
538 MMRADIO_LOG_FLEAVE();
540 return MM_ERROR_NONE;
543 int _mmradio_set_message_callback(mm_radio_t * radio, MMMessageCallback callback, void *user_param)
545 MMRADIO_LOG_FENTER();
547 MMRADIO_CHECK_INSTANCE(radio);
549 radio->msg_cb = callback;
550 radio->msg_cb_param = user_param;
552 MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x\n", callback, user_param);
554 MMRADIO_LOG_FLEAVE();
556 return MM_ERROR_NONE;
559 int _mmradio_get_state(mm_radio_t * radio, int *pState)
563 MMRADIO_LOG_FENTER();
565 MMRADIO_CHECK_INSTANCE(radio);
566 return_val_if_fail(pState, MM_ERROR_INVALID_ARGUMENT);
568 state = __mmradio_get_state(radio);
572 MMRADIO_LOG_FLEAVE();
574 return MM_ERROR_NONE;
577 int _mmradio_start(mm_radio_t * radio)
579 int ret = MM_ERROR_NONE;
581 MMRADIO_LOG_FENTER();
583 MMRADIO_CHECK_INSTANCE(radio);
584 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
586 MMRADIO_SLOG_DEBUG("now tune to frequency : %d\n", radio->freq);
588 ret = mmradio_acquire_audio_focus(&radio->sm);
590 MMRADIO_LOG_ERROR("failed to set audio focus\n");
594 /* set stored frequency */
595 _mmradio_set_frequency(radio, radio->freq);
598 /* if( _mmradio_unmute(radio) != MM_ERROR_NONE) */
599 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
601 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
602 #ifdef USE_GST_PIPELINE
603 ret = _mmradio_start_pipeline(radio);
605 debug_error("_mmradio_start_pipeline is failed\n");
610 MMRADIO_LOG_FLEAVE();
615 int _mmradio_stop(mm_radio_t * radio)
617 int ret = MM_ERROR_NONE;
619 MMRADIO_LOG_FENTER();
621 MMRADIO_CHECK_INSTANCE(radio);
622 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
624 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
625 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
627 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
629 #ifdef USE_GST_PIPELINE
630 ret = _mmradio_stop_pipeline(radio);
632 debug_error("_mmradio_stop_pipeline is failed\n");
637 MMRADIO_LOG_FLEAVE();
642 #ifdef USE_GST_PIPELINE
643 int _mmradio_realize_pipeline(mm_radio_t * radio)
645 int ret = MM_ERROR_NONE;
647 MMRADIO_LOG_FENTER();
648 gst_init(NULL, NULL);
649 radio->pGstreamer_s = g_new0(mm_radio_gstreamer_s, 1);
651 radio->pGstreamer_s->pipeline = gst_pipeline_new("fmradio");
653 radio->pGstreamer_s->audiosrc = gst_element_factory_make("audiotestsrc", "fm audio src");
654 radio->pGstreamer_s->queue2 = gst_element_factory_make("queue2", "queue2");
655 radio->pGstreamer_s->volume = gst_element_factory_make("volume", "volume");
656 radio->pGstreamer_s->audiosink = gst_element_factory_make("pulsesink", "audio sink");
658 val = __mmradio_get_wave_num(radio);
659 g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, "volume", 0.8, NULL);
661 if (!radio->pGstreamer_s->pipeline || !radio->pGstreamer_s->audiosrc || !radio->pGstreamer_s->queue2 || !radio->pGstreamer_s->volume || !radio->pGstreamer_s->audiosink) {
662 MMRADIO_LOG_DEBUG("[%s][%05d] One element could not be created. Exiting.\n", __func__, __LINE__);
663 return MM_ERROR_RADIO_NOT_INITIALIZED;
666 gst_bin_add_many(GST_BIN(radio->pGstreamer_s->pipeline),
667 radio->pGstreamer_s->audiosrc,
668 radio->pGstreamer_s->queue2,
669 radio->pGstreamer_s->volume,
670 radio->pGstreamer_s->audiosink,
672 if (!gst_element_link_many(
673 radio->pGstreamer_s->audiosrc,
674 radio->pGstreamer_s->queue2,
675 radio->pGstreamer_s->volume,
676 radio->pGstreamer_s->audiosink,
678 MMRADIO_LOG_DEBUG(, "[%s][%05d] Fail to link b/w appsrc and ffmpeg in rotate\n", __func__, __LINE__);
679 return MM_ERROR_RADIO_NOT_INITIALIZED;
681 MMRADIO_LOG_FLEAVE();
685 int _mmradio_start_pipeline(mm_radio_t * radio)
687 int ret = MM_ERROR_NONE;
688 GstStateChangeReturn ret_state;
690 MMRADIO_LOG_FENTER();
692 if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
693 MMRADIO_LOG_DEBUG("Fail to change pipeline state");
694 gst_object_unref(radio->pGstreamer_s->pipeline);
695 g_free(radio->pGstreamer_s);
696 return MM_ERROR_RADIO_INVALID_STATE;
699 ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
700 if (ret_state == GST_STATE_CHANGE_FAILURE) {
701 MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
702 gst_object_unref(radio->pGstreamer_s->pipeline);
703 g_free(radio->pGstreamer_s);
704 return MM_ERROR_RADIO_INVALID_STATE;
706 MMRADIO_LOG_DEBUG("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state);
709 MMRADIO_LOG_FLEAVE();
713 int _mmradio_stop_pipeline(mm_radio_t * radio)
715 int ret = MM_ERROR_NONE;
716 GstStateChangeReturn ret_state;
718 MMRADIO_LOG_FENTER();
719 if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
720 MMRADIO_LOG_DEBUG("Fail to change pipeline state");
721 gst_object_unref(radio->pGstreamer_s->pipeline);
722 g_free(radio->pGstreamer_s);
723 return MM_ERROR_RADIO_INVALID_STATE;
726 ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
727 if (ret_state == GST_STATE_CHANGE_FAILURE) {
728 MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
729 gst_object_unref(radio->pGstreamer_s->pipeline);
730 g_free(radio->pGstreamer_s);
731 return MM_ERROR_RADIO_INVALID_STATE;
733 MMRADIO_LOG_DEBUG("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state);
735 MMRADIO_LOG_FLEAVE();
739 int _mmradio_destroy_pipeline(mm_radio_t * radio)
742 GstStateChangeReturn ret_state;
743 MMRADIO_LOG_FENTER();
745 if (gst_element_set_state(radio->pGstreamer_s->pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE) {
746 MMRADIO_LOG_DEBUG("Fail to change pipeline state");
747 gst_object_unref(radio->pGstreamer_s->pipeline);
748 g_free(radio->pGstreamer_s);
749 return MM_ERROR_RADIO_INVALID_STATE;
752 ret_state = gst_element_get_state(radio->pGstreamer_s->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
753 if (ret_state == GST_STATE_CHANGE_FAILURE) {
754 MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
755 gst_object_unref(radio->pGstreamer_s->pipeline);
756 g_free(radio->pGstreamer_s);
757 return MM_ERROR_RADIO_INVALID_STATE;
759 MMRADIO_LOG_DEBUG("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state);
762 gst_object_unref(radio->pGstreamer_s->pipeline);
763 g_free(radio->pGstreamer_s);
764 MMRADIO_LOG_FLEAVE();
769 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
771 MMRADIO_LOG_FENTER();
773 MMRADIO_CHECK_INSTANCE(radio);
774 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
778 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
779 /* return MM_ERROR_RADIO_NOT_INITIALIZED; */
781 MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d\n", direction);
782 radio->seek_direction = direction;
784 ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
787 MMRADIO_LOG_DEBUG("failed create thread\n");
788 return MM_ERROR_RADIO_INTERNAL;
791 MMRADIO_LOG_FLEAVE();
793 return MM_ERROR_NONE;
796 int _mmradio_start_scan(mm_radio_t * radio)
798 MMRADIO_LOG_FENTER();
800 MMRADIO_CHECK_INSTANCE(radio);
801 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
805 radio->stop_scan = false;
807 scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
809 if (scan_tr_id != 0) {
810 MMRADIO_LOG_DEBUG("failed to create thread : scan\n");
811 return MM_ERROR_RADIO_NOT_INITIALIZED;
814 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
816 MMRADIO_LOG_FLEAVE();
818 return MM_ERROR_NONE;
821 int _mmradio_stop_scan(mm_radio_t * radio)
823 MMRADIO_LOG_FENTER();
825 MMRADIO_CHECK_INSTANCE(radio);
826 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
828 radio->stop_scan = true;
830 if (radio->scan_thread > 0) {
831 pthread_cancel(radio->scan_thread);
832 pthread_join(radio->scan_thread, NULL);
833 radio->scan_thread = 0;
836 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
837 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
839 MMRADIO_LOG_FLEAVE();
841 return MM_ERROR_NONE;
844 int _mm_radio_get_signal_strength(mm_radio_t * radio, int *value)
846 MMRADIO_LOG_FENTER();
847 MMRADIO_CHECK_INSTANCE(radio);
849 return_val_if_fail(value, MM_ERROR_INVALID_ARGUMENT);
851 /* just return stored frequency if radio device is not ready */
852 if (radio->radio_fd < 0) {
853 MMRADIO_SLOG_DEBUG("Device not ready so sending 0\n");
855 return MM_ERROR_NONE;
858 unsigned int seed = (unsigned)time(NULL);
859 *value = 0 - ((rand_r(&seed) % 20 + 1) + 80);
860 MMRADIO_LOG_FLEAVE();
861 return MM_ERROR_NONE;
864 void __mmradio_scan_thread(mm_radio_t * radio)
870 MMRADIO_LOG_FENTER();
871 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
872 /* if( _mmradio_mute(radio) != MM_ERROR_NONE) */
875 if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
878 if (radio->old_state == MM_RADIO_STATE_PLAYING) {
879 _mmradio_mute(radio);
882 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
883 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
885 while (!radio->stop_scan) {
887 MMMessageParamType param = { 0, };
889 MMRADIO_LOG_DEBUG("scanning....\n");
891 /* now we can get new frequency from radio device */
893 if (radio->stop_scan)
897 freq = MMRadioEmulatorFreq[EmultatorIdx];
898 MMRADIO_LOG_DEBUG("freq: %d", freq);
900 if (freq < prev_freq) {
901 MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan\n");
905 if (freq == prev_freq)
908 prev_freq = param.radio_scan.frequency = freq;
909 MMRADIO_SLOG_DEBUG("scanning : new frequency : [%d]\n", param.radio_scan.frequency);
911 /* drop if max freq is scanned */
912 if (param.radio_scan.frequency == radio->region_setting.band_max
913 || param.radio_scan.frequency > radio->region_setting.band_max
914 || param.radio_scan.frequency < radio->region_setting.band_min) {
915 MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan\n", param.radio_scan.frequency);
919 if (radio->stop_scan)
920 break; /* doesn't need to post */
922 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, ¶m);
927 radio->scan_thread = 0;
929 if (radio->old_state == MM_RADIO_STATE_READY) {
930 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
931 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
932 _mmradio_unmute(radio);
933 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
936 if (!radio->stop_scan)
937 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
939 MMRADIO_LOG_FLEAVE();
946 bool __is_tunable_frequency(mm_radio_t * radio, int freq)
948 MMRADIO_LOG_FENTER();
950 MMRADIO_CHECK_INSTANCE(radio);
952 if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min)
955 MMRADIO_LOG_FLEAVE();
960 void __mmradio_seek_thread(mm_radio_t * radio)
964 bool seek_stop = false;
965 MMMessageParamType param = { 0, };
966 struct v4l2_hw_freq_seek vs = { 0, };
968 vs.tuner = TUNER_INDEX;
969 vs.type = V4L2_TUNER_RADIO;
970 vs.wrap_around = DEFAULT_WRAP_AROUND;
972 MMRADIO_LOG_FENTER();
973 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
975 /* check direction */
976 switch (radio->seek_direction) {
977 case MM_RADIO_SEEK_UP:
985 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
987 MMRADIO_LOG_DEBUG("seeking....\n");
991 /* now we can get new frequency from radio device */
993 MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
996 for (i = 0; i < EMULATOR_FREQ_MAX; i++)
997 if (MMRadioEmulatorFreq[i] == radio->freq)
1000 if (vs.seek_upward == 1) {
1001 if (EmultatorIdx == EMULATOR_FREQ_MAX - 1)
1003 freq = MMRadioEmulatorFreq[EmultatorIdx + 1];
1005 if (EmultatorIdx == 0)
1006 EmultatorIdx = EMULATOR_FREQ_MAX;
1007 freq = MMRadioEmulatorFreq[EmultatorIdx - 1];
1011 MMRADIO_LOG_DEBUG("radio->freq: %d EmultatorIdx: %d", radio->freq, EmultatorIdx);
1014 MMRADIO_LOG_DEBUG("found frequency\n");
1016 /* if same freq is found, ignore it and search next one. */
1017 if (freq == radio->prev_seek_freq) {
1018 MMRADIO_LOG_DEBUG("It's same with previous found one. So, trying next one. \n");
1022 /* check if it's limit freq or not */
1023 if (__is_tunable_frequency(radio, freq)) {
1024 /* now tune to new frequency */
1025 ret = _mmradio_set_frequency(radio, freq);
1027 MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
1032 /* now turn on radio
1033 * In the case of limit freq, tuner should be unmuted.
1034 * Otherwise, sound can't output even though application set new frequency.
1037 ret = _mmradio_unmute(radio);
1039 MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
1043 param.radio_scan.frequency = radio->prev_seek_freq = freq;
1044 MMRADIO_SLOG_DEBUG("seeking : new frequency : [%d]\n", param.radio_scan.frequency);
1045 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1049 radio->seek_thread = 0;
1051 MMRADIO_LOG_FLEAVE();
1057 /* freq -1 means it's failed to seek */
1058 param.radio_scan.frequency = -1;
1059 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, ¶m);
1064 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param)
1066 MMRADIO_CHECK_INSTANCE(radio);
1068 MMRADIO_LOG_FENTER();
1070 if (!radio->msg_cb) {
1071 debug_warning("failed to post a message\n");
1075 MMRADIO_LOG_DEBUG("address of msg_cb : %d\n", radio->msg_cb);
1077 radio->msg_cb(msgtype, param, radio->msg_cb_param);
1079 MMRADIO_LOG_FLEAVE();
1084 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command)
1086 MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1088 MMRADIO_LOG_FENTER();
1090 MMRADIO_CHECK_INSTANCE(radio);
1092 radio_state = __mmradio_get_state(radio);
1094 MMRADIO_LOG_DEBUG("incomming command : %d current state : %d\n", command, radio_state);
1097 case MMRADIO_COMMAND_CREATE:
1099 if (radio_state != 0)
1104 case MMRADIO_COMMAND_REALIZE:
1106 if (radio_state == MM_RADIO_STATE_READY ||
1107 radio_state == MM_RADIO_STATE_PLAYING ||
1108 radio_state == MM_RADIO_STATE_SCANNING)
1111 if (radio_state == 0)
1116 case MMRADIO_COMMAND_UNREALIZE:
1118 if (radio_state == MM_RADIO_STATE_NULL)
1121 /* we can call unrealize at any higher state */
1125 case MMRADIO_COMMAND_START:
1127 if (radio_state == MM_RADIO_STATE_PLAYING)
1130 if (radio_state != MM_RADIO_STATE_READY)
1135 case MMRADIO_COMMAND_STOP:
1137 if (radio_state == MM_RADIO_STATE_READY)
1140 if (radio_state != MM_RADIO_STATE_PLAYING)
1145 case MMRADIO_COMMAND_START_SCAN:
1147 if (radio_state == MM_RADIO_STATE_SCANNING)
1150 if (radio_state == MM_RADIO_STATE_NULL)
1155 case MMRADIO_COMMAND_STOP_SCAN:
1157 if (radio_state == MM_RADIO_STATE_READY)
1160 if (radio_state != MM_RADIO_STATE_SCANNING)
1165 case MMRADIO_COMMAND_DESTROY:
1166 case MMRADIO_COMMAND_MUTE:
1167 case MMRADIO_COMMAND_UNMUTE:
1168 case MMRADIO_COMMAND_SET_FREQ:
1169 case MMRADIO_COMMAND_GET_FREQ:
1170 case MMRADIO_COMMAND_SET_REGION:
1172 /* we can do it at any state */
1176 case MMRADIO_COMMAND_SEEK:
1178 if (radio_state != MM_RADIO_STATE_PLAYING)
1183 case MMRADIO_COMMAND_GET_REGION:
1185 if (radio_state == MM_RADIO_STATE_NULL)
1191 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it\n");
1195 MMRADIO_LOG_DEBUG("status OK\n");
1197 radio->cmd = command;
1199 MMRADIO_LOG_FLEAVE();
1201 return MM_ERROR_NONE;
1204 debug_warning("invalid state. current : %d command : %d\n", radio_state, command);
1205 MMRADIO_LOG_FLEAVE();
1206 return MM_ERROR_RADIO_INVALID_STATE;
1209 debug_warning("mm-radio is in the desired state(%d). doing noting\n", radio_state);
1210 MMRADIO_LOG_FLEAVE();
1211 return MM_ERROR_RADIO_NO_OP;
1215 static bool __mmradio_set_state(mm_radio_t * radio, int new_state)
1217 MMMessageParamType msg = { 0, };
1218 int msg_type = MM_MESSAGE_UNKNOWN;
1220 MMRADIO_LOG_FENTER();
1221 MMRADIO_CHECK_INSTANCE(radio);
1224 debug_warning("calling set_state with invalid radio handle\n");
1228 if (radio->current_state == new_state && radio->pending_state == 0) {
1229 debug_warning("we are in same state\n");
1234 radio->old_state = radio->current_state;
1235 radio->current_state = new_state;
1237 /* fill message param */
1238 msg.state.previous = radio->old_state;
1239 msg.state.current = radio->current_state;
1241 /* post message to application */
1242 switch (radio->sm.by_focus_cb) {
1243 case MMRADIO_FOCUS_CB_NONE:
1245 msg_type = MM_MESSAGE_STATE_CHANGED;
1246 MMRADIO_POST_MSG(radio, msg_type, &msg);
1250 case MMRADIO_FOCUS_CB_POSTMSG:
1252 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1253 msg.union_type = MM_MSG_UNION_CODE;
1254 msg.code = radio->sm.event_src;
1255 MMRADIO_POST_MSG(radio, msg_type, &msg);
1259 case MMRADIO_FOCUS_CB_SKIP_POSTMSG:
1264 MMRADIO_LOG_FLEAVE();
1269 static int __mmradio_get_state(mm_radio_t * radio)
1271 MMRADIO_CHECK_INSTANCE(radio);
1273 MMRADIO_LOG_DEBUG("radio state : current : [%d] old : [%d] pending : [%d]\n",
1274 radio->current_state, radio->old_state, radio->pending_state);
1276 return radio->current_state;
1279 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
1280 mm_sound_focus_state_e focus_state, const char *reason_for_change,
1281 const char *additional_info, void *user_data)
1283 mm_radio_t *radio = (mm_radio_t *) user_data;
1284 enum MMMessageInterruptedCode event_source;
1285 int result = MM_ERROR_NONE;
1286 int postMsg = false;
1288 MMRADIO_LOG_FENTER();
1289 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1291 mmradio_get_audio_focus_reason(focus_state, reason_for_change, &event_source, &postMsg);
1292 radio->sm.event_src = event_source;
1294 switch (focus_state) {
1295 case FOCUS_IS_RELEASED:{
1296 radio->sm.cur_focus_type &= ~focus_type;
1297 radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG;
1299 result = _mmradio_stop(radio);
1301 MMRADIO_LOG_ERROR("failed to stop radio\n");
1303 MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sm.cur_focus_type);
1307 case FOCUS_IS_ACQUIRED:{
1308 MMMessageParamType msg = { 0, };
1309 msg.union_type = MM_MSG_UNION_CODE;
1310 msg.code = event_source;
1312 radio->sm.cur_focus_type |= focus_type;
1314 if ((postMsg) && (FOCUS_FOR_BOTH == radio->sm.cur_focus_type))
1315 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1317 radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_NONE;
1319 MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sm.cur_focus_type);
1324 MMRADIO_LOG_DEBUG("Unknown focus_state\n");
1328 MMRADIO_LOG_FLEAVE();
1331 static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data)
1333 mm_radio_t *radio = (mm_radio_t *) user_data;
1334 int result = MM_ERROR_NONE;
1335 mm_sound_device_type_e type;
1337 MMRADIO_LOG_FENTER();
1338 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1340 if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) {
1341 debug_error("getting device type failed");
1344 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
1345 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
1346 case MM_SOUND_DEVICE_TYPE_HDMI:
1347 case MM_SOUND_DEVICE_TYPE_MIRRORING:
1348 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
1349 if (!is_connected) {
1350 MMRADIO_LOG_ERROR("sound device unplugged");
1351 radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG;
1352 radio->sm.event_src = MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG;
1354 result = _mmradio_stop(radio);
1355 if (result != MM_ERROR_NONE)
1356 MMRADIO_LOG_ERROR("failed to stop radio\n");
1363 MMRADIO_LOG_FLEAVE();
1366 int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type)
1368 MMRADIO_LOG_FENTER();
1369 MMRADIO_CHECK_INSTANCE(radio);
1370 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1372 return_val_if_fail(type, MM_ERROR_INVALID_ARGUMENT);
1374 *type = radio->region_setting.country;
1376 MMRADIO_LOG_FLEAVE();
1377 return MM_ERROR_NONE;
1380 int _mmradio_get_region_frequency_range(mm_radio_t * radio, unsigned int *min_freq, unsigned int *max_freq)
1382 MMRADIO_LOG_FENTER();
1383 MMRADIO_CHECK_INSTANCE(radio);
1384 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1386 return_val_if_fail(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1388 *min_freq = radio->region_setting.band_min;
1389 *max_freq = radio->region_setting.band_max;
1391 MMRADIO_LOG_FLEAVE();
1392 return MM_ERROR_NONE;
1395 int _mmradio_get_channel_spacing(mm_radio_t * radio, unsigned int *ch_spacing)
1397 MMRADIO_LOG_FENTER();
1398 MMRADIO_CHECK_INSTANCE(radio);
1399 MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1401 return_val_if_fail(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1403 *ch_spacing = radio->region_setting.channel_spacing;
1405 MMRADIO_LOG_FLEAVE();
1406 return MM_ERROR_NONE;
1409 static int __mmradio_get_wave_num(mm_radio_t * radio)
1412 MMRADIO_LOG_FENTER();
1413 switch (radio->freq) {
1438 MMRADIO_LOG_DEBUG("freq: %d, val : %d", radio->freq, val);
1439 MMRADIO_LOG_FLEAVE();