Beispiel #1
0
/**
 * Create a new argument for a method.
 *
 * @param name The name of the argument. Must not be NULL.
 * @param docstring The docstring of the argument.
 * @param type The expected type of the argument. Use XMMSV_TYPE_NONE to
 * accept any type. XMMSV_TYPE_ERROR is reserved and should not be used.
 * @param default_value Value to set this argument to if it's missing in the
 * method call. Implies that the argument is optional. If NULL, the argument
 * is not optional.
 */
xmmsv_t *
xmmsv_sc_argument_new (const char *name, const char *docstring,
                       xmmsv_type_t type, xmmsv_t *default_value)
{
	xmmsv_t *arg;

	x_api_error_if (!name, "with NULL name.", NULL);
	x_api_error_if (type == XMMSV_TYPE_ERROR, "with ERROR type.", NULL);
	x_api_error_if (default_value && type != XMMSV_TYPE_NONE &&
	                xmmsv_get_type (default_value) != type,
	                "with wrong type for default value.", NULL);

	arg = xmmsv_new_dict ();
	if (!arg) {
		x_oom ();
		return NULL;
	}

	xmmsv_dict_set_string (arg, "name", name);
	xmmsv_dict_set_int (arg, "type", type);

	if (docstring) {
		xmmsv_dict_set_string (arg, "docstring", docstring);
	}

	if (default_value) {
		xmmsv_dict_set (arg, "default_value", default_value);
	}

	return arg;
}
Beispiel #2
0
static xmmsv_t *
xmmsv_coll_normalize_order_arguments (xmmsv_t *value)
{
	xmmsv_t *order;
	const char *key;

	if (value == NULL) {
		return NULL;
	}

	if (xmmsv_is_type (value, XMMSV_TYPE_DICT)) {
		return xmmsv_ref (value);
	}

	x_api_error_if (!xmmsv_get_string (value, &key),
	                "order entry must be string or dict", NULL);

	order = xmmsv_new_dict ();

	if (key[0] == '-') {
		xmmsv_dict_set_string (order, "direction", "DESC");
		key++;
	}

	if (strcmp (key, "random") == 0) {
		xmmsv_dict_set_string (order, "type", "random");
	} else if (strcmp (key, "id") == 0) {
		xmmsv_dict_set_string (order, "type", "id");
	} else {
		xmmsv_dict_set_string (order, "type", "value");
		xmmsv_dict_set_string (order, "field", key);
	}

	return order;
}
static void
currently_playing_update_info (currently_playing_t *entry, xmmsv_t *value)
{
	const gchar *noinfo_fields[] = { "playback_status", "playtime", "position"};
	const gchar *time_fields[] = { "duration"};
	xmmsv_t *info;
	gint i;

	info = xmmsv_propdict_to_dict (value, NULL);

	enrich_mediainfo (info);

	/* copy over fields that are not from metadata */
	for (i = 0; i < G_N_ELEMENTS (noinfo_fields); i++) {
		xmmsv_t *copy;
		if (xmmsv_dict_get (entry->data, noinfo_fields[i], &copy)) {
			xmmsv_dict_set (info, noinfo_fields[i], copy);
		}
	}

	/* pretty format time fields */
	for (i = 0; i < G_N_ELEMENTS (time_fields); i++) {
		gint32 tim;
		if (xmmsv_dict_entry_get_int (info, time_fields[i], &tim)) {
			gchar *p = format_time (tim, FALSE);
			xmmsv_dict_set_string (info, time_fields[i], p);
			g_free (p);
		}
	}

	xmmsv_unref (entry->data);
	entry->data = info;
}
static void
currently_playing_update_status (currently_playing_t *entry, xmmsv_t *value)
{
	const gchar *status_name;
	gint status = -1;

	xmmsv_get_int (value, &status);

	switch (status) {
		case XMMS_PLAYBACK_STATUS_STOP:
			status_name = _("Stopped");
			break;
		case XMMS_PLAYBACK_STATUS_PLAY:
			status_name = _("Playing");
			break;
		case XMMS_PLAYBACK_STATUS_PAUSE:
			status_name = _("Paused");
			break;
		default:
			status_name = _("Unknown");
			break;
	}

	xmmsv_dict_set_string (entry->data, "playback_status", status_name);
}
Beispiel #5
0
static void
filter_testcase (const gchar *path, xmmsv_t *list)
{
	gchar *content, *filename;
	xmmsv_t *dict, *data, *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);

	xmmsv_dict_set (dict, "collection", coll);
	xmmsv_unref (coll);

	filename = g_path_get_basename (path);
	xmmsv_dict_set_string (dict, "name", filename);
	g_free (filename);

	xmmsv_list_append (list, dict);
	xmmsv_unref (dict);
}
Beispiel #6
0
/**
 * Creates a count fetch specification
 *
 * @return A new count fetch specification
 */
xmmsv_t *xmmsv_build_count ()
{
	xmmsv_t *res = xmmsv_new_dict ();

	xmmsv_dict_set_string (res, "type", "count");
	return res;
}
Beispiel #7
0
/**
 * Creates a cluster-dict fetch specification.
 *
 * @param cluster_by A list of attributes to cluster by
 * @param cluster_data The fetch specifcation to use when filling the list
 * @return A cluster-list fetch specification
 */
xmmsv_t *xmmsv_build_cluster_dict (xmmsv_t *cluster_by, xmmsv_t *cluster_field, xmmsv_t *cluster_data)
{
	xmmsv_t *res = xmmsv_new_dict ();
	if (res == NULL)
		return NULL;

	xmmsv_dict_set_string (res, "type", "cluster-dict");

	if (cluster_by != NULL) {
		xmmsv_dict_set (res, "cluster-by", cluster_by);
		xmmsv_unref (cluster_by);
	}


	if (cluster_field != NULL) {
		xmmsv_dict_set (res, "cluster-field", cluster_field);
		xmmsv_unref (cluster_field);
	}

	if (cluster_data != NULL) {
		xmmsv_dict_set (res, "data", cluster_data);
		xmmsv_unref (cluster_data);
	}

	return res;
}
static void
currently_playing_update_playtime (currently_playing_t *entry, xmmsv_t *value)
{
	gchar *formatted;
	gint playtime;

	xmmsv_get_int (value, &playtime);

	formatted = format_time (playtime, FALSE);
	xmmsv_dict_set_string (entry->data, "playtime", formatted);
	g_free (formatted);
}
Beispiel #9
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;
}
Beispiel #10
0
/**
 * Creates an organize fetch specification that may be passed to xmmsc_coll_query.
 * It takes a dict with key-value pairs where the values are fetch specifications.
 *
 * @return An organize fetch specification
 */
xmmsv_t *
xmmsv_build_organize (xmmsv_t *data)
{
	xmmsv_t *res;

	x_return_val_if_fail (data != NULL, NULL);
	res = xmmsv_new_dict ();

	if (res != NULL) {
		xmmsv_dict_set_string (res, "type", "organize");
		xmmsv_dict_set (res, "data", data);
		xmmsv_unref (data);
	}

	return res;
}
Beispiel #11
0
/**
 * Converts a fetch specification in xmmsv_t form into a
 * fetch_spec_t structure
 */
xmms_fetch_spec_t *
xmms_fetch_spec_new (xmmsv_t *fetch, xmms_fetch_info_t *info,
                     s4_sourcepref_t *prefs, xmms_error_t *err)
{
	const char *type;

	if (xmmsv_get_type (fetch) != XMMSV_TYPE_DICT) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "A fetch specification must be a dict.");
		return NULL;
	}

	if (xmmsv_dict_entry_get_type (fetch, "type") == XMMSV_TYPE_NONE) {
		xmmsv_dict_set_string (fetch, "type", "metadata");
	}

	if (!xmmsv_dict_entry_get_string (fetch, "type", &type)) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "A fetch specification must have a type.");
		return NULL;
	}

	if (strcmp (type, "metadata") == 0) {
		return xmms_fetch_spec_new_metadata (fetch, info, prefs, err);
	} else if (strcmp (type, "cluster-list") == 0) {
		return xmms_fetch_spec_new_cluster_list (fetch, info, prefs, err);
	} else if (strcmp (type, "cluster-dict") == 0) {
		return xmms_fetch_spec_new_cluster_dict (fetch, info, prefs, err);
	} else if (strcmp (type, "organize") == 0) {
		return xmms_fetch_spec_new_organize (fetch, info, prefs, err);
	} else if (strcmp (type, "count") == 0) {
		return xmms_fetch_spec_new_count (fetch, info, prefs, err);
	}

	xmms_error_set (err, XMMS_ERROR_INVAL, "Unknown fetch type.");

	return NULL;
}
Beispiel #12
0
static gint
normalize_aggregate_function (xmmsv_t *fetch, xmms_error_t *err)
{
	const gchar *name;
	guint32 aggregate;

	if (xmmsv_dict_entry_get_type (fetch, "aggregate") == XMMSV_TYPE_NONE) {
		xmmsv_dict_set_string (fetch, "aggregate", "first");
	}

	/* Default to first as the aggregation function */
	if (!xmmsv_dict_entry_get_string (fetch, "aggregate", &name)) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "'aggregate' must be a string.");
		return -1;
	}

	if (!aggregate_value_from_string (name, &aggregate)) {
		const gchar *message = "'aggregate' must be 'first', 'sum', 'max', 'min', 'list', 'set', 'random', or 'avg'";
		xmms_error_set (err, XMMS_ERROR_INVAL, message);
		return -1;
	}

	return aggregate;
}
Beispiel #13
0
/** 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);
}
Beispiel #14
0
/**
 * Set a string attribute in the given collection.
 *
 * @param coll The collection in which to set the attribute.
 * @param key  The name of the attribute to set.
 * @param value The value of the attribute.
 */
void
xmmsv_coll_attribute_set_string (xmmsv_t *coll, const char *key, const char *value)
{
	x_return_if_fail (xmmsv_is_type (coll, XMMSV_TYPE_COLL));
	xmmsv_dict_set_string (coll->value.coll->attributes, key, value);
}