*/
#include <ruby.h>
+#include <stdio.h>
#include <stdbool.h>
+#include <errno.h>
#include "vcedit.h"
#include "comments.h"
typedef struct {
- VALUE io;
- bool need_close;
-
vcedit_state *state;
-
VALUE comments;
} RbVorbisTagger;
static VALUE c_close (VALUE self);
-static VALUE cComments, eVTError, io_buf;
-static ID id_read, id_write, id_seek, id_length;
-
-static size_t
-on_read (void *ptr, size_t size, size_t nmemb, RbVorbisTagger *o)
-{
- struct RString *buf;
- size_t total = size * nmemb;
- VALUE tmp;
-
- rb_str_resize (io_buf, size * nmemb);
-
- tmp = rb_funcall (o->io, id_read, 2, LONG2NUM (total), io_buf);
- if (NIL_P (tmp))
- return 0;
-
- buf = RSTRING (tmp);
- memcpy (ptr, buf->ptr, buf->len);
-
- return buf->len;
-}
-
-static size_t
-on_write (const void *ptr, size_t size, size_t nmemb, RbVorbisTagger *o)
-{
- size_t total = size * nmemb;
-
- rb_str_resize (io_buf, total);
- memcpy (RSTRING (io_buf)->ptr, ptr, total);
-
- return NUM2LONG (rb_io_write (o->io, io_buf));
-}
-
-static void
-c_mark (RbVorbisTagger *o)
-{
- rb_gc_mark (o->io);
- rb_gc_mark (o->comments);
-}
+static VALUE cComments, eVTError;
+static ID id_length;
static void
c_free (RbVorbisTagger *o)
ruby_xfree (o);
}
+static void
+c_mark (RbVorbisTagger *o)
+{
+ rb_gc_mark (o->comments);
+}
+
static VALUE
c_alloc (VALUE klass)
{
/*
* call-seq:
* Ogg::Vorbis::Tagger.open(arg) -> object
- * Ogg::Vorbis::Tagger.open(arg) { |object| block } -> nil
+ * Ogg::Vorbis::Tagger.open(arg) { |object| block } -> object
*
* If a block isn't specified, Ogg::Vorbis::Tagger.open is a synonym
* for Ogg::Vorbis::Tagger.new.
- * If a block is given, it will be invoked with the
- * Ogg::Vorbis::Tagger object as a parameter, and the file or IO object
- * will be automatically closed when the block terminates.
- * The method always returns +nil+ in this case.
+ * If a block is given, it will be invoked with the * Ogg::Vorbis::Tagger
+ * object as a parameter.
*/
static VALUE
c_open (VALUE klass, VALUE arg)
/*
* call-seq:
- * Ogg::Vorbis::Tagger.new(arg) -> object
+ * Ogg::Vorbis::Tagger.new(filename) -> object
*
- * Returns a new Ogg::Vorbis::Tagger object for the specified argument.
- * *arg* can either be an IO object or a filename.
+ * Returns a new Ogg::Vorbis::Tagger object for the specified file.
*
* FIXME: add optional mode argument (read-only or read-write)
*/
static VALUE
-c_init (VALUE self, VALUE io)
+c_init (VALUE self, VALUE filename)
{
RbVorbisTagger *o;
vorbis_comment *vc;
- int s, i;
+ int i;
Data_Get_Struct (self, RbVorbisTagger, o);
- /* is this actually an IO object or a filename? */
- if (rb_respond_to (io, id_read) &&
- rb_respond_to (io, id_write) &&
- rb_respond_to (io, id_seek))
- o->need_close = false;
- else if (!NIL_P (rb_check_string_type (io))) {
- io = rb_file_open (StringValuePtr (io), "rb+");
- o->need_close = true;
- } else
- rb_raise (rb_eArgError, "invalid argument");
+ StringValue (filename);
- o->io = io;
-
- o->state = vcedit_state_new ();
+ o->state = vcedit_state_new (StringValuePtr (filename));
if (!o->state)
rb_raise (eVTError, "vcedit_new_state() failed - %s",
vcedit_error (o->state));
- s = vcedit_open_callbacks (o->state, o,
- (vcedit_read_func) on_read,
- (vcedit_write_func) on_write);
- if (s < 0)
- rb_raise (eVTError, "vcedit_open_callbacks() failed - %s",
- vcedit_error (o->state));
-
vc = vcedit_comments (o->state);
if (!vc)
rb_raise (eVTError, "vcedit_comments() failed - %s",
vcedit_state_unref (o->state);
o->state = NULL;
- if (o->need_close)
- rb_io_close (o->io);
-
return self;
}
c_write (VALUE self)
{
RbVorbisTagger *o;
- int s;
Data_Get_Struct (self, RbVorbisTagger, o);
- comments_sync (o->comments);
+ comments_sync (o->comments, o->state);
- /* seek back to BOF */
- rb_funcall (o->io, id_seek, 1, INT2FIX (0));
-
- s = vcedit_write (o->state, o);
- if (s < 0)
+ if (vcedit_write (o->state) < 0)
rb_raise (rb_eIOError, "write failed - %s",
vcedit_error (o->state));
rb_define_singleton_method (cVT, "open", c_open, 1);
rb_define_method (cVT, "initialize", c_init, 1);
- rb_define_method (cVT, "close", c_close, 0);
rb_define_method (cVT, "write", c_write, 0);
rb_define_method (cVT, "comments", c_comments, 0);
eVTError = rb_define_class_under (cVT, "TaggerError", eVorbis);
- id_read = rb_intern ("read");
- id_write = rb_intern ("write");
- id_seek = rb_intern ("seek");
id_length = rb_intern ("length");
cComments = Init_Comments (mVorbis);
-
- io_buf = rb_str_buf_new (0);
- rb_global_variable (&io_buf);
}