Merge lp:~jamesh/mediascanner2/mediafile-constructor into lp:mediascanner2

Proposed by James Henstridge
Status: Merged
Approved by: Jussi Pakkanen
Approved revision: 243
Merged at revision: 232
Proposed branch: lp:~jamesh/mediascanner2/mediafile-constructor
Merge into: lp:mediascanner2
Diff against target: 1623 lines (+854/-336)
13 files modified
src/daemon/MetadataExtractor.cc (+1/-1)
src/mediascanner/CMakeLists.txt (+1/-0)
src/mediascanner/MediaFile.cc (+39/-32)
src/mediascanner/MediaFile.hh (+10/-17)
src/mediascanner/MediaFileBuilder.cc (+69/-103)
src/mediascanner/MediaFileBuilder.hh (+16/-54)
src/mediascanner/MediaFilePrivate.cc (+71/-0)
src/mediascanner/MediaStore.cc (+20/-27)
src/mediascanner/internal/MediaFilePrivate.hh (+54/-0)
src/utils/scaletest.cc (+10/-1)
test/test_mediastore.cc (+404/-57)
test/test_mfbuilder.cc (+64/-20)
test/test_qml.cc (+95/-24)
To merge this branch: bzr merge lp:~jamesh/mediascanner2/mediafile-constructor
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Jussi Pakkanen (community) Approve
Review via email: mp+219142@code.launchpad.net

Commit message

Get rid of the direct constructor for MediaFile, forcing creation to go through MediaFileBuilder (which won't break when we add more metadata fields).

Also move MediaFile fields to a private struct to avoid breaking ABI in future when adding new metadata fields.

Description of the change

The many-argument constructor for MediaFile is a problem when we add new metadata items. This branch removes that constructor and tries to make MediaFileBuilder a bit more convenient to use in simple cases.

It also moves the actual metadata properties to an struct pointer, which also means we can add new properties without breaking the API.

I'm not particularly familiar with the details of C++11 move constructors/assignment, but constructing a MediaFile from a MediaFileBuilder could just involve moving the MediaFilePrivate struct between the two.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:237
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jamesh/mediascanner2/mediafile-constructor/+merge/219142/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mediascanner2-ci/64/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-amd64-ci/5
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/5
        deb: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/5/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-i386-ci/5

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mediascanner2-ci/64/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

MediaFileBuilder has a memory leak, it does not have a destructor that would delete its private structure.

Other than that this looks really nice. It really makes things simpler.

One thing which is lost is the protection against trying to set the same variable twice (which means that the class documentation is now incorrect). This may lead to leaked state if people reuse builder objects and are not careful. On the other hand we don't check that every field is set either. I don't have a really good solution for this, but let's at least change the documentation to say explicitly that the way to use an mfbuilder is to:

1. create it
2. populate it
3. assign to Mediafile ONLY ONCE
4. destroy it

review: Needs Fixing
Revision history for this message
James Henstridge (jamesh) wrote :

I will fix the MediaFileBuilder destructor.

As it currently stands, there is still nothing to stop you creating multiple MediaFile objects from a single builder (although there is limited reason to do so: we don't provide a way to change the filename member). Do we really need to tell them not to do so?

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Actually, thinking about this a bit more, one way to achieve this is to make Mediafile's constructor take a move reference to a MediaFileBuilder. Thus trying to use an mdb after constructing an mf would lead to an immediate segfault.

We can do that in a separate MR. Let's just fix the out-of-date class description of MediafileBuilder and get this merged.

238. By James Henstridge

Add missing destructor to MediaFileBuilder.

239. By James Henstridge

Add equality operation to MediaFilePrivate.

240. By James Henstridge

Add a simple move constructor for creating a MediaFile from a
MediaFileBuilder.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:240
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jamesh/mediascanner2/mediafile-constructor/+merge/219142/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mediascanner2-ci/65/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-amd64-ci/6
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/6
        deb: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/6/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-i386-ci/6

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mediascanner2-ci/65/rebuild

review: Needs Fixing (continuous-integration)
241. By James Henstridge

Move fallback title and album_artist code to MediaFile construction
time: this is safe because the properties can't be changed after
construction.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:241
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jamesh/mediascanner2/mediafile-constructor/+merge/219142/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mediascanner2-ci/66/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-amd64-ci/7
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/7
        deb: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/7/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-i386-ci/7

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mediascanner2-ci/66/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:241
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jamesh/mediascanner2/mediafile-constructor/+merge/219142/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mediascanner2-ci/67/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-amd64-ci/8
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/8
        deb: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-armhf-ci/8/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mediascanner2-utopic-i386-ci/8

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mediascanner2-ci/67/rebuild

review: Needs Fixing (continuous-integration)
242. By James Henstridge

Get rid of unneeded build() call.

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

MediaFileBuilder.hh still says that setting a property twice throws an exception, which is not what happens any more. Once that is fixed, this is good to go. Thanks.

review: Approve
243. By James Henstridge

Remove comment about multiple calls to MediaFileBuilder::set*() methods
raising an exception.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/daemon/MetadataExtractor.cc'
2--- src/daemon/MetadataExtractor.cc 2014-05-06 03:37:23 +0000
3+++ src/daemon/MetadataExtractor.cc 2014-05-15 07:01:32 +0000
4@@ -187,7 +187,7 @@
5 }
6 mfb.setDuration(static_cast<int>(
7 gst_discoverer_info_get_duration(info.get())/GST_SECOND));
8- return mfb.build();
9+ return mfb;
10 }
11
12 }
13
14=== modified file 'src/mediascanner/CMakeLists.txt'
15--- src/mediascanner/CMakeLists.txt 2014-01-29 18:07:37 +0000
16+++ src/mediascanner/CMakeLists.txt 2014-05-15 07:01:32 +0000
17@@ -1,6 +1,7 @@
18 add_library(mediascanner SHARED
19 MediaFile.cc
20 MediaFileBuilder.cc
21+ MediaFilePrivate.cc
22 Album.cc
23 MediaStore.cc
24 utils.cc
25
26=== modified file 'src/mediascanner/MediaFile.cc'
27--- src/mediascanner/MediaFile.cc 2014-05-06 03:13:10 +0000
28+++ src/mediascanner/MediaFile.cc 2014-05-15 07:01:32 +0000
29@@ -18,89 +18,96 @@
30 */
31
32 #include "MediaFile.hh"
33+#include "MediaFileBuilder.hh"
34+#include "internal/MediaFilePrivate.hh"
35 #include "internal/utils.hh"
36
37 using namespace std;
38
39 namespace mediascanner {
40
41-MediaFile::MediaFile(std::string filename, std::string content_type, std::string etag, std::string title, std::string date, std::string author, std::string album, std::string album_artist, std::string genre,
42- int disc_number, int track_number, int duration, MediaType type) :
43- filename(filename), content_type(content_type), etag(etag), title(title), date(date), author(author), album(album), album_artist(album_artist), genre(genre), disc_number(disc_number), track_number(track_number), duration(duration), type(type) {
44-
45+MediaFile::MediaFile(const MediaFile &other) :
46+ p(new MediaFilePrivate(*other.p)) {
47+}
48+
49+MediaFile::MediaFile(const MediaFileBuilder &builder) :
50+ p(new MediaFilePrivate(*builder.p)) {
51+ p->setFallbackMetadata();
52+}
53+
54+MediaFile::MediaFile(MediaFileBuilder &&builder) {
55+ p = builder.p;
56+ builder.p = nullptr;
57+ p->setFallbackMetadata();
58+}
59+
60+MediaFile::~MediaFile() {
61+ delete p;
62+}
63+
64+MediaFile &MediaFile::operator=(const MediaFile &other) {
65+ *p = *other.p;
66+ return *this;
67 }
68
69 const std::string& MediaFile::getFileName() const noexcept {
70- return filename;
71+ return p->filename;
72 }
73
74 const std::string& MediaFile::getContentType() const noexcept {
75- return content_type;
76+ return p->content_type;
77 }
78
79 const std::string& MediaFile::getETag() const noexcept {
80- return etag;
81+ return p->etag;
82 }
83
84 const std::string& MediaFile::getTitle() const noexcept {
85- return title;
86+ return p->title;
87 }
88
89 const std::string& MediaFile::getAuthor() const noexcept {
90- return author;
91+ return p->author;
92 }
93
94 const std::string& MediaFile::getAlbum() const noexcept {
95- return album;
96+ return p->album;
97 }
98
99 const std::string& MediaFile::getAlbumArtist() const noexcept {
100- return album_artist;
101+ return p->album_artist;
102 }
103
104 const std::string& MediaFile::getDate() const noexcept {
105- return date;
106+ return p->date;
107 }
108
109 const std::string& MediaFile::getGenre() const noexcept {
110- return genre;
111+ return p->genre;
112 }
113
114 int MediaFile::getDiscNumber() const noexcept {
115- return disc_number;
116+ return p->disc_number;
117 }
118
119 int MediaFile::getTrackNumber() const noexcept {
120- return track_number;
121+ return p->track_number;
122 }
123
124 int MediaFile::getDuration() const noexcept {
125- return duration;
126+ return p->duration;
127 }
128
129 MediaType MediaFile::getType() const noexcept {
130- return type;
131+ return p->type;
132 }
133
134 std::string MediaFile::getUri() const {
135- return mediascanner::getUri(filename);
136+ return mediascanner::getUri(p->filename);
137 }
138
139 bool MediaFile::operator==(const MediaFile &other) const {
140- return
141- filename == other.filename &&
142- content_type == other.content_type &&
143- etag == other.etag &&
144- title == other.title &&
145- author == other.author &&
146- album == other.album &&
147- album_artist == other.album_artist &&
148- date == other.date &&
149- genre == other.genre &&
150- disc_number == other.disc_number &&
151- track_number == other.track_number &&
152- duration == other.duration &&
153- type == other.type;
154+ return *p == *other.p;
155 }
156
157 bool MediaFile::operator!=(const MediaFile &other) const {
158
159=== modified file 'src/mediascanner/MediaFile.hh'
160--- src/mediascanner/MediaFile.hh 2014-05-06 03:13:10 +0000
161+++ src/mediascanner/MediaFile.hh 2014-05-15 07:01:32 +0000
162@@ -25,14 +25,18 @@
163
164 namespace mediascanner {
165
166+class MediaFileBuilder;
167+struct MediaFilePrivate;
168+
169 class MediaFile final {
170+ friend class MediaFileBuilder;
171 public:
172
173- MediaFile(std::string filename) : filename(filename), content_type(""), etag(""), title(""), date(""), author(""),
174- album(""), album_artist(""), genre(""), disc_number(0), track_number(0), duration(0), type(UnknownMedia) {}
175- MediaFile(std::string filename, std::string content_type, std::string etag, std::string title, std::string date, std::string author, std::string album, std::string album_artist, std::string genre,
176- int disc_number, int track_number, int duration, MediaType type);
177 MediaFile() = delete;
178+ MediaFile(const MediaFile &other);
179+ MediaFile(const MediaFileBuilder &builder);
180+ MediaFile(MediaFileBuilder &&builder);
181+ ~MediaFile();
182
183 const std::string& getFileName() const noexcept;
184 const std::string& getContentType() const noexcept;
185@@ -51,24 +55,13 @@
186 MediaType getType() const noexcept;
187 bool operator==(const MediaFile &other) const;
188 bool operator!=(const MediaFile &other) const;
189+ MediaFile &operator=(const MediaFile &other);
190
191 // There are no setters. MediaFiles are immutable.
192 // For piecewise construction use MediaFileBuilder.
193
194 private:
195- std::string filename;
196- std::string content_type;
197- std::string etag;
198- std::string title;
199- std::string date; // ISO date string. Should this be time since epoch?
200- std::string author;
201- std::string album;
202- std::string album_artist;
203- std::string genre;
204- int disc_number;
205- int track_number;
206- int duration; // In seconds.
207- MediaType type;
208+ MediaFilePrivate *p;
209 };
210
211 }
212
213=== modified file 'src/mediascanner/MediaFileBuilder.cc'
214--- src/mediascanner/MediaFileBuilder.cc 2014-05-06 03:13:10 +0000
215+++ src/mediascanner/MediaFileBuilder.cc 2014-05-15 07:01:32 +0000
216@@ -19,118 +19,84 @@
217
218 #include"MediaFileBuilder.hh"
219 #include"MediaFile.hh"
220-#include<stdexcept>
221+#include"internal/MediaFilePrivate.hh"
222
223 namespace mediascanner {
224
225-MediaFileBuilder::MediaFileBuilder(const std::string &fname) {
226- filename = fname;
227+MediaFileBuilder::MediaFileBuilder(const std::string &fname) :
228+ p(new MediaFilePrivate(fname)) {
229 }
230
231 MediaFileBuilder::MediaFileBuilder(const MediaFile &mf) :
232- type(mf.getType()),
233- filename(mf.getFileName()),
234- content_type(mf.getContentType()),
235- etag(mf.getETag()),
236- title(mf.getTitle()),
237- date(mf.getDate()),
238- author(mf.getAuthor()),
239- album(mf.getAlbum()),
240- album_artist(mf.getAlbumArtist()),
241- genre(mf.getGenre()),
242- disc_number(mf.getDiscNumber()),
243- track_number(mf.getTrackNumber()),
244- duration(mf.getDuration()) {
245+ p(new MediaFilePrivate(*mf.p)) {
246+}
247+
248+MediaFileBuilder::~MediaFileBuilder() {
249+ delete p;
250 }
251
252 MediaFile MediaFileBuilder::build() const {
253- return MediaFile(filename, content_type, etag, title, date, author,
254- album, album_artist, genre, disc_number, track_number, duration, type);
255-}
256-
257-void MediaFileBuilder::setType(MediaType t) {
258- if(type_set)
259- throw std::invalid_argument("Tried to set type when it was already set.");
260- type = t;
261- type_set = true;
262-}
263-
264-void MediaFileBuilder::setETag(const std::string &e) {
265- if(etag_set)
266- throw std::invalid_argument("Tried to set filename when it was already set.");
267- etag = e;
268- etag_set = true;
269-
270-}
271-void MediaFileBuilder::setContentType(const std::string &c) {
272- if(content_type_set)
273- throw std::invalid_argument("Tried to set filename when it was already set.");
274- content_type = c;
275- content_type_set = true;
276-
277-}
278-
279-void MediaFileBuilder::setTitle(const std::string &t) {
280- if(title_set)
281- throw std::invalid_argument("Tried to set title when it was already set.");
282- title = t;
283- title_set = true;
284-}
285-
286-void MediaFileBuilder::setDate(const std::string &d) {
287- if(date_set)
288- throw std::invalid_argument("Tried to set date when it was already set.");
289- date = d;
290- date_set = true;
291-}
292-
293-void MediaFileBuilder::setAuthor(const std::string &a) {
294- if(author_set)
295- throw std::invalid_argument("Tried to set author when it was already set.");
296- author = a;
297- author_set = true;
298-}
299-
300-void MediaFileBuilder::setAlbum(const std::string &a) {
301- if(album_set)
302- throw std::invalid_argument("Tried to set album when it was already set.");
303- album = a;
304- album_set = true;
305-}
306-
307-void MediaFileBuilder::setAlbumArtist(const std::string &a) {
308- if(album_artist_set)
309- throw std::invalid_argument("Tried to set album artist when it was already set.");
310- album_artist = a;
311- album_artist_set = true;
312-}
313-
314-void MediaFileBuilder::setGenre(const std::string &g) {
315- if(genre_set)
316- throw std::invalid_argument("Tried to set genre when it was already set.");
317- genre = g;
318- genre_set = true;
319-}
320-
321-void MediaFileBuilder::setDiscNumber(int n) {
322- if(disc_number_set)
323- throw std::invalid_argument("Tried to set disc number when it was already set.");
324- disc_number = n;
325- disc_number_set = true;
326-}
327-
328-void MediaFileBuilder::setTrackNumber(int n) {
329- if(track_number_set)
330- throw std::invalid_argument("Tried to set track number when it was already set.");
331- track_number = n;
332- track_number_set = true;
333-}
334-
335-void MediaFileBuilder::setDuration(int n) {
336- if(duration_set)
337- throw std::invalid_argument("Tried to set duration when it was already set.");
338- duration = n;
339- duration_set = true;
340+ return MediaFile(*this);
341+}
342+
343+MediaFileBuilder &MediaFileBuilder::setType(MediaType t) {
344+ p->type = t;
345+ return *this;
346+}
347+
348+MediaFileBuilder &MediaFileBuilder::setETag(const std::string &e) {
349+ p->etag = e;
350+ return *this;
351+}
352+
353+MediaFileBuilder &MediaFileBuilder::setContentType(const std::string &c) {
354+ p->content_type = c;
355+ return *this;
356+}
357+
358+MediaFileBuilder &MediaFileBuilder::setTitle(const std::string &t) {
359+ p->title = t;
360+ return *this;
361+}
362+
363+MediaFileBuilder &MediaFileBuilder::setDate(const std::string &d) {
364+ p->date = d;
365+ return *this;
366+}
367+
368+MediaFileBuilder &MediaFileBuilder::setAuthor(const std::string &a) {
369+ p->author = a;
370+ return *this;
371+}
372+
373+MediaFileBuilder &MediaFileBuilder::setAlbum(const std::string &a) {
374+ p->album = a;
375+ return *this;
376+}
377+
378+MediaFileBuilder &MediaFileBuilder::setAlbumArtist(const std::string &a) {
379+ p->album_artist = a;
380+ return *this;
381+}
382+
383+MediaFileBuilder &MediaFileBuilder::setGenre(const std::string &g) {
384+ p->genre = g;
385+ return *this;
386+}
387+
388+MediaFileBuilder &MediaFileBuilder::setDiscNumber(int n) {
389+ p->disc_number = n;
390+ return *this;
391+}
392+
393+MediaFileBuilder &MediaFileBuilder::setTrackNumber(int n) {
394+ p->track_number = n;
395+ return *this;
396+}
397+
398+MediaFileBuilder &MediaFileBuilder::setDuration(int n) {
399+ p->duration = n;
400+ return *this;
401 }
402
403 }
404
405=== modified file 'src/mediascanner/MediaFileBuilder.hh'
406--- src/mediascanner/MediaFileBuilder.hh 2014-05-06 03:13:10 +0000
407+++ src/mediascanner/MediaFileBuilder.hh 2014-05-15 07:01:32 +0000
408@@ -26,6 +26,7 @@
409 namespace mediascanner {
410
411 class MediaFile;
412+struct MediaFilePrivate;
413
414 /**
415 * This is a helper class to build MediaFiles. Since we want MediaFiles
416@@ -33,73 +34,34 @@
417 * all variables in the constructor. This is cumbersome so this class
418 * allows you to gather them one by one and then finally construct
419 * a fully valid MediaFile.
420- *
421- * If you try to assign the same property twice, an exception is thrown.
422- * This means that MediaFileBuilders are meant to build only one
423- * MediaFile. To build a new one create a new MediaFileBuilder. This is to
424- * ensure that no state leaks from the first MediaFile to the second.
425 */
426
427 class MediaFileBuilder final {
428+ friend class MediaFile;
429 public:
430 MediaFileBuilder(const std::string &filename);
431 MediaFileBuilder(const MediaFile &mf);
432 MediaFileBuilder(const MediaFileBuilder &) = delete;
433 MediaFileBuilder& operator=(MediaFileBuilder &) = delete;
434+ ~MediaFileBuilder();
435
436 MediaFile build() const;
437
438- void setType(MediaType t);
439- void setETag(const std::string &e);
440- void setContentType(const std::string &c);
441- void setTitle(const std::string &t);
442- void setDate(const std::string &d);
443- void setAuthor(const std::string &a);
444- void setAlbum(const std::string &a);
445- void setAlbumArtist(const std::string &a);
446- void setGenre(const std::string &g);
447- void setDiscNumber(int n);
448- void setTrackNumber(int n);
449- void setDuration(int d);
450+ MediaFileBuilder &setType(MediaType t);
451+ MediaFileBuilder &setETag(const std::string &e);
452+ MediaFileBuilder &setContentType(const std::string &c);
453+ MediaFileBuilder &setTitle(const std::string &t);
454+ MediaFileBuilder &setDate(const std::string &d);
455+ MediaFileBuilder &setAuthor(const std::string &a);
456+ MediaFileBuilder &setAlbum(const std::string &a);
457+ MediaFileBuilder &setAlbumArtist(const std::string &a);
458+ MediaFileBuilder &setGenre(const std::string &g);
459+ MediaFileBuilder &setDiscNumber(int n);
460+ MediaFileBuilder &setTrackNumber(int n);
461+ MediaFileBuilder &setDuration(int d);
462
463 private:
464- bool type_set = false;
465- MediaType type = UnknownMedia;
466-
467- std::string filename;
468-
469- bool content_type_set = false;
470- std::string content_type;
471-
472- bool etag_set = false;
473- std::string etag;
474-
475- bool title_set = false;
476- std::string title;
477-
478- bool date_set = false;
479- std::string date;
480-
481- bool author_set = false;
482- std::string author;
483-
484- bool album_set = false;
485- std::string album;
486-
487- bool album_artist_set = false;
488- std::string album_artist;
489-
490- bool genre_set = false;
491- std::string genre;
492-
493- bool disc_number_set = false;
494- int disc_number = 0;
495-
496- bool track_number_set = false;
497- int track_number = 0;
498-
499- bool duration_set = false;
500- int duration = 0;
501+ MediaFilePrivate *p;
502 };
503
504 }
505
506=== added file 'src/mediascanner/MediaFilePrivate.cc'
507--- src/mediascanner/MediaFilePrivate.cc 1970-01-01 00:00:00 +0000
508+++ src/mediascanner/MediaFilePrivate.cc 2014-05-15 07:01:32 +0000
509@@ -0,0 +1,71 @@
510+/*
511+ * Copyright (C) 2014 Canonical, Ltd.
512+ *
513+ * Authors:
514+ * James Henstridge <james.henstridge@canonical.com>
515+ * Jussi Pakkanen <jussi.pakkanen@canonical.com>
516+ *
517+ * This program is free software: you can redistribute it and/or modify
518+ * it under the terms of the GNU Lesser General Public License version 3 as
519+ * published by the Free Software Foundation.
520+ *
521+ * This program is distributed in the hope that it will be useful,
522+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
523+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
524+ * GNU Lesser General Public License for more details.
525+ *
526+ * You should have received a copy of the GNU Lesser General Public License
527+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
528+ */
529+
530+#include "scannercore.hh"
531+#include "internal/MediaFilePrivate.hh"
532+#include "internal/utils.hh"
533+
534+namespace mediascanner {
535+
536+MediaFilePrivate::MediaFilePrivate() :
537+ disc_number(0), track_number(0), duration(0), type(UnknownMedia) {
538+}
539+
540+MediaFilePrivate::MediaFilePrivate(const std::string &filename) :
541+ filename(filename),
542+ disc_number(0), track_number(0), duration(0), type(UnknownMedia) {
543+}
544+
545+MediaFilePrivate::MediaFilePrivate(const MediaFilePrivate &other) {
546+ *this = other;
547+}
548+
549+bool MediaFilePrivate::operator==(const MediaFilePrivate &other) const {
550+ return
551+ filename == other.filename &&
552+ content_type == other.content_type &&
553+ etag == other.etag &&
554+ title == other.title &&
555+ author == other.author &&
556+ album == other.album &&
557+ album_artist == other.album_artist &&
558+ date == other.date &&
559+ genre == other.genre &&
560+ disc_number == other.disc_number &&
561+ track_number == other.track_number &&
562+ duration == other.duration &&
563+ type == other.type;
564+}
565+
566+bool MediaFilePrivate::operator!=(const MediaFilePrivate &other) const {
567+ return !(*this == other);
568+}
569+
570+void MediaFilePrivate::setFallbackMetadata() {
571+ if (title.empty()) {
572+ title = filenameToTitle(filename);
573+ }
574+ if (album_artist.empty()) {
575+ album_artist = author;
576+ }
577+}
578+
579+
580+}
581
582=== modified file 'src/mediascanner/MediaStore.cc'
583--- src/mediascanner/MediaStore.cc 2014-05-06 03:22:50 +0000
584+++ src/mediascanner/MediaStore.cc 2014-05-15 07:01:32 +0000
585@@ -29,8 +29,9 @@
586 #include <sqlite3.h>
587
588 #include "mozilla/fts3_tokenizer.h"
589-#include"MediaStore.hh"
590-#include"MediaFile.hh"
591+#include "MediaStore.hh"
592+#include "MediaFile.hh"
593+#include "MediaFileBuilder.hh"
594 #include "Album.hh"
595 #include "internal/sqliteutils.hh"
596 #include "internal/utils.hh"
597@@ -288,21 +289,14 @@
598
599 void MediaStorePrivate::insert(const MediaFile &m) const {
600 Statement query(db, "INSERT OR REPLACE INTO media (filename, content_type, etag, title, date, artist, album, album_artist, genre, disc_number, track_number, duration, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
601- string fname = m.getFileName();
602- string title = m.getTitle();
603- if(title.empty())
604- title = filenameToTitle(fname);
605- query.bind(1, fname);
606+ query.bind(1, m.getFileName());
607 query.bind(2, m.getContentType());
608 query.bind(3, m.getETag());
609- query.bind(4, title);
610+ query.bind(4, m.getTitle());
611 query.bind(5, m.getDate());
612 query.bind(6, m.getAuthor());
613 query.bind(7, m.getAlbum());
614- string album_artist = m.getAlbumArtist();
615- if (album_artist.empty())
616- album_artist = m.getAuthor();
617- query.bind(8, album_artist);
618+ query.bind(8, m.getAlbumArtist());
619 query.bind(9, m.getGenre());
620 query.bind(10, m.getDiscNumber());
621 query.bind(11, m.getTrackNumber());
622@@ -313,7 +307,7 @@
623 const char *typestr = m.getType() == AudioMedia ? "song" : "video";
624 printf("Added %s to backing store: %s\n", typestr, m.getFileName().c_str());
625 printf(" author : '%s'\n", m.getAuthor().c_str());
626- printf(" title : %s\n", title.c_str());
627+ printf(" title : %s\n", m.getTitle().c_str());
628 printf(" album : '%s'\n", m.getAlbum().c_str());
629 printf(" duration : %d\n", m.getDuration());
630 }
631@@ -325,20 +319,19 @@
632 }
633
634 static MediaFile make_media(Statement &query) {
635- const string filename = query.getText(0);
636- const string content_type = query.getText(1);
637- const string etag = query.getText(2);
638- const string title = query.getText(3);
639- const string date = query.getText(4);
640- const string author = query.getText(5);
641- const string album = query.getText(6);
642- const string album_artist = query.getText(7);
643- const string genre = query.getText(8);
644- int disc_number = query.getInt(9);
645- int track_number = query.getInt(10);
646- int duration = query.getInt(11);
647- MediaType type = (MediaType)query.getInt(12);
648- return MediaFile(filename, content_type, etag, title, date, author, album, album_artist, genre, disc_number, track_number, duration, type);
649+ return MediaFileBuilder(query.getText(0))
650+ .setContentType(query.getText(1))
651+ .setETag(query.getText(2))
652+ .setTitle(query.getText(3))
653+ .setDate(query.getText(4))
654+ .setAuthor(query.getText(5))
655+ .setAlbum(query.getText(6))
656+ .setAlbumArtist(query.getText(7))
657+ .setGenre(query.getText(8))
658+ .setDiscNumber(query.getInt(9))
659+ .setTrackNumber(query.getInt(10))
660+ .setDuration(query.getInt(11))
661+ .setType((MediaType)query.getInt(12));
662 }
663
664 static vector<MediaFile> collect_media(Statement &query) {
665
666=== added file 'src/mediascanner/internal/MediaFilePrivate.hh'
667--- src/mediascanner/internal/MediaFilePrivate.hh 1970-01-01 00:00:00 +0000
668+++ src/mediascanner/internal/MediaFilePrivate.hh 2014-05-15 07:01:32 +0000
669@@ -0,0 +1,54 @@
670+/*
671+ * Copyright (C) 2013 Canonical, Ltd.
672+ *
673+ * Authors:
674+ * James Henstridge <james.henstridge@canonical.com>
675+ *
676+ * This program is free software: you can redistribute it and/or modify
677+ * it under the terms of the GNU Lesser General Public License version 3 as
678+ * published by the Free Software Foundation.
679+ *
680+ * This program is distributed in the hope that it will be useful,
681+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
682+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
683+ * GNU Lesser General Public License for more details.
684+ *
685+ * You should have received a copy of the GNU Lesser General Public License
686+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
687+ */
688+
689+#ifndef MEDIAFILEPRIVATE_HH
690+#define MEDIAFILEPRIVATE_HH
691+
692+#include <string>
693+
694+namespace mediascanner {
695+
696+struct MediaFilePrivate {
697+ std::string filename;
698+ std::string content_type;
699+ std::string etag;
700+ std::string title;
701+ std::string date; // ISO date string. Should this be time since epoch?
702+ std::string author;
703+ std::string album;
704+ std::string album_artist;
705+ std::string genre;
706+ int disc_number;
707+ int track_number;
708+ int duration; // In seconds.
709+ MediaType type;
710+
711+ MediaFilePrivate();
712+ MediaFilePrivate(const std::string &filename);
713+ MediaFilePrivate(const MediaFilePrivate &other);
714+
715+ bool operator==(const MediaFilePrivate &other) const;
716+ bool operator!=(const MediaFilePrivate &other) const;
717+
718+ void setFallbackMetadata();
719+};
720+
721+}
722+
723+#endif
724
725=== modified file 'src/utils/scaletest.cc'
726--- src/utils/scaletest.cc 2014-05-06 03:13:10 +0000
727+++ src/utils/scaletest.cc 2014-05-15 07:01:32 +0000
728@@ -19,6 +19,7 @@
729
730 #include "mediascanner/MediaStore.hh"
731 #include "mediascanner/MediaFile.hh"
732+#include "mediascanner/MediaFileBuilder.hh"
733 #include "mediascanner/internal/utils.hh"
734
735 #include<vector>
736@@ -84,7 +85,15 @@
737 track += " " + RNDWORD;
738 }
739 string fname = to_string(i) + ".mp3";
740- MediaFile mf(fname, "audio/mp3", "", track, "2013-01-01", artist, album, artist, "", 0, trackCount, rnd() % 300, AudioMedia);
741+ MediaFile mf = MediaFileBuilder(fname)
742+ .setType(AudioMedia)
743+ .setContentType("audio/mp3")
744+ .setTitle(track)
745+ .setDate("2013-01-01")
746+ .setAuthor(artist)
747+ .setAlbum(album)
748+ .setTrackNumber(trackCount)
749+ .setDuration(rnd() % 300);
750 store.insert(mf);
751 i++;
752 //printf("%s, %s, %s\n", artist.c_str(), album.c_str(), track.c_str());
753
754=== modified file 'test/test_mediastore.cc'
755--- test/test_mediastore.cc 2014-05-06 03:13:10 +0000
756+++ test/test_mediastore.cc 2014-05-15 07:01:32 +0000
757@@ -18,6 +18,7 @@
758 */
759
760 #include <mediascanner/MediaFile.hh>
761+#include <mediascanner/MediaFileBuilder.hh>
762 #include <mediascanner/Album.hh>
763 #include <mediascanner/MediaStore.hh>
764 #include <mediascanner/internal/utils.hh>
765@@ -49,16 +50,64 @@
766 MediaStore store(":memory:", MS_READ_WRITE);
767 }
768 TEST_F(MediaStoreTest, mediafile_uri) {
769- MediaFile media("/path/to/file.ogg");
770+ MediaFile media = MediaFileBuilder("/path/to/file.ogg");
771 EXPECT_EQ(media.getUri(), "file:///path/to/file.ogg");
772 }
773
774 TEST_F(MediaStoreTest, equality) {
775- MediaFile audio1("a", "type", "etag", "1900", "b", "c", "d", "e", "f", 0, 1, 5, AudioMedia);
776- MediaFile audio2("aa", "type", "etag", "1900", "b", "c", "d", "e", "f", 0, 1, 5, AudioMedia);
777+ MediaFile audio1 = MediaFileBuilder("a")
778+ .setContentType("type")
779+ .setETag("etag")
780+ .setDate("1900")
781+ .setTitle("b")
782+ .setAuthor("c")
783+ .setAlbum("d")
784+ .setAlbumArtist("e")
785+ .setGenre("f")
786+ .setDiscNumber(0)
787+ .setTrackNumber(1)
788+ .setDuration(5)
789+ .setType(AudioMedia);
790+ MediaFile audio2 = MediaFileBuilder("aa")
791+ .setContentType("type")
792+ .setETag("etag")
793+ .setDate("1900")
794+ .setTitle("b")
795+ .setAuthor("c")
796+ .setAlbum("d")
797+ .setAlbumArtist("e")
798+ .setGenre("f")
799+ .setDiscNumber(0)
800+ .setTrackNumber(1)
801+ .setDuration(5)
802+ .setType(AudioMedia);
803
804- MediaFile video1("a", "type", "etag", "b", "1900", "c", "d", "e", "f", 0, 0, 5, VideoMedia);
805- MediaFile video2("aa", "type", "etag", "b", "1900", "c", "d", "e", "f", 0, 0, 5, VideoMedia);
806+ MediaFile video1 = MediaFileBuilder("a")
807+ .setContentType("type")
808+ .setETag("etag")
809+ .setDate("1900")
810+ .setTitle("b")
811+ .setAuthor("c")
812+ .setAlbum("d")
813+ .setAlbumArtist("e")
814+ .setGenre("f")
815+ .setDiscNumber(0)
816+ .setTrackNumber(1)
817+ .setDuration(5)
818+ .setType(VideoMedia);
819+ MediaFile video2 = MediaFileBuilder("aa")
820+ .setContentType("type")
821+ .setETag("etag")
822+ .setDate("1900")
823+ .setTitle("b")
824+ .setAuthor("c")
825+ .setAlbum("d")
826+ .setAlbumArtist("e")
827+ .setGenre("f")
828+ .setDiscNumber(0)
829+ .setTrackNumber(1)
830+ .setDuration(5)
831+ .setType(VideoMedia);
832
833 EXPECT_EQ(audio1, audio1);
834 EXPECT_EQ(video1, video1);
835@@ -70,7 +119,19 @@
836 }
837
838 TEST_F(MediaStoreTest, lookup) {
839- MediaFile audio("aaa", "type", "etag", "bbb bbb", "1900-01-01", "ccc", "ddd", "eee", "fff", 0, 3, 5, AudioMedia);
840+ MediaFile audio = MediaFileBuilder("aaa")
841+ .setContentType("type")
842+ .setETag("etag")
843+ .setDate("1900-01-01")
844+ .setTitle("bbb bbb")
845+ .setAuthor("ccc")
846+ .setAlbum("ddd")
847+ .setAlbumArtist("eee")
848+ .setGenre("fff")
849+ .setDiscNumber(0)
850+ .setTrackNumber(3)
851+ .setDuration(5)
852+ .setType(AudioMedia);
853 MediaStore store(":memory:", MS_READ_WRITE);
854 store.insert(audio);
855
856@@ -79,8 +140,32 @@
857 }
858
859 TEST_F(MediaStoreTest, roundtrip) {
860- MediaFile audio("aaa", "type", "etag", "bbb bbb", "1900-01-01", "ccc", "ddd", "eee", "fff", 0, 3, 5, AudioMedia);
861- MediaFile video("aaa2", "type", "etag", "bbb bbb", "2012-01-01", "ccc", "ddd", "eee", "fff", 0, 0, 5, VideoMedia);
862+ MediaFile audio = MediaFileBuilder("aaa")
863+ .setContentType("type")
864+ .setETag("etag")
865+ .setDate("1900-01-01")
866+ .setTitle("bbb bbb")
867+ .setAuthor("ccc")
868+ .setAlbum("ddd")
869+ .setAlbumArtist("eee")
870+ .setGenre("fff")
871+ .setDiscNumber(0)
872+ .setTrackNumber(3)
873+ .setDuration(5)
874+ .setType(AudioMedia);
875+ MediaFile video = MediaFileBuilder("aaa2")
876+ .setContentType("type")
877+ .setETag("etag")
878+ .setDate("2012-01-01")
879+ .setTitle("bbb bbb")
880+ .setAuthor("ccc")
881+ .setAlbum("ddd")
882+ .setAlbumArtist("eee")
883+ .setGenre("fff")
884+ .setDiscNumber(0)
885+ .setTrackNumber(0)
886+ .setDuration(5)
887+ .setType(VideoMedia);
888 MediaStore store(":memory:", MS_READ_WRITE);
889 store.insert(audio);
890 store.insert(video);
891@@ -93,7 +178,12 @@
892 }
893
894 TEST_F(MediaStoreTest, query_by_album) {
895- MediaFile audio("/path/foo.ogg", "", "", "title", "1900-01-01", "artist", "album", "albumartist", "genre", 0, 3, 5, AudioMedia);
896+ MediaFile audio = MediaFileBuilder("/path/foo.ogg")
897+ .setType(AudioMedia)
898+ .setTitle("title")
899+ .setAuthor("artist")
900+ .setAlbum("album")
901+ .setAlbumArtist("albumartist");
902 MediaStore store(":memory:", MS_READ_WRITE);
903 store.insert(audio);
904
905@@ -103,7 +193,12 @@
906 }
907
908 TEST_F(MediaStoreTest, query_by_artist) {
909- MediaFile audio("/path/foo.ogg", "", "", "title", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
910+ MediaFile audio = MediaFileBuilder("/path/foo.ogg")
911+ .setType(AudioMedia)
912+ .setTitle("title")
913+ .setAuthor("artist")
914+ .setAlbum("album")
915+ .setAlbumArtist("albumartist");
916 MediaStore store(":memory:", MS_READ_WRITE);
917 store.insert(audio);
918
919@@ -113,11 +208,36 @@
920 }
921
922 TEST_F(MediaStoreTest, query_ranking) {
923- MediaFile audio1("/path/foo1.ogg", "", "", "title", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
924- MediaFile audio2("/path/foo2.ogg", "", "", "title aaa", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
925- MediaFile audio3("/path/foo3.ogg", "", "", "title", "1900-01-01", "artist aaa", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
926- MediaFile audio4("/path/foo4.ogg", "", "", "title", "1900-01-01", "artist", "album aaa", "albumartist", "genre", 1, 3, 5, AudioMedia);
927- MediaFile audio5("/path/foo5.ogg", "", "", "title aaa", "1900-01-01", "artist aaa", "album aaa", "albumartist", "genre", 1, 3, 5, AudioMedia);
928+ MediaFile audio1 = MediaFileBuilder("/path/foo1.ogg")
929+ .setType(AudioMedia)
930+ .setTitle("title")
931+ .setAuthor("artist")
932+ .setAlbum("album")
933+ .setAlbumArtist("albumartist");
934+ MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg")
935+ .setType(AudioMedia)
936+ .setTitle("title aaa")
937+ .setAuthor("artist")
938+ .setAlbum("album")
939+ .setAlbumArtist("albumartist");
940+ MediaFile audio3 = MediaFileBuilder("/path/foo3.ogg")
941+ .setType(AudioMedia)
942+ .setTitle("title")
943+ .setAuthor("artist aaa")
944+ .setAlbum("album")
945+ .setAlbumArtist("albumartist");
946+ MediaFile audio4 = MediaFileBuilder("/path/foo4.ogg")
947+ .setType(AudioMedia)
948+ .setTitle("title")
949+ .setAuthor("artist")
950+ .setAlbum("album aaa")
951+ .setAlbumArtist("albumartist");
952+ MediaFile audio5 = MediaFileBuilder("/path/foo5.ogg")
953+ .setType(AudioMedia)
954+ .setTitle("title aaa")
955+ .setAuthor("artist aaa")
956+ .setAlbum("album aaa")
957+ .setAlbumArtist("albumartist");
958
959 MediaStore store(":memory:", MS_READ_WRITE);
960 store.insert(audio1);
961@@ -135,9 +255,24 @@
962 }
963
964 TEST_F(MediaStoreTest, query_limit) {
965- MediaFile audio1("/path/foo5.ogg", "", "", "title aaa", "1900-01-01", "artist aaa", "album aaa", "albumartist", "genre", 1, 3, 5, AudioMedia);
966- MediaFile audio2("/path/foo2.ogg", "", "", "title aaa", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
967- MediaFile audio3("/path/foo4.ogg", "", "", "title", "1900-01-01", "artist", "album aaa", "albumartist", "genre", 1, 3, 5, AudioMedia);
968+ MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg")
969+ .setType(AudioMedia)
970+ .setTitle("title aaa")
971+ .setAuthor("artist aaa")
972+ .setAlbum("album aaa")
973+ .setAlbumArtist("albumartist");
974+ MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg")
975+ .setType(AudioMedia)
976+ .setTitle("title aaa")
977+ .setAuthor("artist")
978+ .setAlbum("album")
979+ .setAlbumArtist("albumartist");
980+ MediaFile audio3 = MediaFileBuilder("/path/foo4.ogg")
981+ .setType(AudioMedia)
982+ .setTitle("title")
983+ .setAuthor("artist")
984+ .setAlbum("album aaa")
985+ .setAlbumArtist("albumartist");
986
987 MediaStore store(":memory:", MS_READ_WRITE);
988 store.insert(audio1);
989@@ -151,8 +286,18 @@
990 }
991
992 TEST_F(MediaStoreTest, query_short) {
993- MediaFile audio1("/path/foo5.ogg", "", "", "title xyz", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
994- MediaFile audio2("/path/foo2.ogg", "", "", "title xzy", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
995+ MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg")
996+ .setType(AudioMedia)
997+ .setTitle("title xyz")
998+ .setAuthor("artist")
999+ .setAlbum("album")
1000+ .setAlbumArtist("albumartist");
1001+ MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg")
1002+ .setType(AudioMedia)
1003+ .setTitle("title xzy")
1004+ .setAuthor("artist")
1005+ .setAlbum("album")
1006+ .setAlbumArtist("albumartist");
1007
1008 MediaStore store(":memory:", MS_READ_WRITE);
1009 store.insert(audio1);
1010@@ -165,9 +310,24 @@
1011 }
1012
1013 TEST_F(MediaStoreTest, query_empty) {
1014- MediaFile audio1("/path/foo5.ogg", "", "", "title aaa", "1900-01-01", "artist aaa", "album aaa", "albumartist", "genre", 1, 3, 5, AudioMedia);
1015- MediaFile audio2("/path/foo2.ogg", "", "", "title aaa", "1900-01-01", "artist", "album", "albumartist", "genre", 1, 3, 5, AudioMedia);
1016- MediaFile audio3("/path/foo4.ogg", "", "", "title", "1900-01-01", "artist", "album aaa", "albumartist", "genre", 1, 3, 5, AudioMedia);
1017+ MediaFile audio1 = MediaFileBuilder("/path/foo5.ogg")
1018+ .setType(AudioMedia)
1019+ .setTitle("title aaa")
1020+ .setAuthor("artist aaa")
1021+ .setAlbum("album aaa")
1022+ .setAlbumArtist("albumartist");
1023+ MediaFile audio2 = MediaFileBuilder("/path/foo2.ogg")
1024+ .setType(AudioMedia)
1025+ .setTitle("title aaa")
1026+ .setAuthor("artist")
1027+ .setAlbum("album")
1028+ .setAlbumArtist("albumartist");
1029+ MediaFile audio3 = MediaFileBuilder("/path/foo4.ogg")
1030+ .setType(AudioMedia)
1031+ .setTitle("title")
1032+ .setAuthor("artist")
1033+ .setAlbum("album aaa")
1034+ .setAlbumArtist("albumartist");
1035
1036 MediaStore store(":memory:", MS_READ_WRITE);
1037 store.insert(audio1);
1038@@ -180,8 +340,12 @@
1039 }
1040
1041 TEST_F(MediaStoreTest, unmount) {
1042- MediaFile audio1("/media/username/dir/fname.ogg", "", "", "bbb bbb", "2000-01-01", "ccc", "ddd", "eee", "ffff", 0, 1, 5, AudioMedia);
1043- MediaFile audio2("/home/username/Music/fname.ogg", "", "", "bbb bbb", "1900-01-01", "ccc", "ddd", "eee", "ffff", 0, 42, 5, AudioMedia);
1044+ MediaFile audio1 = MediaFileBuilder("/media/username/dir/fname.ogg")
1045+ .setType(AudioMedia)
1046+ .setTitle("bbb bbb");
1047+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/fname.ogg")
1048+ .setType(AudioMedia)
1049+ .setTitle("bbb bbb");
1050 MediaStore store(":memory:", MS_READ_WRITE);
1051 store.insert(audio1);
1052 store.insert(audio2);
1053@@ -210,10 +374,37 @@
1054 }
1055
1056 TEST_F(MediaStoreTest, queryAlbums) {
1057- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1058- MediaFile audio2("/home/username/Music/track2.ogg", "", "", "TitleTwo", "1900-01-01", "ArtistTwo", "AlbumOne", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1059- MediaFile audio3("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistThree", "AlbumOne", "Various Artists", "genre", 1, 3, 5, AudioMedia);
1060- MediaFile audio4("/home/username/Music/fname.ogg", "", "", "TitleFour", "1900-01-01", "ArtistFour", "AlbumTwo", "ArtistFour", "genre", 1, 1, 5, AudioMedia);
1061+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1062+ .setType(AudioMedia)
1063+ .setTitle("TitleOne")
1064+ .setAuthor("ArtistOne")
1065+ .setAlbum("AlbumOne")
1066+ .setAlbumArtist("Various Artists")
1067+ .setDiscNumber(1)
1068+ .setTrackNumber(1);
1069+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg")
1070+ .setType(AudioMedia)
1071+ .setTitle("TitleTwo")
1072+ .setAuthor("ArtistTwo")
1073+ .setAlbum("AlbumOne")
1074+ .setAlbumArtist("Various Artists")
1075+ .setDiscNumber(1)
1076+ .setTrackNumber(2);
1077+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg")
1078+ .setType(AudioMedia)
1079+ .setTitle("TitleThree")
1080+ .setAuthor("ArtistThree")
1081+ .setAlbum("AlbumOne")
1082+ .setAlbumArtist("Various Artists")
1083+ .setDiscNumber(2)
1084+ .setTrackNumber(1);
1085+ MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg")
1086+ .setType(AudioMedia)
1087+ .setTitle("TitleFour")
1088+ .setAuthor("ArtistFour")
1089+ .setAlbum("AlbumTwo")
1090+ .setAlbumArtist("ArtistFour")
1091+ .setTrackNumber(1);
1092
1093 MediaStore store(":memory:", MS_READ_WRITE);
1094 store.insert(audio1);
1095@@ -241,10 +432,37 @@
1096 }
1097
1098 TEST_F(MediaStoreTest, queryAlbums_limit) {
1099- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1100- MediaFile audio2("/home/username/Music/track2.ogg", "", "", "TitleTwo", "1900-01-01", "ArtistTwo", "AlbumOne", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1101- MediaFile audio3("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistThree", "AlbumOne", "Various Artists", "genre", 1, 3, 5, AudioMedia);
1102- MediaFile audio4("/home/username/Music/fname.ogg", "", "", "TitleFour", "1900-01-01", "ArtistFour", "AlbumTwo", "ArtistFour", "genre", 1, 1, 5, AudioMedia);
1103+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1104+ .setType(AudioMedia)
1105+ .setTitle("TitleOne")
1106+ .setAuthor("ArtistOne")
1107+ .setAlbum("AlbumOne")
1108+ .setAlbumArtist("Various Artists")
1109+ .setDiscNumber(1)
1110+ .setTrackNumber(1);
1111+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg")
1112+ .setType(AudioMedia)
1113+ .setTitle("TitleTwo")
1114+ .setAuthor("ArtistTwo")
1115+ .setAlbum("AlbumOne")
1116+ .setAlbumArtist("Various Artists")
1117+ .setDiscNumber(1)
1118+ .setTrackNumber(2);
1119+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg")
1120+ .setType(AudioMedia)
1121+ .setTitle("TitleThree")
1122+ .setAuthor("ArtistThree")
1123+ .setAlbum("AlbumOne")
1124+ .setAlbumArtist("Various Artists")
1125+ .setDiscNumber(2)
1126+ .setTrackNumber(1);
1127+ MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg")
1128+ .setType(AudioMedia)
1129+ .setTitle("TitleFour")
1130+ .setAuthor("ArtistFour")
1131+ .setAlbum("AlbumTwo")
1132+ .setAlbumArtist("ArtistFour")
1133+ .setTrackNumber(1);
1134
1135 MediaStore store(":memory:", MS_READ_WRITE);
1136 store.insert(audio1);
1137@@ -259,10 +477,37 @@
1138 }
1139
1140 TEST_F(MediaStoreTest, queryAlbums_empty) {
1141- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1142- MediaFile audio2("/home/username/Music/track2.ogg", "", "", "TitleTwo", "1900-01-01", "ArtistTwo", "AlbumOne", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1143- MediaFile audio3("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistThree", "AlbumOne", "Various Artists", "genre", 1, 3, 5, AudioMedia);
1144- MediaFile audio4("/home/username/Music/fname.ogg", "", "", "TitleFour", "1900-01-01", "ArtistFour", "AlbumTwo", "ArtistFour", "genre", 1, 1, 5, AudioMedia);
1145+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1146+ .setType(AudioMedia)
1147+ .setTitle("TitleOne")
1148+ .setAuthor("ArtistOne")
1149+ .setAlbum("AlbumOne")
1150+ .setAlbumArtist("Various Artists")
1151+ .setDiscNumber(1)
1152+ .setTrackNumber(1);
1153+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg")
1154+ .setType(AudioMedia)
1155+ .setTitle("TitleTwo")
1156+ .setAuthor("ArtistTwo")
1157+ .setAlbum("AlbumOne")
1158+ .setAlbumArtist("Various Artists")
1159+ .setDiscNumber(1)
1160+ .setTrackNumber(2);
1161+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg")
1162+ .setType(AudioMedia)
1163+ .setTitle("TitleThree")
1164+ .setAuthor("ArtistThree")
1165+ .setAlbum("AlbumOne")
1166+ .setAlbumArtist("Various Artists")
1167+ .setDiscNumber(2)
1168+ .setTrackNumber(1);
1169+ MediaFile audio4 = MediaFileBuilder("/home/username/Music/fname.ogg")
1170+ .setType(AudioMedia)
1171+ .setTitle("TitleFour")
1172+ .setAuthor("ArtistFour")
1173+ .setAlbum("AlbumTwo")
1174+ .setAlbumArtist("ArtistFour")
1175+ .setTrackNumber(1);
1176
1177 MediaStore store(":memory:", MS_READ_WRITE);
1178 store.insert(audio1);
1179@@ -277,9 +522,30 @@
1180 }
1181
1182 TEST_F(MediaStoreTest, getAlbumSongs) {
1183- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1184- MediaFile audio2("/home/username/Music/track2.ogg", "", "", "TitleTwo", "1900-01-01", "ArtistTwo", "AlbumOne", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1185- MediaFile audio3("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistThree", "AlbumOne", "Various Artists", "genre", 1, 3, 5, AudioMedia);
1186+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1187+ .setType(AudioMedia)
1188+ .setTitle("TitleOne")
1189+ .setAuthor("ArtistOne")
1190+ .setAlbum("AlbumOne")
1191+ .setAlbumArtist("Various Artists")
1192+ .setDiscNumber(1)
1193+ .setTrackNumber(1);
1194+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg")
1195+ .setType(AudioMedia)
1196+ .setTitle("TitleTwo")
1197+ .setAuthor("ArtistTwo")
1198+ .setAlbum("AlbumOne")
1199+ .setAlbumArtist("Various Artists")
1200+ .setDiscNumber(1)
1201+ .setTrackNumber(2);
1202+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg")
1203+ .setType(AudioMedia)
1204+ .setTitle("TitleThree")
1205+ .setAuthor("ArtistThree")
1206+ .setAlbum("AlbumOne")
1207+ .setAlbumArtist("Various Artists")
1208+ .setDiscNumber(2)
1209+ .setTrackNumber(1);
1210
1211 MediaStore store(":memory:", MS_READ_WRITE);
1212 store.insert(audio1);
1213@@ -295,7 +561,8 @@
1214 }
1215
1216 TEST_F(MediaStoreTest, getETag) {
1217- MediaFile file("/path/file.ogg", "audio/ogg", "etag", "title", "2013", "artist", "album", "artist", "genre", 1, 1, 5, AudioMedia);
1218+ MediaFile file = MediaFileBuilder("/path/file.ogg")
1219+ .setETag("etag");
1220
1221 MediaStore store(":memory:", MS_READ_WRITE);
1222 store.insert(file);
1223@@ -305,12 +572,42 @@
1224 }
1225
1226 TEST_F(MediaStoreTest, listSongs) {
1227- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "ArtistOne", "genre", 1, 1, 5, AudioMedia);
1228- MediaFile audio2("/home/username/Music/track2.ogg", "", "", "TitleTwo", "1900-01-01", "ArtistOne", "AlbumOne", "ArtistOne", "genre", 1, 2, 5, AudioMedia);
1229- MediaFile audio3("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistOne", "AlbumTwo", "ArtistOne", "genre", 1, 3, 5, AudioMedia);
1230- MediaFile audio4("/home/username/Music/track4.ogg", "", "", "TitleFour", "1900-01-01", "ArtistTwo", "AlbumThree", "ArtistTwo", "genre", 1, 1, 5, AudioMedia);
1231- MediaFile audio5("/home/username/Music/track5.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumFour", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1232- MediaFile audio6("/home/username/Music/track6.ogg", "", "", "TitleFour", "1900-01-01", "ArtistTwo", "AlbumFour", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1233+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1234+ .setType(AudioMedia)
1235+ .setTitle("TitleOne")
1236+ .setAuthor("ArtistOne")
1237+ .setAlbum("AlbumOne")
1238+ .setTrackNumber(1);
1239+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track2.ogg")
1240+ .setType(AudioMedia)
1241+ .setTitle("TitleTwo")
1242+ .setAuthor("ArtistOne")
1243+ .setAlbum("AlbumOne")
1244+ .setTrackNumber(2);
1245+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track3.ogg")
1246+ .setType(AudioMedia)
1247+ .setTitle("TitleThree")
1248+ .setAuthor("ArtistOne")
1249+ .setAlbum("AlbumTwo");
1250+ MediaFile audio4 = MediaFileBuilder("/home/username/Music/track4.ogg")
1251+ .setType(AudioMedia)
1252+ .setTitle("TitleFour")
1253+ .setAuthor("ArtistTwo")
1254+ .setAlbum("AlbumThree");
1255+ MediaFile audio5 = MediaFileBuilder("/home/username/Music/track5.ogg")
1256+ .setType(AudioMedia)
1257+ .setTitle("TitleFive")
1258+ .setAuthor("ArtistOne")
1259+ .setAlbum("AlbumFour")
1260+ .setAlbumArtist("Various Artists")
1261+ .setTrackNumber(1);
1262+ MediaFile audio6 = MediaFileBuilder("/home/username/Music/track6.ogg")
1263+ .setType(AudioMedia)
1264+ .setTitle("TitleSix")
1265+ .setAuthor("ArtistTwo")
1266+ .setAlbum("AlbumFour")
1267+ .setAlbumArtist("Various Artists")
1268+ .setTrackNumber(2);
1269
1270 MediaStore store(":memory:", MS_READ_WRITE);
1271 store.insert(audio1);
1272@@ -352,11 +649,36 @@
1273 }
1274
1275 TEST_F(MediaStoreTest, listAlbums) {
1276- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "ArtistOne", "genre", 1, 1, 5, AudioMedia);
1277- MediaFile audio2("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistOne", "AlbumTwo", "ArtistOne", "genre", 1, 3, 5, AudioMedia);
1278- MediaFile audio3("/home/username/Music/track4.ogg", "", "", "TitleFour", "1900-01-01", "ArtistTwo", "AlbumThree", "ArtistTwo", "genre", 1, 1, 5, AudioMedia);
1279- MediaFile audio4("/home/username/Music/track5.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumFour", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1280- MediaFile audio5("/home/username/Music/track6.ogg", "", "", "TitleFour", "1900-01-01", "ArtistTwo", "AlbumFour", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1281+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1282+ .setType(AudioMedia)
1283+ .setTitle("TitleOne")
1284+ .setAuthor("ArtistOne")
1285+ .setAlbum("AlbumOne")
1286+ .setTrackNumber(1);
1287+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track3.ogg")
1288+ .setType(AudioMedia)
1289+ .setTitle("TitleThree")
1290+ .setAuthor("ArtistOne")
1291+ .setAlbum("AlbumTwo");
1292+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track4.ogg")
1293+ .setType(AudioMedia)
1294+ .setTitle("TitleFour")
1295+ .setAuthor("ArtistTwo")
1296+ .setAlbum("AlbumThree");
1297+ MediaFile audio4 = MediaFileBuilder("/home/username/Music/track5.ogg")
1298+ .setType(AudioMedia)
1299+ .setTitle("TitleFive")
1300+ .setAuthor("ArtistOne")
1301+ .setAlbum("AlbumFour")
1302+ .setAlbumArtist("Various Artists")
1303+ .setTrackNumber(1);
1304+ MediaFile audio5 = MediaFileBuilder("/home/username/Music/track6.ogg")
1305+ .setType(AudioMedia)
1306+ .setTitle("TitleSix")
1307+ .setAuthor("ArtistTwo")
1308+ .setAlbum("AlbumFour")
1309+ .setAlbumArtist("Various Artists")
1310+ .setTrackNumber(2);
1311
1312 MediaStore store(":memory:", MS_READ_WRITE);
1313 store.insert(audio1);
1314@@ -387,11 +709,36 @@
1315 }
1316
1317 TEST_F(MediaStoreTest, listArtists) {
1318- MediaFile audio1("/home/username/Music/track1.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumOne", "ArtistOne", "genre", 1, 1, 5, AudioMedia);
1319- MediaFile audio2("/home/username/Music/track3.ogg", "", "", "TitleThree", "1900-01-01", "ArtistOne", "AlbumTwo", "ArtistOne", "genre", 1, 3, 5, AudioMedia);
1320- MediaFile audio3("/home/username/Music/track4.ogg", "", "", "TitleFour", "1900-01-01", "ArtistTwo", "AlbumThree", "ArtistTwo", "genre", 1, 1, 5, AudioMedia);
1321- MediaFile audio4("/home/username/Music/track5.ogg", "", "", "TitleOne", "1900-01-01", "ArtistOne", "AlbumFour", "Various Artists", "genre", 1, 1, 5, AudioMedia);
1322- MediaFile audio5("/home/username/Music/track6.ogg", "", "", "TitleFour", "1900-01-01", "ArtistTwo", "AlbumFour", "Various Artists", "genre", 1, 2, 5, AudioMedia);
1323+ MediaFile audio1 = MediaFileBuilder("/home/username/Music/track1.ogg")
1324+ .setType(AudioMedia)
1325+ .setTitle("TitleOne")
1326+ .setAuthor("ArtistOne")
1327+ .setAlbum("AlbumOne")
1328+ .setTrackNumber(1);
1329+ MediaFile audio2 = MediaFileBuilder("/home/username/Music/track3.ogg")
1330+ .setType(AudioMedia)
1331+ .setTitle("TitleThree")
1332+ .setAuthor("ArtistOne")
1333+ .setAlbum("AlbumTwo");
1334+ MediaFile audio3 = MediaFileBuilder("/home/username/Music/track4.ogg")
1335+ .setType(AudioMedia)
1336+ .setTitle("TitleFour")
1337+ .setAuthor("ArtistTwo")
1338+ .setAlbum("AlbumThree");
1339+ MediaFile audio4 = MediaFileBuilder("/home/username/Music/track5.ogg")
1340+ .setType(AudioMedia)
1341+ .setTitle("TitleFive")
1342+ .setAuthor("ArtistOne")
1343+ .setAlbum("AlbumFour")
1344+ .setAlbumArtist("Various Artists")
1345+ .setTrackNumber(1);
1346+ MediaFile audio5 = MediaFileBuilder("/home/username/Music/track6.ogg")
1347+ .setType(AudioMedia)
1348+ .setTitle("TitleSix")
1349+ .setAuthor("ArtistTwo")
1350+ .setAlbum("AlbumFour")
1351+ .setAlbumArtist("Various Artists")
1352+ .setTrackNumber(2);
1353
1354 MediaStore store(":memory:", MS_READ_WRITE);
1355 store.insert(audio1);
1356
1357=== modified file 'test/test_mfbuilder.cc'
1358--- test/test_mfbuilder.cc 2014-01-16 09:36:56 +0000
1359+++ test/test_mfbuilder.cc 2014-05-15 07:01:32 +0000
1360@@ -18,7 +18,6 @@
1361 */
1362
1363 #include<gtest/gtest.h>
1364-#include<stdexcept>
1365 #include"mediascanner/MediaFile.hh"
1366 #include"mediascanner/MediaFileBuilder.hh"
1367
1368@@ -49,40 +48,25 @@
1369 std::string album_artist("pqr");
1370 std::string etag("stu");
1371 std::string content_type("vwx");
1372+ std::string genre("yz");
1373+ int disc_number = 2;
1374 int track_number = 13;
1375 int duration = 99;
1376
1377 MediaFileBuilder b(fname);
1378
1379 b.setType(type);
1380- ASSERT_THROW(b.setType(type), std::invalid_argument);
1381-
1382 b.setTitle(title);
1383- ASSERT_THROW(b.setTitle(fname), std::invalid_argument);
1384-
1385 b.setDate(date);
1386- ASSERT_THROW(b.setDate(date), std::invalid_argument);
1387-
1388 b.setAuthor(author);
1389- ASSERT_THROW(b.setAuthor(author), std::invalid_argument);
1390-
1391 b.setAlbum(album);
1392- ASSERT_THROW(b.setAlbum(album), std::invalid_argument);
1393-
1394 b.setAlbumArtist(album_artist);
1395- ASSERT_THROW(b.setAlbumArtist(album_artist), std::invalid_argument);
1396-
1397+ b.setGenre(genre);
1398+ b.setDiscNumber(disc_number);
1399 b.setTrackNumber(track_number);
1400- ASSERT_THROW(b.setTrackNumber(track_number), std::invalid_argument);
1401-
1402 b.setDuration(duration);
1403- ASSERT_THROW(b.setDuration(duration), std::invalid_argument);
1404-
1405 b.setETag(etag);
1406- ASSERT_THROW(b.setETag(etag), std::invalid_argument);
1407-
1408 b.setContentType(content_type);
1409- ASSERT_THROW(b.setContentType(content_type), std::invalid_argument);
1410
1411 // Now see if data survives a round trip.
1412 MediaFile mf = b.build();
1413@@ -93,6 +77,8 @@
1414 ASSERT_EQ(mf.getAuthor(), author);
1415 ASSERT_EQ(mf.getAlbum(), album);
1416 ASSERT_EQ(mf.getAlbumArtist(), album_artist);
1417+ ASSERT_EQ(mf.getGenre(), genre);
1418+ ASSERT_EQ(mf.getDiscNumber(), disc_number);
1419 ASSERT_EQ(mf.getTrackNumber(), track_number);
1420 ASSERT_EQ(mf.getDuration(), duration);
1421 ASSERT_EQ(mf.getETag(), etag);
1422@@ -103,6 +89,64 @@
1423 ASSERT_EQ(mf, mf2);
1424 }
1425
1426+TEST_F(MFBTest, chaining) {
1427+ MediaType type(AudioMedia);
1428+ std::string fname("abc");
1429+ std::string title("def");
1430+ std::string date("ghi");
1431+ std::string author("jkl");
1432+ std::string album("mno");
1433+ std::string album_artist("pqr");
1434+ std::string etag("stu");
1435+ std::string content_type("vwx");
1436+ std::string genre("yz");
1437+ int disc_number = 2;
1438+ int track_number = 13;
1439+ int duration = 99;
1440+
1441+ MediaFile mf = MediaFileBuilder(fname)
1442+ .setType(type)
1443+ .setTitle(title)
1444+ .setDate(date)
1445+ .setAuthor(author)
1446+ .setAlbum(album)
1447+ .setAlbumArtist(album_artist)
1448+ .setGenre(genre)
1449+ .setDiscNumber(disc_number)
1450+ .setTrackNumber(track_number)
1451+ .setDuration(duration)
1452+ .setETag(etag)
1453+ .setContentType(content_type);
1454+
1455+ // Now see if data survives a round trip.
1456+ ASSERT_EQ(mf.getType(), type);
1457+ ASSERT_EQ(mf.getFileName(), fname);
1458+ ASSERT_EQ(mf.getTitle(), title);
1459+ ASSERT_EQ(mf.getDate(), date);
1460+ ASSERT_EQ(mf.getAuthor(), author);
1461+ ASSERT_EQ(mf.getAlbum(), album);
1462+ ASSERT_EQ(mf.getAlbumArtist(), album_artist);
1463+ ASSERT_EQ(mf.getGenre(), genre);
1464+ ASSERT_EQ(mf.getDiscNumber(), disc_number);
1465+ ASSERT_EQ(mf.getTrackNumber(), track_number);
1466+ ASSERT_EQ(mf.getDuration(), duration);
1467+ ASSERT_EQ(mf.getETag(), etag);
1468+ ASSERT_EQ(mf.getContentType(), content_type);
1469+}
1470+
1471+TEST_F(MFBTest, fallback_title) {
1472+ // Fallback title is derived from file name.
1473+ MediaFile mf = MediaFileBuilder("/path/to/abc.ogg");
1474+ EXPECT_EQ(mf.getTitle(), "abc");
1475+}
1476+
1477+TEST_F(MFBTest, fallback_album_artist) {
1478+ // Fallback album_artist is the author.
1479+ MediaFile mf = MediaFileBuilder("abc")
1480+ .setAuthor("author");
1481+ EXPECT_EQ(mf.getAlbumArtist(), "author");
1482+}
1483+
1484 int main(int argc, char **argv) {
1485 ::testing::InitGoogleTest(&argc, argv);
1486 return RUN_ALL_TESTS();
1487
1488=== modified file 'test/test_qml.cc'
1489--- test/test_qml.cc 2014-05-06 04:07:58 +0000
1490+++ test/test_qml.cc 2014-05-15 07:01:32 +0000
1491@@ -5,6 +5,7 @@
1492
1493 #include <mediascanner/MediaStore.hh>
1494 #include <mediascanner/MediaFile.hh>
1495+#include <mediascanner/MediaFileBuilder.hh>
1496
1497 using namespace mediascanner;
1498
1499@@ -27,30 +28,100 @@
1500 void populate() {
1501 MediaStore store(MS_READ_WRITE);
1502
1503- store.insert(MediaFile("/path/foo1.ogg", "audio/ogg", "etag",
1504- "Straight Through The Sun", "2013-11-15", "Spiderbait",
1505- "Spiderbait", "Spiderbait", "rock", 1, 1, 235, AudioMedia));
1506- store.insert(MediaFile("/path/foo2.ogg", "audio/ogg", "etag",
1507- "It's Beautiful", "2013-11-15", "Spiderbait",
1508- "Spiderbait", "Spiderbait", "rock", 1, 2, 220, AudioMedia));
1509-
1510- store.insert(MediaFile("/path/foo3.ogg", "audio/ogg", "etag",
1511- "Buy Me a Pony", "1996-10-04", "Spiderbait",
1512- "Ivy and the Big Apples", "Spiderbait", "rock", 1, 3, 104, AudioMedia));
1513-
1514- store.insert(MediaFile("/path/foo4.ogg", "audio/ogg", "etag",
1515- "Peaches & Cream", "2004-03-08", "The John Butler Trio",
1516- "Sunrise Over Sea", "The John Butler Trio", "roots", 1, 2, 407, AudioMedia));
1517- store.insert(MediaFile("/path/foo5.ogg", "audio/ogg", "etag",
1518- "Zebra", "2004-03-08", "The John Butler Trio",
1519- "Sunrise Over Sea", "The John Butler Trio", "roots", 1, 10, 237, AudioMedia));
1520-
1521- store.insert(MediaFile("/path/foo6.ogg", "audio/ogg", "etag",
1522- "Revolution", "2010-01-01", "The John Butler Trio",
1523- "April Uprising", "The John Butler Trio", "roots", 1, 1, 305, AudioMedia));
1524- store.insert(MediaFile("/path/foo7.ogg", "audio/ogg", "etag",
1525- "One Way Road", "2010-01-01", "The John Butler Trio",
1526- "April Uprising", "The John Butler Trio", "roots", 1, 2, 185, AudioMedia));
1527+ store.insert(MediaFileBuilder("/path/foo1.ogg")
1528+ .setType(AudioMedia)
1529+ .setContentType("audio/ogg")
1530+ .setETag("etag")
1531+ .setTitle("Straight Through The Sun")
1532+ .setAuthor("Spiderbait")
1533+ .setAlbum("Spiderbait")
1534+ .setAlbumArtist("Spiderbait")
1535+ .setDate("2013-11-15")
1536+ .setGenre("rock")
1537+ .setDiscNumber(1)
1538+ .setTrackNumber(1)
1539+ .setDuration(235));
1540+ store.insert(MediaFileBuilder("/path/foo2.ogg")
1541+ .setType(AudioMedia)
1542+ .setContentType("audio/ogg")
1543+ .setETag("etag")
1544+ .setTitle("It's Beautiful")
1545+ .setAuthor("Spiderbait")
1546+ .setAlbum("Spiderbait")
1547+ .setAlbumArtist("Spiderbait")
1548+ .setDate("2013-11-15")
1549+ .setGenre("rock")
1550+ .setDiscNumber(1)
1551+ .setTrackNumber(2)
1552+ .setDuration(220));
1553+
1554+ store.insert(MediaFileBuilder("/path/foo3.ogg")
1555+ .setType(AudioMedia)
1556+ .setContentType("audio/ogg")
1557+ .setETag("etag")
1558+ .setTitle("Buy Me a Pony")
1559+ .setAuthor("Spiderbait")
1560+ .setAlbum("Ivy and the Big Apples")
1561+ .setAlbumArtist("Spiderbait")
1562+ .setDate("1996-10-04")
1563+ .setGenre("rock")
1564+ .setDiscNumber(1)
1565+ .setTrackNumber(3)
1566+ .setDuration(104));
1567+
1568+ store.insert(MediaFileBuilder("/path/foo4.ogg")
1569+ .setType(AudioMedia)
1570+ .setContentType("audio/ogg")
1571+ .setETag("etag")
1572+ .setTitle("Peaches & Cream")
1573+ .setAuthor("The John Butler Trio")
1574+ .setAlbum("Sunrise Over Sea")
1575+ .setAlbumArtist("The John Butler Trio")
1576+ .setDate("2004-03-08")
1577+ .setGenre("roots")
1578+ .setDiscNumber(1)
1579+ .setTrackNumber(2)
1580+ .setDuration(407));
1581+ store.insert(MediaFileBuilder("/path/foo5.ogg")
1582+ .setType(AudioMedia)
1583+ .setContentType("audio/ogg")
1584+ .setETag("etag")
1585+ .setTitle("Zebra")
1586+ .setAuthor("The John Butler Trio")
1587+ .setAlbum("Sunrise Over Sea")
1588+ .setAlbumArtist("The John Butler Trio")
1589+ .setDate("2004-03-08")
1590+ .setGenre("roots")
1591+ .setDiscNumber(1)
1592+ .setTrackNumber(10)
1593+ .setDuration(237));
1594+
1595+ store.insert(MediaFileBuilder("/path/foo6.ogg")
1596+ .setType(AudioMedia)
1597+ .setContentType("audio/ogg")
1598+ .setETag("etag")
1599+ .setTitle("Revolution")
1600+ .setAuthor("The John Butler Trio")
1601+ .setAlbum("April Uprising")
1602+ .setAlbumArtist("The John Butler Trio")
1603+ .setDate("2010-01-01")
1604+ .setGenre("roots")
1605+ .setDiscNumber(1)
1606+ .setTrackNumber(1)
1607+ .setDuration(305));
1608+ store.insert(MediaFileBuilder("/path/foo7.ogg")
1609+ .setType(AudioMedia)
1610+ .setContentType("audio/ogg")
1611+ .setETag("etag")
1612+ .setTitle("One Way Road")
1613+ .setAuthor("The John Butler Trio")
1614+ .setAlbum("April Uprising")
1615+ .setAlbumArtist("The John Butler Trio")
1616+ .setDate("2010-01-01")
1617+ .setGenre("roots")
1618+ .setDiscNumber(1)
1619+ .setTrackNumber(2)
1620+ .setDuration(185));
1621 }
1622
1623 private:

Subscribers

People subscribed via source and target branches