Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
VideoLAN
medialibrary
Commits
e80b62e3
Commit
e80b62e3
authored
Oct 19, 2015
by
Hugo Beauzée-Luyssen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Album: Return tracks as IMedia
parent
b9ab7676
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
80 additions
and
112 deletions
+80
-112
include/IAlbum.h
include/IAlbum.h
+1
-3
src/Album.cpp
src/Album.cpp
+8
-12
src/Album.h
src/Album.h
+1
-1
src/AlbumTrack.cpp
src/AlbumTrack.cpp
+18
-26
src/AlbumTrack.h
src/AlbumTrack.h
+5
-4
src/Media.cpp
src/Media.cpp
+14
-22
src/Media.h
src/Media.h
+0
-1
test/Albums.cpp
test/Albums.cpp
+22
-25
test/Files.cpp
test/Files.cpp
+11
-18
No files found.
include/IAlbum.h
View file @
e80b62e3
...
...
@@ -25,8 +25,6 @@
#include "IMediaLibrary.h"
class
IAlbumTrack
;
class
IAlbum
{
public:
...
...
@@ -37,7 +35,7 @@ class IAlbum
virtual
const
std
::
string
&
shortSummary
()
const
=
0
;
virtual
const
std
::
string
&
artworkUrl
()
const
=
0
;
virtual
time_t
lastSyncDate
()
const
=
0
;
virtual
std
::
vector
<
std
::
shared_ptr
<
I
AlbumTrack
>>
tracks
()
const
=
0
;
virtual
std
::
vector
<
std
::
shared_ptr
<
I
Media
>>
tracks
()
const
=
0
;
virtual
std
::
vector
<
ArtistPtr
>
artists
()
const
=
0
;
};
...
...
src/Album.cpp
View file @
e80b62e3
...
...
@@ -110,16 +110,19 @@ time_t Album::lastSyncDate() const
return
m_lastSyncDate
;
}
std
::
vector
<
AlbumTrack
Ptr
>
Album
::
tracks
()
const
std
::
vector
<
Media
Ptr
>
Album
::
tracks
()
const
{
static
const
std
::
string
req
=
"SELECT * FROM "
+
policy
::
AlbumTrackTable
::
Name
+
" WHERE album_id = ?"
;
return
AlbumTrack
::
fetchAll
(
m_dbConnection
,
req
,
m_id
);
static
const
std
::
string
req
=
"SELECT med.* FROM "
+
policy
::
MediaTable
::
Name
+
" med "
" LEFT JOIN "
+
policy
::
AlbumTrackTable
::
Name
+
" att ON att.media_id = med.id_media "
" WHERE att.album_id = ?"
;
return
Media
::
fetchAll
(
m_dbConnection
,
req
,
m_id
);
}
std
::
shared_ptr
<
AlbumTrack
>
Album
::
addTrack
(
std
::
shared_ptr
<
Media
>
media
,
unsigned
int
trackNb
)
{
return
AlbumTrack
::
create
(
m_dbConnection
,
m_id
,
media
->
name
(),
trackNb
);
auto
track
=
AlbumTrack
::
create
(
m_dbConnection
,
m_id
,
media
.
get
(),
trackNb
);
media
->
setAlbumTrack
(
track
);
return
track
;
}
std
::
vector
<
ArtistPtr
>
Album
::
artists
()
const
...
...
@@ -143,13 +146,6 @@ bool Album::addArtist( std::shared_ptr<Artist> artist )
bool
Album
::
destroy
()
{
auto
ts
=
tracks
();
//FIXME: Have a single request to fetch all files at once, instead of having one per track
for
(
auto
&
it
:
ts
)
{
auto
t
=
std
::
static_pointer_cast
<
AlbumTrack
>
(
it
);
t
->
destroy
();
}
return
_Cache
::
destroy
(
m_dbConnection
,
this
);
}
...
...
src/Album.h
View file @
e80b62e3
...
...
@@ -63,7 +63,7 @@ class Album : public IAlbum, public Cache<Album, IAlbum, policy::AlbumTable>
virtual
const
std
::
string
&
artworkUrl
()
const
override
;
bool
setArtworkUrl
(
const
std
::
string
&
artworkUrl
);
virtual
time_t
lastSyncDate
()
const
override
;
virtual
std
::
vector
<
AlbumTrack
Ptr
>
tracks
()
const
override
;
virtual
std
::
vector
<
Media
Ptr
>
tracks
()
const
override
;
std
::
shared_ptr
<
AlbumTrack
>
addTrack
(
std
::
shared_ptr
<
Media
>
media
,
unsigned
int
trackNb
);
virtual
std
::
vector
<
ArtistPtr
>
artists
()
const
override
;
...
...
src/AlbumTrack.cpp
View file @
e80b62e3
...
...
@@ -35,15 +35,18 @@ AlbumTrack::AlbumTrack( DBConnection dbConnection, sqlite3_stmt* stmt )
,
m_album
(
nullptr
)
{
m_id
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
0
);
m_title
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
1
);
m_genre
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
2
);
m_trackNumber
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
3
);
m_albumId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
4
);
m_mediaId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
1
);
m_title
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
2
);
m_genre
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
3
);
m_trackNumber
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
4
);
m_albumId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
5
);
}
AlbumTrack
::
AlbumTrack
(
const
std
::
string
&
title
,
unsigned
int
trackNumber
,
unsigned
int
albumId
)
//FIXME: constify media
AlbumTrack
::
AlbumTrack
(
Media
*
media
,
unsigned
int
trackNumber
,
unsigned
int
albumId
)
:
m_id
(
0
)
,
m_title
(
title
)
,
m_mediaId
(
media
->
id
()
)
,
m_title
(
media
->
name
()
)
,
m_trackNumber
(
trackNumber
)
,
m_albumId
(
albumId
)
,
m_album
(
nullptr
)
...
...
@@ -59,21 +62,25 @@ bool AlbumTrack::createTable( DBConnection dbConnection )
{
static
const
std
::
string
req
=
"CREATE TABLE IF NOT EXISTS "
+
policy
::
AlbumTrackTable
::
Name
+
"("
"id_track INTEGER PRIMARY KEY AUTOINCREMENT,"
"media_id INTEGER,"
"title TEXT,"
"genre TEXT,"
"track_number UNSIGNED INTEGER,"
"album_id UNSIGNED INTEGER NOT NULL,"
"FOREIGN KEY (album_id) REFERENCES Album(id_album) ON DELETE CASCADE"
"FOREIGN KEY (media_id) REFERENCES "
+
policy
::
MediaTable
::
Name
+
"(id_media)"
" ON DELETE CASCADE, "
"FOREIGN KEY (album_id) REFERENCES Album(id_album) "
" ON DELETE CASCADE"
")"
;
return
sqlite
::
Tools
::
executeRequest
(
dbConnection
,
req
);
}
std
::
shared_ptr
<
AlbumTrack
>
AlbumTrack
::
create
(
DBConnection
dbConnection
,
unsigned
int
albumId
,
const
std
::
string
&
name
,
unsigned
int
trackNb
)
std
::
shared_ptr
<
AlbumTrack
>
AlbumTrack
::
create
(
DBConnection
dbConnection
,
unsigned
int
albumId
,
Media
*
media
,
unsigned
int
trackNb
)
{
auto
self
=
std
::
make_shared
<
AlbumTrack
>
(
na
me
,
trackNb
,
albumId
);
auto
self
=
std
::
make_shared
<
AlbumTrack
>
(
me
dia
,
trackNb
,
albumId
);
static
const
std
::
string
req
=
"INSERT INTO "
+
policy
::
AlbumTrackTable
::
Name
+
"(title, track_number, album_id) VALUES(?, ?, ?)"
;
if
(
_Cache
::
insert
(
dbConnection
,
self
,
req
,
name
,
trackNb
,
albumId
)
==
false
)
+
"(
media_id,
title, track_number, album_id) VALUES(?, ?,
?,
?)"
;
if
(
_Cache
::
insert
(
dbConnection
,
self
,
req
,
media
->
id
(),
media
->
name
()
,
trackNb
,
albumId
)
==
false
)
return
nullptr
;
self
->
m_dbConnection
=
dbConnection
;
return
self
;
...
...
@@ -113,21 +120,6 @@ std::shared_ptr<IAlbum> AlbumTrack::album()
return
m_album
;
}
bool
AlbumTrack
::
destroy
()
{
// Manually remove Files from cache, and let foreign key handling delete them from the DB
auto
fs
=
files
();
if
(
fs
.
size
()
==
0
)
LOG_WARN
(
"No files found for AlbumTrack "
,
m_id
);
for
(
auto
&
f
:
fs
)
{
// Ignore failures to discard from cache, we might want to discard records from
// cache in a near future to avoid running out of memory on mobile devices
Media
::
discard
(
std
::
static_pointer_cast
<
Media
>
(
f
)
);
}
return
_Cache
::
destroy
(
m_dbConnection
,
this
);
}
std
::
vector
<
MediaPtr
>
AlbumTrack
::
files
()
{
static
const
std
::
string
req
=
"SELECT * FROM "
+
policy
::
MediaTable
::
Name
...
...
src/AlbumTrack.h
View file @
e80b62e3
...
...
@@ -32,6 +32,7 @@
class
Album
;
class
AlbumTrack
;
class
Media
;
namespace
policy
{
...
...
@@ -49,7 +50,7 @@ class AlbumTrack : public IAlbumTrack, public Cache<AlbumTrack, IAlbumTrack, pol
typedef
Cache
<
AlbumTrack
,
IAlbumTrack
,
policy
::
AlbumTrackTable
>
_Cache
;
public:
AlbumTrack
(
DBConnection
dbConnection
,
sqlite3_stmt
*
stmt
);
AlbumTrack
(
const
std
::
string
&
title
,
unsigned
int
trackNumber
,
unsigned
int
albumId
);
AlbumTrack
(
Media
*
media
,
unsigned
int
trackNumber
,
unsigned
int
albumId
);
virtual
unsigned
int
id
()
const
override
;
virtual
const
std
::
string
&
genre
()
override
;
...
...
@@ -59,14 +60,14 @@ class AlbumTrack : public IAlbumTrack, public Cache<AlbumTrack, IAlbumTrack, pol
virtual
std
::
shared_ptr
<
IAlbum
>
album
()
override
;
virtual
std
::
vector
<
MediaPtr
>
files
()
override
;
bool
destroy
();
static
bool
createTable
(
DBConnection
dbConnection
);
static
std
::
shared_ptr
<
AlbumTrack
>
create
(
DBConnection
dbConnection
,
unsigned
int
albumId
,
const
std
::
string
&
name
,
unsigned
int
trackNb
);
static
std
::
shared_ptr
<
AlbumTrack
>
create
(
DBConnection
dbConnection
,
unsigned
int
albumId
,
Media
*
media
,
unsigned
int
trackNb
);
private:
DBConnection
m_dbConnection
;
unsigned
int
m_id
;
unsigned
int
m_mediaId
;
std
::
string
m_title
;
std
::
string
m_genre
;
unsigned
int
m_trackNumber
;
...
...
src/Media.cpp
View file @
e80b62e3
...
...
@@ -49,23 +49,21 @@ Media::Media( DBConnection dbConnection, sqlite3_stmt* stmt )
m_id
=
sqlite3_column_int
(
stmt
,
0
);
m_type
=
(
Type
)
sqlite3_column_int
(
stmt
,
1
);
m_duration
=
sqlite
::
Traits
<
int64_t
>::
Load
(
stmt
,
2
);
m_albumTrackId
=
sqlite3_column_int
(
stmt
,
3
);
m_playCount
=
sqlite3_column_int
(
stmt
,
4
);
m_showEpisodeId
=
sqlite3_column_int
(
stmt
,
5
);
m_mrl
=
(
const
char
*
)
sqlite3_column_text
(
stmt
,
6
);
m_movieId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
7
);
m_folderId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
8
);
m_lastModificationDate
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
9
);
m_snapshot
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
10
);
m_isParsed
=
sqlite
::
Traits
<
bool
>::
Load
(
stmt
,
11
);
m_name
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
12
);
m_playCount
=
sqlite3_column_int
(
stmt
,
3
);
m_showEpisodeId
=
sqlite3_column_int
(
stmt
,
4
);
m_mrl
=
(
const
char
*
)
sqlite3_column_text
(
stmt
,
5
);
m_movieId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
6
);
m_folderId
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
7
);
m_lastModificationDate
=
sqlite
::
Traits
<
unsigned
int
>::
Load
(
stmt
,
8
);
m_snapshot
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
9
);
m_isParsed
=
sqlite
::
Traits
<
bool
>::
Load
(
stmt
,
10
);
m_name
=
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
11
);
}
Media
::
Media
(
const
fs
::
IFile
*
file
,
unsigned
int
folderId
,
const
std
::
string
&
name
,
Type
type
)
:
m_id
(
0
)
,
m_type
(
type
)
,
m_duration
(
-
1
)
,
m_albumTrackId
(
0
)
,
m_playCount
(
0
)
,
m_showEpisodeId
(
0
)
,
m_mrl
(
file
->
fullPath
()
)
...
...
@@ -93,20 +91,17 @@ std::shared_ptr<Media> Media::create( DBConnection dbConnection, Type type, cons
AlbumTrackPtr
Media
::
albumTrack
()
{
if
(
m_albumTrack
==
nullptr
&&
m_albumTrackId
!=
0
)
if
(
m_albumTrack
==
nullptr
)
{
m_albumTrack
=
AlbumTrack
::
fetch
(
m_dbConnection
,
m_albumTrackId
);
std
::
string
req
=
"SELECT * FROM "
+
policy
::
AlbumTrackTable
::
Name
+
" WHERE media_id = ?"
;
m_albumTrack
=
AlbumTrack
::
fetchOne
(
m_dbConnection
,
req
,
m_id
);
}
return
m_albumTrack
;
}
bool
Media
::
setAlbumTrack
(
AlbumTrackPtr
albumTrack
)
{
static
const
std
::
string
req
=
"UPDATE "
+
policy
::
MediaTable
::
Name
+
" SET album_track_id = ? "
"WHERE id_media = ?"
;
if
(
sqlite
::
Tools
::
executeUpdate
(
m_dbConnection
,
req
,
albumTrack
->
id
(),
m_id
)
==
false
)
return
false
;
m_albumTrackId
=
albumTrack
->
id
();
m_albumTrack
=
albumTrack
;
return
true
;
}
...
...
@@ -330,7 +325,6 @@ bool Media::createTable( DBConnection connection )
"id_media INTEGER PRIMARY KEY AUTOINCREMENT,"
"type INTEGER,"
"duration INTEGER,"
"album_track_id UNSIGNED INTEGER,"
"play_count UNSIGNED INTEGER,"
"show_episode_id UNSIGNED INTEGER,"
"mrl TEXT UNIQUE ON CONFLICT FAIL,"
...
...
@@ -340,8 +334,6 @@ bool Media::createTable( DBConnection connection )
"snapshot TEXT,"
"parsed BOOLEAN,"
"name TEXT,"
"FOREIGN KEY (album_track_id) REFERENCES "
+
policy
::
AlbumTrackTable
::
Name
+
"(id_track) ON DELETE CASCADE,"
"FOREIGN KEY (show_episode_id) REFERENCES "
+
policy
::
ShowEpisodeTable
::
Name
+
"(id_episode) ON DELETE CASCADE,"
"FOREIGN KEY (movie_id) REFERENCES "
+
policy
::
MovieTable
::
Name
...
...
@@ -403,5 +395,5 @@ const std::string& policy::MediaCache::key(const std::shared_ptr<Media> self )
std
::
string
policy
::
MediaCache
::
key
(
sqlite3_stmt
*
stmt
)
{
return
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
6
);
return
sqlite
::
Traits
<
std
::
string
>::
Load
(
stmt
,
5
);
}
src/Media.h
View file @
e80b62e3
...
...
@@ -111,7 +111,6 @@ class Media : public IMedia, public Cache<Media, IMedia, policy::MediaTable, pol
unsigned
int
m_id
;
Type
m_type
;
int64_t
m_duration
;
unsigned
int
m_albumTrackId
;
unsigned
int
m_playCount
;
unsigned
int
m_showEpisodeId
;
std
::
string
m_mrl
;
...
...
test/Albums.cpp
View file @
e80b62e3
...
...
@@ -64,14 +64,13 @@ TEST_F( Albums, AddTrack )
auto
tracks
=
a
->
tracks
();
ASSERT_EQ
(
tracks
.
size
(),
1u
);
ASSERT_EQ
(
tracks
[
0
],
track
);
Reload
();
a
=
std
::
static_pointer_cast
<
Album
>
(
ml
->
album
(
"albumtag"
)
);
tracks
=
a
->
tracks
();
ASSERT_EQ
(
tracks
.
size
(),
1u
);
ASSERT_EQ
(
tracks
[
0
]
->
titl
e
(),
track
->
title
()
);
ASSERT_EQ
(
tracks
[
0
]
->
nam
e
(),
track
->
title
()
);
}
TEST_F
(
Albums
,
AssignTrack
)
...
...
@@ -80,9 +79,6 @@ TEST_F( Albums, AssignTrack )
auto
a
=
ml
->
createAlbum
(
"album"
);
auto
t
=
a
->
addTrack
(
f
,
1
);
ASSERT_EQ
(
f
->
albumTrack
(),
nullptr
);
bool
res
=
f
->
setAlbumTrack
(
t
);
ASSERT_TRUE
(
res
);
ASSERT_NE
(
f
->
albumTrack
(),
nullptr
);
ASSERT_EQ
(
f
->
albumTrack
(),
t
);
...
...
@@ -94,19 +90,19 @@ TEST_F( Albums, AssignTrack )
ASSERT_EQ
(
t
->
title
(),
f
->
name
()
);
}
TEST_F
(
Albums
,
DeleteTrack
)
{
auto
f
=
ml
->
addFile
(
"file.mp3"
,
nullptr
);
auto
a
=
ml
->
createAlbum
(
"album"
);
auto
t
=
a
->
addTrack
(
f
,
1
);
f
->
setAlbumTrack
(
t
);
//
TEST_F( Albums, DeleteTrack )
//
{
//
auto f = ml->addFile( "file.mp3", nullptr );
//
auto a = ml->createAlbum( "album" );
//
auto t = a->addTrack( f, 1 );
//
f->setAlbumTrack( t );
bool
res
=
t
->
destroy
();
ASSERT_TRUE
(
res
);
//
bool res = t->destroy();
//
ASSERT_TRUE( res );
auto
f2
=
ml
->
file
(
"file.mp3"
);
ASSERT_EQ
(
f2
,
nullptr
);
}
//
auto f2 = ml->file( "file.mp3" );
//
ASSERT_EQ( f2, nullptr );
//
}
TEST_F
(
Albums
,
SetGenre
)
{
...
...
@@ -121,8 +117,9 @@ TEST_F( Albums, SetGenre )
a
=
std
::
static_pointer_cast
<
Album
>
(
ml
->
album
(
"album"
)
);
auto
tracks
=
a
->
tracks
();
ASSERT_EQ
(
tracks
.
size
(),
1u
);
auto
t2
=
tracks
[
0
];
ASSERT_EQ
(
t
->
genre
(),
t2
->
genre
()
);
ASSERT_EQ
(
t
->
genre
(),
t2
->
albumTrack
()
->
genre
()
);
}
TEST_F
(
Albums
,
SetReleaseDate
)
...
...
@@ -183,16 +180,16 @@ TEST_F( Albums, FetchAlbumFromTrack )
TEST_F
(
Albums
,
DestroyAlbum
)
{
auto
a
=
ml
->
createAlbum
(
"album"
);
auto
f
=
ml
->
addFile
(
"file.mp3"
,
nullptr
);
auto
t
=
a
->
addTrack
(
f
,
1
);
f
->
setAlbumTrack
(
t
);
//
auto a = ml->createAlbum( "album" );
//
auto f = ml->addFile( "file.mp3", nullptr );
//
auto t = a->addTrack( f, 1 );
//
f->setAlbumTrack( t );
bool
res
=
a
->
destroy
();
ASSERT_TRUE
(
res
);
//
bool res = a->destroy();
//
ASSERT_TRUE( res );
f
=
std
::
static_pointer_cast
<
Media
>
(
ml
->
file
(
"file.mp3"
)
);
ASSERT_EQ
(
f
,
nullptr
);
//
f = std::static_pointer_cast<Media>( ml->file( "file.mp3" ) );
//
ASSERT_EQ( f, nullptr );
}
TEST_F
(
Albums
,
Artists
)
...
...
test/Files.cpp
View file @
e80b62e3
...
...
@@ -180,21 +180,17 @@ TEST_F( Files, Artists )
}
auto
tracks
=
album
->
tracks
();
ASSERT_NE
(
tracks
.
size
(),
0u
);
for
(
auto
&
it
:
tracks
)
{
//FIXME: This should return a std::vector<IMedia>
auto
t
=
std
::
static_pointer_cast
<
AlbumTrack
>
(
it
);
ASSERT_NE
(
t
->
files
().
size
(),
0u
);
for
(
auto
&
it
:
t
->
files
()
)
{
auto
f
=
std
::
static_pointer_cast
<
Media
>
(
it
);
auto
res
=
f
->
addArtist
(
artist1
);
ASSERT_EQ
(
res
,
true
);
res
=
f
->
addArtist
(
artist2
);
ASSERT_EQ
(
res
,
true
);
auto
artists
=
f
->
artists
();
ASSERT_EQ
(
artists
.
size
(),
2u
);
}
auto
f
=
std
::
static_pointer_cast
<
Media
>
(
it
);
auto
res
=
f
->
addArtist
(
artist1
);
ASSERT_EQ
(
res
,
true
);
res
=
f
->
addArtist
(
artist2
);
ASSERT_EQ
(
res
,
true
);
auto
artists
=
f
->
artists
();
ASSERT_EQ
(
artists
.
size
(),
2u
);
}
auto
artists
=
ml
->
artists
();
...
...
@@ -208,13 +204,10 @@ TEST_F( Files, Artists )
auto
album2
=
ml
->
album
(
"album"
);
auto
tracks2
=
album2
->
tracks
();
for
(
auto
&
t
:
tracks2
)
for
(
auto
&
f
:
tracks2
)
{
for
(
auto
&
f
:
t
->
files
()
)
{
auto
artists
=
f
->
artists
();
ASSERT_EQ
(
artists
.
size
(),
2u
);
}
auto
artists
=
f
->
artists
();
ASSERT_EQ
(
artists
.
size
(),
2u
);
}
auto
artists2
=
ml
->
artists
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment