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>
Tracks only need to be unlisted from the library list when they are
manually removed by the user. Trying to do this during shutdown lead do
a segfault because the library's file_list had already been removed when
I tried to access it.
This allows me to create only one Track() instance for each song in the
library. Before this, a Track() was being created and then copied when
adding new songs to the library. I thought this was wasteful, so now
each song is only created once.
I use these to fill in the UI list for the library. I think this will
be easier to use (and cleaner) than passing a function pointer to a
for_each loop.
This is useful for sorting the library when filling in the list, since I
do many comparisons with the same artists and albums. This beats having
to lowercase them every time!
I don't care about the order of words for indexing, and I don't need
duplicates either. Formatting to a unique set of words should make
things a little faster.
This keeps the index up-to-date with the library. Tracks are indexed as
they are scanned, then the current filter string is run through the
index again to update it.
I need to get the next file out of the library or queue without changing
it immediately. I then queue it up in the gstreamer pipeline so it will
play automatically when the current track finishes.
It was only getting filtered when new songs were added to it and never
unfiltered. This was somewhat confusing for me, and not very useful
since the only visible songs were the last ones added. I fixed this by
creating an init option to enable filtering on songlists.
What if you want to leave and a good song starts playing? This solves
the problem by loading the next song, but not playing it so the user can
go away and listen to it when they come back.
I had a test function, but it wasn't being called. I connected the
widget to the activate signal and improved the function to list the rows
that are currently selected.
relative paths can't be trusted once the program has been installed. To
get around this, I assume that the install directory has been configured
correctly and then point to images located in the subdirectory next to
the executable.
Random hasn't been implemented in libsaria yet, but I can still create
the button to test preferences. The random button should set itself to
the value store in the preferences file.
Lookup by id will be slighly slower, but now I will have one list for
each path that can be merged together and sorted to represent the
library. This sounds like a good tradeoff to me, especially since I can
store an iterator to the current track when deciding what to play next.
This will give me much faster access to song for the current track.
I need to store the inode somewhere if I want to use a linked list to
store LibraryPath data. I currently have a map <ino_t, TrackTag>, so
the obvious choice is to store the inode in the TrackTag structure.
This function is used to access how far into the song the current audio
position is. The value is returned as a percentage of the total length
for easy use by the UI.
I always want to find tags if it's possible. Since I already have a way
to find the tags, it's fairly simple to tag a random file and pass the
result back to the UI.
Namespaces make code easier to follow, and remove the need to mangle the
beginning of function names by using ocarina_*() or libsaria_*(). In
other words: "namespaces are one honking good idea. Let's have more of
them!"
The SourceModel declares an insert() function that is called when
filling the list. I have defined this function in a way that the list
will be filled in through repeated calls to insert()
The source model class is used to more tightly control how songs are
inserted into the UI. I provide an insert() function that the library's
for_each() function can take advantage of. This allows me to directly
insert songs into the UI rather than having to use a static function as
the "middle man"
This function will generate a Track object based on the current file
stored by the audio. I then pass this object to to provided function so
the UI can be updated.
It really should go into the include directory. I don't want to use
relative paths to include header files in a subdirectory... I don't know
why I even did it in the first place!
This cleans up the idle task code a lot, and reduces the size of
ocarina.bin to less than 1MB (with full debugging). It probably won't
stay there long...
I combined reference counting with the get_footer() function to make
using it easier (no manual reference counting). put_footer() will
deallocate the widget if the reference count is 0 (this is already done
by the g_object_unref() function) so it should work in a sane way.
Calling the remove() function will destroy the footer if it has no other
references. To prevent this, I need to call g_object_ref() add a
reference to the widget.
If the user no longer wishes to track a certain path, they can remove it
from the library. Note: it is unsafe to remove a path from the library
while that path is being scanned. This could potentially lead to a
segmentation fault.
The code was a bit messy and didn't make use of namespaces very well.
By converting to a set of functions (instead of a class) I can use
each function as a function pointer if I want to. I am also able to
remove libsaria/library.cpp since this was just a set of wrapper
functions to the old static class functions.
I register the idle task when there are events in the idle queue and I
remove the idle task once those events have been processed. This should
cut down on CPU usage when nothing is happening.
When the first task is queued, I trigger a callback so the UI can start
processing when idle. I return the size of the queue from both
run_task() and queue_task() so the UI knows when to stop processing
callbacks.
I don't actually perform a library update at this point, but I do create
a new task and add it to the update queue. When the run_task() function
is called, the task is removed from the queue and deleted.
A text button will use a slightly larger image to make it easier to see.
This also gives me an opportunity to add some help text to describe what
the button does.
I think ocarina/ is a better name for this directory, and now that I've
named the executable "ocarina.bin" I can do this again. I also added
functions for creating a page footer with the basic controls.
This will include code for seeking and getting the current position in
the song. Right now I just have a function for resetting the position
to the beginning of the song.
Now I won't have to keep using libsaria_get() to access parts of
libsaria. This should also cut down on the number of things that need
to be recompiled when libsaria is changed...
I moved it from the generic button.cpp file to the controls.cpp file to
keep everything together. I also changed the button list to use the new
show / hide functions.
I moved all the button code into a new subdirectory. From there, I
moved the play button code into a file named controls.cpp. This should
help clean up button code.
Scons will track changes to my include/ directory better than make will.
I also have an easier time understanding the Sconstruct file than I did
with Makefiles.
I hide the play button when music is playing and show it when music has
been stopped. I hide the pause button when music is not playing and
show it when music has been stopped. This can give the effect of one
button replacing the other.
I have created generic functions for registering and triggering
callbacks. New callbacks can be added by creating a new constant in the
callback_t enum.
play() and pause() now return true or false base on if the state change
request succeeds or fails. This can be used later to determine if a
callback should be triggered.
I stop playback, and seek to the beginning. I do this as to different
function calls in the Libsaria class so callbacks will still trigger
(once they have been implemented).