
 NAME
 ====
 abcde - create a simple demo RIFF file

 SYNOPSIS
 ========

  abcde

 DESCRIPTION
 ===========
 This program creates a RIFF file with the following 
 structure. FRM1 is a form, CHKA is a single chunk, and LSTA is
 a list containing chunks CHKB and CHKC.

|   FRMA --- CHKB
|            LSTC - CHKD
|                   CHKE

| 

 We will use routines from the Standard C library, RIFFIO and STDCRIFF.

| 
| #include <stdio.h>
| #include "riffio.h"
| #include "stdcriff.h"
| 
| extern void doerror(const char *strMessage);
| 
| int
| main()
| {
| 

 We need a Standard C FILE pointer to our new RIFF file.

| 
|     FILE        *pFILEOut; /* The new RIFF file */  
|     

 We also need an associated RIFFIOFile for RIFFIO file operations.

| 
|     RIFFIOFile  *prf;      /* Also the new RIFF file */
| 
    
 Chunk information is stored in RIFFIOChunk structures. There are 
 no RIFFIOChunkNew() or RIFFIOChunkDelete() routines; we can simply 
 define RIFFIOChunks.

 We need three chunk variables because we have to keep 
 chunk information around until the chunk contents are finalized.
 For example, LSTC cannot be finialized until CHKD and CHKE are written. 

| 
|     RIFFIOChunk chunkForm;  /* FRMA */
|     RIFFIOChunk chunkList;  /* LSTC */
|     RIFFIOChunk chunkChunk; /* CHKB, CHKD, CHKE */
| 

 Open the Standard C library RIFF file for writing and 
 associate it with RIFFIOFile. 
 Make sure the file is opened in binary mode.

| 
|     pFILEOut = fopen("abcde.rif", "wb");
|     if (!pFILEOut)
|         doerror("Can't open abcde.rif for writing");
|     
|     prf = RIFFIOFileNew();
|     if (! prf)
|         doerror("RIFFIOFileNew failed");
|     
|     if (! RIFFIOFileInit(prf, pFILEOut,
|                          STDCRIFFRead, STDCRIFFWrite, 
|                          STDCRIFFSeek, STDCRIFFTell))
|         doerror("RIFFIOFileInit Failed");
| 

 First we must create the form chunk. We do so by filling in the
 form's chunk id (RIFF or RIFX),the form type (FRMA in our case),
 and optionally the form's data size.  Because this example is so
 simple, we could conceivably predict the size of the entire
 form. Ordinarily that would be too difficult so we will leave
 chunkForm.sizeData alone and let RIFFIOChunkFinalize() calculate it
 later. Once the chunkForm's members are initialized we call
 RIFFIOChunkCreate() to write the chunk's header.  

|     chunkForm.fccId = RIFFIO_FOURCC_RIFF;
|     chunkForm.fccType = RIFFIOMAKEFOURCC('F','R','M','A');
| 
|     if (! RIFFIOChunkCreate(prf, &chunkForm))
|         doerror("Couldn't create form chunk");
| 

 RIFFIOChunkCreate() fills in other, private, fields of <chunkForm> that 
 are used later by RIFFIOChunkFinalize().

 RIFFIOChunkCreate() leaves the RIFF file positioned at the start of
 the new chunk's contents.  In this case we are poised to write the
 first chunk of the form, CHKB.

 Because CHKB is neither a form or a list we can ignore the fccType
 member of the chunk. CHKB will be empty, so we can immediately call
 RIFFIOChunkFinalize() to complete the chunk.  

|     chunkChunk.fccId = RIFFIOMAKEFOURCC('C','H','K','B');
|     chunkChunk.sizeData = 0;
|     
|     if (! RIFFIOChunkCreate(prf, &chunkChunk))
|         doerror("Couldn't create chunk CHKB");
|     
|     if (! RIFFIOChunkFinalize(prf, &chunkChunk))
|         doerror("Couldn't finalize chunk CHKB");
| 

 RIFFIOChunkFinalize() updates CHKB's size in the RIFF file if necessary.
 It then writes an NUL pad byte of the chunk has an odd size and leaves
 the RIFF file positioned at the end of the chunk.

 We can now start LSTC.

|         chunkList.fccId = RIFFIO_FOURCC_LIST;
|         chunkList.fccType = RIFFIOMAKEFOURCC('L','S','T','C');
|     
|         if (! RIFFIOChunkCreate(prf, &chunkList))
|                 doerror("Couldn't create chunk LSTC");
| 

 We will reuse chunkChunk to write CHKD. CHKD will contain 18 bytes
 of data so we will demonstrate filling in the sizeData member 
 (even though we really don't need to).

|     chunkChunk.fccId = RIFFIOMAKEFOURCC('C','H','K','D');
|     chunkChunk.sizeData = 18; /* predict the chunk size */
| 
|     if (! RIFFIOChunkCreate(prf, &chunkChunk))
|         doerror("Couldn't create chunk <CHKD>");
|     
|     RIFFIOWrite(prf, "This is CHKD data.", 18); 
|     
|     if (! RIFFIOChunkFinalize(prf, &chunkChunk))
|         doerror("Couldn't finalize chunk <CHKD>");
|     

 When we write CHKE we will let RIFFIOChunkFinalize() calculate the
 correct size.
    
|     chunkChunk.fccId = RIFFIOMAKEFOURCC('C','H','K','E');
|     chunkChunk.sizeData = 999; /* Wrong but will be fixed automatically */
| 
|     if (! RIFFIOChunkCreate(prf, &chunkChunk))
|         doerror("Couldn't create chunk <CHKD>");
|     
|     RIFFIOWrite(prf, "This is CHKE data.", 18); 
|     
|     if (! RIFFIOChunkFinalize(prf, &chunkChunk))
|         doerror("Couldn't finalize chunk <CHKD>");
| 

 Here is the end of LSTC.

|     if (! RIFFIOChunkFinalize(prf, &chunkList))
|         doerror("Couldn't finalize list <LSTC>");
| 

 Here is the end of FRMA.

|     if (! RIFFIOChunkFinalize(prf, &chunkForm))
|         doerror("Couldn't finalize form <FRMA>");
|     

 We are done writing chunks. It is time to clean up. 

| 
|     RIFFIOFileDelete(prf);
| 

 Even though we have deleted the RIFFIOFile we still haven't officially
 closed the Standard C Libarary representation. 

| 
|     fclose(pFILEOut);                
| 
|     return 0;
| 
| }
| 

 Report an error and exit.

| void
| doerror(const char *strMessage)
| {
|         fprintf(stderr, "%s\n", strMessage);
|         exit(1);
| }
