/**
@page smpl_record_syn  NiRecordSynthetic.cpp - sample program

	<b>Source file:</b> Click the following link to view the source code file:
		- NiRecordSynthetic.cpp
	
	This section describes an OpenNI sample program for generating and recording synthetic data.
		
	The program opens a recording, performs a transformation on the data from the recording, and then re-records the transformed data.
	
	The documentation describes the sample program's code from the top of the program file(s) to bottom.
	
	Every OpenNI feature is described the first time it appears in this sample program. Further appearances of the same feature are not described again.	
	
	
	@section rec_syn_xform_depthmd transformDepthMD() function
	
		The following function provides the code for performing a transformation on the image data generated by the OpenNI @ref prod_graph "nodes". The function is described further below feature by feature. 
		@code	
			void transformDepthMD(DepthMetaData& depthMD)
			{
				DepthMap& depthMap = depthMD.WritableDepthMap();
				for (XnUInt32 y = 0; y < depthMap.YRes(); y++)
				{
					for (XnUInt32 x = 0; x < depthMap.XRes(); x++)
					{
						//Punch vertical cut lines in the depth image
						if ((x % 2) == 0)
						{
							depthMap(x, y) = 0;
						}
					}
				}
			}		
		@endcode	
		
		In the above, the @ref xn::DepthMetaData "DepthMetaData" object provides a @ref glos_frame_object "frame object" for the @ref xn::DepthGenerator node. The @ref glos_frame_object "frame object" of a @ref dict_gen_node "generator node" contains a snapshot of generated data frame and all its associated properties. This data frame and its properties are accessible through the node's metadata object.	

		<code>DepthMap</code> is a Map Wrapper class. The Map Wrapper classes are light wrappers for @ref glos_frame_object maps.
		
		The @ref xn::DepthMetaData::WritableDepthMap() "WritableDepthMap()" method gets a light object to wrap the writable depth map. So this initializes the DepthMap map wrapper class.		
		@code	
			DepthMap& depthMap = depthMD.WritableDepthMap();
		@endcode

		The following double loop provides the x and y indexes to access each pixel in the <code>DepthMap</code>. The @ref xn::DepthMap::XRes "XRes()" and @ref xn::DepthMap::YRes "YRes()" methods return the two dimensions of the data frame, width and height, respectively. 
		@code	
			for (XnUInt32 y = 0; y < depthMap.YRes(); y++)
			{
				for (XnUInt32 x = 0; x < depthMap.XRes(); x++)
				{
				 ...
				} 
			}
		@endcode			
		
		Here is the code that performs the data transformation. It punches vertical 'cut' lines in the depth image.
		@code	
			if ((x % 2) == 0)
			{
				depthMap(x, y) = 0;
			}		
		@endcode	
		
				
	@section rec_syn_mainprg main() &ndash; Main Program
	
		@subsection rec_syn_mainprg_dcl_blk Main Program Declaration Block		
			
		@subsection rec_syn_record Initializing the Log from an XML file
	
			In the following, the @ref xn::xnLogInitFromXmlFile() method function initializes the log from an XML file. It initializes only the log; not the context or production graph.  			 
			@code		
				nRetVal = nRetVal = xnLogInitFromXmlFile(SAMPLE_XML_PATH);
				if (nRetVal != XN_STATUS_OK)
				{
					printf("Log couldn't be opened: %s. Running without log", xnGetStatusString(nRetVal));
				}
			@endcode
		
		
		@subsection rec_syn_getparams Creating and Setting up the Nodes
		
			The following initializes the @ref xn::Context object. This is where the application builds an OpenNI production graph. The <i>production graph</i> is a network of <i>production nodes</i> and is the principal OpenNI object structure.
			@code		
				Context context;
				nRetVal = context.Init();
			@endcode
			
					
			The @ref xn::Context::OpenFileRecording() "OpenFileRecording()" method replays a recorded file of a session of OpenNI data generation exactly as it was recorded. This includes recreating the whole @ref prod_graph "production graph", with all its nodes, that was built to run the original data generation session. This method performs this replaying by also creating a 'mock node' for each node in the file, and populates it with the recorded configuration. For an example of a mock node, see @ref xn::MockDepthGenerator.
			@code
				Player player;
				nRetVal = context.OpenFileRecording(strInputFile, player);
			@endcode	
			
			In the following code, the @ref xn::Context::FindExistingNode() "FindExistingNode()" method call gets a reference to a production node in the production graph. This sample program passes the <code>depth</code> parameter to get a reference to a @ref xn::DepthGenerator "DepthGenerator node" so that it can work with it. A @ref xn::DepthGenerator node generates a depth map. Each map pixel value represents a distance from the sensor.
			@code
			DepthGenerator depth;
			nRetVal = context.FindExistingNode(XN_NODE_TYPE_DEPTH, depth);
			@endcode

			// Create mock node based on depth node from recording
			The following declares a mock node. This is to simulate an actual node when recording or playing data from a recording. A mock node does not contain any logic for generating data. Instead, it allows an outside component (such as an application or a real node implementation) to feed it configuration changes and data.  
			@code
				MockDepthGenerator mockDepth;
			@endcode
			
			In the following statement, the @ref xn::MockDepthGenerator node::CreateBasedOn() "CreateBasedOn()" method <i>creates</i> a "mock" @ref xn::DepthGenerator "DepthGenerator" node based on the type and properties of the base node, in this case the <code>depth</code> node. This node does not represent an actual node, but only keeps a state and implements an interface above it. Mock nodes are specifically used for simulating nodes for playing recordings, or for use in tests. 
			@code
				nRetVal = mockDepth.CreateBasedOn(depth);
			@endcode

			In the following, the call to @ref xn::Recorder::Create() "Create()" initalizes a Recorder object. This object records to a specified destination medium the frames of data from each node that was added to it.   	
			@code	
				Recorder recorder;
				nRetVal = recorder.Create(context);
			@endcode
			
			In the following statement, the call to @ref xn::Recorder::SetDestination() "SetDestination()" specifies to where the recorder must send its recording. This is a disk file of ONI type.
			@code			
				nRetVal = recorder.SetDestination(XN_RECORD_MEDIUM_FILE, strOutputFile);
			@endcode		
			
			The following statement adds the node to the recording, and starts recording it.
			@code
				nRetVal = recorder.AddNodeToRecording(mockDepth);
			@endcode
			
			The following statement specifies that the player will not automatically rewind to the beginning of the recording after reaching the end of the recording (the default behavior is to rewind).
			@code
				nRetVal = player.SetRepeat(FALSE);
			@endcode	
			
			The next code block gets the number of frames of a specific node played. In the case of this sample program this is just a statistic to print later on the console.
			@code
				XnUInt32 nNumFrames = 0;
				nRetVal = player.GetNumFrames(depth.GetName(), nNumFrames);
			@endcode
			
			The following declares a metadata object for the DepthGenerator node. The metadata object is described above in the 
			@ref rec_syn_xform_depthmd transformDepthMD() function.
			@code
				DepthMetaData depthMD;
			@endcode
		
		@subsection rec_syn_main_loop Main Program Loop
		
			Following is the main program loop. It waits for available data from the generator and prints it out. The call to the n::Generator::WaitAndUpdateData() "WaitAndUpdateData()" method updates the node's application buffer to the latest available data, first waiting for the  node to have new data available. Since this method is being fed from a recording, the end of the recording is indicated by returning the XN_STATUS_EOF value. 
			
			Note that the @ref xn::Generator::WaitAndUpdateData() "WaitAndUpdateData()" method has to be called for each and every iteration to refresh the node's data.
			@code
				while ((nRetVal = depth.WaitAndUpdateData()) != XN_STATUS_EOF)
				{
					...
				}
			@endcode			
			
			The statements of body of the main loop are presented and explained, in the following.
			
			The following statement gets the DepthGenerator node's @ref glos_frame_object "frame object" (the @ref xn::DepthMetaData frame object). The metadata object is described above in the @ref rec_syn_xform_depthmd transformDepthMD() function.
			@code	
				depth.GetMetaData(depthMD);
			@endcode
			
			Enable the depth map to be modified. In the following statement, the call to the @ref xn::OutputMetaData::MakeDataWritable() "MakeDataWritable()" allocates a buffer and copies current data to it, so that the data can be edited. 
			@code	
				nRetVal = depthMD.MakeDataWritable();
			@endcode	
			
			The following statement makes a call to the transformDepthMD(), already described above in @ref rec_syn_xform_depthmd. This call transforms the data.
			@code	
				transformDepthMD(depthMD);
			@endcode	
			
			The following statement passes the transformed data to the @ref xn::MockDepthGenerator object. The call to the @ref xn::MockDepthGenerator::SetData() "SetData()" method sets the data of the mock node from a metadata object.
			@code	
				nRetVal = mockDepth.SetData(depthMD);
			@endcode	
			
			The following statement records one frame of data from each node that was added to the recorder by the @ref xn::Recorder::AddNodeToRecording() "AddNodeToRecording()" method.  To record continually, the Recorder node must be called repeatedly for each frame.
			@code	
				nRetVal = Recorder.Record();
			@endcode	

			Finally, this sample program prints status information. In the statement below, the @ref xn::OutputMetaData::FrameID() "FrameID()" method gets the frame ID of @ref glos_frame_object "frame object". Frame IDs are a sequential unique number. 
			@code	
				printf("Recorded: frame %u out of %u\r", depthMD.FrameID(), nNumFrames);
			@endcode	

*/


