When creating a thread, waiting for the thread function to start
[platform/core/multimedia/libmm-radio.git] / src / mm_radio_priv_emulator.c
1 /*
2  * mm_radio_priv_emulator.c
3  *
4  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 /*===========================================================================================
21 |                                                                                                                                                                                       |
22 |  INCLUDE FILES                                                                                                                                                        |
23 |                                                                                                                                                                                       |
24 ========================================================================================== */
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include <fcntl.h>
31 #include <sys/ioctl.h>
32 #include <unistd.h>
33 #include <errno.h>
34
35 #include <mm_error.h>
36 #include <mm_message.h>
37 #include <time.h>
38
39 #include "mm_radio_priv.h"
40
41 /*===========================================================================================
42   LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
43 ========================================================================================== */
44 /*---------------------------------------------------------------------------
45     GLOBAL CONSTANT DEFINITIONS:
46 ---------------------------------------------------------------------------*/
47
48 /*---------------------------------------------------------------------------
49     IMPORTED VARIABLE DECLARATIONS:
50 ---------------------------------------------------------------------------*/
51
52 /*---------------------------------------------------------------------------
53     IMPORTED FUNCTION DECLARATIONS:
54 ---------------------------------------------------------------------------*/
55
56 /*---------------------------------------------------------------------------
57     LOCAL #defines:
58 ---------------------------------------------------------------------------*/
59 #define TUNER_INDEX                             0
60
61 #define DEFAULT_FREQ                            107700
62
63 #define FREQ_FRAC                               16
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
68
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 ---------------------------------------------------------------------------*/
77
78 /*---------------------------------------------------------------------------
79     LOCAL DATA TYPE DEFINITIONS:
80 ---------------------------------------------------------------------------*/
81
82 /*---------------------------------------------------------------------------
83     GLOBAL VARIABLE DEFINITIONS:
84 ---------------------------------------------------------------------------*/
85 extern int errno;
86
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. */
97          50,
98          },
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,
104          50,
105          },
106         {
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,
111          50,
112          },
113 };
114
115 static int MMRadioEmulatorFreq[EMULATOR_FREQ_MAX] = {
116         89100, 89900, 91900, 99900, 107700
117 };
118
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);
140
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
146 };
147
148 /*===========================================================================
149   FUNCTION DEFINITIONS
150 ========================================================================== */
151 /* --------------------------------------------------------------------------
152  * Name   : _mmradio_apply_region()
153  * Desc   : update radio region information and set values to device
154  * Param  :
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)
161 {
162         int ret = MM_ERROR_NONE;
163         int count = 0;
164         int index = 0;
165
166         MMRADIO_LOG_FENTER();
167
168         MMRADIO_CHECK_INSTANCE(radio);
169         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
170
171         /* if needed, radio region must be updated.
172          * Otherwise, just applying settings to device without it.
173          */
174         if (update) {
175                 count = ARRAY_SIZE(region_table);
176
177                 /* TODO: if auto is supported...get the region info. here */
178
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;
188                         }
189                 }
190         }
191
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;
196         }
197
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);
201
202         /* set de-emphsasis to device */
203         ret = __mmradio_set_deemphasis(radio);
204
205         MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set de-emphasis");
206
207         /* set band range to device */
208         ret = __mmradio_set_band_range(radio);
209
210         MMRADIO_CHECK_RETURN_IF_FAIL(ret, "set band range");
211
212         MMRADIO_LOG_FLEAVE();
213
214         return ret;
215 }
216
217 int _mmradio_create_radio(mm_radio_t * radio)
218 {
219         int ret = MM_ERROR_NONE;
220
221         MMRADIO_LOG_FENTER();
222
223         MMRADIO_CHECK_INSTANCE(radio);
224         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
225
226         /* set default value */
227         radio->radio_fd = -1;
228         radio->freq = DEFAULT_FREQ;
229         memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
230         radio->subs_id = 0;
231         radio->local_volume = 1.0;
232
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;
238         }
239
240         /* create mutex and thread */
241         ret = __mmradio_create_threads(radio);
242         if (ret) {
243                 MMRADIO_LOG_ERROR("failed to create threads");
244                 goto ERROR_THREAD;
245         }
246
247         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
248
249         /* initialize resource manager */
250         ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
251                         __resource_release_cb, radio, &radio->resource_manager);
252         if (ret) {
253                 MMRADIO_LOG_ERROR("failed to create resource manager");
254                 ret = MM_ERROR_RADIO_INTERNAL;
255                 goto ERROR_RESOURCE;
256         }
257
258         MMRADIO_LOG_FLEAVE();
259
260         return MM_ERROR_NONE;
261
262 ERROR_RESOURCE:
263         __mmradio_destroy_threads(radio);
264 ERROR_THREAD:
265         if (radio->msg_queue)
266                 g_async_queue_unref(radio->msg_queue);
267         return ret;
268 }
269
270 int _mmradio_realize(mm_radio_t *radio)
271 {
272         int ret = MM_ERROR_NONE;
273
274         MMRADIO_LOG_FENTER();
275
276         MMRADIO_CHECK_INSTANCE(radio);
277         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
278
279         /* open radio device */
280         if (radio->radio_fd == -1) {
281                 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
282                 bool update = false;
283
284                 /* open device */
285                 radio->radio_fd = 11;
286
287                 MMRADIO_LOG_DEBUG("radio device fd : %d", radio->radio_fd);
288
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;
293                         update = true;
294                 } else {
295                         /* already initialized by application */
296                         region = radio->region_setting.country;
297                 }
298
299                 ret = _mmradio_apply_region(radio, region, update);
300
301                 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info");
302         }
303
304         /* ready but nosound */
305         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
306         /*      goto error; */
307
308         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
309 #ifdef USE_GST_PIPELINE
310         ret = _mmradio_realize_pipeline(radio);
311         if (ret) {
312                 MMRADIO_LOG_ERROR("failed to realize pipeline");
313                 return ret;
314         }
315 #endif
316         MMRADIO_LOG_FLEAVE();
317
318         return MM_ERROR_NONE;
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
339 #ifdef USE_GST_PIPELINE
340         ret = _mmradio_destroy_pipeline(radio);
341         if (ret) {
342                 MMRADIO_LOG_ERROR("failed to destroy pipeline");
343                 return ret;
344         }
345 #endif
346
347         MMRADIO_LOG_FLEAVE();
348
349         return ret;
350 }
351
352 int _mmradio_destroy(mm_radio_t * radio)
353 {
354         int ret = MM_ERROR_NONE;
355
356         MMRADIO_LOG_FENTER();
357
358         MMRADIO_CHECK_INSTANCE(radio);
359         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
360
361         _mmradio_unrealize(radio);
362         /* destroy mutex and thread */
363         __mmradio_destroy_threads(radio);
364
365         if (radio->msg_queue)
366                 g_async_queue_unref(radio->msg_queue);
367
368         ret = mm_resource_manager_destroy(radio->resource_manager);
369         if (ret) {
370                 MMRADIO_LOG_ERROR("failed to destroy resource manager");
371                 return MM_ERROR_RADIO_INTERNAL;
372         }
373
374         MMRADIO_LOG_FLEAVE();
375
376         return MM_ERROR_NONE;
377 }
378
379 /* unit should be KHz */
380 int _mmradio_set_frequency(mm_radio_t * radio, int freq)
381 {
382         MMRADIO_LOG_FENTER();
383
384         MMRADIO_CHECK_INSTANCE(radio);
385         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
386
387         MMRADIO_SLOG_DEBUG("Setting %d frequency", freq);
388         MMRADIO_LOG_DEBUG("radio->freq: %d freq: %d", radio->freq, freq);
389
390         if (radio->radio_fd < 0) {
391                 MMRADIO_LOG_DEBUG("radio device is not opened yet");
392                 return MM_ERROR_NONE;
393         }
394
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;
399         }
400
401         radio->freq = freq;
402
403 #ifdef USE_GST_PIPELINE
404         if (radio->pGstreamer_s) {
405                 int val = 0;
406                 val = __mmradio_get_wave_num(radio);
407                 g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, NULL);
408         }
409 #endif
410         MMRADIO_LOG_FLEAVE();
411
412         return MM_ERROR_NONE;
413
414 }
415
416 int _mmradio_get_frequency(mm_radio_t * radio, int *pFreq)
417 {
418
419         MMRADIO_LOG_FENTER();
420
421         MMRADIO_CHECK_INSTANCE(radio);
422         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
423
424         MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
425
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;
431         }
432         /* update freq in handle */
433
434         *pFreq = radio->freq;
435
436         MMRADIO_LOG_FLEAVE();
437
438         return MM_ERROR_NONE;
439 }
440
441 int _mmradio_mute(mm_radio_t * radio)
442 {
443         MMRADIO_LOG_FENTER();
444
445         MMRADIO_CHECK_INSTANCE(radio);
446         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
447
448         if (radio->radio_fd < 0)
449                 return MM_ERROR_RADIO_NOT_INITIALIZED;
450
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");
455         }
456 #endif
457         MMRADIO_LOG_FLEAVE();
458
459         return MM_ERROR_NONE;
460
461 }
462
463 int _mmradio_unmute(mm_radio_t * radio)
464 {
465         MMRADIO_LOG_FENTER();
466
467         MMRADIO_CHECK_INSTANCE(radio);
468         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
469         MMRADIO_CHECK_DEVICE_STATE(radio);
470
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");
475         }
476 #endif
477
478         MMRADIO_LOG_FLEAVE();
479
480         return MM_ERROR_NONE;
481 }
482
483 /* --------------------------------------------------------------------------
484  * Name   : __mmradio_set_deemphasis
485  * Desc   : apply de-emphasis value to device
486  * Param  :
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)
491 {
492         int value = 0;
493
494         MMRADIO_LOG_FENTER();
495         return MM_ERROR_NONE;
496         MMRADIO_CHECK_INSTANCE(radio);
497
498         /* get de-emphasis */
499         switch (radio->region_setting.deemphasis) {
500         case MM_RADIO_DEEMPHASIS_50_US:
501                 /* V4L2_DEEMPHASIS_50_uS; */
502                 value = 1;
503                 break;
504
505         case MM_RADIO_DEEMPHASIS_75_US:
506                 /* V4L2_DEEMPHASIS_75_uS; */
507                 value = 2;
508                 break;
509
510         default:
511                 MMRADIO_LOG_ERROR("not availabe de-emphasis value");
512                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
513         }
514
515         MMRADIO_LOG_DEBUG("set deemphasis %d", value);
516
517         MMRADIO_LOG_FLEAVE();
518
519         return MM_ERROR_NONE;
520 }
521
522 /* --------------------------------------------------------------------------
523  * Name   : __mmradio_set_band_range
524  * Desc   : apply max and min frequency to device
525  * Param  :
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)
530 {
531         MMRADIO_LOG_FENTER();
532         return MM_ERROR_NONE;
533         MMRADIO_CHECK_INSTANCE(radio);
534
535         MMRADIO_LOG_FLEAVE();
536
537         return MM_ERROR_NONE;
538 }
539
540 int _mmradio_set_message_callback(mm_radio_t * radio, MMMessageCallback callback, void *user_param)
541 {
542         MMRADIO_LOG_FENTER();
543
544         MMRADIO_CHECK_INSTANCE(radio);
545
546         radio->msg_cb = callback;
547         radio->msg_cb_param = user_param;
548
549         MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
550
551         MMRADIO_LOG_FLEAVE();
552
553         return MM_ERROR_NONE;
554 }
555
556 int _mmradio_get_state(mm_radio_t * radio, int *pState)
557 {
558         int state = 0;
559
560         MMRADIO_LOG_FENTER();
561
562         MMRADIO_CHECK_INSTANCE(radio);
563         MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
564
565         state = __mmradio_get_state(radio);
566
567         *pState = state;
568
569         MMRADIO_LOG_FLEAVE();
570
571         return MM_ERROR_NONE;
572 }
573
574 int _mmradio_start(mm_radio_t * radio)
575 {
576         int ret = MM_ERROR_NONE;
577
578         MMRADIO_LOG_FENTER();
579
580         MMRADIO_CHECK_INSTANCE(radio);
581         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
582
583         MMRADIO_SLOG_DEBUG("now tune to frequency : %d", radio->freq);
584
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;
591         }
592
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;
600                 return ret;
601         }
602
603         /* set stored frequency */
604         _mmradio_set_frequency(radio, radio->freq);
605
606         _mmradio_set_volume(radio, radio->local_volume);
607
608         /* unmute */
609         /*  if( _mmradio_unmute(radio) != MM_ERROR_NONE) */
610         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
611
612 #ifdef USE_GST_PIPELINE
613         ret = _mmradio_start_pipeline(radio);
614         if (ret) {
615                 MMRADIO_LOG_ERROR("failed to start pipeline");
616                 return ret;
617         }
618 #endif
619
620         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
621
622         MMRADIO_LOG_FLEAVE();
623
624         return ret;
625 }
626
627 int _mmradio_stop(mm_radio_t * radio)
628 {
629         int ret = MM_ERROR_NONE;
630
631         MMRADIO_LOG_FENTER();
632
633         MMRADIO_CHECK_INSTANCE(radio);
634         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
635
636         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
637         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
638
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);
646                         return ret;
647                 }
648
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");
652         }
653
654         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
655
656 #ifdef USE_GST_PIPELINE
657         ret = _mmradio_stop_pipeline(radio);
658         if (ret) {
659                 MMRADIO_LOG_ERROR("failed to stop pipeline");
660                 return ret;
661         }
662 #endif
663
664         MMRADIO_LOG_FLEAVE();
665
666         return ret;
667 }
668
669 #ifdef USE_GST_PIPELINE
670 int _mmradio_realize_pipeline(mm_radio_t * radio)
671 {
672         int ret = MM_ERROR_NONE;
673         int val = 0;
674         MMRADIO_LOG_FENTER();
675         gst_init(NULL, NULL);
676         radio->pGstreamer_s = g_new0(mm_radio_gstreamer_s, 1);
677
678         radio->pGstreamer_s->pipeline = gst_pipeline_new("fmradio");
679
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");
684
685         val = __mmradio_get_wave_num(radio);
686         g_object_set(radio->pGstreamer_s->audiosrc, "wave", val, "volume", 0.8, NULL);
687
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;
691         }
692
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,
698                                         NULL);
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,
704                 NULL)) {
705                 MMRADIO_LOG_DEBUG("failed to element link (src - queue - volue - sink)");
706                 return MM_ERROR_RADIO_NOT_INITIALIZED;
707         }
708         MMRADIO_LOG_FLEAVE();
709         return ret;
710 }
711
712 int _mmradio_start_pipeline(mm_radio_t * radio)
713 {
714         int ret = MM_ERROR_NONE;
715         GstStateChangeReturn ret_state;
716
717         MMRADIO_LOG_FENTER();
718
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;
722         }
723
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;
728         } else {
729                 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
730         }
731
732         MMRADIO_LOG_FLEAVE();
733         return ret;
734 }
735
736 int _mmradio_stop_pipeline(mm_radio_t * radio)
737 {
738         int ret = MM_ERROR_NONE;
739         GstStateChangeReturn ret_state;
740
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;
745         }
746
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;
751         } else {
752                 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
753         }
754         MMRADIO_LOG_FLEAVE();
755         return ret;
756 }
757
758 int _mmradio_destroy_pipeline(mm_radio_t * radio)
759 {
760         int ret = 0;
761         GstStateChangeReturn ret_state;
762         MMRADIO_LOG_FENTER();
763
764         MMRADIO_CHECK_ARG(radio->pGstreamer_s);
765
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;
771         }
772
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;
779         } else {
780                 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
781         }
782
783         gst_object_unref(radio->pGstreamer_s->pipeline);
784         MMRADIO_GFREEIF(radio->pGstreamer_s);
785         MMRADIO_LOG_FLEAVE();
786         return ret;
787 }
788 #endif
789
790 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
791 {
792         MMRadioThread_t *p_thread = NULL;
793
794         MMRADIO_LOG_FENTER();
795
796         MMRADIO_CHECK_INSTANCE(radio);
797         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
798
799         p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
800         MMRADIO_CHECK_ARG(p_thread);
801
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;
805         }
806
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);
812
813         MMRADIO_LOG_FLEAVE();
814
815         return MM_ERROR_NONE;
816 }
817
818 int _mmradio_start_scan(mm_radio_t * radio)
819 {
820         MMRadioThread_t *p_thread = NULL;
821
822         MMRADIO_LOG_FENTER();
823
824         MMRADIO_CHECK_INSTANCE(radio);
825         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
826
827         p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
828         MMRADIO_CHECK_ARG(p_thread);
829
830         p_thread->stop = false;
831         p_thread->is_running = true;
832
833         MMRADIO_THREAD_SIGNAL(p_thread);
834
835         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
836
837         MMRADIO_LOG_FLEAVE();
838
839         return MM_ERROR_NONE;
840 }
841
842 int _mmradio_stop_scan(mm_radio_t * radio)
843 {
844         MMRADIO_LOG_FENTER();
845
846         MMRADIO_CHECK_INSTANCE(radio);
847         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
848
849         radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
850
851         MMRADIO_LOG_FLEAVE();
852
853         return MM_ERROR_NONE;
854 }
855
856 int _mm_radio_get_signal_strength(mm_radio_t * radio, int *value)
857 {
858         MMRADIO_LOG_FENTER();
859         MMRADIO_CHECK_INSTANCE(radio);
860
861         MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
862
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");
866                 *value = 0;
867                 return MM_ERROR_NONE;
868         }
869
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;
874 }
875
876 void __mmradio_scan_thread(mm_radio_t * radio)
877 {
878
879         int prev_freq = 0;
880         int emulatoridx = 0;
881         int freq = 0;
882         MMRadioThread_t *p_thread = NULL;
883
884         MMRADIO_LOG_FENTER();
885         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
886
887         p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
888         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
889
890         MMRADIO_THREAD_LOCK(p_thread);
891         MMRADIO_THREAD_SIGNAL(p_thread);
892         MMRADIO_THREAD_UNLOCK(p_thread);
893
894         MMRADIO_THREAD_LOCK(p_thread);
895
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.");
900
901                 if (p_thread->thread_exit) {
902                         MMRADIO_LOG_DEBUG("exiting scan thread");
903                         goto EXIT;
904                 }
905
906                 if (p_thread->stop) {
907                         MMRADIO_LOG_INFO("scan was stopped");
908                         goto FINISHED;
909                 }
910
911                 if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
912                         goto FINISHED;
913
914                 if (radio->old_state == MM_RADIO_STATE_PLAYING)
915                         _mmradio_mute(radio);
916
917                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
918                 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
919
920                 prev_freq = 0;
921                 emulatoridx = 0;
922
923                 while (!p_thread->stop) {
924
925                         freq = 0;
926
927                         MMRADIO_LOG_DEBUG("scanning....");
928
929                         /* now we can get new frequency from radio device */
930                         if (p_thread->thread_exit) {
931                                 MMRADIO_LOG_DEBUG("exiting scan thread");
932                                 goto EXIT;
933                         }
934
935                         if (p_thread->stop)
936                                 break;
937
938                         usleep(1000 * 1000);
939                         freq = MMRadioEmulatorFreq[emulatoridx];
940                         MMRADIO_LOG_DEBUG("freq: %d", freq);
941
942                         if (freq < prev_freq) {
943                                 MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan");
944                                 break;
945                         }
946
947                         if (p_thread->thread_exit) {
948                                 MMRADIO_LOG_DEBUG("exiting scan thread");
949                                 goto EXIT;
950                         }
951
952                         if (p_thread->stop)
953                                 break;
954
955                         if (freq == prev_freq)
956                                 continue;
957
958                         prev_freq = freq;
959                         MMRADIO_LOG_INFO("scanning : new frequency : [%d]", freq);
960
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);
965                                 break;
966                         }
967
968                         if (p_thread->stop)
969                                 break;                  /* doesn't need to post */
970
971                         __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
972                         emulatoridx++;
973                         if (emulatoridx >= EMULATOR_FREQ_MAX)
974                                 break;
975                 }
976
977 FINISHED:
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");
988                         }
989                 }
990
991                 if (!p_thread->stop)
992                         __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
993                 else
994                         __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
995
996                 p_thread->is_running = false;
997                 p_thread->stop = false;
998         }
999
1000 EXIT:
1001         MMRADIO_THREAD_UNLOCK(p_thread);
1002         MMRADIO_LOG_FLEAVE();
1003         pthread_exit(NULL);
1004         return;
1005 }
1006
1007 bool __is_tunable_frequency(mm_radio_t * radio, int freq)
1008 {
1009         MMRADIO_LOG_FENTER();
1010
1011         MMRADIO_CHECK_INSTANCE(radio);
1012
1013         if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min)
1014                 return false;
1015
1016         MMRADIO_LOG_FLEAVE();
1017
1018         return true;
1019 }
1020
1021 void __mmradio_seek_thread(mm_radio_t * radio)
1022 {
1023         int freq = 0;
1024         int i = 0;
1025         int emulatoridx = 0;
1026         MMRadioThread_t *p_thread = NULL;
1027
1028         MMRADIO_LOG_FENTER();
1029         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1030
1031         p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
1032         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1033
1034         MMRADIO_THREAD_LOCK(p_thread);
1035         MMRADIO_THREAD_SIGNAL(p_thread);
1036         MMRADIO_THREAD_UNLOCK(p_thread);
1037
1038         MMRADIO_THREAD_LOCK(p_thread);
1039
1040         while (!p_thread->thread_exit) {
1041                 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.\n");
1042                 MMRADIO_THREAD_WAIT(p_thread);
1043
1044                 if (p_thread->thread_exit) {
1045                         MMRADIO_LOG_DEBUG("exiting seek thread");
1046                         break;
1047                 }
1048
1049                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1050                 MMRADIO_LOG_DEBUG("seeking....");
1051
1052                 if (p_thread->stop) {
1053                         MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1054                         goto SEEK_FAILED;
1055                 }
1056
1057                 emulatoridx = 0;
1058                 MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
1059                 freq = radio->freq;
1060
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];
1065                                         emulatoridx = i;
1066                                         break;
1067                                 }
1068                         }
1069                         if (freq == radio->freq) {
1070                                 freq = MMRadioEmulatorFreq[0];
1071                                 emulatoridx = 0;
1072                         }
1073                 } else {
1074                         for (i = EMULATOR_FREQ_MAX - 1; i < 0; i--) {
1075                                 if (radio->freq > MMRadioEmulatorFreq[i]) {
1076                                         freq = MMRadioEmulatorFreq[i];
1077                                         emulatoridx = i;
1078                                         break;
1079                                 }
1080                         }
1081                         if (freq == radio->freq) {
1082                                 freq = MMRadioEmulatorFreq[EMULATOR_FREQ_MAX - 1];
1083                                 emulatoridx = EMULATOR_FREQ_MAX - 1;
1084                         }
1085                 }
1086
1087                 radio->freq = freq;
1088                 MMRADIO_LOG_DEBUG("radio->freq: %d emulatoridx: %d", radio->freq, emulatoridx);
1089
1090                 MMRADIO_LOG_DEBUG("found frequency");
1091
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.");
1095                         goto SEEK_FAILED;
1096                 }
1097
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");
1103                                 goto SEEK_FAILED;
1104                         }
1105                 }
1106
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;
1112                 continue;
1113
1114 SEEK_FAILED:
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;
1119         }
1120
1121         MMRADIO_THREAD_UNLOCK(p_thread);
1122         MMRADIO_LOG_FLEAVE();
1123         pthread_exit(NULL);
1124         return;
1125 }
1126
1127 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param)
1128 {
1129         MMRADIO_CHECK_INSTANCE(radio);
1130
1131         MMRADIO_LOG_FENTER();
1132
1133         if (!radio->msg_cb) {
1134                 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1135                 return false;
1136         }
1137
1138         MMRADIO_LOG_DEBUG("address of msg_cb : %d", radio->msg_cb);
1139
1140         radio->msg_cb(msgtype, param, radio->msg_cb_param);
1141
1142         MMRADIO_LOG_FLEAVE();
1143
1144         return true;
1145 }
1146
1147 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command)
1148 {
1149         MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1150
1151         MMRADIO_LOG_FENTER();
1152
1153         MMRADIO_CHECK_INSTANCE(radio);
1154
1155         radio_state = __mmradio_get_state(radio);
1156
1157         MMRADIO_LOG_DEBUG("incomming command : %d  current state : %d", command, radio_state);
1158
1159         switch (command) {
1160         case MMRADIO_COMMAND_CREATE:
1161                 {
1162                         if (radio_state != 0)
1163                                 goto NO_OP;
1164                 }
1165                 break;
1166
1167         case MMRADIO_COMMAND_REALIZE:
1168                 {
1169                         if (radio_state == MM_RADIO_STATE_READY ||
1170                                 radio_state == MM_RADIO_STATE_PLAYING ||
1171                                 radio_state == MM_RADIO_STATE_SCANNING)
1172                                 goto NO_OP;
1173
1174                         if (radio_state == 0)
1175                                 goto INVALID_STATE;
1176                 }
1177                 break;
1178
1179         case MMRADIO_COMMAND_UNREALIZE:
1180                 {
1181                         if (radio_state == MM_RADIO_STATE_NULL)
1182                                 goto NO_OP;
1183
1184                         /* we can call unrealize at any higher state */
1185                 }
1186                 break;
1187
1188         case MMRADIO_COMMAND_START:
1189                 {
1190                         if (radio_state == MM_RADIO_STATE_PLAYING)
1191                                 goto NO_OP;
1192
1193                         if (radio_state != MM_RADIO_STATE_READY)
1194                                 goto INVALID_STATE;
1195                 }
1196                 break;
1197
1198         case MMRADIO_COMMAND_STOP:
1199                 {
1200                         if (radio_state == MM_RADIO_STATE_READY)
1201                                 goto NO_OP;
1202
1203                         if (radio_state != MM_RADIO_STATE_PLAYING)
1204                                 goto INVALID_STATE;
1205                 }
1206                 break;
1207
1208         case MMRADIO_COMMAND_START_SCAN:
1209                 {
1210                         if (radio_state == MM_RADIO_STATE_SCANNING)
1211                                 goto NO_OP;
1212
1213                         if (radio_state == MM_RADIO_STATE_NULL)
1214                                 goto INVALID_STATE;
1215                 }
1216                 break;
1217
1218         case MMRADIO_COMMAND_STOP_SCAN:
1219                 {
1220                         if (radio_state == MM_RADIO_STATE_READY)
1221                                 goto NO_OP;
1222
1223                         if (radio_state != MM_RADIO_STATE_SCANNING)
1224                                 goto INVALID_STATE;
1225                 }
1226                 break;
1227
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:
1234                 {
1235                         /* we can do it at any state */
1236                 }
1237                 break;
1238
1239         case MMRADIO_COMMAND_SEEK:
1240                 {
1241                         if (radio_state != MM_RADIO_STATE_PLAYING)
1242                                 goto INVALID_STATE;
1243                 }
1244                 break;
1245
1246         case MMRADIO_COMMAND_GET_REGION:
1247                 {
1248                         if (radio_state == MM_RADIO_STATE_NULL)
1249                                 goto INVALID_STATE;
1250                 }
1251                 break;
1252
1253         default:
1254                 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1255                 break;
1256         }
1257
1258         MMRADIO_LOG_DEBUG("status OK");
1259
1260         radio->cmd = command;
1261
1262         MMRADIO_LOG_FLEAVE();
1263
1264         return MM_ERROR_NONE;
1265
1266 INVALID_STATE:
1267         MMRADIO_LOG_WARNING("invalid state. current : %d  command : %d", radio_state, command);
1268         MMRADIO_LOG_FLEAVE();
1269         return MM_ERROR_RADIO_INVALID_STATE;
1270
1271 NO_OP:
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;
1275
1276 }
1277
1278 static bool __mmradio_set_state(mm_radio_t * radio, int new_state)
1279 {
1280         MMMessageParamType msg = { 0, };
1281         int msg_type = MM_MESSAGE_UNKNOWN;
1282
1283         MMRADIO_LOG_FENTER();
1284
1285         if (!radio) {
1286                 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1287                 return false;
1288         }
1289
1290         if (radio->current_state == new_state && radio->pending_state == 0) {
1291                 MMRADIO_LOG_WARNING("we are in same state");
1292                 return true;
1293         }
1294
1295         /* set state */
1296         radio->old_state = radio->current_state;
1297         radio->current_state = new_state;
1298
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;
1303
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);
1307         } else {
1308                 msg_type = MM_MESSAGE_STATE_CHANGED;
1309                 MMRADIO_POST_MSG(radio, msg_type, &msg);
1310         }
1311
1312         MMRADIO_LOG_FLEAVE();
1313
1314         return true;
1315 }
1316
1317 static int __mmradio_get_state(mm_radio_t * radio)
1318 {
1319         MMRADIO_CHECK_INSTANCE(radio);
1320
1321         MMRADIO_LOG_DEBUG("radio state : current : [%d]   old : [%d]   pending : [%d]",
1322                                                 radio->current_state, radio->old_state, radio->pending_state);
1323
1324         return radio->current_state;
1325 }
1326
1327 int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type)
1328 {
1329         MMRADIO_LOG_FENTER();
1330         MMRADIO_CHECK_INSTANCE(radio);
1331         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1332
1333         MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1334
1335         *type = radio->region_setting.country;
1336
1337         MMRADIO_LOG_FLEAVE();
1338         return MM_ERROR_NONE;
1339 }
1340
1341 int _mmradio_get_region_frequency_range(mm_radio_t * radio, unsigned int *min_freq, unsigned int *max_freq)
1342 {
1343         MMRADIO_LOG_FENTER();
1344         MMRADIO_CHECK_INSTANCE(radio);
1345         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1346
1347         MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1348
1349         *min_freq = radio->region_setting.band_min;
1350         *max_freq = radio->region_setting.band_max;
1351
1352         MMRADIO_LOG_FLEAVE();
1353         return MM_ERROR_NONE;
1354 }
1355
1356 int _mmradio_get_channel_spacing(mm_radio_t * radio, unsigned int *ch_spacing)
1357 {
1358         MMRADIO_LOG_FENTER();
1359         MMRADIO_CHECK_INSTANCE(radio);
1360         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1361
1362         MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1363
1364         *ch_spacing = radio->region_setting.channel_spacing;
1365
1366         MMRADIO_LOG_FLEAVE();
1367         return MM_ERROR_NONE;
1368 }
1369
1370 static int __mmradio_get_wave_num(mm_radio_t * radio)
1371 {
1372         int val = 0;
1373         MMRADIO_LOG_FENTER();
1374         switch (radio->freq) {
1375         case 89100:
1376                 val = 1;
1377                 break;
1378
1379         case 89900:
1380                 val = 2;
1381                 break;
1382
1383         case 91900:
1384                 val = 5;
1385                 break;
1386
1387         case 99900:
1388                 val = 8;
1389                 break;
1390
1391         case 107700:
1392                 val = 9;
1393                 break;
1394
1395         default:
1396                 val = 9;
1397                 break;
1398         }
1399         MMRADIO_LOG_DEBUG("freq: %d, val : %d", radio->freq, val);
1400         MMRADIO_LOG_FLEAVE();
1401         return val;
1402 }
1403
1404 static int __resource_release_cb(mm_resource_manager_h rm,
1405         mm_resource_manager_res_h res, void *user_data)
1406 {
1407         mm_radio_t *radio = NULL;
1408
1409         MMRADIO_LOG_FENTER();
1410
1411         if (!user_data) {
1412                 MMRADIO_LOG_ERROR("user_data is null");
1413                 return FALSE;
1414         }
1415
1416         radio = (mm_radio_t *)user_data;
1417         radio->radio_resource = NULL;
1418
1419         MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1420
1421         radio->interrupted_by_resource_conflict = TRUE;
1422
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);
1427
1428         MMRADIO_LOG_FLEAVE();
1429
1430         return FALSE;
1431 }
1432
1433 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1434 {
1435         MMRADIO_LOG_FENTER();
1436
1437         MMRADIO_CHECK_INSTANCE(radio);
1438         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1439
1440         MMRADIO_SLOG_DEBUG("Setting %f volume", volume);
1441
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;
1446         }
1447
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;
1452         }
1453
1454         radio->local_volume = volume;
1455
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");
1460         }
1461 #endif
1462         MMRADIO_LOG_FLEAVE();
1463
1464         return MM_ERROR_NONE;
1465
1466 }
1467 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1468 {
1469         MMRADIO_LOG_FENTER();
1470
1471         MMRADIO_CHECK_INSTANCE(radio);
1472         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1473
1474         MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1475
1476         MMRADIO_SLOG_DEBUG("volume : %f", radio->local_volume);
1477
1478         *pVolume = radio->local_volume;
1479
1480         MMRADIO_LOG_FLEAVE();
1481
1482         return MM_ERROR_NONE;
1483 }
1484
1485 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1486 {
1487         MMRadioThread_t *p_thread = NULL;
1488
1489         MMRADIO_LOG_FENTER();
1490
1491         MMRADIO_CHECK_INSTANCE(radio);
1492
1493         if (type >= MM_RADIO_THREAD_NUM) {
1494                 MMRADIO_LOG_WARNING("wrong argument thread type");
1495                 return MM_ERROR_RADIO_INTERNAL;
1496         }
1497
1498         p_thread = &radio->thread[type];
1499         MMRADIO_CHECK_ARG(p_thread);
1500
1501         MMRADIO_INIT_MUTEX(p_thread->mutex);
1502         MMRADIO_INIT_COND(p_thread->cond);
1503
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;
1511         }
1512
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);
1517
1518         return MM_ERROR_NONE;
1519
1520 ERROR:
1521         pthread_mutex_destroy(&p_thread->mutex);
1522         pthread_cond_destroy(&p_thread->cond);
1523         return MM_ERROR_RADIO_INTERNAL;
1524
1525 }
1526
1527 static int __mmradio_create_threads(mm_radio_t *radio)
1528 {
1529         int ret = MM_ERROR_NONE;
1530         int type = 0;
1531
1532         MMRADIO_LOG_FENTER();
1533
1534         MMRADIO_CHECK_INSTANCE(radio);
1535
1536         MMRADIO_INIT_MUTEX(radio->cmd_lock);
1537
1538         for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
1539                 ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
1540                 if (ret) {
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);
1544                         goto ERROR;
1545                 }
1546         }
1547
1548         MMRADIO_LOG_FLEAVE();
1549         return ret;
1550
1551 ERROR:
1552         pthread_mutex_destroy(&radio->cmd_lock);
1553         MMRADIO_LOG_FLEAVE();
1554         return MM_ERROR_RADIO_INTERNAL;
1555 }
1556
1557 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1558 {
1559         MMRadioThread_t *p_thread = NULL;
1560         mm_radio_msg_t *msg = NULL;
1561         MMRADIO_LOG_FENTER();
1562
1563         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1564
1565         if (type >= MM_RADIO_THREAD_NUM) {
1566                 MMRADIO_LOG_WARNING("wrong argument thread type");
1567                 return;
1568         }
1569
1570         p_thread = &radio->thread[type];
1571         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1572
1573         if (p_thread->thread) {
1574                 switch (type) {
1575                 case MM_RADIO_THREAD_MSG:
1576                         msg = g_slice_new0(mm_radio_msg_t);
1577                         if (!msg) {
1578                                 MMRADIO_LOG_ERROR("failed to get mm_radio_msg_t");
1579                         } else {
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;
1584                         }
1585                         break;
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;
1594                         break;
1595                 default:
1596                         MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
1597                         break;
1598                 }
1599         } else {
1600                 MMRADIO_LOG_WARNING("(%d)thread is zero", type);
1601         }
1602
1603         pthread_mutex_destroy(&p_thread->mutex);
1604         pthread_cond_destroy(&p_thread->cond);
1605
1606         MMRADIO_LOG_FLEAVE();
1607 }
1608
1609 static void __mmradio_destroy_threads(mm_radio_t *radio)
1610 {
1611         int type = (int)MM_RADIO_THREAD_NUM;
1612         MMRADIO_LOG_FENTER();
1613
1614         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1615
1616         while (--type >= 0)
1617                 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1618
1619         pthread_mutex_destroy(&radio->cmd_lock);
1620
1621         MMRADIO_LOG_FLEAVE();
1622 }
1623
1624
1625 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1626 {
1627         mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1628         if (!msg) {
1629                 MMRADIO_LOG_ERROR("NULL msg pointer");
1630                 return;
1631         }
1632
1633         msg->msg_type = msg_type;
1634         msg->data = msg_data;
1635
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);
1638 }
1639
1640 void __mmradio_msg_thread(mm_radio_t *radio)
1641 {
1642         mm_radio_msg_t *msg = NULL;
1643         MMRadioThread_t *p_thread = NULL;
1644
1645         MMRADIO_LOG_FENTER();
1646         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1647
1648         p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
1649         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1650
1651         p_thread->thread_exit = false;
1652
1653         MMRADIO_THREAD_LOCK(p_thread);
1654         MMRADIO_THREAD_SIGNAL(p_thread);
1655         MMRADIO_THREAD_UNLOCK(p_thread);
1656
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);
1660                 if (!msg) {
1661                         MMRADIO_LOG_ERROR("poped message is NULL!");
1662                         break;
1663                 }
1664
1665                 MMMessageParamType param = {0,};
1666
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);
1675                                 }
1676                         }
1677                         p_thread->thread_exit = true;
1678                         break;
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, &param);
1683                         break;
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);
1687                         break;
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);
1691                         break;
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, &param);
1696                         break;
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, &param);
1704                         break;
1705                 default:
1706                         MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1707                         break;
1708                 }
1709
1710                 if (msg)
1711                         g_slice_free(mm_radio_msg_t, msg);
1712         }
1713
1714         MMRADIO_LOG_INFO("msg thread is finished");
1715         MMRADIO_LOG_FLEAVE();
1716         pthread_exit(NULL);
1717 }