From 9aa2bc7df135f7b96189b60734f6fdf0567f8164 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Sun, 22 Dec 2013 17:22:40 -0500 Subject: [PATCH] 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 --- design.txt | 207 ++++++++++++++++++-------------------------- design/audio.txt | 2 +- design/deck.txt | 44 ++++++++++ design/playlist.txt | 174 ++++++++++--------------------------- 4 files changed, 174 insertions(+), 253 deletions(-) create mode 100644 design/deck.txt diff --git a/design.txt b/design.txt index 281ebcd1..0835083d 100644 --- a/design.txt +++ b/design.txt @@ -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 values; + set 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 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 tracks; /* Keyed on track id */ + vector tracks; unsigned int cur; unsigned int flags; public: - Playlist(); - void add(vector &); - void del(vector &); + 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 deck; unsigned int current_track; File << current_track << deck.size() << endl; File << deck[0] << endl; - File << deck[1] << endl; - -- Deck: - list 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. diff --git a/design/audio.txt b/design/audio.txt index 979ab052..150fa080 100644 --- a/design/audio.txt +++ b/design/audio.txt @@ -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 diff --git a/design/deck.txt b/design/deck.txt new file mode 100644 index 00000000..f157ed9f --- /dev/null +++ b/design/deck.txt @@ -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 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. diff --git a/design/playlist.txt b/design/playlist.txt index 9c31c29d..fb8dab06 100644 --- a/design/playlist.txt +++ b/design/playlist.txt @@ -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 tracks; /* Keyed on track id */ + vector tracks; unsigned int cur; unsigned int flags; public: - Playlist(); - void add(vector &); - void del(vector &); - 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 deck; - unsigned int current_track; - - File << current_track << deck.size() << endl; - File << deck[0] << endl; - File << deck[1] << endl; - -- Deck: - list 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;