返回首页

{S0}简介
本文演示了一个工具,它可以自动生成iTunes播放列表。我们可以创建播放列表,他们已被添加到iTunes资料库的文件夹结构相同。当我们看到后自动生成的iTunes播放列表,将创建的目录结构。此文件夹包含在您的硬盘的确切妆的所有歌曲。要求
使用从苹果公司最畅销的音乐播放器之一时,我发现很难找到设备的歌曲或音乐专辑。这是非常确定,如果我们有一个少数歌曲。但对于音乐随身携带的音乐文件吨,吨的怪胎,它的那种痛苦地发现一个特定的专辑或电影。此播放器提供了这么多的方法,查找和管理歌曲和专辑,但他们都变得有点无用相册计数时。毫无疑问,苹果公司的iPod是在世界上最流行的音乐播放器之一,我预计iTunes将提供一个很好的方法来处理选择 - 但他们不。解决方案
所有我的研究给我买了一个结论:至少在台式机用户的角度来看,iTunes中没有内置,同时考虑大罪状。回想当我用来听歌曲从桌面的天,我曾经安排在几个月甚至几年分组的文件夹中的专辑,也为不同类别,如音乐剧,专辑,电影歌曲,不同的语言等那些日子不同的文件夹,我用拖放到我最喜爱的的播放器Winamp的文件夹,并清除播放列表中,每当我想,或将其保存为播放列表,以备后用。幸运的是,此功能是部分在iTunes中。我可以创造一个"在去"播放列表的iPod上的飞行,并明确表示,只要是不需要。但仍然存在一个问题。我如何找到的专辑,从1000说,我想只找到一些在2005年1月发布的歌曲大集合?我需要创建一个工具,它可以创建在相同的确切顺序出现在我的硬盘中的歌曲。在我的研究发现的iTunes SDK使我的生活更轻松。感谢苹果。如何使用应用程序
应用程序UI包含五个主要元素。您可以使用在应用程序提供的默认设置。甚至有一些小的刀尖提供的帮助。
步骤:启动应用程序和根文件夹重命名,如果需要的话。点击"同步播放"按钮。等待几秒钟,开始操作。你可以看到iTunes的入门和指定的播放列表文件夹下创建新的文件夹和播放列表。如果你想中止操作,你可以在任何时候。迄今取得的进展将被保存在工作文件夹中的iTunes根。如果你喜欢保持它将会在备份文件夹中保存的备份,但是这将更新到您的iPod下次同步时。使用代码
完整的开发周期,我们将看到四个阶段。模拟iTunes文件夹子系统的设计。iTunes的接口系统的设计。用户界面的设计。性能优化和改善用户体验。1)设计模拟iTunes文件夹子系统 - 模型
当我开始调查我发现iTunes的子系统不处理我需要一棵树形成的观点的iTunes的架构。至少它不是暴露的API的一部分(或者更糟,我无法弄明白吗?)。对于每一步,我需要找到从集合中的元素,我没有看到一个可行的解决方案haivng主要的文件夹的名称,可邀请重复。为了解决这个问题,我需要在我的应用程序我自己的树子系统。
设计提取三类树中的元素,这实质上是一个基类在iTunes在iTunes子系统。
)文件夹,B)播放,C)轨道。
这里是实现这一目的的代码。 - FolderElement.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using iTunesLib;

 

namespace ItnuesPlayListManager

{

    public class FolderElement

    {

        public FolderElement(FolderElement parent,IITUserPlaylist itnuesfolder)

        {

            CreateNew(parent, itnuesfolder);

        }

 

        public FolderElement(FolderElement parent,string newfoldername)

        {

            IITUserPlaylist itnuesFolderSource = (

                IITUserPlaylist)parent.ItnuesFolderSource.CreateFolder(newfoldername);

            CreateNew(parent, itnuesFolderSource);

        }

 

        private bool CreateNew(FolderElement parent,IITUserPlaylist itnuesfolder)

        {

            ItnuesFolderSource = itnuesfolder;

            this.Parent = parent;

            SubFolders = new SortedDictionary<string, FolderElement>();

            PlayLists = new SortedDictionary<string, PlayListElement>();

            return true;

        }

       

        

        public FolderElement Parent

        {

            get; private set;

        }

 

        

        public IITUserPlaylist ItnuesFolderSource

        {

            get; private set;

        }

 

        public SortedDictionary<string, FolderElement> SubFolders

        {

            get; private set;

        }

 

        

        public SortedDictionary<string, PlayListElement> PlayLists

        {

            get; private set;

        }

 

        public bool MoveFolder(FolderElement destination)

        {

            if(destination.SubFolders.ContainsKey(this.ItnuesFolderSource.Name))

                return false;

            Parent = destination;

            Parent.SubFolders.Remove(this.ItnuesFolderSource.Name);

            destination.SubFolders.Add(this.ItnuesFolderSource.Name, this);

            object val = destination.ItnuesFolderSource;

            this.ItnuesFolderSource.set_Parent(ref val);

            return true;

        }

 

        public bool DeleteSubFolder(FolderElement folder)

        {

            if (!this.SubFolders.ContainsKey(folder.ItnuesFolderSource.Name))

                return false;

            this.SubFolders.Remove(folder.ItnuesFolderSource.Name);

            folder.ItnuesFolderSource.Delete();

            return true;

        }

    }

}
B - PlaylistElement.cs{C}C - TrackElement.cs
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using iTunesLib;

 

namespace ItnuesPlayListManager

{

    public class TrackElement

    {

        public TrackElement(PlayListElement playlistobject, IITTrack trackobject)

        {

            ItnuesTrackSource = trackobject;

            object obj = (object)trackobject;

            playlistobject.ItnuesFolderSource.AddTrack(ref obj);

            Parent = playlistobject;

        }

                

        public PlayListElement Parent

        {

            get; private set;

        }

 

        public IITTrack ItnuesTrackSource

        {

            get; private set;

        }

    }

}
2)iTunes的接口系统设计
,模拟文件夹系统的设计完成后,我们应该提供一个接口来执行与iTunes进行通信的功能。下面是执行这些操作的类。ItnuesApp.cs
using System.Collections.Generic;

using iTunesLib;

 

namespace ItnuesPlayListManager

{

    public static class ItnuesApp

    {

        static iTunesApp app;

 

        public const string ROOTFOLDERNAME_BACKUP = "(Backup)";

 

        public const string ROOTFOLDERNAME_WORKING = "(Working)";

 

        public static iTunesApp Application

        {

            get

            {

                if(app ==null)

                    app = new iTunesAppClass();

                return app;

            }

        }

 

        public static bool Disconnect()

        {

            app = null;

            return true;

        }

 

        public static PlayListElement GetPlaylist(FolderElement root, List<string> path)

        {

            PlayListElement leaf;

            FolderElement currentfolder = root;

            int i = 0;

            for (i = 1; i < path.Count - 2; i++)

            {

                if (currentfolder.SubFolders.ContainsKey(path[i]) == false)

                {

                    FolderElement folder = new FolderElement(currentfolder, path[i]);

                    currentfolder.SubFolders.Add(path[i], folder);

                    currentfolder = folder;

                }

                else

                {

                    currentfolder = currentfolder.SubFolders[path[i]];

                }

            }

            if (currentfolder.PlayLists.ContainsKey(path[i]) == true)

            {

                leaf = currentfolder.PlayLists[path[i]];

            }

            else

            {

                leaf = new PlayListElement(currentfolder, path[i]);

                currentfolder.PlayLists.Add(path[i], leaf);

            }

            return leaf;

        }

 

        public static FolderElement GetWorkingRootFolder(string rootfoldername)

        {

            IITUserPlaylist rootworkingfolder = IsDuplicateSubFolderExists(null,

                rootfoldername + ROOTFOLDERNAME_WORKING);

            if (rootworkingfolder != null)

            {

                rootworkingfolder.Delete();

            }

            rootworkingfolder = (IITUserPlaylist)ItnuesApp.Application.CreateFolder(

                rootfoldername + ROOTFOLDERNAME_WORKING);

            return new FolderElement(null, rootworkingfolder);

        }

 

        public static bool ManageBackup(FolderElement newrootfolder, string rootfoldername,

            bool keepabackup)

        {

            IITUserPlaylist rootfoldebackup = IsDuplicateSubFolderExists(null,

                rootfoldername + ROOTFOLDERNAME_BACKUP);

            IITUserPlaylist rootfoldercurrent = IsDuplicateSubFolderExists(null,

                rootfoldername);

            if (rootfoldebackup != null)

            {

                rootfoldebackup.Delete();

            }

            if (rootfoldercurrent != null)

            {

                if (keepabackup == true)

                {

                    rootfoldercurrent.Name = rootfoldername + ROOTFOLDERNAME_BACKUP;

                }

                else

                {

                    rootfoldercurrent.Delete();

                }

            }

            newrootfolder.ItnuesFolderSource.Name = rootfoldername;

            return true;

        }

 

        public static IITUserPlaylist IsDuplicateSubFolderExists(IITUserPlaylist play,

            string foldername)

        {

            foreach (object item in ItnuesApp.Application.LibrarySource.Playlists)

            {

                if (item is IITUserPlaylist)

                {

                    IITUserPlaylist itemIITUserPlaylist = (IITUserPlaylist)item;

                    if (itemIITUserPlaylist.Name.ToUpper() == foldername.ToUpper())

                    {

                        if (itemIITUserPlaylist.get_Parent() != null)

                        {

                            if (itemIITUserPlaylist.get_Parent().playlistID == play.playlistID)

                                return itemIITUserPlaylist;

                        }

                        else 

                            return itemIITUserPlaylist;

                    }

                }

            }

            return null;

        }

    }

}
InteractionUtils.cs
using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows.Threading;

 

namespace ItnuesPlayListManager

{

    public static class InteractionUtils

    {

        public static List<string> GetBrokenPaths(string path)

        {

            List<string> list = new List<string>();

            string[] str = path.Split(new char[] { '\\', ':' }, 999,

                StringSplitOptions.RemoveEmptyEntries);

            list.AddRange(str.AsEnumerable());

            return list;

        }

 

        public static void RemoteThreadUpdate(this Dispatcher ctrlControl,

            Action mtdLambadaExpression)

        {

            if (ctrlControl.CheckAccess())

            {

                mtdLambadaExpression();

            }

            else

            {

                ctrlControl.BeginInvoke(DispatcherPriority.Normal, mtdLambadaExpression);

            }

        }

     }

 

    public class DataEventArgs<T> : EventArgs

    {

        public DataEventArgs(T data)

        {

            this.Data = data;

        }

        public T Data { get; set; }

    }

}
3)用户界面设计
最后,考虑UI界面设计时,它似乎使用MVC模式将是适当的UI功能似乎变得复杂。控制器包含iTunes界面和模拟文件夹系统之间的集成逻辑和最后提供输出到UI。本节由三部分组成背后仪表板,仪表板控制器和最后的板UI代码。DashBoardController.cs
using System;

using System.Collections.Generic;

using System.Linq;

using iTunesLib;

using System.Windows.Documents;

 

namespace ItnuesPlayListManager

{

    public class DashBoardController

    {

        public class CreateEventArgs

        {

            public CreateEventArgs(string message,double progress,bool isErrorMessage)

            {

                Message = message;

                Progress = progress;

                IsErrorMessage = isErrorMessage;

            }

            public string Message { get; private set; }

            public double Progress { get; private set; }

            public bool IsErrorMessage { get; private set; }

        }

 

        public event EventHandler<DataEventArgs<CreateEventArgs>> ProgressStatus;

 

        public event EventHandler<DataEventArgs<double>> BeforeCreate;

 

        public event EventHandler<DataEventArgs<bool>> AfterCreate;

 

        public FolderElement Root { get; private set; }

 

        public void CreatePlaylistTree(object obj)

        {

            object[] objarray = (object[])obj;

            bool val = CreatePlaylistTree((string)objarray[0], (bool)objarray[1],

                (bool)objarray[2],(bool)objarray[3]);

            if (AfterCreate != null) AfterCreate(this,new DataEventArgs<bool>(val));

        }

 

        public bool CreatePlaylistTree(string rootfoldername,bool deleteUnfoundtracks,

            bool keepbackup,bool removeEmptyFolders)

        {

            List<IITFileOrCDTrack> trackstodelete = new List<IITFileOrCDTrack>();

            var tracks = ItnuesApp.Application.LibraryPlaylist.Tracks;

            var numTracks = tracks.Count;

            int i=1;

            PlayListElement element = null;

            string lastlocation = string.Empty;

            if(BeforeCreate!=null)

                BeforeCreate(this, new DataEventArgs<double>(numTracks));

            Root = ItnuesApp.GetWorkingRootFolder(rootfoldername);

            //start create the playlists and folders

            for (i = 1; i < numTracks; i++)

            {

                IITFileOrCDTrack currTrack = (IITFileOrCDTrack)tracks[i];

                //temporary arrangement. skip the tracks of those the location is not

                //found. TODO.need to find/remove/save the location of these files.

                if (currTrack.Location != null)

                {

                    string currentlocation = currTrack.Location.Substring(0,

                        currTrack.Location.LastIndexOf("\\"));

                    if (lastlocation == currentlocation)

                    {

                        element.SubTracks.Add(currTrack.Location.Substring(

                            currTrack.Location.LastIndexOf("\\")),new TrackElement(element,

                            tracks[i]));

                    }

                    else

                    {

                        List<string> patharray = InteractionUtils.GetBrokenPaths(

                            currTrack.Location);

                        element = ItnuesApp.GetPlaylist(Root, patharray);

                        element.SubTracks.Add(patharray[patharray.Count - 1],

                            new TrackElement(element, tracks[i]));

                    }

                    if(ProgressStatus!=null) ProgressStatus(this,

                        new DataEventArgs<CreateEventArgs>(new CreateEventArgs(

                        "Created [" + currTrack.Location + "] - [" + currTrack.Name + "]",

                        i, false)));

                    lastlocation = currentlocation;

                }

                else

                {

                    if(deleteUnfoundtracks ==true)

                    {

                        if (ProgressStatus != null) ProgressStatus(this,

                            new DataEventArgs<CreateEventArgs>(new CreateEventArgs(

                            "Deleted the track [" + currTrack.Name + "]", i, true)));

                    }

                }

            }

            //optionaly deletes the missing tracks.

            foreach (var item in trackstodelete)

            {

                item.Delete();

            }

            //deletes the unrequired subfolders

            if (removeEmptyFolders == true)

            {

                if (ProgressStatus != null) ProgressStatus(this,

                    new DataEventArgs<CreateEventArgs>(new CreateEventArgs(

                    "Removing unrequired folders", i, false)));

                FolderElement singlefolder = Root;

                while (singlefolder.SubFolders.Count <= 1)

                {

                    singlefolder = singlefolder.SubFolders.ElementAt(0).Value;

                }

                if (singlefolder != Root)

                {

                    FolderElement foldertodelete = Root.SubFolders.ElementAt(0).Value;

                    foreach (var item in singlefolder.SubFolders)

                    {

                        item.Value.MoveFolder(Root);

                    }

                    Root.DeleteSubFolder(foldertodelete);

                }

            }

            ItnuesApp.ManageBackup(Root, rootfoldername, keepbackup);

            return true;

        }

   }

}
DashBoard.xaml.cs
using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

using System.Threading;

 

namespace ItnuesPlayListManager

{

    public partial class DashBoard : Window

    {

        Thread navigatethread;

        double MaxTracks = 0;

        public DashBoard()

        {

            InitializeComponent();

            //the scripting object will be locked even after utility terminates.

            //so need to explicitily release those.

            Application.Current.Exit+=new ExitEventHandler((x, y) =>

            {

                ItnuesApp.Disconnect();

                ItnuesPlayListManager.Properties.Settings.Default.Save();

            }

            );

        }

 

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            this.chkRemoveUnfoundtracks.IsChecked = 

                ItnuesPlayListManager.Properties.Settings.Default.RemoveUnFoundTracks;

            this.chkBackCurrent.IsChecked = 

                ItnuesPlayListManager.Properties.Settings.Default.KeepBackup;

            this.txtRootFolderName.Text = 

                ItnuesPlayListManager.Properties.Settings.Default.AutoString;

            this.chkRemoveUnusedRoots.IsChecked = 

                ItnuesPlayListManager.Properties.Settings.Default.RemoveUnusedRoots;

            chkRemoveUnfoundtracks.Checked += new RoutedEventHandler((x, y) =>

            {

                if (MessageBox.Show("This will remove all the tracks from ITnues which" +

                    "the files cannot be located. Files from Removable Media or Network" +

                    " Locations also will be affected. " + Environment.NewLine + 

                    Environment.NewLine + "Checking this option is recommended only" +

                    "if you have all the files in your local Hard Disk.  Are You sure" +

                    " you want to check this option?", "File Removal",

                    MessageBoxButton.YesNo,MessageBoxImage.Question) == MessageBoxResult.No)

                {

                    chkRemoveUnfoundtracks.IsChecked = false;

                    return;

                }

                ItnuesPlayListManager.Properties.Settings.Default.RemoveUnFoundTracks = true;

            });

            chkBackCurrent.Checked += new RoutedEventHandler((x, y) =>

            {

                ItnuesPlayListManager.Properties.Settings.Default.KeepBackup = true;

            });

            chkRemoveUnusedRoots.Checked+=new RoutedEventHandler((x,y) => 

            {

                ItnuesPlayListManager.Properties.Settings.Default.RemoveUnusedRoots = true;

            });

            chkRemoveUnfoundtracks.Unchecked += new RoutedEventHandler((x, y) =>

            {

                ItnuesPlayListManager.Properties.Settings.Default.RemoveUnFoundTracks = false;

            });

            chkBackCurrent.Unchecked += new RoutedEventHandler((x, y) =>

            {

                ItnuesPlayListManager.Properties.Settings.Default.KeepBackup = false;

            });

            chkRemoveUnusedRoots.Unchecked += new RoutedEventHandler((x, y) =>

            {

                ItnuesPlayListManager.Properties.Settings.Default.RemoveUnusedRoots = false;



            });

            txtRootFolderName.TextChanged += new TextChangedEventHandler((x, y) =>

            {

                ItnuesPlayListManager.Properties.Settings.Default.AutoString = 

                    txtRootFolderName.Text;

            });

        }

 

        private void btnsyncplaylist_Click(object sender, RoutedEventArgs e)

        {

            try

            {

                if (txtRootFolderName.Text.Trim().Length < 1)

                {

                    MessageBox.Show("Root folder name cannot be empty.");

                    return;

                }

                if (navigatethread == null)

                {

                    DashBoardController playlistmanager = new DashBoardController();

                    playlistmanager.ProgressStatus += 

                        new EventHandler<DataEventArgs<DashBoardController.CreateEventArgs>>(

                        playlistmanager_ProgressStatus);

                    playlistmanager.BeforeCreate += 

                        new EventHandler<DataEventArgs<double>>((x,

                        y) => { MaxTracks = y.Data; );

                    playlistmanager.AfterCreate += new EventHandler<DataEventArgs<bool>>(

                        playlistmanager_AfterCreate);

                    lstOutput.Items.Clear();

                    lstOutput.Items.Add("Connecting to ITnues Application..");

                    barProgress.Value = 0;

                    navigatethread = new Thread(new ParameterizedThreadStart(

                        playlistmanager.CreatePlaylistTree));

                    navigatethread.Start(new object[] {txtRootFolderName.Text,

                        chkRemoveUnfoundtracks.IsChecked.Value,chkBackCurrent.IsChecked.Value,

                        chkRemoveUnusedRoots.IsChecked.Value});

                    btnsyncplaylist.Content = "Abort";

                }

                else

                {

                    navigatethread.Abort();

                    navigatethread = null;

                    btnsyncplaylist.Content = "Sync Playlist";

                }

            }

            catch (Exception ex)

            {

                lstOutput.Items.Add(ex.Message);

            }

        }

 

        void playlistmanager_AfterCreate(object sender, DataEventArgs<bool> e)

        {

            btnsyncplaylist.Dispatcher.RemoteThreadUpdate(() =>

            {

                btnsyncplaylist.Content = "Sync Playlist";

                navigatethread = null;

            });

        }

 

        void playlistmanager_ProgressStatus(object sender,



            DataEventArgs<DashBoardController.CreateEventArgs> e)

        {

            lstOutput.Dispatcher.RemoteThreadUpdate(() => 

            {

                if (e.Data.IsErrorMessage == false)

                    lstOutput.Items.Insert(0, e.Data.Message);

                else

                {

                    ListBoxItem item = new ListBoxItem();

                    item.Foreground = Brushes.Red;

                    item.Content = e.Data.Message;

                    lstOutput.Items.Insert(0,item);

                }

            });

            barProgress.Dispatcher.RemoteThreadUpdate(() =>

            {

                barProgress.Value = (e.Data.Progress / MaxTracks) * 100;

            }

            );

        }

    }

}
4)性能优化和用户体验方面的改进
确定。最后,我们得到了应用程序的编译和运行。如果您尝试运行应用程序,你可以看到在硬盘上的歌曲文件夹中的结构相同iTunes的应用程序创建的子文件夹。显然,你需要配置iTunes中的iTunes文件夹复制到您的所有歌曲文件,因为你将无法控制您的文件的位置。这是你可以得到很多的音乐你的口袋里,并得到更好地控制你的音乐文件(至少对我的作品完美)的方式。
应用程序启动和正常运行并创建播放列表。但我想带出一些性能调整,并有一些用户体验的项目添加到应用程序。1)多线程组件 - 冗长的操作过程中停止冻结的用户界面
我们可以看到在iTunes的输出,但是,我们的应用程序没有响应,直到操作完成。这是因为UI和后台操作是在同一个线程,所以我们需要从主线程的iTunes操作。因此,我们共创另一个该线程。第1节)
这段代码,可以发现在InteractionUtils类。这个扩展方法的重视,分派对象,我们可以通过一个lambda表达式或Action实例在主线程中执行操作。
        public static void RemoteThreadUpdate(this Dispatcher ctrlControl,

            Action mtdLambadaExpression)

        {

            if (ctrlControl.CheckAccess())

            {

                mtdLambadaExpression();

            }

            else

            {

                ctrlControl.BeginInvoke(DispatcherPriority.Normal, mtdLambadaExpression);

            }

        }
第2节)
一个新的线程被实例(对象发件人,发送RoutedEventArgs)内btnsyncplaylist_Click DashBorad.xaml.cs
        navigatethread = new Thread(new ParameterizedThreadStart(

            playlistmanager.CreatePlaylistTree));

        navigatethread.Start(new object[] {txtRootFolderName.Text,

            chkRemoveUnfoundtracks.IsChecked.Value,chkBackCurrent.IsChecked.Value,

            chkRemoveUnusedRoots.IsChecked.Value});

相关数据传递到业务层,DashBoardController.cs超载
        public void CreatePlaylistTree(object obj)

        {

            object[] objarray = (object[])obj;

            bool val = CreatePlaylistTree((string)objarray[0], (bool)objarray[1],

                (bool)objarray[2],(bool)objarray[3]);

            if (AfterCreate != null) AfterCreate(this,new DataEventArgs<bool>(val));

        }
第3节)
更新进步和操作日志的用户界面,需要从子线程的消息传递。这是通过在DashBoardController.cs一些事件。
        public event EventHandler<DataEventArgs<CreateEventArgs>> ProgressStatus;

 

        public event EventHandler<DataEventArgs<double>> BeforeCreate;

 

        public event EventHandler<DataEventArgs<bool>> AfterCreate;

这些事件在Dashboard.xaml.cs订阅
        void playlistmanager_AfterCreate(object sender, DataEventArgs<bool> e)

 

        void playlistmanager_ProgressStatus(object sender,



            DataEventArgs<DashBoardController.CreateEventArgs> e)
2)循环优化第1节)
iTunes不提供一种机制,存在一个特定的文件夹内找到一个播放列表/文件夹/曲目。 iTunes的软件开发工具包提供了一些有限的搜索功能,但在高度执行的方式,我们需要建立我们自己的搜索算法实现这样的功能。创建的文件夹系统,解决了这个问题。 (最初的时候我没有斜坡;在iTunes上的SDK我注意到缺少此功能,所以我决定创建一个树图系统,应用程序将能够导航和通过树木)。第2节)
我们得到了一些改善左。如果你调试通过曲目列表(LibraryPlaylist.Tracks),你会发现,在大多数情况下,曲目是在连续的顺序,每个文件夹可以包含多个曲目。因此,有没有需要导航从根到叶子,如果在同一播放当前的曲目是最后一首曲目。
这是由一个简单的位置检查,
        if (lastlocation == currentlocation)

创建一个显着的,而这种优化运行的应用程序。在你可以看到小停顿在一个新的文件夹位于输出。3)选择性地删除缺少的轨道
的方法
public bool CreatePlaylistTree(string rootfoldername,bool deleteUnfoundtracks,

    bool keepbackup,bool removeEmptyFolders)

你可以看到这个代码删除哪个位置是空的轨道。我知道iTunes商店原来的位置soemwhere我不能findout。 Probabaly它不是通过COM API之外。
        if (currTrack.Location != null)

        {

        .....

 

        }

        else

        { 

        if(deleteUnfoundtracks ==true)

        {

        if (ProgressStatus != null) ProgressStatus(this,

            new DataEventArgs<CreateEventArgs>(new CreateEventArgs(

            "Deleted the track [" + currTrack.Name + "]", i, true)));

        trackstodelete.Add(currTrack);

        }

        }

 

        ....

        foreach (var item in trackstodelete)

        {

        item.Delete();

        }
4)可以从根目录中删除空文件夹
此功能是有用的,如果主要的音乐文件夹开始像iTunes Music文件夹的子文件夹内的某个地方。我相信而通过iTunes naviagting人不想通过一系列空的播放列表文件夹导航到一个子文件夹达到。的方法,你可以找到这样的代码:
        private void RemoveEmptyFolders(bool removeEmptyFolders)
5)正确断开的iTunes
的iTunes instnce将被锁定,即使在该实用程序终止。出现这种情况,因为。NET不能释放COM资源,即使在应用程序终止。因此,我们需要释放那些explicitily。
        Application.Current.Exit+=new ExitEventHandler((x, y) =>

        {

        ItnuesApp.Disconnect();

        ItnuesPlayListManager.Properties.Settings.Default.Save();

        });
例外该工具只考虑标题可以发现其中的物理路径。通常情况下,如果你打开​​iTunes,如果你看到一个感叹号(!)到您的轨道附近的标志,那些不会自动生成播放列表。我的工作后,这个,你可以期望未来的版本与此修复程序。建议在iTunes中设置的选项,所以它应该不会复制到iTunes中的本地文件夹添加到库中的所有文件。像那些被转换成几个文件确定。太多了,将结束在同样的情况发生默认的iTunes功能,在一个名为"我的音乐"文件夹中有太多的播放列表。系统需求
这个软件是已知的工作具有以下配置:微软视窗XP的SP1/Vista/Windows7微软。NET框架3.5 苹果公司的iTunes 9.0或更高版本
该软件可能工作在不同的配置,但是这并没有核实日期。结论
我希望本文帮助的人希望有一个小工具,他们可以摆脱在发现在他们的苹果音乐播放设备的音乐的痛苦。虽然有很多在MAC平台,我没有看到很多人做接口,在Windows平台上的iTunes。我想给那些希望有一个入门的例子休息。请添加下面在论坛上的意见,建议,和改善。

回答

评论会员:Micmann 时间:2012/01/25
喜四条,

DashBoardController.cs文件使用此代码:

/ /开始创建播放列表和文件夹
(I = 1 I
但是如果你测试,验证,将不包括最后的音乐在你的库。

Insted,使用:
(I = 1 I

最好的问候,

米歇尔 - 巴西
评论会员:Peter_Suhauub 时间:2012/01/25
编译时,这个应用程序将引发2个错误

CS0234和CS0246

请协助
评论会员:!truforce 时间:2012/01/25
所以我解压缩文件,我下载的和无法工作,如何启动应用程序?
对不起,新的IM有点愚蠢的问题
评论会员:!四条约瑟夫 时间:2012/01/25
你的运气不好,有没有可执行源代码提供。您需要编译的源代码,以创建可执行。我无法找到一个位置,在那里我可以后的可执行文件(代码项目的接口不列入提供上传,并非家伙文件didnot做)....您需要有Microsoft Visual Studio来创建您的系统executabel或至少csc.exe的Net框架2.0(让你一个技术人员..)...{ BR}
四条约瑟夫到未来Chiramattel编程