示例#1
0
/**
 * Allocate a new collection of the given type.
 * The pointer will have to be deallocated using #xmmsv_coll_unref.
 *
 * @param type the #xmmsv_coll_type_t specifying the type of collection to create.
 * @return a pointer to the newly created collection, or NULL if the type is invalid.
 */
static xmmsv_coll_internal_t*
_xmmsv_coll_new (xmmsv_coll_type_t type)
{
	xmmsv_coll_internal_t *coll;

	x_return_val_if_fail (type <= XMMS_COLLECTION_TYPE_LAST, NULL);

	coll = x_new0 (xmmsv_coll_internal_t, 1);
	if (!coll) {
		x_oom ();
		return NULL;
	}

	coll->type = type;

	coll->idlist = xmmsv_new_list ();
	xmmsv_list_restrict_type (coll->idlist, XMMSV_TYPE_INT64);

	coll->operands = xmmsv_new_list ();
	xmmsv_list_restrict_type (coll->operands, XMMSV_TYPE_COLL);

	coll->attributes = xmmsv_new_dict ();

	return coll;
}
示例#2
0
文件: playlist.c 项目: chrippa/xmms2
/** List a playlist */
static xmmsv_t *
xmms_playlist_client_list_entries (xmms_playlist_t *playlist, const gchar *plname,
                                   xmms_error_t *err)
{
    xmmsv_t *entries = NULL;
    xmmsv_coll_t *plcoll;
    xmms_medialib_entry_t entry;
    xmmsv_list_iter_t *it;

    g_return_val_if_fail (playlist, NULL);

    g_mutex_lock (playlist->mutex);

    plcoll = xmms_playlist_get_coll (playlist, plname, err);
    if (plcoll == NULL) {
        g_mutex_unlock (playlist->mutex);
        return NULL;
    }

    entries = xmmsv_new_list ();

    xmmsv_get_list_iter (xmmsv_coll_idlist_get (plcoll), &it);
    for (xmmsv_list_iter_first (it);
            xmmsv_list_iter_valid (it);
            xmmsv_list_iter_next (it)) {

        xmmsv_list_iter_entry_int (it, &entry);
        xmmsv_list_append_int (entries, entry);
    }
    xmmsv_list_iter_explicit_destroy (it);

    g_mutex_unlock (playlist->mutex);

    return entries;
}
static xmmsv_t *
aggregate_set (xmmsv_t *current, gint int_value, const gchar *str_value)
{
	set_data_t *data;
	xmmsv_t *value;
	gpointer key;
	guint length;

	if (current == NULL) {
		set_data_t init = {
			.ht = g_hash_table_new (NULL, NULL),
			.list = xmmsv_new_list ()
		};
		current = xmmsv_new_bin ((guchar *) &init, sizeof (set_data_t));
	}

	xmmsv_get_bin (current, (const guchar **) &data, &length);

	if (str_value != NULL) {
		value = xmmsv_new_string (str_value);
		key = (gpointer) str_value;
	} else {
		value = xmmsv_new_int (int_value);
		key = GINT_TO_POINTER (int_value);
	}

	if (g_hash_table_lookup (data->ht, key) == NULL) {
		g_hash_table_insert (data->ht, key, value);
		xmmsv_list_append (data->list, value);
	}

	xmmsv_unref (value);

	return current;
}
示例#4
0
文件: object.c 项目: dsheeler/xmms2
/**
 * Create a new #xmmsv_t list initialized with the argument.
 * @param list The list of values to initially fill the #xmmsv_t with.
 * @return a new #xmmsv_t list.
 */
static xmmsv_t *
xmms_create_xmmsv_list (GList *list)
{
	xmmsv_t *v = xmmsv_new_list ();
	g_list_foreach (list, create_xmmsv_list_foreach, (gpointer) v);
	return v;
}
示例#5
0
/**
 * List the ids of all media matched by the given collection.
 * A list of ordering properties can be specified, as well as offsets
 * to only retrieve part of the result set.
 *
 * @param conn  The connection to the server.
 * @param coll  The collection used to query.
 * @param order  The list of properties to order by, passed as an #xmmsv_t list of strings.
 * @param limit_start  The offset at which to start retrieving results (0 to disable).
 * @param limit_len  The maximum number of entries to retrieve (0 to disable).
 */
xmmsc_result_t*
xmmsc_coll_query_ids (xmmsc_connection_t *conn, xmmsv_coll_t *coll,
                      xmmsv_t *order, int limit_start,
                      int limit_len)
{
	xmms_ipc_msg_t *msg;

	x_check_conn (conn, NULL);
	x_api_error_if (!coll, "with a NULL collection", NULL);

	/* default to empty ordering */
	if (!order) {
		order = xmmsv_new_list ();
	} else {
		xmmsv_ref (order);
	}

	msg = xmms_ipc_msg_new (XMMS_IPC_OBJECT_COLLECTION, XMMS_IPC_CMD_QUERY_IDS);
	xmms_ipc_msg_put_collection (msg, coll);
	xmms_ipc_msg_put_int32 (msg, limit_start);
	xmms_ipc_msg_put_int32 (msg, limit_len);
	xmms_ipc_msg_put_value_list (msg, order); /* purposedly skip typing */

	xmmsv_unref (order);

	return xmmsc_send_msg (conn, msg);
}
示例#6
0
static int
xmmsc_deserialize_list (xmmsv_t *bb, xmmsv_t **val)
{
	xmmsv_t *list;
	int32_t len;

	list = xmmsv_new_list ();

	if (!_internal_get_from_bb_int32_positive (bb, &len)) {
		goto err;
	}

	while (len--) {
		xmmsv_t *v;
		if (xmmsv_bitbuffer_deserialize_value (bb, &v)) {
			xmmsv_list_append (list, v);
		} else {
			goto err;
		}
		xmmsv_unref (v);
	}

	*val = list;

	return true;

err:
	x_internal_error ("Message from server did not parse correctly!");
	xmmsv_unref (list);
	return false;
}
示例#7
0
xmmsv_t *
xmmsv_build_list_va (xmmsv_t *first_entry, va_list ap)
{
	xmmsv_t *val, *res;

	res = xmmsv_new_list ();
	if (!res)
		return NULL;

	val = first_entry;

	while (val) {
		if (!xmmsv_list_append (res, val)) {
			xmmsv_unref (res);
			res = NULL;
			break;
		}

		xmmsv_unref (val);

		val = va_arg (ap, xmmsv_t *);
	}

	return res;
}
示例#8
0
文件: main.c 项目: chrippa/xmms2
static xmmsv_t *
xmms_main_client_list_plugins (xmms_object_t *main, gint32 type, xmms_error_t *err)
{
	xmmsv_t *list = xmmsv_new_list ();
	xmms_plugin_foreach (type, xmms_main_client_list_foreach, list);
	return list;
}
示例#9
0
void
xmms_medialib_session_track_garbage (xmms_medialib_session_t *session,
                                     xmmsv_t *data)
{
	if (session->vals == NULL)
		session->vals = xmmsv_new_list ();
	xmmsv_list_append (session->vals, data);
}
示例#10
0
static xmmsv_t *
create_structure (int stack_offset, int is_object)
{
	if (is_object) {
		return xmmsv_new_dict ();
	} else {
		return xmmsv_new_list ();
	}
}
/* Converts an S4 resultset into an xmmsv_t, based on the fetch specification */
xmmsv_t *
xmms_medialib_query_to_xmmsv (s4_resultset_t *set, xmms_fetch_spec_t *spec)
{
	GHashTable *set_table;
	GList *sets;
	xmmsv_t *val, *ret = NULL;
	gint i;

	switch (spec->type) {
		case FETCH_COUNT:
			ret = xmmsv_new_int (s4_resultset_get_rowcount (set));
			break;
		case FETCH_METADATA:
			ret = metadata_to_xmmsv (set, spec);
			break;
		case FETCH_ORGANIZE:
			ret = xmmsv_new_dict ();

			for (i = 0; i < spec->data.organize.count; i++) {
				val = xmms_medialib_query_to_xmmsv (set, spec->data.organize.data[i]);
				if (val != NULL) {
					xmmsv_dict_set (ret, spec->data.organize.keys[i], val);
					xmmsv_unref (val);
				}
			}
			break;
		case FETCH_CLUSTER_LIST:
			sets = cluster_list (set, spec);
			ret = xmmsv_new_list ();
			for (; sets != NULL; sets = g_list_delete_link (sets, sets)) {
				set = sets->data;

				val = xmms_medialib_query_to_xmmsv (set, spec->data.cluster.data);
				if (val != NULL) {
					xmmsv_list_append (ret, val);
					xmmsv_unref (val);
				}
				s4_resultset_free (set);
			}
			break;
		case FETCH_CLUSTER_DICT:
			set_table = cluster_dict (set, spec);
			ret = convert_ghashtable_to_xmmsv (set_table, spec->data.cluster.data);

			g_hash_table_destroy (set_table);
			break;
		default:
			g_assert_not_reached ();
	}

	return ret;
}
示例#12
0
/**
 * Creates a metadata fetch specification.
 *
 * @param fields A list of fields to fetch, or NULL to fetch everything
 * @param get A list of what to get ("id", "key", "value", "source")
 * @param aggregate The aggregation function to use
 * @param sourcepref A list of sources, first one has the highest priority
 * @return A metadata fetch specification
 */
xmmsv_t *xmmsv_build_metadata (xmmsv_t *fields, xmmsv_t *get, const char *aggregate, xmmsv_t *sourcepref)
{
	xmmsv_t *res = xmmsv_new_dict ();
	if (res == NULL)
		return NULL;

	xmmsv_dict_set_string (res, "type", "metadata");

	if (fields != NULL) {
		if (xmmsv_get_type (fields) == XMMSV_TYPE_STRING) {
			xmmsv_t *list = xmmsv_new_list ();
			xmmsv_list_append (list, fields);
			xmmsv_unref (fields);
			fields = list;
		}
		xmmsv_dict_set (res, "fields", fields);
		xmmsv_unref (fields);
	}
	if (get != NULL) {
		if (xmmsv_get_type (get) == XMMSV_TYPE_STRING) {
			xmmsv_t *list = xmmsv_new_list ();
			xmmsv_list_append (list, get);
			xmmsv_unref (get);
			get = list;
		}
		xmmsv_dict_set (res, "get", get);
		xmmsv_unref (get);
	}
	if (sourcepref != NULL) {
		xmmsv_dict_set (res, "source-preference", sourcepref);
		xmmsv_unref (sourcepref);
	}
	if (aggregate != NULL) {
		xmmsv_dict_set_string (res, "aggregate", aggregate);
	}

	return res;
}
示例#13
0
/**
 * Sanitize the 'get' property of a 'metadata' fetch specification.
 */
static xmmsv_t *
normalize_metadata_get (xmmsv_t *fetch, xmms_error_t *err)
{
	xmmsv_list_iter_t *it;
	xmmsv_t *get, *list;
	guint32 values;

	if (!xmmsv_dict_get (fetch, "get", &get) ||
	    xmmsv_get_type (get) != XMMSV_TYPE_LIST ||
	    xmmsv_list_get_size (get) < 1) {
		const gchar *message = "'get' must be a non-empty list of strings.";
		xmms_error_set (err, XMMS_ERROR_INVAL, message);
		return NULL;
	}

	list = xmmsv_new_list ();
	values = 0;

	/* Scan for duplicates or invalid values */
	xmmsv_get_list_iter (get, &it);
	while (xmmsv_list_iter_valid (it)) {
		const gchar *value = NULL;
		guint32 get_as_int, mask;

		xmmsv_list_iter_entry_string (it, &value);

		if (!metadata_value_from_string (value, &get_as_int)) {
			const gchar *message = "'get' entries must be 'id', 'field', 'value' or 'source'.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			xmmsv_unref (list);
			return NULL;
		}

		mask = 1 << (get_as_int + 1);
		if (values & mask) {
			const gchar *message = "'get' entries must be unique.";
			xmms_error_set (err, XMMS_ERROR_INVAL, message);
			xmmsv_unref (list);
			return NULL;
		}

		values |= mask;

		xmmsv_list_append_int (list, get_as_int);
		xmmsv_list_iter_next (it);
	}

	return list;
}
static xmmsv_t *
aggregate_list (xmmsv_t *current, gint int_value, const gchar *str_value)
{
	if (current == NULL) {
		current = xmmsv_new_list ();
	}

	if (str_value != NULL) {
		xmmsv_list_append_string (current, str_value);
	} else {
		xmmsv_list_append_int (current, int_value);
	}

	return current;
}
示例#15
0
/**
 * Helper function to build a list #xmmsv_t containing the
 * strings from the input array.
 *
 * @param array An array of C strings. Must be NULL-terminated if num
 *              is -1.
 * @param num The optional number of elements to read from the array. Set to
 *            -1 if the array is NULL-terminated.
 * @return An #xmmsv_t containing the list of strings. Must be
 *         unreffed manually when done.
 */
xmmsv_t *
xmmsv_make_stringlist (char *array[], int num)
{
	xmmsv_t *list, *elem;
	int i;

	list = xmmsv_new_list ();
	if (array) {
		for (i = 0; (num >= 0 && i < num) || array[i]; i++) {
			elem = xmmsv_new_string (array[i]);
			xmmsv_list_append (list, elem);
			xmmsv_unref (elem);
		}
	}

	return list;
}
示例#16
0
void
xmms_xform_browse_add_entry (xmms_xform_t *xform, const gchar *filename,
                             guint32 flags)
{
	const gchar *url;
	gchar *efile, *eurl, *t;
	gint l, isdir;

	g_return_if_fail (filename);

	t = strchr (filename, '/');
	g_return_if_fail (!t); /* filenames can't contain '/', can they? */

	url = xmms_xform_get_url (xform);
	g_return_if_fail (url);

	xform->browse_dict = xmmsv_new_dict ();

	eurl = xmms_medialib_url_encode (url);
	efile = xmms_medialib_url_encode (filename);

	/* can't use g_build_filename as we need to preserve
	   slashes stuff like file:/// */
	l = strlen (url);
	if (l && url[l - 1] == '/') {
		t = g_strdup_printf ("%s%s", eurl, efile);
	} else {
		t = g_strdup_printf ("%s/%s", eurl, efile);
	}

	isdir = !!(flags & XMMS_XFORM_BROWSE_FLAG_DIR);
	xmms_xform_browse_add_entry_property_str (xform, "path", t);
	xmms_xform_browse_add_entry_property_int (xform, "isdir", isdir);

	if (xform->browse_list == NULL) {
		xform->browse_list = xmmsv_new_list ();
	}
	xmmsv_list_append (xform->browse_list, xform->browse_dict);
	xmmsv_unref (xform->browse_dict);

	g_free (t);
	g_free (efile);
	g_free (eurl);
}
示例#17
0
xmmsv_t *
xmms_xform_browse_method (xmms_xform_t *xform, const gchar *url,
                          xmms_error_t *error)
{
	xmmsv_t *list = NULL;

	if (xmms_xform_plugin_can_browse (xform->plugin)) {
		xform->browse_list = xmmsv_new_list ();
		if (!xmms_xform_plugin_browse (xform->plugin, xform, url, error)) {
			return NULL;
		}
		list = xform->browse_list;
		xform->browse_list = NULL;
		xmmsv_list_sort (list, xmms_browse_list_sortfunc);
	} else {
		xmms_error_set (error, XMMS_ERROR_GENERIC, "Couldn't handle that URL");
	}

	return list;
}
示例#18
0
/** Initialize the cache, must still be started to be filled. */
cli_cache_t *
cli_cache_init ()
{
    cli_cache_t *cache;

    cache = g_new0 (cli_cache_t, 1);
    cache->currpos = -1;
    cache->currid = 0;
    cache->playback_status = 0;
    cache->active_playlist = xmmsv_new_list ();
    cache->active_playlist_name = NULL;

    /* Init the freshness state */
    freshness_init (&cache->freshness_currpos);
    freshness_init (&cache->freshness_currid);
    freshness_init (&cache->freshness_playback_status);
    freshness_init (&cache->freshness_active_playlist);
    freshness_init (&cache->freshness_active_playlist_name);

    return cache;
}
示例#19
0
xmmsv_t *
duplicate_list_value (xmmsv_t *val)
{
	xmmsv_t *dup_val;
	xmmsv_list_iter_t *it;
	xmmsv_t *v;
	xmmsv_t *new_elem;

	x_return_val_if_fail (xmmsv_get_list_iter (val, &it), NULL);
	dup_val = xmmsv_new_list ();
	while (xmmsv_list_iter_entry (it, &v)) {
		new_elem = xmmsv_copy (v);
		xmmsv_list_append (dup_val, new_elem);
		xmmsv_unref (new_elem);
		xmmsv_list_iter_next (it);
	}

	xmmsv_list_iter_explicit_destroy (it);

	return dup_val;

}
示例#20
0
static xmmsv_t *
scan_path (const gchar *path, xmms_path_predicate predicate)
{
	const gchar *filename;
	xmmsv_t *list;
	GDir *dir;

	g_debug ("Scanning path: %s", path);

	list = xmmsv_new_list ();

	if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) {
		predicate (path, list);
		return list;
	}

	dir = g_dir_open (path, 0, NULL);
	if (dir == NULL) {
		g_print ("Could not open directory: %s\n", path);
		exit (EXIT_FAILURE);
	}

	while ((filename = g_dir_read_name (dir)) != NULL) {
		gchar *filepath;

		filepath = g_build_filename (path, filename, NULL);

		g_debug ("Found file: %s", filepath);
		predicate (filepath, list);

		g_free (filepath);
	}

	g_dir_close (dir);

	return list;
}
示例#21
0
文件: main.c 项目: theefer/xmms2
/**
 * @internal Destroy the main object
 * @param[in] object The object to destroy
 */
static void
xmms_main_destroy (xmms_object_t *object)
{
	xmms_main_t *mainobj = (xmms_main_t *) object;
	xmms_object_cmd_arg_t arg;
	xmms_config_property_t *cv;

	cv = xmms_config_lookup ("core.shutdownpath");
	do_scriptdir (xmms_config_property_get_string (cv), "stop");

	/* stop output */
	xmms_object_cmd_arg_init (&arg);
	arg.args = xmmsv_new_list ();
	xmms_object_cmd_call (XMMS_OBJECT (mainobj->output),
	                      XMMS_IPC_CMD_STOP, &arg);
	xmmsv_unref (arg.args);

	g_usleep (G_USEC_PER_SEC); /* wait for the output thread to end */

	xmms_object_unref (mainobj->vis);
	xmms_object_unref (mainobj->output);

	xmms_object_unref (xform_obj);

	xmms_config_save ();

	xmms_config_shutdown ();

	xmms_plugin_shutdown ();

	xmms_main_unregister_ipc_commands ();

	xmms_ipc_shutdown ();

	xmms_log_shutdown ();
}
示例#22
0
文件: playlist.c 项目: dsheeler/xmms2
/** 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);
}
/* Converts the temporary value returned by result_to_xmmsv into the real value */
static xmmsv_t *
aggregate_data (xmmsv_t *value, aggregate_function_t aggr_func)
{
	const random_data_t *random_data;
	const avg_data_t *avg_data;
	const set_data_t *set_data;
	gconstpointer data;
	xmmsv_t *ret;
	guint len;

	ret = NULL;
	data = NULL;

	if (value != NULL && xmmsv_is_type (value, XMMSV_TYPE_BIN))
		xmmsv_get_bin (value, (const guchar **) &data, &len);

	switch (aggr_func) {
		case AGGREGATE_FIRST:
		case AGGREGATE_MIN:
		case AGGREGATE_MAX:
		case AGGREGATE_SUM:
			if (value != NULL) {
				ret = xmmsv_ref (value);
			} else {
				ret = xmmsv_new_none ();
			}
			break;
		case AGGREGATE_LIST:
			if (value != NULL) {
				ret = xmmsv_ref (value);
			} else {
				ret = xmmsv_new_list ();
			}
			break;
		case AGGREGATE_RANDOM:
			random_data = data;
			if (random_data != NULL) {
				ret = random_data->data;
			} else {
				ret = xmmsv_new_none ();
			}
			break;
		case AGGREGATE_SET:
			set_data = data;
			if (set_data != NULL) {
				g_hash_table_destroy (set_data->ht);
				ret = set_data->list;
			} else {
				ret = xmmsv_new_list ();
			}
			break;
		case AGGREGATE_AVG:
			avg_data = data;
			if (avg_data != NULL) {
				ret = xmmsv_new_float (avg_data->n ? avg_data->sum * 1.0 / avg_data->n : 0);
			} else {
				ret = xmmsv_new_none ();
			}
			break;
		default:
			g_assert_not_reached ();
	}

	if (value != NULL) {
		xmmsv_unref (value);
	}

	return ret;
}