Always Use an Active Scheduler
This can't be stated enough: the multimedia subsystem cannot work without proper use of an active scheduler and associated active objects. Some APIs (for example, within ICL) explicitly use TRequestStatus to show asynchronous behavior and expect the client to drive them via an active object. With others, the behavior is callback-based and its asynchronous nature is hidden. Virtually all the APIs make extensive use of CActive-based active objects behind the scenes and need an active scheduler to operate correctly.
When making function calls from your main application, this should seem self-evident, because the same rules apply to the application framework. On Symbian OS, all standard applications run within an active scheduler, with calls made from the RunL() calls of individual active objects. You have to make an asynchronous call from one RunL() instance and exit without waiting for the response. For example, when handling menu events, you might write the following code to open a clip in a descriptor, pending play:
iPlayer->OpenDesL(*iMyBuffer);
1 Advice for C++ developers new to Symbian OS can be found in a range of Symbian Press books and booklets, available from developer.symbian.com/books, and in articles published online at developer.symbian.com.
You can fire off several such calls, but should then return through the AppUi::HandleCommandL() call or equivalent. At some later stage, the callbacks are made by the associated API implementation. At the root of these callbacks, there is always a RunL() call; if you have access to the Symbian OS source code then you can see this in the stack trace when you're debugging on the Windows emulator.
If you are running within the main application thread, this all comes for free-the standard application environment is itself based on active objects and needs an active scheduler. If you create your own threads, you need to create and install an active scheduler to get this to work. If you forget, the result is unpredictable - depending on the API - but, in general, not much will happen. The active objects are used not just for callback support but also for internal asynchronous processing.
Sometimes, you find yourself calling an asynchronous call from what was previously a synchronous function, for example when you are modifying existing applications to use the multimedia calls. It is preferable to redesign your main program: for instance to re-classify the calling function as asynchronous, so the underlying action is not considered 'finished' on return and to allow for actions in the background. Sometimes this is not possible or it looks undesirable. One option in this scenario is to use the CActiveSchedulerWait class, for which documentation is available in the Symbian Developer Library (in the Base section of the Symbian OS Reference).
Our experience is that it is less of a problem to use asynchronous styles of programming rather than forming synchronous calls from asynchronous ones. However, this is sometimes all you can do - sometimes you have to fit into an existing API structure that is synchronous. This is often the case if you are using existing code modules, perhaps ported from another operating system. If you do use CActiveSchedulerWait, then take extra care not to block program input while a relatively long action is occurring. Remember, the RunL() method in which you start the CActiveSchedulerWait is blocked until it returns.
Post a comment