9e4fe0202e2a60205033b81fd3c9e2f53add38ba
[framework/api/radio.git] / src / radio.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. 
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <mm_types.h>
21 #include <radio_private.h>
22 #include <dlog.h>
23 #include <glib.h>
24
25
26 #ifdef LOG_TAG
27 #undef LOG_TAG
28 #endif
29 #define LOG_TAG "TIZEN_N_RADIO"
30
31 /*
32 * Internal Macros
33 */
34 #define RADIO_CHECK_CONDITION(condition,error,msg)      \
35                 if(condition) {} else \
36                 { LOGE("[%s] %s(0x%08x)",(char*)__FUNCTION__, msg,error); return error;}; \
37
38 #define RADIO_INSTANCE_CHECK(radio)     \
39         RADIO_CHECK_CONDITION(radio != NULL, RADIO_ERROR_INVALID_PARAMETER,"RADIO_ERROR_INVALID_PARAMETER")
40         
41 #define RADIO_STATE_CHECK(radio,expected_state) \
42         RADIO_CHECK_CONDITION(radio->state == expected_state,RADIO_ERROR_INVALID_STATE,"RADIO_ERROR_INVALID_STATE")
43
44 #define RADIO_NULL_ARG_CHECK(arg)       \
45         RADIO_CHECK_CONDITION(arg != NULL,RADIO_ERROR_INVALID_PARAMETER,"RADIO_ERROR_INVALID_PARAMETER")
46
47 /*
48 * Internal Implementation
49 */
50 static int __convert_error_code(int code, char *func_name)
51 {
52         int ret = RADIO_ERROR_NONE;
53         char* msg="RADIO_ERROR_NONE";
54         switch(code)
55         {
56                 case MM_ERROR_NONE:
57                         ret = RADIO_ERROR_NONE;
58                         msg = "RADIO_ERROR_NONE";
59                         break;
60
61                 case  MM_ERROR_RADIO_NO_FREE_SPACE:
62                         ret = RADIO_ERROR_OUT_OF_MEMORY;
63                         msg = "RADIO_ERROR_OUT_OF_MEMORY";
64                         break;
65                 case MM_ERROR_RADIO_NOT_INITIALIZED:
66                 case MM_ERROR_RADIO_NO_OP:
67                         ret = RADIO_ERROR_INVALID_STATE;
68                         msg = "RADIO_ERROR_INVALID_STATE";
69                         break;
70                 case MM_ERROR_COMMON_INVALID_ARGUMENT:
71                         ret = RADIO_ERROR_INVALID_PARAMETER;
72                         msg = "RADIO_ERROR_INVALID_PARAMETER";
73                         break;
74                 case MM_ERROR_POLICY_BLOCKED:
75                 case MM_ERROR_POLICY_INTERRUPTED:
76                 case MM_ERROR_POLICY_INTERNAL:
77                 case MM_ERROR_POLICY_DUPLICATED:
78                         ret = RADIO_ERROR_SOUND_POLICY;
79                         msg = "RADIO_ERROR_SOUND_POLICY";
80                         break;
81                 case  MM_ERROR_RADIO_INTERNAL:
82                 case  MM_ERROR_RADIO_RESPONSE_TIMEOUT:
83                 case  MM_ERROR_RADIO_DEVICE_NOT_OPENED:
84                 case  MM_ERROR_RADIO_DEVICE_NOT_FOUND:
85                 default :
86                         ret= RADIO_ERROR_INVALID_OPERATION;
87                         msg = "RADIO_ERROR_INVALID_OPERATION";
88         } 
89         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
90         return ret;     
91 }
92
93 static radio_state_e __convert_radio_state(MMRadioStateType state)
94 {
95         int converted_state = RADIO_STATE_READY;
96         switch(state)
97         {
98                 
99                 case MM_RADIO_STATE_PLAYING:
100                         converted_state = RADIO_STATE_PLAYING;
101                         break;
102                 case MM_RADIO_STATE_SCANNING:
103                         converted_state = RADIO_STATE_SCANNING;
104                         break;
105                 case MM_RADIO_STATE_NULL:
106                 case MM_RADIO_STATE_READY:
107                 default:
108                          converted_state = RADIO_STATE_READY;
109                          break;
110         }
111         return converted_state;
112 }
113
114 static int __set_callback(_radio_event_e type, radio_h radio, void* callback, void *user_data)
115 {
116         RADIO_INSTANCE_CHECK(radio);
117         RADIO_NULL_ARG_CHECK(callback);
118         radio_s * handle = (radio_s *) radio; 
119         handle->user_cb[type] = callback;
120         handle->user_data[type] = user_data;
121         LOGI("[%s] Event type : %d ",__FUNCTION__, type);
122         return RADIO_ERROR_NONE; 
123 }
124
125 static int __unset_callback(_radio_event_e type, radio_h radio)
126 {
127         RADIO_INSTANCE_CHECK(radio);
128         radio_s * handle = (radio_s *) radio; 
129         handle->user_cb[type] = NULL;
130         handle->user_data[type] = NULL;
131         LOGI("[%s] Event type : %d ",__FUNCTION__, type);
132         return RADIO_ERROR_NONE; 
133 }
134
135 static int __msg_callback(int message, void *param, void *user_data)
136 {
137         radio_s * handle = (radio_s*)user_data;
138         MMMessageParamType *msg = (MMMessageParamType*)param;
139         LOGI("[%s] Got message type : 0x%x" ,__FUNCTION__, message);
140         switch(message)
141         {
142                 case MM_MESSAGE_RADIO_SCAN_INFO: 
143                         if( handle->user_cb[_RADIO_EVENT_TYPE_SCAN_INFO] )
144                         {
145                                 ((radio_scan_updated_cb)handle->user_cb[_RADIO_EVENT_TYPE_SCAN_INFO])(msg->radio_scan.frequency,handle->user_data[_RADIO_EVENT_TYPE_SCAN_INFO]);
146                         }       
147                         break;  
148                 case MM_MESSAGE_RADIO_SCAN_STOP: 
149                         if( handle->user_cb[_RADIO_EVENT_TYPE_SCAN_STOP] )
150                         {
151                                 ((radio_scan_stopped_cb)handle->user_cb[_RADIO_EVENT_TYPE_SCAN_STOP])(handle->user_data[_RADIO_EVENT_TYPE_SCAN_STOP]);
152                         }
153                         break;
154                 case MM_MESSAGE_RADIO_SCAN_FINISH:
155                         if( handle->user_cb[_RADIO_EVENT_TYPE_SCAN_FINISH] )
156                         {
157                                 ((radio_scan_completed_cb)handle->user_cb[_RADIO_EVENT_TYPE_SCAN_FINISH])(handle->user_data[_RADIO_EVENT_TYPE_SCAN_FINISH]);
158                         }
159                         break;
160                 case MM_MESSAGE_RADIO_SEEK_FINISH: 
161                         if( handle->user_cb[_RADIO_EVENT_TYPE_SEEK_FINISH] )
162                         {
163                                 ((radio_seek_completed_cb)handle->user_cb[_RADIO_EVENT_TYPE_SEEK_FINISH])(msg->radio_scan.frequency, handle->user_data[_RADIO_EVENT_TYPE_SEEK_FINISH]);
164                         }       
165                         break;
166                 case MM_MESSAGE_STATE_INTERRUPTED: 
167                         if( handle->user_cb[_RADIO_EVENT_TYPE_INTERRUPT] )
168                         {
169                                 ((radio_interrupted_cb)handle->user_cb[_RADIO_EVENT_TYPE_INTERRUPT])(msg->code,handle->user_data[_RADIO_EVENT_TYPE_INTERRUPT]);
170                         }
171                         break;
172                 case  MM_MESSAGE_ERROR: 
173                                 __convert_error_code(msg->code,(char*)__FUNCTION__);
174                         break;
175                 case MM_MESSAGE_RADIO_SCAN_START: 
176                         LOGI("[%s] Scan Started");
177                         break;
178                 case  MM_MESSAGE_STATE_CHANGED: 
179                         handle->state = __convert_radio_state(msg->state.current);
180                         LOGI("[%s] State Changed --- from : %d , to : %d" ,__FUNCTION__,  __convert_radio_state(msg->state.previous), handle->state);
181                         break;
182                 case MM_MESSAGE_RADIO_SEEK_START:
183                         LOGI("[%s] Seek Started", __FUNCTION__);
184                         break;  
185                 default:
186                         break;
187         }
188         return 1;
189 }
190
191
192 /*
193 * Public Implementation
194 */
195 int radio_create(radio_h *radio)
196 {
197         RADIO_INSTANCE_CHECK(radio);
198         radio_s * handle;
199         handle = (radio_s*)malloc( sizeof(radio_s));
200         if (handle != NULL)
201                 memset(handle, 0 , sizeof(radio_s));
202         else
203         {
204                 LOGE("[%s] RADIO_ERROR_OUT_OF_MEMORY(0x%08x)" ,__FUNCTION__,RADIO_ERROR_OUT_OF_MEMORY);
205                 return RADIO_ERROR_OUT_OF_MEMORY;
206         }
207         int ret = mm_radio_create(&handle->mm_handle);
208         if( ret != MM_ERROR_NONE)
209         {
210                 LOGE("[%s] RADIO_ERROR_INVALID_OPERATION(0x%08x)" ,__FUNCTION__,RADIO_ERROR_INVALID_OPERATION);
211                 free(handle);
212                 handle=NULL;
213                 return RADIO_ERROR_INVALID_OPERATION;
214         }
215         else
216         {
217                 *radio = (radio_h)handle;
218                 
219                 ret = mm_radio_set_message_callback(handle->mm_handle, __msg_callback, (void*)handle);
220                 if(ret != MM_ERROR_NONE)
221                 {
222                         LOGW("[%s] Failed to set message callback function (0x%x)" ,__FUNCTION__, ret);
223                 }
224                 ret = mm_radio_realize(handle->mm_handle);
225                 if(ret != MM_ERROR_NONE)
226                 {
227                         return __convert_error_code(ret,(char*)__FUNCTION__);
228                 }
229                 handle->state = RADIO_STATE_READY;
230                 handle->mute = FALSE;
231                 return RADIO_ERROR_NONE;
232         }
233 }
234
235 int radio_destroy(radio_h radio)
236 {
237         RADIO_INSTANCE_CHECK(radio);
238         radio_s * handle = (radio_s *) radio;
239
240         int ret;
241         ret = mm_radio_unrealize(handle->mm_handle);
242         if ( ret!= MM_ERROR_NONE)
243         {
244                 LOGW("[%s] Failed to unrealize (0x%x)" ,__FUNCTION__, ret);
245         }
246         
247         ret = mm_radio_destroy(handle->mm_handle);
248         if (ret!= MM_ERROR_NONE)
249         {
250                 LOGE("[%s] RADIO_ERROR_INVALID_OPERATION (0x%08x)" ,__FUNCTION__,RADIO_ERROR_INVALID_OPERATION);
251                 return RADIO_ERROR_INVALID_OPERATION;
252         }
253         else
254         {
255                 free(handle);
256                 handle= NULL;
257                 return RADIO_ERROR_NONE;
258         }
259 }
260
261 int  radio_get_state(radio_h radio, radio_state_e *state)
262 {
263         RADIO_INSTANCE_CHECK(radio);
264         RADIO_NULL_ARG_CHECK(state);
265         radio_s * handle = (radio_s *) radio;
266         MMRadioStateType currentStat = MM_RADIO_STATE_NULL;
267         int ret = mm_radio_get_state(handle->mm_handle, &currentStat);
268         if(ret != MM_ERROR_NONE)
269         {
270                 *state = handle->state;
271                 return __convert_error_code(ret,(char*)__FUNCTION__);
272         }
273         else
274         {
275                 handle->state  = __convert_radio_state(currentStat);
276                 *state = handle->state;
277                 return RADIO_ERROR_NONE;
278         }
279 }
280
281 int radio_start(radio_h radio)
282 {
283         RADIO_INSTANCE_CHECK(radio);
284         radio_s * handle = (radio_s *) radio;
285         RADIO_STATE_CHECK(handle,RADIO_STATE_READY);  
286
287         int ret = mm_radio_start(handle->mm_handle);
288         if(ret != MM_ERROR_NONE)
289         {
290                 return __convert_error_code(ret,(char*)__FUNCTION__);
291         }
292         else
293         {
294                 handle->state = RADIO_STATE_PLAYING;
295                 return RADIO_ERROR_NONE;
296         }
297 }
298
299 int radio_stop(radio_h radio)
300 {
301         RADIO_INSTANCE_CHECK(radio);
302         radio_s * handle = (radio_s *) radio;
303         RADIO_STATE_CHECK(handle,RADIO_STATE_PLAYING);  
304         
305         int ret = mm_radio_stop(handle->mm_handle);
306         if(ret != MM_ERROR_NONE)
307         {
308                 return __convert_error_code(ret,(char*)__FUNCTION__);
309         }
310         else
311         {
312                 handle->state = RADIO_STATE_READY;
313                 return RADIO_ERROR_NONE;
314         }
315 }
316
317 int radio_seek_up(radio_h radio,radio_seek_completed_cb callback, void *user_data )
318 {
319         RADIO_INSTANCE_CHECK(radio);
320         radio_s * handle = (radio_s *) radio;
321         RADIO_STATE_CHECK(handle,RADIO_STATE_PLAYING);
322         
323         if(callback!=NULL)
324         {
325                 __set_callback(_RADIO_EVENT_TYPE_SEEK_FINISH,radio,callback,user_data);
326         }
327         else
328         {
329                 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH,radio);
330         }
331         
332         int ret = mm_radio_seek(handle->mm_handle, MM_RADIO_SEEK_UP);
333         if(ret != MM_ERROR_NONE)
334         {
335                 return __convert_error_code(ret,(char*)__FUNCTION__);
336         }
337         else
338         {
339                 return RADIO_ERROR_NONE;
340         }
341 }
342
343 int radio_seek_down(radio_h radio,radio_seek_completed_cb callback, void *user_data )
344 {
345         RADIO_INSTANCE_CHECK(radio);
346         radio_s * handle = (radio_s *) radio;
347         RADIO_STATE_CHECK(handle,RADIO_STATE_PLAYING);
348         
349         if(callback!=NULL)
350         {
351                 __set_callback(_RADIO_EVENT_TYPE_SEEK_FINISH,radio,callback,user_data);
352         }
353         else
354         {
355                 __unset_callback(_RADIO_EVENT_TYPE_SEEK_FINISH,radio);
356         }
357         
358         int ret = mm_radio_seek(handle->mm_handle, MM_RADIO_SEEK_DOWN);
359         if(ret != MM_ERROR_NONE)
360         {
361                 return __convert_error_code(ret,(char*)__FUNCTION__);
362         }
363         else
364         {
365                 return RADIO_ERROR_NONE;
366         }
367 }
368
369 int radio_set_frequency(radio_h radio, int frequency)
370 {
371         RADIO_INSTANCE_CHECK(radio);
372         if(frequency < 87500 || frequency > 108000)
373         {
374                 LOGE("[%s] RADIO_ERROR_INVALID_PARAMETER(0x%08x) : Out of range (87500 ~ 108000)" ,__FUNCTION__,RADIO_ERROR_INVALID_PARAMETER);
375                 return RADIO_ERROR_INVALID_PARAMETER;
376         }
377         int freq= frequency;
378         radio_s * handle = (radio_s *) radio;
379         int ret = mm_radio_set_frequency(handle->mm_handle, freq);
380         if(ret != MM_ERROR_NONE)
381         {
382                 return __convert_error_code(ret,(char*)__FUNCTION__);
383         }
384         else
385         {
386                 return RADIO_ERROR_NONE;
387         }
388 }
389
390 int radio_get_frequency(radio_h radio, int *frequency)
391 {
392         RADIO_INSTANCE_CHECK(radio);
393         radio_s * handle = (radio_s *) radio;
394
395         int freq;
396         int ret = mm_radio_get_frequency(handle->mm_handle, &freq);
397         if(ret != MM_ERROR_NONE)
398         {
399                 return __convert_error_code(ret,(char*)__FUNCTION__);
400         }
401         else
402         {
403                 *frequency = freq; 
404                 return RADIO_ERROR_NONE;
405         }
406 }       
407
408 int radio_scan_start(radio_h radio, radio_scan_updated_cb callback, void *user_data)
409 {
410         RADIO_INSTANCE_CHECK(radio);
411         radio_s * handle = (radio_s *) radio;
412         RADIO_STATE_CHECK(handle,RADIO_STATE_READY);  
413
414         if(callback!=NULL)
415         {
416                 __set_callback(_RADIO_EVENT_TYPE_SCAN_INFO,radio,callback,user_data);
417         }
418         else
419         {
420                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_INFO,radio);
421         }
422         
423         int ret = mm_radio_scan_start(handle->mm_handle);
424         if(ret != MM_ERROR_NONE)
425         {
426                 return __convert_error_code(ret,(char*)__FUNCTION__);
427         }
428         else
429         {
430                 handle->state = RADIO_STATE_SCANNING;
431                 return RADIO_ERROR_NONE;
432         }
433 }
434
435 int radio_scan_stop(radio_h radio, radio_scan_stopped_cb callback, void *user_data)
436 {
437         RADIO_INSTANCE_CHECK(radio);
438         radio_s * handle = (radio_s *) radio;
439         RADIO_STATE_CHECK(handle,RADIO_STATE_SCANNING);  
440
441         if(callback!=NULL)
442         {
443                 __set_callback(_RADIO_EVENT_TYPE_SCAN_STOP,radio,callback,user_data);
444         }
445         else
446         {
447                 __unset_callback(_RADIO_EVENT_TYPE_SCAN_STOP,radio);
448         }
449         
450         int ret = mm_radio_scan_stop(handle->mm_handle);
451         if(ret != MM_ERROR_NONE)
452         {
453                 return __convert_error_code(ret,(char*)__FUNCTION__);
454         }
455         else
456         {
457                 handle->state = RADIO_STATE_READY;
458                 return RADIO_ERROR_NONE;
459         }
460 }
461
462
463 int radio_set_mute(radio_h radio, bool muted)
464 {
465         RADIO_INSTANCE_CHECK(radio);
466         radio_s * handle = (radio_s *) radio;
467
468         int ret = mm_radio_set_mute(handle->mm_handle, muted);
469         if(ret != MM_ERROR_NONE)
470         {
471                 return __convert_error_code(ret,(char*)__FUNCTION__);
472         }
473         else
474         {
475                 handle->mute = muted;
476                 return RADIO_ERROR_NONE;
477         }
478 }
479
480 int radio_is_muted(radio_h radio, bool *muted)
481 {
482         RADIO_INSTANCE_CHECK(radio);
483         RADIO_NULL_ARG_CHECK(muted);
484         radio_s * handle = (radio_s *) radio;
485         *muted = handle->mute;
486         return RADIO_ERROR_NONE;
487 }
488
489 int radio_set_scan_completed_cb(radio_h radio, radio_scan_completed_cb callback, void *user_data)
490 {
491         return __set_callback(_RADIO_EVENT_TYPE_SCAN_FINISH,radio,callback,user_data);
492 }
493
494 int radio_unset_scan_completed_cb(radio_h radio)
495 {
496         return __unset_callback(_RADIO_EVENT_TYPE_SCAN_FINISH,radio);
497 }
498
499 int radio_set_interrupted_cb(radio_h radio, radio_interrupted_cb callback, void *user_data)
500 {
501         return __set_callback(_RADIO_EVENT_TYPE_INTERRUPT,radio,callback,user_data);
502 }
503
504 int radio_unset_interrupted_cb(radio_h radio)
505 {
506         return __unset_callback(_RADIO_EVENT_TYPE_INTERRUPT,radio);
507 }