00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <ctype.h>
00021
00022 #include "xmmsc/xmmsc_idnumbers.h"
00023 #include "xmmsc/xmmsv.h"
00024 #include "xmmsc/xmmsv_coll.h"
00025 #include "xmmsc/xmmsc_util.h"
00026 #include "xmmspriv/xmms_list.h"
00027
00028
00029 struct xmmsv_coll_St {
00030
00031
00032 int ref;
00033
00034 xmmsv_coll_type_t type;
00035
00036 xmmsv_t *operands;
00037 x_list_t *operand_iter_stack;
00038
00039
00040 xmmsv_t *attributes;
00041 xmmsv_dict_iter_t *attributes_iter;
00042
00043
00044 uint32_t *idlist;
00045 size_t idlist_size;
00046 size_t idlist_allocated;
00047
00048 };
00049
00050
00051 static void xmmsv_coll_free (xmmsv_coll_t *coll);
00052
00053 static int xmmsv_coll_idlist_resize (xmmsv_coll_t *coll, size_t newsize);
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 xmmsv_coll_t *
00071 xmmsv_coll_ref (xmmsv_coll_t *coll)
00072 {
00073 x_return_val_if_fail (coll, NULL);
00074
00075 coll->ref++;
00076
00077 return coll;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087 xmmsv_coll_t*
00088 xmmsv_coll_new (xmmsv_coll_type_t type)
00089 {
00090 xmmsv_list_iter_t *i;
00091 xmmsv_coll_t *coll;
00092
00093 x_return_val_if_fail (type <= XMMS_COLLECTION_TYPE_LAST, NULL);
00094
00095 coll = x_new0 (xmmsv_coll_t, 1);
00096 if (!coll) {
00097 x_oom ();
00098 return NULL;
00099 }
00100
00101 if (!(coll->idlist = x_new0 (uint32_t, 1))) {
00102 x_oom ();
00103 return NULL;
00104 }
00105 coll->idlist_size = 1;
00106 coll->idlist_allocated = 1;
00107
00108 coll->ref = 0;
00109 coll->type = type;
00110
00111 coll->operands = xmmsv_new_list ();
00112 xmmsv_list_restrict_type (coll->operands, XMMSV_TYPE_COLL);
00113 xmmsv_get_list_iter (coll->operands, &i);
00114
00115 coll->operand_iter_stack = x_list_prepend (coll->operand_iter_stack, i);
00116
00117 coll->attributes = xmmsv_new_dict ();
00118 xmmsv_get_dict_iter (coll->attributes, &coll->attributes_iter);
00119
00120
00121 xmmsv_coll_ref (coll);
00122
00123 return coll;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133 static void
00134 xmmsv_coll_free (xmmsv_coll_t *coll)
00135 {
00136 x_return_if_fail (coll);
00137
00138
00139 xmmsv_unref (coll->operands);
00140 x_list_free (coll->operand_iter_stack);
00141
00142 xmmsv_unref (coll->attributes);
00143
00144 free (coll->idlist);
00145
00146 free (coll);
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 void
00157 xmmsv_coll_unref (xmmsv_coll_t *coll)
00158 {
00159 x_return_if_fail (coll);
00160 x_api_error_if (coll->ref < 1, "with a freed collection",);
00161
00162 coll->ref--;
00163 if (coll->ref == 0) {
00164 xmmsv_coll_free (coll);
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void
00178 xmmsv_coll_set_idlist (xmmsv_coll_t *coll, unsigned int ids[])
00179 {
00180 unsigned int i;
00181 unsigned int size = 0;
00182
00183 x_return_if_fail (coll);
00184
00185 while (ids[size] != 0) {
00186 ++size;
00187 }
00188 ++size;
00189
00190 free (coll->idlist);
00191 if (!(coll->idlist = x_new0 (uint32_t, size))) {
00192 x_oom ();
00193 return;
00194 }
00195
00196 for (i = 0; i < size; ++i) {
00197 coll->idlist[i] = ids[i];
00198 }
00199
00200 coll->idlist_size = size;
00201 coll->idlist_allocated = size;
00202 }
00203
00204 static int
00205 _xmmsv_coll_operand_find (xmmsv_list_iter_t *it, xmmsv_coll_t *op)
00206 {
00207 xmmsv_coll_t *c;
00208 xmmsv_t *v;
00209
00210 while (xmmsv_list_iter_valid (it)) {
00211 xmmsv_list_iter_entry (it, &v);
00212 if (xmmsv_get_coll (v, &c)) {
00213 if (c == op) {
00214 return 1;
00215 }
00216 }
00217 xmmsv_list_iter_next (it);
00218 }
00219 return 0;
00220 }
00221
00222
00223
00224
00225
00226
00227 void
00228 xmmsv_coll_add_operand (xmmsv_coll_t *coll, xmmsv_coll_t *op)
00229 {
00230 xmmsv_list_iter_t *it;
00231 xmmsv_t *v;
00232 x_return_if_fail (coll);
00233 x_return_if_fail (op);
00234
00235
00236 if (!xmmsv_get_list_iter (coll->operands, &it))
00237 return;
00238
00239 if (_xmmsv_coll_operand_find (it, op)) {
00240 x_api_warning ("with an operand already in operand list");
00241 xmmsv_list_iter_explicit_destroy (it);
00242 return;
00243 }
00244
00245 xmmsv_list_iter_explicit_destroy (it);
00246
00247 v = xmmsv_new_coll (op);
00248 x_return_if_fail (v);
00249 xmmsv_list_append (coll->operands, v);
00250 xmmsv_unref (v);
00251 }
00252
00253
00254
00255
00256
00257
00258 void
00259 xmmsv_coll_remove_operand (xmmsv_coll_t *coll, xmmsv_coll_t *op)
00260 {
00261 xmmsv_list_iter_t *it;
00262
00263 x_return_if_fail (coll);
00264 x_return_if_fail (op);
00265
00266 if (!xmmsv_get_list_iter (coll->operands, &it))
00267 return;
00268
00269 if (_xmmsv_coll_operand_find (it, op)) {
00270 xmmsv_list_iter_remove (it);
00271 } else {
00272 x_api_warning ("with an operand not in operand list");
00273 }
00274 xmmsv_list_iter_explicit_destroy (it);
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284 int
00285 xmmsv_coll_idlist_append (xmmsv_coll_t *coll, unsigned int id)
00286 {
00287 x_return_val_if_fail (coll, 0);
00288
00289 return xmmsv_coll_idlist_insert (coll, coll->idlist_size - 1, id);
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 int
00300 xmmsv_coll_idlist_insert (xmmsv_coll_t *coll, unsigned int index, unsigned int id)
00301 {
00302 int i;
00303 x_return_val_if_fail (coll, 0);
00304
00305 if (index >= coll->idlist_size) {
00306 return 0;
00307 }
00308
00309
00310 if (coll->idlist_size == coll->idlist_allocated) {
00311 int success;
00312 size_t double_size = coll->idlist_allocated * 2;
00313 success = xmmsv_coll_idlist_resize (coll, double_size);
00314 x_return_val_if_fail (success, 0);
00315 }
00316
00317 for (i = coll->idlist_size; i > index; i--) {
00318 coll->idlist[i] = coll->idlist[i - 1];
00319 }
00320
00321 coll->idlist[index] = id;
00322 coll->idlist_size++;
00323
00324 return 1;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334 int
00335 xmmsv_coll_idlist_move (xmmsv_coll_t *coll, unsigned int index, unsigned int newindex)
00336 {
00337 int i;
00338 uint32_t tmp;
00339
00340 x_return_val_if_fail (coll, 0);
00341
00342 if ((index >= coll->idlist_size - 1) || (newindex >= coll->idlist_size - 1)) {
00343 return 0;
00344 }
00345
00346 tmp = coll->idlist[index];
00347 if (index < newindex) {
00348 for (i = index; i < newindex; i++) {
00349 coll->idlist[i] = coll->idlist[i + 1];
00350 }
00351 }
00352 else if (index > newindex) {
00353 for (i = index; i > newindex; i--) {
00354 coll->idlist[i] = coll->idlist[i - 1];
00355 }
00356 }
00357 coll->idlist[newindex] = tmp;
00358
00359 return 1;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368 int
00369 xmmsv_coll_idlist_remove (xmmsv_coll_t *coll, unsigned int index)
00370 {
00371 int i;
00372 size_t half_size;
00373
00374 x_return_val_if_fail (coll, 0);
00375
00376 if (index >= coll->idlist_size - 1) {
00377 return 0;
00378 }
00379
00380 coll->idlist_size--;
00381 for (i = index; i < coll->idlist_size; i++) {
00382 coll->idlist[i] = coll->idlist[i + 1];
00383 }
00384
00385
00386 half_size = coll->idlist_allocated / 2;
00387 if (coll->idlist_size <= half_size) {
00388 xmmsv_coll_idlist_resize (coll, half_size);
00389 }
00390
00391 return 1;
00392 }
00393
00394
00395
00396
00397
00398
00399 int
00400 xmmsv_coll_idlist_clear (xmmsv_coll_t *coll)
00401 {
00402 unsigned int empty[] = { 0 };
00403
00404 x_return_val_if_fail (coll, 0);
00405
00406 xmmsv_coll_set_idlist (coll, empty);
00407
00408 return 1;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418 int
00419 xmmsv_coll_idlist_get_index (xmmsv_coll_t *coll, unsigned int index, uint32_t *val)
00420 {
00421 x_return_val_if_fail (coll, 0);
00422
00423 if (index >= (coll->idlist_size - 1)) {
00424 return 0;
00425 }
00426
00427 *val = coll->idlist[index];
00428
00429 return 1;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439 int
00440 xmmsv_coll_idlist_set_index (xmmsv_coll_t *coll, unsigned int index, uint32_t val)
00441 {
00442 x_return_val_if_fail (coll, 0);
00443
00444 if (index >= (coll->idlist_size - 1)) {
00445 return 0;
00446 }
00447
00448 coll->idlist[index] = val;
00449
00450 return 1;
00451 }
00452
00453
00454
00455
00456
00457
00458 size_t
00459 xmmsv_coll_idlist_get_size (xmmsv_coll_t *coll)
00460 {
00461 x_return_val_if_fail (coll, 0);
00462
00463 return coll->idlist_size - 1;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 xmmsv_coll_type_t
00474 xmmsv_coll_get_type (xmmsv_coll_t *coll)
00475 {
00476 x_return_val_if_fail (coll, -1);
00477
00478 return coll->type;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 uint32_t*
00491 xmmsv_coll_get_idlist (xmmsv_coll_t *coll)
00492 {
00493 x_return_null_if_fail (coll);
00494
00495 return coll->idlist;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505 int
00506 xmmsv_coll_operand_list_first (xmmsv_coll_t *coll)
00507 {
00508 xmmsv_list_iter_t *i;
00509
00510 x_return_val_if_fail (coll, 0);
00511 x_return_val_if_fail (coll->operand_iter_stack, 0);
00512
00513 i = coll->operand_iter_stack->data;
00514
00515 xmmsv_list_iter_first (i);
00516
00517 return 1;
00518 }
00519
00520
00521
00522
00523
00524
00525
00526 int
00527 xmmsv_coll_operand_list_valid (xmmsv_coll_t *coll)
00528 {
00529 xmmsv_list_iter_t *i;
00530
00531 x_return_val_if_fail (coll, 0);
00532 x_return_val_if_fail (coll->operand_iter_stack, 0);
00533
00534 i = coll->operand_iter_stack->data;
00535
00536 return xmmsv_list_iter_valid (i);
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 int
00550 xmmsv_coll_operand_list_entry (xmmsv_coll_t *coll, xmmsv_coll_t **operand)
00551 {
00552 xmmsv_list_iter_t *i;
00553 xmmsv_t *v;
00554
00555 x_return_val_if_fail (coll, 0);
00556 x_return_val_if_fail (coll->operand_iter_stack, 0);
00557
00558 i = coll->operand_iter_stack->data;
00559
00560 if (!xmmsv_list_iter_entry (i, &v))
00561 return 0;
00562
00563 return xmmsv_get_coll (v, operand);
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 int
00573 xmmsv_coll_operand_list_next (xmmsv_coll_t *coll)
00574 {
00575 xmmsv_list_iter_t *i;
00576
00577 x_return_val_if_fail (coll, 0);
00578 x_return_val_if_fail (coll->operand_iter_stack, 0);
00579
00580 i = coll->operand_iter_stack->data;
00581
00582 if (!xmmsv_list_iter_valid (i))
00583 return 0;
00584
00585 xmmsv_list_iter_next (i);
00586 return 1;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 int
00601 xmmsv_coll_operand_list_save (xmmsv_coll_t *coll)
00602 {
00603 xmmsv_list_iter_t *i;
00604
00605 x_return_val_if_fail (coll, 0);
00606 x_return_val_if_fail (coll->operand_iter_stack, 0);
00607
00608 if (!xmmsv_get_list_iter (coll->operands, &i))
00609 return 0;
00610
00611 coll->operand_iter_stack = x_list_prepend (coll->operand_iter_stack, i);
00612
00613 return 1;
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 int
00628 xmmsv_coll_operand_list_restore (xmmsv_coll_t *coll)
00629 {
00630 x_return_val_if_fail (coll, 0);
00631 x_return_val_if_fail (coll->operand_iter_stack, 0);
00632 x_return_val_if_fail (coll->operand_iter_stack->next, 0);
00633
00634 xmmsv_list_iter_explicit_destroy (coll->operand_iter_stack->data);
00635 coll->operand_iter_stack = x_list_delete_link (coll->operand_iter_stack, coll->operand_iter_stack);
00636
00637 return 1;
00638 }
00639
00640
00641
00642
00643
00644
00645
00646 void
00647 xmmsv_coll_operand_list_clear (xmmsv_coll_t *coll)
00648 {
00649 xmmsv_list_iter_t *i;
00650
00651 x_return_if_fail (coll);
00652
00653 xmmsv_list_clear (coll->operands);
00654
00655 if (!xmmsv_get_list_iter (coll->operands, &i))
00656 return;
00657
00658 x_list_free (coll->operand_iter_stack);
00659 coll->operand_iter_stack = x_list_prepend (NULL, i);
00660 }
00661
00662 xmmsv_t *
00663 xmmsv_coll_operands_get (xmmsv_coll_t *coll)
00664 {
00665 x_return_val_if_fail (coll, NULL);
00666
00667 return coll->operands;
00668 }
00669
00670 xmmsv_t *
00671 xmmsv_coll_attributes_get (xmmsv_coll_t *coll)
00672 {
00673 x_return_val_if_fail (coll, NULL);
00674
00675 return coll->attributes;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685 void
00686 xmmsv_coll_attribute_set (xmmsv_coll_t *coll, const char *key, const char *value)
00687 {
00688 xmmsv_t *v;
00689
00690 v = xmmsv_new_string (value);
00691 x_return_if_fail (v);
00692
00693 xmmsv_dict_set (coll->attributes, key, v);
00694 xmmsv_unref (v);
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 int
00707 xmmsv_coll_attribute_remove (xmmsv_coll_t *coll, const char *key)
00708 {
00709 return xmmsv_dict_remove (coll->attributes, key);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 int
00724 xmmsv_coll_attribute_get (xmmsv_coll_t *coll, const char *key, char **value)
00725 {
00726 if (xmmsv_dict_entry_get_string (coll->attributes, key, value)) {
00727 return 1;
00728 }
00729 *value = NULL;
00730 return 0;
00731 }
00732
00733
00734
00735 struct attr_fe_data {
00736 xmmsv_coll_attribute_foreach_func func;
00737 void *userdata;
00738 };
00739
00740 static void
00741 attr_fe_func (const char *key, xmmsv_t *val, void *user_data)
00742 {
00743 struct attr_fe_data *d = user_data;
00744 const char *v;
00745 int r;
00746
00747 r = xmmsv_get_string (val, &v);
00748 x_return_if_fail (r)
00749
00750 d->func (key, v, d->userdata);
00751 }
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 void
00764 xmmsv_coll_attribute_foreach (xmmsv_coll_t *coll,
00765 xmmsv_coll_attribute_foreach_func func,
00766 void *user_data)
00767 {
00768 struct attr_fe_data d = {func, user_data};
00769 xmmsv_dict_foreach (coll->attributes, attr_fe_func, &d);
00770 }
00771
00772 void
00773 xmmsv_coll_attribute_list_first (xmmsv_coll_t *coll)
00774 {
00775 x_return_if_fail (coll);
00776 xmmsv_dict_iter_first (coll->attributes_iter);
00777 }
00778
00779 int
00780 xmmsv_coll_attribute_list_valid (xmmsv_coll_t *coll)
00781 {
00782 x_return_val_if_fail (coll, 0);
00783
00784 return xmmsv_dict_iter_valid (coll->attributes_iter);
00785 }
00786
00787 void
00788 xmmsv_coll_attribute_list_entry (xmmsv_coll_t *coll, const char **k, const char **v)
00789 {
00790 xmmsv_t *val;
00791 int r;
00792
00793 x_return_if_fail (coll);
00794
00795 r = xmmsv_dict_iter_pair (coll->attributes_iter, k, &val);
00796 x_return_if_fail (r);
00797
00798 r = xmmsv_get_string (val, v);
00799 x_return_if_fail (r);
00800 }
00801
00802 void
00803 xmmsv_coll_attribute_list_next (xmmsv_coll_t *coll)
00804 {
00805 x_return_if_fail (coll);
00806
00807 xmmsv_dict_iter_next (coll->attributes_iter);
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 xmmsv_coll_t*
00819 xmmsv_coll_universe ()
00820 {
00821 xmmsv_coll_t *univ = xmmsv_coll_new (XMMS_COLLECTION_TYPE_REFERENCE);
00822 xmmsv_coll_attribute_set (univ, "reference", "All Media");
00823
00824
00825 return univ;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835 static int
00836 xmmsv_coll_idlist_resize (xmmsv_coll_t *coll, size_t newsize)
00837 {
00838 uint32_t *newmem;
00839
00840 newmem = realloc (coll->idlist, newsize * sizeof (uint32_t));
00841
00842 if (newmem == NULL) {
00843 x_oom ();
00844 return 0;
00845 }
00846
00847 coll->idlist = newmem;
00848 coll->idlist_allocated = newsize;
00849
00850 return 1;
00851 }