PageRenderTime 69ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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. using GlassLib;
  21. using System;
  22. using System.ComponentModel;
  23. using System.Collections;
  24. using System.Collections.ObjectModel;
  25. using System.Collections.Generic;
  26. using System.Collections.Specialized;
  27. using System.Configuration;
  28. using System.Windows.Data;
  29. using System.Globalization;
  30. using System.IO;
  31. using System.Reflection;
  32. using System.Threading;
  33. using System.Windows;
  34. using System.Windows.Controls;
  35. using System.Windows.Input;
  36. using System.Windows.Media;
  37. using System.Windows.Media.Imaging;
  38. using System.Windows.Threading;
  39. using System.Windows.Interop;
  40. using System.Windows.Shell;
  41. using Hardcodet.Wpf.TaskbarNotification;
  42. using Microsoft.WindowsAPICodePack.Dialogs;
  43. using Microsoft.Win32;
  44. using Tomers.WPF.Localization;
  45. namespace Stoffi
  46. {
  47. /// <summary>
  48. /// Interaction logic for MainWindow.xaml
  49. /// </summary>
  50. public partial class StoffiWindow : Window, INotifyPropertyChanged
  51. {
  52. #region Members
  53. private KeyboardListener kListener = new KeyboardListener();
  54. public ContextMenu trayMenu;
  55. public MenuItem trayMenuShow;
  56. public MenuItem trayMenuPlay;
  57. public MenuItem trayMenuNext;
  58. public MenuItem trayMenuPrev;
  59. public MenuItem trayMenuExit;
  60. private ContextMenu addMenu;
  61. public MenuItem addMenuFile;
  62. public MenuItem addMenuFolder;
  63. public MenuItem addMenuPlaylist;
  64. private ContextMenu showMenu;
  65. public MenuItem showMenuDetailsPane;
  66. public MenuItem showMenuMenuBar;
  67. private ContextMenu toolsMenu;
  68. public MenuItem toolsMenuImporter;
  69. public MenuItem toolsMenuExporter;
  70. public MenuItem toolsMenuGenerate;
  71. public Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton taskbarPrev;
  72. public Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton taskbarPlay;
  73. public Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton taskbarNext;
  74. public TaskbarIcon trayIcon;
  75. private WindowState oldWindowState = WindowState.Minimized;
  76. private WindowState currentWindowState = WindowState.Normal;
  77. public System.Windows.Shell.JumpList jumpList;
  78. public System.Windows.Shell.JumpTask jumpTaskPlay;
  79. public System.Windows.Shell.JumpTask jumpTaskNext;
  80. public System.Windows.Shell.JumpTask jumpTaskPrev;
  81. private bool glassEffect = true;
  82. private List<Key> currentPressedKeys = new List<Key>();
  83. public Microsoft.WindowsAPICodePack.Taskbar.TabbedThumbnail taskbarPreview;
  84. private EditableTextBlock etbInEdit = null;
  85. private Equalizer equalizer = null;
  86. private DispatcherTimer resortDelay = new DispatcherTimer();
  87. private List<string> pathsThatWasChanged = new List<string>();
  88. public MenuItem listMenuPlay = new MenuItem();
  89. public MenuItem listMenuRemove = new MenuItem();
  90. public MenuItem listMenuDelete = new MenuItem();
  91. public MenuItem listMenuInfo = new MenuItem();
  92. public MenuItem listMenuQueue = new MenuItem();
  93. public MenuItem listMenuAddToNew = new MenuItem();
  94. public MenuItem listMenuAddToPlaylist = new MenuItem();
  95. public MenuItem listMenuRemoveFromPlaylist = new MenuItem();
  96. public MenuItem listMenuWatchOnYouTube = new MenuItem();
  97. public MenuItem listMenuShareSong = new MenuItem();
  98. private ContextMenu listMenu = new ContextMenu();
  99. private string dialogPath = @"C:\";
  100. private DispatcherTimer sourceModifiedDelay = new DispatcherTimer();
  101. private Hashtable sourceModifiedTracks = new Hashtable();
  102. private bool doRestart = false;
  103. private TrackData currentlySelectedTrack = null;
  104. private ScannerCallback sourceModifiedCallback;
  105. private bool resumeWhenBack = false; // whether or not to resume playback at login/unlock
  106. private object sourceModifiedCallbackParams;
  107. private bool initialized = false;
  108. private bool showMediaError = false; // whether or not to show errors from media manager as popup
  109. #endregion
  110. #region Properties
  111. /// <summary>
  112. /// The total time of all tracks in the history (in seconds)
  113. /// </summary>
  114. public double HistoryTime { get; private set; }
  115. /// <summary>
  116. /// The total time of all tracks in the queue (in seconds)
  117. /// </summary>
  118. public double QueueTime { get; private set; }
  119. /// <summary>
  120. /// The total time of all tracks in the library (in seconds)
  121. /// </summary>
  122. public double LibraryTime { get; private set; }
  123. /// <summary>
  124. /// A table of the TrackList for each playlist
  125. /// </summary>
  126. public Hashtable PlaylistTrackLists { get; private set; }
  127. /// <summary>
  128. /// The height of the details pane
  129. /// </summary>
  130. public double DetailsPaneHeight
  131. {
  132. get { return SettingsManager.DetailsPaneHeight; }
  133. set { SettingsManager.DetailsPaneHeight = value; }
  134. }
  135. #endregion
  136. #region Constructor
  137. /// <summary>
  138. ///
  139. /// </summary>
  140. public StoffiWindow()
  141. {
  142. U.L(LogLevel.Debug, "MAIN", "Creating main window");
  143. //SettingsManager.FirstRun = true;
  144. //*********** Next ***********/
  145. // TODO: In-place track edit
  146. // TODO: Images (currently playing, queue) in front of t + style
  147. // TODO: Images (currently playing) in front of playlists/library
  148. // TODO: MusicBrainz
  149. // TODO: Jumplist: playlists
  150. // TODO: Drag search text
  151. // TODO: Track score (how good is it?)
  152. // TODO: Last.fm support
  153. // TODO: Spotify
  154. // TODO: Spectrum
  155. // TODO: Views (album, artist, genre, all)
  156. // TODO: Playlist view
  157. // TODO: Network sources
  158. // TODO: Device sources
  159. // TODO: Tools for cutting track
  160. // TODO: Album cover download
  161. // TODO: Lyrics
  162. // TODO: Radio
  163. // TODO: TaskDialogs
  164. // TODO: Wikipedia
  165. // TODO: Social music
  166. U.L(LogLevel.Debug, "MAIN", "Setting culture");
  167. LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo(SettingsManager.Language);
  168. if (!Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.IsPlatformSupported)
  169. {
  170. MessageBox.Show(U.T("MessageOldWindows", "Message"), U.T("MessageOldWindows", "Title"), MessageBoxButton.OK, MessageBoxImage.Error);
  171. Application.Current.Shutdown();
  172. return;
  173. }
  174. U.L(LogLevel.Debug, "MAIN", "Initialize");
  175. InitializeComponent();
  176. U.L(LogLevel.Debug, "MAIN", "Initialized");
  177. // we have to remove controls from their parent so "LastChildFill" doesn't screw everything up
  178. // we add them later on when they are toggled
  179. MainContainer.Children.Remove(ControlPanel);
  180. }
  181. #endregion
  182. #region Methods
  183. #region Public
  184. /// <summary>
  185. /// Restarts the application
  186. /// </summary>
  187. public void Restart()
  188. {
  189. doRestart = true;
  190. this.Close();
  191. }
  192. /// <summary>
  193. ///
  194. /// </summary>
  195. /// <param name="modifiers"></param>
  196. /// <returns></returns>
  197. public String GetModifiersAsText(List<Key> modifiers)
  198. {
  199. String txt = "";
  200. foreach (Key k in modifiers)
  201. {
  202. if (k == Key.LeftCtrl || k == Key.RightCtrl) txt += "Ctrl+";
  203. else if (k == Key.LeftAlt || k == Key.RightAlt) txt += "Alt+";
  204. else if (k == Key.LWin || k == Key.RWin) txt += "Win+";
  205. else if (k == Key.LeftShift || k == Key.RightShift) txt += "Shift+";
  206. }
  207. if (txt.Length > 0) return txt.Substring(0, txt.Length - 1);
  208. else return "";
  209. }
  210. /// <summary>
  211. ///
  212. /// </summary>
  213. /// <param name="k"></param>
  214. /// <returns></returns>
  215. public String KeyToString(Key k)
  216. {
  217. switch (k)
  218. {
  219. case Key.NumPad0:
  220. return "0 (numpad)";
  221. case Key.NumPad1:
  222. return "1 (numpad)";
  223. case Key.NumPad2:
  224. return "2 (numpad)";
  225. case Key.NumPad3:
  226. return "3 (numpad)";
  227. case Key.NumPad4:
  228. return "4 (numpad)";
  229. case Key.NumPad5:
  230. return "5 (numpad)";
  231. case Key.NumPad6:
  232. return "6 (numpad)";
  233. case Key.NumPad7:
  234. return "7 (numpad)";
  235. case Key.NumPad8:
  236. return "8 (numpad)";
  237. case Key.NumPad9:
  238. return "9 (numpad)";
  239. case Key.D0:
  240. return "0";
  241. case Key.D1:
  242. return "1";
  243. case Key.D2:
  244. return "2";
  245. case Key.D3:
  246. return "3";
  247. case Key.D4:
  248. return "4";
  249. case Key.D5:
  250. return "5";
  251. case Key.D6:
  252. return "6";
  253. case Key.D7:
  254. return "7";
  255. case Key.D8:
  256. return "8";
  257. case Key.D9:
  258. return "9";
  259. case Key.OemComma:
  260. return ",";
  261. case Key.OemPeriod:
  262. return ".";
  263. case Key.Subtract:
  264. return "-";
  265. case Key.Multiply:
  266. return "*";
  267. case Key.Divide:
  268. return "/";
  269. case Key.Add:
  270. return "+";
  271. case Key.Back:
  272. return "Backspace";
  273. case Key.OemMinus:
  274. return "-";
  275. case Key.CapsLock:
  276. return "CapsLock";
  277. case Key.Scroll:
  278. return "ScrollLock";
  279. case Key.PrintScreen:
  280. return "PrintScreen";
  281. case Key.Return:
  282. return "Enter";
  283. case Key.PageDown:
  284. return "PageDown";
  285. case Key.PageUp:
  286. return "PageUp";
  287. // TODO: hardcoded temporary fix
  288. case Key.Oem3:
  289. return "ยด";
  290. case Key.OemPlus:
  291. return "=";
  292. case Key.OemOpenBrackets:
  293. return "[";
  294. case Key.Oem6:
  295. return "]";
  296. case Key.Oem5:
  297. return @"\";
  298. case Key.Oem1:
  299. return ";";
  300. case Key.OemQuotes:
  301. return "'";
  302. case Key.OemQuestion:
  303. return "/";
  304. default:
  305. return k.ToString();
  306. }
  307. }
  308. /// <summary>
  309. ///
  310. /// </summary>
  311. /// <param name="argument"></param>
  312. public void CallFromSecondInstance(String argument)
  313. {
  314. if (argument == "/play")
  315. {
  316. PlayPause();
  317. }
  318. else if (argument == "/next")
  319. {
  320. MediaManager.Next();
  321. if (SettingsManager.MediaState != MediaState.Playing)
  322. MediaManager.Tick(null, null);
  323. }
  324. else if (argument == "/previous")
  325. {
  326. MediaManager.Previous();
  327. if (SettingsManager.MediaState != MediaState.Playing)
  328. MediaManager.Tick(null, null);
  329. }
  330. else
  331. {
  332. if (File.Exists(argument))
  333. {
  334. // file is a playlist
  335. if (PlaylistManager.IsSupported(argument))
  336. {
  337. PlaylistData pl = PlaylistManager.LoadPlaylist(argument);
  338. if (pl != null)
  339. {
  340. NavigationPane.SwitchNavigation("Playlist:" + pl.Name);
  341. if (pl.Tracks.Count > 0)
  342. {
  343. MediaManager.Load(pl.Tracks[0]);
  344. MediaManager.Play();
  345. }
  346. }
  347. }
  348. // file is a track
  349. else if (MediaManager.IsSupported(argument))
  350. {
  351. Open(argument);
  352. }
  353. }
  354. // TODO: bring to front
  355. }
  356. }
  357. /// <summary>
  358. /// Retrives the currently selected track list's source.
  359. /// </summary>
  360. /// <returns>The collection used as ItemsSource for the current track list</returns>
  361. public ObservableCollection<TrackData> GetCurrentTrackCollection()
  362. {
  363. if (SettingsManager.CurrentSelectedNavigation == "History")
  364. return SettingsManager.HistoryTracks;
  365. else if (SettingsManager.CurrentSelectedNavigation == "Queue")
  366. return SettingsManager.QueueTracks;
  367. else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  368. {
  369. PlaylistData p = PlaylistManager.FindPlaylist(SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1]);
  370. if (p == null) return null;
  371. return p.Tracks;
  372. }
  373. else if (SettingsManager.CurrentSelectedNavigation == "Files")
  374. return SettingsManager.FileTracks;
  375. else if (SettingsManager.CurrentSelectedNavigation == "YouTube")
  376. return YouTubeManager.TrackSource;
  377. else
  378. return null;
  379. }
  380. /// <summary>
  381. ///
  382. /// </summary>
  383. /// <returns></returns>
  384. public ViewDetails GetCurrentTrackList()
  385. {
  386. if (SettingsManager.CurrentSelectedNavigation == "History")
  387. return HistoryTracks;
  388. else if (SettingsManager.CurrentSelectedNavigation == "Queue")
  389. return QueueTracks;
  390. else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  391. return (ViewDetails)PlaylistTrackLists[SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1]];
  392. else if (SettingsManager.CurrentSelectedNavigation == "Files")
  393. return FileTracks;
  394. else if (SettingsManager.CurrentSelectedNavigation == "YouTube")
  395. return YouTubeContainer.YouTubeTracks;
  396. else
  397. return null;
  398. }
  399. /// <summary>
  400. ///
  401. /// </summary>
  402. /// <returns></returns>
  403. public ViewDetails GetActiveTrackList()
  404. {
  405. string can = SettingsManager.CurrentActiveNavigation;
  406. if (can == "History" || can == "Queue")
  407. can = SettingsManager.CurrentTrack == null ? "Files" : SettingsManager.CurrentTrack.Source;
  408. if (can.StartsWith("Playlist:"))
  409. {
  410. PlaylistData p = PlaylistManager.FindPlaylist(can.Split(new[] { ':' }, 2)[1]);
  411. if (p != null)
  412. return (ViewDetails)PlaylistTrackLists[p.Name];
  413. }
  414. if (can == "YouTube")
  415. return YouTubeContainer.YouTubeTracks;
  416. else
  417. return FileTracks;
  418. }
  419. /// <summary>
  420. ///
  421. /// </summary>
  422. /// <param name="name"></param>
  423. public void OnPropertyChanged(string name)
  424. {
  425. if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
  426. }
  427. #endregion
  428. #region Private
  429. /// <summary>
  430. /// Play the currently selected track
  431. /// </summary>
  432. /// <param name="resume">Resume at the current position if the selected track is the CurrentTrack</param>
  433. private void Play(bool resume = false)
  434. {
  435. showMediaError = true;
  436. if (resume && SettingsManager.CurrentTrack != null)
  437. MediaManager.Play();
  438. else if (GetCurrentTrackList().SelectedItem is TrackData)
  439. {
  440. string pl = "";
  441. if (SettingsManager.CurrentSelectedNavigation == "Library")
  442. pl = "";
  443. else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  444. pl = SettingsManager.CurrentSelectedNavigation.Split(new[]{':'},2)[1];
  445. TrackData track = GetCurrentTrackList().SelectedItem as TrackData;
  446. MediaManager.TrackCollection = GetCurrentTrackList().Items;
  447. if (SettingsManager.CurrentSelectedNavigation == "History")
  448. SettingsManager.HistoryIndex = SettingsManager.HistoryTracks.IndexOf(track);
  449. else
  450. SettingsManager.HistoryIndex = SettingsManager.HistoryTracks.Count;
  451. SettingsManager.CurrentActiveNavigation = SettingsManager.CurrentSelectedNavigation;
  452. if (SettingsManager.CurrentActiveNavigation.StartsWith("Playlist:"))
  453. PlaylistManager.CurrentPlaylist = SettingsManager.CurrentActiveNavigation.Split(new[] { ':' }, 2)[1];
  454. else
  455. PlaylistManager.CurrentPlaylist = "";
  456. MediaManager.Stop();
  457. MediaManager.Load(track);
  458. MediaManager.Play();
  459. }
  460. }
  461. /// <summary>
  462. /// Toggle the play and pause state
  463. /// </summary>
  464. private void PlayPause()
  465. {
  466. if (SettingsManager.MediaState == MediaState.Playing)
  467. SettingsManager.MediaState = MediaState.Paused;
  468. else
  469. SettingsManager.MediaState = MediaState.Playing;
  470. }
  471. /// <summary>
  472. /// Removes a set of tracks from a given collection of tracks.
  473. /// </summary>
  474. /// <param name="tracksToRemove">The tracks to remove</param>
  475. /// <param name="tracks">The collection from where to remove the tracks</param>
  476. private void RemoveTracks(SortedList<string, TrackData> tracksToRemove, ObservableCollection<TrackData> tracks)
  477. {
  478. for (int i = 0; i < tracks.Count; i++)
  479. {
  480. if (tracksToRemove.ContainsKey(tracks[i].Path))
  481. {
  482. tracks.RemoveAt(i--);
  483. }
  484. }
  485. }
  486. /// <summary>
  487. /// Removes a set of tracks from a given collection of tracks.
  488. /// </summary>
  489. /// <param name="tracksToRemove">The tracks to remove</param>
  490. /// <param name="tracks">The collection from where to remove the tracks</param>
  491. private void RemoveTracks(SortedList<string, TrackData> tracksToRemove, List<TrackData> tracks)
  492. {
  493. for (int i = 0; i < tracks.Count; i++)
  494. {
  495. if (tracksToRemove.ContainsKey(tracks[i].Path))
  496. {
  497. tracks.RemoveAt(i--);
  498. }
  499. }
  500. }
  501. /// <summary>
  502. /// Removes tracks with a given filename for a specific collection of tracks
  503. /// </summary>
  504. /// <param name="filename">The filename of the tracks to remove</param>
  505. /// <param name="tracks">The collection of tracks from which to remove</param>
  506. private void RemoveTrack(String filename, ObservableCollection<TrackData> tracks)
  507. {
  508. for (int i = 0; i < tracks.Count; i++)
  509. {
  510. if (tracks[i].Path == filename)
  511. {
  512. tracks.RemoveAt(i);
  513. break;
  514. }
  515. }
  516. }
  517. /// <summary>
  518. /// Removes tracks with a given filename for a specific list of tracks
  519. /// </summary>
  520. /// <param name="filename">The filename of the tracks to remove</param>
  521. /// <param name="tracks">The list of tracks from which to remove</param>
  522. private void RemoveTrack(String filename, List<TrackData> tracks)
  523. {
  524. for (int i = 0; i < tracks.Count; i++)
  525. {
  526. if (tracks[i].Path == filename)
  527. {
  528. tracks.RemoveAt(i);
  529. break;
  530. }
  531. }
  532. }
  533. /// <summary>
  534. /// Reapply the sorting on a tracklist
  535. /// </summary>
  536. /// <param name="tl">The tracklist to re-sort</param>
  537. /// <param name="paths">A list of the paths that was changed</param>
  538. private void ResortTracklist(ViewDetails tl, List<string> paths)
  539. {
  540. bool resort = false;
  541. foreach (TrackData t in SettingsManager.FileTracks)
  542. {
  543. if (paths.Contains(t.Path))
  544. {
  545. resort = true;
  546. break;
  547. }
  548. }
  549. if (resort)
  550. {
  551. if (tl.Items.SortDescriptions.Count > 0)
  552. {
  553. SortDescription sd = tl.Items.SortDescriptions[0];
  554. tl.Items.SortDescriptions.Remove(sd);
  555. tl.Items.SortDescriptions.Insert(0, sd);
  556. }
  557. }
  558. }
  559. /// <summary>
  560. /// Load a file and add it according to the AddPolicy and play
  561. /// it according to the PlayPolicy
  562. /// </summary>
  563. /// <param name="filename">The filename of the track</param>
  564. /// <param name="forcePlay">Whether or not to override the PlayPolicy</param>
  565. private void Open(string filename, bool forcePlay = false)
  566. {
  567. U.L(LogLevel.Debug, "MAIN", "Opening " + filename);
  568. OpenAddPolicy DoAdd = SettingsManager.OpenAddPolicy;
  569. OpenPlayPolicy DoPlay = SettingsManager.OpenPlayPolicy;
  570. TrackData track = null;
  571. // add track
  572. if (DoAdd == OpenAddPolicy.Library || DoAdd == OpenAddPolicy.LibraryAndPlaylist)
  573. {
  574. // add track to library if needed
  575. track = FilesystemManager.GetTrack(filename);
  576. if (track == null)
  577. {
  578. U.L(LogLevel.Debug, "MAIN", "Adding to collection");
  579. FilesystemManager.AddSource(new SourceData()
  580. {
  581. Data = filename,
  582. Include = true,
  583. HumanType = U.T("SourcesTypeFile"),
  584. Type = SourceType.File
  585. });
  586. track = FilesystemManager.GetTrack(filename);
  587. }
  588. if (track == null)
  589. U.L(LogLevel.Warning, "MAIN", "Could not add track to Library: " + filename);
  590. // add track to current playlist as well
  591. if (DoAdd == OpenAddPolicy.LibraryAndPlaylist && track != null)
  592. {
  593. if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  594. {
  595. U.L(LogLevel.Debug, "MAIN", "Adding to current playlist");
  596. String playlistName = SettingsManager.CurrentSelectedNavigation.Split(new[]{':'},2)[1];
  597. List<object> tracks = new List<object>();
  598. tracks.Add(track);
  599. PlaylistManager.AddToPlaylist(tracks, playlistName);
  600. }
  601. }
  602. }
  603. // play track
  604. if (DoPlay != OpenPlayPolicy.DoNotPlay || forcePlay)
  605. {
  606. // create track if it is null
  607. if (track == null)
  608. {
  609. U.L(LogLevel.Debug, "MAIN", "Creating track");
  610. track = FilesystemManager.CreateTrack(filename);
  611. if (track == null)
  612. {
  613. U.L(LogLevel.Warning, "MAIN", "Could not create track for: " + filename);
  614. return;
  615. }
  616. FilesystemManager.UpdateTrack(track);
  617. }
  618. if (DoPlay == OpenPlayPolicy.Play || forcePlay)
  619. {
  620. U.L(LogLevel.Debug, "MAIN", "Playing track");
  621. MediaManager.Stop();
  622. MediaManager.Load(track);
  623. MediaManager.Play();
  624. if (DoAdd == OpenAddPolicy.LibraryAndPlaylist && SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  625. SettingsManager.CurrentActiveNavigation = SettingsManager.CurrentSelectedNavigation;
  626. else if (DoAdd == OpenAddPolicy.Library)
  627. SettingsManager.CurrentActiveNavigation = "Library";
  628. }
  629. else if (DoPlay == OpenPlayPolicy.BackOfQueue)
  630. MediaManager.Queue(new List<TrackData>() { track });
  631. else if (DoPlay == OpenPlayPolicy.FrontOfQueue)
  632. MediaManager.Queue(new List<TrackData>() { track }, 0);
  633. }
  634. }
  635. /// <summary>
  636. /// Creates a playlist track list and navigation items
  637. /// </summary>
  638. /// <param name="playlist">The data for the playlist to create</param>
  639. /// <param name="select">Whether to select the playlist after it has been created</param>
  640. private void CreatePlaylist(PlaylistData playlist, bool select = true)
  641. {
  642. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  643. {
  644. // create track list
  645. ViewDetails vd = new ViewDetails();
  646. Grid.SetRow(vd, 1);
  647. TrackContainer.Children.Add(vd);
  648. vd.ItemsSource = playlist.Tracks;
  649. playlist.Tracks.CollectionChanged +=
  650. new System.Collections.Specialized.NotifyCollectionChangedEventHandler(vd.ItemsSource_CollectionChanged);
  651. if (playlist.ListConfig == null)
  652. {
  653. ViewDetailsConfig vdc = SettingsManager.CreateListConfig();
  654. SettingsManager.InitViewDetailsConfig(vdc);
  655. vdc.HasNumber = true;
  656. playlist.ListConfig = vdc;
  657. }
  658. if (PlaylistTrackLists.ContainsKey(playlist.Name))
  659. PlaylistTrackLists.Remove(playlist.Name);
  660. PlaylistTrackLists.Add(playlist.Name, vd);
  661. vd.ContextMenu = listMenu;
  662. vd.Visibility = Visibility.Collapsed;
  663. vd.BorderThickness = new Thickness(0);
  664. vd.ItemsSource = playlist.Tracks;
  665. vd.Config = playlist.ListConfig;
  666. vd.FilterMatch = TrackList_SearchMatch;
  667. vd.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
  668. vd.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
  669. vd.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
  670. vd.FilesDropped += new FileDropEventHandler(TrackList_FilesDropped);
  671. vd.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
  672. // create the item in the navigation tree
  673. TreeViewItem item = new TreeViewItem();
  674. item.Selected += NavigationPane.Playlist_Selected;
  675. item.Drop += NavigationPane.Playlist_Drop;
  676. item.KeyDown += NavigationPlaylist_KeyDown;
  677. item.Tag = playlist.Name;
  678. item.Padding = new Thickness(8, 0, 0, 0);
  679. StackPanel sp = new StackPanel();
  680. sp.Orientation = System.Windows.Controls.Orientation.Horizontal;
  681. Image img = new Image();
  682. img.Source = Utilities.GetIcoImage("pack://application:,,,/GUI/Images/Icons/DiscAudio.ico", 16, 16);
  683. img.Width = 16;
  684. img.Height = 16;
  685. sp.Children.Add(img);
  686. EditableTextBlock etb = new EditableTextBlock();
  687. etb.EnteredEditMode += new EventHandler(EditableTextBlock_EnteredEditMode);
  688. etb.Text = playlist.Name;
  689. etb.Margin = new Thickness(5, 0, 5, 0);
  690. etb.Edited += NavigationPane.Playlist_Edited;
  691. sp.Children.Add(etb);
  692. item.Header = sp;
  693. item.ContextMenuOpening += new ContextMenuEventHandler(NavigationPane.Playlist_ContextMenuOpening);
  694. item.ContextMenu = NavigationPane.playlistMenu;
  695. NavigationPane.Playlists.Items.Insert(NavigationPane.Playlists.Items.Count - 1, item);
  696. if (select)
  697. item.Focus();
  698. // create list context menu items
  699. MenuItem miAdd = new MenuItem();
  700. miAdd.Header = playlist.Name;
  701. miAdd.Click += new RoutedEventHandler(listMenuAddToPlaylist_Click);
  702. listMenuAddToPlaylist.Visibility = System.Windows.Visibility.Visible;
  703. listMenuAddToPlaylist.Items.Insert(listMenuAddToPlaylist.Items.Count - 1, miAdd);
  704. MenuItem miDel = new MenuItem();
  705. miDel.Header = playlist.Name;
  706. miDel.Click += new RoutedEventHandler(listMenuRemoveFromPlaylist_Click);
  707. listMenuRemoveFromPlaylist.Visibility = System.Windows.Visibility.Visible;
  708. listMenuRemoveFromPlaylist.Items.Add(miDel);
  709. PlaybackControls.Search.AddPlaylist(playlist);
  710. }));
  711. }
  712. /// <summary>
  713. /// Updates the visibility of a given element according to the settings
  714. /// </summary>
  715. /// <param name="element">The element to update (menubar or details)</param>
  716. private void UpdateVisibility(string element)
  717. {
  718. switch (element)
  719. {
  720. case "menubar":
  721. bool mv = SettingsManager.MenuBarVisibile;
  722. showMenuMenuBar.IsChecked = mv;
  723. MenuItemViewMenuBar.IsChecked = mv;
  724. MenuBar.Visibility = mv ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  725. break;
  726. case "details":
  727. bool dv = SettingsManager.DetailsPaneVisible;
  728. showMenuDetailsPane.IsChecked = dv;
  729. MenuItemViewDetailsPane.IsChecked = dv;
  730. DetailsRow.MinHeight = (dv ? 80 : 0);
  731. DetailsRow.Height = new GridLength((dv ? SettingsManager.DetailsPaneHeight : 0));
  732. DetailsPane.Visibility = dv ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  733. HorizontalSplitter.Visibility = dv ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  734. break;
  735. }
  736. }
  737. /// <summary>
  738. /// Updates the strings around the GUI, that are hardcoded, according to the current Language
  739. /// </summary>
  740. private void UpdateGUIStrings()
  741. {
  742. // change column headers of list views
  743. foreach (ViewDetailsColumn c in SettingsManager.SourceListConfig.Columns)
  744. {
  745. if (c.Binding == "HumanType") c.Text = U.T("ColumnType");
  746. else if (c.Binding == "Data") c.Text = U.T("ColumnLocation");
  747. }
  748. foreach (ViewDetailsColumn c in SettingsManager.YouTubeListConfig.Columns)
  749. {
  750. if (c.Binding == "Artist") c.Text = U.T("ColumnArtist");
  751. else if (c.Binding == "Title") c.Text = U.T("ColumnTitle");
  752. else if (c.Binding == "Path") c.Text = U.T("ColumnPath");
  753. else if (c.Binding == "Length") c.Text = U.T("ColumnLength");
  754. }
  755. foreach (ViewDetailsColumn c in SettingsManager.FileListConfig.Columns)
  756. {
  757. if (c.Binding == "Artist") c.Text = U.T("ColumnArtist");
  758. else if (c.Binding == "Title") c.Text = U.T("ColumnTitle");
  759. else if (c.Binding == "Album") c.Text = U.T("ColumnAlbum");
  760. else if (c.Binding == "Genre") c.Text = U.T("ColumnGenre");
  761. else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnLastPlayed");
  762. else if (c.Binding == "Length") c.Text = U.T("ColumnLength");
  763. else if (c.Binding == "PlayCount") c.Text = U.T("ColumnPlayCount");
  764. else if (c.Binding == "Path") c.Text = U.T("ColumnPath");
  765. else if (c.Binding == "Track") c.Text = U.T("ColumnTrack");
  766. else if (c.Binding == "Year") c.Text = U.T("ColumnYear");
  767. }
  768. foreach (ViewDetailsColumn c in SettingsManager.QueueListConfig.Columns)
  769. {
  770. if (c.Binding == "Artist") c.Text = U.T("ColumnArtist");
  771. else if (c.Binding == "Title") c.Text = U.T("ColumnTitle");
  772. else if (c.Binding == "Album") c.Text = U.T("ColumnAlbum");
  773. else if (c.Binding == "Genre") c.Text = U.T("ColumnGenre");
  774. else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnLastPlayed");
  775. else if (c.Binding == "Length") c.Text = U.T("ColumnLength");
  776. else if (c.Binding == "PlayCount") c.Text = U.T("ColumnPlayCount");
  777. else if (c.Binding == "Path") c.Text = U.T("ColumnPath");
  778. else if (c.Binding == "Track") c.Text = U.T("ColumnTrack");
  779. else if (c.Binding == "Year") c.Text = U.T("ColumnYear");
  780. }
  781. foreach (ViewDetailsColumn c in SettingsManager.HistoryListConfig.Columns)
  782. {
  783. if (c.Binding == "Artist") c.Text = U.T("ColumnArtist");
  784. else if (c.Binding == "Title") c.Text = U.T("ColumnTitle");
  785. else if (c.Binding == "Album") c.Text = U.T("ColumnAlbum");
  786. else if (c.Binding == "Genre") c.Text = U.T("ColumnGenre");
  787. else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnPlayed");
  788. else if (c.Binding == "Length") c.Text = U.T("ColumnLength");
  789. else if (c.Binding == "PlayCount") c.Text = U.T("ColumnPlayCount");
  790. else if (c.Binding == "Path") c.Text = U.T("ColumnPath");
  791. else if (c.Binding == "Track") c.Text = U.T("ColumnTrack");
  792. else if (c.Binding == "Year") c.Text = U.T("ColumnYear");
  793. }
  794. foreach (PlaylistData p in SettingsManager.Playlists)
  795. foreach (ViewDetailsColumn c in p.ListConfig.Columns)
  796. {
  797. if (c.Binding == "Artist") c.Text = U.T("ColumnArtist");
  798. else if (c.Binding == "Title") c.Text = U.T("ColumnTitle");
  799. else if (c.Binding == "Album") c.Text = U.T("ColumnAlbum");
  800. else if (c.Binding == "Genre") c.Text = U.T("ColumnGenre");
  801. else if (c.Binding == "LastPlayed") c.Text = U.T("ColumnPlayed");
  802. else if (c.Binding == "Length") c.Text = U.T("ColumnLength");
  803. else if (c.Binding == "PlayCount") c.Text = U.T("ColumnPlayCount");
  804. else if (c.Binding == "Path") c.Text = U.T("ColumnPath");
  805. else if (c.Binding == "Track") c.Text = U.T("ColumnTrack");
  806. else if (c.Binding == "Year") c.Text = U.T("ColumnYear");
  807. }
  808. // change source types
  809. foreach (SourceData s in SettingsManager.Sources)
  810. switch (s.Type)
  811. {
  812. case SourceType.File:
  813. s.HumanType = U.T("SourcesTypeFile");
  814. break;
  815. case SourceType.Folder:
  816. s.HumanType = U.T("SourcesTypeFolder");
  817. break;
  818. case SourceType.Library:
  819. s.HumanType = U.T("SourcesTypeLibrary");
  820. break;
  821. }
  822. // change shortcuts
  823. ControlPanel.GlobalLabel.Content = U.T("ShortcutGlobal");
  824. foreach (TextBlock t in ControlPanel.ShortcutTitles)
  825. t.Text = U.T((string)t.Tag);
  826. foreach (TextBlock t in ControlPanel.ShortcutDescriptions)
  827. t.Text = U.T((string)t.Tag);
  828. foreach (Label l in ControlPanel.ShortcutLabels)
  829. l.Content = U.T((string)l.Tag);
  830. // change menus
  831. trayMenuShow.Header = U.T("TrayShow");
  832. trayMenuPlay.Header = U.T("TrayPlay");
  833. trayMenuNext.Header = U.T("TrayNext");
  834. trayMenuPrev.Header = U.T("TrayPrev");
  835. trayMenuExit.Header = U.T("TrayExit");
  836. taskbarPlay.Tooltip = U.T("TaskbarPlay");
  837. taskbarNext.Tooltip = U.T("TaskbarNext");
  838. taskbarPrev.Tooltip = U.T("TaskbarPrev");
  839. jumpTaskPlay.Title = U.T("JumpPlay", "Title");
  840. jumpTaskNext.Title = U.T("JumpNext", "Title");
  841. jumpTaskPrev.Title = U.T("JumpPrev", "Title");
  842. jumpTaskPlay.Description = U.T("JumpPlay", "Description");
  843. jumpTaskNext.Description = U.T("JumpNext", "Description");
  844. jumpTaskPrev.Description = U.T("JumpPrev", "Description");
  845. listMenuAddToPlaylist.Header = U.T("MenuAddToPlaylist", "Header");
  846. listMenuAddToNew.Header = U.T("MenuCreateNew", "Header");
  847. listMenuDelete.Header = U.T("MenuDelete");
  848. listMenuInfo.Header = U.T("MenuInfo");
  849. listMenuPlay.Header = U.T("MenuPlay");
  850. listMenuQueue.Header = U.T("MenuQueue");
  851. listMenuRemove.Header = U.T("MenuRemove");
  852. listMenuRemoveFromPlaylist.Header = U.T("MenuRemoveFromPlaylist", "Header");
  853. listMenuWatchOnYouTube.Header = U.T("MenuWatchOnYouTube");
  854. listMenuShareSong.Header = U.T("MenuShareSong");
  855. addMenuFile.Header = U.T("ToolbarAddTrack");
  856. addMenuFolder.Header = U.T("ToolbarAddFolder");
  857. addMenuPlaylist.Header = U.T("ToolbarAddPlaylist");
  858. showMenuDetailsPane.Header = U.T("ToolbarDetailsPane");
  859. showMenuMenuBar.Header = U.T("ToolbarMenuBar");
  860. toolsMenuExporter.Header = U.T("ToolbarExporter");
  861. toolsMenuImporter.Header = U.T("ToolbarImporter");
  862. toolsMenuGenerate.Header = U.T("ToolbarGeneratePlaylist");
  863. NavigationPane.playlistMenuRemove.Header = U.T("MenuRemovePlaylist");
  864. NavigationPane.playlistMenuRename.Header = U.T("MenuRenamePlaylist");
  865. NavigationPane.playlistMenuSave.Header = U.T("MenuSavePlaylist");
  866. NavigationPane.playlistMenuShare.Header = U.T("MenuSharePlaylist");
  867. NavigationPane.CreateNewPlaylistETB.Text = U.T("NavigationCreateNew");
  868. ControlPanel.menuRemove.Header = U.T("MenuRemove");
  869. // change tracklist header
  870. string csn = SettingsManager.CurrentSelectedNavigation;
  871. switch (csn)
  872. {
  873. case "Files":
  874. InfoPaneTitle.Text = U.T("NavigationFilesTitle");
  875. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)LibraryTime)); ;
  876. InfoPaneTracks.Text = SettingsManager.FileTracks.Count.ToString() + " " + U.T("HeaderTracks");
  877. break;
  878. case "Queue":
  879. InfoPaneTitle.Text = U.T("NavigationQueueTitle");
  880. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)QueueTime)); ;
  881. InfoPaneTracks.Text = SettingsManager.QueueTracks.Count.ToString() + " " + U.T("HeaderTracks");
  882. break;
  883. case "History":
  884. InfoPaneTitle.Text = U.T("NavigationHistoryTitle");
  885. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)HistoryTime)); ;
  886. InfoPaneTracks.Text = SettingsManager.HistoryTracks.Count.ToString() + " " + U.T("HeaderTracks");
  887. break;
  888. default:
  889. if (csn.StartsWith("Playlist:"))
  890. {
  891. PlaylistData p = PlaylistManager.FindPlaylist(csn.Split(new[] { ':' }, 2)[1]);
  892. InfoPaneTitle.Text = U.T("NavigationPlaylistTitle") + " '" + p.Name + "'";
  893. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)p.Time)); ;
  894. InfoPaneTracks.Text = p.Tracks.Count.ToString() + " " + U.T("HeaderTracks");
  895. }
  896. break;
  897. }
  898. }
  899. /// <summary>
  900. /// Will repaint the glass effect behind the playback pane.
  901. /// </summary>
  902. private void RefreshGlassEffect()
  903. {
  904. try
  905. {
  906. Dwm.Glass[this].Enabled = true;
  907. Thickness foo = new Thickness(1, 75, 1, 1);
  908. Dwm.Glass[this].Margins = foo;
  909. Background = Brushes.Transparent;
  910. glassEffect = true;
  911. }
  912. catch (Exception e)
  913. {
  914. U.L(LogLevel.Warning, "MAIN", "Could not set glass effect: " + e.Message);
  915. if (System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName == "")
  916. Background = SystemColors.ControlBrush;
  917. else
  918. Background = SystemColors.GradientActiveCaptionBrush;
  919. glassEffect = false;
  920. }
  921. }
  922. /// <summary>
  923. /// Initializes the GUI
  924. /// </summary>
  925. private void InitGUI()
  926. {
  927. U.L(LogLevel.Debug, "MAIN", "Init settings manager");
  928. SettingsManager.Initialize();
  929. U.L(LogLevel.Debug, "MAIN", "Init service manager");
  930. ServiceManager.Initialize();
  931. // create playlists
  932. ThreadStart PlaylistThread = delegate()
  933. {
  934. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  935. {
  936. if (SettingsManager.CurrentSelectedNavigation == "YouTube")
  937. NavigationPane.Youtube.Focus();
  938. else if (SettingsManager.CurrentSelectedNavigation == "Queue")
  939. NavigationPane.Queue.Focus();
  940. else if (SettingsManager.CurrentSelectedNavigation == "History")
  941. NavigationPane.History.Focus();
  942. else if (!SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  943. NavigationPane.Files.Focus();
  944. // create playlists
  945. PlaylistManager.Initialize();
  946. foreach (PlaylistData playlist in SettingsManager.Playlists)
  947. CreatePlaylist(playlist, false);
  948. PlaylistManager.PlaylistModified += new ModifiedEventHandler(PlaylistManager_PlaylistModified);
  949. PlaylistManager.PlaylistRenamed += new RenamedEventHandler(PlaylistManager_PlaylistRenamed);
  950. // if csn == playlist: select
  951. if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  952. {
  953. string name = SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1];
  954. foreach (TreeViewItem tvi in NavigationPane.Playlists.Items)
  955. {
  956. if ((string)tvi.Tag == name)
  957. {
  958. tvi.Focus();
  959. break;
  960. }
  961. }
  962. }
  963. }));
  964. };
  965. ThreadStart GUIThread = delegate()
  966. {
  967. // init media manager
  968. ThreadStart MediaManagerThread = delegate()
  969. {
  970. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  971. {
  972. MediaManager.Initialize(new WindowInteropHelper(this).Handle);
  973. MediaManager.Browser = NowPlayingContainer.Browser;
  974. // load the track collection
  975. if (SettingsManager.CurrentActiveNavigation == "Queue")
  976. MediaManager.TrackCollection = QueueTracks.Items;
  977. else if (SettingsManager.CurrentActiveNavigation == "History")
  978. MediaManager.TrackCollection = HistoryTracks.Items;
  979. else if (SettingsManager.CurrentActiveNavigation == "YouTube")
  980. MediaManager.TrackCollection = YouTubeContainer.YouTubeTracks.Items;
  981. else if (SettingsManager.CurrentActiveNavigation.StartsWith("Playlist:"))
  982. {
  983. string pname = SettingsManager.CurrentActiveNavigation.Split(new[] { ':' }, 2)[1];
  984. ViewDetails p = (ViewDetails)PlaylistTrackLists[pname];
  985. if (p == null)
  986. MediaManager.TrackCollection = FileTracks.Items;
  987. else
  988. MediaManager.TrackCollection = p.Items;
  989. }
  990. else
  991. MediaManager.TrackCollection = FileTracks.Items;
  992. // check if we have any command line arguments
  993. String[] arguments = Environment.GetCommandLineArgs();
  994. if (arguments.Length > 1)
  995. {
  996. if (arguments[1] == "/play") MediaManager.Play();
  997. else if (arguments[1] == "/pause") MediaManager.Pause();
  998. else if (arguments[1] == "/stop") MediaManager.Stop();
  999. else if (arguments[1] == "/next") MediaManager.Next();
  1000. else if (arguments[1] == "/previous") MediaManager.Previous();
  1001. else if (File.Exists(arguments[1]) && MediaManager.IsSupported(arguments[1]))
  1002. {
  1003. Open(arguments[1], true);
  1004. }
  1005. }
  1006. }));
  1007. };
  1008. // init upgrade manager
  1009. ThreadStart UpgradeManagerThread = delegate()
  1010. {
  1011. UpgradeManager.Initialize(new TimeSpan(0, 60, 0));
  1012. UpgradeManager.Probe(null, null);
  1013. };
  1014. // init filesystem manager
  1015. ThreadStart FilesystemManagerThread = delegate()
  1016. {
  1017. FilesystemManager.Initialize();
  1018. if (SettingsManager.FirstRun)
  1019. {
  1020. FilesystemManager.ScanLibraries(true, false);
  1021. if (SettingsManager.Sources.Count == 0)
  1022. {
  1023. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  1024. {
  1025. Welcome dialog = new Welcome();
  1026. dialog.ShowDialog();
  1027. FilesystemManager.ScanSources();
  1028. }));
  1029. }
  1030. SettingsManager.FirstRun = false;
  1031. }
  1032. else
  1033. FilesystemManager.ScanLibraries(true);
  1034. };
  1035. // calculate play time
  1036. ThreadStart PTThread = delegate()
  1037. {
  1038. LibraryTime = 0;
  1039. QueueTime = 0;
  1040. HistoryTime = 0;
  1041. if (SettingsManager.FileTracks != null)
  1042. foreach (TrackData track in SettingsManager.FileTracks)
  1043. LibraryTime += track.RawLength;
  1044. if (SettingsManager.QueueTracks != null)
  1045. foreach (TrackData track in SettingsManager.QueueTracks)
  1046. QueueTime += track.RawLength;
  1047. if (SettingsManager.HistoryTracks != null)
  1048. foreach (TrackData track in SettingsManager.HistoryTracks)
  1049. HistoryTime += track.RawLength;
  1050. };
  1051. Thread mm_thread = new Thread(MediaManagerThread);
  1052. Thread um_thread = new Thread(UpgradeManagerThread);
  1053. Thread fm_thread = new Thread(FilesystemManagerThread);
  1054. Thread pt_thread = new Thread(PTThread);
  1055. mm_thread.Name = "Init Media Manager";
  1056. um_thread.Name = "Init Upgrade Manager";
  1057. fm_thread.Name = "Init Filesystem Manager";
  1058. pt_thread.Name = "Playing Time Thread";
  1059. mm_thread.Priority = ThreadPriority.BelowNormal;
  1060. um_thread.Priority = ThreadPriority.BelowNormal;
  1061. fm_thread.Priority = ThreadPriority.BelowNormal;
  1062. pt_thread.Priority = ThreadPriority.BelowNormal;
  1063. mm_thread.Start();
  1064. um_thread.Start();
  1065. fm_thread.Start();
  1066. pt_thread.Start();
  1067. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  1068. {
  1069. FileTracks.Config = SettingsManager.FileListConfig;
  1070. HistoryTracks.Config = SettingsManager.HistoryListConfig;
  1071. QueueTracks.Config = SettingsManager.QueueListConfig;
  1072. ControlPanel.SourceList.Config = SettingsManager.SourceListConfig;
  1073. YouTubeContainer.YouTubeTracks.Config = SettingsManager.YouTubeListConfig;
  1074. FileTracks.ItemsSource = SettingsManager.FileTracks;
  1075. QueueTracks.ItemsSource = SettingsManager.QueueTracks;
  1076. HistoryTracks.ItemsSource = SettingsManager.HistoryTracks;
  1077. ControlPanel.SourceList.ItemsSource = SettingsManager.Sources;
  1078. YouTubeContainer.Search(SettingsManager.YouTubeListConfig.Filter);
  1079. }));
  1080. SettingsManager.FileTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(FileTracks.ItemsSource_CollectionChanged);
  1081. SettingsManager.QueueTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(QueueTracks.ItemsSource_CollectionChanged);
  1082. SettingsManager.HistoryTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(HistoryTracks.ItemsSource_CollectionChanged);
  1083. SettingsManager.QueueTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(QueueTracks_CollectionChanged);
  1084. SettingsManager.HistoryTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(HistoryTracks_CollectionChanged);
  1085. SettingsManager.FileTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(LibraryTracks_CollectionChanged);
  1086. jumpTaskPlay = new JumpTask()
  1087. {
  1088. Title = U.T("JumpPlay", "Title"),
  1089. Arguments = "/play",
  1090. Description = U.T("JumpPlay", "Description"),
  1091. IconResourceIndex = -1,
  1092. ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
  1093. };
  1094. jumpTaskNext = new JumpTask()
  1095. {
  1096. Title = U.T("JumpNext", "Title"),
  1097. Arguments = "/next",
  1098. Description = U.T("JumpNext", "Description"),
  1099. IconResourceIndex = -1,
  1100. ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
  1101. };
  1102. jumpTaskPrev = new JumpTask()
  1103. {
  1104. Title = U.T("JumpPrev", "Title"),
  1105. Arguments = "/previous",
  1106. Description = U.T("JumpPrev", "Description"),
  1107. IconResourceIndex = -1,
  1108. ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
  1109. };
  1110. jumpList = new JumpList();
  1111. jumpList.JumpItems.Add(jumpTaskPlay);
  1112. jumpList.JumpItems.Add(jumpTaskNext);
  1113. jumpList.JumpItems.Add(jumpTaskPrev);
  1114. jumpList.ShowRecentCategory = true;
  1115. jumpList.ShowFrequentCategory = true;
  1116. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  1117. {
  1118. PlaybackControls.VolumeSlide.Value = SettingsManager.Volume;
  1119. NavigationColumn.Width = new GridLength(SettingsManager.NavigationPaneWidth);
  1120. double h = SettingsManager.DetailsPaneHeight;
  1121. DetailsRow.Height = new GridLength(h);
  1122. UpdateVisibility("menubar");
  1123. UpdateVisibility("details");
  1124. ControlPanel.InitShortcuts();
  1125. JumpList.SetJumpList(Application.Current, jumpList);
  1126. UpdateGUIStrings();
  1127. }));
  1128. };
  1129. Thread pl_thread = new Thread(PlaylistThread);
  1130. Thread gui_thread = new Thread(GUIThread);
  1131. pl_thread.Name = "Init Playlist Manager";
  1132. gui_thread.Name = "Init managers and GUI";
  1133. pl_thread.Priority = ThreadPriority.BelowNormal;
  1134. gui_thread.Priority = ThreadPriority.BelowNormal;
  1135. pl_thread.Start();
  1136. gui_thread.Start();
  1137. }
  1138. #endregion
  1139. #region Event handlers
  1140. /// <summary>
  1141. ///
  1142. /// </summary>
  1143. /// <param name="sender"></param>
  1144. /// <param name="e"></param>
  1145. private void Window_Loaded(object sender, RoutedEventArgs e)
  1146. {
  1147. U.L(LogLevel.Debug, "MAIN", "Loaded");
  1148. System.Windows.Forms.Application.EnableVisualStyles();
  1149. WindowState = (WindowState)Enum.Parse(typeof(WindowState), SettingsManager.WinState);
  1150. kListener.KeyDown += new RawKeyEventHandler(KListener_KeyDown);
  1151. kListener.KeyUp += new RawKeyEventHandler(KListener_KeyUp);
  1152. addMenu = new ContextMenu();
  1153. showMenu = new ContextMenu();
  1154. toolsMenu = new ContextMenu();
  1155. addMenuFile = new MenuItem();
  1156. addMenuFile.Header = U.T("ToolbarAddTrack");
  1157. addMenuFile.Click += AddFile_Clicked;
  1158. addMenuFolder = new MenuItem();
  1159. addMenuFolder.Header = U.T("ToolbarAddFolder");
  1160. addMenuFolder.Click += AddFolder_Clicked;
  1161. addMenuPlaylist = new MenuItem();
  1162. addMenuPlaylist.Header = U.T("ToolbarAddPlaylist");
  1163. addMenuPlaylist.Click += OpenPlaylist_Clicked;
  1164. showMenuDetailsPane = new MenuItem();
  1165. showMenuDetailsPane.Header = U.T("ToolbarDetailsPane");
  1166. showMenuDetailsPane.IsCheckable = true;
  1167. showMenuDetailsPane.Click += ToggleDetailsPane;
  1168. showMenuMenuBar = new MenuItem();
  1169. showMenuMenuBar.Header = U.T("ToolbarMenuBar");
  1170. showMenuMenuBar.IsCheckable = true;
  1171. showMenuMenuBar.Click += ToggleMenuBar;
  1172. toolsMenuImporter = new MenuItem();
  1173. toolsMenuImporter.Header = U.T("ToolbarImporter");
  1174. toolsMenuImporter.Click += Importer_Clicked;
  1175. toolsMenuExporter = new MenuItem();
  1176. toolsMenuExporter.Header = U.T("ToolbarExporter");
  1177. toolsMenuExporter.Click += Exporter_Clicked;
  1178. toolsMenuGenerate = new MenuItem();
  1179. toolsMenuGenerate.Header = U.T("ToolbarGeneratePlaylist");
  1180. toolsMenuGenerate.Click += GeneratePlaylist_Clicked;
  1181. addMenu.Items.Add(addMenuFile);
  1182. addMenu.Items.Add(addMenuFolder);
  1183. addMenu.Items.Add(addMenuPlaylist);
  1184. showMenu.Items.Add(showMenuMenuBar);
  1185. showMenu.Items.Add(showMenuDetailsPane);
  1186. toolsMenu.Items.Add(toolsMenuImporter);
  1187. toolsMenu.Items.Add(toolsMenuExporter);
  1188. toolsMenu.Items.Add(toolsMenuGenerate);
  1189. addMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
  1190. showMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
  1191. toolsMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
  1192. listMenuAddToPlaylist.Header = U.T("MenuAddToPlaylist", "Header");
  1193. listMenuDelete.Header = U.T("MenuDelete");
  1194. listMenuDelete.Click += new RoutedEventHandler(listMenuDelete_Click);
  1195. listMenuInfo.Header = U.T("MenuInfo");
  1196. listMenuInfo.Click += new RoutedEventHandler(listMenuInfo_Click);
  1197. listMenuPlay.Header = U.T("MenuPlay");
  1198. listMenuPlay.Click += new RoutedEventHandler(listMenuPlay_Click);
  1199. listMenuWatchOnYouTube.Header = U.T("MenuWatchOnYouTube");
  1200. listMenuWatchOnYouTube.Click += new RoutedEventHandler(listMenuWatchOnYouTube_Click);
  1201. listMenuQueue.Header = U.T("MenuQueue");
  1202. listMenuQueue.Click += new RoutedEventHandler(listMenuQueue_Click);
  1203. listMenuRemove.Header = U.T("MenuRemove");
  1204. listMenuRemove.Click += new RoutedEventHandler(listMenuRemove_Click);
  1205. listMenuRemoveFromPlaylist.Header = U.T("MenuRemoveFromPlaylist", "Header");
  1206. listMenuRemoveFromPlaylist.Visibility = System.Windows.Visibility.Collapsed;
  1207. listMenuAddToNew = new MenuItem();
  1208. listMenuAddToNew.Header = U.T("MenuCreateNew", "Header");
  1209. listMenuAddToNew.FontStyle = FontStyles.Italic;
  1210. listMenuAddToNew.Click += new RoutedEventHandler(listMenuAddToPlaylist_Click);
  1211. listMenuAddToPlaylist.Items.Add(listMenuAddToNew);
  1212. listMenu.Items.Add(listMenuPlay);
  1213. listMenu.Items.Add(listMenuQueue);
  1214. listMenu.Items.Add(new Separator());
  1215. listMenu.Items.Add(listMenuAddToPlaylist);
  1216. listMenu.Items.Add(listMenuRemoveFromPlaylist);
  1217. listMenu.Items.Add(listMenuRemove);
  1218. listMenu.Items.Add(listMenuDelete);
  1219. listMenu.Items.Add(new Separator());
  1220. listMenu.Items.Add(listMenuWatchOnYouTube);
  1221. listMenu.Items.Add(listMenuInfo);
  1222. PlaylistTrackLists = new Hashtable();
  1223. //// TODO: remove all these lines
  1224. ////FileTracks.ParentWindow = this;
  1225. ////QueueTracks.ParentWindow = this;
  1226. ////HistoryTracks.ParentWindow = this;
  1227. ControlPanel.ParentWindow = this;
  1228. NavigationPane.ParentWindow = this;
  1229. PlaybackControls.ParentWindow = this;
  1230. FileTracks.ContextMenu = listMenu;
  1231. HistoryTracks.ContextMenu = listMenu;
  1232. QueueTracks.ContextMenu = listMenu;
  1233. YouTubeContainer.YouTubeTracks.ContextMenu = listMenu;
  1234. YouTubeContainer.YouTubeTracks.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
  1235. YouTubeContainer.YouTubeTracks.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
  1236. YouTubeContainer.YouTubeTracks.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
  1237. YouTubeContainer.YouTubeTracks.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
  1238. sourceModifiedDelay.Tick += new EventHandler(SourceModifiedDelay_Tick);
  1239. sourceModifiedDelay.Interval = new TimeSpan(0, 0, 0, 1, 500);
  1240. SettingsManager.PropertyChanged += new PropertyChangedWithValuesEventHandler(SettingsManager_PropertyChanged);
  1241. NavigationPane.CreateNewPlaylistETB.EnteredEditMode += new EventHandler(EditableTextBlock_EnteredEditMode);
  1242. U.ListenForShortcut = true;
  1243. SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
  1244. String defaultAlbumArt = "/GUI/Images/AlbumArt/Default.jpg";
  1245. //// rough detection of aero vs classic
  1246. //// you'll se a lot more of these around the code
  1247. if (System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName == "")
  1248. {
  1249. // applying classic theme
  1250. SolidColorBrush scb = (SolidColorBrush)FindResource("DetailsPaneKey");
  1251. scb.Color = SystemColors.ControlTextColor;
  1252. scb = (SolidColorBrush)FindResource("DetailsPaneValue");
  1253. scb.Color = SystemColors.ControlTextColor;
  1254. scb = (SolidColorBrush)FindResource("InfoPaneTitle");
  1255. scb.Color = SystemColors.ControlTextColor;
  1256. scb = (SolidColorBrush)FindResource("InfoPaneText");
  1257. scb.Color = SystemColors.ControlTextColor;
  1258. MainFrame.BorderBrush = SystemColors.ControlBrush;
  1259. MainFrame.Background = SystemColors.ControlBrush;
  1260. MainContainer.Background = SystemColors.ControlBrush;
  1261. InfoPane.Background = SystemColors.WindowBrush;
  1262. VerticalSplitter.Background = SystemColors.ControlBrush;
  1263. TopToolbar.Style = null;
  1264. AddButton.Style = (Style)FindResource("ClassicToolbarButtonStyle");
  1265. ShowButton.Style = (Style)FindResource("ClassicToolbarButtonStyle");
  1266. ToolsButton.Style = (Style)FindResource("ClassicToolbarButtonStyle");
  1267. EqualizerButton.Style = (Style)FindResource("ClassicToolbarButtonStyle");
  1268. PreferencesButton.Style = (Style)FindResource("ClassicToolbarButtonStyle");
  1269. HelpButton.Style = (Style)FindResource("ClassicToolbarSmallButtonStyle");
  1270. DetailsPane.Style = (Style)FindResource("ClassicDetailsPaneStyle");
  1271. OuterBottomRight.BorderBrush = SystemColors.ControlLightLightBrush;
  1272. OuterTopLeft.BorderBrush = SystemColors.ControlDarkBrush;
  1273. InnerBottomRight.BorderBrush = SystemColors.ControlDarkBrush;
  1274. InnerTopLeft.BorderBrush = SystemColors.ControlLightLightBrush;
  1275. ControlPanel.SourceTitle.Style = (Style)FindResource("ClassicControlPanelTitleStyle");
  1276. ControlPanel.AboutTitle.Style = (Style)FindResource("ClassicControlPanelTitleStyle");
  1277. ControlPanel.ShortcutTitle.Style = (Style)FindResource("ClassicControlPanelTitleStyle");
  1278. ControlPanel.GeneralTitle.Style = (Style)FindResource("ClassicControlPanelTitleStyle");
  1279. defaultAlbumArt = "/GUI/Images/AlbumArt/Classic.jpg";
  1280. }
  1281. // create system tray icon
  1282. trayIcon = (TaskbarIcon)FindResource("NotifyIcon");
  1283. trayIcon.TrayToolTip = new TrayToolTip(this);
  1284. trayIcon.TrayLeftMouseUp += TaskbarClicked;
  1285. trayMenu = new ContextMenu();
  1286. trayMenuShow = new MenuItem();
  1287. trayMenuExit = new MenuItem();
  1288. trayMenuPlay = new MenuItem();
  1289. trayMenuNext = new MenuItem();
  1290. trayMenuPrev = new MenuItem();
  1291. trayMenuShow.Header = U.T("TrayShow");
  1292. trayMenuExit.Header = U.T("TrayExit");
  1293. trayMenuPlay.Header = U.T("TrayPlay");
  1294. trayMenuNext.Header = U.T("TrayNext");
  1295. trayMenuPrev.Header = U.T("TrayPrev");
  1296. trayMenuShow.Click += TrayShow_Clicked;
  1297. trayMenuExit.Click += TrayExit_Clicked;
  1298. trayMenuPlay.Click += TrayPlayPause_Clicked;
  1299. trayMenuNext.Click += TrayNext_Clicked;
  1300. trayMenuPrev.Click += TrayPrevious_Clicked;
  1301. trayMenu.Items.Add(trayMenuShow);
  1302. trayMenu.Items.Add(new Separator());
  1303. trayMenu.Items.Add(trayMenuPlay);
  1304. trayMenu.Items.Add(trayMenuNext);
  1305. trayMenu.Items.Add(trayMenuPrev);
  1306. trayMenu.Items.Add(new Separator());
  1307. trayMenu.Items.Add(trayMenuExit);
  1308. trayIcon.ContextMenu = trayMenu;
  1309. //// create glass effect
  1310. RefreshGlassEffect();
  1311. System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.PerUserRoamingAndLocal);
  1312. //// create thumbnail buttons
  1313. taskbarPrev = new Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton(Properties.Resources.Previous, U.T("TaskbarPrev"));
  1314. taskbarPrev.Enabled = true;
  1315. taskbarPrev.Click += TaskbarPrevious_Clicked;
  1316. taskbarPlay = new Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton(Properties.Resources.Play, U.T("TaskbarPlay"));
  1317. taskbarPlay.Enabled = true;
  1318. taskbarPlay.Click += TaskbarPlayPause_Clicked;
  1319. taskbarNext = new Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton(Properties.Resources.Next, U.T("TaskbarNext"));
  1320. taskbarNext.Enabled = true;
  1321. taskbarNext.Click += TaskbarNext_Clicked;
  1322. Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.Instance.ThumbnailToolbars.AddButtons(
  1323. new WindowInteropHelper(this).Handle,
  1324. new Microsoft.WindowsAPICodePack.Taskbar.ThumbnailToolbarButton[] { taskbarPrev, taskbarPlay, taskbarNext }
  1325. );
  1326. resortDelay.Interval = new TimeSpan(0, 0, 0, 0, 500);
  1327. resortDelay.Tick += new EventHandler(ResortDelay_Tick);
  1328. FilesystemManager.SourceModified += new SourceModifiedEventHandler(FilesystemManager_SourceModified);
  1329. FilesystemManager.TrackModified += new PropertyChangedEventHandler(FilesystemManager_TrackModified);
  1330. FilesystemManager.PathModified += new PathModifiedEventHandler(FilesystemManager_PathModified);
  1331. FilesystemManager.PathRenamed += new RenamedEventHandler(FilesystemManager_PathRenamed);
  1332. FilesystemManager.ProgressChanged += new ProgressChangedEventHandler(FilesystemManager_ProgressChanged);
  1333. FilesystemManager.SourceAdded += new SourcesModifiedEventHandler(FilesystemManager_SourceAdded);
  1334. FilesystemManager.SourceRemoved += new SourcesModifiedEventHandler(FilesystemManager_SourceRemoved);
  1335. FilesystemManager.DefaultAlbumArt = defaultAlbumArt;
  1336. MediaManager.TrackSwitched += new TrackSwitchedEventHandler(MediaManager_TrackSwitched);
  1337. MediaManager.ConnectionProblem += new EventHandler(MediaManager_ConnectionProblem);
  1338. MediaManager.SearchMatch = TrackList_SearchMatch;
  1339. UpgradeManager.Checked += new EventHandler(UpgradeManager_Checked);
  1340. UpgradeManager.ErrorOccured += new ErrorEventHandler(UpgradeManager_ErrorOccured);
  1341. UpgradeManager.ProgressChanged += new ProgressChangedEventHandler(UpgradeManager_ProgressChanged);
  1342. UpgradeManager.Upgraded += new EventHandler(UpgradeManager_Upgraded);
  1343. UpgradeManager.UpgradeFound += new EventHandler(UpgradeManager_UpgradeFound);
  1344. FileTracks.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
  1345. FileTracks.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
  1346. FileTracks.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
  1347. FileTracks.FilesDropped += new FileDropEventHandler(TrackList_FilesDropped);
  1348. FileTracks.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
  1349. FileTracks.FilterMatch = TrackList_SearchMatch;
  1350. HistoryTracks.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
  1351. HistoryTracks.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
  1352. HistoryTracks.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
  1353. HistoryTracks.FilesDropped += new FileDropEventHandler(TrackList_FilesDropped);
  1354. HistoryTracks.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
  1355. HistoryTracks.FilterMatch = TrackList_SearchMatch;
  1356. QueueTracks.SelectionChanged += new SelectionChangedEventHandler(TrackList_SelectionChanged);
  1357. QueueTracks.MouseDoubleClick += new MouseButtonEventHandler(TrackList_MouseDoubleClick);
  1358. QueueTracks.ContextMenuOpening += new ContextMenuEventHandler(TrackList_ContextMenuOpening);
  1359. QueueTracks.FilesDropped += new FileDropEventHandler(TrackList_FilesDropped);
  1360. QueueTracks.MoveItem += new MoveItemEventHandler(TrackList_MoveItem);
  1361. QueueTracks.FilterMatch = TrackList_SearchMatch;
  1362. YouTubePlayerInterface ypi = new YouTubePlayerInterface();
  1363. ypi.ErrorOccured += new ErrorEventHandler(YouTube_ErrorOccured);
  1364. ypi.NoFlashDetected += new EventHandler(YouTube_NoFlashDetected);
  1365. ypi.PlayerReady += new EventHandler(YouTube_PlayerReady);
  1366. // WebBrowser will not load if it's not visible
  1367. // so we remove it from now playing...
  1368. NowPlayingContainer.Video.Children.Remove(NowPlayingContainer.Browser);
  1369. // ...put it inside main window...
  1370. TrackContainer.Children.Add(NowPlayingContainer.Browser);
  1371. // ...and remove it from here quickly again...
  1372. TrackContainer.Children.Remove(NowPlayingContainer.Browser);
  1373. NowPlayingContainer.Browser.Visibility = System.Windows.Visibility.Collapsed;
  1374. // (man this was fugly :P)
  1375. NowPlayingContainer.Browser.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
  1376. NowPlayingContainer.Browser.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
  1377. NowPlayingContainer.Browser.Width = double.NaN;
  1378. NowPlayingContainer.Browser.Height = double.NaN;
  1379. NowPlayingContainer.Browser.ObjectForScripting = ypi;
  1380. NowPlayingContainer.NoVideoMessage.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
  1381. NowPlayingContainer.NoVideoMessage.Visibility = System.Windows.Visibility.Visible;
  1382. if (YouTubeManager.IsYouTube(SettingsManager.CurrentTrack))
  1383. {
  1384. NowPlayingContainer.NoVideoMessage.Visibility = System.Windows.Visibility.Collapsed;
  1385. NowPlayingContainer.Browser.Visibility = System.Windows.Visibility.Visible;
  1386. }
  1387. U.L(LogLevel.Debug, "MAIN", "Startup complete");
  1388. ThreadStart GUIThread = delegate()
  1389. {
  1390. InitGUI();
  1391. };
  1392. Thread gui_thread = new Thread(GUIThread);
  1393. gui_thread.Name = "Init GUI Thread";
  1394. gui_thread.Priority = ThreadPriority.BelowNormal;
  1395. gui_thread.Start();
  1396. //long timestamp = (long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
  1397. //string newVersion = timestamp.ToString();
  1398. //Console.WriteLine(String.Format("Timestamp: {0}", timestamp));
  1399. }
  1400. /// <summary>
  1401. /// Invoked when the user switches the session.
  1402. /// Eg: lock or log off
  1403. /// </summary>
  1404. /// <param name="sender">The sender of the event</param>
  1405. /// <param name="e">The event data</param>
  1406. private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
  1407. {
  1408. if ((e.Reason == SessionSwitchReason.SessionLock && SettingsManager.PauseWhileLocked) ||
  1409. (e.Reason == SessionSwitchReason.SessionLogoff && SettingsManager.PauseWhileLoggedOut))
  1410. {
  1411. resumeWhenBack = SettingsManager.MediaState == MediaState.Playing;
  1412. MediaManager.Pause();
  1413. }
  1414. else if (resumeWhenBack &&
  1415. (e.Reason == SessionSwitchReason.SessionLogon || e.Reason == SessionSwitchReason.SessionUnlock))
  1416. {
  1417. MediaManager.Play();
  1418. resumeWhenBack = false;
  1419. }
  1420. }
  1421. /// <summary>
  1422. /// Invoked when a playlist is modified
  1423. /// </summary>
  1424. /// <param name="sender">The sender of the event</param>
  1425. /// <param name="e">The event data</param>
  1426. private void PlaylistManager_PlaylistModified(object sender, ModifiedEventArgs e)
  1427. {
  1428. PlaylistData playlist = sender as PlaylistData;
  1429. if (e.Type == ModifyType.Created)
  1430. {
  1431. CreatePlaylist(playlist);
  1432. }
  1433. else if (e.Type == ModifyType.Removed)
  1434. {
  1435. ((ViewDetails)PlaylistTrackLists[playlist.Name]).Visibility = Visibility.Collapsed;
  1436. PlaylistTrackLists.Remove(playlist.Name);
  1437. // remove from context menu
  1438. for (int i = 0; i < listMenuAddToPlaylist.Items.Count; i++)
  1439. {
  1440. if ((string)((MenuItem)listMenuAddToPlaylist.Items[i]).Header == playlist.Name)
  1441. {
  1442. listMenuAddToPlaylist.Items.RemoveAt(i);
  1443. break;
  1444. }
  1445. }
  1446. for (int i = 0; i < listMenuRemoveFromPlaylist.Items.Count; i++)
  1447. {
  1448. if ((string)((MenuItem)listMenuRemoveFromPlaylist.Items[i]).Header == playlist.Name)
  1449. {
  1450. listMenuRemoveFromPlaylist.Items.RemoveAt(i);
  1451. break;
  1452. }
  1453. }
  1454. if (listMenuRemoveFromPlaylist.Items.Count == 0)
  1455. listMenuRemoveFromPlaylist.Visibility = System.Windows.Visibility.Collapsed;
  1456. PlaybackControls.Search.RemovePlaylist(playlist);
  1457. for (int i = 0; i < NavigationPane.Playlists.Items.Count; i++)
  1458. {
  1459. TreeViewItem tvi = (TreeViewItem)NavigationPane.Playlists.Items[i];
  1460. if (tvi.Header is StackPanel)
  1461. {
  1462. EditableTextBlock tb = ((StackPanel)tvi.Header).Children[1] as EditableTextBlock;
  1463. if (tb.Text == playlist.Name)
  1464. {
  1465. NavigationPane.historyList.Remove(tvi);
  1466. if (tvi.IsSelected)
  1467. {
  1468. if (NavigationPane.historyList.Count > 0)
  1469. {
  1470. TreeViewItem prevItem = NavigationPane.historyList[NavigationPane.historyList.Count - 1];
  1471. prevItem.IsSelected = true;
  1472. prevItem.Focus();
  1473. }
  1474. else
  1475. {
  1476. if (SettingsManager.Playlists.Count > 0)
  1477. ((TreeViewItem)NavigationPane.Playlists.Items[0]).IsSelected = true;
  1478. else
  1479. NavigationPane.Library.IsSelected = true;
  1480. }
  1481. }
  1482. NavigationPane.Playlists.Items.Remove(tvi);
  1483. break;
  1484. }
  1485. }
  1486. }
  1487. // fix navigation references
  1488. if (SettingsManager.CurrentSelectedNavigation == "Playlist:" + playlist.Name)
  1489. SettingsManager.CurrentSelectedNavigation = "Files";
  1490. if (SettingsManager.CurrentActiveNavigation == "Playlist:" + playlist.Name)
  1491. SettingsManager.CurrentActiveNavigation = "Files";
  1492. }
  1493. }
  1494. /// <summary>
  1495. /// Invoked when a playlist is renamed
  1496. /// </summary>
  1497. /// <param name="sender">The sender of the event</param>
  1498. /// <param name="e">The event data</param>
  1499. private void PlaylistManager_PlaylistRenamed(object sender, RenamedEventArgs e)
  1500. {
  1501. PlaylistData playlist = sender as PlaylistData;
  1502. // rename key value in hashtable of tracklists
  1503. PlaylistTrackLists.Add(e.Name, PlaylistTrackLists[e.OldName]);
  1504. PlaylistTrackLists.Remove(e.OldName);
  1505. // rename list context menu items
  1506. foreach (MenuItem mi in listMenuAddToPlaylist.Items)
  1507. if ((string)mi.Header == e.OldName)
  1508. mi.Header = e.Name;
  1509. foreach (MenuItem mi in listMenuRemoveFromPlaylist.Items)
  1510. if ((string)mi.Header == e.OldName)
  1511. mi.Header = e.Name;
  1512. PlaybackControls.Search.RenamePlaylist(e.OldName, e.Name);
  1513. // rename navigation items
  1514. foreach (TreeViewItem item in NavigationPane.Playlists.Items)
  1515. {
  1516. StackPanel sp = item.Header as StackPanel;
  1517. EditableTextBlock etb = sp.Children[1] as EditableTextBlock;
  1518. if (etb.Text == e.OldName)
  1519. {
  1520. etb.Text = e.Name;
  1521. etb.Focus();
  1522. break;
  1523. }
  1524. }
  1525. playlist.Name = e.Name;
  1526. // fix navigation references
  1527. if (SettingsManager.CurrentSelectedNavigation == "Playlist:" + e.OldName)
  1528. SettingsManager.CurrentSelectedNavigation = "Playlist:" + e.Name;
  1529. if (SettingsManager.CurrentActiveNavigation == "Playlist:" + e.OldName)
  1530. SettingsManager.CurrentActiveNavigation = "Playlist:" + e.Name;
  1531. }
  1532. /// <summary>
  1533. /// Invoked when the progress of an upgrade changes
  1534. /// </summary>
  1535. /// <param name="sender">The sender of the event</param>
  1536. /// <param name="e">The event data</param>
  1537. private void UpgradeManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
  1538. {
  1539. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  1540. {
  1541. ProgressState ps = e.UserState as ProgressState;
  1542. ControlPanel.UpgradeProgressInfo.Text = ps.Message;
  1543. ControlPanel.UpgradeProgressBar.Value = e.ProgressPercentage;
  1544. ControlPanel.UpgradeProgressBar.IsIndeterminate = ps.IsIndetermined;
  1545. TaskbarItemInfo.ProgressValue = (double)e.ProgressPercentage / 100;
  1546. TaskbarItemInfo.ProgressState = (ps.IsIndetermined ? TaskbarItemProgressState.Indeterminate : TaskbarItemProgressState.Normal);
  1547. }));
  1548. }
  1549. /// <summary>
  1550. /// Invoked when an error occurs during an upgrade
  1551. /// </summary>
  1552. /// <param name="sender">The sender of the event</param>
  1553. /// <param name="message">The error message</param>
  1554. private void UpgradeManager_ErrorOccured(object sender, string message)
  1555. {
  1556. U.L(LogLevel.Debug, "MAIN", "Upgrade manager encountered an error: " + message);
  1557. Dispatcher.Invoke(new Action(delegate
  1558. {
  1559. if (TaskbarItemInfo != null)
  1560. TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
  1561. ControlPanel.UpgradeMessageText.Text = message;
  1562. ControlPanel.UpgradeMessageIcon.Source = new BitmapImage(new Uri("/GUI/Images/Icons/Error.ico", UriKind.RelativeOrAbsolute));
  1563. ControlPanel.UpgradeMessage.Visibility = System.Windows.Visibility.Visible;
  1564. if (UpgradeManager.Policy == UpgradePolicy.Manual)
  1565. ControlPanel.EnableUpgradeCheck();
  1566. else if (UpgradeManager.Policy == UpgradePolicy.Notify && UpgradeManager.ForceDownload)
  1567. ControlPanel.EnableUpgradeDo();
  1568. }));
  1569. }
  1570. /// <summary>
  1571. /// Invoked when an upgrade is found
  1572. /// </summary>
  1573. /// <param name="sender">The sender of the event</param>
  1574. /// <param name="e">The event data</param>
  1575. private void UpgradeManager_UpgradeFound(object sender, EventArgs e)
  1576. {
  1577. U.L(LogLevel.Debug, "MAIN", "Upgrade manager found upgrade");
  1578. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  1579. {
  1580. ControlPanel.UpgradeMessageText.Text = U.T("UpgradeFound");
  1581. ControlPanel.UpgradeMessageIcon.Source = new BitmapImage(new Uri("/GUI/Images/Icons/Info.ico", UriKind.RelativeOrAbsolute));
  1582. ControlPanel.UpgradeMessage.Visibility = System.Windows.Visibility.Visible;
  1583. ControlPanel.EnableUpgradeDo();
  1584. if (TaskbarItemInfo != null)
  1585. TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
  1586. if (SettingsManager.UpgradePolicy == UpgradePolicy.Notify)
  1587. {
  1588. TrayNotification notification = new TrayNotification(this);
  1589. trayIcon.ShowCustomBalloon(notification, System.Windows.Controls.Primitives.PopupAnimation.Fade, 3600000);
  1590. ControlPanel.PrefDoUpgrade.Visibility = Visibility.Visible;
  1591. }
  1592. }));
  1593. }
  1594. /// <summary>
  1595. /// Invoked when a check for upgrades has been performed
  1596. /// </summary>
  1597. /// <param name="sender">The sender of the event</param>
  1598. /// <param name="e">The event data</param>
  1599. private void UpgradeManager_Checked(object sender, EventArgs e)
  1600. {
  1601. U.L(LogLevel.Debug, "MAIN", "Upgrade manager completed check");
  1602. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  1603. {
  1604. TimeSpan _ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0));
  1605. SettingsManager.UpgradeCheck = (long)_ts.TotalSeconds;
  1606. ControlPanel.UpdateUpgradeCheck();
  1607. if (TaskbarItemInfo != null)
  1608. TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
  1609. if (UpgradeManager.Policy == UpgradePolicy.Manual && !UpgradeManager.Found)
  1610. {
  1611. ControlPanel.EnableUpgradeCheck();
  1612. ControlPanel.UpgradeMessageIcon.Source = new BitmapImage(new Uri("/GUI/Images/Icons/Info.ico", UriKind.RelativeOrAbsolute));
  1613. ControlPanel.UpgradeMessageText.Text = U.T("UpgradeNotFound");
  1614. ControlPanel.UpgradeMessage.Visibility = System.Windows.Visibility.Visible;
  1615. }
  1616. }));
  1617. }
  1618. /// <summary>
  1619. /// Invoked when the application has been upgraded
  1620. /// </summary>
  1621. /// <param name="sender">The sender of the event</param>
  1622. /// <param name="e">The event data</param>
  1623. private void UpgradeManager_Upgraded(object sender, EventArgs e)
  1624. {
  1625. U.L(LogLevel.Debug, "MAIN", "Upgrade manager has upgraded Stoffi");
  1626. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  1627. {
  1628. ControlPanel.PrefDoUpgrade.Visibility = Visibility.Collapsed;
  1629. ControlPanel.UpgradeProgress.Visibility = Visibility.Collapsed;
  1630. if (TaskbarItemInfo != null)
  1631. TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
  1632. if (SettingsManager.UpgradePolicy == UpgradePolicy.Manual)
  1633. {
  1634. ControlPanel.EnableRestart();
  1635. ControlPanel.UpgradeMessageText.Text = U.T("UpgradePending");
  1636. ControlPanel.UpgradeMessageIcon.Source = new BitmapImage(new Uri("/GUI/Images/Icons/Info.ico", UriKind.RelativeOrAbsolute));
  1637. ControlPanel.UpgradeMessage.Visibility = System.Windows.Visibility.Visible;
  1638. }
  1639. else
  1640. ControlPanel.UpgradeMessage.Visibility = Visibility.Collapsed;
  1641. }));
  1642. }
  1643. /// <summary>
  1644. /// Invoked when there's a problem with the Internet connection.
  1645. /// </summary>
  1646. /// <param name="sender">The sender of the event</param>
  1647. /// <param name="e">The event data</param>
  1648. private void MediaManager_ConnectionProblem(object sender, EventArgs e)
  1649. {
  1650. if (showMediaError)
  1651. {
  1652. showMediaError = false;
  1653. MessageBox.Show(U.T("MessageConnectionProblem", "Message"),
  1654. U.T("MessageConnectionProblem", "Title"), MessageBoxButton.OK, MessageBoxImage.Error);
  1655. }
  1656. }
  1657. /// <summary>
  1658. /// Invoked when the media manager switches from one track to another
  1659. /// </summary>
  1660. /// <param name="e">The event data</param>
  1661. private void MediaManager_TrackSwitched(TrackSwitchedEventArgs e)
  1662. {
  1663. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  1664. {
  1665. ViewDetails tl = GetCurrentTrackList();
  1666. if (tl == null) return;
  1667. ListViewItem lvi = tl.ItemContainerGenerator.ContainerFromItem(e.OldTrack) as ListViewItem;
  1668. if (lvi != null)
  1669. {
  1670. Point trackLoc = lvi.TranslatePoint(new Point(0, 0), tl);
  1671. double trackListHeight = tl.ActualHeight;
  1672. double trackHeight = lvi.ActualHeight;
  1673. if (trackLoc.Y + trackHeight > 0 || trackLoc.Y <= trackListHeight)
  1674. tl.ScrollIntoView(MediaManager.GetSourceTrack(e.NewTrack));
  1675. }
  1676. if (trayIcon != null) ((TrayToolTip)trayIcon.TrayToolTip).SetTrack(e.NewTrack);
  1677. if (SettingsManager.ShowOSD)
  1678. {
  1679. TrayNotification notification = new TrayNotification(e.NewTrack, this);
  1680. if (trayIcon != null)
  1681. trayIcon.ShowCustomBalloon(notification, System.Windows.Controls.Primitives.PopupAnimation.Fade, 4000);
  1682. }
  1683. // TODO: This hangs Stoffi sometimes for a few seconds
  1684. JumpTask jumpTask = new JumpTask()
  1685. {
  1686. Title = e.NewTrack.Artist + " - " + e.NewTrack.Title,
  1687. Arguments = e.NewTrack.Path,
  1688. Description = e.NewTrack.Artist + " - " + e.NewTrack.Title,
  1689. IconResourcePath = "C:\\Windows\\System32\\imageres.dll",
  1690. IconResourceIndex = 190,
  1691. ApplicationPath = Assembly.GetEntryAssembly().CodeBase,
  1692. };
  1693. JumpList.AddToRecentCategory(jumpTask);
  1694. }));
  1695. }
  1696. /// <summary>
  1697. /// Invoked when the user clicks Next inside the Properties window
  1698. /// </summary>
  1699. /// <param name="sender">The sender of the event</param>
  1700. /// <param name="e">The event data</param>
  1701. private void Properties_NextClick(object sender, EventArgs e)
  1702. {
  1703. PropertiesWindow pw = sender as PropertiesWindow;
  1704. ViewDetails trackList = GetCurrentTrackList();
  1705. ItemCollection items = trackList.Items;
  1706. List<TrackData> t = new List<TrackData>();
  1707. for (int i = (trackList.IndexOf(pw.Tracks[pw.Tracks.Count - 1]) + 1) % items.Count; // use % to wrap
  1708. t.Count < pw.Tracks.Count;
  1709. i = ++i % items.Count) // use % to wrap
  1710. {
  1711. // find next non-youtube
  1712. TrackData track = (TrackData)trackList.GetItemAt(i);
  1713. int end = (i - 1 + items.Count) % items.Count; // stop when checking this far
  1714. while (YouTubeManager.IsYouTube(track) && i != end)
  1715. {
  1716. i = ++i % items.Count; // use % to wrap
  1717. track = (TrackData)trackList.GetItemAt(i);
  1718. }
  1719. // add if any non-youtube
  1720. if (i < items.Count)
  1721. t.Add(track);
  1722. }
  1723. if (t.Count > 0)
  1724. pw.AddTracks(t);
  1725. // else?
  1726. }
  1727. /// <summary>
  1728. /// Invoked when the user clicks Previous inside the Properties window
  1729. /// </summary>
  1730. /// <param name="sender">The sender of the event</param>
  1731. /// <param name="e">The event data</param>
  1732. private void Properties_PrevClick(object sender, EventArgs e)
  1733. {
  1734. PropertiesWindow pw = sender as PropertiesWindow;
  1735. ViewDetails trackList = GetCurrentTrackList();
  1736. ItemCollection items = trackList.Items;
  1737. List<TrackData> t = new List<TrackData>();
  1738. for (int i = (trackList.IndexOf(pw.Tracks[0]) - 1 + items.Count) % items.Count; // use % to wrap
  1739. t.Count < pw.Tracks.Count;
  1740. i = --i + items.Count % items.Count) // use % to wrap
  1741. {
  1742. // find next non-youtube
  1743. TrackData track = (TrackData)trackList.GetItemAt(i);
  1744. int end = (i + 1) % items.Count; // stop when checking this far
  1745. while (YouTubeManager.IsYouTube(track) && i != end)
  1746. {
  1747. i = --i + items.Count % items.Count; // use % to wrap
  1748. if (i < 0) i = items.Count + i;
  1749. track = (TrackData)trackList.GetItemAt(i);
  1750. }
  1751. // add if any non-youtube
  1752. if (i < items.Count)
  1753. t.Add(track);
  1754. }
  1755. t.Reverse();
  1756. if (t.Count > 0)
  1757. pw.AddTracks(t);
  1758. }
  1759. /// <summary>
  1760. /// Invoked when an editable text block enters edit mode
  1761. /// </summary>
  1762. /// <param name="sender">The sender of the event</param>
  1763. /// <param name="e">The event data</param>
  1764. private void EditableTextBlock_EnteredEditMode(object sender, EventArgs e)
  1765. {
  1766. etbInEdit = sender as EditableTextBlock;
  1767. }
  1768. /// <summary>
  1769. /// Invoked when the user doubleclicks a track in a track list
  1770. /// </summary>
  1771. /// <param name="sender">The sender of the event</param>
  1772. /// <param name="e">The event data</param>
  1773. private void TrackList_MouseDoubleClick(object sender, RoutedEventArgs e)
  1774. {
  1775. Play();
  1776. }
  1777. /// <summary>
  1778. /// Invoked when the user right-clicks the track list
  1779. /// </summary>
  1780. /// <param name="sender">The sender of the event</param>
  1781. /// <param name="e">The event data</param>
  1782. private void TrackList_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  1783. {
  1784. if (SettingsManager.CurrentSelectedNavigation == "Queue")
  1785. listMenuQueue.Visibility = System.Windows.Visibility.Collapsed;
  1786. else
  1787. listMenuQueue.Visibility = System.Windows.Visibility.Visible;
  1788. bool containsYouTube = false;
  1789. bool containsFiles = false;
  1790. bool isPlaying = true;
  1791. bool isQueued = false;
  1792. ViewDetails vd = sender as ViewDetails;
  1793. foreach (TrackData t in vd.SelectedItems)
  1794. {
  1795. if (YouTubeManager.IsYouTube(t))
  1796. containsYouTube = true;
  1797. else
  1798. containsFiles = true;
  1799. if (SettingsManager.CurrentTrack == null || SettingsManager.CurrentTrack.Path != t.Path || SettingsManager.MediaState != MediaState.Playing)
  1800. isPlaying = false;
  1801. if (!isQueued)
  1802. foreach (TrackData u in SettingsManager.QueueTracks)
  1803. if (t.Path == u.Path)
  1804. isQueued = true;
  1805. }
  1806. listMenuInfo.Visibility = containsYouTube ? System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
  1807. listMenuRemove.Visibility = containsFiles ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  1808. listMenuDelete.Visibility = containsFiles ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  1809. listMenuWatchOnYouTube.Visibility = containsYouTube ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  1810. listMenuShareSong.Visibility = containsYouTube && ServiceManager.Linked ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  1811. listMenuPlay.Header = (isPlaying ? U.T("MenuPause") : U.T("MenuPlay"));
  1812. listMenuQueue.Header = (isQueued ? U.T("MenuDequeue") : U.T("MenuQueue"));
  1813. }
  1814. /// <summary>
  1815. /// Invoked when the user clicks play in the track list's context menu
  1816. /// </summary>
  1817. /// <param name="sender">The sender of the event</param>
  1818. /// <param name="e">The event data</param>
  1819. private void listMenuPlay_Click(object sender, RoutedEventArgs e)
  1820. {
  1821. MenuItem mi = sender as MenuItem;
  1822. if ((string)mi.Header == U.T("MenuPlay"))
  1823. Play(false);
  1824. else
  1825. MediaManager.Pause();
  1826. }
  1827. /// <summary>
  1828. /// Invoked when the user clicks remove in the track list's context menu
  1829. /// </summary>
  1830. /// <param name="sender">The sender of the event</param>
  1831. /// <param name="e">The event data</param>
  1832. private void listMenuRemove_Click(object sender, RoutedEventArgs e)
  1833. {
  1834. int i = GetCurrentTrackList().SelectedIndex;
  1835. List<TrackData> tracks = new List<TrackData>();
  1836. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  1837. tracks.Add(track);
  1838. // stop playing if removing active tracks
  1839. foreach (TrackData t in tracks)
  1840. {
  1841. if (t.IsActive)
  1842. {
  1843. MediaManager.Stop();
  1844. break;
  1845. }
  1846. }
  1847. // remove from whole collection
  1848. if (SettingsManager.CurrentSelectedNavigation == "Files")
  1849. {
  1850. foreach (TrackData track in tracks)
  1851. {
  1852. RemoveTrack(track.Path, SettingsManager.FileTracks);
  1853. RemoveTrack(track.Path, SettingsManager.QueueTracks);
  1854. RemoveTrack(track.Path, SettingsManager.HistoryTracks);
  1855. foreach (PlaylistData p in SettingsManager.Playlists)
  1856. RemoveTrack(track.Path, p.Tracks);
  1857. SourceData source = FilesystemManager.GetSource(track.Path);
  1858. // remove from sources?
  1859. if (FilesystemManager.PathIsAdded(track.Path) && source != null)
  1860. FilesystemManager.RemoveSource(source);
  1861. else if (!FilesystemManager.PathIsIgnored(track.Path))
  1862. FilesystemManager.AddSource(new SourceData
  1863. {
  1864. Data = track.Path,
  1865. Ignore = true,
  1866. Icon = "pack://application:,,,/GUI/Images/Icons/FileAudio.ico",
  1867. HumanType = U.T("SourcesTypeFile"),
  1868. Type = SourceType.File
  1869. });
  1870. }
  1871. }
  1872. // dequeue
  1873. else if (SettingsManager.CurrentSelectedNavigation == "Queue")
  1874. MediaManager.Dequeue(tracks);
  1875. // remove from history
  1876. else if (SettingsManager.CurrentSelectedNavigation == "History")
  1877. {
  1878. foreach (TrackData track in tracks)
  1879. {
  1880. if (SettingsManager.HistoryTracks.IndexOf(track) <= SettingsManager.HistoryIndex)
  1881. SettingsManager.HistoryIndex--;
  1882. RemoveTrack(track.Path, SettingsManager.HistoryTracks);
  1883. }
  1884. if (SettingsManager.HistoryIndex > SettingsManager.HistoryTracks.Count)
  1885. SettingsManager.HistoryIndex = SettingsManager.HistoryTracks.Count;
  1886. }
  1887. // remove from playlist
  1888. else
  1889. {
  1890. string pl = SettingsManager.CurrentSelectedNavigation.Split(new[]{':'},2)[1];
  1891. PlaylistManager.RemoveFromPlaylist(tracks, pl);
  1892. }
  1893. // refresh selection
  1894. if (GetCurrentTrackList().Items.Count > 0)
  1895. {
  1896. if (i >= GetCurrentTrackList().Items.Count)
  1897. GetCurrentTrackList().SelectedIndex = GetCurrentTrackList().Items.Count - 1;
  1898. else
  1899. GetCurrentTrackList().SelectedIndex = i;
  1900. }
  1901. }
  1902. /// <summary>
  1903. /// Invoked when the user clicks delete in the track list's context menu
  1904. /// </summary>
  1905. /// <param name="sender">The sender of the event</param>
  1906. /// <param name="e">The event data</param>
  1907. private void listMenuDelete_Click(object sender, RoutedEventArgs e)
  1908. {
  1909. if (MessageBox.Show(U.T("MessageConfirmDelete", "Message"), U.T("MessageConfirmDelete", "Title"),
  1910. MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No) == MessageBoxResult.Yes)
  1911. {
  1912. int i = GetCurrentTrackList().SelectedIndex;
  1913. List<TrackData> tracks = new List<TrackData>();
  1914. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  1915. tracks.Add(track);
  1916. foreach (TrackData t in tracks)
  1917. {
  1918. if (t.IsActive)
  1919. {
  1920. MediaManager.Stop();
  1921. break;
  1922. }
  1923. }
  1924. foreach (TrackData track in tracks)
  1925. {
  1926. try
  1927. {
  1928. File.Delete(track.Path);
  1929. }
  1930. catch (Exception exc)
  1931. {
  1932. MessageBox.Show(exc.Message, U.T("MessageErrorDeleting", "Title"), MessageBoxButton.OK, MessageBoxImage.Error);
  1933. }
  1934. }
  1935. if (GetCurrentTrackList().Items.Count > 0)
  1936. {
  1937. if (i >= GetCurrentTrackList().Items.Count)
  1938. GetCurrentTrackList().SelectedIndex = GetCurrentTrackList().Items.Count - 1;
  1939. else
  1940. GetCurrentTrackList().SelectedIndex = i;
  1941. }
  1942. }
  1943. }
  1944. /// <summary>
  1945. /// Invoked when the user clicks information in the track list's
  1946. /// context menu
  1947. /// </summary>
  1948. /// <param name="sender">The sender of the event</param>
  1949. /// <param name="e">The event data</param>
  1950. private void listMenuInfo_Click(object sender, RoutedEventArgs e)
  1951. {
  1952. if (GetCurrentTrackList().SelectedItems.Count > 0)
  1953. {
  1954. List<TrackData> tracks = new List<TrackData>();
  1955. foreach (TrackData t in GetCurrentTrackList().SelectedItems)
  1956. if (!YouTubeManager.IsYouTube(t))
  1957. tracks.Add(t);
  1958. PropertiesWindow dialog = new PropertiesWindow(tracks);
  1959. dialog.NextClick += new EventHandler(Properties_NextClick);
  1960. dialog.PreviousClick += new EventHandler(Properties_PrevClick);
  1961. dialog.ShowDialog();
  1962. }
  1963. }
  1964. /// <summary>
  1965. /// Invoked when the user clicks add to a playlist in the track
  1966. /// list's context menu
  1967. /// </summary>
  1968. /// <param name="sender">The sender of the event</param>
  1969. /// <param name="e">The event data</param>
  1970. private void listMenuAddToPlaylist_Click(object sender, RoutedEventArgs e)
  1971. {
  1972. if (sender is MenuItem)
  1973. {
  1974. MenuItem item = sender as MenuItem;
  1975. String name = item.Header.ToString();
  1976. if (name == U.T("MenuCreateNew", "Header"))
  1977. {
  1978. NavigationPane.AddToPlaylistQueue.Clear();
  1979. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  1980. NavigationPane.AddToPlaylistQueue.Add(track);
  1981. NavigationPane.CreateNewPlaylistETB.IsInEditMode = true;
  1982. }
  1983. else
  1984. {
  1985. List<object> tracks = new List<object>();
  1986. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  1987. tracks.Add(track);
  1988. PlaylistManager.AddToPlaylist(tracks, name);
  1989. }
  1990. }
  1991. }
  1992. /// <summary>
  1993. /// Invoked when the user clicks add to a new playlist in the
  1994. /// track list's context menu
  1995. /// </summary>
  1996. /// <param name="sender">The sender of the event</param>
  1997. /// <param name="e">The event data</param>
  1998. private void listMenuAddToNew_Click(object sender, RoutedEventArgs e)
  1999. {
  2000. NavigationPane.AddToPlaylistQueue.Clear();
  2001. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  2002. NavigationPane.AddToPlaylistQueue.Add(track);
  2003. NavigationPane.CreateNewPlaylistETB.IsInEditMode = true;
  2004. }
  2005. /// <summary>
  2006. /// Invoked when the user clicks remove from a playlist in
  2007. /// the track list's context menu
  2008. /// </summary>
  2009. /// <param name="sender">The sender of the event</param>
  2010. /// <param name="e">The event data</param>
  2011. private void listMenuRemoveFromPlaylist_Click(object sender, RoutedEventArgs e)
  2012. {
  2013. if (sender is MenuItem)
  2014. {
  2015. MenuItem item = sender as MenuItem;
  2016. String name = item.Header.ToString();
  2017. List<TrackData> tracks = new List<TrackData>();
  2018. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  2019. tracks.Add(track);
  2020. PlaylistManager.RemoveFromPlaylist(tracks, name);
  2021. }
  2022. }
  2023. /// <summary>
  2024. /// Invoked when the user clicks queue/dequeue in the track
  2025. /// list's context menu
  2026. /// </summary>
  2027. /// <param name="sender">The sender of the event</param>
  2028. /// <param name="e">The event data</param>
  2029. private void listMenuQueue_Click(object sender, RoutedEventArgs e)
  2030. {
  2031. List<TrackData> tracks = new List<TrackData>();
  2032. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  2033. tracks.Add(track);
  2034. MenuItem mi = sender as MenuItem;
  2035. if ((string)mi.Header == U.T("MenuQueue"))
  2036. MediaManager.Queue(tracks);
  2037. else
  2038. MediaManager.Dequeue(tracks);
  2039. }
  2040. /// <summary>
  2041. /// Invoked when the user clicks to watch a track on YouTube
  2042. /// in the track list's context menu
  2043. /// </summary>
  2044. /// <param name="sender">The sender of the event</param>
  2045. /// <param name="e">The event data</param>
  2046. private void listMenuWatchOnYouTube_Click(object sender, RoutedEventArgs e)
  2047. {
  2048. if (GetCurrentTrackList().SelectedItems.Count > 0)
  2049. {
  2050. List<TrackData> tracks = new List<TrackData>();
  2051. foreach (TrackData t in GetCurrentTrackList().SelectedItems)
  2052. if (YouTubeManager.IsYouTube(t))
  2053. tracks.Add(t);
  2054. foreach (TrackData track in tracks)
  2055. {
  2056. string vid = track.Path.Substring(10);
  2057. MediaManager.Pause();
  2058. int autoplay = tracks.Count > 0 && tracks.IndexOf(track) > 0 ? 0 : 1;
  2059. System.Diagnostics.Process.Start(String.Format("http://www.youtube.com/watch?v={0}&autoplay={1}&feature=stoffi", vid, autoplay));
  2060. }
  2061. }
  2062. }
  2063. /// <summary>
  2064. /// Invoked when the user clicks to share a YouTube track
  2065. /// in the track list's context menu
  2066. /// </summary>
  2067. /// <param name="sender">The sender of the event</param>
  2068. /// <param name="e">The event data</param>
  2069. private void listMenuShareSong_Click(object sender, RoutedEventArgs e)
  2070. {
  2071. if (GetCurrentTrackList().SelectedItems.Count > 0)
  2072. {
  2073. List<TrackData> tracks = new List<TrackData>();
  2074. foreach (TrackData t in GetCurrentTrackList().SelectedItems)
  2075. if (YouTubeManager.IsYouTube(t))
  2076. tracks.Add(t);
  2077. foreach (TrackData track in tracks)
  2078. {
  2079. ServiceManager.ShareSong(track);
  2080. }
  2081. }
  2082. }
  2083. /// <summary>
  2084. ///
  2085. /// </summary>
  2086. /// <param name="sender"></param>
  2087. /// <param name="e"></param>
  2088. private void KListener_KeyDown(object sender, RawKeyEventArgs e)
  2089. {
  2090. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() { KeyPressed(e.key, e.key, true); }));
  2091. }
  2092. /// <summary>
  2093. ///
  2094. /// </summary>
  2095. /// <param name="sender"></param>
  2096. /// <param name="e"></param>
  2097. private void KListener_KeyUp(object sender, RawKeyEventArgs e)
  2098. {
  2099. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() { KeyReleased(e.key, e.key); }));
  2100. }
  2101. /// <summary>
  2102. ///
  2103. /// </summary>
  2104. /// <param name="sender"></param>
  2105. /// <param name="e"></param>
  2106. public void NavigationPlaylist_KeyDown(object sender, KeyEventArgs e)
  2107. {
  2108. if (e.Key == Key.F2)
  2109. NavigationPane.RenamePlaylist_Clicked(sender, null);
  2110. }
  2111. /// <summary>
  2112. ///
  2113. /// </summary>
  2114. /// <param name="sender"></param>
  2115. /// <param name="e"></param>
  2116. public void OpenPlaylist_Clicked(object sender, RoutedEventArgs e)
  2117. {
  2118. Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
  2119. dialog.Title = "Open Playlist";
  2120. dialog.DefaultExt = ".pls";
  2121. dialog.Filter = "Playlists (.pls)|*.pls|Playlists (.m3u)|*.m3u";
  2122. bool result = (bool)dialog.ShowDialog();
  2123. if (result == true)
  2124. PlaylistManager.LoadPlaylist(dialog.FileName);
  2125. }
  2126. /// <summary>
  2127. ///
  2128. /// </summary>
  2129. /// <param name="key"></param>
  2130. /// <param name="sysKey"></param>
  2131. private void KeyReleased(Key key, Key sysKey)
  2132. {
  2133. if (!U.ListenForShortcut) return;
  2134. if (key == Key.System && (sysKey == Key.LeftAlt || sysKey == Key.RightAlt || sysKey == Key.LeftCtrl))
  2135. {
  2136. if (currentPressedKeys.Contains(sysKey)) currentPressedKeys.Remove(sysKey);
  2137. }
  2138. else if (key == Key.RightShift)
  2139. {
  2140. if (currentPressedKeys.Contains(Key.LeftShift)) currentPressedKeys.Remove(Key.LeftShift);
  2141. }
  2142. else
  2143. {
  2144. if (currentPressedKeys.Contains(key)) currentPressedKeys.Remove(key);
  2145. }
  2146. }
  2147. /// <summary>
  2148. ///
  2149. /// </summary>
  2150. /// <param name="key"></param>
  2151. /// <param name="sysKey"></param>
  2152. /// <param name="global"></param>
  2153. /// <returns></returns>
  2154. private bool KeyPressed(Key key, Key sysKey, bool global = false)
  2155. {
  2156. // catch media keys
  2157. switch (key)
  2158. {
  2159. case Key.MediaPlayPause:
  2160. if (!global && kListener.CheckHandlers()) return false;
  2161. PlayPause();
  2162. return true;
  2163. case Key.MediaStop:
  2164. MediaManager.Pause();
  2165. return true;
  2166. case Key.MediaNextTrack:
  2167. if (!global && kListener.CheckHandlers()) return false;
  2168. MediaManager.Next(true);
  2169. return true;
  2170. case Key.MediaPreviousTrack:
  2171. if (!global && kListener.CheckHandlers()) return false;
  2172. MediaManager.Previous();
  2173. return true;
  2174. default:
  2175. break;
  2176. }
  2177. // are we listening?
  2178. if (!U.ListenForShortcut) return false;
  2179. switch (key)
  2180. {
  2181. // convert right shift to left shift
  2182. case Key.RightShift:
  2183. if (!currentPressedKeys.Contains(Key.LeftShift)) currentPressedKeys.Add(Key.LeftShift);
  2184. return false;
  2185. // catch modifier keys
  2186. case Key.LeftShift:
  2187. case Key.LeftCtrl:
  2188. case Key.LeftAlt:
  2189. case Key.LWin:
  2190. case Key.RightCtrl:
  2191. case Key.RightAlt:
  2192. case Key.RWin:
  2193. if (!currentPressedKeys.Contains(key)) currentPressedKeys.Add(key);
  2194. return false;
  2195. // catch alt/left ctrl key when disguised as system key
  2196. case Key.System:
  2197. if (sysKey == Key.LeftAlt || sysKey == Key.RightAlt || sysKey == Key.LeftCtrl)
  2198. {
  2199. if (!currentPressedKeys.Contains(sysKey)) currentPressedKeys.Add(sysKey);
  2200. return false;
  2201. }
  2202. break;
  2203. // ignore these keys
  2204. case Key.None:
  2205. case Key.DeadCharProcessed:
  2206. return false;
  2207. default:
  2208. break;
  2209. }
  2210. // turn key combination into string
  2211. // TODO: convert Oem keys to nice strings
  2212. String currentKey = key == Key.System ? KeyToString(sysKey) : KeyToString(key);
  2213. String txt = GetModifiersAsText(currentPressedKeys);
  2214. if (txt.Length > 0) txt += "+" + currentKey;
  2215. else txt = currentKey;
  2216. // find matching shortcut
  2217. KeyboardShortcut sc = SettingsManager.GetKeyboardShortcut(SettingsManager.GetCurrentShortcutProfile(), txt);
  2218. // hardcoded shortcuts
  2219. if (!global)
  2220. {
  2221. if (txt == "Ctrl+A")
  2222. {
  2223. ViewDetails tl = GetCurrentTrackList();
  2224. if (tl != null && tl.IsVisible)
  2225. {
  2226. tl.SelectAll();
  2227. tl.Focus();
  2228. }
  2229. }
  2230. }
  2231. if (sc == null) return false;
  2232. // skip if we received a global event but shortcut is not set to global
  2233. // and prevent the shortcut from being executed twice if set to global
  2234. if (sc.IsGlobal != global && kListener.CheckHandlers()) return false;
  2235. // execute command
  2236. if (sc.Category == "Application")
  2237. {
  2238. if (sc.Name == "Add track")
  2239. {
  2240. currentPressedKeys.Clear();
  2241. AddFile_Clicked(null, null);
  2242. }
  2243. else if (sc.Name == "Add folder")
  2244. {
  2245. currentPressedKeys.Clear();
  2246. AddFolder_Clicked(null, null);
  2247. }
  2248. else if (sc.Name == "Open playlist")
  2249. {
  2250. currentPressedKeys.Clear();
  2251. OpenPlaylist_Clicked(null, null);
  2252. }
  2253. else if (sc.Name == "Help")
  2254. {
  2255. currentPressedKeys.Clear();
  2256. Help_Clicked(null, null);
  2257. }
  2258. else if (sc.Name == "Minimize")
  2259. {
  2260. currentPressedKeys.Clear();
  2261. Hide_Clicked(null, null);
  2262. }
  2263. else if (sc.Name == "Restore")
  2264. {
  2265. currentPressedKeys.Clear();
  2266. TaskbarClicked(null, null);
  2267. }
  2268. else if (sc.Name == "Close")
  2269. Close_Clicked(null, null);
  2270. }
  2271. else if (sc.Category == "MainWindow")
  2272. {
  2273. if (sc.Name == "Library")
  2274. {
  2275. NavigationPane.SwitchNavigation("Files");
  2276. }
  2277. if (sc.Name == "Now playing")
  2278. {
  2279. NavigationPane.SwitchNavigation("NowPlaying");
  2280. }
  2281. else if (sc.Name == "Queue")
  2282. {
  2283. NavigationPane.SwitchNavigation("Queue");
  2284. }
  2285. else if (sc.Name == "History")
  2286. {
  2287. NavigationPane.SwitchNavigation("History");
  2288. }
  2289. else if (sc.Name == "Playlists")
  2290. {
  2291. MainContainer.Children.Remove(ControlPanel);
  2292. MusicPanel.Visibility = System.Windows.Visibility.Visible;
  2293. PlaybackControls.Search.Box.IsEnabled = true;
  2294. NavigationPane.Playlists.Focus();
  2295. }
  2296. else if (sc.Name == "Create playlist")
  2297. {
  2298. MainContainer.Children.Remove(ControlPanel);
  2299. MusicPanel.Visibility = System.Windows.Visibility.Visible;
  2300. PlaybackControls.Search.Box.IsEnabled = true;
  2301. NavigationPane.CreateNewPlaylist.Focus();
  2302. }
  2303. else if (sc.Name == "Tracklist")
  2304. {
  2305. MainContainer.Children.Remove(ControlPanel);
  2306. MusicPanel.Visibility = System.Windows.Visibility.Visible;
  2307. PlaybackControls.Search.Box.IsEnabled = true;
  2308. GetCurrentTrackList().Focus();
  2309. }
  2310. else if (sc.Name == "Search")
  2311. {
  2312. currentPressedKeys.Clear();
  2313. PlaybackControls.Search.Box.Focus();
  2314. }
  2315. else if (sc.Name == "General preferences")
  2316. {
  2317. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2318. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2319. PlaybackControls.Search.Box.IsEnabled = false;
  2320. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.General);
  2321. }
  2322. else if (sc.Name == "Library sources")
  2323. {
  2324. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2325. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2326. PlaybackControls.Search.Box.IsEnabled = false;
  2327. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.Sources);
  2328. }
  2329. else if (sc.Name == "Services")
  2330. {
  2331. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2332. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2333. PlaybackControls.Search.Box.IsEnabled = false;
  2334. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.Services);
  2335. }
  2336. else if (sc.Name == "Keyboard shortcuts")
  2337. {
  2338. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2339. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2340. PlaybackControls.Search.Box.IsEnabled = false;
  2341. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.Shortcuts);
  2342. }
  2343. else if (sc.Name == "About")
  2344. {
  2345. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2346. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2347. PlaybackControls.Search.Box.IsEnabled = false;
  2348. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.About);
  2349. }
  2350. else if (sc.Name == "Toggle details pane")
  2351. ToggleDetailsPane(null, null);
  2352. else if (sc.Name == "Toggle menu bar")
  2353. ToggleMenuBar(null, null);
  2354. }
  2355. else if (sc.Category == "MediaCommands")
  2356. {
  2357. if (sc.Name == "Play or pause")
  2358. PlayPause();
  2359. else if (sc.Name == "Next")
  2360. MediaManager.Next();
  2361. else if (sc.Name == "Previous")
  2362. MediaManager.Previous();
  2363. else if (sc.Name == "Increase volume")
  2364. PlaybackControls.VolumeSlide.Value += 0.5;
  2365. else if (sc.Name == "Decrease volume")
  2366. PlaybackControls.VolumeSlide.Value -= 0.5;
  2367. else if (sc.Name == "Seek forward")
  2368. PlaybackControls.SongProgress.Value += PlaybackControls.SongProgress.Maximum / 50;
  2369. else if (sc.Name == "Seek backward")
  2370. PlaybackControls.SongProgress.Value -= PlaybackControls.SongProgress.Maximum / 50;
  2371. else if (sc.Name == "Toggle shuffle")
  2372. PlaybackControls.Shuffle_Click(null, null);
  2373. else if (sc.Name == "Toggle repeat")
  2374. PlaybackControls.Repeat_Click(null, null);
  2375. else if (sc.Name == "Add bookmark")
  2376. {
  2377. double pos = MediaManager.CreateBookmark();
  2378. if (pos >= 0)
  2379. PlaybackControls.AddBookmark(pos);
  2380. }
  2381. else if (sc.Name == "Jump to first bookmark")
  2382. MediaManager.JumpToFirstBookmark();
  2383. else if (sc.Name == "Jump to last bookmark")
  2384. MediaManager.JumpToLastBookmark();
  2385. else if (sc.Name == "Jump to previous bookmark")
  2386. MediaManager.JumpToPreviousBookmark();
  2387. else if (sc.Name == "Jump to next bookmark")
  2388. MediaManager.JumpToNextBookmark();
  2389. else if (sc.Name.StartsWith("Jump to bookmark "))
  2390. MediaManager.JumpToBookmark(Convert.ToInt32(sc.Name.Substring(17)));
  2391. else if (sc.Name == "Jump to current track")
  2392. {
  2393. NavigationPane.SwitchNavigation(SettingsManager.CurrentActiveNavigation);
  2394. GetCurrentTrackList().SelectItem(SettingsManager.CurrentTrack);
  2395. }
  2396. }
  2397. else if (sc.Category == "Track")
  2398. {
  2399. ViewDetails tl = GetCurrentTrackList();
  2400. if (tl == null) return false;
  2401. ListViewItem lvi = (ListViewItem)tl.ItemContainerGenerator.ContainerFromItem(tl.SelectedItem);
  2402. if (lvi == null) return false;
  2403. bool focused = tl.IsFocused;
  2404. foreach (object i in tl.SelectedItems)
  2405. if (((ListViewItem)tl.ItemContainerGenerator.ContainerFromItem(i)).IsFocused)
  2406. focused = true;
  2407. if (!focused) return false;
  2408. if (sc.Name == "Queue and dequeue")
  2409. {
  2410. List<TrackData> tracks = new List<TrackData>();
  2411. foreach (TrackData track in GetCurrentTrackList().SelectedItems)
  2412. tracks.Add(track);
  2413. MediaManager.ToggleQueue(tracks);
  2414. }
  2415. else if (sc.Name == "Remove track")
  2416. listMenuRemove_Click(null, null);
  2417. else if (sc.Name == "Play track")
  2418. listMenuPlay_Click(null, null);
  2419. else if (sc.Name == "View information")
  2420. {
  2421. currentPressedKeys.Clear();
  2422. listMenuInfo_Click(null, null);
  2423. }
  2424. }
  2425. return true;
  2426. }
  2427. /// <summary>
  2428. ///
  2429. /// </summary>
  2430. /// <param name="sender"></param>
  2431. /// <param name="e"></param>
  2432. private void TaskbarPlayPause_Clicked(object sender, Microsoft.WindowsAPICodePack.Taskbar.ThumbnailButtonClickedEventArgs e)
  2433. {
  2434. PlayPause();
  2435. }
  2436. /// <summary>
  2437. ///
  2438. /// </summary>
  2439. /// <param name="sender"></param>
  2440. /// <param name="e"></param>
  2441. private void TaskbarNext_Clicked(object sender, Microsoft.WindowsAPICodePack.Taskbar.ThumbnailButtonClickedEventArgs e)
  2442. {
  2443. MediaManager.Next();
  2444. }
  2445. /// <summary>
  2446. ///
  2447. /// </summary>
  2448. /// <param name="sender"></param>
  2449. /// <param name="e"></param>
  2450. private void TaskbarPrevious_Clicked(object sender, Microsoft.WindowsAPICodePack.Taskbar.ThumbnailButtonClickedEventArgs e)
  2451. {
  2452. MediaManager.Previous();
  2453. }
  2454. /// <summary>
  2455. ///
  2456. /// </summary>
  2457. /// <param name="sender"></param>
  2458. /// <param name="e"></param>
  2459. private void Equalizer_Clicked(object sender, RoutedEventArgs e)
  2460. {
  2461. if (equalizer == null || !equalizer.Activate())
  2462. {
  2463. equalizer = new Equalizer();
  2464. double l = SettingsManager.EqualizerLeft;
  2465. double t = SettingsManager.EqualizerTop;
  2466. if (l < 0)
  2467. l = (System.Windows.SystemParameters.PrimaryScreenWidth / 2) - (equalizer.Width / 2);
  2468. if (t < 0)
  2469. t = (System.Windows.SystemParameters.PrimaryScreenHeight / 2) - (equalizer.Height / 2);
  2470. equalizer.Owner = App.Current.MainWindow;
  2471. equalizer.Show();
  2472. equalizer.Left = l;
  2473. equalizer.Top = t;
  2474. }
  2475. else
  2476. equalizer.Activate();
  2477. }
  2478. /// <summary>
  2479. ///
  2480. /// </summary>
  2481. /// <param name="sender"></param>
  2482. /// <param name="e"></param>
  2483. private void Preferences_Clicked(object sender, RoutedEventArgs e)
  2484. {
  2485. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2486. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2487. PlaybackControls.Search.Box.IsEnabled = false;
  2488. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.General);
  2489. }
  2490. /// <summary>
  2491. /// Invoked when the user clicks "Import"
  2492. /// </summary>
  2493. /// <param name="sender">The sender of the event</param>
  2494. /// <param name="e">The event data</param>
  2495. private void Importer_Clicked(object sender, RoutedEventArgs e)
  2496. {
  2497. Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
  2498. dialog.Title = "Import Configuration";
  2499. dialog.DefaultExt = ".scf";
  2500. dialog.Filter = "Stoffi Configuration File (*.scf)|*.scf";
  2501. bool result = (bool)dialog.ShowDialog();
  2502. if (result == true)
  2503. SettingsManager.Import(dialog.FileName);
  2504. }
  2505. /// <summary>
  2506. /// Invoked when the user clicks "Export"
  2507. /// </summary>
  2508. /// <param name="sender">The sender of the event</param>
  2509. /// <param name="e">The event data</param>
  2510. private void Exporter_Clicked(object sender, RoutedEventArgs e)
  2511. {
  2512. Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
  2513. dialog.Title = "Export Configuration";
  2514. dialog.DefaultExt = ".scf";
  2515. dialog.Filter = "Stoffi Configuration File (*.scf)|*.scf";
  2516. bool result = (bool)dialog.ShowDialog();
  2517. if (result == true)
  2518. {
  2519. SettingsManager.Export(dialog.FileName);
  2520. }
  2521. }
  2522. /// <summary>
  2523. /// Invoked when the user clicks "Generate playlist"
  2524. /// </summary>
  2525. /// <param name="sender">The sender of the event</param>
  2526. /// <param name="e">The event data</param>
  2527. private void GeneratePlaylist_Clicked(object sender, RoutedEventArgs e)
  2528. {
  2529. GeneratePlaylist d = new GeneratePlaylist();
  2530. d.Show();
  2531. }
  2532. /// <summary>
  2533. ///
  2534. /// </summary>
  2535. /// <param name="sender"></param>
  2536. /// <param name="e"></param>
  2537. private void About_Clicked(object sender, RoutedEventArgs e)
  2538. {
  2539. MusicPanel.Visibility = System.Windows.Visibility.Collapsed;
  2540. if (!MainContainer.Children.Contains(ControlPanel)) MainContainer.Children.Add(ControlPanel);
  2541. PlaybackControls.Search.Box.IsEnabled = false;
  2542. ControlPanel.SwitchTab(Stoffi.ControlPanel.Tab.About);
  2543. }
  2544. /// <summary>
  2545. ///
  2546. /// </summary>
  2547. /// <param name="sender"></param>
  2548. /// <param name="e"></param>
  2549. private void Help_Clicked(object sender, RoutedEventArgs e)
  2550. {
  2551. System.Diagnostics.Process.Start("http://www.stoffiplayer.com/help?ref=stoffi");
  2552. }
  2553. /// <summary>
  2554. /// Invoked when the user clicks "Add" in the toolbar
  2555. /// </summary>
  2556. /// <param name="sender">The sender of the event</param>
  2557. /// <param name="e">The event data</param>
  2558. private void Add_Clicked(object sender, RoutedEventArgs e)
  2559. {
  2560. addMenu.PlacementTarget = AddButton;
  2561. addMenu.IsOpen = !addMenu.IsOpen;
  2562. }
  2563. /// <summary>
  2564. /// Invoked when the user clicks "Show" in the toolbar
  2565. /// </summary>
  2566. /// <param name="sender">The sender of the event</param>
  2567. /// <param name="e">The event data</param>
  2568. private void Show_Clicked(object sender, RoutedEventArgs e)
  2569. {
  2570. showMenu.PlacementTarget = ShowButton;
  2571. showMenu.IsOpen = !showMenu.IsOpen;
  2572. }
  2573. /// <summary>
  2574. /// Invoked when the user clicks "Tools" in the toolbar
  2575. /// </summary>
  2576. /// <param name="sender">The sender of the event</param>
  2577. /// <param name="e">The event data</param>
  2578. private void Tools_Clicked(object sender, RoutedEventArgs e)
  2579. {
  2580. toolsMenu.PlacementTarget = ToolsButton;
  2581. toolsMenu.IsOpen = !toolsMenu.IsOpen;
  2582. }
  2583. /// <summary>
  2584. ///
  2585. /// </summary>
  2586. /// <param name="sender"></param>
  2587. /// <param name="e"></param>
  2588. public void AddFile_Clicked(object sender, RoutedEventArgs e)
  2589. {
  2590. Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialog dialog = new Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialog();
  2591. Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult result = dialog.ShowDialog();
  2592. if (result == Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult.OK)
  2593. {
  2594. if (FilesystemManager.PathIsAdded(dialog.FileName))
  2595. MessageBox.Show(
  2596. U.T("MessageAlreadyAddedSource", "Message"),
  2597. U.T("MessageAlreadyAddedSource", "Title"),
  2598. MessageBoxButton.OK, MessageBoxImage.Information);
  2599. else
  2600. {
  2601. SourceData s = new SourceData();
  2602. s.Data = dialog.FileName;
  2603. s.HumanType = U.T("SourcesTypeFile");
  2604. s.Type = SourceType.File;
  2605. s.Include = true;
  2606. s.Icon = "pack://application:,,,/GUI/Images/Icons/FileAudio.ico";
  2607. FilesystemManager.AddSource(s);
  2608. }
  2609. }
  2610. }
  2611. /// <summary>
  2612. ///
  2613. /// </summary>
  2614. /// <param name="sender"></param>
  2615. /// <param name="e"></param>
  2616. public void AddFolder_Clicked(object sender, RoutedEventArgs e)
  2617. {
  2618. System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
  2619. dialog.SelectedPath = dialogPath;
  2620. System.Windows.Forms.DialogResult result = dialog.ShowDialog();
  2621. if (result == System.Windows.Forms.DialogResult.OK)
  2622. {
  2623. if (FilesystemManager.PathIsAdded(dialog.SelectedPath))
  2624. MessageBox.Show(
  2625. U.T("MessageAlreadyAddedSource", "Message"),
  2626. U.T("MessageAlreadyAddedSource", "Title"),
  2627. MessageBoxButton.OK, MessageBoxImage.Information);
  2628. else
  2629. {
  2630. SourceData s = new SourceData();
  2631. s.Data = dialog.SelectedPath;
  2632. s.HumanType = U.T("SourcesTypeFolder");
  2633. s.Type = SourceType.Folder;
  2634. s.Include = true;
  2635. s.Icon = "pack://application:,,,/GUI/Images/Icons/Folder.ico";
  2636. FilesystemManager.AddSource(s);
  2637. }
  2638. }
  2639. dialogPath = dialog.SelectedPath;
  2640. }
  2641. /// <summary>
  2642. ///
  2643. /// </summary>
  2644. /// <param name="sender"></param>
  2645. /// <param name="e"></param>
  2646. public void IgnoreFile_Clicked(object sender, RoutedEventArgs e)
  2647. {
  2648. Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialog dialog = new Microsoft.WindowsAPICodePack.Dialogs.CommonOpenFileDialog();
  2649. Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult result = dialog.ShowDialog();
  2650. if (result == Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogResult.OK)
  2651. {
  2652. if (FilesystemManager.PathIsIgnored(dialog.FileName))
  2653. MessageBox.Show(
  2654. U.T("MessageAlreadyAddedSource", "Message"),
  2655. U.T("MessageAlreadyAddedSource", "Title"),
  2656. MessageBoxButton.OK, MessageBoxImage.Information);
  2657. else
  2658. {
  2659. SourceData s = new SourceData();
  2660. s.Data = dialog.FileName;
  2661. s.HumanType = U.T("SourcesTypeFile");
  2662. s.Type = SourceType.File;
  2663. s.Ignore = true;
  2664. s.Icon = "pack://application:,,,/GUI/Images/Icons/FileAudio.ico";
  2665. FilesystemManager.AddSource(s);
  2666. }
  2667. }
  2668. }
  2669. /// <summary>
  2670. ///
  2671. /// </summary>
  2672. /// <param name="sender"></param>
  2673. /// <param name="e"></param>
  2674. public void IgnoreFolder_Clicked(object sender, RoutedEventArgs e)
  2675. {
  2676. System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
  2677. dialog.SelectedPath = dialogPath;
  2678. System.Windows.Forms.DialogResult result = dialog.ShowDialog();
  2679. if (result == System.Windows.Forms.DialogResult.OK)
  2680. {
  2681. if (FilesystemManager.PathIsIgnored(dialog.SelectedPath))
  2682. MessageBox.Show(
  2683. U.T("MessageAlreadyAddedSource", "Message"),
  2684. U.T("MessageAlreadyAddedSource", "Title"),
  2685. MessageBoxButton.OK, MessageBoxImage.Information);
  2686. else
  2687. {
  2688. SourceData s = new SourceData();
  2689. s.Data = dialog.SelectedPath;
  2690. s.HumanType = U.T("SourcesTypeFolder");
  2691. s.Type = SourceType.Folder;
  2692. s.Ignore = true;
  2693. s.Icon = "pack://application:,,,/GUI/Images/Icons/Folder.ico";
  2694. FilesystemManager.AddSource(s);
  2695. }
  2696. }
  2697. dialogPath = dialog.SelectedPath;
  2698. }
  2699. /// <summary>
  2700. ///
  2701. /// </summary>
  2702. /// <param name="sender"></param>
  2703. /// <param name="e"></param>
  2704. private void Hide_Clicked(object sender, RoutedEventArgs e)
  2705. {
  2706. WindowState = System.Windows.WindowState.Minimized;
  2707. }
  2708. /// <summary>
  2709. ///
  2710. /// </summary>
  2711. /// <param name="sender"></param>
  2712. /// <param name="e"></param>
  2713. private void Close_Clicked(object sender, RoutedEventArgs e)
  2714. {
  2715. Close();
  2716. }
  2717. /// <summary>
  2718. ///
  2719. /// </summary>
  2720. /// <param name="sender"></param>
  2721. /// <param name="e"></param>
  2722. private void RemoveBookmarkClicked(object sender, EventArgs e)
  2723. {
  2724. Bookmark bm = sender as Bookmark;
  2725. if (bm != null)
  2726. {
  2727. MediaManager.RemoveBookmark(bm.Position);
  2728. PlaybackControls.RemoveBookmark(bm.Position);
  2729. }
  2730. }
  2731. /// <summary>
  2732. ///
  2733. /// </summary>
  2734. /// <param name="sender"></param>
  2735. /// <param name="e"></param>
  2736. private void ToggleDetailsPane(object sender, RoutedEventArgs e)
  2737. {
  2738. SettingsManager.DetailsPaneVisible = !SettingsManager.DetailsPaneVisible;
  2739. }
  2740. /// <summary>
  2741. ///
  2742. /// </summary>
  2743. /// <param name="sender"></param>
  2744. /// <param name="e"></param>
  2745. private void ToggleMenuBar(object sender, RoutedEventArgs e)
  2746. {
  2747. if (SettingsManager.MenuBarVisibile)
  2748. {
  2749. showMenuMenuBar.IsChecked = false;
  2750. MenuItemViewMenuBar.IsChecked = false;
  2751. }
  2752. else
  2753. {
  2754. showMenuMenuBar.IsChecked = true;
  2755. MenuItemViewMenuBar.IsChecked = true;
  2756. }
  2757. SettingsManager.MenuBarVisibile = !SettingsManager.MenuBarVisibile;
  2758. MenuBar.Visibility = SettingsManager.MenuBarVisibile ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  2759. }
  2760. /// <summary>
  2761. ///
  2762. /// </summary>
  2763. /// <param name="sender"></param>
  2764. /// <param name="e"></param>
  2765. private void ChangeSize(object sender, SizeChangedEventArgs e)
  2766. {
  2767. SettingsManager.WinWidth = ActualWidth;
  2768. SettingsManager.WinHeight = ActualHeight;
  2769. PlaybackControls.Compress(ActualWidth);
  2770. }
  2771. /// <summary>
  2772. ///
  2773. /// </summary>
  2774. /// <param name="sender"></param>
  2775. /// <param name="e"></param>
  2776. private void ChangePos(object sender, EventArgs e)
  2777. {
  2778. SettingsManager.WinTop = Top;
  2779. SettingsManager.WinLeft = Left;
  2780. }
  2781. /// <summary>
  2782. ///
  2783. /// </summary>
  2784. /// <param name="sender"></param>
  2785. /// <param name="e"></param>
  2786. private void TaskbarClicked(object sender, RoutedEventArgs e)
  2787. {
  2788. if (WindowState != System.Windows.WindowState.Minimized)
  2789. {
  2790. oldWindowState = WindowState;
  2791. WindowState = System.Windows.WindowState.Minimized;
  2792. }
  2793. else
  2794. {
  2795. WindowState = oldWindowState;
  2796. Activate();
  2797. }
  2798. }
  2799. /// <summary>
  2800. ///
  2801. /// </summary>
  2802. /// <param name="sender"></param>
  2803. /// <param name="e"></param>
  2804. private void TrayShow_Clicked(object sender, RoutedEventArgs e)
  2805. {
  2806. if (WindowState == System.Windows.WindowState.Minimized)
  2807. WindowState = oldWindowState;
  2808. Activate();
  2809. }
  2810. /// <summary>
  2811. ///
  2812. /// </summary>
  2813. /// <param name="sender"></param>
  2814. /// <param name="e"></param>
  2815. private void TrayPlayPause_Clicked(object sender, RoutedEventArgs e)
  2816. {
  2817. PlayPause();
  2818. }
  2819. /// <summary>
  2820. ///
  2821. /// </summary>
  2822. /// <param name="sender"></param>
  2823. /// <param name="e"></param>
  2824. private void TrayNext_Clicked(object sender, RoutedEventArgs e)
  2825. {
  2826. MediaManager.Next();
  2827. }
  2828. /// <summary>
  2829. ///
  2830. /// </summary>
  2831. /// <param name="sender"></param>
  2832. /// <param name="e"></param>
  2833. private void TrayPrevious_Clicked(object sender, RoutedEventArgs e)
  2834. {
  2835. MediaManager.Previous();
  2836. }
  2837. /// <summary>
  2838. ///
  2839. /// </summary>
  2840. /// <param name="sender"></param>
  2841. /// <param name="e"></param>
  2842. private void TrayExit_Clicked(object sender, RoutedEventArgs e)
  2843. {
  2844. trayMenu.Visibility = System.Windows.Visibility.Hidden;
  2845. Close_Clicked(sender, e);
  2846. }
  2847. /// <summary>
  2848. /// Updates the scan indicator
  2849. /// </summary>
  2850. /// <param name="sender">The sender of the event</param>
  2851. /// <param name="e">The event data</param>
  2852. private void FilesystemManager_ProgressChanged(object sender, ProgressChangedEventArgs e)
  2853. {
  2854. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  2855. {
  2856. switch ((string)e.UserState)
  2857. {
  2858. case "start":
  2859. ScanProgressBar.Value = 0;
  2860. ScanProgressBar.IsIndeterminate = true;
  2861. ScanProgress.Visibility = System.Windows.Visibility.Visible;
  2862. break;
  2863. case "progress":
  2864. ScanProgressBar.IsIndeterminate = false;
  2865. ScanProgressBar.Value = e.ProgressPercentage;
  2866. break;
  2867. case "done":
  2868. ScanProgress.Visibility = System.Windows.Visibility.Collapsed;
  2869. break;
  2870. }
  2871. }));
  2872. }
  2873. /// <summary>
  2874. ///
  2875. /// </summary>
  2876. /// <param name="sender"></param>
  2877. /// <param name="e"></param>
  2878. private void Window_Closing(object sender, CancelEventArgs e)
  2879. {
  2880. if (UpgradeManager.InProgress)
  2881. {
  2882. if (MessageBox.Show(U.T("MessageUpgradeInProgress", "Message"),
  2883. U.T("MessageUpgradeInProgress", "Title"),
  2884. MessageBoxButton.YesNo,
  2885. MessageBoxImage.Warning,
  2886. MessageBoxResult.No) == MessageBoxResult.No)
  2887. {
  2888. e.Cancel = true;
  2889. return;
  2890. }
  2891. }
  2892. kListener.Dispose();
  2893. CloseProgress cp = new CloseProgress();
  2894. try
  2895. {
  2896. cp.Owner = this;
  2897. }
  2898. catch { }
  2899. cp.ShowDialog();
  2900. if (doRestart)
  2901. System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
  2902. }
  2903. /// <summary>
  2904. /// Invoked when the window become active
  2905. /// </summary>
  2906. /// <param name="sender">The sender of the event</param>
  2907. /// <param name="e">The event data</param>
  2908. private void Window_Activated(object sender, EventArgs e)
  2909. {
  2910. RefreshGlassEffect();
  2911. }
  2912. /// <summary>
  2913. /// Invoked when the window becomes inactive
  2914. /// </summary>
  2915. /// <param name="sender">The sender of the event</param>
  2916. /// <param name="e">The event data</param>
  2917. private void Window_Deactivated(object sender, EventArgs e)
  2918. {
  2919. if (!glassEffect && System.Windows.Forms.VisualStyles.VisualStyleInformation.DisplayName != "")
  2920. Background = SystemColors.GradientInactiveCaptionBrush;
  2921. if (etbInEdit != null)
  2922. {
  2923. etbInEdit.IsInEditMode = false;
  2924. etbInEdit = null;
  2925. }
  2926. }
  2927. /// <summary>
  2928. /// Invoked when the user moves the mouse over the window
  2929. /// </summary>
  2930. /// <param name="sender">The sender of the event</param>
  2931. /// <param name="e">The event data</param>
  2932. private void Window_MouseMove(object sender, MouseEventArgs e)
  2933. {
  2934. //if (GetCurrentTrackList() != null)
  2935. // GetCurrentTrackList().ClearDropTarget();
  2936. }
  2937. /// <summary>
  2938. /// Invoked when the window changes state
  2939. /// </summary>
  2940. /// <param name="sender">The sender of the event</param>
  2941. /// <param name="e">The event data</param>
  2942. private void Window_StateChanged(object sender, EventArgs e)
  2943. {
  2944. oldWindowState = currentWindowState;
  2945. currentWindowState = WindowState;
  2946. SettingsManager.WinState = WindowState.ToString();
  2947. if (SettingsManager.MinimizeToTray)
  2948. ShowInTaskbar = WindowState != System.Windows.WindowState.Minimized;
  2949. }
  2950. /// <summary>
  2951. /// Invoked when a key is pressed
  2952. /// </summary>
  2953. /// <param name="sender">The sender of the event</param>
  2954. /// <param name="e">The event data</param>
  2955. private void Window_KeyDown(object sender, KeyEventArgs e)
  2956. {
  2957. if (KeyPressed(e.Key, e.SystemKey))
  2958. e.Handled = true;
  2959. }
  2960. /// <summary>
  2961. /// Invoked when a key is released
  2962. /// </summary>
  2963. /// <param name="sender">The sender of the event</param>
  2964. /// <param name="e">The event data</param>
  2965. private void Window_KeyUp(object sender, KeyEventArgs e)
  2966. {
  2967. KeyReleased(e.Key, e.SystemKey);
  2968. }
  2969. /// <summary>
  2970. /// Invoked when the left mouse button is pressed
  2971. /// </summary>
  2972. /// <param name="sender">The sender of the event</param>
  2973. /// <param name="e">The event data</param>
  2974. private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  2975. {
  2976. if (etbInEdit != null && etbInEdit.IsInEditMode)
  2977. {
  2978. EditableTextBlock etb = ViewDetailsUtilities.TryFindParent<EditableTextBlock>((DependencyObject)e.OriginalSource);
  2979. if (etb == null || etb != etbInEdit)
  2980. {
  2981. etbInEdit.Done();
  2982. etbInEdit = null;
  2983. }
  2984. }
  2985. }
  2986. /// <summary>
  2987. /// Event handler that saves the changed width of the navigation pane
  2988. /// </summary>
  2989. /// <param name="sender">The sender of the event</param>
  2990. /// <param name="e">The event data</param>
  2991. private void VerticalSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
  2992. {
  2993. SettingsManager.NavigationPaneWidth = NavigationColumn.Width.Value;
  2994. }
  2995. /// <summary>
  2996. /// Event handler that saves the changed height of the details pane
  2997. /// </summary>
  2998. /// <param name="sender">The sender of the event</param>
  2999. /// <param name="e">The event data</param>
  3000. private void HorizontalSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
  3001. {
  3002. SettingsManager.DetailsPaneHeight = DetailsRow.Height.Value;
  3003. }
  3004. /// <summary>
  3005. /// Prevents the size of DetailsPane from become too large
  3006. /// because of the behaviour of the GridSplitter.
  3007. /// </summary>
  3008. /// <param name="sender">The sender of the event</param>
  3009. /// <param name="e">The event data</param>
  3010. private void DetailsPane_SizeChanged(object sender, SizeChangedEventArgs e)
  3011. {
  3012. double a = MainFrame.ActualHeight;
  3013. double b = RootPanel.ActualHeight;
  3014. double total = MainFrame.ActualHeight;
  3015. double occupied = TopToolbar.ActualHeight + MusicPane.ActualHeight;
  3016. double free = total - occupied;
  3017. if (DetailsRow.Height.Value > free)
  3018. DetailsRow.Height = new GridLength(free);
  3019. }
  3020. /// <summary>
  3021. /// Invoked when a field is edited inside the details pane.
  3022. /// Will update the file tags.
  3023. /// </summary>
  3024. /// <param name="sender">The sender of the event</param>
  3025. /// <param name="e">The event data</param>
  3026. private void DetailsPane_FieldEdited(object sender, FieldEditedEventArgs e)
  3027. {
  3028. switch (e.Field)
  3029. {
  3030. case "Artist":
  3031. currentlySelectedTrack.Artist = e.Value;
  3032. break;
  3033. case "Album":
  3034. currentlySelectedTrack.Album = e.Value;
  3035. break;
  3036. case "Title":
  3037. currentlySelectedTrack.Title = e.Value;
  3038. break;
  3039. case "Genre":
  3040. currentlySelectedTrack.Genre = e.Value;
  3041. break;
  3042. case "Year":
  3043. currentlySelectedTrack.Year = Convert.ToUInt32(e.Value);
  3044. break;
  3045. }
  3046. try
  3047. {
  3048. FilesystemManager.SaveTrack(currentlySelectedTrack);
  3049. DetailsPane.SetField(e.Field, e.Value);
  3050. }
  3051. catch (Exception exc)
  3052. {
  3053. MessageBox.Show("Error saving: " + currentlySelectedTrack.Path + "\n\n" + exc.Message, "Could Not Write Tag", MessageBoxButton.OK, MessageBoxImage.Error);
  3054. }
  3055. }
  3056. /// <summary>
  3057. ///
  3058. /// </summary>
  3059. /// <param name="sender"></param>
  3060. /// <param name="e"></param>
  3061. private void FilesystemManager_SourceModified(object sender, SourceModifiedEventArgs e)
  3062. {
  3063. sourceModifiedDelay.Stop();
  3064. sourceModifiedCallback = e.Callback;
  3065. sourceModifiedCallbackParams = e.CallbackParams;
  3066. if (sourceModifiedTracks.ContainsKey(e.Track))
  3067. sourceModifiedTracks[e.Track] = e.ModificationType;
  3068. else
  3069. sourceModifiedTracks.Add(e.Track, e.ModificationType);
  3070. sourceModifiedDelay.Start();
  3071. }
  3072. /// <summary>
  3073. /// Invoked when a source has been added
  3074. /// </summary>
  3075. /// <param name="sender">The sender of the event</param>
  3076. /// <param name="e">The event data</param>
  3077. private void FilesystemManager_SourceAdded(object sender, SourcesModifiedEventArgs e)
  3078. {
  3079. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  3080. {
  3081. SettingsManager.Sources.Add(e.Source);
  3082. }));
  3083. }
  3084. /// <summary>
  3085. /// Invoked when a source has been removed
  3086. /// </summary>
  3087. /// <param name="sender">The sender of the event</param>
  3088. /// <param name="e">The event data</param>
  3089. private void FilesystemManager_SourceRemoved(object sender, SourcesModifiedEventArgs e)
  3090. {
  3091. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  3092. {
  3093. SettingsManager.Sources.Remove(e.Source);
  3094. }));
  3095. }
  3096. /// <summary>
  3097. /// Invoked when something happens to a track.
  3098. /// Updates the library/queue/history time and the TrackList(s) of the parent.
  3099. /// </summary>
  3100. /// <param name="sender">Sender of the event</param>
  3101. /// <param name="e">Event arguments</param>
  3102. private void FilesystemManager_TrackModified(object sender, PropertyChangedEventArgs e)
  3103. {
  3104. TrackData track = sender as TrackData;
  3105. if (!pathsThatWasChanged.Contains(track.Path))
  3106. {
  3107. pathsThatWasChanged.Add(track.Path);
  3108. resortDelay.Stop();
  3109. resortDelay.Start();
  3110. }
  3111. if (e.PropertyName != "RawLength") return;
  3112. // update time trackers
  3113. LibraryTime += track.diff;
  3114. if (SettingsManager.QueueTracks.Contains(track))
  3115. QueueTime += track.diff;
  3116. if (SettingsManager.HistoryTracks.Contains(track))
  3117. HistoryTime += track.diff;
  3118. foreach (PlaylistData p in SettingsManager.Playlists)
  3119. if (p.Tracks.Contains(track))
  3120. p.Time += track.diff;
  3121. if (GetCurrentTrackList() != null && GetCurrentTrackList().Items.Contains(track))
  3122. {
  3123. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  3124. {
  3125. if (SettingsManager.CurrentSelectedNavigation == "Files")
  3126. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)LibraryTime));
  3127. else if (SettingsManager.CurrentSelectedNavigation == "History")
  3128. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)HistoryTime));
  3129. else if (SettingsManager.CurrentSelectedNavigation == "Queue")
  3130. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)QueueTime));
  3131. else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  3132. {
  3133. String playlistName = SettingsManager.CurrentSelectedNavigation.Split(new[]{':'},2)[1];
  3134. PlaylistData pl = PlaylistManager.FindPlaylist(playlistName);
  3135. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)pl.Time));
  3136. }
  3137. }));
  3138. }
  3139. }
  3140. /// <summary>
  3141. /// Invoked when a file or folder has been renamed
  3142. /// </summary>
  3143. /// <param name="sender">The sender of the event</param>
  3144. /// <param name="e">The event data</param>
  3145. private void FilesystemManager_PathRenamed(object sender, RenamedEventArgs e)
  3146. {
  3147. foreach (TrackData track in SettingsManager.FileTracks)
  3148. if (track.Path.StartsWith(e.OldName))
  3149. track.Path = track.Path.Replace(e.OldName, e.Name);
  3150. foreach (TrackData track in SettingsManager.HistoryTracks)
  3151. if (track.Path.StartsWith(e.OldName))
  3152. track.Path = track.Path.Replace(e.OldName, e.Name);
  3153. foreach (TrackData track in SettingsManager.QueueTracks)
  3154. if (track.Path.StartsWith(e.OldName))
  3155. track.Path = track.Path.Replace(e.OldName, e.Name);
  3156. foreach (PlaylistData playlist in SettingsManager.Playlists)
  3157. foreach (TrackData track in playlist.Tracks)
  3158. if (track.Path.StartsWith(e.OldName))
  3159. track.Path = track.Path.Replace(e.OldName, e.Name);
  3160. foreach (SourceData src in SettingsManager.Sources)
  3161. if (src.Data.StartsWith(e.OldName))
  3162. src.Data.Replace(e.OldName, e.Name);
  3163. }
  3164. /// <summary>
  3165. /// Invoked when a change is detected in a file
  3166. /// </summary>
  3167. /// <param name="sender">The sender of the event</param>
  3168. /// <param name="e">The event data</param>
  3169. private void FilesystemManager_PathModified(object sender, PathModifiedEventArgs e)
  3170. {
  3171. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  3172. {
  3173. foreach (TrackData track in SettingsManager.FileTracks)
  3174. if (track.Path == e.Path)
  3175. FilesystemManager.UpdateTrack(track);
  3176. foreach (TrackData track in SettingsManager.QueueTracks)
  3177. if (track.Path == e.Path)
  3178. FilesystemManager.UpdateTrack(track);
  3179. foreach (TrackData track in SettingsManager.HistoryTracks)
  3180. if (track.Path == e.Path)
  3181. FilesystemManager.UpdateTrack(track);
  3182. foreach (PlaylistData playlist in SettingsManager.Playlists)
  3183. foreach (TrackData track in playlist.Tracks)
  3184. if (track.Path == e.Path)
  3185. FilesystemManager.UpdateTrack(track);
  3186. }));
  3187. }
  3188. /// <summary>
  3189. /// Invoked when a property of the settings manager changes
  3190. /// </summary>
  3191. /// <param name="sender">The sender of the event</param>
  3192. /// <param name="e">The event data</param>
  3193. private void SettingsManager_PropertyChanged(object sender, PropertyChangedWithValuesEventArgs e)
  3194. {
  3195. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  3196. {
  3197. switch (e.PropertyName)
  3198. {
  3199. case "DetailsPaneHeight":
  3200. DetailsRow.Height = new GridLength(SettingsManager.DetailsPaneHeight);
  3201. break;
  3202. case "DetailsPaneVisible":
  3203. UpdateVisibility("details");
  3204. break;
  3205. case "MenuBarVisible":
  3206. UpdateVisibility("menubar");
  3207. break;
  3208. case "NavigationPaneWidth":
  3209. NavigationColumn.Width = new GridLength(SettingsManager.NavigationPaneWidth);
  3210. break;
  3211. case "Language":
  3212. LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo(SettingsManager.Language);
  3213. UpdateGUIStrings();
  3214. break;
  3215. case "CurrentActiveNavigation":
  3216. ViewDetails vd = GetActiveTrackList();
  3217. if (vd != null) MediaManager.TrackCollection = vd.Items;
  3218. else MediaManager.TrackCollection = FileTracks.Items;
  3219. break;
  3220. case "CurrentTrack":
  3221. if (SettingsManager.CurrentTrack == null)
  3222. {
  3223. NowPlayingContainer.InfoPaneTitle.Text = U.T("PlaybackEmpty");
  3224. NowPlayingContainer.InfoPaneArtist.Text = "";
  3225. }
  3226. else
  3227. {
  3228. NowPlayingContainer.InfoPaneTitle.Text = SettingsManager.CurrentTrack.Title;
  3229. NowPlayingContainer.InfoPaneArtist.Text = SettingsManager.CurrentTrack.Artist;
  3230. }
  3231. break;
  3232. case "MediaState":
  3233. switch (SettingsManager.MediaState)
  3234. {
  3235. case MediaState.Playing:
  3236. if (taskbarPlay != null) taskbarPlay.Icon = Properties.Resources.Pause;
  3237. if (trayMenuPlay != null) trayMenuPlay.Header = "Pause";
  3238. if (jumpTaskPlay != null) jumpTaskPlay.Title = "Pause";
  3239. if (YouTubeManager.IsYouTube(SettingsManager.CurrentTrack))
  3240. {
  3241. MediaManager.Browser.Visibility = System.Windows.Visibility.Visible;
  3242. if (!NowPlayingContainer.Video.Children.Contains(MediaManager.Browser))
  3243. NowPlayingContainer.Video.Children.Add(MediaManager.Browser);
  3244. NowPlayingContainer.NoVideoMessage.Visibility = System.Windows.Visibility.Collapsed;
  3245. }
  3246. else
  3247. {
  3248. MediaManager.Browser.Visibility = System.Windows.Visibility.Collapsed;
  3249. NowPlayingContainer.Video.Children.Remove(MediaManager.Browser);
  3250. NowPlayingContainer.NoVideoMessage.Visibility = System.Windows.Visibility.Visible;
  3251. }
  3252. break;
  3253. case MediaState.Paused:
  3254. case MediaState.Stopped:
  3255. if (taskbarPlay != null) taskbarPlay.Icon = Properties.Resources.Play;
  3256. if (trayMenuPlay != null) trayMenuPlay.Header = "Play";
  3257. if (jumpTaskPlay != null) jumpTaskPlay.Title = "Play";
  3258. break;
  3259. }
  3260. break;
  3261. case "QueueListConfig":
  3262. QueueTracks.Config = SettingsManager.QueueListConfig;
  3263. break;
  3264. case "HistoryListConfig":
  3265. HistoryTracks.Config = SettingsManager.HistoryListConfig;
  3266. break;
  3267. case "FileListConfig":
  3268. FileTracks.Config = SettingsManager.FileListConfig;
  3269. break;
  3270. }
  3271. }));
  3272. }
  3273. /// <summary>
  3274. /// Invoked when an error occured in the YouTube player
  3275. /// </summary>
  3276. /// <param name="sender">The sender of the event</param>
  3277. /// <param name="message">The error message</param>
  3278. private void YouTube_ErrorOccured(object sender, string message)
  3279. {
  3280. int errorCode = Convert.ToInt32(message);
  3281. if (showMediaError)
  3282. {
  3283. showMediaError = false;
  3284. switch (errorCode)
  3285. {
  3286. case 2:
  3287. MessageBox.Show(
  3288. U.T("MessageYouTubeBadParams", "Message"),
  3289. U.T("MessageYouTubeBadParams", "Title"),
  3290. MessageBoxButton.OK,
  3291. MessageBoxImage.Error
  3292. );
  3293. break;
  3294. case 100:
  3295. MessageBox.Show(
  3296. U.T("MessageYouTubeNotFound", "Message"),
  3297. U.T("MessageYouTubeNotFound", "Title"),
  3298. MessageBoxButton.OK,
  3299. MessageBoxImage.Error
  3300. );
  3301. break;
  3302. case 101:
  3303. case 150: // restricted
  3304. MediaManager.Next();
  3305. break;
  3306. default:
  3307. MessageBox.Show(
  3308. U.T("MessageYouTubeUnknown", "Message"),
  3309. String.Format(U.T("MessageYouTubeUnknown", "Title"), message),
  3310. MessageBoxButton.OK,
  3311. MessageBoxImage.Error
  3312. );
  3313. break;
  3314. }
  3315. MediaManager.Stop();
  3316. }
  3317. }
  3318. /// <summary>
  3319. /// Invoked when the YouTube player complains that there is no flash installed
  3320. /// </summary>
  3321. /// <param name="sender">The sender of the event</param>
  3322. /// <param name="e">The event data</param>
  3323. private void YouTube_NoFlashDetected(object sender, EventArgs e)
  3324. {
  3325. if (showMediaError)
  3326. {
  3327. showMediaError = false;
  3328. YouTubeManager.HasFlash = false;
  3329. MessageBoxResult r = MessageBox.Show(
  3330. U.T("MessageNoFlash", "Message"),
  3331. U.T("MessageNoFlash", "Title"),
  3332. MessageBoxButton.YesNo,
  3333. MessageBoxImage.Error
  3334. );
  3335. if (r == MessageBoxResult.Yes)
  3336. {
  3337. System.Diagnostics.Process.Start("IEXPLORE.EXE", "http://get.adobe.com/flashplayer");
  3338. }
  3339. MediaManager.Stop();
  3340. }
  3341. }
  3342. /// <summary>
  3343. /// Invoked when the YouTube player is ready
  3344. /// </summary>
  3345. /// <param name="sender">The sender of the event</param>
  3346. /// <param name="e">The event data</param>
  3347. private void YouTube_PlayerReady(object sender, EventArgs e)
  3348. {
  3349. YouTubeManager.HasFlash = true;
  3350. MediaManager.LoadYouTube();
  3351. }
  3352. /// <summary>
  3353. /// Adds or removes a track from the library collection
  3354. /// </summary>
  3355. /// <param name="sender">The sender of the event (the timer)</param>
  3356. /// <param name="e">The event data</param>
  3357. private void SourceModifiedDelay_Tick(object sender, EventArgs e)
  3358. {
  3359. sourceModifiedDelay.Stop();
  3360. ScanProgressBar.IsIndeterminate = true;
  3361. ScanProgress.Visibility = System.Windows.Visibility.Visible;
  3362. ThreadStart GUIScanThread = delegate()
  3363. {
  3364. // copy the tracks into two lists
  3365. SortedSet<string> trackPaths = new SortedSet<string>();
  3366. List<TrackData> tracksToAdd = new List<TrackData>();
  3367. SortedList<string, TrackData> tracksToRemove = new SortedList<string, TrackData>();
  3368. List<TrackData> tracksToUpdate = new List<TrackData>();
  3369. foreach (DictionaryEntry de in sourceModifiedTracks)
  3370. {
  3371. SourceModificationType modType = (SourceModificationType)de.Value;
  3372. TrackData track = (TrackData)de.Key;
  3373. if (modType == SourceModificationType.Added)
  3374. tracksToAdd.Add(track);
  3375. else if (modType == SourceModificationType.Removed)
  3376. {
  3377. if (!tracksToRemove.ContainsKey(track.Path))
  3378. tracksToRemove.Add(track.Path, track);
  3379. }
  3380. else
  3381. tracksToUpdate.Add(de.Key as TrackData);
  3382. }
  3383. sourceModifiedTracks.Clear();
  3384. // copy the observable collections so we can work on them
  3385. // outside the gui thread
  3386. ObservableCollection<TrackData> files = new ObservableCollection<TrackData>();
  3387. foreach (TrackData t in SettingsManager.FileTracks)
  3388. {
  3389. files.Add(t);
  3390. trackPaths.Add(t.Path);
  3391. }
  3392. // add tracks
  3393. for (int j=0; j < tracksToAdd.Count; j++)
  3394. {
  3395. TrackData track = tracksToAdd[j];
  3396. if (trackPaths.Contains(track.Path))
  3397. tracksToAdd.RemoveAt(j--);
  3398. else
  3399. files.Add(track);
  3400. }
  3401. // update source for file list
  3402. U.L(LogLevel.Debug, "MAIN", "Adding tracks to GUI list");
  3403. Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(delegate()
  3404. {
  3405. SettingsManager.FileTracks = files;
  3406. SettingsManager.FileTracks.CollectionChanged += new NotifyCollectionChangedEventHandler(LibraryTracks_CollectionChanged);
  3407. FileTracks.ItemsSource = files;
  3408. if (SettingsManager.CurrentSelectedNavigation == "Files")
  3409. InfoPaneTracks.Text = SettingsManager.FileTracks.Count + " " + U.T("HeaderTracks", "Text");
  3410. ScanProgressBar.IsIndeterminate = false;
  3411. }));
  3412. // remove tracks
  3413. U.L(LogLevel.Debug, "MAIN", "Tracks to remove: " + tracksToRemove.Count);
  3414. if (tracksToRemove.Count > 0)
  3415. {
  3416. U.L(LogLevel.Debug, "MAIN", "Removing tracks");
  3417. Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(delegate()
  3418. {
  3419. foreach (PlaylistData p in SettingsManager.Playlists)
  3420. RemoveTracks(tracksToRemove, p.Tracks);
  3421. RemoveTracks(tracksToRemove, SettingsManager.QueueTracks);
  3422. RemoveTracks(tracksToRemove, SettingsManager.HistoryTracks);
  3423. RemoveTracks(tracksToRemove, SettingsManager.FileTracks);
  3424. }));
  3425. }
  3426. // update tracks
  3427. double progressDelta = 100.0 / (double)(tracksToAdd.Count + tracksToUpdate.Count);
  3428. U.L(LogLevel.Debug, "MAIN", "Updating tracks");
  3429. DateTime start = DateTime.Now;
  3430. int numTracks = tracksToAdd.Count + tracksToUpdate.Count;
  3431. double progress = 0;
  3432. for (int j=0; j < tracksToAdd.Count; j++)
  3433. {
  3434. TrackData track = tracksToAdd[j];
  3435. if (FilesystemManager.ProgramIsClosed) return;
  3436. FilesystemManager.UpdateTrack(track, false);
  3437. if (j % 100 == 0)
  3438. {
  3439. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  3440. {
  3441. ScanProgressBar.Value = progress;
  3442. }));
  3443. }
  3444. progress += progressDelta;
  3445. }
  3446. for (int j=0; j < tracksToUpdate.Count; j++)
  3447. {
  3448. TrackData track = tracksToUpdate[j];
  3449. if (FilesystemManager.ProgramIsClosed) return;
  3450. FilesystemManager.UpdateTrack(track, false);
  3451. if (j % 100 == 0)
  3452. {
  3453. Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
  3454. {
  3455. ScanProgressBar.Value = progress;
  3456. }));
  3457. }
  3458. progress += progressDelta;
  3459. }
  3460. TimeSpan ts = (DateTime.Now - start);
  3461. double time = Math.Round(ts.TotalMilliseconds / numTracks, 2);
  3462. U.L(LogLevel.Debug, "FILESYSTEM", String.Format("Scanning meta took {0} seconds, an average of {1} ms/track", Math.Round(ts.TotalSeconds, 2), time));
  3463. // hide progressbar
  3464. Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(delegate()
  3465. {
  3466. ScanProgress.Visibility = System.Windows.Visibility.Collapsed;
  3467. }));
  3468. // call callback
  3469. if (sourceModifiedCallback != null)
  3470. sourceModifiedCallback(sourceModifiedCallbackParams);
  3471. sourceModifiedCallback = null;
  3472. sourceModifiedCallbackParams = null;
  3473. U.L(LogLevel.Debug, "MAIN", "Scan complete");
  3474. };
  3475. Thread gs_thread = new Thread(GUIScanThread);
  3476. gs_thread.Name = "GUI scan updater";
  3477. gs_thread.IsBackground = true;
  3478. gs_thread.Priority = ThreadPriority.Lowest;
  3479. gs_thread.Start();
  3480. }
  3481. /// <summary>
  3482. /// Reapplies the sorting on a TrackList when a track was changed.
  3483. ///
  3484. /// This method is called from a Timer in order to prevent many calls from being made in a short period of time.
  3485. /// </summary>
  3486. /// <param name="sender">The sender of the event (the timer)</param>
  3487. /// <param name="e">The event data</param>
  3488. private void ResortDelay_Tick(object sender, EventArgs e)
  3489. {
  3490. resortDelay.IsEnabled = false;
  3491. ResortTracklist(FileTracks, pathsThatWasChanged);
  3492. ResortTracklist(HistoryTracks, pathsThatWasChanged);
  3493. ResortTracklist(QueueTracks, pathsThatWasChanged);
  3494. foreach (DictionaryEntry o in PlaylistTrackLists)
  3495. ResortTracklist((ViewDetails)o.Value, pathsThatWasChanged);
  3496. pathsThatWasChanged.Clear();
  3497. }
  3498. /// <summary>
  3499. /// Invoked when something happens to the library collection.
  3500. /// Updates the library time and the library TrackList.
  3501. /// </summary>
  3502. /// <param name="sender">Sender of the event</param>
  3503. /// <param name="e">Event arguments</param>
  3504. private void LibraryTracks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  3505. {
  3506. LibraryTime = 0;
  3507. foreach (TrackData t in SettingsManager.FileTracks)
  3508. LibraryTime += t.RawLength;
  3509. if (SettingsManager.CurrentSelectedNavigation == "Files")
  3510. {
  3511. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  3512. {
  3513. InfoPaneTracks.Text = SettingsManager.FileTracks.Count + " " + U.T("HeaderTracks", "Text");
  3514. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)LibraryTime));
  3515. }));
  3516. }
  3517. }
  3518. /// <summary>
  3519. /// Invoked when something happens to the queue collection.
  3520. /// Updates the queue time and the queue TrackList.
  3521. /// </summary>
  3522. /// <param name="sender">Sender of the event</param>
  3523. /// <param name="e">Event arguments</param>
  3524. private void QueueTracks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  3525. {
  3526. QueueTime = 0;
  3527. foreach (TrackData t in SettingsManager.QueueTracks)
  3528. QueueTime += t.RawLength;
  3529. if (SettingsManager.CurrentSelectedNavigation == "Queue")
  3530. {
  3531. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  3532. {
  3533. // are all selected items removed?
  3534. bool allRemoved = true;
  3535. foreach (TrackData selectedTrack in QueueTracks.SelectedItems)
  3536. {
  3537. if (!e.OldItems.Contains(selectedTrack))
  3538. {
  3539. allRemoved = false;
  3540. break;
  3541. }
  3542. }
  3543. LanguageDictionary dictionary = LanguageDictionary.GetDictionary(LanguageContext.Instance.Culture);
  3544. string tracks = dictionary.Translate("HeaderTracks", "Text", "tracks", typeof(string)) as string;
  3545. InfoPaneTracks.Text = SettingsManager.QueueTracks.Count + " " + U.T("HeaderTracks", "Text");
  3546. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)QueueTime));
  3547. // select the last item that is not being removed
  3548. if (allRemoved && QueueTracks.SelectedItems.Count > 0)
  3549. {
  3550. if (QueueTracks.Items.Count > 0)
  3551. {
  3552. int indexToSelect = e.OldStartingIndex >= QueueTracks.Items.Count ? QueueTracks.Items.Count - 1 : e.OldStartingIndex;
  3553. QueueTracks.FocusAndSelectItem(indexToSelect);
  3554. }
  3555. }
  3556. }));
  3557. }
  3558. }
  3559. /// <summary>
  3560. /// Invoked when something happens to the history collection.
  3561. /// Updates the history time and the history TrackList.
  3562. /// </summary>
  3563. /// <param name="sender">Sender of the event</param>
  3564. /// <param name="e">Event arguments</param>
  3565. private void HistoryTracks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  3566. {
  3567. HistoryTime = 0;
  3568. foreach (TrackData t in SettingsManager.HistoryTracks)
  3569. HistoryTime += t.RawLength;
  3570. if (SettingsManager.CurrentSelectedNavigation == "History")
  3571. {
  3572. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  3573. {
  3574. LanguageDictionary dictionary = LanguageDictionary.GetDictionary(LanguageContext.Instance.Culture);
  3575. string tracks = dictionary.Translate("HeaderTracks", "Text", "tracks", typeof(string)) as string;
  3576. InfoPaneTracks.Text = SettingsManager.HistoryTracks.Count + " " + U.T("HeaderTracks", "Text");
  3577. InfoPaneDuration.Text = U.TimeSpanToLongString(new TimeSpan(0, 0, (int)HistoryTime));
  3578. }));
  3579. }
  3580. }
  3581. /// <summary>
  3582. /// Invoked when the selection of a track list changes
  3583. /// </summary>
  3584. /// <param name="sender">The sender of the event</param>
  3585. /// <param name="e">The event data</param>
  3586. private void TrackList_SelectionChanged(object sender, SelectionChangedEventArgs e)
  3587. {
  3588. ViewDetails vd = sender as ViewDetails;
  3589. if (vd.SelectedItem == null)
  3590. DetailsPane.Clear();
  3591. else
  3592. {
  3593. TrackData track = vd.SelectedItem as TrackData;
  3594. currentlySelectedTrack = track;
  3595. DetailsPane.Clear();
  3596. DetailsPane.Description = MediaManager.TrackType(track);
  3597. if (YouTubeManager.IsYouTube(track))
  3598. {
  3599. DetailsPane.Title = track.Title;
  3600. DetailsPane.AddField(U.T("ColumnArtist"), track.Artist);
  3601. DetailsPane.AddField(U.T("ColumnViews"), track.Views);
  3602. DetailsPane.AddField(U.T("ColumnPath"), YouTubeManager.GetURL(track));
  3603. }
  3604. else
  3605. {
  3606. DetailsPane.Title = Path.GetFileName(track.Path);
  3607. DetailsPane.AddField(U.T("ColumnArtist"), track.Artist, true);
  3608. DetailsPane.AddField(U.T("ColumnTitle"), track.Title, true);
  3609. DetailsPane.AddField(U.T("ColumnAlbum"), track.Album, true);
  3610. DetailsPane.AddField(U.T("ColumnGenre"), track.Genre, true);
  3611. DetailsPane.AddField(U.T("ColumnLength"), track.Length);
  3612. if (File.Exists(track.Path))
  3613. {
  3614. FileInfo fi = new FileInfo(track.Path);
  3615. DetailsPane.AddField(U.T("ColumnSize"), U.HumanSize(fi.Length));
  3616. }
  3617. DetailsPane.AddField(U.T("ColumnBitrate"), String.Format(U.T("BeatsPerMinute"), track.Bitrate));
  3618. DetailsPane.AddField(U.T("ColumnYear"), track.Year.ToString(), true);
  3619. DetailsPane.AddField(U.T("ColumnPlayCount"), track.PlayCount.ToString());
  3620. DetailsPane.AddField(U.T("ColumnLastPlayed"), track.LastPlayed);
  3621. DetailsPane.AddField(U.T("ColumnChannels"), track.Channels.ToString());
  3622. DetailsPane.AddField(U.T("ColumnSampleRate"), track.SampleRate.ToString());
  3623. DetailsPane.AddField(U.T("ColumnCodecs"), track.Codecs);
  3624. DetailsPane.AddField(U.T("ColumnPath"), track.Path);
  3625. }
  3626. // set image in a background thread
  3627. ThreadStart DetailsImageThread = delegate()
  3628. {
  3629. Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(delegate()
  3630. {
  3631. DetailsPane.Image = FilesystemManager.GetImageTag(track);
  3632. }));
  3633. };
  3634. Thread di_thread = new Thread(DetailsImageThread);
  3635. di_thread.Name = "Details Image";
  3636. di_thread.IsBackground = true;
  3637. di_thread.Priority = ThreadPriority.Lowest;
  3638. di_thread.Start();
  3639. }
  3640. }
  3641. /// <summary>
  3642. /// Evaluates if a given track matches a specific string
  3643. /// </summary>
  3644. /// <param name="item">The track to match</param>
  3645. /// <param name="needles">The string to match the track against</param>
  3646. /// <returns>true if the track matches the string, otherwise false</returns>
  3647. private bool TrackList_SearchMatch(object item, string needles)
  3648. {
  3649. if (needles == null || needles == "") return true;
  3650. TrackData track = (TrackData)item;
  3651. String artist = track.Artist == null ? "" : track.Artist.ToLower();
  3652. String album = track.Album == null ? "" : track.Album.ToLower();
  3653. String title = track.Title == null ? "" : track.Title.ToLower();
  3654. String genre = track.Genre == null ? "" : track.Genre.ToLower();
  3655. String year = track.Year.ToString().ToLower();
  3656. String path = track.Path.ToLower();
  3657. foreach (String needle in needles.ToLower().Split(' '))
  3658. {
  3659. if (!artist.Contains(needle) &&
  3660. !album.Contains(needle) &&
  3661. !title.Contains(needle) &&
  3662. !genre.Contains(needle) &&
  3663. !year.Contains(needle) &&
  3664. !path.Contains(needle))
  3665. return false;
  3666. }
  3667. return true;
  3668. }
  3669. /// <summary>
  3670. /// Invoked when files are dropped on a track list
  3671. /// </summary>
  3672. /// <param name="sender">The sender of the event</param>
  3673. /// <param name="e">The event data</param>
  3674. private void TrackList_FilesDropped(object sender, FileDropEventArgs e)
  3675. {
  3676. ViewDetails vd = GetCurrentTrackList();
  3677. if (vd == null || vd == HistoryTracks) return;
  3678. foreach (string path in e.Paths)
  3679. {
  3680. // create callback params
  3681. List<object> l = new List<object>();
  3682. l.Add(vd as object);
  3683. l.Add(e as object);
  3684. l.Add(path as object);
  3685. // add source?
  3686. bool addSource = false;
  3687. foreach (SourceData source in SettingsManager.Sources)
  3688. {
  3689. if (source.Data == path)
  3690. {
  3691. addSource = true;
  3692. break;
  3693. }
  3694. }
  3695. if (!addSource)
  3696. FilesystemManager.AddSource(path, TrackList_MoveNewlyAdded, l as object);
  3697. else
  3698. TrackList_MoveNewlyAdded(l as object);
  3699. }
  3700. }
  3701. /// <summary>
  3702. /// Invoked when a new source has been added after a file drop
  3703. /// after the scan has finished.
  3704. /// </summary>
  3705. /// <param name="param">
  3706. /// A list of three objects:
  3707. /// * The ViewDetails that was dropped upon
  3708. /// * The FileDropEventArgs containing the event data for the drop
  3709. /// * The string of the path that was scanned
  3710. /// </param>
  3711. private void TrackList_MoveNewlyAdded(object param)
  3712. {
  3713. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
  3714. {
  3715. // extract parameters
  3716. List<object> l = param as List<object>;
  3717. ViewDetails vd = l[0] as ViewDetails;
  3718. FileDropEventArgs e = l[1] as FileDropEventArgs;
  3719. string path = l[2] as string;
  3720. // remove sorting but keep positions
  3721. vd.ClearSort(true);
  3722. int p = e.Position;
  3723. if (vd == FileTracks)
  3724. {
  3725. for (int i = 0; i < SettingsManager.FileTracks.Count; i++)
  3726. {
  3727. TrackData t = SettingsManager.FileTracks[i];
  3728. if (t.Path.StartsWith(path) && i != (i >= p ? p : p - 1))
  3729. {
  3730. SettingsManager.FileTracks.Remove(t);
  3731. if (i >= p) // move back
  3732. {
  3733. SettingsManager.FileTracks.Insert(p++, t);
  3734. }
  3735. else // move forward
  3736. {
  3737. SettingsManager.FileTracks.Insert(p - 1, t);
  3738. i--;
  3739. }
  3740. }
  3741. }
  3742. }
  3743. else
  3744. {
  3745. ObservableCollection<TrackData> source = GetCurrentTrackCollection();
  3746. if (source != null)
  3747. {
  3748. List<TrackData> libTracks = U.GetTracks(SettingsManager.FileTracks, path);
  3749. if (vd == QueueTracks)
  3750. {
  3751. MediaManager.Queue(libTracks, e.Position);
  3752. }
  3753. else if (SettingsManager.CurrentSelectedNavigation.StartsWith("Playlist:"))
  3754. {
  3755. String playlistName = SettingsManager.CurrentSelectedNavigation.Split(new[] { ':' }, 2)[1];
  3756. PlaylistManager.AddToPlaylist(libTracks, playlistName, e.Position);
  3757. }
  3758. }
  3759. // find tracks in library
  3760. // each track:
  3761. // if addSource:
  3762. // check for tracks in track list
  3763. // if found: move and break
  3764. // insert
  3765. Console.WriteLine("check each track, move or insert to queue/playlist at " + e.Position);
  3766. }
  3767. }));
  3768. }
  3769. /// <summary>
  3770. /// Invoked when an item needs to be moved in a track list
  3771. /// </summary>
  3772. /// <param name="sender">The sender of the event</param>
  3773. /// <param name="e">The event data</param>
  3774. private void TrackList_MoveItem(object sender, MoveItemEventArgs e)
  3775. {
  3776. TrackData track = e.Item as TrackData;
  3777. ViewDetails vd = sender as ViewDetails;
  3778. ObservableCollection<TrackData> tracks = GetCurrentTrackCollection();
  3779. int i = tracks.IndexOf(track);
  3780. Console.WriteLine(String.Format("[moveitem] #{0}->{1}: {2} - {3}", e.Position, i, track.Artist, track.Title));
  3781. if (i == e.Position) return; // already at position
  3782. int j = i < e.Position ? e.Position - 1 : e.Position;
  3783. Console.WriteLine(String.Format("[inserting] #{0}: {1} - {2}", j, track.Artist, track.Title));
  3784. tracks.Remove(track);
  3785. tracks.Insert(j, track);
  3786. }
  3787. /// <summary>
  3788. /// Invoked when the upgrade button is clicked.
  3789. /// Will restart the application.
  3790. /// </summary>
  3791. /// <param name="sender">The sender of the event</param>
  3792. /// <param name="e">The event data</param>
  3793. private void UpgradeButton_Click(object sender, RoutedEventArgs e)
  3794. {
  3795. Restart();
  3796. }
  3797. #endregion
  3798. #endregion
  3799. #region Events
  3800. /// <summary>
  3801. ///
  3802. /// </summary>
  3803. public event PropertyChangedEventHandler PropertyChanged;
  3804. #endregion
  3805. }
  3806. }