#include "headphone.h"
+#define HANDLING_DELAY 2000
+#define MAX_HANDLING_COUNT 3
+
ctx::device_status_headphone::device_status_headphone()
: connected(false)
, audio_jack_state(RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED)
, bt_audio_state(false)
, bt_audio_callback_on(false)
+ , bt_event_handler_added(false)
+ , bt_event_handling_count(0)
{
}
int ctx::device_status_headphone::subscribe(const char* subject, const char* zone)
{
- //FIXME: in case of TV?
if (client_zone.empty()) {
connected = get_current_status();
// Wired headphone
- int ret = runtime_info_set_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, audio_jack_cb, this);
+ int ret = runtime_info_set_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, on_audio_jack_state_changed, this);
IF_FAIL_RETURN(ret == RUNTIME_INFO_ERROR_NONE, ERR_OPERATION_FAILED);
// Bluetooth headphone
return;
}
- ret = bt_audio_initialize();
- if (ret != BT_ERROR_NONE) {
- bt_deinitialize();
- _W("Bluetooth audio initialization failed");
- return;
- }
-
- ret = bt_audio_set_connection_state_changed_cb(bt_audio_cb, this);
+ ret = bt_device_set_connection_state_changed_cb(on_bt_connection_changed, this);
if (ret != BT_ERROR_NONE) {
- bt_audio_deinitialize();
bt_deinitialize();
return;
}
{
IF_FAIL_VOID(bt_audio_callback_on);
- bt_audio_unset_connection_state_changed_cb();
- bt_audio_deinitialize();
+ bt_device_unset_connection_state_changed_cb();
bt_deinitialize();
+
+ bt_audio_callback_on = false;
}
void ctx::device_status_headphone::set_bt_audio_state(bool state)
bt_audio_state = false;
ret = bt_initialize();
if (ret == BT_ERROR_NONE) {
- bt_adapter_foreach_bonded_device(bt_bonded_device_cb, this);
+ bt_adapter_foreach_bonded_device(on_bt_bond, this);
bt_deinitialize();
}
}
}
-void ctx::device_status_headphone::handle_event()
+bool ctx::device_status_headphone::handle_event()
{
bool prev_state = connected;
connected = ((audio_jack_state != RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED) || bt_audio_state);
- IF_FAIL_VOID(prev_state != connected);
+ IF_FAIL_RETURN(prev_state != connected, false);
ctx::json data;
generate_data_packet(data);
publish(DEVICE_ST_SUBJ_HEADPHONE, ERR_NONE, data, client_zone);
+ return true;
}
void ctx::device_status_headphone::handle_audio_jack_event()
handle_event();
}
-void ctx::device_status_headphone::handle_bt_audio_event(bool conn)
-{
- bt_audio_state = conn;
- handle_event();
-}
-
-void ctx::device_status_headphone::audio_jack_cb(runtime_info_key_e runtime_key, void* user_data)
+void ctx::device_status_headphone::on_audio_jack_state_changed(runtime_info_key_e runtime_key, void* user_data)
{
_D("EarJack");
ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
instance->handle_audio_jack_event();
}
-void ctx::device_status_headphone::bt_audio_cb(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data)
+void ctx::device_status_headphone::on_bt_connection_changed(bool connected, bt_device_connection_info_s *conn_info, void *user_data)
{
- _D("BlueTooth");
- IF_FAIL_VOID_TAG(result == BT_ERROR_NONE, _E, "Error: %d", result);
-
ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
- instance->handle_bt_audio_event(connected);
+ IF_FAIL_VOID(connected != instance->bt_audio_state);
+ IF_FAIL_VOID(!instance->bt_event_handler_added);
+
+ if (connected) {
+ _D("BT state checking scheduled");
+ instance->bt_event_handler_added = true;
+ instance->bt_event_handling_count = 0;
+ g_timeout_add(HANDLING_DELAY, handle_bt_event, user_data);
+ } else {
+ handle_bt_event(user_data);
+ }
}
-bool ctx::device_status_headphone::bt_bonded_device_cb(bt_device_info_s *device_info, void* user_data)
+gboolean ctx::device_status_headphone::handle_bt_event(gpointer data)
{
- if (device_info->bt_class.major_device_class == BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO)
- bt_device_foreach_connected_profiles(device_info->remote_address, bt_profile_cb, user_data);
+ _D("BT state checking started");
+ ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(data);
+ instance->bt_event_handler_added = false;
- return true;
+ instance->set_bt_audio_state(false);
+ int err = bt_adapter_foreach_bonded_device(on_bt_bond, data);
+ IF_FAIL_RETURN_TAG(err == BT_ERROR_NONE, FALSE, _E, "bt_adapter_foreach_bonded_device() failed");
+
+ instance->bt_event_handling_count++;
+
+ if (instance->handle_event() || instance->bt_event_handling_count >= MAX_HANDLING_COUNT)
+ return FALSE;
+
+ return TRUE;
}
-bool ctx::device_status_headphone::bt_profile_cb(bt_profile_e profile, void* user_data)
+bool ctx::device_status_headphone::on_bt_bond(bt_device_info_s *device_info, void* user_data)
{
- if (profile == BT_PROFILE_A2DP || profile == BT_PROFILE_HSP) {
+ if (device_info->bt_class.major_device_class != BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO)
+ return true;
+
+ bool st = false;
+ int err = bt_device_is_profile_connected(device_info->remote_address, BT_PROFILE_A2DP, &st);
+ IF_FAIL_RETURN_TAG(err == BT_ERROR_NONE, false, _E, "bt_device_is_profile_connected() failed");
+
+ if (st) {
ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
instance->set_bt_audio_state(true);
return false;
}
+
return true;
}
#ifndef _DEVICE_STATUS_HEADPHONE_H_
#define _DEVICE_STATUS_HEADPNOHE_H_
+#include <glib.h>
#include <runtime_info.h>
#include <bluetooth.h>
#include "../sub_provider_base.h"
int audio_jack_state;
bool bt_audio_state;
bool bt_audio_callback_on;
+ bool bt_event_handler_added;
+ int bt_event_handling_count;
bool get_current_status();
void set_bt_audio_callback();
void set_bt_audio_state(bool state);
void generate_data_packet(json &data);
- void handle_event();
+ bool handle_event();
void handle_audio_jack_event();
- void handle_bt_audio_event(bool conn);
- static void bt_audio_cb(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data);
- static void audio_jack_cb(runtime_info_key_e runtime_key, void* user_data);
- static bool bt_bonded_device_cb(bt_device_info_s *device_info, void* user_data);
- static bool bt_profile_cb(bt_profile_e profile, void* user_data);
+ static gboolean handle_bt_event(gpointer data);
+ static void on_audio_jack_state_changed(runtime_info_key_e runtime_key, void* user_data);
+ static void on_bt_connection_changed(bool connected, bt_device_connection_info_s *conn_info, void *user_data);
+ static bool on_bt_bond(bt_device_info_s *device_info, void* user_data);
};
}