I only needed this to make the jump from Ocarina 5.10 -> Ocarina 6.0.
It's not needed anymore, now that 6.0 is out.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
This should offer a performance increase since the item to insert will
only be copied if it is not already in the database.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
Inserting into a vector can sometimes cause the entire vector to
reallocate itself. The insert() function returns a pointer to the
caller, so this reallocation could invalidate the returned pointer.
This is not what we want.
Instead, store pointers to the data in the vector. C++ provides a
default copy constructor that can be used to allocate a new item before
inserting. By doing it this way callers won't have to allocate memory
themselves. In addition, I will no longer need to keep a valid bit
since we can simply check for a NULL entry in the database.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
This gives me the item directly, which is usually what I want when I
call these functions. Save iterators for iterating.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
I properly initialize variables, and I created supporting databases that
will be used to look up artist, album, genre and library information.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
Rather than returning an index into the database, instead return an
iterator pointing at the item we just inserted.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
When items are deleted from a database we write out a line representing
"invalid entry". This patch changes the invalid entry line from "0 " to
"0"
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
I found that databases were always decrementing _size when remove() was
called. This patch fixes the bug by checking if the entry is valid
before removal.
Signed-off-by: Anna Schumaker <anna@ocarinaproject.net>
This will let me set up a Track class that has pointers to the
corresponding artist, album and genre information without needing to
know their IDs directly. Having this information available means I
won't need to keep a "join struct" when doing lookups - instead I can
return a pointer to a Track class that already knows everything.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I didn't have any changes to make to the IdleQueue itself, but I did
need to update the unit test and reword a few things in the design.
Signed-off-by: Anna Schuamker <schumaker.anna@gmail.com>
- filter :: add() now returns the lowercased text
- Don't cache lowercased strings
- Remove functions depending on CONFIG_TEST
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I updated the design and rewrote the unit tests. This creates something
more consistent with how I ended up using the index.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I add:
- Autosaving option
- Real iterators
- Better accessor functions
The new design and unit test also allows me to remove the 300,000+ line
"database.good" file that the old tests were based on.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Needing to use throw / catch was getting in the way. Instead, check for
a boolean return value.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I changed primary_key() into a function since it is only called once,
and there is no point in using more mmemory than I need to. I also
created a basic unit test for everything that database entries are
supposed to do.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This time I don't keep a global "sorting count". Instead, this count
belongs to individual tabs so flipping between them quickly could
display different sorting fields.
Signed-off-by: Anna Schumaker <schuamker.anna@gmail.com>
I'm taking a break from gui code to clean up the build system and update
my unit tests. This patch updates how code is built, and reworks my
"print" test to test version number instead.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I've been putting this off for a while since it seemed like a lot of
work. Time to get it done!
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This one is based on inheritance, and I think it will be the best way to
create several tab types that do things just slightly differently.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I need to create a FilterDesc struct with needed widgets and then
filtering can happen generically on all tabs!
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I'm creating as many "static tabs" as I can using GtkBuilder, and
splitting their code out of tabs.cpp. This should help to contain the
growth of this file and make all the code easier to work with.
This patch begins the redesign and adds beginning code for a new
collection tab.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I made a couple of templated functions to get widgets and objects out of
the Gtk::Builder easier.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Number keys to switch pages
- c, h, p, m to switch to collection, history, playlist and collection
manager tabs.
- Slash key to focus on the search entry
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This is called by the GUI to tell the playqueue that a track has been
selected. This gives the PQ a chance to (possibly) remove it.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I love tis feature, and I've been missing it the last few days of
Ocarina 6.0 preview testing.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Initialize stamp with a random integer (this is how a Gtk::ListStore
works)
- Increment the stamp in a way that it will never be 0 (AKA: invalid)
- iter_n_root_children() does not take any arguments, so fix up my
function.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
When a track finishes, I tell the library to update playcount. Then,
the library triggers a callback to the playqueue deck telling it to
update.
This patch also finds and prints the track that causes a gstreamer
error.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Reimplement binary search for neater code
- Flip sort order when resetting sort if the first field is the one we
are sorting by.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The history playqueue should never change sort order, so use this flag
to prevent user changes.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I set up a 3-second timeout to decrement the count. When the count is
at 0, I reset sorting on the playlist.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I don't have user-configurable sorting (yet), but for now I'm sorting by
Artist -> Year -> Track #.
I also fix a bug where the library wasn't lowercasing artist, album,
genere, and track fields when reading from file.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The history and collection playqueues are never saved to disk, so I only
care about saving when a flag is changed.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
When the count is changed or pausing finishes, I trigger this callback
to notify the UI. I also added in a line to enable pausing any time the
count is incremented.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I almost did this on the gui side, but then I remembered that this isn't
a trivial job. I chose to stick with my rule: "if something can be done
in the backend then it should be done in the backend"
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Only available when CONFIG_TESTING is enabled. Used to test clearing
the library and library playqueue for testing.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This prevents an error message (and possible corruption) by continuing
with the open() function even if the file doesn't exist.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I implemented an entire Gtk::TreeModel in this commit, plus some minor
supporting code in the library to look up playlist entries by index.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The signal connections for these features are really difficult to test
programmatically, but I can test the effects by calling each function
directly.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Gstreamer includes <errno.h>, which already defines several of these
symbols. I rename them to avoid namespace collisions. Perhaps a better
solution would be to use the errno.h definitions directly?
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This is used for the recently played playqueue to iterate backwards when
the previous() function is called.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I was using CONFIG_DEBUG for these, but they really should be under
CONFIG_TEST for use by the testing code ONLY.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This returns a pointer to the library :: Library structure requested.
The gui will use this to display information about each path.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I track the size of each library path for display purposes. I also had
to add in a check for if a new track already exists in the db before
tagging it so updating a library should be much faster now.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Combine Artist and Genre struct
- Add in exceptions, rather than boolean returns
- Update the library through idle tasks
I have not implemented importing Ocarina 5.11 libraries yet.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I do not make any of the library spec changes yet, instead I update the
backend code so it compiles and still works with the changes I have made
so far.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
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 function will convert the provided text to lowercase. This really
isn't a filter function, but the filter already implements a lowercase
cache that should be useful.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I had been returning success / failed boolean values for various
operations. I think it's better to throw an exception in these
"exceptional" circumstances since error values can give more information
about why a function failed.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This patch implements the pause-after-N-tracks feature. I also included
various improvements to the audio code.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Seek(), position() and duration() functions are implemented
- There are bugs in the test program :(
- Clean up next()
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The read and write functions will be called by a higher up layer, so I
need to open the file manually in the test.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I make sure to remove empty playlists from the deck and throw an error
if there are no playable tracks on the deck.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The file will be passed in by the deck layer, since it stores multiple
files. I just fake up a file in test_2() that is used for storing the
playlist.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I was using _size as an index into the database, but _size represents
the total number of valid rows and not the id of the new item. If a row
is deleted _size will decrease and the wrong entries will be marked
valid.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This patch updates the design so indexes are built upon databases using
a special IndexEntry. I also updated the tests/index/ test to match
the new system, but I have not updated filter or group tests yet.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I require entries to have a "primary key" that is stored in a map to
make it easy to find database rows by key.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
If the id is valid, I fill out a song structure and return true.
If the id is invalid, I return false.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This is each song's track number, play count, and anything else specific
to a single file. After updating, save all the changed databases.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Passing the TagLib :: Tag pointer is much easier and cuts down on extra
arguments to each constructor.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I don't build up a complete set of databases yet, but I do create the
Artist name database to use later.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Eventually these functions may have to become idle tasks, but for now I
write to disk whenever the library_db is changed and then read from disk
by calling the init() function.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I can add and remove root-level directories from the library database.
I do not save the database when modified, and I don't yet run an update
on all the files.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Check if we are finding the "last" iterator in an empty database
- Better print() descriptions
- Print test return codes that aren't 0 to help find segfaults
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
It doesn't make sense to need to set this value outside of the database
code like I had been doing. So when a new row is inserted mark it as
valid right away.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This function is used in debug mode to print the current status of the
index. I also created a print_keys() function to only list the keys.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Other tests may need to print out a database. To make this easier I've
added a print() function to the base database class. This function will
only exist when CONFIG.TEST == True, so don't use it outside of testing!
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I was using my own cpp file to remove old test data to start with a
clean slate. I've decided it's easier to just remove the files before
running tests if they exist.
I also use this patch to update the test design and add an idea for the
future.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The library will need databases that have unique values (such as the
artist or album tables). This patch adds support for that in my
existing database code.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
The idle queue is used to schedule tasks ... later. This code was
mostly adoted from a reference TDD experiment by Josh Larson
(themutatedshrimp@gmail.com). Thanks Josh!
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I only handle the "All Music", "Library" and "Banned" groups at the
moment but I'll eventually add in more features (in future versions).
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I have everything except for save() and load() written. My unittest is
fairly comprehensive and tests everything implemented so far, so with
any luck putting in save() and load() features will go quickly.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I had planned on using the stream operator for my database class but
this created some crazy compiler error that I was having difficulty
figuring out. I decided to take the easy route for now and instead
create read() and write() functions that do exactly the same thing.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
Items will be marked "invalid" rather than directly removed from the
database. This make it easier, since I won't need to reassign IDs to
every database item after the removed one.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
A database may have invalid rows. If this is the case, then the next()
function needs to return the id of the next valid row. I'm aware that
this could get horribly inefficient on large DBs with many invalid rows.
I don't expect people to delete large chunks of music all at once, but a
defragment tool is on my "todo" list for a future Ocarina version.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I've been excited about this! I think it'll be a better design than
what I had for Ocarina 5.x.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
I changed print to compile in the dprint() function when the testing
flag is enabled. This allows tests to have the same output regardless
of debugging status.
Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
- Inherit from fstream to gain access to << and >> operators.
- Make the file version accessable to the outside world.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- Support OPEN_READ and OPEN_WRITE
- Update the design to accomidate for error checking
- Add lib/test.cpp containing basic functions that can be used for
testing
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The class resolves the path to the ocarina directory based on the file
hint provided. NOTE: compile-debug.good and compile.good resolve paths
to my home directory. Other users will need to change the values for
the test to pass.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The class is in charge of resetting fields at will, and will be able to
maintain everything easier than if I were to do it by hand.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I was using a debug and a release environment for programs, that way
both versions of tests could be checked. Instead, it'll be simpler to
only use a single environment and then control debug information using
CONFIG_DEBUG.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I store release and debug options in a list so that env.Replace() can be
used to set, modify, and restore values.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I only have one application so there is no point in having a way to
create multiple application directories.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I was keeping a vector of objects, and then pass pointers to these
objects around everywhere. HOWEVER, when vectors are resized they
allocate new memory and copy things over invalidating iterators and
pointers to the original objects. This can cause memory corruption
issues when I try to use a pointer to an object that no longer exists.
The simple solution? Allocate tracks dynamically and then store the
pointer in the library path.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I want to remove the various idle task types that have built up and
replace everything with a single idle type. I also want the idle layer
to be the only place new tasks are allocated.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Now that I'm using vectors for everything I don't need to maintain my
own class. Nothing uses it now, so it can be safely removed.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
For each library path, I replace the linked list with a vector allowing
me to easily index into the list to find tracks.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The vector should be simpler than a linked list for tracking playlists.
I also changed reading playlists to use a function in the playlist class
rather than a function outside of the playlist.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to gradually move this out of the playlist/ directory since it
doesn't really belong there. I also plan on cleaning up / rewriting
much of the code as I go along.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I plan on removing this class in favor STL classes. I probably
shouldn't have even tried to implement this myself...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Most of this was commented out and hasn't been used in almost a year.
The new gstreamer code doesn't have the property probe feature anymore,
so I can't reimplement my old alsa code. I'll drop it for now and
figure it out later (after cleaning up this other code).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I used to use my own inverted index implementation, which makes sense if
I'm searching all songs for a specific match. Instead, GTK was visiting
each track and asking "does this song match?" and this requires a
different implementation. So rather than make an index, instead I have
each track generate substrings for its tags and then I compare filter
text against the substring set.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I also replace a few PLAYLIST_* notifications with a generic
PLAYLIST_CHANGED notification for when small changes occur. I think
that using set_flag() and check_flag() will make code cleaner and easier
to maintain.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
My "insert while sorted" code was getting complicated, and didn't send
all the notifications to the UI (only the first ~1200 songs were
displayed). This patch both simplifies the code and produces the right
answer without a noticable performance penalty.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I can make this simplier by simply passing the index into the vector,
rather than needing to calculate the iterator and pass the index.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
There is no reason to track this on my own, iterating over all tracks
and calculating it on the fly is easier and basically unnoticable.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I don't need to iterate through a linked list to find the track anymore.
Instead, I can access tracks directly using an index.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I know what playlists are library, recent and banned. All others are
just named "Playlist" so there is no need to set up a name variable.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Vectors are more straightforward than linked lists and they should allow
me to clean up the code a lot. For now I just put in the straight
conversion, I'll clean things up in future patches.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I didn't realize this was still around. It should be removed since I
switched to a notification system instead of using the renderer.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This finishes the job I started in the last commit. Once again, I use
an enum of string properties to determine the right field to return.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Rathen than using a bunch of get_PROPERTY_NAME() functions, I think it's
cleaner to use dictionary-like indexing to access properties. This
patch converts most track access functions, but I haven't gotten around
to strings yet.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Rather than hardcode this as a flag, if I set this through the
preferences code users can change the value.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Flags let me manually set properties after the playlist has been
created, rather than needing to decide upfront with no way of converting
to something else.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I plan on removing the extra playlist classes to simplify code a bit, so
this function needs to be implemented for everything.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I created simpler functions using the push_front() / push_back() names
that stl uses. If we're a set-type playlist, then call the
insert_sorted function instead. I also remove unnecessary bulk-inserts
of a single track. Packing and unpacking a list each time seems stupid.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- Read a command from the pipe, rather than reading a file with a
command in it.
- Use a single ocarina script for all commands, rather than several two
line scripts.
- Change ocarina.bin to point to ocarina instead of ocarina-player for
convenience.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The build system hadn't been touched in a while, so it needed some
cleaning up. I moved ocarina-specific files into the ocarina/ directory
and use the ocarina/Sconscript to set up build commands.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This was old code that had been replaced by fs.cpp months ago. I must
have forgotten about removing the rest of it...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Ocarina no longer has a header file subdirectory so there is no reason
to have a libsaria subdirectory anymore. Putting header files directly
in the include/ directory is a bit simpler.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I was trying to add an empty list, rather than track items. This caused
the library count to increase (on the library path tab), but the library
playlist was never given track pointers so you had to restart ocarina to
see songs.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I have notifications to handle everything the renderer used to do, and
I've removed it from the UI side.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
ocarina/playlist/ was the last subdirectory remaining in the ocarina
code, and I can finally remove it. Thank you GtkBuilder! At this
point, there is only one ocarina header file, so I move it to the main
ocarina directory.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This lets me remove the "if treeview is focused" special cases that keep
popping up in the window keypress handler.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Disabled playlists are ignored when picking the next song. I grey-out
the widgets on the UI when this notification is received. I keep
filtering enabled this time (the entry was disabled too in Ocarina 5.9)
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I put it on the tab page this time, instead of in the tab label. I
don't want wide tab labels, so I should eventually come up with a way of
closing playlists without having to change tabs. Maybe a right-click
menu?
I also noticed that the libsaria delete_playlist() code didn't work, so
I simplified it a bit.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
It's easier to refilter automatically after setting the filter text,
rather than going through a bunch of function pointers to change the filter.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The first time Escape is pressed, rows are unselected. The second time
Escape is pressed, the toplevel window is selected.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Instead of using a "on_new_playlist()" function, I now use the
notification system to tell the gui that a new playlist has been
created. For now I just put it on the front of the tab list.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Dynamic playlists are going to need to run the same code to generate
playlist tabs as the static tabs. Since I don't know how to use
GtkBuilder fragments, instead I write the code for generating each page.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
One for managing the notebook tabs (tabs.cpp) and one for managing a
specific playlist page (playlist.cpp).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Since I don't have dynamic playlists re-implemented yet, I just swtch
between the library, recent, and banned playlists.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I have to track if a filter-text entry has focus to do this properly,
otherwise using a shortcut key while searching a playlist will trigger
that shortcut.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This was in body/playlist.cpp, but I eventually plan on removing this
file so the code I'm using from there needs to be moved somewhere else.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This notification is sent when a track in the playlist is updated, such
as when the play count is incremented. I also remove the
track_updated() functions from the library renderer and ocarina::Playlist.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This class is slowly going away, and these functions have already been
reimplemented using my GtkBuilder interface.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Dynamic playlists are disabled right now, so I'm making use of this time
to clear out old code. This patch removes library renderer functions
that have already been reimplemented.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
My old code was doing this by looking for widgets getting mapped or
unmapped. This was stupid, so now I'm using the GtkNotebook switch-page
signal.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Used to notify the UI that the playlist size has changed. Other options
include: Set the size automatically when responding to PLAYLIST_ADD (and
evenutally "PLAYLIST_RM")
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This tab is appended at the end of the notebook, so it looks as if there
are two Library tabs. I'm going to use notifications and GtkBuilder on
the new tab to remove the PlaylistRenderer and to hopefully make adding
new features easier. Right now only inserting tracks into the
LibraryPlist works, and I eventually want to remove the LibraryPlist
liststore in favor of a custom treemodel.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I initially made this class so that multiple front ends could be used at
once and all receive the same notifications. I see now that this was a
stupid idea, since I only need to keep one list of the library. My
notify() function does the same stuff without the need for a driver
list.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Any void * will do, or even NULL! Try to keep notify.h up-to-date with
what argument is passed and please don't send out the same notification
with multiple argument types.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Right now it only notifies that an event happened. I think I should
eventually pass in an additional argument related to the event that
happened. This will allow me to send out notifications for preferences
or library paths changing.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Clicking them doesn't do anything yet, and the buttons are
non-functional as well. But paths are displayed as they're configured!
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I modified the code slightly from what I used to have. The biggest
difference is changing the counter will always enable automatic pausing,
so I no longer need the extra click to enable this feature.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I check the size of the idle queue during the timeout poll and then
enable the progress bar. When the queue size reaches zero I hide the
bar again.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The shortcuts were hiding more than they probably should have, and I
didn't have much using them. The only function in window.h that I'm
going to use is init_window(), so I'll just declare it in ocarina.h.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I wasn't doing anything with these, so they're just getting in the way
and increasing complexity. This change also allows me to remove the
"enabled" variable from the idle queue.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This makes more sense than pushing a single track into a list and then
iterating over the single item...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I was using multiple boolean fields, but I think it'll be easier to set
up a single bit-flag field instead.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I kept around the old list while I was converting everything over to the
new list. Now that I support all the needed features, I can remove the
old variable.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- The erase() function returns the previous item
- Implement a push_front() function
- Implement a pop_front() function
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Not really C++ iterators, but close enough. I can get the first and
last values values to use in for loops, I also made a next() function
for list items.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This function takes a function pointer argument that should return
"true" if the current item is the item we're looking for and "false"
otherwise.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Return the "count" variable and hope we don't have more than
MAX_UNSIGNED_INT objects in the list...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I free the memory in the destructor, too! Be careful, though, the copy
constructor isn't actually a copy constructor.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to gradually replace the stl list with my own implementation.
This should make everything more efficient and I won't have to deal with
those pesky iterators.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I copy images and other files to lib/ocarina/ during the build to make
installing easier. The lib directory should always be relative to the
bin (executable) path, so I can easily find the lib path based on
executable path (/proc/self/exe).
I can also use this to find bugs in the buld process, such as adding a
file to the images/ directory but forgetting to add it as an install
target.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This lets me pull code out of the generic Sconstruct, so it can't be
bad! I also removed the test directory since I never made unit tests.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Having tracks add themselves to the recent playlist means that it also
adds itself when going backwards through the playlist, resetting the
cur iterator and causing the same 2 songs to be played. To get around
this, I gave tracks a new load_unlisted() function to load without
adding themselves to the recently played list.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I created a new renderer function for updating tracks when they change.
Using this, I can show the new playcount of tracks as it is incremented.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This allows me to restore it when restarting ocarina. I also need to
notify the renderer that the playlist status has changed so I can change
the button state.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Right now, this just toggles the "banned" field in the Track class and
then skips to the next track.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I plan on using this to track if the user has banned a track or not.
This patch introduces the new field and handles the library version
upgrade.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Scripts should write commands to a temporary file and then write the
path to that file to the application pipe. I can then write results of
the command to this file before exiting.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to use the pipe with shell scripts for remote-controlling
ocarina (possibly through a web interface).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Passing individual variables through works for a small number of
variables, but passing a struct makes it easier to add new arguments.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
On the libsaria side, I created a function for finding and deleting a
playlist pointer. On the ocarina side, I added a button to each
playlist tab to remove the tab.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Used for passing extra data through the button clicked callback. I also
use this patch to remove the extra GdkEvent argument passed to buttons,
since this argument isn't actually part of the callback...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I do this after choosing the next song and after tracks are removed from
each playlist. This allows me to remove playlists as they empty.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Before I was only adding tracks that were picked through the
deck::next() function. Now I have the track add itself to the recent
list (except when I'm playing an outside track).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This should set the gst pipeline to the correct state when the song is
loaded, rather than pausing after telling it to play.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Derived classes need to implement a do_add_tracks() function instead so
I have a single place to notify the renderer and save the playlist.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- The old header functions
- The old callback header file
- The old shortcut registering system
- The old main() code
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I've been wanting to do this for a long time. I don't think I need it
anymore, so it can all be safely removed.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The "S" or "Q" shortcut will create a new playlist on the front of the
deck, "s" or "q" creates a shortcut on the back of the deck.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I don't want to keep creating functions for doing things to playlists.
Instead, I'd rather just get the playlist directly.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I create directories with numbered files for the library and playlist,
this patch creates generic code for reading them during startup.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I do this in another idle task, I also had to give the library a
function to find tracks based on (libid, trackid).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I do this whenever the playlist changes (tracks added, removed or
playlist renumbered). When playlists are deleted I remove the file. I
also remove the file when new_number < cur_number.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
From index.cpp to filter.cpp. I also added in an "is_visible()"
function for testing visibility of tracks.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Right now I just add and remove songs from the index as they are added
and removed from the playlist.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Right now I just pause after the current song, but I eventually plan on
adding controls to pause after N songs.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I keep a counter that is decremented after every call to next(). When
it reaches zero, pause after loading the next song.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- Delete the library file
- Remove tracks from each playlist
- Notify the renderer that tracks have been removed
- Notify library drivers that the path has been removed
- Remove the path from the list
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- Renumber when new playlists are either added or removed
- Finding nth playlist is much easier now
- Insert new playlists right before the library
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to make it less stack-ish because I was getting confused.
Turns out people don't think people have a hard time thinking about song
order starting from the end... :-(
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
0 - 9: Switch to playlist N
L / l: Switch to library
R / r: Switch to recent songs
N / n: Play next song
P / p: Play previous song
Escape: Give main window focus
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This way people can see what has played recently and directly select
from a list. Generic playlist classes are awesome!
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- Only works for new sets
- Set a callback function when created
- Add a right-click menu to the ocarina treeview
- Remove songs from playlist when picking next song
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I now only have a single instance of the control buttons, so the old
code can be removed now. The footer has been completely replaced by now.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
- Change WriteTask() to take an extra void pointer argument
- Pass library path pointer through WriteTask
- Store tracks to file named after library id.
- Remove newline from tags
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I plan on using (library, track) ids as a way of storing playlists. I
made both counters unsigned ints, since I'm willing to bet that people
won't have 4,294,967,295 songs or library paths...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'll eventually allow more playlists to be stacked, but for now picking
from the library is easy. I may eventually add in a way to pick
sequentially from a set.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I now have direct access to the track that was selected, so I created a
dummy function to play it (to be filled in soon).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
For sets, I keep a sorted list and merge-sort the new songs. I also
created insert_prepare() and insert_done() functions to tell the UI that
we are about to insert (this gives me a chance to call the
freeze_child_notify() and thaw_child_notify() in GTK).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Right now this must be set when a new playlist is constructed. I can
eventually change this to use a default name based on what type of
playlist has been created.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The renderer doesn't actually render anything yet, but it is statically
defined in ocarina/playlist.cpp and it will eventually display the
library.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This makes more sense to me conceptually than having a class called
PlaylistRenderer. I also commented out a lot of code, so the renderer
doesn't do anything right now.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to re-implement my old SongList class as a PlaylistRenderer,
so for now I create a new directory and a new header file.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I sort the subset of tracks to be added, and then use insertion sort to
add them to the playlist object.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I don't pull out the audio properties yet, but I do find artist, album,
title and everything else that I can.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This will eventually be used to determine if the track is visible based
on library path visibility.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This gives the UI a chance to set the new path or new size. I also
updated Ocarina to show the library path size in its liststore row.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This also removed the other `typedef sid_t` left in the header file.
I'll re-add in functions and variables as I need them, and hopefully
keep things working more efficiently.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I was using the sid_t to lookups for tracks and library paths. I think
I can simplify things by storing pointers in the UI rather than using
id numbers. This will give me direct access to whatever it is I want to
manipulate.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I created a new "list_dir()" function to recursively list directory
contents. I plan on using this to find songs to add to the library, but
it could also be modified to read playlists and library paths in the
appdir.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Whenever a task is queued, I increment a counter. When it is run, I
increment a different counter. This allows me to track the idle queue
completion percentage. I also created a progress bar for Ocarina to
display in the toes of the footer.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This allows other tools to be written to modify the library of a
currently running program without having to create a library driver
instance.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to need a polling loop for the progress bar. I might as well
only create one poll() function that is used to do everything...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I want to eventually use this to create a library file for each library
path. The "visible" field will be used to enable and disable different
paths during run time.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The UI calls the library::add_path() function to create a new
LibraryPath structure to be managed by the library.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I want to gradually re-add everything and clean it up as I go along. To
help with this, I comment out the old code so I can use it as a
reference while writing new code.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to use a ribbon-ish interface for the footer and work the
settings pages in with the now playing widgets to make things easier to
find. Right now, I created everything with placeholders.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm not using a notebook as the main widget anymore. I'm also setting
the content directly, rather than getting the widget from the body code
and setting it in the window code.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This is one of the first things that happens when initializing libsaria.
This also allows me to remove the remaining commented out code from the
preferences file.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I made a WriteTask class to use for saving files. This allows me to
create a file in the appdir and write out the new preferences if they've
changed.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I do this from the window init function using default values, rather
than pass it as a parameter to the init function.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I combined the ocarina.h and gtk.h header files into one single file. I
also began writing new window managing code under a window namespace for
code separation.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I'm going to replace my old path lookup code with something designed
around accessing files in a pre-set directory. I'm also moving back to
putting files in the home diretory, rather than the XDG_CONFIG directory.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Instead, I pass a string with the name of the application being run.
This will be used to have separate applications using libsaria.
This commit also comments out most of the libsaria and ocarina init
functions until I can revise and clean up everything.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I eventually plan on creating more cpp binaries that link with libsaria
for pipe actions and other things. It's helpful to only initialize the
parts of libsaria that I intend to use.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The UI shortcuts may remove songs from the queue with no way of
notifying the stack layer. The UI should call the stack_top_pop()
function to check if the top playlist is empty and ready for removal.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Now renderers don't need to track this on their own, and renderers will
update as tracks are added.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Not all renderers are created dynamically, so I made a way of telling
the playlist system if renderers should be deleted.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I only allow one queue instance right now, but this allows me to remove
the queue directory since it is no longer needed. I also removed the
QUEUE_REFRESH callback since all this is handled through the libsaria
playlist code. All that's left is reloading saved playlists on startup.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Right now it's just for a single queue, but I should be able to expand
this once I enable more stacking in the backend.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This allows for bookkeeping and other cleanup (schedule playlist
removal, remove from UI, and so on).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This patch does two things. First, I remove the Page class and let each
notebook page manage itself. Second, I created functions to add the
header and footer to a GtkWidget and then prepend the page in the
notebook (so it adds pages as if it was a stack).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
My goal is to eventually pick songs from whatever is on top of the
playlist stack. Right now, only the library is added and no songs are
picked.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This replaces the "remove id" ability and replaces it with a "remove
index" ability. Removing an index will remove the correct song in the
case that the same song has been added multiple times. I also modified
the UI to remove rows at a specific index.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I can get everything I need using playlists and renderers, so I can
safely remove this bit of code (I never really liked it anyway...). I
have to keep around the queue::size() function for a little bit longer,
since choosing the next song still uses it.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I don't need these now that I have playlist renderers, so I might as
well rip out the code while I'm thinking about it.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Rather than exposing iterator functions, I now have a function to walk
the playlist and call the renderer insert() function for each track.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This class will be given a Playlist and will be in charge of calling
Playlist functions. I eventually plan on expanding this to allow the
playlist to call renderer functions instead of using my current callback
system.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I don't think I'll need this once I implement dynamic, stackable
playlists, but for now I need a way of scheduling the idle task.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I put in a generic IOTask function. I'm sure this could eventually be
expanded to open and pass the appropriate stream to functions using this
task.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I do this if PL_RANDOM is set before checking PL_SEQUENTIAL. I still
need to respond to the case that both flags are set...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The improved next() function will increment the current iterator to the
next visible song. If no songs are visible, then it moves to the next
song on the list. The PL_DRAIN flags is then checked, and if draining
is enabled then the current track is removed from the list before
returning.
This patch also switches over the library sequential next function to
use the lib_playlist version.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I can do this easier with library::lookup() since this avoids having to
loop on the entire track_list.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
get_info() performed a loop over all library paths and over each track
in each path to find the requested sid_t. I now keep a map sid_t ->
Track * to make finding the track easier and faster.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This allows more direct access to each item in the list. It also speeds
up sorting, since I don't need to keep looking up the same tracks over
and over again in the library.
Siged-off-by: Bryan Schumaker <bjschuma@gmail.com>
With this change, my old queue code no longer saves itself. Instead, it
only sends out QUEUE_REFRESH notifications.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Note that this follows the broken implementation used by the queue. It
will remove all ids with the given values rather than the ones at a
specifix index. This will be fixed later when I update the UI to make
it Playlist-aware.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I replace the old queue iterator functions with calls to the queue
playlist object that way I don't need to modify the UI. This creates a
common iterator that can be used by all playlists.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
My goal is to slowly phase in use of a Playlist class. This patch
begins this effort by creating the Playlist class and changing the queue
code to load queue.q as a playlist in addition to the queue's hardcoded
list.
Signed-off-by: Bryan Schumake <bjschuma@gmail.com>
I want to pass a playlist argument through during playlist construction,
so I changed the LoadTask to handle it.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The UI now passes in a string to use as the filename. In addition, I
store the filename and remove it when the application is closed. If the
pipe already exists, then I return the path without creating a new one.
Pipes will only be removed by the application that creates them.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I save the song before refreshing the library so I can scroll back to
it. This way the user isn't interrupted too much...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I want to store the currently selected row and go back there after a
refresh or a filter. This allows me to find the current songid and
scroll back to it later.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
The library only needs to refresh if new tracks were found, so don't do
anything if nothing new has been added.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I created a new preference for "Using ALSA" that people can set if they
want to use extra alsa features. This should allow the UI to provide a
dropdown list of outputs that users can select. Once a UI is in place,
users can play music either on their computer speakers or pipe it out to
their blu ray players (or other device).
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
After listening to a long queue, I noticed that there were problems
re-realizing widgets after moving the footer to a different page (the
header might have the same problem?). I decided to fix this issue by
creating a new footer instance for each notebook page.
If I do the same thing for the page header then I can get rid of the
"move this widget from page X to page Y" logic AND allow pages to use
their own custom header AND allow for separate library and queue
filters.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
If the text is "play", "pause", or "next" then I call the appropriate
libsaria function. I eventually plan on adding more commands so bash
can act as a generic remote control, but for now this is a good start!
To use: `echo play > ~/.config/saria[-debug]/saria.pipe` after creating
the fifo (see scripts/makepipe).
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
This makes it easier to loop over all the library paths without needing
to know anything about implementation. I modified the update functions
to use the new way, so it should be ready for use by the UI.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I moved ocarina over to the new system, so the old one can go away now
since it isn't thread safe and nothing uses it anymore.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Rather than keeping a map of function pointers, I want the UI to
register a single function that takes a callback_t as an argument. From
there, the UI can decide the best way to handle callback lookups (such
as grabbing a lock before changing anything). At the very least, a
switch statement or array lookup should be faster than searching a map.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I found it was calling itself over and over again, rather than calling
the stdlib rand(). This wasn't the desired behavior...
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>