Пример #1
0
static void
xmms_playlist_client_load (xmms_playlist_t *playlist, const gchar *name, xmms_error_t *err)
{
	xmmsv_coll_t *plcoll, *active_coll;

	if (strcmp (name, XMMS_ACTIVE_PLAYLIST) == 0) {
		xmms_error_set (err, XMMS_ERROR_INVAL, "invalid playlist to load");
		return;
	}

	active_coll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
	if (active_coll == NULL) {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "no active playlist");
		return;
	}

	plcoll = xmms_playlist_get_coll (playlist, name, err);
	if (plcoll == NULL) {
		xmms_error_set (err, XMMS_ERROR_NOENT, "no such playlist");
		return;
	}

	if (active_coll == plcoll) {
		XMMS_DBG ("Not loading %s playlist, already active!", name);
		return;
	}

	XMMS_DBG ("Loading new playlist! %s", name);
	xmms_collection_update_pointer (playlist->colldag, XMMS_ACTIVE_PLAYLIST,
	                                XMMS_COLLECTION_NSID_PLAYLISTS, plcoll);

	xmms_object_emit (XMMS_OBJECT (playlist),
	                  XMMS_IPC_SIGNAL_PLAYLIST_LOADED,
	                  xmmsv_new_string (name));
}
Пример #2
0
/**
 * Retrieve the position of the currently active xmms_medialib_entry_t
 *
 */
xmmsv_t *
xmms_playlist_client_current_pos (xmms_playlist_t *playlist, const gchar *plname,
                                  xmms_error_t *err)
{
	guint32 pos;
	xmmsv_coll_t *plcoll;
	xmmsv_t *dict;

	g_return_val_if_fail (playlist, 0);

	g_mutex_lock (playlist->mutex);

	plcoll = xmms_playlist_get_coll (playlist, plname, err);
	if (plcoll == NULL) {
		g_mutex_unlock (playlist->mutex);
		xmms_error_set (err, XMMS_ERROR_INVAL, "no such playlist");
		return 0;
	}

	pos = xmms_playlist_coll_get_currpos (plcoll);
	if (pos == -1) {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "no current entry");
	}

	g_mutex_unlock (playlist->mutex);

	dict = xmms_playlist_current_pos_msg_new (playlist, pos, plname);

	return dict;
}
Пример #3
0
/**
 * Retrieve a copy of the name of the currently active playlist.
 *
 */
static gchar *
xmms_playlist_client_current_active (xmms_playlist_t *playlist, xmms_error_t *err)
{
	gchar *alias = NULL;
	xmmsv_coll_t *active_coll;

	g_return_val_if_fail (playlist, 0);

	g_mutex_lock (playlist->mutex);

	active_coll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
	if (active_coll != NULL) {
		alias = xmms_collection_find_alias (playlist->colldag,
		                                    XMMS_COLLECTION_NSID_PLAYLISTS,
		                                    active_coll, XMMS_ACTIVE_PLAYLIST);
		if (alias == NULL) {
			xmms_error_set (err, XMMS_ERROR_GENERIC, "active playlist not referenced!");
		}
	} else {
		xmms_error_set (err, XMMS_ERROR_GENERIC, "no active playlist");
	}

	g_mutex_unlock (playlist->mutex);

	return alias;
}
Пример #4
0
/** List a playlist */
static GList *
xmms_playlist_client_list_entries (xmms_playlist_t *playlist, const gchar *plname,
                                   xmms_error_t *err)
{
	GList *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;
	}

	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);
		entries = g_list_prepend (entries, xmmsv_new_int (entry));
	}
	xmmsv_list_iter_explicit_destroy (it);

	g_mutex_unlock (playlist->mutex);

	entries = g_list_reverse (entries);

	return entries;
}
Пример #5
0
static gint
xmms_playlist_set_current_position_do (xmms_playlist_t *playlist, guint32 pos,
                                       xmms_error_t *err)
{
	gint size;
	xmms_medialib_entry_t mid;
	xmmsv_coll_t *plcoll;
	const gchar *jumplist;

	g_return_val_if_fail (playlist, FALSE);

	plcoll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
	if (plcoll == NULL) {
		return 0;
	}

	size = xmms_playlist_coll_get_size (plcoll);

	if (pos == size &&
	    xmmsv_coll_attribute_get (plcoll, "jumplist", &jumplist)) {

		xmms_collection_set_int_attr (plcoll, "position", 0);
		XMMS_PLAYLIST_CURRPOS_MSG (0, XMMS_ACTIVE_PLAYLIST);

		xmms_playlist_client_load (playlist, jumplist, err);
		if (xmms_error_iserror (err)) {
			return 0;
		}

		plcoll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
		if (plcoll == NULL) {
			return 0;
		}
	} else if (pos < size) {
		XMMS_DBG ("newpos! %d", pos);
		xmms_collection_set_int_attr (plcoll, "position", pos);
		XMMS_PLAYLIST_CURRPOS_MSG (pos, XMMS_ACTIVE_PLAYLIST);
	} else {
		xmms_error_set (err, XMMS_ERROR_INVAL,
		                "Can't set pos outside the current playlist!");
		return 0;
	}

	xmmsv_coll_idlist_get_index (plcoll, pos, &mid);

	return mid;
}
Пример #6
0
/**
 * Insert an entry at a given position in the playlist without
 * validating it.
 *
 * @internal
 */
void
xmms_playlist_insert_entry (xmms_playlist_t *playlist, const gchar *plname,
                            guint32 pos, xmms_medialib_entry_t file,
                            xmms_error_t *err)
{
    xmms_medialib_session_t *session;
    xmmsv_t *dict;
    gint currpos;
    gint len;
    xmmsv_coll_t *plcoll;
    gboolean valid;

    g_mutex_lock (playlist->mutex);

    do {
        session = xmms_medialib_session_begin_ro (playlist->medialib);
        valid = xmms_medialib_check_id (session, file);
    } while (!xmms_medialib_session_commit (session));

    if (!valid) {
        g_mutex_unlock (playlist->mutex);
        xmms_error_set (err, XMMS_ERROR_NOENT,
                        "That is not a valid medialib id!");
        return;
    }


    plcoll = xmms_playlist_get_coll (playlist, plname, err);
    if (plcoll == NULL) {
        /* FIXME: happens ? */
        g_mutex_unlock (playlist->mutex);
        return;
    }

    len = xmms_playlist_coll_get_size (plcoll);
    if (pos > len) {
        xmms_error_set (err, XMMS_ERROR_GENERIC,
                        "Could not insert entry outside of playlist!");
        g_mutex_unlock (playlist->mutex);
        return;
    }
    xmmsv_coll_idlist_insert (plcoll, pos, file);

    /** propagate the MID ! */
    dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_INSERT, file, plname);
    xmmsv_dict_set_int (dict, "position", pos);
    xmms_playlist_changed_msg_send (playlist, dict);

    /** update position once client is familiar with the new item. */
    currpos = xmms_playlist_coll_get_currpos (plcoll);
    if (pos <= currpos) {
        currpos++;
        xmms_collection_set_int_attr (plcoll, "position", currpos);
        XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);
    }

    g_mutex_unlock (playlist->mutex);
}
Пример #7
0
static gboolean
xmms_playlist_advance_do (xmms_playlist_t *playlist)
{
	gint size, currpos;
	gboolean ret = TRUE;
	xmmsv_coll_t *plcoll;
	const gchar *jumplist;
	xmms_error_t err;
	xmms_playlist_t *buffer = playlist;
	guint newpos;

	xmms_error_reset (&err);

	plcoll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, NULL);
	if (plcoll == NULL) {
		ret = FALSE;
	} else if ((size = xmms_playlist_coll_get_size (plcoll)) == 0) {
		if (xmmsv_coll_attribute_get (plcoll, "jumplist", &jumplist)) {
			xmms_playlist_client_load (buffer, jumplist, &err);
			if (xmms_error_isok (&err)) {
				ret = xmms_playlist_advance_do (playlist);
			} else {
				ret = FALSE;
			}
		} else {
			ret = FALSE;
		}
	} else if (!playlist->repeat_one) {
		currpos = xmms_playlist_coll_get_currpos (plcoll);
		currpos++;

		if (currpos == size && !playlist->repeat_all &&
		    xmmsv_coll_attribute_get (plcoll, "jumplist", &jumplist)) {

			xmms_collection_set_int_attr (plcoll, "position", -1);
			XMMS_PLAYLIST_CURRPOS_MSG (-1, XMMS_ACTIVE_PLAYLIST);

			xmms_playlist_client_load (buffer, jumplist, &err);
			if (xmms_error_isok (&err)) {
				ret = xmms_playlist_advance_do (playlist);
			} else {
				ret = FALSE;
			}
		} else {
			newpos = currpos%size;
			xmms_collection_set_int_attr (plcoll, "position", newpos);
			XMMS_PLAYLIST_CURRPOS_MSG (newpos, XMMS_ACTIVE_PLAYLIST);
			ret = (currpos != size) || playlist->repeat_all;
		}
	}

	return ret;
}
Пример #8
0
/**
 * Add an entry to the playlist without validating it.
 *
 * @internal
 */
void
xmms_playlist_add_entry (xmms_playlist_t *playlist, const gchar *plname,
                         xmms_medialib_entry_t file, xmms_error_t *err)
{
	xmmsv_coll_t *plcoll;

	g_mutex_lock (playlist->mutex);

	plcoll = xmms_playlist_get_coll (playlist, plname, err);
	if (plcoll != NULL) {
		xmms_playlist_add_entry_unlocked (playlist, plname, plcoll, file, err);
	}

	g_mutex_unlock (playlist->mutex);

}
Пример #9
0
/**
 * Remove an entry from playlist.
 *
 */
void
xmms_playlist_client_remove_entry (xmms_playlist_t *playlist,
                                   const gchar *plname,
                                   gint32 pos, xmms_error_t *err)
{
	xmmsv_coll_t *plcoll;

	g_return_if_fail (playlist);

	g_mutex_lock (playlist->mutex);
	plcoll = xmms_playlist_get_coll (playlist, plname, err);
	if (plcoll != NULL) {
		xmms_playlist_remove_unlocked (playlist, plname, plcoll, pos, err);
	}
	g_mutex_unlock (playlist->mutex);
}
Пример #10
0
static void
xmms_playlist_update_unlocked (xmms_playlist_t *playlist, const gchar *plname)
{
	xmmsv_coll_t *plcoll;
	const gchar *type = NULL;

	plcoll = xmms_playlist_get_coll (playlist, plname, NULL);
	if (plcoll) {
		xmmsv_coll_attribute_get (plcoll, "type", &type);
		if (g_strcmp0 (type, "queue") == 0) {
			xmms_playlist_update_queue (playlist, plname, plcoll);
		} else if (g_strcmp0 (type, "pshuffle") == 0) {
			xmms_playlist_update_partyshuffle (playlist, plname, plcoll);
		}
	}
}
Пример #11
0
/**
 * Shuffle the playlist.
 *
 */
static void
xmms_playlist_client_shuffle (xmms_playlist_t *playlist, const gchar *plname,
                              xmms_error_t *err)
{
	guint j,i;
	gint len, currpos;
	xmmsv_coll_t *plcoll;

	g_return_if_fail (playlist);

	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);
	len = xmms_playlist_coll_get_size (plcoll);
	if (len > 1) {
		/* put current at top and exclude from shuffling */
		if (currpos != -1) {
			swap_entries (plcoll, 0, currpos);
			currpos = 0;
			xmms_collection_set_int_attr (plcoll, "position", currpos);
		}

		/* knuth <3 */
		for (i = currpos + 1; i < len; i++) {
			j = g_random_int_range (i, len);

			if (i != j) {
				swap_entries (plcoll, i, j);
			}
		}

	}

	XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_SHUFFLE, 0, plname);
	XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);

	g_mutex_unlock (playlist->mutex);
}
Пример #12
0
static gint
xmms_playlist_client_set_next_rel (xmms_playlist_t *playlist, gint32 pos,
                                   xmms_error_t *err)
{
	gint currpos, newpos, size;
	xmms_medialib_entry_t mid = 0;
	xmmsv_coll_t *plcoll;

	g_return_val_if_fail (playlist, FALSE);

	g_mutex_lock (playlist->mutex);

	plcoll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, err);
	if (plcoll != NULL) {
		currpos = xmms_playlist_coll_get_currpos (plcoll);

		if (playlist->repeat_all) {
			newpos = pos + currpos;
			size = (gint) xmmsv_coll_idlist_get_size (plcoll);

			if (size > 0) {
				newpos %= size;
				if (newpos < 0) {
					newpos += size;
				}
			}

			mid = xmms_playlist_set_current_position_do (playlist, newpos, err);
		} else {
			if (currpos + pos >= 0) {
				mid = xmms_playlist_set_current_position_do (playlist,
				                                             currpos + pos,
				                                             err);
			} else {
				xmms_error_set (err, XMMS_ERROR_INVAL,
				                "Can't set pos outside the current playlist!");
			}
		}
	}

	g_mutex_unlock (playlist->mutex);

	return mid;
}
Пример #13
0
/** Clear the playlist */
static void
xmms_playlist_client_clear (xmms_playlist_t *playlist, const gchar *plname,
                            xmms_error_t *err)
{
	xmmsv_coll_t *plcoll;

	g_return_if_fail (playlist);

	g_mutex_lock (playlist->mutex);

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

	xmmsv_coll_idlist_clear (plcoll);
	xmms_collection_set_int_attr (plcoll, "position", -1);

	XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_CLEAR, 0, plname);
	g_mutex_unlock (playlist->mutex);

}
Пример #14
0
/**
 * Retrieve the currently active xmms_medialib_entry_t.
 *
 */
xmms_medialib_entry_t
xmms_playlist_current_entry (xmms_playlist_t *playlist)
{
	gint size, currpos;
	xmmsv_coll_t *plcoll;
	xmms_medialib_entry_t ent = 0;

	g_return_val_if_fail (playlist, 0);

	g_mutex_lock (playlist->mutex);

	plcoll = xmms_playlist_get_coll (playlist, XMMS_ACTIVE_PLAYLIST, NULL);
	if (plcoll == NULL) {
		/* FIXME: What happens? */
		g_mutex_unlock (playlist->mutex);
		return 0;
	}

	currpos = xmms_playlist_coll_get_currpos (plcoll);
	size = xmms_playlist_coll_get_size (plcoll);

	if (currpos == -1 && (size > 0)) {
		currpos = 0;
		xmms_collection_set_int_attr (plcoll, "position", currpos);
		XMMS_PLAYLIST_CURRPOS_MSG (0, XMMS_ACTIVE_PLAYLIST);
	}

	if (currpos < size) {
		xmmsv_coll_idlist_get_index (plcoll, currpos, &ent);
	} else {
		ent = 0;
	}

	g_mutex_unlock (playlist->mutex);

	return ent;
}
Пример #15
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);
}
Пример #16
0
/**
 * Move an entry in playlist
 *
 */
static void
xmms_playlist_client_move_entry (xmms_playlist_t *playlist,
                                 const gchar *plname, gint32 pos,
                                 gint32 newpos, xmms_error_t *err)
{
	xmmsv_t *dict;
	xmms_medialib_entry_t id;
	gint currpos, size;
	gint64 ipos, inewpos;
	xmmsv_coll_t *plcoll;

	g_return_if_fail (playlist);

	XMMS_DBG ("Moving %d, to %d", pos, newpos);

	g_mutex_lock (playlist->mutex);

	plcoll = xmms_playlist_get_coll (playlist, plname, err);
	if (plcoll == NULL) {
		/* FIXME: happens ? */
		g_mutex_unlock (playlist->mutex);
		return;
	}

	currpos = xmms_playlist_coll_get_currpos (plcoll);
	size = xmms_playlist_coll_get_size (plcoll);

	if (size == 0 || newpos > (size - 1)) {
		xmms_error_set (err, XMMS_ERROR_NOENT,
		                "Cannot move entry outside playlist");
		g_mutex_unlock (playlist->mutex);
		return;
	}

	if (!xmmsv_coll_idlist_move (plcoll, pos, newpos)) {
		xmms_error_set (err, XMMS_ERROR_NOENT, "Entry was not in list!");
		g_mutex_unlock (playlist->mutex);
		return;
	}

	/* Update the current position pointer */
	ipos = pos;
	inewpos = newpos;
	if (inewpos <= currpos && ipos > currpos)
		currpos++;
	else if (inewpos >= currpos && ipos < currpos)
		currpos--;
	else if (ipos == currpos)
		currpos = inewpos;

	xmms_collection_set_int_attr (plcoll, "position", currpos);

	xmmsv_coll_idlist_get_index (plcoll, newpos, &id);

	dict = xmms_playlist_changed_msg_new (playlist, XMMS_PLAYLIST_CHANGED_MOVE, id, plname);
	xmmsv_dict_set_int (dict, "position", pos);
	xmmsv_dict_set_int (dict, "newposition", newpos);
	xmms_playlist_changed_msg_send (playlist, dict);

	XMMS_PLAYLIST_CURRPOS_MSG (currpos, plname);

	g_mutex_unlock (playlist->mutex);

	return;

}
Пример #17
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_replace (xmms_playlist_t *playlist, const gchar *plname,
                              xmmsv_coll_t *coll, xmms_playlist_position_action_t action,
                              xmms_error_t *err)
{
    xmms_medialib_entry_t id, current_id;
    xmmsv_coll_t *plcoll;
    xmmsv_t *result;
    gint current_position, i;

    g_return_if_fail (playlist);
    g_return_if_fail (coll);

    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;
    }

    current_position = xmms_playlist_coll_get_currpos (plcoll);
    xmmsv_coll_idlist_get_index (plcoll, current_position, &current_id);

    result = xmms_collection_query_ids (playlist->colldag, coll, err);
    if (result == NULL) {
        g_mutex_unlock (playlist->mutex);
        return;
    }

    xmmsv_coll_idlist_clear (plcoll);

    current_position = -1;

    for (i = 0; xmmsv_list_get_int (result, i, &id); i++) {
        if (id == current_id)
            current_position = i;
        xmmsv_coll_idlist_append (plcoll, id);
    }

    switch (action) {
    case XMMS_PLAYLIST_CURRENT_ID_FORGET:
        current_position = -1;
        break;
    case XMMS_PLAYLIST_CURRENT_ID_MOVE_TO_FRONT:
        if (current_position > 0) {
            xmmsv_coll_idlist_move (plcoll, current_position, 0);
            current_position = 0;
        }
        break;
    default:
        break;
    }

    xmmsv_unref (result);

    xmms_collection_set_int_attr (plcoll, "position", current_position);

    XMMS_PLAYLIST_CHANGED_MSG (XMMS_PLAYLIST_CHANGED_REPLACE,
                               (current_position < 0) ? 0 : current_id, plname);
    XMMS_PLAYLIST_CURRPOS_MSG (current_position, plname);

    g_mutex_unlock (playlist->mutex);
}