Fixed scan_thread initialization bug
[platform/core/multimedia/libmm-radio.git] / src / mm_radio_priv_hal.c
1 /*
2  * mm_radio_priv_hal.c
3  *
4  * Copyright (c) 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 <float.h>
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <unistd.h>
34 #include <errno.h>
35
36 #include <mm_error.h>
37 #include <mm_message.h>
38 #include <mm_sound.h>
39
40 #include "mm_radio_priv_hal.h"
41
42 /*===========================================================================================
43   LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE
44 ========================================================================================== */
45 /*---------------------------------------------------------------------------
46     GLOBAL CONSTANT DEFINITIONS:
47 ---------------------------------------------------------------------------*/
48
49 /*---------------------------------------------------------------------------
50     IMPORTED VARIABLE DECLARATIONS:
51 ---------------------------------------------------------------------------*/
52
53 /*---------------------------------------------------------------------------
54     IMPORTED FUNCTION DECLARATIONS:
55 ---------------------------------------------------------------------------*/
56
57 /*---------------------------------------------------------------------------
58     LOCAL #defines:
59 ---------------------------------------------------------------------------*/
60 #define DEFAULT_DEVICE                          "/dev/radio0"
61 #define TUNER_INDEX                             0
62
63 #define DEFAULT_FREQ                            107700
64
65 #define FREQ_FRAC                               16
66 #define RADIO_FREQ_FORMAT_SET(x_freq)           ((x_freq) * FREQ_FRAC)
67 #define RADIO_FREQ_FORMAT_GET(x_freq)           ((x_freq) / FREQ_FRAC)
68 /* If non-zero, wrap around when at the end of the frequency range, else stop seeking */
69 #define DEFAULT_WRAP_AROUND             1
70
71 #define RADIO_DEFAULT_REGION    MM_RADIO_REGION_GROUP_USA
72 #define READ_MAX_BUFFER_SIZE    1024
73 #define DEFAULT_MAX_MEDIA_VOLUME        15
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 /*---------------------------------------------------------------------------
116     LOCAL FUNCTION PROTOTYPES:
117 ---------------------------------------------------------------------------*/
118 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param);
119 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command);
120 static int __mmradio_get_state(mm_radio_t *radio);
121 static bool __mmradio_set_state(mm_radio_t *radio, int new_state);
122 void _mmradio_seek_cancel(mm_radio_t *radio);
123 static void __mmradio_seek_thread(mm_radio_t *radio);
124 static void __mmradio_scan_thread(mm_radio_t *radio);
125 static bool __is_tunable_frequency(mm_radio_t *radio, int freq);
126
127 #ifdef TIZEN_FEATURE_SOUND_FOCUS
128 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
129         mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
130         const char *additional_info, void *user_data);
131 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
132         mm_sound_focus_state_e focus_state, const char *reason_for_change,
133         const char *additional_info, void *user_data);
134 #endif
135
136 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data);
137 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level);
138
139 int _mmradio_apply_region(mm_radio_t *radio, MMRadioRegionType region, bool update)
140 {
141         int ret = MM_ERROR_NONE;
142         int count = 0;
143         int index = 0;
144
145         MMRADIO_LOG_FENTER();
146
147         MMRADIO_CHECK_INSTANCE(radio);
148         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_REGION);
149
150         /* if needed, radio region must be updated.
151          * Otherwise, just applying settings to device without it.
152          */
153         if (update) {
154                 count = ARRAY_SIZE(region_table);
155
156                 /* TODO: if auto is supported...get the region info. here */
157
158                 /* update radio region settings */
159                 for (index = 0; index < count; index++) {
160                         /* find the region from pre-defined table */
161                         if (region_table[index].country == region) {
162                                 radio->region_setting.country = region_table[index].country;
163                                 radio->region_setting.deemphasis = region_table[index].deemphasis;
164                                 radio->region_setting.band_min = region_table[index].band_min;
165                                 radio->region_setting.band_max = region_table[index].band_max;
166                                 radio->region_setting.channel_spacing = region_table[index].channel_spacing;
167                         }
168                 }
169         }
170
171         MMRADIO_LOG_INFO("setting region - country: %d, de-emphasis: %d, band range: %d ~ %d KHz",
172                 radio->region_setting.country, radio->region_setting.deemphasis,
173                 radio->region_setting.band_min, radio->region_setting.band_max);
174
175         MMRADIO_LOG_FLEAVE();
176
177         return ret;
178 }
179
180 int _mmradio_create_radio(mm_radio_t *radio)
181 {
182         int ret = MM_ERROR_NONE;
183
184         MMRADIO_LOG_FENTER();
185
186         MMRADIO_CHECK_INSTANCE(radio);
187         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_CREATE);
188
189         /* set default value */
190         radio->freq = DEFAULT_FREQ;
191 #ifdef TIZEN_FEATURE_SOUND_FOCUS
192         memset(&radio->sound_focus, 0, sizeof(mm_radio_sound_focus));
193 #endif
194         memset(&radio->region_setting, 0, sizeof(MMRadioRegion_t));
195         radio->local_volume = 1.0;
196
197         /* create command lock */
198         ret = pthread_mutex_init(&radio->cmd_lock, NULL);
199         if (ret) {
200                 MMRADIO_LOG_ERROR("mutex creation failed");
201                 return MM_ERROR_RADIO_INTERNAL;
202         }
203
204         ret = pthread_mutex_init(&radio->volume_lock, NULL);
205         if (ret) {
206                 MMRADIO_LOG_ERROR("volume mutex creation failed");
207                 return MM_ERROR_RADIO_INTERNAL;
208         }
209
210         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
211
212         /* initialize resource manager */
213         ret = mmradio_resource_manager_init(&radio->resource_manager, radio);
214         if (ret) {
215                 MMRADIO_LOG_ERROR("failed to initialize resource manager\n");
216                 return MM_ERROR_RADIO_INTERNAL;
217         }
218
219 #ifdef TIZEN_FEATURE_SOUND_FOCUS
220         ret = mmradio_sound_focus_register(&radio->sound_focus,
221                 (mm_sound_focus_changed_cb)__mmradio_sound_focus_cb,
222                 (mm_sound_focus_changed_watch_cb)__mmradio_sound_focus_watch_cb,
223                 (void *)radio);
224
225         if (ret) {
226                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
227                 MMRADIO_LOG_ERROR("mmradio_audio_focus_register is failed");
228                 return MM_ERROR_RADIO_INTERNAL;
229         }
230 #endif
231
232         ret = radio_hal_interface_init(&(radio->hal_inf));
233         if (ret) {
234                 MMRADIO_LOG_ERROR("mmradio hal interface init failed");
235                 return ret;
236         }
237
238         MMRADIO_LOG_FLEAVE();
239
240         return MM_ERROR_NONE;
241 }
242
243 int _mmradio_realize(mm_radio_t *radio)
244 {
245         int ret = MM_ERROR_NONE;
246         bool update = false;
247         int max = 0;
248         unsigned volume = 0;
249         MMRadioRegionType region = MM_RADIO_REGION_GROUP_NONE;
250
251         MMRADIO_LOG_FENTER();
252
253         MMRADIO_CHECK_INSTANCE(radio);
254         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_REALIZE);
255
256         ret = pthread_mutex_init(&radio->seek_cancel_mutex, NULL);
257         if (ret < 0) {
258                 MMRADIO_LOG_ERROR("Mutex creation failed %d", ret);
259                 return MM_ERROR_RADIO_INTERNAL;
260         }
261
262         if (radio->region_setting.country == MM_RADIO_REGION_GROUP_NONE) {
263                 /* not initialized      yet. set it with default region */
264                 region = RADIO_DEFAULT_REGION;
265                 update = true;
266         } else {
267                 /* already initialized by application */
268                 region = radio->region_setting.country;
269         }
270
271         ret = _mmradio_apply_region(radio, region, update);
272
273 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
274         ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_RADIO, NULL, radio, &radio->stream_info);
275         if (ret != MM_ERROR_NONE) {
276                 MMRADIO_LOG_ERROR("sound_manager_create_stream_information_internal error");
277                 MMRADIO_LOG_FLEAVE();
278                 return ret;
279         }
280         ret = sound_manager_create_virtual_stream(radio->stream_info, &radio->vstream);
281         if (ret != MM_ERROR_NONE) {
282                 MMRADIO_LOG_ERROR("sound_manager_create_virtual_stream error");
283                 MMRADIO_LOG_FLEAVE();
284                 return ret;
285         }
286 #endif
287
288         ret = sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max);
289         if (ret != MM_ERROR_NONE) {
290                 MMRADIO_LOG_WARNING("sound_manager_get_max_volume error");
291                 radio->max_media_volume = DEFAULT_MAX_MEDIA_VOLUME;
292         } else {
293                 radio->max_media_volume = max;
294         }
295
296         ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
297
298         if (ret != MM_ERROR_NONE)
299                 MMRADIO_LOG_WARNING("failed to get MEDIA_VOLUME");
300
301         MMRADIO_VOLUME_LOCK(radio);
302         radio->media_volume = volume;
303         MMRADIO_VOLUME_UNLOCK(radio);
304
305         ret = mm_sound_add_volume_changed_callback(__mmradio_volume_changed_cb, (void *)radio, &radio->volume_subs_id);
306         if (ret != MM_ERROR_NONE)
307                 MMRADIO_LOG_WARNING("mm_sound_add_volume_changed_callback error");
308
309         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
310
311         MMRADIO_LOG_FLEAVE();
312
313         return MM_ERROR_NONE;
314 }
315
316 int _mmradio_unrealize(mm_radio_t *radio)
317 {
318         int ret = MM_ERROR_NONE;
319
320         MMRADIO_LOG_FENTER();
321
322         MMRADIO_CHECK_INSTANCE(radio);
323         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNREALIZE);
324
325         ret = mm_sound_remove_volume_changed_callback(radio->volume_subs_id);
326         if (ret != MM_ERROR_NONE)
327                 MMRADIO_LOG_WARNING("mm_sound_remove_volume_changed_callback error");
328
329         /*Finish if there are scans*/
330         _mmradio_stop_scan(radio);
331
332         /*Stop radio if started*/
333         _mmradio_stop(radio);
334
335         /* close radio device here !!!! */
336         radio_hal_close(radio->hal_inf);
337         radio_hal_unprepare(radio->hal_inf);
338 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
339         sound_manager_destroy_virtual_stream(radio->vstream);
340         sound_manager_destroy_stream_information(radio->stream_info);
341 #endif
342
343         pthread_mutex_destroy(&radio->seek_cancel_mutex);
344
345         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_NULL);
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         MMRADIO_LOG_FENTER();
356
357         MMRADIO_CHECK_INSTANCE(radio);
358         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_DESTROY);
359
360         _mmradio_unrealize(radio);
361
362         ret = radio_hal_interface_deinit(radio->hal_inf);
363         if (ret) {
364                 MMRADIO_LOG_ERROR("mmradio hal interface deinit failed");
365                 return ret;
366         }
367
368         /* destroy command lock */
369         ret = pthread_mutex_destroy(&radio->cmd_lock);
370         if (ret)
371                 MMRADIO_LOG_ERROR("mutex destroy failed\n");
372
373         ret = pthread_mutex_destroy(&radio->volume_lock);
374         if (ret)
375                 MMRADIO_LOG_ERROR("volume mutex destroy failed\n");
376
377 #ifdef TIZEN_FEATURE_SOUND_FOCUS
378         ret = mmradio_sound_focus_deregister(&radio->sound_focus);
379         if (ret) {
380                 MMRADIO_LOG_ERROR("failed to deregister sound focus");
381                 return MM_ERROR_RADIO_INTERNAL;
382         }
383 #endif
384
385         ret = mmradio_resource_manager_deinit(&radio->resource_manager);
386         if (ret) {
387                 MMRADIO_LOG_ERROR("failed to initialize resource manager\n");
388                 return MM_ERROR_RADIO_INTERNAL;
389         }
390
391         MMRADIO_LOG_FLEAVE();
392
393         return MM_ERROR_NONE;
394 }
395
396 /* unit should be KHz */
397 int _mmradio_set_frequency(mm_radio_t *radio, int freq)
398 {
399         int ret = MM_ERROR_NONE;
400
401         MMRADIO_LOG_FENTER();
402
403         MMRADIO_CHECK_INSTANCE(radio);
404         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_FREQ);
405
406         MMRADIO_LOG_INFO("Setting %d frequency", freq);
407
408         radio->freq = freq;
409
410         ret = radio_hal_set_frequency(radio->hal_inf, freq);
411         if (ret != MM_ERROR_NONE) {
412                 MMRADIO_LOG_ERROR("radio_hal_set_frequency error");
413                 MMRADIO_LOG_FLEAVE();
414                 return ret;
415         }
416
417         MMRADIO_LOG_FLEAVE();
418
419         return ret;
420
421 }
422
423 int _mmradio_get_frequency(mm_radio_t *radio, int *pFreq)
424 {
425         int ret = MM_ERROR_NONE;
426         uint32_t freq = 0;
427         MMRADIO_LOG_FENTER();
428
429         MMRADIO_CHECK_INSTANCE(radio);
430         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_FREQ);
431
432         MMRADIO_RETURN_VAL_IF_FAIL(pFreq, MM_ERROR_INVALID_ARGUMENT);
433
434         ret = radio_hal_get_frequency(radio->hal_inf, &freq);
435         if (ret != MM_ERROR_NONE) {
436                 MMRADIO_LOG_ERROR("radio_hal_get_frequency error");
437                 *pFreq = 0;
438                 return ret;
439         }
440
441         /* update freq in handle */
442         MMRADIO_LOG_INFO("Updating %d frequency", freq);
443         radio->freq = freq;
444
445         *pFreq = (int)radio->freq;
446
447         MMRADIO_LOG_FLEAVE();
448
449         return ret;
450 }
451
452 int _mmradio_mute(mm_radio_t *radio)
453 {
454         int ret = MM_ERROR_NONE;
455         MMRADIO_LOG_FENTER();
456
457         MMRADIO_CHECK_INSTANCE(radio);
458         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_MUTE);
459
460         ret = radio_hal_mute(radio->hal_inf);
461         if (ret == MM_ERROR_NOT_SUPPORT_API) {
462                 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
463         } else if (ret != MM_ERROR_NONE) {
464                 MMRADIO_LOG_ERROR("radio_hal_mute error");
465                 MMRADIO_LOG_FLEAVE();
466                 return ret;
467         }
468
469         radio->is_muted = TRUE;
470         MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
471         MMRADIO_LOG_FLEAVE();
472
473         return ret;
474 }
475
476 int _mmradio_unmute(mm_radio_t *radio)
477 {
478         int ret = MM_ERROR_NONE;
479         MMRADIO_LOG_FENTER();
480
481         MMRADIO_CHECK_INSTANCE(radio);
482         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_UNMUTE);
483
484         ret = radio_hal_unmute(radio->hal_inf);
485         if (ret == MM_ERROR_NOT_SUPPORT_API) {
486                 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
487         } else if (ret != MM_ERROR_NONE) {
488                 MMRADIO_LOG_ERROR("radio_hal_unmute error");
489                 MMRADIO_LOG_FLEAVE();
490                 return ret;
491         }
492
493         radio->is_muted = FALSE;
494         MMRADIO_LOG_INFO("Radio mute state [%d]", radio->is_muted);
495         MMRADIO_LOG_FLEAVE();
496
497         return ret;
498 }
499
500 int _mmradio_set_message_callback(mm_radio_t *radio, MMMessageCallback callback, void *user_param)
501 {
502         MMRADIO_LOG_FENTER();
503
504         MMRADIO_CHECK_INSTANCE(radio);
505
506         radio->msg_cb = callback;
507         radio->msg_cb_param = user_param;
508
509         MMRADIO_LOG_DEBUG("msg_cb : 0x%x msg_cb_param : 0x%x", callback, user_param);
510
511         MMRADIO_LOG_FLEAVE();
512
513         return MM_ERROR_NONE;
514 }
515
516 int _mmradio_get_state(mm_radio_t *radio, int *pState)
517 {
518         int state = 0;
519
520         MMRADIO_LOG_FENTER();
521
522         MMRADIO_CHECK_INSTANCE(radio);
523         MMRADIO_RETURN_VAL_IF_FAIL(pState, MM_ERROR_INVALID_ARGUMENT);
524
525         state = __mmradio_get_state(radio);
526
527         *pState = state;
528
529         MMRADIO_LOG_FLEAVE();
530
531         return MM_ERROR_NONE;
532 }
533
534 int _mmradio_start(mm_radio_t *radio)
535 {
536         int ret = MM_ERROR_NONE;
537         unsigned int volume = 0;
538
539         MMRADIO_LOG_FENTER();
540
541         MMRADIO_CHECK_INSTANCE(radio);
542         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START);
543
544         MMRADIO_LOG_INFO("now tune to frequency : %d", radio->freq);
545
546 #ifdef TIZEN_FEATURE_SOUND_FOCUS
547         if (radio->sound_focus.handle > 0) {
548                 ret = mmradio_acquire_sound_focus(&radio->sound_focus);
549                 if (ret != MM_ERROR_NONE) {
550                         MMRADIO_LOG_ERROR("failed to set sound focus");
551                         return ret;
552                 }
553         }
554
555         /* check previous acquired focus */
556         if (radio->sound_focus.watch_id > 0) {
557                 char *stream_type = NULL;
558                 char *ext_info = NULL;
559                 int option = 0;
560
561                 ret = mm_sound_get_stream_type_of_acquired_focus(FOCUS_FOR_BOTH, &stream_type, &option, &ext_info);
562                 if (ret == MM_ERROR_NONE) {
563                         MMRADIO_LOG_DEBUG("Focus is acquired by stream_type[%s], option[%d], ext_info[%s]",
564                                 stream_type, option, ext_info);
565                         if (!strcmp(stream_type, "alarm") || !strcmp(stream_type, "ringtone-voip") ||
566                                 !strcmp(stream_type, "ringtone-call") || !strcmp(stream_type, "voip") ||
567                                 !strcmp(stream_type, "call-voice") || !strcmp(stream_type, "call-video")) {
568                                 MMRADIO_LOG_DEBUG("Blcoked by session policy, focus_acquired_by[%s]", stream_type);
569                                 free(ext_info);
570                                 free(stream_type);
571                                 return MM_ERROR_POLICY_BLOCKED;
572                         }
573                         free(ext_info);
574                         free(stream_type);
575                 }
576         }
577 #endif
578
579         if (!radio->is_ready) {
580                 ret = mmradio_resource_manager_prepare(&radio->resource_manager, MM_RADIO_RESOURCE_TYPE_RADIO);
581                 if (ret != MM_ERROR_NONE) {
582                         MMRADIO_LOG_ERROR("resource manager prepare fail");
583                         return MM_ERROR_RADIO_INTERNAL;
584                 }
585                 ret = mmradio_resource_manager_acquire(&radio->resource_manager);
586                 if (ret != MM_ERROR_NONE) {
587                         MMRADIO_LOG_ERROR("failed to acquire resource manager");
588                         mmradio_resource_manager_unprepare(&radio->resource_manager);
589                         return ret;
590                 }
591                 ret = radio_hal_prepare(radio->hal_inf);
592                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
593                         MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
594                 } else if (ret != MM_ERROR_NONE) {
595                         MMRADIO_LOG_ERROR("radio_hal_prepare_device error");
596                         goto error2;
597                 }
598
599                 ret = radio_hal_open(radio->hal_inf);
600                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
601                         MMRADIO_LOG_WARNING("radio_hal_open is not supported");
602                 } else if (ret != MM_ERROR_NONE) {
603                         MMRADIO_LOG_ERROR("radio_hal_init error");
604                         goto error1;
605                 }
606                 radio->is_ready = TRUE;
607         } else {
608                 MMRADIO_LOG_DEBUG("radio prepared and opened");
609         }
610
611         ret = mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &volume);
612         if (ret != MM_ERROR_NONE)
613                 MMRADIO_LOG_WARNING("failed to get MEDIA_VOLUME");
614
615         ret = __mmradio_set_media_volume(radio, volume);
616         if (ret != MM_ERROR_NONE) {
617                 MMRADIO_LOG_ERROR("failed to media volume");
618                 goto error1;
619         }
620
621         ret = radio_hal_start(radio->hal_inf);
622         if (ret == MM_ERROR_NOT_SUPPORT_API) {
623                 MMRADIO_LOG_WARNING("radio_hal_start is not supported");
624         } else if (ret) {
625                 MMRADIO_LOG_ERROR("failed to radio_hal_start");
626                 goto error1;
627         }
628
629         /* set stored frequency */
630         ret = radio_hal_set_frequency(radio->hal_inf, radio->freq);
631         if (ret) {
632                 MMRADIO_LOG_ERROR("failed to radio_hal_set_frequency");
633                 goto error1;
634         }
635
636 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
637         ret = sound_manager_start_virtual_stream(radio->vstream);
638         if (ret) {
639                 MMRADIO_LOG_ERROR("failed to sound_manager_start_virtual_stream");
640                 goto error;
641         }
642 #endif
643
644         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
645
646         MMRADIO_LOG_FLEAVE();
647
648         return MM_ERROR_NONE;
649
650 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
651 error:
652         sound_manager_stop_virtual_stream(radio->vstream);
653 #endif
654 error1:
655         radio_hal_close(radio->hal_inf);
656 error2:
657         radio_hal_unprepare(radio->hal_inf);
658         radio->is_ready = FALSE;
659         return ret;
660 }
661
662 int _mmradio_stop(mm_radio_t *radio)
663 {
664         int ret = MM_ERROR_NONE;
665         mm_radio_resource_state_e resource_state = MM_RADIO_RESOURCE_STATE_NONE;
666
667         MMRADIO_LOG_FENTER();
668
669         MMRADIO_CHECK_INSTANCE(radio);
670         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP);
671
672         radio->seek_unmute = FALSE;
673         /*cancel if any seek*/
674         _mmradio_seek_cancel(radio);
675 #ifdef TIZEN_FEATURE_SOUND_VSTREAM
676         ret = sound_manager_stop_virtual_stream(radio->vstream);
677         if (ret != MM_ERROR_NONE) {
678                 MMRADIO_LOG_ERROR("failed to stop virtual_stream");
679                 return ret;
680         }
681 #endif
682
683         ret = radio_hal_stop(radio->hal_inf);
684         if (ret == MM_ERROR_NOT_SUPPORT_API) {
685                 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
686         } else if (ret) {
687                 MMRADIO_LOG_ERROR("failed to radio_hal_stop");
688                 return ret;
689         }
690
691         /* close radio device here !!!! */
692         ret = radio_hal_close(radio->hal_inf);
693         if (ret == MM_ERROR_NOT_SUPPORT_API) {
694                 MMRADIO_LOG_WARNING("radio_hal_close is not supported");
695         } else if (ret != MM_ERROR_NONE) {
696                 MMRADIO_LOG_ERROR("radio_hal_close_device error");
697                 return ret;
698         }
699
700         ret = radio_hal_unprepare(radio->hal_inf);
701         if (ret == MM_ERROR_NOT_SUPPORT_API) {
702                 MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
703         } else if (ret != MM_ERROR_NONE) {
704                 MMRADIO_LOG_ERROR("radio_hal_close_device error");
705                 return ret;
706         }
707
708         radio->is_ready = FALSE;
709
710         if (!radio->resource_manager.by_rm_cb && /* is being released */
711                 mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
712                 if (resource_state == MM_RADIO_RESOURCE_STATE_ACQUIRED) {
713                         ret = mmradio_resource_manager_release(&radio->resource_manager);
714                         if (ret != MM_ERROR_NONE) {
715                                 MMRADIO_LOG_ERROR("failed to release resource, ret(0x%x)", ret);
716                                 return ret;
717                         }
718                 }
719         }
720
721         if (mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
722                 if (resource_state == MM_RADIO_RESOURCE_STATE_PREPARED) {
723                         ret = mmradio_resource_manager_unprepare(&radio->resource_manager);
724                         if (ret != MM_ERROR_NONE)
725                                 MMRADIO_LOG_ERROR("resource manager unprepare fail");
726                 }
727         }
728
729 #ifdef TIZEN_FEATURE_SOUND_FOCUS
730         if (radio->sound_focus.handle > 0) {
731                 ret = mmradio_release_sound_focus(&radio->sound_focus);
732                 if (ret) {
733                         MMRADIO_LOG_ERROR("mmradio_release_audio_focus is failed");
734                         return ret;
735                 }
736         }
737 #endif
738         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
739
740         MMRADIO_LOG_FLEAVE();
741
742         return MM_ERROR_NONE;
743 }
744
745 int _mmradio_seek(mm_radio_t *radio, MMRadioSeekDirectionType direction)
746 {
747         int ret = MM_ERROR_NONE;
748
749         MMRADIO_LOG_FENTER();
750
751         MMRADIO_CHECK_INSTANCE(radio);
752         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SEEK);
753
754         if (radio->is_seeking) {
755                 MMRADIO_LOG_ERROR("[RADIO_ERROR_INVALID_OPERATION]radio is seeking, can't serve another request try again");
756                 return MM_ERROR_RADIO_INTERNAL;
757         }
758
759         radio->seek_unmute = FALSE;
760         radio->is_seeking = TRUE;
761         radio->seek_cancel = FALSE;
762
763         if (!radio->is_muted) {
764                 ret = radio_hal_mute(radio->hal_inf);
765                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
766                         MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
767                 } else if (ret) {
768                         MMRADIO_LOG_ERROR("failed to radio_hal_mute");
769                         return ret;
770                 }
771                 radio->seek_unmute = TRUE;
772         }
773
774         MMRADIO_LOG_INFO("trying to seek. direction[0:UP/1:DOWN) %d", direction);
775         radio->seek_direction = direction;
776
777         ret = pthread_create(&radio->seek_thread, NULL, (void *)__mmradio_seek_thread, (void *)radio);
778
779         if (ret) {
780                 MMRADIO_LOG_DEBUG("failed create thread");
781                 radio->is_seeking = FALSE;
782                 radio->seek_cancel = TRUE;
783                 if (radio->seek_unmute) {
784                         ret = radio_hal_mute(radio->hal_inf);
785                         if (ret == MM_ERROR_NOT_SUPPORT_API) {
786                                 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
787                         } else if (ret) {
788                                 MMRADIO_LOG_ERROR("failed to radio_hal_mute");
789                                 radio->seek_unmute = FALSE;
790                                 return ret;
791                         }
792                 }
793                 return MM_ERROR_RADIO_INTERNAL;
794         }
795
796         MMRADIO_LOG_FLEAVE();
797
798         return MM_ERROR_NONE;
799 }
800
801 void _mmradio_seek_cancel(mm_radio_t *radio)
802 {
803         int ret = MM_ERROR_NONE;
804         char str_error[READ_MAX_BUFFER_SIZE];
805         MMRADIO_LOG_FENTER();
806
807         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
808
809         /*cancel any outstanding seek request*/
810         radio->seek_cancel = TRUE;
811         if (radio->seek_thread) {
812                 ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
813                 MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
814                 if (ret == EBUSY) { /* it was already locked by other */
815                         MMRADIO_LOG_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
816                 } else if (ret == 0) {
817                         MMRADIO_LOG_INFO("trylock is successful. unlock now");
818                         pthread_mutex_unlock(&radio->seek_cancel_mutex);
819                 } else {
820                         MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
821                 }
822                 MMRADIO_LOG_DEBUG("pthread_join seek_thread");
823                 pthread_join(radio->seek_thread, NULL);
824                 MMRADIO_LOG_DEBUG("done");
825                 radio->is_seeking = FALSE;
826                 radio->seek_thread = 0;
827         }
828         MMRADIO_LOG_FLEAVE();
829 }
830
831
832 int _mmradio_start_scan(mm_radio_t *radio)
833 {
834         int ret = MM_ERROR_NONE;
835
836         MMRADIO_LOG_FENTER();
837
838         MMRADIO_CHECK_INSTANCE(radio);
839         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_START_SCAN);
840
841         int scan_tr_id = 0;
842
843         radio->stop_scan = false;
844
845         if (!radio->is_ready) {
846                 ret = mmradio_resource_manager_prepare(&radio->resource_manager, MM_RADIO_RESOURCE_TYPE_RADIO);
847                 if (ret != MM_ERROR_NONE) {
848                         MMRADIO_LOG_ERROR("resource manager prepare fail");
849                         return MM_ERROR_RADIO_INTERNAL;
850                 }
851                 ret = mmradio_resource_manager_acquire(&radio->resource_manager);
852                 if (ret != MM_ERROR_NONE) {
853                         MMRADIO_LOG_ERROR("failed to acquire resource manager");
854                         mmradio_resource_manager_unprepare(&radio->resource_manager);
855                         return ret;
856                 }
857
858                 ret = radio_hal_prepare(radio->hal_inf);
859                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
860                         MMRADIO_LOG_WARNING("radio_hal_prepare is not supported");
861                 } else if (ret != MM_ERROR_NONE) {
862                         MMRADIO_LOG_ERROR("radio_hal_prepare_device error");
863                         return ret;
864                 }
865
866                 ret = radio_hal_open(radio->hal_inf);
867                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
868                         MMRADIO_LOG_WARNING("radio_hal_open is not supported");
869                 } else if (ret != MM_ERROR_NONE) {
870                         MMRADIO_LOG_ERROR("radio_hal_init error");
871                         MMRADIO_LOG_FLEAVE();
872                         return ret;
873                 }
874                 radio->is_ready = TRUE;
875         } else {
876                 MMRADIO_LOG_DEBUG("radio prepared and opened");
877         }
878
879         scan_tr_id = pthread_create(&radio->scan_thread, NULL, (void *)__mmradio_scan_thread, (void *)radio);
880
881         if (scan_tr_id != 0) {
882                 MMRADIO_LOG_ERROR("failed to create thread : scan");
883                 return MM_ERROR_RADIO_NOT_INITIALIZED;
884         }
885
886         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
887
888         MMRADIO_LOG_FLEAVE();
889
890         return MM_ERROR_NONE;
891 }
892
893 int _mmradio_stop_scan(mm_radio_t *radio)
894 {
895         int ret = 0;
896         char str_error[READ_MAX_BUFFER_SIZE];
897         MMRADIO_LOG_FENTER();
898
899         MMRADIO_CHECK_INSTANCE(radio);
900         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_STOP_SCAN);
901
902         radio->stop_scan = true;
903
904         if (radio->scan_thread > 0) {
905                 /* make sure all the search is stopped else we'll wait till search finish which is not ideal*/
906                 ret = pthread_mutex_trylock(&radio->seek_cancel_mutex);
907                 MMRADIO_LOG_DEBUG("try lock ret: %s (%d)", strerror_r(ret, str_error, sizeof(str_error)), ret);
908                 if (ret == EBUSY) { /* it was already locked by other */
909                         MMRADIO_LOG_WARNING("send SEEK ABORT with FMRX_PROPERTY_SEARCH_ABORT");
910                 } else if (ret == 0) {
911                         MMRADIO_LOG_INFO("trylock is successful. unlock now");
912                         pthread_mutex_unlock(&radio->seek_cancel_mutex);
913                 } else {
914                         MMRADIO_LOG_ERROR("trylock is failed but Not EBUSY. ret: %d", ret);
915                 }
916                 MMRADIO_LOG_DEBUG("pthread_join scan_thread");
917                 pthread_join(radio->scan_thread, NULL);
918                 radio->scan_thread = 0;
919         }
920
921         MMRADIO_LOG_FLEAVE();
922
923         return MM_ERROR_NONE;
924 }
925
926 int _mm_radio_get_signal_strength(mm_radio_t *radio, int *value)
927 {
928         int ret = MM_ERROR_NONE;
929         int32_t strength = 0;
930         MMRADIO_LOG_FENTER();
931         MMRADIO_CHECK_INSTANCE(radio);
932
933         MMRADIO_RETURN_VAL_IF_FAIL(value, MM_ERROR_INVALID_ARGUMENT);
934
935         /* just return stored frequency if radio device is not ready */
936         ret = radio_hal_get_signal_strength(radio->hal_inf, &strength);
937         if (ret == MM_ERROR_NOT_SUPPORT_API) {
938                 MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
939         } else if (ret != MM_ERROR_NONE) {
940                 MMRADIO_LOG_ERROR("radio_hal_get_signal_strength error");
941                 *value = 0;
942                 MMRADIO_LOG_FLEAVE();
943                 return ret;
944         }
945         *value = (int)strength;
946         MMRADIO_LOG_FLEAVE();
947         return MM_ERROR_NONE;
948 }
949
950 void __mmradio_scan_thread(mm_radio_t *radio)
951 {
952         int ret = MM_ERROR_NONE;
953         int prev_freq = 0;
954         mm_radio_resource_state_e resource_state = MM_RADIO_RESOURCE_STATE_NONE;
955
956         MMRADIO_LOG_FENTER();
957         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
958
959         ret = radio_hal_mute(radio->hal_inf);
960
961         if (ret == MM_ERROR_NOT_SUPPORT_API) {
962                 MMRADIO_LOG_WARNING("radio_hal_mute is not supported");
963         } else if (ret != MM_ERROR_NONE) {
964                 MMRADIO_LOG_ERROR("radio_hal_mute error");
965                 goto FINISHED;
966         }
967         ret = radio_hal_set_frequency(radio->hal_inf, radio->region_setting.band_min);
968
969         if (ret != MM_ERROR_NONE)
970                 goto FINISHED;
971
972         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_START, NULL);
973         MMRADIO_SET_STATE(radio, MM_RADIO_STATE_SCANNING);
974
975         while (!radio->stop_scan) {
976                 uint32_t freq = 0;
977                 MMMessageParamType param = { 0, };
978
979                 MMRADIO_LOG_DEBUG("scanning....");
980
981                 pthread_mutex_lock(&radio->seek_cancel_mutex);
982
983                 if (radio->stop_scan) {
984                         MMRADIO_LOG_INFO("scan was canceled");
985                         pthread_mutex_unlock(&radio->seek_cancel_mutex);
986                         goto FINISHED;
987                 }
988
989                 ret = radio_hal_seek(radio->hal_inf, MM_RADIO_SEEK_UP);
990
991                 pthread_mutex_unlock(&radio->seek_cancel_mutex);
992
993                 if (ret != MM_ERROR_NONE) {
994                         MMRADIO_LOG_ERROR("radio scanning error");
995                         break;
996                 }
997
998                 /* now we can get new frequency from radio device */
999                 if (radio->stop_scan)
1000                         break;
1001
1002                 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1003                 if (ret != MM_ERROR_NONE) {
1004                         MMRADIO_LOG_ERROR("failed to get current frequency");
1005                 } else {
1006                         if (freq <= prev_freq) {
1007                                 MMRADIO_LOG_ERROR("frequency is less than previous [%d] -> [%d] we wrapped around, we are finished scanning", prev_freq, freq);
1008                                 break;
1009                         }
1010
1011                         prev_freq = param.radio_scan.frequency = (int)freq;
1012                         MMRADIO_LOG_INFO("scanning : new frequency : [%d]", param.radio_scan.frequency);
1013
1014                         /* drop if max freq is scanned */
1015                         if (param.radio_scan.frequency >= radio->region_setting.band_max) {
1016                                 MMRADIO_LOG_WARNING("%d freq is dropping...and stopping scan", param.radio_scan.frequency);
1017                                 break;
1018                         }
1019
1020                         if (radio->stop_scan) {
1021                                 /* doesn't need to post */
1022                                 break;
1023                         }
1024
1025                         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_INFO, &param);
1026                 }
1027         }
1028 FINISHED:
1029         if (radio->old_state == MM_RADIO_STATE_READY) {
1030                 MMRADIO_LOG_DEBUG("old state is ready");
1031         } else if (radio->old_state == MM_RADIO_STATE_PLAYING) {
1032                 MMRADIO_LOG_DEBUG("old state is playing");
1033                 ret = radio_hal_unmute(radio->hal_inf);
1034                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
1035                         MMRADIO_LOG_WARNING("radio_hal_unmute is not supported");
1036                 } else if (ret != MM_ERROR_NONE) {
1037                         MMRADIO_LOG_ERROR("radio_hal_unmute error");
1038                         goto FINISHED_ERR;
1039                 }
1040                 ret = radio_hal_set_frequency(radio->hal_inf, prev_freq);
1041                 if (ret == MM_ERROR_NOT_SUPPORT_API) {
1042                         MMRADIO_LOG_WARNING("radio_hal_set_frequency is not supported");
1043                 } else if (ret != MM_ERROR_NONE) {
1044                         MMRADIO_LOG_ERROR("radio_hal_set_frequency error");
1045                         goto FINISHED_ERR;
1046                 }
1047         }
1048
1049 FINISHED_ERR:
1050
1051         if (radio->old_state == MM_RADIO_STATE_PLAYING) {
1052                 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_PLAYING);
1053         } else {
1054                 /* close radio device here !!!! */
1055                 ret = radio_hal_close(radio->hal_inf);
1056                 if (ret == MM_ERROR_NOT_SUPPORT_API)
1057                         MMRADIO_LOG_WARNING("radio_hal_close is not supported");
1058                 else if (ret != MM_ERROR_NONE)
1059                         MMRADIO_LOG_ERROR("radio_hal_close_device error");
1060
1061                 ret = radio_hal_unprepare(radio->hal_inf);
1062                 if (ret == MM_ERROR_NOT_SUPPORT_API)
1063                         MMRADIO_LOG_WARNING("radio_hal_unprepare is not supported");
1064                 else if (ret != MM_ERROR_NONE)
1065                         MMRADIO_LOG_ERROR("radio_hal_close_device error");
1066
1067                 radio->is_ready = FALSE;
1068
1069                 if (!radio->resource_manager.by_rm_cb && /* is being released */
1070                         mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
1071                         if (resource_state == MM_RADIO_RESOURCE_STATE_ACQUIRED) {
1072                                 ret = mmradio_resource_manager_release(&radio->resource_manager);
1073                                 if (ret != MM_ERROR_NONE)
1074                                         MMRADIO_LOG_ERROR("failed to release resource, ret(0x%x)", ret);
1075                         }
1076                 }
1077
1078                 if (mmradio_resource_manager_get_state(&radio->resource_manager, &resource_state) == MM_ERROR_NONE) {
1079                         if (resource_state == MM_RADIO_RESOURCE_STATE_PREPARED) {
1080                                 ret = mmradio_resource_manager_unprepare(&radio->resource_manager);
1081                                 if (ret != MM_ERROR_NONE)
1082                                         MMRADIO_LOG_ERROR("resource manager unprepare fail");
1083                         }
1084                 }
1085
1086                 MMRADIO_SET_STATE(radio, MM_RADIO_STATE_READY);
1087         }
1088
1089         if (!radio->stop_scan)
1090                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_FINISH, NULL);
1091         else
1092                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SCAN_STOP, NULL);
1093
1094         MMRADIO_LOG_FLEAVE();
1095
1096         radio->scan_thread = 0;
1097         pthread_exit(NULL);
1098 }
1099
1100 bool __is_tunable_frequency(mm_radio_t *radio, int freq)
1101 {
1102         MMRADIO_LOG_FENTER();
1103
1104         MMRADIO_CHECK_INSTANCE(radio);
1105
1106         if (freq >= radio->region_setting.band_max
1107                 || freq <= radio->region_setting.band_min)
1108                 return false;
1109
1110         MMRADIO_LOG_FLEAVE();
1111
1112         return true;
1113 }
1114
1115 void __mmradio_seek_thread(mm_radio_t *radio)
1116 {
1117         int ret = MM_ERROR_NONE;
1118         uint32_t freq = 0;
1119         MMMessageParamType param = {0, };
1120
1121         MMRADIO_LOG_FENTER();
1122         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1123
1124         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_START, NULL);
1125
1126         MMRADIO_LOG_DEBUG("seeking....");
1127
1128         if (!radio->seek_cancel) {
1129
1130                 MMRADIO_LOG_DEBUG("try to seek ");
1131                 pthread_mutex_lock(&radio->seek_cancel_mutex);
1132                 MMRADIO_LOG_DEBUG("seek start");
1133
1134                 if (radio->seek_cancel) {
1135                         MMRADIO_LOG_INFO("seek was canceled so we return failure to application");
1136                         pthread_mutex_unlock(&radio->seek_cancel_mutex);
1137                         goto SEEK_FAILED;
1138                 }
1139
1140                 ret = radio_hal_seek(radio->hal_inf, radio->seek_direction);
1141                 pthread_mutex_unlock(&radio->seek_cancel_mutex);
1142                 if (ret) {
1143                         MMRADIO_LOG_ERROR("radio_hal_seek failed");
1144                         goto SEEK_FAILED;
1145                 }
1146
1147                 /* now we can get new frequency from radio device */
1148                 ret = radio_hal_get_frequency(radio->hal_inf, &freq);
1149                 if (ret) {
1150                         MMRADIO_LOG_ERROR("failed to get current frequency");
1151                         goto SEEK_FAILED;
1152                 }
1153
1154                 MMRADIO_LOG_DEBUG("found frequency");
1155
1156                 /* if same freq is found, ignore it and search next one. */
1157                 if (freq == radio->prev_seek_freq) {
1158                         MMRADIO_LOG_WARNING("It's same with previous found one. So, trying next one.");
1159                         goto SEEK_FAILED;
1160                 }
1161
1162                 /* check if it's limit freq or not */
1163                 if (__is_tunable_frequency(radio, freq)) {
1164                         /* now tune to new frequency */
1165                         ret = radio_hal_set_frequency(radio->hal_inf, freq);
1166                         if (ret) {
1167                                 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1168                                 goto SEEK_FAILED;
1169                         }
1170                         radio->freq = (int)freq;
1171                         MMRADIO_LOG_WARNING("setting frequency : [%d]", radio->freq);
1172                 }
1173
1174                 if (radio->seek_unmute) {
1175                         /* now turn on radio
1176                          * In the case of limit freq, tuner should be unmuted.
1177                          * Otherwise, sound can't output even though application set new frequency.
1178                          */
1179                         ret = radio_hal_unmute(radio->hal_inf);
1180                         if (ret) {
1181                                 MMRADIO_LOG_ERROR("failed to tune to new frequency");
1182                                 goto SEEK_FAILED;
1183                         }
1184                         radio->seek_unmute = FALSE;
1185                 }
1186
1187                 param.radio_scan.frequency = radio->prev_seek_freq = (int)freq;
1188                 MMRADIO_LOG_INFO("seeking : new frequency : [%d]", param.radio_scan.frequency);
1189                 MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
1190         }
1191
1192         radio->seek_thread = 0;
1193         radio->is_seeking = FALSE;
1194
1195         MMRADIO_LOG_FLEAVE();
1196
1197         pthread_exit(NULL);
1198
1199 SEEK_FAILED:
1200         if (radio->seek_unmute) {
1201                 /* now turn on radio
1202                 * In the case of limit freq, tuner should be unmuted.
1203                 * Otherwise, sound can't output even though application set new frequency.
1204                 */
1205                 ret = radio_hal_unmute(radio->hal_inf);
1206                 if (ret)
1207                         MMRADIO_LOG_ERROR("failed to tune to new frequency");
1208                 radio->seek_unmute = FALSE;
1209         }
1210         /* freq -1 means it's failed to seek */
1211         param.radio_scan.frequency = -1;
1212         MMRADIO_POST_MSG(radio, MM_MESSAGE_RADIO_SEEK_FINISH, &param);
1213         radio->is_seeking = FALSE;
1214         radio->seek_thread = 0;
1215         pthread_exit(NULL);
1216 }
1217
1218 static bool __mmradio_post_message(mm_radio_t *radio, enum MMMessageType msgtype, MMMessageParamType *param)
1219 {
1220         MMRADIO_CHECK_INSTANCE(radio);
1221
1222         MMRADIO_LOG_FENTER();
1223
1224         if (!radio->msg_cb) {
1225                 MMRADIO_LOG_WARNING("failed to post a message");
1226                 return false;
1227         }
1228
1229         MMRADIO_LOG_DEBUG("address of msg_cb : %p", radio->msg_cb);
1230
1231         radio->msg_cb(msgtype, param, radio->msg_cb_param);
1232
1233         MMRADIO_LOG_FLEAVE();
1234
1235         return true;
1236 }
1237
1238 static int __mmradio_check_state(mm_radio_t *radio, MMRadioCommand command)
1239 {
1240         MMRadioStateType radio_state = MM_RADIO_STATE_NUM;
1241
1242         MMRADIO_LOG_FENTER();
1243
1244         MMRADIO_CHECK_INSTANCE(radio);
1245
1246         radio_state = __mmradio_get_state(radio);
1247
1248         MMRADIO_LOG_INFO("incomming command : %d  current state : %d", command, radio_state);
1249
1250         switch (command) {
1251         case MMRADIO_COMMAND_CREATE:
1252                 {
1253                         if (radio_state != 0)
1254                                 goto NO_OP;
1255                 }
1256                 break;
1257
1258         case MMRADIO_COMMAND_REALIZE:
1259                 {
1260                         if (radio_state == MM_RADIO_STATE_READY ||
1261                                 radio_state == MM_RADIO_STATE_PLAYING ||
1262                                 radio_state == MM_RADIO_STATE_SCANNING)
1263                                 goto NO_OP;
1264
1265                         if (radio_state == 0)
1266                                 goto INVALID_STATE;
1267                 }
1268                 break;
1269
1270         case MMRADIO_COMMAND_UNREALIZE:
1271                 {
1272                         if (radio_state == MM_RADIO_STATE_NULL)
1273                                 goto NO_OP;
1274
1275                         /* we can call unrealize at any higher state */
1276                 }
1277                 break;
1278
1279         case MMRADIO_COMMAND_START:
1280                 {
1281                         if (radio_state == MM_RADIO_STATE_PLAYING)
1282                                 goto NO_OP;
1283
1284                         if (radio_state != MM_RADIO_STATE_READY)
1285                                 goto INVALID_STATE;
1286                 }
1287                 break;
1288
1289         case MMRADIO_COMMAND_STOP:
1290                 {
1291                         if (radio_state == MM_RADIO_STATE_READY)
1292                                 goto NO_OP;
1293
1294                         if (radio_state != MM_RADIO_STATE_PLAYING)
1295                                 goto INVALID_STATE;
1296                 }
1297                 break;
1298
1299         case MMRADIO_COMMAND_START_SCAN:
1300                 {
1301                         if (radio_state == MM_RADIO_STATE_SCANNING)
1302                                 goto NO_OP;
1303
1304                         if (radio_state == MM_RADIO_STATE_NULL)
1305                                 goto INVALID_STATE;
1306                 }
1307                 break;
1308
1309         case MMRADIO_COMMAND_STOP_SCAN:
1310                 {
1311                         if (radio_state == MM_RADIO_STATE_READY)
1312                                 goto NO_OP;
1313
1314                         if (radio_state != MM_RADIO_STATE_SCANNING)
1315                                 goto INVALID_STATE;
1316                 }
1317                 break;
1318
1319         case MMRADIO_COMMAND_DESTROY:
1320         case MMRADIO_COMMAND_MUTE:
1321         case MMRADIO_COMMAND_UNMUTE:
1322         case MMRADIO_COMMAND_SET_FREQ:
1323         case MMRADIO_COMMAND_GET_FREQ:
1324         case MMRADIO_COMMAND_SET_REGION:
1325         case MMRADIO_COMMAND_SET_VOLUME:
1326         case MMRADIO_COMMAND_GET_VOLUME:
1327                 {
1328                         /* we can do it at any state */
1329                 }
1330                 break;
1331
1332         case MMRADIO_COMMAND_SEEK:
1333                 {
1334                         if (radio_state != MM_RADIO_STATE_PLAYING)
1335                                 goto INVALID_STATE;
1336                 }
1337                 break;
1338
1339         case MMRADIO_COMMAND_GET_REGION:
1340                 {
1341                         if (radio_state == MM_RADIO_STATE_NULL)
1342                                 goto INVALID_STATE;
1343                 }
1344                 break;
1345
1346         default:
1347                 MMRADIO_LOG_DEBUG("not handled in FSM. don't care it");
1348                 break;
1349         }
1350
1351         MMRADIO_LOG_DEBUG("status OK");
1352
1353         radio->cmd = command;
1354
1355         MMRADIO_LOG_FLEAVE();
1356
1357         return MM_ERROR_NONE;
1358
1359 INVALID_STATE:
1360         MMRADIO_LOG_WARNING("invalid state. current : %d  command : %d", radio_state, command);
1361         MMRADIO_LOG_FLEAVE();
1362         return MM_ERROR_RADIO_INVALID_STATE;
1363
1364 NO_OP:
1365         MMRADIO_LOG_WARNING("mm-radio is in the desired state(%d). doing noting", radio_state);
1366         MMRADIO_LOG_FLEAVE();
1367         return MM_ERROR_RADIO_NO_OP;
1368
1369 }
1370
1371 static bool __mmradio_set_state(mm_radio_t *radio, int new_state)
1372 {
1373         MMMessageParamType msg = { 0, };
1374         int msg_type = MM_MESSAGE_UNKNOWN;
1375
1376         MMRADIO_LOG_FENTER();
1377
1378         if (!radio) {
1379                 MMRADIO_LOG_WARNING("calling set_state with invalid radio handle");
1380                 return false;
1381         }
1382
1383         if (radio->current_state == new_state && radio->pending_state == 0) {
1384                 MMRADIO_LOG_WARNING("we are in same state");
1385                 return true;
1386         }
1387
1388         /* set state */
1389         radio->old_state = radio->current_state;
1390         radio->current_state = new_state;
1391
1392         /* fill message param */
1393         msg.union_type = MM_MSG_UNION_STATE;
1394         msg.state.previous = radio->old_state;
1395         msg.state.current = radio->current_state;
1396
1397 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1398         /* post message to application */
1399         if (radio->sound_focus.by_focus_cb) {
1400                 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1401                 msg.state.code = radio->sound_focus.event_src;
1402                 MMRADIO_POST_MSG(radio, msg_type, &msg);
1403         } else if (radio->resource_manager.by_rm_cb) {
1404                 msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1405                 msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1406                 MMRADIO_POST_MSG(radio, msg_type, &msg);
1407         } else {
1408                 msg_type = MM_MESSAGE_STATE_CHANGED;
1409                 MMRADIO_POST_MSG(radio, msg_type, &msg);
1410         }
1411 #else
1412         if (radio->resource_manager.by_rm_cb) {
1413                  msg_type = MM_MESSAGE_STATE_INTERRUPTED;
1414                  msg.state.code = MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT;
1415                  MMRADIO_POST_MSG(radio, msg_type, &msg);
1416          } else {
1417                  msg_type = MM_MESSAGE_STATE_CHANGED;
1418                  MMRADIO_POST_MSG(radio, msg_type, &msg);
1419          }
1420
1421 #endif
1422
1423         MMRADIO_LOG_FLEAVE();
1424
1425         return true;
1426 }
1427
1428 static int __mmradio_get_state(mm_radio_t *radio)
1429 {
1430         MMRADIO_CHECK_INSTANCE(radio);
1431
1432         MMRADIO_LOG_INFO("radio state : current : [%d]   old : [%d]   pending : [%d]",
1433                 radio->current_state, radio->old_state, radio->pending_state);
1434
1435         return radio->current_state;
1436 }
1437
1438 #ifdef TIZEN_FEATURE_SOUND_FOCUS
1439 static void __mmradio_sound_focus_cb(int id, mm_sound_focus_type_e focus_type,
1440         mm_sound_focus_state_e focus_state, const char *reason_for_change, int option,
1441         const char *additional_info, void *user_data)
1442 {
1443         mm_radio_t *radio = (mm_radio_t *)user_data;
1444         enum MMMessageInterruptedCode event_source;
1445         int result = MM_ERROR_NONE;
1446         int postMsg = false;
1447
1448         MMRADIO_LOG_FENTER();
1449         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1450         MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1451
1452         mmradio_get_sound_focus_reason(focus_state, reason_for_change, FALSE, &event_source, &postMsg);
1453         radio->sound_focus.event_src = event_source;
1454
1455         switch (focus_state) {
1456         case FOCUS_IS_RELEASED:{
1457                         radio->sound_focus.cur_focus_type &= ~focus_type;
1458                         radio->sound_focus.by_focus_cb = true;
1459
1460                         MMRADIO_CMD_LOCK(radio);
1461                         result = _mmradio_stop(radio);
1462                         if (result)
1463                                 MMRADIO_LOG_ERROR("failed to stop radio");
1464                         MMRADIO_CMD_UNLOCK(radio);
1465
1466                         radio->sound_focus.by_focus_cb = false;
1467
1468                         MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1469                 }
1470                 break;
1471
1472         case FOCUS_IS_ACQUIRED:{
1473                         MMMessageParamType msg = { 0, };
1474                         msg.union_type = MM_MSG_UNION_CODE;
1475                         msg.code = event_source;
1476
1477                         radio->sound_focus.cur_focus_type |= focus_type;
1478
1479                         if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1480                                 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1481
1482                         MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1483                 }
1484                 break;
1485
1486         default:
1487                 MMRADIO_LOG_DEBUG("Unknown focus_state");
1488                 break;
1489         }
1490
1491         MMRADIO_LOG_FLEAVE();
1492 }
1493
1494 static void __mmradio_sound_focus_watch_cb(int id, mm_sound_focus_type_e focus_type,
1495         mm_sound_focus_state_e focus_state, const char *reason_for_change,
1496         const char *additional_info, void *user_data)
1497 {
1498         mm_radio_t *radio = (mm_radio_t *)user_data;
1499         enum MMMessageInterruptedCode event_source;
1500         int result = MM_ERROR_NONE;
1501         int postMsg = false;
1502
1503         MMRADIO_LOG_FENTER();
1504         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1505         MMRADIO_LOG_INFO("focus_state [%d]", focus_state);
1506
1507         mmradio_get_sound_focus_reason(focus_state, reason_for_change, TRUE, &event_source, &postMsg);
1508         radio->sound_focus.event_src = event_source;
1509
1510         switch (focus_state) {
1511         case FOCUS_IS_ACQUIRED: {
1512                         radio->sound_focus.cur_focus_type &= ~focus_type;
1513                         radio->sound_focus.by_focus_cb = true;
1514
1515                         MMRADIO_CMD_LOCK(radio);
1516                         result = _mmradio_stop(radio);
1517                         if (result)
1518                                 MMRADIO_LOG_ERROR("failed to stop radio");
1519                         MMRADIO_CMD_UNLOCK(radio);
1520
1521                         radio->sound_focus.by_focus_cb = false;
1522
1523                         MMRADIO_LOG_DEBUG("FOCUS_IS_RELEASED cur_focus_type : %d\n", radio->sound_focus.cur_focus_type);
1524                 }
1525                 break;
1526
1527         case FOCUS_IS_RELEASED: {
1528                         MMMessageParamType msg = { 0, };
1529                         msg.union_type = MM_MSG_UNION_CODE;
1530                         msg.code = event_source;
1531
1532                         radio->sound_focus.cur_focus_type |= focus_type;
1533
1534                         if ((postMsg) && (FOCUS_FOR_BOTH == radio->sound_focus.cur_focus_type))
1535                                 MMRADIO_POST_MSG(radio, MM_MESSAGE_READY_TO_RESUME, &msg);
1536
1537                         MMRADIO_LOG_DEBUG("FOCUS_IS_ACQUIRED cur_focus_type : %d", radio->sound_focus.cur_focus_type);
1538                 }
1539                 break;
1540
1541         default:
1542                 MMRADIO_LOG_DEBUG("Unknown focus_state");
1543                 break;
1544         }
1545
1546         MMRADIO_LOG_FLEAVE();
1547 }
1548 #endif
1549
1550 static void __mmradio_volume_changed_cb(volume_type_t type, unsigned int volume, void *user_data)
1551 {
1552         mm_radio_t *radio = (mm_radio_t *)user_data;
1553         int ret = MM_ERROR_NONE;
1554         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
1555         if (type == VOLUME_TYPE_MEDIA) {
1556                 MMRADIO_LOG_INFO("Change FM Radio volume to %d", volume);
1557                 ret = __mmradio_set_media_volume(radio, volume);
1558                 if (ret != MM_ERROR_NONE)
1559                         MMRADIO_LOG_ERROR("__mmradio_set_media_volume error");
1560                 return;
1561         }
1562 }
1563
1564 int _mmradio_get_region_type(mm_radio_t *radio, MMRadioRegionType *type)
1565 {
1566         MMRADIO_LOG_FENTER();
1567         MMRADIO_CHECK_INSTANCE(radio);
1568         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1569
1570         MMRADIO_RETURN_VAL_IF_FAIL(type, MM_ERROR_INVALID_ARGUMENT);
1571
1572         *type = radio->region_setting.country;
1573
1574         MMRADIO_LOG_FLEAVE();
1575         return MM_ERROR_NONE;
1576 }
1577
1578 int _mmradio_get_region_frequency_range(mm_radio_t *radio, unsigned int *min_freq, unsigned int *max_freq)
1579 {
1580         MMRADIO_LOG_FENTER();
1581         MMRADIO_CHECK_INSTANCE(radio);
1582         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1583
1584         MMRADIO_RETURN_VAL_IF_FAIL(min_freq && max_freq, MM_ERROR_INVALID_ARGUMENT);
1585
1586         *min_freq = radio->region_setting.band_min;
1587         *max_freq = radio->region_setting.band_max;
1588
1589         MMRADIO_LOG_FLEAVE();
1590         return MM_ERROR_NONE;
1591 }
1592
1593 int _mmradio_get_channel_spacing(mm_radio_t *radio, unsigned int *ch_spacing)
1594 {
1595         MMRADIO_LOG_FENTER();
1596         MMRADIO_CHECK_INSTANCE(radio);
1597         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_REGION);
1598
1599         MMRADIO_RETURN_VAL_IF_FAIL(ch_spacing, MM_ERROR_INVALID_ARGUMENT);
1600
1601         *ch_spacing = radio->region_setting.channel_spacing;
1602
1603         MMRADIO_LOG_FLEAVE();
1604         return MM_ERROR_NONE;
1605 }
1606
1607 int _mmradio_set_volume(mm_radio_t *radio, float volume)
1608 {
1609         int ret = MM_ERROR_NONE;
1610
1611         MMRADIO_LOG_FENTER();
1612
1613         MMRADIO_CHECK_INSTANCE(radio);
1614         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1615
1616         MMRADIO_LOG_INFO("Setting %f volume", volume);
1617
1618         MMRADIO_VOLUME_LOCK(radio);
1619         radio->local_volume = volume;
1620         MMRADIO_VOLUME_UNLOCK(radio);
1621
1622         ret = radio_hal_set_volume(radio->hal_inf, volume);
1623         if (ret != MM_ERROR_NONE)
1624                 MMRADIO_LOG_ERROR("radio_hal_set_volume error");
1625
1626         MMRADIO_LOG_FLEAVE();
1627
1628         return ret;
1629 }
1630
1631 int _mmradio_get_volume(mm_radio_t *radio, float *pVolume)
1632 {
1633         int ret = MM_ERROR_NONE;
1634         float volume = 0.0;
1635         MMRADIO_LOG_FENTER();
1636
1637         MMRADIO_CHECK_INSTANCE(radio);
1638         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_GET_VOLUME);
1639
1640         MMRADIO_RETURN_VAL_IF_FAIL(pVolume, MM_ERROR_INVALID_ARGUMENT);
1641
1642         ret = radio_hal_get_volume(radio->hal_inf, &volume);
1643         if (ret != MM_ERROR_NONE) {
1644                 MMRADIO_LOG_ERROR("radio_hal_get_volume error");
1645                 *pVolume = 0;
1646                 return ret;
1647         }
1648
1649         MMRADIO_VOLUME_LOCK(radio);
1650         radio->local_volume = volume;
1651         *pVolume = (float)radio->local_volume;
1652         MMRADIO_VOLUME_UNLOCK(radio);
1653
1654         MMRADIO_LOG_FLEAVE();
1655
1656         return ret;
1657 }
1658
1659 static int __mmradio_set_media_volume(mm_radio_t *radio, unsigned int level)
1660 {
1661         int ret = MM_ERROR_NONE;
1662
1663         MMRADIO_LOG_FENTER();
1664
1665         MMRADIO_CHECK_INSTANCE(radio);
1666         MMRADIO_CHECK_STATE_RETURN_IF_FAIL(radio, MMRADIO_COMMAND_SET_VOLUME);
1667
1668         MMRADIO_LOG_INFO("Setting %d volume", level);
1669
1670         MMRADIO_VOLUME_LOCK(radio);
1671         radio->media_volume = level;
1672         MMRADIO_VOLUME_UNLOCK(radio);
1673
1674         ret = radio_hal_set_media_volume(radio->hal_inf, level);
1675         if (ret != MM_ERROR_NONE)
1676                 MMRADIO_LOG_ERROR("radio_hal_set_media_volume error");
1677
1678         MMRADIO_LOG_FLEAVE();
1679
1680         return ret;
1681 }
1682