playlist: Update the design and unit test
I updated the code to better match how I use playlists and to make sure that everything is tested. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
f6306faac8
commit
11df56139d
119
DESIGN
119
DESIGN
|
@ -991,6 +991,81 @@ File Format:
|
|||
|
||||
|
||||
|
||||
Playlist:
|
||||
Playlists are a new feature in Ocarina 6 and are modeled after Gmail
|
||||
labels. Ocarina 6.1 will support two different playlists that the
|
||||
user can add tracks to: banned and favorites.
|
||||
|
||||
The playlist layer will maintain a queue that is used by the UI to
|
||||
display tracks in a given playlist. This queue is inherited from
|
||||
the base Queue class to provide extra features.
|
||||
|
||||
Future releases will add support for more playlists.
|
||||
|
||||
- Index:
|
||||
Index playlist_db("playlist.db", true);
|
||||
|
||||
- Queue:
|
||||
class PlaylistQueue : public Queue {
|
||||
public:
|
||||
PlaylistQueue();
|
||||
fill(IndexEntry *);
|
||||
};
|
||||
|
||||
- Default playlists:
|
||||
Favorites:
|
||||
The user will add music they really like to this playlist.
|
||||
|
||||
Banned:
|
||||
The user should add music they do not like to this playlist.
|
||||
Tracks should be removed from the Library playqueue when they
|
||||
are banned and added back to the playqueue when they are
|
||||
un-banned.
|
||||
|
||||
- PlaylistQueue API:
|
||||
PlaylistQueue :: PlaylistQueue();
|
||||
Initialize a Queue with the flags Q_ENABLED, Q_REPEAT, and
|
||||
Q_NO_SORT set. Default sorting order should be artist, year,
|
||||
track.
|
||||
|
||||
PlaylistQueue :: fill(IndexEntry *ent);
|
||||
Remove all tracks in the queue and repopulate using ent.
|
||||
|
||||
- API
|
||||
void playlist :: init():
|
||||
Load the playlist index from file.
|
||||
|
||||
void playlist :: add(Track *track, const std::string &name);
|
||||
Add track->id to the playlist named "name" and return true.
|
||||
Return false if the playlist does not exist.
|
||||
|
||||
If "name" is the currently selected playlist, add the track
|
||||
to the PlaylistQueue.
|
||||
|
||||
void playlist :: del(Track *track, const std::string &name);
|
||||
Remove track->id from the playlist named "name" and return true.
|
||||
Return false if the playlist does not exist or if the track
|
||||
is not in the playlist.
|
||||
|
||||
If "name" is the currently selected playlist, remove the track
|
||||
from the PlaylistQueue.
|
||||
|
||||
bool playlist :: has(Track *track, const std::string &name);
|
||||
Return true if the chosen playlist has the given track.
|
||||
Return false otherwise.
|
||||
|
||||
void playlist :: select(const std::string &name);
|
||||
Change the currently displayed playlist to "name".
|
||||
|
||||
const IndexEntry *playlist :: get_tracks(const std::string &name);
|
||||
Return the IndexEntry represeting the requested playlist.
|
||||
Return NULL if the requested playlist does not exist.
|
||||
|
||||
Queue *playlist :: get_queue();
|
||||
Return the PlaylistQueue to the caller.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1101,50 +1176,6 @@ Library: (lib/library.cpp)
|
|||
|
||||
|
||||
|
||||
Playlists: (lib/playlist.cpp)
|
||||
Playlists are a new feature in Ocarina 6 and are modeled after Gmail
|
||||
labels. Ocarina 6.1 will support two different playlists that the
|
||||
user can add tracks to: banned and favorites.
|
||||
|
||||
Future releases will add support for more playlists.
|
||||
|
||||
- Database:
|
||||
Database<database :: IndexEntry> playlist_db
|
||||
|
||||
- Default playlists:
|
||||
Favorites:
|
||||
The user will add music they really like to this playlist.
|
||||
|
||||
Banned:
|
||||
The user should add music they do not like to this playlist.
|
||||
Tracks should be removed from the Library playqueue when they
|
||||
are banned and added back to the playqueue when they are
|
||||
un-banned.
|
||||
|
||||
- API
|
||||
void playlist :: init():
|
||||
Load the playlist database.
|
||||
|
||||
void playlist :: add(name, track_id);
|
||||
Add the track_id to the playlist named "name". Save the
|
||||
database to disk.
|
||||
Throw -EEXIST if "name" does not exist.
|
||||
|
||||
void playlist :: del(name, track_id);
|
||||
Remove the track_id from the playlist named "name". Save the
|
||||
database to disk. Attempting to remove a track_id that does
|
||||
not exist is not an error.
|
||||
Throw -EEXIST if "name" does not exist.
|
||||
|
||||
const std::set<unsigned int> &playlist :: get_tracks(name);
|
||||
Return the set of tracks representing the requested group.
|
||||
Throw -EEXIST if "name" does not exist.
|
||||
|
||||
void playlist :: clear();
|
||||
This function only exists if CONFIG_TEST is enabled. Clear
|
||||
(reset) the playlist database.
|
||||
|
||||
|
||||
|
||||
Deck: (lib/deck.cpp)
|
||||
The playqueue deck is used to hold the temporary playqueues created by
|
||||
|
|
|
@ -46,7 +46,7 @@ bool CollectionTab :: on_key_press_event(const std::string &key)
|
|||
|
||||
tab_selected_ids(ids);
|
||||
for (unsigned int i = 0; i < ids.size(); i++)
|
||||
playlist :: add("Banned", ids[i]);
|
||||
playlist :: add(tagdb :: lookup(ids[i]), "Banned");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
17
gui/gui.cpp
17
gui/gui.cpp
|
@ -78,11 +78,8 @@ static void on_track_loaded(Track *track)
|
|||
set_label_text(album, "x-large", "From: " + track->album->name);
|
||||
duration->set_text(track->length_str);
|
||||
|
||||
std::set<unsigned int> ids = playlist :: get_tracks("Banned");
|
||||
bool banned = ids.find(track->id) != ids.end();
|
||||
|
||||
ids = playlist :: get_tracks("Favorites");
|
||||
bool favorite = ids.find(track->id) != ids.end();
|
||||
bool banned = playlist :: has(track, "Banned");
|
||||
bool favorite = playlist :: has(track, "Favorites");
|
||||
|
||||
ban_connection.block();
|
||||
fav_connection.block();
|
||||
|
@ -107,12 +104,12 @@ static void on_pause_count_changed(bool enabled, unsigned int count)
|
|||
|
||||
static void on_ban_toggled()
|
||||
{
|
||||
Gtk::ToggleButton *ban = get_widget<Gtk::ToggleButton>("o_pan");
|
||||
Gtk::ToggleButton *ban = get_widget<Gtk::ToggleButton>("o_ban");
|
||||
|
||||
if (ban->get_active() == true)
|
||||
playlist :: add("Banned", audio::current_trackid());
|
||||
playlist :: add(tagdb :: lookup(audio :: current_trackid()), "Banned");
|
||||
else
|
||||
playlist :: del("Banned", audio::current_trackid());
|
||||
playlist :: del(tagdb :: lookup(audio::current_trackid()), "Banned");
|
||||
}
|
||||
|
||||
static void on_fav_toggled()
|
||||
|
@ -120,9 +117,9 @@ static void on_fav_toggled()
|
|||
Gtk::ToggleButton *fav = get_widget<Gtk::ToggleButton>("o_favorite");
|
||||
|
||||
if (fav->get_active() == true)
|
||||
playlist :: add("Favorites", audio::current_trackid());
|
||||
playlist :: add(tagdb :: lookup(audio::current_trackid()), "Favorites");
|
||||
else
|
||||
playlist :: del("Favorites", audio::current_trackid());
|
||||
playlist :: del(tagdb :: lookup(audio::current_trackid()), "Favorites");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ Gtk::Window *ocarina_init(int *argc, char ***argv)
|
|||
library::init();
|
||||
playlist::init();
|
||||
|
||||
playlist :: select("Favorites");
|
||||
share_file("ocarina6.glade");
|
||||
post_init_tabs();
|
||||
audio::load_state();
|
||||
|
|
|
@ -58,7 +58,7 @@ void QueueModel::on_row_changed(unsigned int row)
|
|||
void QueueModel::on_path_selected(const Gtk::TreePath &path)
|
||||
{
|
||||
audio :: load_trackid(path_to_id(path));
|
||||
queue->path_selected(path[0]);
|
||||
queue->track_selected(path[0]);
|
||||
audio :: play();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
|
||||
PlaylistTab :: PlaylistTab()
|
||||
: Tab(playlist :: get_pq())
|
||||
: Tab(playlist :: get_queue())
|
||||
{
|
||||
tab_search = get_widget<Gtk::SearchEntry>("o_playlist_entry");
|
||||
tab_treeview = get_widget<Gtk::TreeView>("o_playlist_pq_treeview");
|
||||
|
@ -43,7 +43,7 @@ bool PlaylistTab :: on_key_press_event(const std::string &key)
|
|||
|
||||
tab_selected_ids(ids);
|
||||
for (unsigned int i = 0; i < ids.size(); i++)
|
||||
playlist :: del(current_playlist(), ids[i]);
|
||||
playlist :: del(tagdb :: lookup(ids[i]), current_playlist());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ bool Tab :: tab_add_to_playlist(const std::string &playlist)
|
|||
|
||||
tab_selected_ids(ids);
|
||||
for (unsigned int i = 0; i < ids.size(); i++)
|
||||
playlist :: add(playlist, ids[i]);
|
||||
playlist :: add(tagdb :: lookup(ids[i]), playlist);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,6 @@ struct Callbacks {
|
|||
void (*on_library_track_add)(unsigned int);
|
||||
void (*on_library_track_del)(unsigned int);
|
||||
void (*on_library_track_updated)(unsigned int);
|
||||
void (*on_library_import_ban)(unsigned int);
|
||||
|
||||
/* Playlist callbacks */
|
||||
void (*on_playlist_ban)(unsigned int);
|
||||
void (*on_playlist_unban)(unsigned int);
|
||||
|
||||
/* Queue callbacks */
|
||||
void (*on_queue_track_add)(Queue *, unsigned int);
|
||||
|
|
|
@ -4,25 +4,22 @@
|
|||
#ifndef OCARINA_PLAYLIST_H
|
||||
#define OCARINA_PLAYLIST_H
|
||||
|
||||
#include <index.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace playlist
|
||||
{
|
||||
|
||||
void init();
|
||||
void add(const std::string &, unsigned int);
|
||||
void del(const std::string &, unsigned int);
|
||||
bool has(Track *, const std::string &);
|
||||
void add(Track *, const std::string &);
|
||||
void del(Track *, const std::string &);
|
||||
void select(const std::string &);
|
||||
const std::set<unsigned int> &get_tracks(const std::string &);
|
||||
Queue *get_pq();
|
||||
IndexEntry *get_tracks(const std::string &);
|
||||
Queue *get_queue();
|
||||
|
||||
#ifdef CONFIG_TEST
|
||||
void clear();
|
||||
#endif /* CONFIG_TEST */
|
||||
};
|
||||
|
||||
#endif /* OCARINA_PLAYLIST_H */
|
||||
|
|
|
@ -27,10 +27,6 @@ static struct Callbacks callbacks = {
|
|||
.on_library_track_add = no_op,
|
||||
.on_library_track_del = no_op,
|
||||
.on_library_track_updated = no_op,
|
||||
.on_library_import_ban = no_op,
|
||||
|
||||
.on_playlist_ban = no_op,
|
||||
.on_playlist_unban = no_op,
|
||||
|
||||
.on_queue_track_add = no_op,
|
||||
.on_queue_track_del = no_op,
|
||||
|
|
|
@ -37,8 +37,6 @@ void deck :: init()
|
|||
library_playqueue.sort(SORT_TRACK, false);
|
||||
read();
|
||||
|
||||
get_callbacks()->on_playlist_ban = del_library_track;
|
||||
get_callbacks()->on_playlist_unban = add_library_track;
|
||||
get_callbacks()->on_library_track_add = add_library_track;
|
||||
get_callbacks()->on_library_track_del = del_library_track;
|
||||
get_callbacks()->on_library_track_updated = change_library_track;
|
||||
|
|
139
lib/playlist.cpp
139
lib/playlist.cpp
|
@ -1,103 +1,96 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <callback.h>
|
||||
#include <error.h>
|
||||
#include <index.h>
|
||||
#include <playlist.h>
|
||||
|
||||
static std::set<unsigned int> empty_set;
|
||||
static Index playlist_db("playlist.db", false);
|
||||
static Queue playlist_pq(Q_ENABLED | Q_REPEAT | Q_NO_SORT);
|
||||
static std::string cur_pq;
|
||||
|
||||
static void import_ban_track(unsigned int track_id)
|
||||
{
|
||||
playlist :: add("Banned", track_id);
|
||||
}
|
||||
class PlaylistQueue : public Queue {
|
||||
public:
|
||||
|
||||
PlaylistQueue() : Queue(Q_ENABLED | Q_REPEAT)
|
||||
{
|
||||
sort(SORT_ARTIST, true);
|
||||
sort(SORT_YEAR, false);
|
||||
sort(SORT_TRACK, false);
|
||||
set_flag(Q_NO_SORT);
|
||||
}
|
||||
|
||||
void fill(IndexEntry *ent)
|
||||
{
|
||||
std::set<unsigned int>::iterator it;
|
||||
|
||||
while (size() > 0)
|
||||
del((unsigned)0);
|
||||
|
||||
for (it = ent->values.begin(); it != ent->values.end(); it++)
|
||||
add(tagdb :: lookup(*it));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
static Index playlist_db("playlist.db", true);
|
||||
static PlaylistQueue playlist_q;
|
||||
static std::string cur_plist;
|
||||
|
||||
|
||||
void playlist :: init()
|
||||
{
|
||||
std::set<unsigned int> ids;
|
||||
std::set<unsigned int>::iterator it;
|
||||
|
||||
playlist_pq.sort(SORT_ARTIST, true);
|
||||
playlist_pq.sort(SORT_YEAR, false);
|
||||
playlist_pq.sort(SORT_TRACK, false);
|
||||
|
||||
get_callbacks()->on_library_import_ban = import_ban_track;
|
||||
|
||||
playlist_db.load();
|
||||
}
|
||||
|
||||
ids = get_tracks("Banned");
|
||||
for (it = ids.begin(); it != ids.end(); it++)
|
||||
get_callbacks()->on_playlist_ban(*it);
|
||||
bool playlist :: has(Track *track, const std::string &name)
|
||||
{
|
||||
std::set<unsigned int>::iterator it;
|
||||
IndexEntry *ent = playlist_db.find(name);
|
||||
|
||||
if (cur_pq == "")
|
||||
if (ent == NULL)
|
||||
return false;
|
||||
|
||||
it = ent->values.find(track->id);
|
||||
return it != ent->values.end();
|
||||
}
|
||||
|
||||
void playlist :: add(Track *track, const std::string &name)
|
||||
{
|
||||
if (!( (name == "Banned") || (name == "Favorites") ))
|
||||
return;
|
||||
|
||||
ids = get_tracks(cur_pq);
|
||||
for (it = ids.begin(); it != ids.end(); it++)
|
||||
playlist_pq.add(tagdb :: lookup(*it));
|
||||
if (!has(track, name)) {
|
||||
playlist_db.insert(name, track->id);
|
||||
if (cur_plist == name)
|
||||
playlist_q.add(track);
|
||||
}
|
||||
}
|
||||
|
||||
void playlist :: add(const std::string &name, unsigned int track_id)
|
||||
void playlist :: del(Track *track, const std::string &name)
|
||||
{
|
||||
if ((name == "Banned") || (name == "Favorites")) {
|
||||
playlist_db.insert(name, track_id);
|
||||
playlist_db.save();
|
||||
if (name == cur_pq)
|
||||
playlist_pq.add(tagdb :: lookup(track_id));
|
||||
if (name == "Banned")
|
||||
get_callbacks()->on_playlist_ban(track_id);
|
||||
} else
|
||||
throw -E_EXIST;
|
||||
}
|
||||
|
||||
void playlist :: del(const std::string &name, unsigned int track_id)
|
||||
{
|
||||
if ((name == "Banned") || (name == "Favorites")) {
|
||||
playlist_db.remove(name, track_id);
|
||||
playlist_db.save();
|
||||
if (name == cur_pq)
|
||||
playlist_pq.del(tagdb :: lookup(track_id));
|
||||
if (name == "Banned")
|
||||
get_callbacks()->on_playlist_unban(track_id);
|
||||
} else
|
||||
throw -E_EXIST;
|
||||
playlist_db.remove(name, track->id);
|
||||
if (cur_plist == name)
|
||||
playlist_q.del(track);
|
||||
}
|
||||
|
||||
void playlist :: select(const std::string &name)
|
||||
{
|
||||
std::set<unsigned int> ids = get_tracks(name);
|
||||
std::set<unsigned int>::iterator it;
|
||||
IndexEntry *ent;
|
||||
|
||||
while (playlist_pq.size() > 0)
|
||||
playlist_pq.del((unsigned)0);
|
||||
if (cur_plist == name)
|
||||
return;
|
||||
|
||||
for (it = ids.begin(); it != ids.end(); it++)
|
||||
playlist_pq.add(tagdb :: lookup(*it));
|
||||
cur_pq = name;
|
||||
ent = playlist_db.find(name);
|
||||
if (ent == NULL)
|
||||
return;
|
||||
|
||||
playlist_q.fill(ent);
|
||||
cur_plist = name;
|
||||
}
|
||||
|
||||
const std::set<unsigned int> &playlist :: get_tracks(const std::string &name)
|
||||
IndexEntry *playlist :: get_tracks(const std::string &name)
|
||||
{
|
||||
if ((name == "Banned") || (name == "Favorites")) {
|
||||
IndexEntry *it = playlist_db.find(name);
|
||||
if (it != NULL)
|
||||
return it->values;
|
||||
return empty_set;
|
||||
}
|
||||
throw -E_EXIST;
|
||||
return playlist_db.find(name);
|
||||
}
|
||||
|
||||
Queue *playlist :: get_pq()
|
||||
Queue *playlist :: get_queue()
|
||||
{
|
||||
return &playlist_pq;
|
||||
return &playlist_q;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TEST
|
||||
void playlist :: clear()
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_TEST */
|
||||
|
|
|
@ -7,3 +7,4 @@ idle
|
|||
tags
|
||||
random
|
||||
queue
|
||||
playlist
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
0
|
||||
2
|
||||
1 Banned
|
||||
4 0 1 2 3
|
||||
1 Favorites
|
||||
8 16 17 18 19 20 21 22 23
|
|
@ -18,6 +18,7 @@ tests = [
|
|||
("tags.cpp", True, [], [ "taglib" ]),
|
||||
("random.cpp", False, [ "random.cpp" ], []),
|
||||
("queue.cpp", True, [ "callback.cpp", "random.cpp" ], []),
|
||||
("playlist.cpp", True, [], []),
|
||||
|
||||
]
|
||||
|
||||
|
@ -65,8 +66,8 @@ for src, lib, extra, pkgs in tests:
|
|||
name = "%s" % src.rsplit(".")[0]
|
||||
|
||||
if lib == True:
|
||||
lib_files += [ src ]
|
||||
extra = lib_files + extra
|
||||
lib_files += [ src ] + extra
|
||||
extra = lib_files
|
||||
|
||||
for p in pkgs:
|
||||
env.UsePackage(p)
|
||||
|
@ -81,4 +82,4 @@ ignore.close();
|
|||
|
||||
Return("res")
|
||||
|
||||
##scripts = [ "playlist", "library", "deck", "audio", "gui" ]
|
||||
##scripts = [ "library", "deck", "audio", "gui" ]
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <playlist.h>
|
||||
#include "test.h"
|
||||
|
||||
static IndexEntry *IDX_NULL = NULL;
|
||||
static Queue *Q_NULL = NULL;
|
||||
|
||||
static void test_init()
|
||||
{
|
||||
IndexEntry *ent;
|
||||
Queue *q = playlist :: get_queue();
|
||||
|
||||
test_not_equal(q, Q_NULL);
|
||||
test_equal(q->has_flag(Q_ENABLED), true);
|
||||
test_equal(q->has_flag(Q_REPEAT), true);
|
||||
test_equal(q->has_flag(Q_NO_SORT), true);
|
||||
|
||||
tagdb :: init();
|
||||
playlist :: init();
|
||||
|
||||
ent = playlist :: get_tracks("Banned");
|
||||
test_equal(ent->values.size(), (size_t)4);
|
||||
ent = playlist :: get_tracks("Favorites");
|
||||
test_equal(ent->values.size(), (size_t)8);
|
||||
ent = playlist :: get_tracks("No Such Playlist");
|
||||
test_equal(ent, IDX_NULL);
|
||||
}
|
||||
|
||||
static void test_queue()
|
||||
{
|
||||
Queue *q = playlist :: get_queue();
|
||||
|
||||
playlist :: select("Banned");
|
||||
test_equal(q->size(), (unsigned)4);
|
||||
|
||||
playlist :: select("Favorites");
|
||||
test_equal(q->size(), (unsigned)8);
|
||||
}
|
||||
|
||||
static void test_add()
|
||||
{
|
||||
IndexEntry *ent;
|
||||
Queue *q = playlist :: get_queue();
|
||||
|
||||
playlist :: add(tagdb :: lookup(5), "Banned");
|
||||
ent = playlist :: get_tracks("Banned");
|
||||
test_equal(ent->values.size(), (size_t)5);
|
||||
test_equal(q->size(), (unsigned)8);
|
||||
|
||||
playlist :: add(tagdb :: lookup(16), "Favorites");
|
||||
playlist :: add(tagdb :: lookup(5), "Favorites");
|
||||
ent = playlist :: get_tracks("Favorites");
|
||||
test_equal(ent->values.size(), (size_t)9);
|
||||
test_equal(q->size(), (unsigned)9);
|
||||
|
||||
playlist :: add(tagdb :: lookup(6), "No Playlist");
|
||||
test_equal(playlist :: get_tracks("No Playlist"), IDX_NULL);
|
||||
}
|
||||
|
||||
static void test_delete()
|
||||
{
|
||||
IndexEntry *ent;
|
||||
Queue *q = playlist :: get_queue();
|
||||
|
||||
playlist :: del(tagdb :: lookup(5), "Banned");
|
||||
ent = playlist :: get_tracks("Banned");
|
||||
test_equal(ent->values.size(), (size_t)4);
|
||||
test_equal(q->size(), (unsigned)9);
|
||||
|
||||
playlist :: del(tagdb :: lookup(5), "Favorites");
|
||||
ent = playlist :: get_tracks("Favorites");
|
||||
test_equal(ent->values.size(), (size_t)8);
|
||||
test_equal(q->size(), (unsigned)8);
|
||||
|
||||
playlist :: del(tagdb :: lookup(6), "No Playlist");
|
||||
test_equal(playlist :: get_tracks("No Playlist"), IDX_NULL);
|
||||
}
|
||||
|
||||
static void test_has()
|
||||
{
|
||||
test :: begin();
|
||||
for (unsigned int i = 0; i < 24; i++) {
|
||||
Track *track = tagdb :: lookup(i);
|
||||
if (i <= 3)
|
||||
check_equal(playlist :: has(track, "Banned"), true);
|
||||
else
|
||||
check_equal(playlist :: has(track, "Banned"), false);
|
||||
}
|
||||
test :: success();
|
||||
|
||||
test :: begin();
|
||||
for (unsigned int i = 0; i < 24; i++) {
|
||||
Track *track = tagdb :: lookup(i);
|
||||
if (i >= 16)
|
||||
check_equal(playlist :: has(track, "Favorites"), true);
|
||||
else
|
||||
check_equal(playlist :: has(track, "Favorites"), false);
|
||||
}
|
||||
test :: success();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test :: cp_playlist();
|
||||
|
||||
run_test("Playlist Initialization Test", test_init);
|
||||
run_test("Playlist Queue Test", test_queue);
|
||||
run_test("Playlist Add Test", test_add);
|
||||
run_test("Playlist Delete Test", test_delete);
|
||||
run_test("Playlist Has Test", test_has);
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
Import("Test", "CONFIG")
|
||||
|
||||
CONFIG.PLAYLIST = True
|
||||
|
||||
Test("playlist", "playlist.cpp")
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <error.h>
|
||||
#include <playlist.h>
|
||||
#include <print.h>
|
||||
|
||||
|
||||
void list_tracks(const std::string &name)
|
||||
{
|
||||
std::set<unsigned int> tracks = playlist :: get_tracks(name);
|
||||
std::set<unsigned int>::iterator it;
|
||||
|
||||
print("Playlist \"%s\": ", name.c_str());
|
||||
for (it = tracks.begin(); it != tracks.end(); it++) {
|
||||
if (it != tracks.begin())
|
||||
print(", ");
|
||||
print("%u", *it);
|
||||
}
|
||||
|
||||
print("\n");
|
||||
}
|
||||
|
||||
void check_error(int expected, int error)
|
||||
{
|
||||
if (expected != error)
|
||||
print("Exception error: expected %d actual %d", expected, error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add songs to different playlists
|
||||
*/
|
||||
void test_0()
|
||||
{
|
||||
for (unsigned int i = 0; i < 128; i++) {
|
||||
switch (i % 3) {
|
||||
case 0:
|
||||
playlist :: add("Banned", i);
|
||||
break;
|
||||
case 1:
|
||||
playlist :: add("Favorites", i);
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
playlist :: add("No Such Playlist", i);
|
||||
} catch (int error) {
|
||||
check_error(-E_EXIST, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find tracks in a playlist
|
||||
*/
|
||||
void test_1()
|
||||
{
|
||||
list_tracks("Banned");
|
||||
list_tracks("Favorites");
|
||||
|
||||
try {
|
||||
list_tracks("No Such Playlist");
|
||||
} catch (int error) {
|
||||
check_error(-E_EXIST, error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete tracks from a playlist
|
||||
*/
|
||||
void test_2()
|
||||
{
|
||||
print("\n");
|
||||
for (unsigned int i = 0; i < 30; i+=3)
|
||||
playlist :: del("Banned", i);
|
||||
list_tracks("Banned");
|
||||
|
||||
try {
|
||||
playlist :: del("No Such Playlist", 2);
|
||||
} catch (int error) {
|
||||
check_error(-E_EXIST, error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check persistence of playlists
|
||||
*/
|
||||
void test_3()
|
||||
{
|
||||
print("\n");
|
||||
|
||||
playlist :: clear();
|
||||
playlist :: init();
|
||||
|
||||
list_tracks("Banned");
|
||||
list_tracks("Favorites");
|
||||
|
||||
try {
|
||||
list_tracks("No Schu Playlist");
|
||||
} catch (int error) {
|
||||
check_error(-E_EXIST, error);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_0();
|
||||
test_1();
|
||||
test_2();
|
||||
test_3();
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
Playlist "Banned": 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126
|
||||
Playlist "Favorites": 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127
|
||||
|
||||
Playlist "Banned": 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126
|
||||
|
||||
Playlist "Banned": 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126
|
||||
Playlist "Favorites": 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127
|
|
@ -124,6 +124,13 @@ namespace test
|
|||
std::string cmd = "cp -r tests/Library/* " + data_dir();
|
||||
system(cmd.c_str());
|
||||
}
|
||||
|
||||
void cp_playlist()
|
||||
{
|
||||
cp_library();
|
||||
std::string cmd = "cp -r tests/Playlist/* " + data_dir();
|
||||
system(cmd.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#define run_test(name, func, ...) \
|
||||
|
|
Loading…
Reference in New Issue