You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebluez/src/tdebluez/application.cpp

373 lines
10 KiB

/*
*
* New Bluetooth App for TDE and bluez5
*
* Copyright (C) 2018 Emanoil Kotsev <deloptes@gmail.com>
*
*
* This file is part of tdebluez.
*
* tdebluez is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* tdebluez is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with kbluetooth; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <dcopclient.h>
#include <kuser.h>
#include <tqregexp.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include "trayicon.h"
#include "application.h"
#define WAIT_BEFORE_KILL 5000 // 5sec
#define CONFIGURATION_FILE "tdebluezrc"
#define TDEBLUEZAUTH_EXE "tdebluezauth"
#define OBEX_EXE "/usr/lib/bluetooth/obexd"
#define OBEX_EXE_ALT "/usr/libexec/bluetooth/obexd"
#define BLUEZ_DN "org.bluez"
#define DOWNLOAD_DIRECTORY "Downloads"
TDEBluetoothApp::TDEBluetoothApp() :
KUniqueApplication()
{
// set default config file
m_config = new TDEConfig(CONFIGURATION_FILE);
m_config->setGroup("General");
bool autostart = m_config->readBoolEntry("autoStart", false);
m_waitBeforeKill = m_config->readNumEntry("waitBeforeKill", WAIT_BEFORE_KILL);
TQString authAgentExe = m_config->readEntry("authAgentExe", TDEBLUEZAUTH_EXE);
TQString obexSrvExe = m_config->readEntry("obexSrvExe", OBEX_EXE);
TQString downloadDir = m_config->readPathEntry("downloadDir", "");
if (!autostart)
disableSessionManagement();
if (m_waitBeforeKill == 0)
{
m_waitBeforeKill = WAIT_BEFORE_KILL;
m_config->writeEntry("waitBeforeKill", m_waitBeforeKill);
}
if (obexSrvExe.isEmpty())
{
obexSrvExe=TQString(OBEX_EXE);
}
if (authAgentExe.isEmpty())
{
authAgentExe = TDEBLUEZAUTH_EXE;
m_config->writePathEntry("authAgentExe", authAgentExe);
}
if (downloadDir.isEmpty())
{
downloadDir = DOWNLOAD_DIRECTORY;
m_config->writePathEntry("downloadDir", downloadDir);
}
manager = new ObjectManagerImpl(BLUEZ_DN, "/", this, "ObjectManager");
if (!manager->isConnectedToDBUS())
{
tqDebug(i18n("ObjectManager is not connected to DBus"));
return;
}
ObjectManagerImpl::AdapterList al = manager->getAdapters();
ObjectManagerImpl::AdapterList::Iterator ait = al.begin();
for (ait; ait != al.end(); ++ait)
{
AdapterImpl *a = new AdapterImpl(BLUEZ_DN, (*ait));
a->setConnection((*(manager->getConnection())));
adapters.insert((*ait), a);
}
ObjectManagerImpl::DeviceList dl = manager->getDevices();
ObjectManagerImpl::DeviceList::Iterator dit = dl.begin();
for (dit; dit != dl.end(); ++dit)
{
DeviceImpl *d = new DeviceImpl(BLUEZ_DN, (*dit));
d->setConnection((*(manager->getConnection())));
devices.insert((*dit), d);
}
authAgent = new TQProcess(authAgentExe, this);
authAgent->addArgument("--nofork");
TQFileInfo obexSrvExeFile( obexSrvExe );
if (!obexSrvExeFile.exists())
{
obexSrvExeFile.setFile(OBEX_EXE_ALT);
if (obexSrvExeFile.exists())
{
m_config->writePathEntry("obexSrvExe", obexSrvExeFile.filePath());
}
else
{
tqWarning(i18n("obexd executable was not found\nSet path in configuration file \"%1\"\nVariable: obexSrvExe=<path to obexd>").arg(CONFIGURATION_FILE));
m_config->writeEntry("obexSrv", false);
}
}
obexServer = new TQProcess(obexSrvExeFile.filePath(), this);
obexServer->addArgument("-n");
obexServer->addArgument("-a");
obexServer->addArgument("-l");
obexServer->addArgument("-r");
obexServer->addArgument(downloadDir);
//stop tdebluezauth or obexd daemon to regain control
KUser user;
long uid = user.uid();
TQDir d("/proc");
d.setFilter(TQDir::Dirs);
TQRegExp rx( "^\\d+$" );
for (int i = 0; i < d.count(); i++)
{
if ( ! rx.exactMatch(d[i]) )
continue;
TQFile f("/proc/" + d[i] + "/status");
if ( ! f.open( IO_ReadOnly ) )
{
tqDebug(i18n("Failed to open file for reading: %1").arg(f.name()));
continue;
}
TQTextStream stream( &f );
TQString pid;
bool tokill = false;
while ( !stream.atEnd() ) {
TQString line = stream.readLine(); // line of text excluding '\n'
if (line.startsWith("Name:") &&
( line.endsWith("tdebluezauth") || line.endsWith("obexd") ))
{
pid = d[i];
}
if (line.find(TQRegExp(TQString("Uid:\\s+%1").arg(uid))) != -1)
{
tokill = true;
}
}
f.close();
if (tokill && ! pid.isEmpty())
{
if ( kill( (pid_t) pid.toLong(), SIGKILL ) == -1 )
{
switch ( errno )
{
case EINVAL:
tqDebug(i18n("4\t%1").arg(pid) );
break;
case ESRCH:
tqDebug(i18n("3\t%1").arg(pid) );
break;
case EPERM:
tqDebug(i18n("2\t%1").arg(pid) );
break;
default: /* unknown error */
tqDebug(i18n("1\t%1").arg(pid) );
break;
}
} else {
tqWarning(i18n("Cleanup pid\t%1").arg(pid) );
}
}
}
// connect to manager signals
connect(manager, TQ_SIGNAL(adapterAdded(const TQString&)), TQ_SLOT(slotAdapterAdded(const TQString&)));
connect(manager, TQ_SIGNAL(adapterRemoved(const TQString&)), TQ_SLOT(slotAdapterRemoved(const TQString&)));
connect(manager, TQ_SIGNAL(deviceAdded(const TQString&)), TQ_SLOT(slotDeviceAdded(const TQString&)));
connect(manager, TQ_SIGNAL(deviceRemoved(const TQString&)), TQ_SLOT(slotDeviceRemoved(const TQString&)));
// connect(manager, TQ_SIGNAL(adapterPowerOnChanged(const TQString&, bool)), TQ_SLOT(slotPowerOnChanged(const TQString&, bool)));
trayIcon = new TrayIcon(this);
setMainWidget(trayIcon);
}
TDEBluetoothApp::~TDEBluetoothApp()
{
if (obexServer)
{
if (obexServer->isRunning())
obexServer->kill();
delete obexServer;
}
if (authAgent)
{
if (authAgent->isRunning())
authAgent->kill();
delete authAgent;
}
delete trayIcon;
if (manager->isConnectedToDBUS())
{
DevicesMap::Iterator dit = devices.begin();
for (dit; dit != devices.end(); ++dit)
{
DeviceImpl *d = dit.data();
if (d)
delete d;
}
devices.clear();
AdaptersMap::Iterator ait = adapters.begin();
for (ait; ait != adapters.end(); ++ait)
{
AdapterImpl *a = ait.data();
if (a)
{
TQT_DBusError error;
if (a->getDiscovering(error))
a->StopDiscovery(error);
if (error.isValid())
tqDebug(i18n("Stop discoverable for the adapter failed: %1").arg(error.message()));
delete a;
}
}
adapters.clear();
}
delete manager;
if (m_config->isDirty())
m_config->sync();
delete m_config;
}
bool TDEBluetoothApp::startAuthAgent()
{
if (!authAgent->isRunning())
{
if (!authAgent->start())
return false;
}
return true;
}
bool TDEBluetoothApp::stopAuthAgent()
{
if (authAgent->isRunning())
{
authAgent->tryTerminate();
TQTimer::singleShot(m_waitBeforeKill, authAgent, TQ_SLOT(kill()));
}
return true;
}
bool TDEBluetoothApp::startObexSrv()
{
if (!obexServer->isRunning())
{
if (!obexServer->start())
return false;
}
return true;
}
bool TDEBluetoothApp::stopObexSrv()
{
if (obexServer->isRunning())
{
obexServer->tryTerminate();
TQTimer::singleShot(m_waitBeforeKill, obexServer, TQ_SLOT(kill()));
}
return true;
}
bool TDEBluetoothApp::isConnected()
{
return manager->isConnectedToDBUS();
}
void TDEBluetoothApp::setAutoStart(bool val)
{
if (val)
enableSessionManagement();
else
disableSessionManagement();
m_config->setGroup("General");
m_config->writeEntry("autoStart", val);
}
void TDEBluetoothApp::setStartObex(bool val)
{
m_config->setGroup("General");
m_config->writeEntry("obexSrv", val);
}
void TDEBluetoothApp::setStartAuthAgent(bool val)
{
m_config->setGroup("General");
m_config->writeEntry("authAgent", val);
}
bool TDEBluetoothApp::getAutoStart()
{
m_config->setGroup("General");
return m_config->readBoolEntry("autoStart");
}
bool TDEBluetoothApp::getStartObex()
{
m_config->setGroup("General");
return m_config->readBoolEntry("obexSrv");
}
bool TDEBluetoothApp::getStartAuthAgent()
{
m_config->setGroup("General");
return m_config->readBoolEntry("authAgent");
}
void TDEBluetoothApp::slotAdapterAdded(const TQString &adapter)
{
AdapterImpl *a = new AdapterImpl(BLUEZ_DN, adapter);
a->setConnection((*(manager->getConnection())));
adapters.insert(adapter, a);
emit signalAdapterAdded(adapter);
}
void TDEBluetoothApp::slotAdapterRemoved(const TQString &adapter)
{
delete adapters[adapter];
adapters.remove(adapter);
emit signalAdapterRemoved(adapter);
}
void TDEBluetoothApp::slotDeviceAdded(const TQString &device)
{
DeviceImpl *d = new DeviceImpl(BLUEZ_DN, device);
d->setConnection((*(manager->getConnection())));
devices.insert(device, d);
}
void TDEBluetoothApp::slotDeviceRemoved(const TQString &device)
{
delete devices[device];
devices.remove(device);
}
#include "application.moc"