Skip to content

Commit

Permalink
Separate Engine Database2/schema concepts
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-smidge committed Nov 19, 2024
1 parent 4cd4f7a commit c2fa0b6
Show file tree
Hide file tree
Showing 23 changed files with 502 additions and 250 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10)
project(libdjinterop
VERSION 0.23.0
VERSION 0.23.1
DESCRIPTION "C++ library providing access to DJ record libraries")
set(PROJECT_HOMEPAGE_URL "https://github.com/xsco/libdjinterop")

Expand Down Expand Up @@ -42,8 +42,10 @@ add_library(
src/djinterop/impl/crate_impl.cpp
src/djinterop/impl/database_impl.cpp
src/djinterop/impl/track_impl.cpp
src/djinterop/engine/base_engine_library.cpp
src/djinterop/engine/encode_decode_utils.cpp
src/djinterop/engine/engine.cpp
src/djinterop/engine/engine_library_dir_utils.cpp
src/djinterop/engine/schema/schema_1_6_0.cpp
src/djinterop/engine/schema/schema_1_7_1.cpp
src/djinterop/engine/schema/schema_1_9_1.cpp
Expand Down
2 changes: 1 addition & 1 deletion example/engine_library_v2_low_level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ int main()
auto dir = "Engine Library";
auto exists = ev2::engine_library::exists(dir);
auto library = exists
? ev2::engine_library{dir}
? ev2::engine_library::load(dir)
: ev2::engine_library::create(dir, e::latest_v2_schema);

std::cout << (exists ? "Loaded" : "Created")
Expand Down
81 changes: 81 additions & 0 deletions include/djinterop/engine/base_engine_library.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
This file is part of libdjinterop.
libdjinterop is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libdjinterop is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with libdjinterop. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#if __cplusplus < 201703L
#error This library needs at least a C++17 compliant compiler
#endif

#include <memory>
#include <string>

#include <djinterop/config.hpp>
#include <djinterop/database.hpp>
#include <djinterop/engine/engine_schema.hpp>

namespace djinterop::engine
{
struct engine_library_context;

/// Abstract base class for an Engine Library.
///
class DJINTEROP_PUBLIC base_engine_library
{
public:
/// Construct an instance of the class using an Engine library context.
///
/// \param context Engine library context.
explicit base_engine_library(
std::shared_ptr<engine_library_context> context);

virtual ~base_engine_library() = default;

/// Verify the correctness of the Engine library database schema for its
/// stated version.
void verify() const;

/// Get the Engine library top-level directory.
///
/// \return Returns the top-level directory.
[[nodiscard]] std::string directory() const;

/// Get the schema version of the Engine library.
///
/// \return Returns the Engine schema version.
[[nodiscard]] engine_schema schema() const;

/// Get the unified database interface for this Engine library.
[[nodiscard]] virtual djinterop::database database() const = 0;

protected:
static std::shared_ptr<engine_library_context> load(
const std::string& directory);

static std::shared_ptr<engine_library_context> create(
const std::string& directory, const engine_schema& schema);

static std::shared_ptr<engine_library_context> create_temporary(
const engine_schema& schema);

static bool exists(const std::string& directory);

// Pimpl-like idiom, also used by other classes.
std::shared_ptr<engine_library_context> context_;
};

} // namespace djinterop::engine
8 changes: 4 additions & 4 deletions include/djinterop/engine/engine_schema.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ constexpr std::array<engine_schema, 18> supported_schemas{
engine_schema::schema_2_20_3, engine_schema::schema_2_21_0,
engine_schema::schema_2_21_1, engine_schema::schema_2_21_2};

/// Set of supported legacy schema versions.
/// Set of supported schema 1.x versions.
constexpr std::array<engine_schema, 11> supported_v1_schemas{
engine_schema::schema_1_6_0, engine_schema::schema_1_7_1,
engine_schema::schema_1_9_1, engine_schema::schema_1_11_1,
Expand All @@ -76,7 +76,7 @@ constexpr std::array<engine_schema, 11> supported_v1_schemas{
engine_schema::schema_1_17_0, engine_schema::schema_1_18_0_desktop,
engine_schema::schema_1_18_0_os};

/// Set of supported "Database2" schema versions.
/// Set of supported schema 2.x versions.
constexpr std::array<engine_schema, 7> supported_v2_schemas{
engine_schema::schema_2_18_0, engine_schema::schema_2_20_1,
engine_schema::schema_2_20_2, engine_schema::schema_2_20_3,
Expand All @@ -86,10 +86,10 @@ constexpr std::array<engine_schema, 7> supported_v2_schemas{
/// The most recent schema version supported by the library.
constexpr engine_schema latest_schema = engine_schema::schema_2_21_2;

/// The most recent legacy schema version supported by the library.
/// The most recent schema 1.x version supported by the library.
constexpr engine_schema latest_v1_schema = engine_schema::schema_1_18_0_os;

/// The most recent "Database2" schema version supported by the library.
/// The most recent schema 2.x version supported by the library.
constexpr engine_schema latest_v2_schema = engine_schema::schema_2_21_2;

/// Get a string representation of the schema.
Expand Down
6 changes: 5 additions & 1 deletion include/djinterop/engine/v2/change_log_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@

#include <djinterop/config.hpp>

namespace djinterop::engine::v2
namespace djinterop::engine
{
struct engine_library_context;
}

namespace djinterop::engine::v2
{

/// Represents a single row in the `ChangeLog` table.
///
Expand Down
64 changes: 26 additions & 38 deletions include/djinterop/engine/v2/engine_library.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,8 @@
#error This library needs at least a C++17 compliant compiler
#endif

#include <memory>
#include <string>

#include <djinterop/config.hpp>
#include <djinterop/database.hpp>
#include <djinterop/engine/engine_schema.hpp>
#include <djinterop/engine/base_engine_library.hpp>
#include <djinterop/engine/v2/change_log_table.hpp>
#include <djinterop/engine/v2/information_table.hpp>
#include <djinterop/engine/v2/playlist_entity_table.hpp>
Expand All @@ -35,34 +31,40 @@

namespace djinterop::engine::v2
{
struct engine_library_context;

/// Represents a version 2 Engine Library.
/// Represents an Engine Library with schema version 2.x.
///
/// A version 2 Engine Library is achieved by having a specific directory
/// A library with this schema is achieved by having a specific directory
/// structure in which one or more SQLite databases are stored. The top-level
/// directory is typically named `Engine Library`, and there must then be a
/// sub-directory beneath that named `Database2`. The main SQLite database
/// subdirectory beneath that named `Database2`. The main SQLite database
/// resides in that directory, and is named `m.db`.
///
/// Note that the directory that should be passed to constructors and member
/// functions of this class must be the `Engine Library` directory, not the
/// `Database2` directory.
class DJINTEROP_PUBLIC engine_library
class DJINTEROP_PUBLIC engine_library : public base_engine_library
{
public:
/// Construct by loading from an existing directory.
using base_engine_library::base_engine_library;

/// Load an existing library from a directory.
///
/// \param directory Directory to load from.
explicit engine_library(const std::string& directory);
static engine_library load(const std::string& directory)
{
return engine_library{base_engine_library::load(directory)};
}

/// Make a new, empty library of a given version.
///
/// \param directory Directory in which to create the new library.
/// \param schema Version to create.
/// \return Returns the new Engine library.
static engine_library create(
const std::string& directory, const engine_schema& schema);
const std::string& directory, const engine_schema& schema)
{
return engine_library{base_engine_library::create(directory, schema)};
}

/// Make a new, empty, in-memory library of a given version.
///
Expand All @@ -71,30 +73,19 @@ class DJINTEROP_PUBLIC engine_library
///
/// \param schema Version to create.
/// \return Returns the new temporary Engine library.
static engine_library create_temporary(const engine_schema& schema);
static engine_library create_temporary(const engine_schema& schema)
{
return engine_library{base_engine_library::create_temporary(schema)};
}

/// Test whether an Engine Library already exists in the given directory.
///
/// \param directory Directory to test.
/// \return Returns a flag indicating whether an Engine library exists.
static bool exists(const std::string& directory);

/// Verify the correctness of the Engine library database schema for its
/// stated version.
void verify() const;

/// Get the unified database interface for this Engine library.
[[nodiscard]] djinterop::database database() const;

/// Get the Engine library top-level directory.
///
/// \return Returns the top-level directory.
[[nodiscard]] std::string directory() const;

/// Get the schema version of the Engine library.
///
/// \return Returns the Engine schema version.
[[nodiscard]] engine_schema schema() const;
static bool exists(const std::string& directory)
{
return base_engine_library::exists(directory);
}

/// Get a class representing the `ChangeLog` table.
[[nodiscard]] change_log_table change_log() const
Expand Down Expand Up @@ -123,11 +114,8 @@ class DJINTEROP_PUBLIC engine_library
/// Get a class representing the `Track` table.
[[nodiscard]] track_table track() const { return track_table{context_}; }

private:
explicit engine_library(std::shared_ptr<engine_library_context> context);

// Pimpl-like idiom, also used by other classes.
std::shared_ptr<engine_library_context> context_;
/// Get the unified database interface for this Engine library.
[[nodiscard]] djinterop::database database() const override;
};

} // namespace djinterop::engine::v2
6 changes: 5 additions & 1 deletion include/djinterop/engine/v2/information_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@

#include <djinterop/config.hpp>

namespace djinterop::engine::v2
namespace djinterop::engine
{
struct engine_library_context;
}

namespace djinterop::engine::v2
{

/// Represents the single-row contents of the `Information` table.
struct DJINTEROP_PUBLIC information_row
Expand Down
6 changes: 5 additions & 1 deletion include/djinterop/engine/v2/playlist_entity_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@

#include <djinterop/config.hpp>

namespace djinterop::engine::v2
namespace djinterop::engine
{
struct engine_library_context;
}

namespace djinterop::engine::v2
{

/// Thrown when the id on a playlist entity row is in an erroneous state for a
/// given operation.
Expand Down
6 changes: 5 additions & 1 deletion include/djinterop/engine/v2/playlist_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@
#include <djinterop/config.hpp>
#include <djinterop/stream_helper.hpp>

namespace djinterop::engine::v2
namespace djinterop::engine
{
struct engine_library_context;
}

namespace djinterop::engine::v2
{

/// Thrown when the id on a playlist row is in an erroneous state for a given
/// operation.
Expand Down
13 changes: 8 additions & 5 deletions include/djinterop/engine/v2/track_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@
#include <djinterop/engine/v2/track_data_blob.hpp>
#include <djinterop/stream_helper.hpp>

namespace djinterop::engine::v2
namespace djinterop::engine
{
struct engine_library_context;
}

namespace djinterop::engine::v2
{

/// Thrown when the id on a track row is in an erroneous state for a given
/// operation.
Expand Down Expand Up @@ -545,8 +549,7 @@ class DJINTEROP_PUBLIC track_table
std::optional<std::string> get_album_art(int64_t id);

/// Set the `albumArt` column for a given track.
void set_album_art(
int64_t id, const std::optional<std::string>& album_art);
void set_album_art(int64_t id, const std::optional<std::string>& album_art);

/// Get the `timeLastPlayed` column for a given track.
std::optional<std::chrono::system_clock::time_point> get_time_last_played(
Expand Down Expand Up @@ -598,8 +601,8 @@ class DJINTEROP_PUBLIC track_table
/// Set the `dateAdded` column for a given track, representing the time at
/// which the track was added to the database.
void set_date_added(
int64_t id, const std::optional<std::chrono::system_clock::time_point>&
date_added);
int64_t id,
const std::optional<std::chrono::system_clock::time_point>& date_added);

/// Get the `isAvailable` column for a given track, indicating if the file
/// underlying the track entry is available.
Expand Down
Loading

0 comments on commit c2fa0b6

Please sign in to comment.