Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: chrome/browser/media_galleries/fileapi/itunes_data_provider.cc

Issue 16158004: iTunes file util and data provider for media galleries (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Basic bug fixes Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h"
6
7 #include "base/format_macros.h"
8 #include "base/logging.h"
9 #include "base/platform_file.h"
10 #include "base/stl_util.h"
11 #include "base/stringprintf.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "chrome/browser/media_galleries/fileapi/itunes_library_parser.h"
14
15 namespace itunes {
16
17 namespace {
18
19 const int64 kMaxLibraryFileSize = 50 * 1024 * 1024;
20
21 std::string ReadFile(const base::FilePath& path) {
22 base::ThreadRestrictions::AssertIOAllowed();
23
24 base::PlatformFile file = base::CreatePlatformFile(
25 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL, NULL);
26 if (file == base::kInvalidPlatformFileValue)
27 return std::string();
28
29 base::PlatformFileInfo file_info;
30 if (!base::GetPlatformFileInfo(file, &file_info) ||
31 file_info.size > kMaxLibraryFileSize) {
32 base::ClosePlatformFile(file);
33 return std::string();
34 }
35
36 std::string result(file_info.size, 0);
37 if (base::ReadPlatformFile(file, 0, string_as_array(&result),
38 file_info.size) != file_info.size) {
39 result.clear();
40 }
41
42 base::ClosePlatformFile(file);
43 return result;
44 }
45
46 } // namespace
47
48 ITunesDataProvider::ITunesDataProvider(const base::FilePath& library_path)
49 : library_path_(library_path),
50 needs_refresh_(true) {
51 }
52
53 ITunesDataProvider::~ITunesDataProvider() {}
54
55 // TODO(vandebo): add a file watch that resets |needs_refresh_| when the
56 // file changes.
57 void ITunesDataProvider::RefreshData(const base::Closure& ready_callback) {
58 if (!needs_refresh_) {
59 ready_callback.Run();
60 return;
61 }
62
63 ParseLibrary();
64 needs_refresh_ = false;
65 ready_callback.Run();
66 }
67
68 base::FilePath ITunesDataProvider::library_path() const {
69 return library_path_;
70 }
71
72 bool ITunesDataProvider::KnownArtist(const ArtistName& artist) const {
73 DCHECK(!needs_refresh_);
74 return ContainsKey(library_, artist);
75 }
76
77 bool ITunesDataProvider::KnownAlbum(const ArtistName& artist,
78 const AlbumName& album) const {
79 DCHECK(!needs_refresh_);
80 Library::const_iterator library_it = library_.find(artist);
81 if (library_it == library_.end())
82 return false;
83 return ContainsKey(library_it->second, album);
84
85 }
86
87 bool ITunesDataProvider::GetTrackLocation(const ArtistName& artist,
88 const AlbumName& album,
89 const TrackName& track,
90 base::FilePath* result) const {
91 DCHECK(!needs_refresh_);
92 Library::const_iterator library_it = library_.find(artist);
93 if (library_it == library_.end())
94 return false;
95
96 Artist::const_iterator artist_it = library_it->second.find(album);
97 if (artist_it == library_it->second.end())
98 return false;
99
100 Album::const_iterator album_it = artist_it->second.find(track);
101 if (album_it == artist_it->second.end())
102 return false;
103
104 if (result)
105 *result = album_it->second;
106 return true;
107 }
108
109 std::set<ITunesDataProvider::ArtistName>
110 ITunesDataProvider::GetArtists() const {
111 DCHECK(!needs_refresh_);
112 std::set<ArtistName> result;
113 Library::const_iterator it;
114 for (it = library_.begin(); it != library_.end(); ++it) {
115 result.insert(it->first);
116 }
117 return result;
118 }
119
120 std::set<ITunesDataProvider::AlbumName> ITunesDataProvider::GetAlbums(
121 const ArtistName& artist) const {
122 DCHECK(!needs_refresh_);
123 std::set<AlbumName> result;
124 Library::const_iterator artist_lookup = library_.find(artist);
125 if (artist_lookup == library_.end())
126 return result;
127
128 const Artist& artist_entry = artist_lookup->second;
129 Artist::const_iterator it;
130 for (it = artist_entry.begin(); it != artist_entry.end(); ++it) {
131 result.insert(it->first);
132 }
133 return result;
134 }
135
136 std::map<ITunesDataProvider::TrackName, base::FilePath>
137 ITunesDataProvider::GetTracks(const ArtistName& artist,
138 const AlbumName& album) const {
139 DCHECK(!needs_refresh_);
140 std::map<TrackName, base::FilePath> empty_result;
141 Library::const_iterator artist_lookup = library_.find(artist);
142 if (artist_lookup == library_.end())
143 return empty_result;
144
145 Artist::const_iterator album_lookup = artist_lookup->second.find(album);
146 if (album_lookup == artist_lookup->second.end())
147 return empty_result;
148
149 return album_lookup->second;
150 }
151
152 // static
153 ITunesDataProvider::Album ITunesDataProvider::MakeUniqueTrackNames(
154 const ITunesLibraryParser::Album& album) {
155 // TODO(vandebo): It would be nice to ensure that names returned from here
156 // are stable, but aside from persisting every name returned, it's not
157 // obvious how to do that (without including the track id in every name).
158 typedef std::set<const ITunesLibraryParser::Track*> TrackRefs;
159 typedef std::map<TrackName, TrackRefs> AlbumInfo;
160
161 Album result;
162 AlbumInfo duped_tracks;
163
164 ITunesLibraryParser::Album::const_iterator album_it;
165 for (album_it = album.begin(); album_it != album.end(); ++album_it) {
166 std::string name = album_it->location.BaseName().AsUTF8Unsafe();
167 duped_tracks[name].insert(&*album_it);
168 }
169
170 for (AlbumInfo::const_iterator name_it = duped_tracks.begin();
171 name_it != duped_tracks.end();
172 ++name_it) {
173 if (name_it->second.size() == 1) {
174 result[name_it->first] = (*name_it->second.begin())->location;
175 } else {
176 for (TrackRefs::const_iterator track_it = name_it->second.begin();
177 track_it != name_it->second.end(); ++track_it) {
178 std::string id =
179 base::StringPrintf(" (%" PRId64 ")", (*track_it)->id);
180 base::FilePath unique_name =
181 (*track_it)->location.BaseName().InsertBeforeExtensionASCII(id);
182 result[unique_name.AsUTF8Unsafe()] = (*track_it)->location;
183 }
184 }
185 }
186
187 return result;
188 }
189
190 void ITunesDataProvider::ParseLibrary() {
191 std::string xml = ReadFile(library_path_);
192
193 library_.clear();
194 ITunesLibraryParser parser;
195 if (!parser.Parse(xml))
196 return;
197
198 ITunesLibraryParser::Library::const_iterator artist_it;
199 ITunesLibraryParser::Albums::const_iterator album_it;
200 for (artist_it = parser.library().begin();
201 artist_it != parser.library().end();
202 ++artist_it) {
203 for (album_it = artist_it->second.begin();
204 album_it != artist_it->second.end();
205 ++album_it) {
206 library_[artist_it->first][album_it->first] =
207 ITunesDataProvider::MakeUniqueTrackNames(album_it->second);
208 }
209 }
210 };
211
212 } // namespace itunes
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698