Fix coverity/Svace issues (BAD_CHECK_OF_WAIT_COND, MISSING_UNLOCK, NULL_AFTER_DEREF)
[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_emul.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         {                                                       /* North America, South America, South Korea, Taiwan, Australia */
93          MM_RADIO_REGION_GROUP_USA,     /* region type */
94          MM_RADIO_DEEMPHASIS_75_US,     /* de-emphasis */
95          MM_RADIO_FREQ_MIN_87500_KHZ,   /* min freq. */
96          MM_RADIO_FREQ_MAX_108000_KHZ,  /* max freq. */
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         /* check device is opened or not. if it's not ready, skip to apply region to device now */
193         if (radio->radio_fd < 0) {
194                 MMRADIO_LOG_DEBUG("not opened device. just updating region info.");
195                 return MM_ERROR_NONE;
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-emphasis 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->local_volume = 1.0;
231
232         /* create msg queue for msg thread */
233         radio->msg_queue = g_async_queue_new();
234         if (!radio->msg_queue) {
235                 MMRADIO_LOG_ERROR("failed to get msg g_async_queue_new");
236                 return  MM_ERROR_RADIO_INTERNAL;
237         }
238
239         /* create mutex and thread */
240         ret = __mmradio_create_threads(radio);
241         if (ret) {
242                 MMRADIO_LOG_ERROR("failed to create threads");
243                 goto ERROR_THREAD;
244         }
245
246         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
247
248         /* initialize resource manager */
249         ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
250                         __resource_release_cb, radio, &radio->resource_manager);
251         if (ret) {
252                 MMRADIO_LOG_ERROR("failed to create resource manager");
253                 ret = MM_ERROR_RADIO_INTERNAL;
254                 goto ERROR_RESOURCE;
255         }
256
257         MMRADIO_LOG_FLEAVE();
258
259         return MM_ERROR_NONE;
260
261 ERROR_RESOURCE:
262         __mmradio_destroy_threads(radio);
263 ERROR_THREAD:
264         if (radio->msg_queue)
265                 g_async_queue_unref(radio->msg_queue);
266         return ret;
267 }
268
269 int _mmradio_realize(mm_radio_t *radio)
270 {
271         int ret = MM_ERROR_NONE;
272
273         MMRADIO_LOG_FENTER();
274
275         MMRADIO_CHECK_INSTANCE(radio);
276         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
277
278         /* open radio device */
279         if (radio->radio_fd == -1) {
280                 MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
281                 bool update = false;
282
283                 /* open device */
284                 radio->radio_fd = 11;
285
286                 MMRADIO_LOG_DEBUG("radio device fd : %d", radio->radio_fd);
287
288                 /* check region country type if it's updated or not */
289                 if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
290                         /* not initialized  yet. set it with default region */
291                         region = RADIO_DEFAULT_REGION;
292                         update = true;
293                 } else {
294                         /* already initialized by application */
295                         region = radio->region_setting.country;
296                 }
297
298                 ret = _mmradio_apply_region(radio, region, update);
299
300                 MMRADIO_CHECK_RETURN_IF_FAIL(ret, "update region info");
301         }
302
303         /* ready but no sound */
304         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
305         /*      goto error; */
306
307         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
308
309         ret = _mmradio_realize_pipeline(radio);
310         if (ret) {
311                 MMRADIO_LOG_ERROR("failed to realize pipeline");
312                 return ret;
313         }
314
315         MMRADIO_LOG_FLEAVE();
316
317         return MM_ERROR_NONE;
318 }
319
320 int _mmradio_unrealize(mm_radio_t * radio)
321 {
322         int ret = MM_ERROR_NONE;
323
324         MMRADIO_LOG_FENTER();
325
326         MMRADIO_CHECK_INSTANCE(radio);
327         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
328
329         /*Finish if there are scans*/
330         ret = _mmradio_stop_scan(radio);
331         if (ret != MM_ERROR_NONE)
332                 MMRADIO_LOG_WARNING("failed to stop radio scan");
333
334         /*Stop radio if started*/
335         ret = _mmradio_stop(radio);
336         if (ret != MM_ERROR_NONE)
337                 MMRADIO_LOG_WARNING("failed to stop radio");
338
339         /* close radio device here !!!! */
340         if (radio->radio_fd >= 0)
341                 radio->radio_fd = -1;
342
343         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
344
345         ret = _mmradio_destroy_pipeline(radio);
346         if (ret) {
347                 MMRADIO_LOG_ERROR("failed to destroy pipeline");
348                 return ret;
349         }
350
351         MMRADIO_LOG_FLEAVE();
352
353         return ret;
354 }
355
356 int _mmradio_destroy(mm_radio_t * radio)
357 {
358         int ret = MM_ERROR_NONE;
359
360         MMRADIO_LOG_FENTER();
361
362         MMRADIO_CHECK_INSTANCE(radio);
363         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
364
365         _mmradio_unrealize(radio);
366
367         /* destroy mutex and thread */
368         __mmradio_destroy_threads(radio);
369
370         if (radio->msg_queue)
371                 g_async_queue_unref(radio->msg_queue);
372
373         ret = mm_resource_manager_destroy(radio->resource_manager);
374         if (ret) {
375                 MMRADIO_LOG_ERROR("failed to destroy resource manager");
376                 return MM_ERROR_RADIO_INTERNAL;
377         }
378
379         MMRADIO_LOG_FLEAVE();
380
381         return MM_ERROR_NONE;
382 }
383
384 /* unit should be KHz */
385 int _mmradio_set_frequency(mm_radio_t * radio, int freq)
386 {
387
388         int val = 0;
389         MMRADIO_LOG_FENTER();
390
391         MMRADIO_CHECK_INSTANCE(radio);
392         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
393
394         MMRADIO_SLOG_DEBUG("Setting %d frequency", freq);
395         MMRADIO_LOG_DEBUG("radio->freq: %d freq: %d", radio->freq, freq);
396
397         if (radio->radio_fd < 0) {
398                 MMRADIO_LOG_DEBUG("radio device is not opened yet");
399                 return MM_ERROR_NONE;
400         }
401
402         /* check frequency range */
403         if (freq < radio->region_setting.band_min || freq > radio->region_setting.band_max) {
404                 MMRADIO_LOG_ERROR("out of frequency range %d", freq);
405                 return MM_ERROR_INVALID_ARGUMENT;
406         }
407
408         radio->freq = freq;
409         val = __mmradio_get_wave_num(radio);
410
411         if (radio->pipeline && radio->pipeline->audiosrc)
412                 g_object_set(radio->pipeline->audiosrc, "wave", val, NULL);
413
414         MMRADIO_LOG_FLEAVE();
415
416         return MM_ERROR_NONE;
417
418 }
419
420 int _mmradio_get_frequency(mm_radio_t * radio, int *pFreq)
421 {
422
423         MMRADIO_LOG_FENTER();
424
425         MMRADIO_CHECK_INSTANCE(radio);
426         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
427
428         MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
429
430         /* just return stored frequency if radio device is not ready */
431         if (radio->radio_fd < 0) {
432                 MMRADIO_SLOG_DEBUG("freq : %d", radio->freq);
433                 *pFreq = radio->freq;
434                 return MM_ERROR_NONE;
435         }
436         /* update freq in handle */
437
438         *pFreq = radio->freq;
439
440         MMRADIO_LOG_FLEAVE();
441
442         return MM_ERROR_NONE;
443 }
444
445 int _mmradio_mute(mm_radio_t * radio)
446 {
447         MMRADIO_LOG_FENTER();
448
449         MMRADIO_CHECK_INSTANCE(radio);
450         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
451
452         if (radio->radio_fd < 0)
453                 return MM_ERROR_RADIO_NOT_INITIALIZED;
454
455         if (radio->pipeline && radio->pipeline->volume) {
456                 g_object_set(radio->pipeline->volume, "mute", 1, NULL);
457                 MMRADIO_LOG_DEBUG("g_object set mute");
458         }
459
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         if (radio->pipeline && radio->pipeline->volume) {
475                 g_object_set(radio->pipeline->volume, "mute", 0, NULL);
476                 MMRADIO_LOG_DEBUG("g_object set unmute");
477         }
478
479         MMRADIO_LOG_FLEAVE();
480
481         return MM_ERROR_NONE;
482 }
483
484 /* --------------------------------------------------------------------------
485  * Name   : __mmradio_set_deemphasis
486  * Desc   : apply de-emphasis value to device
487  * Param  :
488  *          [in] radio : radio handle
489  * Return : zero on success, or negative value with error code
490  *---------------------------------------------------------------------------*/
491 int __mmradio_set_deemphasis(mm_radio_t * radio)
492 {
493         int value = 0;
494
495         MMRADIO_LOG_FENTER();
496         return MM_ERROR_NONE;
497         MMRADIO_CHECK_INSTANCE(radio);
498
499         /* get de-emphasis */
500         switch (radio->region_setting.deemphasis) {
501         case MM_RADIO_DEEMPHASIS_50_US:
502                 /* V4L2_DEEMPHASIS_50_uS; */
503                 value = 1;
504                 break;
505
506         case MM_RADIO_DEEMPHASIS_75_US:
507                 /* V4L2_DEEMPHASIS_75_uS; */
508                 value = 2;
509                 break;
510
511         default:
512                 MMRADIO_LOG_ERROR("not available de-emphasis value");
513                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
514         }
515
516         MMRADIO_LOG_DEBUG("set deemphasis %d", value);
517
518         MMRADIO_LOG_FLEAVE();
519
520         return MM_ERROR_NONE;
521 }
522
523 /* --------------------------------------------------------------------------
524  * Name   : __mmradio_set_band_range
525  * Desc   : apply max and min frequency to device
526  * Param  :
527  *          [in] radio : radio handle
528  * Return : zero on success, or negative value with error code
529  *---------------------------------------------------------------------------*/
530 int __mmradio_set_band_range(mm_radio_t * radio)
531 {
532         MMRADIO_LOG_FENTER();
533         return MM_ERROR_NONE;
534         MMRADIO_CHECK_INSTANCE(radio);
535
536         MMRADIO_LOG_FLEAVE();
537
538         return MM_ERROR_NONE;
539 }
540
541 int _mmradio_set_message_callback(mm_radio_t * radio, MMMessageCallback callback, void *user_param)
542 {
543         MMRADIO_LOG_FENTER();
544
545         MMRADIO_CHECK_INSTANCE(radio);
546
547         radio->msg_cb = callback;
548         radio->msg_cb_param = user_param;
549
550         MMRADIO_LOG_DEBUG("msg_cb : %p msg_cb_param : %p", callback, user_param);
551
552         MMRADIO_LOG_FLEAVE();
553
554         return MM_ERROR_NONE;
555 }
556
557 int _mmradio_get_state(mm_radio_t * radio, int *pState)
558 {
559         int state = 0;
560
561         MMRADIO_LOG_FENTER();
562
563         MMRADIO_CHECK_INSTANCE(radio);
564         MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
565
566         state = __mmradio_get_state(radio);
567
568         *pState = state;
569
570         MMRADIO_LOG_FLEAVE();
571
572         return MM_ERROR_NONE;
573 }
574
575 int _mmradio_start(mm_radio_t * radio)
576 {
577         int ret = MM_ERROR_NONE;
578
579         MMRADIO_LOG_FENTER();
580
581         MMRADIO_CHECK_INSTANCE(radio);
582         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
583
584         MMRADIO_SLOG_DEBUG("now tune to frequency : %d", radio->freq);
585
586         ret = mm_resource_manager_mark_for_acquire(radio->resource_manager,
587                 MM_RESOURCE_MANAGER_RES_TYPE_RADIO,
588                 MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &radio->radio_resource);
589         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
590                 MMRADIO_LOG_ERROR("resource manager mark for acquire fail");
591                 return MM_ERROR_RADIO_INTERNAL;
592         }
593
594         radio->interrupted_by_resource_conflict = FALSE;
595         ret = mm_resource_manager_commit(radio->resource_manager);
596         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
597                 MMRADIO_LOG_ERROR("failed to commit resource manager");
598                 mm_resource_manager_mark_for_release(radio->resource_manager,
599                         radio->radio_resource);
600                 radio->radio_resource = NULL;
601                 return ret;
602         }
603
604         /* set stored frequency */
605         _mmradio_set_frequency(radio, radio->freq);
606
607         _mmradio_set_volume(radio, radio->local_volume);
608
609         ret = _mmradio_start_pipeline(radio);
610         if (ret) {
611                 MMRADIO_LOG_ERROR("failed to start pipeline");
612                 return ret;
613         }
614
615         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
616
617         MMRADIO_LOG_FLEAVE();
618
619         return ret;
620 }
621
622 int _mmradio_stop(mm_radio_t * radio)
623 {
624         int ret = MM_ERROR_NONE;
625
626         MMRADIO_LOG_FENTER();
627
628         MMRADIO_CHECK_INSTANCE(radio);
629         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
630
631         /*  if( _mmradio_mute(radio) != MM_ERROR_NONE) */
632         /*      return MM_ERROR_RADIO_NOT_INITIALIZED; */
633
634         if (!radio->interrupted_by_resource_conflict && /* is being released */
635                         radio->radio_resource != NULL) {
636                 ret = mm_resource_manager_mark_for_release(radio->resource_manager,
637                                 radio->radio_resource);
638                 radio->radio_resource = NULL;
639                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
640                         MMRADIO_LOG_ERROR("failed to mark resource for release, ret(0x%x)", ret);
641                         return ret;
642                 }
643
644                 ret = mm_resource_manager_commit(radio->resource_manager);
645                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
646                         MMRADIO_LOG_ERROR("resource manager commit fail");
647         }
648
649         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
650
651         ret = _mmradio_stop_pipeline(radio);
652         if (ret) {
653                 MMRADIO_LOG_ERROR("failed to stop pipeline");
654                 return ret;
655         }
656
657         MMRADIO_LOG_FLEAVE();
658
659         return ret;
660 }
661
662 int _mmradio_realize_pipeline(mm_radio_t * radio)
663 {
664         int ret = MM_ERROR_NONE;
665         int val = 0;
666         MMRADIO_LOG_FENTER();
667         gst_init(NULL, NULL);
668         radio->pipeline = g_new0(mm_radio_gstreamer_s, 1);
669
670         radio->pipeline->pipeline = gst_pipeline_new("fmradio");
671
672         radio->pipeline->audiosrc = gst_element_factory_make("audiotestsrc", "fm audio src");
673         radio->pipeline->converter = gst_element_factory_make("audioconvert", "audioconvert");
674         radio->pipeline->volume = gst_element_factory_make("volume", "audiovolume");
675         radio->pipeline->audiosink = gst_element_factory_make("pulsesink", "audio sink");
676
677         val = __mmradio_get_wave_num(radio);
678         g_object_set(radio->pipeline->audiosrc, "wave", val, "volume", 0.8, NULL);
679
680         if (!radio->pipeline->pipeline || !radio->pipeline->audiosrc
681                 || !radio->pipeline->converter || !radio->pipeline->volume
682                 || !radio->pipeline->audiosink) {
683                 MMRADIO_LOG_DEBUG("One element could not be created. Exiting.");
684                 return MM_ERROR_RADIO_NOT_INITIALIZED;
685         }
686
687         gst_bin_add_many(GST_BIN(radio->pipeline->pipeline),
688                                         radio->pipeline->audiosrc,
689                                         radio->pipeline->converter,
690                                         radio->pipeline->volume,
691                                         radio->pipeline->audiosink,
692                                         NULL);
693         if (!gst_element_link_many(radio->pipeline->audiosrc,
694                                                         radio->pipeline->converter,
695                                                         radio->pipeline->volume,
696                                                         radio->pipeline->audiosink,
697                                                         NULL)) {
698                 MMRADIO_LOG_DEBUG("failed to element link (src - queue - sink)");
699                 return MM_ERROR_RADIO_NOT_INITIALIZED;
700         }
701         MMRADIO_LOG_FLEAVE();
702         return ret;
703 }
704
705 int _mmradio_start_pipeline(mm_radio_t * radio)
706 {
707         int ret = MM_ERROR_NONE;
708         GstStateChangeReturn ret_state;
709
710         MMRADIO_LOG_FENTER();
711
712         if (gst_element_set_state(radio->pipeline->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
713                 MMRADIO_LOG_ERROR("failed to change pipeline state");
714                 return MM_ERROR_RADIO_INVALID_STATE;
715         }
716
717         ret_state = gst_element_get_state(radio->pipeline->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
718         if (ret_state == GST_STATE_CHANGE_FAILURE) {
719                 MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
720                 return MM_ERROR_RADIO_INVALID_STATE;
721         } else {
722                 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
723         }
724
725         MMRADIO_LOG_FLEAVE();
726         return ret;
727 }
728
729 int _mmradio_stop_pipeline(mm_radio_t * radio)
730 {
731         int ret = MM_ERROR_NONE;
732         GstStateChangeReturn ret_state;
733
734         MMRADIO_LOG_FENTER();
735         if (gst_element_set_state(radio->pipeline->pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
736                 MMRADIO_LOG_ERROR("Fail to change pipeline state");
737                 return MM_ERROR_RADIO_INVALID_STATE;
738         }
739
740         ret_state = gst_element_get_state(radio->pipeline->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
741         if (ret_state == GST_STATE_CHANGE_FAILURE) {
742                 MMRADIO_LOG_ERROR("GST_STATE_CHANGE_FAILURE");
743                 return MM_ERROR_RADIO_INVALID_STATE;
744         } else {
745                 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
746         }
747         MMRADIO_LOG_FLEAVE();
748         return ret;
749 }
750
751 int _mmradio_destroy_pipeline(mm_radio_t * radio)
752 {
753         int ret = 0;
754         GstStateChangeReturn ret_state;
755         MMRADIO_LOG_FENTER();
756
757         MMRADIO_CHECK_ARG(radio->pipeline);
758
759         if (gst_element_set_state(radio->pipeline->pipeline, GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE) {
760                 MMRADIO_LOG_DEBUG("failed to change pipeline state");
761                 gst_object_unref(radio->pipeline->pipeline);
762                 MMRADIO_GFREEIF(radio->pipeline);
763                 return MM_ERROR_RADIO_INVALID_STATE;
764         }
765
766         ret_state = gst_element_get_state(radio->pipeline->pipeline, NULL, NULL, RADIO_GST_STATE_CHANGE_TIMEOUT);
767         if (ret_state == GST_STATE_CHANGE_FAILURE) {
768                 MMRADIO_LOG_DEBUG("GST_STATE_CHANGE_FAILURE");
769                 gst_object_unref(radio->pipeline->pipeline);
770                 MMRADIO_GFREEIF(radio->pipeline);
771                 return MM_ERROR_RADIO_INVALID_STATE;
772         } else {
773                 MMRADIO_LOG_DEBUG("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)", ret_state);
774         }
775
776         gst_object_unref(radio->pipeline->pipeline);
777         MMRADIO_GFREEIF(radio->pipeline);
778         MMRADIO_LOG_FLEAVE();
779         return ret;
780 }
781
782 int _mmradio_seek(mm_radio_t * radio, MMRadioSeekDirectionType direction)
783 {
784         MMRadioThread_t *p_thread = NULL;
785
786         MMRADIO_LOG_FENTER();
787
788         MMRADIO_CHECK_INSTANCE(radio);
789         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
790
791         p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
792         MMRADIO_CHECK_ARG(p_thread);
793
794         if (p_thread->is_running) {
795                 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
796                 return MM_ERROR_RADIO_INTERNAL;
797         }
798
799         MMRADIO_SLOG_DEBUG("trying to seek. direction[0:UP/1:DOWN) %d", direction);
800         radio->seek_direction = direction;
801         p_thread->is_running = true;
802         p_thread->stop = false;
803         MMRADIO_THREAD_SIGNAL(p_thread);
804
805         MMRADIO_LOG_FLEAVE();
806
807         return MM_ERROR_NONE;
808 }
809
810 int _mmradio_start_scan(mm_radio_t * radio)
811 {
812         MMRadioThread_t *p_thread = NULL;
813
814         MMRADIO_LOG_FENTER();
815
816         MMRADIO_CHECK_INSTANCE(radio);
817         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
818
819         p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
820         MMRADIO_CHECK_ARG(p_thread);
821
822         p_thread->stop = false;
823         p_thread->is_running = true;
824
825         MMRADIO_THREAD_SIGNAL(p_thread);
826
827         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
828
829         MMRADIO_LOG_FLEAVE();
830
831         return MM_ERROR_NONE;
832 }
833
834 int _mmradio_stop_scan(mm_radio_t * radio)
835 {
836         MMRADIO_LOG_FENTER();
837
838         MMRADIO_CHECK_INSTANCE(radio);
839         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
840
841         radio->thread[MM_RADIO_THREAD_SCAN].stop = true;
842
843         MMRADIO_LOG_FLEAVE();
844
845         return MM_ERROR_NONE;
846 }
847
848 int _mm_radio_get_signal_strength(mm_radio_t * radio, int *value)
849 {
850         MMRADIO_LOG_FENTER();
851         MMRADIO_CHECK_INSTANCE(radio);
852
853         MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
854
855         /* just return stored frequency if radio device is not ready */
856         if (radio->radio_fd < 0) {
857                 MMRADIO_SLOG_DEBUG("Device not ready so sending 0");
858                 *value = 0;
859                 return MM_ERROR_NONE;
860         }
861
862         unsigned int seed = (unsigned)time(NULL);
863         *value = 0 - ((rand_r(&seed) % 20 + 1) + 80);
864         MMRADIO_LOG_FLEAVE();
865         return MM_ERROR_NONE;
866 }
867
868 void __mmradio_scan_thread(mm_radio_t * radio)
869 {
870
871         int prev_freq = 0;
872         int emulatoridx = 0;
873         int freq = 0;
874         MMRadioThread_t *p_thread = NULL;
875
876         MMRADIO_LOG_FENTER();
877         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
878
879         p_thread = &radio->thread[MM_RADIO_THREAD_SCAN];
880         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
881
882         MMRADIO_THREAD_LOCK(p_thread);
883         MMRADIO_THREAD_SIGNAL(p_thread);
884         MMRADIO_THREAD_UNLOCK(p_thread);
885
886         MMRADIO_THREAD_LOCK(p_thread);
887
888         while (!p_thread->thread_exit) {
889                 MMRADIO_LOG_DEBUG("scan thread started. waiting for signal.");
890                 MMRADIO_THREAD_WAIT(p_thread);
891                 MMRADIO_LOG_DEBUG("scan thread started. got signal.");
892
893                 if (p_thread->thread_exit) {
894                         MMRADIO_LOG_DEBUG("exiting scan thread");
895                         goto EXIT;
896                 }
897
898                 if (p_thread->stop) {
899                         MMRADIO_LOG_INFO("scan was stopped");
900                         goto FINISHED;
901                 }
902
903                 if (_mmradio_set_frequency(radio, radio->region_setting.band_min) != MM_ERROR_NONE)
904                         goto FINISHED;
905
906                 if (radio->old_state == MM_RADIO_STATE_PLAYING)
907                         _mmradio_mute(radio);
908
909                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
910                 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
911
912                 prev_freq = 0;
913                 emulatoridx = 0;
914
915                 while (!p_thread->stop) {
916
917                         freq = 0;
918
919                         MMRADIO_LOG_DEBUG("scanning....");
920
921                         /* now we can get new frequency from radio device */
922                         if (p_thread->thread_exit) {
923                                 MMRADIO_LOG_DEBUG("exiting scan thread");
924                                 goto EXIT;
925                         }
926
927                         if (p_thread->stop)
928                                 break;
929
930                         usleep(1000 * 1000);
931                         freq = MMRadioEmulatorFreq[emulatoridx];
932                         MMRADIO_LOG_DEBUG("freq: %d", freq);
933
934                         if (freq < prev_freq) {
935                                 MMRADIO_LOG_DEBUG("scanning wrapped around. stopping scan");
936                                 break;
937                         }
938
939                         if (p_thread->thread_exit) {
940                                 MMRADIO_LOG_DEBUG("exiting scan thread");
941                                 goto EXIT;
942                         }
943
944                         if (p_thread->stop)
945                                 break;
946
947                         if (freq == prev_freq)
948                                 continue;
949
950                         prev_freq = freq;
951                         MMRADIO_LOG_INFO("scanning : new frequency : [%d]", freq);
952
953                         /* drop if out of range freq is scanned */
954                         if (freq >= radio->region_setting.band_max
955                             || freq < radio->region_setting.band_min) {
956                                 MMRADIO_LOG_DEBUG("%d freq is dropping...and stopping scan", freq);
957                                 break;
958                         }
959
960                         if (p_thread->stop)
961                                 break;                  /* doesn't need to post */
962
963                         __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_INFO, freq);
964                         emulatoridx++;
965                         if (emulatoridx >= EMULATOR_FREQ_MAX)
966                                 break;
967                 }
968
969 FINISHED:
970                 if (radio->old_state == MM_RADIO_STATE_READY) {
971                         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
972                 } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
973                         _mmradio_unmute(radio);
974                         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
975                         /* check if it's limit freq or not */
976                         if (__is_tunable_frequency(radio, freq)) {
977                                 /* now tune to new frequency */
978                                 if (_mmradio_set_frequency(radio, freq))
979                                         MMRADIO_LOG_ERROR("failed to tune to new frequency");
980                         }
981                 }
982
983                 p_thread->is_running = false;
984
985                 if (p_thread->stop)
986                         __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_STOPPED, 0);
987                 else
988                         __mmradio_msg_push(radio, MM_RADIO_MSG_SCAN_FINISHED, 0);
989
990                 /* reset thread stop flag */
991                 p_thread->stop = false;
992
993         }
994
995 EXIT:
996         MMRADIO_THREAD_UNLOCK(p_thread);
997         MMRADIO_LOG_FLEAVE();
998         pthread_exit(NULL);
999         return;
1000 }
1001
1002 bool __is_tunable_frequency(mm_radio_t * radio, int freq)
1003 {
1004         MMRADIO_LOG_FENTER();
1005
1006         MMRADIO_CHECK_INSTANCE(radio);
1007
1008         if (freq == radio->region_setting.band_max || freq == radio->region_setting.band_min)
1009                 return false;
1010
1011         MMRADIO_LOG_FLEAVE();
1012
1013         return true;
1014 }
1015
1016 void __mmradio_seek_thread(mm_radio_t * radio)
1017 {
1018         int freq = 0;
1019         int i = 0;
1020         int emulatoridx = 0;
1021         MMRadioThread_t *p_thread = NULL;
1022
1023         MMRADIO_LOG_FENTER();
1024         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1025
1026         p_thread = &radio->thread[MM_RADIO_THREAD_SEEK];
1027         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1028
1029         MMRADIO_THREAD_LOCK(p_thread);
1030         MMRADIO_THREAD_SIGNAL(p_thread);
1031         MMRADIO_THREAD_UNLOCK(p_thread);
1032
1033         MMRADIO_THREAD_LOCK(p_thread);
1034
1035         while (!p_thread->thread_exit) {
1036                 MMRADIO_LOG_DEBUG("seek thread started. waiting for signal.\n");
1037                 MMRADIO_THREAD_WAIT(p_thread);
1038
1039                 if (p_thread->thread_exit) {
1040                         MMRADIO_LOG_DEBUG("exiting seek thread");
1041                         break;
1042                 }
1043
1044                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1045                 MMRADIO_LOG_DEBUG("seeking....");
1046
1047                 if (p_thread->stop) {
1048                         MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1049                         goto SEEK_FAILED;
1050                 }
1051
1052                 emulatoridx = 0;
1053                 freq = 0;
1054                 MMRADIO_LOG_DEBUG("start radio->freq: %d", radio->freq);
1055
1056                 if (radio->seek_direction == MM_RADIO_SEEK_UP) {
1057                         for (i = 0; i < EMULATOR_FREQ_MAX; i++) {
1058                                 if (radio->freq < MMRadioEmulatorFreq[i]) {
1059                                         freq = MMRadioEmulatorFreq[i];
1060                                         emulatoridx = i;
1061                                         break;
1062                                 }
1063                         }
1064                         if (!freq) {
1065                                 freq = MMRadioEmulatorFreq[0];
1066                                 emulatoridx = 0;
1067                         }
1068                 } else {
1069                         for (i = EMULATOR_FREQ_MAX - 1; i >= 0; i--) {
1070                                 if (radio->freq > MMRadioEmulatorFreq[i]) {
1071                                         freq = MMRadioEmulatorFreq[i];
1072                                         emulatoridx = i;
1073                                         break;
1074                                 }
1075                         }
1076                         if (!freq) {
1077                                 freq = MMRadioEmulatorFreq[EMULATOR_FREQ_MAX - 1];
1078                                 emulatoridx = EMULATOR_FREQ_MAX - 1;
1079                         }
1080                 }
1081
1082                 radio->freq = freq;
1083                 MMRADIO_LOG_DEBUG("radio->freq: %d emulatoridx: %d", radio->freq, emulatoridx);
1084
1085                 MMRADIO_LOG_DEBUG("found frequency");
1086
1087                 /* if same freq is found, ignore it and search next one. */
1088                 if (freq == radio->prev_seek_freq) {
1089                         MMRADIO_LOG_DEBUG("It's same with previous found one. So, trying next one.");
1090                         goto SEEK_FAILED;
1091                 }
1092
1093                 /* check if it's limit freq or not */
1094                 if (__is_tunable_frequency(radio, freq)) {
1095                         /* now tune to new frequency */
1096                         if (_mmradio_set_frequency(radio, freq)) {
1097                                 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1098                                 goto SEEK_FAILED;
1099                         }
1100                 }
1101
1102                 radio->prev_seek_freq = freq;
1103                 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", (int) freq);
1104                 p_thread->is_running = false;
1105                 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, freq);
1106                 p_thread->stop = true;
1107                 continue;
1108
1109 SEEK_FAILED:
1110                 /* freq -1 means it's failed to seek */
1111                 __mmradio_msg_push(radio, MM_RADIO_MSG_SEEK_FINISHED, -1);
1112                 p_thread->stop = true;
1113                 p_thread->is_running = false;
1114         }
1115
1116         MMRADIO_THREAD_UNLOCK(p_thread);
1117         MMRADIO_LOG_FLEAVE();
1118         pthread_exit(NULL);
1119         return;
1120 }
1121
1122 static bool __mmradio_post_message(mm_radio_t * radio, enum MMMessageType msgtype, MMMessageParamType * param)
1123 {
1124         MMRADIO_CHECK_INSTANCE(radio);
1125
1126         MMRADIO_LOG_FENTER();
1127
1128         if (!radio->msg_cb) {
1129                 MMRADIO_LOG_WARNING("failed to post a message because msg cb didn't register");
1130                 return false;
1131         }
1132
1133         MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1134
1135         radio->msg_cb(msgtype, param, radio->msg_cb_param);
1136
1137         MMRADIO_LOG_FLEAVE();
1138
1139         return true;
1140 }
1141
1142 static int __mmradio_check_state(mm_radio_t * radio, MMRadioCommand command)
1143 {
1144         MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1145
1146         MMRADIO_LOG_FENTER();
1147
1148         MMRADIO_CHECK_INSTANCE(radio);
1149
1150         radio_state = __mmradio_get_state(radio);
1151
1152         MMRADIO_LOG_DEBUG("incoming command : %d  current state : %d", command, radio_state);
1153
1154         switch (command) {
1155         case MMRADIO_COMMAND_CREATE:
1156                 {
1157                         if (radio_state != 0)
1158                                 goto NO_OP;
1159                 }
1160                 break;
1161
1162         case MMRADIO_COMMAND_REALIZE:
1163                 {
1164                         if (radio_state == MM_RADIO_STATE_READY ||
1165                                 radio_state == MM_RADIO_STATE_PLAYING ||
1166                                 radio_state == MM_RADIO_STATE_SCANNING)
1167                                 goto NO_OP;
1168
1169                         if (radio_state == 0)
1170                                 goto INVALID_STATE;
1171                 }
1172                 break;
1173
1174         case MMRADIO_COMMAND_UNREALIZE:
1175                 {
1176                         if (radio_state == MM_RADIO_STATE_NULL)
1177                                 goto NO_OP;
1178
1179                         /* we can call unrealize at any higher state */
1180                 }
1181                 break;
1182
1183         case MMRADIO_COMMAND_START:
1184                 {
1185                         if (radio_state == MM_RADIO_STATE_PLAYING)
1186                                 goto NO_OP;
1187
1188                         if (radio_state != MM_RADIO_STATE_READY)
1189                                 goto INVALID_STATE;
1190                 }
1191                 break;
1192
1193         case MMRADIO_COMMAND_STOP:
1194                 {
1195                         if (radio_state == MM_RADIO_STATE_READY)
1196                                 goto NO_OP;
1197
1198                         if (radio_state != MM_RADIO_STATE_PLAYING)
1199                                 goto INVALID_STATE;
1200                 }
1201                 break;
1202
1203         case MMRADIO_COMMAND_START_SCAN:
1204                 {
1205                         if (radio_state == MM_RADIO_STATE_SCANNING)
1206                                 goto NO_OP;
1207
1208                         if (radio_state == MM_RADIO_STATE_NULL)
1209                                 goto INVALID_STATE;
1210                 }
1211                 break;
1212
1213         case MMRADIO_COMMAND_STOP_SCAN:
1214                 {
1215                         if (radio_state == MM_RADIO_STATE_READY)
1216                                 goto NO_OP;
1217
1218                         if (radio_state != MM_RADIO_STATE_SCANNING)
1219                                 goto INVALID_STATE;
1220                 }
1221                 break;
1222
1223         case MMRADIO_COMMAND_DESTROY:
1224         case MMRADIO_COMMAND_MUTE:
1225         case MMRADIO_COMMAND_UNMUTE:
1226         case MMRADIO_COMMAND_SET_FREQ:
1227         case MMRADIO_COMMAND_GET_FREQ:
1228         case MMRADIO_COMMAND_SET_REGION:
1229                 {
1230                         /* we can do it at any state */
1231                 }
1232                 break;
1233
1234         case MMRADIO_COMMAND_SEEK:
1235                 {
1236                         if (radio_state != MM_RADIO_STATE_PLAYING)
1237                                 goto INVALID_STATE;
1238                 }
1239                 break;
1240
1241         case MMRADIO_COMMAND_GET_REGION:
1242                 {
1243                         if (radio_state == MM_RADIO_STATE_NULL)
1244                                 goto INVALID_STATE;
1245                 }
1246                 break;
1247
1248         default:
1249                 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1250                 break;
1251         }
1252
1253         MMRADIO_LOG_DEBUG("status OK");
1254
1255         radio->cmd = command;
1256
1257         MMRADIO_LOG_FLEAVE();
1258
1259         return MM_ERROR_NONE;
1260
1261 INVALID_STATE:
1262         MMRADIO_LOG_WARNING("invalid state. current : %d  command : %d", radio_state, command);
1263         MMRADIO_LOG_FLEAVE();
1264         return MM_ERROR_RADIO_INVALID_STATE;
1265
1266 NO_OP:
1267         MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1268         MMRADIO_LOG_FLEAVE();
1269         return MM_ERROR_RADIO_NO_OP;
1270
1271 }
1272
1273 static bool __mmradio_set_state(mm_radio_t * radio, int new_state)
1274 {
1275         MMMessageParamType msg = { 0, };
1276         int msg_type = MM_MESSAGE_UNKNOWN;
1277
1278         MMRADIO_LOG_FENTER();
1279
1280         if (!radio) {
1281                 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1282                 return false;
1283         }
1284
1285         if (radio->current_state == new_state && radio->pending_state == 0) {
1286                 MMRADIO_LOG_WARNING("we are in same state");
1287                 return true;
1288         }
1289
1290         /* set state */
1291         radio->old_state = radio->current_state;
1292         radio->current_state = new_state;
1293
1294         /* fill message param */
1295         msg.union_type = MM_MSG_UNION_STATE;
1296         msg.state.previous = radio->old_state;
1297         msg.state.current = radio->current_state;
1298
1299         if (radio->interrupted_by_resource_conflict) {
1300                 __mmradio_msg_push(radio, MM_RADIO_MSG_STATE_INTERRUPTED,
1301                         MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT);
1302         } else {
1303                 msg_type = MM_MESSAGE_STATE_CHANGED;
1304                 MMRADIO_POST_MSG(radio, msg_type, &msg);
1305         }
1306
1307         MMRADIO_LOG_FLEAVE();
1308
1309         return true;
1310 }
1311
1312 static int __mmradio_get_state(mm_radio_t * radio)
1313 {
1314         MMRADIO_CHECK_INSTANCE(radio);
1315
1316         MMRADIO_LOG_DEBUG("radio state : current : [%d]   old : [%d]   pending : [%d]",
1317                                                 radio->current_state, radio->old_state, radio->pending_state);
1318
1319         return radio->current_state;
1320 }
1321
1322 int _mmradio_get_region_type(mm_radio_t * radio, MMRadioRegionType * type)
1323 {
1324         MMRADIO_LOG_FENTER();
1325         MMRADIO_CHECK_INSTANCE(radio);
1326         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1327
1328         MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1329
1330         *type = radio->region_setting.country;
1331
1332         MMRADIO_LOG_FLEAVE();
1333         return MM_ERROR_NONE;
1334 }
1335
1336 int _mmradio_get_region_frequency_range(mm_radio_t * radio, unsigned int *min_freq, unsigned int *max_freq)
1337 {
1338         MMRADIO_LOG_FENTER();
1339         MMRADIO_CHECK_INSTANCE(radio);
1340         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1341
1342         MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1343
1344         *min_freq = radio->region_setting.band_min;
1345         *max_freq = radio->region_setting.band_max;
1346
1347         MMRADIO_LOG_FLEAVE();
1348         return MM_ERROR_NONE;
1349 }
1350
1351 int _mmradio_get_channel_spacing(mm_radio_t * radio, unsigned int *ch_spacing)
1352 {
1353         MMRADIO_LOG_FENTER();
1354         MMRADIO_CHECK_INSTANCE(radio);
1355         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1356
1357         MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1358
1359         *ch_spacing = radio->region_setting.channel_spacing;
1360
1361         MMRADIO_LOG_FLEAVE();
1362         return MM_ERROR_NONE;
1363 }
1364
1365 static int __mmradio_get_wave_num(mm_radio_t * radio)
1366 {
1367         int val = 0;
1368         MMRADIO_LOG_FENTER();
1369
1370         if (radio->freq <= MMRadioEmulatorFreq[0])
1371                 val = 1;
1372         else if (radio->freq <= MMRadioEmulatorFreq[1])
1373                 val = 2;
1374         else if (radio->freq <= MMRadioEmulatorFreq[2])
1375                 val = 5;
1376         else if (radio->freq <= MMRadioEmulatorFreq[3])
1377                 val = 7;
1378         else if (radio->freq <= MMRadioEmulatorFreq[4])
1379                 val = 9;
1380         else
1381                 val = 11;
1382
1383         MMRADIO_LOG_DEBUG("freq: %d, val : %d", radio->freq, val);
1384         MMRADIO_LOG_FLEAVE();
1385         return val;
1386 }
1387
1388 static int __resource_release_cb(mm_resource_manager_h rm,
1389         mm_resource_manager_res_h res, void *user_data)
1390 {
1391         mm_radio_t *radio = NULL;
1392
1393         MMRADIO_LOG_FENTER();
1394
1395         if (!user_data) {
1396                 MMRADIO_LOG_ERROR("user_data is null");
1397                 return FALSE;
1398         }
1399
1400         radio = (mm_radio_t *)user_data;
1401         radio->radio_resource = NULL;
1402
1403         MMRADIO_LOG_DEBUG("radio resource conflict so, resource will be freed by _mmradio_stop");
1404
1405         radio->interrupted_by_resource_conflict = TRUE;
1406
1407         MMRADIO_CMD_LOCK(radio);
1408         if (_mmradio_stop(radio) != MM_ERROR_NONE)
1409                 MMRADIO_LOG_ERROR("failed to stop radio");
1410         MMRADIO_CMD_UNLOCK(radio);
1411
1412         MMRADIO_LOG_FLEAVE();
1413
1414         return FALSE;
1415 }
1416
1417 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1418 {
1419         MMRADIO_LOG_FENTER();
1420
1421         MMRADIO_CHECK_INSTANCE(radio);
1422         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1423
1424         MMRADIO_SLOG_DEBUG("Setting %f volume", volume);
1425
1426         /* check volume range */
1427         if (volume < RADIO_MIN_VOLUME || volume > RADIO_MAX_VOLUME) {
1428                 MMRADIO_LOG_ERROR("out of volume range");
1429                 return MM_ERROR_INVALID_ARGUMENT;
1430         }
1431
1432         if (radio->radio_fd < 0) {
1433                 MMRADIO_LOG_DEBUG("radio device is not opened yet");
1434                 radio->local_volume = volume;
1435                 return MM_ERROR_NONE;
1436         }
1437
1438         radio->local_volume = volume;
1439
1440         if (radio->pipeline && radio->pipeline->volume) {
1441                 g_object_set(radio->pipeline->volume, "volume", volume, NULL);
1442                 MMRADIO_LOG_DEBUG("g_object set volume");
1443         }
1444
1445         MMRADIO_LOG_FLEAVE();
1446
1447         return MM_ERROR_NONE;
1448
1449 }
1450 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1451 {
1452         MMRADIO_LOG_FENTER();
1453
1454         MMRADIO_CHECK_INSTANCE(radio);
1455         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1456
1457         MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1458
1459         MMRADIO_SLOG_DEBUG("volume : %f", radio->local_volume);
1460
1461         *pVolume = radio->local_volume;
1462
1463         MMRADIO_LOG_FLEAVE();
1464
1465         return MM_ERROR_NONE;
1466 }
1467
1468 static int __mmradio_create_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1469 {
1470         MMRadioThread_t *p_thread = NULL;
1471
1472         MMRADIO_LOG_FENTER();
1473
1474         MMRADIO_CHECK_INSTANCE(radio);
1475
1476         if (type >= MM_RADIO_THREAD_NUM) {
1477                 MMRADIO_LOG_WARNING("wrong argument thread type");
1478                 return MM_ERROR_RADIO_INTERNAL;
1479         }
1480
1481         p_thread = &radio->thread[type];
1482         MMRADIO_CHECK_ARG(p_thread);
1483
1484         MMRADIO_INIT_MUTEX(p_thread->mutex);
1485         MMRADIO_INIT_COND(p_thread->cond);
1486
1487         MMRADIO_THREAD_LOCK(p_thread);
1488         p_thread->thread_id = pthread_create(&p_thread->thread, NULL,
1489                 (void *)__mmradio_thread_function[type], (void *)radio);
1490         if (p_thread->thread_id) {
1491                 MMRADIO_LOG_DEBUG("failed to create thread : [%d]", type);
1492                 MMRADIO_THREAD_UNLOCK(p_thread);
1493                 return MM_ERROR_RADIO_INTERNAL;
1494         }
1495
1496         MMRADIO_LOG_DEBUG("wait for [%d] thread", type);
1497         MMRADIO_THREAD_WAIT(p_thread);
1498         MMRADIO_LOG_DEBUG("[%d] thread started", type);
1499         MMRADIO_THREAD_UNLOCK(p_thread);
1500
1501         return MM_ERROR_NONE;
1502
1503 ERROR:
1504         pthread_mutex_destroy(&p_thread->mutex);
1505         pthread_cond_destroy(&p_thread->cond);
1506         return MM_ERROR_RADIO_INTERNAL;
1507
1508 }
1509
1510 static int __mmradio_create_threads(mm_radio_t *radio)
1511 {
1512         int ret = MM_ERROR_NONE;
1513         int type = 0;
1514
1515         MMRADIO_LOG_FENTER();
1516
1517         MMRADIO_CHECK_INSTANCE(radio);
1518
1519         MMRADIO_INIT_MUTEX(radio->cmd_lock);
1520
1521         for (type = (int)MM_RADIO_THREAD_MSG; type < (int)MM_RADIO_THREAD_NUM; type++) {
1522                 ret = __mmradio_create_thread_type(radio, (MMRadioThreadTypes)type);
1523                 if (ret) {
1524                         MMRADIO_LOG_ERROR("failed to create thread(%d)", type);
1525                         while (--type >= (int)MM_RADIO_THREAD_MSG)
1526                                 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1527                         goto ERROR;
1528                 }
1529         }
1530
1531         MMRADIO_LOG_FLEAVE();
1532         return ret;
1533
1534 ERROR:
1535         pthread_mutex_destroy(&radio->cmd_lock);
1536         MMRADIO_LOG_FLEAVE();
1537         return MM_ERROR_RADIO_INTERNAL;
1538 }
1539
1540 static void __mmradio_destroy_thread_type(mm_radio_t *radio, MMRadioThreadTypes type)
1541 {
1542         MMRadioThread_t *p_thread = NULL;
1543         mm_radio_msg_t *msg = NULL;
1544         MMRADIO_LOG_FENTER();
1545
1546         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1547
1548         if (type >= MM_RADIO_THREAD_NUM) {
1549                 MMRADIO_LOG_WARNING("wrong argument thread type");
1550                 return;
1551         }
1552
1553         p_thread = &radio->thread[type];
1554         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1555
1556         if (p_thread->thread) {
1557                 switch (type) {
1558                 case MM_RADIO_THREAD_MSG:
1559                         msg = g_slice_new0(mm_radio_msg_t);
1560                         msg->msg_type = MM_RADIO_MSG_DESTROY;
1561                         g_async_queue_push_front(radio->msg_queue, msg);
1562                         pthread_join(p_thread->thread, NULL);
1563                         p_thread->thread = 0;
1564                         break;
1565                 case MM_RADIO_THREAD_SEEK:
1566                 case MM_RADIO_THREAD_SCAN:
1567                         MMRADIO_THREAD_LOCK(p_thread);
1568                         p_thread->thread_exit = true;
1569                         MMRADIO_THREAD_SIGNAL(p_thread);
1570                         MMRADIO_THREAD_UNLOCK(p_thread);
1571                         pthread_join(p_thread->thread, NULL);
1572                         p_thread->thread = 0;
1573                         break;
1574                 default:
1575                         MMRADIO_LOG_WARNING("(%d)type isn't handled", type);
1576                         break;
1577                 }
1578         } else {
1579                 MMRADIO_LOG_WARNING("(%d)thread is zero", type);
1580         }
1581
1582         pthread_mutex_destroy(&p_thread->mutex);
1583         pthread_cond_destroy(&p_thread->cond);
1584
1585         MMRADIO_LOG_FLEAVE();
1586 }
1587
1588 static void __mmradio_destroy_threads(mm_radio_t *radio)
1589 {
1590         int type = (int)MM_RADIO_THREAD_NUM;
1591         MMRADIO_LOG_FENTER();
1592
1593         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1594
1595         while (--type >= 0)
1596                 __mmradio_destroy_thread_type(radio, (MMRadioThreadTypes)type);
1597
1598         pthread_mutex_destroy(&radio->cmd_lock);
1599
1600         MMRADIO_LOG_FLEAVE();
1601 }
1602
1603
1604 void __mmradio_msg_push(mm_radio_t *radio, MMRadioMsgTypes msg_type, int msg_data)
1605 {
1606         mm_radio_msg_t *msg = g_slice_new0(mm_radio_msg_t);
1607
1608         msg->msg_type = msg_type;
1609         msg->data = msg_data;
1610
1611         MMRADIO_LOG_INFO("push msg_type: %d, msg_data: %d", (int)msg->msg_type, msg->data);
1612         g_async_queue_push(radio->msg_queue, msg);
1613 }
1614
1615 void __mmradio_msg_thread(mm_radio_t *radio)
1616 {
1617         mm_radio_msg_t *msg = NULL;
1618         MMRadioThread_t *p_thread = NULL;
1619
1620         MMRADIO_LOG_FENTER();
1621         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1622
1623         p_thread = &radio->thread[MM_RADIO_THREAD_MSG];
1624         MMRADIO_CHECK_ARG_RETURN_VOID(p_thread);
1625
1626         p_thread->thread_exit = false;
1627
1628         MMRADIO_THREAD_LOCK(p_thread);
1629         MMRADIO_THREAD_SIGNAL(p_thread);
1630         MMRADIO_THREAD_UNLOCK(p_thread);
1631
1632         /*we run a while one loop*/
1633         while (!p_thread->thread_exit) {
1634                 msg = (mm_radio_msg_t *)g_async_queue_pop(radio->msg_queue);
1635                 if (!msg) {
1636                         MMRADIO_LOG_ERROR("popped message is NULL!");
1637                         break;
1638                 }
1639
1640                 MMMessageParamType param = {0,};
1641
1642                 switch (msg->msg_type) {
1643                 case MM_RADIO_MSG_DESTROY:
1644                         MMRADIO_LOG_INFO("get destroy msg. pop all event to finish this thread");
1645                         mm_radio_msg_t *msg_pop = NULL;
1646                         while ((msg_pop = (mm_radio_msg_t *)g_async_queue_try_pop(radio->msg_queue))) {
1647                                 if (msg_pop != NULL) {
1648                                         MMRADIO_LOG_DEBUG("drop this msg type: %d", msg_pop->msg_type);
1649                                         g_slice_free(mm_radio_msg_t, msg_pop);
1650                                 }
1651                         }
1652                         p_thread->thread_exit = true;
1653                         break;
1654                 case MM_RADIO_MSG_SCAN_INFO:
1655                         MMRADIO_LOG_INFO("get scan info frequency: %d", msg->data);
1656                         param.radio_scan.frequency = (int) msg->data;
1657                         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
1658                         break;
1659                 case MM_RADIO_MSG_SCAN_STOPPED:
1660                         MMRADIO_LOG_INFO("get scan stopped");
1661                         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1662                         break;
1663                 case MM_RADIO_MSG_SCAN_FINISHED:
1664                         MMRADIO_LOG_INFO("get scan finished");
1665                         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1666                         break;
1667                 case MM_RADIO_MSG_SEEK_FINISHED:
1668                         MMRADIO_LOG_INFO("get seek finished frequency: %d", msg->data);
1669                         param.radio_scan.frequency = (int) msg->data;
1670                         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
1671                         break;
1672                 case MM_RADIO_MSG_STATE_INTERRUPTED:
1673                         MMRADIO_LOG_INFO("get state interrupted type: %d", msg->data);
1674                         param.union_type = MM_MSG_UNION_STATE;
1675                         param.state.previous = radio->old_state;
1676                         param.state.current = radio->current_state;
1677                         param.state.code = msg->data;
1678                         MMRADIO_POST_MSG(radio, MM_MESSAGE_STATE_INTERRUPTED, &param);
1679                         break;
1680                 default:
1681                         MMRADIO_LOG_ERROR("wrong msg_type : %d", msg->msg_type);
1682                         break;
1683                 }
1684
1685                 if (msg)
1686                         g_slice_free(mm_radio_msg_t, msg);
1687         }
1688
1689         MMRADIO_LOG_INFO("msg thread is finished");
1690         MMRADIO_LOG_FLEAVE();
1691         pthread_exit(NULL);
1692 }