Merge lp:~jpakkane/thumbnailer/standalone-albumart into lp:thumbnailer

Proposed by Jussi Pakkanen
Status: Rejected
Rejected by: Jussi Pakkanen
Proposed branch: lp:~jpakkane/thumbnailer/standalone-albumart
Merge into: lp:thumbnailer
Diff against target: 158 lines (+73/-11)
3 files modified
src/thumbnailer.cpp (+47/-10)
src/videoscreenshotter.cpp (+1/-1)
tests/basic.cpp (+25/-0)
To merge this branch: bzr merge lp:~jpakkane/thumbnailer/standalone-albumart
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Unity Team Pending
Review via email: mp+235637@code.launchpad.net

Commit message

Load album art from standalone image files.

Description of the change

Load album art from standalone image files.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andrew Hayzen (ahayzen) wrote :

Do you mind making it case insensitive (or at least support title case), if it isn't already, so it doesn't matter if you have done Folder or folder etc?

105. By Jussi Pakkanen

Now with case insensitivity.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Unmerged revisions

105. By Jussi Pakkanen

Now with case insensitivity.

104. By Jussi Pakkanen

Load album art from a standalone image file.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/thumbnailer.cpp'
2--- src/thumbnailer.cpp 2014-09-15 10:37:48 +0000
3+++ src/thumbnailer.cpp 2014-09-24 07:42:10 +0000
4@@ -33,6 +33,9 @@
5 #include<gio/gio.h>
6 #include<glib.h>
7 #include<memory>
8+#include<dirent.h>
9+#include<sys/types.h>
10+#include<algorithm>
11
12 using namespace std;
13
14@@ -43,7 +46,9 @@
15 string create_audio_thumbnail(const string &abspath, ThumbnailSize desired_size,
16 ThumbnailPolicy policy);
17 string create_video_thumbnail(const string &abspath, ThumbnailSize desired_size);
18- string create_generic_thumbnail(const string &abspath, ThumbnailSize desired_size);
19+ string create_generic_thumbnail(const string &abspath, ThumbnailSize desired_size,
20+ const string &original_location="");
21+ string detect_standalone_thumbnail(const string &abspath, ThumbnailSize desired_size);
22
23 public:
24 ThumbnailCache cache;
25@@ -85,6 +90,39 @@
26 return fname;
27 }
28
29+string ThumbnailerPrivate::detect_standalone_thumbnail(const string &abspath, ThumbnailSize desired_size) {
30+ static const std::array<const char *, 2> suffixes{"png", "jpg"};
31+ static const std::array<const char *, 6> namebases{"cover", "album", "albumart", "front", ".folder", "folder"};
32+ auto slash = abspath.rfind('/');
33+ if (slash == string::npos) {
34+ return "";
35+ }
36+ string dirname = abspath.substr(0, slash);
37+ string detected;
38+ unique_ptr<DIR, int(*)(DIR*)> dir(opendir(dirname.c_str()), closedir);
39+ unique_ptr<struct dirent, void(*)(void*)> entry((dirent*)malloc(sizeof(dirent) + NAME_MAX + 1), free);
40+ struct dirent *de = nullptr;
41+ while(readdir_r(dir.get(), entry.get(), &de) == 0 && de) {
42+ const string fname(entry->d_name);
43+ auto sufpoint = fname.rfind('.');
44+ if(sufpoint == string::npos) {
45+ continue;
46+ }
47+ auto namebase = fname.substr(0, sufpoint);
48+ auto suffix = fname.substr(sufpoint+1);
49+ transform(namebase.begin(), namebase.end(), namebase.begin(), ::tolower);
50+ transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
51+ if(find(namebases.begin(), namebases.end(), namebase) != namebases.end() &&
52+ find(suffixes.begin(), suffixes.end(), suffix) != suffixes.end()) {
53+ detected = dirname + "/" + fname;
54+ }
55+ }
56+ if(detected.empty()) {
57+ return "";
58+ }
59+ return create_generic_thumbnail(detected, desired_size, abspath);
60+}
61+
62 string ThumbnailerPrivate::create_audio_thumbnail(const string &abspath,
63 ThumbnailSize desired_size, ThumbnailPolicy /*policy*/) {
64 string tnfile = cache.get_cache_file_name(abspath, desired_size);
65@@ -101,18 +139,21 @@
66 unlink(tmpname.c_str());
67 return tnfile;
68 }
69- return "";
70+ return detect_standalone_thumbnail(abspath, desired_size);
71 }
72-string ThumbnailerPrivate::create_generic_thumbnail(const string &abspath, ThumbnailSize desired_size) {
73+
74+string ThumbnailerPrivate::create_generic_thumbnail(const string &abspath, ThumbnailSize desired_size,
75+ const string &orig_loc) {
76 int tmpw, tmph;
77- string tnfile = cache.get_cache_file_name(abspath, desired_size);
78+ const string &original_location = orig_loc.empty() ? abspath : orig_loc;
79+ string tnfile = cache.get_cache_file_name(original_location, desired_size);
80 // Special case: full size image files are their own preview.
81 if(desired_size == TN_SIZE_ORIGINAL &&
82 gdk_pixbuf_get_file_info(abspath.c_str(), &tmpw, &tmph)) {
83 return abspath;
84 }
85 try {
86- if(scaler.scale(abspath, tnfile, desired_size, abspath))
87+ if(scaler.scale(abspath, tnfile, desired_size, original_location))
88 return tnfile;
89 } catch(const runtime_error &e) {
90 fprintf(stderr, "Scaling thumbnail failed: %s\n", e.what());
91@@ -186,11 +227,7 @@
92 std::string estimate = p->cache.get_if_exists(abspath, desired_size);
93 if(!estimate.empty())
94 return estimate;
95- string generated = p->create_thumbnail(abspath, desired_size, policy);
96- if(generated == abspath) {
97- return abspath;
98- }
99- return p->cache.get_if_exists(abspath, desired_size);
100+ return p->create_thumbnail(abspath, desired_size, policy);
101 }
102
103 string Thumbnailer::get_thumbnail(const string &filename, ThumbnailSize desired_size) {
104
105=== modified file 'src/videoscreenshotter.cpp'
106--- src/videoscreenshotter.cpp 2014-06-03 07:59:52 +0000
107+++ src/videoscreenshotter.cpp 2014-09-24 07:42:10 +0000
108@@ -93,7 +93,7 @@
109 }
110 if(child == 0) {
111 execl(cmd.c_str(), cmd.c_str(), ifname.c_str(), ofname.c_str(), (char*) NULL);
112- fprintf(stderr, "Could not execute worker process: %s", strerror(errno));
113+ fprintf(stderr, "Could not execute worker process: %s\n", strerror(errno));
114 _exit(100);
115 } else {
116 try {
117
118=== modified file 'tests/basic.cpp'
119--- tests/basic.cpp 2014-09-15 10:37:48 +0000
120+++ tests/basic.cpp 2014-09-24 07:42:10 +0000
121@@ -199,6 +199,31 @@
122 }
123 }
124
125+TEST(Thumbnailer, standalone_album_art_original) {
126+ Thumbnailer tn;
127+ string track1(TESTDATADIR "/standalone album/track1.mp3");
128+ string track2(TESTDATADIR "/standalone album/track2.mp3");
129+ string nonexisting_track(TESTDATADIR "/standalone album/track4.mp3");
130+ string dstimg1 = tn.get_thumbnail(track1, TN_SIZE_ORIGINAL);
131+ string dstimg2 = tn.get_thumbnail(track2, TN_SIZE_ORIGINAL);
132+ ASSERT_FALSE(dstimg1.empty());
133+ ASSERT_EQ(dstimg1, dstimg2);
134+ ASSERT_TRUE(tn.get_thumbnail(nonexisting_track, TN_SIZE_ORIGINAL).empty());
135+}
136+
137+TEST(Thumbnailer, standalone_album_art_small) {
138+ Thumbnailer tn;
139+ string track1(TESTDATADIR "/standalone album/track1.mp3");
140+ string track2(TESTDATADIR "/standalone album/track2.mp3");
141+ string nonexisting_track(TESTDATADIR "/standalone album/track4.mp3");
142+ string dstimg1 = tn.get_thumbnail(track1, TN_SIZE_SMALL);
143+ string dstimg2 = tn.get_thumbnail(track2, TN_SIZE_SMALL);
144+ ASSERT_FALSE(dstimg1.empty());
145+ ASSERT_FALSE(dstimg2.empty());
146+ ASSERT_NE(dstimg1, dstimg2);
147+ ASSERT_TRUE(tn.get_thumbnail(nonexisting_track, TN_SIZE_SMALL).empty());
148+}
149+
150 int main(int argc, char **argv) {
151 ::testing::InitGoogleTest(&argc, argv);
152 return RUN_ALL_TESTS();
153
154=== added directory 'tests/standalone album'
155=== added file 'tests/standalone album/album.png'
156Binary files tests/standalone album/album.png 1970-01-01 00:00:00 +0000 and tests/standalone album/album.png 2014-09-24 07:42:10 +0000 differ
157=== added file 'tests/standalone album/track1.mp3'
158=== added file 'tests/standalone album/track2.mp3'

Subscribers

People subscribed via source and target branches

to all changes: