PageRenderTime 119ms CodeModel.GetById 53ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 1ms

/Application/GUI/Windows/MainWindow.xaml.cs

http://yet-another-music-application.googlecode.com/
C# | 4225 lines | 3044 code | 419 blank | 762 comment | 855 complexity | 9652eeb869a0fa5525fb94a2d665a38c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/**
   2 * MainWindow.xaml.cs
   3 * 
   4 * The logic behind the main window. Contains
   5 * the code that connects the different part
   6 * of Stoffi. Sort of like the spider in the net.
   7 * 
   8 * * * * * * * * *
   9 * 
  10 * This code is part of the Stoffi Music Player Project.
  11 * Visit our website at: stoffiplayer.com
  12 *
  13 * This program is free software; you can redistribute it and/or
  14 * modify it under the terms of the GNU General Public License
  15 * as published by the Free Software Foundation; either version
  16 * 3 of the License, or (at your option) any later version.
  17 * 
  18 * See stoffiplayer.com/license for more information.
  19 **/
  20
  21using GlassLib;
  22using System;
  23using System.ComponentModel;
  24using System.Collections;
  25using System.Collections.ObjectModel;
  26using System.Collections.Generic;
  27using System.Collections.Specialized;
  28using System.Configuration;
  29using System.Windows.Data;
  30using System.Globalization;
  31using System.IO;
  32using System.Reflection;
  33using System.Threading;
  34using System.Windows;
  35using System.Windows.Controls;
  36using System.Windows.Input;
  37using System.Windows.Media;
  38using System.Windows.Media.Imaging;
  39using System.Windows.Threading;
  40using System.Windows.Interop;
  41using System.Windows.Shell;
  42using Hardcodet.Wpf.TaskbarNotification;
  43using Microsoft.WindowsAPICodePack.Dialogs;
  44using Microsoft.Win32;
  45using Tomers.WPF.Localization;
  46
  47namespace Stoffi
  48{
  49	/// <summary>
  50	/// Interaction logic for MainWindow.xaml
  51	/// </summary>
  52	public partial class StoffiWindow : Window, INotifyPropertyChanged
  53	{
  54		#region Members
  55
  56		private KeyboardListener kListener = new KeyboardListener();
  57		public ContextMenu trayMenu;
  58		public MenuItem trayMenuShow;
  59		public MenuItem trayMenuPlay;
  60		public MenuItem trayMenuNext;
  61		public MenuItem trayMenuPrev;
  62		public MenuItem trayMenuExit;
  63		private ContextMenu addMenu;
  64		public MenuItem addMenuFile;
  65		public MenuItem addMenuFolder;
  66		public MenuItem addMenuPlaylist;
  67		private ContextMenu showMenu;
  68		public MenuItem showMenuDetailsPane;
  69		public MenuItem showMenuMenuBar;
  70		private ContextMenu toolsMenu;
  71		public MenuItem toolsMenuImporter;
  72		public MenuItem toolsMenuExporter;
  73		public MenuItem toolsMenuGenerate;
  74		public Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton taskbarPrev;
  75		public Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton taskbarPlay;
  76		public Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton taskbarNext;
  77		public TaskbarIcon trayIcon;
  78		private WindowState oldWindowState = WindowState.Minimized;
  79		private WindowState currentWindowState = WindowState.Normal;
  80		public System.Windows.Shell.JumpList jumpList;
  81		public System.Windows.Shell.JumpTask jumpTaskPlay;
  82		public System.Windows.Shell.JumpTask jumpTaskNext;
  83		public System.Windows.Shell.JumpTask jumpTaskPrev;
  84		private bool glassEffect = true;
  85		private List<Key> currentPressedKeys = new List<Key>();
  86		public Microsoft.WindowsAPICodePack.Taskbar.TabbedThumbnail taskbarPreview;
  87		private EditableTextBlock etbInEdit = null;
  88		private Equalizer equalizer = null;
  89		private DispatcherTimer resortDelay = new DispatcherTimer();
  90		private List<string> pathsThatWasChanged = new List<string>();
  91		public MenuItem listMenuPlay = new MenuItem();
  92		public MenuItem listMenuRemove = new MenuItem();
  93		public MenuItem listMenuDelete = new MenuItem();
  94		public MenuItem listMenuInfo = new MenuItem();
  95		public MenuItem listMenuQueue = new MenuItem();
  96		public MenuItem listMenuAddToNew = new MenuItem();
  97		public MenuItem listMenuAddToPlaylist = new MenuItem();
  98		public MenuItem listMenuRemoveFromPlaylist = new MenuItem();
  99		public MenuItem listMenuWatchOnYouTube = new MenuItem();
 100		public MenuItem listMenuShareSong = new MenuItem();
 101		private ContextMenu listMenu = new ContextMenu();
 102		private string dialogPath = @"C:\";
 103		private DispatcherTimer sourceModifiedDelay = new DispatcherTimer();
 104		private Hashtable sourceModifiedTracks = new Hashtable();
 105		private bool doRestart = false;
 106		private TrackData currentlySelectedTrack = null;
 107		private ScannerCallback sourceModifiedCallback;
 108		private bool resumeWhenBack = false; // whether or not to resume playback at login/unlock
 109		private object sourceModifiedCallbackParams;
 110		private bool initialized = false;
 111		private bool showMediaError = false; // whether or not to show errors from media manager as popup
 112
 113		#endregion
 114
 115		#region Properties
 116
 117		/// <summary>
 118		/// The total time of all tracks in the history (in seconds)
 119		/// </summary>
 120		public double HistoryTime { get; private set; }
 121
 122		/// <summary>
 123		/// The total time of all tracks in the queue (in seconds)
 124		/// </summary>
 125		public double QueueTime { get; private set; }
 126
 127		/// <summary>
 128		/// The total time of all tracks in the library (in seconds)
 129		/// </summary>
 130		public double LibraryTime { get; private set; }
 131
 132		/// <summary>
 133		/// A table of the TrackList for each playlist
 134		/// </summary>
 135		public Hashtable PlaylistTrackLists { get; private set; }
 136
 137		/// <summary>
 138		/// The height of the details pane
 139		/// </summary>
 140		public double DetailsPaneHeight
 141		{
 142			get { return SettingsManager.DetailsPaneHeight; }
 143			set { SettingsManager.DetailsPaneHeight = value; }
 144		}
 145
 146		#endregion
 147
 148		#region Constructor
 149
 150		/// <summary>
 151		/// 
 152		/// </summary>
 153		public StoffiWindow()
 154		{
 155			U.L(LogLevel.Debug, "MAIN", "Creating main window");
 156			//SettingsManager.FirstRun = true;
 157			//*********** Next ***********/
 158			// TODO: In-place track edit
 159			// TODO: Images (currently playing, queue) in front of t + style
 160			// TODO: Images (currently playing) in front of playlists/library
 161			// TODO: MusicBrainz
 162			// TODO: Jumplist: playlists
 163			// TODO: Drag search text
 164			// TODO: Track score (how good is it?)
 165			// TODO: Last.fm support
 166			// TODO: Spotify
 167			// TODO: Spectrum
 168			// TODO: Views (album, artist, genre, all)
 169			// TODO: Playlist view
 170			// TODO: Network sources
 171			// TODO: Device sources
 172			// TODO: Tools for cutting track
 173			// TODO: Album cover download
 174			// TODO: Lyrics
 175			// TODO: Radio
 176			// TODO: TaskDialogs
 177			// TODO: Wikipedia
 178			// TODO: Social music
 179
 180			U.L(LogLevel.Debug, "MAIN", "Setting culture");
 181			LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo(SettingsManager.Language);
 182
 183			if (!Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.IsPlatformSupported)
 184			{
 185				MessageBox.Show(U.T("MessageOldWindows", "Message"), U.T("MessageOldWindows", "Title"), MessageBoxButton.OK, MessageBoxImage.Error);
 186				Application.Current.Shutdown();
 187				return;
 188			}
 189
 190			U.L(LogLevel.Debug, "MAIN", "Initialize");
 191			InitializeComponent();
 192			U.L(LogLevel.Debug, "MAIN", "Initialized");
 193
 194			// we have to remove controls from their parent so "LastChildFill" doesn't screw everything up
 195			// we add them later on when they are toggled
 196			MainContainer.Children.Remove(ControlPanel);
 197		}
 198
 199		#endregion
 200
 201		#region Methods
 202
 203		#region Public
 204
 205		/// <summary>
 206		/// Restarts the application
 207		/// </summary>
 208		public void Restart()
 209		{
 210			doRestart = true;
 211			this.Close();
 212		}
 213
 214		/// <summary>
 215		/// 
 216		/// </summary>
 217		/// <param name="modifiers"></param>
 218		/// <returns></returns>
 219		public String GetModifiersAsText(List<Key> modifiers)
 220		{
 221			String txt = "";
 222			foreach (Key k in modifiers)
 223			{
 224				if (k == Key.LeftCtrl || k == Key.RightCtrl) txt += "Ctrl+";
 225				else if (k == Key.LeftAlt || k == Key.RightAlt) txt += "Alt+";
 226				else if (k == Key.LWin || k == Key.RWin) txt += "Win+";
 227				else if (k == Key.LeftShift || k == Key.RightShift) txt += "Shift+";
 228			}
 229			if (txt.Length > 0) return txt.Substring(0, txt.Length - 1);
 230			else return "";
 231		}
 232
 233		/// <summary>
 234		/// 
 235		/// </summary>
 236		/// <param name="k"></param>
 237		/// <returns></returns>
 238		public String KeyToString(Key k)
 239		{
 240			switch (k)
 241			{
 242				case Key.NumPad0:
 243					return "0 (numpad)";
 244				case Key.NumPad1:
 245					return "1 (numpad)";
 246				case Key.NumPad2:
 247					return "2 (numpad)";
 248				case Key.NumPad3:
 249					return "3 (numpad)";
 250				case Key.NumPad4:
 251					return "4 (numpad)";
 252				case Key.NumPad5:
 253					return "5 (numpad)";
 254				case Key.NumPad6:
 255					return "6 (numpad)";
 256				case Key.NumPad7:
 257					return "7 (numpad)";
 258				case Key.NumPad8:
 259					return "8 (numpad)";
 260				case Key.NumPad9:
 261					return "9 (numpad)";
 262				case Key.D0:
 263					return "0";
 264				case Key.D1:
 265					return "1";
 266				case Key.D2:
 267					return "2";
 268				case Key.D3:
 269					return "3";
 270				case Key.D4:
 271					return "4";
 272				case Key.D5:
 273					return "5";
 274				case Key.D6:
 275					return "6";
 276				case Key.D7:
 277					return "7";
 278				case Key.D8:
 279					return "8";
 280				case Key.D9:
 281					return "9";
 282				case Key.OemComma:
 283					return ",";
 284				case Key.OemPeriod:
 285					return ".";
 286				case Key.Subtract:
 287					return "-";
 288				case Key.Multiply:
 289					return "*";
 290				case Key.Divide:
 291					return "/";
 292				case Key.Add:
 293					return "+";
 294				case Key.Back:
 295					return "Backspace";
 296				case Key.OemMinus:
 297					return "-";
 298				case Key.CapsLock:
 299					return "CapsLock";
 300				case Key.Scroll:
 301					return "ScrollLock";
 302				case Key.PrintScreen:
 303					return "PrintScreen";
 304				case Key.Return:
 305					return "Enter";
 306				case Key.PageDown:
 307					return "PageDown";
 308				case Key.PageUp:
 309					return "PageUp";
 310
 311				// TODO: hardcoded temporary fix
 312				case Key.Oem3:
 313					return "´";
 314				case Key.OemPlus:
 315					return "=";
 316				case Key.OemOpenBrackets:
 317					return "[";
 318				case Key.Oem6:
 319					return "]";
 320				case Key.Oem5:
 321					return @"\";
 322				case Key.Oem1:
 323					return ";";
 324				case Key.OemQuotes:
 325					return "'";
 326				case Key.OemQuestion:
 327					return "/";
 328
 329				default:
 330					return k.ToString();
 331			}
 332		}
 333
 334		/// <summary>
 335		/// 
 336		/// </summary>
 337		/// <param name="argument"></param>
 338		public void CallFromSecondInstance(String argument)
 339		{
 340			if (argument == "/play")
 341			{
 342				PlayPause();
 343			}
 344			else if (argument == "/next")
 345			{
 346				MediaManager.Next();
 347				if (SettingsManager.MediaState != MediaState.Playing)
 348					MediaManager.Tick(null, null);
 349			}
 350			else if (argument == "/previous")
 351			{
 352				MediaManager.Previous();
 353				if (SettingsManager.MediaState != MediaState.Playing)
 354					MediaManager.Tick(null, null);
 355			}
 356			else
 357			{
 358				if (File.Exists(argument))
 359				{
 360					// file is a playlist
 361					if (PlaylistManager.IsSupported(argument))
 362					{
 363						PlaylistData pl = PlaylistManager.LoadPlaylist(argument);
 364						if (pl != null)
 365						{
 366							NavigationPane.SwitchNavigation("Playlist:" + pl.Name);
 367							if (pl.Tracks.Count > 0)
 368							{
 369								MediaManager.Load(pl.Tracks[0]);
 370								MediaManager.Play();
 371							}
 372						}
 373					}
 374
 375					// file is a track
 376					else if (MediaManager.IsSupported(argument))
 377					{
 378						Open(argument);
 379					}
 380				}
 381				// TODO: bring to front
 382			}
 383		}
 384
 385		/// <summary>
 386		/// Retrives the currently selected track list's source.
 387		/// </summary>
 388		/// <returns>The collection used as ItemsSource for the current track list</returns>
 389		public ObservableCollection<TrackData> GetCurrentTrackCollection()
 390		{
 391			if (SettingsManager.CurrentSelectedNavigation == "History")
 392				return SettingsManager.HistoryTracks;
 393			else if (SettingsManager.CurrentSelectedNavigation == "Queue")
 394				return SettingsManager.QueueTracks;
 395			else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
 396			{
 397				PlaylistData p = PlaylistManager.FindPlaylist(SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1]);
 398				if (p == null) return null;
 399				return p.Tracks;
 400			}
 401			else if (SettingsManager.CurrentSelectedNavigation == "Files")
 402				return SettingsManager.FileTracks;
 403			else if (SettingsManager.CurrentSelectedNavigation == "YouTube")
 404				return YouTubeManager.TrackSource;
 405			else
 406				return null;
 407		}
 408
 409		/// <summary>
 410		/// 
 411		/// </summary>
 412		/// <returns></returns>
 413		public ViewDetails GetCurrentTrackList()
 414		{
 415			if (SettingsManager.CurrentSelectedNavigation == "History")
 416				return HistoryTracks;
 417			else if (SettingsManager.CurrentSelectedNavigation == "Queue")
 418				return QueueTracks;
 419			else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
 420				return (ViewDetails)PlaylistTrackLists[SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1]];
 421			else if (SettingsManager.CurrentSelectedNavigation == "Files")
 422				return FileTracks;
 423			else if (SettingsManager.CurrentSelectedNavigation == "YouTube")
 424				return YouTubeContainer.YouTubeTracks;
 425			else
 426				return null;
 427		}
 428
 429		/// <summary>
 430		/// 
 431		/// </summary>
 432		/// <returns></returns>
 433		public ViewDetails GetActiveTrackList()
 434		{
 435			string can = SettingsManager.CurrentActiveNavigation;
 436			if (can == "History" || can == "Queue")
 437				can = SettingsManager.CurrentTrack == null ? "Files" : SettingsManager.CurrentTrack.Source;
 438
 439			if (can.StartsWith("Playlist:"))
 440			{
 441				PlaylistData p = PlaylistManager.FindPlaylist(can.Split(new[] { ':' }, 2)[1]);
 442				if (p != null)
 443					return (ViewDetails)PlaylistTrackLists[p.Name];
 444			}
 445			if (can == "YouTube")
 446				return YouTubeContainer.YouTubeTracks;
 447			else
 448				return FileTracks;
 449		}
 450
 451		/// <summary>
 452		/// 
 453		/// </summary>
 454		/// <param name="name"></param>
 455		public void OnPropertyChanged(string name)
 456		{
 457			if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
 458		}
 459
 460		#endregion
 461
 462		#region Private
 463
 464		/// <summary>
 465		/// Play the currently selected track
 466		/// </summary>
 467		/// <param name="resume">Resume at the current position if the selected track is the CurrentTrack</param>
 468		private void Play(bool resume = false)
 469		{
 470			showMediaError = true;
 471
 472			if (resume && SettingsManager.CurrentTrack != null)
 473				MediaManager.Play();
 474
 475			else if (GetCurrentTrackList().SelectedItem is TrackData)
 476			{
 477				string pl = "";
 478
 479				if (SettingsManager.CurrentSelectedNavigation == "Library")
 480					pl = "";
 481				else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
 482					pl = SettingsManager.CurrentSelectedNavigation.Split(new[]{':'},2)[1];
 483
 484				TrackData track = GetCurrentTrackList().SelectedItem as TrackData;
 485				MediaManager.TrackCollection = GetCurrentTrackList().Items;
 486
 487				if (SettingsManager.CurrentSelectedNavigation == "History")
 488					SettingsManager.HistoryIndex = SettingsManager.HistoryTracks.IndexOf(track);
 489				else
 490					SettingsManager.HistoryIndex = SettingsManager.HistoryTracks.Count;
 491
 492				SettingsManager.CurrentActiveNavigation = SettingsManager.CurrentSelectedNavigation;
 493
 494				if (SettingsManager.CurrentActiveNavigation.StartsWith("Playlist:"))
 495					PlaylistManager.CurrentPlaylist = SettingsManager.CurrentActiveNavigation.Split(new[] { ':' }, 2)[1];
 496				else
 497					PlaylistManager.CurrentPlaylist = "";
 498
 499
 500				MediaManager.Stop();
 501				MediaManager.Load(track);
 502				MediaManager.Play();
 503			}
 504		}
 505
 506		/// <summary>
 507		/// Toggle the play and pause state
 508		/// </summary>
 509		private void PlayPause()
 510		{
 511			if (SettingsManager.MediaState == MediaState.Playing)
 512				SettingsManager.MediaState = MediaState.Paused;
 513			else
 514				SettingsManager.MediaState = MediaState.Playing;
 515		}
 516
 517		/// <summary>
 518		/// Removes a set of tracks from a given collection of tracks.
 519		/// </summary>
 520		/// <param name="tracksToRemove">The tracks to remove</param>
 521		/// <param name="tracks">The collection from where to remove the tracks</param>
 522		private void RemoveTracks(SortedList<string, TrackData> tracksToRemove, ObservableCollection<TrackData> tracks)
 523		{
 524			for (int i = 0; i < tracks.Count; i++)
 525			{
 526				if (tracksToRemove.ContainsKey(tracks[i].Path))
 527				{
 528					tracks.RemoveAt(i--);
 529				}
 530			}
 531		}
 532
 533		/// <summary>
 534		/// Removes a set of tracks from a given collection of tracks.
 535		/// </summary>
 536		/// <param name="tracksToRemove">The tracks to remove</param>
 537		/// <param name="tracks">The collection from where to remove the tracks</param>
 538		private void RemoveTracks(SortedList<string, TrackData> tracksToRemove, List<TrackData> tracks)
 539		{
 540			for (int i = 0; i < tracks.Count; i++)
 541			{
 542				if (tracksToRemove.ContainsKey(tracks[i].Path))
 543				{
 544					tracks.RemoveAt(i--);
 545				}
 546			}
 547		}
 548
 549		/// <summary>
 550		/// Removes tracks with a given filename for a specific collection of tracks
 551		/// </summary>
 552		/// <param name="filename">The filename of the tracks to remove</param>
 553		/// <param name="tracks">The collection of tracks from which to remove</param>
 554		private void RemoveTrack(String filename, ObservableCollection<TrackData> tracks)
 555		{
 556			for (int i = 0; i < tracks.Count; i++)
 557			{
 558				if (tracks[i].Path == filename)
 559				{
 560					tracks.RemoveAt(i);
 561					break;
 562				}
 563			}
 564		}
 565
 566		/// <summary>
 567		/// Removes tracks with a given filename for a specific list of tracks
 568		/// </summary>
 569		/// <param name="filename">The filename of the tracks to remove</param>
 570		/// <param name="tracks">The list of tracks from which to remove</param>
 571		private void RemoveTrack(String filename, List<TrackData> tracks)
 572		{
 573			for (int i = 0; i < tracks.Count; i++)
 574			{
 575				if (tracks[i].Path == filename)
 576				{
 577					tracks.RemoveAt(i);
 578					break;
 579				}
 580			}
 581		}
 582
 583		/// <summary>
 584		/// Reapply the sorting on a tracklist
 585		/// </summary>
 586		/// <param name="tl">The tracklist to re-sort</param>
 587		/// <param name="paths">A list of the paths that was changed</param>
 588		private void ResortTracklist(ViewDetails tl, List<string> paths)
 589		{
 590			bool resort = false;
 591			foreach (TrackData t in SettingsManager.FileTracks)
 592			{
 593				if (paths.Contains(t.Path))
 594				{
 595					resort = true;
 596					break;
 597				}
 598			}
 599			if (resort)
 600			{
 601				if (tl.Items.SortDescriptions.Count > 0)
 602				{
 603					SortDescription sd = tl.Items.SortDescriptions[0];
 604					tl.Items.SortDescriptions.Remove(sd);
 605					tl.Items.SortDescriptions.Insert(0, sd);
 606				}
 607			}
 608		}
 609
 610		/// <summary>
 611		/// Load a file and add it according to the AddPolicy and play 
 612		/// it according to the PlayPolicy
 613		/// </summary>
 614		/// <param name="filename">The filename of the track</param>
 615		/// <param name="forcePlay">Whether or not to override the PlayPolicy</param>
 616		private void Open(string filename, bool forcePlay = false)
 617		{
 618			U.L(LogLevel.Debug, "MAIN", "Opening " + filename);
 619			OpenAddPolicy DoAdd = SettingsManager.OpenAddPolicy;
 620			OpenPlayPolicy DoPlay = SettingsManager.OpenPlayPolicy;
 621			TrackData track = null;
 622
 623			// add track
 624			if (DoAdd == OpenAddPolicy.Library || DoAdd == OpenAddPolicy.LibraryAndPlaylist)
 625			{
 626				// add track to library if needed
 627				track = FilesystemManager.GetTrack(filename);
 628				if (track == null)
 629				{
 630					U.L(LogLevel.Debug, "MAIN", "Adding to collection");
 631					FilesystemManager.AddSource(new SourceData() 
 632					{ 
 633						Data = filename, 
 634						Include = true, 
 635						HumanType = U.T("SourcesTypeFile"),
 636						Type = SourceType.File 
 637					});
 638					track = FilesystemManager.GetTrack(filename);
 639				}
 640
 641				if (track == null)
 642					U.L(LogLevel.Warning, "MAIN", "Could not add track to Library: " + filename);
 643
 644				// add track to current playlist as well
 645				if (DoAdd == OpenAddPolicy.LibraryAndPlaylist && track != null)
 646				{
 647					if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
 648					{
 649						U.L(LogLevel.Debug, "MAIN", "Adding to current playlist");
 650						String playlistName = SettingsManager.CurrentSelectedNavigation.Split(new[]{':'},2)[1];
 651						List<object> tracks = new List<object>();
 652						tracks.Add(track);
 653						PlaylistManager.AddToPlaylist(tracks, playlistName);
 654					}
 655				}
 656			}
 657
 658			// play track
 659			if (DoPlay != OpenPlayPolicy.DoNotPlay || forcePlay)
 660			{
 661				// create track if it is null
 662				if (track == null)
 663				{
 664					U.L(LogLevel.Debug, "MAIN", "Creating track");
 665					track = FilesystemManager.CreateTrack(filename);
 666					if (track == null)
 667					{
 668						U.L(LogLevel.Warning, "MAIN", "Could not create track for: " + filename);
 669						return;
 670					}
 671					FilesystemManager.UpdateTrack(track);
 672				}
 673
 674				if (DoPlay == OpenPlayPolicy.Play || forcePlay)
 675				{
 676					U.L(LogLevel.Debug, "MAIN", "Playing track");
 677					MediaManager.Stop();
 678					MediaManager.Load(track);
 679					MediaManager.Play();
 680
 681					if (DoAdd == OpenAddPolicy.LibraryAndPlaylist && SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
 682						SettingsManager.CurrentActiveNavigation = SettingsManager.CurrentSelectedNavigation;
 683					else if (DoAdd == OpenAddPolicy.Library)
 684						SettingsManager.CurrentActiveNavigation = "Library";
 685				}
 686
 687				else if (DoPlay == OpenPlayPolicy.BackOfQueue)
 688					MediaManager.Queue(new List<TrackData>() { track });
 689
 690				else if (DoPlay == OpenPlayPolicy.FrontOfQueue)
 691					MediaManager.Queue(new List<TrackData>() { track }, 0);
 692			}
 693		}
 694
 695		/// <summary>
 696		/// Creates a playlist track list and navigation items
 697		/// </summary>
 698		/// <param name="playlist">The data for the playlist to create</param>
 699		/// <param name="select">Whether to select the playlist after it has been created</param>
 700		private void CreatePlaylist(PlaylistData playlist, bool select = true)
 701		{
 702			Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
 703			{
 704				// create track list
 705				ViewDetails vd = new ViewDetails();
 706				Grid.SetRow(vd, 1);
 707				TrackContainer.Children.Add(vd);
 708				vd.ItemsSource = playlist.Tracks;
 709				playlist.Tracks.CollectionChanged +=
 710					new System.Collections.Specialized.NotifyCollectionChangedEventHandler(vd.ItemsSource_CollectionChanged);
 711				if (playlist.ListConfig == null)
 712				{
 713					ViewDetailsConfig vdc = SettingsManager.CreateListConfig();
 714					SettingsManager.InitViewDetailsConfig(vdc);
 715					vdc.HasNumber = true;
 716					playlist.ListConfig = vdc;
 717				}
 718				if (PlaylistTrackLists.ContainsKey(playlist.Name))
 719					PlaylistTrackLists.Remove(playlist.Name);
 720				PlaylistTrackLists.Add(playlist.Name, vd);
 721				vd.ContextMenu = listMenu;
 722				vd.Visibility = Visibility.Collapsed;
 723				vd.BorderThickness = new Thickness(0);
 724				vd.ItemsSource = playlist.Tracks;
 725				vd.Config = playlist.ListConfig;
 726				vd.FilterMatch = TrackList_SearchMatch;
 727				vd.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
 728				vd.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
 729				vd.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
 730				vd.FilesDropped += new FileDropEventHandler(TrackList_FilesDropped);
 731				vd.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
 732
 733				// create the item in the navigation tree
 734				TreeViewItem item = new TreeViewItem();
 735				item.Selected += NavigationPane.Playlist_Selected;
 736				item.Drop += NavigationPane.Playlist_Drop;
 737				item.KeyDown += NavigationPlaylist_KeyDown;
 738				item.Tag = playlist.Name;
 739				item.Padding = new Thickness(8, 0, 0, 0);
 740
 741				StackPanel sp = new StackPanel();
 742				sp.Orientation = System.Windows.Controls.Orientation.Horizontal;
 743
 744				Image img = new Image();
 745				img.Source = Utilities.GetIcoImage("pack://application:,,,/GUI/Images/Icons/DiscAudio.ico", 16, 16);
 746				img.Width = 16;
 747				img.Height = 16;
 748				sp.Children.Add(img);
 749
 750				EditableTextBlock etb = new EditableTextBlock();
 751				etb.EnteredEditMode += new EventHandler(EditableTextBlock_EnteredEditMode);
 752				etb.Text = playlist.Name;
 753				etb.Margin = new Thickness(5, 0, 5, 0);
 754				etb.Edited += NavigationPane.Playlist_Edited;
 755				sp.Children.Add(etb);
 756
 757				item.Header = sp;
 758				item.ContextMenuOpening += new ContextMenuEventHandler(NavigationPane.Playlist_ContextMenuOpening);
 759				item.ContextMenu = NavigationPane.playlistMenu;
 760				NavigationPane.Playlists.Items.Insert(NavigationPane.Playlists.Items.Count - 1, item);
 761				if (select)
 762					item.Focus();
 763
 764				// create list context menu items
 765				MenuItem miAdd = new MenuItem();
 766				miAdd.Header = playlist.Name;
 767				miAdd.Click += new RoutedEventHandler(listMenuAddToPlaylist_Click);
 768				listMenuAddToPlaylist.Visibility = System.Windows.Visibility.Visible;
 769				listMenuAddToPlaylist.Items.Insert(listMenuAddToPlaylist.Items.Count - 1, miAdd);
 770
 771				MenuItem miDel = new MenuItem();
 772				miDel.Header = playlist.Name;
 773				miDel.Click += new RoutedEventHandler(listMenuRemoveFromPlaylist_Click);
 774				listMenuRemoveFromPlaylist.Visibility = System.Windows.Visibility.Visible;
 775				listMenuRemoveFromPlaylist.Items.Add(miDel);
 776
 777				PlaybackControls.Search.AddPlaylist(playlist);
 778			}));
 779		}
 780
 781		/// <summary>
 782		/// Updates the visibility of a given element according to the settings
 783		/// </summary>
 784		/// <param name="element">The element to update (menubar or details)</param>
 785		private void UpdateVisibility(string element)
 786		{
 787			switch (element)
 788			{
 789				case "menubar":
 790					bool mv = SettingsManager.MenuBarVisibile;
 791					showMenuMenuBar.IsChecked = mv;
 792					MenuItemViewMenuBar.IsChecked = mv;
 793					MenuBar.Visibility = mv ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
 794					break;
 795
 796				case "details":
 797					bool dv = SettingsManager.DetailsPaneVisible;
 798					showMenuDetailsPane.IsChecked = dv;
 799					MenuItemViewDetailsPane.IsChecked = dv;
 800					DetailsRow.MinHeight = (dv ? 80 : 0);
 801					DetailsRow.Height = new GridLength((dv ? SettingsManager.DetailsPaneHeight : 0));
 802					DetailsPane.Visibility = dv ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
 803					HorizontalSplitter.Visibility = dv ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
 804					break;
 805			}
 806		}
 807
 808		/// <summary>
 809		/// Updates the strings around the GUI, that are hardcoded, according to the current Language
 810		/// </summary>
 811		private void UpdateGUIStrings()
 812		{
 813			// change column headers of list views
 814			foreach (ViewDetailsColumn c in SettingsManager.SourceListConfig.Columns)
 815			{
 816				if (c.Binding == "HumanType") c.Text = U.T("ColumnType");
 817				else if (c.Binding == "Data") c.Text = U.T("ColumnLocation");
 818			}
 819			foreach (ViewDetailsColumn c in SettingsManager.YouTubeListConfig.Columns)
 820			{
 821				if (c.Binding == "Artist")      c.Text = U.T("ColumnArtist");
 822				else if (c.Binding == "Title")  c.Text = U.T("ColumnTitle");
 823				else if (c.Binding == "Path")   c.Text = U.T("ColumnPath");
 824				else if (c.Binding == "Length") c.Text = U.T("ColumnLength");
 825			}
 826			foreach (ViewDetailsColumn c in SettingsManager.FileListConfig.Columns)
 827			{
 828				if (c.Binding == "Artist")          c.Text = U.T("ColumnArtist");
 829				else if (c.Binding == "Title")      c.Text = U.T("ColumnTitle");
 830				else if (c.Binding == "Album")      c.Text = U.T("ColumnAlbum");
 831				else if (c.Binding == "Genre")      c.Text = U.T("ColumnGenre");
 832				else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnLastPlayed");
 833				else if (c.Binding == "Length")     c.Text = U.T("ColumnLength");
 834				else if (c.Binding == "PlayCount")  c.Text = U.T("ColumnPlayCount");
 835				else if (c.Binding == "Path")       c.Text = U.T("ColumnPath");
 836				else if (c.Binding == "Track")      c.Text = U.T("ColumnTrack");
 837				else if (c.Binding == "Year")       c.Text = U.T("ColumnYear");
 838			}
 839			foreach (ViewDetailsColumn c in SettingsManager.QueueListConfig.Columns)
 840			{
 841				if (c.Binding == "Artist")          c.Text = U.T("ColumnArtist");
 842				else if (c.Binding == "Title")      c.Text = U.T("ColumnTitle");
 843				else if (c.Binding == "Album")      c.Text = U.T("ColumnAlbum");
 844				else if (c.Binding == "Genre")      c.Text = U.T("ColumnGenre");
 845				else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnLastPlayed");
 846				else if (c.Binding == "Length")     c.Text = U.T("ColumnLength");
 847				else if (c.Binding == "PlayCount")  c.Text = U.T("ColumnPlayCount");
 848				else if (c.Binding == "Path")       c.Text = U.T("ColumnPath");
 849				else if (c.Binding == "Track")      c.Text = U.T("ColumnTrack");
 850				else if (c.Binding == "Year")       c.Text = U.T("ColumnYear");
 851			}
 852			foreach (ViewDetailsColumn c in SettingsManager.HistoryListConfig.Columns)
 853			{
 854				if (c.Binding == "Artist")          c.Text = U.T("ColumnArtist");
 855				else if (c.Binding == "Title")      c.Text = U.T("ColumnTitle");
 856				else if (c.Binding == "Album")      c.Text = U.T("ColumnAlbum");
 857				else if (c.Binding == "Genre")      c.Text = U.T("ColumnGenre");
 858				else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnPlayed");
 859				else if (c.Binding == "Length")     c.Text = U.T("ColumnLength");
 860				else if (c.Binding == "PlayCount")  c.Text = U.T("ColumnPlayCount");
 861				else if (c.Binding == "Path")       c.Text = U.T("ColumnPath");
 862				else if (c.Binding == "Track")      c.Text = U.T("ColumnTrack");
 863				else if (c.Binding == "Year")       c.Text = U.T("ColumnYear");
 864			}
 865			foreach (PlaylistData p in SettingsManager.Playlists)
 866				foreach (ViewDetailsColumn c in p.ListConfig.Columns)
 867				{
 868					if (c.Binding == "Artist")          c.Text = U.T("ColumnArtist");
 869					else if (c.Binding == "Title")      c.Text = U.T("ColumnTitle");
 870					else if (c.Binding == "Album")      c.Text = U.T("ColumnAlbum");
 871					else if (c.Binding == "Genre")      c.Text = U.T("ColumnGenre");
 872					else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnPlayed");
 873					else if (c.Binding == "Length")     c.Text = U.T("ColumnLength");
 874					else if (c.Binding == "PlayCount")  c.Text = U.T("ColumnPlayCount");
 875					else if (c.Binding == "Path")       c.Text = U.T("ColumnPath");
 876					else if (c.Binding == "Track")      c.Text = U.T("ColumnTrack");
 877					else if (c.Binding == "Year")       c.Text = U.T("ColumnYear");
 878				}
 879
 880			// change source types
 881			foreach (SourceData s in SettingsManager.Sources)
 882				switch (s.Type)
 883				{
 884					case SourceType.File:
 885						s.HumanType = U.T("SourcesTypeFile");
 886						break;
 887
 888					case SourceType.Folder:
 889						s.HumanType = U.T("SourcesTypeFolder");
 890						break;
 891
 892					case SourceType.Library:
 893						s.HumanType = U.T("SourcesTypeLibrary");
 894						break;
 895				}
 896
 897			// change shortcuts
 898			ControlPanel.GlobalLabel.Content = U.T("ShortcutGlobal");
 899			foreach (TextBlock t in ControlPanel.ShortcutTitles)
 900				t.Text = U.T((string)t.Tag);
 901			foreach (TextBlock t in ControlPanel.ShortcutDescriptions)
 902				t.Text = U.T((string)t.Tag);
 903			foreach (Label l in ControlPanel.ShortcutLabels)
 904				l.Content = U.T((string)l.Tag);
 905
 906			// change menus
 907			trayMenuShow.Header = U.T("TrayShow");
 908			trayMenuPlay.Header = U.T("TrayPlay");
 909			trayMenuNext.Header = U.T("TrayNext");
 910			trayMenuPrev.Header = U.T("TrayPrev");
 911			trayMenuExit.Header = U.T("TrayExit");
 912			taskbarPlay.Tooltip = U.T("TaskbarPlay");
 913			taskbarNext.Tooltip = U.T("TaskbarNext");
 914			taskbarPrev.Tooltip = U.T("TaskbarPrev");
 915			jumpTaskPlay.Title = U.T("JumpPlay", "Title");
 916			jumpTaskNext.Title = U.T("JumpNext", "Title");
 917			jumpTaskPrev.Title = U.T("JumpPrev", "Title");
 918			jumpTaskPlay.Description = U.T("JumpPlay", "Description");
 919			jumpTaskNext.Description = U.T("JumpNext", "Description");
 920			jumpTaskPrev.Description = U.T("JumpPrev", "Description");
 921			listMenuAddToPlaylist.Header = U.T("MenuAddToPlaylist", "Header");
 922			listMenuAddToNew.Header = U.T("MenuCreateNew", "Header");
 923			listMenuDelete.Header = U.T("MenuDelete");
 924			listMenuInfo.Header = U.T("MenuInfo");
 925			listMenuPlay.Header = U.T("MenuPlay");
 926			listMenuQueue.Header = U.T("MenuQueue");
 927			listMenuRemove.Header = U.T("MenuRemove");
 928			listMenuRemoveFromPlaylist.Header = U.T("MenuRemoveFromPlaylist", "Header");
 929			listMenuWatchOnYouTube.Header = U.T("MenuWatchOnYouTube");
 930			listMenuShareSong.Header = U.T("MenuShareSong");
 931			addMenuFile.Header = U.T("ToolbarAddTrack");
 932			addMenuFolder.Header = U.T("ToolbarAddFolder");
 933			addMenuPlaylist.Header = U.T("ToolbarAddPlaylist");
 934			showMenuDetailsPane.Header = U.T("ToolbarDetailsPane");
 935			showMenuMenuBar.Header = U.T("ToolbarMenuBar");
 936			toolsMenuExporter.Header = U.T("ToolbarExporter");
 937			toolsMenuImporter.Header = U.T("ToolbarImporter");
 938			toolsMenuGenerate.Header = U.T("ToolbarGeneratePlaylist");
 939			NavigationPane.playlistMenuRemove.Header = U.T("MenuRemovePlaylist");
 940			NavigationPane.playlistMenuRename.Header = U.T("MenuRenamePlaylist");
 941			NavigationPane.playlistMenuSave.Header = U.T("MenuSavePlaylist");
 942			NavigationPane.playlistMenuShare.Header = U.T("MenuSharePlaylist");
 943			NavigationPane.CreateNewPlaylistETB.Text = U.T("NavigationCreateNew");
 944			ControlPanel.menuRemove.Header = U.T("MenuRemove");
 945
 946			// change tracklist header
 947			string csn = SettingsManager.CurrentSelectedNavigation;
 948			switch (csn)
 949			{
 950				case "Files":
 951					InfoPaneTitle.Text = U.T("NavigationFilesTitle");
 952					InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)LibraryTime)); ;
 953					InfoPaneTracks.Text = SettingsManager.FileTracks.Count.ToString() + " " + U.T("HeaderTracks");
 954					break;
 955
 956				case "Queue":
 957					InfoPaneTitle.Text = U.T("NavigationQueueTitle");
 958					InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)QueueTime)); ;
 959					InfoPaneTracks.Text = SettingsManager.QueueTracks.Count.ToString() + " " + U.T("HeaderTracks");
 960					break;
 961
 962				case "History":
 963					InfoPaneTitle.Text = U.T("NavigationHistoryTitle");
 964					InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)HistoryTime)); ;
 965					InfoPaneTracks.Text = SettingsManager.HistoryTracks.Count.ToString() + " " + U.T("HeaderTracks");
 966					break;
 967
 968				default:
 969					if (csn.StartsWith("Playlist:"))
 970					{
 971						PlaylistData p = PlaylistManager.FindPlaylist(csn.Split(new[] { ':' }, 2)[1]);
 972						InfoPaneTitle.Text = U.T("NavigationPlaylistTitle") + " '" + p.Name + "'";
 973						InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)p.Time)); ;
 974						InfoPaneTracks.Text = p.Tracks.Count.ToString() + " " + U.T("HeaderTracks");
 975					}
 976					break;
 977			}
 978		}
 979
 980		/// <summary>
 981		/// Will repaint the glass effect behind the playback pane.
 982		/// </summary>
 983		private void RefreshGlassEffect()
 984		{
 985			try
 986			{
 987				Dwm.Glass[this].Enabled = true;
 988				Thickness foo = new Thickness(1, 75, 1, 1);
 989				Dwm.Glass[this].Margins = foo;
 990				Background = Brushes.Transparent;
 991				glassEffect = true;
 992			}
 993			catch (Exception e)
 994			{
 995				U.L(LogLevel.Warning, "MAIN", "Could not set glass effect: " + e.Message);
 996				if (System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName == "")
 997					Background = SystemColors.ControlBrush;
 998				else
 999					Background = SystemColors.GradientActiveCaptionBrush;
1000				glassEffect = false;
1001			}
1002		}
1003
1004		/// <summary>
1005		/// Initializes the GUI
1006		/// </summary>
1007		private void InitGUI()
1008		{
1009			U.L(LogLevel.Debug, "MAIN", "Init settings manager");
1010			SettingsManager.Initialize();
1011
1012			U.L(LogLevel.Debug, "MAIN", "Init service manager");
1013			ServiceManager.Initialize();
1014
1015			// create playlists
1016			ThreadStart PlaylistThread = delegate()
1017			{
1018				Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
1019				{
1020					if (SettingsManager.CurrentSelectedNavigation == "YouTube")
1021						NavigationPane.Youtube.Focus();
1022					else if (SettingsManager.CurrentSelectedNavigation == "Queue")
1023						NavigationPane.Queue.Focus();
1024					else if (SettingsManager.CurrentSelectedNavigation == "History")
1025						NavigationPane.History.Focus();
1026					else if (!SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
1027						NavigationPane.Files.Focus();
1028
1029					// create playlists
1030					PlaylistManager.Initialize();
1031
1032					foreach (PlaylistData playlist in SettingsManager.Playlists)
1033						CreatePlaylist(playlist, false);
1034
1035					PlaylistManager.PlaylistModified += new ModifiedEventHandler(PlaylistManager_PlaylistModified);
1036					PlaylistManager.PlaylistRenamed += new RenamedEventHandler(PlaylistManager_PlaylistRenamed);
1037
1038					// if csn == playlist: select
1039					if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
1040					{
1041						string name = SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1];
1042						foreach (TreeViewItem tvi in NavigationPane.Playlists.Items)
1043						{
1044							if ((string)tvi.Tag == name)
1045							{
1046								tvi.Focus();
1047								break;
1048							}
1049						}
1050					}
1051				}));
1052			};
1053
1054			ThreadStart GUIThread = delegate()
1055			{
1056				// init media manager
1057				ThreadStart MediaManagerThread = delegate()
1058				{
1059					Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
1060					{
1061						MediaManager.Initialize(new WindowInteropHelper(this).Handle);
1062						MediaManager.Browser = NowPlayingContainer.Browser;
1063
1064						// load the track collection
1065						if (SettingsManager.CurrentActiveNavigation == "Queue")
1066							MediaManager.TrackCollection = QueueTracks.Items;
1067						else if (SettingsManager.CurrentActiveNavigation == "History")
1068							MediaManager.TrackCollection = HistoryTracks.Items;
1069						else if (SettingsManager.CurrentActiveNavigation == "YouTube")
1070							MediaManager.TrackCollection = YouTubeContainer.YouTubeTracks.Items;
1071						else if (SettingsManager.CurrentActiveNavigation.StartsWith("Playlist:"))
1072						{
1073							string pname = SettingsManager.CurrentActiveNavigation.Split(new[] { ':' }, 2)[1];
1074							ViewDetails p = (ViewDetails)PlaylistTrackLists[pname];
1075							if (p == null)
1076								MediaManager.TrackCollection = FileTracks.Items;
1077							else
1078								MediaManager.TrackCollection = p.Items;
1079						}
1080						else
1081							MediaManager.TrackCollection = FileTracks.Items;
1082
1083						// check if we have any command line arguments
1084						String[] arguments = Environment.GetCommandLineArgs();
1085						if (arguments.Length > 1)
1086						{
1087							if (arguments[1] == "/play") MediaManager.Play();
1088							else if (arguments[1] == "/pause") MediaManager.Pause();
1089							else if (arguments[1] == "/stop") MediaManager.Stop();
1090							else if (arguments[1] == "/next") MediaManager.Next();
1091							else if (arguments[1] == "/previous") MediaManager.Previous();
1092
1093							else if (File.Exists(arguments[1]) && MediaManager.IsSupported(arguments[1]))
1094							{
1095								Open(arguments[1], true);
1096							}
1097						}
1098					}));
1099				};
1100
1101				// init upgrade manager
1102				ThreadStart UpgradeManagerThread = delegate()
1103				{
1104					UpgradeManager.Initialize(new TimeSpan(0, 60, 0));
1105					UpgradeManager.Probe(null, null);
1106				};
1107
1108				// init filesystem manager
1109				ThreadStart FilesystemManagerThread = delegate()
1110				{
1111					FilesystemManager.Initialize();
1112
1113					if (SettingsManager.FirstRun)
1114					{
1115						FilesystemManager.ScanLibraries(true, false);
1116						if (SettingsManager.Sources.Count == 0)
1117						{
1118							Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
1119							{
1120								Welcome dialog = new Welcome();
1121								dialog.ShowDialog();
1122								FilesystemManager.ScanSources();
1123							}));
1124						}
1125
1126						SettingsManager.FirstRun = false;
1127					}
1128					else
1129						FilesystemManager.ScanLibraries(true);
1130				};
1131
1132				// calculate play time
1133				ThreadStart PTThread = delegate()
1134				{
1135					LibraryTime = 0;
1136					QueueTime = 0;
1137					HistoryTime = 0;
1138					if (SettingsManager.FileTracks != null)
1139						foreach (TrackData track in SettingsManager.FileTracks)
1140							LibraryTime += track.RawLength;
1141					if (SettingsManager.QueueTracks != null)
1142						foreach (TrackData track in SettingsManager.QueueTracks)
1143							QueueTime += track.RawLength;
1144					if (SettingsManager.HistoryTracks != null)
1145						foreach (TrackData track in SettingsManager.HistoryTracks)
1146							HistoryTime += track.RawLength;
1147				};
1148
1149				Thread mm_thread = new Thread(MediaManagerThread);
1150				Thread um_thread = new Thread(UpgradeManagerThread);
1151				Thread fm_thread = new Thread(FilesystemManagerThread);
1152				Thread pt_thread = new Thread(PTThread);
1153				mm_thread.Name = "Init Media Manager";
1154				um_thread.Name = "Init Upgrade Manager";
1155				fm_thread.Name = "Init Filesystem Manager";
1156				pt_thread.Name = "Playing Time Thread";
1157				mm_thread.Priority = ThreadPriority.BelowNormal;
1158				um_thread.Priority = ThreadPriority.BelowNormal;
1159				fm_thread.Priority = ThreadPriority.BelowNormal;
1160				pt_thread.Priority = ThreadPriority.BelowNormal;
1161				mm_thread.Start();
1162				um_thread.Start();
1163				fm_thread.Start();
1164				pt_thread.Start();
1165
1166				Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
1167				{
1168					FileTracks.Config = SettingsManager.FileListConfig;
1169					HistoryTracks.Config = SettingsManager.HistoryListConfig;
1170					QueueTracks.Config = SettingsManager.QueueListConfig;
1171					ControlPanel.SourceList.Config = SettingsManager.SourceListConfig;
1172					YouTubeContainer.YouTubeTracks.Config = SettingsManager.YouTubeListConfig;
1173
1174					FileTracks.ItemsSource = SettingsManager.FileTracks;
1175					QueueTracks.ItemsSource = SettingsManager.QueueTracks;
1176					HistoryTracks.ItemsSource = SettingsManager.HistoryTracks;
1177					ControlPanel.SourceList.ItemsSource = SettingsManager.Sources;
1178					YouTubeContainer.Search(SettingsManager.YouTubeListConfig.Filter);
1179				}));
1180
1181				SettingsManager.FileTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(FileTracks.ItemsSource_CollectionChanged);
1182				SettingsManager.QueueTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(QueueTracks.ItemsSource_CollectionChanged);
1183				SettingsManager.HistoryTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(HistoryTracks.ItemsSource_CollectionChanged);
1184				SettingsManager.QueueTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(QueueTracks_CollectionChanged);
1185				SettingsManager.HistoryTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(HistoryTracks_CollectionChanged);
1186				SettingsManager.FileTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(LibraryTracks_CollectionChanged);
1187
1188				jumpTaskPlay = new JumpTask()
1189				{
1190					Title = U.T("JumpPlay", "Title"),
1191					Arguments = "/play",
1192					Description = U.T("JumpPlay", "Description"),
1193					IconResourceIndex = -1,
1194					ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
1195				};
1196
1197				jumpTaskNext = new JumpTask()
1198				{
1199					Title = U.T("JumpNext", "Title"),
1200					Arguments = "/next",
1201					Description = U.T("JumpNext", "Description"),
1202					IconResourceIndex = -1,
1203					ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
1204				};
1205
1206				jumpTaskPrev = new JumpTask()
1207				{
1208					Title = U.T("JumpPrev", "Title"),
1209					Arguments = "/previous",
1210					Description = U.T("JumpPrev", "Description"),
1211					IconResourceIndex = -1,
1212					ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
1213				};
1214
1215				jumpList = new JumpList();
1216				jumpList.JumpItems.Add(jumpTaskPlay);
1217				jumpList.JumpItems.Add(jumpTaskNext);
1218				jumpList.JumpItems.Add(jumpTaskPrev);
1219				jumpList.ShowRecentCategory = true;
1220				jumpList.ShowFrequentCategory = true;
1221
1222				Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
1223				{
1224					PlaybackControls.VolumeSlide.Value = SettingsManager.Volume;
1225
1226					NavigationColumn.Width = new GridLength(SettingsManager.NavigationPaneWidth);
1227					double h = SettingsManager.DetailsPaneHeight;
1228					DetailsRow.Height = new GridLength(h);
1229
1230					UpdateVisibility("menubar");
1231					UpdateVisibility("details");
1232
1233					ControlPanel.InitShortcuts();
1234					JumpList.SetJumpList(Application.Current, jumpList);
1235
1236					UpdateGUIStrings();
1237				}));  
1238
1239			};
1240
1241			Thread pl_thread = new Thread(PlaylistThread);
1242			Thread gui_thread = new Thread(GUIThread);
1243			pl_thread.Name = "Init Playlist Manager";
1244			gui_thread.Name = "Init managers and GUI";
1245			pl_thread.Priority = ThreadPriority.BelowNormal;
1246			gui_thread.Priority = ThreadPriority.BelowNormal;
1247			pl_thread.Start();
1248			gui_thread.Start();
1249		}
1250
1251		#endregion
1252
1253		#region Event handlers
1254
1255		/// <summary>
1256		/// 
1257		/// </summary>
1258		/// <param name="sender"></param>
1259		/// <param name="e"></param>
1260		private void Window_Loaded(object sender, RoutedEventArgs e)
1261		{
1262			U.L(LogLevel.Debug, "MAIN", "Loaded");
1263
1264			System.Windows.Forms.Application.EnableVisualStyles();
1265
1266			WindowState = (WindowState)Enum.Parse(typeof(WindowState), SettingsManager.WinState);
1267
1268			kListener.KeyDown += new RawKeyEventHandler(KListener_KeyDown);
1269			kListener.KeyUp += new RawKeyEventHandler(KListener_KeyUp);
1270
1271			addMenu = new ContextMenu();
1272			showMenu = new ContextMenu();
1273			toolsMenu = new ContextMenu();
1274
1275			addMenuFile = new MenuItem();
1276			addMenuFile.Header = U.T("ToolbarAddTrack");
1277			addMenuFile.Click += AddFile_Clicked;
1278
1279			addMenuFolder = new MenuItem();
1280			addMenuFolder.Header = U.T("ToolbarAddFolder");
1281			addMenuFolder.Click += AddFolder_Clicked;
1282
1283			addMenuPlaylist = new MenuItem();
1284			addMenuPlaylist.Header = U.T("ToolbarAddPlaylist");
1285			addMenuPlaylist.Click += OpenPlaylist_Clicked;
1286
1287			showMenuDetailsPane = new MenuItem();
1288			showMenuDetailsPane.Header = U.T("ToolbarDetailsPane");
1289			showMenuDetailsPane.IsCheckable = true;
1290			showMenuDetailsPane.Click += ToggleDetailsPane;
1291
1292			showMenuMenuBar = new MenuItem();
1293			showMenuMenuBar.Header = U.T("ToolbarMenuBar");
1294			showMenuMenuBar.IsCheckable = true;
1295			showMenuMenuBar.Click += ToggleMenuBar;
1296
1297			toolsMenuImporter = new MenuItem();
1298			toolsMenuImporter.Header = U.T("ToolbarImporter");
1299			toolsMenuImporter.Click += Importer_Clicked;
1300
1301			toolsMenuExporter = new MenuItem();
1302			toolsMenuExporter.Header = U.T("ToolbarExporter");
1303			toolsMenuExporter.Click += Exporter_Clicked;
1304
1305			toolsMenuGenerate = new MenuItem();
1306			toolsMenuGenerate.Header = U.T("ToolbarGeneratePlaylist");
1307			toolsMenuGenerate.Click += GeneratePlaylist_Clicked;
1308
1309			addMenu.Items.Add(addMenuFile);
1310			addMenu.Items.Add(addMenuFolder);
1311			addMenu.Items.Add(addMenuPlaylist);
1312			showMenu.Items.Add(showMenuMenuBar);
1313			showMenu.Items.Add(showMenuDetailsPane);
1314			toolsMenu.Items.Add(toolsMenuImporter);
1315			toolsMenu.Items.Add(toolsMenuExporter);
1316			toolsMenu.Items.Add(toolsMenuGenerate);
1317			addMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
1318			showMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
1319			toolsMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
1320
1321			listMenuAddToPlaylist.Header = U.T("MenuAddToPlaylist", "Header");
1322			listMenuDelete.Header = U.T("MenuDelete");
1323			listMenuDelete.Click += new RoutedEventHandler(listMenuDelete_Click);
1324			listMenuInfo.Header = U.T("MenuInfo");
1325			listMenuInfo.Click += new RoutedEventHandler(listMenuInfo_Click);
1326			listMenuPlay.Header = U.T("MenuPlay");
1327			listMenuPlay.Click += new RoutedEventHandler(listMenuPlay_Click);
1328			listMenuWatchOnYouTube.Header = U.T("MenuWatchOnYouTube");
1329			listMenuWatchOnYouTube.Click += new RoutedEventHandler(listMenuWatchOnYouTube_Click);
1330			listMenuQueue.Header = U.T("MenuQueue");
1331			listMenuQueue.Click += new RoutedEventHandler(listMenuQueue_Click);
1332			listMenuRemove.Header = U.T("MenuRemove");
1333			listMenuRemove.Click += new RoutedEventHandler(listMenuRemove_Click);
1334			listMenuRemoveFromPlaylist.Header = U.T("MenuRemoveFromPlaylist", "Header");
1335			listMenuRemoveFromPlaylist.Visibility = System.Windows.Visibility.Collapsed;
1336
1337			listMenuAddToNew = new MenuItem();
1338			listMenuAddToNew.Header = U.T("MenuCreateNew", "Header");
1339			listMenuAddToNew.FontStyle = FontStyles.Italic;
1340			listMenuAddToNew.Click += new RoutedEventHandler(listMenuAddToPlaylist_Click);
1341			listMenuAddToPlaylist.Items.Add(listMenuAddToNew);
1342
1343			listMenu.Items.Add(listMenuPlay);
1344			listMenu.Items.Add(listMenuQueue);
1345			listMenu.Items.Add(new Separator());
1346			listMenu.Items.Add(listMenuAddToPlaylist);
1347			listMenu.Items.Add(listMenuRemoveFromPlaylist);
1348			listMenu.Items.Add(listMenuRemove);
1349			listMenu.Items.Add(listMenuDelete);
1350			listMenu.Items.Add(new Separator());
1351			listMenu.Items.Add(listMenuWatchOnYouTube);
1352			listMenu.Items.Add(listMenuInfo);
1353
1354			PlaylistTrackLists = new Hashtable();
1355
1356			//// TODO: remove all these lines
1357			////FileTracks.ParentWindow = this;
1358			////QueueTracks.ParentWindow = this;
1359			////HistoryTracks.ParentWindow = this;
1360			ControlPanel.ParentWindow = this;
1361			NavigationPane.ParentWindow = this;
1362			PlaybackControls.ParentWindow = this;
1363
1364			FileTracks.ContextMenu = listMenu;
1365			HistoryTracks.ContextMenu = listMenu;
1366			QueueTracks.ContextMenu = listMenu;
1367			YouTubeContainer.YouTubeTracks.ContextMenu = listMenu;
1368
1369			YouTubeContainer.YouTubeTracks.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
1370			YouTubeContainer.YouTubeTracks.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
1371			YouTubeContainer.YouTubeTracks.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
1372			YouTubeContainer.YouTubeTracks.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
1373
1374			sourceModifiedDelay.Tick += new EventHandler(SourceModifiedDelay_Tick);
1375			sourceModifiedDelay.Interval = new TimeSpan(0, 0, 0, 1, 500);
1376
1377			SettingsManager.PropertyChanged += new PropertyChangedWithValuesEventHandler(SettingsManager_PropertyChanged);
1378
1379			NavigationPane.CreateNewPlaylistETB.EnteredEditMode += new EventHandler(EditableTextBlock_EnteredEditMode);
1380
1381			U.ListenForShortcut = true;
1382
1383			SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
1384
1385			String defaultAlbumArt = "/GUI/Images/AlbumArt/Default.jpg";
1386
1387			//// rough detection of aero vs classic
1388			//// you'll se a lot more of these around the code
1389			if (System.Windows.Forms.VisualStyles.VisualStyl

Large files files are truncated, but you can click here to view the full file