The Receiver object is designed to interface with an application program to provide the facilities necessary to accept audio and video data from a network transport layer, and to play/display it for the application program.
To use the Receiver object, the application program needs to create the SOM environment, then instantiate the Receiver object and initialize it via method calls with parameters that specify the following information to the object:
In addition to the above required parameters, the application program needs to set up a callback routine to be invoked when the Receiver object needs to communicate back with the application program to indicate unexpected errors, or to notify of occurring events.
After the object is initialized and the callback routine is registered, the application program needs to issue the receive method call to notify the Receiver object to open the network connection and to begin listening for incoming data. After issuing this method call, the application program needs to enter an event loop to wait for and process events and errors that might be returned from the Receiver object.
When the Receiver detects incoming data, the application program is notified via the above mentioned callback routine that a SourceConnReq event has occurred. It is then the responsibility of the application program to issue either an accept_connection or a reject-connection method call to specify to the Receiver what it should do with the incoming data. The application program should then return to the event loop and wait for other events.
If the incoming stream contains video data, and the connection is accepted via the accept_connection method call, the Receiver issues another event called the NeedDisplayInfo event to inform the application program that it must supply an X Window display pointer (a window ID to be used to display the video data and the window ID of the user interface's toplevel widget). This information is then returned by the application program to the Receiver via the set_monitor_display_information method call.
In addition to processing receiver events, the application program can at any time while the Receiver object is in the receive mode (receive method call issued) alter or add the following parameters:
When the application program has completed, the program needs to issue the terminate method call and free the instantiated Receiver object before exiting.
The following sample code illustrates the preceding calling sequence:
#include <stdio.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <UMSNetReceiver.h>int main(int argc, char * argv[]) { int error_code; /* Returned error code */ int rc; /* Call return code */ long eventhandle; /* Event handle */
/* Create the user interface */ create_user_interface(&argc,argv); XFlush(display); XSync(display,FALSE); XtRealizeWidget(TopLevel);
Unlike the Sender object, the user interface does not need to be created first because it can be created when a request for display information is received from the Receiver. The base user interface is created first in this example simply for clarity. Later when a window is needed to display video, just the window needs to be created. The following calls create the Receiver object.
/* Initialize the SOM environment */ somEnv = somGetGlobalEnvironment(); SOM_InitEnvironment(somEnv);
/* Create the Receiver object */ netrecv = UMSNetReceiverNew(); if(netrecv == NULL) { printf(Unable to create Receiver object\n"); error_code = -1; goto ErrorExit; }
The following method calls set up the network connection and start the Receiver object running.
/* Setup the network connection */ if((rc=UMSNetReceiver_setup_h323 (netrecv,somEnv,"8.88.8.1","227.0.0.4",9005)) != UMSNetReceiver_Success) { printf("Unable to setup network connection. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
/* Issue the receive method call to wait for data */ if((rc=UMSNetReceiver_receive(netrecv,somEnv))!=UMSNetReceiver_Success){ printf("Unable to start receiver. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
An event/error handler must be registered to handle events and errors. The following method call and X call does this.
/* Flush all X events */ XSync(display,FALSE);
/* Get the event/error handle */ if((rc=UMSNetReceiver_get_event_handle(netrecv, somEnv, &eventhandle)) != UMSNetReceiver_Success) { printf("Unable to get event handle. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
/* Now register the event/error handler with the handle*/ XtInputID=XtAddInput(eventhandle,XtInputReadMask,ReceiverEvent,NULL);
Lastly, the application program enters an X event loop to wait for and process X events and Receiver events and/or errors.
/* Process X events and Receiver events and/or errors */ XtMainLoop();
ErrorExit: if(netrecv!=NULL) { UMSNetReceiver_terminate(netrecv,somEnv); _somFree(netrecv); } exit(error_code); }
The following routine is an example of the event/error handler that is registered above.
void ReceiverEvent(Widget w, int *fid, XtInputId *id) { UMSNetReceiver_EventData event_data; int rc; int error_code;
/* Get the event data */ if((rc = UMSNetReceiver_get_event(netrecv, somEnv, &event_data)) != UMSNetReceiver_Success) printf("Unable to get the next event. RC:%d\n",rc); if(netrecv !=NULL) _somFree(netrecv); SOM_UninitEnvironment(somEnv); exit(-1);} /* Process the event */
switch(event_data.type) { /* Error event */ case UMSNetReceiver_Error: printf("Network Receiver returned an error %d\n", event_data.specific); break; /* Request event */ case UMSNetReceiver_Request: /* Process the particuar request event */ switch(event_data.specific) { /* Connection request */ case UMSNetReceiver_SourceConnReq: /* Determine what the user wants to do about it. then */ /* either accept or reject the connection. */ /* In this example we will automatically accept it */ /* regardless if event_data.string1 contains the */ /* identifier. */ if((rc=UMSNetReceiver_accept_connection(netrecv, somEnv, event_data.long1, UMSNetReceiver_Any)) != UMSNetReceiver_Success) { printf("Unable to accept a connection. RC:%d\n",rc); error_code = -1; goto ErrorExit;} break; /* Receiver needs a window to display the video */ case UMSNetReceiver_NeedDisplayInfo: /* Create a window to be used to display the video. Be */ /* sure that the window is mapped before issuing the */ /* set_monitor method call. */ create_window(event_data.long2,event_data.long3); /* Now pass the window information back to the Receiver */ rc=UMSNetReceiver_set_monitor_display_information(netrecv, somEnv,event_data.long1,WindowID,TopWin, DisplayPtr); if(rc!= UMSNetReceiver_Success) { printf("Unable to send window information" "to the Network Receiver. RC:%d\n",rc); error_code = -1; goto ErrorExit; } break; default:;} default:;} return;
ErrorExit: if(netrecv!=NULL) { UMSNetReceiver_terminate(netrecv,somEnv); _somFree(netrecv); } exit(error_code); }
For introductory information, see Programming with Collaboration Objects.