Something went wrong. Try again.
Mixxx DJ software with MCP, Subsonic/Navidrome streaming library support — browse and load tracks from your self-hosted music server mixxx.org
subsonic navidrome streaming audio dj mac linux midi
Something went wrong. Try again.
4.8 kB · 129 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130#include "android.h"
#include <android/api-level.h>#include <android/log.h>#include <qjnitypes.h>
#include <QtJniTypes>#include <cstddef>
namespace mixxx {namespace android {std::mutex s_androidLock = {};std::condition_variable s_grantingWaitCond = {};std::vector<std::pair<QJniObject, bool>> s_grantingResult = {};QJniObject s_intent = {};QJniObject s_usbManager = {};
const QJniObject& getIntent() { __android_log_print(ANDROID_LOG_VERBOSE, "mixxx", "about to get intent"); std::unique_lock lock(s_androidLock); if (s_intent.isValid()) { return s_intent; } // QNativeInterface::QAndroidApplication::runOnAndroidMainThread([]() { if (!QNativeInterface::QAndroidApplication::isActivityContext()) { __android_log_print(ANDROID_LOG_WARN, "mixxx", "current context doesn't refer to an activity!"); }
QJniObject context = QNativeInterface::QAndroidApplication::context();
s_usbManager = QJniObject("org/mixxx/UsbPermission"); jint FLAG_IMMUTABLE = QJniObject::getStaticField<jint>( "android/app/PendingIntent", "FLAG_IMMUTABLE"); QtJniTypes::String ACTION_USB_PERMISSION = QJniObject::fromString("org.mixxx.permissions.USB_PERMISSION"); QtJniTypes::Intent intent = QJniObject("android/content/Intent", "(Ljava/lang/String;)V", ACTION_USB_PERMISSION.object<jstring>()); if (!intent.isValid()) { __android_log_print(ANDROID_LOG_WARN, "mixxx", "pending intent is invalid!"); } s_intent = QJniObject::callStaticMethod<jobject>("android/app/PendingIntent", "getBroadcast", "(Landroid/content/Context;ILandroid/content/" "Intent;I)Landroid/app/PendingIntent;", context, 0, intent, FLAG_IMMUTABLE);
if (!s_intent.isValid()) { __android_log_print(ANDROID_LOG_WARN, "mixxx", "pending intent is invalid!"); }
__android_log_print(ANDROID_LOG_VERBOSE, "mixxx", "about to register the the receiver %d", s_usbManager.isValid()); auto success = s_usbManager.callMethod<jboolean>("registerServiceBroadcastReceiver", "(Landroid/content/Context;)Z", context.object<jobject>()); if (!success) { __android_log_print(ANDROID_LOG_WARN, "mixxx", "failed to registered the receiver!"); } // }); return s_intent;}
bool waitForPermission(const QJniObject& device) { __android_log_print(ANDROID_LOG_VERBOSE, "mixxx", "about to wait for perm"); std::unique_lock lock(s_androidLock); std::vector<std::pair<QJniObject, bool>>::const_iterator result = s_grantingResult.cend();
int retries = 0;
while (!s_grantingWaitCond.wait_for( lock, std::chrono::seconds(1), [&result, device] { result = std::find_if(s_grantingResult.cbegin(), s_grantingResult.cend(), [device](auto resultPair) { return resultPair.first == device; }); return result != s_grantingResult.cend(); })) { __android_log_print(ANDROID_LOG_VERBOSE, "mixxx", "Not found - current result count: %lu", s_grantingResult.size()); QCoreApplication::processEvents(); retries++; if (retries >= 10) { __android_log_print(ANDROID_LOG_WARN, "mixxx", "wait for perm timeout"); qWarning() << "Timeout reached when waiting for Android permission to USB device"; return false; } } __android_log_print(ANDROID_LOG_VERBOSE, "mixxx", "got perm result"); return result->second;}
void usbDeviceAccessResult(QJniObject device, bool granted) { std::unique_lock lock(s_androidLock); __android_log_print(ANDROID_LOG_WARN, "mixxx", "received permission result: %d", granted); s_grantingResult.push_back(std::make_pair<>(device, granted)); s_grantingWaitCond.notify_one(); // FIXME Handle large list?}} // namespace android} // namespace mixxx
Q_DECLARE_JNI_CLASS(UsbPermissionClass, "org/mixxx/UsbPermission")
void usbDeviceAccessResult(JNIEnv*, jobject, jobject device, jboolean granted) { mixxx::android::usbDeviceAccessResult(device, granted);}Q_DECLARE_JNI_NATIVE_METHOD(usbDeviceAccessResult)
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM*, void*) { QJniEnvironment env; env.registerNativeMethods<QtJniTypes::UsbPermissionClass>({ Q_JNI_NATIVE_METHOD(usbDeviceAccessResult), }); return JNI_VERSION_1_6;}