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.
tdenetwork/kopete/protocols/sms/services/gsmlib.cpp

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: