- 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 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>
The set_tab_packing() function is deprecated, so I might as well just
use the real way to do this...
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>
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'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>
This allows for bookkeeping and other cleanup (schedule playlist
removal, remove from UI, and so on).
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>
Unfortunately, this doesn't hide the queue when empty anymore. I
probably won't see this behavior again until I create the stack.
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 have filtering enabled right now, but I may change my mind in
the future. Might as well prepare now...
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>
If both PL_RANDOM and PL_SEQUENTIAL are enabled, then I want to check
the random preference to determine what to do.
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 Playlists this code is no longer needed. I'll remove more of this
code once I've updated the UI.
Signed-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>
My environment variables were set in a way that the path
/home/bjschuma/~/.config/saria-debug was being returned as the working
directory. Obviously this is wrong, so I changed the function to make
better use of default values when finding the directory.
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
Rather than resetting the preference, it's easier to call the add_alsa()
function if the preference is set. This also cuts down on startup
warnings!
Signed-off-by: Bryan Schumaker <bjschuma@gmail.com>
I've found that without ALSA enabled, the about-to-finish will hang. To
solve this, I only enable it when ALSA is enabled.
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>
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>
I have a hard time remembering how this works, so instead I leave it up
to the UI to determine how to handle this event running from multiple
threads.
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>
When either HOME or XDG_CONFIG_HOME are unset getenv() can return NULL.
C++ strings don't like being set to NULL, so we need to check for this
case.
Bryan: Edited Sconstruct and commit message.
Signed-off-by: Josh Larson <theMutatedShrimp@gmail.com>
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>
If a file has been moved to another location in the same library root
the new location won't be added since it'll have the same inode number.
The track would then be removed during the library validation step. I
switch the order for correctness.
It was being initialized with '==' instead of '=', so the for loop was
always causing a segmentation fault. This was caused by commit
180707a6c2
Author: Bryan Schumaker <bjschuma@gmail.com>
Date: Thu Dec 29 22:08:53 2011 -0500
libsaria: Remove redundant code
Nothing needs to call this function anymore. I also cleaned
up the header file a bit.
I check two things during this step:
1) Does the file still exist?
2) Does the file have the same inode number?
If the answer to either of these is "no", then the track is removed from
the library.
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 removed the old list functions while I was at it. I also changed the
next() function in the controls.cpp file to work with filepaths so the
library and queue won't have to load the chosen file themselves.
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!
Each cache miss will add a new word to either the format cache or the
substring cache. I can look at the size of the caches to determine the
number of misses rather than keep track of this with a new variable.
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.
Without this, pressing "play" on an empty library will cause an error.
The recovery code will then try to pick a new song, and fail (since
there are no tracks to choose from). It will then try to play, cause an
error and repeat forever.
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.
I look for an audio-changed signal and push this to the message bus. I
then use the message to send out the TRACK_LOADED callback to the UI.
This should be even more useful for gapless playback.
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 was doing 50, but I think I can handle 100. I also defined a constant
at the top of the file to make it easier to change this value again in
the future.
I return the number of visible songs, so if the user has entered a
filter string then I return the size of the results set. If we're not
filtered then I return the size of the playlist.
This is an index of every substring in the (artist, album, title) tags
of the library. This should be easier to work with than regular
expression based filtering since I don't need to compare every key with
every search term.
Right now this will only be triggered when the library is loaded from
disk. Once I get farther I can easily create a function to index a
track as it is added to the library (so I won't need to reindex
everything during this case)
If we are unable to open the preferences file we shouldn't try to read
from it. This led to a segmentation fault when compiled in release
mode, but for some reason it worked when compiled in debug mode?
I sort by artist / album / track, so I need to check each of these
fields in order. It would be nice if I could expand numbers into words
for some tags (3 Doors Down, Matchbox 20 and so on), but I'm happy with
what I have right now.
Pointers to a TrackTag structure are easier to pass around than the
TrackTag structure, so this should speed up sorting. Also it removes
duplicated memory between the LibraryPaths and the play_list.
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.
I was using a map, but the map required duplicating the library path
everywhere. Except for removing a path, I don't ever need to look up a
specific path by name, so why bother optimizing this case? Iterating
over a linked list should be more efficient (and easier to comprehend)