#include #include #include #include #include #include #include #include #include #include #include "avrcpctrl.h" #include "gdbus.h" #define COLOR_OFF "\x1B[0m" #define COLOR_RED "\x1B[0;91m" #define COLOR_GREEN "\x1B[0;92m" #define COLOR_YELLOW "\x1B[0;93m" #define COLOR_BLUE "\x1B[0;94m" #define COLOR_BOLDGRAY "\x1B[1;30m" #define COLOR_BOLDWHITE "\x1B[1;37m" /* String display constants */ #define COLORED_NEW COLOR_GREEN "NEW" COLOR_OFF #define COLORED_CHG COLOR_YELLOW "CHG" COLOR_OFF #define COLORED_DEL COLOR_RED "DEL" COLOR_OFF #define PROMPT_ON COLOR_BLUE "[bluetooth]" COLOR_OFF "# " #define PROMPT_OFF "[bluetooth]# " #define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1" #define BLUEZ_MEDIA_FOLDER_INTERFACE "org.bluez.MediaFolder1" #define BLUEZ_MEDIA_ITEM_INTERFACE "org.bluez.MediaItem1" DBusConnection *dbus_conn; GDBusProxy *default_player; GSList *players = NULL; GSList *folders = NULL; GSList *items = NULL; GDBusClient *client; GMainLoop *main_loop = NULL; void connect_handler(DBusConnection *connection, void *user_data) { rl_set_prompt(PROMPT_ON); printf("\r"); rl_on_new_line(); rl_redisplay(); } void disconnect_handler(DBusConnection *connection, void *user_data) { rl_set_prompt(PROMPT_OFF); printf("\r"); rl_on_new_line(); rl_redisplay(); } void print_folder(GDBusProxy *proxy, const char *description) { const char *path; path = g_dbus_proxy_get_path(proxy); /*Log::debug("%s%s%sFolder %s\n", description ? "[" : "", description ? : "", description ? "] " : "", path);*/ } void folder_removed(GDBusProxy *proxy) { folders = g_slist_remove(folders, proxy); print_folder(proxy, COLORED_DEL); } char *proxy_description(GDBusProxy *proxy, const char *title, const char *description) { const char *path; path = g_dbus_proxy_get_path(proxy); return g_strdup_printf("%s%s%s%s %s ", description ? "[" : "", description ? : "", description ? "] " : "", title, path); } void print_player(GDBusProxy *proxy, const char *description) { char *str; char strplay[256]; str = proxy_description(proxy, "Player", description); memset(strplay, 0x00, 256); sprintf(strplay,"%s%s\n", str, (default_player == proxy ? "[default]" : "")); printf(strplay); g_free(str); } void player_added(GDBusProxy *proxy) { printf("player_added \n"); players = g_slist_append(players, proxy); if (default_player == NULL){ printf("set default player"); default_player = proxy; } print_player(proxy, COLORED_NEW); } void print_item(GDBusProxy *proxy, const char *description) { const char *path, *name; DBusMessageIter iter; path = g_dbus_proxy_get_path(proxy); if (g_dbus_proxy_get_property(proxy, "Name", &iter)) dbus_message_iter_get_basic(&iter, &name); else name = ""; /*Log::debug("%s%s%sItem %s %s\n", description ? "[" : "", description ? : "", description ? "] " : "", path, name);*/ } void item_added(GDBusProxy *proxy) { items = g_slist_append(items, proxy); print_item(proxy, COLORED_NEW); } void folder_added(GDBusProxy *proxy) { folders = g_slist_append(folders, proxy); print_folder(proxy, COLORED_NEW); } void proxy_added(GDBusProxy *proxy, void *user_data) { printf("proxy_added \n"); const char *interface; const char interfacestr[128] ; interface = g_dbus_proxy_get_interface(proxy); memset(interfacestr, 0x00, 128); sprintf(interfacestr," interface:%s \n", interface); printf(interfacestr); if (!strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE)) player_added(proxy); else if (!strcmp(interface, BLUEZ_MEDIA_FOLDER_INTERFACE)) folder_added(proxy); else if (!strcmp(interface, BLUEZ_MEDIA_ITEM_INTERFACE)) item_added(proxy); } void player_removed(GDBusProxy *proxy) { print_player(proxy, COLORED_DEL); if (default_player == proxy) default_player = NULL; players = g_slist_remove(players, proxy); } void item_removed(GDBusProxy *proxy) { items = g_slist_remove(items, proxy); print_item(proxy, COLORED_DEL); } void proxy_removed(GDBusProxy *proxy, void *user_data) { printf("proxy_removed \n"); const char *interface; interface = g_dbus_proxy_get_interface(proxy); if (!strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE)) player_removed(proxy); if (!strcmp(interface, BLUEZ_MEDIA_FOLDER_INTERFACE)) folder_removed(proxy); if (!strcmp(interface, BLUEZ_MEDIA_ITEM_INTERFACE)) item_removed(proxy); } void print_iter(const char *label, const char *name, DBusMessageIter *iter) { dbus_bool_t valbool; dbus_uint32_t valu32; dbus_uint16_t valu16; dbus_int16_t vals16; const char *valstr; DBusMessageIter subiter; if (iter == NULL) { //Log::debug("%s%s is nil\n", label, name); return; } switch (dbus_message_iter_get_arg_type(iter)) { case DBUS_TYPE_INVALID: //Log::debug("%s%s is invalid\n", label, name); break; case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: dbus_message_iter_get_basic(iter, &valstr); //Log::debug("%s%s: %s\n", label, name, valstr); break; case DBUS_TYPE_BOOLEAN: dbus_message_iter_get_basic(iter, &valbool); //Log::debug("%s%s: %s\n", label, name, // valbool == TRUE ? "yes" : "no"); break; case DBUS_TYPE_UINT32: dbus_message_iter_get_basic(iter, &valu32); //Log::debug("%s%s: 0x%06x\n", label, name, valu32); break; case DBUS_TYPE_UINT16: dbus_message_iter_get_basic(iter, &valu16); //Log::debug("%s%s: 0x%04x\n", label, name, valu16); break; case DBUS_TYPE_INT16: dbus_message_iter_get_basic(iter, &vals16); //Log::debug("%s%s: %d\n", label, name, vals16); break; case DBUS_TYPE_VARIANT: dbus_message_iter_recurse(iter, &subiter); print_iter(label, name, &subiter); break; case DBUS_TYPE_ARRAY: dbus_message_iter_recurse(iter, &subiter); while (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_INVALID) { print_iter(label, name, &subiter); dbus_message_iter_next(&subiter); } break; case DBUS_TYPE_DICT_ENTRY: dbus_message_iter_recurse(iter, &subiter); dbus_message_iter_get_basic(&subiter, &valstr); dbus_message_iter_next(&subiter); print_iter(label, valstr, &subiter); break; default: //Log::debug("%s%s has unsupported type\n", label, name); break; } } void player_property_changed(GDBusProxy *proxy, const char *name, DBusMessageIter *iter) { char *str; str = proxy_description(proxy, "Player", COLORED_CHG); print_iter(str, name, iter); g_free(str); } void folder_property_changed(GDBusProxy *proxy, const char *name, DBusMessageIter *iter) { char *str; str = proxy_description(proxy, "Folder", COLORED_CHG); print_iter(str, name, iter); g_free(str); } void item_property_changed(GDBusProxy *proxy, const char *name, DBusMessageIter *iter) { char *str; str = proxy_description(proxy, "Item", COLORED_CHG); print_iter(str, name, iter); g_free(str); } void property_changed(GDBusProxy *proxy, const char *name, DBusMessageIter *iter, void *user_data) { printf("property_changed \n"); const char *interface; interface = g_dbus_proxy_get_interface(proxy); if (!strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE)) player_property_changed(proxy, name, iter); else if (!strcmp(interface, BLUEZ_MEDIA_FOLDER_INTERFACE)) folder_property_changed(proxy, name, iter); else if (!strcmp(interface, BLUEZ_MEDIA_ITEM_INTERFACE)) item_property_changed(proxy, name, iter); } bool check_default_player(void) { if (!default_player) { if(NULL != players) { GSList *l; l = players; GDBusProxy *proxy = l->data; default_player = proxy; printf("set default player\n"); return TRUE; } printf("No default player available\n"); return FALSE; } //printf(" player ok\n"); return TRUE; } gboolean option_version = FALSE; GOptionEntry options[] = { { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version, "Show version information and exit" }, { NULL }, }; int init_avrcp() { GError *error = NULL; dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL); if(NULL== dbus_conn){ printf("dbus init fail!"); return -1; } client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez"); if(NULL == client) { printf("client inti fail"); dbus_connection_unref(dbus_conn); return -1; } main_loop = g_main_loop_new(NULL, FALSE); rl_set_prompt(PROMPT_OFF); rl_redisplay(); g_dbus_client_set_connect_watch(client, connect_handler, NULL); g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL); g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed, property_changed, NULL); printf("init ok\n"); g_main_loop_run(main_loop); } int init_avrcp_ctrl() { pthread_t avrcp_thread; pthread_create(&avrcp_thread, NULL, &init_avrcp, NULL); return 1; } int release_avrcp_ctrl() { g_dbus_client_unref(client); dbus_connection_unref(dbus_conn); g_main_loop_unref(main_loop); } void play_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { //rl_printf("Failed to play: %s\n", error.name); dbus_error_free(&error); return; } printf("Play successful\n"); } void play_avrcp(){ if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "Play", NULL, play_reply, NULL, NULL) == FALSE) { printf("Failed to play\n"); return; } printf("Attempting to play\n"); } void pause_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { printf("Failed to pause: %s\n"); dbus_error_free(&error); return; } printf("Pause successful\n"); } void pause_avrcp(){ if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "Pause", NULL, pause_reply, NULL, NULL) == FALSE) { printf("Failed to pause\n"); return; } printf("Attempting to pause\n"); } void stop_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { //rl_printf("Failed to stop: %s\n", error.name); dbus_error_free(&error); return; } printf("Stop successful\n"); } void stop_avrcp(){ if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "Stop", NULL, stop_reply, NULL, NULL) == FALSE) { printf("Failed to stop\n"); return; } printf("Attempting to stop\n"); } void next_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { printf("Failed to jump to next\n"); dbus_error_free(&error); return; } printf("Next successful\n"); } void next_avrcp() { if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "Next", NULL, next_reply, NULL, NULL) == FALSE) { printf("Failed to jump to next\n"); return; } printf("Attempting to jump to next\n"); } void previous_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { //rl_printf("Failed to jump to previous: %s\n", error.name); dbus_error_free(&error); return; } printf("Previous successful\n"); } void previous_avrcp(){ if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "Previous", NULL, previous_reply, NULL, NULL) == FALSE) { printf("Failed to jump to previous\n"); return; } printf("Attempting to jump to previous\n"); } void fast_forward_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { //rl_printf("Failed to fast forward: %s\n", error.name); dbus_error_free(&error); return; } printf("FastForward successful\n"); } void fast_forward_avrcp() { if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "FastForward", NULL, fast_forward_reply, NULL, NULL) == FALSE) { printf("Failed to jump to previous\n"); return; } printf("Fast forward playback\n"); } void rewind_reply(DBusMessage *message, void *user_data) { DBusError error; dbus_error_init(&error); if (dbus_set_error_from_message(&error, message) == TRUE) { //rl_printf("Failed to rewind: %s\n", error.name); dbus_error_free(&error); return; } printf("Rewind successful\n"); } void rewind_avrcp(){ if (!check_default_player()) return; if (g_dbus_proxy_method_call(default_player, "Rewind", NULL, rewind_reply, NULL, NULL) == FALSE) { printf("Failed to rewind\n"); return; } printf("Rewind playback\n"); } int getstatus_avrcp(){ GDBusProxy *proxy; DBusMessageIter iter; const char *valstr; if (check_default_player() == FALSE) return AVRCP_PLAY_STATUS_ERROR; //default player no find proxy = default_player; if (g_dbus_proxy_get_property(proxy, "Status", &iter) == FALSE) return AVRCP_PLAY_STATUS_ERROR; //unkonw status dbus_message_iter_get_basic(&iter, &valstr); if (!strcasecmp(valstr, "stopped")) return AVRCP_PLAY_STATUS_STOPPED; else if (!strcasecmp(valstr, "playing")) return AVRCP_PLAY_STATUS_PLAYING; else if (!strcasecmp(valstr, "paused")) return AVRCP_PLAY_STATUS_PAUSED; else if (!strcasecmp(valstr, "forward-seek")) return AVRCP_PLAY_STATUS_FWD_SEEK; else if (!strcasecmp(valstr, "reverse-seek")) return AVRCP_PLAY_STATUS_REV_SEEK; else if (!strcasecmp(valstr, "error")) return AVRCP_PLAY_STATUS_ERROR; return AVRCP_PLAY_STATUS_ERROR; }