Pushing missing changes

This commit is contained in:
LukePulverenti
2013-02-20 20:33:05 -05:00
parent 845554722e
commit 767cdc1f6f
924 changed files with 103121 additions and 18677 deletions

View File

@@ -1,25 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="ProgramDataPath" value="..\..\..\ProgramData-Server" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Core" publicKeyToken="f300afd708cefcd3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.20823.0" newVersion="2.0.20823.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Interfaces" publicKeyToken="f300afd708cefcd3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.20823.0" newVersion="2.0.20823.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
</configSections>
<system.diagnostics>
<assert assertuienabled="false" />
</system.diagnostics>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets async="true">
</targets>
</nlog>
<appSettings>
<add key="DebugProgramDataPath" value="..\..\..\..\ProgramData-Server" />
<add key="ReleaseProgramDataPath" value="%CommonApplicationData%" />
<add key="ProgramDataFolderName" value="MediaBrowser-Server"/>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<gcServer enabled ="true" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Core" publicKeyToken="f300afd708cefcd3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.20823.0" newVersion="2.0.20823.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Interfaces" publicKeyToken="f300afd708cefcd3" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.20823.0" newVersion="2.0.20823.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
</configuration>

View File

@@ -1,67 +1,195 @@
using MediaBrowser.Common.Kernel;
using MediaBrowser.Common.UI;
using MediaBrowser.Controller;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
namespace MediaBrowser.ServerApplication
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : BaseApplication, IApplication
{
[STAThread]
public static void Main()
{
RunApplication<App>("MediaBrowserServer");
}
protected override void OnSecondInstanceLaunched(IList<string> args)
{
base.OnSecondInstanceLaunched(args);
OpenDashboard();
InitializeComponent();
}
public static void OpenDashboard()
{
OpenUrl("http://localhost:" + Kernel.Instance.Configuration.HttpServerPortNumber + "/mediabrowser/dashboard/index.html");
}
public static void OpenUrl(string url)
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = url
},
EnableRaisingEvents = true
};
process.Exited += ProcessExited;
process.Start();
}
static void ProcessExited(object sender, EventArgs e)
{
(sender as Process).Dispose();
}
protected override IKernel InstantiateKernel()
{
return new Kernel();
}
protected override Window InstantiateMainWindow()
{
return new MainWindow();
}
}
}
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Kernel;
using MediaBrowser.Common.UI;
using MediaBrowser.Controller;
using MediaBrowser.IsoMounter;
using MediaBrowser.Server.Uninstall;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
namespace MediaBrowser.ServerApplication
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : BaseApplication, IApplication
{
/// <summary>
/// Defines the entry point of the application.
/// </summary>
[STAThread]
public static void Main()
{
RunApplication<App>("MediaBrowserServer");
}
/// <summary>
/// Gets the instance.
/// </summary>
/// <value>The instance.</value>
public static App Instance
{
get
{
return Current as App;
}
}
/// <summary>
/// Gets the name of the product.
/// </summary>
/// <value>The name of the product.</value>
protected override string ProductName
{
get { return Globals.ProductName; }
}
/// <summary>
/// Gets the name of the publisher.
/// </summary>
/// <value>The name of the publisher.</value>
protected override string PublisherName
{
get { return Globals.PublisherName; }
}
/// <summary>
/// Gets the name of the suite.
/// </summary>
/// <value>The name of the suite.</value>
protected override string SuiteName
{
get { return Globals.SuiteName; }
}
/// <summary>
/// Gets the name of the uninstaller file.
/// </summary>
/// <value>The name of the uninstaller file.</value>
protected override string UninstallerFileName
{
get { return "MediaBrowser.Server.Uninstall.exe"; }
}
/// <summary>
/// Instantiates the iso manager.
/// </summary>
/// <param name="kernel">The kernel.</param>
/// <returns>IIsoManager.</returns>
protected override IIsoManager InstantiateIsoManager(IKernel kernel)
{
return new IsoManager(kernel);
}
/// <summary>
/// Called when [second instance launched].
/// </summary>
/// <param name="args">The args.</param>
protected override void OnSecondInstanceLaunched(IList<string> args)
{
base.OnSecondInstanceLaunched(args);
OpenDashboard();
InitializeComponent();
}
/// <summary>
/// Opens the dashboard.
/// </summary>
public static void OpenDashboard()
{
OpenDashboardPage("dashboard.html");
}
/// <summary>
/// Opens the dashboard page.
/// </summary>
/// <param name="page">The page.</param>
public static void OpenDashboardPage(string page)
{
var url = "http://localhost:" + Controller.Kernel.Instance.Configuration.HttpServerPortNumber + "/" +
Controller.Kernel.Instance.WebApplicationName + "/dashboard/" + page;
url = AddAutoLoginToDashboardUrl(url);
OpenUrl(url);
}
/// <summary>
/// Adds the auto login to dashboard URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <returns>System.String.</returns>
public static string AddAutoLoginToDashboardUrl(string url)
{
var user = Controller.Kernel.Instance.Users.FirstOrDefault(u => u.Configuration.IsAdministrator);
if (user != null)
{
if (url.IndexOf('?') == -1)
{
url += "?u=" + user.Id;
}
else
{
url += "&u=" + user.Id;
}
}
return url;
}
/// <summary>
/// Opens the URL.
/// </summary>
/// <param name="url">The URL.</param>
public static void OpenUrl(string url)
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = url
},
EnableRaisingEvents = true
};
process.Exited += ProcessExited;
process.Start();
}
/// <summary>
/// Processes the exited.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
static void ProcessExited(object sender, EventArgs e)
{
((Process)sender).Dispose();
}
/// <summary>
/// Instantiates the kernel.
/// </summary>
/// <returns>IKernel.</returns>
protected override IKernel InstantiateKernel()
{
return new Kernel();
}
/// <summary>
/// Instantiates the main window.
/// </summary>
/// <returns>Window.</returns>
protected override Window InstantiateMainWindow()
{
return new MainWindow();
}
}
}

View File

@@ -0,0 +1,63 @@
<UserControl x:Class="MediaBrowser.ServerApplication.Controls.ItemUpdateNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid MaxHeight="280" MaxWidth="600" Margin="20">
<Border BorderThickness="0" Background="#333333">
<Border.Effect>
<DropShadowEffect BlurRadius="25" ShadowDepth="0">
</DropShadowEffect>
</Border.Effect>
</Border>
<Grid>
<Grid.Background>
<LinearGradientBrush SpreadMethod="Reflect" ColorInterpolationMode="SRgbLinearInterpolation" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#ff222222" Offset="0" />
<GradientStop Color="#ffbbbbbb" Offset="1.0" />
</LinearGradientBrush>
</Grid.Background>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0">
<Image x:Name="imgParentLogo" Stretch="Uniform" Height="40" RenderOptions.BitmapScalingMode="Fant" HorizontalAlignment="Left"></Image>
<TextBlock x:Name="txtParentName" FontSize="26" Foreground="White"></TextBlock>
<TextBlock x:Name="txtName" FontSize="26" Foreground="White"></TextBlock>
</StackPanel>
<Grid Grid.Row="1" Margin="0 20 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 20 0" VerticalAlignment="Top">
<Image x:Name="img" Stretch="Uniform" RenderOptions.BitmapScalingMode="Fant" Height="150"></Image>
</StackPanel>
<TextBlock x:Name="txtTagline" Foreground="White" Grid.Column="1" Grid.Row="0" Margin="0 0 0 20" TextWrapping="Wrap" FontStyle="Italic"></TextBlock>
<StackPanel x:Name="pnlRating" Orientation="Horizontal" Margin="0 2 0 20" Grid.Column="1" Grid.Row="1"></StackPanel>
<TextBlock x:Name="txtOverview" Foreground="White" Grid.Column="1" Grid.Row="2" TextWrapping="Wrap" Margin="0 0 0 20"></TextBlock>
<TextBlock x:Name="txtPremeireDate" Foreground="White" Grid.Column="1" Grid.Row="3"></TextBlock>
</Grid>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,249 @@
using MediaBrowser.Common.Logging;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace MediaBrowser.ServerApplication.Controls
{
/// <summary>
/// Interaction logic for ItemUpdateNotification.xaml
/// </summary>
public partial class ItemUpdateNotification : UserControl
{
/// <summary>
/// The logger
/// </summary>
private static readonly ILogger Logger = LogManager.GetLogger("MultiItemUpdateNotification");
/// <summary>
/// Gets the children changed event args.
/// </summary>
/// <value>The children changed event args.</value>
private BaseItem Item
{
get { return DataContext as BaseItem; }
}
/// <summary>
/// Initializes a new instance of the <see cref="ItemUpdateNotification" /> class.
/// </summary>
public ItemUpdateNotification()
{
InitializeComponent();
Loaded += ItemUpdateNotification_Loaded;
}
/// <summary>
/// Handles the Loaded event of the ItemUpdateNotification control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
void ItemUpdateNotification_Loaded(object sender, RoutedEventArgs e)
{
DisplayItem(Item);
}
/// <summary>
/// Gets the display name.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="includeParentName">if set to <c>true</c> [include parent name].</param>
/// <returns>System.String.</returns>
internal static string GetDisplayName(BaseItem item, bool includeParentName)
{
var name = item.Name;
if (item.ProductionYear.HasValue && !(item is Episode))
{
name += string.Format(" ({0})", item.ProductionYear);
}
var episode = item as Episode;
if (episode != null)
{
var indexNumbers = new List<int>();
if (episode.Season.IndexNumber.HasValue)
{
indexNumbers.Add(episode.Season.IndexNumber.Value);
}
if (episode.IndexNumber.HasValue)
{
indexNumbers.Add(episode.IndexNumber.Value);
}
var indexNumber = string.Join(".", indexNumbers.ToArray());
name = string.Format("{0} - {1}", indexNumber, name);
if (includeParentName)
{
name = episode.Series.Name + " - " + name;
}
}
if (includeParentName)
{
var season = item as Season;
if (season != null)
{
name = season.Series.Name + " - " + name;
}
}
return name;
}
/// <summary>
/// Displays the parent title.
/// </summary>
/// <param name="item">The item.</param>
private void DisplayParentTitle(BaseItem item)
{
if (!(item is Episode || item is Season))
{
txtParentName.Visibility = Visibility.Collapsed;
imgParentLogo.Visibility = Visibility.Collapsed;
return;
}
var series = item is Episode ? (item as Episode).Series : (item as Season).Series;
var logo = series.GetImage(ImageType.Logo);
if (string.IsNullOrEmpty(logo))
{
imgParentLogo.Visibility = Visibility.Collapsed;
txtParentName.Visibility = Visibility.Visible;
}
else
{
imgParentLogo.Visibility = Visibility.Visible;
txtParentName.Visibility = Visibility.Collapsed;
imgParentLogo.Source = App.Instance.GetBitmapImage(logo);
}
txtParentName.Text = series.Name;
}
/// <summary>
/// Displays the title.
/// </summary>
/// <param name="item">The item.</param>
private void DisplayTitle(BaseItem item)
{
txtName.Text = GetDisplayName(item, false);
}
/// <summary>
/// Displays the item.
/// </summary>
/// <param name="item">The item.</param>
private void DisplayItem(BaseItem item)
{
DisplayParentTitle(item);
DisplayTitle(item);
DisplayRating(item);
var path = MultiItemUpdateNotification.GetImagePath(item);
if (string.IsNullOrEmpty(path))
{
img.Visibility = Visibility.Collapsed;
}
else
{
img.Visibility = Visibility.Visible;
try
{
img.Source = App.Instance.GetBitmapImage(path);
}
catch (FileNotFoundException)
{
Logger.Error("Image file not found {0}", path);
}
}
if (string.IsNullOrEmpty(item.Overview))
{
txtOverview.Visibility = Visibility.Collapsed;
}
else
{
txtOverview.Visibility = Visibility.Visible;
txtOverview.Text = item.Overview;
}
if (item.Taglines == null || item.Taglines.Count == 0)
{
txtTagline.Visibility = Visibility.Collapsed;
}
else
{
txtTagline.Visibility = Visibility.Visible;
txtTagline.Text = item.Taglines[0];
}
if (!item.PremiereDate.HasValue)
{
txtPremeireDate.Visibility = Visibility.Collapsed;
}
else
{
txtPremeireDate.Visibility = Visibility.Visible;
txtPremeireDate.Text = "Premiered " + item.PremiereDate.Value.ToShortDateString();
}
}
/// <summary>
/// Displays the rating.
/// </summary>
/// <param name="item">The item.</param>
private void DisplayRating(BaseItem item)
{
if (!item.CommunityRating.HasValue)
{
pnlRating.Visibility = Visibility.Collapsed;
return;
}
pnlRating.Children.Clear();
pnlRating.Visibility = Visibility.Visible;
var rating = item.CommunityRating.Value;
for (var i = 0; i < 10; i++)
{
Image image;
if (rating < i - 1)
{
image = App.Instance.GetImage(new Uri("../Resources/Images/starEmpty.png", UriKind.Relative));
}
else if (rating < i)
{
image = App.Instance.GetImage(new Uri("../Resources/Images/starHalf.png", UriKind.Relative));
}
else
{
image = App.Instance.GetImage(new Uri("../Resources/Images/starFull.png", UriKind.Relative));
}
RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.Fant);
image.Stretch = Stretch.Uniform;
image.Height = 16;
pnlRating.Children.Add(image);
}
}
}
}

View File

@@ -0,0 +1,37 @@
<UserControl x:Class="MediaBrowser.ServerApplication.Controls.MultiItemUpdateNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid MaxHeight="400" MaxWidth="600" Margin="20">
<Border BorderThickness="0" Background="#333333">
<Border.Effect>
<DropShadowEffect BlurRadius="25" ShadowDepth="0">
</DropShadowEffect>
</Border.Effect>
</Border>
<Grid>
<Grid.Background>
<LinearGradientBrush SpreadMethod="Reflect" ColorInterpolationMode="SRgbLinearInterpolation" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#ff222222" Offset="0" />
<GradientStop Color="#ffbbbbbb" Offset="1" />
</LinearGradientBrush>
</Grid.Background>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="header" FontSize="26" Foreground="White" Grid.Row="0"></TextBlock>
<UniformGrid x:Name="itemsPanel" Columns="4" Margin="0 20 0 0" Grid.Row="1"></UniformGrid>
</Grid>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,144 @@
using MediaBrowser.Common.Logging;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace MediaBrowser.ServerApplication.Controls
{
/// <summary>
/// Interaction logic for MultiItemUpdateNotification.xaml
/// </summary>
public partial class MultiItemUpdateNotification : UserControl
{
/// <summary>
/// The logger
/// </summary>
private static readonly ILogger Logger = LogManager.GetLogger("MultiItemUpdateNotification");
/// <summary>
/// Gets the children changed event args.
/// </summary>
/// <value>The children changed event args.</value>
private List<BaseItem> Items
{
get { return DataContext as List<BaseItem>; }
}
/// <summary>
/// Initializes a new instance of the <see cref="MultiItemUpdateNotification" /> class.
/// </summary>
public MultiItemUpdateNotification()
{
InitializeComponent();
Loaded += MultiItemUpdateNotification_Loaded;
}
/// <summary>
/// Handles the Loaded event of the MultiItemUpdateNotification control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
void MultiItemUpdateNotification_Loaded(object sender, RoutedEventArgs e)
{
header.Text = string.Format("{0} New Items!", Items.Count);
PopulateItems();
}
/// <summary>
/// Populates the items.
/// </summary>
private void PopulateItems()
{
itemsPanel.Children.Clear();
var items = Items;
const int maxItemsToDisplay = 8;
var index = 0;
foreach (var item in items)
{
if (index >= maxItemsToDisplay)
{
break;
}
// Try our best to find an image
var path = GetImagePath(item);
if (string.IsNullOrEmpty(path))
{
continue;
}
Image img;
try
{
img = App.Instance.GetImage(path);
}
catch (FileNotFoundException)
{
Logger.Error("Image file not found {0}", path);
continue;
}
img.Stretch = Stretch.Uniform;
img.Margin = new Thickness(0, 0, 5, 5);
img.ToolTip = ItemUpdateNotification.GetDisplayName(item, true);
RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.Fant);
itemsPanel.Children.Add(img);
index++;
}
}
/// <summary>
/// Gets the image path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
internal static string GetImagePath(BaseItem item)
{
// Try our best to find an image
var path = item.PrimaryImagePath;
if (string.IsNullOrEmpty(path) && item.BackdropImagePaths != null)
{
path = item.BackdropImagePaths.FirstOrDefault();
}
if (string.IsNullOrEmpty(path))
{
path = item.GetImage(ImageType.Thumb);
}
if (string.IsNullOrEmpty(path))
{
path = item.GetImage(ImageType.Art);
}
if (string.IsNullOrEmpty(path))
{
path = item.GetImage(ImageType.Logo);
}
if (string.IsNullOrEmpty(path))
{
path = item.GetImage(ImageType.Disc);
}
return path;
}
}
}

View File

@@ -0,0 +1,65 @@
<Window x:Class="MediaBrowser.ServerApplication.LibraryExplorer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MediaBrowser.ServerApplication"
Title="Library Explorer" Height="733.75" Width="893">
<Grid Margin="0,0,0,10">
<TreeView x:Name="tvwLibrary" HorizontalAlignment="Left" Margin="10,54,0,0" Width="399" SelectedItemChanged="tvwLibrary_SelectedItemChanged" Height="417" VerticalAlignment="Top">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="img" Width="20" Height="20" Stretch="Fill"
Source="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type TreeViewItem}},
Path=Tag,
Converter={x:Static local:ItemToImageConverter.Instance}}"
/>
<TextBlock Text="{Binding}" Margin="5,0" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
<Button x:Name="btnLoad" Content="Load" HorizontalAlignment="Left" Margin="218,25,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.373,0.045" Click="btnLoad_Click" Visibility="Hidden"/>
<TextBox x:Name="txtData" Margin="427,54,0,0" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="417" Width="444" VerticalScrollBarVisibility="Auto" />
<Label Content="Contents&#xD;&#xA;" HorizontalAlignment="Left" Margin="440,23,0,0" VerticalAlignment="Top" Height="26" Width="74" FontWeight="Bold"/>
<ListView x:Name="lstPreviews" HorizontalAlignment="Left" Margin="10,476,0,10" Width="861">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" MinWidth="100" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Image Source="{Binding Preview}" Height="140" MaxWidth="300" Grid.Row="0"/>
<TextBlock Text="{Binding Name}" Grid.Row="1" FontFamily="Segoe Media Center" FontSize="14" FontWeight="Bold" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ComboBox x:Name="ddlProfile" HorizontalAlignment="Left" Margin="10,25,0,0" VerticalAlignment="Top" Width="191" SelectionChanged="ddlProfile_SelectionChanged"/>
<Label Content="View;" HorizontalAlignment="Left" Margin="10,1,0,0" VerticalAlignment="Top" Height="24" Width="119" FontWeight="Bold" />
<Label x:Name="lblLoading" Content="Loading..." HorizontalAlignment="Left" Margin="140,150,0,0" VerticalAlignment="Top" FontSize="18" Foreground="LightGray" Visibility="Hidden" FontStyle="Italic" FontWeight="Bold" RenderTransformOrigin="0.258,0.5"/>
<Label x:Name="lblObjType" Content="Type:&#xA;" HorizontalAlignment="Left" Margin="534,23,0,0" VerticalAlignment="Top" Height="26" Width="158" FontWeight="Bold"/>
<Button x:Name="btnRefresh" Content="Refresh" HorizontalAlignment="Left" Margin="712,25,0,0" VerticalAlignment="Top" Width="82" Click="btnRefresh_Click"/>
<CheckBox x:Name="cbxForce" Content="Force" HorizontalAlignment="Left" Margin="816,28,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.14,-0.562" Width="51"/>
<ComboBox x:Name="ddlIndexBy" HorizontalAlignment="Left" Margin="218,25,0,0" VerticalAlignment="Top" Width="92" SelectionChanged="ddlIndexBy_SelectionChanged"/>
<Label x:Name="lblIndexBy" Content="Index By" HorizontalAlignment="Left" Margin="218,0,0,0" VerticalAlignment="Top" Height="34" Width="75" FontWeight="Bold" />
<ComboBox x:Name="ddlSortBy" HorizontalAlignment="Left" Margin="315,25,0,0" VerticalAlignment="Top" Width="94" SelectionChanged="ddlSortBy_SelectionChanged"/>
<Label x:Name="lblSortBy" Content="Sort By" HorizontalAlignment="Left" Margin="314,0,0,0" VerticalAlignment="Top" Height="34" Width="75" FontWeight="Bold" />
<Label x:Name="lblVersion" Content="Version: " HorizontalAlignment="Left" Margin="729,-6,0,0" VerticalAlignment="Top" Width="138"/>
</Grid>
</Window>

View File

@@ -0,0 +1,581 @@
using MediaBrowser.Common.Serialization;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media.Imaging;
namespace MediaBrowser.ServerApplication
{
/// <summary>
/// Interaction logic for LibraryExplorer.xaml
/// </summary>
public partial class LibraryExplorer : Window
{
/// <summary>
/// The current user
/// </summary>
private User CurrentUser;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryExplorer" /> class.
/// </summary>
public LibraryExplorer()
{
InitializeComponent();
lblVersion.Content = "Version: " + Kernel.Instance.DisplayVersion;
foreach (var user in Kernel.Instance.Users)
ddlProfile.Items.Add(user);
ddlProfile.Items.Insert(0,new User {Name = "Physical"});
ddlProfile.SelectedIndex = 0;
ddlIndexBy.Visibility = ddlSortBy.Visibility = lblIndexBy.Visibility = lblSortBy.Visibility = Visibility.Hidden;
}
/// <summary>
/// Handles the Click event of the btnLoad control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
}
/// <summary>
/// Loads the tree.
/// </summary>
/// <returns>Task.</returns>
private async Task LoadTree()
{
tvwLibrary.Items.Clear();
lblLoading.Visibility = Visibility.Visible;
//grab UI context so we can update within the below task
var ui = TaskScheduler.FromCurrentSynchronizationContext();
//this whole async thing doesn't really work in this instance since all my work pretty much needs to be on the UI thread...
Cursor = Cursors.Wait;
await Task.Run(() =>
{
IEnumerable<BaseItem> children;
children = CurrentUser.Name == "Physical" ? Kernel.Instance.RootFolder.Children.OrderBy(i => i.SortName) : Kernel.Instance.RootFolder.GetChildren(CurrentUser, sortBy: LocalizedStrings.Instance.GetString("NameDispPref"));
foreach (Folder folder in children)
{
var currentFolder = folder;
Task.Factory.StartNew(() =>
{
var prefs = ddlProfile.SelectedItem != null ? currentFolder.GetDisplayPrefs(ddlProfile.SelectedItem as User, false) ?? new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")} : new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")};
var node = new TreeViewItem { Tag = currentFolder };
AddChildren(node, currentFolder.GetChildren(CurrentUser, prefs.IndexBy, prefs.SortBy ?? LocalizedStrings.Instance.GetString("NameDispPref")), CurrentUser);
node.Header = currentFolder.Name + " (" +
node.Items.Count + ")";
tvwLibrary.Items.Add(node);
}, CancellationToken.None, TaskCreationOptions.None, ui);
}
});
lblLoading.Visibility = Visibility.Hidden;
Cursor = Cursors.Arrow;
}
/// <summary>
/// Adds the children.
/// </summary>
/// <param name="parent">The parent.</param>
/// <param name="children">The children.</param>
/// <param name="user">The user.</param>
private void AddChildren(TreeViewItem parent, IEnumerable<BaseItem> children, User user)
{
foreach (var item in children)
{
var node = new TreeViewItem { Tag = item };
var subFolder = item as Folder;
if (subFolder != null)
{
var prefs = subFolder.GetDisplayPrefs(user, false) ?? new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")};
AddChildren(node, subFolder.GetChildren(user, sortBy: prefs.SortBy), user);
node.Header = item.Name + " (" + node.Items.Count + ")";
}
else
{
node.Header = item.Name;
}
parent.Items.Add(node);
}
}
/// <summary>
/// TVWs the library_ selected item changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
private async void tvwLibrary_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (tvwLibrary.SelectedItem != null)
{
var item = (BaseItem)(tvwLibrary.SelectedItem as TreeViewItem).Tag;
lblObjType.Content = "Type: " + item.GetType().Name;
var trailers = item.LocalTrailers != null && item.LocalTrailers.Count > 0
? "\nTrailers: " +
String.Join(Environment.NewLine, item.LocalTrailers.Select(t => t.Path))
: "";
var movie = item as Movie;
var features = movie != null && movie.SpecialFeatures != null
? "\nSpecial Features: " +
string.Join(Environment.NewLine,
movie.SpecialFeatures.Select(f => f.Path))
: "";
var folder = item as Folder;
if (folder != null)
{
lblIndexBy.Visibility = ddlIndexBy.Visibility = ddlSortBy.Visibility = lblSortBy.Visibility = Visibility.Visible;
ddlIndexBy.ItemsSource = folder.IndexByOptionStrings;
ddlSortBy.ItemsSource = folder.SortByOptionStrings;
var prefs = folder.GetDisplayPrefs(ddlProfile.SelectedItem as User, false);
ddlIndexBy.SelectedItem = prefs != null
? prefs.IndexBy ?? LocalizedStrings.Instance.GetString("NoneDispPref")
: LocalizedStrings.Instance.GetString("NoneDispPref");
ddlSortBy.SelectedItem = prefs != null
? prefs.SortBy ?? LocalizedStrings.Instance.GetString("NameDispPref")
: LocalizedStrings.Instance.GetString("NameDispPref");
}
else
{
lblIndexBy.Visibility = ddlIndexBy.Visibility = ddlSortBy.Visibility = lblSortBy.Visibility = Visibility.Hidden;
}
txtData.Text = FormatJson(JsonSerializer.SerializeToString(item)) + trailers + features;
var previews = new List<PreviewItem>();
await Task.Run(() =>
{
if (!string.IsNullOrEmpty(item.PrimaryImagePath))
{
previews.Add(new PreviewItem(item.PrimaryImagePath, "Primary"));
}
if (item.HasImage(ImageType.Banner))
{
previews.Add(new PreviewItem(item.GetImage(ImageType.Banner), "Banner"));
}
if (item.HasImage(ImageType.Logo))
{
previews.Add(new PreviewItem(item.GetImage(ImageType.Logo), "Logo"));
}
if (item.HasImage(ImageType.Art))
{
previews.Add(new PreviewItem(item.GetImage(ImageType.Art), "Art"));
}
if (item.HasImage(ImageType.Thumb))
{
previews.Add(new PreviewItem(item.GetImage(ImageType.Thumb), "Thumb"));
}
if (item.BackdropImagePaths != null)
previews.AddRange(
item.BackdropImagePaths.Select(
image => new PreviewItem(image, "Backdrop")));
});
lstPreviews.ItemsSource = previews;
lstPreviews.Items.Refresh();
}
}
/// <summary>
/// The INDEN t_ STRING
/// </summary>
private const string INDENT_STRING = " ";
/// <summary>
/// Formats the json.
/// </summary>
/// <param name="str">The STR.</param>
/// <returns>System.String.</returns>
private static string FormatJson(string str)
{
var indent = 0;
var quoted = false;
var sb = new StringBuilder();
for (var i = 0; i < str.Length; i++)
{
var ch = str[i];
switch (ch)
{
case '{':
case '[':
sb.Append(ch);
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case '}':
case ']':
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
}
sb.Append(ch);
break;
case '"':
sb.Append(ch);
bool escaped = false;
var index = i;
while (index > 0 && str[--index] == '\\')
escaped = !escaped;
if (!escaped)
quoted = !quoted;
break;
case ',':
sb.Append(ch);
if (!quoted)
{
sb.AppendLine();
Enumerable.Range(0, indent).ForEach(item => sb.Append(INDENT_STRING));
}
break;
case ':':
sb.Append(ch);
if (!quoted)
sb.Append(" ");
break;
default:
sb.Append(ch);
break;
}
}
return sb.ToString();
}
/// <summary>
/// Handles the SelectionChanged event of the ddlProfile control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="SelectionChangedEventArgs" /> instance containing the event data.</param>
private void ddlProfile_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
CurrentUser = ddlProfile.SelectedItem as User;
if (CurrentUser != null)
LoadTree().ConfigureAwait(false);
}
/// <summary>
/// Handles the Click event of the btnRefresh control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void btnRefresh_Click(object sender, RoutedEventArgs e)
{
if (tvwLibrary.SelectedItem != null)
{
var item = ((TreeViewItem)tvwLibrary.SelectedItem).Tag as BaseItem;
if (item != null)
{
item.RefreshMetadata(CancellationToken.None, forceRefresh: cbxForce.IsChecked.Value);
tvwLibrary_SelectedItemChanged(this, null);
}
}
}
/// <summary>
/// Handles the SelectionChanged event of the ddlIndexBy control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="SelectionChangedEventArgs" /> instance containing the event data.</param>
private async void ddlIndexBy_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ddlIndexBy.SelectedItem != null)
{
var treeItem = tvwLibrary.SelectedItem as TreeViewItem;
var folder = treeItem != null
? treeItem.Tag as Folder
: null;
var prefs = folder != null ? folder.GetDisplayPrefs(CurrentUser, true) : new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")};
if (folder != null && prefs.IndexBy != ddlIndexBy.SelectedItem as string)
{
//grab UI context so we can update within the below task
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Cursor = Cursors.Wait;
await Task.Factory.StartNew(() =>
{
using (
new Profiler("Explorer full index expansion for " +
folder.Name))
{
//re-build the current item's children as an index
prefs.IndexBy = ddlIndexBy.SelectedItem as string;
treeItem.Items.Clear();
AddChildren(treeItem,folder.GetChildren(CurrentUser, prefs.IndexBy, prefs.SortBy), CurrentUser);
treeItem.Header = folder.Name + "(" +
treeItem.Items.Count + ")";
Cursor = Cursors.Arrow;
}
}, CancellationToken.None, TaskCreationOptions.None,
ui);
}
}
}
/// <summary>
/// Handles the SelectionChanged event of the ddlSortBy control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="SelectionChangedEventArgs" /> instance containing the event data.</param>
private async void ddlSortBy_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ddlSortBy.SelectedItem != null)
{
var treeItem = tvwLibrary.SelectedItem as TreeViewItem;
var folder = treeItem != null
? treeItem.Tag as Folder
: null;
var prefs = folder != null ? folder.GetDisplayPrefs(CurrentUser, true) : new DisplayPreferences();
if (folder != null && prefs.SortBy != ddlSortBy.SelectedItem as string)
{
//grab UI context so we can update within the below task
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Cursor = Cursors.Wait;
await Task.Factory.StartNew(() =>
{
using (
new Profiler("Explorer sorting by " + ddlSortBy.SelectedItem + " for " +
folder.Name))
{
//re-sort
prefs.SortBy = ddlSortBy.SelectedItem as string;
treeItem.Items.Clear();
AddChildren(treeItem,folder.GetChildren(CurrentUser,prefs.IndexBy, prefs.SortBy ?? LocalizedStrings.Instance.GetString("NameDispPref")), CurrentUser);
treeItem.Header = folder.Name + "(" +
treeItem.Items.Count + ")";
Cursor = Cursors.Arrow;
}
}, CancellationToken.None, TaskCreationOptions.None,
ui);
}
}
}
}
/// <summary>
/// Class PreviewItem
/// </summary>
public class PreviewItem
{
/// <summary>
/// The preview
/// </summary>
private readonly string preview;
/// <summary>
/// The name
/// </summary>
private readonly string name;
/// <summary>
/// Gets the preview.
/// </summary>
/// <value>The preview.</value>
public string Preview
{
get { return preview; }
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name
{
get { return name; }
}
/// <summary>
/// Initializes a new instance of the <see cref="PreviewItem" /> class.
/// </summary>
/// <param name="p">The p.</param>
/// <param name="n">The n.</param>
public PreviewItem(string p, string n)
{
preview = p;
name = n;
}
}
/// <summary>
/// Class Extensions
/// </summary>
static class Extensions
{
/// <summary>
/// Fors the each.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ie">The ie.</param>
/// <param name="action">The action.</param>
public static void ForEach<T>(this IEnumerable<T> ie, Action<T> action)
{
foreach (var i in ie)
{
action(i);
}
}
}
#region ItemToImageConverter
/// <summary>
/// Class ItemToImageConverter
/// </summary>
[ValueConversion(typeof(string), typeof(bool))]
public class ItemToImageConverter : IValueConverter
{
/// <summary>
/// The instance
/// </summary>
public static ItemToImageConverter Instance =
new ItemToImageConverter();
/// <summary>
/// Converts a value.
/// </summary>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
var item = value as BaseItem ?? new Folder();
switch (item.DisplayMediaType)
{
case "DVD":
case "HD DVD":
case "Blu-ray":
case "Blu-Ray":
case "Movie":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/movie.png");
var source = new BitmapImage(uri);
return source;
}
case "Series":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/series.png");
var source = new BitmapImage(uri);
return source;
}
case "Season":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/season.png");
var source = new BitmapImage(uri);
return source;
}
case "Episode":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/episode.png");
var source = new BitmapImage(uri);
return source;
}
case "BoxSet":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/boxset.png");
var source = new BitmapImage(uri);
return source;
}
case "Audio":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/audio.png");
var source = new BitmapImage(uri);
return source;
}
case "Person":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/persons.png");
var source = new BitmapImage(uri);
return source;
}
case "MusicArtist":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/artist.png");
var source = new BitmapImage(uri);
return source;
}
case "MusicAlbum":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/album.png");
var source = new BitmapImage(uri);
return source;
}
case "Trailer":
{
var uri = new Uri
("pack://application:,,,/Resources/Images/trailer.png");
var source = new BitmapImage(uri);
return source;
}
case "None":
{
Uri uri;
if (item is Movie)
uri = new Uri("pack://application:,,,/Resources/Images/movie.png");
else if (item is Series)
uri = new Uri("pack://application:,,,/Resources/Images/series.png");
else if (item is BoxSet)
uri = new Uri("pack://application:,,,/Resources/Images/boxset.png");
else
uri = new Uri("pack://application:,,,/Resources/Images/folder.png");
return new BitmapImage(uri);
}
default:
{
var uri = new Uri("pack://application:,,,/Resources/Images/folder.png");
var source = new BitmapImage(uri);
return source;
}
}
}
/// <summary>
/// Converts a value.
/// </summary>
/// <param name="value">The value that is produced by the binding target.</param>
/// <param name="targetType">The type to convert to.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
/// <exception cref="System.NotSupportedException">Cannot convert back</exception>
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotSupportedException("Cannot convert back");
}
}
#endregion // ItemToImageConverter
}

View File

@@ -1,41 +1,53 @@
<Window x:Class="MediaBrowser.ServerApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="http://www.hardcodet.net/taskbar"
Title="MainWindow" Height="350" Width="525" AllowsTransparency="True" Background="Transparent" WindowStyle="None" ShowInTaskbar="False">
<Grid>
<tb:TaskbarIcon Name="MbTaskbarIcon" ToolTipText="MediaBrowser Server">
<tb:TaskbarIcon.ContextMenu>
<ContextMenu Background="White">
<MenuItem Name="cmOpenDashboard" Header="Open Dashboard" Click="cmOpenDashboard_click"/>
<MenuItem Name="cmdReloadServer" Header="Reload Server" Click="cmdReloadServer_click"/>
<MenuItem Name="cmVisitCT" Header="Visit Community Tracker" Click="cmVisitCT_click"/>
<Separator/>
<MenuItem Name="cmExit" Header="Exit" Click="cmExit_click"/>
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>
<tb:TaskbarIcon.Style>
<Style TargetType="{x:Type tb:TaskbarIcon}">
<Setter Property="IconSource" Value="/Resources/Images/icon.ico" />
<Style.Triggers>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="1">
<Setter Property="IconSource" Value="/Resources/Images/loadingIcon1.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="2">
<Setter Property="IconSource" Value="/Resources/Images/loadingIcon2.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="3">
<Setter Property="IconSource" Value="/Resources/Images/loadingIcon3.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="4">
<Setter Property="IconSource" Value="/Resources/Images/loadingIcon4.ico" />
</DataTrigger>
</Style.Triggers>
</Style>
</tb:TaskbarIcon.Style>
</tb:TaskbarIcon>
</Grid>
</Window>
<Window x:Class="MediaBrowser.ServerApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="http://www.hardcodet.net/taskbar"
Title="Media Browser Server" Height="350" Width="525" AllowsTransparency="True" Background="Transparent" WindowStyle="None" ShowInTaskbar="False">
<Grid>
<tb:TaskbarIcon Name="MbTaskbarIcon" ToolTipText="Media Browser Server">
<tb:TaskbarIcon.ContextMenu>
<ContextMenu Background="White">
<MenuItem x:Name="cmdBrowseLibrary" Header="Browse Library" Click="cmdBrowseLibrary_click"/>
<MenuItem x:Name="cmOpenDashboard" Header="Configure Media Browser" Click="cmOpenDashboard_click"/>
<Separator x:Name="separatorDeveloperTools"/>
<MenuItem x:Name="cmOpenExplorer" Header="Open Library Explorer" Click="cmOpenExplorer_click" />
<MenuItem x:Name="cmdReloadServer" Header="Restart Server" Click="cmdReloadServer_click" />
<MenuItem x:Name="cmdApiDocs" Header="View Api Documentation" Click="cmdApiDocs_Click" />
<Separator/>
<MenuItem x:Name="cmShowLogWindow" Header="Show Log Window" IsCheckable="True" Click="CmShowLogWindow_click"/>
<MenuItem x:Name="cmVisitCT" Header="Visit Community" Click="cmVisitCT_click"/>
<Separator/>
<MenuItem x:Name="cmExit" Header="Exit" Click="cmExit_click"/>
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>
<tb:TaskbarIcon.Style>
<Style TargetType="{x:Type tb:TaskbarIcon}">
<Setter Property="IconSource" Value="/Resources/Images/icon.ico" />
<Style.Triggers>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="1">
<Setter Property="IconSource" Value="/Resources/Images/Loading/1.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="2">
<Setter Property="IconSource" Value="/Resources/Images/Loading/2.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="3">
<Setter Property="IconSource" Value="/Resources/Images/Loading/3.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="4">
<Setter Property="IconSource" Value="/Resources/Images/Loading/4.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="5">
<Setter Property="IconSource" Value="/Resources/Images/Loading/5.ico" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadingImageIndex}" Value="6">
<Setter Property="IconSource" Value="/Resources/Images/Loading/6.ico" />
</DataTrigger>
</Style.Triggers>
</Style>
</tb:TaskbarIcon.Style>
</tb:TaskbarIcon>
</Grid>
</Window>

View File

@@ -1,109 +1,335 @@
using Hardcodet.Wpf.TaskbarNotification;
using MediaBrowser.Common.Events;
using MediaBrowser.Controller;
using MediaBrowser.Model.Progress;
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
namespace MediaBrowser.ServerApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private Timer LoadingIconTimer { get; set; }
public MainWindow()
{
InitializeComponent();
Loaded += MainWindowLoaded;
}
void MainWindowLoaded(object sender, RoutedEventArgs e)
{
DataContext = this;
Kernel.Instance.ReloadBeginning += KernelReloadBeginning;
Kernel.Instance.ReloadCompleted += KernelReloadCompleted;
}
void KernelReloadBeginning(object sender, GenericEventArgs<IProgress<TaskProgress>> e)
{
MbTaskbarIcon.ShowBalloonTip("Media Browser is reloading", "Please wait...", BalloonIcon.Info);
LoadingImageIndex = 0;
LoadingIconTimer = new Timer(LoadingIconTimerCallback, null, 0, 250);
}
void KernelReloadCompleted(object sender, GenericEventArgs<IProgress<TaskProgress>> e)
{
LoadingIconTimer.Dispose();
LoadingImageIndex = 0;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private int _loadingImageIndex;
public int LoadingImageIndex
{
get { return _loadingImageIndex; }
set
{
_loadingImageIndex = value;
OnPropertyChanged("LoadingImageIndex");
}
}
#region Context Menu events
private void cmOpenDashboard_click(object sender, RoutedEventArgs e)
{
App.OpenDashboard();
}
private void cmVisitCT_click(object sender, RoutedEventArgs e)
{
App.OpenUrl("http://community.mediabrowser.tv/");
}
private void cmExit_click(object sender, RoutedEventArgs e)
{
Close();
}
private async void cmdReloadServer_click(object sender, RoutedEventArgs e)
{
await Kernel.Instance.Reload(new Progress<TaskProgress>()).ConfigureAwait(false);
}
private void LoadingIconTimerCallback(object stateInfo)
{
const int numImages = 4;
if (LoadingImageIndex < numImages)
{
LoadingImageIndex++;
}
else
{
LoadingImageIndex = 1;
}
}
#endregion
}
}
using MediaBrowser.Common.Logging;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.ServerApplication.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;
namespace MediaBrowser.ServerApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
/// <summary>
/// Holds the list of new items to display when the NewItemTimer expires
/// </summary>
private readonly List<BaseItem> _newlyAddedItems = new List<BaseItem>();
/// <summary>
/// The amount of time to wait before showing a new item notification
/// This allows us to group items together into one notification
/// </summary>
private const int NewItemDelay = 60000;
/// <summary>
/// The current new item timer
/// </summary>
/// <value>The new item timer.</value>
private Timer NewItemTimer { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="MainWindow" /> class.
/// </summary>
public MainWindow()
{
InitializeComponent();
Loaded += MainWindowLoaded;
}
/// <summary>
/// Mains the window loaded.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
void MainWindowLoaded(object sender, RoutedEventArgs e)
{
DataContext = this;
Instance_ConfigurationUpdated(null, EventArgs.Empty);
Kernel.Instance.ReloadCompleted += KernelReloadCompleted;
Kernel.Instance.LoggerLoaded += LoadLogWindow;
Kernel.Instance.HasPendingRestartChanged += Instance_HasPendingRestartChanged;
Kernel.Instance.ConfigurationUpdated += Instance_ConfigurationUpdated;
}
/// <summary>
/// Handles the ConfigurationUpdated event of the Instance control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
void Instance_ConfigurationUpdated(object sender, EventArgs e)
{
Dispatcher.InvokeAsync(() =>
{
var developerToolsVisibility = Kernel.Instance.Configuration.EnableDeveloperTools
? Visibility.Visible
: Visibility.Collapsed;
separatorDeveloperTools.Visibility = developerToolsVisibility;
cmdReloadServer.Visibility = developerToolsVisibility;
cmOpenExplorer.Visibility = developerToolsVisibility;
});
}
/// <summary>
/// Sets visibility of the restart message when the kernel value changes
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
void Instance_HasPendingRestartChanged(object sender, EventArgs e)
{
Dispatcher.InvokeAsync(() =>
{
MbTaskbarIcon.ToolTipText = Kernel.Instance.HasPendingRestart ? "Media Browser Server - Please restart to finish updating." : "Media Browser Server";
});
}
/// <summary>
/// Handles the LibraryChanged event of the Instance control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
void Instance_LibraryChanged(object sender, ChildrenChangedEventArgs e)
{
var newItems = e.ItemsAdded.Where(i => !i.IsFolder).ToList();
// Use a timer to prevent lots of these notifications from showing in a short period of time
if (newItems.Count > 0)
{
lock (_newlyAddedItems)
{
_newlyAddedItems.AddRange(newItems);
if (NewItemTimer == null)
{
NewItemTimer = new Timer(NewItemTimerCallback, null, NewItemDelay, Timeout.Infinite);
}
else
{
NewItemTimer.Change(NewItemDelay, Timeout.Infinite);
}
}
}
}
/// <summary>
/// Called when the new item timer expires
/// </summary>
/// <param name="state">The state.</param>
private void NewItemTimerCallback(object state)
{
List<BaseItem> newItems;
// Lock the list and release all resources
lock (_newlyAddedItems)
{
newItems = _newlyAddedItems.ToList();
_newlyAddedItems.Clear();
NewItemTimer.Dispose();
NewItemTimer = null;
}
// Show the notification
if (newItems.Count == 1)
{
Dispatcher.InvokeAsync(() => MbTaskbarIcon.ShowCustomBalloon(new ItemUpdateNotification { DataContext = newItems[0] }, PopupAnimation.Slide, 6000));
}
else if (newItems.Count > 1)
{
Dispatcher.InvokeAsync(() => MbTaskbarIcon.ShowCustomBalloon(new MultiItemUpdateNotification { DataContext = newItems }, PopupAnimation.Slide, 6000));
}
}
/// <summary>
/// Loads the log window.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="EventArgs" /> instance containing the event data.</param>
void LoadLogWindow(object sender, EventArgs args)
{
CloseLogWindow();
Dispatcher.InvokeAsync(() =>
{
// Add our log window if specified
if (Kernel.Instance.Configuration.ShowLogWindow)
{
Trace.Listeners.Add(new WindowTraceListener(new LogWindow(Kernel.Instance)));
}
else
{
Trace.Listeners.Remove("MBLogWindow");
}
// Set menu option indicator
cmShowLogWindow.IsChecked = Kernel.Instance.Configuration.ShowLogWindow;
}, DispatcherPriority.Normal);
}
/// <summary>
/// Closes the log window.
/// </summary>
void CloseLogWindow()
{
Dispatcher.InvokeAsync(() =>
{
foreach (var win in Application.Current.Windows.OfType<LogWindow>())
{
win.Close();
}
});
}
/// <summary>
/// Kernels the reload completed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
void KernelReloadCompleted(object sender, EventArgs e)
{
Kernel.Instance.LibraryManager.LibraryChanged -= Instance_LibraryChanged;
Kernel.Instance.LibraryManager.LibraryChanged += Instance_LibraryChanged;
if (Kernel.Instance.IsFirstRun)
{
LaunchStartupWizard();
}
}
/// <summary>
/// Launches the startup wizard.
/// </summary>
private void LaunchStartupWizard()
{
App.OpenDashboardPage("wizardStart.html");
}
/// <summary>
/// Handles the Click event of the cmdApiDocs control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
void cmdApiDocs_Click(object sender, EventArgs e)
{
App.OpenUrl("http://localhost:" + Controller.Kernel.Instance.Configuration.HttpServerPortNumber + "/" +
Controller.Kernel.Instance.WebApplicationName + "/metadata");
}
/// <summary>
/// Occurs when [property changed].
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Called when [property changed].
/// </summary>
/// <param name="info">The info.</param>
public void OnPropertyChanged(String info)
{
if (PropertyChanged != null)
{
try
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
catch (Exception ex)
{
Logger.LogException("Error in event handler", ex);
}
}
}
#region Context Menu events
/// <summary>
/// Handles the click event of the cmOpenExplorer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmOpenExplorer_click(object sender, RoutedEventArgs e)
{
(new LibraryExplorer()).Show();
}
/// <summary>
/// Handles the click event of the cmOpenDashboard control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmOpenDashboard_click(object sender, RoutedEventArgs e)
{
App.OpenDashboard();
}
/// <summary>
/// Handles the click event of the cmVisitCT control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmVisitCT_click(object sender, RoutedEventArgs e)
{
App.OpenUrl("http://community.mediabrowser.tv/");
}
/// <summary>
/// Handles the click event of the cmdBrowseLibrary control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmdBrowseLibrary_click(object sender, RoutedEventArgs e)
{
App.OpenDashboardPage("index.html");
}
/// <summary>
/// Handles the click event of the cmExit control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmExit_click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
/// <summary>
/// Handles the click event of the cmdReloadServer control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmdReloadServer_click(object sender, RoutedEventArgs e)
{
App.Instance.Restart();
}
/// <summary>
/// Handles the click event of the CmShowLogWindow control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void CmShowLogWindow_click(object sender, RoutedEventArgs e)
{
Kernel.Instance.Configuration.ShowLogWindow = !Kernel.Instance.Configuration.ShowLogWindow;
Kernel.Instance.SaveConfiguration();
LoadLogWindow(sender, e);
}
#endregion
private void cmdApiDocs_Click_1(object sender, RoutedEventArgs e)
{
}
}
}

View File

@@ -1,143 +1,346 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{156EA256-AD2D-4D2F-B116-2ED4B9EFD869}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MediaBrowser.ServerApplication</RootNamespace>
<AssemblyName>MediaBrowser.ServerApplication</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>MediaBrowser.ServerApplication.App</StartupObject>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\Images\icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Hardcodet.Wpf.TaskbarNotification">
<HintPath>..\packages\Hardcodet.Wpf.TaskbarNotification.1.0.4.0\lib\net40\Hardcodet.Wpf.TaskbarNotification.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Runtime.Remoting" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Page Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
<Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
<Name>MediaBrowser.Common</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\icon.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\loadingIcon1.ico" />
<Resource Include="Resources\Images\loadingIcon2.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\loadingIcon3.ico" />
<Resource Include="Resources\Images\loadingIcon4.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{156EA256-AD2D-4D2F-B116-2ED4B9EFD869}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MediaBrowser.ServerApplication</RootNamespace>
<AssemblyName>MediaBrowser.ServerApplication</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<IsWebBootstrapper>true</IsWebBootstrapper>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<PublishUrl>http://www.mb3admin.com/downloads/server/</PublishUrl>
<Install>true</Install>
<InstallFrom>Web</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Background</UpdateMode>
<UpdateInterval>1</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<SupportUrl>http://forum.mediabrowser3.com</SupportUrl>
<ProductName>Media Browser Server</ProductName>
<PublisherName>Media Browser Team</PublisherName>
<SuiteName>Media Browser 3</SuiteName>
<ApplicationRevision>3033</ApplicationRevision>
<ApplicationVersion>2.9.4795.3033</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>1</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>MediaBrowser.ServerApplication.App</StartupObject>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\Images\icon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>9633DCDB4A07D3328EFB99299C6DFB1823EBC4BE</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>
</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
</PropertyGroup>
<PropertyGroup>
<ManifestTimestampUrl>http://timestamp.verisign.com/scripts/timstamp.dll</ManifestTimestampUrl>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>MediaBrowser.ServerApplication_TemporaryKey.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>1</WarningLevel>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Hardcodet.Wpf.TaskbarNotification">
<HintPath>..\packages\Hardcodet.Wpf.TaskbarNotification.1.0.4.0\lib\net40\Hardcodet.Wpf.TaskbarNotification.dll</HintPath>
</Reference>
<Reference Include="Platinum.Managed, Version=1.0.4794.22684, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\UPnP\Libs\Platinum.Managed.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Data.SQLite.1.0.84.0\lib\net45\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Data.SQLite.Linq">
<HintPath>..\packages\System.Data.SQLite.1.0.84.0\lib\net45\System.Data.SQLite.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Runtime.Remoting" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Page Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\ItemUpdateNotification.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\MultiItemUpdateNotification.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="LibraryExplorer.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Controls\ItemUpdateNotification.xaml.cs">
<DependentUpon>ItemUpdateNotification.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\MultiItemUpdateNotification.xaml.cs">
<DependentUpon>MultiItemUpdateNotification.xaml</DependentUpon>
</Compile>
<Compile Include="LibraryExplorer.xaml.cs">
<DependentUpon>LibraryExplorer.xaml</DependentUpon>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.manifest" />
<None Include="MediaBrowser.ServerApplication_TemporaryKey.pfx" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
<Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
<Name>MediaBrowser.Common</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj">
<Project>{5356ae30-6a6e-4a64-81e3-f76c50595e64}</Project>
<Name>MediaBrowser.IsoMounter</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Server.Uninstall\MediaBrowser.Server.Uninstall.csproj">
<Project>{5443422f-9548-417a-90dd-2fc91f2b5999}</Project>
<Name>MediaBrowser.Server.Uninstall</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\icon.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\folder.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\movie.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\series.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\season.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\episode.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\audio.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\starEmpty.png" />
<Resource Include="Resources\Images\starFull.png" />
<Resource Include="Resources\Images\starHalf.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\artist.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\persons.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\album.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\boxset.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\trailer.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\folder.jpg" />
<Resource Include="Resources\Images\mblogoblackfull.png" />
<Resource Include="Resources\Images\mblogowhitefull.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\Loading\1.ico" />
<Resource Include="Resources\Images\Loading\2.ico" />
<Resource Include="Resources\Images\Loading\3.ico" />
<Resource Include="Resources\Images\Loading\4.ico" />
<Resource Include="Resources\Images\Loading\5.ico" />
<Resource Include="Resources\Images\Loading\6.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Visual.C++.10.0.x86">
<Visible>False</Visible>
<ProductName>Visual C++ 2010 Runtime Libraries %28x86%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="MediaBrowser.Api.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="MediaBrowser.ApiInteraction.Javascript.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="MediaBrowser.WebDashboard.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="x64\SQLite.Interop.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="x86\SQLite.Interop.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(SolutionDir)\packages\System.Data.SQLite.1.0.84.0\content\net40\x86\SQLite.Interop.dll" "$(TargetDir)" /y</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,53 +1,52 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MediaBrowser.ServerApplication")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MediaBrowser.ServerApplication")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Media Browser Server")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Media Browser Server")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.9.*")]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel node will disable file and registry virtualization.
If you want to utilize File and Registry Virtualization for backward
compatibility then delete the requestedExecutionLevel node.
-->
</requestedPrivileges>
<applicationRequestMinimum>
<defaultAssemblyRequest permissionSetReference="Custom" />
<PermissionSet ID="Custom" SameSite="site" Unrestricted="true" />
</applicationRequestMinimum>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of all Windows versions that this application is designed to work with.
Windows will automatically select the most compatible environment.-->
<!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
<!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
<!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
</application>
</compatibility>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!-- <dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>-->
</asmv1:assembly>

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Hardcodet.Wpf.TaskbarNotification" version="1.0.4.0" targetFramework="net45" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Hardcodet.Wpf.TaskbarNotification" version="1.0.4.0" targetFramework="net45" />
<package id="System.Data.SQLite" version="1.0.84.0" targetFramework="net45" />
</packages>