/** * 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; }
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], ©)) { 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); }
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); }
/** * 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; }
/** * 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); }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
/** 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); }
/** * 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); }