diff --git a/Daemon.cpp b/Daemon.cpp index 3cd0efcb..64bb0a2e 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -277,5 +277,5 @@ namespace i2p return true; } - } + } } diff --git a/Daemon.h b/Daemon.h index 7467a518..6f1d3e88 100644 --- a/Daemon.h +++ b/Daemon.h @@ -33,8 +33,7 @@ namespace i2p #if defined(QT_GUI_LIB) // check if QT #define Daemon i2p::util::DaemonQT::Instance() - class DaemonQTImpl; - class DaemonQT: public i2p::util::Daemon_Singleton + class DaemonQT: public i2p::util::Daemon_Singleton { public: @@ -45,12 +44,7 @@ namespace i2p } bool init(int argc, char* argv[]); - void run (); - - private: - - std::shared_ptr m_Impl; - }; + }; #elif defined(_WIN32) #define Daemon i2p::util::DaemonWin32::Instance() diff --git a/FS.cpp b/FS.cpp index 380ab2e5..89cdb7c8 100644 --- a/FS.cpp +++ b/FS.cpp @@ -54,6 +54,9 @@ namespace fs { dataDir = (home != NULL && strlen(home) > 0) ? home : ""; dataDir += "/Library/Application Support/" + appName; return; +#elif defined(ANDROID) + dataDir = "/sdcard/" + appName; // TODO: might not work for some devices + return; #else /* other unix */ char *home = getenv("HOME"); if (isService) { diff --git a/i2pd.cpp b/i2pd.cpp index f3ac6b3f..e6c7abfa 100644 --- a/i2pd.cpp +++ b/i2pd.cpp @@ -1,15 +1,54 @@ -#include -#include "Daemon.h" +#ifndef ANDROID +# include +# include "Daemon.h" +#else +# include "qt/i2pd_qt/i2pd_qt_gui.h" +# include +# include +# include "DaemonQT.h" +# include "mainwindow.h" +# include +#endif int main( int argc, char* argv[] ) { - if (Daemon.init(argc, argv)) +#ifdef ANDROID + //int result = runGUI(argc, argv); + //QMessageBox::information(0,"Debug","runGUI completed"); + QApplication app(argc, argv); + qDebug("Initialising the daemon..."); + bool daemonInitSuccess = i2p::qt::DaemonQTImpl::init(argc, argv); + if(!daemonInitSuccess) { + QMessageBox::critical(0, "Error", "Daemon init failed"); + return 1; + } + qDebug("Initialised, creating the main window..."); + MainWindow w; + qDebug("Before main window.show()..."); + w.show (); + int result; + { + i2p::qt::Controller daemonQtController; + qDebug("Starting the daemon..."); + emit daemonQtController.startDaemon(); + qDebug("Starting gui event loop..."); + result = app.exec(); + //QMessageBox::information(&w, "Debug", "exec finished"); + } + i2p::qt::DaemonQTImpl::deinit(); + //QMessageBox::information(&w, "Debug", "demon stopped"); + //exit(result); //return from main() causes intermittent sigsegv bugs in some Androids. exit() is a workaround for this + qDebug("Exiting the application"); + return result; +#else + if (Daemon.init(argc, argv)) { if (Daemon.start()) Daemon.run (); Daemon.stop(); } return EXIT_SUCCESS; +#endif } #ifdef _WIN32 diff --git a/qt/.gitignore b/qt/.gitignore index e3a93c87..8fe8328a 100644 --- a/qt/.gitignore +++ b/qt/.gitignore @@ -1,2 +1,3 @@ /build-i2pd_qt-Android_armeabi_v7a_GCC_4_9_Qt_5_6_0-Debug/ /build-i2pd_qt-Desktop_Qt_5_6_0_GCC_64bit-Debug/ +/build-i2pd_qt-Android_x86_GCC_4_9_Qt_5_6_0-Debug/ diff --git a/qt/i2pd_qt/DaemonQT.cpp b/qt/i2pd_qt/DaemonQT.cpp index 41242e3b..6cef8133 100644 --- a/qt/i2pd_qt/DaemonQT.cpp +++ b/qt/i2pd_qt/DaemonQT.cpp @@ -1,64 +1,87 @@ -#include -#include "mainwindow.h" -#include -#include +#include "DaemonQT.h" #include "../../Daemon.h" +#include +#include namespace i2p { namespace util { - class DaemonQTImpl: public std::enable_shared_from_this - { - public: - - DaemonQTImpl (int argc, char* argv[]): - m_App (argc, argv) - { - } - - void Run () - { - MainWindow w; - w.show (); - m_App.exec(); - } + bool DaemonQT::init(int argc, char* argv[]) + { + return Daemon_Singleton::init(argc, argv); + } +} +} - private: +namespace i2p +{ +namespace qt +{ - void StartDaemon () - { - Daemon.start (); - } + void Worker::startDaemon() { + qDebug("Performing daemon start..."); + DaemonQTImpl::start(); + qDebug("Daemon started."); + emit resultReady(); + } + void Worker::restartDaemon() { + qDebug("Performing daemon restart..."); + DaemonQTImpl::restart(); + qDebug("Daemon restarted."); + emit resultReady(); + } + void Worker::stopDaemon() { + qDebug("Performing daemon stop..."); + DaemonQTImpl::stop(); + qDebug("Daemon stopped."); + emit resultReady(); + } - void StopDaemon () - { - Daemon.stop (); - } + Controller::Controller() { + Worker *worker = new Worker; + worker->moveToThread(&workerThread); + connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); + connect(this, &Controller::startDaemon, worker, &Worker::startDaemon); + connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon); + connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon); + connect(worker, &Worker::resultReady, this, &Controller::handleResults); + workerThread.start(); + } + Controller::~Controller() { + qDebug("Closing and waiting for daemon worker thread..."); + workerThread.quit(); + workerThread.wait(); + qDebug("Waiting for daemon worker thread finished."); + if(DaemonQTImpl::isRunning()) { + qDebug("Stopping the daemon..."); + DaemonQTImpl::stop(); + qDebug("Stopped the daemon."); + } + } - bool IsRunning () const - { - return Daemon.running; - } - private: - QApplication m_App; - }; + static DaemonQTImpl::runningChangedCallback DaemonQTImpl_runningChanged; + static bool DaemonQTImpl_running; + static QMutex* mutex; - bool DaemonQT::init(int argc, char* argv[]) - { - m_Impl = std::make_shared (argc, argv); - return Daemon_Singleton::init(argc, argv); - } + bool DaemonQTImpl::init(int argc, char* argv[]){mutex=new QMutex(QMutex::Recursive);setRunningCallback(0);DaemonQTImpl_running=false;return Daemon.init(argc,argv);} + void DaemonQTImpl::deinit(){delete mutex;} + void DaemonQTImpl::start(){QMutexLocker locker(mutex);setRunning(true);Daemon.start();} + void DaemonQTImpl::stop(){QMutexLocker locker(mutex);Daemon.stop();setRunning(false);} + void DaemonQTImpl::restart(){QMutexLocker locker(mutex);stop();start();} - void DaemonQT::run () - { - if (m_Impl) - { - m_Impl->Run (); - m_Impl = nullptr; + void DaemonQTImpl::setRunningCallback(runningChangedCallback cb){DaemonQTImpl_runningChanged=cb;} + bool DaemonQTImpl::isRunning(){return DaemonQTImpl_running;} + void DaemonQTImpl::setRunning(bool newValue){ + bool oldValue = DaemonQTImpl_running; + if(oldValue!=newValue) { + DaemonQTImpl_running = newValue; + if(DaemonQTImpl_runningChanged!=0)DaemonQTImpl_runningChanged(); } - } +} + } } + diff --git a/qt/i2pd_qt/DaemonQT.h b/qt/i2pd_qt/DaemonQT.h new file mode 100644 index 00000000..d76ed531 --- /dev/null +++ b/qt/i2pd_qt/DaemonQT.h @@ -0,0 +1,63 @@ +#ifndef DAEMONQT_H +#define DAEMONQT_H + +#include +#include + +namespace i2p +{ +namespace qt +{ + class Worker : public QObject + { + Q_OBJECT + + public slots: + void startDaemon(); + void restartDaemon(); + void stopDaemon(); + + signals: + void resultReady(); + }; + + class DaemonQTImpl + { + public: + typedef void (*runningChangedCallback)(); + + /** + * @brief init + * @param argc + * @param argv + * @return success + */ + bool static init(int argc, char* argv[]); + void static deinit(); + void static start(); + void static stop(); + void static restart(); + void static setRunningCallback(runningChangedCallback cb); + bool static isRunning(); + private: + void static setRunning(bool running); + }; + + class Controller : public QObject + { + Q_OBJECT + QThread workerThread; + public: + Controller(); + ~Controller(); + public slots: + void handleResults(){} + signals: + void startDaemon(); + void stopDaemon(); + void restartDaemon(); + }; +} +} + +#endif // DAEMONQT_H diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 603776e7..73f6eb6d 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,6 +1,6 @@ - + @@ -46,7 +46,7 @@ - +