Expand the prestate of radio_scan_start function
[platform/core/multimedia/libmm-radio.git] / src / mm_radio_priv_emulator.c
1 /*
2  * libmm-radio
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 /*===========================================================================================
23 |                                                                                                                                                                                       |
24 |  INCLUDE FILES                                                                                                                                                        |
25 |                                                                                                                                                                                       |
26 ========================================================================================== */
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #include <unistd.h>
35 #include <errno.h>
36
37 #include <mm_error.h>
38 #include <mm_debug.h>
39 #include <mm_message.h>
40 #include <time.h>
41
42 #include <mm_sound.h>
43 #include <mm_sound_focus.h>
44 #include <mm_sound_device.h>
45
46 #include "mm_radio_priv.h"
47
48 /*===========================================================================================
49   LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
50 ========================================================================================== */
51 /*---------------------------------------------------------------------------
52     GLOBAL CONSTANT DEFINITIONS:
53 ---------------------------------------------------------------------------*/
54
55 /*---------------------------------------------------------------------------
56     IMPORTED VARIABLE DECLARATIONS:
57 ---------------------------------------------------------------------------*/
58
59 /*---------------------------------------------------------------------------
60     IMPORTED FUNCTION DECLARATIONS:
61 ---------------------------------------------------------------------------*/
62
63 /*---------------------------------------------------------------------------
64     LOCAL #defines:
65 ---------------------------------------------------------------------------*/
66 #define TUNER_INDEX                             0
67
68 #define DEFAULT_FREQ                            107700
69
70 #define FREQ_FRAC                               16
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
75
76 #define RADIO_DEFAULT_REGION    MM_RADIO_REGION_GROUP_USA
77 #define EMULATOR_FREQ_MAX               5
78
79 /*---------------------------------------------------------------------------
80     LOCAL CONSTANT DEFINITIONS:
81 ---------------------------------------------------------------------------*/
82
83 /*---------------------------------------------------------------------------
84     LOCAL DATA TYPE DEFINITIONS:
85 ---------------------------------------------------------------------------*/
86
87 /*---------------------------------------------------------------------------
88     GLOBAL VARIABLE DEFINITIONS:
89 ---------------------------------------------------------------------------*/
90 extern int errno;
91
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. */
102          50,
103          },
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,
109          50,
110          },
111         {
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,
116          50,
117          },
118 };
119
120 static int MMRadioEmulatorFreq[EMULATOR_FREQ_MAX] = {
121         89100, 89900, 91900, 99900, 107700
122 };
123
124 static int EmultatorIdx = 0;
125
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);
143
144 /*===========================================================================
145   FUNCTION DEFINITIONS
146 ========================================================================== */
147 /* --------------------------------------------------------------------------
148  * Name   : _mmradio_apply_region()
149  * Desc   : update radio region information and set values to device
150  * Param  :
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)
157 {
158         int ret = MM_ERROR_NONE;
159         int count = 0;
160         int index = 0;
161
162         MMRADIO_LOG_FENTER();
163
164         MMRADIO_CHECK_INSTANCE(radio);
165         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
166
167         /* if needed, radio region must be updated.
168          * Otherwise, just applying settings to device without it.
169          */
170         if (update) {
171                 count = ARRAY_SIZE(region_table);
172
173                 /* TODO: if auto is supported...get the region info. here */
174
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;
184                         }
185                 }
186         }
187
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;
192         }
193
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);
197
198         /* set de-emphsasis to device */
199         ret = __mmradio_set_deemphasis(radio);
200
201         MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set de-emphasis");
202
203         /* set band range to device */
204         ret = __mmradio_set_band_range(radio);
205
206         MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set band range");
207
208         MMRADIO_LOG_FLEAVE();
209
210         return ret;
211 }
212
213 int _mmradio_create_radio(mm_radio_t * radio)
214 {
215         int ret = 0;
216
217         MMRADIO_LOG_FENTER();
218
219         MMRADIO_CHECK_INSTANCE(radio);
220         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
221
222         /* set default value */
223         radio->radio_fd = -1;
224         radio->freq = DEFAULT_FREQ;
225         memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
226         radio->subs_id = 0;
227
228         /* create command lock */
229         ret = pthread_mutex_init(&radio->cmd_lock, NULL);
230         if (ret) {
231                 MMRADIO_LOG_ERROR("mutex creation failed\n");
232                 return MM_ERROR_RADIO_INTERNAL;
233         }
234
235         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
236
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);
241         if (ret) {
242                 MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed\n");
243                 return MM_ERROR_RADIO_INTERNAL;
244         }
245
246         /* register to audio focus */
247         ret = mmradio_audio_focus_register(&radio->sm, __mmradio_sound_focus_cb, (void *)radio);
248         if (ret) {
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;
252         }
253
254         MMRADIO_LOG_FLEAVE();
255
256         return MM_ERROR_NONE;
257 }
258
259 int _mmradio_realize(mm_radio_t * radio)
260 {
261         int ret = MM_ERROR_NONE;
262
263         MMRADIO_LOG_FENTER();
264
265         MMRADIO_CHECK_INSTANCE(radio);
266         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
267
268         /* open radio device */
269         if (radio->radio_fd == -1) {
270                 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
271                 bool update = false;
272
273                 /* open device */
274                 radio->radio_fd = 11;
275
276                 MMRADIO_LOG_DEBUG("radio device fd : %d\n", radio->radio_fd);
277
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;
282                         update = true;
283                 } else {
284                         /* already initialized by application */
285                         region = radio->region_setting.country;
286                 }
287
288                 ret = _mmradio_apply_region(radio, region, update);
289
290                 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info");
291         }
292
293         /* ready but nosound */
294         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
295         /*      goto error; */
296
297         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
298 #ifdef USE_GST_PIPELINE
299         ret = _mmradio_realize_pipeline(radio);
300         if (ret) {
301                 debug_error("_mmradio_realize_pipeline is failed\n");
302                 return ret;
303         }
304 #endif
305         MMRADIO_LOG_FLEAVE();
306
307         return MM_ERROR_NONE;
308
309 /* error:
310         if (radio->radio_fd >= 0) {
311                 close(radio->radio_fd);
312                 radio->radio_fd = -1;
313         }
314
315         MMRADIO_LOG_FLEAVE();
316
317         return MM_ERROR_RADIO_INTERNAL;
318 */
319 }
320
321 int _mmradio_unrealize(mm_radio_t * radio)
322 {
323         int ret = MM_ERROR_NONE;
324
325         MMRADIO_LOG_FENTER();
326
327         MMRADIO_CHECK_INSTANCE(radio);
328         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
329
330         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
331         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
332
333         /* close radio device here !!!! */
334         if (radio->radio_fd >= 0)
335                 radio->radio_fd = -1;
336
337         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
338         ret = mmradio_release_audio_focus(&radio->sm);
339         if (ret) {
340                 MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed\n");
341                 return ret;
342         }
343 #ifdef USE_GST_PIPELINE
344         ret = _mmradio_destroy_pipeline(radio);
345         if (ret) {
346                 MMRADIO_LOG_ERROR("_mmradio_destroy_pipeline is failed\n");
347                 return ret;
348         }
349 #endif
350
351         MMRADIO_LOG_FLEAVE();
352
353         return MM_ERROR_NONE;
354 }
355
356 int _mmradio_destroy(mm_radio_t * radio)
357 {
358         int ret = 0;
359         MMRADIO_LOG_FENTER();
360
361         MMRADIO_CHECK_INSTANCE(radio);
362         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
363
364         ret = mmradio_audio_focus_deregister(&radio->sm);
365         if (ret) {
366                 MMRADIO_LOG_ERROR("failed to deregister audio focus\n");
367                 return MM_ERROR_RADIO_INTERNAL;
368         }
369
370         ret = mm_sound_remove_device_connected_callback(radio->subs_id);
371         if (ret) {
372                 MMRADIO_LOG_ERROR("mm_sound_remove_device_connected_callback error %d\n", ret);
373                 return MM_ERROR_RADIO_INTERNAL;
374         }
375         _mmradio_unrealize(radio);
376
377         MMRADIO_LOG_FLEAVE();
378
379         return MM_ERROR_NONE;
380 }
381
382 /* unit should be KHz */
383 int _mmradio_set_frequency(mm_radio_t * radio, int freq)
384 {
385         MMRADIO_LOG_FENTER();
386
387         MMRADIO_CHECK_INSTANCE(radio);
388         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
389
390         MMRADIO_SLOG_DEBUG("Setting %d frequency\n", freq);
391         MMRADIO_LOG_DEBUG("radio->freq: %d freq: %d\n", radio->freq, freq);
392
393         if (radio->radio_fd < 0) {
394                 MMRADIO_LOG_DEBUG("radio device is not opened yet\n");
395                 return MM_ERROR_NONE;
396         }
397
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;
402         }
403
404         radio->freq = freq;
405
406 #ifdef USE_GST_PIPELINE
407         if (radio->pGstreamer_s) {
408                 int val = 0;
409                 val = __mmradio_get_wave_num(radio);
410                 g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, NULL);
411         }
412 #endif
413         MMRADIO_LOG_FLEAVE();
414
415         return MM_ERROR_NONE;
416
417 }
418
419 int _mmradio_get_frequency(mm_radio_t * radio, int *pFreq)
420 {
421
422         MMRADIO_LOG_FENTER();
423
424         MMRADIO_CHECK_INSTANCE(radio);
425         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
426
427         return_val_if_fail(pFreq, MM_ERROR_INVALID_ARGUMENT);
428
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;
434         }
435         /* update freq in handle */
436
437         *pFreq = radio->freq;
438
439         MMRADIO_LOG_FLEAVE();
440
441         return MM_ERROR_NONE;
442 }
443
444 int _mmradio_mute(mm_radio_t * radio)
445 {
446         MMRADIO_LOG_FENTER();
447
448         MMRADIO_CHECK_INSTANCE(radio);
449         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
450
451         if (radio->radio_fd < 0)
452                 return MM_ERROR_RADIO_NOT_INITIALIZED;
453
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");
458         }
459 #endif
460         MMRADIO_LOG_FLEAVE();
461
462         return MM_ERROR_NONE;
463
464 }
465
466 int _mmradio_unmute(mm_radio_t * radio)
467 {
468         MMRADIO_LOG_FENTER();
469
470         MMRADIO_CHECK_INSTANCE(radio);
471         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
472         MMRADIO_CHECK_DEVICE_STATE(radio);
473
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");
478         }
479 #endif
480
481         MMRADIO_LOG_FLEAVE();
482
483         return MM_ERROR_NONE;
484 }
485
486 /* --------------------------------------------------------------------------
487  * Name   : __mmradio_set_deemphasis
488  * Desc   : apply de-emphasis value to device
489  * Param  :
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)
494 {
495         int value = 0;
496
497         MMRADIO_LOG_FENTER();
498         return MM_ERROR_NONE;
499         MMRADIO_CHECK_INSTANCE(radio);
500
501         /* get de-emphasis */
502         switch (radio->region_setting.deemphasis) {
503         case MM_RADIO_DEEMPHASIS_50_US:
504                 /* V4L2_DEEMPHASIS_50_uS; */
505                 value = 1;
506                 break;
507
508         case MM_RADIO_DEEMPHASIS_75_US:
509                 /* V4L2_DEEMPHASIS_75_uS; */
510                 value = 2;
511                 break;
512
513         default:
514                 MMRADIO_LOG_ERROR("not availabe de-emphasis value\n");
515                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
516         }
517
518         MMRADIO_LOG_DEBUG("set deemphasis %d", value);
519
520         MMRADIO_LOG_FLEAVE();
521
522         return MM_ERROR_NONE;
523 }
524
525 /* --------------------------------------------------------------------------
526  * Name   : __mmradio_set_band_range
527  * Desc   : apply max and min frequency to device
528  * Param  :
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)
533 {
534         MMRADIO_LOG_FENTER();
535         return MM_ERROR_NONE;
536         MMRADIO_CHECK_INSTANCE(radio);
537
538         MMRADIO_LOG_FLEAVE();
539
540         return MM_ERROR_NONE;
541 }
542
543 int _mmradio_set_message_callback(mm_radio_t * radio, MMMessageCallback callback, void *user_param)
544 {
545         MMRADIO_LOG_FENTER();
546
547         MMRADIO_CHECK_INSTANCE(radio);
548
549         radio->msg_cb = callback;
550         radio->msg_cb_param = user_param;
551
552         MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x\n", callback, user_param);
553
554         MMRADIO_LOG_FLEAVE();
555
556         return MM_ERROR_NONE;
557 }
558
559 int _mmradio_get_state(mm_radio_t * radio, int *pState)
560 {
561         int state = 0;
562
563         MMRADIO_LOG_FENTER();
564
565         MMRADIO_CHECK_INSTANCE(radio);
566         return_val_if_fail(pState, MM_ERROR_INVALID_ARGUMENT);
567
568         state = __mmradio_get_state(radio);
569
570         *pState = state;
571
572         MMRADIO_LOG_FLEAVE();
573
574         return MM_ERROR_NONE;
575 }
576
577 int _mmradio_start(mm_radio_t * radio)
578 {
579         int ret = MM_ERROR_NONE;
580
581         MMRADIO_LOG_FENTER();
582
583         MMRADIO_CHECK_INSTANCE(radio);
584         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
585
586         MMRADIO_SLOG_DEBUG("now tune to frequency : %d\n", radio->freq);
587
588         ret = mmradio_acquire_audio_focus(&radio->sm);
589         if (ret) {
590                 MMRADIO_LOG_ERROR("failed to set audio focus\n");
591                 return ret;
592         }
593
594         /* set stored frequency */
595         _mmradio_set_frequency(radio, radio->freq);
596
597         /* unmute */
598         /*  if( _mmradio_unmute(radio) != MM_ERROR_NONE) */
599         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
600
601         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
602 #ifdef USE_GST_PIPELINE
603         ret = _mmradio_start_pipeline(radio);
604         if (ret) {
605                 debug_error("_mmradio_start_pipeline is failed\n");
606                 return ret;
607         }
608 #endif
609
610         MMRADIO_LOG_FLEAVE();
611
612         return ret;
613 }
614
615 int _mmradio_stop(mm_radio_t * radio)
616 {
617         int ret = MM_ERROR_NONE;
618
619         MMRADIO_LOG_FENTER();
620
621         MMRADIO_CHECK_INSTANCE(radio);
622         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
623
624         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
625         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
626
627         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
628
629 #ifdef USE_GST_PIPELINE
630         ret = _mmradio_stop_pipeline(radio);
631         if (ret) {
632                 debug_error("_mmradio_stop_pipeline is failed\n");
633                 return ret;
634         }
635 #endif
636
637         MMRADIO_LOG_FLEAVE();
638
639         return ret;
640 }
641
642 #ifdef USE_GST_PIPELINE
643 int _mmradio_realize_pipeline(mm_radio_t * radio)
644 {
645         int ret = MM_ERROR_NONE;
646         int val = 0;
647         MMRADIO_LOG_FENTER();
648         gst_init(NULL, NULL);
649         radio->pGstreamer_s = g_new0(mm_radio_gstreamer_s, 1);
650
651         radio->pGstreamer_s->pipeline = gst_pipeline_new("fmradio");
652
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");
657
658         val = __mmradio_get_wave_num(radio);
659         g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, "volume", 0.8, NULL);
660
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;
664         }
665
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,
671                          NULL);
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,
677                 NULL)) {
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;
680         }
681         MMRADIO_LOG_FLEAVE();
682         return ret;
683 }
684
685 int _mmradio_start_pipeline(mm_radio_t * radio)
686 {
687         int ret = MM_ERROR_NONE;
688         GstStateChangeReturn ret_state;
689
690         MMRADIO_LOG_FENTER();
691
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;
697         }
698
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;
705         } else {
706                 MMRADIO_LOG_DEBUG("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state);
707         }
708
709         MMRADIO_LOG_FLEAVE();
710         return ret;
711 }
712
713 int _mmradio_stop_pipeline(mm_radio_t * radio)
714 {
715         int ret = MM_ERROR_NONE;
716         GstStateChangeReturn ret_state;
717
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;
724         }
725
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;
732         } else {
733                 MMRADIO_LOG_DEBUG("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state);
734         }
735         MMRADIO_LOG_FLEAVE();
736         return ret;
737 }
738
739 int _mmradio_destroy_pipeline(mm_radio_t * radio)
740 {
741         int ret = 0;
742         GstStateChangeReturn ret_state;
743         MMRADIO_LOG_FENTER();
744
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;
750         }
751
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;
758         } else {
759                 MMRADIO_LOG_DEBUG("[%s][%05d] GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", __func__, __LINE__, ret_state);
760         }
761
762         gst_object_unref(radio->pGstreamer_s->pipeline);
763         g_free(radio->pGstreamer_s);
764         MMRADIO_LOG_FLEAVE();
765         return ret;
766 }
767 #endif
768
769 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
770 {
771         MMRADIO_LOG_FENTER();
772
773         MMRADIO_CHECK_INSTANCE(radio);
774         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
775
776         int ret = 0;
777
778         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
779         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
780
781         MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d\n", direction);
782         radio->seek_direction = direction;
783
784         ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
785
786         if (ret) {
787                 MMRADIO_LOG_DEBUG("failed create thread\n");
788                 return MM_ERROR_RADIO_INTERNAL;
789         }
790
791         MMRADIO_LOG_FLEAVE();
792
793         return MM_ERROR_NONE;
794 }
795
796 int _mmradio_start_scan(mm_radio_t * radio)
797 {
798         MMRADIO_LOG_FENTER();
799
800         MMRADIO_CHECK_INSTANCE(radio);
801         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
802
803         int scan_tr_id = 0;
804
805         radio->stop_scan = false;
806
807         scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
808
809         if (scan_tr_id != 0) {
810                 MMRADIO_LOG_DEBUG("failed to create thread : scan\n");
811                 return MM_ERROR_RADIO_NOT_INITIALIZED;
812         }
813
814         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
815
816         MMRADIO_LOG_FLEAVE();
817
818         return MM_ERROR_NONE;
819 }
820
821 int _mmradio_stop_scan(mm_radio_t * radio)
822 {
823         MMRADIO_LOG_FENTER();
824
825         MMRADIO_CHECK_INSTANCE(radio);
826         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
827
828         radio->stop_scan = true;
829
830         if (radio->scan_thread > 0) {
831                 pthread_cancel(radio->scan_thread);
832                 pthread_join(radio->scan_thread, NULL);
833                 radio->scan_thread = 0;
834         }
835
836         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
837         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
838
839         MMRADIO_LOG_FLEAVE();
840
841         return MM_ERROR_NONE;
842 }
843
844 int _mm_radio_get_signal_strength(mm_radio_t * radio, int *value)
845 {
846         MMRADIO_LOG_FENTER();
847         MMRADIO_CHECK_INSTANCE(radio);
848
849         return_val_if_fail(value, MM_ERROR_INVALID_ARGUMENT);
850
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");
854                 *value = 0;
855                 return MM_ERROR_NONE;
856         }
857
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;
862 }
863
864 void __mmradio_scan_thread(mm_radio_t * radio)
865 {
866
867         int prev_freq = 0;
868         EmultatorIdx = 0;
869
870         MMRADIO_LOG_FENTER();
871         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
872         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
873         /*      goto FINISHED; */
874
875         if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
876                 goto FINISHED;
877
878         if (radio->old_state == MM_RADIO_STATE_PLAYING) {
879                 _mmradio_mute(radio);
880         }
881
882         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
883         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
884
885         while (!radio->stop_scan) {
886                 int freq = 0;
887                 MMMessageParamType param = { 0, };
888
889                 MMRADIO_LOG_DEBUG("scanning....\n");
890
891                 /* now we can get new frequency from radio device */
892
893                 if (radio->stop_scan)
894                         break;
895                 {
896                         usleep(1000 * 1000);
897                         freq = MMRadioEmulatorFreq[EmultatorIdx];
898                         MMRADIO_LOG_DEBUG("freq: %d", freq);
899
900                         if (freq < prev_freq) {
901                                 MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan\n");
902                                 break;
903                         }
904
905                         if (freq == prev_freq)
906                                 continue;
907
908                         prev_freq = param.radio_scan.frequency = freq;
909                         MMRADIO_SLOG_DEBUG("scanning : new frequency : [%d]\n", param.radio_scan.frequency);
910
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);
916                                 break;
917                         }
918
919                         if (radio->stop_scan)
920                                 break;                  /* doesn't need to post */
921
922                         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
923                         EmultatorIdx++;
924                 }
925         }
926  FINISHED:
927         radio->scan_thread = 0;
928
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);
934         }
935
936         if (!radio->stop_scan)
937                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
938
939         MMRADIO_LOG_FLEAVE();
940
941         pthread_exit(NULL);
942
943         return;
944 }
945
946 bool __is_tunable_frequency(mm_radio_t * radio, int freq)
947 {
948         MMRADIO_LOG_FENTER();
949
950         MMRADIO_CHECK_INSTANCE(radio);
951
952         if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min)
953                 return false;
954
955         MMRADIO_LOG_FLEAVE();
956
957         return true;
958 }
959
960 void __mmradio_seek_thread(mm_radio_t * radio)
961 {
962         int ret = 0;
963         int freq = 0;
964         bool seek_stop = false;
965         MMMessageParamType param = { 0, };
966         struct v4l2_hw_freq_seek vs = { 0, };
967
968         vs.tuner = TUNER_INDEX;
969         vs.type = V4L2_TUNER_RADIO;
970         vs.wrap_around = DEFAULT_WRAP_AROUND;
971
972         MMRADIO_LOG_FENTER();
973         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
974
975         /* check direction */
976         switch (radio->seek_direction) {
977         case MM_RADIO_SEEK_UP:
978                 vs.seek_upward = 1;
979                 break;
980         default:
981                 vs.seek_upward = 0;
982                 break;
983         }
984
985         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
986
987         MMRADIO_LOG_DEBUG("seeking....\n");
988
989         EmultatorIdx = 0;
990         while (!seek_stop) {
991                 /* now we can get new frequency from radio device */
992                 {
993                         MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
994
995                         int i = 0;
996                         for (i = 0; i < EMULATOR_FREQ_MAX; i++)
997                                 if (MMRadioEmulatorFreq[i] == radio->freq)
998                                         EmultatorIdx = i;
999
1000                         if (vs.seek_upward == 1) {
1001                                 if (EmultatorIdx == EMULATOR_FREQ_MAX - 1)
1002                                         EmultatorIdx = -1;
1003                                 freq = MMRadioEmulatorFreq[EmultatorIdx + 1];
1004                         } else {
1005                                 if (EmultatorIdx == 0)
1006                                         EmultatorIdx = EMULATOR_FREQ_MAX;
1007                                 freq = MMRadioEmulatorFreq[EmultatorIdx - 1];
1008                         }
1009
1010                         radio->freq = freq;
1011                         MMRADIO_LOG_DEBUG("radio->freq: %d EmultatorIdx: %d", radio->freq, EmultatorIdx);
1012                 }
1013
1014                 MMRADIO_LOG_DEBUG("found frequency\n");
1015
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");
1019                         continue;
1020                 }
1021
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);
1026                         if (ret) {
1027                                 MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
1028                                 goto SEEK_FAILED;
1029                         }
1030                 }
1031
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.
1035                  */
1036 #if 0
1037                 ret = _mmradio_unmute(radio);
1038                 if (ret) {
1039                         MMRADIO_LOG_ERROR("failed to tune to new frequency\n");
1040                         goto SEEK_FAILED;
1041                 }
1042 #endif
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, &param);
1046                 seek_stop = true;
1047         }
1048
1049         radio->seek_thread = 0;
1050
1051         MMRADIO_LOG_FLEAVE();
1052
1053         pthread_exit(NULL);
1054         return;
1055
1056  SEEK_FAILED:
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, &param);
1060         pthread_exit(NULL);
1061         return;
1062 }
1063
1064 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param)
1065 {
1066         MMRADIO_CHECK_INSTANCE(radio);
1067
1068         MMRADIO_LOG_FENTER();
1069
1070         if (!radio->msg_cb) {
1071                 debug_warning("failed to post a message\n");
1072                 return false;
1073         }
1074
1075         MMRADIO_LOG_DEBUG("address of msg_cb : %d\n", radio->msg_cb);
1076
1077         radio->msg_cb(msgtype, param, radio->msg_cb_param);
1078
1079         MMRADIO_LOG_FLEAVE();
1080
1081         return true;
1082 }
1083
1084 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command)
1085 {
1086         MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1087
1088         MMRADIO_LOG_FENTER();
1089
1090         MMRADIO_CHECK_INSTANCE(radio);
1091
1092         radio_state = __mmradio_get_state(radio);
1093
1094         MMRADIO_LOG_DEBUG("incomming command : %d  current state : %d\n", command, radio_state);
1095
1096         switch (command) {
1097         case MMRADIO_COMMAND_CREATE:
1098                 {
1099                         if (radio_state != 0)
1100                                 goto NO_OP;
1101                 }
1102                 break;
1103
1104         case MMRADIO_COMMAND_REALIZE:
1105                 {
1106                         if (radio_state == MM_RADIO_STATE_READY ||
1107                                 radio_state == MM_RADIO_STATE_PLAYING ||
1108                                 radio_state == MM_RADIO_STATE_SCANNING)
1109                                 goto NO_OP;
1110
1111                         if (radio_state == 0)
1112                                 goto INVALID_STATE;
1113                 }
1114                 break;
1115
1116         case MMRADIO_COMMAND_UNREALIZE:
1117                 {
1118                         if (radio_state == MM_RADIO_STATE_NULL)
1119                                 goto NO_OP;
1120
1121                         /* we can call unrealize at any higher state */
1122                 }
1123                 break;
1124
1125         case MMRADIO_COMMAND_START:
1126                 {
1127                         if (radio_state == MM_RADIO_STATE_PLAYING)
1128                                 goto NO_OP;
1129
1130                         if (radio_state != MM_RADIO_STATE_READY)
1131                                 goto INVALID_STATE;
1132                 }
1133                 break;
1134
1135         case MMRADIO_COMMAND_STOP:
1136                 {
1137                         if (radio_state == MM_RADIO_STATE_READY)
1138                                 goto NO_OP;
1139
1140                         if (radio_state != MM_RADIO_STATE_PLAYING)
1141                                 goto INVALID_STATE;
1142                 }
1143                 break;
1144
1145         case MMRADIO_COMMAND_START_SCAN:
1146                 {
1147                         if (radio_state == MM_RADIO_STATE_SCANNING)
1148                                 goto NO_OP;
1149
1150                         if (radio_state == MM_RADIO_STATE_NULL)
1151                                 goto INVALID_STATE;
1152                 }
1153                 break;
1154
1155         case MMRADIO_COMMAND_STOP_SCAN:
1156                 {
1157                         if (radio_state == MM_RADIO_STATE_READY)
1158                                 goto NO_OP;
1159
1160                         if (radio_state != MM_RADIO_STATE_SCANNING)
1161                                 goto INVALID_STATE;
1162                 }
1163                 break;
1164
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:
1171                 {
1172                         /* we can do it at any state */
1173                 }
1174                 break;
1175
1176         case MMRADIO_COMMAND_SEEK:
1177                 {
1178                         if (radio_state != MM_RADIO_STATE_PLAYING)
1179                                 goto INVALID_STATE;
1180                 }
1181                 break;
1182
1183         case MMRADIO_COMMAND_GET_REGION:
1184                 {
1185                         if (radio_state == MM_RADIO_STATE_NULL)
1186                                 goto INVALID_STATE;
1187                 }
1188                 break;
1189
1190         default:
1191                 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it\n");
1192                 break;
1193         }
1194
1195         MMRADIO_LOG_DEBUG("status OK\n");
1196
1197         radio->cmd = command;
1198
1199         MMRADIO_LOG_FLEAVE();
1200
1201         return MM_ERROR_NONE;
1202
1203  INVALID_STATE:
1204         debug_warning("invalid state. current : %d  command : %d\n", radio_state, command);
1205         MMRADIO_LOG_FLEAVE();
1206         return MM_ERROR_RADIO_INVALID_STATE;
1207
1208  NO_OP:
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;
1212
1213 }
1214
1215 static bool __mmradio_set_state(mm_radio_t * radio, int new_state)
1216 {
1217         MMMessageParamType msg = { 0, };
1218         int msg_type = MM_MESSAGE_UNKNOWN;
1219
1220         MMRADIO_LOG_FENTER();
1221         MMRADIO_CHECK_INSTANCE(radio);
1222
1223         if (!radio) {
1224                 debug_warning("calling set_state with invalid radio handle\n");
1225                 return false;
1226         }
1227
1228         if (radio->current_state == new_state && radio->pending_state == 0) {
1229                 debug_warning("we are in same state\n");
1230                 return true;
1231         }
1232
1233         /* set state */
1234         radio->old_state = radio->current_state;
1235         radio->current_state = new_state;
1236
1237         /* fill message param */
1238         msg.state.previous = radio->old_state;
1239         msg.state.current = radio->current_state;
1240
1241         /* post message to application */
1242         switch (radio->sm.by_focus_cb) {
1243         case MMRADIO_FOCUS_CB_NONE:
1244                 {
1245                         msg_type = MM_MESSAGE_STATE_CHANGED;
1246                         MMRADIO_POST_MSG(radio, msg_type, &msg);
1247                 }
1248                 break;
1249
1250         case MMRADIO_FOCUS_CB_POSTMSG:
1251                 {
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);
1256                 }
1257                 break;
1258
1259         case MMRADIO_FOCUS_CB_SKIP_POSTMSG:
1260         default:
1261                 break;
1262         }
1263
1264         MMRADIO_LOG_FLEAVE();
1265
1266         return true;
1267 }
1268
1269 static int __mmradio_get_state(mm_radio_t * radio)
1270 {
1271         MMRADIO_CHECK_INSTANCE(radio);
1272
1273         MMRADIO_LOG_DEBUG("radio state : current : [%d]   old : [%d]   pending : [%d]\n",
1274                           radio->current_state, radio->old_state, radio->pending_state);
1275
1276         return radio->current_state;
1277 }
1278
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)
1282 {
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;
1287
1288         MMRADIO_LOG_FENTER();
1289         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1290
1291         mmradio_get_audio_focus_reason(focus_state, reason_for_change, &event_source, &postMsg);
1292         radio->sm.event_src = event_source;
1293
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;
1298
1299                         result = _mmradio_stop(radio);
1300                         if (result)
1301                                 MMRADIO_LOG_ERROR("failed to stop radio\n");
1302
1303                         MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sm.cur_focus_type);
1304                 }
1305                 break;
1306
1307         case FOCUS_IS_ACQUIRED:{
1308                         MMMessageParamType msg = { 0, };
1309                         msg.union_type = MM_MSG_UNION_CODE;
1310                         msg.code = event_source;
1311
1312                         radio->sm.cur_focus_type |= focus_type;
1313
1314                         if ((postMsg) && (FOCUS_FOR_BOTH == radio->sm.cur_focus_type))
1315                                 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1316
1317                         radio->sm.by_focus_cb = MMRADIO_FOCUS_CB_NONE;
1318
1319                         MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d\n", radio->sm.cur_focus_type);
1320                 }
1321                 break;
1322
1323         default:
1324                 MMRADIO_LOG_DEBUG("Unknown focus_state\n");
1325                 break;
1326         }
1327
1328         MMRADIO_LOG_FLEAVE();
1329 }
1330
1331 static void __mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data)
1332 {
1333         mm_radio_t *radio = (mm_radio_t *) user_data;
1334         int result = MM_ERROR_NONE;
1335         mm_sound_device_type_e type;
1336
1337         MMRADIO_LOG_FENTER();
1338         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1339
1340         if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) {
1341                 debug_error("getting device type failed");
1342         } else {
1343                 switch (type) {
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;
1353
1354                                 result = _mmradio_stop(radio);
1355                                 if (result != MM_ERROR_NONE)
1356                                         MMRADIO_LOG_ERROR("failed to stop radio\n");
1357                         }
1358                         break;
1359                 default:
1360                         break;
1361                 }
1362         }
1363         MMRADIO_LOG_FLEAVE();
1364 }
1365
1366 int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type)
1367 {
1368         MMRADIO_LOG_FENTER();
1369         MMRADIO_CHECK_INSTANCE(radio);
1370         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1371
1372         return_val_if_fail(type, MM_ERROR_INVALID_ARGUMENT);
1373
1374         *type = radio->region_setting.country;
1375
1376         MMRADIO_LOG_FLEAVE();
1377         return MM_ERROR_NONE;
1378 }
1379
1380 int _mmradio_get_region_frequency_range(mm_radio_t * radio, unsigned int *min_freq, unsigned int *max_freq)
1381 {
1382         MMRADIO_LOG_FENTER();
1383         MMRADIO_CHECK_INSTANCE(radio);
1384         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1385
1386         return_val_if_fail(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1387
1388         *min_freq = radio->region_setting.band_min;
1389         *max_freq = radio->region_setting.band_max;
1390
1391         MMRADIO_LOG_FLEAVE();
1392         return MM_ERROR_NONE;
1393 }
1394
1395 int _mmradio_get_channel_spacing(mm_radio_t * radio, unsigned int *ch_spacing)
1396 {
1397         MMRADIO_LOG_FENTER();
1398         MMRADIO_CHECK_INSTANCE(radio);
1399         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1400
1401         return_val_if_fail(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1402
1403         *ch_spacing = radio->region_setting.channel_spacing;
1404
1405         MMRADIO_LOG_FLEAVE();
1406         return MM_ERROR_NONE;
1407 }
1408
1409 static int __mmradio_get_wave_num(mm_radio_t * radio)
1410 {
1411         int val = 0;
1412         MMRADIO_LOG_FENTER();
1413         switch (radio->freq) {
1414         case 89100:
1415                 val = 1;
1416                 break;
1417
1418         case 89900:
1419                 val = 5;
1420                 break;
1421
1422         case 91900:
1423                 val = 6;
1424                 break;
1425
1426         case 99900:
1427                 val = 8;
1428                 break;
1429
1430         case 107700:
1431                 val = 9;
1432                 break;
1433
1434         default:
1435                 val = 9;
1436                 break;
1437         }
1438         MMRADIO_LOG_DEBUG("freq: %d, val : %d", radio->freq, val);
1439         MMRADIO_LOG_FLEAVE();
1440         return val;
1441 }