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

Tracks: Don't attempt to share tracks across media.

Simply store every media track as a new record in their respective
tables. There is too much incertainty regarding what we will parse and
whether or not the tracks will appear as different for a single media.
parent c70a4930
......@@ -22,6 +22,8 @@
#include "AudioTrack.h"
#include "Media.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;
......@@ -35,11 +37,13 @@ AudioTrack::AudioTrack( DBConnection dbConnection, sqlite::Row& row )
>> m_sampleRate
>> m_nbChannels
>> m_language
>> m_description;
>> m_description
>> m_mediaId;
}
AudioTrack::AudioTrack( const std::string& codec, unsigned int bitrate , unsigned int sampleRate,
unsigned int nbChannels, const std::string& language, const std::string& desc )
unsigned int nbChannels, const std::string& language, const std::string& desc,
unsigned int mediaId )
: m_id( 0 )
, m_codec( codec )
, m_bitrate( bitrate )
......@@ -47,6 +51,7 @@ AudioTrack::AudioTrack( const std::string& codec, unsigned int bitrate , unsigne
, m_nbChannels( nbChannels )
, m_language( language )
, m_description( desc )
, m_mediaId( mediaId )
{
}
......@@ -87,6 +92,7 @@ const std::string& AudioTrack::description() const
bool AudioTrack::createTable( DBConnection dbConnection )
{
//FIXME: Index on media_id ? Unless it's already implied by the foreign key
static const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::AudioTrackTable::Name
+ "(" +
policy::AudioTrackTable::CacheColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
......@@ -96,29 +102,21 @@ bool AudioTrack::createTable( DBConnection dbConnection )
"nb_channels UNSIGNED INTEGER,"
"language TEXT,"
"description TEXT,"
"UNIQUE ( codec, bitrate, samplerate, nb_channels, language, description ) ON CONFLICT FAIL"
"media_id UNSIGNED INT,"
"FOREIGN KEY ( media_id ) REFERENCES " + policy::MediaTable::Name
+ "( id_media ) ON DELETE CASCADE"
")";
return sqlite::Tools::executeRequest( dbConnection, req );
}
std::shared_ptr<AudioTrack> AudioTrack::fetch(DBConnection dbConnection, const std::string& codec,
unsigned int bitrate , unsigned int sampleRate, unsigned int nbChannels,
const std::string& language, const std::string& desc )
{
static const std::string req = "SELECT * FROM " + policy::AudioTrackTable::Name
+ " WHERE codec = ? AND bitrate = ? AND samplerate = ? AND nb_channels = ?"
" AND language = ? AND description = ?";
return AudioTrack::fetchOne( dbConnection, req, codec, bitrate, sampleRate, nbChannels, language, desc );
}
std::shared_ptr<AudioTrack> AudioTrack::create( DBConnection dbConnection, const std::string& codec,
unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels,
const std::string& language, const std::string& desc )
const std::string& language, const std::string& desc, unsigned int mediaId )
{
static const std::string req = "INSERT INTO " + policy::AudioTrackTable::Name
+ "(codec, bitrate, samplerate, nb_channels, language, description) VALUES(?, ?, ?, ?, ?, ?)";
auto track = std::make_shared<AudioTrack>( codec, bitrate, sampleRate, nbChannels, language, desc );
if ( _Cache::insert( dbConnection, track, req, codec, bitrate, sampleRate, nbChannels, language, desc ) == false )
+ "(codec, bitrate, samplerate, nb_channels, language, description, media_id) VALUES(?, ?, ?, ?, ?, ?, ?)";
auto track = std::make_shared<AudioTrack>( codec, bitrate, sampleRate, nbChannels, language, desc, mediaId );
if ( _Cache::insert( dbConnection, track, req, codec, bitrate, sampleRate, nbChannels, language, desc, mediaId ) == false )
return nullptr;
track->m_dbConnection = dbConnection;
return track;
......
......@@ -43,7 +43,7 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol
{
public:
AudioTrack( DBConnection dbConnection, sqlite::Row& row );
AudioTrack( const std::string& codec, unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels, const std::string& language, const std::string& desc );
AudioTrack(const std::string& codec, unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels, const std::string& language, const std::string& desc , unsigned int mediaId);
virtual unsigned int id() const override;
virtual const std::string&codec() const override;
......@@ -54,12 +54,9 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol
virtual const std::string& description() const override;
static bool createTable( DBConnection dbConnection );
static std::shared_ptr<AudioTrack> fetch( DBConnection dbConnection, const std::string& codec,
unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels,
const std::string& language, const std::string& desc );
static std::shared_ptr<AudioTrack> create( DBConnection dbConnection, const std::string& codec,
unsigned int bitrate , unsigned int sampleRate, unsigned int nbChannels,
const std::string& language, const std::string& desc );
const std::string& language, const std::string& desc, unsigned int mediaId );
private:
DBConnection m_dbConnection;
......@@ -70,6 +67,7 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol
unsigned int m_nbChannels;
std::string m_language;
std::string m_description;
unsigned int m_mediaId;
private:
......
......@@ -198,23 +198,13 @@ bool Media::setMovie( MoviePtr movie )
bool Media::addVideoTrack(const std::string& codec, unsigned int width, unsigned int height, float fps)
{
static const std::string req = "INSERT INTO VideoTrackFileRelation VALUES(?, ?)";
auto track = VideoTrack::fetch( m_dbConnection, codec, width, height, fps );
if ( track == nullptr )
{
track = VideoTrack::create( m_dbConnection, codec, width, height, fps );
if ( track == nullptr )
return false;
}
return sqlite::Tools::executeRequest( m_dbConnection, req, track->id(), m_id );
return VideoTrack::create( m_dbConnection, codec, width, height, fps, m_id ) != nullptr;
}
std::vector<VideoTrackPtr> Media::videoTracks()
{
static const std::string req = "SELECT t.* FROM " + policy::VideoTrackTable::Name +
" t LEFT JOIN VideoTrackFileRelation vtfr ON vtfr.id_track = t.id_track"
" WHERE vtfr.id_media = ?";
static const std::string req = "SELECT * FROM " + policy::VideoTrackTable::Name +
" WHERE media_id = ?";
return VideoTrack::fetchAll( m_dbConnection, req, m_id );
}
......@@ -222,23 +212,13 @@ bool Media::addAudioTrack( const std::string& codec, unsigned int bitrate,
unsigned int sampleRate, unsigned int nbChannels,
const std::string& language, const std::string& desc )
{
static const std::string req = "INSERT INTO AudioTrackFileRelation VALUES(?, ?)";
auto track = AudioTrack::fetch( m_dbConnection, codec, bitrate, sampleRate, nbChannels, language, desc );
if ( track == nullptr )
{
track = AudioTrack::create( m_dbConnection, codec, bitrate, sampleRate, nbChannels, language, desc );
if ( track == nullptr )
return false;
}
return sqlite::Tools::executeRequest( m_dbConnection, req, track->id(), m_id );
return AudioTrack::create( m_dbConnection, codec, bitrate, sampleRate, nbChannels, language, desc, m_id ) != nullptr;
}
std::vector<AudioTrackPtr> Media::audioTracks()
{
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_media = ?";
static const std::string req = "SELECT * FROM " + policy::AudioTrackTable::Name +
" WHERE media_id = ?";
return AudioTrack::fetchAll( m_dbConnection, req, m_id );
}
......@@ -343,28 +323,6 @@ bool Media::createTable( DBConnection connection )
"FOREIGN KEY (folder_id) REFERENCES " + policy::FolderTable::Name
+ "(id_folder) ON DELETE CASCADE"
")";
if ( sqlite::Tools::executeRequest( connection, req ) == false )
return false;
req = "CREATE TABLE IF NOT EXISTS VideoTrackFileRelation("
"id_track INTEGER,"
"id_media INTEGER,"
"PRIMARY KEY ( id_track, id_media ), "
"FOREIGN KEY ( id_track ) REFERENCES " + policy::VideoTrackTable::Name +
"(id_track) ON DELETE CASCADE,"
"FOREIGN KEY ( id_media ) REFERENCES " + policy::MediaTable::Name
+ "(id_media) ON DELETE CASCADE"
")";
if ( sqlite::Tools::executeRequest( connection, req ) == false )
return false;
req = "CREATE TABLE IF NOT EXISTS AudioTrackFileRelation("
"id_track INTEGER,"
"id_media INTEGER,"
"PRIMARY KEY ( id_track, id_media ), "
"FOREIGN KEY ( id_track ) REFERENCES " + policy::AudioTrackTable::Name +
"(id_track) ON DELETE CASCADE,"
"FOREIGN KEY ( id_media ) REFERENCES " + policy::MediaTable::Name
+ "(id_media) ON DELETE CASCADE"
")";
return sqlite::Tools::executeRequest( connection, req );
}
......
......@@ -21,6 +21,7 @@
*****************************************************************************/
#include "VideoTrack.h"
#include "Media.h"
const std::string policy::VideoTrackTable::Name = "VideoTrack";
const std::string policy::VideoTrackTable::CacheColumn = "id_track";
......@@ -33,15 +34,17 @@ VideoTrack::VideoTrack( DBConnection dbConnection, sqlite::Row& row )
>> m_codec
>> m_width
>> m_height
>> m_fps;
>> m_fps
>> m_mediaId;
}
VideoTrack::VideoTrack( const std::string& codec, unsigned int width, unsigned int height, float fps )
VideoTrack::VideoTrack( const std::string& codec, unsigned int width, unsigned int height, float fps, unsigned int mediaId )
: m_id( 0 )
, m_codec( codec )
, m_width( width )
, m_height( height )
, m_fps( fps )
, m_mediaId( mediaId )
{
}
......@@ -70,12 +73,13 @@ float VideoTrack::fps() const
return m_fps;
}
std::shared_ptr<VideoTrack> VideoTrack::create( DBConnection dbConnection, const std::string &codec, unsigned int width, unsigned int height, float fps )
std::shared_ptr<VideoTrack> VideoTrack::create( DBConnection dbConnection, const std::string &codec, unsigned int width,
unsigned int height, float fps, unsigned int mediaId )
{
static const std::string req = "INSERT INTO " + policy::VideoTrackTable::Name
+ "(codec, width, height, fps) VALUES(?, ?, ?, ?)";
auto track = std::make_shared<VideoTrack>( codec, width, height, fps );
if ( _Cache::insert( dbConnection, track, req, codec, width, height, fps ) == false )
+ "(codec, width, height, fps, media_id) VALUES(?, ?, ?, ?, ?)";
auto track = std::make_shared<VideoTrack>( codec, width, height, fps, mediaId );
if ( _Cache::insert( dbConnection, track, req, codec, width, height, fps, mediaId ) == false )
return nullptr;
track->m_dbConnection = dbConnection;
return track;
......@@ -90,14 +94,9 @@ bool VideoTrack::createTable( DBConnection dbConnection )
"width UNSIGNED INTEGER,"
"height UNSIGNED INTEGER,"
"fps FLOAT,"
"UNIQUE ( codec, width, height, fps ) ON CONFLICT FAIL"
"media_id UNSIGNED INT,"
"FOREIGN KEY ( media_id ) REFERENCES " + policy::MediaTable::Name +
"(id_media) ON DELETE CASCADE"
")";
return sqlite::Tools::executeRequest( dbConnection, req );
}
std::shared_ptr<VideoTrack> VideoTrack::fetch( DBConnection dbConnection, const std::string& codec, unsigned int width, unsigned int height, float fps )
{
static const std::string req = "SELECT * FROM " + policy::VideoTrackTable::Name +
" WHERE codec = ? AND width = ? AND height = ? AND fps = ?";
return VideoTrack::fetchOne( dbConnection, req, codec, width, height, fps );
}
......@@ -44,7 +44,7 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol
{
public:
VideoTrack( DBConnection dbConnection, sqlite::Row& row );
VideoTrack( const std::string& codec, unsigned int width, unsigned int height, float fps );
VideoTrack( const std::string& codec, unsigned int width, unsigned int height, float fps, unsigned int mediaId );
virtual unsigned int id() const override;
virtual const std::string& codec() const override;
......@@ -53,10 +53,8 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol
virtual float fps() const override;
static bool createTable( DBConnection dbConnection );
static std::shared_ptr<VideoTrack> fetch( DBConnection dbConnection, const std::string& codec,
unsigned int width, unsigned int height, float fps );
static std::shared_ptr<VideoTrack> create( DBConnection dbConnection, const std::string& codec,
unsigned int width, unsigned int height, float fps );
unsigned int width, unsigned int height, float fps, unsigned int mediaId );
private:
DBConnection m_dbConnection;
......@@ -65,6 +63,7 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol
unsigned int m_width;
unsigned int m_height;
float m_fps;
unsigned int m_mediaId;
private:
typedef Cache<VideoTrack, IVideoTrack, policy::VideoTrackTable> _Cache;
......
......@@ -251,7 +251,7 @@ public:
case SQLITE_CONSTRAINT:
throw errors::ConstraintViolation( m_req, errMsg );
default:
throw std::runtime_error( errMsg );
throw std::runtime_error( errMsg );
}
}
}
......
......@@ -75,23 +75,3 @@ TEST_F( AudioTracks, FetchTracks )
auto ts = f->audioTracks();
ASSERT_EQ( ts.size(), 2u );
}
TEST_F( AudioTracks, CheckUnique )
{
auto f = std::static_pointer_cast<Media>( ml->addFile( "file.mp3", nullptr ) );
f->addAudioTrack( "PCM", 128, 44100, 2, "en", "test desc" );
auto f2 = std::static_pointer_cast<Media>( ml->addFile( "file2.mp3", nullptr ) );
f2->addAudioTrack( "PCM", 128, 44100, 2, "en", "test desc" );
auto ts = f->audioTracks();
auto ts2 = f2->audioTracks();
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() );
}
......@@ -46,20 +46,3 @@ TEST_F( VideoTracks, FetchTracks )
ASSERT_EQ( ts.size(), 2u );
}
TEST_F( VideoTracks, CheckUnique )
{
auto f = std::static_pointer_cast<Media>( ml->addFile( "file.avi", nullptr ) );
f->addVideoTrack( "H264", 1920, 1080, 29.97 );
auto f2 = std::static_pointer_cast<Media>( ml->addFile( "file2.avi", nullptr ) );
f2->addVideoTrack( "H264", 1920, 1080, 29.97 );
auto ts = f->videoTracks();
auto ts2 = f2->videoTracks();
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() );
}
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