void configure_playlist (xmmsc_result_t *res, cli_infos_t *infos, gchar *playlist, gint history, gint upcoming, xmmsv_coll_type_t type, gchar *input) { xmmsc_result_t *saveres; xmmsv_coll_t *coll; xmmsv_coll_t *newcoll; xmmsv_t *val; gboolean copied = FALSE; val = xmmsc_result_get_value (res); if (xmmsv_get_coll (val, &coll)) { if (type >= 0 && xmmsv_coll_get_type (coll) != type) { newcoll = coll_copy_retype (coll, type); coll = newcoll; copied = TRUE; } if (history >= 0) { coll_int_attribute_set (coll, "history", history); } if (upcoming >= 0) { coll_int_attribute_set (coll, "upcoming", upcoming); } if (input) { /* Replace previous operand. */ newcoll = coll_make_reference (input, XMMS_COLLECTION_NS_COLLECTIONS); xmmsv_list_clear (xmmsv_coll_operands_get (coll)); xmmsv_coll_add_operand (coll, newcoll); xmmsv_coll_unref (newcoll); } saveres = xmmsc_coll_save (infos->sync, coll, playlist, XMMS_COLLECTION_NS_PLAYLISTS); xmmsc_result_wait (saveres); done (saveres, infos); } else { g_printf (_("Cannot find the playlist to configure!\n")); cli_infos_loop_resume (infos); } if (copied) { xmmsv_coll_unref (coll); } xmmsc_result_unref (res); }
/** * Convenient function for adding a directory to the playlist, * It will dive down the URL you feed it and recursivly add * all files there. * * @param playlist the playlist to add it URL to. * @param plname the name of the playlist to modify. * @param nurl the URL of an directory you want to add * @param err an #xmms_error_t that should be defined upon error. */ static void xmms_playlist_client_radd (xmms_playlist_t *playlist, const gchar *plname, const gchar *path, xmms_error_t *err) { xmmsv_coll_t *idlist; xmmsv_list_iter_t *it; xmmsv_t *list; idlist = xmms_medialib_add_recursive (playlist->medialib, path, err); list = xmmsv_coll_idlist_get (idlist); xmmsv_get_list_iter (list, &it); while (xmmsv_list_iter_valid (it)) { xmms_medialib_entry_t entry; xmmsv_t *value; xmmsv_list_iter_entry (it, &value); xmmsv_get_int (value, &entry); xmms_playlist_add_entry (playlist, plname, entry, err); xmmsv_list_iter_next (it); } xmmsv_coll_unref (idlist); }
static void playlist_setup_pshuffle (xmmsc_connection_t *conn, xmmsv_coll_t *coll, gchar *ref) { xmmsc_result_t *psres; xmmsv_coll_t *refcoll; gchar *s_name, *s_namespace; if (!coll_read_collname (ref, &s_name, &s_namespace)) { print_error ("invalid source collection name"); } /* Quick shortcut to use Universe for "All Media" */ if (strcmp (s_name, "All Media") == 0) { refcoll = xmmsv_coll_universe (); } else { psres = xmmsc_coll_get (conn, s_name, s_namespace); xmmsc_result_wait (psres); if (xmmsc_result_iserror (psres)) { print_error ("%s", xmmsc_result_get_error (psres)); } refcoll = xmmsv_coll_new (XMMS_COLLECTION_TYPE_REFERENCE); xmmsv_coll_attribute_set (refcoll, "reference", s_name); xmmsv_coll_attribute_set (refcoll, "namespace", s_namespace); } /* Set operand */ xmmsv_coll_add_operand (coll, refcoll); xmmsv_coll_unref (refcoll); g_free (s_name); g_free (s_namespace); }
static void handle_file_del (xmonitor_t *mon, gchar *filename) { xmmsc_result_t *res; xmmsv_coll_t *univ, *coll; gchar tmp[MON_FILENAME_MAX]; g_snprintf (tmp, MON_FILENAME_MAX, "file://%s%%", filename); univ = xmmsv_coll_universe (); coll = xmmsv_coll_new (XMMS_COLLECTION_TYPE_MATCH); xmmsv_coll_add_operand (coll, univ); xmmsv_coll_attribute_set (coll, "field", "url"); xmmsv_coll_attribute_set (coll, "value", tmp); res = xmmsc_coll_query_ids (mon->conn, coll, NULL, 0, 0); DBG ("remove '%s' from mlib", tmp); xmmsc_result_notifier_set (res, handle_remove_from_mlib, mon); xmmsc_result_unref (res); xmmsv_coll_unref (coll); xmmsv_coll_unref (univ); }
/** * Create a new empty playlist. */ xmmsc_result_t * xmmsc_playlist_create (xmmsc_connection_t *c, const char *playlist) { xmmsc_result_t *res; xmmsv_coll_t *plcoll; x_check_conn (c, NULL); x_api_error_if (!playlist, "playlist name cannot be NULL", NULL); plcoll = xmmsv_coll_new (XMMS_COLLECTION_TYPE_IDLIST); res = xmmsc_coll_save (c, plcoll, playlist, XMMS_COLLECTION_NS_PLAYLISTS); xmmsv_coll_unref (plcoll); return res; }
static void filter_testcase (const gchar *path, xmmsv_t *list) { gchar *content, *filename; xmmsv_t *dict, *data, *holder; xmmsv_coll_t *coll; g_assert (g_file_get_contents (path, &content, NULL, NULL)); dict = xmmsv_from_json (content); if (dict == NULL) { g_error ("Could not parse '%s'!\n", path); g_assert_not_reached (); } g_free (content); g_assert (xmmsv_dict_has_key (dict, "medialib")); g_assert (xmmsv_dict_has_key (dict, "collection")); g_assert (xmmsv_dict_has_key (dict, "specification")); g_assert (xmmsv_dict_has_key (dict, "expected")); g_assert (xmmsv_dict_get (dict, "collection", &data)); g_assert (xmmsv_is_type (data, XMMSV_TYPE_DICT)); coll = xmmsv_coll_from_dict (data); holder = xmmsv_new_coll (coll); xmmsv_coll_unref (coll); xmmsv_dict_set (dict, "collection", holder); xmmsv_unref (holder); filename = g_path_get_basename (path); xmmsv_dict_set_string (dict, "name", filename); g_free (filename); xmmsv_list_append (list, dict); xmmsv_unref (dict); }
/** Sorts the playlist by properties. * * This will sort the list. * @param playlist The playlist to sort. * @param properties Tells xmms_playlist_sort which properties it * should use when sorting. * @param err An #xmms_error_t - needed since xmms_playlist_sort is an ipc * method handler. */ static void xmms_playlist_client_sort (xmms_playlist_t *playlist, const gchar *plname, xmmsv_t *properties, xmms_error_t *err) { xmmsv_t *tmp, *idlist, *val, *spec, *metadata, *get; xmmsv_coll_t *plcoll, *ordered; gint currpos, pos; xmms_medialib_entry_t currid; g_return_if_fail (playlist); g_return_if_fail (properties); if (xmmsv_list_get_size (properties) < 1) { xmms_error_set (err, XMMS_ERROR_NOENT, "need at least one property to sort"); return; } g_mutex_lock (playlist->mutex); plcoll = xmms_playlist_get_coll (playlist, plname, err); if (plcoll == NULL) { xmms_error_set (err, XMMS_ERROR_NOENT, "no such playlist!"); g_mutex_unlock (playlist->mutex); return; } currpos = xmms_playlist_coll_get_currpos (plcoll); xmmsv_coll_idlist_get_index (plcoll, currpos, &currid); get = xmmsv_new_list (); xmmsv_list_append_string (get, "id"); metadata = xmmsv_new_dict (); xmmsv_dict_set_string (metadata, "type", "metadata"); xmmsv_dict_set_string (metadata, "aggregate", "first"); xmmsv_dict_set (metadata, "get", get); xmmsv_unref (get); spec = xmmsv_new_dict (); xmmsv_dict_set_string (spec, "type", "cluster-list"); xmmsv_dict_set_string (spec, "cluster-by", "position"); xmmsv_dict_set (spec, "data", metadata); xmmsv_unref (metadata); ordered = xmmsv_coll_add_order_operators (plcoll, properties); MEDIALIB_BEGIN (playlist->medialib); tmp = xmms_medialib_query (session, ordered, spec, err); MEDIALIB_COMMIT (); xmmsv_coll_unref (ordered); xmmsv_unref (spec); if (tmp == NULL) { g_mutex_unlock (playlist->mutex); return; } idlist = xmmsv_coll_idlist_get (plcoll); xmmsv_list_clear (idlist); for (pos = 0; xmmsv_list_get (tmp, pos, &val); pos++) { xmms_medialib_entry_t id; xmmsv_get_int (val, &id); xmmsv_list_append (idlist, val); if (id == currid) { xmms_collection_set_int_attr (plcoll, "position", pos); currpos = pos; } } xmmsv_unref (tmp); XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_SORT, 0, plname); XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname); g_mutex_unlock (playlist->mutex); }
static bool _internal_get_from_bb_value_of_type_alloc (xmmsv_t *bb, xmmsv_type_t type, xmmsv_t **val) { int32_t i; uint32_t len; char *s; xmmsv_coll_t *c; unsigned char *d; switch (type) { case XMMSV_TYPE_ERROR: if (!_internal_get_from_bb_error_alloc (bb, &s, &len)) { return false; } *val = xmmsv_new_error (s); free (s); break; case XMMSV_TYPE_INT32: if (!_internal_get_from_bb_int32 (bb, &i)) { return false; } *val = xmmsv_new_int (i); break; case XMMSV_TYPE_STRING: if (!_internal_get_from_bb_string_alloc (bb, &s, &len)) { return false; } *val = xmmsv_new_string (s); free (s); break; case XMMSV_TYPE_DICT: if (!xmmsc_deserialize_dict (bb, val)) { return false; } break; case XMMSV_TYPE_LIST : if (!xmmsc_deserialize_list (bb, val)) { return false; } break; case XMMSV_TYPE_COLL: if (!_internal_get_from_bb_collection_alloc (bb, &c)) { return false; } *val = xmmsv_new_coll (c); xmmsv_coll_unref (c); break; case XMMSV_TYPE_BIN: if (!_internal_get_from_bb_bin_alloc (bb, &d, &len)) { return false; } *val = xmmsv_new_bin (d, len); free (d); break; case XMMSV_TYPE_NONE: *val = xmmsv_new_none (); break; default: x_internal_error ("Got message of unknown type!"); return false; } return true; }
static bool _internal_get_from_bb_collection_alloc (xmmsv_t *bb, xmmsv_coll_t **coll) { int i; int32_t type; int32_t n_items; int id; int32_t *idlist = NULL; char *key, *val; /* Get the type and create the collection */ if (!_internal_get_from_bb_int32_positive (bb, &type)) { return false; } *coll = xmmsv_coll_new (type); /* Get the list of attributes */ if (!_internal_get_from_bb_int32_positive (bb, &n_items)) { goto err; } for (i = 0; i < n_items; i++) { unsigned int len; if (!_internal_get_from_bb_string_alloc (bb, &key, &len)) { goto err; } if (!_internal_get_from_bb_string_alloc (bb, &val, &len)) { free (key); goto err; } xmmsv_coll_attribute_set (*coll, key, val); free (key); free (val); } /* Get the idlist */ if (!_internal_get_from_bb_int32_positive (bb, &n_items)) { goto err; } if (!(idlist = x_new (int32_t, n_items + 1))) { goto err; } for (i = 0; i < n_items; i++) { if (!_internal_get_from_bb_int32 (bb, &id)) { goto err; } idlist[i] = id; } idlist[i] = 0; xmmsv_coll_set_idlist (*coll, idlist); free (idlist); idlist = NULL; /* Get the operands */ if (!_internal_get_from_bb_int32_positive (bb, &n_items)) { goto err; } for (i = 0; i < n_items; i++) { xmmsv_coll_t *operand; if (!_internal_get_from_bb_int32_positive (bb, &type) || type != XMMSV_TYPE_COLL || !_internal_get_from_bb_collection_alloc (bb, &operand)) { goto err; } xmmsv_coll_add_operand (*coll, operand); xmmsv_coll_unref (operand); } return true; err: if (idlist != NULL) { free (idlist); } xmmsv_coll_unref (*coll); return false; }
/** Given a collection id, query the DB to build the corresponding * collection DAG. * * @param session The medialib session connected to the DB. * @param id The id of the collection to create. * @param type The type of the collection operator. * @return The created collection DAG. */ static xmmsv_coll_t * xmms_collection_dbread_operator (xmms_medialib_session_t *session, gint id, xmmsv_coll_type_t type) { xmmsv_coll_t *coll; xmmsv_coll_t *op; GList *res; GList *n; xmmsv_t *cmdval; gchar query[256]; coll = xmmsv_coll_new (type); /* Retrieve the attributes */ g_snprintf (query, sizeof (query), "SELECT attr.key AS key, attr.value AS value " "FROM CollectionOperators AS op, CollectionAttributes AS attr " "WHERE op.id=%d AND attr.collid=op.id", id); res = xmms_medialib_select (session, query, NULL); for (n = res; n; n = n->next) { const gchar *key, *value; cmdval = (xmmsv_t*) n->data; key = value_get_dict_string (cmdval, "key"); value = value_get_dict_string (cmdval, "value"); xmmsv_coll_attribute_set (coll, key, value); xmmsv_unref (n->data); } g_list_free (res); /* Retrieve the idlist */ g_snprintf (query, sizeof (query), "SELECT idl.mid AS mid " "FROM CollectionOperators AS op, CollectionIdlists AS idl " "WHERE op.id=%d AND idl.collid=op.id " "ORDER BY idl.position", id); res = xmms_medialib_select (session, query, NULL); for (n = res; n; n = n->next) { cmdval = (xmmsv_t *) n->data; xmmsv_coll_idlist_append (coll, value_get_dict_int (cmdval, "mid")); xmmsv_unref (cmdval); } g_list_free (res); /* Retrieve the operands */ g_snprintf (query, sizeof (query), "SELECT op.id AS id, op.type AS type " "FROM CollectionOperators AS op, CollectionConnections AS conn " "WHERE conn.to_id=%d AND conn.from_id=op.id", id); res = xmms_medialib_select (session, query, NULL); for (n = res; n; n = n->next) { gint _id; gint type; cmdval = (xmmsv_t *) n->data; _id = value_get_dict_int (cmdval, "id"); type = value_get_dict_int (cmdval, "type"); op = xmms_collection_dbread_operator (session, _id, type); xmmsv_coll_add_operand (coll, op); xmmsv_coll_unref (op); xmmsv_unref (cmdval); } g_list_free (res); return coll; }
void cmd_playlist_type (xmmsc_connection_t *conn, gint argc, gchar **argv) { gchar *name; xmmsv_coll_type_t prevtype, newtype; xmmsc_result_t *res; xmmsv_t *val; xmmsv_coll_t *coll; /* Read playlist name */ if (argc < 4) { print_error ("usage: type_playlist [playlistname] [type] [options]"); } name = argv[3]; /* Retrieve the playlist operator */ res = xmmsc_coll_get (conn, name, XMMS_COLLECTION_NS_PLAYLISTS); xmmsc_result_wait (res); val = xmmsc_result_get_value (res); if (xmmsv_is_error (val)) { print_error ("%s", xmmsv_get_error_old (val)); } xmmsv_get_coll (val, &coll); prevtype = xmmsv_coll_get_type (coll); /* No type argument, simply display the current type */ if (argc < 5) { print_info (get_playlist_type_string (prevtype)); /* Type argument, set the new type */ } else { gint typelen; gint idlistsize; xmmsc_result_t *saveres; xmmsv_coll_t *newcoll; gint i; typelen = strlen (argv[4]); if (g_ascii_strncasecmp (argv[4], "list", typelen) == 0) { newtype = XMMS_COLLECTION_TYPE_IDLIST; } else if (g_ascii_strncasecmp (argv[4], "queue", typelen) == 0) { newtype = XMMS_COLLECTION_TYPE_QUEUE; } else if (g_ascii_strncasecmp (argv[4], "pshuffle", typelen) == 0) { newtype = XMMS_COLLECTION_TYPE_PARTYSHUFFLE; /* Setup operand for party shuffle (set operand) ! */ if (argc < 6) { print_error ("Give the source collection for the party shuffle"); } } else { print_error ("Invalid playlist type (valid types: list, queue, pshuffle)"); } /* Copy collection idlist, attributes and operand (if needed) */ newcoll = xmmsv_coll_new (newtype); idlistsize = xmmsv_coll_idlist_get_size (coll); for (i = 0; i < idlistsize; i++) { guint id; xmmsv_coll_idlist_get_index (coll, i, &id); xmmsv_coll_idlist_append (newcoll, id); } xmmsv_coll_attribute_foreach (coll, coll_copy_attributes, newcoll); if (newtype == XMMS_COLLECTION_TYPE_PARTYSHUFFLE) { playlist_setup_pshuffle (conn, newcoll, argv[5]); } /* Overwrite with new collection */ saveres = xmmsc_coll_save (conn, newcoll, name, XMMS_COLLECTION_NS_PLAYLISTS); xmmsc_result_wait (saveres); if (xmmsc_result_iserror (saveres)) { print_error ("Couldn't save %s : %s", name, xmmsc_result_get_error (saveres)); } xmmsv_coll_unref (newcoll); xmmsc_result_unref (saveres); } xmmsc_result_unref (res); }
static bool _internal_get_from_bb_collection_alloc (xmmsv_t *bb, xmmsv_coll_t **coll) { int i; int32_t type; int32_t n_items; int id; int32_t *idlist = NULL; xmmsv_t *dict, *attrs; xmmsv_dict_iter_t *it; /* Get the type and create the collection */ if (!_internal_get_from_bb_int32_positive (bb, &type)) { return false; } *coll = xmmsv_coll_new (type); /* Get the attributes */ if (!_internal_get_from_bb_value_dict_alloc (bb, &dict)) { return false; } attrs = xmmsv_coll_attributes_get (*coll); xmmsv_get_dict_iter (dict, &it); while (xmmsv_dict_iter_valid (it)) { const char *key; xmmsv_t *value; xmmsv_dict_iter_pair (it, &key, &value); xmmsv_dict_set (attrs, key, value); xmmsv_dict_iter_next (it); } xmmsv_unref (dict); /* Get the idlist */ if (!_internal_get_from_bb_int32_positive (bb, &n_items)) { goto err; } if (!(idlist = x_new (int32_t, n_items + 1))) { goto err; } for (i = 0; i < n_items; i++) { if (!_internal_get_from_bb_int32 (bb, &id)) { goto err; } idlist[i] = id; } idlist[i] = 0; xmmsv_coll_set_idlist (*coll, idlist); free (idlist); idlist = NULL; /* Get the operands */ if (!_internal_get_from_bb_int32_positive (bb, &n_items)) { goto err; } for (i = 0; i < n_items; i++) { xmmsv_coll_t *operand; if (!_internal_get_from_bb_int32_positive (bb, &type) || type != XMMSV_TYPE_COLL || !_internal_get_from_bb_collection_alloc (bb, &operand)) { goto err; } xmmsv_coll_add_operand (*coll, operand); xmmsv_coll_unref (operand); } return true; err: if (idlist != NULL) { free (idlist); } xmmsv_coll_unref (*coll); return false; }