Merge lp:~jamesh/mediascanner2/bug-1436110 into lp:mediascanner2

Proposed by James Henstridge
Status: Merged
Approved by: Michi Henning
Approved revision: 303
Merged at revision: 299
Proposed branch: lp:~jamesh/mediascanner2/bug-1436110
Merge into: lp:mediascanner2
Diff against target: 189 lines (+102/-6)
4 files modified
CMakeLists.txt (+1/-1)
src/daemon/MetadataExtractor.cc (+3/-0)
test/basic.cc (+9/-3)
test/test_metadataextractor.cc (+89/-2)
To merge this branch: bzr merge lp:~jamesh/mediascanner2/bug-1436110
Reviewer Review Type Date Requested Status
Michi Henning (community) Approve
Review via email: mp+260917@code.launchpad.net

Commit message

Treat invalid dates in MP3s as missing metadata.

Description of the change

If an MP3 includes a year of "-1", or the date is otherwise unparsable, treat that metadata as missing.

I couldn't trigger the bug mentioned in the bug using vorbis files, so I've added tests using mp3 sample files. These tests should only run when the corresponding codec is available, so won't cover us in Jenkins (since the non-free codecs aren't available), but will catch problems when run locally.

I also took the opportunity to add a test for standard metadata extraction on an MP3 file.

To post a comment you must log in.
lp:~jamesh/mediascanner2/bug-1436110 updated
301. By James Henstridge

Move QML plugin directory so that it isn't shadowed by the installed
version.

302. By James Henstridge

Update test to actually check what it claims to, and work now that we've
got more test audio files.

303. By James Henstridge

More cleanups.

Revision history for this message
Michi Henning (michihenning) wrote :

LGTM!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-10-09 08:48:05 +0000
3+++ CMakeLists.txt 2015-06-04 00:53:07 +0000
4@@ -41,7 +41,7 @@
5 add_subdirectory(src/mediascanner)
6 add_subdirectory(src/daemon)
7 add_subdirectory(src/ms-dbus)
8-add_subdirectory(src/qml/Ubuntu/MediaScanner)
9+add_subdirectory(src/qml/Ubuntu/MediaScanner.0.1)
10 add_subdirectory(src/utils)
11 add_subdirectory(test)
12
13
14=== modified file 'src/daemon/MetadataExtractor.cc'
15--- src/daemon/MetadataExtractor.cc 2015-01-22 09:04:17 +0000
16+++ src/daemon/MetadataExtractor.cc 2015-06-04 00:53:07 +0000
17@@ -172,6 +172,9 @@
18 } else if (G_VALUE_HOLDS(val, GST_TYPE_DATE_TIME)) {
19 if (tagname == GST_TAG_DATE_TIME) {
20 GstDateTime *dt = static_cast<GstDateTime*>(g_value_get_boxed(val));
21+ if (!dt) {
22+ continue;
23+ }
24 char *dt_string = gst_date_time_to_iso8601_string(dt);
25 mfb->setDate(dt_string);
26 g_free(dt_string);
27
28=== renamed directory 'src/qml/Ubuntu/MediaScanner' => 'src/qml/Ubuntu/MediaScanner.0.1'
29=== modified file 'test/basic.cc'
30--- test/basic.cc 2014-10-24 13:55:20 +0000
31+++ test/basic.cc 2015-06-04 00:53:07 +0000
32@@ -224,10 +224,16 @@
33
34 TEST(Mediascanner, root_skip) {
35 MetadataExtractor e;
36- string root(SOURCE_DIR);
37+ string root(SOURCE_DIR "/media");
38 Scanner s(&e, root, AudioMedia);
39- s.next();
40- ASSERT_THROW(s.next(), StopIteration);
41+ while (true) {
42+ try {
43+ auto d = s.next();
44+ EXPECT_EQ(std::string::npos, d.filename.find("fake_root")) << d.filename;
45+ } catch (const StopIteration &e) {
46+ break;
47+ }
48+ }
49 }
50
51 TEST(Mediascanner, scan_files_found_in_new_dir) {
52
53=== added file 'test/media/baddate.mp3'
54Binary files test/media/baddate.mp3 1970-01-01 00:00:00 +0000 and test/media/baddate.mp3 2015-06-04 00:53:07 +0000 differ
55=== added file 'test/media/baddate.ogg'
56Binary files test/media/baddate.ogg 1970-01-01 00:00:00 +0000 and test/media/baddate.ogg 2015-06-04 00:53:07 +0000 differ
57=== added file 'test/media/testfile.mp3'
58Binary files test/media/testfile.mp3 1970-01-01 00:00:00 +0000 and test/media/testfile.mp3 2015-06-04 00:53:07 +0000 differ
59=== modified file 'test/test_metadataextractor.cc'
60--- test/test_metadataextractor.cc 2015-01-22 09:04:17 +0000
61+++ test/test_metadataextractor.cc 2015-06-04 00:53:07 +0000
62@@ -25,6 +25,7 @@
63 #include<algorithm>
64 #include<stdexcept>
65 #include<cstdio>
66+#include<memory>
67 #include<string>
68 #include<gst/gst.h>
69 #include <gtest/gtest.h>
70@@ -32,6 +33,46 @@
71 using namespace std;
72 using namespace mediascanner;
73
74+namespace {
75+
76+bool supports_decoder(const std::string& format)
77+{
78+ static std::set<std::string> formats;
79+
80+ if (formats.empty())
81+ {
82+ std::unique_ptr<GList, decltype(&gst_plugin_feature_list_free)> decoders(
83+ gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER, GST_RANK_NONE),
84+ gst_plugin_feature_list_free);
85+ for (const GList* l = decoders.get(); l != nullptr; l = l->next)
86+ {
87+ const auto factory = static_cast<GstElementFactory*>(l->data);
88+
89+ const GList* templates = gst_element_factory_get_static_pad_templates(factory);
90+ for (const GList* l = templates; l != nullptr; l = l->next)
91+ {
92+ const auto t = static_cast<GstStaticPadTemplate*>(l->data);
93+ if (t->direction != GST_PAD_SINK)
94+ {
95+ continue;
96+ }
97+
98+ std::unique_ptr<GstCaps, decltype(&gst_caps_unref)> caps(gst_static_caps_get(&t->static_caps),
99+ gst_caps_unref);
100+ for (unsigned int i = 0; i < gst_caps_get_size(caps.get()); i++)
101+ {
102+ const auto structure = gst_caps_get_structure(caps.get(), i);
103+ formats.emplace(gst_structure_get_name(structure));
104+ }
105+ }
106+ }
107+ }
108+
109+ return formats.find(format) != formats.end();
110+}
111+
112+}
113+
114 class MetadataExtractorTest : public ::testing::Test {
115 protected:
116 MetadataExtractorTest() {
117@@ -89,6 +130,25 @@
118 EXPECT_EQ(file.getDuration(), 5);
119 }
120
121+TEST_F(MetadataExtractorTest, extract_mp3) {
122+ if (!supports_decoder("audio/mpeg")) {
123+ printf("MP3 codec not supported\n");
124+ return;
125+ }
126+ MetadataExtractor e;
127+ string testfile = SOURCE_DIR "/media/testfile.mp3";
128+ MediaFile file = e.extract(e.detect(testfile));
129+
130+ EXPECT_EQ(file.getType(), AudioMedia);
131+ EXPECT_EQ(file.getTitle(), "track1");
132+ EXPECT_EQ(file.getAuthor(), "artist1");
133+ EXPECT_EQ(file.getAlbum(), "album1");
134+ EXPECT_EQ(file.getDate(), "2013-06-03");
135+ EXPECT_EQ(file.getTrackNumber(), 1);
136+ EXPECT_EQ(file.getDuration(), 1);
137+ EXPECT_EQ(file.getGenre(), "Hip-Hop");
138+}
139+
140 TEST_F(MetadataExtractorTest, extract_video) {
141 MetadataExtractor e;
142
143@@ -133,17 +193,44 @@
144 EXPECT_DOUBLE_EQ(153.1727346, file.getLongitude());
145 }
146
147+TEST_F(MetadataExtractorTest, extract_bad_date) {
148+ MetadataExtractor e;
149+ string testfile = SOURCE_DIR "/media/baddate.ogg";
150+ MediaFile file = e.extract(e.detect(testfile));
151+
152+ EXPECT_EQ(file.getType(), AudioMedia);
153+ EXPECT_EQ(file.getTitle(), "Track");
154+ EXPECT_EQ(file.getAuthor(), "Artist");
155+ EXPECT_EQ(file.getAlbum(), "Album");
156+ EXPECT_EQ(file.getDate(), "");
157+}
158+
159+TEST_F(MetadataExtractorTest, extract_mp3_bad_date) {
160+ if (!supports_decoder("audio/mpeg")) {
161+ printf("MP3 codec not supported\n");
162+ return;
163+ }
164+ MetadataExtractor e;
165+ string testfile = SOURCE_DIR "/media/baddate.mp3";
166+ MediaFile file = e.extract(e.detect(testfile));
167+
168+ EXPECT_EQ(file.getType(), AudioMedia);
169+ EXPECT_EQ(file.getTitle(), "Track");
170+ EXPECT_EQ(file.getAuthor(), "Artist");
171+ EXPECT_EQ(file.getAlbum(), "Album");
172+ EXPECT_EQ(file.getDate(), "");
173+}
174+
175 TEST_F(MetadataExtractorTest, blacklist) {
176 MetadataExtractor e;
177 string testfile = SOURCE_DIR "/media/playlist.m3u";
178 try {
179 e.detect(testfile);
180+ FAIL();
181 } catch(const std::runtime_error &e) {
182 std::string error_message(e.what());
183 ASSERT_NE(error_message.find("blacklist"), std::string::npos);
184- return;
185 }
186- ASSERT_TRUE(false) << "Blacklist exception was not thrown.\n";
187 }
188
189 TEST_F(MetadataExtractorTest, png_file) {

Subscribers

People subscribed via source and target branches