XMMS2
|
00001 /* XMMS2 - X Music Multiplexer System 00002 * Copyright (C) 2003-2011 XMMS2 Team 00003 * 00004 * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!! 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 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 /* refcounting */ 00032 int ref; 00033 00034 xmmsv_coll_type_t type; 00035 xmmsv_t *operands; 00036 xmmsv_t *attributes; 00037 xmmsv_t *idlist; 00038 00039 int32_t *legacy_idlist; 00040 }; 00041 00042 00043 static void xmmsv_coll_free (xmmsv_coll_t *coll); 00044 00045 00046 /** 00047 * @defgroup CollectionStructure CollectionStructure 00048 * @ingroup Collections 00049 * @brief The API to be used to work with collection structures. 00050 * 00051 * @{ 00052 */ 00053 00054 /** 00055 * Increases the references for the #xmmsv_coll_t 00056 * 00057 * @param coll the collection to reference. 00058 * @return coll 00059 */ 00060 xmmsv_coll_t * 00061 xmmsv_coll_ref (xmmsv_coll_t *coll) 00062 { 00063 x_return_val_if_fail (coll, NULL); 00064 00065 coll->ref++; 00066 00067 return coll; 00068 } 00069 00070 /** 00071 * Allocate a new collection of the given type. 00072 * The pointer will have to be deallocated using #xmmsv_coll_unref. 00073 * 00074 * @param type the #xmmsv_coll_type_t specifying the type of collection to create. 00075 * @return a pointer to the newly created collection, or NULL if the type is invalid. 00076 */ 00077 xmmsv_coll_t* 00078 xmmsv_coll_new (xmmsv_coll_type_t type) 00079 { 00080 xmmsv_coll_t *coll; 00081 00082 x_return_val_if_fail (type <= XMMS_COLLECTION_TYPE_LAST, NULL); 00083 00084 coll = x_new0 (xmmsv_coll_t, 1); 00085 if (!coll) { 00086 x_oom (); 00087 return NULL; 00088 } 00089 00090 coll->ref = 0; 00091 coll->type = type; 00092 00093 coll->idlist = xmmsv_new_list (); 00094 xmmsv_list_restrict_type (coll->idlist, XMMSV_TYPE_INT32); 00095 00096 coll->operands = xmmsv_new_list (); 00097 xmmsv_list_restrict_type (coll->operands, XMMSV_TYPE_COLL); 00098 00099 coll->attributes = xmmsv_new_dict (); 00100 00101 coll->legacy_idlist = NULL; 00102 00103 /* user must give this back */ 00104 xmmsv_coll_ref (coll); 00105 00106 return coll; 00107 } 00108 00109 /** 00110 * Free the memory owned by the collection. 00111 * You probably want to use #xmmsv_coll_unref instead, which handles 00112 * reference counting. 00113 * 00114 * @param coll the collection to free. 00115 */ 00116 static void 00117 xmmsv_coll_free (xmmsv_coll_t *coll) 00118 { 00119 x_return_if_fail (coll); 00120 00121 /* Unref all the operands and attributes */ 00122 xmmsv_unref (coll->operands); 00123 xmmsv_unref (coll->attributes); 00124 xmmsv_unref (coll->idlist); 00125 if (coll->legacy_idlist) { 00126 free (coll->legacy_idlist); 00127 } 00128 00129 free (coll); 00130 } 00131 00132 /** 00133 * Decreases the references for the #xmmsv_coll_t 00134 * When the number of references reaches 0 it will 00135 * be freed and all its operands unreferenced as well. 00136 * 00137 * @param coll the collection to unref. 00138 */ 00139 void 00140 xmmsv_coll_unref (xmmsv_coll_t *coll) 00141 { 00142 x_return_if_fail (coll); 00143 x_api_error_if (coll->ref < 1, "with a freed collection",); 00144 00145 coll->ref--; 00146 if (coll->ref == 0) { 00147 xmmsv_coll_free (coll); 00148 } 00149 } 00150 00151 00152 /** 00153 * Set the list of ids in the given collection. 00154 * The list must be 0-terminated. 00155 * Note that the idlist is only relevant for idlist collections. 00156 * 00157 * @param coll the collection to modify. 00158 * @param ids the 0-terminated list of ids to store in the collection. 00159 */ 00160 void 00161 xmmsv_coll_set_idlist (xmmsv_coll_t *coll, int ids[]) 00162 { 00163 unsigned int i; 00164 00165 xmmsv_list_clear (coll->idlist); 00166 for (i = 0; ids[i]; i++) { 00167 xmmsv_list_append_int (coll->idlist, ids[i]); 00168 } 00169 } 00170 00171 static int 00172 _xmmsv_coll_operand_find (xmmsv_list_iter_t *it, xmmsv_coll_t *op) 00173 { 00174 xmmsv_coll_t *c; 00175 xmmsv_t *v; 00176 00177 while (xmmsv_list_iter_valid (it)) { 00178 xmmsv_list_iter_entry (it, &v); 00179 if (xmmsv_get_coll (v, &c)) { 00180 if (c == op) { 00181 return 1; 00182 } 00183 } 00184 xmmsv_list_iter_next (it); 00185 } 00186 return 0; 00187 } 00188 00189 /** 00190 * Add the operand to the given collection. 00191 * @param coll The collection to add the operand to. 00192 * @param op The operand to add. 00193 */ 00194 void 00195 xmmsv_coll_add_operand (xmmsv_coll_t *coll, xmmsv_coll_t *op) 00196 { 00197 xmmsv_list_iter_t *it; 00198 xmmsv_t *v; 00199 x_return_if_fail (coll); 00200 x_return_if_fail (op); 00201 00202 /* we used to check if it already existed here before */ 00203 if (!xmmsv_get_list_iter (coll->operands, &it)) 00204 return; 00205 00206 if (_xmmsv_coll_operand_find (it, op)) { 00207 x_api_warning ("with an operand already in operand list"); 00208 xmmsv_list_iter_explicit_destroy (it); 00209 return; 00210 } 00211 00212 xmmsv_list_iter_explicit_destroy (it); 00213 00214 v = xmmsv_new_coll (op); 00215 x_return_if_fail (v); 00216 xmmsv_list_append (coll->operands, v); 00217 xmmsv_unref (v); 00218 } 00219 00220 /** 00221 * Remove all the occurences of the operand in the given collection. 00222 * @param coll The collection to remove the operand from. 00223 * @param op The operand to remove. 00224 */ 00225 void 00226 xmmsv_coll_remove_operand (xmmsv_coll_t *coll, xmmsv_coll_t *op) 00227 { 00228 xmmsv_list_iter_t *it; 00229 00230 x_return_if_fail (coll); 00231 x_return_if_fail (op); 00232 00233 if (!xmmsv_get_list_iter (coll->operands, &it)) 00234 return; 00235 00236 if (_xmmsv_coll_operand_find (it, op)) { 00237 xmmsv_list_iter_remove (it); 00238 } else { 00239 x_api_warning ("with an operand not in operand list"); 00240 } 00241 xmmsv_list_iter_explicit_destroy (it); 00242 } 00243 00244 00245 /** 00246 * Append a value to the idlist. 00247 * @param coll The collection to update. 00248 * @param id The id to append to the idlist. 00249 * @return TRUE on success, false otherwise. 00250 */ 00251 int 00252 xmmsv_coll_idlist_append (xmmsv_coll_t *coll, int id) 00253 { 00254 x_return_val_if_fail (coll, 0); 00255 00256 return xmmsv_list_append_int (coll->idlist, id); 00257 } 00258 00259 /** 00260 * Insert a value at a given position in the idlist. 00261 * @param coll The collection to update. 00262 * @param id The id to insert in the idlist. 00263 * @param index The position at which to insert the value. 00264 * @return TRUE on success, false otherwise. 00265 */ 00266 int 00267 xmmsv_coll_idlist_insert (xmmsv_coll_t *coll, int index, int id) 00268 { 00269 x_return_val_if_fail (coll, 0); 00270 00271 return xmmsv_list_insert_int (coll->idlist, index, id); 00272 } 00273 00274 /** 00275 * Move a value of the idlist to a new position. 00276 * @param coll The collection to update. 00277 * @param index The index of the value to move. 00278 * @param newindex The newindex to which to move the value. 00279 * @return TRUE on success, false otherwise. 00280 */ 00281 int 00282 xmmsv_coll_idlist_move (xmmsv_coll_t *coll, int index, int newindex) 00283 { 00284 x_return_val_if_fail (coll, 0); 00285 00286 return xmmsv_list_move (coll->idlist, index, newindex); 00287 } 00288 00289 /** 00290 * Remove the value at a given index from the idlist. 00291 * @param coll The collection to update. 00292 * @param index The index at which to remove the value. 00293 * @return TRUE on success, false otherwise. 00294 */ 00295 int 00296 xmmsv_coll_idlist_remove (xmmsv_coll_t *coll, int index) 00297 { 00298 x_return_val_if_fail (coll, 0); 00299 00300 return xmmsv_list_remove (coll->idlist, index); 00301 } 00302 00303 /** 00304 * Empties the idlist. 00305 * @param coll The collection to update. 00306 * @return TRUE on success, false otherwise. 00307 */ 00308 int 00309 xmmsv_coll_idlist_clear (xmmsv_coll_t *coll) 00310 { 00311 x_return_val_if_fail (coll, 0); 00312 00313 return xmmsv_list_clear (coll->idlist); 00314 } 00315 00316 /** 00317 * Retrieves the value at the given position in the idlist. 00318 * @param coll The collection to update. 00319 * @param index The position of the value to retrieve. 00320 * @param val The pointer at which to store the found value. 00321 * @return TRUE on success, false otherwise. 00322 */ 00323 int 00324 xmmsv_coll_idlist_get_index (xmmsv_coll_t *coll, int index, int32_t *val) 00325 { 00326 x_return_val_if_fail (coll, 0); 00327 00328 return xmmsv_list_get_int (coll->idlist, index, val); 00329 } 00330 00331 /** 00332 * Sets the value at the given position in the idlist. 00333 * @param coll The collection to update. 00334 * @param index The position of the value to set. 00335 * @param val The new value. 00336 * @return TRUE on success, false otherwise. 00337 */ 00338 int 00339 xmmsv_coll_idlist_set_index (xmmsv_coll_t *coll, int index, int32_t val) 00340 { 00341 x_return_val_if_fail (coll, 0); 00342 00343 return xmmsv_list_set_int (coll->idlist, index, val); 00344 } 00345 00346 /** 00347 * Get the size of the idlist. 00348 * @param coll The collection to update. 00349 * @return The size of the idlist. 00350 */ 00351 size_t 00352 xmmsv_coll_idlist_get_size (xmmsv_coll_t *coll) 00353 { 00354 x_return_val_if_fail (coll, 0); 00355 00356 return xmmsv_list_get_size (coll->idlist); 00357 } 00358 00359 00360 00361 /** 00362 * Return the type of the collection. 00363 * @param coll The collection to consider. 00364 * @return The #xmmsv_coll_type_t of the collection, or -1 if invalid. 00365 */ 00366 xmmsv_coll_type_t 00367 xmmsv_coll_get_type (xmmsv_coll_t *coll) 00368 { 00369 x_return_val_if_fail (coll, -1); 00370 00371 return coll->type; 00372 } 00373 00374 /** 00375 * Return the list of ids stored in the collection. 00376 * The list is owned by the collection. 00377 * Note that this must not be confused with the content of the 00378 * collection, which must be queried using xmmsc_coll_query_ids! 00379 * 00380 * Also note that this function is deprecated (use xmmsv_coll_idlist_get 00381 * instead) and that changes to the returned array will be ignored. The array 00382 * is also not updated when the idlist is changed using the supplied functions. 00383 * Additionally every call to this function allocates a new array, so calling 00384 * it repetitively will be a performance penalty. 00385 * 00386 * @param coll The collection to consider. 00387 * @return The 0-terminated list of ids. 00388 */ 00389 const int32_t* 00390 xmmsv_coll_get_idlist (xmmsv_coll_t *coll) 00391 { 00392 xmmsv_list_iter_t *it; 00393 unsigned int i; 00394 int32_t entry; 00395 00396 x_return_null_if_fail (coll); 00397 00398 /* free and allocate a new legacy list */ 00399 if (coll->legacy_idlist) { 00400 free (coll->legacy_idlist); 00401 } 00402 coll->legacy_idlist = calloc (xmmsv_coll_idlist_get_size (coll) + 1, 00403 sizeof (int32_t)); 00404 00405 /* copy contents to legacy list */ 00406 for (xmmsv_get_list_iter (coll->idlist, &it), i = 0; 00407 xmmsv_list_iter_valid (it); 00408 xmmsv_list_iter_next (it), i++) { 00409 xmmsv_list_iter_entry_int (it, &entry); 00410 coll->legacy_idlist[i] = entry; 00411 } 00412 coll->legacy_idlist[i] = 0; 00413 00414 return coll->legacy_idlist; 00415 } 00416 00417 /** 00418 * Return the list of ids stored in the collection. 00419 * This function does not increase the refcount of the list, the reference is 00420 * still owned by the collection. 00421 * 00422 * Note that this must not be confused with the content of the collection, 00423 * which must be queried using xmmsc_coll_query_ids! 00424 * 00425 * @param coll The collection to consider. 00426 * @return The 0-terminated list of ids. 00427 */ 00428 xmmsv_t * 00429 xmmsv_coll_idlist_get (xmmsv_coll_t *coll) 00430 { 00431 x_return_null_if_fail (coll); 00432 00433 return coll->idlist; 00434 } 00435 00436 xmmsv_t * 00437 xmmsv_coll_operands_get (xmmsv_coll_t *coll) 00438 { 00439 x_return_val_if_fail (coll, NULL); 00440 00441 return coll->operands; 00442 } 00443 00444 xmmsv_t * 00445 xmmsv_coll_attributes_get (xmmsv_coll_t *coll) 00446 { 00447 x_return_val_if_fail (coll, NULL); 00448 00449 return coll->attributes; 00450 } 00451 00452 /** 00453 * Set an attribute in the given collection. 00454 * 00455 * @param coll The collection in which to set the attribute. 00456 * @param key The name of the attribute to set. 00457 * @param value The value of the attribute. 00458 */ 00459 void 00460 xmmsv_coll_attribute_set (xmmsv_coll_t *coll, const char *key, const char *value) 00461 { 00462 xmmsv_t *v; 00463 00464 v = xmmsv_new_string (value); 00465 x_return_if_fail (v); 00466 00467 xmmsv_dict_set (coll->attributes, key, v); 00468 xmmsv_unref (v); 00469 } 00470 00471 /** 00472 * Remove an attribute from the given collection. 00473 * The return value indicated whether the attribute was found (and 00474 * removed) 00475 * 00476 * @param coll The collection to remove the attribute from. 00477 * @param key The name of the attribute to remove. 00478 * @return 1 upon success, 0 otherwise 00479 */ 00480 int 00481 xmmsv_coll_attribute_remove (xmmsv_coll_t *coll, const char *key) 00482 { 00483 return xmmsv_dict_remove (coll->attributes, key); 00484 } 00485 00486 /** 00487 * Retrieve the value of the attribute of the given collection. 00488 * The return value is 1 if the attribute was found and 0 otherwise. 00489 * The value of the attribute is owned by the collection and must not 00490 * be freed by the caller. 00491 * 00492 * @param coll The collection to retrieve the attribute from. 00493 * @param key The name of the attribute. 00494 * @param value The value of the attribute if found (owned by the collection). 00495 * @return 1 if the attribute was found, 0 otherwise 00496 */ 00497 int 00498 xmmsv_coll_attribute_get (xmmsv_coll_t *coll, const char *key, char **value) 00499 { 00500 if (xmmsv_dict_entry_get_string (coll->attributes, key, value)) { 00501 return 1; 00502 } 00503 *value = NULL; 00504 return 0; 00505 } 00506 00507 00508 00509 struct attr_fe_data { 00510 xmmsv_coll_attribute_foreach_func func; 00511 void *userdata; 00512 }; 00513 00514 static void 00515 attr_fe_func (const char *key, xmmsv_t *val, void *user_data) 00516 { 00517 struct attr_fe_data *d = user_data; 00518 const char *v; 00519 int r; 00520 00521 r = xmmsv_get_string (val, &v); 00522 x_return_if_fail (r) 00523 00524 d->func (key, v, d->userdata); 00525 } 00526 /** 00527 * Iterate over all key/value-pair of the collection attributes. 00528 * 00529 * Calls specified function for each key/value-pair of the attribute list. 00530 * 00531 * void function (const char *key, const char *value, void *user_data); 00532 * 00533 * @param coll the #xmmsv_coll_t. 00534 * @param func function that is called for each key/value-pair 00535 * @param user_data extra data passed to func 00536 */ 00537 void 00538 xmmsv_coll_attribute_foreach (xmmsv_coll_t *coll, 00539 xmmsv_coll_attribute_foreach_func func, 00540 void *user_data) 00541 { 00542 struct attr_fe_data d = {func, user_data}; 00543 xmmsv_dict_foreach (coll->attributes, attr_fe_func, &d); 00544 } 00545 00546 /** 00547 * Return a collection referencing the whole media library, 00548 * that is a reference to the "All Media" collection. 00549 * The returned structure must be unref'd using #xmmsv_coll_unref 00550 * after usage. 00551 * 00552 * @return a collection referring to the "All Media" collection. 00553 */ 00554 xmmsv_coll_t* 00555 xmmsv_coll_universe () 00556 { 00557 xmmsv_coll_t *univ = xmmsv_coll_new (XMMS_COLLECTION_TYPE_REFERENCE); 00558 xmmsv_coll_attribute_set (univ, "reference", "All Media"); 00559 /* FIXME: namespace? */ 00560 00561 return univ; 00562 } 00563 00564 /** @} */