X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=ext%2Fvcedit.c;h=24622e855974eafc7a6c7765c7edfc21a017d302;hb=2cedce4cb348f6980ec64ab746b58d32f62b20a3;hp=c7bd8e75becb618d5ace62fd212f33db2001ca0b;hpb=310e91e26bebf168b6081e91da123b4a8cfb9b67;p=ruby-vorbistagger.git diff --git a/ext/vcedit.c b/ext/vcedit.c index c7bd8e7..24622e8 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,42 @@ 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; } void @@ -126,6 +147,7 @@ vcedit_state_unref (vcedit_state *state) state->refcount--; if (!state->refcount) { + fclose (state->in); vcedit_clear_internals (state); free (state); } @@ -145,6 +167,8 @@ _v_writestring (oggpack_buffer *o, char *s, int len) static int _commentheader_out (vorbis_comment *vc, char *vendor, ogg_packet *op) { + int i; + oggpack_buffer opb; oggpack_writeinit (&opb); @@ -160,16 +184,13 @@ _commentheader_out (vorbis_comment *vc, char *vendor, ogg_packet *op) /* 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); + for (i = 0; i < vc->comments; i++) { + if (!vc->user_comments[i]) + oggpack_write (&opb, 0, 32); + else { + oggpack_write (&opb, vc->comment_lengths[i], 32); + _v_writestring (&opb, vc->user_comments[i], + vc->comment_lengths[i]); } } @@ -191,13 +212,12 @@ _commentheader_out (vorbis_comment *vc, char *vendor, ogg_packet *op) static int _blocksize (vcedit_state *s, ogg_packet *p) { - int this = vorbis_packet_blocksize (s->vi, p); - int ret = (this + s->prevW) / 4; + int this, ret = 0; - if (!s->prevW) { - s->prevW = this; - return 0; - } + this = vorbis_packet_blocksize (s->vi, p); + + if (s->prevW) + ret = (this + s->prevW) / 4; s->prevW = this; @@ -220,7 +240,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 +260,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 +270,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 +362,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,18 +385,37 @@ 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; - state->eosin = 0; - state->extrapage = 0; + 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->prevW = state->extrapage = state->eosin = 0; header_main.bytes = state->mainlen; header_main.packet = state->mainbuf; @@ -405,11 +438,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 +455,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 +498,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 +536,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 +556,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 +581,10 @@ cleanup: return -1; } + vcedit_clear_internals (state); + + state->in = fopen (state->filename, "rb"); + vcedit_open (state); + return 0; }