2
// DatabaseRebuilder.cs
5
// Aaron Bockover <abockover@novell.com>
7
// Copyright (C) 2006-2008 Novell, Inc.
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
using System.Threading;
32
using System.Collections.Generic;
40
using Banshee.ServiceStack;
41
using Banshee.Widgets;
43
namespace Banshee.Dap.Ipod
45
public class DatabaseRebuilder
47
private class FileContainer
50
public TagLib.File File;
53
private class FileContainerComparer : IComparer<FileContainer>
55
public int Compare (FileContainer a, FileContainer b)
57
int artist = String.Compare (a.File.Tag.FirstPerformer, b.File.Tag.FirstPerformer);
62
int album = String.Compare (a.File.Tag.Album, b.File.Tag.Album);
67
int at = (int)a.File.Tag.Track;
68
int bt = (int)b.File.Tag.Track;
80
private IpodSource source;
81
private UserJob user_job;
82
private Queue<FileInfo> song_queue = new Queue<FileInfo>();
83
private List<FileContainer> files = new List<FileContainer>();
84
private int discovery_count;
86
public event EventHandler Finished;
88
public DatabaseRebuilder (IpodSource source)
92
user_job = new UserJob (Catalog.GetString ("Rebuilding Database"));
93
user_job.PriorityHints = PriorityHints.SpeedSensitive | PriorityHints.DataLossIfStopped;
94
user_job.SetResources (Resource.Disk, Resource.Cpu);
95
user_job.Title = Catalog.GetString ("Rebuilding Database");
96
user_job.Status = Catalog.GetString ("Scanning iPod...");
97
user_job.IconNames = source._GetIconNames ();
98
user_job.CanCancel = true;
101
ThreadPool.QueueUserWorkItem (RebuildDatabase);
104
private void RebuildDatabase (object state)
106
string music_path = Paths.Combine (source.IpodDevice.ControlPath, "Music");
108
Directory.CreateDirectory (source.IpodDevice.ControlPath);
109
Directory.CreateDirectory (music_path);
111
DirectoryInfo music_dir = new DirectoryInfo (music_path);
113
foreach (DirectoryInfo directory in music_dir.GetDirectories ()) {
114
ScanMusicDirectory (directory);
117
ProcessTrackQueue ();
120
private void ScanMusicDirectory (DirectoryInfo directory)
122
foreach (FileInfo file in directory.GetFiles ()) {
123
song_queue.Enqueue (file);
127
private void ProcessTrackQueue ()
129
discovery_count = song_queue.Count;
131
user_job.Status = Catalog.GetString ("Processing Tracks...");
133
while (song_queue.Count > 0) {
134
user_job.Progress = (double)(discovery_count - song_queue.Count) / (double)discovery_count;
137
ProcessTrack (song_queue.Dequeue ());
141
if (user_job.IsCancelRequested) {
146
user_job.Progress = 0.0;
147
user_job.Status = Catalog.GetString ("Ordering Tracks...");
149
files.Sort (new FileContainerComparer ());
151
foreach (FileContainer container in files) {
153
ProcessTrack (container);
157
if (user_job.IsCancelRequested) {
162
if (!user_job.IsCancelRequested) {
172
private void ProcessTrack (FileInfo file)
174
TagLib.File af = Banshee.IO.DemuxVfs.OpenFile (file.FullName);
175
FileContainer container = new FileContainer ();
177
container.Path = file.FullName;
178
files.Add (container);
181
private void ProcessTrack (FileContainer container)
183
TagLib.File af = container.File;
184
Track song = source.IpodDevice.TrackDatabase.CreateTrack ();
186
song.FileName = container.Path;
187
song.Album = af.Tag.Album;
188
song.Artist = af.Tag.FirstPerformer;
189
song.Title = af.Tag.Title;
190
song.Genre = af.Tag.FirstGenre;
191
song.TrackNumber = (int)af.Tag.Track;
192
song.TotalTracks = (int)af.Tag.TrackCount;
193
song.Duration = af.Properties.Duration;
194
song.Year = (int)af.Tag.Year;
195
song.BitRate = af.Properties.AudioBitrate / 1024;
196
song.SampleRate = (ushort)af.Properties.AudioSampleRate;
197
song.Type = MediaType.Audio;
198
if ((af.Properties.MediaTypes & TagLib.MediaTypes.Video) != 0) {
199
song.Type = MediaType.Video;
202
ResolveCoverArt (song);
205
private void ResolveCoverArt (Track track)
207
string aaid = CoverArtSpec.CreateArtistAlbumId (track.Artist, track.Album);
208
string path = CoverArtSpec.GetPath (aaid);
210
if (File.Exists (path)) {
211
IpodTrackInfo.SetIpodCoverArt (source.IpodDevice, track, path);
215
private void SaveDatabase ()
217
user_job.CanCancel = false;
218
user_job.Status = Catalog.GetString ("Saving new database...");
219
user_job.Progress = 0.0;
222
source.IpodDevice.Name = source.Name;
223
source.IpodDevice.TrackDatabase.Save ();
225
File.Delete (source.NamePath);
228
} catch (Exception e) {
230
Log.Error (Catalog.GetString ("Error rebuilding iPod database"), e.Message);
234
protected virtual void OnFinished ()
236
ThreadAssist.ProxyToMain (delegate {
237
EventHandler handler = Finished;
238
if (handler != null) {
239
handler (this, EventArgs.Empty);