#include "dbus.hpp" #include "log.hpp" const char *DBusAPI::serviceName = "com.experimentalcraft.looper"; const char *DBusAPI::objectPath = "/com/experimentalcraft/looper"; const char *DBusAPI::interfaceName = "com.experimentalcraft.Looper"; DBusAPI::DBusAPI(Playback *playback) { this->playback = playback; connection = sdbus::createSessionBusConnection(serviceName); api = sdbus::createObject(*connection, objectPath); api->registerMethod(interfaceName, "open", "s", "", [this](sdbus::MethodCall call) { std::string filePath; call >> filePath; this->playback->Start(filePath); }); api->registerSignal(interfaceName, "playbackEngineStarted", ""); api->registerSignal(interfaceName, "speedChanged", "d"); api->registerSignal(interfaceName, "tempoChanged", "d"); api->registerSignal(interfaceName, "pitchChanged", "d"); api->registerSignal(interfaceName, "pauseChanged", "b"); api->registerSignal(interfaceName, "stopped", ""); api->registerSignal(interfaceName, "errorOccurred", "s"); api->registerSignal(interfaceName, "seeked", "d"); api->registerSignal(interfaceName, "fileChanged", "s"); api->registerProperty(interfaceName, "speed", "d", [this](sdbus::PropertyGetReply reply) { reply << this->playback->GetSpeed(); }, [this](sdbus::PropertySetCall set_call) { double newValue; set_call >> newValue; this->playback->SetSpeed(newValue); }); api->registerProperty(interfaceName, "tempo", "d", [this](sdbus::PropertyGetReply reply) { reply << this->playback->GetTempo(); }, [this](sdbus::PropertySetCall set_call) { double newValue; set_call >> newValue; this->playback->SetTempo(newValue); }); api->registerProperty(interfaceName, "pitch", "d", [this](sdbus::PropertyGetReply reply) { reply << this->playback->GetPitch(); }, [this](sdbus::PropertySetCall set_call) { double newValue; set_call >> newValue; this->playback->SetPitch(newValue); }); api->registerProperty(interfaceName, "volume", "d", [this](sdbus::PropertyGetReply reply) { reply << this->playback->GetVolume(); }, [this](sdbus::PropertySetCall set_call) { double newValue; set_call >> newValue; this->playback->SetVolume(newValue); }); api->registerMethod(interfaceName, "stop", "", "", [this](sdbus::MethodCall call) { this->playback->Stop(); }); api->registerMethod(interfaceName, "togglePause", "", "", [this](sdbus::MethodCall call) { this->playback->Pause(); }); api->registerProperty(interfaceName, "paused", "b", [this](sdbus::PropertyGetReply reply) { reply << this->playback->IsPaused(); }, [this](sdbus::PropertySetCall call) { bool shouldBePaused; call >> shouldBePaused; this->playback->SetPaused(shouldBePaused); }); api->registerProperty(interfaceName, "stopped", "b", [this](sdbus::PropertyGetReply reply) { reply << this->playback->IsStopped(); }); api->registerMethod(interfaceName, "errorExists", "", "b", [this](sdbus::MethodCall call) { auto reply = call.createReply(); reply << this->playback->ErrorExists(); }); api->registerMethod(interfaceName, "getLastError", "", "s", [this](sdbus::MethodCall call) { auto error = this->playback->GetError(); if (error.has_value()) { auto reply = call.createReply(); reply << error.value(); } else { auto errorReply = call.createErrorReply(sdbus::createError(0, "No error found.")); } }); api->registerProperty(interfaceName, "position", "d", [this](sdbus::PropertyGetReply reply) { reply << this->playback->GetPosition(); }, [this](sdbus::PropertySetCall call) { double value; call >> value; this->playback->Seek(value); }); api->registerProperty(interfaceName, "length", "d", [this](sdbus::PropertyGetReply reply) { reply << this->playback->GetLength(); }); api->registerProperty(interfaceName, "current_file_path", "s", [this](sdbus::PropertyGetReply reply) { auto file_maybe = this->playback->get_current_file(); if (file_maybe.has_value()) { reply << file_maybe.value(); } else { reply << ""; } }); api->registerProperty(interfaceName, "current_file_title", "s", [this](sdbus::PropertyGetReply reply) { auto title_maybe = this->playback->get_current_title(); if (title_maybe.has_value()) { reply << title_maybe.value(); } else { reply << ""; } }); api->finishRegistration(); connection->enterEventLoopAsync(); } bool DBusAPISender::isOnlyInstance() { return !connected; } void DBusAPISender::playFile(std::string file) { if (connected) { auto method = proxy->createMethodCall(DBusAPI::interfaceName, "open"); method.dontExpectReply(); method << file; proxy->callMethod(method); } } void DBusAPISender::setPitch(double value) { if (connected) { proxy->setProperty("pitch").onInterface(DBusAPI::interfaceName).toValue(value); } } void DBusAPISender::setSpeed(double value) { if (connected) { proxy->setProperty("speed").onInterface(DBusAPI::interfaceName).toValue(value); } } void DBusAPISender::setTempo(double value) { if (connected) { proxy->setProperty("tempo").onInterface(DBusAPI::interfaceName).toValue(value); } } double DBusAPISender::getPitch() { if (connected) { return proxy->getProperty("pitch").onInterface(DBusAPI::interfaceName); } else { return -1.0; } } double DBusAPISender::getTempo() { if (connected) { return proxy->getProperty("tempo").onInterface(DBusAPI::interfaceName); } else { return -1.0; } } double DBusAPISender::getSpeed() { if (connected) { return proxy->getProperty("speed").onInterface(DBusAPI::interfaceName); } else { return -1.0; } } DBusAPISender::DBusAPISender() { DEBUG.writeln("Checking and connecting to main instance..."); try { connection = sdbus::createSessionBusConnection(); proxy = sdbus::createProxy(*connection, DBusAPI::serviceName, DBusAPI::objectPath); proxy->finishRegistration(); { auto method = proxy->createMethodCall("org.freedesktop.DBus.Peer", "Ping"); proxy->callMethod(method); } DEBUG.writeln("Main instance found."); } catch (sdbus::Error) { connected = false; DEBUG.writeln("Main instance not found."); } }