summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>2009-10-23 18:00:20 +0200
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>2009-10-23 18:00:20 +0200
commit1af61fefa8f22932cc0db0559782ec11b0e39fd0 (patch)
tree0c582cc87579edd7bc9eae2f41aa8889494541fc
parentd35dcd8dbef7e5dc6f2d87870267231f99379082 (diff)
downloadqt-creator-1af61fefa8f22932cc0db0559782ec11b0e39fd0.tar.gz
S60: Add startup logic for Bluetooth to the project/run configuration
Prepare trk::Launcher to deal with a shared trkdevice. Add encapsulation for the rfcomm listener process and helper classes for prompting the user to connect the Bluetooth device. Add a command line prompt to the trklauncher test.
-rw-r--r--src/plugins/coreplugin/messagemanager.cpp11
-rw-r--r--src/plugins/coreplugin/messagemanager.h4
-rw-r--r--src/plugins/debugger/gdb/gdb.pri2
-rw-r--r--src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp51
-rw-r--r--src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h55
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/qt-s60.pri8
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp17
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp24
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp52
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h53
-rw-r--r--src/shared/trk/bluetoothlistener.cpp383
-rw-r--r--src/shared/trk/bluetoothlistener.h174
-rw-r--r--src/shared/trk/bluetoothlistener_gui.cpp74
-rw-r--r--src/shared/trk/bluetoothlistener_gui.h58
-rw-r--r--src/shared/trk/launcher.cpp112
-rw-r--r--src/shared/trk/launcher.h13
-rw-r--r--src/shared/trk/trk.pri19
-rw-r--r--tests/manual/trklauncher/main.cpp103
-rw-r--r--tests/manual/trklauncher/trklauncher.pro2
19 files changed, 1132 insertions, 83 deletions
diff --git a/src/plugins/coreplugin/messagemanager.cpp b/src/plugins/coreplugin/messagemanager.cpp
index 6252d119d4..7ff9cee01c 100644
--- a/src/plugins/coreplugin/messagemanager.cpp
+++ b/src/plugins/coreplugin/messagemanager.cpp
@@ -82,3 +82,14 @@ void MessageManager::printToOutputPane(const QString &text, bool bringToForegrou
m_messageOutputWindow->popup(false);
m_messageOutputWindow->append(text);
}
+
+void MessageManager::printToOutputPanePopup(const QString &text)
+{
+ printToOutputPane(text, true);
+}
+
+void MessageManager::printToOutputPane(const QString &text)
+{
+ printToOutputPane(text, false);
+}
+
diff --git a/src/plugins/coreplugin/messagemanager.h b/src/plugins/coreplugin/messagemanager.h
index 664269cda6..4191145cd8 100644
--- a/src/plugins/coreplugin/messagemanager.h
+++ b/src/plugins/coreplugin/messagemanager.h
@@ -55,7 +55,9 @@ public:
void showOutputPane();
public slots:
- void printToOutputPane(const QString &text, bool bringToForeground = true);
+ void printToOutputPane(const QString &text, bool bringToForeground);
+ void printToOutputPanePopup(const QString &text); // pops up
+ void printToOutputPane(const QString &text);
private:
Internal::MessageOutputWindow *m_messageOutputWindow;
diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri
index e7763cecb6..19f453ba7d 100644
--- a/src/plugins/debugger/gdb/gdb.pri
+++ b/src/plugins/debugger/gdb/gdb.pri
@@ -19,6 +19,7 @@ HEADERS += \
$$PWD/termgdbadapter.h \
$$PWD/remotegdbadapter.h \
$$PWD/trkgdbadapter.h \
+ $$PWD/s60debuggerbluetoothstarter.h
SOURCES += \
$$PWD/gdbmi.cpp \
@@ -34,6 +35,7 @@ SOURCES += \
$$PWD/termgdbadapter.cpp \
$$PWD/remotegdbadapter.cpp \
$$PWD/trkgdbadapter.cpp \
+ $$PWD/s60debuggerbluetoothstarter.cpp
FORMS += $$PWD/gdboptionspage.ui \
$$PWD/trkoptionswidget.ui
diff --git a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp
new file mode 100644
index 0000000000..b1d34f4ff3
--- /dev/null
+++ b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.cpp
@@ -0,0 +1,51 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "s60debuggerbluetoothstarter.h"
+#include "debuggermanager.h"
+
+namespace Debugger {
+namespace Internal {
+
+S60DebuggerBluetoothStarter::S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent) :
+ trk::AbstractBluetoothStarter(trkDevice, parent)
+{
+}
+
+trk::BluetoothListener *S60DebuggerBluetoothStarter::createListener()
+{
+ DebuggerManager *dm = DebuggerManager::instance();
+ trk::BluetoothListener *rc = new trk::BluetoothListener(dm);
+ rc->setMode(trk::BluetoothListener::Listen);
+ connect(rc, SIGNAL(message(QString)), dm, SLOT(showDebuggerOutput(QString)));
+ return rc;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h
new file mode 100644
index 0000000000..216ab80a4b
--- /dev/null
+++ b/src/plugins/debugger/gdb/s60debuggerbluetoothstarter.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef S60DEBUGGERBLUETOOTHSTARTER_H
+#define S60DEBUGGERBLUETOOTHSTARTER_H
+
+#include "bluetoothlistener.h"
+
+namespace Debugger {
+namespace Internal {
+
+/* S60DebuggerBluetoothStarter: Creates a listener in 'Listen' mode
+ * parented on the Debugger manager which outputs to the debugger window.
+ * Note: This is a "last resort" starter, normally, the run configuration
+ * should have already started a listener. */
+
+class S60DebuggerBluetoothStarter : public trk::AbstractBluetoothStarter
+{
+public:
+ explicit S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+
+protected:
+ virtual trk::BluetoothListener *createListener();
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // S60DEBUGGERBLUETOOTHSTARTER_H
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
index 8a445fa8de..c1f2e85765 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
+++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
@@ -10,7 +10,9 @@
$$PWD/s60devicerunconfiguration.cpp \
$$PWD/s60devicerunconfigurationwidget.cpp \
$$PWD/serialdevicelister.cpp \
- $$PWD/rvcttoolchain.cpp
+ $$PWD/rvcttoolchain.cpp \
+ $$PWD/s60runconfigbluetoothstarter.cpp
+
HEADERS += $$PWD/s60devices.h \
$$PWD/s60devicespreferencepane.h \
$$PWD/s60manager.h \
@@ -20,7 +22,9 @@
$$PWD/s60devicerunconfiguration.h \
$$PWD/s60devicerunconfigurationwidget.h \
$$PWD/serialdevicelister.h \
- $$PWD/rvcttoolchain.h
+ $$PWD/rvcttoolchain.h \
+ $$PWD/s60runconfigbluetoothstarter.h
+
FORMS += $$PWD/s60devicespreferencepane.ui
OTHER_FILES += $$PWD/qt-s60-todo.txt
include(../../../shared/trk/trk.pri)||error("could not include trk.pri")
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index 64b1ee120c..9ab5d93b3b 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -34,6 +34,8 @@
#include "profilereader.h"
#include "s60manager.h"
#include "s60devices.h"
+#include "s60runconfigbluetoothstarter.h"
+#include "bluetoothlistener_gui.h"
#include "serialdevicelister.h"
#include <coreplugin/icore.h>
@@ -572,6 +574,21 @@ void S60DeviceRunControlBase::signsisProcessFinished()
initLauncher(runFileName, m_launcher);
emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(copySrc), m_serialPortFriendlyName));
QString errorMessage;
+ // Prompt the user to start up the Blue tooth connection
+ if (m_communicationType == BlueToothCommunication) {
+ S60RunConfigBluetoothStarter starter(m_launcher->trkDevice());
+ switch (trk::startBluetoothGui(starter, 0, &errorMessage)) {
+ case trk::BluetoothGuiConnected:
+ break;
+ case trk::BluetoothGuiCanceled:
+ case trk::BluetoothGuiError:
+ delete m_launcher;
+ m_launcher = 0;
+ error(this, errorMessage);
+ emit finished();
+ return;
+ };
+ }
if (!m_launcher->startServer(&errorMessage)) {
delete m_launcher;
m_launcher = 0;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
index c0964e6fbb..71369923ab 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
@@ -29,8 +29,12 @@
#include "s60devicerunconfigurationwidget.h"
#include "s60devicerunconfiguration.h"
+#include "s60runconfigbluetoothstarter.h"
+#include "bluetoothlistener_gui.h"
#include "s60manager.h"
#include "launcher.h"
+#include "bluetoothlistener.h"
+#include "bluetoothlistener_gui.h"
#include "serialdevicelister.h"
#include <utils/detailswidget.h>
@@ -278,6 +282,7 @@ void S60DeviceRunConfigurationWidget::setDeviceInfoLabel(const QString &message,
QString(QLatin1String("background-color: red;")) :
QString());
m_deviceInfoLabel->setText(message);
+ m_deviceInfoLabel->adjustSize();
}
void S60DeviceRunConfigurationWidget::updateDeviceInfo()
@@ -290,12 +295,29 @@ void S60DeviceRunConfigurationWidget::updateDeviceInfo()
bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
{
+ message->clear();
// Do a launcher run with the ping protocol. Instantiate launcher on heap
// as not to introduce delays when destructing a device with timeout
- trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, this);
+ trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, QSharedPointer<trk::TrkDevice>(), this);
const CommunicationDevice commDev = currentDevice();
launcher->setSerialFrame(commDev.type == SerialPortCommunication);
launcher->setTrkServerName(commDev.portName);
+ // Prompt the user to start
+ if (commDev.type == BlueToothCommunication) {
+ S60RunConfigBluetoothStarter starter(launcher->trkDevice());
+ starter.setDevice(launcher->trkServerName());
+ const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, this, message);
+ switch (src) {
+ case trk::BluetoothGuiConnected:
+ break;
+ case trk::BluetoothGuiCanceled:
+ launcher->deleteLater();
+ return true;
+ case trk::BluetoothGuiError:
+ launcher->deleteLater();
+ return false;
+ };
+ }
if (!launcher->startServer(message)) {
launcher->deleteLater();
return false;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
new file mode 100644
index 0000000000..305d917597
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.cpp
@@ -0,0 +1,52 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "s60runconfigbluetoothstarter.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+S60RunConfigBluetoothStarter::S60RunConfigBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent) :
+ trk::AbstractBluetoothStarter(trkDevice, parent)
+{
+}
+
+trk::BluetoothListener *S60RunConfigBluetoothStarter::createListener()
+{
+ Core::ICore *core = Core::ICore::instance();
+ trk::BluetoothListener *rc = new trk::BluetoothListener(core);
+ rc->setMode(trk::BluetoothListener::Listen);
+ connect(rc, SIGNAL(message(QString)), core->messageManager(), SLOT(printToOutputPane(QString)));
+ return rc;
+}
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
new file mode 100644
index 0000000000..340f74082f
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/s60runconfigbluetoothstarter.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef S60RUNCONFIGBLUETOOTHSTARTER_H
+#define S60RUNCONFIGBLUETOOTHSTARTER_H
+
+#include "bluetoothlistener.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+/* S60RunConfigBluetoothStarter: Creates a listener in 'Listen' mode
+ * parented on the Qt Creator core which outputs to the message manager. */
+
+class S60RunConfigBluetoothStarter : public trk::AbstractBluetoothStarter
+{
+public:
+ explicit S60RunConfigBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+
+protected:
+ virtual trk::BluetoothListener *createListener();
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // S60RUNCONFIGBLUETOOTHSTARTER_H
diff --git a/src/shared/trk/bluetoothlistener.cpp b/src/shared/trk/bluetoothlistener.cpp
new file mode 100644
index 0000000000..b395131ad3
--- /dev/null
+++ b/src/shared/trk/bluetoothlistener.cpp
@@ -0,0 +1,383 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "bluetoothlistener.h"
+#include "trkdevice.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+#include <QtCore/QEventLoop>
+
+#ifdef Q_OS_UNIX
+# include <unistd.h>
+# include <signal.h>
+#endif
+
+enum { debug = 0 };
+
+namespace trk {
+
+struct BluetoothListenerPrivate {
+ BluetoothListenerPrivate();
+ QString device;
+ QProcess process;
+ Q_PID pid;
+ bool printConsoleMessages;
+ BluetoothListener::Mode mode;
+};
+
+BluetoothListenerPrivate::BluetoothListenerPrivate() :
+ pid(0),
+ printConsoleMessages(false),
+ mode(BluetoothListener::Listen)
+{
+}
+
+BluetoothListener::BluetoothListener(QObject *parent) :
+ QObject(parent),
+ d(new BluetoothListenerPrivate)
+{
+ d->process.setProcessChannelMode(QProcess::MergedChannels);
+
+ connect(&d->process, SIGNAL(readyReadStandardError()),
+ this, SLOT(slotStdError()));
+ connect(&d->process, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(slotStdOutput()));
+ connect(&d->process, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
+ connect(&d->process, SIGNAL(error(QProcess::ProcessError)),
+ this, SLOT(slotProcessError(QProcess::ProcessError)));
+}
+
+BluetoothListener::~BluetoothListener()
+{
+ const int trc = terminateProcess();
+ if (debug)
+ qDebug() << "~BluetoothListener: terminated" << trc;
+ delete d;
+}
+
+BluetoothListener::Mode BluetoothListener::mode() const
+{
+ return d->mode;
+}
+
+void BluetoothListener::setMode(Mode m)
+{
+ d->mode = m;
+}
+
+bool BluetoothListener::printConsoleMessages() const
+{
+ return d->printConsoleMessages;
+}
+
+void BluetoothListener::setPrintConsoleMessages(bool p)
+{
+ d->printConsoleMessages = p;
+}
+
+int BluetoothListener::terminateProcess()
+{
+ enum { TimeOutMS = 200 };
+ if (debug)
+ qDebug() << "terminateProcess" << d->process.pid() << d->process.state();
+ if (d->process.state() == QProcess::NotRunning)
+ return -1;
+ emitMessage(tr("%1: Stopping listener %2...").arg(d->device).arg(d->process.pid()));
+ // When listening, the process should terminate by itself after closing the connection
+ if (mode() == Listen && d->process.waitForFinished(TimeOutMS))
+ return 0;
+#ifdef Q_OS_UNIX
+ kill(d->process.pid(), SIGHUP); // Listens for SIGHUP
+ if (d->process.waitForFinished(TimeOutMS))
+ return 1;
+#endif
+ d->process.terminate();
+ if (d->process.waitForFinished(TimeOutMS))
+ return 2;
+ d->process.kill();
+ return 3;
+}
+
+bool BluetoothListener::start(const QString &device, QString *errorMessage)
+{
+ if (d->process.state() != QProcess::NotRunning) {
+ *errorMessage = QLatin1String("Internal error: Still running.");
+ return false;
+ }
+ d->device = device;
+ const QString binary = QLatin1String("rfcomm");
+ QStringList arguments;
+ arguments << QLatin1String("-r")
+ << (d->mode == Listen ? QLatin1String("listen") : QLatin1String("watch"))
+ << device << QString(QLatin1Char('1'));
+ if (debug)
+ qDebug() << binary << arguments;
+ emitMessage(tr("%1: Starting Bluetooth listener %2...").arg(device, binary));
+ d->pid = 0;
+ d->process.start(binary, arguments);
+ if (!d->process.waitForStarted()) {
+ *errorMessage = tr("Unable to run '%1': %2").arg(binary, d->process.errorString());
+ return false;
+ }
+ d->pid = d->process.pid(); // Forgets it after crash/termination
+ emitMessage(tr("%1: Bluetooth listener running (%2).").arg(device).arg(d->process.pid()));
+ return true;
+}
+
+void BluetoothListener::slotStdOutput()
+{
+ emitMessage(QString::fromLocal8Bit(d->process.readAllStandardOutput()));
+}
+
+void BluetoothListener::emitMessage(const QString &m)
+{
+ if (d->printConsoleMessages || debug)
+ qDebug("%s\n", qPrintable(m));
+ emit message(m);
+}
+
+void BluetoothListener::slotStdError()
+{
+ emitMessage(QString::fromLocal8Bit(d->process.readAllStandardError()));
+}
+
+void BluetoothListener::slotProcessFinished(int ex, QProcess::ExitStatus state)
+{
+ switch (state) {
+ case QProcess::NormalExit:
+ emitMessage(tr("%1: Process %2 terminated with exit code %3.")
+ .arg(d->device).arg(d->pid).arg(ex));
+ break;
+ case QProcess::CrashExit:
+ emitMessage(tr("%1: Process %2 crashed.").arg(d->device).arg(d->pid));
+ break;
+ }
+ emit terminated();
+}
+
+void BluetoothListener::slotProcessError(QProcess::ProcessError error)
+{
+ emitMessage(tr("%1: Process error %2: %3")
+ .arg(d->device).arg(error).arg(d->process.errorString()));
+}
+
+// --------------- AbstractBluetoothStarter
+struct AbstractBluetoothStarterPrivate {
+ explicit AbstractBluetoothStarterPrivate(const AbstractBluetoothStarter::TrkDevicePtr &d);
+
+ const AbstractBluetoothStarter::TrkDevicePtr trkDevice;
+ BluetoothListener *listener;
+ QTimer *timer;
+ int intervalMS;
+ int attempts;
+ int n;
+ QString device;
+ QString errorString;
+ AbstractBluetoothStarter::State state;
+};
+
+AbstractBluetoothStarterPrivate::AbstractBluetoothStarterPrivate(const AbstractBluetoothStarter::TrkDevicePtr &d) :
+
+ trkDevice(d),
+ listener(0),
+ timer(0),
+ intervalMS(1000),
+ attempts(-1),
+ n(0),
+ device(QLatin1String("/dev/rfcomm0")),
+ state(AbstractBluetoothStarter::TimedOut)
+{
+}
+
+AbstractBluetoothStarter::AbstractBluetoothStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
+ QObject(parent),
+ d(new AbstractBluetoothStarterPrivate(trkDevice))
+{
+}
+
+AbstractBluetoothStarter::~AbstractBluetoothStarter()
+{
+ stopTimer();
+ delete d;
+}
+
+void AbstractBluetoothStarter::stopTimer()
+{
+ if (d->timer && d->timer->isActive())
+ d->timer->stop();
+}
+
+AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start()
+{
+ if (state() == Running) {
+ d->errorString = QLatin1String("Internal error, attempt to re-start AbstractBluetoothStarter.\n");
+ return StartError;
+ }
+ // Before we instantiate timers, and such, try to open the device,
+ // which should succeed if another listener is already running in
+ // 'Watch' mode
+ if (d->trkDevice->open(d->device , &(d->errorString)))
+ return ConnectionSucceeded;
+ // Fire up the listener
+ d->n = 0;
+ d->listener = createListener();
+ if (!d->listener->start(d->device, &(d->errorString)))
+ return StartError;
+ // Start timer
+ if (!d->timer) {
+ d->timer = new QTimer;
+ connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimer()));
+ }
+ d->timer->setInterval(d->intervalMS);
+ d->timer->setSingleShot(false);
+ d->timer->start();
+ d->state = Running;
+ return Started;
+}
+
+AbstractBluetoothStarter::State AbstractBluetoothStarter::state() const
+{
+ return d->state;
+}
+
+int AbstractBluetoothStarter::intervalMS() const
+{
+ return d->intervalMS;
+}
+
+void AbstractBluetoothStarter::setIntervalMS(int i)
+{
+ d->intervalMS = i;
+ if (d->timer)
+ d->timer->setInterval(i);
+}
+
+int AbstractBluetoothStarter::attempts() const
+{
+ return d->attempts;
+}
+
+void AbstractBluetoothStarter::setAttempts(int a)
+{
+ d->attempts = a;
+}
+
+QString AbstractBluetoothStarter::device() const
+{
+ return d->device;
+}
+
+void AbstractBluetoothStarter::setDevice(const QString &dv)
+{
+ d->device = dv;
+}
+
+QString AbstractBluetoothStarter::errorString() const
+{
+ return d->errorString;
+}
+
+void AbstractBluetoothStarter::slotTimer()
+{
+ ++d->n;
+ // Check for timeout
+ if (d->attempts >= 0 && d->n >= d->attempts) {
+ stopTimer();
+ d->errorString = tr("%1: timed out after %n attempts using an interval of %2ms.", 0, d->n)
+ .arg(d->device).arg(d->intervalMS);
+ d->state = TimedOut;
+ emit timeout();
+ } else {
+ // Attempt n to connect?
+ if (d->trkDevice->open(d->device , &(d->errorString))) {
+ stopTimer();
+ const QString msg = tr("%1: Connection attempt %2 succeeded.").arg(d->device).arg(d->n);
+ d->listener->emitMessage(msg);
+ d->state = Connected;
+ emit connected();
+ } else {
+ const QString msg = tr("%1: Connection attempt %2 failed: %3 (retrying)...")
+ .arg(d->device).arg(d->n).arg(d->errorString);
+ d->listener->emitMessage(msg);
+ }
+ }
+}
+
+// -------- ConsoleBluetoothStarter
+ConsoleBluetoothStarter::ConsoleBluetoothStarter(const TrkDevicePtr &trkDevice,
+ QObject *listenerParent,
+ QObject *parent) :
+ AbstractBluetoothStarter(trkDevice, parent),
+ m_listenerParent(listenerParent)
+{
+}
+
+BluetoothListener *ConsoleBluetoothStarter::createListener()
+{
+ BluetoothListener *rc = new BluetoothListener(m_listenerParent);
+ rc->setMode(BluetoothListener::Listen);
+ rc->setPrintConsoleMessages(true);
+ return rc;
+}
+
+bool ConsoleBluetoothStarter::startBluetooth(const TrkDevicePtr &trkDevice,
+ QObject *listenerParent,
+ const QString &device,
+ int attempts,
+ QString *errorMessage)
+{
+ // Set up a console starter to print to stdout.
+ ConsoleBluetoothStarter starter(trkDevice, listenerParent);
+ starter.setDevice(device);
+ starter.setAttempts(attempts);
+ switch (starter.start()) {
+ case Started:
+ break;
+ case ConnectionSucceeded:
+ return true;
+ case StartError:
+ *errorMessage = starter.errorString();
+ return false;
+ }
+ // Run the starter with an event loop. @ToDo: Implement
+ // some asynchronous keypress read to cancel.
+ QEventLoop eventLoop;
+ connect(&starter, SIGNAL(connected()), &eventLoop, SLOT(quit()));
+ connect(&starter, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
+ eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
+ if (starter.state() != AbstractBluetoothStarter::Connected) {
+ *errorMessage = starter.errorString();
+ return false;
+ }
+ return true;
+}
+
+} // namespace trk
diff --git a/src/shared/trk/bluetoothlistener.h b/src/shared/trk/bluetoothlistener.h
new file mode 100644
index 0000000000..581a32cde1
--- /dev/null
+++ b/src/shared/trk/bluetoothlistener.h
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BLUETOOTHLISTENER_H
+#define BLUETOOTHLISTENER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QProcess>
+#include <QtCore/QSharedPointer>
+
+namespace trk {
+class TrkDevice;
+struct BluetoothListenerPrivate;
+struct AbstractBluetoothStarterPrivate;
+
+/* BluetoothListener: Starts a helper process watching connections on a
+ * Bluetooth device, Linux only:
+ * The rfcomm command is used. It process can be started in the background
+ * while connection attempts (TrkDevice::open()) are made in the foreground. */
+
+class BluetoothListener : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(BluetoothListener)
+public:
+ // The Mode property must be set before calling start().
+ enum Mode {
+ Listen, /* Terminate after client closed (read: Trk app
+ * on the phone terminated or disconnected).*/
+ Watch // Keep running, watch for next connection from client
+ };
+
+ explicit BluetoothListener(QObject *parent = 0);
+ virtual ~BluetoothListener();
+
+ Mode mode() const;
+ void setMode(Mode m);
+
+ bool start(const QString &device, QString *errorMessage);
+
+ // Print messages on the console.
+ bool printConsoleMessages() const;
+ void setPrintConsoleMessages(bool p);
+
+signals:
+ void terminated();
+ void message(const QString &);
+
+public slots:
+ void emitMessage(const QString &m); // accessed by starter
+
+private slots:
+ void slotStdOutput();
+ void slotStdError();
+ void slotProcessFinished(int, QProcess::ExitStatus);
+ void slotProcessError(QProcess::ProcessError error);
+
+private:
+ int terminateProcess();
+
+ BluetoothListenerPrivate *d;
+};
+
+/* AbstractBluetoothStarter: Repeatedly tries to open a trk device
+ * until a connection succeeds, allowing to do something else in the
+ * foreground (local event loop or asynchronous operation).
+ * Note that in case a Listener is already running in watch mode, it might
+ * also happen that connection succeeds immediately.
+ * Implementations must provide a factory function that creates and sets up the
+ * listener (mode, message connection, etc). */
+
+class AbstractBluetoothStarter : public QObject {
+ Q_OBJECT
+ Q_DISABLE_COPY(AbstractBluetoothStarter)
+public:
+ typedef QSharedPointer<TrkDevice> TrkDevicePtr;
+
+ enum State { Running, Connected, TimedOut };
+
+ virtual ~AbstractBluetoothStarter();
+
+ int intervalMS() const;
+ void setIntervalMS(int i);
+
+ int attempts() const;
+ void setAttempts(int a);
+
+ QString device() const;
+ void setDevice(const QString &);
+
+ State state() const;
+ QString errorString() const;
+
+ enum StartResult {
+ Started, // Starter is now running.
+ ConnectionSucceeded, /* Initial connection attempt succeeded,
+ * no need to keep running. */
+ StartError // Error occurred during start.
+ };
+
+ StartResult start();
+
+signals:
+ void connected();
+ void timeout();
+
+private slots:
+ void slotTimer();
+
+protected:
+ explicit AbstractBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
+ // Overwrite to create and parametrize the listener.
+ virtual BluetoothListener *createListener() = 0;
+
+private:
+ inline void stopTimer();
+
+ AbstractBluetoothStarterPrivate *d;
+};
+
+/* ConsoleBluetoothStarter: Convenience class for console processes. Creates a
+ * listener in "Listen" mode with the messages redirected to standard output. */
+
+class ConsoleBluetoothStarter : public AbstractBluetoothStarter {
+ Q_OBJECT
+ Q_DISABLE_COPY(ConsoleBluetoothStarter)
+public:
+
+ static bool startBluetooth(const TrkDevicePtr& trkDevice,
+ QObject *listenerParent,
+ const QString &device,
+ int attempts,
+ QString *errorMessage);
+
+protected:
+ virtual BluetoothListener *createListener();
+
+private:
+ explicit ConsoleBluetoothStarter(const TrkDevicePtr& trkDevice,
+ QObject *listenerParent,
+ QObject *parent = 0);
+
+ QObject *m_listenerParent;
+};
+
+} // namespace trk
+
+#endif // BLUETOOTHLISTENER_H
diff --git a/src/shared/trk/bluetoothlistener_gui.cpp b/src/shared/trk/bluetoothlistener_gui.cpp
new file mode 100644
index 0000000000..9723a36d9d
--- /dev/null
+++ b/src/shared/trk/bluetoothlistener_gui.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "bluetoothlistener_gui.h"
+#include "bluetoothlistener.h"
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+
+namespace trk {
+
+StartBluetoothGuiResult
+ startBluetoothGui(AbstractBluetoothStarter &starter,
+ QWidget *msgBoxParent,
+ QString *errorMessage)
+{
+ errorMessage->clear();
+ switch (starter.start()) {
+ case AbstractBluetoothStarter::Started:
+ break;
+ case AbstractBluetoothStarter::ConnectionSucceeded:
+ return BluetoothGuiConnected;
+ case AbstractBluetoothStarter::StartError:
+ *errorMessage = starter.errorString();
+ return BluetoothGuiError;
+ }
+ // Run the starter with the event loop of a message box, close it
+ // with the finished signals.
+ const QString title = QCoreApplication::translate("trk::startBluetoothGui", "Waiting for Bluetooth Connection");
+ const QString message = QCoreApplication::translate("trk::startBluetoothGui", "Connecting to %1...").arg(starter.device());
+ QMessageBox messageBox(QMessageBox::Information, title, message, QMessageBox::Cancel, msgBoxParent);
+ QObject::connect(&starter, SIGNAL(connected()), &messageBox, SLOT(close()));
+ QObject::connect(&starter, SIGNAL(timeout()), &messageBox, SLOT(close()));
+ messageBox.exec();
+ // Only starter.state() is reliable here.
+ if (starter.state() == AbstractBluetoothStarter::Running) {
+ *errorMessage = QCoreApplication::translate("trk::startBluetoothGui", "Connection on %1 canceled.").arg(starter.device());
+ return BluetoothGuiCanceled;
+ }
+ if (starter.state() != AbstractBluetoothStarter::Connected) {
+ *errorMessage = starter.errorString();
+ return BluetoothGuiError;
+ }
+ return BluetoothGuiConnected;
+}
+} // namespace trk
diff --git a/src/shared/trk/bluetoothlistener_gui.h b/src/shared/trk/bluetoothlistener_gui.h
new file mode 100644
index 0000000000..2a7c57e291
--- /dev/null
+++ b/src/shared/trk/bluetoothlistener_gui.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef BLUETOOTHLISTENER_GUI_H
+#define BLUETOOTHLISTENER_GUI_H
+
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+QT_END_NAMESPACE
+
+namespace trk {
+ class AbstractBluetoothStarter;
+
+ /* startBluetoothGui(): Prompt the user to start a Bluetooth
+ * connection with a message box he can cancel. Pass in
+ * the starter with device and parameters set up. */
+
+ enum StartBluetoothGuiResult {
+ BluetoothGuiConnected,
+ BluetoothGuiCanceled,
+ BluetoothGuiError
+ };
+
+ StartBluetoothGuiResult
+ startBluetoothGui(AbstractBluetoothStarter &starter,
+ QWidget *msgBoxParent,
+ QString *errorMessage);
+} // namespace trk
+
+#endif // BLUETOOTHLISTENER_GUI_H
diff --git a/src/shared/trk/launcher.cpp b/src/shared/trk/launcher.cpp
index cff53c02a1..f066ab4864 100644
--- a/src/shared/trk/launcher.cpp
+++ b/src/shared/trk/launcher.cpp
@@ -30,6 +30,7 @@
#include "launcher.h"
#include "trkutils.h"
#include "trkdevice.h"
+#include "bluetoothlistener.h"
#include <QtCore/QTimer>
#include <QtCore/QDateTime>
@@ -50,8 +51,9 @@ struct LauncherPrivate {
int position;
};
- LauncherPrivate();
- TrkDevice m_device;
+ explicit LauncherPrivate(const TrkDevicePtr &d);
+
+ TrkDevicePtr m_device;
QString m_trkServerName;
QByteArray m_trkReadBuffer;
@@ -65,21 +67,28 @@ struct LauncherPrivate {
int m_verbose;
Launcher::Actions m_startupActions;
bool m_connected;
+ bool m_closeDevice;
};
-LauncherPrivate::LauncherPrivate() :
+LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) :
+ m_device(d),
m_verbose(0),
- m_connected(false)
+ m_connected(false),
+ m_closeDevice(true)
{
+ if (m_device.isNull())
+ m_device = TrkDevicePtr(new TrkDevice);
}
-Launcher::Launcher(Actions startupActions, QObject *parent) :
+Launcher::Launcher(Actions startupActions,
+ const TrkDevicePtr &dev,
+ QObject *parent) :
QObject(parent),
- d(new LauncherPrivate)
+ d(new LauncherPrivate(dev))
{
d->m_startupActions = startupActions;
- connect(&d->m_device, SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult)));
- connect(this, SIGNAL(finished()), &d->m_device, SLOT(close()));
+ connect(d->m_device.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult)));
+ connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close()));
}
Launcher::~Launcher()
@@ -98,6 +107,16 @@ void Launcher::setTrkServerName(const QString &name)
d->m_trkServerName = name;
}
+QString Launcher::trkServerName() const
+{
+ return d->m_trkServerName;
+}
+
+TrkDevicePtr Launcher::trkDevice() const
+{
+ return d->m_device;
+}
+
void Launcher::setFileName(const QString &name)
{
d->m_fileName = name;
@@ -116,16 +135,28 @@ void Launcher::setInstallFileName(const QString &name)
void Launcher::setSerialFrame(bool b)
{
- d->m_device.setSerialFrame(b);
+ d->m_device->setSerialFrame(b);
}
bool Launcher::serialFrame() const
{
- return d->m_device.serialFrame();
+ return d->m_device->serialFrame();
+}
+
+
+bool Launcher::closeDevice() const
+{
+ return d->m_closeDevice;
+}
+
+void Launcher::setCloseDevice(bool c)
+{
+ d->m_closeDevice = c;
}
bool Launcher::startServer(QString *errorMessage)
{
+ errorMessage->clear();
if (d->m_verbose) {
const QString msg = QString::fromLatin1("Port=%1 Executable=%2 Package=%3 Remote Package=%4 Install file=%5")
.arg(d->m_trkServerName, d->m_fileName, d->m_copyState.sourceFileName, d->m_copyState.destinationFileName, d->m_installFileName);
@@ -148,15 +179,21 @@ bool Launcher::startServer(QString *errorMessage)
qWarning("No remote executable given for running.");
return false;
}
- if (!d->m_device.open(d->m_trkServerName, errorMessage))
+ if (!d->m_device->isOpen() && !d->m_device->open(d->m_trkServerName, errorMessage))
return false;
- d->m_device.sendTrkInitialPing();
- d->m_device.sendTrkMessage(TrkDisconnect); // Disconnect, as trk might be still connected
- d->m_device.sendTrkMessage(TrkSupported, TrkCallback(this, &Launcher::handleSupportMask));
- d->m_device.sendTrkMessage(TrkCpuType, TrkCallback(this, &Launcher::handleCpuType));
- d->m_device.sendTrkMessage(TrkVersions, TrkCallback(this, &Launcher::handleTrkVersion));
+ if (d->m_closeDevice) {
+ connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close()));
+ } else {
+ disconnect(this, SIGNAL(finished()), d->m_device.data(), 0);
+ }
+
+ d->m_device->sendTrkInitialPing();
+ d->m_device->sendTrkMessage(TrkDisconnect); // Disconnect, as trk might be still connected
+ d->m_device->sendTrkMessage(TrkSupported, TrkCallback(this, &Launcher::handleSupportMask));
+ d->m_device->sendTrkMessage(TrkCpuType, TrkCallback(this, &Launcher::handleCpuType));
+ d->m_device->sendTrkMessage(TrkVersions, TrkCallback(this, &Launcher::handleTrkVersion));
if (d->m_startupActions != ActionPingOnly)
- d->m_device.sendTrkMessage(TrkConnect, TrkCallback(this, &Launcher::handleConnect));
+ d->m_device->sendTrkMessage(TrkConnect, TrkCallback(this, &Launcher::handleConnect));
return true;
}
@@ -178,7 +215,7 @@ void Launcher::handleConnect(const TrkResult &result)
void Launcher::setVerbose(int v)
{
d->m_verbose = v;
- d->m_device.setVerbose(v);
+ d->m_device->setVerbose(v);
}
void Launcher::logMessage(const QString &msg)
@@ -193,7 +230,7 @@ void Launcher::terminate()
QByteArray ba;
appendShort(&ba, 0x0000, TargetByteOrder);
appendInt(&ba, d->m_session.pid, TargetByteOrder);
- d->m_device.sendTrkMessage(TrkDeleteItem, TrkCallback(this, &Launcher::handleRemoteProcessKilled), ba);
+ d->m_device->sendTrkMessage(TrkDeleteItem, TrkCallback(this, &Launcher::handleRemoteProcessKilled), ba);
} else if (d->m_connected) {
if (d->m_copyState.copyFileHandle)
closeRemoteFile(true);
@@ -235,17 +272,17 @@ void Launcher::handleResult(const TrkResult &result)
// uint pid = extractInt(data + 4); // ProcessID: 4 bytes;
// uint tid = extractInt(data + 8); // ThreadID: 4 bytes
//logMessage(prefix << " ADDR: " << addr << " PID: " << pid << " TID: " << tid);
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
break;
}
case TrkNotifyException: { // Notify Exception (obsolete)
logMessage(prefix + "NOTE: EXCEPTION " + str);
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
break;
}
case TrkNotifyInternalError: { //
logMessage(prefix + "NOTE: INTERNAL ERROR: " + str);
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
break;
}
@@ -278,8 +315,8 @@ void Launcher::handleResult(const TrkResult &result)
break;
QByteArray ba;
ba.append(result.data.mid(2, 8));
- d->m_device.sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
- //d->m_device.sendTrkAck(result.token)
+ d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
+ //d->m_device->sendTrkAck(result.token)
break;
}
case TrkNotifyDeleted: { // NotifyDeleted
@@ -289,7 +326,7 @@ void Launcher::handleResult(const TrkResult &result)
logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3").
arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")).
arg(name));
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
if (itemType == 0 // process
&& result.data.size() >= 10
&& d->m_session.pid == extractInt(result.data.data() + 6)) {
@@ -299,17 +336,17 @@ void Launcher::handleResult(const TrkResult &result)
}
case TrkNotifyProcessorStarted: { // NotifyProcessorStarted
logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str);
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
break;
}
case TrkNotifyProcessorStandBy: { // NotifyProcessorStandby
logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str);
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
break;
}
case TrkNotifyProcessorReset: { // NotifyProcessorReset
logMessage(prefix + "NOTE: PROCESSOR RESET: " + str);
- d->m_device.sendTrkAck(result.token);
+ d->m_device->sendTrkAck(result.token);
break;
}
default: {
@@ -384,7 +421,7 @@ void Launcher::continueCopying(uint lastCopiedBlockSize)
QByteArray ba;
appendInt(&ba, d->m_copyState.copyFileHandle, TargetByteOrder);
appendString(&ba, d->m_copyState.data->mid(d->m_copyState.position, 2048), TargetByteOrder, false);
- d->m_device.sendTrkMessage(TrkWriteFile, TrkCallback(this, &Launcher::handleCopy), ba);
+ d->m_device->sendTrkMessage(TrkWriteFile, TrkCallback(this, &Launcher::handleCopy), ba);
} else {
closeRemoteFile();
}
@@ -395,7 +432,7 @@ void Launcher::closeRemoteFile(bool failed)
QByteArray ba;
appendInt(&ba, d->m_copyState.copyFileHandle, TargetByteOrder);
appendInt(&ba, QDateTime::currentDateTime().toTime_t(), TargetByteOrder);
- d->m_device.sendTrkMessage(TrkCloseFile,
+ d->m_device->sendTrkMessage(TrkCloseFile,
failed ? TrkCallback() : TrkCallback(this, &Launcher::handleFileCopied),
ba);
d->m_copyState.data.reset();
@@ -458,7 +495,7 @@ void Launcher::handleCreateProcess(const TrkResult &result)
QByteArray ba;
appendInt(&ba, d->m_session.pid);
appendInt(&ba, d->m_session.tid);
- d->m_device.sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
+ d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE");
}
void Launcher::handleWaitForFinished(const TrkResult &result)
@@ -496,7 +533,7 @@ void Launcher::cleanUp()
appendByte(&ba, 0x00);
appendByte(&ba, 0x00);
appendInt(&ba, d->m_session.pid);
- d->m_device.sendTrkMessage(TrkDeleteItem, TrkCallback(), ba, "Delete process");
+ d->m_device->sendTrkMessage(TrkDeleteItem, TrkCallback(), ba, "Delete process");
//---TRK------------------------------------------------------
// Command: 0x80 Acknowledge
@@ -540,7 +577,7 @@ void Launcher::cleanUp()
void Launcher::disconnectTrk()
{
- d->m_device.sendTrkMessage(TrkDisconnect, TrkCallback(this, &Launcher::handleWaitForFinished));
+ d->m_device->sendTrkMessage(TrkDisconnect, TrkCallback(this, &Launcher::handleWaitForFinished));
}
void Launcher::copyFileToRemote()
@@ -549,7 +586,7 @@ void Launcher::copyFileToRemote()
QByteArray ba;
appendByte(&ba, 0x10);
appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false);
- d->m_device.sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba);
+ d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba);
}
void Launcher::installRemotePackageSilently()
@@ -558,7 +595,7 @@ void Launcher::installRemotePackageSilently()
QByteArray ba;
appendByte(&ba, 'C');
appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false);
- d->m_device.sendTrkMessage(TrkInstallFile, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba);
+ d->m_device->sendTrkMessage(TrkInstallFile, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba);
}
void Launcher::handleInstallPackageFinished(const TrkResult &result)
@@ -586,7 +623,6 @@ void Launcher::startInferiorIfNeeded()
appendByte(&ba, 0); // create new process
appendByte(&ba, 0); // ?
appendString(&ba, d->m_fileName.toLocal8Bit(), TargetByteOrder);
- d->m_device.sendTrkMessage(TrkCreateItem, TrkCallback(this, &Launcher::handleCreateProcess), ba); // Create Item
-}
-
+ d->m_device->sendTrkMessage(TrkCreateItem, TrkCallback(this, &Launcher::handleCreateProcess), ba); // Create Item
}
+} // namespace trk
diff --git a/src/shared/trk/launcher.h b/src/shared/trk/launcher.h
index 93f5d52923..2c4881de6d 100644
--- a/src/shared/trk/launcher.h
+++ b/src/shared/trk/launcher.h
@@ -29,8 +29,11 @@
#ifndef LAUNCHER_H
#define LAUNCHER_H
+#include "trkdevice.h"
+
#include <QtCore/QObject>
#include <QtCore/QVariant>
+#include <QtCore/QSharedPointer>
namespace trk {
@@ -38,9 +41,12 @@ struct TrkResult;
struct TrkMessage;
struct LauncherPrivate;
+typedef QSharedPointer<TrkDevice> TrkDevicePtr;
+
class Launcher : public QObject
{
Q_OBJECT
+ Q_DISABLE_COPY(Launcher)
public:
typedef void (Launcher::*TrkCallBack)(const TrkResult &);
@@ -56,10 +62,12 @@ public:
};
explicit Launcher(trk::Launcher::Actions startupActions = trk::Launcher::ActionPingOnly,
+ const TrkDevicePtr &trkDevice = TrkDevicePtr(),
QObject *parent = 0);
~Launcher();
void addStartupActions(trk::Launcher::Actions startupActions);
void setTrkServerName(const QString &name);
+ QString trkServerName() const;
void setFileName(const QString &name);
void setCopyFileName(const QString &srcName, const QString &dstName);
void setInstallFileName(const QString &name);
@@ -67,6 +75,11 @@ public:
void setVerbose(int v);
void setSerialFrame(bool b);
bool serialFrame() const;
+ // Close device or leave it open
+ bool closeDevice() const;
+ void setCloseDevice(bool c);
+
+ TrkDevicePtr trkDevice() const;
// becomes valid after successful execution of ActionPingOnly
QString deviceDescription(unsigned verbose = 0u) const;
diff --git a/src/shared/trk/trk.pri b/src/shared/trk/trk.pri
index 1564e4684d..8965948f19 100644
--- a/src/shared/trk/trk.pri
+++ b/src/shared/trk/trk.pri
@@ -1,13 +1,20 @@
INCLUDEPATH *= $$PWD
# Input
-HEADERS += \
- $$PWD/callback.h \
+HEADERS += $$PWD/callback.h \
$$PWD/trkutils.h \
$$PWD/trkdevice.h \
- $$PWD/launcher.h
+ $$PWD/launcher.h \
+ $$PWD/bluetoothlistener.h
-SOURCES += \
- $$PWD/trkutils.cpp \
+SOURCES += $$PWD/trkutils.cpp \
$$PWD/trkdevice.cpp \
- $$PWD/launcher.cpp
+ $$PWD/launcher.cpp \
+ $$PWD/bluetoothlistener.cpp
+
+contains(QT, gui) {
+ HEADERS += $$PWD/bluetoothlistener_gui.h
+ SOURCES += $$PWD/bluetoothlistener_gui.cpp
+} else {
+ message(Trk: Console ...)
+}
diff --git a/tests/manual/trklauncher/main.cpp b/tests/manual/trklauncher/main.cpp
index 65031e7cc5..e9847d33b8 100644
--- a/tests/manual/trklauncher/main.cpp
+++ b/tests/manual/trklauncher/main.cpp
@@ -1,13 +1,19 @@
#include "launcher.h"
+#include "bluetoothlistener.h"
#include <QtCore/QCoreApplication>
+#include <QtCore/QSharedPointer>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
static const char *usageC =
-"\nUsage: %1 <trk_port_name> [-v] [-i remote_sis_file | -I local_sis_file remote_sis_file] [<remote_executable_name>]\n"
+"\n"
+"Usage: %1 [options] <trk_port_name>\n"
+" %1 [options] -i <trk_port_name> remote_sis_file\n"
+" %1 [options] -I local_sis_file remote_sis_file] [<remote_executable_name>]\n"
"\nOptions:\n -v verbose\n"
- " -f turn serial message frame off\n\n"
+ " -b Prompt for Bluetooth connect (Linux only)\n"
+ " -f turn serial message frame off (Bluetooth)\n"
"\nPing:\n"
"%1 COM5\n"
"\nRemote launch:\n"
@@ -27,74 +33,94 @@ static void usage()
qWarning("%s", qPrintable(msg));
}
-static bool parseArguments(const QStringList &arguments, trk::Launcher &launcher)
+typedef QSharedPointer<trk::Launcher> TrkLauncherPtr;
+
+// Parse arguments, return pointer or a null none.
+
+static inline TrkLauncherPtr createLauncher(trk::Launcher::Actions actions,
+ const QString &serverName,
+ bool serialFrame,
+ int verbosity)
+{
+ TrkLauncherPtr launcher(new trk::Launcher(actions));
+ launcher->setTrkServerName(serverName);
+ launcher->setSerialFrame(serialFrame);
+ launcher->setVerbose(verbosity);
+ return launcher;
+}
+
+static TrkLauncherPtr parseArguments(const QStringList &arguments, bool *bluetooth)
{
// Parse away options
bool install = false;
bool customInstall = false;
+ bool serialFrame = true;
const int argCount = arguments.size();
int verbosity = 0;
+ *bluetooth = false;
+ trk::Launcher::Actions actions = trk::Launcher::ActionPingOnly;
int a = 1;
for ( ; a < argCount; a++) {
const QString option = arguments.at(a);
if (!option.startsWith(QLatin1Char('-')))
break;
if (option.size() != 2)
- return false;
+ return TrkLauncherPtr();
switch (option.at(1).toAscii()) {
case 'v':
verbosity++;
break;
case 'f':
- launcher.setSerialFrame(false);
- break;verbosity++;
+ serialFrame = false;
+ break;
+ case 'b':
+ *bluetooth = true;
+ break;
case 'i':
install = true;
- launcher.addStartupActions(trk::Launcher::ActionInstall);
+ actions = trk::Launcher::ActionInstall;
break;
case 'I':
customInstall = true;
- launcher.addStartupActions(trk::Launcher::ActionCopyInstall);
+ actions = trk::Launcher::ActionCopyInstall;
break;
default:
- return false;
+ return TrkLauncherPtr();
}
}
-
- launcher.setVerbose(verbosity);
// Evaluate arguments
const int remainingArgsCount = argCount - a;
- if (remainingArgsCount == 1 && !install && !customInstall) {
- launcher.setTrkServerName(arguments.at(a)); // ping
- return true;
+ if (remainingArgsCount == 1 && !install && !customInstall) { // Ping
+ return createLauncher(actions, arguments.at(a), serialFrame, verbosity);
}
if (remainingArgsCount == 2 && !install && !customInstall) {
// remote exec
- launcher.addStartupActions(trk::Launcher::ActionRun);
- launcher.setTrkServerName(arguments.at(a));
- launcher.setFileName(arguments.at(a + 1));
- return true;
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(arguments.at(a + 1));
+ return launcher;
}
if ((remainingArgsCount == 3 || remainingArgsCount == 2) && install && !customInstall) {
- launcher.setTrkServerName(arguments.at(a)); // ping
- launcher.setInstallFileName(arguments.at(a + 1));
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->setInstallFileName(arguments.at(a + 1));
if (remainingArgsCount == 3) {
- launcher.addStartupActions(trk::Launcher::ActionRun);
- launcher.setFileName(arguments.at(a + 2));
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(arguments.at(a + 2));
}
- return true;
+ return launcher;
}
if ((remainingArgsCount == 4 || remainingArgsCount == 3) && !install && customInstall) {
- launcher.setTrkServerName(arguments.at(a)); // ping
- launcher.setCopyFileName(arguments.at(a + 1), arguments.at(a + 2));
- launcher.setInstallFileName(arguments.at(a + 2));
+ TrkLauncherPtr launcher = createLauncher(actions, arguments.at(a), serialFrame, verbosity);
+ launcher->setTrkServerName(arguments.at(a)); // ping
+ launcher->setCopyFileName(arguments.at(a + 1), arguments.at(a + 2));
+ launcher->setInstallFileName(arguments.at(a + 2));
if (remainingArgsCount == 4) {
- launcher.addStartupActions(trk::Launcher::ActionRun);
- launcher.setFileName(arguments.at(a + 3));
+ launcher->addStartupActions(trk::Launcher::ActionRun);
+ launcher->setFileName(arguments.at(a + 3));
}
- return true;
+ return launcher;
}
- return false;
+ return TrkLauncherPtr();
}
int main(int argc, char *argv[])
@@ -103,14 +129,23 @@ int main(int argc, char *argv[])
QCoreApplication::setApplicationName(QLatin1String("trklauncher"));
QCoreApplication::setOrganizationName(QLatin1String("Nokia"));
- trk::Launcher launcher;
- if (!parseArguments(app.arguments(), launcher)) {
+ bool bluetooth;
+ const TrkLauncherPtr launcher = parseArguments(app.arguments(), &bluetooth);
+ if (launcher.isNull()) {
usage();
return 1;
}
- QObject::connect(&launcher, SIGNAL(finished()), &app, SLOT(quit()));
+ QObject::connect(launcher.data(), SIGNAL(finished()), &app, SLOT(quit()));
+ // BLuetooth: Open with prompt
QString errorMessage;
- if (launcher.startServer(&errorMessage))
+ if (bluetooth && !trk::ConsoleBluetoothStarter::startBluetooth(launcher->trkDevice(),
+ launcher.data(),
+ launcher->trkServerName(),
+ 30, &errorMessage)) {
+ qWarning("%s\n", qPrintable(errorMessage));
+ return -1;
+ }
+ if (launcher->startServer(&errorMessage))
return app.exec();
qWarning("%s\n", qPrintable(errorMessage));
return 4;
diff --git a/tests/manual/trklauncher/trklauncher.pro b/tests/manual/trklauncher/trklauncher.pro
index 73e7f7d781..943afde4ad 100644
--- a/tests/manual/trklauncher/trklauncher.pro
+++ b/tests/manual/trklauncher/trklauncher.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
QT = core
+CONFIG += console
include(../../../src/shared/trk/trk.pri)
-win32:CONFIG += console
SOURCES += main.cpp