Artist and genre information are already saved by the album tag. In
addition, we can save a single date stamp instead of (year, day, month)
triplets.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
And perform an upgrade when reading back in. After track tags are read,
we can save the database in the new format and remove the old tags.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
And propegate these through the alloc steps to create an album with the
correct artist and genre tags set.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This allows for representing albums with multiple genres. I know this
doesn't happen too often, but it doesn't hurt to be covered. At the
very least, now we have a genre id for constructing new albums!
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
I need a way to represent the same album with different artists to
account for multi-artist albums.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
The date stamp is a single value that represents year, month, and day.
This should be slightly easier than working with three separate values.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
Removing items from the database leaves a NULL pointer "hole" that is
never filled in. This doesn't affect correctness, but it could be
wasteful as items are added and removed. This patch adds a function to
defragment the database without changing the order of items.
Implements #66: Add support for rebalancing databases
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
I plan to change the file format of some tags, so add versioning so we
can change things at different times.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
I need to disable filtering when adding artist playlists to avoid some
weird memory corruption issues.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
I query the underlying playlist to see if it is selectable, and then
update the settings file if it is.
Implements #10: Select default playlist
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
I need to have integer playlist ids to store into the settings database
once I allow changing the default playlist.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
Right now tracks are picked from this playlist whenever possible. A
system for selecting the default playlist will be added shortly.
Implements #20: Only one queue for "Up Next"
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
The playlist code is heavily tested by unit tests for the files in
core/playlists/, so we no longer need to have a separate playlist test.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I initially tried making several helper functions to reuse code and make
it easier to add new playlists. This didn't work all that well, mostly
because glib wasn't able to expand variable values or find the line
number that errors occured on. Macros don't have this problem, since
they are expanded at compile time.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This test can take a long time to run, especially on slow internet
connections. Let's add a way to disable it when testing other things.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This changes test output slightly, in that files are now placed under
subdirectories of $XDG_USER_DATA_DIR/ocarina-test/ instead of in this
directory directly. This should help avoid conflicting files, and lets
me use a single "rm" command to remove everything before testing.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
The view is now responsible for allocating the filter, but the gui_queue
still needs to set the filter function during an init step.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
Now that we can switch between different queues we no longer need to
allocate multiple models.
Implements #72: Only allocate a single GuiQueueModel for all playlists
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
The dbe_index of a given database item might change in the future, so we
can't rely on it everywhere. Let's just use it for saving and loading
files, with the expectation that changes will happen sometime after
startup.
Implements #69: Reduce use of dbe_index in Ocarina code
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
Three unsigned integers is overkill for handling dates.
Implements #65: Date structure can be represented with a single 32bit
value
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
Albums tend to have a single genre for all tracks, so it makes more
sense for an album to point to genre information.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
- Define __queue_filter_how_changed() for tests that need queue
callback functions
- Increase column sizes in the view test to make test more reliable
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This is called to check if any string in an artist's token list is
prefixed by the given string.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This is called to check if any string in an album's token list is
prefixed by the given string.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This will be used to replace the current filtering code with a token
comparison for each track.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I set the history playlist to use a noop function, since changing the
history doesn't really make sense.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I'm hitting this problem while developing 6.5, since file formats are
going to change. Let's handle this situation gracefully rather than
segfaulting.
This patch changes versioning problems into fatal errors to prevent us
from overwriting data already on disk.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
The pl_artist_init() function is used to allocate a playlist for each
artist already in the database, and pl_artist_deinit() is then used to
free up this memory during cleanup.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
System playlists cannot be created or deleted, so these functions simply
return false in this case. Library playlists will use this to add new
library paths to Ocarina.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I also take the opportunity to add in a generic lookup function to
convert a library path into a playlist.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This function is for both adding and removing tracks, and only returns
false. Tracks will only be added and removed through the update
function.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
The pl_library_init() function is used to allocate a playlist for each
library path already in the database, and pl_library_deinit() is then
used to free this memory during cleanup.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Similar to the library tag, this is a void pointer that should only be
used by the playlist layer.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I decided to set this as a void pointer to keep other layers from using
the playlist without our knowledge. The only user of this variable
should be the playlist code.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I'm going to use this to distinguish between various playlist types that
are about to be added. Let's update the playlist functions first, and
then add more types in a future patch.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I'll need this to toggle the random flag for the Collection playlist to
avoid cycling through the GUI in order to save.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
It doesn't make sense to have a subdirectory with a single file. Let's
move it back to core/
Implements #45: Move database into core/
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I think this is cleaner than having an upper layer allocate the results
set manually. This also lets me return NULL in the case that there were
no results.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I was storing database indexes, but this assumes that database indexes
are constant. I intend to change this with database defragmentation.
Implements #46: Filter stores a track pointer
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This is used to remove tracks from the filtering index. We'll need this
once we switch over to storing pointers to keep the same track from
getting added multiple times.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
The thread pool is used to fetch album art in the background, but this
can slow down most tests that aren't interested in album art. Adding a
(testing-only) function for running without the thread pool speeds
things up a bit.
Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
I plan to remove the containers/queue implementation, so we need a new
iterator for queue access.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I use this status indicator in the playlist code fairly often, so let's
return it directly rather than needing to code around it.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This is needed so the user can manually set album artwork in the cases
where either we don't fetch the right image or no image is found.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I want to reuse as much file code as I can for cache files, but I need a
new struct since data and cache files track different properties.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I don't think it makes sense that callers of file_open() are expected to
check the file version after opening. This should be something handled
by the file code so we can print a consistent error message.
Implements issue #5: Better file versioning
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
And then rename the temporary file when closed. This protects users
data in case Ocarina gets killed.
Implements issue #31: Make file writes seem atomic
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I'm going to use this for saving album art to the right place. I moved
it into an include file to avoid duplicating code.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
The track database now tallys total play count and unplayed track count,
so we can use this information for calculating averages. I also changed
the least played tracks playlist to allow tracks with play count equal
to the average.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This function returns the average count of tracks that have been played,
and not the average count of all tracks.
Implements #29: Efficiently calculate average play count of tracks
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I no longer need these now that the queue is using the glib
g_random_int_range() function.
Implements #32: Remove custom RNG code
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Using somebody else's library is probably better than relying on my own
random number function.
Implements #32: Remove custom RNG code
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Load all tag databases with the new load function.
Implements #15: Load track database through an idle task
Implements #16: Load library database through an idle task
Implements #17: Load genre database through an idle task
Implements #18: Load artist database through an idle task
Implements #19: Load album database through an idle task
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Scan over all tracks in the database first, and then schedule a
collection update.
Implements #13: Load collection queue through an idle task
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This will help reduce disk accesses during thet main startup sequence.
Implements #12: Load temporary queues through an idle task
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Let's save this disk access for when we're idle.
Implements #11: Load initial track through an idle task
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This patch adds support for changing a rows font face to bold for the
currently playing track. This should make it easier to find what track
is playing while quickly skimming through the list.
Fixes#22: Highlight the currently-playing song in the collection
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This function is similar to queue_remove(), except the remove can be
prevented if qop_erase() returns false.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
We don't need different operations for each queue. If we store this
then a higher layer doesn't need to keep passing the same structure over
and over again.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I'm not even going to try converting my C++ code. Let's just start
fresh, and write unit tests as we build this up.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This gets cleared every time the queue is changed and disabled when we
show pages that cannot be filtered.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I need to change the state of these toggle buttons whenever the
sidebar's current selection changes. Some gtk themes have trouble
showing the state of toggle buttons, so I change the sensitivity of both
the button and associated image so users know the current state.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This function is used to notify a higher layer that a queue is being
deinitialized. The higher layer should then clean up any state
associated with that queue.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This function is used to notify a higher layer that a queue has been
initialized. That higher layer can return a pointer to be attached to
the "private data" field of the queue.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Most of the time people want to pause playback, rather than stop
entirely. Let's remove the button since it's not getting any use.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This feature isn't used very often, and keeping the checkbox in the
sidebar looks pretty ugly.
Fixes#50: Remove Collection checkbox
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
Saving maximized state is too complicated, so let's just store width and
height of the window when it is not maximized.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
I have tests running on ocarinaproject.net, which is headless and
doesn't run an X server. Gui tests cann't run without an X server.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This is better than calling audio_*() functions directly, since we can
make sure signals are wired up properly in glade.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
The settings layer will track various configuration options set by the
user. This belongs in the gui, and not core, because it controls
settings specific to this gui implementation.
Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>