projects
/
ruby-vorbistagger.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Reworked the loop that finds the first ogg page in the input stream.
[ruby-vorbistagger.git]
/
ext
/
vcedit.c
diff --git
a/ext/vcedit.c
b/ext/vcedit.c
index 073196b3fdb1b1b9ebfcda7166b871f7d1354de3..46d68ee578231999db4d9f0b236fe0a234d44579 100644
(file)
--- a/
ext/vcedit.c
+++ b/
ext/vcedit.c
@@
-31,66
+31,51
@@
#define CHUNKSIZE 4096
#define CHUNKSIZE 4096
-static int vcedit_open (vcedit_state *state);
-
struct vcedit_state_St {
int refcount;
struct vcedit_state_St {
int refcount;
- ogg_sync_state *oy;
- ogg_stream_state *os;
-
- vorbis_comment *vc;
- vorbis_info *vi;
+ ogg_sync_state oy;
+ ogg_stream_state os;
- char filename[PATH_MAX];
+ vorbis_comment vc;
+ vorbis_info vi;
FILE *in;
FILE *in;
+ bool opened;
long serial;
unsigned char *mainbuf;
unsigned char *bookbuf;
int mainlen;
int booklen;
long serial;
unsigned char *mainbuf;
unsigned char *bookbuf;
int mainlen;
int booklen;
- const char *lasterror;
char *vendor;
int prevW;
int extrapage;
int eosin;
char *vendor;
int prevW;
int extrapage;
int eosin;
+
+ char filename[0];
};
static void
vcedit_state_free (vcedit_state *state)
{
};
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);
free (state->mainbuf);
free (state->bookbuf);
free (state->vendor);
+ if (state->in) {
+ fclose (state->in);
+ state->in = NULL;
+ }
+
free (state);
}
static bool
free (state);
}
static bool
-vcedit_state_init (vcedit_state *state)
+vcedit_state_init (vcedit_state *state
, const char *filename
)
{
state->refcount = 1;
{
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;
+ strcpy (state->filename, filename);
return true;
}
return true;
}
@@
-99,24
+84,19
@@
vcedit_state *
vcedit_state_new (const char *filename)
{
vcedit_state *state;
vcedit_state_new (const char *filename)
{
vcedit_state *state;
+ size_t len;
-
state = malloc (sizeof (vcedit_state)
);
- if (
!state
)
+
len = strlen (filename
);
+ if (
len > PATH_MAX
)
return NULL;
return NULL;
- memset (state, 0, sizeof (vcedit_state));
-
- if (!vcedit_state_init (state)) {
- vcedit_state_free (state);
+ state = malloc (sizeof (vcedit_state) + len + 1);
+ if (!state)
return NULL;
return NULL;
- }
-
- snprintf (state->filename, sizeof (state->filename),
- "%s", filename);
-
state->in = fopen (state->filename, "rb"
);
+
memset (state, 0, sizeof (vcedit_state)
);
- if (
vcedit_open (state) < 0
) {
+ if (
!vcedit_state_init (state, filename)
) {
vcedit_state_free (state);
return NULL;
}
vcedit_state_free (state);
return NULL;
}
@@
-124,26
+104,20
@@
vcedit_state_new (const char *filename)
return state;
}
return state;
}
-const char *
-vcedit_error (vcedit_state *state)
-{
- return state->lasterror;
-}
-
vorbis_comment *
vcedit_comments (vcedit_state *state)
{
vorbis_comment *
vcedit_comments (vcedit_state *state)
{
- return state->
vc
;
+ return state->
opened ? &state->vc : NULL
;
}
static void
vcedit_clear_internals (vcedit_state *state)
{
}
static void
vcedit_clear_internals (vcedit_state *state)
{
- ogg_stream_clear (state->os);
- ogg_sync_clear (state->oy);
+ ogg_stream_clear (
&
state->os);
+ ogg_sync_clear (
&
state->oy);
- vorbis_info_clear (state->vi);
- vorbis_comment_clear (state->vc);
+ vorbis_info_clear (
&
state->vi);
+ vorbis_comment_clear (
&
state->vc);
free (state->vendor);
state->vendor = NULL;
free (state->vendor);
state->vendor = NULL;
@@
-157,6
+131,7
@@
vcedit_clear_internals (vcedit_state *state)
state->booklen = 0;
state->serial = 0;
state->booklen = 0;
state->serial = 0;
+ state->opened = false;
}
void
}
void
@@
-171,7
+146,9
@@
vcedit_state_unref (vcedit_state *state)
if (--state->refcount)
return;
if (--state->refcount)
return;
- vcedit_clear_internals (state);
+ if (state->opened)
+ vcedit_clear_internals (state);
+
vcedit_state_free (state);
}
vcedit_state_free (state);
}
@@
-236,7
+213,7
@@
_blocksize (vcedit_state *s, ogg_packet *p)
{
int this, ret = 0;
{
int this, ret = 0;
- this = vorbis_packet_blocksize (s->vi, p);
+ this = vorbis_packet_blocksize (
&
s->vi, p);
if (s->prevW)
ret = (this + s->prevW) / 4;
if (s->prevW)
ret = (this + s->prevW) / 4;
@@
-252,7
+229,7
@@
_fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
char *buffer;
int result, bytes;
char *buffer;
int result, bytes;
- result = ogg_stream_packetout (s->os, p);
+ result = ogg_stream_packetout (
&
s->os, p);
if (result > 0)
return 1;
if (result > 0)
return 1;
@@
-260,10
+237,10
@@
_fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
if (s->eosin)
return 0;
if (s->eosin)
return 0;
- while (ogg_sync_pageout (s->oy, page) <= 0) {
- buffer = ogg_sync_buffer (s->oy, CHUNKSIZE);
+ while (ogg_sync_pageout (
&
s->oy, page) <= 0) {
+ buffer = ogg_sync_buffer (
&
s->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, s->in);
bytes = fread (buffer, 1, CHUNKSIZE, s->in);
- ogg_sync_wrote (s->oy, bytes);
+ ogg_sync_wrote (
&
s->oy, bytes);
if (!bytes)
return 0;
if (!bytes)
return 0;
@@
-277,61
+254,62
@@
_fetch_next_packet (vcedit_state *s, ogg_packet *p, ogg_page *page)
return 0;
}
return 0;
}
- ogg_stream_pagein (s->os, page);
+ ogg_stream_pagein (
&
s->os, page);
return _fetch_next_packet (s, p, page);
}
return _fetch_next_packet (s, p, page);
}
-static int
+vcedit_error
vcedit_open (vcedit_state *state)
{
vcedit_open (vcedit_state *state)
{
+ vcedit_error ret;
char *buffer;
char *buffer;
-
int bytes, i
;
- int
chunks = 0
;
+
size_t bytes, total = 0
;
+ int
i
;
ogg_packet *header;
ogg_packet header_main, header_comments, header_codebooks;
ogg_page og;
ogg_packet *header;
ogg_packet header_main, header_comments, header_codebooks;
ogg_page og;
- ogg_sync_init (state->oy);
-
- while (1) {
- buffer = ogg_sync_buffer (state->oy, CHUNKSIZE);
- bytes = fread (buffer, 1, CHUNKSIZE, state->in);
-
- ogg_sync_wrote (state->oy, bytes);
+ state->in = fopen (state->filename, "rb");
+ if (!state->in)
+ return VCEDIT_ERR_OPEN;
- if (ogg_sync_pageout (state->oy, &og) == 1)
- break;
+ ogg_sync_init (&state->oy);
+ do {
/* Bail if we don't find data in the first 40 kB */
/* 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.";
+ if (feof (state->in) || total >= (CHUNKSIZE * 10)) {
+ ogg_sync_clear (&state->oy);
-
goto err
;
+
return VCEDIT_ERR_INVAL
;
}
}
- }
+
+ buffer = ogg_sync_buffer (&state->oy, CHUNKSIZE);
+
+ bytes = fread (buffer, 1, CHUNKSIZE, state->in);
+ total += bytes;
+
+ ogg_sync_wrote (&state->oy, bytes);
+ } while (ogg_sync_pageout (&state->oy, &og) != 1);
state->serial = ogg_page_serialno (&og);
state->serial = ogg_page_serialno (&og);
- ogg_stream_init (state->os, state->serial);
- vorbis_info_init (state->vi);
- vorbis_comment_init (state->vc);
+ ogg_stream_init (
&
state->os, state->serial);
+ vorbis_info_init (
&
state->vi);
+ vorbis_comment_init (
&
state->vc);
- if (ogg_stream_pagein (state->os, &og) < 0) {
-
state->lasterror = "Error reading first page of Ogg bitstream."
;
+ if (ogg_stream_pagein (
&
state->os, &og) < 0) {
+
ret = VCEDIT_ERR_INVAL
;
goto err;
}
goto err;
}
- if (ogg_stream_packetout (state->os, &header_main) != 1) {
-
state->lasterror = "Error reading initial header packet."
;
+ if (ogg_stream_packetout (
&
state->os, &header_main) != 1) {
+
ret = VCEDIT_ERR_INVAL
;
goto err;
}
goto err;
}
- if (vorbis_synthesis_headerin (
state->vi,
state->vc, &header_main) < 0) {
-
state->lasterror = "Ogg bitstream does not contain vorbis data."
;
+ if (vorbis_synthesis_headerin (
&state->vi, &
state->vc, &header_main) < 0) {
+
ret = VCEDIT_ERR_INVAL
;
goto err;
}
goto err;
}
@@
-344,26
+322,26
@@
vcedit_open (vcedit_state *state)
while (i < 2) {
while (i < 2) {
while (i < 2) {
while (i < 2) {
- int result = ogg_sync_pageout (state->oy, &og);
+ int result = ogg_sync_pageout (
&
state->oy, &og);
if (!result)
break; /* Too little data so far */
if (result == 1) {
if (!result)
break; /* Too little data so far */
if (result == 1) {
- ogg_stream_pagein (state->os, &og);
+ ogg_stream_pagein (
&
state->os, &og);
while (i < 2) {
while (i < 2) {
- result = ogg_stream_packetout (state->os, header);
+ result = ogg_stream_packetout (
&
state->os, header);
if (!result)
break;
if (result == -1) {
if (!result)
break;
if (result == -1) {
-
state->lasterror = "Corrupt secondary header."
;
+
ret = VCEDIT_ERR_INVAL
;
goto err;
}
goto err;
}
- vorbis_synthesis_headerin (
state->vi,
state->vc, header);
+ vorbis_synthesis_headerin (
&state->vi, &
state->vc, header);
if (i == 1) {
state->booklen = header->bytes;
if (i == 1) {
state->booklen = header->bytes;
@@
-377,30
+355,32
@@
vcedit_open (vcedit_state *state)
}
}
}
}
- buffer = ogg_sync_buffer (state->oy, CHUNKSIZE);
+ buffer = ogg_sync_buffer (
&
state->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
if (bytes == 0 && i < 2) {
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;
}
goto err;
}
- ogg_sync_wrote (state->oy, bytes);
+ ogg_sync_wrote (
&
state->oy, bytes);
}
/* Copy the vendor tag */
}
/* Copy the vendor tag */
- state->vendor = strdup (state->vc
->
vendor);
+ state->vendor = strdup (state->vc
.
vendor);
/* Headers are done! */
/* Headers are done! */
- return 0;
+ state->opened = true;
+
+ return VCEDIT_ERR_SUCCESS;
err:
vcedit_clear_internals (state);
err:
vcedit_clear_internals (state);
- return
-1
;
+ return
ret
;
}
}
-int
+vcedit_error
vcedit_write (vcedit_state *state)
{
ogg_stream_state streamout;
vcedit_write (vcedit_state *state)
{
ogg_stream_state streamout;
@@
-412,23
+392,22
@@
vcedit_write (vcedit_state *state)
int s, result, bytes, needflush = 0, needout = 0;
size_t tmp;
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);
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);
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;
}
state->prevW = state->extrapage = state->eosin = 0;
@@
-447,7
+426,7
@@
vcedit_write (vcedit_state *state)
ogg_stream_init (&streamout, state->serial);
ogg_stream_init (&streamout, state->serial);
- _commentheader_out (state->vc, state->vendor, &header_comments);
+ _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_main);
ogg_stream_packetin (&streamout, &header_comments);
@@
-541,14
+520,12
@@
vcedit_write (vcedit_state *state)
* through, a page at a time.
*/
while (1) {
* through, a page at a time.
*/
while (1) {
- result = ogg_sync_pageout (state->oy, &ogout);
+ result = ogg_sync_pageout (
&
state->oy, &ogout);
if (!result)
break;
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
*/
/* Don't bother going through the rest, we can just
* write the page out now
*/
@@
-562,9
+539,9
@@
vcedit_write (vcedit_state *state)
}
}
}
}
- buffer = ogg_sync_buffer (state->oy, CHUNKSIZE);
+ buffer = ogg_sync_buffer (
&
state->oy, CHUNKSIZE);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
bytes = fread (buffer, 1, CHUNKSIZE, state->in);
- ogg_sync_wrote (state->oy, bytes);
+ ogg_sync_wrote (
&
state->oy, bytes);
if (!bytes) {
state->eosin = 1;
if (!bytes) {
state->eosin = 1;
@@
-591,16
+568,11
@@
cleanup:
state->mainbuf = state->bookbuf = NULL;
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);
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;
}
}