2 * Copyright (C) 2006 Tilman Sauerbeck (tilman at code-monkey de)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation, version 2.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 #define CHECK_CLOSED(o) \
30 rb_raise (eClosed, "closed stream");
37 static VALUE c_close (VALUE self);
39 static VALUE cComments, eVT, eClosed, eOpen, eInvalidData,
40 eInvalidComment, eTempFile, eReopen;
44 c_free (RbVorbisTagger *o)
46 /* just in case the user forgot to call #close himself */
48 vcedit_state_unref (o->state);
54 c_mark (RbVorbisTagger *o)
56 rb_gc_mark (o->comments);
64 return Data_Make_Struct (klass, RbVorbisTagger, c_mark, c_free, o);
69 * Ogg::Vorbis::Tagger.open(arg) -> object
70 * Ogg::Vorbis::Tagger.open(arg) { |object| block } -> object
72 * If a block isn't specified, Ogg::Vorbis::Tagger.open is a synonym
73 * for Ogg::Vorbis::Tagger.new.
74 * If a block is given, it will be invoked with the * Ogg::Vorbis::Tagger
75 * object as a parameter.
78 c_open (VALUE klass, VALUE arg)
80 VALUE obj = rb_class_new_instance (1, &arg, klass);
82 if (rb_block_given_p ())
83 return rb_ensure (rb_yield, obj, c_close, obj);
90 * Ogg::Vorbis::Tagger.new(filename) -> object
92 * Returns a new Ogg::Vorbis::Tagger object for the specified file.
94 * FIXME: add optional mode argument (read-only or read-write)
97 c_init (VALUE self, VALUE filename)
103 Data_Get_Struct (self, RbVorbisTagger, o);
105 StringValue (filename);
107 o->state = vcedit_state_new (StringValuePtr (filename));
109 rb_raise (rb_eNoMemError, "Out of Memory");
111 switch (vcedit_open (o->state)) {
112 case VCEDIT_ERR_OPEN:
113 rb_raise (eOpen, "Cannot open file");
114 case VCEDIT_ERR_INVAL:
115 rb_raise (eInvalidData, "Invalid data");
120 vc = vcedit_comments (o->state);
122 /* vcedit_open() succeeded, so vcedit_comments() cannot
127 /* check whether all comments are well-formed */
128 for (i = 0; i < vc->comments; i++) {
129 char *ptr, *content = vc->user_comments[i];
131 ptr = strchr (content, '=');
132 if (!ptr || ptr == content)
133 rb_raise (eInvalidComment, "invalid comment - %s", content);
136 o->comments = rb_class_new_instance (0, NULL, cComments);
138 comments_init (o->comments, o->state);
145 * object.close -> nil
147 * Closes *object*. Further method calls on *object* will raise an
148 * Ogg::Vorbis::Tagger::ClosedStreamError exception.
156 Data_Get_Struct (self, RbVorbisTagger, o);
160 vcedit_state_unref (o->state);
168 * object.write -> integer
170 * Writes the comments from *object* back to the IO object and
171 * returns the numbers of comments written.
178 Data_Get_Struct (self, RbVorbisTagger, o);
182 comments_sync (o->comments, o->state);
184 switch (vcedit_write (o->state)) {
185 case VCEDIT_ERR_INVAL:
186 rb_raise (eInvalidData, "Invalid data");
187 case VCEDIT_ERR_TMPFILE:
188 rb_raise (eTempFile, "Cannot create temporary file");
189 case VCEDIT_ERR_REOPEN:
190 rb_raise (eReopen, "Cannot reopen file");
195 return rb_funcall2 (o->comments, id_length, 0, NULL);
200 * object.comments -> comments
202 * Returns the comments collection of *object*, which is an instance of
203 * Ogg::Vorbis::Comments.
206 c_comments (VALUE self)
210 Data_Get_Struct (self, RbVorbisTagger, o);
219 Init_vorbistagger_ext (void)
221 VALUE mOgg, mVorbis, eOgg, eVorbis, cVT;
223 mOgg = rb_define_module ("Ogg");
224 mVorbis = rb_define_module_under (mOgg, "Vorbis");
226 eOgg = rb_define_class_under (mOgg, "OggError", rb_eStandardError);
227 eVorbis = rb_define_class_under (mVorbis, "VorbisError", eOgg);
229 cVT = rb_define_class_under (mVorbis, "Tagger", rb_cObject);
231 rb_define_alloc_func (cVT, c_alloc);
233 rb_define_singleton_method (cVT, "open", c_open, 1);
234 rb_define_method (cVT, "initialize", c_init, 1);
235 rb_define_method (cVT, "close", c_close, 0);
236 rb_define_method (cVT, "write", c_write, 0);
237 rb_define_method (cVT, "comments", c_comments, 0);
239 eVT = rb_define_class_under (cVT, "TaggerError", eVorbis);
240 eClosed = rb_define_class_under (cVT, "ClosedStreamError", eVT);
241 eOpen = rb_define_class_under (cVT, "OpenError", eVT);
242 eInvalidData = rb_define_class_under (cVT, "InvalidDataError", eVT);
243 eInvalidComment = rb_define_class_under (cVT, "InvalidCommentError",
245 eTempFile = rb_define_class_under (cVT, "TempFileError", eVT);
246 eReopen = rb_define_class_under (cVT, "ReopenError", eVT);
248 id_length = rb_intern ("length");
250 cComments = Init_Comments (mVorbis);