CTimer problem

Login to reply to this topic.
Sun, 2008-04-27 15:22
Joined: 2005-09-04
Forum posts: 135

Hi
On S60 3rd edition:
I send DTMF's during a voice call (which I initiate) using RMobilePhone::StartDTMFTone().
between each DTMF I call CTimer::After() in order to make a delay between DTMF's. the TimerExpired() method calls CActive::RunL() again and another DTMF is started.
The problem occures when I want to create a delay without sending DTMF (like a pause) ,
which means calling iTimer.After() without calling StartDTMFTone() - THE DELAY IS MUCH SHORTER THAN DEFINED.
Here is the code I use, any suggestions of how to correct this ?

Thank you

void CActiveClass::TimerExpired()
{
  RunL();
}
void CActiveClass::RunL()
{
  // --- when call is connected ---
  //if tone is "p" (pause)
  {
    dtmfIndex++;
    TTimeIntervalMicroSeconds32 interval = 2000000;// 2 seconds
    //###### 'PAUSE' DELAY - DOESN'T WORK - DTMF'S JUST CONTINUE #####
    iTimeOutTimer->After(interval);	
  }
  else // tone is numeric
  {
    iPhone.StartDTMFTone((DTMF_Buf->Des())[dtmfIndex]);// send DTMF
    dtmfIndex++;
    iPhone.StopDTMFTone();
    TTimeIntervalMicroSeconds32 interval = 100000;
    //### SHORT DELAY BETWEEN DTMF'S - WORKS WELL ###
    iTimeOutTimer->After(interval);
  }
  iLine.NotifyStatusChange(iStatus, iCallStatus); 
  SetActive();
}


Sun, 2008-04-27 20:59
Joined: 2003-12-05
Forum posts: 588
Re: CTimer problem

What worries me is that you call RunL yourself -- something you should never do. Only the scheduler calls the RunL, when the async operation has been done.

Mon, 2008-04-28 12:59
Joined: 2005-09-04
Forum posts: 135
Re: CTimer problem

Thanks Andreas I will keep that in mind.

If I'll put this code (below) inside the TimerExpired() method, do you think it would be ok?

//if tone is "p" (pause)
  {
    dtmfIndex++;
    TTimeIntervalMicroSeconds32 interval = 2000000;// 2 seconds
    iTimeOutTimer->After(interval);	
  }
  else // tone is numeric
  {
    iPhone.StartDTMFTone((DTMF_Buf->Des())[dtmfIndex]);// send DTMF
    dtmfIndex++;
    iPhone.StopDTMFTone();
    TTimeIntervalMicroSeconds32 interval = 100000;
    iTimeOutTimer->After(interval);
  }

Mon, 2008-04-28 16:03
Joined: 2004-11-29
Forum posts: 1142
Re: CTimer problem

are you really sure your timeout timer works at all?

Are you sure the delay isn't inside any of those dtmf functions or the line status?

to me that code looks a bit funky... what is the thought there?

If you have a active object that wants to send dtmf tones on some interval with the help of some timer, I would expect the runl to send new requests to the timer, but here you do some kind of request on an external timer, and then issue a request to the line status...
so next call to runl will not be when the timer times out, but when the line status request completes...

what is that iTimeouttimer and how is it supposed to work?

Tue, 2008-04-29 14:01
Joined: 2005-09-04
Forum posts: 135
Re: CTimer problem

Thank you for your reply alh

The iTimeouttimer inherits CTimer.

I tried to use RTimer also, this way (iTimer is a RTimer):

//### INSIDE CActive::RunL() - WHEN CALL STATUS IS CONNECTED ###
while(dtmfIndex<DTMF_Buf->Length())
{
  if tone is 'p'
  {
    dtmfIndex++;
    iTimer.After(iStatus,2000000);//2 sec delay
    User::WaitForRequest(iStatus);
  }
  else
  {
    iPhone.StartDTMFTone((DTMF_Buf->Des())[dtmfIndex]);
    dtmfIndex++;
    iPhone.StopDTMFTone();
    iTimer.After(iStatus,100000);//very short delay between DTMF's
    User::WaitForRequest(iStatus);
  }
}

I also tried User::After instead of iTimer.After.

The result was that the delay was much shorter than 2 seconds and further more - the rest of the DTMF's after the delay were not equal in their length and the short delay between them.

If you can suggest me a better way to do this, I'll be happy to hear about it !

Thank you very much Smiling

Tue, 2008-04-29 15:53
Joined: 2004-11-29
Forum posts: 1142
Re: CTimer problem

I would try splitting code up some, and not try to handle everything in the same CActive.
Trying to handle more then one kind of request in the same active object often gives weird and wonderful problems.

I would expect this second code block to work though (and also User::After), or at least not produce as weird results as you describe...

Sorry, don't think I can help much more then that...

Tue, 2008-04-29 16:00
Joined: 2003-12-05
Forum posts: 588
Re: CTimer problem

You shouldn't call User::WaitForRequest in RunL -- the AO framework (specifically, the CActiveScheduler) will do the waiting and call your RunL when the async request has been finished. Read a tutorial on using active objects, e.g. this: http://developer.symbian.com/main/downloads/papers/CActiveAndFriends/CActiveAndFriends.pdf

Also follow alh's suggestion to Keep It Simple Sir.

Tue, 2008-04-29 22:24
Joined: 2005-09-04
Forum posts: 135
Re: CTimer problem

Thank you both very much

Can you please explain what you mean by "splitting the code"?

Thanks

Sun, 2008-05-04 18:20
Joined: 2003-12-05
Forum posts: 588
Re: CTimer problem

Splitting the code means design -- design your classes to handle (optimally) only one thing per class. This is a good object oriented design heuristic. In practice, you can sometimes overlook this heuristic. So in your case let one active object handle one asynchronous service and implement another active object to handle some other asynchronous service.

Wed, 2008-05-07 13:15
Joined: 2005-09-04
Forum posts: 135
Re: CTimer problem

Hi Andreas
Thank you for the info.
Please advise,
what would be a good to communicate between 2 active objects? how can one object "tell" another objects to start a specific async request?

Thanks

Wed, 2008-05-07 14:15
Joined: 2004-11-29
Forum posts: 1142
Re: CTimer problem

The same way any other class would communicate to it, by storing a pointer or reference to the object and call a member function on it.

Wed, 2008-05-07 18:42
Joined: 2003-12-05
Forum posts: 588
Re: CTimer problem

// CA.h
class CB;

class CA : public CActive {
...
public:
   void DoBeDoBeDooL();
...
private:
  CB * iB;
};

// CB.h
class CB : public CActive {
...
public:
   void DamDiDamDiDamL();
...
private:
  RTimer iTimer;
};

//CA.cpp
...
void CA::DoBeDoBeDooL()
   {
   iB->DamDiDamDiDamL();
   }

// CB.cpp
void CB::DamDiDamDIDamL()
   {
   iTimer.After(iStatus, 1000000);
   SetActive();
   }

Thu, 2008-05-08 13:44
Joined: 2005-09-04
Forum posts: 135
Re: CTimer problem

Great , That is what I thought,
Thank you very much for your help!

  • Login to reply to this topic.