[xiph-cvs] cvs commit: vorbis-python/src vcedit.c vcedit.h pyvorbiscodec.c pyvorbisinfo.c pyvorbisinfo.h

Andrew Catham Master of Python andrew at xiph.org
Mon Jan 21 17:57:58 PST 2002



andrew      02/01/21 17:57:57

  Modified:    src      pyvorbiscodec.c pyvorbisinfo.c pyvorbisinfo.h
  Added:       src      vcedit.c vcedit.h
  Log:
  2001-01-21  Andrew H. Chatham <andrew.chatham at duke.edu>
          * pyvorbisinfo.c: Comment objects now store pointers to the
          comment structures, not the structure itself. Helps with dealloc.
          * pyvorbisinfo.c (write_comments), (py_comment_append_to),
          (py_comment_write_to): Added
          * pyvorbisinfo.c (py_comment_assign): Catch del on a comment
          object. Returns not implemented exception for now
          * README: Explain how to use comments
          * vcedit.h Copied in from vorbiscomment
          * vcedit.c: Copied in from vorbiscomment

Revision  Changes    Path
1.4       +1 -1      vorbis-python/src/pyvorbiscodec.c

Index: pyvorbiscodec.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-python/src/pyvorbiscodec.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- pyvorbiscodec.c	2001/06/01 20:54:46	1.3
+++ pyvorbiscodec.c	2002/01/22 01:57:56	1.4
@@ -158,7 +158,7 @@
   if (comm == NULL) {
     vorbis_comment_init(&vc); /* Initialize an empty comment struct */
   } else {
-    vc = comm->vc;
+    vc = *comm->vc;
   }
     
   if ((code = vorbis_analysis_headerout(&dsp_self->vd, &vc, &header,

<p><p>1.4       +161 -26   vorbis-python/src/pyvorbisinfo.c

Index: pyvorbisinfo.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-python/src/pyvorbisinfo.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- pyvorbisinfo.c	2001/06/01 20:54:46	1.3
+++ pyvorbisinfo.c	2002/01/22 01:57:56	1.4
@@ -7,6 +7,8 @@
 #include "pyvorbisinfo.h"
 #include "pyvorbiscodec.h"
 
+#include "vcedit.h"
+
 /*  
    *********************************************************
                         VorbisInfo Object methods 
@@ -66,13 +68,13 @@
 {
   py_vinfo *newobj;
   newobj = (py_vinfo *) PyObject_NEW(py_vinfo, 
-				     &py_vinfo_type);
+																		 &py_vinfo_type);
   newobj->vi = *vi;
   return (PyObject *) newobj;
 }
 
 static char *py_info_new_kw[] = {"channels", "rate", "max_bitrate",
-				 "nominal_bitrate", "min_bitrate", NULL};
+																 "nominal_bitrate", "min_bitrate", NULL};
 
 PyObject *
 py_info_new(PyObject *self, PyObject *args, PyObject *kwdict)
@@ -192,6 +194,10 @@
 FDEF(vorbis_comment_query) "Returns a comment_query";
 FDEF(vorbis_comment_query_count) "Returns a comment_query_count";
 
+FDEF(comment_write_to) "Write comments to an existing vorbis file";
+FDEF(comment_append_to) "Append comments to an existing vorbis file";
+
+
 FDEF(comment_as_dict) "Returns a dictionary representation of \
 this VorbisComment object";
 
@@ -225,12 +231,16 @@
    METH_VARARGS, py_comment_items_doc},
   {"values", py_comment_values,
    METH_VARARGS, py_comment_values_doc},
+	{"write_to", py_comment_write_to,
+	 METH_VARARGS, py_comment_write_to_doc},
+	{"append_to", py_comment_append_to,
+	 METH_VARARGS, py_comment_append_to_doc},
   {NULL, NULL}
 };
 
 static int py_comment_length(py_vcomment *);
 static int py_comment_assign(py_vcomment *, 
-				   PyObject *, PyObject *);
+														 PyObject *, PyObject *);
 static PyObject *py_comment_subscript(py_vcomment *, PyObject *);
 
 static PyMappingMethods py_vcomment_Mapping_Methods = {
@@ -293,9 +303,10 @@
   py_vcomment *newobj;
 
   newobj = (py_vcomment *) PyObject_NEW(py_vcomment, 
-					&py_vcomment_type);
-  newobj->vc = *vc;
+																				&py_vcomment_type);
+  newobj->vc = vc;
   newobj->parent = parent;
+	newobj->malloced = 0;
   Py_XINCREF(parent);
   return (PyObject *) newobj;
 }
@@ -309,9 +320,18 @@
     return NULL;
 
   newobj = (py_vcomment *) PyObject_NEW(py_vcomment, 
-					&py_vcomment_type);
-  vorbis_comment_init(&newobj->vc);
+																				&py_vcomment_type);
+	if (!newobj)
+		return NULL;
+
   newobj->parent = NULL;
+	newobj->malloced = 1;
+	newobj->vc = (vorbis_comment *) malloc(sizeof(vorbis_comment));
+	if (!newobj->vc) {
+		PyErr_SetString(PyExc_MemoryError, "Could not create vorbis_comment");
+		return NULL;
+	}
+	vorbis_comment_init(newobj->vc);
   return (PyObject *) newobj;
 }
 
@@ -323,8 +343,8 @@
   if (!PyArg_ParseTuple(args, ""))
     return NULL;
 
-  vorbis_comment_clear(&ovc_self->vc);
-  vorbis_comment_init(&ovc_self->vc);
+  vorbis_comment_clear(ovc_self->vc);
+  vorbis_comment_init(ovc_self->vc);
 
   Py_INCREF(Py_None);
   return Py_None;
@@ -335,12 +355,15 @@
 {
   py_vcomment *ovc_self = (py_vcomment *) self;
 
-  if (ovc_self->parent)
+  if (ovc_self->parent) {
     Py_DECREF(ovc_self->parent); /* parent will clear for us */
-  else
-    vorbis_comment_clear(&ovc_self->vc); 
+  } else {
+    vorbis_comment_clear(ovc_self->vc); 
+	}
+	if (ovc_self->malloced)
+		free(ovc_self->vc);
 
-  PyMem_DEL(self);
+	PyMem_DEL(self);
 }
 
 static PyObject*
@@ -355,14 +378,14 @@
 static int
 py_comment_length(py_vcomment *self)
 {
-  int val = self->vc.comments;
-  if (self->vc.vendor) val++;
+  int val = self->vc->comments;
+  if (self->vc->vendor) val++;
   return val;
 }
 
 static PyObject *
 py_comment_subscript(py_vcomment *self, 
-		     PyObject *keyobj)
+										 PyObject *keyobj)
 {
   char *res, *tag;
   int cur = 0;
@@ -376,7 +399,7 @@
   tag = PyString_AsString(keyobj);
   retlist = PyList_New(0);
 
-  res = vorbis_comment_query(&self->vc, tag, cur++);
+  res = vorbis_comment_query(self->vc, tag, cur++);
   while (res != NULL) {
     int vallen = strlen(res);
 #if PY_UNICODE
@@ -387,7 +410,7 @@
     PyList_Append(retlist, item);
     Py_DECREF(item);
     
-    res = vorbis_comment_query(&self->vc, tag, cur++);
+    res = vorbis_comment_query(self->vc, tag, cur++);
   }
 
   if (cur == 1) {
@@ -400,15 +423,20 @@
 
 static int
 py_comment_assign(py_vcomment *self, 
-		  PyObject *keyobj, PyObject *valobj)
+									PyObject *keyobj, PyObject *valobj)
 {
-  vorbis_comment *vc = &self->vc;
+  vorbis_comment *vc = PY_VCOMMENT(self);
   char *tag, *val;
 
-  if (!PyString_Check(keyobj)) {
+	if (!PyString_Check(keyobj)) {
     PyErr_SetString(PyExc_KeyError, "Keys may only be ASCII strings");
     return -1;
   }
+	
+	if (valobj == NULL) {
+		PyErr_SetString(PyExc_NotImplementedError, "Cannot yet delete comments");
+		return -1;
+	}
 
   if (PyString_Check(valobj)) {
     val = PyString_AsString(valobj);
@@ -521,7 +549,7 @@
   if (!PyArg_ParseTuple(args, "s", &comment))
     return NULL;
   
-  vorbis_comment_add(&ovc_self->vc, comment);
+  vorbis_comment_add(ovc_self->vc, comment);
   Py_INCREF(Py_None);
   return Py_None;
 }
@@ -537,7 +565,7 @@
   if (!PyArg_ParseTuple(args, "ss", &comment, &tag))
     return NULL;
 
-  vorbis_comment_add_tag(&ovc_self->vc, comment, tag);
+  vorbis_comment_add_tag(ovc_self->vc, comment, tag);
 
   Py_INCREF(Py_None);
   return Py_None;
@@ -548,7 +576,7 @@
 {
   char *tag, *res;
   int count;
-  vorbis_comment *vc = &((py_vcomment *) self)->vc;
+  vorbis_comment *vc = PY_VCOMMENT(self);
 
   if (!PyArg_ParseTuple(args, "si", &tag, &count))
     return NULL;
@@ -561,7 +589,7 @@
 py_vorbis_comment_query_count(PyObject *self, PyObject *args)
 {
   char *tag;
-  vorbis_comment *vc = &((py_vcomment *) self)->vc;
+  vorbis_comment *vc = PY_VCOMMENT(self);
 
   if (!PyArg_ParseTuple(args, "s", &tag))
     return NULL;
@@ -598,7 +626,7 @@
   if (args != NULL && !PyArg_ParseTuple(args, ""))
     return NULL;
 
-  comment = &ovc_self->vc;
+  comment = ovc_self->vc;
   retdict = PyDict_New();
 
 
@@ -669,6 +697,113 @@
   if (key)
     free(key);
   return NULL;
+}
+
+/* Helper function which writes/appends comments to a file */
+static PyObject*
+write_comments(vorbis_comment *vc, const char *filename, int append)
+{
+	vcedit_state *state;
+	vorbis_comment *file_comments;
+	FILE *in_file, *out_file;
+	int k;
+	char *tempfile = malloc(strlen(filename) + sizeof(".pytemp"));
+	strcpy(tempfile, filename);
+	strcat(tempfile, ".pytemp");
+	
+	/* Open the file */
+	in_file = fopen(filename, "r");
+	if (!in_file) {
+		printf("No in file %s\n", filename);
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	out_file = fopen(tempfile, "wb");
+	if (!out_file) {
+		fclose(in_file);
+		printf("No out file\n");
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+
+	state = vcedit_new_state();
+
+	/* Make sure it's a vorbis file */
+	if (vcedit_open(state, in_file) < 0) {
+		char buff[256];
+		snprintf(buff, sizeof(buff), "Could not open file %s as vorbis: %s", 
+						 filename,
+						 vcedit_error(state));
+		PyErr_SetString(Py_VorbisError, buff);
+
+		vcedit_clear(state);
+		fclose(in_file);
+		fclose(out_file);
+
+		return NULL;
+	}
+
+	/* Get the vorbis comments that are already in the file, 
+		 and clear if necessary */
+	file_comments = vcedit_comments(state);
+	if (!append) {
+		vorbis_comment_clear(file_comments);
+		vorbis_comment_init(file_comments);
+	}
+
+	/* Append all the comments we already have in vc */
+	for (k = 0; k < vc->comments; k++) {
+		vorbis_comment_add(file_comments, vc->user_comments[k]);
+	}
+
+	if (vcedit_write(state, out_file) < 0) {
+		char buff[256];
+		snprintf(buff, sizeof(buff), "Could not write comments to file: %s",
+						vcedit_error(state));
+		PyErr_SetString(Py_VorbisError, buff);
+
+		vcedit_clear(state);
+		fclose(in_file);
+		fclose(out_file);
+
+		return NULL;
+	}
+
+	vcedit_clear(state);
+
+	fclose(in_file);
+	fclose(out_file);
+
+	if (rename(tempfile, filename)) {
+		PyErr_SetFromErrno(PyExc_IOError);
+		return NULL;
+	}
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+py_comment_append_to(PyObject *self, PyObject *args) 
+{
+	vorbis_comment *vc = PY_VCOMMENT(self);
+	PyObject *ret;
+	const char *filename;
+	if (!PyArg_ParseTuple(args, "s", &filename))
+		return NULL;
+
+	return write_comments(vc, filename, 1);
+}
+
+static PyObject *
+py_comment_write_to(PyObject *self, PyObject *args)
+{
+	vorbis_comment *vc = PY_VCOMMENT(self);
+	const char *filename;
+	if (!PyArg_ParseTuple(args, "s", &filename))
+		return NULL;
+
+	return write_comments(vc, filename, 0);
 }
 
 

<p><p>1.4       +3 -2      vorbis-python/src/pyvorbisinfo.h

Index: pyvorbisinfo.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-python/src/pyvorbisinfo.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- pyvorbisinfo.h	2001/06/01 20:54:46	1.3
+++ pyvorbisinfo.h	2002/01/22 01:57:56	1.4
@@ -10,12 +10,13 @@
 
 typedef struct {
   PyObject_HEAD
-  vorbis_comment vc;
+	int malloced;
+  vorbis_comment *vc;
   PyObject *parent;
 } py_vcomment;
 
 #define PY_VINFO(x) (&(((py_vinfo *) (x))->vi))
-#define PY_VCOMMENT(x) (&(((py_vcomment *) (x))->vc))
+#define PY_VCOMMENT(x) ((((py_vcomment *) (x))->vc))
 
 extern PyTypeObject py_vinfo_type;
 extern PyTypeObject py_vcomment_type;

<p><p>1.1                  vorbis-python/src/vcedit.c

Index: vcedit.c
===================================================================
/* This program is licensed under the GNU Library General Public License, version 2,
 * a copy of which is included with this program (LICENCE.LGPL).
 *
 * (c) 2000-2001 Michael Smith <msmith at labyrinth.net.au>
 *
 *
 * Comment editing backend, suitable for use by nice frontend interfaces.
 *
 * last modified: $Id: vcedit.c,v 1.1 2002/01/22 01:57:56 andrew Exp $
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>

#include "vcedit.h"

#define CHUNKSIZE 4096

vcedit_state *vcedit_new_state(void)
{
        vcedit_state *state = malloc(sizeof(vcedit_state));
        memset(state, 0, sizeof(vcedit_state));

        return state;
}

char *vcedit_error(vcedit_state *state)
{
        return state->lasterror;
}

vorbis_comment *vcedit_comments(vcedit_state *state)
{
        return state->vc;
}

tatic void vcedit_clear_internals(vcedit_state *state)
{
        if(state->vc)
        {
                vorbis_comment_clear(state->vc);
                free(state->vc);
                state->vc=NULL;
        }
        if(state->os)
        {
                ogg_stream_clear(state->os);
                free(state->os);
                state->os=NULL;
        }
        if(state->oy)
        {
                ogg_sync_clear(state->oy);
                free(state->oy);
                state->oy=NULL;
        }
        if(state->vendor)
        {
                free(state->vendor);
                state->vendor=NULL;
        }
}

void vcedit_clear(vcedit_state *state)
{
        if(state)
        {
                vcedit_clear_internals(state);
                free(state);
        }
}

/* Next two functions pulled straight from libvorbis, apart from one change
 * - we don't want to overwrite the vendor string.
 */
static void _v_writestring(oggpack_buffer *o,char *s, int len)
{
        while(len--)
        {
                oggpack_write(o,*s++,8);
        }
}

tatic int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op)
{
        oggpack_buffer opb;

        oggpack_writeinit(&opb);

        /* preamble */  
        oggpack_write(&opb,0x03,8);
        _v_writestring(&opb,"vorbis", 6);

        /* vendor */
        oggpack_write(&opb,strlen(vendor),32);
        _v_writestring(&opb,vendor, strlen(vendor));

        /* comments */
        oggpack_write(&opb,vc->comments,32);
        if(vc->comments){
                int i;
                for(i=0;i<vc->comments;i++){
                        if(vc->user_comments[i]){
                                oggpack_write(&opb,vc->comment_lengths[i],32);
                                _v_writestring(&opb,vc->user_comments[i], 
                        vc->comment_lengths[i]);
                        }else{
                                oggpack_write(&opb,0,32);
                        }
                }
        }
        oggpack_write(&opb,1,1);

        op->packet = _ogg_malloc(oggpack_bytes(&opb));
        memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));

        op->bytes=oggpack_bytes(&opb);
        op->b_o_s=0;
        op->e_o_s=0;
        op->granulepos=0;

        return 0;
}

tatic int _blocksize(vcedit_state *s, ogg_packet *p)
{
        int this = vorbis_packet_blocksize(&s->vi, p);
        int ret = (this + s->prevW)/4;

        if(!s->prevW)
        {
                s->prevW = this;
                return 0;
        }

        s->prevW = this;
        return ret;
}

tatic int _fetch_next_packet(vcedit_state *s, ogg_packet *p, ogg_page *page)
{
        int result;
        char *buffer;
        int bytes;

        result = ogg_stream_packetout(s->os, p);

        if(result > 0)
                return 1;
        else
        {
                if(s->eosin)
                        return 0;
                while(ogg_sync_pageout(s->oy, page) <= 0)
                {
                        buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
                        bytes = s->read(buffer,1, CHUNKSIZE, s->in);
                        ogg_sync_wrote(s->oy, bytes);
                        if(bytes == 0) 
                                return 0;
                }
                if(ogg_page_eos(page))
                        s->eosin = 1;
                else if(ogg_page_serialno(page) != s->serial)
                {
                        s->eosin = 1;
                        s->extrapage = 1;
                        return 0;
                }

                ogg_stream_pagein(s->os, page);
                return _fetch_next_packet(s, p, page);
        }
}

int vcedit_open(vcedit_state *state, FILE *in)
{
        return vcedit_open_callbacks(state, (void *)in, 
                        (vcedit_read_func)fread, (vcedit_write_func)fwrite);
}

int vcedit_open_callbacks(vcedit_state *state, void *in,
                vcedit_read_func read_func, vcedit_write_func write_func)
{

        char *buffer;
        int bytes,i;
        ogg_packet *header;
        ogg_packet	header_main;
        ogg_packet  header_comments;
        ogg_packet	header_codebooks;
        ogg_page    og;

        state->in = in;
        state->read = read_func;
        state->write = write_func;

        state->oy = malloc(sizeof(ogg_sync_state));
        ogg_sync_init(state->oy);

        buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
        bytes = state->read(buffer, 1, CHUNKSIZE, state->in);

        ogg_sync_wrote(state->oy, bytes);

        if(ogg_sync_pageout(state->oy, &og) != 1)
        {
                if(bytes<CHUNKSIZE)
                        state->lasterror = "Input truncated or empty.";
                else
                        state->lasterror = "Input is not an Ogg bitstream.";
                goto err;
        }

        state->serial = ogg_page_serialno(&og);

        state->os = malloc(sizeof(ogg_stream_state));
        ogg_stream_init(state->os, state->serial);

        vorbis_info_init(&state->vi);

        state->vc = malloc(sizeof(vorbis_comment));
        vorbis_comment_init(state->vc);

        if(ogg_stream_pagein(state->os, &og) < 0)
        {
                state->lasterror = "Error reading first page of Ogg bitstream.";
                goto err;
        }

        if(ogg_stream_packetout(state->os, &header_main) != 1)
        {
                state->lasterror = "Error reading initial header packet.";
                goto err;
        }

        if(vorbis_synthesis_headerin(&state->vi, state->vc, &header_main) < 0)
        {
                state->lasterror = "Ogg bitstream does not contain vorbis data.";
                goto err;
        }

        state->mainlen = header_main.bytes;
        state->mainbuf = malloc(state->mainlen);
        memcpy(state->mainbuf, header_main.packet, header_main.bytes);

        i = 0;
        header = &header_comments;
        while(i<2) {
                while(i<2) {
                        int result = ogg_sync_pageout(state->oy, &og);
                        if(result == 0) break; /* Too little data so far */
                        else if(result == 1)
                        {
                                ogg_stream_pagein(state->os, &og);
                                while(i<2)
                                {
                                        result = ogg_stream_packetout(state->os, header);
                                        if(result == 0) break;
                                        if(result == -1)
                                        {
                                                state->lasterror = "Corrupt secondary header.";
                                                goto err;
                                        }
                                        vorbis_synthesis_headerin(&state->vi, state->vc, header);
                                        if(i==1)
                                        {
                                                state->booklen = header->bytes;
                                                state->bookbuf = malloc(state->booklen);
                                                memcpy(state->bookbuf, header->packet, 
                                                                header->bytes);
                                        }
                                        i++;
                                        header = &header_codebooks;
                                }
                        }
                }

                buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
                bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
                if(bytes == 0 && i < 2)
                {
                        state->lasterror = "EOF before end of vorbis headers.";
                        goto err;
                }
                ogg_sync_wrote(state->oy, bytes);
        }

        /* Copy the vendor tag */
        state->vendor = malloc(strlen(state->vc->vendor) +1);
        strcpy(state->vendor, state->vc->vendor);

        /* Headers are done! */
        return 0;

err:
        vcedit_clear_internals(state);
        return -1;
}

int vcedit_write(vcedit_state *state, void *out)
{
        ogg_stream_state streamout;
        ogg_packet header_main;
        ogg_packet header_comments;
        ogg_packet header_codebooks;

        ogg_page ogout, ogin;
        ogg_packet op;
        ogg_int64_t granpos = 0;
        int result;
        char *buffer;
        int bytes;
        int needflush=0, needout=0;

        state->eosin = 0;
        state->extrapage = 0;

        header_main.bytes = state->mainlen;
        header_main.packet = state->mainbuf;
        header_main.b_o_s = 1;
        header_main.e_o_s = 0;
        header_main.granulepos = 0;

        header_codebooks.bytes = state->booklen;
        header_codebooks.packet = state->bookbuf;
        header_codebooks.b_o_s = 0;
        header_codebooks.e_o_s = 0;
        header_codebooks.granulepos = 0;

        ogg_stream_init(&streamout, state->serial);

        _commentheader_out(state->vc, state->vendor, &header_comments);

        ogg_stream_packetin(&streamout, &header_main);
        ogg_stream_packetin(&streamout, &header_comments);
        ogg_stream_packetin(&streamout, &header_codebooks);

        while((result = ogg_stream_flush(&streamout, &ogout)))
        {
                if(state->write(ogout.header,1,ogout.header_len, out) !=
                                (size_t) ogout.header_len)
                        goto cleanup;
                if(state->write(ogout.body,1,ogout.body_len, out) != 
                                (size_t) ogout.body_len)
                        goto cleanup;
        }

        while(_fetch_next_packet(state, &op, &ogin))
        {
                int size;
                size = _blocksize(state, &op);
                granpos += size;

                if(needflush)
                {
                        if(ogg_stream_flush(&streamout, &ogout))
                        {
                                if(state->write(ogout.header,1,ogout.header_len, 
                                                        out) != (size_t) ogout.header_len)
                                        goto cleanup;
                                if(state->write(ogout.body,1,ogout.body_len, 
                                                        out) != (size_t) ogout.body_len)
                                        goto cleanup;
                        }
                }
                else if(needout)
                {
                        if(ogg_stream_pageout(&streamout, &ogout))
                        {
                                if(state->write(ogout.header,1,ogout.header_len, 
                                                        out) != (size_t) ogout.header_len)
                                        goto cleanup;
                                if(state->write(ogout.body,1,ogout.body_len, 
                                                        out) != (size_t) ogout.body_len)
                                        goto cleanup;
                        }
                }

                needflush=needout=0;

                if(op.granulepos == -1)
                {
                        op.granulepos = granpos;
                        ogg_stream_packetin(&streamout, &op);
                }
                else /* granulepos is set, validly. Use it, and force a flush to 
                                account for shortened blocks (vcut) when appropriate */ 
                {
                        if(granpos > op.granulepos)
                        {
                                granpos = op.granulepos;
                                ogg_stream_packetin(&streamout, &op);
                                needflush=1;
                        }
                        else 
                        {
                                ogg_stream_packetin(&streamout, &op);
                                needout=1;
                        }
                }		
        }

        streamout.e_o_s = 1;
        while(ogg_stream_flush(&streamout, &ogout))
        {
                if(state->write(ogout.header,1,ogout.header_len, 
                                        out) != (size_t) ogout.header_len)
                        goto cleanup;
                if(state->write(ogout.body,1,ogout.body_len, 
                                        out) != (size_t) ogout.body_len)
                        goto cleanup;
        }

        /* FIXME: freeing this here probably leaks memory */
        /* Done with this, now */
        vorbis_info_clear(&state->vi);

        if (state->extrapage)
        {
                if(state->write(ogin.header,1,ogin.header_len,
                                out) != (size_t) ogin.header_len)
                        goto cleanup;
                if (state->write(ogin.body,1,ogin.body_len, out) !=
                                (size_t) ogin.body_len)
                        goto cleanup;
        }

        state->eosin=0; /* clear it, because not all paths to here do */
        while(!state->eosin) /* We reached eos, not eof */
        {
                /* We copy the rest of the stream (other logical streams)
                 * through, a page at a time. */
                while(1)
                {
                        result = ogg_sync_pageout(state->oy, &ogout);
                        if(result==0) break;
                        if(result<0)
                                state->lasterror = "Corrupt or missing data, continuing...";
                        else
                        {
                                /* Don't bother going through the rest, we can just 
                                 * write the page out now */
                                if(state->write(ogout.header,1,ogout.header_len, 
                                                out) != (size_t) ogout.header_len)
                                        goto cleanup;
                                if(state->write(ogout.body,1,ogout.body_len, out) !=
                                                (size_t) ogout.body_len)
                                        goto cleanup;
                        }
                }
                buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
                bytes = state->read(buffer,1, CHUNKSIZE, state->in);
                ogg_sync_wrote(state->oy, bytes);
                if(bytes == 0) 
                {
                        state->eosin = 1;
                        break;
                }
        }
                                                        

cleanup:
        ogg_stream_clear(&streamout);
        ogg_packet_clear(&header_comments);

        free(state->mainbuf);
        free(state->bookbuf);

        vcedit_clear_internals(state);
        if(!state->eosin)
        {
                state->lasterror =  
                        "Error writing stream to output. "
                        "Output stream may be corrupted or truncated.";
                return -1;
        }

        return 0;
}

<p><p><p>1.1                  vorbis-python/src/vcedit.h

Index: vcedit.h
===================================================================
/* This program is licensed under the GNU Library General Public License, version 2,
 * a copy of which is included with this program (with filename LICENSE.LGPL).
 *
 * (c) 2000-2001 Michael Smith <msmith at labyrinth.net.au>
 *
 * VCEdit header.
 *
 * last modified: $ID:$
 */

#ifndef __VCEDIT_H
#define __VCEDIT_H

#ifdef __cplusplus
extern "C" {
#endif 

#include <stdio.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>

typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);

typedef struct {
        ogg_sync_state		*oy;
        ogg_stream_state	*os;

        vorbis_comment		*vc;
        vorbis_info          vi;

        vcedit_read_func read;
        vcedit_write_func write;

        void		*in;
        long		serial;
        unsigned char	*mainbuf;
        unsigned char	*bookbuf;
        int		mainlen;
        int		booklen;
        char 	    *lasterror;
        char   *vendor;
        int prevW;
        int extrapage;
        int eosin;
} vcedit_state;

extern vcedit_state *	vcedit_new_state(void);
extern void		vcedit_clear(vcedit_state *state);
extern vorbis_comment *	vcedit_comments(vcedit_state *state);
extern int		vcedit_open(vcedit_state *state, FILE *in);
extern int		vcedit_open_callbacks(vcedit_state *state, void *in,
                vcedit_read_func read_func, vcedit_write_func write_func);
extern int		vcedit_write(vcedit_state *state, void *out);
extern char *   vcedit_error(vcedit_state *state);

#ifdef __cplusplus
}
#endif 

#endif /* __VCEDIT_H */

<p><p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list