Fix the coding style errors (bt-service)
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-avrcp-controller.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
18 #include "bt-internal-types.h"
19 #include "bt-service-common.h"
20 #include "bt-service-avrcp-controller.h"
21 #include "bt-service-audio.h"
22 #include "bt-service-event.h"
23
24 static bt_player_settinngs_t repeat_status[] = {
25         { REPEAT_INVALID, "" },
26         { REPEAT_MODE_OFF, "off" },
27         { REPEAT_SINGLE_TRACK, "singletrack" },
28         { REPEAT_ALL_TRACK, "alltracks" },
29         { REPEAT_GROUP, "group" },
30         { REPEAT_INVALID, "" }
31 };
32
33 static bt_player_settinngs_t equalizer_status[] = {
34         { EQUALIZER_INVALID, "" },
35         { EQUALIZER_OFF, "off" },
36         { EQUALIZER_ON, "on" },
37         { EQUALIZER_INVALID, "" },
38 };
39
40 static bt_player_settinngs_t scan_status[] = {
41         { SCAN_INVALID, "" },
42         { SCAN_MODE_OFF, "off" },
43         { SCAN_ALL_TRACK, "alltracks" },
44         { SCAN_GROUP, "group" },
45         { SCAN_INVALID, "" },
46 };
47
48 static bt_player_settinngs_t shuffle_settings[] = {
49         { SHUFFLE_INVALID, "" },
50         { SHUFFLE_MODE_OFF, "off" },
51         { SHUFFLE_ALL_TRACK, "alltracks" },
52         { SHUFFLE_GROUP, "group" },
53         { SHUFFLE_INVALID, "" }
54 };
55
56 static char *avrcp_control_path = NULL;
57
58 void _bt_set_control_device_path(const char *path)
59 {
60
61         ret_if(path == NULL);
62
63         g_free(avrcp_control_path);
64         BT_DBG("control_path = %s", path);
65         avrcp_control_path = g_strdup(path);
66 }
67
68 void _bt_remove_control_device_path(const char *path)
69 {
70         ret_if(path == NULL);
71
72         if (avrcp_control_path &&
73                         !g_strcmp0(avrcp_control_path, path)) {
74                 BT_DBG("control_path = %s", path);
75                 g_free(avrcp_control_path);
76                 avrcp_control_path = NULL;
77         }
78 }
79
80 static char *__bt_get_control_device_path(void)
81 {
82         char *adapter_path;
83         char *control_path;
84         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
85
86         BT_DBG("+");
87
88         retv_if(avrcp_control_path != NULL, avrcp_control_path);
89
90         retv_if(!_bt_is_headset_type_connected(BT_AVRCP,
91                         connected_address), NULL);
92
93         BT_DBG("device address = %s", connected_address);
94
95         adapter_path = _bt_get_device_object_path(connected_address);
96         retv_if(adapter_path == NULL, NULL);
97
98         control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path);
99         g_free(adapter_path);
100
101         avrcp_control_path = control_path;
102         BT_DBG("control_path = %s", control_path);
103         return control_path;
104 }
105
106 static int __bt_media_send_control_msg(const char *name)
107 {
108         GVariant *reply = NULL;
109         GError *err = NULL;
110         GDBusConnection *conn = NULL;
111         GDBusProxy *proxy = NULL;
112         char *control_path = NULL;
113
114         retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL);
115
116         conn = _bt_get_system_conn();
117         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
118
119         control_path = __bt_get_control_device_path();
120         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
121         BT_DBG("control_path %s", control_path);
122
123         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
124                         BT_BLUEZ_NAME, control_path,
125                         BT_PLAYER_CONTROL_INTERFACE, NULL, &err);
126         if (proxy == NULL) {
127                 BT_ERR("Unable to allocate new proxy \n");
128                 if (err) {
129                         BT_ERR("%s", err->message);
130                         g_clear_error(&err);
131                 }
132                 return BLUETOOTH_ERROR_INTERNAL;
133         }
134
135         reply = g_dbus_proxy_call_sync(proxy, name, NULL,
136                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
137
138         g_object_unref(proxy);
139
140         if (!reply) {
141                 BT_ERR("Error returned in method call");
142                 if (err) {
143                         BT_ERR("%s", err->message);
144                         g_clear_error(&err);
145                 }
146                 return BLUETOOTH_ERROR_INTERNAL;
147         }
148
149         g_variant_unref(reply);
150
151         BT_DBG("-");
152         return BLUETOOTH_ERROR_NONE;
153 }
154
155 int _bt_avrcp_control_cmd(int type)
156 {
157         int ret = BLUETOOTH_ERROR_INTERNAL;
158         BT_DBG("+");
159
160         switch (type) {
161         case PLAY:
162                 ret = __bt_media_send_control_msg("Play");
163                 break;
164         case PAUSE:
165                 ret = __bt_media_send_control_msg("Pause");
166                 break;
167         case STOP:
168                 ret = __bt_media_send_control_msg("Stop");
169                 break;
170         case NEXT:
171                 ret = __bt_media_send_control_msg("Next");
172                 break;
173         case PREVIOUS:
174                 ret = __bt_media_send_control_msg("Previous");
175                 break;
176         case FAST_FORWARD:
177                 ret = __bt_media_send_control_msg("FastForward");
178                 break;
179         case REWIND:
180                 ret = __bt_media_send_control_msg("Rewind");
181                 break;
182         default:
183                 BT_DBG("Invalid Type\n");
184                 return BLUETOOTH_ERROR_INTERNAL;
185         }
186         BT_DBG("-");
187         return ret;
188 }
189
190 GDBusProxy *__bt_get_control_properties_proxy(void)
191 {
192         GDBusProxy *proxy = NULL;
193         GError *error = NULL;
194         char *control_path = NULL;
195         GDBusConnection *conn = NULL;
196
197         control_path = __bt_get_control_device_path();
198         retv_if(control_path == NULL, NULL);
199         BT_DBG("control_path = %s", control_path);
200
201         conn = _bt_get_system_conn();
202         retv_if(conn == NULL, NULL);
203
204         proxy = g_dbus_proxy_new_sync(conn,
205                         G_DBUS_PROXY_FLAGS_NONE, NULL,
206                         BT_BLUEZ_NAME, control_path,
207                         BT_PROPERTIES_INTERFACE, NULL, &error);
208         if (proxy == NULL) {
209                 BT_ERR("Unable to allocate new proxy");
210                 if (error) {
211                         BT_ERR("%s", error->message);
212                         g_clear_error(&error);
213                 }
214                 return NULL;
215         }
216
217         return proxy;
218 }
219
220 static int __bt_media_attr_to_event(const char *str)
221 {
222         if (!strcasecmp(str, "Equalizer"))
223                 return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS;
224         else if (!strcasecmp(str, "Repeat"))
225                 return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS;
226         else if (!strcasecmp(str, "Shuffle"))
227                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS;
228         else if (!strcasecmp(str, "Scan"))
229                 return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS;
230         else if (!strcasecmp(str, "Position"))
231                 return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS;
232         else if (!strcasecmp(str, "Track"))
233                 return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED;
234         else if (!strcasecmp(str, "Status"))
235                 return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED;
236
237         return 0;
238 }
239
240 static int __bt_media_attr_to_type(const char *str)
241 {
242         if (!strcasecmp(str, "Equalizer"))
243                 return EQUALIZER;
244         else if (!strcasecmp(str, "Repeat"))
245                 return REPEAT;
246         else if (!strcasecmp(str, "Shuffle"))
247                 return SHUFFLE;
248         else if (!strcasecmp(str, "Scan"))
249                 return SCAN;
250         else if (!strcasecmp(str, "Position"))
251                 return POSITION;
252         else if (!strcasecmp(str, "Track"))
253                 return METADATA;
254         else if (!strcasecmp(str, "Status"))
255                 return STATUS;
256
257         return 0;
258 }
259
260 static const char *__bt_media_type_to_str(int type)
261 {
262         switch (type) {
263         case EQUALIZER:
264                 return "Equalizer";
265         case REPEAT:
266                 return "Repeat";
267         case SHUFFLE:
268                 return "Shuffle";
269         case SCAN:
270                 return "Scan";
271         case POSITION:
272                 return "Position";
273         case METADATA:
274                 return "Track";
275         case STATUS:
276                 return "Status";
277         }
278         return NULL;
279 }
280
281 static int __bt_media_attrval_to_val(int type, const char *value)
282 {
283         int ret = 0;
284
285         switch (type) {
286         case EQUALIZER:
287                 if (!strcmp(value, "off"))
288                         ret = EQUALIZER_OFF;
289                 else if (!strcmp(value, "on"))
290                         ret = EQUALIZER_ON;
291                 else
292                         ret = EQUALIZER_INVALID;
293                 break;
294
295         case REPEAT:
296                 if (!strcmp(value, "off"))
297                         ret = REPEAT_MODE_OFF;
298                 else if (!strcmp(value, "singletrack"))
299                         ret = REPEAT_SINGLE_TRACK;
300                 else if (!strcmp(value, "alltracks"))
301                         ret = REPEAT_ALL_TRACK;
302                 else if (!strcmp(value, "group"))
303                         ret = REPEAT_GROUP;
304                 else
305                         ret = REPEAT_INVALID;
306                 break;
307
308         case SHUFFLE:
309                 if (!strcmp(value, "off"))
310                         ret = SHUFFLE_MODE_OFF;
311                 else if (!strcmp(value, "alltracks"))
312                         ret = SHUFFLE_ALL_TRACK;
313                 else if (!strcmp(value, "group"))
314                         ret = SHUFFLE_GROUP;
315                 else
316                         ret = SHUFFLE_INVALID;
317                 break;
318
319         case SCAN:
320                 if (!strcmp(value, "off"))
321                         ret = SCAN_MODE_OFF;
322                 else if (!strcmp(value, "alltracks"))
323                         ret = SCAN_ALL_TRACK;
324                 else if (!strcmp(value, "group"))
325                         ret = SCAN_GROUP;
326                 else
327                         ret = SCAN_INVALID;
328                 break;
329
330         case STATUS:
331                 if (!strcmp(value, "stopped"))
332                         ret = STATUS_STOPPED;
333                 else if (!strcmp(value, "playing"))
334                         ret = STATUS_PLAYING;
335                 else if (!strcmp(value, "paused"))
336                         ret = STATUS_PAUSED;
337                 else if (!strcmp(value, "forward-seek"))
338                         ret = STATUS_FORWARD_SEEK;
339                 else if (!strcmp(value, "reverse-seek"))
340                         ret = STATUS_REVERSE_SEEK;
341                 else if (!strcmp(value, "error"))
342                         ret = STATUS_ERROR;
343                 else
344                         ret = STATUS_INVALID;
345         }
346         return ret;
347 }
348
349 int _bt_avrcp_control_get_property(int type, unsigned int *value)
350 {
351         GDBusProxy *proxy = NULL;
352         char *name = NULL;
353         int ret = BLUETOOTH_ERROR_NONE;
354         GError *err = NULL;
355         GVariant *reply = NULL;
356
357         BT_CHECK_PARAMETER(value, return);
358
359         proxy = __bt_get_control_properties_proxy();
360         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
361
362         reply = g_dbus_proxy_call_sync(proxy,
363                                         "Get", g_variant_new("ss", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type)),
364                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
365
366         g_object_unref(proxy);
367
368         if (!reply) {
369                 BT_ERR("Can't get managed objects");
370                 if (err) {
371                         BT_ERR("%s", err->message);
372                         g_clear_error(&err);
373                 }
374                 return BLUETOOTH_ERROR_INTERNAL;
375         } else {
376                         switch (type) {
377                         case EQUALIZER:
378                         case REPEAT:
379                         case SHUFFLE:
380                         case SCAN:
381                         case STATUS:
382                                 name = (char *)g_variant_get_string(reply, NULL);
383                                 *value = __bt_media_attrval_to_val(type, name);
384                                 BT_DBG("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name);
385                                 break;
386                         case POSITION:
387                                 *value = g_variant_get_uint32(reply);
388                                 break;
389                         default:
390                                 BT_DBG("Invalid Type\n");
391                                 ret =  BLUETOOTH_ERROR_INTERNAL;
392                         }
393                 }
394         g_variant_unref(reply);
395         return ret;
396 }
397
398 int _bt_avrcp_control_set_property(int type, unsigned int value)
399 {
400         GValue *attr_value = NULL;
401         GDBusProxy *proxy = NULL;
402         GError *error = NULL;
403         GVariant *reply, *param;
404
405         g_value_init(attr_value, G_TYPE_STRING);
406
407         switch (type) {
408         case EQUALIZER:
409                 param = g_variant_new("s", equalizer_status[value].property);
410                 BT_DBG("equalizer_status %s", equalizer_status[value].property);
411                 break;
412         case REPEAT:
413                 param = g_variant_new("s", repeat_status[value].property);
414                 BT_DBG("repeat_status %s", repeat_status[value].property);
415                 break;
416         case SHUFFLE:
417                 param = g_variant_new("s", shuffle_settings[value].property);
418                 BT_DBG("shuffle_settings %s", shuffle_settings[value].property);
419                 break;
420         case SCAN:
421                 param = g_variant_new("s", scan_status[value].property);
422                 BT_DBG("scan_status %s", scan_status[value].property);
423                 break;
424         default:
425                 BT_ERR("Invalid property type: %d", type);
426                 g_value_unset(attr_value);
427                 return BLUETOOTH_ERROR_INTERNAL;
428         }
429
430         proxy = __bt_get_control_properties_proxy();
431         retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
432
433         reply = g_dbus_proxy_call_sync(proxy,
434                                         "Set", g_variant_new("ssv", BT_PLAYER_CONTROL_INTERFACE, __bt_media_type_to_str(type), param),
435                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
436
437         g_object_unref(proxy);
438         g_variant_unref(param);
439
440         if (!reply) {
441                 BT_ERR("Can't get managed objects");
442                 if (error) {
443                         BT_ERR("SetProperty Fail: %s", error->message);
444                         g_clear_error(&error);
445                         return BLUETOOTH_ERROR_INTERNAL;
446                 }
447         }
448
449         g_variant_unref(reply);
450         g_value_unset(attr_value);
451
452         return BLUETOOTH_ERROR_NONE;
453 }
454
455 static int __bt_avrcp_control_parse_properties(
456                                 media_metadata_attributes_t *metadata,
457                                 GVariant *item)
458 {
459         GVariant *value = NULL;
460         GVariantIter iter;
461         char *value_string = NULL;
462         unsigned int value_uint;
463         const char *key = NULL;
464
465         g_variant_iter_init(&iter, item);
466         while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
467                 if (strcasecmp(key, "Title") == 0) {
468                         value_string = (char *)g_variant_get_string(value, NULL);
469                         BT_DBG("Value : %s ", value_string);
470                         metadata->title = value_string;
471                 } else if (strcasecmp(key, "Artist") == 0) {
472                         value_string = (char *)g_variant_get_string(value, NULL);
473                         BT_DBG("Value : %s ", value_string);
474                         metadata->artist = value_string;
475                 } else if (strcasecmp(key, "Album") == 0) {
476                         value_string = (char *)g_variant_get_string(value, NULL);
477                         BT_DBG("Value : %s ", value_string);
478                         metadata->album = value_string;
479                 } else if (strcasecmp(key, "Genre") == 0) {
480                         value_string = (char *)g_variant_get_string(value, NULL);
481                         BT_DBG("Value : %s ", value_string);
482                         metadata->genre = value_string;
483                 } else if (strcasecmp(key, "Duration") == 0) {
484                         value_uint = g_variant_get_uint32(value);
485                         metadata->duration = value_uint;
486                 } else if (strcasecmp(key, "NumberOfTracks") == 0) {
487                         value_uint = g_variant_get_uint32(value);
488                         metadata->total_tracks = value_uint;
489                 } else if (strcasecmp(key, "TrackNumber") == 0) {
490                         value_uint = g_variant_get_uint32(value);
491                         metadata->number = value_uint;
492                 } else
493                         BT_DBG("%s not supported, ignoring", key);
494         }
495
496         if (!metadata->title)
497                 metadata->title = g_strdup("");
498         if (!metadata->artist)
499                 metadata->artist = g_strdup("");
500         if (!metadata->album)
501                 metadata->album = g_strdup("");
502         if (!metadata->genre)
503                 metadata->genre = g_strdup("");
504
505         return BLUETOOTH_ERROR_NONE;
506
507 }
508
509 int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata)
510 {
511         GDBusProxy *proxy = NULL;
512         GVariant *reply = NULL;
513         GVariant *item = NULL;
514         GError *err = NULL;
515         GDBusConnection *conn = NULL;
516         char *control_path = NULL;
517         char *interface_name = NULL;
518         char *property_name = NULL;
519         GVariant *parameters = NULL;
520         int ret = BLUETOOTH_ERROR_NONE;
521
522         retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL);
523
524         conn = _bt_get_system_conn();
525         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
526
527         control_path = __bt_get_control_device_path();
528         retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
529         BT_DBG("control_path %s", control_path);
530
531         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
532                         BT_BLUEZ_NAME, control_path,
533                         BT_PROPERTIES_INTERFACE, NULL, &err);
534         if (proxy == NULL) {
535                 BT_ERR("Unable to allocate new proxy \n");
536                 if (err) {
537                         BT_ERR("%s", err->message);
538                         g_clear_error(&err);
539                 }
540                 return BLUETOOTH_ERROR_INTERNAL;
541         }
542
543         interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE);
544         property_name = g_strdup("Track");
545
546         parameters = g_variant_new("(ss)", interface_name, property_name);
547
548         g_free(interface_name);
549         g_free(property_name);
550
551         reply = g_dbus_proxy_call_sync(proxy, "Get", parameters,
552                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
553
554         g_object_unref(proxy);
555
556         if (!reply) {
557                 BT_ERR("Error returned in method call");
558                 if (err) {
559                         BT_ERR("%s", err->message);
560                         g_clear_error(&err);
561                 }
562                 return BLUETOOTH_ERROR_INTERNAL;
563         }
564
565         g_variant_get(reply, "(v)", &item);
566
567         ret = __bt_avrcp_control_parse_properties(metadata, item);
568
569         g_variant_unref(reply);
570         BT_DBG("-");
571         return ret;
572 }
573
574 void _bt_handle_avrcp_control_event(GVariant *reply, const char *path)
575 {
576         GVariant *param = NULL;
577         const char *property = NULL;
578
579         if (!reply) {
580                 BT_ERR("Error returned in method call\n");
581                 return;
582         }
583
584         GVariantIter iter;
585         GVariant *value = NULL;
586         g_variant_iter_init(&iter, reply);
587         while (g_variant_iter_loop(&iter, "{sv}", &property,
588                                 &value)) {
589                 if ((strcasecmp(property, "Equalizer") == 0) ||
590                         (strcasecmp(property, "Repeat") == 0) ||
591                         (strcasecmp(property, "Shuffle") == 0) ||
592                         (strcasecmp(property, "Scan") == 0) ||
593                         (strcasecmp(property, "Status") == 0)) {
594                                 const char *valstr;
595                                 unsigned int type, val;
596
597                                 valstr = g_variant_get_string(value, NULL);
598                                 BT_DBG("Value : %s ", valstr);
599                                 type = __bt_media_attr_to_type(property);
600                                 val = __bt_media_attrval_to_val(type, valstr);
601
602                                 /* Send event to application */
603                                 param = g_variant_new("(u)", val);
604                                 _bt_send_event(BT_AVRCP_CONTROL_EVENT,
605                                         __bt_media_attr_to_event(property), param);
606                 } else if (strcasecmp(property, "Position") == 0) {
607                         unsigned int val;
608
609                         val = g_variant_get_uint32(value);
610                         BT_DBG("Value : %d ", val);
611
612                         /* Send event to application */
613                         param = g_variant_new("(u)", val);
614                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
615                                 __bt_media_attr_to_event(property), param);
616                 } else if (strcasecmp(property, "Track") == 0) {
617                         int ret = BLUETOOTH_ERROR_NONE;
618                         media_metadata_attributes_t metadata;
619
620                         memset(&metadata, 0x00, sizeof(media_metadata_attributes_t));
621
622                         ret = __bt_avrcp_control_parse_properties(
623                                                                 &metadata, reply);
624                         if (BLUETOOTH_ERROR_NONE != ret) {
625                                 /* Free key and value because of break unless free not required */
626                                 free((char *)property);
627                                 g_variant_unref(value);
628                                 break;
629                         }
630
631                                 /* Send event to application */
632                         param = g_variant_new("(ssssuuu)",
633                                                         metadata.title,
634                                                         metadata.artist,
635                                                         metadata.album,
636                                                         metadata.genre,
637                                                         metadata.total_tracks,
638                                                         metadata.number,
639                                                         metadata.duration);
640                         _bt_send_event(BT_AVRCP_CONTROL_EVENT,
641                                 BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, param);
642
643                         g_free((char *)metadata.title);
644                         g_free((char *)metadata.artist);
645                         g_free((char *)metadata.album);
646                         g_free((char *)metadata.genre);
647                 } else {
648                         BT_DBG("Property not handled");
649                 }
650         }
651
652         BT_DBG("-");
653 }