Commit c0913ec3 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Add Audio tracks handling

parent de6d1664
#ifndef IAUDIOTRACK_H
#define IAUDIOTRACK_H
#include "IMediaLibrary.h"
class IAudioTrack
{
public:
virtual ~IAudioTrack() {}
virtual unsigned int id() const = 0;
virtual const std::string& codec() const = 0;
virtual unsigned int bitrate() const = 0;
};
#endif // IAUDIOTRACK_H
......@@ -40,6 +40,8 @@ class IFile
virtual bool addVideoTrack( const std::string& codec, unsigned int width,
unsigned int height, float fps ) = 0;
virtual bool videoTracks( std::vector<VideoTrackPtr>& tracks ) = 0;
virtual bool addAudioTrack( const std::string& codec, unsigned int bitrate ) = 0;
virtual bool audioTracks( std::vector<AudioTrackPtr>& tracks ) = 0;
};
#endif // IFILE_H
......@@ -11,6 +11,7 @@ class IMetadataService;
class IMovie;
class IShow;
class IShowEpisode;
class IAudioTrack;
class IVideoTrack;
struct sqlite3;
......@@ -22,6 +23,7 @@ typedef std::shared_ptr<IAlbumTrack> AlbumTrackPtr;
typedef std::shared_ptr<IShow> ShowPtr;
typedef std::shared_ptr<IShowEpisode> ShowEpisodePtr;
typedef std::shared_ptr<IMovie> MoviePtr;
typedef std::shared_ptr<IAudioTrack> AudioTrackPtr;
typedef std::shared_ptr<IVideoTrack> VideoTrackPtr;
typedef std::weak_ptr<sqlite3> DBConnection;
......
#include "AudioTrack.h"
const std::string policy::AudioTrackTable::Name = "AudioTrack";
const std::string policy::AudioTrackTable::CacheColumn = "id_track";
unsigned int AudioTrack::* const policy::AudioTrackTable::PrimaryKey = &AudioTrack::m_id;
AudioTrack::AudioTrack( DBConnection dbConnection, sqlite3_stmt* stmt )
: m_dbConnection( dbConnection )
, m_id( Traits<unsigned int>::Load( stmt, 0 ) )
, m_codec( Traits<std::string>::Load( stmt, 1 ) )
, m_bitrate( Traits<unsigned int>::Load( stmt, 2 ) )
{
}
AudioTrack::AudioTrack( const std::string& codec, unsigned int bitrate )
: m_id( 0 )
, m_codec( codec )
, m_bitrate( bitrate )
{
}
unsigned int AudioTrack::id() const
{
return m_id;
}
const std::string&AudioTrack::codec() const
{
return m_codec;
}
unsigned int AudioTrack::bitrate() const
{
return m_bitrate;
}
bool AudioTrack::createTable( DBConnection dbConnection )
{
static const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::AudioTrackTable::Name
+ "(" +
policy::AudioTrackTable::CacheColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
"codec TEXT,"
"bitrate UNSIGNED INTEGER,"
"UNIQUE ( codec, bitrate ) ON CONFLICT FAIL"
")";
return SqliteTools::executeRequest( dbConnection, req );
}
AudioTrackPtr AudioTrack::fetch( DBConnection dbConnection, const std::string& codec, unsigned int bitrate )
{
static const std::string req = "SELECT * FROM " + policy::AudioTrackTable::Name
+ " WHERE codec = ? AND bitrate = ?";
return SqliteTools::fetchOne<AudioTrack>( dbConnection, req, codec, bitrate );
}
AudioTrackPtr AudioTrack::create( DBConnection dbConnection, const std::string& codec, unsigned int bitrate )
{
static const std::string req = "INSERT INTO " + policy::AudioTrackTable::Name
+ "(codec, bitrate) VALUES(?, ?)";
auto track = std::make_shared<AudioTrack>( codec, bitrate );
if ( _Cache::insert( dbConnection, track, req, codec, bitrate ) == false )
return nullptr;
track->m_dbConnection = dbConnection;
return track;
}
#ifndef AUDIOTRACK_H
#define AUDIOTRACK_H
#include "IAudioTrack.h"
#include "IMediaLibrary.h"
#include "Cache.h"
class AudioTrack;
namespace policy
{
struct AudioTrackTable
{
static const std::string Name;
static const std::string CacheColumn;
static unsigned int AudioTrack::* const PrimaryKey;
};
}
class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, policy::AudioTrackTable>
{
public:
AudioTrack( DBConnection dbConnection, sqlite3_stmt* stmt );
AudioTrack( const std::string& codec, unsigned int bitrate );
virtual unsigned int id() const;
virtual const std::string&codec() const;
virtual unsigned int bitrate() const;
static bool createTable( DBConnection dbConnection );
static AudioTrackPtr fetch( DBConnection dbConnection, const std::string& codec, unsigned int bitrate );
static AudioTrackPtr create( DBConnection dbConnection, const std::string& codec, unsigned int bitrate );
private:
DBConnection m_dbConnection;
unsigned int m_id;
const std::string m_codec;
const unsigned int m_bitrate;
private:
typedef Cache<AudioTrack, IAudioTrack, policy::AudioTrackTable> _Cache;
friend struct policy::AudioTrackTable;
};
#endif // AUDIOTRACK_H
......@@ -31,6 +31,7 @@ list(APPEND SRC_LIST ${HEADERS_LIST}
Factory.cpp
Movie.cpp
VideoTrack.cpp
AudioTrack.cpp
)
find_package(Sqlite3 REQUIRED)
......
......@@ -4,6 +4,7 @@
#include "Album.h"
#include "AlbumTrack.h"
#include "AudioTrack.h"
#include "File.h"
#include "Label.h"
#include "Movie.h"
......@@ -159,6 +160,28 @@ bool File::videoTracks(std::vector<VideoTrackPtr>& tracks)
return SqliteTools::fetchAll<VideoTrack>( m_dbConnection, req, tracks, m_id );
}
bool File::addAudioTrack(const std::string& codec, unsigned int bitrate)
{
static const std::string req = "INSERT INTO AudioTrackFileRelation VALUES(?, ?)";
auto track = AudioTrack::fetch( m_dbConnection, codec, bitrate );
if ( track == nullptr )
{
track = AudioTrack::create( m_dbConnection, codec, bitrate );
if ( track == nullptr )
return false;
}
return SqliteTools::executeRequest( m_dbConnection, req, track->id(), m_id );
}
bool File::audioTracks( std::vector<AudioTrackPtr>& tracks )
{
static const std::string req = "SELECT t.* FROM " + policy::AudioTrackTable::Name +
" t LEFT JOIN AudioTrackFileRelation atfr ON atfr.id_track = t.id_track"
" WHERE atfr.id_file = ?";
return SqliteTools::fetchAll<AudioTrack>( m_dbConnection, req, tracks, m_id );
}
unsigned int File::id() const
{
return m_id;
......@@ -193,6 +216,17 @@ bool File::createTable( DBConnection connection )
"FOREIGN KEY ( id_file ) REFERENCES " + policy::FileTable::Name
+ "(id_file) ON DELETE CASCADE"
")";
if ( SqliteTools::executeRequest( connection, req ) == false )
return false;
req = "CREATE TABLE IF NOT EXISTS AudioTrackFileRelation("
"id_track INTEGER,"
"id_file INTEGER,"
"PRIMARY KEY ( id_track, id_file ), "
"FOREIGN KEY ( id_track ) REFERENCES " + policy::AudioTrackTable::Name +
"(id_track) ON DELETE CASCADE,"
"FOREIGN KEY ( id_file ) REFERENCES " + policy::FileTable::Name
+ "(id_file) ON DELETE CASCADE"
")";
return SqliteTools::executeRequest( connection, req );
}
......
......@@ -61,6 +61,8 @@ class File : public IFile, public Cache<File, IFile, policy::FileTable, policy::
virtual bool addVideoTrack( const std::string& codec, unsigned int width,
unsigned int height, float fps );
virtual bool videoTracks( std::vector<VideoTrackPtr>& tracks );
virtual bool addAudioTrack( const std::string& codec, unsigned int bitrate );
virtual bool audioTracks( std::vector<AudioTrackPtr>& tracks );
private:
DBConnection m_dbConnection;
......
#include <algorithm>
#include <functional>
#include "Album.h"
#include "AlbumTrack.h"
#include "AudioTrack.h"
#include "File.h"
#include "MediaLibrary.h"
#include "IMetadataService.h"
#include "SqliteTools.h"
#include "File.h"
#include "Label.h"
#include "Album.h"
#include "AlbumTrack.h"
#include "Movie.h"
#include "Show.h"
#include "ShowEpisode.h"
#include "SqliteTools.h"
#include "VideoTrack.h"
MediaLibrary::MediaLibrary()
......@@ -27,6 +28,7 @@ MediaLibrary::~MediaLibrary()
ShowEpisode::clear();
Movie::clear();
VideoTrack::clear();
AudioTrack::clear();
}
bool MediaLibrary::initialize(const std::string& dbPath)
......@@ -45,7 +47,8 @@ bool MediaLibrary::initialize(const std::string& dbPath)
Show::createTable( m_dbConnection ) &&
ShowEpisode::createTable( m_dbConnection ) &&
Movie::createTable( m_dbConnection ) ) &&
VideoTrack::createTable( m_dbConnection );
VideoTrack::createTable( m_dbConnection ) &&
AudioTrack::createTable( m_dbConnection );
}
......
#include "gtest/gtest.h"
#include "IFile.h"
#include "IAudioTrack.h"
class AudioTracks : public testing::Test
{
public:
static std::unique_ptr<IMediaLibrary> ml;
protected:
virtual void SetUp()
{
ml.reset( MediaLibraryFactory::create() );
bool res = ml->initialize( "test.db" );
ASSERT_TRUE( res );
}
virtual void TearDown()
{
ml.reset();
unlink("test.db");
}
};
std::unique_ptr<IMediaLibrary> AudioTracks::ml;
TEST_F( AudioTracks, AddTrack )
{
auto f = ml->addFile( "file" );
bool res = f->addAudioTrack( "PCM", 44100 );
ASSERT_TRUE( res );
}
TEST_F( AudioTracks, FetchTracks )
{
auto f = ml->addFile( "file" );
f->addAudioTrack( "PCM", 44100 );
f->addAudioTrack( "WMA", 48000 );
std::vector<AudioTrackPtr> ts;
bool res = f->audioTracks( ts );
ASSERT_TRUE( res );
ASSERT_EQ( ts.size(), 2u );
}
TEST_F( AudioTracks, CheckUnique )
{
auto f = ml->addFile( "file" );
f->addAudioTrack( "PCM", 44100 );
auto f2 = ml->addFile( "file2" );
f2->addAudioTrack( "PCM", 44100 );
std::vector<AudioTrackPtr> ts;
f->audioTracks( ts );
std::vector<AudioTrackPtr> ts2;
f2->audioTracks( ts2 );
ASSERT_EQ( ts.size(), 1u );
ASSERT_EQ( ts2.size(), 1u );
// Check that only 1 track has been created in DB
ASSERT_EQ( ts[0]->id(), ts2[0]->id() );
}
......@@ -38,6 +38,7 @@ list(APPEND TEST_SRCS
Shows.cpp
Movies.cpp
VideoTracks.cpp
AudioTracks.cpp
)
add_executable(unittest ${TEST_SRCS})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment