X-Git-Url: http://git.code-monkey.de/?p=ruby-vorbistagger.git;a=blobdiff_plain;f=ext%2Fvcedit.c;h=b6c7dfd8d0d0db18e361b0fd79b37fa74a1664cb;hp=c7bd8e75becb618d5ace62fd212f33db2001ca0b;hb=fcd91ff1a3cc4a4f889abfd2af89119cbe262ad1;hpb=6f0baf7ecfc693b12cb0485eb8b9f9851415833c diff --git a/ext/vcedit.c b/ext/vcedit.c index c7bd8e7..b6c7dfd 100644 --- a/ext/vcedit.c +++ b/ext/vcedit.c @@ -20,13 +20,18 @@ #include #include #include +#include +#include #include #include +#include #include "vcedit.h" #define CHUNKSIZE 4096 +static int vcedit_open (vcedit_state *state); + struct vcedit_state_St { int refcount; @@ -36,10 +41,9 @@ struct vcedit_state_St { vorbis_comment *vc; vorbis_info *vi; - vcedit_read_func read; - vcedit_write_func write; + char filename[PATH_MAX]; - void *in; + FILE *in; long serial; unsigned char *mainbuf; unsigned char *bookbuf; @@ -53,7 +57,7 @@ struct vcedit_state_St { }; vcedit_state * -vcedit_state_new (void) +vcedit_state_new (const char *filename) { vcedit_state *state; @@ -65,6 +69,16 @@ vcedit_state_new (void) state->refcount = 1; + 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; } @@ -83,35 +97,43 @@ vcedit_comments (vcedit_state *state) static void vcedit_clear_internals (vcedit_state *state) { - const char *tmp; - 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; } free (state->vendor); + state->vendor = NULL; + free (state->mainbuf); + state->mainbuf = NULL; + state->mainlen = 0; + free (state->bookbuf); + state->bookbuf = NULL; + state->booklen = 0; - if (state->vi) { + if (state->vi) { vorbis_info_clear (state->vi); - free (state->vi); - } + free (state->vi); + state->vi = NULL; + } - tmp = state->lasterror; - memset (state, 0, sizeof (vcedit_state)); - state->lasterror = tmp; + state->serial = 0; + state->prevW = state->extrapage = state->eosin = 0; } void @@ -126,6 +148,7 @@ vcedit_state_unref (vcedit_state *state) state->refcount--; if (!state->refcount) { + fclose (state->in); vcedit_clear_internals (state); free (state); } @@ -220,7 +243,7 @@ _fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page) while (ogg_sync_pageout (s->oy, page) <= 0) { buffer = ogg_sync_buffer (s->oy, CHUNKSIZE); - bytes = s->read (buffer, 1, CHUNKSIZE, s->in); + bytes = fread (buffer, 1, CHUNKSIZE, s->in); ogg_sync_wrote (s->oy, bytes); if (!bytes) @@ -240,10 +263,8 @@ _fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page) return _fetch_next_packet (s, p, page); } -int -vcedit_open_callbacks (vcedit_state *state, void *in, - vcedit_read_func read_func, - vcedit_write_func write_func) +static int +vcedit_open (vcedit_state *state) { char *buffer; int bytes, i; @@ -252,16 +273,12 @@ vcedit_open_callbacks (vcedit_state *state, void *in, ogg_packet header_main, header_comments, 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); while (1) { buffer = ogg_sync_buffer (state->oy, CHUNKSIZE); - bytes = state->read (buffer, 1, CHUNKSIZE, state->in); + bytes = fread (buffer, 1, CHUNKSIZE, state->in); ogg_sync_wrote (state->oy, bytes); @@ -348,7 +365,7 @@ vcedit_open_callbacks (vcedit_state *state, void *in, } buffer = ogg_sync_buffer (state->oy, CHUNKSIZE); - bytes = state->read (buffer, 1, CHUNKSIZE, state->in); + bytes = fread (buffer, 1, CHUNKSIZE, state->in); if (bytes == 0 && i < 2) { state->lasterror = "EOF before end of vorbis headers."; @@ -371,16 +388,36 @@ err: } int -vcedit_write (vcedit_state *state, void *out) +vcedit_write (vcedit_state *state) { ogg_stream_state streamout; ogg_packet header_main, header_comments, header_codebooks, op; ogg_page ogout, ogin; ogg_int64_t granpos = 0; - int result, bytes, needflush = 0, needout = 0; - char *buffer; + FILE *out; + char *buffer, tmpfile[PATH_MAX]; + int s, result, bytes, needflush = 0, needout = 0; size_t tmp; + 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; + } + + out = fdopen (s, "wb"); + if (!out) { + unlink (tmpfile); + close (s); + state->lasterror = "Error writing stream to output. " + "Cannot open temporary file."; + return -1; + } + state->eosin = 0; state->extrapage = 0; @@ -405,11 +442,11 @@ vcedit_write (vcedit_state *state, void *out) ogg_stream_packetin (&streamout, &header_codebooks); while ((result = ogg_stream_flush (&streamout, &ogout))) { - tmp = state->write (ogout.header, 1, ogout.header_len, out); + tmp = fwrite (ogout.header, 1, ogout.header_len, out); if (tmp != (size_t) ogout.header_len) goto cleanup; - tmp = state->write (ogout.body, 1, ogout.body_len, out); + tmp = fwrite (ogout.body, 1, ogout.body_len, out); if (tmp != (size_t) ogout.body_len) goto cleanup; } @@ -422,21 +459,21 @@ vcedit_write (vcedit_state *state, void *out) if (needflush) { if (ogg_stream_flush (&streamout, &ogout)) { - tmp = state->write (ogout.header, 1, ogout.header_len, out); + tmp = fwrite (ogout.header, 1, ogout.header_len, out); if (tmp != (size_t) ogout.header_len) goto cleanup; - tmp = state->write (ogout.body, 1, ogout.body_len, out); + tmp = fwrite (ogout.body, 1, ogout.body_len, out); if (tmp != (size_t) ogout.body_len) goto cleanup; } } else if (needout) { if (ogg_stream_pageout (&streamout, &ogout)) { - tmp = state->write (ogout.header, 1, ogout.header_len, out); + tmp = fwrite (ogout.header, 1, ogout.header_len, out); if (tmp != (size_t) ogout.header_len) goto cleanup; - tmp = state->write (ogout.body, 1, ogout.body_len, out); + tmp = fwrite (ogout.body, 1, ogout.body_len, out); if (tmp != (size_t) ogout.body_len) goto cleanup; } @@ -465,21 +502,21 @@ vcedit_write (vcedit_state *state, void *out) streamout.e_o_s = 1; while (ogg_stream_flush (&streamout, &ogout)) { - tmp = state->write (ogout.header, 1, ogout.header_len, out); + tmp = fwrite (ogout.header, 1, ogout.header_len, out); if (tmp != (size_t) ogout.header_len) goto cleanup; - tmp = state->write (ogout.body, 1, ogout.body_len, out); + tmp = fwrite (ogout.body, 1, ogout.body_len, out); if (tmp != (size_t) ogout.body_len) goto cleanup; } if (state->extrapage) { - tmp = state->write (ogin.header, 1, ogin.header_len, out); + tmp = fwrite (ogin.header, 1, ogin.header_len, out); if (tmp != (size_t) ogin.header_len) goto cleanup; - tmp = state->write (ogin.body, 1, ogin.body_len, out); + tmp = fwrite (ogin.body, 1, ogin.body_len, out); if (tmp != (size_t) ogin.body_len) goto cleanup; } @@ -503,18 +540,18 @@ vcedit_write (vcedit_state *state, void *out) /* Don't bother going through the rest, we can just * write the page out now */ - tmp = state->write (ogout.header,1,ogout.header_len, out); + tmp = fwrite (ogout.header, 1, ogout.header_len, out); if (tmp != (size_t) ogout.header_len) goto cleanup; - tmp = state->write (ogout.body,1,ogout.body_len, out); + tmp = fwrite (ogout.body, 1, ogout.body_len, out); if (tmp != (size_t) ogout.body_len) goto cleanup; } } buffer = ogg_sync_buffer (state->oy, CHUNKSIZE); - bytes = state->read (buffer, 1, CHUNKSIZE, state->in); + bytes = fread (buffer, 1, CHUNKSIZE, state->in); ogg_sync_wrote (state->oy, bytes); if (!bytes) { @@ -523,6 +560,12 @@ vcedit_write (vcedit_state *state, void *out) } } + fclose (out); + fclose (state->in); + + unlink (state->filename); + rename (tmpfile, state->filename); + cleanup: ogg_stream_clear (&streamout); @@ -542,5 +585,10 @@ cleanup: return -1; } + vcedit_clear_internals (state); + + state->in = fopen (state->filename, "rb"); + vcedit_open (state); + return 0; }