Blame src/examples/modify-headers.c

Packit a38265
/*
Packit a38265
   Copyright (C) 2007 Annodex Association
Packit a38265
Packit a38265
   Redistribution and use in source and binary forms, with or without
Packit a38265
   modification, are permitted provided that the following conditions
Packit a38265
   are met:
Packit a38265
Packit a38265
   - Redistributions of source code must retain the above copyright
Packit a38265
   notice, this list of conditions and the following disclaimer.
Packit a38265
Packit a38265
   - Redistributions in binary form must reproduce the above copyright
Packit a38265
   notice, this list of conditions and the following disclaimer in the
Packit a38265
   documentation and/or other materials provided with the distribution.
Packit a38265
Packit a38265
   - Neither the name of the Annodex Association nor the names of its
Packit a38265
   contributors may be used to endorse or promote products derived from
Packit a38265
   this software without specific prior written permission.
Packit a38265
Packit a38265
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit a38265
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit a38265
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit a38265
   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ASSOCIATION OR
Packit a38265
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit a38265
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit a38265
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit a38265
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit a38265
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit a38265
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit a38265
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit a38265
*/
Packit a38265
Packit a38265
#include <stdio.h>
Packit a38265
#include <stdlib.h>
Packit a38265
#include "oggz/oggz.h"
Packit a38265
Packit a38265
#define ID_WRITE_DIRECT
Packit a38265
/* define USE_FLUSH_NEXT */
Packit a38265
Packit a38265
#ifdef USE_FLUSH_NEXT
Packit a38265
static int flush_next = 0;
Packit a38265
#endif
Packit a38265
Packit a38265
typedef struct {
Packit a38265
  OggzTable * tracks;
Packit a38265
  OGGZ * reader;
Packit a38265
  OGGZ * writer;
Packit a38265
  FILE * outfile;
Packit a38265
} MHData;
Packit a38265
Packit a38265
static int
Packit a38265
read_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
Packit a38265
{
Packit a38265
  MHData * mhdata = (MHData *)user_data;
Packit a38265
Packit a38265
  if (fwrite (og->header, 1, og->header_len, mhdata->outfile) == (size_t)og->header_len)
Packit a38265
    if (fwrite (og->body, 1, og->body_len, mhdata->outfile) != (size_t)og->body_len)
Packit a38265
      return OGGZ_STOP_ERR;
Packit a38265
Packit a38265
  return OGGZ_CONTINUE;
Packit a38265
}
Packit a38265
Packit a38265
static int
Packit a38265
read_packet (OGGZ * oggz, oggz_packet * zp, long serialno, void * user_data)
Packit a38265
{
Packit a38265
  ogg_packet * op = &zp->op;
Packit a38265
  MHData * mhdata = (MHData *)user_data;
Packit a38265
  int flush;
Packit a38265
  int ret;
Packit a38265
Packit a38265
  if (op->b_o_s) {
Packit a38265
    /* Record this track in the tracks table. We don't need to store any
Packit a38265
     * information about the track, just the fact that it exists.
Packit a38265
     * Store a dummy value (as NULL is not allowed in an OggzTable).
Packit a38265
     */
Packit a38265
    oggz_table_insert (mhdata->tracks, serialno, (void *)0x01);
Packit a38265
  }
Packit a38265
Packit a38265
#ifdef USE_FLUSH_NEXT
Packit a38265
  flush = flush_next;
Packit a38265
  if (op->granulepos == -1) {
Packit a38265
    flush_next = 0;
Packit a38265
  } else {
Packit a38265
    flush_next = OGGZ_FLUSH_BEFORE;
Packit a38265
  }
Packit a38265
#else
Packit a38265
  if (op->granulepos == -1) {
Packit a38265
    flush = 0;
Packit a38265
  } else {
Packit a38265
    flush = OGGZ_FLUSH_AFTER;
Packit a38265
  }
Packit a38265
#endif
Packit a38265
Packit a38265
  /* Do something with the packet data */
Packit a38265
  if (op->packetno == 1) {
Packit a38265
    oggz_comments_copy (mhdata->reader, serialno, mhdata->writer, serialno);
Packit a38265
    oggz_comment_add_byname (mhdata->writer, serialno,
Packit a38265
                             "EDITOR", "modify-headers");
Packit a38265
    op = oggz_comments_generate (mhdata->writer, serialno, 0);
Packit a38265
  }
Packit a38265
Packit a38265
  /* Feed the packet into the writer */
Packit a38265
  if ((ret = oggz_write_feed (mhdata->writer, op, serialno, flush, NULL)) != 0) {
Packit a38265
    printf ("oggz_write_feed: %d\n", ret);
Packit a38265
  }
Packit a38265
Packit a38265
  /* Determine if we're finished processing headers */
Packit a38265
  if (op->packetno+1 >= oggz_stream_get_numheaders (mhdata->reader, serialno)) {
Packit a38265
    /* If this was the last header for this track, remove it from the
Packit a38265
       track list */
Packit a38265
    oggz_table_remove (mhdata->tracks, serialno);
Packit a38265
Packit a38265
    /* If no more tracks are left in the track list, then we have processed
Packit a38265
     * all the headers; stop processing of packets. */
Packit a38265
    if (oggz_table_size (mhdata->tracks) == 0) {
Packit a38265
      return OGGZ_STOP_ERR;
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  return OGGZ_CONTINUE;
Packit a38265
}
Packit a38265
Packit a38265
Packit a38265
int
Packit a38265
main (int argc, char ** argv)
Packit a38265
{
Packit a38265
  char * infilename, * outfilename;
Packit a38265
  MHData mhdata;
Packit a38265
  unsigned char buf[1024];
Packit a38265
  long n;
Packit a38265
Packit a38265
  if (argc < 3) {
Packit a38265
    printf ("usage: %s infile outfile\n", argv[0]);
Packit a38265
    exit (1);
Packit a38265
  }
Packit a38265
Packit a38265
  infilename = argv[1];
Packit a38265
  outfilename = argv[2];
Packit a38265
Packit a38265
  /* Set up reader */
Packit a38265
  if ((mhdata.reader = oggz_open (infilename, OGGZ_READ | OGGZ_AUTO)) == NULL) {
Packit a38265
    printf ("unable to open file %s\n", infilename);
Packit a38265
    exit (1);
Packit a38265
  }
Packit a38265
Packit a38265
  /* Set up writer, filling in mhdata for callbacks */
Packit a38265
  mhdata.tracks = oggz_table_new ();
Packit a38265
  if ((mhdata.writer = oggz_new (OGGZ_WRITE)) == NULL) {
Packit a38265
    printf ("Unable to create new writer\n");
Packit a38265
  }
Packit a38265
  mhdata.outfile = fopen (outfilename, "w");
Packit a38265
Packit a38265
  /* First, process headers packet-by-packet. */
Packit a38265
  oggz_set_read_callback (mhdata.reader, -1, read_packet, &mhdata);
Packit a38265
  while ((n = oggz_read (mhdata.reader, 1024)) > 0) {
Packit a38265
    while (oggz_write_output (mhdata.writer, buf, n) > 0) {
Packit a38265
      if (fwrite (buf, 1, n, mhdata.outfile) != (size_t)n)
Packit a38265
        break;
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  /* We actually don't use the writer any more from here, so close it */
Packit a38265
  oggz_close (mhdata.writer);
Packit a38265
Packit a38265
  /* Now, the headers are processed. We deregister the packet reading
Packit a38265
   * callback. */
Packit a38265
  oggz_set_read_callback (mhdata.reader, -1, NULL, NULL);
Packit a38265
Packit a38265
  /* We deal with the rest of the file as pages. */
Packit a38265
  /* Register a callbak that copies page data directly across to outfile */
Packit a38265
  oggz_set_read_page (mhdata.reader, -1, read_page, &mhdata);
Packit a38265
  while ((n = oggz_read (mhdata.reader, 1024)) > 0);
Packit a38265
Packit a38265
  oggz_close (mhdata.reader);
Packit a38265
Packit a38265
  oggz_table_delete (mhdata.tracks);
Packit a38265
Packit a38265
  fclose (mhdata.outfile);
Packit a38265
Packit a38265
  exit (0);
Packit a38265
}