/* *************************************************************************
* 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 <tqcombobox.h>
# include <tqlayout.h>
# include <tqapplication.h>
# include <tqevent.h>
# include <tqmutex.h>
# include <tqthread.h>
# include <tqcheckbox.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 ) : TQCustomEvent ( TQEvent : : User + GSMLIB_EVENT_ID )
{
setSubType ( t ) ;
}
GSMLibEvent : : SubType GSMLibEvent : : subType ( )
{
return m_subType ;
}
void GSMLibEvent : : setSubType ( GSMLibEvent : : SubType t )
{
m_subType = t ;
}
/////////////////////////////////////////////////////////////////////
GSMLibThread : : GSMLibThread ( TQString 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 ;
TQApplication : : 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 = TQString ( " GSMLib: Not Connected " ) ;
e - > Message = msg ;
TQApplication : : 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 ) ;
TQApplication : : 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 ( ) ;
TQApplication : : postEvent ( m_parent , e ) ;
}
m_newMessages . clear ( ) ;
}
catch ( gsmlib : : GsmException & e )
{
kdWarning ( 14160 ) < < k_funcinfo < < e . what ( ) < < endl ;
m_run = false ;
}
}
void GSMLibThread : : sendMessageQueue ( )
{
TQMutexLocker _ ( & 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 )
{
TQString reason ;
if ( ! m_MeTa )
{
GSMLibEvent * e = new GSMLibEvent ( GSMLibEvent : : MSG_NOT_SENT ) ;
e - > Reason = TQString ( " GSMLib: Not Connected " ) ;
e - > Message = msg ;
TQApplication : : postEvent ( m_parent , e ) ;
}
TQString message = msg . plainBody ( ) ;
TQString 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 ;
TQApplication : : postEvent ( m_parent , e ) ;
}
catch ( gsmlib : : GsmException & e )
{
GSMLibEvent * ev = new GSMLibEvent ( GSMLibEvent : : MSG_NOT_SENT ) ;
ev - > Reason = TQString ( " GSMLib: " ) + e . what ( ) ;
ev - > Message = msg ;
TQApplication : : 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 ( TQString ( " %1:%2 " ) . arg ( " GSMLib " ) . arg ( " Device " ) , m_device ) ;
}
}
void GSMLib : : loadConfig ( )
{
m_device = " /dev/bluetooth/rfcomm0 " ;
if ( m_account ! = NULL )
{
TQString temp ;
KConfigGroup * c = m_account - > configGroup ( ) ;
temp = c - > readEntry ( TQString ( " %1:%2 " ) . arg ( " GSMLib " ) . arg ( " Device " ) , TQString : : null ) ;
if ( temp ! = TQString : : 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 ( TQWidget * parent , TQGridLayout * layout )
{
m_parent = parent ;
m_layout = layout ;
TQWidget * configWidget = configureWidget ( parent ) ;
layout - > addMultiCellWidget ( configWidget , 0 , 1 , 0 , 1 ) ;
configWidget - > show ( ) ;
}
void GSMLib : : send ( const Kopete : : Message & msg )
{
m_thread - > send ( msg ) ;
}
TQWidget * GSMLib : : configureWidget ( TQWidget * 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 ( TQCustomEvent * e )
{
if ( e - > type ( ) ! = TQEvent : : 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 :
{
TQString nr = ge - > Number ;
TQString 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 TQString & GSMLib : : description ( )
{
TQString 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: