mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-25 06:58:40 +02:00
expose Tmdb collection id in editor.
This commit is contained in:
parent
07e5b74f13
commit
1f162e39b1
|
@ -147,9 +147,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup />
|
||||||
<Folder Include="Filters\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
|
|
|
@ -16,6 +16,7 @@ using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.Updates;
|
using MediaBrowser.Model.Updates;
|
||||||
|
using ServiceStack;
|
||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -181,6 +182,9 @@ namespace MediaBrowser.Common.Implementations
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public virtual async Task Init()
|
public virtual async Task Init()
|
||||||
{
|
{
|
||||||
|
// https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Web.config#L4
|
||||||
|
Licensing.RegisterLicense("1001-e1JlZjoxMDAxLE5hbWU6VGVzdCBCdXNpbmVzcyxUeXBlOkJ1c2luZXNzLEhhc2g6UHVNTVRPclhvT2ZIbjQ5MG5LZE1mUTd5RUMzQnBucTFEbTE3TDczVEF4QUNMT1FhNXJMOWkzVjFGL2ZkVTE3Q2pDNENqTkQyUktRWmhvUVBhYTBiekJGUUZ3ZE5aZHFDYm9hL3lydGlwUHI5K1JsaTBYbzNsUC85cjVJNHE5QVhldDN6QkE4aTlvdldrdTgyTk1relY2eis2dFFqTThYN2lmc0JveHgycFdjPSxFeHBpcnk6MjAxMy0wMS0wMX0=");
|
||||||
|
|
||||||
JsonSerializer = CreateJsonSerializer();
|
JsonSerializer = CreateJsonSerializer();
|
||||||
|
|
||||||
IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted;
|
IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted;
|
||||||
|
|
|
@ -273,7 +273,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return base.GetDeletePaths();
|
return base.GetDeletePaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<MediaStream> GetMediaStreams()
|
public virtual IEnumerable<MediaStream> GetMediaStreams()
|
||||||
{
|
{
|
||||||
return ItemRepository.GetMediaStreams(new MediaStreamQuery
|
return ItemRepository.GetMediaStreams(new MediaStreamQuery
|
||||||
{
|
{
|
||||||
|
@ -281,7 +281,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaStream GetDefaultVideoStream()
|
public virtual MediaStream GetDefaultVideoStream()
|
||||||
{
|
{
|
||||||
if (!DefaultVideoStreamIndex.HasValue)
|
if (!DefaultVideoStreamIndex.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace MediaBrowser.Providers
|
||||||
public class ImageFromMediaLocationProvider : BaseMetadataProvider
|
public class ImageFromMediaLocationProvider : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
protected readonly IFileSystem FileSystem;
|
protected readonly IFileSystem FileSystem;
|
||||||
|
|
||||||
public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
|
public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem)
|
||||||
: base(logManager, configurationManager)
|
: base(logManager, configurationManager)
|
||||||
{
|
{
|
||||||
|
@ -54,6 +54,7 @@ namespace MediaBrowser.Providers
|
||||||
|
|
||||||
return item.IsInMixedFolder && item.Parent != null && !(item is Episode);
|
return item.IsInMixedFolder && item.Parent != null && !(item is Episode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +154,13 @@ namespace MediaBrowser.Providers
|
||||||
.FirstOrDefault(i => i != null);
|
.FirstOrDefault(i => i != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual FileSystemInfo GetImage(List<FileSystemInfo> files, string filenameWithoutExtension)
|
||||||
|
{
|
||||||
|
return BaseItem.SupportedImageExtensions
|
||||||
|
.Select(i => files.FirstOrDefault(f => string.Equals(f.Extension, i, StringComparison.OrdinalIgnoreCase) && string.Equals(filenameWithoutExtension, Path.GetFileNameWithoutExtension(f.Name), StringComparison.OrdinalIgnoreCase)))
|
||||||
|
.FirstOrDefault(i => i != null);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual string GetFullImagePath(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension, string extension)
|
protected virtual string GetFullImagePath(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension, string extension)
|
||||||
{
|
{
|
||||||
var path = item.MetaLocation;
|
var path = item.MetaLocation;
|
||||||
|
@ -258,24 +266,13 @@ namespace MediaBrowser.Providers
|
||||||
var isFileSystemItem = item.LocationType == LocationType.FileSystem;
|
var isFileSystemItem = item.LocationType == LocationType.FileSystem;
|
||||||
|
|
||||||
// Support plex/xbmc convention
|
// Support plex/xbmc convention
|
||||||
if (image == null && item is Season && item.IndexNumber.HasValue && isFileSystemItem)
|
if (image == null)
|
||||||
{
|
{
|
||||||
var seasonMarker = item.IndexNumber.Value == 0
|
// Supprt xbmc conventions
|
||||||
? "-specials"
|
var season = item as Season;
|
||||||
: item.IndexNumber.Value.ToString("00", _usCulture);
|
if (season != null && item.IndexNumber.HasValue && isFileSystemItem)
|
||||||
|
|
||||||
// Get this one directly from the file system since we have to go up a level
|
|
||||||
var filename = "season" + seasonMarker + "-poster";
|
|
||||||
|
|
||||||
var path = Path.GetDirectoryName(item.Path);
|
|
||||||
|
|
||||||
path = Path.Combine(path, filename);
|
|
||||||
|
|
||||||
image = new FileInfo(path);
|
|
||||||
|
|
||||||
if (!image.Exists)
|
|
||||||
{
|
{
|
||||||
image = null;
|
image = GetSeasonImageFromSeriesFolder(season, "-poster");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,26 +312,13 @@ namespace MediaBrowser.Providers
|
||||||
|
|
||||||
if (image == null)
|
if (image == null)
|
||||||
{
|
{
|
||||||
|
var isFileSystemItem = item.LocationType == LocationType.FileSystem;
|
||||||
|
|
||||||
// Supprt xbmc conventions
|
// Supprt xbmc conventions
|
||||||
if (item is Season && item.IndexNumber.HasValue && item.LocationType == LocationType.FileSystem)
|
var season = item as Season;
|
||||||
|
if (season != null && item.IndexNumber.HasValue && isFileSystemItem)
|
||||||
{
|
{
|
||||||
var seasonMarker = item.IndexNumber.Value == 0
|
image = GetSeasonImageFromSeriesFolder(season, "-banner");
|
||||||
? "-specials"
|
|
||||||
: item.IndexNumber.Value.ToString("00", _usCulture);
|
|
||||||
|
|
||||||
// Get this one directly from the file system since we have to go up a level
|
|
||||||
var filename = "season" + seasonMarker + "-banner";
|
|
||||||
|
|
||||||
var path = Path.GetDirectoryName(item.Path);
|
|
||||||
|
|
||||||
path = Path.Combine(path, filename);
|
|
||||||
|
|
||||||
image = new FileInfo(path);
|
|
||||||
|
|
||||||
if (!image.Exists)
|
|
||||||
{
|
|
||||||
image = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,26 +340,13 @@ namespace MediaBrowser.Providers
|
||||||
|
|
||||||
if (image == null)
|
if (image == null)
|
||||||
{
|
{
|
||||||
|
var isFileSystemItem = item.LocationType == LocationType.FileSystem;
|
||||||
|
|
||||||
// Supprt xbmc conventions
|
// Supprt xbmc conventions
|
||||||
if (item is Season && item.IndexNumber.HasValue && item.LocationType == LocationType.FileSystem)
|
var season = item as Season;
|
||||||
|
if (season != null && item.IndexNumber.HasValue && isFileSystemItem)
|
||||||
{
|
{
|
||||||
var seasonMarker = item.IndexNumber.Value == 0
|
image = GetSeasonImageFromSeriesFolder(season, "-landscape");
|
||||||
? "-specials"
|
|
||||||
: item.IndexNumber.Value.ToString("00", _usCulture);
|
|
||||||
|
|
||||||
// Get this one directly from the file system since we have to go up a level
|
|
||||||
var filename = "season" + seasonMarker + "-landscape";
|
|
||||||
|
|
||||||
var path = Path.GetDirectoryName(item.Path);
|
|
||||||
|
|
||||||
path = Path.Combine(path, filename);
|
|
||||||
|
|
||||||
image = new FileInfo(path);
|
|
||||||
|
|
||||||
if (!image.Exists)
|
|
||||||
{
|
|
||||||
image = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,22 +391,12 @@ namespace MediaBrowser.Providers
|
||||||
PopulateBackdrops(item, args, backdropFiles, "background", "background-");
|
PopulateBackdrops(item, args, backdropFiles, "background", "background-");
|
||||||
PopulateBackdrops(item, args, backdropFiles, "art", "art-");
|
PopulateBackdrops(item, args, backdropFiles, "art", "art-");
|
||||||
|
|
||||||
if (item is Season && item.IndexNumber.HasValue && isFileSystemItem)
|
var season = item as Season;
|
||||||
|
if (season != null && item.IndexNumber.HasValue && isFileSystemItem)
|
||||||
{
|
{
|
||||||
var seasonMarker = item.IndexNumber.Value == 0
|
var image = GetSeasonImageFromSeriesFolder(season, "-fanart");
|
||||||
? "-specials"
|
|
||||||
: item.IndexNumber.Value.ToString("00", _usCulture);
|
|
||||||
|
|
||||||
// Get this one directly from the file system since we have to go up a level
|
if (image != null)
|
||||||
var filename = "season" + seasonMarker + "-fanart";
|
|
||||||
|
|
||||||
var path = Path.GetDirectoryName(item.Path);
|
|
||||||
|
|
||||||
path = Path.Combine(path, filename);
|
|
||||||
|
|
||||||
var image = new FileInfo(path);
|
|
||||||
|
|
||||||
if (image.Exists)
|
|
||||||
{
|
{
|
||||||
backdropFiles.Add(image.FullName);
|
backdropFiles.Add(image.FullName);
|
||||||
}
|
}
|
||||||
|
@ -452,6 +413,51 @@ namespace MediaBrowser.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FileSystemInfo GetSeasonImageFromSeriesFolder(Season season, string imageSuffix)
|
||||||
|
{
|
||||||
|
var series = season.Series;
|
||||||
|
var seriesFolderArgs = series.ResolveArgs;
|
||||||
|
|
||||||
|
var seasonNumber = season.IndexNumber;
|
||||||
|
|
||||||
|
string filename = null;
|
||||||
|
FileSystemInfo image;
|
||||||
|
|
||||||
|
if (seasonNumber.HasValue)
|
||||||
|
{
|
||||||
|
var seasonMarker = seasonNumber.Value == 0
|
||||||
|
? "-specials"
|
||||||
|
: seasonNumber.Value.ToString("00", _usCulture);
|
||||||
|
|
||||||
|
// Get this one directly from the file system since we have to go up a level
|
||||||
|
filename = "season" + seasonMarker + imageSuffix;
|
||||||
|
|
||||||
|
image = GetImage(series, seriesFolderArgs, filename);
|
||||||
|
|
||||||
|
if (image != null && image.Exists)
|
||||||
|
{
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousFilename = filename;
|
||||||
|
|
||||||
|
// Try using the season name
|
||||||
|
filename = season.Name.ToLower().Replace(" ", string.Empty) + imageSuffix;
|
||||||
|
|
||||||
|
if (!string.Equals(previousFilename, filename))
|
||||||
|
{
|
||||||
|
image = GetImage(series, seriesFolderArgs, filename);
|
||||||
|
|
||||||
|
if (image != null && image.Exists)
|
||||||
|
{
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates the backdrops from extra fanart.
|
/// Populates the backdrops from extra fanart.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -74,7 +74,8 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sizeDictionary = jsonSerializer.DeserializeFromFile<Dictionary<Guid, ImageSize>>(ImageSizeFile);
|
sizeDictionary = jsonSerializer.DeserializeFromFile<Dictionary<Guid, ImageSize>>(ImageSizeFile) ??
|
||||||
|
new Dictionary<Guid, ImageSize>();
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException)
|
catch (FileNotFoundException)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,6 @@ using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using ServiceStack;
|
using ServiceStack;
|
||||||
using ServiceStack.Configuration;
|
|
||||||
using ServiceStack.Host;
|
using ServiceStack.Host;
|
||||||
using ServiceStack.Host.Handlers;
|
using ServiceStack.Host.Handlers;
|
||||||
using ServiceStack.Host.HttpListener;
|
using ServiceStack.Host.HttpListener;
|
||||||
|
@ -58,9 +57,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices)
|
public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices)
|
||||||
: base(serviceName, assembliesWithServices)
|
: base(serviceName, assembliesWithServices)
|
||||||
{
|
{
|
||||||
// https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Web.config#L4
|
|
||||||
Licensing.RegisterLicense("1001-e1JlZjoxMDAxLE5hbWU6VGVzdCBCdXNpbmVzcyxUeXBlOkJ1c2luZXNzLEhhc2g6UHVNTVRPclhvT2ZIbjQ5MG5LZE1mUTd5RUMzQnBucTFEbTE3TDczVEF4QUNMT1FhNXJMOWkzVjFGL2ZkVTE3Q2pDNENqTkQyUktRWmhvUVBhYTBiekJGUUZ3ZE5aZHFDYm9hL3lydGlwUHI5K1JsaTBYbzNsUC85cjVJNHE5QVhldDN6QkE4aTlvdldrdTgyTk1relY2eis2dFFqTThYN2lmc0JveHgycFdjPSxFeHBpcnk6MjAxMy0wMS0wMX0=");
|
|
||||||
|
|
||||||
DefaultRedirectPath = defaultRedirectPath;
|
DefaultRedirectPath = defaultRedirectPath;
|
||||||
ServerName = serviceName;
|
ServerName = serviceName;
|
||||||
HandlerPath = handlerPath;
|
HandlerPath = handlerPath;
|
||||||
|
|
|
@ -37,18 +37,23 @@
|
||||||
<Reference Include="Alchemy">
|
<Reference Include="Alchemy">
|
||||||
<HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
|
<HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ServiceStack, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Client">
|
<Reference Include="ServiceStack.Client, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Client.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Client.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ServiceStack.Common, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ServiceStack.Interfaces, Version=4.0.0.0, Culture=neutral, PublicKeyToken=e06fbc6124f57c43, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ServiceStack.Text, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Text.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Text.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -143,6 +148,7 @@
|
||||||
<Compile Include="Persistence\SqliteMediaStreamsRepository.cs" />
|
<Compile Include="Persistence\SqliteMediaStreamsRepository.cs" />
|
||||||
<Compile Include="Persistence\SqliteNotificationsRepository.cs" />
|
<Compile Include="Persistence\SqliteNotificationsRepository.cs" />
|
||||||
<Compile Include="Persistence\SqliteProviderInfoRepository.cs" />
|
<Compile Include="Persistence\SqliteProviderInfoRepository.cs" />
|
||||||
|
<Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" />
|
||||||
<Compile Include="Persistence\TypeMapper.cs" />
|
<Compile Include="Persistence\TypeMapper.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Providers\ImageSaver.cs" />
|
<Compile Include="Providers\ImageSaver.cs" />
|
||||||
|
@ -237,9 +243,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Localization\Ratings\ca.txt" />
|
<EmbeddedResource Include="Localization\Ratings\ca.txt" />
|
||||||
<Content Include="swagger-ui\index.html">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||||
|
|
|
@ -44,7 +44,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create index if not exists idx_chapters on chapters(ItemId, ChapterIndex)",
|
"create index if not exists idx_chapters on chapters(ItemId, ChapterIndex)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -86,8 +86,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
|
|
||||||
"create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)",
|
"create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)",
|
||||||
"create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)",
|
"create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -124,18 +124,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
|
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
||||||
PrepareStatements();
|
PrepareStatements();
|
||||||
|
|
||||||
_mediaStreamsRepository.Initialize();
|
_mediaStreamsRepository.Initialize();
|
||||||
_providerInfoRepository.Initialize();
|
_providerInfoRepository.Initialize();
|
||||||
_chapterRepository.Initialize();
|
_chapterRepository.Initialize();
|
||||||
|
|
||||||
|
_shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SqliteShrinkMemoryTimer _shrinkMemoryTimer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _write lock
|
/// The _write lock
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -402,6 +408,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
{
|
{
|
||||||
lock (_disposeLock)
|
lock (_disposeLock)
|
||||||
{
|
{
|
||||||
|
if (_shrinkMemoryTimer != null)
|
||||||
|
{
|
||||||
|
_shrinkMemoryTimer.Dispose();
|
||||||
|
_shrinkMemoryTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (_connection != null)
|
if (_connection != null)
|
||||||
{
|
{
|
||||||
if (_connection.IsOpen())
|
if (_connection.IsOpen())
|
||||||
|
@ -412,30 +424,30 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
_connection.Dispose();
|
_connection.Dispose();
|
||||||
_connection = null;
|
_connection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_chapterRepository != null)
|
||||||
|
{
|
||||||
|
_chapterRepository.Dispose();
|
||||||
|
_chapterRepository = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mediaStreamsRepository != null)
|
||||||
|
{
|
||||||
|
_mediaStreamsRepository.Dispose();
|
||||||
|
_mediaStreamsRepository = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_providerInfoRepository != null)
|
||||||
|
{
|
||||||
|
_providerInfoRepository.Dispose();
|
||||||
|
_providerInfoRepository = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error disposing database", ex);
|
_logger.ErrorException("Error disposing database", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_chapterRepository != null)
|
|
||||||
{
|
|
||||||
_chapterRepository.Dispose();
|
|
||||||
_chapterRepository = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_mediaStreamsRepository != null)
|
|
||||||
{
|
|
||||||
_mediaStreamsRepository.Dispose();
|
|
||||||
_mediaStreamsRepository = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_providerInfoRepository != null)
|
|
||||||
{
|
|
||||||
_providerInfoRepository.Dispose();
|
|
||||||
_providerInfoRepository = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create index if not exists idx_mediastreams on mediastreams(ItemId, StreamIndex)",
|
"create index if not exists idx_mediastreams on mediastreams(ItemId, StreamIndex)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -45,7 +45,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create index if not exists idx_Notifications on Notifications(Id, UserId)",
|
"create index if not exists idx_Notifications on Notifications(Id, UserId)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -42,7 +42,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create index if not exists idx_providerinfos on providerinfos(ItemId, ProviderId)",
|
"create index if not exists idx_providerinfos on providerinfos(ItemId, ProviderId)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
|
{
|
||||||
|
class SqliteShrinkMemoryTimer : IDisposable
|
||||||
|
{
|
||||||
|
private Timer _shrinkMemoryTimer;
|
||||||
|
|
||||||
|
private readonly SemaphoreSlim _writeLock;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly IDbConnection _connection;
|
||||||
|
|
||||||
|
public SqliteShrinkMemoryTimer(IDbConnection connection, SemaphoreSlim writeLock, ILogger logger)
|
||||||
|
{
|
||||||
|
_connection = connection;
|
||||||
|
_writeLock = writeLock;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
_shrinkMemoryTimer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(30));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void TimerCallback(object state)
|
||||||
|
{
|
||||||
|
await _writeLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
IDbTransaction transaction = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
transaction = _connection.BeginTransaction();
|
||||||
|
|
||||||
|
using (var cmd = _connection.CreateCommand())
|
||||||
|
{
|
||||||
|
cmd.Transaction = transaction;
|
||||||
|
cmd.CommandText = "pragma shrink_memory";
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
if (transaction != null)
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Failed to save items:", e);
|
||||||
|
|
||||||
|
if (transaction != null)
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (transaction != null)
|
||||||
|
{
|
||||||
|
transaction.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_writeLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_shrinkMemoryTimer != null)
|
||||||
|
{
|
||||||
|
_shrinkMemoryTimer.Dispose();
|
||||||
|
_shrinkMemoryTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,7 +72,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create unique index if not exists userdataindex on userdata (key, userId)",
|
"create unique index if not exists userdataindex on userdata (key, userId)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -77,8 +77,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
||||||
"create table if not exists users (guid GUID primary key, data BLOB)",
|
"create table if not exists users (guid GUID primary key, data BLOB)",
|
||||||
"create index if not exists idx_users on users(guid)",
|
"create index if not exists idx_users on users(guid)",
|
||||||
"create table if not exists schema_version (table_name primary key, version)",
|
"create table if not exists schema_version (table_name primary key, version)",
|
||||||
|
|
||||||
//pragmas
|
//pragmas
|
||||||
"pragma temp_store = memory"
|
"pragma temp_store = memory",
|
||||||
|
|
||||||
|
"pragma shrink_memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
_connection.RunQueries(queries, _logger);
|
_connection.RunQueries(queries, _logger);
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Swagger UI</title>
|
|
||||||
<link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
|
|
||||||
<link href='css/hightlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
|
|
||||||
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
|
|
||||||
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/handlebars-1.0.rc.1.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/underscore-min.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/backbone-min.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/swagger.js' type='text/javascript'></script>
|
|
||||||
<script src='swagger-ui.js' type='text/javascript'></script>
|
|
||||||
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function () {
|
|
||||||
window.swaggerUi = new SwaggerUi({
|
|
||||||
discoveryUrl: "../resources",
|
|
||||||
apiKey: "special-key",
|
|
||||||
dom_id:"swagger-ui-container",
|
|
||||||
supportHeaderParams: false,
|
|
||||||
supportedSubmitMethods: ['get', 'post', 'put'],
|
|
||||||
onComplete: function(swaggerApi, swaggerUi){
|
|
||||||
if(console) {
|
|
||||||
console.log("Loaded SwaggerUI")
|
|
||||||
console.log(swaggerApi);
|
|
||||||
console.log(swaggerUi);
|
|
||||||
}
|
|
||||||
$('pre code').each(function(i, e) {hljs.highlightBlock(e)});
|
|
||||||
},
|
|
||||||
onFailure: function(data) {
|
|
||||||
if(console) {
|
|
||||||
console.log("Unable to Load SwaggerUI");
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
docExpansion: "none"
|
|
||||||
});
|
|
||||||
|
|
||||||
window.swaggerUi.load();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id='header'>
|
|
||||||
<div class="swagger-ui-wrap">
|
|
||||||
<a id="logo" href="http://swagger.wordnik.com">swagger</a>
|
|
||||||
|
|
||||||
<form id='api_selector'>
|
|
||||||
<div class='input icon-btn'>
|
|
||||||
<img id="show-pet-store-icon" src="images/pet_store_api.png" title="Show Swagger Petstore Example Apis">
|
|
||||||
</div>
|
|
||||||
<div class='input icon-btn'>
|
|
||||||
<img id="show-wordnik-dev-icon" src="images/wordnik_api.png" title="Show Wordnik Developer Apis">
|
|
||||||
</div>
|
|
||||||
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl"
|
|
||||||
type="text"/></div>
|
|
||||||
<div class='input'><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
|
|
||||||
<div class='input'><a id="explore" href="#">Explore</a></div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="message-bar" class="swagger-ui-wrap">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="swagger-ui-container" class="swagger-ui-wrap">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using MediaBrowser.Controller.Plugins;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace MediaBrowser.ServerApplication.EntryPoints
|
||||||
|
{
|
||||||
|
public class ResourceEntryPoint : IServerEntryPoint
|
||||||
|
{
|
||||||
|
private Timer _timer;
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
_timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(30));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TimerCallback(object state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Bad practice, i know. But we keep a lot in memory, unfortunately.
|
||||||
|
GC.Collect(2, GCCollectionMode.Forced, true);
|
||||||
|
GC.Collect(2, GCCollectionMode.Forced, true);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_timer != null)
|
||||||
|
{
|
||||||
|
_timer.Dispose();
|
||||||
|
_timer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -131,8 +131,7 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\MediaBrowser.IsoMounting.3.0.65\lib\net45\pfmclrapi.dll</HintPath>
|
<HintPath>..\packages\MediaBrowser.IsoMounting.3.0.65\lib\net45\pfmclrapi.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ServiceStack.Interfaces">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector, Version=2.3.6.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
<Reference Include="SimpleInjector, Version=2.3.6.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
|
@ -161,6 +160,7 @@
|
||||||
<Compile Include="BackgroundService.cs">
|
<Compile Include="BackgroundService.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="EntryPoints\ResourceEntryPoint.cs" />
|
||||||
<Compile Include="EntryPoints\StartupWizard.cs" />
|
<Compile Include="EntryPoints\StartupWizard.cs" />
|
||||||
<Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
|
<Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
|
||||||
<Compile Include="FFMpeg\FFMpegInfo.cs" />
|
<Compile Include="FFMpeg\FFMpegInfo.cs" />
|
||||||
|
|
Loading…
Reference in a new issue