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