diff options
Diffstat (limited to 'kopete/protocols/sms/services/gsmlib.cpp')
-rw-r--r-- | kopete/protocols/sms/services/gsmlib.cpp | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/kopete/protocols/sms/services/gsmlib.cpp b/kopete/protocols/sms/services/gsmlib.cpp new file mode 100644 index 00000000..e9b0542b --- /dev/null +++ b/kopete/protocols/sms/services/gsmlib.cpp @@ -0,0 +1,462 @@ +/* ************************************************************************* + * 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: + |