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,
32 static ID id_casecmp, id_replace, id_compare;
35 comments_init (VALUE self, vcedit_state *state)
41 Data_Get_Struct (self, RbVorbisComments, o);
44 vcedit_state_ref (state);
46 vc = vcedit_comments (o->state);
48 o->items = rb_ary_new2 (vc->comments);
50 for (i = 0; i < vc->comments; i++) {
52 char *ptr, *content = vc->user_comments[i];
54 ptr = strchr (content, '=');
57 k = rb_str_new (content, ptr - content);
60 v = rb_str_new2 (ptr + 1);
62 pair = rb_ary_new3 (2, k, v);
65 rb_ary_store (o->items, i, pair);
68 rb_iv_set (self, "@items", o->items);
72 comments_sync (VALUE self)
79 Data_Get_Struct (self, RbVorbisComments, o);
81 vc = vcedit_comments (o->state);
83 vorbis_comment_clear (vc);
84 vorbis_comment_init (vc);
86 items = RARRAY (o->items);
88 for (i = 0; i < items->len; i++) {
89 struct RArray *pair = RARRAY (items->ptr[i]);
91 vorbis_comment_add_tag (vc,
92 StringValuePtr (pair->ptr[0]),
93 StringValuePtr (pair->ptr[1]));
98 c_mark (RbVorbisComments *o)
100 rb_gc_mark (o->items);
104 c_free (RbVorbisComments *o)
106 vcedit_state_unref (o->state);
112 c_alloc (VALUE klass)
116 return Data_Make_Struct (klass, RbVorbisComments, c_mark, c_free, o);
121 * object.inspect -> string
123 * Returns the contents of *object* as a string.
126 c_inspect (VALUE self)
130 struct RArray *items;
133 Data_Get_Struct (self, RbVorbisComments, o);
135 items = RARRAY (o->items);
137 ret = rb_str_buf_new (128);
138 rb_str_buf_cat (ret, "{", 1);
140 for (i = 0; i < items->len; i++) {
141 struct RArray *pair = RARRAY (items->ptr[i]);
144 rb_str_buf_cat (ret, ", ", 2);
146 rb_str_buf_append (ret, rb_inspect (pair->ptr[0]));
147 rb_str_buf_cat (ret, "=>", 2);
148 rb_str_buf_append (ret, rb_inspect (pair->ptr[1]));
151 rb_str_buf_cat (ret, "}", 1);
158 * object.clear -> object
160 * Removes all elements from *object* and returns it.
167 Data_Get_Struct (self, RbVorbisComments, o);
169 rb_ary_clear (o->items);
176 * object.delete(key) -> string or nil
178 * If a tag with the specified key exists, that tag is deleted and
179 * the tag's value is returned. Otherwise, +nil+ is returned.
182 c_delete (VALUE self, VALUE key)
186 struct RArray *items;
189 Data_Get_Struct (self, RbVorbisComments, o);
191 items = RARRAY (o->items);
193 for (i = 0; i < items->len; i++) {
194 struct RArray *pair = RARRAY (items->ptr[i]);
197 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
198 if (tmp == INT2FIX (0)) {
206 rb_ary_delete_at (o->items, pos);
213 * object.keys -> array
215 * Returns an array that contains the keys of the tags in *object*.
222 struct RArray *items;
225 Data_Get_Struct (self, RbVorbisComments, o);
227 items = RARRAY (o->items);
228 ret = rb_ary_new2 (items->len);
230 for (i = 0; i < items->len; i++) {
231 struct RArray *pair = RARRAY (items->ptr[i]);
233 rb_ary_store (ret, i, pair->ptr[0]);
241 * object.values -> array
243 * Returns an array that contains the values of the tags in *object*.
246 c_values (VALUE self)
250 struct RArray *items;
253 Data_Get_Struct (self, RbVorbisComments, o);
255 items = RARRAY (o->items);
256 ret = rb_ary_new2 (items->len);
258 for (i = 0; i < items->len; i++) {
259 struct RArray *pair = RARRAY (items->ptr[i]);
261 rb_ary_store (ret, i, pair->ptr[1]);
269 * object.length -> integer
271 * Returns the number of tags in *object*.
274 c_length (VALUE self)
278 Data_Get_Struct (self, RbVorbisComments, o);
280 return LONG2NUM (RARRAY (o->items)->len);
285 * object.empty? -> true or false
287 * Returns true if *object* is empty or false otherwise.
290 c_get_empty (VALUE self)
294 Data_Get_Struct (self, RbVorbisComments, o);
296 return !RARRAY(o->items)->len;
301 * object[key] -> string
303 * Returns the value of the tag with the key *key* or +nil+ if the
304 * tag cannot be found.
307 c_aref (VALUE self, VALUE key)
310 struct RArray *items;
313 Data_Get_Struct (self, RbVorbisComments, o);
315 items = RARRAY (o->items);
317 for (i = 0; i < items->len; i++) {
318 struct RArray *pair = RARRAY (items->ptr[i]);
321 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
322 if (tmp == INT2FIX (0))
331 * object[key] = string
333 * Sets the value of the tag with the key *key* to *string*.
336 c_aset (VALUE self, VALUE key, VALUE value)
340 struct RArray *items;
343 Data_Get_Struct (self, RbVorbisComments, o);
345 items = RARRAY (o->items);
347 for (i = 0; i < items->len; i++) {
348 struct RArray *pair = RARRAY (items->ptr[i]);
351 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
352 if (tmp == INT2FIX (0)) {
353 rb_funcall (pair->ptr[1], id_replace, 1, value);
358 tmp = rb_ary_new3 (2, key, value);
361 rb_ary_push (o->items, tmp);
368 * object.has_key?(key) -> true or false
370 * Returns true if a tag exists with the specified key or false
374 c_has_key (VALUE self, VALUE key)
377 struct RArray *items;
380 Data_Get_Struct (self, RbVorbisComments, o);
382 items = RARRAY (o->items);
384 for (i = 0; i < items->len; i++) {
385 struct RArray *pair = RARRAY (items->ptr[i]);
388 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
389 if (tmp == INT2FIX (0))
398 * object <=> other -> -1, 0 or 1
400 * Compares *object* to *other* and returns -1, 0 or 1 if
401 * *object* is less than, equal or greater than *other*.
404 c_compare (VALUE self, VALUE other)
406 RbVorbisComments *o, *o2;
407 struct RArray *a, *b;
410 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
411 rb_raise (rb_eArgError, "invalid argument");
413 Data_Get_Struct (self, RbVorbisComments, o);
414 Data_Get_Struct (other, RbVorbisComments, o2);
416 a = RARRAY (o->items);
417 b = RARRAY (o2->items);
425 for (i = 0; i < a->len; i++) {
426 struct RArray *aa = RARRAY (a->ptr[i]);
427 struct RArray *bb = RARRAY (b->ptr[i]);
429 for (j = 0; j < 2; j++) {
432 tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]);
433 if (FIX2INT (tmp) != 0)
443 * object.each { |key, value| block } -> object
445 * Calls _block_ once for each tag in *object*, passing the key and
453 struct RArray *items;
456 Data_Get_Struct (self, RbVorbisComments, o);
458 items = RARRAY (o->items);
460 for (i = 0; i < items->len; i++) {
461 struct RArray *pair = RARRAY (items->ptr[i]);
463 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
471 * object.each_key { |key| block } -> object
473 * Calls _block_ once for each tag in *object*, passing the key
478 c_each_key (VALUE self)
481 struct RArray *items;
484 Data_Get_Struct (self, RbVorbisComments, o);
486 items = RARRAY (o->items);
488 for (i = 0; i < items->len; i++) {
489 struct RArray *pair = RARRAY (items->ptr[i]);
491 rb_yield (pair->ptr[0]);
499 * object.each_value { |value| block } -> object
501 * Calls _block_ once for each tag in *object*, passing the value
502 * of the tag. Returns *object*.
505 c_each_value (VALUE self)
508 struct RArray *items;
511 Data_Get_Struct (self, RbVorbisComments, o);
513 items = RARRAY (o->items);
515 for (i = 0; i < items->len; i++) {
516 struct RArray *pair = RARRAY (items->ptr[i]);
518 rb_yield (pair->ptr[1]);
525 Init_Comments (VALUE mVorbis)
529 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
531 rb_define_alloc_func (c, c_alloc);
533 rb_define_method (c, "inspect", c_inspect, 0);
534 rb_define_method (c, "clear", c_clear, 0);
535 rb_define_method (c, "delete", c_delete, 1);
536 rb_define_method (c, "length", c_length, 0);
537 rb_define_method (c, "has_key?", c_has_key, 1);
538 rb_define_method (c, "[]", c_aref, 1);
539 rb_define_method (c, "[]=", c_aset, 2);
540 rb_define_method (c, "empty?", c_get_empty, 0);
541 rb_define_method (c, "keys", c_keys, 0);
542 rb_define_method (c, "values", c_values, 0);
544 rb_include_module (c, rb_mComparable);
545 rb_define_method (c, "<=>", c_compare, 1);
547 rb_include_module (c, rb_mEnumerable);
548 rb_define_method (c, "each", c_each, 0);
549 rb_define_method (c, "each_key", c_each_key, 0);
550 rb_define_method (c, "each_value", c_each_value, 0);
552 rb_define_alias (c, "size", "length");
553 rb_define_alias (c, "each_pair", "each");
555 id_casecmp = rb_intern ("casecmp");
556 id_replace = rb_intern ("replace");
557 id_compare = rb_intern ("<=>");