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 @@ ...@@ -22,6 +22,8 @@
#include "AudioTrack.h" #include "AudioTrack.h"
#include "Media.h"
const std::string policy::AudioTrackTable::Name = "AudioTrack"; const std::string policy::AudioTrackTable::Name = "AudioTrack";
const std::string policy::AudioTrackTable::CacheColumn = "id_track"; const std::string policy::AudioTrackTable::CacheColumn = "id_track";
unsigned int AudioTrack::* const policy::AudioTrackTable::PrimaryKey = &AudioTrack::m_id; unsigned int AudioTrack::* const policy::AudioTrackTable::PrimaryKey = &AudioTrack::m_id;
...@@ -35,11 +37,13 @@ AudioTrack::AudioTrack( DBConnection dbConnection, sqlite::Row& row ) ...@@ -35,11 +37,13 @@ AudioTrack::AudioTrack( DBConnection dbConnection, sqlite::Row& row )
>> m_sampleRate >> m_sampleRate
>> m_nbChannels >> m_nbChannels
>> m_language >> m_language
>> m_description; >> m_description
>> m_mediaId;
} }
AudioTrack::AudioTrack( const std::string& codec, unsigned int bitrate , unsigned int sampleRate, 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_id( 0 )
, m_codec( codec ) , m_codec( codec )
, m_bitrate( bitrate ) , m_bitrate( bitrate )
...@@ -47,6 +51,7 @@ AudioTrack::AudioTrack( const std::string& codec, unsigned int bitrate , unsigne ...@@ -47,6 +51,7 @@ AudioTrack::AudioTrack( const std::string& codec, unsigned int bitrate , unsigne
, m_nbChannels( nbChannels ) , m_nbChannels( nbChannels )
, m_language( language ) , m_language( language )
, m_description( desc ) , m_description( desc )
, m_mediaId( mediaId )
{ {
} }
...@@ -87,6 +92,7 @@ const std::string& AudioTrack::description() const ...@@ -87,6 +92,7 @@ const std::string& AudioTrack::description() const
bool AudioTrack::createTable( DBConnection dbConnection ) 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 static const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::AudioTrackTable::Name
+ "(" + + "(" +
policy::AudioTrackTable::CacheColumn + " INTEGER PRIMARY KEY AUTOINCREMENT," policy::AudioTrackTable::CacheColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
...@@ -96,29 +102,21 @@ bool AudioTrack::createTable( DBConnection dbConnection ) ...@@ -96,29 +102,21 @@ bool AudioTrack::createTable( DBConnection dbConnection )
"nb_channels UNSIGNED INTEGER," "nb_channels UNSIGNED INTEGER,"
"language TEXT," "language TEXT,"
"description 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 ); 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, std::shared_ptr<AudioTrack> AudioTrack::create( DBConnection dbConnection, const std::string& codec,
unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels, 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 static const std::string req = "INSERT INTO " + policy::AudioTrackTable::Name
+ "(codec, bitrate, samplerate, nb_channels, language, description) VALUES(?, ?, ?, ?, ?, ?)"; + "(codec, bitrate, samplerate, nb_channels, language, description, media_id) VALUES(?, ?, ?, ?, ?, ?, ?)";
auto track = std::make_shared<AudioTrack>( codec, bitrate, sampleRate, nbChannels, language, desc ); 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 ) == false ) if ( _Cache::insert( dbConnection, track, req, codec, bitrate, sampleRate, nbChannels, language, desc, mediaId ) == false )
return nullptr; return nullptr;
track->m_dbConnection = dbConnection; track->m_dbConnection = dbConnection;
return track; return track;
......
...@@ -43,7 +43,7 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol ...@@ -43,7 +43,7 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol
{ {
public: public:
AudioTrack( DBConnection dbConnection, sqlite::Row& row ); 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 unsigned int id() const override;
virtual const std::string&codec() const override; virtual const std::string&codec() const override;
...@@ -54,12 +54,9 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol ...@@ -54,12 +54,9 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol
virtual const std::string& description() const override; virtual const std::string& description() const override;
static bool createTable( DBConnection dbConnection ); 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, static std::shared_ptr<AudioTrack> create( DBConnection dbConnection, const std::string& codec,
unsigned int bitrate , unsigned int sampleRate, unsigned int nbChannels, 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: private:
DBConnection m_dbConnection; DBConnection m_dbConnection;
...@@ -70,6 +67,7 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol ...@@ -70,6 +67,7 @@ class AudioTrack : public IAudioTrack, public Cache<AudioTrack, IAudioTrack, pol
unsigned int m_nbChannels; unsigned int m_nbChannels;
std::string m_language; std::string m_language;
std::string m_description; std::string m_description;
unsigned int m_mediaId;
private: private:
......
...@@ -198,23 +198,13 @@ bool Media::setMovie( MoviePtr movie ) ...@@ -198,23 +198,13 @@ bool Media::setMovie( MoviePtr movie )
bool Media::addVideoTrack(const std::string& codec, unsigned int width, unsigned int height, float fps) bool Media::addVideoTrack(const std::string& codec, unsigned int width, unsigned int height, float fps)
{ {
static const std::string req = "INSERT INTO VideoTrackFileRelation VALUES(?, ?)"; return VideoTrack::create( m_dbConnection, codec, width, height, fps, m_id ) != nullptr;
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 );
} }
std::vector<VideoTrackPtr> Media::videoTracks() std::vector<VideoTrackPtr> Media::videoTracks()
{ {
static const std::string req = "SELECT t.* FROM " + policy::VideoTrackTable::Name + static const std::string req = "SELECT * FROM " + policy::VideoTrackTable::Name +
" t LEFT JOIN VideoTrackFileRelation vtfr ON vtfr.id_track = t.id_track" " WHERE media_id = ?";
" WHERE vtfr.id_media = ?";
return VideoTrack::fetchAll( m_dbConnection, req, m_id ); return VideoTrack::fetchAll( m_dbConnection, req, m_id );
} }
...@@ -222,23 +212,13 @@ bool Media::addAudioTrack( const std::string& codec, unsigned int bitrate, ...@@ -222,23 +212,13 @@ bool Media::addAudioTrack( const std::string& codec, unsigned int bitrate,
unsigned int sampleRate, unsigned int nbChannels, unsigned int sampleRate, unsigned int nbChannels,
const std::string& language, const std::string& desc ) const std::string& language, const std::string& desc )
{ {
static const std::string req = "INSERT INTO AudioTrackFileRelation VALUES(?, ?)"; return AudioTrack::create( m_dbConnection, codec, bitrate, sampleRate, nbChannels, language, desc, m_id ) != nullptr;
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 );
} }
std::vector<AudioTrackPtr> Media::audioTracks() std::vector<AudioTrackPtr> Media::audioTracks()
{ {
static const std::string req = "SELECT t.* FROM " + policy::AudioTrackTable::Name + static const std::string req = "SELECT * FROM " + policy::AudioTrackTable::Name +
" t LEFT JOIN AudioTrackFileRelation atfr ON atfr.id_track = t.id_track" " WHERE media_id = ?";
" WHERE atfr.id_media = ?";
return AudioTrack::fetchAll( m_dbConnection, req, m_id ); return AudioTrack::fetchAll( m_dbConnection, req, m_id );
} }
...@@ -343,28 +323,6 @@ bool Media::createTable( DBConnection connection ) ...@@ -343,28 +323,6 @@ bool Media::createTable( DBConnection connection )
"FOREIGN KEY (folder_id) REFERENCES " + policy::FolderTable::Name "FOREIGN KEY (folder_id) REFERENCES " + policy::FolderTable::Name
+ "(id_folder) ON DELETE CASCADE" + "(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 ); return sqlite::Tools::executeRequest( connection, req );
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
*****************************************************************************/ *****************************************************************************/
#include "VideoTrack.h" #include "VideoTrack.h"
#include "Media.h"
const std::string policy::VideoTrackTable::Name = "VideoTrack"; const std::string policy::VideoTrackTable::Name = "VideoTrack";
const std::string policy::VideoTrackTable::CacheColumn = "id_track"; const std::string policy::VideoTrackTable::CacheColumn = "id_track";
...@@ -33,15 +34,17 @@ VideoTrack::VideoTrack( DBConnection dbConnection, sqlite::Row& row ) ...@@ -33,15 +34,17 @@ VideoTrack::VideoTrack( DBConnection dbConnection, sqlite::Row& row )
>> m_codec >> m_codec
>> m_width >> m_width
>> m_height >> 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_id( 0 )
, m_codec( codec ) , m_codec( codec )
, m_width( width ) , m_width( width )
, m_height( height ) , m_height( height )
, m_fps( fps ) , m_fps( fps )
, m_mediaId( mediaId )
{ {
} }
...@@ -70,12 +73,13 @@ float VideoTrack::fps() const ...@@ -70,12 +73,13 @@ float VideoTrack::fps() const
return m_fps; 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 static const std::string req = "INSERT INTO " + policy::VideoTrackTable::Name
+ "(codec, width, height, fps) VALUES(?, ?, ?, ?)"; + "(codec, width, height, fps, media_id) VALUES(?, ?, ?, ?, ?)";
auto track = std::make_shared<VideoTrack>( codec, width, height, fps ); auto track = std::make_shared<VideoTrack>( codec, width, height, fps, mediaId );
if ( _Cache::insert( dbConnection, track, req, codec, width, height, fps ) == false ) if ( _Cache::insert( dbConnection, track, req, codec, width, height, fps, mediaId ) == false )
return nullptr; return nullptr;
track->m_dbConnection = dbConnection; track->m_dbConnection = dbConnection;
return track; return track;
...@@ -90,14 +94,9 @@ bool VideoTrack::createTable( DBConnection dbConnection ) ...@@ -90,14 +94,9 @@ bool VideoTrack::createTable( DBConnection dbConnection )
"width UNSIGNED INTEGER," "width UNSIGNED INTEGER,"
"height UNSIGNED INTEGER," "height UNSIGNED INTEGER,"
"fps FLOAT," "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 ); 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 ...@@ -44,7 +44,7 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol
{ {
public: public:
VideoTrack( DBConnection dbConnection, sqlite::Row& row ); 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 unsigned int id() const override;
virtual const std::string& codec() const override; virtual const std::string& codec() const override;
...@@ -53,10 +53,8 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol ...@@ -53,10 +53,8 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol
virtual float fps() const override; virtual float fps() const override;
static bool createTable( DBConnection dbConnection ); 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, 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: private:
DBConnection m_dbConnection; DBConnection m_dbConnection;
...@@ -65,6 +63,7 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol ...@@ -65,6 +63,7 @@ class VideoTrack : public IVideoTrack, public Cache<VideoTrack, IVideoTrack, pol
unsigned int m_width; unsigned int m_width;
unsigned int m_height; unsigned int m_height;
float m_fps; float m_fps;
unsigned int m_mediaId;
private: private:
typedef Cache<VideoTrack, IVideoTrack, policy::VideoTrackTable> _Cache; typedef Cache<VideoTrack, IVideoTrack, policy::VideoTrackTable> _Cache;
......
...@@ -251,7 +251,7 @@ public: ...@@ -251,7 +251,7 @@ public:
case SQLITE_CONSTRAINT: case SQLITE_CONSTRAINT:
throw errors::ConstraintViolation( m_req, errMsg ); throw errors::ConstraintViolation( m_req, errMsg );
default: default:
throw std::runtime_error( errMsg ); throw std::runtime_error( errMsg );
} }
} }
} }
......
...@@ -75,23 +75,3 @@ TEST_F( AudioTracks, FetchTracks ) ...@@ -75,23 +75,3 @@ TEST_F( AudioTracks, FetchTracks )
auto ts = f->audioTracks(); auto ts = f->audioTracks();
ASSERT_EQ( ts.size(), 2u ); 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 ) ...@@ -46,20 +46,3 @@ TEST_F( VideoTracks, FetchTracks )
ASSERT_EQ( ts.size(), 2u ); 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