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.
463 lines
10 KiB
463 lines
10 KiB
/* *************************************************************************
|
|
* copyright: (C) 2005 Justin Huff <jjhuff@mspin.net> *
|
|
*************************************************************************
|
|
*/
|
|
|
|
/* *************************************************************************
|
|
* *
|
|
* This program 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. *
|
|
* *
|
|
*************************************************************************
|
|
*/
|
|
#include "config.h"
|
|
#ifdef INCLUDE_SMSGSM
|
|
|
|
#include <qcombobox.h>
|
|
#include <qlayout.h>
|
|
#include <qapplication.h>
|
|
#include <qevent.h>
|
|
#include <qmutex.h>
|
|
#include <qthread.h>
|
|
#include <qcheckbox.h>
|
|
|
|
#include <klocale.h>
|
|
#include <kurlrequester.h>
|
|
#include <kmessagebox.h>
|
|
#include <kprocess.h>
|
|
#include <kdebug.h>
|
|
#include <kconfigbase.h>
|
|
|
|
#include <unistd.h>
|
|
#include <gsmlib/gsm_me_ta.h>
|
|
#include <gsmlib/gsm_sms.h>
|
|
#include <gsmlib/gsm_util.h>
|
|
#include <gsmlib/gsm_error.h>
|
|
|
|
#include "kopeteaccount.h"
|
|
#include "kopeteuiglobal.h"
|
|
#include "kopetemetacontact.h"
|
|
#include "kopetecontactlist.h"
|
|
#include "kopetechatsessionmanager.h"
|
|
|
|
#include "gsmlib.h"
|
|
#include "gsmlibprefs.h"
|
|
#include "smsprotocol.h"
|
|
#include "smscontact.h"
|
|
|
|
#include "kopete_unix_serial.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
#define GSMLIB_EVENT_ID 245
|
|
GSMLibEvent::GSMLibEvent(SubType t) : QCustomEvent(QEvent::User+GSMLIB_EVENT_ID)
|
|
{
|
|
setSubType(t);
|
|
}
|
|
|
|
GSMLibEvent::SubType GSMLibEvent::subType()
|
|
{
|
|
return m_subType;
|
|
}
|
|
|
|
void GSMLibEvent::setSubType(GSMLibEvent::SubType t)
|
|
{
|
|
m_subType = t;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
GSMLibThread::GSMLibThread(QString dev, GSMLib* parent)
|
|
{
|
|
m_device = dev;
|
|
m_parent = parent;
|
|
m_run = true;
|
|
m_MeTa = NULL;
|
|
}
|
|
|
|
GSMLibThread::~GSMLibThread()
|
|
{
|
|
m_run = false;
|
|
}
|
|
|
|
void GSMLibThread::stop()
|
|
{
|
|
m_run = false;
|
|
kdDebug( 14160 ) << "Waiting from GSMLibThread to die"<<endl;
|
|
if( wait(4000) == false )
|
|
kdWarning( 14160 ) << "GSMLibThread didn't exit!"<<endl;
|
|
}
|
|
void GSMLibThread::run()
|
|
{
|
|
if( doConnect() )
|
|
{
|
|
while( m_run )
|
|
{
|
|
pollForMessages();
|
|
sendMessageQueue();
|
|
}
|
|
}
|
|
|
|
delete m_MeTa;
|
|
m_MeTa = NULL;
|
|
QApplication::postEvent(m_parent, new GSMLibEvent(GSMLibEvent::DISCONNECTED));
|
|
kdDebug( 14160 ) << "GSMLibThread exited"<<endl;
|
|
}
|
|
|
|
void GSMLibThread::send(const Kopete::Message& msg)
|
|
{
|
|
if( m_MeTa )
|
|
{
|
|
m_outMessagesMutex.lock();
|
|
m_outMessages.push_back(msg);
|
|
m_outMessagesMutex.unlock();
|
|
}
|
|
else
|
|
{
|
|
GSMLibEvent* e = new GSMLibEvent( GSMLibEvent::MSG_NOT_SENT );
|
|
e->Reason = QString("GSMLib: Not Connected");
|
|
e->Message = msg;
|
|
QApplication::postEvent(m_parent, e);
|
|
}
|
|
}
|
|
|
|
|
|
bool GSMLibThread::doConnect()
|
|
{
|
|
// open the port and ME/TA
|
|
try
|
|
{
|
|
kdDebug( 14160 ) << "Connecting to: '"<<m_device<<"'"<<endl;
|
|
|
|
gsmlib::Ref<gsmlib::Port> port = new gsmlib::KopeteUnixSerialPort(m_device.latin1(), 9600, gsmlib::DEFAULT_INIT_STRING, false);
|
|
|
|
kdDebug( 14160 ) << "Port created"<<endl;
|
|
|
|
m_MeTa = new gsmlib::MeTa(port);
|
|
std::string dummy1, dummy2, receiveStoreName;
|
|
m_MeTa->getSMSStore(dummy1, dummy2, receiveStoreName );
|
|
m_MeTa->setSMSStore(receiveStoreName, 3);
|
|
|
|
m_MeTa->setMessageService(1);
|
|
|
|
// switch on SMS routing
|
|
m_MeTa->setSMSRoutingToTA(true, false, false, true);
|
|
|
|
m_MeTa->setEventHandler(this);
|
|
QApplication::postEvent(m_parent, new GSMLibEvent(GSMLibEvent::CONNECTED));
|
|
return true;
|
|
}
|
|
catch(gsmlib::GsmException &e)
|
|
{
|
|
kdWarning( 14160 ) << k_funcinfo<< e.what()<<endl;
|
|
m_run = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void GSMLibThread::SMSReception(gsmlib::SMSMessageRef newMessage, SMSMessageType messageType)
|
|
{
|
|
try
|
|
{
|
|
IncomingMessage m;
|
|
m.Type = messageType;
|
|
m.Message = newMessage;
|
|
|
|
m_newMessages.push_back(m);
|
|
}
|
|
catch(gsmlib::GsmException &e)
|
|
{
|
|
kdWarning( 14160 ) << k_funcinfo<< e.what()<<endl;
|
|
m_run = false;
|
|
}
|
|
}
|
|
|
|
void GSMLibThread::SMSReceptionIndication(std::string storeName, unsigned int index, SMSMessageType messageType)
|
|
{
|
|
kdDebug( 14160 ) << k_funcinfo << "New Message in store: "<<storeName.c_str() << endl;
|
|
|
|
try
|
|
{
|
|
if( messageType != gsmlib::GsmEvent::NormalSMS )
|
|
return;
|
|
|
|
IncomingMessage m;
|
|
m.Index = index;
|
|
m.StoreName = storeName.c_str();
|
|
m.Type = messageType;
|
|
m_newMessages.push_back(m);
|
|
}
|
|
catch(gsmlib::GsmException &e)
|
|
{
|
|
kdWarning( 14160 ) << k_funcinfo<< e.what()<<endl;
|
|
m_run = false;
|
|
}
|
|
}
|
|
|
|
void GSMLibThread::pollForMessages( )
|
|
{
|
|
if( m_MeTa == NULL )
|
|
return;
|
|
|
|
try
|
|
{
|
|
struct timeval timeoutVal;
|
|
timeoutVal.tv_sec = 1;
|
|
timeoutVal.tv_usec = 0;
|
|
m_MeTa->waitEvent(&timeoutVal);
|
|
|
|
MessageList::iterator it;
|
|
for( it=m_newMessages.begin(); it!=m_newMessages.end(); it++)
|
|
{
|
|
IncomingMessage m = *it;
|
|
|
|
// Do we need to fetch it from the ME?
|
|
if( m.Message.isnull() )
|
|
{
|
|
gsmlib::SMSStoreRef store = m_MeTa->getSMSStore(m.StoreName.latin1());
|
|
store->setCaching(false);
|
|
|
|
m.Message = (*store.getptr())[m.Index].message();
|
|
store->erase(store->begin() + m.Index);
|
|
}
|
|
|
|
GSMLibEvent* e = new GSMLibEvent( GSMLibEvent::NEW_MESSAGE );
|
|
e->Text = m.Message->userData().c_str();
|
|
e->Number = m.Message->address().toString().c_str();
|
|
|
|
QApplication::postEvent(m_parent, e);
|
|
|
|
}
|
|
m_newMessages.clear();
|
|
}
|
|
catch(gsmlib::GsmException &e)
|
|
{
|
|
kdWarning( 14160 ) << k_funcinfo<< e.what()<<endl;
|
|
m_run = false;
|
|
}
|
|
}
|
|
|
|
void GSMLibThread::sendMessageQueue()
|
|
{
|
|
QMutexLocker _(&m_outMessagesMutex);
|
|
|
|
if(m_outMessages.size() == 0 )
|
|
return;
|
|
|
|
KopeteMessageList::iterator it;
|
|
for( it=m_outMessages.begin(); it!=m_outMessages.end(); it++)
|
|
sendMessage(*it);
|
|
m_outMessages.clear();
|
|
}
|
|
|
|
void GSMLibThread::sendMessage(const Kopete::Message& msg)
|
|
{
|
|
QString reason;
|
|
|
|
if (!m_MeTa)
|
|
{
|
|
GSMLibEvent* e = new GSMLibEvent( GSMLibEvent::MSG_NOT_SENT );
|
|
e->Reason = QString("GSMLib: Not Connected");
|
|
e->Message = msg;
|
|
QApplication::postEvent(m_parent, e);
|
|
}
|
|
|
|
QString message = msg.plainBody();
|
|
QString nr = msg.to().first()->contactId();
|
|
|
|
// send SMS
|
|
try
|
|
{
|
|
gsmlib::Ref<gsmlib::SMSSubmitMessage> submitSMS = new gsmlib::SMSSubmitMessage();
|
|
gsmlib::Address destAddr( nr.latin1() );
|
|
submitSMS->setDestinationAddress(destAddr);
|
|
m_MeTa->sendSMSs(submitSMS, message.latin1(), true);
|
|
|
|
GSMLibEvent* e = new GSMLibEvent( GSMLibEvent::MSG_SENT );
|
|
e->Message = msg;
|
|
QApplication::postEvent(m_parent, e);
|
|
}
|
|
catch(gsmlib::GsmException &e)
|
|
{
|
|
GSMLibEvent* ev = new GSMLibEvent( GSMLibEvent::MSG_NOT_SENT );
|
|
ev->Reason = QString("GSMLib: ") + e.what();
|
|
ev->Message = msg;
|
|
QApplication::postEvent(m_parent, ev);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
GSMLib::GSMLib(Kopete::Account* account)
|
|
: SMSService(account)
|
|
{
|
|
prefWidget = 0L;
|
|
m_thread = NULL;
|
|
|
|
loadConfig();
|
|
}
|
|
|
|
GSMLib::~GSMLib()
|
|
{
|
|
disconnect();
|
|
}
|
|
|
|
void GSMLib::saveConfig()
|
|
{
|
|
if( m_account != NULL )
|
|
{
|
|
KConfigGroup* c = m_account->configGroup();
|
|
|
|
c->writeEntry(QString("%1:%2").arg("GSMLib").arg("Device"), m_device);
|
|
}
|
|
}
|
|
|
|
void GSMLib::loadConfig()
|
|
{
|
|
m_device = "/dev/bluetooth/rfcomm0";
|
|
if( m_account != NULL )
|
|
{
|
|
QString temp;
|
|
KConfigGroup* c = m_account->configGroup();
|
|
|
|
temp = c->readEntry(QString("%1:%2").arg("GSMLib").arg("Device"), QString::null);
|
|
if( temp != QString::null )
|
|
m_device = temp;
|
|
}
|
|
}
|
|
|
|
void GSMLib::connect()
|
|
{
|
|
|
|
m_thread = new GSMLibThread(m_device, this);
|
|
m_thread->start();
|
|
|
|
}
|
|
|
|
void GSMLib::disconnect()
|
|
{
|
|
kdDebug( 14160 ) << k_funcinfo <<endl;
|
|
|
|
if( m_thread )
|
|
{
|
|
m_thread->stop();
|
|
delete m_thread;
|
|
m_thread = NULL;
|
|
emit disconnected();
|
|
}
|
|
|
|
}
|
|
|
|
void GSMLib::setWidgetContainer(QWidget* parent, QGridLayout* layout)
|
|
{
|
|
m_parent = parent;
|
|
m_layout = layout;
|
|
QWidget *configWidget = configureWidget(parent);
|
|
layout->addMultiCellWidget(configWidget, 0, 1, 0, 1);
|
|
configWidget->show();
|
|
}
|
|
|
|
void GSMLib::send(const Kopete::Message& msg)
|
|
{
|
|
m_thread->send(msg);
|
|
}
|
|
|
|
QWidget* GSMLib::configureWidget(QWidget* parent)
|
|
{
|
|
|
|
if (prefWidget == 0L)
|
|
prefWidget = new GSMLibPrefsUI(parent);
|
|
|
|
loadConfig();
|
|
prefWidget->device->setURL(m_device);
|
|
|
|
return prefWidget;
|
|
}
|
|
|
|
void GSMLib::savePreferences()
|
|
{
|
|
if( prefWidget )
|
|
{
|
|
m_device = prefWidget->device->url();
|
|
}
|
|
saveConfig();
|
|
}
|
|
|
|
int GSMLib::maxSize()
|
|
{
|
|
return 160;
|
|
}
|
|
|
|
void GSMLib::customEvent(QCustomEvent* e)
|
|
{
|
|
if( e->type() != QEvent::User+GSMLIB_EVENT_ID )
|
|
return;
|
|
|
|
if( m_account == NULL )
|
|
return;
|
|
|
|
GSMLibEvent* ge = (GSMLibEvent*)e;
|
|
|
|
kdDebug( 14160 ) << "Got event "<<ge->subType()<<endl;
|
|
switch( ge->subType() )
|
|
{
|
|
case GSMLibEvent::CONNECTED:
|
|
emit connected();
|
|
break;
|
|
case GSMLibEvent::DISCONNECTED:
|
|
disconnect();
|
|
break;
|
|
case GSMLibEvent::MSG_SENT:
|
|
emit messageSent(ge->Message);
|
|
break;
|
|
case GSMLibEvent::MSG_NOT_SENT:
|
|
emit messageNotSent(ge->Message, ge->Reason);
|
|
break;
|
|
case GSMLibEvent::NEW_MESSAGE:
|
|
{
|
|
QString nr = ge->Number;
|
|
QString text = ge->Text;
|
|
|
|
// Locate a contact
|
|
SMSContact* contact = static_cast<SMSContact*>( m_account->contacts().find( nr ));
|
|
if ( contact==NULL )
|
|
{
|
|
// No contact found, make a new one
|
|
Kopete::MetaContact* metaContact = new Kopete::MetaContact ();
|
|
metaContact->setTemporary ( true );
|
|
contact = new SMSContact(m_account, nr, nr, metaContact );
|
|
Kopete::ContactList::self ()->addMetaContact( metaContact );
|
|
contact->setOnlineStatus( SMSProtocol::protocol()->SMSOnline );
|
|
}
|
|
|
|
// Deliver the msg
|
|
Kopete::Message msg( contact, m_account->myself(), text, Kopete::Message::Inbound, Kopete::Message::RichText );
|
|
contact->manager(Kopete::Contact::CanCreate)->appendMessage( msg );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString& GSMLib::description()
|
|
{
|
|
QString url = "http://www.pxh.de/fs/gsmlib/";
|
|
m_description = i18n("<qt>GSMLib is a library (and utilities) for sending SMS via a GSM device. The program can be found on <a href=\"%1\">%1</a></qt>").arg(url).arg(url);
|
|
return m_description;
|
|
}
|
|
|
|
#include "gsmlib.moc"
|
|
|
|
#endif
|
|
/*
|
|
* Local variables:
|
|
* c-indentation-style: k&r
|
|
* c-basic-offset: 8
|
|
* indent-tabs-mode: t
|
|
* End:
|
|
*/
|
|
// vim: set noet ts=4 sts=4 sw=4:
|
|
|