Skip to main content

Courier Sample App

Description

In this tutorial, a SampleApp application is created to explain the main building blocks of a Courier application. Among others, the following use cases will be implemented step-by-step:

  • Upon Courier::StartupMessage, the application will show the ClusterScene already known from the CGI Studio Getting Started example
  • Play the CarGeneric animation, triggered by a Courier message
  • Finally, a Courier::ShutdownMessage will be fired to finish the application

For the application code, refer to

  • cgi_studio_courier_apps/src/CourierSampleApp

Configuration

1. Setup Visual Studio Solution "CourierSampleApp.sln"

  • Start CMake;
  • Set "Where is the source code:" to <cgi_studio_root>/cgi_studio_courier_apps/src/CourierSampleApp;
  • Set "Where to build the binaries:" to <cgi_studio_root>/cgi_studio_courier_apps/src/CourierSampleApp/build. Note that the name of the build directory can be freely chosen. Avoid blanks in the path;
  • Click "Configure", select "Visual Studio 12", confirm the dialog with OK. You can see some lines in the main area appearing;
  • Check "COURIER_ADD_SCHOST_PROJECT" check-box;
  • Set "COURIER_PLATFORM" to the platform you want to use - e.g. iMX6IntegrityPlatform;
  • Click "Configure" again and wait until it says "Configuring done";
  • Click "Generate", the solution is generated. Wait for the message "Generating done".

2. Start Visual Studio C++ and load the generated solution from <cgi_studio_root>/cgi_studio_courier_apps/src/CourierSampleApp/build/CourierSampleApp.sln.

3. Set project "CourierSampleApp" as startup project in VisualStudio.

4. Press F7 to build the application.

5. Generate an AssetLibrary from the CourierSampleApp's SceneComposer solution:

  • Start SceneComposer
  • Open the CourierSampleApp's SceneComposer solution in SceneComposer. Appropriate solutions for all platforms can be found in <cgi_studio_root>/cgi_studio_courier_apps/src/CourierSampleApp/SCSolution. Choose the folder of your preferred platform; the file to open in SceneComposer is called "Solution.scs".
  • Now, generate the AssetLibrary via the menu "Generate Asset Library..." or "Ctrl+G". In the "Generate Asset Library" dialog set the "Asset Location:" to the build directory you chose for CMake (e.g. <cgi_studio_root>/cgi_studio_courier_apps/src/CourierSampleApp/build). Change the name of the generated file to "AssetLibCff.bin" and click the button "Generate".

6. Switch to VisualStudio again and press F7 to execute the application.

7. You should now be able to see the see a window showing the same scene you just saw in SceneComposer when generating the AssetLibrary.

Chapters



Main.cpp 

Implement Main.cpp

A simple Main.cpp is implemented to initialize Courier and create, init and start a "SampleApp" application instance. Refer to cgi_studio_courier_apps/src/CourierSampleApp/Main.cpp

AppEnvironment

The application environment configuration part of the SampleApp example provides the following features:

  • logging settings,
  • asset configuration,
  • platform component,
  • platform-specific display and event handling.

Refer to cgi_studio_courier_apps/src/CourierSampleApp/AppPlatform/AppEnvironment.h.

Courier::Init

Basic courier functionality like a message router must be intialized before starting a Courier application.

CourierSampleApp

The CourierSampleApp itself is implemented as a class which implements only a few methods like Init, Run and Finalize. Those methods are suitable for this pretty simple sample. Anyway it is up to the implementer of an application how to structure the "application".

Back to the menu


AppEnvironment - Asset Configuration 

Courier::AssetConfiguration

To configure the asset repositories which shall be used by the Courier ViewHandler component to load assets, Courier provides an implementation of Candera::AssetConfig, namely Courier::AssetConfiguration.

The following code shows the instantiation of a Candera::FileAssetRepository. Alternatively Candera::MemoryAssetRepository could be used or a complete set of assets which are later registered.


The FileAssetRepository is then added to an instance of Courier::AssetConfiguration:


Finally, the Courier ViewHandler must be initialized with this asset configuration - refer to Courier::ViewHandler::Init - this will be done later during SampleApp initialization.

Configure ViewIDs and ItemIds

For accessing single views, view containers, animations, widgets or other parts of the asset(s), it is recommended to provide corresponding constants. For the ClusterScene, following constants and IDs are defined:


Refer to cgi_studio_courier_apps/src/CourierSampleApp/Constants.h and .cpp

Back to the menu


CourierSampledApp - Initialization 

Building Block Declarations

The following building blocks are used inside the SampleApp:


As you can see, the SampleApp example only derives two standard Courier classes:


There are standard render components for 3D only, 2D only, as well as 3D and 2D available.

Take care to use the render component appropriate to the content to be rendered.

Init Building Blocks

The SampleApp Init method is called to initialize all building blocks, like adding the asset to the asset configuration, registering factories to the ViewHandler and others.



Source of errors are usually misconfigured assets, e.g. the asset file cannot be found or the asset was generated by an incompatible CGI SceneComposer (wrong asset version).

In such a case, the Init method of the ViewHandler would fail.

Back to the menu


SampleApp - Start Message Processing 

Attaching Components to Threads

Although the described activities could also be part of the initialization phase they are described separately in this chapter. All components have to be attached to the applications Courier::ComponentMessageReceiver instance. Alternatively, different multi-threading strategies can be realized by attaching components to different messaging threads.

In the SampleApp example, a single thread is used for all components, which means they are all attached to the MsgReceiver instance of the application.


Starting Message Loop

After having attached the components to the message receiver instance, a StartupMsg broadcast message is posted.


After that, the message receiver main loop starts.

  • The Process method dispatches the messages and invokes the Execute methods of all attached components - e.g., in case of the RenderComponent, the Execute method implements the rendering functionality.
  • The main loop is executed until shut-down is triggered by one of the components attached to this message receiver.


For a detailed description of message processing, please refer to Message Processing.

Back to the menu

SampleAppControllerComponent - Show Scene upon Courier::StartupMsg 

Handle StartupMsg

As shown on the previous page, the broadcast message Courier::StartupMsg has been fired by the SampleApp. Any component attached to the message receiver could handle this message.

In the CourierSampleApp example, the job is done by the application specific controller component SampleAppControllerComponent, which consumes the Courier::StartupMsg in its OnMessage method implementation:


To make the ClusterScene visible right after startup, it must be loaded from the asset and be activated. This is achieved by posting corresponding standard Courier messages - Courier::ViewReqMsg and Courier::ActivationReqMsg - handled by view components like view handler.

SampleAppViewFactory

The simplest way to load all the views available via AssetConfiguration is to post a Courier::ViewReqMsg with parameter "ViewAction::CreateAll". See this example:

           //This message creates the hierarchical structure "automatically"
           postMsg = (COURIER_MESSAGE_NEW(ViewReqMsg)(ViewAction::CreateAll, ViewId(""), false));
           rc = rc && (postMsg!=0 && postMsg->Post());

However, in our CourierSampleApp example, we want to control the creation of the required views regarding memory management. That's why the application specific view factory SampleAppViewFactory is implemented with the following code:


Besides the Create method, the SampleAppViewFactory must also implement a regarding Destroy method - refer to cgi_studio_courier_apps/src/CourierSampleApp/SampleAppViewFactory.cpp.

Back to the menu

Play an Animation with Courier::AnimationReqMsg 

Key Event Handling

In our CourierSampleApp application we want to check key strokes from the keyboard and transform them to some Courier::KeyDownMsg which allow controlling the application logic.

For this purpose the Win32 Host environment provides a platform specific Component which will be attached to the main Courier::ComponentMessageReceiver.

 


This system will allow catching Win32 messages and converting them to Courier::KeyDownMsg which are platform independent. The platform specific Win32MessagePumpComponent allows cyclic "peeking" of Win32 messages and post them to the Courier::Platform::ExtComm::Windows::WindowsExternalInputDeliverer. This WindowsExternalInputDeliverer will then pass Win32 messages to the Courier::Platform::ExtComm::Windows::WindowsExternalInputHandling objects own thread which finally create and post the Courier::KeyDownMsg. It is up to the platform implementation how Courier::KeyDownMsg are created.

Key events on Win32 host are posted by Courier::Platform::ExtComm::Windows::WindowsExternalInputHandling (as long as no application specific input handling hook is activated), so the SampleAppControllerComponent can handle Courier::KeyDownMsg similar to the Courier::StartupMsg in its OnMessage method implementation.

Handle Key Events to trigger Animation Playing

Since we want to provide several keys to start, stop, pause, resume and fast finish the CarGeneric animation, the Courier::AnimationReqMsg needs to be configured accordingly. See following code:


Like view request and activation messages, also the standard Courier::AnimationReqMsg will be processed by related Courier view handler components.

Back to the menu


Shutdown 

Shutdown Application

At the end of Courier Sample App, shutting down the application is not a big deal anymore:

  • Any of the components involved needs to trigger a Courier::ShutdownMsg,
  • which will be handled by standard Courier components to savely free all used resources.
  • Finally the SampleApp::Run method will finish, once the message receiver returns true for Courier::ComponentMessageReceiver::IsShutdownTriggered.

The SampleAppControllerComponent triggers the ShutdownMsg upon a 'Q' key down event:


Refer to the following tutorial chapters to learn more about the details of message processing, component architecture, data binding, and other advanced topics:

Back to the menu