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.
tdebase/khotkeys/shared/voices.cpp

304 lines
6.2 KiB

/****************************************************************************
KHotKeys
Copyright (C) 2005 Olivier Goffart <ogoffart @ kde.org>
Distributed under the terms of the GNU General Public License version 2.
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "voices.h"
#include "voicesignature.h"
#include "triggers.h"
#include "soundrecorder.h"
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kxerrorhandler.h>
#include <kkeynative.h>
#include <tqtimer.h>
#include <kglobalaccel.h>
#include <X11/Xlib.h>
#include <fixx11h.h>
namespace KHotKeys
{
Voice* voice_handler;
Voice::Voice( bool enabled_P, TQObject* parent_P )
: TQObject( parent_P) ,_enabled( enabled_P ), _recording( false ), _recorder(0)
{
assert( voice_handler == NULL );
voice_handler = this;
_kga=0L;
_timer=0L;
kdDebug(1217) << k_funcinfo << endl;
}
Voice::~Voice()
{
kdDebug(1217) << k_funcinfo << endl;
enable( false );
voice_handler = NULL;
}
void Voice::enable( bool enabled_P )
{
#ifndef HAVE_ARTS
enabled_P = false; // never enabled when there's no support
#endif
if( _enabled == enabled_P )
return;
_enabled = enabled_P;
if( _enabled ) // activate the shortcut
set_shortcut( _shortcut );
else
{
delete _kga;
_kga = NULL;
}
}
void Voice::register_handler( Voice_trigger *trigger_P )
{
if( !_references.contains( trigger_P ))
_references.append(trigger_P);
}
void Voice::unregister_handler( Voice_trigger *trigger_P )
{
_references.remove(trigger_P);
}
void Voice::record_start()
{
kdDebug(1217) << k_funcinfo << endl;
if(!_recorder)
{
_recorder= SoundRecorder::create(this);
connect(_recorder, TQT_SIGNAL(recorded(const Sound& )), this, TQT_SLOT(slot_sound_recorded(const Sound& )));
}
_recorder->start();
_recording=true;
}
void Voice::record_stop()
{
if(!_recording)
return;
kdDebug(1217) << k_funcinfo << endl;
delete _timer;
_timer=0L;
_recording=false;
if(_recorder)
_recorder->stop();
}
void Voice::slot_sound_recorded(const Sound &sound_P)
{
VoiceSignature signature(sound_P);
Voice_trigger *trig=0L;
Voice_trigger *sec_trig=0L;
double minimum=800000;
double second_minimum=80000;
int got_count=0;
TQValueList<Voice_trigger*>::Iterator it;
for ( it = _references.begin(); it != _references.end(); ++it )
{
for(int ech=1; ech<=2 ; ech++)
{
Voice_trigger *t=*it;
double diff=VoiceSignature::diff(signature, t->voicesignature(ech));
if(minimum>=diff)
{
second_minimum=minimum;
minimum=diff;
sec_trig=trig;
trig=t;
}
else if(second_minimum>=diff)
{
second_minimum=diff;
sec_trig=t;
}
if( diff < REJECT_FACTOR_DIFF )
got_count++;
kdDebug(1217) << k_funcinfo << ( (diff < REJECT_FACTOR_DIFF) ? "+++" : "---" ) <<t->voicecode() << ech << " : " << diff << endl;
}
}
// double ecart_relatif=(second_minimum-minimum)/minimum;
// kdDebug(1217) << k_funcinfo << ecart_relatif << endl;
if(trig)
kdDebug(1217) << k_funcinfo << "**** " << trig->voicecode() << " : " << minimum << endl;
// if(trig && ecart_relatif > REJECT_FACTOR_ECART_REL)
// if(trig && got_count==1)
bool selected=trig && (got_count==1 || ( minimum < 1.5*REJECT_FACTOR_DIFF && trig==sec_trig ) );
if(selected)
{
trig->handle_Voice();
}
}
/*bool Voice::x11Event( XEvent* pEvent )
{
if( pEvent->type != XKeyPress && pEvent->type != XKeyRelease )
return false;
KKeyNative keyNative( pEvent );
//kdDebug(1217) << k_funcinfo << keyNative.key().toString() << endl;
if(_shortcut.contains(keyNative))
{
if(pEvent->type == XKeyPress && !_recording )
{
record_start();
return true;
}
if(pEvent->type == XKeyRelease && _recording )
{
record_stop();
return true;
}
}
return false;
}
*/
void Voice::set_shortcut( const KShortcut &shortcut)
{
_shortcut = shortcut;
if( !_enabled )
return;
if(!_kga)
_kga = new TDEGlobalAccel( this );
_kga->remove("voice");
_kga->insert( "voice", i18n("Voice"), TQString::null, shortcut, 0, this, TQT_SLOT(slot_key_pressed())) ;
_kga->updateConnections();
}
void Voice::slot_key_pressed()
{
if( !haveArts())
return;
if( _recording )
record_stop();
else
{
record_start();
if(!_timer)
{
_timer=new TQTimer(this);
connect(_timer, TQT_SIGNAL(timeout()) , this, TQT_SLOT(slot_timeout()));
}
_timer->start(1000*20,true);
}
}
void Voice::slot_timeout()
{
if(_recording && _recorder)
{
_recorder->abort();
_recording=false;
}
_timer->deleteLater();
_timer=0L;
}
TQString Voice::isNewSoundFarEnough(const VoiceSignature& signature, const TQString &currentTrigger)
{
Voice_trigger *trig=0L;
Voice_trigger *sec_trig=0L;
double minimum=800000;
double second_minimum=80000;
int got_count=0;
TQValueList<Voice_trigger*>::Iterator it;
for ( it = _references.begin(); it != _references.end(); ++it )
{
Voice_trigger *t=*it;
if(t->voicecode()==currentTrigger)
continue;
for(int ech=1; ech<=2 ; ech++)
{
double diff=VoiceSignature::diff(signature, t->voicesignature(ech));
if(minimum>=diff)
{
second_minimum=minimum;
minimum=diff;
sec_trig=trig;
trig=t;
}
else if(second_minimum>=diff)
{
second_minimum=diff;
sec_trig=t;
}
if( diff < REJECT_FACTOR_DIFF )
got_count++;
kdDebug(1217) << k_funcinfo << ( (diff < REJECT_FACTOR_DIFF) ? "+++" : "---" ) <<t->voicecode() << ech << " : " << diff << endl;
}
}
if(trig)
kdDebug(1217) << k_funcinfo << "**** " << trig->voicecode() << " : " << minimum << endl;
bool selected=trig && ((got_count==1 && minimum < REJECT_FACTOR_DIFF*0.7 ) || ( minimum < REJECT_FACTOR_DIFF && trig==sec_trig ) );
return selected ? trig->voicecode() : TQString::null;
}
bool Voice::doesVoiceCodeExists(const TQString &vc)
{
TQValueList<Voice_trigger*>::Iterator it;
for ( it = _references.begin(); it != _references.end(); ++it )
{
Voice_trigger *t=*it;
if(t->voicecode()==vc)
return true;
}
return false;
}
} // namespace KHotKeys
#include "voices.moc"