summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/sms/services/gsmlib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/sms/services/gsmlib.cpp')
-rw-r--r--kopete/protocols/sms/services/gsmlib.cpp462
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 <[email protected]> *
+ *************************************************************************
+*/
+
+/* *************************************************************************
+ * *
+ * 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:
+