Concepts with Symbian OS (779878), страница 53
Текст из файла (страница 53)
Initializing is allowed to beasynchronous, because it may take some time to set up the telephonydevice.When a phone subsession is open and the device has been initialized,applications can use the other functions of the phone device or makequeries of it thorough the RPhone class interface.Let’s continue the CPhoneCall class example. We need to expandthe implementation of the InitL() function to encompass initializingphones. The result is below:void CPhoneCall::InitL(){RTelServer::TPhoneInfo phoneInfo;RPhone::TLineInfo lineInfo;RPhone::TCaps capabilities;RLine::TCaps lCapabilities;TInt result;TInt phones,lines,calls;TFullName name;// code to initialize the telephony server connection// Get the information on the phone we needresult = iTelServer.GetPhoneInfo(0, phoneInfo);User::LeaveIfError(result);name.Copy(phoneInfo.iName);// Open the phone and get its capabilitiesresult = iGsmPhone.Open(iTelServer, name);User::LeaveIfError(result);result = iGsmPhone.GetCaps(capabilities);User::LeaveIfError(result);if ((capabilities.iFlags & RPhone::KCapsVoice) == 0)User::LeaveIfError(KErrNotSupported);// other code to init lines and calls}Note that the phone is initialized when the first asynchronous requestis sent.
So we do not need to call Initialize() from this initializationcode. In the code above, we retrieve the name of the first phone from thetelephony server and open it up. On a Nokia 8290 phone (a GSM phoneused in the United States), the name of this first phone is ‘GsmPhone1’.We conclude this code by making sure that the phone we obtained canindeed support voice capability.256TELEPHONYThe line abstractionOnce a subsession with a phone has been established, we may establish asubsession for a particular line.
The line implementation is implementedby the RLine class. As with RPhone objects, RLine object subsessionsare opened and closed with Open() and Close() functions.As with RPhone objects, RLine objects can be notified when properties of a line change. There are many different properties that can changeand this is reflected in the number of notification functions that are definedfor the RLine class. There are four notification functions, each with itsown cancellation function.
Each is also asynchronous and requires astatus variable for monitoring; notification functions are useful here.Let’s continue to flesh out the CPhoneCall class example. Initializinga line for a phone means getting its name and opening a subsession, asbelow:void CPhoneCall::InitL(){RTelServer::TPhoneInfo phoneInfo;RPhone::TLineInfo lineInfo;RPhone::TCaps capabilities;RLine::TCaps lCapabilities;TInt result;TInt phones,lines,calls;TFullName name;// code to initialize the telephony server and phone// Get the info on the line we need – we have hard-coded 2 to open// the 3rd line. In reality, one should use EnumerateLines() to// determine the required line on any particular phoneresult = iGsmPhone.GetLineInfo(2, lineInfo);User::LeaveIfError(result);name.Copy(lineInfo.iName);// Open the line and get its capabilitiesresult = iPhoneLine.Open(iGsmPhone, name);User::LeaveIfError(result);result = iPhoneLine.GetCaps(lCapabilities);User::LeaveIfError(result);if ((lCapabilities.iFlags & RLine::KCapsVoice) == 0)User::LeaveIfError(KErrNotSupported);// code to initialize call}A STRUCTURAL OVERVIEW257This example chooses the third line available on the phone and checksits capabilities.
On a Nokia 8290 phone, the third line is the voice line(the first two are fax and data lines) and the name of this line is Voice.The call objectWith a session established to the telephony server and phone and linesubsessions now open, we can finally open and manage a call. Callsare implemented by the RCall class. Before we discuss how to use thisclass, we should point out a few things about calls.• Calls have names, as with other telephony-server objects. The nameof a call is generated by the operating system through the TSY andreturned when a call subsession is opened. A ‘fully qualified name’ isone that includes call, line and phone information in the format:PhoneName::LineName::CallName• Opening a call subsession does not connect a call. As with phonesand lines, a call subsession must be opened before we can use acall.
Opening a subsession allows the telephony server to allocatememory and resources for a call but does not manipulate the call inany way.• Calls can be incoming as well as outgoing. In addition to instructingthe telephony server to make a call, we can instruct the server toanswer a call. Unlike the other layers in the model, a new subsessionis opened with calls other than Open() and Close(). The OpenNewCall() function in its several forms creates a new call in an idlestate.
OpenExistingCall() is more usually used to open a call inan ‘alerting’ state. A new call can be opened by referencing an opentelephony server session, a phone subsession or a line subsession.Subsessions can be opened with existing calls, i.e., calls in progress.This is done by applications that want to work with calls alreadyreceived or started by other applications.
For example, if one application placed a voice call, a second application could implement a calltimer. To hang up after a certain time period, the timer applicationwould have to open the existing call with the OpenExistingCall()function.258TELEPHONYAs an example, we can complete the CPhoneCall::InitL() function. Here, we simply open a new call subsession by referencing the linesubsession:void CPhoneCall::InitL(){RTelServer::TPhoneInfo phoneInfo;RPhone::TLineInfo lineInfo;RPhone::TCaps capabilities;RLine::TCaps lCapabilities;TInt result;TInt phones,lines,calls;TFullName name;// code to initialize server, phone and line// Open a new callresult = iPhoneCall.OpenNewCall(iPhoneLine, name);User::LeaveIfError(result);}On our Nokia phone, this call is assigned the name VoiceCall1.Although it may seem like a long journey, eventually all sessions andsubsessions are opened and initialized. At this point, we still have notmade a call, but the system is ready for this next step.Calls are made by instructing the Symbian phone to dial with a directorynumber or by connecting to an already dialed call.
To dial a call, we usethe Dial() function from the RCall class. Dialing functions come insynchronous or asynchronous varieties and can include call parameters.To illustrate this, let’s define the MakeCall() function from ourCPhoneCall example. We have decided to make the CPhoneCallclass an active object and we can use an asynchronous version of theDial() function:void CPhoneCall::MakeCall(TDesC& aNumber){iPhoneCall.Dial(iCallStatus, aNumber);iCallState = EDialing;SetActive();}Since we have already set up the telephony system, this is a simpleimplementation. The number is a string, and we return from this functionright away while the system dials the call.
When the call is dialed, theA STRUCTURAL OVERVIEW259status variable changes state and the active object’s RunL() function iscalled. We can implement this change by including the following codein the RunL() function:switch (iCallState){case EDialing:if (iCallStatus == KErrNone){// handle the successful call}else{// handle the call error}break;...This is just like the active object code we have seen before.If we have successfully created all the sessions and subsessions weneed, answering an incoming call is straightforward. The AnswerIncomingCall() function – in synchronous and asynchronous versions – allows the phone to answer the call.
Once a call has beenanswered, the application can monitor the call’s state and performvarious operations on it.If it is a data call, the application might want to access the data portdirectly for a time. For example, if it is making a call with a modem totransfer some data, the application might want the telephony server to takecare of dialing the phone number and connecting to the opposite side, butit will then want to take control to pass the data. This is done by ‘loaning’the data port to the application using the RCall::LoanDataPort()function. Once the data port has been used for the transmission of data, itcan be returned to the telephony server using the RecoverDataPort()function. While the port is loaned to the client it is possible that someETel operations are not available.For a call, there are a few notifications that the system can give anapplication.
The hook status (a phone is ‘on hook’ when it is idle and ‘offhook’ when it is being used), the call phase state, and the call durationcan be registered for notification. Remember that remote devices or theswitching network can terminate a call at any time without asking forpermission or giving prior warning.
The call state status is a representationof the state of a call as it passes through its lifecycle: idle, dialing, ringing,answering, connecting, connected, or hanging up. The call duration is260TELEPHONYthe time, in seconds, that the call has been active. Notification is sentevery second (useful for making an indication to the user based on theduration of the call).To avoid problems with multiple clients accessing the same call,Symbian OS designates a specific client as the owner of a call. Thisownership is initially passed to the client that connected to a phone callfirst, but it can be transferred to another client.