Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/medialibrary
  • luyikei/medialibrary
  • qiubit/medialibrary
  • lemourin/medialibrary
  • gsoc/GSoC2017/Bubu/medialibrary
  • Nerf/medialibrary
  • Dekans/medialibrary
  • Skantes/medialibrary
  • robUx4/medialibrary
  • bubu/medialibrary
  • craig_janeway/medialibrary
  • rom1v/medialibrary
  • tguillem/medialibrary
  • b1ue/medialibrary
  • Corbax/medialibrary
  • ilearninging/medialibrary
  • stevengivens542/medialibrary
  • fkuehne/medialibrary
  • gorbahaaa/medialibrary
  • 1480c1/medialibrary
  • ashleerenee2727/medialibrary
  • ashrafuddin5636/medialibrary
  • hkosacki/medialibrary
  • joykim/medialibrary
  • gsoc/gsoc2020/arnav-ishaan/medialibrary
  • elbrujo1987/medialibrary
  • asenat/medialibrary
  • Aza/medialibrary
  • gtskhadadze83/medialibrary
  • rm10161130/medialibrary
  • sandsmark/medialibrary
  • Aymeriic/medialibrary
  • louis/medialibrary
  • krsingh.chandan/medialibrary
  • ForteFrankie/medialibrary
  • mstorsjo/medialibrary
  • luc65r/medialibrary
  • abodbre1/medialibrary
  • Juniorzito8415/medialibrary
  • atas70835/medialibrary
  • Ninaquinin/medialibrary
  • litteh82/medialibrary
  • king7532/medialibrary
  • bharatraval7162/medialibrary
  • yenidunyabetul443/medialibrary
  • sergiomb2/medialibrary
  • boykaisaac758/medialibrary
  • Niram7777/medialibrary
  • tvermaashutosh/medialibrary
  • chub/medialibrary
  • bdazzle431/medialibrary
51 results
Show changes
Commits on Source (6)
......@@ -123,19 +123,48 @@ public:
/// If the position is greater than the playlist size, it will be interpreted
/// as a regular append operation, and the item position will be set to
/// <playlist size>
/// For instance, on the playlist [<B,0>, <A,1>, <C,2>], if add(D, 999)
/// gets called, the resulting playlist will be [<A,0>, <C,1>, <B,2>, <D,3>]
/// For instance, on the playlist [<A,0>, <B,1>, <C,2>], if add(D, 999)
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <C,2>, <D,3>]
///
virtual bool add( const IMedia& media, uint32_t position ) = 0;
/// \brief append a list of medias to a playlist
/// The medias will be the last element of a subsequent call to media()
/// \param mediaList The medias to add
/// \return true on success, false on failure.
///
/// For instance on the playlist [<A,0>, <B,1>, <C,2>], if apend([D,E])
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>]
///
virtual bool append( const std::vector<MediaPtr>& mediaList ) = 0;
///
/// \brief add Add a list of medias to the playlist at the given position.
/// \param mediaList The medias to add
/// \param position The position of this new medias, in the [0;size-1] range
/// \return true on success, false on failure
///
/// For instance on the playlist [<A,0>, <B,1>, <C,2>], if apend([D,E], 2)
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <D,2>, <E,3>, <C,4>]
///
/// If the position is greater than the playlist size, it will be interpreted
/// as a regular append operation, and the item position will be set to
/// <playlist size
/// For instance, on the playlist [<A,0>, <B,1>, <C,2>], if add([D,E], 999)
/// gets called, the resulting playlist will be [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>]
///
virtual bool add( const std::vector<MediaPtr>& mediaList, uint32_t position ) = 0;
/// Convenience wrappers
virtual bool append( int64_t mediaId ) = 0;
virtual bool add( int64_t mediaId, uint32_t position ) = 0;
virtual bool append( const std::vector<int64_t>& mediaList ) = 0;
virtual bool add( const std::vector<int64_t>& mediaList, uint32_t position ) = 0;
///
/// \brief move Change the position of a media
/// \param from The position of the item being moved
/// \param to The moved item target position
/// \param count The number of elements to move
///
/// \return true on success, false on failure
///
......@@ -145,18 +174,32 @@ public:
/// [<A,0>, <B,1>, <C,2>] on which move(0, 1) is called will result in the
/// playlist being changed to
/// [<B,0>, <A,1>, <C,2>]
///
/// Likewise, when moving multiple elements:
/// On the playlist [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>], move(1, 3, 2) results in
/// [<A,0>, <D,1>, <B,2>, <C,3>, <E,4>]
///
/// Moving one or multiple elements at the same position or within its range has no effects.
/// On the playlist [<A,0>, <B,1>, <C,2>, <D,3>, <E,4>], move(1,1) or move(2,3,2)
/// doesn't alter the playlist. Modification won't be notified, the function returns true
///
/// If the target position is out of range (ie greater than the playlist size)
/// the target position will be interpreted as the playlist size (prior to insertion).
/// For instance, on the playlist [<B,0>, <A,1>, <C,2>], if move(0, 999)
/// gets called, the resulting playlist will be [<A,0>, <C,1>, <B,2>]
/// For instance, on the playlist [<A,0>, <B,1>, <C,2>], if move(0, 999)
/// gets called, the resulting playlist will be [<B,0>, <C,1>, <A,2>].
///
virtual bool move( uint32_t from, uint32_t to ) = 0;
virtual bool move( uint32_t from, uint32_t to, uint32_t count = 1 ) = 0;
///
/// \brief remove Removes an item from the playlist
/// \brief remove Removes a range of items from the playlist
/// \param position The position of the item to remove.
/// \param count The number of element to remove (one by default)
/// \return true on success, false on failure
///
virtual bool remove( uint32_t position ) = 0;
/// For instance, a playlist with <media,position> like
/// [<A,0>, <B,1>, <C,2>, <D,3>] on which remove(1, 2) is called will result in the
/// playlist being changed to[<A,0>, <D,1>]
///
virtual bool remove( uint32_t position, uint32_t count = 1 ) = 0;
///
/// \brief isReadOnly Return true if the playlist is backed by an actual file
/// and should therefore not modified directly.
......
......@@ -308,141 +308,174 @@ int64_t Playlist::mediaAt( uint32_t position )
bool Playlist::addInternal( int64_t mediaId, uint32_t position, bool updateCounters )
{
auto media = m_ml->media( mediaId );
if ( media == nullptr )
return false;
return addInternal( *media, position, updateCounters );
std::vector<int64_t> mediaList{ mediaId };
return addInternal( mediaList, position, updateCounters );
}
bool Playlist::addInternal( const IMedia& media, uint32_t position, bool updateCounters )
struct CounterAccumulator
{
auto t = m_ml->getConn()->newTransaction();
bool res;
if ( position == UINT32_MAX )
{
static const std::string req = "INSERT INTO " + Playlist::MediaRelationTable::Name +
"(media_id, playlist_id, position) VALUES(?1, ?2, "
"(SELECT COUNT(media_id) FROM " + Playlist::MediaRelationTable::Name +
" WHERE playlist_id = ?2))";
res = sqlite::Tools::executeInsert( m_ml->getConn(), req, media.id(),
m_id );
}
else
{
static const std::string req = "INSERT INTO " + Playlist::MediaRelationTable::Name + " "
"(media_id, playlist_id, position) VALUES(?1, ?2,"
"min(?3, (SELECT COUNT(media_id) FROM " + Playlist::MediaRelationTable::Name +
" WHERE playlist_id = ?2)))";
res = sqlite::Tools::executeInsert( m_ml->getConn(), req, media.id(),
m_id, position );
}
if ( res == false )
return false;
if ( updateCounters == true )
uint32_t video = 0u;
uint32_t videoPresent = 0u;
uint32_t audio = 0u;
uint32_t audioPresent = 0u;
uint32_t unknown = 0u;
uint32_t unknownPresent = 0u;
int64_t duration = 0u;
uint32_t unknownDuration = 0u;
void update( const IMedia& media )
{
auto videoIncrement = 0u;
auto audioIncrement = 0u;
auto unknownIncrement = 0u;
auto present = media.isPresent() ? 1 : 0;
auto mediaDuration = media.duration() > 0 ? media.duration() : 0;
switch ( media.type() )
{
case IMedia::Type::Video:
videoIncrement = 1;
video += 1;
videoPresent += present;
break;
case IMedia::Type::Audio:
audioIncrement = 1;
audio += 1;
audioPresent += present;
break;
case IMedia::Type::Unknown:
unknownIncrement = 1;
unknown += 1;
unknownPresent += present;
break;
}
duration += mediaDuration;
unknownDuration += (mediaDuration <= 0) ? 1 : 0;
}
};
bool Playlist::addInternal( const std::vector<int64_t>& mediaList, uint32_t position, bool updateCounters )
{
auto t = m_ml->getConn()->newTransaction();
CounterAccumulator counterAcc;
bool res;
for ( int64_t mediaId : mediaList )
{
if ( position == UINT32_MAX )
{
static const std::string req = "INSERT INTO " + Playlist::MediaRelationTable::Name +
"(media_id, playlist_id, position) VALUES(?1, ?2, "
"(SELECT COUNT(media_id) FROM " + Playlist::MediaRelationTable::Name +
" WHERE playlist_id = ?2))";
res = sqlite::Tools::executeInsert( m_ml->getConn(), req, mediaId,
m_id );
}
else
{
static const std::string req = "INSERT INTO " + Playlist::MediaRelationTable::Name + " "
"(media_id, playlist_id, position) VALUES(?1, ?2,"
"min(?3, (SELECT COUNT(media_id) FROM " + Playlist::MediaRelationTable::Name +
" WHERE playlist_id = ?2)))";
res = sqlite::Tools::executeInsert( m_ml->getConn(), req, mediaId,
m_id, position );
position++;
}
if ( res == false )
return false;
if ( updateCounters == true )
{
auto media = m_ml->media( mediaId );
if ( media == nullptr )
return false;
counterAcc.update(*media);
}
}
if ( updateCounters == true )
{
const std::string updateCountReq = "UPDATE " + Table::Name + " SET"
" nb_video = nb_video + ?, nb_present_video = nb_present_video + ?,"
" nb_audio = nb_audio + ?, nb_present_audio = nb_present_audio + ?,"
" nb_unknown = nb_unknown + ?, nb_present_unknown = nb_present_unknown + ?,"
" duration = duration + ?, nb_duration_unknown = nb_duration_unknown + ?"
" WHERE id_playlist = ?";
auto isPresent = media.isPresent();
auto duration = media.duration() > 0 ? media.duration() : 0;
auto unknownDurationIncrement = duration <= 0 ? 1 : 0;
if ( sqlite::Tools::executeUpdate( m_ml->getConn(), updateCountReq,
videoIncrement, videoIncrement & isPresent,
audioIncrement, audioIncrement & isPresent,
unknownIncrement, unknownIncrement & isPresent,
duration, unknownDurationIncrement, m_id ) == false )
counterAcc.video,
counterAcc.videoPresent,
counterAcc.audio,
counterAcc.audioPresent,
counterAcc.unknown,
counterAcc.unknownPresent,
counterAcc.duration,
counterAcc.unknownDuration, m_id ) == false )
return false;
m_nbVideo += videoIncrement;
m_nbPresentVideo += videoIncrement & isPresent;
m_nbAudio += audioIncrement;
m_nbPresentAudio += audioIncrement & isPresent;
m_nbUnknown += unknownIncrement;
m_nbPresentUnknown += unknownIncrement & isPresent;
m_duration += duration;
m_nbUnknownDuration += unknownDurationIncrement;
m_nbVideo += counterAcc.video;
m_nbPresentVideo += counterAcc.video;
m_nbAudio += counterAcc.audio;
m_nbPresentAudio += counterAcc.audioPresent;
m_nbUnknown += counterAcc.unknown;
m_nbPresentUnknown += counterAcc.unknownPresent;
m_duration += counterAcc.duration;
m_nbUnknownDuration += counterAcc.unknownDuration;
}
t->commit();
return true;
}
bool Playlist::removeInternal( uint32_t position, int64_t mediaId , bool updateCounters )
bool Playlist::removeInternal( uint32_t position, uint32_t count , bool updateCounters )
{
if ( count == 0 )
return true;
std::unique_ptr<sqlite::Transaction> t;
t = m_ml->getConn()->newTransaction();
CounterAccumulator counterAcc;
if ( updateCounters == true )
t = m_ml->getConn()->newTransaction();
static const std::string req = "DELETE FROM " + MediaRelationTable::Name +
" WHERE playlist_id = ? AND position = ?";
if ( sqlite::Tools::executeDelete( m_ml->getConn(), req, m_id, position ) == false )
return false;
{
if ( updateCounters == false )
return true;
auto deletedMediasQuery = this->media( nullptr );
if ( !deletedMediasQuery )
return false;
auto deletedMedias = deletedMediasQuery->items( count, position );
auto media = m_ml->media( mediaId );
if ( media == nullptr )
return false;
for ( auto m : deletedMedias )
counterAcc.update( *m );
auto videoDecrement = 0u;
auto audioDecrement = 0u;
auto unknownDecrement = 0u;
switch ( media->type() )
{
case IMedia::Type::Video:
videoDecrement = 1;
break;
case IMedia::Type::Audio:
audioDecrement = 1;
break;
case IMedia::Type::Unknown:
unknownDecrement = 1;
break;
}
auto isPresent = media->isPresent();
const std::string updateCountReq = "UPDATE " + Table::Name + " SET"
const std::string updateCountReq = "UPDATE " + Table::Name + " SET"
" nb_video = nb_video - ?, nb_present_video = nb_present_video - ?,"
" nb_audio = nb_audio - ?, nb_present_audio = nb_present_audio - ?,"
" nb_unknown = nb_unknown - ?, nb_present_unknown = nb_present_unknown - ?,"
" duration = duration - ?, nb_duration_unknown = nb_duration_unknown - ?"
" WHERE id_playlist = ?";
auto duration = media->duration() > 0 ? media->duration() : 0;
auto unknownDurationDecrement = duration <= 0 ? 1 : 0;
if ( sqlite::Tools::executeUpdate( m_ml->getConn(), updateCountReq,
videoDecrement, videoDecrement & isPresent,
audioDecrement, audioDecrement & isPresent,
unknownDecrement, unknownDecrement & isPresent,
duration, unknownDurationDecrement, m_id ) == false )
if ( sqlite::Tools::executeUpdate( m_ml->getConn(), updateCountReq,
counterAcc.video, counterAcc.videoPresent,
counterAcc.audio, counterAcc.audioPresent,
counterAcc.unknown, counterAcc.unknownPresent,
counterAcc.duration, counterAcc.unknownDuration, m_id ) == false )
return false;
}
static const std::string req = "DELETE FROM " + MediaRelationTable::Name +
" WHERE playlist_id = ? AND position >= ? AND position < ?";
if ( sqlite::Tools::executeDelete( m_ml->getConn(), req, m_id, position, position + count ) == false )
return false;
if ( t != nullptr )
t->commit();
m_nbVideo -= videoDecrement;
m_nbPresentVideo -= videoDecrement & isPresent;
m_nbAudio -= audioDecrement;
m_nbPresentAudio -= audioDecrement & isPresent;
m_nbUnknown -= unknownDecrement;
m_nbPresentUnknown -= unknownDecrement & isPresent;
m_duration -= duration;
m_nbUnknownDuration -= unknownDurationDecrement;
if ( updateCounters )
{
m_nbVideo -= counterAcc.video;
m_nbPresentVideo -= counterAcc.videoPresent;
m_nbAudio -= counterAcc.audio;
m_nbPresentAudio -= counterAcc.audioPresent;
m_nbUnknown -= counterAcc.unknown;
m_nbPresentUnknown -= counterAcc.unknownPresent;
m_duration -= counterAcc.duration;
m_nbUnknownDuration -= counterAcc.unknownDuration;
}
return true;
}
......@@ -456,32 +489,71 @@ std::shared_ptr<File> Playlist::file() const
bool Playlist::append( const IMedia& media )
{
return addInternal( media, UINT32_MAX, true );
std::vector<int64_t> mediaList { media.id() };
return append( mediaList );
}
bool Playlist::add( const IMedia& media, uint32_t position )
{
return addInternal( media, position, true );
std::vector<int64_t> mediaList { media.id() };
return add( mediaList, position );
}
bool Playlist::append( int64_t mediaId )
{
auto media = m_ml->media( mediaId );
if ( media == nullptr )
return false;
return append( *media );
std::vector<int64_t> mediaList { mediaId };
return append( mediaList );
}
bool Playlist::add( int64_t mediaId, uint32_t position )
{
auto media = m_ml->media( mediaId );
if ( media == nullptr )
return false;
return add( *media, position );
std::vector<int64_t> mediaList { mediaId };
return add( mediaList, position );
}
bool Playlist::append( const std::vector<int64_t>& mediaList )
{
return addInternal( mediaList, UINT32_MAX, true );
}
bool Playlist::move( uint32_t from, uint32_t position )
bool Playlist::add( const std::vector<int64_t>& mediaList, uint32_t position )
{
return addInternal( mediaList, position, true );
}
bool Playlist::append( const std::vector<MediaPtr>& mediaList )
{
std::vector<int64_t> mediaListId;
std::transform(
mediaList.cbegin(), mediaList.cend(),
std::back_inserter(mediaListId), [](const MediaPtr& media) {
return media->id();
});
return append( mediaListId );
}
bool Playlist::add( const std::vector<MediaPtr>& mediaList, uint32_t position )
{
std::vector<int64_t> mediaListId;
std::transform(
mediaList.cbegin(), mediaList.cend(),
std::back_inserter(mediaListId),
[](const MediaPtr& media) {
return media->id();
});
return add( mediaListId, position );
}
bool Playlist::move( uint32_t from, uint32_t position, uint32_t count )
{
//no-op
if (count == 0)
return true;
// no-op
if ( from <= position && (position + 1) <= (from + count) )
return true;
auto dbConn = m_ml->getConn();
/*
......@@ -492,18 +564,26 @@ bool Playlist::move( uint32_t from, uint32_t position )
* However to do so, we need to fetch the media ID at the previous location.
*/
auto t = dbConn->newTransaction();
auto mediaId = mediaAt( from );
if ( mediaId == 0 )
std::vector<int64_t> medialist;
for ( uint32_t i = from; i < from + count; i++ )
{
LOG_ERROR( "Failed to find an item at position ", from, " in playlist" );
return false;
auto mediaId = mediaAt( i );
if ( mediaId == 0 )
{
LOG_ERROR( "Failed to find an item at position ", from, " in playlist" );
return false;
}
medialist.push_back(mediaId);
}
if ( removeInternal( from, mediaId, false ) == false )
if ( removeInternal( from, count, false ) == false )
{
LOG_ERROR( "Failed to remove element ", from, " from playlist" );
return false;
}
if ( addInternal( mediaId, position, false ) == false )
auto newPosition = (position < from) ? position : (position - (count - 1));
if ( addInternal( medialist, newPosition, false ) == false )
{
LOG_ERROR( "Failed to re-add element in playlist" );
return false;
......@@ -517,12 +597,9 @@ bool Playlist::move( uint32_t from, uint32_t position )
return true;
}
bool Playlist::remove( uint32_t position )
bool Playlist::remove( uint32_t position, uint32_t count )
{
auto mediaId = mediaAt( position );
if ( mediaId == 0 )
return false;
return removeInternal( position, mediaId, true );
return removeInternal( position, count, true );
}
bool Playlist::isReadOnly() const
......
......@@ -109,8 +109,14 @@ public:
virtual bool add( const IMedia& media, uint32_t position ) override;
virtual bool append( int64_t mediaId ) override;
virtual bool add( int64_t mediaId, uint32_t position ) override;
virtual bool move( uint32_t from, uint32_t position ) override;
virtual bool remove( uint32_t position ) override;
virtual bool append( const std::vector<int64_t>& mediaList ) override;
virtual bool add( const std::vector<int64_t>& mediaList, uint32_t position) override;
virtual bool append( const std::vector<MediaPtr>& mediaList ) override;
virtual bool add( const std::vector<MediaPtr>& mediaList, uint32_t position ) override;
virtual bool move( uint32_t from, uint32_t position, uint32_t count = 1 ) override;
virtual bool remove( uint32_t position, uint32_t count = 1 ) override;
virtual bool isReadOnly() const override;
virtual std::string mrl() const override;
virtual bool isFavorite() const override;
......@@ -163,8 +169,8 @@ private:
*/
int64_t mediaAt( uint32_t position );
bool addInternal( int64_t mediaId, uint32_t position, bool updateCounters );
bool addInternal( const IMedia& media, uint32_t position, bool updateCounters );
bool removeInternal( uint32_t position, int64_t mediaId, bool updateCounters );
bool addInternal( const std::vector<int64_t>& mediaList, uint32_t position, bool updateCounters );
bool removeInternal( uint32_t position, uint32_t count, bool updateCounters );
std::shared_ptr<File> file() const;
private:
......
......@@ -160,6 +160,46 @@ static void Append( PlaylistTests* T )
T->CheckContiguity();
}
static void AppendMany( PlaylistTests* T )
{
for ( auto i = 1; i <= 4; ++i )
{
auto m = T->ml->addMedia( "media" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
ASSERT_NE( nullptr, m );
T->pl->append( *m );
}
// [1,2,3,4]
auto media = T->pl->media( nullptr )->all();
ASSERT_EQ( 4u, media.size() );
T->CheckContiguity();
std::vector<MediaPtr> mediaList;
for ( auto i = 5; i <= 8; ++i )
{
auto media = T->ml->addMedia( "append" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
mediaList.push_back( media );
}
// [1,2,3,4,5,6,7,8]
T->pl->append( mediaList );
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 8u, media.size() );
T->CheckContiguity();
for ( auto i = 0u; i < 4; ++i )
{
auto name = "media" + std::to_string( i+1 ) + ".mkv";
ASSERT_EQ( media[i]->title(), name );
ASSERT_EQ( media[i]->id(), i+1 );
}
for ( auto i = 4u; i < 8; ++i )
{
auto name = "append" + std::to_string( i+1 ) + ".mkv";
ASSERT_EQ( media[i]->title(), name );
ASSERT_EQ( media[i]->id(), i+1 );
}
}
static void Insert( PlaylistTests* T )
{
for ( auto i = 1; i < 4; ++i )
......@@ -190,6 +230,52 @@ static void Insert( PlaylistTests* T )
ASSERT_EQ( 3u, media[4]->id() );
}
static void InsertMany( PlaylistTests* T )
{
for ( auto i = 1; i <= 3; ++i )
{
auto m = T->ml->addMedia( "media" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
ASSERT_NE( nullptr, m );
auto res = T->pl->append( m->id() );
ASSERT_TRUE( res );
}
// [<1,0>,<2,1>,<3,2>]
std::vector<MediaPtr> frontMedias;
for ( auto i = 4; i <= 6; ++i )
{
auto media = T->ml->addMedia( "front" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
frontMedias.push_back( media );
}
T->pl->add( frontMedias, 0 );
T->CheckContiguity();
std::vector<MediaPtr> middleMedias;
for ( auto i = 7; i <= 9; ++i )
{
auto media = T->ml->addMedia( "middle" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
middleMedias.push_back( media );
}
T->pl->add( middleMedias, 2 );
T->CheckContiguity();
// [<4,0>,<1,1>,<5,2>,<2,3>,<3,4>]
auto media = T->pl->media( nullptr )->all();
ASSERT_EQ( 9u, media.size() );
ASSERT_EQ( 4u, media[0]->id() );
ASSERT_EQ( 5u, media[1]->id() );
ASSERT_EQ( 7u, media[2]->id() );
ASSERT_EQ( 8u, media[3]->id() );
ASSERT_EQ( 9u, media[4]->id() );
ASSERT_EQ( 6u, media[5]->id() );
ASSERT_EQ( 1u, media[6]->id() );
ASSERT_EQ( 2u, media[7]->id() );
ASSERT_EQ( 3u, media[8]->id() );
}
static void Move( PlaylistTests* T )
{
for ( auto i = 1; i < 6; ++i )
......@@ -254,11 +340,89 @@ static void Move( PlaylistTests* T )
ASSERT_EQ( 2u, media[3]->id() );
ASSERT_EQ( 3u, media[4]->id() );
// move an element at the same place
T->pl->move( 2, 2 );
// [<5,0>,<4,1>,<1,2>,<2,3>,<3,9/4>]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 5u, media.size() );
ASSERT_EQ( 5u, media[0]->id() );
ASSERT_EQ( 4u, media[1]->id() );
ASSERT_EQ( 1u, media[2]->id() );
ASSERT_EQ( 2u, media[3]->id() );
ASSERT_EQ( 3u, media[4]->id() );
// Try to remove a dummy element and check that it's handled properly
res = T->pl->move( 123, 2 );
ASSERT_FALSE( res );
}
static void MoveMany( PlaylistTests* T )
{
for ( auto i = 1; i < 6; ++i )
{
auto m = T->ml->addMedia( "media" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
ASSERT_NE( nullptr, m );
auto res = T->pl->append( *m );
ASSERT_TRUE( res );
}
T->CheckContiguity();
// [1,2,3,4,5]
// move a range of elements after its original position
T->pl->move( 1, 3, 2 );
// [1,4,2,3,5]
auto media = T->pl->media( nullptr )->all();
ASSERT_EQ( 5u, media.size() );
ASSERT_EQ( 1u, media[0]->id() );
ASSERT_EQ( 4u, media[1]->id() );
ASSERT_EQ( 2u, media[2]->id() );
ASSERT_EQ( 3u, media[3]->id() );
ASSERT_EQ( 5u, media[4]->id() );
// move a range of elements before its original position
T->pl->move( 2, 0, 2 );
// [2,3,1,4,5]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 5u, media.size() );
ASSERT_EQ( 2u, media[0]->id() );
ASSERT_EQ( 3u, media[1]->id() );
ASSERT_EQ( 1u, media[2]->id() );
ASSERT_EQ( 4u, media[3]->id() );
ASSERT_EQ( 5u, media[4]->id() );
// move a range of elements past the last element
T->pl->move( 2, 10, 2 );
// [2,3,1,4,5]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 5u, media.size() );
ASSERT_EQ( 2u, media[0]->id() );
ASSERT_EQ( 3u, media[1]->id() );
ASSERT_EQ( 5u, media[2]->id() );
ASSERT_EQ( 1u, media[3]->id() );
ASSERT_EQ( 4u, media[4]->id() );
// move a range of elements at the same place
T->pl->move( 2, 3, 2 );
// [2,3,1,4,5]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 5u, media.size() );
ASSERT_EQ( 2u, media[0]->id() );
ASSERT_EQ( 3u, media[1]->id() );
ASSERT_EQ( 5u, media[2]->id() );
ASSERT_EQ( 1u, media[3]->id() );
ASSERT_EQ( 4u, media[4]->id() );
}
static void Remove( PlaylistTests* T )
{
for ( auto i = 1; i < 6; ++i )
......@@ -286,6 +450,71 @@ static void Remove( PlaylistTests* T )
T->CheckContiguity();
}
static void RemoveMany( PlaylistTests* T )
{
for ( auto i = 1; i <= 8; ++i )
{
auto m = T->ml->addMedia( "media" + std::to_string( i ) + ".mkv", IMedia::Type::Video );
ASSERT_NE( nullptr, m );
auto res = T->pl->append( *m );
ASSERT_TRUE( res );
}
// [<1,0>,<2,1>,<3,2>,<4,3>,<5,4>]
auto media = T->pl->media( nullptr )->all();
ASSERT_EQ( 8u, media.size() );
T->CheckContiguity();
//remove in the middle
T->pl->remove( 2, 2 );
// [<1,0>,<2,1>,<5,3>]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 6u, media.size() );
ASSERT_EQ( 1u, media[0]->id() );
ASSERT_EQ( 2u, media[1]->id() );
ASSERT_EQ( 5u, media[2]->id() );
ASSERT_EQ( 6u, media[3]->id() );
ASSERT_EQ( 7u, media[4]->id() );
ASSERT_EQ( 8u, media[5]->id() );
T->CheckContiguity();
//remove in the front
T->pl->remove( 0, 2 );
// [<5,0>,<6,1>,<7,2>,<8,3>]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 4u, media.size() );
ASSERT_EQ( 5u, media[0]->id() );
ASSERT_EQ( 6u, media[1]->id() );
ASSERT_EQ( 7u, media[2]->id() );
ASSERT_EQ( 8u, media[3]->id() );
T->CheckContiguity();
//remove past the end, no-op
T->pl->remove( 5, 2 );
// [<5,0>,<6,1>,<7,2>,<8,3>]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 4u, media.size() );
ASSERT_EQ( 5u, media[0]->id() );
ASSERT_EQ( 6u, media[1]->id() );
ASSERT_EQ( 7u, media[2]->id() );
ASSERT_EQ( 8u, media[3]->id() );
T->CheckContiguity();
//remove end and beyond
T->pl->remove( 2, 5 );
// [<5,0>,<6,1>]
media = T->pl->media( nullptr )->all();
ASSERT_EQ( 2u, media.size() );
ASSERT_EQ( 5u, media[0]->id() );
ASSERT_EQ( 6u, media[1]->id() );
T->CheckContiguity();
}
static void DeleteFile( PlaylistTests* T )
{
for ( auto i = 1; i < 6; ++i )
......@@ -758,6 +987,24 @@ static void NbMedia( PlaylistTests* T )
T->pl = std::static_pointer_cast<Playlist>( T->ml->playlist( T->pl->id() ) );
ASSERT_EQ( 0u, T->pl->nbMedia() );
ASSERT_EQ( 0u, T->pl->nbPresentMedia() );
std::vector<MediaPtr> medialist = { media, media, media };
res = T->pl->append( medialist );
ASSERT_TRUE( res );
ASSERT_EQ( 3u, T->pl->nbMedia() );
ASSERT_EQ( 3u, T->pl->nbPresentMedia() );
res = T->pl->add( medialist, 2 );
ASSERT_TRUE( res );
ASSERT_EQ( 6u, T->pl->nbMedia() );
ASSERT_EQ( 6u, T->pl->nbPresentMedia() );
/* remove the media we just inserted */
res = T->pl->remove( 2, 3 );
ASSERT_TRUE( res );
ASSERT_EQ( 3u, T->pl->nbMedia() );
ASSERT_EQ( 3u, T->pl->nbPresentMedia() );
}
static void Duration( PlaylistTests* T )
......@@ -873,12 +1120,31 @@ static void Duration( PlaylistTests* T )
T->ml->deleteMedia( m1->id() );
T->pl = std::static_pointer_cast<Playlist>( T->ml->playlist( T->pl->id() ) );
ASSERT_EQ( 0, T->pl->duration() );
/* Now insert a list of media */
auto m3 = T->ml->addExternalMedia( "http://media.org/test2.mkv", 1300 );
ASSERT_EQ( m3->duration(), 1300 );
std::vector<MediaPtr> medialist = { m3, m3, m3 };
res = T->pl->append( medialist );
ASSERT_TRUE( res );
ASSERT_EQ( 3 * m1->duration(), T->pl->duration() );
res = T->pl->add( medialist, 2 );
ASSERT_TRUE( res );
ASSERT_EQ( 6 * m1->duration(), T->pl->duration() );
/* remove the medias we just inserted */
res = T->pl->remove( 2, 3 );
ASSERT_TRUE( res );
ASSERT_EQ( 3 * m1->duration(), T->pl->duration() );
}
static void UpdateNbMediaOnInsertAndDelete( PlaylistTests* T )
{
auto m1 = T->ml->addMedia( "media1.mp3", IMedia::Type::Audio );
auto m2 = T->ml->addMedia( "media2.mkv", IMedia::Type::Video );
auto m3 = T->ml->addMedia( "media3.unk", IMedia::Type::Unknown );
ASSERT_EQ( 0u, T->pl->nbAudio() );
ASSERT_EQ( 0u, T->pl->nbVideo() );
......@@ -913,6 +1179,27 @@ static void UpdateNbMediaOnInsertAndDelete( PlaylistTests* T )
ASSERT_EQ( 1u, T->pl->nbAudio() );
ASSERT_EQ( 0u, T->pl->nbVideo() );
ASSERT_EQ( 0u, T->pl->nbUnknown() );
// append/add a range of medias
std::vector<MediaPtr> medialist = { m1, m2, m1, m3, m3, m3 };
res = T->pl->append( medialist );
ASSERT_TRUE( res );
ASSERT_EQ( 3u, T->pl->nbAudio() );
ASSERT_EQ( 1u, T->pl->nbVideo() );
ASSERT_EQ( 3u, T->pl->nbUnknown() );
res = T->pl->add( medialist, 2 );
ASSERT_TRUE( res );
ASSERT_EQ( 5u, T->pl->nbAudio() );
ASSERT_EQ( 2u, T->pl->nbVideo() );
ASSERT_EQ( 6u, T->pl->nbUnknown() );
//remove the elements we just inserted
res = T->pl->remove( 2, 6 );
ASSERT_TRUE( res );
ASSERT_EQ( 3u, T->pl->nbAudio() );
ASSERT_EQ( 1u, T->pl->nbVideo() );
ASSERT_EQ( 3u, T->pl->nbUnknown() );
}
static void UpdateNbMediaOnMediaRemoval( PlaylistTests* T )
......@@ -1314,9 +1601,13 @@ int main( int ac, char** av )
ADD_TEST( FetchAll );
ADD_TEST( Add );
ADD_TEST( Append );
ADD_TEST( AppendMany );
ADD_TEST( Insert );
ADD_TEST( InsertMany );
ADD_TEST( Move );
ADD_TEST( MoveMany );
ADD_TEST( Remove );
ADD_TEST( RemoveMany );
ADD_TEST( DeleteFile );
ADD_TEST( Search );
ADD_TEST( SearchAndSort );
......
......@@ -712,9 +712,13 @@ playlist_tests = [
'FetchAll',
'Add',
'Append',
'AppendMany',
'Insert',
'InsertMany',
'Move',
'MoveMany',
'Remove',
'RemoveMany',
'DeleteFile',
'Search',
'SearchAndSort',
......