4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <dbus/dbus-glib-lowlevel.h>
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus.h>
26 #include <syspopup_caller.h>
28 #include "bluetooth-api.h"
29 #include "bt-internal-types.h"
31 #include "bt-service-common.h"
32 #include "bt-service-avrcp.h"
33 #include "bt-service-event.h"
34 #include "bt-service-util.h"
36 struct player_settinngs_t {
41 static struct player_settinngs_t equalizer_settings[] = {
42 { EQUALIZER_INVALID, "" },
43 { EQUALIZER_OFF, "off" },
44 { EQUALIZER_ON, "on" },
45 { EQUALIZER_INVALID, "" }
48 static struct player_settinngs_t repeat_settings[] = {
49 { REPEAT_INVALID, "" },
50 { REPEAT_MODE_OFF, "off" },
51 { REPEAT_SINGLE_TRACK, "singletrack" },
52 { REPEAT_ALL_TRACK, "alltracks" },
53 { REPEAT_GROUP, "group" },
54 { REPEAT_INVALID, "" }
57 static struct player_settinngs_t shuffle_settings[] = {
58 { SHUFFLE_INVALID, "" },
59 { SHUFFLE_MODE_OFF, "off" },
60 { SHUFFLE_ALL_TRACK, "alltracks" },
61 { SHUFFLE_GROUP, "group" },
62 { SHUFFLE_INVALID, "" }
65 static struct player_settinngs_t scan_settings[] = {
67 { SCAN_MODE_OFF, "off" },
68 { SCAN_ALL_TRACK, "alltracks" },
69 { SCAN_GROUP, "group" },
73 static struct player_settinngs_t player_status[] = {
74 { STATUS_STOPPED, "stopped" },
75 { STATUS_PLAYING, "playing" },
76 { STATUS_PAUSED, "paused" },
77 { STATUS_FORWARD_SEEK, "forward-seek" },
78 { STATUS_REVERSE_SEEK, "reverse-seek" },
79 { STATUS_ERROR, "error" },
80 { STATUS_INVALID, "" }
91 GType bt_media_agent_get_type(void);
93 #define BT_MEDIA_TYPE_AGENT (bt_media_agent_get_type())
94 #define BT_MEDIA_GET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), BT_MEDIA_TYPE_AGENT, BtMediaAgent))
95 #define BT_MEDIA_IS_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BT_MEDIA_TYPE_AGENT))
96 #define BT_MEDIA_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST((class), BT_MEDIA_TYPE_AGENT, \
98 #define BT_MEDIA_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BT_MEDIA_TYPE_AGENT, \
100 #define BT_MEDIA_IS_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE((class), BT_MEDIA_TYPE_AGENT))
102 G_DEFINE_TYPE(BtMediaAgent, bt_media_agent, G_TYPE_OBJECT)
104 static gboolean bt_media_agent_set_property(BtMediaAgent *agent,
105 const char *property, GValue *value,
106 DBusGMethodInvocation *context);
108 static BtMediaAgent *bt_media_obj = NULL;
110 #include "bt-media-agent-method.h"
113 BT_MEDIA_AGENT_ERROR_INVALID_PARAM,
114 BT_MEDIA_AGENT_ERROR_NOT_AVAILABLE,
115 BT_MEDIA_AGENT_ERROR_BUSY,
118 #define BT_MEDIA_AGENT_ERROR (bt_media_agent_error_quark())
120 static GQuark bt_media_agent_error_quark(void)
122 static GQuark quark = 0;
124 quark = g_quark_from_static_string("agent");
129 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
131 static GError *bt_media_agent_error(BtMediaAgentError error, const char *err_msg)
133 return g_error_new(BT_MEDIA_AGENT_ERROR, error, err_msg, NULL);
136 static void bt_media_agent_init(BtMediaAgent *agent)
138 BT_DBG("agent %p\n", agent);
141 static void bt_media_agent_finalize(GObject *agent)
143 BT_DBG("Free agent %p\n", agent);
145 G_OBJECT_CLASS(bt_media_agent_parent_class)->finalize(agent);
148 static void bt_media_agent_class_init(BtMediaAgentClass *klass)
150 GObjectClass *object_class = (GObjectClass *) klass;
152 BT_DBG("class %p\n", klass);
154 object_class->finalize = bt_media_agent_finalize;
156 dbus_g_object_type_install_info(BT_MEDIA_TYPE_AGENT,
157 &dbus_glib_bt_media_agent_object_info);
160 static BtMediaAgent *__bt_media_agent_new(void)
164 agent = BT_MEDIA_GET_AGENT(g_object_new(BT_MEDIA_TYPE_AGENT, NULL));
166 BT_DBG("agent %p\n", agent);
171 static gboolean bt_media_agent_set_property(BtMediaAgent *agent,
172 const char *property, GValue *val,
173 DBusGMethodInvocation *context)
179 BT_DBG("property %s\n", property);
181 if (!(G_VALUE_TYPE (val) == G_TYPE_STRING)) {
182 error = bt_media_agent_error(
183 BT_MEDIA_AGENT_ERROR_INVALID_PARAM,
184 "Invalid Arguments");
185 dbus_g_method_return_error(context, error);
189 value = g_value_get_string (val);
190 BT_DBG("value %s\n", value);
192 if (g_strcmp0(property, "Shuffle") == 0) {
193 if (g_strcmp0(value, "alltracks") == 0)
194 status = SHUFFLE_ALL_TRACK;
195 else if (g_strcmp0(value, "group") == 0)
196 status = SHUFFLE_GROUP;
197 else if (g_strcmp0(value, "off") == 0)
198 status = SHUFFLE_MODE_OFF;
200 status = SHUFFLE_INVALID;
202 _bt_send_event(BT_AVRCP_EVENT,
203 BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS,
204 DBUS_TYPE_UINT32, &status,
207 } else if (g_strcmp0(property, "Equalizer") == 0) {
208 status = (g_strcmp0(value, "off") == 0) ? EQUALIZER_OFF : EQUALIZER_ON;
210 _bt_send_event(BT_AVRCP_EVENT,
211 BLUETOOTH_EVENT_AVRCP_SETTING_EQUALIZER_STATUS,
212 DBUS_TYPE_UINT32, &status,
215 } else if (g_strcmp0(property, "Repeat") == 0) {
216 if (g_strcmp0(value, "singletrack") == 0)
217 status = REPEAT_SINGLE_TRACK;
218 else if (g_strcmp0(value, "alltracks") == 0)
219 status = REPEAT_ALL_TRACK;
220 else if (g_strcmp0(value, "group") == 0)
221 status = REPEAT_GROUP;
222 else if (g_strcmp0(value, "off") == 0)
223 status = REPEAT_MODE_OFF;
225 status = REPEAT_INVALID;
227 _bt_send_event(BT_AVRCP_EVENT,
228 BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS,
229 DBUS_TYPE_UINT32, &status,
231 } else if (g_strcmp0(property, "Scan") == 0) {
232 if (g_strcmp0(value, "alltracks") == 0)
233 status = SCAN_ALL_TRACK;
234 else if (g_strcmp0(value, "group") == 0)
236 else if (g_strcmp0(value, "off") == 0)
237 status = SCAN_MODE_OFF;
239 status = SCAN_INVALID;
241 _bt_send_event(BT_AVRCP_EVENT,
242 BLUETOOTH_EVENT_AVRCP_SETTING_SCAN_STATUS,
243 DBUS_TYPE_UINT32, &status,
246 dbus_g_method_return(context);
251 static void __bt_media_append_variant(DBusMessageIter *iter,
252 int type, void *value)
255 DBusMessageIter value_iter;
258 case DBUS_TYPE_BOOLEAN:
259 sig = DBUS_TYPE_BOOLEAN_AS_STRING;
261 case DBUS_TYPE_STRING:
262 sig = DBUS_TYPE_STRING_AS_STRING;
265 sig = DBUS_TYPE_BYTE_AS_STRING;
267 case DBUS_TYPE_UINT16:
268 sig = DBUS_TYPE_UINT16_AS_STRING;
270 case DBUS_TYPE_UINT32:
271 sig = DBUS_TYPE_UINT32_AS_STRING;
273 case DBUS_TYPE_INT16:
274 sig = DBUS_TYPE_INT16_AS_STRING;
276 case DBUS_TYPE_INT32:
277 sig = DBUS_TYPE_INT32_AS_STRING;
279 case DBUS_TYPE_OBJECT_PATH:
280 sig = DBUS_TYPE_OBJECT_PATH_AS_STRING;
283 sig = DBUS_TYPE_VARIANT_AS_STRING;
287 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig,
290 dbus_message_iter_append_basic(&value_iter, type, value);
292 dbus_message_iter_close_container(iter, &value_iter);
295 static gboolean __bt_media_emit_property_changed(
296 DBusConnection *connection,
298 const char *interface,
304 DBusMessageIter entry;
307 sig = dbus_message_new_signal(path, interface,
309 retv_if(sig == NULL, FALSE);
311 dbus_message_iter_init_append(sig, &entry);
312 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name);
314 __bt_media_append_variant(&entry, type, property);
316 ret = dbus_connection_send(connection, sig, NULL);
317 dbus_message_unref(sig);
322 static void __bt_media_append_dict_entry(DBusMessageIter *iter,
323 const char *key, int type, void *property)
325 DBusMessageIter dict_entry;
328 if (type == DBUS_TYPE_STRING) {
329 str_ptr = *((const char **)property);
330 ret_if(str_ptr == NULL);
333 dbus_message_iter_open_container(iter,
334 DBUS_TYPE_DICT_ENTRY,
337 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
339 __bt_media_append_variant(&dict_entry, type, property);
341 dbus_message_iter_close_container(iter, &dict_entry);
344 int _bt_register_media_player(void)
348 DBusMessageIter iter;
349 DBusMessageIter property_dict;
350 DBusMessageIter metadata_dict;
354 DBusConnection *conn;
355 DBusGConnection *gconn;
357 media_player_settings_t player_settings = {0,};
358 media_metadata_attributes_t metadata = {0,};
360 player_settings.equalizer = EQUALIZER_OFF;
361 player_settings.repeat = REPEAT_MODE_OFF;
362 player_settings.shuffle = SHUFFLE_MODE_OFF;
363 player_settings.scan = SCAN_MODE_OFF;
364 player_settings.status = STATUS_STOPPED;
365 player_settings.position = 0;
367 metadata.title = "\0";
368 metadata.artist = "\0";
369 metadata.album = "\0";
370 metadata.genre = "\0";
371 metadata.total_tracks = 0;
373 metadata.duration = 0;
375 gconn = _bt_get_system_gconn();
376 retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL);
378 conn = _bt_get_system_conn();
379 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
382 bt_media_obj = __bt_media_agent_new();
384 retv_if(bt_media_obj == NULL, BLUETOOTH_ERROR_INTERNAL);
386 dbus_g_connection_register_g_object(gconn,
387 BT_MEDIA_OBJECT_PATH,
388 G_OBJECT(bt_media_obj));
391 adapter_path = _bt_get_adapter_path();
392 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
394 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
395 BT_MEDIA_INTERFACE, "RegisterPlayer");
397 g_free(adapter_path);
399 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
401 object = g_strdup(BT_MEDIA_OBJECT_PATH);
403 dbus_message_iter_init_append(msg, &iter);
404 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object);
407 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
408 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
409 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
410 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
412 __bt_media_append_dict_entry(&property_dict,
415 &equalizer_settings[player_settings.equalizer].property);
417 __bt_media_append_dict_entry(&property_dict,
420 &repeat_settings[player_settings.repeat].property);
422 __bt_media_append_dict_entry(&property_dict,
425 &shuffle_settings[player_settings.shuffle].property);
427 __bt_media_append_dict_entry(&property_dict,
430 &scan_settings[player_settings.scan].property);
432 __bt_media_append_dict_entry(&property_dict,
435 &player_status[player_settings.status].property);
437 __bt_media_append_dict_entry(&property_dict,
439 DBUS_TYPE_UINT32, &player_settings.position);
441 dbus_message_iter_close_container(&iter, &property_dict);
443 dbus_message_iter_init_append(msg, &iter);
444 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
445 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
446 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
447 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata_dict);
449 __bt_media_append_dict_entry(&metadata_dict,
451 DBUS_TYPE_STRING, &metadata.title);
453 __bt_media_append_dict_entry(&metadata_dict,
455 DBUS_TYPE_STRING, &metadata.artist);
457 __bt_media_append_dict_entry(&metadata_dict,
459 DBUS_TYPE_STRING, &metadata.album);
461 __bt_media_append_dict_entry(&metadata_dict,
463 DBUS_TYPE_STRING, &metadata.genre);
465 __bt_media_append_dict_entry(&metadata_dict,
467 DBUS_TYPE_UINT32, &metadata.total_tracks);
469 __bt_media_append_dict_entry(&metadata_dict,
471 DBUS_TYPE_UINT32, &metadata.number);
473 __bt_media_append_dict_entry(&metadata_dict,
475 DBUS_TYPE_UINT32, &metadata.duration);
477 dbus_message_iter_close_container(&iter, &metadata_dict);
479 dbus_error_init(&err);
480 reply = dbus_connection_send_with_reply_and_block(conn,
482 dbus_message_unref(msg);
485 BT_ERR("Error in registering the Music Player \n");
487 if (dbus_error_is_set(&err)) {
488 BT_ERR("%s", err.message);
489 dbus_error_free(&err);
490 return BLUETOOTH_ERROR_INTERNAL;
494 dbus_g_connection_unregister_g_object(gconn,
495 G_OBJECT(bt_media_obj));
496 g_object_unref(bt_media_obj);
502 dbus_message_unref(reply);
504 return BLUETOOTH_ERROR_NONE;
507 int _bt_unregister_media_player(void)
514 DBusConnection *conn;
516 conn = _bt_get_system_conn();
517 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
519 adapter_path = _bt_get_adapter_path();
520 retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
522 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path,
523 BT_MEDIA_INTERFACE, "UnregisterPlayer");
525 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
527 object = g_strdup(BT_MEDIA_OBJECT_PATH);
529 dbus_message_append_args(msg,
530 DBUS_TYPE_OBJECT_PATH, &object,
535 dbus_error_init(&err);
536 reply = dbus_connection_send_with_reply_and_block(conn,
538 dbus_message_unref(msg);
541 BT_ERR("Error in unregistering the Music Player \n");
543 if (dbus_error_is_set(&err)) {
544 BT_DBG("%s", err.message);
545 dbus_error_free(&err);
546 return BLUETOOTH_ERROR_INTERNAL;
549 dbus_message_unref(reply);
553 dbus_g_connection_unregister_g_object(_bt_get_system_gconn(),
554 G_OBJECT(bt_media_obj));
555 g_object_unref(bt_media_obj);
559 return BLUETOOTH_ERROR_NONE;
562 int _bt_avrcp_set_track_info(media_metadata_attributes_t *meta_data)
565 DBusMessageIter iter;
566 DBusMessageIter metadata_dict;
567 DBusConnection *conn;
569 retv_if(meta_data == NULL, BLUETOOTH_ERROR_INTERNAL);
571 conn = _bt_get_system_conn();
572 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
574 signal = dbus_message_new_signal(BT_MEDIA_OBJECT_PATH,
575 BT_MEDIA_PLAYER_INTERFACE, "TrackChanged");
577 retv_if(signal == NULL, BLUETOOTH_ERROR_INTERNAL);
579 dbus_message_iter_init_append(signal, &iter);
581 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
582 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
583 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
584 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata_dict);
586 if (meta_data->title) {
587 __bt_media_append_dict_entry(&metadata_dict,
589 DBUS_TYPE_STRING, &meta_data->title);
592 if (meta_data->artist) {
593 __bt_media_append_dict_entry(&metadata_dict,
595 DBUS_TYPE_STRING, &meta_data->artist);
598 if (meta_data->album) {
599 __bt_media_append_dict_entry(&metadata_dict,
601 DBUS_TYPE_STRING, &meta_data->album);
604 if (meta_data->genre) {
605 __bt_media_append_dict_entry(&metadata_dict,
607 DBUS_TYPE_STRING, &meta_data->genre);
610 if (0 != meta_data->total_tracks)
611 __bt_media_append_dict_entry(&metadata_dict,
613 DBUS_TYPE_UINT32, &meta_data->total_tracks);
615 if (0 != meta_data->number)
616 __bt_media_append_dict_entry(&metadata_dict,
618 DBUS_TYPE_UINT32, &meta_data->number);
620 if (0 != meta_data->duration)
621 __bt_media_append_dict_entry(&metadata_dict,
623 DBUS_TYPE_UINT32, &meta_data->duration);
625 dbus_message_iter_close_container(&iter, &metadata_dict);
627 if (!dbus_connection_send(conn, signal, NULL))
628 BT_ERR("Unable to send TrackChanged signal\n");
630 dbus_message_unref(signal);
632 return BLUETOOTH_ERROR_NONE;
636 int _bt_avrcp_set_properties(media_player_settings_t *properties)
638 if (_bt_avrcp_set_property(EQUALIZER,
639 properties->equalizer) != BLUETOOTH_ERROR_NONE) {
640 return BLUETOOTH_ERROR_INTERNAL;
643 if (_bt_avrcp_set_property(REPEAT,
644 properties->repeat) != BLUETOOTH_ERROR_NONE) {
645 return BLUETOOTH_ERROR_INTERNAL;
648 if (_bt_avrcp_set_property(SHUFFLE,
649 properties->shuffle) != BLUETOOTH_ERROR_NONE) {
650 return BLUETOOTH_ERROR_INTERNAL;
653 if (_bt_avrcp_set_property(SCAN,
654 properties->scan) != BLUETOOTH_ERROR_NONE) {
655 return BLUETOOTH_ERROR_INTERNAL;
658 if (_bt_avrcp_set_property(STATUS,
659 properties->status) != BLUETOOTH_ERROR_NONE) {
660 return BLUETOOTH_ERROR_INTERNAL;
663 if (_bt_avrcp_set_property(POSITION,
664 properties->position) != BLUETOOTH_ERROR_NONE) {
665 return BLUETOOTH_ERROR_INTERNAL;
668 return BLUETOOTH_ERROR_NONE;
671 int _bt_avrcp_set_property(int type, unsigned int value)
673 DBusConnection *conn;
675 conn = _bt_get_system_conn();
676 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
680 if (!__bt_media_emit_property_changed(
682 BT_MEDIA_OBJECT_PATH,
683 BT_MEDIA_PLAYER_INTERFACE,
686 &equalizer_settings[value].property)) {
687 BT_ERR("Error sending the PropertyChanged signal \n");
688 return BLUETOOTH_ERROR_INTERNAL;
692 if (!__bt_media_emit_property_changed(
694 BT_MEDIA_OBJECT_PATH,
695 BT_MEDIA_PLAYER_INTERFACE,
698 &repeat_settings[value].property)) {
699 BT_ERR("Error sending the PropertyChanged signal \n");
700 return BLUETOOTH_ERROR_INTERNAL;
704 if (!__bt_media_emit_property_changed(
706 BT_MEDIA_OBJECT_PATH,
707 BT_MEDIA_PLAYER_INTERFACE,
710 &shuffle_settings[value].property)) {
711 BT_ERR("Error sending the PropertyChanged signal \n");
712 return BLUETOOTH_ERROR_INTERNAL;
716 if (!__bt_media_emit_property_changed(
718 BT_MEDIA_OBJECT_PATH,
719 BT_MEDIA_PLAYER_INTERFACE,
722 &scan_settings[value].property)) {
723 BT_ERR("Error sending the PropertyChanged signal \n");
724 return BLUETOOTH_ERROR_INTERNAL;
728 if (!__bt_media_emit_property_changed(
730 BT_MEDIA_OBJECT_PATH,
731 BT_MEDIA_PLAYER_INTERFACE,
734 &player_status[value].property)) {
735 BT_ERR("Error sending the PropertyChanged signal \n");
736 return BLUETOOTH_ERROR_INTERNAL;
740 if (!__bt_media_emit_property_changed(
742 BT_MEDIA_OBJECT_PATH,
743 BT_MEDIA_PLAYER_INTERFACE,
747 BT_ERR("Error sending the PropertyChanged signal \n");
748 return BLUETOOTH_ERROR_INTERNAL;
752 BT_ERR("Invalid Type\n");
753 return BLUETOOTH_ERROR_INTERNAL;
756 return BLUETOOTH_ERROR_NONE;