~kelemeng/banshee/bug743928

« back to all changes in this revision

Viewing changes to src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/DatabaseRebuilder.cs

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2011-05-14 22:25:36 UTC
  • mfrom: (6.3.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20110514222536-u1x7ikxdqkmfvyuz
Tags: 2.1.0-1ubuntu1
* [2396c18] Merge from Debian Unstable, remaining changes:
  + Enable SoundMenu and Disable NotificationArea by default
  + Disable boo and karma extensions
  + Enable and recommnd u1ms and soundmenu extensions
  + Move desktop file for Meego UI to /usr/share/une/applications
  + Change the url for the Amazon store redirector
  + Create the U1MS widget earlier and bump libu1 requirement
* [9d7c600] Drop upstreamed u1ms-initialize-earlier patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// DatabaseRebuilder.cs
3
 
//
4
 
// Author:
5
 
//   Aaron Bockover <abockover@novell.com>
6
 
//
7
 
// Copyright (C) 2006-2008 Novell, Inc.
8
 
//
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:
16
 
//
17
 
// The above copyright notice and this permission notice shall be
18
 
// included in all copies or substantial portions of the Software.
19
 
//
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.
27
 
//
28
 
 
29
 
using System;
30
 
using System.IO;
31
 
using System.Threading;
32
 
using System.Collections.Generic;
33
 
using Mono.Unix;
34
 
using IPod;
35
 
 
36
 
using Hyena;
37
 
using Hyena.Jobs;
38
 
 
39
 
using Banshee.Base;
40
 
using Banshee.ServiceStack;
41
 
using Banshee.Widgets;
42
 
 
43
 
namespace Banshee.Dap.Ipod
44
 
{
45
 
    public class DatabaseRebuilder
46
 
    {
47
 
        private class FileContainer
48
 
        {
49
 
            public string Path;
50
 
            public TagLib.File File;
51
 
        }
52
 
 
53
 
        private class FileContainerComparer : IComparer<FileContainer>
54
 
        {
55
 
            public int Compare (FileContainer a, FileContainer b)
56
 
            {
57
 
                int artist = String.Compare (a.File.Tag.FirstPerformer, b.File.Tag.FirstPerformer);
58
 
                if (artist != 0) {
59
 
                    return artist;
60
 
                }
61
 
 
62
 
                int album = String.Compare (a.File.Tag.Album, b.File.Tag.Album);
63
 
                if (album != 0) {
64
 
                    return album;
65
 
                }
66
 
 
67
 
                int at = (int)a.File.Tag.Track;
68
 
                int bt = (int)b.File.Tag.Track;
69
 
 
70
 
                if (at == bt) {
71
 
                    return 0;
72
 
                } else if (at < bt) {
73
 
                    return -1;
74
 
                }
75
 
 
76
 
                return 1;
77
 
            }
78
 
        }
79
 
 
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;
85
 
 
86
 
        public event EventHandler Finished;
87
 
 
88
 
        public DatabaseRebuilder (IpodSource source)
89
 
        {
90
 
            this.source = source;
91
 
 
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;
99
 
            user_job.Register ();
100
 
 
101
 
            ThreadPool.QueueUserWorkItem (RebuildDatabase);
102
 
        }
103
 
 
104
 
        private void RebuildDatabase (object state)
105
 
        {
106
 
            string music_path = Paths.Combine (source.IpodDevice.ControlPath, "Music");
107
 
 
108
 
            Directory.CreateDirectory (source.IpodDevice.ControlPath);
109
 
            Directory.CreateDirectory (music_path);
110
 
 
111
 
            DirectoryInfo music_dir = new DirectoryInfo (music_path);
112
 
 
113
 
            foreach (DirectoryInfo directory in music_dir.GetDirectories ()) {
114
 
                ScanMusicDirectory (directory);
115
 
            }
116
 
 
117
 
            ProcessTrackQueue ();
118
 
        }
119
 
 
120
 
        private void ScanMusicDirectory (DirectoryInfo directory)
121
 
        {
122
 
            foreach (FileInfo file in directory.GetFiles ()) {
123
 
                song_queue.Enqueue (file);
124
 
            }
125
 
        }
126
 
 
127
 
        private void ProcessTrackQueue ()
128
 
        {
129
 
            discovery_count = song_queue.Count;
130
 
 
131
 
            user_job.Status = Catalog.GetString ("Processing Tracks...");
132
 
 
133
 
            while (song_queue.Count > 0) {
134
 
                user_job.Progress = (double)(discovery_count - song_queue.Count) / (double)discovery_count;
135
 
 
136
 
                try {
137
 
                    ProcessTrack (song_queue.Dequeue ());
138
 
                } catch {
139
 
                }
140
 
 
141
 
                if (user_job.IsCancelRequested) {
142
 
                    break;
143
 
                }
144
 
            }
145
 
 
146
 
            user_job.Progress = 0.0;
147
 
            user_job.Status = Catalog.GetString ("Ordering Tracks...");
148
 
 
149
 
            files.Sort (new FileContainerComparer ());
150
 
 
151
 
            foreach (FileContainer container in files) {
152
 
                try {
153
 
                    ProcessTrack (container);
154
 
                } catch {
155
 
                }
156
 
 
157
 
                if (user_job.IsCancelRequested) {
158
 
                    break;
159
 
                }
160
 
            }
161
 
 
162
 
            if (!user_job.IsCancelRequested) {
163
 
                SaveDatabase ();
164
 
            }
165
 
 
166
 
            user_job.Finish ();
167
 
            user_job = null;
168
 
 
169
 
            OnFinished ();
170
 
        }
171
 
 
172
 
        private void ProcessTrack (FileInfo file)
173
 
        {
174
 
            TagLib.File af = Banshee.IO.DemuxVfs.OpenFile (file.FullName);
175
 
            FileContainer container = new FileContainer ();
176
 
            container.File = af;
177
 
            container.Path = file.FullName;
178
 
            files.Add (container);
179
 
        }
180
 
 
181
 
        private void ProcessTrack (FileContainer container)
182
 
        {
183
 
            TagLib.File af = container.File;
184
 
            Track song = source.IpodDevice.TrackDatabase.CreateTrack ();
185
 
 
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;
200
 
            }
201
 
 
202
 
            ResolveCoverArt (song);
203
 
        }
204
 
 
205
 
        private void ResolveCoverArt (Track track)
206
 
        {
207
 
            string aaid = CoverArtSpec.CreateArtistAlbumId (track.Artist, track.Album);
208
 
            string path = CoverArtSpec.GetPath (aaid);
209
 
 
210
 
            if (File.Exists (path)) {
211
 
                IpodTrackInfo.SetIpodCoverArt (source.IpodDevice, track, path);
212
 
            }
213
 
        }
214
 
 
215
 
        private void SaveDatabase ()
216
 
        {
217
 
            user_job.CanCancel = false;
218
 
            user_job.Status = Catalog.GetString ("Saving new database...");
219
 
            user_job.Progress = 0.0;
220
 
 
221
 
            try {
222
 
                source.IpodDevice.Name = source.Name;
223
 
                source.IpodDevice.TrackDatabase.Save ();
224
 
                try {
225
 
                    File.Delete (source.NamePath);
226
 
                } catch {
227
 
                }
228
 
            } catch (Exception e) {
229
 
                Log.Exception (e);
230
 
                Log.Error (Catalog.GetString ("Error rebuilding iPod database"), e.Message);
231
 
            }
232
 
        }
233
 
 
234
 
        protected virtual void OnFinished ()
235
 
        {
236
 
            ThreadAssist.ProxyToMain (delegate {
237
 
                EventHandler handler = Finished;
238
 
                if (handler != null) {
239
 
                    handler (this, EventArgs.Empty);
240
 
                }
241
 
            });
242
 
        }
243
 
    }
244
 
}