design: Split playlist design

To keep the design readable, I split the playlist class (playlist.txt)
from the playlist deck (deck.txt).

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2013-12-22 17:22:40 -05:00 committed by Anna Schumaker
parent a3cf5daa18
commit 9aa2bc7df1
4 changed files with 174 additions and 253 deletions

View File

@ -34,6 +34,7 @@ Files:
audio.h
database.h
database.hpp
deck.h
file.h
filter.h
groups.h
@ -46,6 +47,7 @@ Files:
ocarina/lib/
audio.cpp
database.cpp
deck.cpp
file.cpp
filter.cpp
groups.cpp
@ -239,7 +241,7 @@ Database: (lib/database.cpp)
class IndexEntry : public DatabaseEntry {
public:
string key;
vector<unsigned int> values;
set<unsigned int> values;
const std::string &primary_key();
void write(File &);
@ -264,6 +266,7 @@ Database: (lib/database.cpp)
void save();
void clear();
void print();
void print_keys();
unsigned int insert(T);
void delete(unsigned int);
@ -273,7 +276,8 @@ Database: (lib/database.cpp)
unsigned int first();
unsigned int last();
unsigned int next(unsigned int &);
unsigned int find(const std::string &);
unsigned int find_index(const std::string &);
T &find(const std::string &);
T &operator[](unsigned int);
};
@ -303,6 +307,10 @@ Database: (lib/database.cpp)
Following a similar format for writing to disk, print the
database to the console in a human-readable format.
void Database :: print_keys()
This function exists only if CONFIG_DEBUG is enabled.
Print out the collected primary keys in the database.
template <class T>
unsigned int Database :: insert(T &);
Adds a new item to the db and marks it as valid. A reverse
@ -642,162 +650,115 @@ endif /* CONFIG_DEBUG */
Playlist: (lib/playlist.cpp)
Playlists are a list of songs that the user has configured to play. I
will create a pool of playlists that will be filled by user actions.
Playlists will be put on a "deck" that is used to give an order to the
next songs played. When deck :: next() is called, find the first
playlist with PL_ENABLED set and call that playlists next() function.
When a playlist is empty, remove it from the deck.
Playlists are a list of songs that the user has requested to play.
- Flags:
enum playlist_flags {
PL_ENABLED (1 << 0),
PL_RANDOM (1 << 1),
PL_DRAIN (1 << 2),
PL_LOCKED (1 << 2),
};
- Playlist:
class Playlist : public Database {
class Playlist {
private:
database<track_id> tracks; /* Keyed on track id */
vector<track_id> tracks;
unsigned int cur;
unsigned int flags;
public:
Playlist();
void add(vector<track_id> &);
void del(vector<track_id> &);
Playlist(flags);
unsigned int add(track_id);
void del(playlist_id);
void set_flag(playlist_flags);
void unset_flag(playlist_flags);
const unsigned int get_flags();
unsigned int size()
unsigned int size();
File &operator<<(File &);
File &operator>>(File &);
void write(File &);
void read(File &);
void sort();
void next();
unsigned int next();
}
File << flags << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N];
- API
Playlist :: Playlist(unsigned int flags);
Create a new playlist with the appropriate flags set.
unsigned int Playlist :: add(unsigned int track_id);
Add a new track to the tracks vector and return the index.
void del(unsigned int playlist_id);
Erase tracks[playlist_id] from the tracks vector.
void set_flag(playlist_flags flag);
void unset_flag(playlist_flags flag);
Set or unset the given flag.
const unsigned int get_flags();
Return the currently enabled flags.
unsigned int size();
Return tracks.size();
void write(File &);
void read(File &);
Read or write the playlist to the file.
void sort();
Sort a playlist in Artist -> Year -> Track number order.
unsigned int next();
if (flags & PL_RANDOM):
cur += rand() % tracks.size();
else:
cur += 1;
if (cur > = tracks.size())
cur -= tracks.size();
track = tracks[cur];
if (!(flags & PL_LOCKED)):
tracks.erase(cur);
return track;
Deck: (lib/deck.cpp)
The playlist deck is used to hold the temporary playlists created by
the user.
- Deck:
list<Playlist> deck;
unsigned int current_track;
File << current_track << deck.size() << endl;
File << deck[0] << endl;
File << deck[1] << endl;
- Deck:
list<Playlist> deck;
File << deck[0] << endl;
File << deck[1] << endl;
File << deck[N] << endl;
- API
deck :: init();
Read in the playlist file
void deck :: init();
Read in the playlist file.
deck :: new();
Adds a new playlist to the deck
unsigned int deck :: new();
Adds a new playlist to the end of the deck and returns its id.
The id is only valid until the deck is changed in some way.
deck :: rm(N)
Removes playlist N from the deck
void deck :: rm(N);
Remove playlist N from the deck.
Playlist *deck :: get(N)
Return playlist N from the deck
Playlist *deck :: get(N);
Return playlist N from the deck.
deck :: next()
Play the next song from the deck
unsigned int deck :: next();
Iterate through the deck until you find a playlist with the
flag PL_ENABLED set. Call next() on this playlist and return
the result.
- TODO <<<<<
What if each playlist has its own playlist_id for tracks? This would
allow for simpler removals, since I won't need to search for a track id.
I can easily create a function for mapping a list of playlist_ids to
track_ids...
- API
void playlist :: init();
Read in the playlist file
* Playlist *playlist :: add();
Add a new playlist to the deck, return the created playlist
to the caller.
* void playlist :: remove(Playlist *);
Remove the provided playlist from the deck. The pointer will
be unusable after calling this function.
void playlist :: move(Playlist *, unsigned int);
Move the playlist to the provided location in the deck.
* trackid_t playlist :: next()
Return the next trackid from the top playlist on the playlist
deck (id = deck[0].next()). If the top playlist is now empty,
remove it.
void playlist :: prev()
Keep a playlist :: Playlist recent(PL_ENABLED)
Whenever next() is called, add the returned track to the front
of this playlist, reset recent.cur to 0.
When prev() is called, return recent.next();
trackid_t playlist :: Playlist :: next()
If PL_RANDOM is set:
Randomly pick a value between 1 and size(). Increment
the cur pointer by this value, taking into account any
roll over.
Else:
cur += 1, if cur == size(): cur = 0;
if PL_DRAIN is set:
Remove the trackid pointed to by cur from the list and
return its value.
return list[cur]
void playlist :: Playlist :: set_flag(flag);
Set the user-requested flag
void playlist :: Playlist :: clear_flag(flag);
Clear the user-requested flag
const unsigned int playlist :: Playlist :: get_flags();
return flags
bool playlist :: Playlist :: play_row(unsigned int id);
Call this fuction to play a song from the playlist. id matches
up to the index in the playlist to play. Return true if the
selected row should be removed from the playlist, false
otherwise.
string playlist :: Playlist :: get_length()
Calculate the length of the playlist and return a string
in mm:ss format with the results.
unsigned int playlist :: Playlist :: size()
Return the number of tracks in your playlist
unsigned int playlist :: Playlist :: current_index()
Return the current index into the playlist
unsigned int playlist :: Playlist :: filter(string text)
Set the current filter text
unsigned int playlist :: Playlist :: is_visible(id)
Check if the playlist id is visible based on playlis text
* unsigned int playlist :: Playlist :: add_track(trackid_t)
Add a new track to the playlist
* unsigned int playlist :: Playlist :: rm_track(playlistid_t)
Remove a row from the playlist
If the playlist is empty after calling next(), remove it from
the deck.

View File

@ -5,7 +5,7 @@
audio.cpp
== Depends ==
playlist library
deck library
Audio: (lib/audio.cpp)
This file will introduce an "audio" namespace containing all of the

44
design/deck.txt Normal file
View File

@ -0,0 +1,44 @@
== Files ==
ocarina/include/
deck.h
ocarina/lib/
deck.cpp
$HOME/.ocarina{-debug}/
playlists.lst
== Depends ==
playlist
Deck: (lib/deck.cpp)
The playlist deck is used to hold the temporary playlists created by
the user.
- Deck:
list<Playlist> deck;
unsigned int current_track;
File << current_track << deck.size() << endl;
File << deck[0] << endl;
File << deck[N] << endl;
- API
void deck :: init();
Read in the playlist file.
unsigned int deck :: new();
Adds a new playlist to the end of the deck and returns its id.
The id is only valid until the deck is changed in some way.
void deck :: rm(N);
Remove playlist N from the deck.
Playlist *deck :: get(N);
Return playlist N from the deck.
unsigned int deck :: next();
Iterate through the deck until you find a playlist with the
flag PL_ENABLED set. Call next() on this playlist and return
the result.
If the playlist is empty after calling next(), remove it from
the deck.

View File

@ -3,166 +3,82 @@
playlist.h
ocarina/lib/
playlist.cpp
$HOME/.ocarina{-debug}/
playlists.lst
== Depends ==
database
file
Playlist: (lib/playlist.cpp)
Playlists are a list of songs that the user has configured to play. I
will create a pool of playlists that will be filled by user actions.
Playlists will be put on a "deck" that is used to give an order to the
next songs played. When deck :: next() is called, find the first
playlist with PL_ENABLED set and call that playlists next() function.
When a playlist is empty, remove it from the deck.
Playlists are a list of songs that the user has requested to play.
- Flags:
enum playlist_flags {
PL_ENABLED (1 << 0),
PL_RANDOM (1 << 1),
PL_DRAIN (1 << 2),
PL_LOCKED (1 << 2),
};
- Playlist:
class Playlist : public Database {
class Playlist {
private:
database<track_id> tracks; /* Keyed on track id */
vector<track_id> tracks;
unsigned int cur;
unsigned int flags;
public:
Playlist();
void add(vector<track_id> &);
void del(vector<track_id> &);
void set_flag(playlist_flags);
const unsigned int get_flags();
unsigned int size()
Playlist(flags);
unsigned int add(track_id);
void del(playlist_id);
unsigned int size();
File &operator<<(File &);
File &operator>>(File &);
void set_flag(playlist_flags);
void unset_flag(playlist_flags);
const unsigned int get_flags();
void write(File &);
void read(File &);
void sort();
void next();
unsigned int next();
}
File << flags << tracks.size() << tracks[0] << tracks[1] << ... << tracks[N];
- Deck:
list<Playlist> deck;
unsigned int current_track;
File << current_track << deck.size() << endl;
File << deck[0] << endl;
File << deck[1] << endl;
- Deck:
list<Playlist> deck;
File << deck[0] << endl;
File << deck[1] << endl;
File << deck[N] << endl;
- API
deck :: init();
Read in the playlist file
Playlist :: Playlist(unsigned int flags);
Create a new playlist with the appropriate flags set.
deck :: new();
Adds a new playlist to the deck
unsigned int Playlist :: add(unsigned int track_id);
Add a new track to the tracks vector and return the index.
deck :: rm(N)
Removes playlist N from the deck
void del(unsigned int playlist_id);
Erase tracks[playlist_id] from the tracks vector.
Playlist *deck :: get(N)
Return playlist N from the deck
void set_flag(playlist_flags flag);
void unset_flag(playlist_flags flag);
Set or unset the given flag.
deck :: next()
Play the next song from the deck
const unsigned int get_flags();
Return the currently enabled flags.
- TODO <<<<<
What if each playlist has its own playlist_id for tracks? This would
allow for simpler removals, since I won't need to search for a track id.
I can easily create a function for mapping a list of playlist_ids to
track_ids...
unsigned int size();
Return tracks.size();
void write(File &);
void read(File &);
Read or write the playlist to the file.
void sort();
Sort a playlist in Artist -> Year -> Track number order.
unsigned int next();
if (flags & PL_RANDOM):
cur += rand() % tracks.size();
else:
cur += 1;
if (cur > = tracks.size())
cur -= tracks.size();
track = tracks[cur];
- API
void playlist :: init();
Read in the playlist file
* Playlist *playlist :: add();
Add a new playlist to the deck, return the created playlist
to the caller.
* void playlist :: remove(Playlist *);
Remove the provided playlist from the deck. The pointer will
be unusable after calling this function.
void playlist :: move(Playlist *, unsigned int);
Move the playlist to the provided location in the deck.
* trackid_t playlist :: next()
Return the next trackid from the top playlist on the playlist
deck (id = deck[0].next()). If the top playlist is now empty,
remove it.
void playlist :: prev()
Keep a playlist :: Playlist recent(PL_ENABLED)
Whenever next() is called, add the returned track to the front
of this playlist, reset recent.cur to 0.
When prev() is called, return recent.next();
trackid_t playlist :: Playlist :: next()
If PL_RANDOM is set:
Randomly pick a value between 1 and size(). Increment
the cur pointer by this value, taking into account any
roll over.
Else:
cur += 1, if cur == size(): cur = 0;
if PL_DRAIN is set:
Remove the trackid pointed to by cur from the list and
return its value.
return list[cur]
void playlist :: Playlist :: set_flag(flag);
Set the user-requested flag
void playlist :: Playlist :: clear_flag(flag);
Clear the user-requested flag
const unsigned int playlist :: Playlist :: get_flags();
return flags
bool playlist :: Playlist :: play_row(unsigned int id);
Call this fuction to play a song from the playlist. id matches
up to the index in the playlist to play. Return true if the
selected row should be removed from the playlist, false
otherwise.
string playlist :: Playlist :: get_length()
Calculate the length of the playlist and return a string
in mm:ss format with the results.
unsigned int playlist :: Playlist :: size()
Return the number of tracks in your playlist
unsigned int playlist :: Playlist :: current_index()
Return the current index into the playlist
unsigned int playlist :: Playlist :: filter(string text)
Set the current filter text
unsigned int playlist :: Playlist :: is_visible(id)
Check if the playlist id is visible based on playlis text
* unsigned int playlist :: Playlist :: add_track(trackid_t)
Add a new track to the playlist
* unsigned int playlist :: Playlist :: rm_track(playlistid_t)
Remove a row from the playlist
if (!(flags & PL_LOCKED)):
tracks.erase(cur);
return track;