*/
#define AVC_PRESS_TIMEOUT 2
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+/* We need to send hold event before AVC_PRESS time runs out */
+#define AVC_HOLD_TIMEOUT 1
+#endif
+
#define CONTROL_TIMEOUT 10
#define BROWSING_TIMEOUT 10
struct key_pressed {
uint16_t op;
guint timer;
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+ bool hold;
+#endif
};
struct avctp {
session->state = AVCTP_STATE_DISCONNECTED;
session->uinput = -1;
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+ session->key.op = AVC_INVALID;
+#endif
server->sessions = g_slist_append(server->sessions, session);
return session;
{
struct avctp *session = user_data;
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
avctp_passthrough_release(session, session->key.op);
+#endif
#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
avctp_passthrough_press(session, session->key.op);
#endif
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
static void release_pressed(struct avctp *session)
+#else
+static int release_pressed(struct avctp *session)
+#endif
{
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
if (session->key.op != AVC_FAST_FORWARD && session->key.op != AVC_REWIND)
#endif
- avctp_passthrough_release(session, session->key.op);
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+ avctp_passthrough_release(session, session->key.op);
+#else
+ int ret = avctp_passthrough_release(session, session->key.op);
+#endif
if (session->key.timer > 0)
g_source_remove(session->key.timer);
session->key.timer = 0;
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+ session->key.op = AVC_INVALID;
+ session->key.hold = false;
+
+ return ret;
+#endif
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
static bool set_pressed(struct avctp *session, uint8_t op)
+#else
+static bool hold_pressed(struct avctp *session, uint8_t op)
+#endif
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
if (session->key.timer > 0) {
if (session->key.op == op)
return TRUE;
}
if (op != AVC_FAST_FORWARD && op != AVC_REWIND)
+#else
+ if (session->key.op != op || !session->key.hold)
+#endif
return FALSE;
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
session->key.op = op;
session->key.timer = g_timeout_add_seconds(AVC_PRESS_TIMEOUT,
+#else
+ if (session->key.timer == 0)
+ session->key.timer = g_timeout_add_seconds(AVC_HOLD_TIMEOUT,
+#endif
repeat_timeout,
session);
uint8_t *operands, size_t operand_count,
void *user_data)
{
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+ uint8_t op = operands[0];
+#endif
+
if (code != AVC_CTYPE_ACCEPTED)
return FALSE;
-
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
if (set_pressed(session, operands[0]))
+#else
+ if (hold_pressed(session, op))
+#endif
return FALSE;
-
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
avctp_passthrough_release(session, operands[0]);
-
+#else
+ if (op == session->key.op)
+ release_pressed(session);
+#endif
return FALSE;
}
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
int avctp_send_passthrough(struct avctp *session, uint8_t op)
+#else
+int avctp_send_passthrough(struct avctp *session, uint8_t op, bool hold)
+#endif
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
/* Auto release if key pressed */
if (session->key.timer > 0)
- release_pressed(session);
+#else
+ if (op & 0x80)
+ return -EINVAL;
+ /* Release previously unreleased key */
+ if (session->key.op != AVC_INVALID && session->key.op != op)
+#endif
+ release_pressed(session);
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+ session->key.op = op;
+ session->key.hold = hold;
+#endif
return avctp_passthrough_press(session, op);
}
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+int avctp_send_release_passthrough(struct avctp *session)
+{
+ if (session->key.op != AVC_INVALID)
+ return release_pressed(session);
+
+ return 0;
+}
+#endif
+
#ifdef TIZEN_FEATURE_BLUEZ_A2DP_MULTISTREAM
static int avctp_passthrough_press_fast(struct avctp *session, uint8_t op)
{
#define AVC_YELLOW 0x7c
#define AVC_VENDOR_UNIQUE 0x7e
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+#define AVC_INVALID 0xff
+#endif
struct avctp;
typedef enum {
GDestroyNotify destroy);
gboolean avctp_unregister_browsing_pdu_handler(unsigned int id);
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
int avctp_send_passthrough(struct avctp *session, uint8_t op);
+#else
+int avctp_send_passthrough(struct avctp *session, uint8_t op, bool hold);
+int avctp_send_release_passthrough(struct avctp *session);
+#endif
+
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
int avctp_send_release_passthrough(struct avctp *session, uint8_t op);
#endif
static int ct_press(struct avrcp_player *player, uint8_t op)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
int err;
struct avrcp *session;
-
+#else
+ struct avrcp *session = player->sessions->data;
+#endif
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
session = player->sessions->data;
+#endif
if (session == NULL)
return -ENOTCONN;
set_ct_player(session, player);
-
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
err = avctp_send_passthrough(session->conn, op);
if (err < 0)
return err;
return 0;
+#else
+ return avctp_send_passthrough(session->conn, op, false);
+#endif
+}
+
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+static int ct_hold(struct avrcp_player *player, uint8_t op)
+{
+ struct avrcp *session = player->sessions->data;
+
+ if (session == NULL)
+ return -ENOTCONN;
+
+ set_ct_player(session, player);
+
+ return avctp_send_passthrough(session->conn, op, true);
}
+static int ct_release(struct avrcp_player *player)
+{
+ struct avrcp *session = player->sessions->data;
+
+ if (session == NULL)
+ return -ENOTCONN;
+
+ set_ct_player(session, player);
+
+ return avctp_send_release_passthrough(session->conn);
+}
+#endif
+
#if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(TIZEN_FEATURE_BLUEZ_A2DP_MULTISTREAM)
static int ct_press_send_atonce(struct avrcp_player *player, uint8_t op)
{
{
struct avrcp_player *player = user_data;
- return ct_press(player, AVC_FAST_FORWARD);
+ return ct_hold(player, AVC_FAST_FORWARD);
}
static int ct_rewind(struct media_player *mp, void *user_data)
{
struct avrcp_player *player = user_data;
- return ct_press(player, AVC_REWIND);
+ return ct_hold(player, AVC_REWIND);
+}
+
+static int ct_press_key(struct media_player *mp, uint8_t avc_key,
+ void *user_data)
+{
+ struct avrcp_player *player = user_data;
+
+ return ct_press(player, avc_key);
+}
+
+static int ct_hold_key(struct media_player *mp, uint8_t avc_key,
+ void *user_data)
+{
+ struct avrcp_player *player = user_data;
+
+ return ct_hold(player, avc_key);
+}
+
+static int ct_release_key(struct media_player *mp, void *user_data)
+{
+ struct avrcp_player *player = user_data;
+
+ return ct_release(player);
}
#endif
#else
.fast_forward = ct_fast_forward,
.rewind = ct_rewind,
+ .press = ct_press_key,
+ .hold = ct_hold_key,
+ .release = ct_release_key,
#endif
.list_items = ct_list_items,
.change_folder = ct_change_folder,
}
static DBusMessage *key_pressed(DBusConnection *conn, DBusMessage *msg,
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
uint8_t op, void *data)
+#else
+ uint8_t op, bool hold, void *data)
+#endif
{
struct control *control = data;
int err;
if (!control->target)
return btd_error_not_supported(msg);
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
err = avctp_send_passthrough(control->session, op);
+#else
+ err = avctp_send_passthrough(control->session, op, hold);
+#endif
if (err < 0)
return btd_error_failed(msg, strerror(-err));
static DBusMessage *control_volume_up(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_VOLUME_UP, data);
+#else
+ return key_pressed(conn, msg, AVC_VOLUME_UP, false, data);
+#endif
}
static DBusMessage *control_volume_down(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_VOLUME_DOWN, data);
+#else
+ return key_pressed(conn, msg, AVC_VOLUME_DOWN, false, data);
+#endif
}
static DBusMessage *control_play(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_PLAY, data);
+#else
+ return key_pressed(conn, msg, AVC_PLAY, false, data);
+#endif
}
static DBusMessage *control_pause(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_PAUSE, data);
+#else
+ return key_pressed(conn, msg, AVC_PAUSE, false, data);
+#endif
}
static DBusMessage *control_stop(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_STOP, data);
+#else
+ return key_pressed(conn, msg, AVC_STOP, false, data);
+#endif
}
static DBusMessage *control_next(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_FORWARD, data);
+#else
+ return key_pressed(conn, msg, AVC_FORWARD, false, data);
+#endif
}
static DBusMessage *control_previous(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_BACKWARD, data);
+#else
+ return key_pressed(conn, msg, AVC_BACKWARD, false, data);
+#endif
}
static DBusMessage *control_fast_forward(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_FAST_FORWARD, data);
+#else
+ return key_pressed(conn, msg, AVC_FAST_FORWARD, true, data);
+#endif
}
static DBusMessage *control_rewind(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
return key_pressed(conn, msg, AVC_REWIND, data);
+#else
+ return key_pressed(conn, msg, AVC_REWIND, true, data);
+#endif
}
static gboolean control_property_get_connected(
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
+
+static DBusMessage *media_player_press(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct media_player *mp = data;
+ struct player_callback *cb = mp->cb;
+ int err;
+ uint8_t avc_key;
+
+ if (cb->cbs->press == NULL)
+ return btd_error_not_supported(msg);
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BYTE, &avc_key,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ err = cb->cbs->press(mp, avc_key, cb->user_data);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *media_player_hold(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct media_player *mp = data;
+ struct player_callback *cb = mp->cb;
+ int err;
+ uint8_t avc_key;
+
+ if (cb->cbs->hold == NULL)
+ return btd_error_not_supported(msg);
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BYTE, &avc_key,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ err = cb->cbs->hold(mp, avc_key, cb->user_data);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *media_player_release(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct media_player *mp = data;
+ struct player_callback *cb = mp->cb;
+ int err;
+
+ if (cb->cbs->release == NULL)
+ return btd_error_not_supported(msg);
+
+ err = cb->cbs->release(mp, cb->user_data);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
#endif
static void parse_folder_list(gpointer data, gpointer user_data)
{
#else
{ GDBUS_METHOD("FastForward", NULL, NULL, media_player_fast_forward) },
{ GDBUS_METHOD("Rewind", NULL, NULL, media_player_rewind) },
+ { GDBUS_METHOD("Press", GDBUS_ARGS({"avc_key", "y"}), NULL,
+ media_player_press) },
+ { GDBUS_METHOD("Hold", GDBUS_ARGS({"avc_key", "y"}), NULL,
+ media_player_hold) },
+ { GDBUS_METHOD("Release", NULL, NULL, media_player_release) },
#endif
{ }
};
struct media_item;
struct media_player_callback {
- bool (*set_setting) (struct media_player *mp, const char *key,
+ bool (*set_setting)(struct media_player *mp, const char *key,
const char *value, void *user_data);
- int (*play) (struct media_player *mp, void *user_data);
- int (*pause) (struct media_player *mp, void *user_data);
- int (*stop) (struct media_player *mp, void *user_data);
- int (*next) (struct media_player *mp, void *user_data);
- int (*previous) (struct media_player *mp, void *user_data);
+ int (*play)(struct media_player *mp, void *user_data);
+ int (*pause)(struct media_player *mp, void *user_data);
+ int (*stop)(struct media_player *mp, void *user_data);
+ int (*next)(struct media_player *mp, void *user_data);
+ int (*previous)(struct media_player *mp, void *user_data);
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
- int (*press_fast_forward) (struct media_player *mp, void *user_data);
- int (*release_fast_forward) (struct media_player *mp, void *user_data);
- int (*press_rewind) (struct media_player *mp, void *user_data);
- int (*release_rewind) (struct media_player *mp, void *user_data);
- int (*volume_up) (struct media_player *mp, void *user_data);
- int (*volume_down) (struct media_player *mp, void *user_data);
+ int (*press_fast_forward)(struct media_player *mp, void *user_data);
+ int (*release_fast_forward)(struct media_player *mp, void *user_data);
+ int (*press_rewind)(struct media_player *mp, void *user_data);
+ int (*release_rewind)(struct media_player *mp, void *user_data);
+ int (*volume_up)(struct media_player *mp, void *user_data);
+ int (*volume_down)(struct media_player *mp, void *user_data);
#else
- int (*fast_forward) (struct media_player *mp, void *user_data);
- int (*rewind) (struct media_player *mp, void *user_data);
+ int (*fast_forward)(struct media_player *mp, void *user_data);
+ int (*rewind)(struct media_player *mp, void *user_data);
+ int (*press)(struct media_player *mp, uint8_t avc_key,
+ void *user_data);
+ int (*hold)(struct media_player *mp, uint8_t avc_key,
+ void *user_data);
+ int (*release)(struct media_player *mp, void *user_data);
#endif
- int (*list_items) (struct media_player *mp, const char *name,
+ int (*list_items)(struct media_player *mp, const char *name,
uint32_t start, uint32_t end, void *user_data);
- int (*change_folder) (struct media_player *mp, const char *path,
+ int (*change_folder)(struct media_player *mp, const char *path,
uint64_t uid, void *user_data);
- int (*search) (struct media_player *mp, const char *string,
+ int (*search)(struct media_player *mp, const char *string,
void *user_data);
- int (*play_item) (struct media_player *mp, const char *name,
+ int (*play_item)(struct media_player *mp, const char *name,
uint64_t uid, void *user_data);
- int (*add_to_nowplaying) (struct media_player *mp, const char *name,
+ int (*add_to_nowplaying)(struct media_player *mp, const char *name,
uint64_t uid, void *user_data);
- int (*total_items) (struct media_player *mp, const char *name,
+ int (*total_items)(struct media_player *mp, const char *name,
void *user_data);
};