X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=ext%2Fvcedit.c;h=1aee14c25ed1fcf4cd0b0ba2fb2d53edd903b3fa;hb=66ba15d0d5f7e8278f88962bac2d60a725244a10;hp=24622e855974eafc7a6c7765c7edfc21a017d302;hpb=2cedce4cb348f6980ec64ab746b58d32f62b20a3;p=ruby-vorbistagger.git diff --git a/ext/vcedit.c b/ext/vcedit.c index 24622e8..1aee14c 100644 --- a/ext/vcedit.c +++ b/ext/vcedit.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -30,8 +31,6 @@ #define CHUNKSIZE 4096 -static int vcedit_open (vcedit_state *state); - struct vcedit_state_St { int refcount; @@ -44,18 +43,61 @@ struct vcedit_state_St { char filename[PATH_MAX]; FILE *in; + bool opened; long serial; unsigned char *mainbuf; unsigned char *bookbuf; int mainlen; int booklen; - const char *lasterror; char *vendor; int prevW; int extrapage; int eosin; }; +static void +vcedit_state_free (vcedit_state *state) +{ + free (state->oy); + free (state->os); + free (state->vc); + free (state->vi); + free (state->mainbuf); + free (state->bookbuf); + free (state->vendor); + + if (state->in) { + fclose (state->in); + state->in = NULL; + } + + free (state); +} + +static bool +vcedit_state_init (vcedit_state *state) +{ + state->refcount = 1; + + state->oy = malloc (sizeof (ogg_sync_state)); + if (!state->oy) + return false; + + state->os = malloc (sizeof (ogg_stream_state)); + if (!state->os) + return false; + + state->vc = malloc (sizeof (vorbis_comment)); + if (!state->vc) + return false; + + state->vi = malloc (sizeof (vorbis_info)); + if (!state->vi) + return false; + + return true; +} + vcedit_state * vcedit_state_new (const char *filename) { @@ -67,53 +109,31 @@ vcedit_state_new (const char *filename) memset (state, 0, sizeof (vcedit_state)); - state->refcount = 1; + if (!vcedit_state_init (state)) { + vcedit_state_free (state); + return NULL; + } snprintf (state->filename, sizeof (state->filename), "%s", filename); - state->in = fopen (state->filename, "rb"); - - if (vcedit_open (state) < 0) { - free (state); - return NULL; - } - return state; } -const char * -vcedit_error (vcedit_state *state) -{ - return state->lasterror; -} - vorbis_comment * vcedit_comments (vcedit_state *state) { - return state->vc; + return state->opened ? state->vc : NULL; } static void vcedit_clear_internals (vcedit_state *state) { - if (state->vc) { - vorbis_comment_clear (state->vc); - free (state->vc); - state->vc = NULL; - } + ogg_stream_clear (state->os); + ogg_sync_clear (state->oy); - 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; - } + vorbis_info_clear (state->vi); + vorbis_comment_clear (state->vc); free (state->vendor); state->vendor = NULL; @@ -126,13 +146,8 @@ vcedit_clear_internals (vcedit_state *state) state->bookbuf = NULL; state->booklen = 0; - if (state->vi) { - vorbis_info_clear (state->vi); - free (state->vi); - state->vi = NULL; - } - state->serial = 0; + state->opened = false; } void @@ -144,13 +159,13 @@ vcedit_state_ref (vcedit_state *state) void vcedit_state_unref (vcedit_state *state) { - state->refcount--; + if (--state->refcount) + return; - if (!state->refcount) { - fclose (state->in); + if (state->opened) vcedit_clear_internals (state); - free (state); - } + + vcedit_state_free (state); } /* Next two functions pulled straight from libvorbis, apart from one change @@ -260,9 +275,10 @@ _fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page) return _fetch_next_packet (s, p, page); } -static int +vcedit_error vcedit_open (vcedit_state *state) { + vcedit_error ret; char *buffer; int bytes, i; int chunks = 0; @@ -270,7 +286,10 @@ vcedit_open (vcedit_state *state) ogg_packet header_main, header_comments, header_codebooks; ogg_page og; - state->oy = malloc (sizeof (ogg_sync_state)); + state->in = fopen (state->filename, "rb"); + if (!state->in) + return VCEDIT_ERR_OPEN; + ogg_sync_init (state->oy); while (1) { @@ -284,38 +303,30 @@ vcedit_open (vcedit_state *state) /* Bail if we don't find data in the first 40 kB */ if (chunks++ >= 10) { - if (bytes < CHUNKSIZE) - state->lasterror = "Input truncated or empty."; - else - state->lasterror = "Input is not an Ogg bitstream."; + ogg_sync_clear (state->oy); - goto err; + return VCEDIT_ERR_INVAL; } } state->serial = ogg_page_serialno (&og); - state->os = malloc (sizeof (ogg_stream_state)); ogg_stream_init (state->os, state->serial); - - state->vi = malloc (sizeof (vorbis_info)); 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."; + ret = VCEDIT_ERR_INVAL; goto err; } if (ogg_stream_packetout (state->os, &header_main) != 1) { - state->lasterror = "Error reading initial header packet."; + ret = VCEDIT_ERR_INVAL; goto err; } if (vorbis_synthesis_headerin (state->vi, state->vc, &header_main) < 0) { - state->lasterror = "Ogg bitstream does not contain vorbis data."; + ret = VCEDIT_ERR_INVAL; goto err; } @@ -343,7 +354,7 @@ vcedit_open (vcedit_state *state) break; if (result == -1) { - state->lasterror = "Corrupt secondary header."; + ret = VCEDIT_ERR_INVAL; goto err; } @@ -365,7 +376,7 @@ vcedit_open (vcedit_state *state) bytes = fread (buffer, 1, CHUNKSIZE, state->in); if (bytes == 0 && i < 2) { - state->lasterror = "EOF before end of vorbis headers."; + ret = VCEDIT_ERR_INVAL; goto err; } @@ -376,15 +387,17 @@ vcedit_open (vcedit_state *state) state->vendor = strdup (state->vc->vendor); /* Headers are done! */ - return 0; + state->opened = true; + + return VCEDIT_ERR_SUCCESS; err: vcedit_clear_internals (state); - return -1; + return ret; } -int +vcedit_error vcedit_write (vcedit_state *state) { ogg_stream_state streamout; @@ -396,23 +409,22 @@ vcedit_write (vcedit_state *state) int s, result, bytes, needflush = 0, needout = 0; size_t tmp; + if (!state->opened) + return VCEDIT_ERR_INVAL; + strcpy (tmpfile, state->filename); strcat (tmpfile, ".XXXXXX"); s = mkstemp (tmpfile); - if (s == -1) { - state->lasterror = "Error writing stream to output. " - "Cannot open temporary file."; - return -1; - } + if (s == -1) + return VCEDIT_ERR_TMPFILE; out = fdopen (s, "wb"); if (!out) { unlink (tmpfile); close (s); - state->lasterror = "Error writing stream to output. " - "Cannot open temporary file."; - return -1; + + return VCEDIT_ERR_TMPFILE; } state->prevW = state->extrapage = state->eosin = 0; @@ -530,9 +542,7 @@ vcedit_write (vcedit_state *state) if (!result) break; - if (result < 0) - state->lasterror = "Corrupt or missing data, continuing..."; - else { + if (result >= 0) { /* Don't bother going through the rest, we can just * write the page out now */ @@ -575,16 +585,11 @@ cleanup: state->mainbuf = state->bookbuf = NULL; - if (!state->eosin) { - state->lasterror = "Error writing stream to output. " - "Output stream may be corrupted or truncated."; - return -1; - } + if (!state->eosin) + return VCEDIT_ERR_INVAL; vcedit_clear_internals (state); - state->in = fopen (state->filename, "rb"); - vcedit_open (state); - - return 0; + return (vcedit_open (state) == VCEDIT_ERR_SUCCESS) ? + VCEDIT_ERR_SUCCESS : VCEDIT_ERR_REOPEN; }