playlist: Implement reachitecting of playlists
I changed the two playlists that are supported, added in exception handling, and removed the list() function since I will always know the names of playlists. I also rename everything to "playlist" from "group". Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
parent
914473e10a
commit
114c22bb12
20
config
20
config
|
@ -34,16 +34,16 @@ class Config:
|
|||
if self.TEST: env.Append( CCFLAGS = [ "-DCONFIG_TEST" ])
|
||||
|
||||
def reset(self, TEST = False):
|
||||
self.AUDIO = False
|
||||
self.DATABASE = False
|
||||
self.DECK = False
|
||||
self.FILE = False
|
||||
self.FILTER = False
|
||||
self.GROUP = False
|
||||
self.IDLE = False
|
||||
self.LIBRARY = False
|
||||
self.PLAYLIST = False
|
||||
self.TEST = TEST
|
||||
self.AUDIO = False
|
||||
self.DATABASE = False
|
||||
self.DECK = False
|
||||
self.FILE = False
|
||||
self.FILTER = False
|
||||
self.IDLE = False
|
||||
self.LIBRARY = False
|
||||
self.PLAYLIST = False
|
||||
self.PLAYQUEUE = False
|
||||
self.TEST = TEST
|
||||
self.reconfigure()
|
||||
|
||||
CONFIG = Config()
|
||||
|
|
33
design.txt
33
design.txt
|
@ -496,9 +496,9 @@ Idle queue: (lib/idle.cpp)
|
|||
|
||||
|
||||
Playlists: (lib/playlist.cpp)
|
||||
Playlists are going to be a new feature in Ocarina 6 and can compare
|
||||
directly to Gmail-style labels. Ocarina 6.0 will support two different
|
||||
playlists that the user can add songs to: banned and favorites.
|
||||
Playlists are a new feature in Ocarina 6 and are modeled after Gmail
|
||||
labels. Ocarina 6.0 will support two different playlists that the
|
||||
user can add tracks to: banned and favorites.
|
||||
|
||||
Future releases will add support for more playlists.
|
||||
|
||||
|
@ -508,24 +508,35 @@ Playlists: (lib/playlist.cpp)
|
|||
- 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 playlist when they
|
||||
are banned and added back to the playlist when they are
|
||||
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);
|
||||
playlist_idx.insert(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);
|
||||
playlist_idx.delete(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.
|
||||
|
||||
void void playlist :: list(list<string> &);
|
||||
return playlist_idx.keys();
|
||||
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 :: get_tracks(name);
|
||||
return playlist_idx[name]
|
||||
void playlist :: clear();
|
||||
This function only exists if CONFIG_TEST is enabled. Clear
|
||||
(reset) the playlist database.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
database
|
||||
|
||||
Playlists: (lib/playlist.cpp)
|
||||
Playlists are going to be a new feature in Ocarina 6 and can compare
|
||||
directly to Gmail-style labels. Ocarina 6.0 will support two different
|
||||
playlists that the user can add songs to: banned and favorites.
|
||||
Playlists are a new feature in Ocarina 6 and are modeled after Gmail
|
||||
labels. Ocarina 6.0 will support two different playlists that the
|
||||
user can add tracks to: banned and favorites.
|
||||
|
||||
Future releases will add support for more playlists.
|
||||
|
||||
|
@ -22,21 +22,32 @@ Playlists: (lib/playlist.cpp)
|
|||
- 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 playlist when they
|
||||
are banned and added back to the playlist when they are
|
||||
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);
|
||||
playlist_idx.insert(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);
|
||||
playlist_idx.delete(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.
|
||||
|
||||
void void playlist :: list(list<string> &);
|
||||
return playlist_idx.keys();
|
||||
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 :: get_tracks(name);
|
||||
return playlist_idx[name]
|
||||
void playlist :: clear();
|
||||
This function only exists if CONFIG_TEST is enabled. Clear
|
||||
(reset) the playlist database.
|
||||
|
|
|
@ -82,7 +82,7 @@ static inline void index_insert(Database<IndexEntry> &db,
|
|||
{
|
||||
try {
|
||||
db.find(key).insert(val);
|
||||
} catch (...) {
|
||||
} catch (int error) {
|
||||
db.insert(IndexEntry(key, val));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#ifndef OCARINA_GROUP_H
|
||||
#define OCARINA_GROUP_H
|
||||
#ifndef OCARINA_PLAYLIST_H
|
||||
#define OCARINA_PLAYLIST_H
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace group
|
||||
namespace playlist
|
||||
{
|
||||
|
||||
void init();
|
||||
void add(const std::string &, unsigned int);
|
||||
void del(const std::string &, unsigned int);
|
||||
void list(std::list<std::string> &);
|
||||
const std::set<unsigned int> &get_tracks(const std::string &);
|
||||
|
||||
#ifdef CONFIG_TEST
|
||||
void clear();
|
||||
#endif /* CONFIG_TEST */
|
||||
};
|
||||
|
||||
#endif /* OCARINA_GROUP_H */
|
||||
#endif /* OCARINA_PLAYLIST_H */
|
||||
|
|
|
@ -20,9 +20,9 @@ modules = {
|
|||
"DECK" : Module("deck.cpp", depends = [ "PLAYQUEUE" ]),
|
||||
"FILE" : Module("file.cpp", package = "glib-2.0"),
|
||||
"FILTER" : Module("filter.cpp", depends = [ "DATABASE" ]),
|
||||
"PLAYLIST" : Module("playlist.cpp", depends = [ "DATABASE" ]),
|
||||
"IDLE" : Module("idle.cpp"),
|
||||
"LIBRARY" : Module("library.cpp", package = "taglib", depends = [ "DATABASE", "IDLE" ]),
|
||||
"PLAYLIST" : Module("playlist.cpp", depends = [ "DATABASE" ]),
|
||||
"PLAYQUEUE" : Module("playlist.cpp", depends = [ "FILE" ]),
|
||||
|
||||
###########################
|
||||
|
|
|
@ -2,45 +2,50 @@
|
|||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <database.h>
|
||||
#include <group.h>
|
||||
#include <error.h>
|
||||
#include <playlist.h>
|
||||
|
||||
static std::set<unsigned int> empty_set;
|
||||
Database<IndexEntry, const std::string> group_index("");
|
||||
static Database<IndexEntry> playlist_db("playlist.db");
|
||||
|
||||
void group :: add(const std::string &name, unsigned int track_id)
|
||||
void playlist :: init()
|
||||
{
|
||||
if ((name == "All Music") || (name == "Library") || (name == "Banned")) {
|
||||
playlist_db.load();
|
||||
}
|
||||
|
||||
void playlist :: add(const std::string &name, unsigned int track_id)
|
||||
{
|
||||
if ((name == "Banned") || (name == "Favorites")) {
|
||||
index_insert(playlist_db, name, track_id);
|
||||
playlist_db.save();
|
||||
} else
|
||||
throw -EEXIST;
|
||||
}
|
||||
|
||||
void playlist :: del(const std::string &name, unsigned int track_id)
|
||||
{
|
||||
if ((name == "Banned") || (name == "Favorites")) {
|
||||
index_remove(playlist_db, name, track_id);
|
||||
playlist_db.save();
|
||||
} else
|
||||
throw -EEXIST;
|
||||
}
|
||||
|
||||
const std::set<unsigned int> &playlist :: get_tracks(const std::string &name)
|
||||
{
|
||||
if ((name == "Banned") || (name == "Favorites")) {
|
||||
try {
|
||||
index_insert(group_index, name, track_id);
|
||||
} catch (...) {
|
||||
return;
|
||||
return playlist_db.find(name).values;
|
||||
} catch (int error) {
|
||||
return empty_set;
|
||||
}
|
||||
}
|
||||
throw -EEXIST;
|
||||
}
|
||||
|
||||
void group :: del(const std::string &name, unsigned int track_id)
|
||||
#ifdef CONFIG_TEST
|
||||
void playlist :: clear()
|
||||
{
|
||||
if ((name == "All Music") || (name == "Library") || (name == "Banned")) {
|
||||
try {
|
||||
index_remove(group_index, name, track_id);
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void group :: list(std::list<std::string> &res)
|
||||
{
|
||||
res.push_back("All Music");
|
||||
res.push_back("Library");
|
||||
res.push_back("Banned");
|
||||
}
|
||||
|
||||
const std::set<unsigned int> &group :: get_tracks(const std::string &name)
|
||||
{
|
||||
try {
|
||||
return group_index.find(name).values;
|
||||
} catch (...) {
|
||||
return empty_set;
|
||||
}
|
||||
playlist_db.clear();
|
||||
}
|
||||
#endif /* CONFIG_TEST */
|
||||
|
|
|
@ -57,8 +57,9 @@ rm_test_dir(xdg.BaseDirectory.xdg_data_home);
|
|||
#
|
||||
# Read SConscript files
|
||||
#
|
||||
scripts = [ "audio", "database", "deck", "file", "filter", "group", "idle",
|
||||
"index", "library", "playlist", "print" ]
|
||||
#scripts = [ "audio", "database", "deck", "file", "filter", "group", "idle",
|
||||
# "index", "library", "playlist", "print" ]
|
||||
scripts = [ "print", "file", "database", "index", "filter", "idle", "playlist" ]
|
||||
for s in scripts:
|
||||
CONFIG.reset(TEST = True)
|
||||
SConscript("%s/Sconscript" % s)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python
|
||||
Import("Test", "CONFIG")
|
||||
|
||||
CONFIG.GROUP = True
|
||||
CONFIG.PLAYLIST = True
|
||||
|
||||
Test("group", "group.cpp")
|
||||
Test("playlist", "playlist.cpp")
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <group.h>
|
||||
#include <print.h>
|
||||
|
||||
|
||||
void list_tracks(const std::string &name)
|
||||
{
|
||||
std::set<unsigned int> tracks = group :: get_tracks(name);
|
||||
std::set<unsigned int>::iterator it;
|
||||
|
||||
print("Group \"%s\": ", name.c_str());
|
||||
for (it = tracks.begin(); it != tracks.end(); it++) {
|
||||
if (it != tracks.begin())
|
||||
print(", ");
|
||||
print("%u", *it);
|
||||
}
|
||||
|
||||
print("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Add songs to different groups
|
||||
*/
|
||||
void test_0()
|
||||
{
|
||||
for (unsigned int i = 0; i < 128; i++) {
|
||||
group :: add("All Music", i);
|
||||
if (i % 3 == 0)
|
||||
group :: add("Banned", i);
|
||||
else
|
||||
group :: add("Library", i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find group names
|
||||
*/
|
||||
void test_1()
|
||||
{
|
||||
std::list<std::string> groups;
|
||||
std::list<std::string>::iterator it;
|
||||
|
||||
group :: list(groups);
|
||||
for (it = groups.begin(); it != groups.end(); it++)
|
||||
print("Found group: %s\n", it->c_str());
|
||||
print("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Find tracks in a group
|
||||
*/
|
||||
void test_2()
|
||||
{
|
||||
list_tracks("All Music");
|
||||
list_tracks("Library");
|
||||
list_tracks("Banned");
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete tracks from a group
|
||||
*/
|
||||
void test_3()
|
||||
{
|
||||
print("\n");
|
||||
for (unsigned int i = 0; i < 30; i+=3)
|
||||
group :: del("Banned", i);
|
||||
list_tracks("Banned");
|
||||
}
|
||||
|
||||
/*
|
||||
* Do stuff with groups that don't exist
|
||||
*/
|
||||
void test_4()
|
||||
{
|
||||
print("\n");
|
||||
for (unsigned int i = 0; i < 10; i++)
|
||||
group :: add("No Group", i);
|
||||
|
||||
list_tracks("No Group");
|
||||
|
||||
for (unsigned int i = 0; i < 10; i+=2)
|
||||
group :: del("No Group", i);
|
||||
|
||||
list_tracks("No Group");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_0();
|
||||
test_1();
|
||||
test_2();
|
||||
test_3();
|
||||
test_4();
|
||||
return 0;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
Found group: All Music
|
||||
Found group: Library
|
||||
Found group: Banned
|
||||
|
||||
Group "All Music": 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127
|
||||
Group "Library": 1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, 113, 115, 116, 118, 119, 121, 122, 124, 125, 127
|
||||
Group "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
|
||||
|
||||
Group "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
|
||||
|
||||
Group "No Group":
|
||||
Group "No Group":
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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(-EEXIST, 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(-EEXIST, 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(-EEXIST, 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(-EEXIST, error);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_0();
|
||||
test_1();
|
||||
test_2();
|
||||
test_3();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
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
|
Loading…
Reference in New Issue