static jboolean discoverServicesNative(JNIEnv *env, jobject object, jstring path, jstring pattern) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_path = env->GetStringUTFChars(path, NULL); const char *c_pattern = env->GetStringUTFChars(pattern, NULL); int len = env->GetStringLength(path) + 1; char *context_path = (char *)calloc(len, sizeof(char)); strlcpy(context_path, c_path, len); // for callback LOGV("... Object Path = %s", c_path); LOGV("... Pattern = %s, strlen = %d", c_pattern, strlen(c_pattern)); bool ret = dbus_func_args_async(env, nat->conn, -1, onDiscoverServicesResult, context_path, eventLoopNat, c_path, DBUS_DEVICE_IFACE, "DiscoverServices", DBUS_TYPE_STRING, &c_pattern, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); env->ReleaseStringUTFChars(pattern, c_pattern); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean disconnectSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); size_t path_sz = env->GetStringUTFLength(path) + 1; char *c_path_copy = (char *)malloc(path_sz); // callback data strncpy(c_path_copy, c_path, path_sz); bool ret = dbus_func_args_async(env, nat->conn, -1, onDisconnectSinkResult, (void *)c_path_copy, nat, c_path, "org.bluez.audio.Sink", "Disconnect", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); if (!ret) { free(c_path_copy); return JNI_FALSE; } return JNI_TRUE; } #endif return JNI_FALSE; }
static jboolean createDeviceNative(JNIEnv *env, jobject object, jstring address) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_address = env->GetStringUTFChars(address, NULL); LOGV("... address = %s", c_address); char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); strlcpy(context_address, c_address, BTADDR_SIZE); // for callback bool ret = dbus_func_args_async(env, nat->conn, -1, onCreateDeviceResult, context_address, eventLoopNat, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "CreateDevice", DBUS_TYPE_STRING, &c_address, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(address, c_address); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object, jstring address, jint timeout_ms) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_address = env->GetStringUTFChars(address, NULL); LOGV("... address = %s", c_address); char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); const char *capabilities = "DisplayYesNo"; const char *agent_path = "/android/bluetooth/remote_device_agent"; strlcpy(context_address, c_address, BTADDR_SIZE); // for callback bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, onCreatePairedDeviceResult, // callback context_address, eventLoopNat, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "CreatePairedDeviceOutOfBand", DBUS_TYPE_STRING, &c_address, DBUS_TYPE_OBJECT_PATH, &agent_path, DBUS_TYPE_STRING, &capabilities, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(address, c_address); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean sendMetaDataNative(JNIEnv *env, jobject obj, jstring path) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { jstring title, artist, album, media_number, total_media_count, playing_time; jstring genre; const char *c_title, *c_artist, *c_album, *c_media_number, *c_genre; const char *c_total_media_count, *c_playing_time; const char *c_path = env->GetStringUTFChars(path, NULL); title = (jstring) env->GetObjectField(obj, field_mTrackName); artist = (jstring) env->GetObjectField(obj, field_mArtistName); album = (jstring) env->GetObjectField(obj, field_mAlbumName); media_number = (jstring) env->GetObjectField(obj, field_mMediaNumber); total_media_count = (jstring) env->GetObjectField(obj, field_mMediaCount); playing_time = (jstring) env->GetObjectField(obj, field_mDuration); genre = (jstring) env->GetObjectField(obj, field_mGenre); c_title = env->GetStringUTFChars(title, NULL); c_artist = env->GetStringUTFChars(artist, NULL); c_album = env->GetStringUTFChars(album, NULL); c_media_number = env->GetStringUTFChars(media_number, NULL); c_total_media_count = env->GetStringUTFChars(total_media_count, NULL); c_playing_time = env->GetStringUTFChars(playing_time, NULL); c_genre = env->GetStringUTFChars(genre, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, onStatusReply, NULL, nat, c_path, "org.bluez.Control", "UpdateMetaData", DBUS_TYPE_STRING, &c_title, DBUS_TYPE_STRING, &c_artist, DBUS_TYPE_STRING, &c_album, DBUS_TYPE_STRING, &c_media_number, DBUS_TYPE_STRING, &c_total_media_count, DBUS_TYPE_STRING, &c_playing_time, DBUS_TYPE_STRING, &c_genre, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); env->ReleaseStringUTFChars(title, c_title); env->ReleaseStringUTFChars(artist, c_artist); env->ReleaseStringUTFChars(album, c_album); env->ReleaseStringUTFChars(media_number, c_media_number); env->ReleaseStringUTFChars(total_media_count, c_total_media_count); env->ReleaseStringUTFChars(playing_time, c_playing_time); env->ReleaseStringUTFChars(genre, c_genre); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, c_path, "org.bluez.Control", "VolumeDown", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean suspendSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH LOGV("%s", __FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, c_path, "org.bluez.audio.Sink", "Suspend", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean disconnectInputNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); LOGV("DBUS call disconnectInputNative \n"); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, c_path, "org.bluez.Input", "Disconnect", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean sendEventNative(JNIEnv *env, jobject object, jstring path, jint event_id, jlong data) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, onStatusReply, NULL, nat, c_path, "org.bluez.Control", "UpdateNotification", DBUS_TYPE_UINT16, &event_id, DBUS_TYPE_UINT64, &data, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean sendPlayStatusNative(JNIEnv *env, jobject object, jstring path, jint duration, jint position, jint play_status) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, onStatusReply, NULL, nat, c_path, "org.bluez.Control", "UpdatePlayStatus", DBUS_TYPE_UINT32, &duration, DBUS_TYPE_UINT32, &position, DBUS_TYPE_UINT32, &play_status, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); int len = env->GetStringLength(path) + 1; char *context_path = (char *)calloc(len, sizeof(char)); strlcpy(context_path, c_path, len); // for callback bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, context_path, nat, c_path, "org.bluez.AudioSink", "Connect", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }
static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { const char *c_object_path = env->GetStringUTFChars(object_path, NULL); bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, NULL, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "RemoveDevice", DBUS_TYPE_OBJECT_PATH, &c_object_path, DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(object_path, c_object_path); return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; }